From f5bec8ea666c873ffb1bbfc79b88bf3801ab92fc Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 18 Mar 2020 16:24:53 +0100 Subject: [PATCH] Add query parameter to score context (#60414) * Fix typo and i18n * Make state init lazy Otherwise we are needlessly reading and JSON.parse'ing on every state update * Support the query parameter in requests to Painless * Fix borked i18n --- .../public/application/common/constants.tsx | 16 ++- .../public/application/common/types.ts | 1 + .../public/application/components/main.tsx | 24 +++-- .../application/components/main_controls.tsx | 102 +++++++++--------- .../components/output_pane/context_tab.tsx | 54 ++++++++++ .../components/output_pane/output_pane.tsx | 6 ++ .../public/application/lib/format.ts | 22 ++-- x-pack/plugins/painless_lab/public/index.scss | 2 +- .../painless_lab/public/styles/_index.scss | 19 +++- 9 files changed, 169 insertions(+), 77 deletions(-) diff --git a/x-pack/plugins/painless_lab/public/application/common/constants.tsx b/x-pack/plugins/painless_lab/public/application/common/constants.tsx index 8ee10a7392557..8cf3c6b03a2e6 100644 --- a/x-pack/plugins/painless_lab/public/application/common/constants.tsx +++ b/x-pack/plugins/painless_lab/public/application/common/constants.tsx @@ -29,7 +29,11 @@ export const painlessContextOptions = [ <> {defaultLabel} -

The script result will be converted to a string

+

+ {i18n.translate('xpack.painlessLab.context.scoreLabel', { + defaultMessage: 'The script result will be converted to a string', + })} +

), @@ -41,7 +45,11 @@ export const painlessContextOptions = [ <> {filterLabel} -

Use the context of a filter’s script query

+

+ {i18n.translate('xpack.painlessLab.context.scoreLabel', { + defaultMessage: "Use the context of a filter's script query", + })} +

), @@ -54,7 +62,9 @@ export const painlessContextOptions = [ {scoreLabel}

- Use the context of a cript_score function in function_score query + {i18n.translate('xpack.painlessLab.context.scoreLabel', { + defaultMessage: 'Use the context of a script_score function in function_score query', + })}

diff --git a/x-pack/plugins/painless_lab/public/application/common/types.ts b/x-pack/plugins/painless_lab/public/application/common/types.ts index 97f83f7088a1e..d2fda58eff13b 100644 --- a/x-pack/plugins/painless_lab/public/application/common/types.ts +++ b/x-pack/plugins/painless_lab/public/application/common/types.ts @@ -13,6 +13,7 @@ export interface RequestPayloadConfig { parameters?: string; index?: string; document?: string; + query?: string; } export enum PayloadFormat { diff --git a/x-pack/plugins/painless_lab/public/application/components/main.tsx b/x-pack/plugins/painless_lab/public/application/components/main.tsx index b88d96b897ea2..88685874d19e3 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main.tsx @@ -24,20 +24,21 @@ interface Props { const PAINLESS_LAB_KEY = 'painlessLabState'; export function Main({ http }: Props) { - const [state, setState] = useState({ + const [state, setState] = useState(() => ({ code: exampleScript, context: painlessContextOptions[0].value, parameters: '', index: '', document: '', + query: '', ...JSON.parse(localStorage.getItem(PAINLESS_LAB_KEY) || '{}'), - }); + })); const [isRequestFlyoutOpen, setRequestFlyoutOpen] = useState(false); const { inProgress, response, submit } = useSubmitCode(http); // Live-update the output and persist state as the user changes it. - const { code, context, parameters, index, document } = state; + const { code, context, parameters, index, document, query } = state; useEffect(() => { submit(state); localStorage.setItem(PAINLESS_LAB_KEY, JSON.stringify(state)); @@ -63,13 +64,17 @@ export function Main({ http }: Props) { setState({ ...state, document: newDocument }); }; + const onQueryChange = (newQuery: string) => { + setState({ ...state, query: newQuery }); + }; + const toggleRequestFlyout = () => { setRequestFlyoutOpen(!isRequestFlyoutOpen); }; return ( - <> - +
+

@@ -90,10 +95,12 @@ export function Main({ http }: Props) { parameters={parameters} index={index} document={document} + query={query} onContextChange={onContextChange} onParametersChange={onParametersChange} onIndexChange={onIndexChange} onDocumentChange={onDocumentChange} + onQueryChange={onQueryChange} /> @@ -108,13 +115,10 @@ export function Main({ http }: Props) { {isRequestFlyoutOpen && ( setRequestFlyoutOpen(false)} - requestBody={formatRequestPayload( - { code, context, document, index, parameters }, - PayloadFormat.PRETTY - )} + requestBody={formatRequestPayload(state, PayloadFormat.PRETTY)} response={response ? formatJson(response.result || response.error) : ''} /> )} - +

); } diff --git a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx index 9e24fd9fb5a93..cbdf92d01b7de 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main_controls.tsx @@ -77,58 +77,54 @@ export function MainControls({ toggleRequestFlyout, isRequestFlyoutOpen, reset } ]; return ( - <> -
- - - - - - - setIsHelpOpen(!isHelpOpen)} - > - {i18n.translate('xpack.painlessLab.helpButtonLabel', { - defaultMessage: 'Help', - })} - - } - isOpen={isHelpOpen} - closePopover={() => setIsHelpOpen(false)} - panelPaddingSize="none" - withTitle - anchorPosition="upRight" - > - - - - - - - - {isRequestFlyoutOpen - ? i18n.translate('xpack.painlessLab.hideRequestButtonLabel', { - defaultMessage: 'Hide API request', - }) - : i18n.translate('xpack.painlessLab.showRequestButtonLabel', { - defaultMessage: 'Show API request', - })} - - - - - + + + + + + setIsHelpOpen(!isHelpOpen)} + > + {i18n.translate('xpack.painlessLab.helpButtonLabel', { + defaultMessage: 'Help', + })} + + } + isOpen={isHelpOpen} + closePopover={() => setIsHelpOpen(false)} + panelPaddingSize="none" + withTitle + anchorPosition="upRight" + > + + + + + + + + {isRequestFlyoutOpen + ? i18n.translate('xpack.painlessLab.hideRequestButtonLabel', { + defaultMessage: 'Hide API request', + }) + : i18n.translate('xpack.painlessLab.showRequestButtonLabel', { + defaultMessage: 'Show API request', + })} + + + + ); } diff --git a/x-pack/plugins/painless_lab/public/application/components/output_pane/context_tab.tsx b/x-pack/plugins/painless_lab/public/application/components/output_pane/context_tab.tsx index 4a0c18733075f..b1ac68e1f5719 100644 --- a/x-pack/plugins/painless_lab/public/application/components/output_pane/context_tab.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/output_pane/context_tab.tsx @@ -26,18 +26,22 @@ interface Props { context: any; index: string; document: string; + query: string; onContextChange: (context: string) => void; onIndexChange: (index: string) => void; onDocumentChange: (document: string) => void; + onQueryChange: (query: string) => void; } export const ContextTab = ({ context, index, document, + query, onContextChange, onIndexChange, onDocumentChange, + onQueryChange, }: Props) => ( <> @@ -100,6 +104,56 @@ export const ContextTab = ({ onIndexChange(e.target.value)} /> )} + {/* Query DSL Code Editor */} + {'score'.indexOf(context) !== -1 && ( + + + {' '} + + + + } + labelAppend={ + + + {i18n.translate('xpack.painlessLab.queryFieldDocLinkText', { + defaultMessage: 'Query DSL docs', + })} + + + } + fullWidth + > + + + + + )} {['filter', 'score'].indexOf(context) !== -1 && ( void; onParametersChange: (change: string) => void; onIndexChange: (change: string) => void; onDocumentChange: (change: string) => void; + onQueryChange: (change: string) => void; } export function OutputPane({ @@ -40,10 +42,12 @@ export function OutputPane({ parameters, index, document, + query, onContextChange, onParametersChange, onIndexChange, onDocumentChange, + onQueryChange, }: Props) { const outputTabLabel = ( @@ -96,9 +100,11 @@ export function OutputPane({ context={context} index={index} document={document} + query={query} onContextChange={onContextChange} onIndexChange={onIndexChange} onDocumentChange={onDocumentChange} + onQueryChange={onQueryChange} /> ), }, diff --git a/x-pack/plugins/painless_lab/public/application/lib/format.ts b/x-pack/plugins/painless_lab/public/application/lib/format.ts index 0b941577c0ddc..5f98266ee9774 100644 --- a/x-pack/plugins/painless_lab/public/application/lib/format.ts +++ b/x-pack/plugins/painless_lab/public/application/lib/format.ts @@ -16,16 +16,17 @@ function prettifyPayload(payload = '', indentationLevel = 0) { * e.g. 1.0, is preserved instead of being coerced to an integer, e.g. 1. */ export function formatRequestPayload( - { code, context, parameters, index, document }: RequestPayloadConfig, + { code, context, parameters, index, document, query }: RequestPayloadConfig, format: PayloadFormat = PayloadFormat.UGLY ): string { const isAdvancedContext = context === 'filter' || context === 'score'; - let formattedCode; - let formattedParameters; - let formattedContext; - let formattedIndex; - let formattedDocument; + let formattedCode: string | undefined; + let formattedParameters: string | undefined; + let formattedContext: string | undefined; + let formattedIndex: string | undefined; + let formattedDocument: string | undefined; + let formattedQuery: string | undefined; if (format === PayloadFormat.UGLY) { formattedCode = JSON.stringify(code); @@ -33,6 +34,7 @@ export function formatRequestPayload( formattedContext = context; formattedIndex = index; formattedDocument = document; + formattedQuery = query; } else { // Triple quote the code because it's multiline. formattedCode = `"""${prettifyPayload(code, 4)}"""`; @@ -40,6 +42,7 @@ export function formatRequestPayload( formattedContext = prettifyPayload(context, 6); formattedIndex = prettifyPayload(index); formattedDocument = prettifyPayload(document, 4); + formattedQuery = prettifyPayload(query, 4); } const requestPayload = `{ @@ -56,7 +59,12 @@ export function formatRequestPayload( "context": "${formattedContext}", "context_setup": { "index": "${formattedIndex}", - "document": ${formattedDocument} + "document": ${formattedDocument}${ + query && context === 'score' + ? `, + "query": ${formattedQuery}` + : '' + } }` : `` } diff --git a/x-pack/plugins/painless_lab/public/index.scss b/x-pack/plugins/painless_lab/public/index.scss index 370ec54a85539..29a5761255278 100644 --- a/x-pack/plugins/painless_lab/public/index.scss +++ b/x-pack/plugins/painless_lab/public/index.scss @@ -1 +1 @@ -@import 'styles/index' +@import 'styles/index'; diff --git a/x-pack/plugins/painless_lab/public/styles/_index.scss b/x-pack/plugins/painless_lab/public/styles/_index.scss index 26f58cf82266a..733c5a4b56aef 100644 --- a/x-pack/plugins/painless_lab/public/styles/_index.scss +++ b/x-pack/plugins/painless_lab/public/styles/_index.scss @@ -1,10 +1,13 @@ +@import '@elastic/eui/src/components/header/variables'; /** - * 1. This is a very brittle way of preventing the editor and other content from disappearing - * behind the bottom bar. + * This is a very brittle way of preventing the editor and other content from disappearing + * behind the bottom bar. */ +$bottomBarHeight: calc(#{$euiSize} * 3); + .painlessLabBottomBarPlaceholder { - height: $euiSize * 3; /* [1] */ + height: $bottomBarHeight } .painlessLabRightPane { @@ -23,9 +26,19 @@ [role="tabpanel"] { height: 100%; + overflow-y: auto; } } .painlessLab__betaLabelContainer { line-height: 0; } + +.painlessLabMainContainer { + height: calc(100vh - calc(#{$euiHeaderChildSize} * 2) - #{$bottomBarHeight}); +} + +.painlessLabPanelsContainer { + // The panels container should adopt the height of the main container + height: 100%; +}