Skip to content

Commit

Permalink
Add query parameter to score context (#60414)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
jloleysens authored Mar 18, 2020
1 parent f89b489 commit f5bec8e
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ export const painlessContextOptions = [
<>
<strong>{defaultLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">The script result will be converted to a string</p>
<p className="euiTextColor--subdued">
{i18n.translate('xpack.painlessLab.context.scoreLabel', {
defaultMessage: 'The script result will be converted to a string',
})}
</p>
</EuiText>
</>
),
Expand All @@ -41,7 +45,11 @@ export const painlessContextOptions = [
<>
<strong>{filterLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">Use the context of a filter&rsquo;s script query</p>
<p className="euiTextColor--subdued">
{i18n.translate('xpack.painlessLab.context.scoreLabel', {
defaultMessage: "Use the context of a filter's script query",
})}
</p>
</EuiText>
</>
),
Expand All @@ -54,7 +62,9 @@ export const painlessContextOptions = [
<strong>{scoreLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">
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',
})}
</p>
</EuiText>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface RequestPayloadConfig {
parameters?: string;
index?: string;
document?: string;
query?: string;
}

export enum PayloadFormat {
Expand Down
24 changes: 14 additions & 10 deletions x-pack/plugins/painless_lab/public/application/components/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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 (
<>
<EuiFlexGroup gutterSize="s">
<div className="painlessLabMainContainer">
<EuiFlexGroup className="painlessLabPanelsContainer" responsive={false} gutterSize="none">
<EuiFlexItem>
<EuiTitle className="euiScreenReaderOnly">
<h1>
Expand All @@ -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}
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand All @@ -108,13 +115,10 @@ export function Main({ http }: Props) {
{isRequestFlyoutOpen && (
<RequestFlyout
onClose={() => setRequestFlyoutOpen(false)}
requestBody={formatRequestPayload(
{ code, context, document, index, parameters },
PayloadFormat.PRETTY
)}
requestBody={formatRequestPayload(state, PayloadFormat.PRETTY)}
response={response ? formatJson(response.result || response.error) : ''}
/>
)}
</>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,58 +77,54 @@ export function MainControls({ toggleRequestFlyout, isRequestFlyoutOpen, reset }
];

return (
<>
<div className="painlessLabBottomBarPlaceholder" />

<EuiBottomBar paddingSize="s">
<EuiFlexGroup gutterSize="s" justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s" justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiPopover
id="painlessLabHelpContextMenu"
button={
<EuiButtonEmpty
size="s"
iconType="help"
iconSide="left"
color="ghost"
onClick={() => setIsHelpOpen(!isHelpOpen)}
>
{i18n.translate('xpack.painlessLab.helpButtonLabel', {
defaultMessage: 'Help',
})}
</EuiButtonEmpty>
}
isOpen={isHelpOpen}
closePopover={() => setIsHelpOpen(false)}
panelPaddingSize="none"
withTitle
anchorPosition="upRight"
>
<EuiContextMenuPanel items={items} />
</EuiPopover>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="s"
color="ghost"
onClick={toggleRequestFlyout}
data-test-subj="btnViewRequest"
>
{isRequestFlyoutOpen
? i18n.translate('xpack.painlessLab.hideRequestButtonLabel', {
defaultMessage: 'Hide API request',
})
: i18n.translate('xpack.painlessLab.showRequestButtonLabel', {
defaultMessage: 'Show API request',
})}
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
</>
<EuiBottomBar paddingSize="s">
<EuiFlexGroup gutterSize="s" justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s" justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiPopover
id="painlessLabHelpContextMenu"
button={
<EuiButtonEmpty
size="s"
iconType="help"
iconSide="left"
color="ghost"
onClick={() => setIsHelpOpen(!isHelpOpen)}
>
{i18n.translate('xpack.painlessLab.helpButtonLabel', {
defaultMessage: 'Help',
})}
</EuiButtonEmpty>
}
isOpen={isHelpOpen}
closePopover={() => setIsHelpOpen(false)}
panelPaddingSize="none"
withTitle
anchorPosition="upRight"
>
<EuiContextMenuPanel items={items} />
</EuiPopover>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="s"
color="ghost"
onClick={toggleRequestFlyout}
data-test-subj="btnViewRequest"
>
{isRequestFlyoutOpen
? i18n.translate('xpack.painlessLab.hideRequestButtonLabel', {
defaultMessage: 'Hide API request',
})
: i18n.translate('xpack.painlessLab.showRequestButtonLabel', {
defaultMessage: 'Show API request',
})}
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) => (
<>
<EuiSpacer size="m" />
Expand Down Expand Up @@ -100,6 +104,56 @@ export const ContextTab = ({
<EuiFieldText fullWidth value={index || ''} onChange={e => onIndexChange(e.target.value)} />
</EuiFormRow>
)}
{/* Query DSL Code Editor */}
{'score'.indexOf(context) !== -1 && (
<EuiFormRow
label={
<EuiToolTip
content={i18n.translate('xpack.painlessLab.queryFieldTooltipText', {
defaultMessage:
'Use query to specify that that _score will be used to calculate score.',
})}
>
<span>
<FormattedMessage id="xpack.painlessLab.queryFieldLabel" defaultMessage="Query" />{' '}
<EuiIcon type="questionInCircle" color="subdued" />
</span>
</EuiToolTip>
}
labelAppend={
<EuiText size="xs">
<EuiLink
href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html"
target="_blank"
>
{i18n.translate('xpack.painlessLab.queryFieldDocLinkText', {
defaultMessage: 'Query DSL docs',
})}
</EuiLink>
</EuiText>
}
fullWidth
>
<EuiPanel paddingSize="s">
<CodeEditor
languageId="json"
height={150}
value={query}
onChange={onQueryChange}
options={{
fontSize: 12,
minimap: {
enabled: false,
},
scrollBeyondLastLine: false,
wordWrap: 'on',
wrappingIndent: 'indent',
automaticLayout: true,
}}
/>
</EuiPanel>
</EuiFormRow>
)}
{['filter', 'score'].indexOf(context) !== -1 && (
<EuiFormRow
label={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ interface Props {
parameters: string;
index: string;
document: string;
query: string;
onContextChange: (change: string) => void;
onParametersChange: (change: string) => void;
onIndexChange: (change: string) => void;
onDocumentChange: (change: string) => void;
onQueryChange: (change: string) => void;
}

export function OutputPane({
Expand All @@ -40,10 +42,12 @@ export function OutputPane({
parameters,
index,
document,
query,
onContextChange,
onParametersChange,
onIndexChange,
onDocumentChange,
onQueryChange,
}: Props) {
const outputTabLabel = (
<EuiFlexGroup gutterSize="s" alignItems="center">
Expand Down Expand Up @@ -96,9 +100,11 @@ export function OutputPane({
context={context}
index={index}
document={document}
query={query}
onContextChange={onContextChange}
onIndexChange={onIndexChange}
onDocumentChange={onDocumentChange}
onQueryChange={onQueryChange}
/>
),
},
Expand Down
22 changes: 15 additions & 7 deletions x-pack/plugins/painless_lab/public/application/lib/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,33 @@ 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);
formattedParameters = parameters;
formattedContext = context;
formattedIndex = index;
formattedDocument = document;
formattedQuery = query;
} else {
// Triple quote the code because it's multiline.
formattedCode = `"""${prettifyPayload(code, 4)}"""`;
formattedParameters = prettifyPayload(parameters, 4);
formattedContext = prettifyPayload(context, 6);
formattedIndex = prettifyPayload(index);
formattedDocument = prettifyPayload(document, 4);
formattedQuery = prettifyPayload(query, 4);
}

const requestPayload = `{
Expand All @@ -56,7 +59,12 @@ export function formatRequestPayload(
"context": "${formattedContext}",
"context_setup": {
"index": "${formattedIndex}",
"document": ${formattedDocument}
"document": ${formattedDocument}${
query && context === 'score'
? `,
"query": ${formattedQuery}`
: ''
}
}`
: ``
}
Expand Down
Loading

0 comments on commit f5bec8e

Please sign in to comment.