Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Painless Playground PoC #54578

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
fba34eb
Initial commit
kertal Jan 13, 2020
4cb4e5e
Migrate feature registration to NP
kertal Jan 13, 2020
c6e6712
Simplify code
kertal Jan 13, 2020
27fd28e
Add syntax highlighting
kertal Jan 14, 2020
7281471
Improve error response from server
kertal Jan 14, 2020
032b30c
Simplify code
kertal Jan 15, 2020
78d510c
Add Tabs to output
kertal Jan 15, 2020
a348fce
Add context API
kertal Jan 15, 2020
7055abe
Redesign
kertal Jan 15, 2020
eba55b3
Redesign
kertal Jan 16, 2020
b8a2064
Small Adaptions
kertal Jan 16, 2020
743d60d
Code improvements
kertal Jan 16, 2020
c1fd087
Code improvements
kertal Jan 16, 2020
f92dbaa
Change text
kertal Jan 16, 2020
9fa6a27
Fix translations
kertal Jan 16, 2020
02b37ef
Improve code
kertal Jan 16, 2020
987445f
Added feature flag
jloleysens Jan 17, 2020
4640b4d
A number of UI tweaks and updates
jloleysens Jan 17, 2020
6a4e8ca
Merge feedback PR by jloysenes
kertal Jan 20, 2020
c052211
Merge branch 'master' into kertal-pr-2020-01-13-painless-playground
elasticmachine Jan 21, 2020
39ee9e6
Fix types
kertal Jan 22, 2020
56a74a9
Split up components, restructure
kertal Jan 23, 2020
0554d13
Replace newline in results
kertal Jan 23, 2020
5a48070
Fix i18n
kertal Jan 23, 2020
6b270fb
Merge remote-tracking branch 'upstream/master' into kertal-pr-2020-01…
kertal Jan 23, 2020
7af0845
Merge remote-tracking branch 'upstream/master' into kertal-pr-2020-01…
kertal Jan 29, 2020
98f01f0
Improve issues found while preparing the demo
kertal Jan 30, 2020
8318b8c
Merge branch 'master' into kertal-pr-2020-01-13-painless-playground
elasticmachine Feb 6, 2020
4f7c9e2
Change dev_tools to devTools to accommodate change to plugin name.
cjcenizal Feb 6, 2020
7785ccd
Convert to 2-panel layout. Move Context tab into right panel. Use Eui…
cjcenizal Feb 7, 2020
27e5cac
Live-update output as the user enters input for a faster iteration lo…
cjcenizal Feb 8, 2020
fb3dc4b
Move response into a tab in the request flyout.
cjcenizal Feb 8, 2020
f9eb8c3
Remove unnecessary 'Test' button. Surface loading/success/error state…
cjcenizal Feb 8, 2020
8b09b7e
Add beta label to feature name in home registry and DevTools tab.
cjcenizal Feb 8, 2020
32a55b2
Refine Context tab form components and help text. Add doc links.
cjcenizal Feb 8, 2020
f9b53c4
Extract out parameters tab. Refactor output pane.
cjcenizal Feb 8, 2020
5191995
Add Help menu with links to docs and a button for resetting the script.
cjcenizal Feb 9, 2020
b7b12df
Improve parameters help text.
cjcenizal Feb 9, 2020
3165960
Make bottom bar smaller.
cjcenizal Feb 10, 2020
15e5064
Merge pull request #5 from cjcenizal/painless-playground-ui-suggestions
kertal Feb 13, 2020
fc41e51
Merge branch 'master' into kertal-pr-2020-01-13-painless-playground
cjcenizal Feb 13, 2020
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
1 change: 1 addition & 0 deletions x-pack/.i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"xpack.maps": "legacy/plugins/maps",
"xpack.ml": "legacy/plugins/ml",
"xpack.monitoring": "legacy/plugins/monitoring",
"xpack.painless_playground": "legacy/plugins/painless_playground",
"xpack.remoteClusters": ["plugins/remote_clusters", "legacy/plugins/remote_clusters"],
"xpack.reporting": ["plugins/reporting", "legacy/plugins/reporting"],
"xpack.rollupJobs": "legacy/plugins/rollup",
Expand Down
2 changes: 2 additions & 0 deletions x-pack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { security } from './legacy/plugins/security';
import { ml } from './legacy/plugins/ml';
import { tilemap } from './legacy/plugins/tilemap';
import { grokdebugger } from './legacy/plugins/grokdebugger';
import { painlessPlayground } from './legacy/plugins/painless_playground';
import { dashboardMode } from './legacy/plugins/dashboard_mode';
import { logstash } from './legacy/plugins/logstash';
import { beats } from './legacy/plugins/beats_management';
Expand Down Expand Up @@ -50,6 +51,7 @@ module.exports = function(kibana) {
ml(kibana),
tilemap(kibana),
grokdebugger(kibana),
painlessPlayground(kibana),
dashboardMode(kibana),
logstash(kibana),
beats(kibana),
Expand Down
11 changes: 11 additions & 0 deletions x-pack/legacy/plugins/painless_playground/common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

export const PLUGIN_ID = 'painless_playground';

export const API_ROUTE_EXECUTE = '/api/painless_playground/execute';

export const ADVANCED_SETTINGS_FLAG_NAME = 'devTools:enablePainlessPlayground';
50 changes: 50 additions & 0 deletions x-pack/legacy/plugins/painless_playground/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import { resolve } from 'path';
import { PLUGIN_ID, ADVANCED_SETTINGS_FLAG_NAME } from './common/constants';

import { registerLicenseChecker } from './server/register_license_checker';
import { registerExecuteRoute } from './server/register_execute_route';
import { Legacy } from '../../../../kibana';

export const painlessPlayground = (kibana: any) =>
new kibana.Plugin({
id: PLUGIN_ID,
publicDir: resolve(__dirname, 'public'),
require: ['kibana', 'elasticsearch', 'xpack_main'],
configPrefix: 'xpack.painless_playground',
config(Joi: any) {
return Joi.object({
enabled: Joi.boolean().default(true),
}).default();
},
uiExports: {
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
devTools: [resolve(__dirname, 'public/register')],
},
init: (server: Legacy.Server) => {
// Register feature flag
server.newPlatform.setup.core.uiSettings.register({
[ADVANCED_SETTINGS_FLAG_NAME]: {
name: i18n.translate('xpack.painless_playground.devTools.painlessPlaygroundTitle', {
defaultMessage: 'Painless Playground',
}),
description: i18n.translate(
'xpack.painless_playground.devTools.painlessPlaygroundDescription',
{
defaultMessage: 'Enable experimental Painless Playground.',
}
),
value: false,
category: ['Dev Tools'],
},
});

registerLicenseChecker(server);
registerExecuteRoute(server);
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';

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

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

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

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

export const painlessContextOptions = [
{
value: 'painless_test',
inputDisplay: defaultLabel,
dropdownDisplay: (
<>
<strong>{defaultLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">The script result will be converted to a string</p>
</EuiText>
</>
),
},
{
value: 'filter',
inputDisplay: filterLabel,
dropdownDisplay: (
<>
<strong>{filterLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">Use the context of a filter&rsquo;s script query</p>
</EuiText>
</>
),
},
{
value: 'score',
inputDisplay: scoreLabel,
dropdownDisplay: (
<>
<strong>{scoreLabel}</strong>
<EuiText size="s" color="subdued">
<p className="euiTextColor--subdued">
Use the context of a cript_score function in function_score query
</p>
</EuiText>
</>
),
},
];
39 changes: 39 additions & 0 deletions x-pack/legacy/plugins/painless_playground/public/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export interface Request {
script: {
source: string;
params?: Record<string, unknown>;
};
context?: string;
context_setup?: {
document: Record<string, unknown>;
index: string;
};
}

export interface Response {
error?: ExecutionError;
result?: string;
}

export type ExecutionErrorScriptStack = string[];

export interface ExecutionError {
script_stack?: ExecutionErrorScriptStack;
caused_by?: {
type: string;
reason: string;
};
message?: string;
}

export type JsonArray = JsonValue[];
export type JsonValue = null | boolean | number | string | JsonObject | JsonArray;

export interface JsonObject {
[key: string]: JsonValue;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { EuiSpacer, EuiPageContent } from '@elastic/eui';
import { CodeEditor } from '../../../../../../src/plugins/kibana_react/public';

interface Props {
code: string;
setCode: (code: string) => void;
}

export function Editor({ code, setCode }: Props) {
return (
<CodeEditor
languageId="painless"
// 99% width allows the editor to resize horizontally. 100% prevents it from resizing.
width="99%"
height="100%"
value={code}
onChange={setCode}
options={{
fontSize: 12,
minimap: {
enabled: false,
},
scrollBeyondLastLine: false,
wordWrap: 'on',
wrappingIndent: 'indent',
automaticLayout: true,
}}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useState } from 'react';
import {
EuiPopover,
EuiBottomBar,
EuiContextMenuItem,
EuiContextMenuPanel,
EuiFlexGroup,
EuiFlexItem,
EuiButtonEmpty,
EuiButton,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';

interface Props {
toggleRequestFlyout: () => void;
isRequestFlyoutOpen: boolean;
isLoading: boolean;
reset: () => void;
}

export function MainControls({
toggleRequestFlyout,
isRequestFlyoutOpen,
isLoading,
reset,
}: Props) {
const [isHelpOpen, setIsHelpOpen] = useState(false);

const items = [
<EuiContextMenuItem
key="walkthrough"
icon="popout"
href="https://www.elastic.co/guide/en/elasticsearch/painless/7.5/painless-walkthrough.html"
target="_blank"
onClick={() => setIsHelpOpen(false)}
>
{i18n.translate('xpack.painless_playground.walkthroughButtonLabel', {
defaultMessage: 'Walkthrough',
})}
</EuiContextMenuItem>,

<EuiContextMenuItem
key="api"
icon="popout"
href="https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-api-reference.html"
target="_blank"
onClick={() => setIsHelpOpen(false)}
>
{i18n.translate('xpack.painless_playground.apiReferenceButtonLabel', {
defaultMessage: 'API reference',
})}
</EuiContextMenuItem>,

<EuiContextMenuItem
key="languageSpec"
icon="popout"
href="https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-lang-spec.html"
target="_blank"
onClick={() => setIsHelpOpen(false)}
>
{i18n.translate('xpack.painless_playground.languageSpecButtonLabel', {
defaultMessage: 'Language spec',
})}
</EuiContextMenuItem>,

<EuiContextMenuItem
key="reset"
icon="bolt"
onClick={() => {
reset();
setIsHelpOpen(false);
}}
>
{i18n.translate('xpack.painless_playground.resetButtonLabel', {
defaultMessage: 'Reset script',
})}
</EuiContextMenuItem>,
];

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

<EuiBottomBar paddingSize="none">
<EuiFlexGroup gutterSize="s" justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s" justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiPopover
id="painlessPlaygroundHelpContextMenu"
button={
<EuiButtonEmpty
size="s"
iconType="help"
iconSide="left"
color="ghost"
onClick={() => setIsHelpOpen(!isHelpOpen)}
>
{i18n.translate('xpack.painless_playground.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.painless_playground.hideRequestButtonLabel', {
defaultMessage: 'Hide API request',
})
: i18n.translate('xpack.painless_playground.showRequestButtonLabel', {
defaultMessage: 'Show API request',
})}
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
</>
);
}
Loading