diff --git a/x-pack/legacy/plugins/painless_lab/common/constants.ts b/x-pack/legacy/plugins/painless_lab/common/constants.ts index 771d4979143fd..7179daedb338c 100644 --- a/x-pack/legacy/plugins/painless_lab/common/constants.ts +++ b/x-pack/legacy/plugins/painless_lab/common/constants.ts @@ -7,5 +7,3 @@ export const PLUGIN_ID = 'painlessLab'; export const API_ROUTE_EXECUTE = '/api/painless_lab/execute'; - -export const ADVANCED_SETTINGS_FLAG_NAME = 'devTools:enablePainlessLab'; diff --git a/x-pack/legacy/plugins/painless_lab/index.ts b/x-pack/legacy/plugins/painless_lab/index.ts index 3be4a25508bad..5372bbf37cf2e 100644 --- a/x-pack/legacy/plugins/painless_lab/index.ts +++ b/x-pack/legacy/plugins/painless_lab/index.ts @@ -3,9 +3,8 @@ * 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 { PLUGIN_ID } from './common/constants'; import { registerLicenseChecker } from './server/register_license_checker'; import { registerExecuteRoute } from './server/register_execute_route'; @@ -27,20 +26,6 @@ export const painlessLab = (kibana: any) => 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.painlessLab.devTools.painlessLabTitle', { - defaultMessage: 'Painless Lab', - }), - description: i18n.translate('xpack.painlessLab.devTools.painlessLabDescription', { - defaultMessage: 'Enable experimental Painless Lab.', - }), - value: false, - category: ['Dev Tools'], - }, - }); - registerLicenseChecker(server); registerExecuteRoute(server); }, diff --git a/x-pack/legacy/plugins/painless_lab/public/common/constants.tsx b/x-pack/legacy/plugins/painless_lab/public/common/constants.tsx index 4ff1f9fe340bf..b88ff1e226d27 100644 --- a/x-pack/legacy/plugins/painless_lab/public/common/constants.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/common/constants.tsx @@ -61,3 +61,66 @@ export const painlessContextOptions = [ ), }, ]; + +// 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)); + return distanceFromCircleCenter <= radius; +} + +boolean isOnCircle(def posX, def posY, def circleX, def circleY, def radius, def thickness, def squashY) { + double distanceFromCircleCenter = Math.sqrt(Math.pow(circleX - posX, 2) + Math.pow((circleY - posY) / squashY, 2)); + return ( + distanceFromCircleCenter >= radius - thickness + && distanceFromCircleCenter <= radius + thickness + ); +} + +def result = ''; +int charCount = 0; + +// Canvas dimensions +int width = 31; +int height = 31; +double halfWidth = Math.floor(width * 0.5); +double halfHeight = Math.floor(height * 0.5); + +// Style constants +double strokeWidth = 0.6; + +// Smiley face configuration +int headSize = 13; +double headSquashY = 0.78; +int eyePositionX = 10; +int eyePositionY = 12; +int eyeSize = 1; +int mouthSize = 15; +int mouthPositionX = width / 2; +int mouthPositionY = 5; +int mouthOffsetY = 11; + +for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + boolean isHead = isOnCircle(x, y, halfWidth, halfHeight, headSize, strokeWidth, headSquashY); + boolean isLeftEye = isInCircle(x, y, eyePositionX, eyePositionY, eyeSize); + boolean isRightEye = isInCircle(x, y, width - eyePositionX - 1, eyePositionY, eyeSize); + boolean isMouth = isOnCircle(x, y, mouthPositionX, mouthPositionY, mouthSize, strokeWidth, 1) && y > mouthPositionY + mouthOffsetY; + + if (isLeftEye || isRightEye || isMouth || isHead) { + result += "*"; + } else { + result += "."; + } + + result += " "; + + // Make sure the smiley face doesn't deform as the container changes width. + charCount++; + if (charCount % width === 0) { + result += "\\\\n"; + } + } +} + +return result; +`; diff --git a/x-pack/legacy/plugins/painless_lab/public/common/types.ts b/x-pack/legacy/plugins/painless_lab/public/common/types.ts index 825b0a7848136..697247415c428 100644 --- a/x-pack/legacy/plugins/painless_lab/public/common/types.ts +++ b/x-pack/legacy/plugins/painless_lab/public/common/types.ts @@ -3,25 +3,40 @@ * 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 ContextSetup { + params?: any; + document: Record; + index: string; +} + +// This should be an enumerated list +export type Context = string; + +export interface Script { + source: string; + params?: Record; +} + export interface Request { - script: { - source: string; - params?: Record; - }; - context?: string; - context_setup?: { - document: Record; - index: string; - }; + script: Script; + context?: Context; + context_setup?: ContextSetup; } export interface Response { - error?: ExecutionError; + error?: ExecutionError | Error; result?: string; } export type ExecutionErrorScriptStack = string[]; +export interface ExecutionErrorPosition { + start: number; + end: number; + offset: number; +} + export interface ExecutionError { script_stack?: ExecutionErrorScriptStack; caused_by?: { @@ -29,6 +44,8 @@ export interface ExecutionError { reason: string; }; message?: string; + position: ExecutionErrorPosition; + script: string; } export type JsonArray = JsonValue[]; @@ -37,3 +54,8 @@ export type JsonValue = null | boolean | number | string | JsonObject | JsonArra export interface JsonObject { [key: string]: JsonValue; } + +export type ContextChangeHandler = (change: { + context?: Partial; + contextSetup?: Partial; +}) => void; diff --git a/x-pack/legacy/plugins/painless_lab/public/components/editor.tsx b/x-pack/legacy/plugins/painless_lab/public/components/editor.tsx index f77f4ab888be6..8c2f07e539871 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/editor.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/editor.tsx @@ -4,7 +4,6 @@ * 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 { diff --git a/x-pack/legacy/plugins/painless_lab/public/components/main.tsx b/x-pack/legacy/plugins/painless_lab/public/components/main.tsx index a1c6a9f0080f7..cc91f9d93d5bf 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/main.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/main.tsx @@ -4,136 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ +import { HttpSetup } from 'kibana/public'; import React, { useState, useEffect } from 'react'; -import { debounce } from 'lodash'; -import { - EuiCodeBlock, - EuiFlexGroup, - EuiFlexItem, - EuiTabbedContent, - EuiTitle, - EuiSpacer, - EuiPageContent, - EuiFlyout, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { buildRequestPayload, formatJson, getFromLocalStorage } from '../lib/helpers'; -import { Request, Response } from '../common/types'; +import { ContextChangeHandler } from '../common/types'; import { OutputPane } from './output_pane'; import { MainControls } from './main_controls'; import { Editor } from './editor'; import { RequestFlyout } from './request_flyout'; +import { useSubmitCode } from '../hooks'; +import { exampleScript } from '../common/constants'; -let _mostRecentRequestId = 0; - -const submit = async (code, context, contextSetup, executeCode, setResponse, setIsLoading) => { - // Prevent an older request that resolves after a more recent request from clobbering it. - // We store the resulting ID in this closure for comparison when the request resolves. - const requestId = ++_mostRecentRequestId; - setIsLoading(true); - - try { - localStorage.setItem('painlessLabCode', code); - localStorage.setItem('painlessLabContext', context); - localStorage.setItem('painlessLabContextSetup', JSON.stringify(contextSetup)); - const response = await executeCode(buildRequestPayload(code, context, contextSetup)); - - if (_mostRecentRequestId === requestId) { - if (response.error) { - setResponse({ - success: undefined, - error: response.error, - }); - } else { - setResponse({ - success: response, - error: undefined, - }); - } - setIsLoading(false); - } - } catch (error) { - if (_mostRecentRequestId === requestId) { - setResponse({ - success: undefined, - error: { error }, - }); - setIsLoading(false); - } - } -}; - -const debouncedSubmit = debounce(submit, 800); - -// Render a smiley face as an example. -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)); - return distanceFromCircleCenter <= radius; -} - -boolean isOnCircle(def posX, def posY, def circleX, def circleY, def radius, def thickness, def squashY) { - double distanceFromCircleCenter = Math.sqrt(Math.pow(circleX - posX, 2) + Math.pow((circleY - posY) / squashY, 2)); - return ( - distanceFromCircleCenter >= radius - thickness - && distanceFromCircleCenter <= radius + thickness - ); -} - -def result = ''; -int charCount = 0; - -// Canvas dimensions -int width = 31; -int height = 31; -double halfWidth = Math.floor(width * 0.5); -double halfHeight = Math.floor(height * 0.5); - -// Style constants -double strokeWidth = 0.6; - -// Smiley face configuration -int headSize = 13; -double headSquashY = 0.78; -int eyePositionX = 10; -int eyePositionY = 12; -int eyeSize = 1; -int mouthSize = 15; -int mouthPositionX = width / 2; -int mouthPositionY = 5; -int mouthOffsetY = 11; - -for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - boolean isHead = isOnCircle(x, y, halfWidth, halfHeight, headSize, strokeWidth, headSquashY); - boolean isLeftEye = isInCircle(x, y, eyePositionX, eyePositionY, eyeSize); - boolean isRightEye = isInCircle(x, y, width - eyePositionX - 1, eyePositionY, eyeSize); - boolean isMouth = isOnCircle(x, y, mouthPositionX, mouthPositionY, mouthSize, strokeWidth, 1) && y > mouthPositionY + mouthOffsetY; - - if (isLeftEye || isRightEye || isMouth || isHead) { - result += "*"; - } else { - result += "."; - } - - result += " "; - - // Make sure the smiley face doesn't deform as the container changes width. - charCount++; - if (charCount % width === 0) { - result += "\\\\n"; - } - } +interface Props { + http: HttpSetup; } -return result; -`; - -export function Main({ executeCode }: { executeCode: (payload: Request) => Promise }) { +export function Main({ http }: Props) { const [code, setCode] = useState(getFromLocalStorage('painlessLabCode', exampleScript)); - const [response, setResponse] = useState({ error: undefined, success: undefined }); const [isRequestFlyoutOpen, setRequestFlyoutOpen] = useState(false); - const [isLoading, setIsLoading] = useState(false); const [context, setContext] = useState( getFromLocalStorage('painlessLabContext', 'painless_test_without_params') @@ -143,15 +33,29 @@ export function Main({ executeCode }: { executeCode: (payload: Request) => Promi getFromLocalStorage('painlessLabContextSetup', {}, true) ); + const { inProgress, response, submit } = useSubmitCode(http); + // Live-update the output as the user changes the input code. useEffect(() => { - debouncedSubmit(code, context, contextSetup, executeCode, setResponse, setIsLoading); - }, [code, context, contextSetup, executeCode]); + submit(code, context, contextSetup); + }, [submit, code, context, contextSetup]); const toggleRequestFlyout = () => { setRequestFlyoutOpen(!isRequestFlyoutOpen); }; + const contextChangeHandler: ContextChangeHandler = ({ + context: nextContext, + contextSetup: nextContextSetup, + }) => { + if (nextContext) { + setContext(nextContext); + } + if (nextContextSetup) { + setContextSetup(nextContextSetup); + } + }; + return ( <> @@ -171,17 +75,15 @@ export function Main({ executeCode }: { executeCode: (payload: Request) => Promi submit(code, context, contextSetup, executeCode, setResponse)} - isLoading={isLoading} + isLoading={inProgress} toggleRequestFlyout={toggleRequestFlyout} isRequestFlyoutOpen={isRequestFlyoutOpen} reset={() => setCode(exampleScript)} @@ -191,7 +93,7 @@ export function Main({ executeCode }: { executeCode: (payload: Request) => Promi setRequestFlyoutOpen(false)} requestBody={formatJson(buildRequestPayload(code, context, contextSetup))} - response={formatJson(response.success || response.error)} + response={response ? formatJson(response.result || response.error) : ''} /> )} diff --git a/x-pack/legacy/plugins/painless_lab/public/components/main_controls.tsx b/x-pack/legacy/plugins/painless_lab/public/components/main_controls.tsx index 8ee0d7fb09275..9e24fd9fb5a93 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/main_controls.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/main_controls.tsx @@ -12,9 +12,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, - EuiButton, } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; interface Props { @@ -24,12 +22,7 @@ interface Props { reset: () => void; } -export function MainControls({ - toggleRequestFlyout, - isRequestFlyoutOpen, - isLoading, - reset, -}: Props) { +export function MainControls({ toggleRequestFlyout, isRequestFlyoutOpen, reset }: Props) { const [isHelpOpen, setIsHelpOpen] = useState(false); const items = [ diff --git a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/context_tab.tsx b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/context_tab.tsx index 12c56577b8db6..06325c5c2661e 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/context_tab.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/context_tab.tsx @@ -21,16 +21,15 @@ import { i18n } from '@kbn/i18n'; import { CodeEditor } from '../../../../../../../src/plugins/kibana_react/public'; import { painlessContextOptions } from '../../common/constants'; +import { ContextChangeHandler, ContextSetup } from '../../common/types'; interface Props { context: string; - contextSetup: Record; - setContext: (context: string) => void; - setContextSetup: (contextSetup: Record) => void; - renderMainControls: () => React.ReactElement; + contextSetup: ContextSetup; + onContextChange: ContextChangeHandler; } -export function ContextTab({ context, contextSetup, setContext, setContextSetup }: Props) { +export function ContextTab({ context, contextSetup, onContextChange }: Props) { return ( <> @@ -67,7 +66,7 @@ export function ContextTab({ context, contextSetup, setContext, setContextSetup setContext(value)} + onChange={(value: any) => onContextChange({ context: value })} itemLayoutAlign="top" hasDividers fullWidth @@ -94,9 +93,11 @@ export function ContextTab({ context, contextSetup, setContext, setContextSetup - setContextSetup(Object.assign({}, contextSetup, { index: e.target.value })) - } + onChange={e => { + onContextChange({ + contextSetup: Object.assign({}, contextSetup, { index: e.target.value }), + }); + }} /> )} @@ -123,10 +124,12 @@ export function ContextTab({ context, contextSetup, setContext, setContextSetup - setContextSetup(Object.assign({}, contextSetup, { document: value })) - } + value={JSON.stringify(contextSetup.document, null, 2)} + onChange={(value: string) => { + onContextChange({ + contextSetup: Object.assign({}, contextSetup, { document: value }), + }); + }} options={{ fontSize: 12, minimap: { diff --git a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_pane.tsx b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_pane.tsx index 55aa8f5b220e8..db6e58124d74a 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_pane.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_pane.tsx @@ -15,28 +15,26 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { formatJson, formatResponse } from '../../lib/helpers'; -import { Response } from '../../common/types'; +import { Response, ContextSetup, Context, ContextChangeHandler } from '../../common/types'; import { OutputTab } from './output_tab'; import { ParametersTab } from './parameters_tab'; import { ContextTab } from './context_tab'; -export function OutputPane({ - response, - context, - contextSetup, - setContext, - setContextSetup, - isLoading, -}: { +interface Props { + context: Context; + contextSetup: ContextSetup; + isLoading: boolean; + onContextChange: ContextChangeHandler; response?: Response; -}) { +} + +export function OutputPane({ response, context, contextSetup, onContextChange, isLoading }: Props) { const outputTabLabel = ( {isLoading ? ( - ) : response.error ? ( + ) : response && response.error ? ( ) : ( @@ -59,7 +57,8 @@ export function OutputPane({ tabs={[ { id: 'output', - name: outputTabLabel, + // TODO: Currently this causes an Eui prop error because it is expecting string, but we give it React.ReactNode - should fix. + name: outputTabLabel as any, content: , }, { @@ -68,12 +67,7 @@ export function OutputPane({ defaultMessage: 'Parameters', }), content: ( - + ), }, { @@ -85,8 +79,7 @@ export function OutputPane({ ), }, diff --git a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_tab.tsx b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_tab.tsx index 4b69e7969c924..55bb9a34c78b6 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_tab.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/output_tab.tsx @@ -6,7 +6,6 @@ import React from 'react'; import { EuiCodeBlock, EuiSpacer } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { formatResponse } from '../../lib/helpers'; import { Response } from '../../common/types'; @@ -15,12 +14,12 @@ interface Props { response?: Response; } -export function OutputTab({ response = {} }: Props) { +export function OutputTab({ response }: Props) { return ( <> - {formatResponse(response.success || response.error)} + {formatResponse(response)} ); diff --git a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/parameters_tab.tsx b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/parameters_tab.tsx index abfb99842846e..b731ba0cbdaa7 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/output_pane/parameters_tab.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/output_pane/parameters_tab.tsx @@ -16,17 +16,14 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { CodeEditor } from '../../../../../../../src/plugins/kibana_react/public'; -import { painlessContextOptions } from '../../common/constants'; +import { ContextChangeHandler, ContextSetup } from '../../common/types'; interface Props { - context: string; - contextSetup: Record; - setContext: (context: string) => void; - setContextSetup: (contextSetup: Record) => void; - renderMainControls: () => React.ReactElement; + contextSetup: ContextSetup; + onContextChange: ContextChangeHandler; } -export function ParametersTab({ context, contextSetup, setContext, setContextSetup }: Props) { +export function ParametersTab({ contextSetup, onContextChange }: Props) { return ( <> @@ -68,7 +65,7 @@ export function ParametersTab({ context, contextSetup, setContext, setContextSet languageId="javascript" height={600} value={contextSetup.params} - onChange={(value: string) => setContextSetup({ params: value })} + onChange={(value: string) => onContextChange({ contextSetup: { params: value } })} options={{ fontSize: 12, minimap: { diff --git a/x-pack/legacy/plugins/painless_lab/public/components/request_flyout.tsx b/x-pack/legacy/plugins/painless_lab/public/components/request_flyout.tsx index def4ae2876bb6..2d0262503b162 100644 --- a/x-pack/legacy/plugins/painless_lab/public/components/request_flyout.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/components/request_flyout.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { EuiCodeBlock, EuiTabbedContent, diff --git a/x-pack/legacy/plugins/painless_lab/public/hooks/index.ts b/x-pack/legacy/plugins/painless_lab/public/hooks/index.ts new file mode 100644 index 0000000000000..159ff96d2278c --- /dev/null +++ b/x-pack/legacy/plugins/painless_lab/public/hooks/index.ts @@ -0,0 +1,7 @@ +/* + * 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 { useSubmitCode } from './use_submit_code'; diff --git a/x-pack/legacy/plugins/painless_lab/public/hooks/use_submit_code.ts b/x-pack/legacy/plugins/painless_lab/public/hooks/use_submit_code.ts new file mode 100644 index 0000000000000..87b2fb0a7b2bf --- /dev/null +++ b/x-pack/legacy/plugins/painless_lab/public/hooks/use_submit_code.ts @@ -0,0 +1,62 @@ +/* + * 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 { useRef, useCallback, useState } from 'react'; +import { HttpSetup } from 'kibana/public'; +import { debounce } from 'lodash'; +import { Response } from '../common/types'; +import { buildRequestPayload } from '../lib/helpers'; +import { executeCode } from '../lib/execute_code'; + +const DEBOUNCE_MS = 800; + +export const useSubmitCode = (http: HttpSetup) => { + const currentRequestIdRef = useRef(0); + const [response, setResponse] = useState(undefined); + const [inProgress, setInProgress] = useState(false); + + const submit = useCallback( + debounce( + async (code: string, context: string, contextSetup: Record) => { + setInProgress(true); + + // Prevent an older request that resolves after a more recent request from clobbering it. + // We store the resulting ID in this closure for comparison when the request resolves. + const requestId = ++currentRequestIdRef.current; + + try { + localStorage.setItem('painlessLabCode', code); + localStorage.setItem('painlessLabContext', context); + localStorage.setItem('painlessLabContextSetup', JSON.stringify(contextSetup)); + const result = await executeCode(http, buildRequestPayload(code, context, contextSetup)); + + if (currentRequestIdRef.current === requestId) { + setResponse(result); + setInProgress(false); + } + // else ignore this response... + } catch (error) { + if (currentRequestIdRef.current === requestId) { + setResponse({ + error, + }); + setInProgress(false); + } + // else ignore this response... + } + }, + DEBOUNCE_MS, + { trailing: true } + ), + [http] + ); + + return { + response, + inProgress, + submit, + }; +}; diff --git a/x-pack/legacy/plugins/painless_lab/public/lib/helpers.ts b/x-pack/legacy/plugins/painless_lab/public/lib/helpers.ts index ddc633b2e99d7..d5c35476948d0 100644 --- a/x-pack/legacy/plugins/painless_lab/public/lib/helpers.ts +++ b/x-pack/legacy/plugins/painless_lab/public/lib/helpers.ts @@ -75,7 +75,6 @@ export function formatResponse(response?: Response): string { if (!response) { return ''; } - if (typeof response.result === 'string') { return response.result.replace(/\\n/g, '\n'); } else if (response.error) { @@ -84,15 +83,23 @@ export function formatResponse(response?: Response): string { return formatJson(response); } -export function formatExecutionError(json: ExecutionError): string { - if (json.script_stack && json.caused_by) { - return `Unhandled Exception ${json.caused_by.type} +export function formatExecutionError(executionErrorOrError: ExecutionError | Error): string { + if (executionErrorOrError instanceof Error) { + return executionErrorOrError.message; + } + + if ( + executionErrorOrError.script_stack && + executionErrorOrError.caused_by && + executionErrorOrError.position + ) { + return `Unhandled Exception ${executionErrorOrError.caused_by.type} -${json.caused_by.reason} +${executionErrorOrError.caused_by.reason} -Located at: -${formatJson(json.script_stack)} +Stack: +${formatJson(executionErrorOrError.script_stack)} `; } - return formatJson(json); + return formatJson(executionErrorOrError); } diff --git a/x-pack/legacy/plugins/painless_lab/public/register.tsx b/x-pack/legacy/plugins/painless_lab/public/register.tsx index 3f3561e1f52bb..1f5446bd07c27 100644 --- a/x-pack/legacy/plugins/painless_lab/public/register.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/register.tsx @@ -12,7 +12,6 @@ import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; import { npSetup, npStart } from 'ui/new_platform'; import { registerPainless } from './register_painless'; import { FeatureCatalogueCategory } from '../../../../../src/plugins/home/public'; -import { ADVANCED_SETTINGS_FLAG_NAME } from '../common/constants'; npSetup.plugins.home.featureCatalogue.register({ id: 'painlessLab', @@ -28,12 +27,8 @@ npSetup.plugins.home.featureCatalogue.register({ category: FeatureCatalogueCategory.ADMIN, }); -npSetup.core.uiSettings.get$(ADVANCED_SETTINGS_FLAG_NAME, false).subscribe(value => { - // eslint-disable-next-line - console.log('use this to figure out whether we should register', value); -}); - npSetup.plugins.devTools.register({ + id: 'painless_lab', order: 7, title: ( @@ -54,7 +49,7 @@ npSetup.plugins.devTools.register({ /> - ), + ) as any, enableRouting: false, disabled: false, tooltipContent: xpackInfo.get('features.painlessLab.message'), diff --git a/x-pack/legacy/plugins/painless_lab/public/register_painless.ts b/x-pack/legacy/plugins/painless_lab/public/register_painless.ts index 16c799ff32a2b..a3952c1941c6e 100644 --- a/x-pack/legacy/plugins/painless_lab/public/register_painless.ts +++ b/x-pack/legacy/plugins/painless_lab/public/register_painless.ts @@ -190,6 +190,6 @@ function getPainlessLanguage() { export function registerPainless() { // TODO: Referring to `window.monaco` is a temporary fix for the imported `monaco` module not // being the same one in use by the editor. - window.monaco.languages.register({ id: LANGUAGE_ID }); - window.monaco.languages.setMonarchTokensProvider(LANGUAGE_ID, getPainlessLanguage()); + (window as any).monaco.languages.register({ id: LANGUAGE_ID }); + (window as any).monaco.languages.setMonarchTokensProvider(LANGUAGE_ID, getPainlessLanguage()); } diff --git a/x-pack/legacy/plugins/painless_lab/public/render_app.tsx b/x-pack/legacy/plugins/painless_lab/public/render_app.tsx index f6c0a5b6069b0..78102fd1002e5 100644 --- a/x-pack/legacy/plugins/painless_lab/public/render_app.tsx +++ b/x-pack/legacy/plugins/painless_lab/public/render_app.tsx @@ -9,7 +9,6 @@ import { CoreStart } from 'kibana/public'; import { render, unmountComponentAtNode } from 'react-dom'; import { Main } from './components/main'; import { createKibanaReactContext } from '../../../../../src/plugins/kibana_react/public'; -import { executeCode } from './lib/execute_code'; export function renderApp(element: any, { http, i18n, uiSettings }: CoreStart) { const { Provider: KibanaReactContextProvider } = createKibanaReactContext({ @@ -18,7 +17,7 @@ export function renderApp(element: any, { http, i18n, uiSettings }: CoreStart) { render( -
executeCode(http, payload)} /> +
, element