Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
*/

import React from 'react';
import { PainlessLang, PainlessContext } from '@kbn/monaco';
import { PainlessLang } from '@kbn/monaco';

import { CodeEditor } from '../../../../../../src/plugins/kibana_react/public';
import { ExecutionContext } from '../types';

interface Props {
code: string;
onChange: (code: string) => void;
context: PainlessContext;
context: ExecutionContext;
}

export function Editor({ code, onChange, context }: Props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ import {
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { PainlessContext } from '@kbn/monaco';

import { CodeEditor } from '../../../../../../../src/plugins/kibana_react/public';
import { painlessContextOptions } from '../../constants';
import { useAppContext } from '../../context';
import { isAdvancedContext } from '../../lib/utils';
import { ExecutionContext } from '../../types';

export const ContextTab: FunctionComponent = () => {
const {
Expand Down Expand Up @@ -66,14 +67,14 @@ export const ContextTab: FunctionComponent = () => {
<EuiSuperSelect
options={painlessContextOptions}
valueOfSelected={context}
onChange={(nextContext: PainlessContext) => updatePayload({ context: nextContext })}
onChange={(nextContext: ExecutionContext) => updatePayload({ context: nextContext })}
itemLayoutAlign="top"
hasDividers
fullWidth
/>
</EuiFormRow>

{['filter', 'score'].indexOf(context) !== -1 && (
{isAdvancedContext(context) && (
<EuiFormRow
label={
<EuiToolTip
Expand Down Expand Up @@ -160,7 +161,8 @@ export const ContextTab: FunctionComponent = () => {
</EuiPanel>
</EuiFormRow>
)}
{['filter', 'score'].indexOf(context) !== -1 && (

{isAdvancedContext(context) && (
<EuiFormRow
label={
<EuiToolTip
Expand Down
168 changes: 105 additions & 63 deletions x-pack/plugins/painless_lab/public/application/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,75 +9,117 @@ import React from 'react';

import { EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { PainlessContext } from '@kbn/monaco';
import { EuiSuperSelectOption } from '@elastic/eui';

const defaultLabel = i18n.translate('xpack.painlessLab.contextDefaultLabel', {
defaultMessage: 'Basic',
});

const filterLabel = i18n.translate('xpack.painlessLab.contextFilterLabel', {
defaultMessage: 'Filter',
});

const scoreLabel = i18n.translate('xpack.painlessLab.contextScoreLabel', {
defaultMessage: 'Score',
});

export const painlessContextOptions: Array<EuiSuperSelectOption<PainlessContext>> = [
{
value: 'painless_test',
inputDisplay: defaultLabel,
'data-test-subj': 'basicButtonDropdown',
dropdownDisplay: (
<>
<strong>{defaultLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">
{i18n.translate('xpack.painlessLab.context.defaultLabel', {
defaultMessage: 'The script result will be converted to a string',
})}
</p>
</EuiText>
</>
),
import { ExecutionContext } from './types';

const i18nTexts: {
[key in ExecutionContext]: {
buttonLabel: string;
dropdownDescription: string;
};
} = {
painless_test: {
buttonLabel: i18n.translate('xpack.painlessLab.contextDefaultLabel', {
defaultMessage: 'Basic',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.defaultLabel', {
defaultMessage: 'The script result will be converted to a string',
}),
},
filter: {
buttonLabel: i18n.translate('xpack.painlessLab.contextFilterLabel', {
defaultMessage: 'Filter',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.filterLabel', {
defaultMessage: "Use the context of a filter's script query",
}),
},
score: {
buttonLabel: i18n.translate('xpack.painlessLab.contextScoreLabel', {
defaultMessage: 'Score',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.scoreLabel', {
defaultMessage: 'Use the context of a script_score function in function_score query',
}),
},
boolean_script_field_script_field: {
buttonLabel: i18n.translate('xpack.painlessLab.contextBooleanLabel', {
defaultMessage: 'Boolean',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.booleanLabel', {
defaultMessage: 'TODO',
}),
},
{
value: 'filter',
inputDisplay: filterLabel,
'data-test-subj': 'filterButtonDropdown',
dropdownDisplay: (
<>
<strong>{filterLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">
{i18n.translate('xpack.painlessLab.context.filterLabel', {
defaultMessage: "Use the context of a filter's script query",
})}
</p>
</EuiText>
</>
),
date_script_field: {
buttonLabel: i18n.translate('xpack.painlessLab.contextDateLabel', {
defaultMessage: 'Date',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.dateLabel', {
defaultMessage: 'TODO',
}),
},
{
value: 'score',
inputDisplay: scoreLabel,
'data-test-subj': 'scoreButtonDropdown',
dropdownDisplay: (
<>
<strong>{scoreLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">
{i18n.translate('xpack.painlessLab.context.scoreLabel', {
defaultMessage: 'Use the context of a script_score function in function_score query',
})}
</p>
</EuiText>
</>
),
double_script_field_script_field: {
buttonLabel: i18n.translate('xpack.painlessLab.contextDoubleLabel', {
defaultMessage: 'Double',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.doubleLabel', {
defaultMessage: 'TODO',
}),
},
ip_script_field_script_field: {
buttonLabel: i18n.translate('xpack.painlessLab.contextIpLabel', {
defaultMessage: 'IP',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.ipLabel', {
defaultMessage: 'TODO',
}),
},
long_script_field_script_field: {
buttonLabel: i18n.translate('xpack.painlessLab.contextLongLabel', {
defaultMessage: 'Long',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.longLabel', {
defaultMessage: 'TODO',
}),
},
string_script_field_script_field: {
buttonLabel: i18n.translate('xpack.painlessLab.contextStringLabel', {
defaultMessage: 'String',
}),
dropdownDescription: i18n.translate('xpack.painlessLab.context.stringLabel', {
defaultMessage: 'TODO',
}),
},
};

const painlessContexts: ExecutionContext[] = [
'painless_test',
'filter',
'score',
'boolean_script_field_script_field',
'date_script_field',
'double_script_field_script_field',
'ip_script_field_script_field',
'long_script_field_script_field',
'string_script_field_script_field',
];

export const painlessContextOptions: Array<
EuiSuperSelectOption<ExecutionContext>
> = painlessContexts.map((context) => ({
value: context,
inputDisplay: i18nTexts[context].buttonLabel,
'data-test-subj': `${context}ButtonDropdown`,
dropdownDisplay: (
<>
<strong>{i18nTexts[context].buttonLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">{i18nTexts[context].dropdownDescription}</p>
</EuiText>
</>
),
}));

// Render a smiley face as an example.
export const exampleScript = `boolean isInCircle(def posX, def posY, def circleX, def circleY, def radius) {
double distanceFromCircleCenter = Math.sqrt(Math.pow(circleX - posX, 2) + Math.pow(circleY - posY, 2));
Expand Down
5 changes: 2 additions & 3 deletions x-pack/plugins/painless_lab/public/application/lib/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { Response, ExecutionError, PayloadFormat, Payload } from '../types';
import { isAdvancedContext } from './utils';

function prettifyPayload(payload = '', indentationLevel = 0) {
const indentation = new Array(indentationLevel + 1).join(' ');
Expand All @@ -20,8 +21,6 @@ export function formatRequestPayload(
{ code, context, parameters, index, document, query }: Partial<Payload>,
format: PayloadFormat = PayloadFormat.UGLY
): string {
const isAdvancedContext = context === 'filter' || context === 'score';

let formattedCode: string | undefined;
let formattedParameters: string | undefined;
let formattedContext: string | undefined;
Expand Down Expand Up @@ -55,7 +54,7 @@ export function formatRequestPayload(
: ``
}
}${
isAdvancedContext
isAdvancedContext(context)
? `,
"context": "${formattedContext}",
"context_setup": {
Expand Down
27 changes: 27 additions & 0 deletions x-pack/plugins/painless_lab/public/application/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { ExecutionContext } from '../types';

/*
* Excludes the "painless_test" context
* This util is used to determine whether or not to show
* the "Index" and "Document" fields under the "Context" tab
*/
const advancedContextTypes: ExecutionContext[] = [
'filter',
'score',
'boolean_script_field_script_field',
'date_script_field',
'double_script_field_script_field',
'ip_script_field_script_field',
'long_script_field_script_field',
'string_script_field_script_field',
];

export const isAdvancedContext = (context?: ExecutionContext) =>
Boolean(context && advancedContextTypes.indexOf(context) !== -1);
7 changes: 3 additions & 4 deletions x-pack/plugins/painless_lab/public/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ export interface Store {
validation: Validation;
}

export type ExecutionContext = Exclude<PainlessContext, 'processor_conditional'>;

export interface Payload {
context: PainlessContext;
context: ExecutionContext;
code: string;
parameters: string;
index: string;
Expand All @@ -28,9 +30,6 @@ export interface Validation {
};
}

// TODO: This should be an enumerated list
export type Context = string;

export enum PayloadFormat {
UGLY = 'ugly',
PRETTY = 'pretty',
Expand Down