From e2285327ad9801c6d55883426e4959590bb4ed8f Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Wed, 19 Oct 2022 14:10:20 -0700 Subject: [PATCH] [Feature] Expressions example plugin (#1438) (#2602) * feat(Expressions): Initial demo plugin Signed-off-by: Ashwin Pc * feat(Expressions): Adds handlers tab Signed-off-by: Ashwin Pc * feat(Expressions): Adds playground tab Signed-off-by: Ashwin Pc * chore: Better expression playground messaging Signed-off-by: Ashwin Pc * feat(Expressions): Adds expression explorer Signed-off-by: Ashwin Pc * feat(Expressions): A better explorer Signed-off-by: Ashwin Pc * fix(Expressions): Fix basic demo abort error Signed-off-by: Ashwin Pc * Updates readme and fixes rendering visualizations Signed-off-by: Ashwin Pc (cherry picked from commit b7ca138c231d87d05062cfd25cfecf80e53ecac5) Co-authored-by: Ashwin P Chandran --- examples/expressions_example/.eslintrc.js | 12 ++ examples/expressions_example/.i18nrc.json | 7 + examples/expressions_example/README.md | 11 ++ .../expression_functions/action/index.ts | 7 + .../action/quick_form_fn.ts | 53 ++++++ .../action/quick_form_renderer.tsx | 61 +++++++ .../expression_functions/basic/index.ts | 7 + .../expression_functions/basic/sleep.ts | 31 ++++ .../expression_functions/basic/square.ts | 18 ++ .../common/expression_functions/index.ts | 8 + .../expression_functions/render/avatar_fn.ts | 52 ++++++ .../render/avatar_renderer.tsx | 30 ++++ .../expression_functions/render/index.ts | 7 + examples/expressions_example/common/index.ts | 7 + .../opensearch_dashboards.json | 14 ++ .../public/application.tsx | 32 ++++ .../public/components/actions_tab.tsx | 53 ++++++ .../public/components/app.tsx | 138 +++++++++++++++ .../public/components/basic_tab.tsx | 107 ++++++++++++ .../public/components/explorer_section.tsx | 78 +++++++++ .../public/components/explorer_tab.tsx | 163 ++++++++++++++++++ .../public/components/playground_section.tsx | 140 +++++++++++++++ .../public/components/playground_tab.tsx | 53 ++++++ .../public/components/render_tab.tsx | 89 ++++++++++ .../expressions_example/public/index.scss | 13 ++ examples/expressions_example/public/index.ts | 15 ++ examples/expressions_example/public/plugin.ts | 92 ++++++++++ examples/expressions_example/public/types.ts | 30 ++++ src/plugins/expressions/README.md | 86 ++++++--- .../expressions/expressions_example.png | Bin 0 -> 85702 bytes .../public/_expression_renderer.scss | 5 + .../public/react_expression_renderer.tsx | 3 +- src/plugins/expressions/public/render.ts | 2 +- 33 files changed, 1400 insertions(+), 24 deletions(-) create mode 100644 examples/expressions_example/.eslintrc.js create mode 100644 examples/expressions_example/.i18nrc.json create mode 100755 examples/expressions_example/README.md create mode 100644 examples/expressions_example/common/expression_functions/action/index.ts create mode 100644 examples/expressions_example/common/expression_functions/action/quick_form_fn.ts create mode 100644 examples/expressions_example/common/expression_functions/action/quick_form_renderer.tsx create mode 100644 examples/expressions_example/common/expression_functions/basic/index.ts create mode 100644 examples/expressions_example/common/expression_functions/basic/sleep.ts create mode 100644 examples/expressions_example/common/expression_functions/basic/square.ts create mode 100644 examples/expressions_example/common/expression_functions/index.ts create mode 100644 examples/expressions_example/common/expression_functions/render/avatar_fn.ts create mode 100644 examples/expressions_example/common/expression_functions/render/avatar_renderer.tsx create mode 100644 examples/expressions_example/common/expression_functions/render/index.ts create mode 100644 examples/expressions_example/common/index.ts create mode 100644 examples/expressions_example/opensearch_dashboards.json create mode 100644 examples/expressions_example/public/application.tsx create mode 100644 examples/expressions_example/public/components/actions_tab.tsx create mode 100644 examples/expressions_example/public/components/app.tsx create mode 100644 examples/expressions_example/public/components/basic_tab.tsx create mode 100644 examples/expressions_example/public/components/explorer_section.tsx create mode 100644 examples/expressions_example/public/components/explorer_tab.tsx create mode 100644 examples/expressions_example/public/components/playground_section.tsx create mode 100644 examples/expressions_example/public/components/playground_tab.tsx create mode 100644 examples/expressions_example/public/components/render_tab.tsx create mode 100644 examples/expressions_example/public/index.scss create mode 100644 examples/expressions_example/public/index.ts create mode 100644 examples/expressions_example/public/plugin.ts create mode 100644 examples/expressions_example/public/types.ts create mode 100644 src/plugins/expressions/expressions_example.png diff --git a/examples/expressions_example/.eslintrc.js b/examples/expressions_example/.eslintrc.js new file mode 100644 index 000000000000..d40ef4ec9091 --- /dev/null +++ b/examples/expressions_example/.eslintrc.js @@ -0,0 +1,12 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +module.exports = { + root: true, + extends: ['@elastic/eslint-config-kibana', 'plugin:@elastic/eui/recommended'], + rules: { + '@osd/eslint/require-license-header': 'off', + }, +}; diff --git a/examples/expressions_example/.i18nrc.json b/examples/expressions_example/.i18nrc.json new file mode 100644 index 000000000000..a4777b0c81b7 --- /dev/null +++ b/examples/expressions_example/.i18nrc.json @@ -0,0 +1,7 @@ +{ + "prefix": "expressionsExample", + "paths": { + "expressionsExample": "." + }, + "translations": ["translations/ja-JP.json"] +} diff --git a/examples/expressions_example/README.md b/examples/expressions_example/README.md new file mode 100755 index 000000000000..009a67cd6504 --- /dev/null +++ b/examples/expressions_example/README.md @@ -0,0 +1,11 @@ +# expressions_example + +An OpenSearch Dashboards example plugin to demonstrate the expressions plugin + +--- + +## Development + +See the [OpenSearch Dashboards contributing +guide](https://github.com/opensearch-project/OpenSearch-Dashboards/blob/master/CONTRIBUTING.md) for instructions +setting up your development environment. diff --git a/examples/expressions_example/common/expression_functions/action/index.ts b/examples/expressions_example/common/expression_functions/action/index.ts new file mode 100644 index 000000000000..17e5f37c3d31 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/action/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './quick_form_fn'; +export * from './quick_form_renderer'; diff --git a/examples/expressions_example/common/expression_functions/action/quick_form_fn.ts b/examples/expressions_example/common/expression_functions/action/quick_form_fn.ts new file mode 100644 index 000000000000..1eb4c59d0029 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/action/quick_form_fn.ts @@ -0,0 +1,53 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { i18n } from '@osd/i18n'; +import { + ExpressionFunctionDefinition, + Render, +} from '../../../../../src/plugins/expressions/public'; +import { QuickFormRenderValue } from './quick_form_renderer'; + +type Arguments = QuickFormRenderValue; + +export const quickFormFn = (): ExpressionFunctionDefinition< + 'quick-form', + unknown, + Arguments, + Render +> => ({ + name: 'quick-form', + type: 'render', + help: i18n.translate('expressionsExample.function.avatar.help', { + defaultMessage: 'Render a simple form that sends the value back as an event on click', + }), + args: { + label: { + types: ['string'], + help: i18n.translate('expressionsExample.function.form.args.label.help', { + defaultMessage: 'Form label', + }), + default: i18n.translate('expressionsExample.function.form.args.label.default', { + defaultMessage: 'Input', + }), + }, + buttonLabel: { + types: ['string'], + help: i18n.translate('expressionsExample.function.form.args.buttonLabel.help', { + defaultMessage: 'Button label', + }), + default: i18n.translate('expressionsExample.function.form.args.buttonLabel.default', { + defaultMessage: 'Submit', + }), + }, + }, + fn: (input, args) => { + return { + type: 'render', + as: 'quick-form-renderer', + value: { ...args }, + }; + }, +}); diff --git a/examples/expressions_example/common/expression_functions/action/quick_form_renderer.tsx b/examples/expressions_example/common/expression_functions/action/quick_form_renderer.tsx new file mode 100644 index 000000000000..5c987595e1f2 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/action/quick_form_renderer.tsx @@ -0,0 +1,61 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useCallback, useState } from 'react'; +import { EuiForm, EuiFormRow, EuiButton, EuiFieldText } from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { ExpressionRenderDefinition } from '../../../../../src/plugins/expressions/public'; + +export interface QuickFormRenderValue { + label: string; + buttonLabel: string; +} + +export const quickFormRenderer: ExpressionRenderDefinition = { + name: 'quick-form-renderer', + displayName: i18n.translate('expressionsExample.form.render.help', { + defaultMessage: 'Render a simple input form', + }), + reuseDomNode: true, + render: (domNode, config, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render( + + handlers.event({ + data: value, + }) + } + />, + domNode, + handlers.done + ); + }, +}; + +interface QuickFormProps extends QuickFormRenderValue { + onSubmit: Function; +} + +const QuickForm = ({ onSubmit, buttonLabel, label }: QuickFormProps) => { + const [value, setValue] = useState(''); + const handleClick = useCallback(() => { + onSubmit(value); + }, [onSubmit, value]); + + return ( + + + setValue(e.target.value)} /> + + {buttonLabel} + + ); +}; diff --git a/examples/expressions_example/common/expression_functions/basic/index.ts b/examples/expressions_example/common/expression_functions/basic/index.ts new file mode 100644 index 000000000000..551f8e4f2d59 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/basic/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './sleep'; +export * from './square'; diff --git a/examples/expressions_example/common/expression_functions/basic/sleep.ts b/examples/expressions_example/common/expression_functions/basic/sleep.ts new file mode 100644 index 000000000000..5722369920b5 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/basic/sleep.ts @@ -0,0 +1,31 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { i18n } from '@osd/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../src/plugins/expressions/public'; + +interface Arguments { + time: number; +} + +export const sleep = (): ExpressionFunctionDefinition<'sleep', any, Arguments, any> => ({ + name: 'sleep', + help: i18n.translate('expressionsExample.function.sleep.help', { + defaultMessage: 'Generates range object', + }), + args: { + time: { + types: ['number'], + help: i18n.translate('expressionsExample.function.sleep.time.help', { + defaultMessage: 'Time for settimeout', + }), + required: false, + }, + }, + fn: async (input, args, context) => { + await new Promise((r) => setTimeout(r, args.time)); + return input; + }, +}); diff --git a/examples/expressions_example/common/expression_functions/basic/square.ts b/examples/expressions_example/common/expression_functions/basic/square.ts new file mode 100644 index 000000000000..899afed37e05 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/basic/square.ts @@ -0,0 +1,18 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { i18n } from '@osd/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../src/plugins/expressions/public'; + +export const square = (): ExpressionFunctionDefinition<'square', number, {}, any> => ({ + name: 'square', + help: i18n.translate('expressionsExample.function.square.help', { + defaultMessage: 'Squares the input', + }), + args: {}, + fn: async (input, args, context) => { + return input * input; + }, +}); diff --git a/examples/expressions_example/common/expression_functions/index.ts b/examples/expressions_example/common/expression_functions/index.ts new file mode 100644 index 000000000000..2bf7e68d0038 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './basic'; +export * from './render'; +export * from './action'; diff --git a/examples/expressions_example/common/expression_functions/render/avatar_fn.ts b/examples/expressions_example/common/expression_functions/render/avatar_fn.ts new file mode 100644 index 000000000000..7fe377b3f1d3 --- /dev/null +++ b/examples/expressions_example/common/expression_functions/render/avatar_fn.ts @@ -0,0 +1,52 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { i18n } from '@osd/i18n'; +import { + ExpressionFunctionDefinition, + Render, +} from '../../../../../src/plugins/expressions/public'; +import { AvatarRenderValue } from './avatar_renderer'; + +type Arguments = AvatarRenderValue; + +export const avatarFn = (): ExpressionFunctionDefinition< + 'avatar', + unknown, + Arguments, + Render +> => ({ + name: 'avatar', + type: 'render', + help: i18n.translate('expressionsExample.function.avatar.help', { + defaultMessage: 'Avatar expression function', + }), + args: { + name: { + types: ['string'], + help: i18n.translate('expressionsExample.function.avatar.args.name.help', { + defaultMessage: 'Enter Name', + }), + required: true, + }, + size: { + types: ['string'], + help: i18n.translate('expressionsExample.function.avatar.args.size.help', { + defaultMessage: 'Size of the avatar', + }), + default: 'l', + }, + }, + fn: (input, args) => { + return { + type: 'render', + as: 'avatar', + value: { + name: args.name, + size: args.size, + }, + }; + }, +}); diff --git a/examples/expressions_example/common/expression_functions/render/avatar_renderer.tsx b/examples/expressions_example/common/expression_functions/render/avatar_renderer.tsx new file mode 100644 index 000000000000..8b2fb3e8efaa --- /dev/null +++ b/examples/expressions_example/common/expression_functions/render/avatar_renderer.tsx @@ -0,0 +1,30 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { EuiAvatar, EuiAvatarProps } from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { ExpressionRenderDefinition } from '../../../../../src/plugins/expressions/public'; + +export interface AvatarRenderValue { + name: string; + size: EuiAvatarProps['size']; +} + +export const avatar: ExpressionRenderDefinition = { + name: 'avatar', + displayName: i18n.translate('expressionsExample.render.help', { + defaultMessage: 'Render an avatar', + }), + reuseDomNode: true, + render: (domNode, { name, size }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render(, domNode, handlers.done); + }, +}; diff --git a/examples/expressions_example/common/expression_functions/render/index.ts b/examples/expressions_example/common/expression_functions/render/index.ts new file mode 100644 index 000000000000..437b2ac9512b --- /dev/null +++ b/examples/expressions_example/common/expression_functions/render/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './avatar_fn'; +export * from './avatar_renderer'; diff --git a/examples/expressions_example/common/index.ts b/examples/expressions_example/common/index.ts new file mode 100644 index 000000000000..3208d933b77c --- /dev/null +++ b/examples/expressions_example/common/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export const PLUGIN_ID = 'expressionsExample'; +export const PLUGIN_NAME = 'expressions_example'; diff --git a/examples/expressions_example/opensearch_dashboards.json b/examples/expressions_example/opensearch_dashboards.json new file mode 100644 index 000000000000..8a1eb85f6176 --- /dev/null +++ b/examples/expressions_example/opensearch_dashboards.json @@ -0,0 +1,14 @@ +{ + "id": "expressionsExample", + "version": "1.0.0", + "opensearchDashboardsVersion": "opensearchDashboards", + "server": false, + "ui": true, + "requiredPlugins": [ + "navigation", + "expressions", + "developerExamples", + "opensearchDashboardsReact" + ], + "optionalPlugins": [] +} \ No newline at end of file diff --git a/examples/expressions_example/public/application.tsx b/examples/expressions_example/public/application.tsx new file mode 100644 index 000000000000..15953cf73ce4 --- /dev/null +++ b/examples/expressions_example/public/application.tsx @@ -0,0 +1,32 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { AppMountParameters, CoreStart } from '../../../src/core/public'; +import { ExpressionsExampleStartDependencies } from './types'; +import { ExpressionsExampleApp } from './components/app'; +import { OpenSearchDashboardsContextProvider } from '../../../src/plugins/opensearch_dashboards_react/public'; + +export const renderApp = ( + { notifications, http }: CoreStart, + { navigation, expressions }: ExpressionsExampleStartDependencies, + { appBasePath, element }: AppMountParameters +) => { + const services = { expressions, notifications }; + ReactDOM.render( + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/examples/expressions_example/public/components/actions_tab.tsx b/examples/expressions_example/public/components/actions_tab.tsx new file mode 100644 index 000000000000..0d1d9a699c36 --- /dev/null +++ b/examples/expressions_example/public/components/actions_tab.tsx @@ -0,0 +1,53 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiCallOut, EuiCodeBlock, EuiFormLabel, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import React, { useCallback } from 'react'; +import { ReactExpressionRenderer } from '../../../../src/plugins/expressions/public'; +import { useOpenSearchDashboards } from '../../../../src/plugins/opensearch_dashboards_react/public'; +import { ExpressionsExampleServices } from '../types'; + +export function ActionsTab() { + const { + services: { notifications }, + } = useOpenSearchDashboards(); + const handleEvent = useCallback( + ({ data }) => { + notifications.toasts.addSuccess(data); + }, + [notifications.toasts] + ); + + const expressionString = `quick-form label="Toast message" buttonLabel="Toast"`; + + return ( + <> + + + + + + + + + {expressionString} + + + + ); +} diff --git a/examples/expressions_example/public/components/app.tsx b/examples/expressions_example/public/components/app.tsx new file mode 100644 index 000000000000..99db0d40765f --- /dev/null +++ b/examples/expressions_example/public/components/app.tsx @@ -0,0 +1,138 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useMemo } from 'react'; +import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; +import { BrowserRouter as Router } from 'react-router-dom'; + +import { + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageContentHeader, + EuiPageHeader, + EuiTitle, + EuiText, + EuiTabbedContent, +} from '@elastic/eui'; + +import { CoreStart } from '../../../../src/core/public'; +import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public'; + +import { BasicTab } from './basic_tab'; +import { RenderTab } from './render_tab'; +import { ActionsTab } from './actions_tab'; +import { PlaygroundTab } from './playground_tab'; +import { ExplorerTab } from './explorer_tab'; + +interface ExpressionsExampleAppDeps { + basename: string; + notifications: CoreStart['notifications']; + http: CoreStart['http']; + navigation: NavigationPublicPluginStart; +} + +export const ExpressionsExampleApp = ({ basename }: ExpressionsExampleAppDeps) => { + const tabs = useMemo( + () => [ + { + id: 'demo-1', + name: ( + + ), + content: , + }, + { + id: 'demo-2', + name: ( + + ), + content: , + }, + { + id: 'demo-3', + name: ( + + ), + content: , + }, + { + id: 'playground', + name: ( + + ), + content: , + }, + { + id: 'explorer', + name: ( + + ), + content: , + }, + ], + [] + ); + // Render the application DOM. + return ( + + + <> + + + + +

+ +

+
+
+ + + +

+ +

+
+
+ + + +
+
+
+ +
+
+ ); +}; diff --git a/examples/expressions_example/public/components/basic_tab.tsx b/examples/expressions_example/public/components/basic_tab.tsx new file mode 100644 index 000000000000..06005b7ca8d6 --- /dev/null +++ b/examples/expressions_example/public/components/basic_tab.tsx @@ -0,0 +1,107 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiCodeBlock, + EuiFieldNumber, + EuiForm, + EuiFormRow, + EuiSpacer, + EuiStat, + EuiFormLabel, + EuiCallOut, + EuiProgress, +} from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import React, { useEffect, useState } from 'react'; +import { useOpenSearchDashboards } from '../../../../src/plugins/opensearch_dashboards_react/public'; +import { ExpressionsExampleServices } from '../types'; + +export function BasicTab() { + const { + services: { expressions }, + } = useOpenSearchDashboards(); + const [input, setInput] = useState(2); + const [loading, setLoading] = useState(false); + const [result, setResult] = useState( + i18n.translate('expressionsExample.tab.demo1.loading', { + defaultMessage: 'Still sleeping', + }) + ); + const expression = `sleep time=2000 | square`; + + useEffect(() => { + let isMounted = true; + + try { + setLoading(true); + const execution = expressions.execute(expression, input); + execution.getData().then((data: any) => { + if (!isMounted) return; + + const value = + data?.type === 'error' + ? `Error: ${data?.error?.message ?? 'Something went wrong'}` + : data; + + setLoading(false); + setResult(String(value)); + }); + } catch (error) { + setLoading(false); + setResult(String(error)); + } + + return () => { + isMounted = false; + }; + }, [expressions, input, expression]); + + return ( + <> + + + + + + + + setInput(Number(e.target.value))} /> + + + + + + + + {loading && } + {expression} + + + + + ); +} diff --git a/examples/expressions_example/public/components/explorer_section.tsx b/examples/expressions_example/public/components/explorer_section.tsx new file mode 100644 index 000000000000..b6b04efc61d4 --- /dev/null +++ b/examples/expressions_example/public/components/explorer_section.tsx @@ -0,0 +1,78 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiCallOut, + EuiDescriptionList, + EuiPanel, + EuiSpacer, + EuiTitle, + EuiBasicTable, + EuiText, + EuiBadge, +} from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import React, { useMemo } from 'react'; +import { ExpressionFunction } from '../../../../src/plugins/expressions'; + +interface Props { + fn: ExpressionFunction; +} + +export function ExplorerSection({ fn }: Props) { + const argumentItems = useMemo( + () => + Object.values(fn.args).map((arg) => ({ + name: arg.name, + default: arg.default, + types: String(arg.types), + required: arg.required, + help: arg.help, + })), + [fn] + ); + + return ( + + {/* arguments */} + +

+ +

+
+ +
+ ); +} diff --git a/examples/expressions_example/public/components/explorer_tab.tsx b/examples/expressions_example/public/components/explorer_tab.tsx new file mode 100644 index 000000000000..14030751e5b3 --- /dev/null +++ b/examples/expressions_example/public/components/explorer_tab.tsx @@ -0,0 +1,163 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiCallOut, + EuiFieldSearch, + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiFormRow, + EuiSelect, + EuiSpacer, + EuiBasicTable, + EuiButtonIcon, +} from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import React, { useMemo, useState } from 'react'; +import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; +import { useOpenSearchDashboards } from '../../../../src/plugins/opensearch_dashboards_react/public'; +import { ExpressionsExampleServices } from '../types'; +import { ExplorerSection } from './explorer_section'; + +interface ExpressionFunctionItem { + name: string; + type: string; + help: string; +} + +export function ExplorerTab() { + const { + services: { expressions }, + } = useOpenSearchDashboards(); + const [search, setSearch] = useState(''); + const [filter, setFilter] = useState('all'); + const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState({}); + + const functions = expressions.getFunctions(); + + const types = useMemo(() => { + const allTypes = new Set(Object.values(functions).map((fn) => fn.type)); + + // Catch all filter and remove + allTypes.delete(undefined); + allTypes.add('all'); + + return [...allTypes].map((type) => ({ text: type })); + }, [functions]); + + const items = useMemo( + () => + Object.values(functions) + .filter((fn) => fn.name.includes(search)) + .filter((fn) => (filter === 'all' ? true : fn.type === filter)) + .map((fn) => ({ + name: fn.name, + type: fn.type, + help: fn.help, + })), + [filter, functions, search] + ); + + const toggleDetails = (item: ExpressionFunctionItem) => { + const { name: id } = item; + const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; + if (itemIdToExpandedRowMapValues[id]) { + delete itemIdToExpandedRowMapValues[id]; + } else { + itemIdToExpandedRowMapValues[id] = ; + } + setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); + }; + + return ( + <> + + + + + + + + + + + setSearch(e.target.value)} + /> + + + + + setFilter(e.target.value)} + /> + + + + + + + ( + toggleDetails(item)} + aria-label={itemIdToExpandedRowMap[item.name] ? 'Collapse' : 'Expand'} + iconType={itemIdToExpandedRowMap[item.name] ? 'arrowUp' : 'arrowDown'} + /> + ), + }, + ]} + items={items} + /> + + {/* {sections} */} + + ); +} diff --git a/examples/expressions_example/public/components/playground_section.tsx b/examples/expressions_example/public/components/playground_section.tsx new file mode 100644 index 000000000000..ce957eeb0845 --- /dev/null +++ b/examples/expressions_example/public/components/playground_section.tsx @@ -0,0 +1,140 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiCodeBlock, + EuiFormLabel, + EuiSpacer, + EuiCodeEditor, + EuiPanel, + EuiForm, + EuiFormRow, + EuiFieldText, + EuiTitle, + EuiProgress, + EuiCallOut, +} from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import React, { useEffect, useState } from 'react'; +import { ReactExpressionRenderer } from '../../../../src/plugins/expressions/public'; +import { useOpenSearchDashboards } from '../../../../src/plugins/opensearch_dashboards_react/public'; +import { ExpressionsExampleServices } from '../types'; + +interface Props { + title: string; + defaultInput?: string; + defaultExpression: string; + renderType?: boolean; +} + +export function PlaygroundSection({ + title, + defaultExpression, + defaultInput = '10', + renderType = false, +}: Props) { + const { + services: { expressions }, + } = useOpenSearchDashboards(); + const [loading, setLoading] = useState(false); + const [input, setInput] = useState(defaultInput); + const [expression, setExpression] = useState(defaultExpression); + const [result, setResult] = useState(''); + + useEffect(() => { + let isMounted = true; + if (renderType) return; + + try { + setLoading(true); + const execution = expressions.execute(expression, input); + execution.getData().then((data: any) => { + if (!isMounted) return; + + const value = + data?.type === 'error' + ? `Error: ${data?.error?.message ?? 'Something went wrong'}` + : data; + + const parsedValue = typeof value === 'object' ? JSON.stringify(value, null, 2) : value; + + setLoading(false); + setResult(parsedValue); + }); + } catch (error) { + setLoading(false); + setResult(String(error)); + } + + return () => { + isMounted = false; + }; + }, [expressions, input, expression, renderType]); + + return ( + <> + + +

{title}

+
+ + {/* Rendered the input field only for non renderable expressions */} + {!renderType && ( + <> + + + setInput(e.target.value)} /> + + + + + )} + + + + setExpression(value)} + /> + + + + + {renderType ? ( + <> + + + + + ) : ( + + {loading && } + {result} + + )} +
+ + ); +} diff --git a/examples/expressions_example/public/components/playground_tab.tsx b/examples/expressions_example/public/components/playground_tab.tsx new file mode 100644 index 000000000000..9acdbfa89796 --- /dev/null +++ b/examples/expressions_example/public/components/playground_tab.tsx @@ -0,0 +1,53 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import React from 'react'; +import { PlaygroundSection } from './playground_section'; + +export function PlaygroundTab() { + return ( + <> + + + + + + + + + + + + + ); +} diff --git a/examples/expressions_example/public/components/render_tab.tsx b/examples/expressions_example/public/components/render_tab.tsx new file mode 100644 index 000000000000..30342da63081 --- /dev/null +++ b/examples/expressions_example/public/components/render_tab.tsx @@ -0,0 +1,89 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiCodeBlock, + EuiFieldText, + EuiForm, + EuiFormLabel, + EuiFormRow, + EuiSpacer, + EuiSelect, + EuiCallOut, +} from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import React, { useState } from 'react'; +import { ReactExpressionRenderer } from '../../../../src/plugins/expressions/public'; + +export function RenderTab() { + const [value, setValue] = useState('OpenSearch Dashboards'); + const [size, setSize] = useState('xl'); + const expressionString = `avatar name="${value}" size="${size}"`; + + return ( + <> + + + + + + + + setValue(String(e.target.value))} /> + + + setSize(String(e.target.value))} + /> + + + + + + + {expressionString} + + + + + + + ); +} diff --git a/examples/expressions_example/public/index.scss b/examples/expressions_example/public/index.scss new file mode 100644 index 000000000000..e33c1b1f588e --- /dev/null +++ b/examples/expressions_example/public/index.scss @@ -0,0 +1,13 @@ +.expressions-demo { + .explorer_list .euiDescriptionList__title { + max-width: 400px; + } + + .explorer_section_type > code { + margin-left: $euiSizeXS; + } + + .playgroundRenderer { + height: 500px; // Visualizations require the container to have a valid width and height to render + } +} diff --git a/examples/expressions_example/public/index.ts b/examples/expressions_example/public/index.ts new file mode 100644 index 000000000000..b930fc76eb65 --- /dev/null +++ b/examples/expressions_example/public/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import './index.scss'; + +import { ExpressionsExamplePlugin } from './plugin'; + +// This exports static code and TypeScript types, +// as well as, OpenSearch Dashboards Platform `plugin()` initializer. +export function plugin() { + return new ExpressionsExamplePlugin(); +} +export { ExpressionsExamplePluginSetup, ExpressionsExamplePluginStart } from './types'; diff --git a/examples/expressions_example/public/plugin.ts b/examples/expressions_example/public/plugin.ts new file mode 100644 index 000000000000..47e02ae1d006 --- /dev/null +++ b/examples/expressions_example/public/plugin.ts @@ -0,0 +1,92 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { i18n } from '@osd/i18n'; +import { + AppMountParameters, + AppNavLinkStatus, + CoreSetup, + CoreStart, + Plugin, +} from '../../../src/core/public'; +import { + ExpressionsExamplePluginSetup, + ExpressionsExamplePluginStart, + ExpressionsExampleSetupDependencies, + ExpressionsExampleStartDependencies, +} from './types'; +import { PLUGIN_NAME } from '../common'; + +import { + sleep, + square, + avatar, + avatarFn, + quickFormFn, + quickFormRenderer, +} from '../common/expression_functions'; + +export class ExpressionsExamplePlugin + implements Plugin { + public setup( + core: CoreSetup, + { expressions, developerExamples }: ExpressionsExampleSetupDependencies + ): ExpressionsExamplePluginSetup { + // Register an application into the side navigation menu + core.application.register({ + id: 'expressions-example', + title: PLUGIN_NAME, + navLinkStatus: AppNavLinkStatus.hidden, + async mount(params: AppMountParameters) { + // Load application bundle + const { renderApp } = await import('./application'); + // Get start services as specified in opensearch_dashboards.json + const [coreStart, depsStart] = await core.getStartServices(); + // Render the application + return renderApp(coreStart, depsStart as ExpressionsExampleStartDependencies, params); + }, + }); + + const expressionFunctions = [sleep, square, avatarFn, quickFormFn]; + const expressionRenderers = [avatar, quickFormRenderer]; + + expressionFunctions.forEach((createExpressionFunction) => { + expressions.registerFunction(createExpressionFunction); + }); + + expressionRenderers.forEach((createExpressionRenderer) => { + expressions.registerRenderer(createExpressionRenderer); + }); + + developerExamples.register({ + appId: 'expressions-example', + title: i18n.translate('expressionsExample.developerExamples.title', { + defaultMessage: 'Expressions', + }), + description: i18n.translate('expressionsExample.developerExamples.description', { + defaultMessage: + 'Examples showing you how the expressions plugin is used to chain functions and render content', + }), + links: [ + { + label: 'README', + href: + 'https://github.com/opensearch-project/OpenSearch-Dashboards/blob/main/src/plugins/expressions/README.md', + iconType: 'logoGithub', + target: '_blank', + size: 's', + }, + ], + }); + + return {}; + } + + public start(core: CoreStart): ExpressionsExamplePluginStart { + return {}; + } + + public stop() {} +} diff --git a/examples/expressions_example/public/types.ts b/examples/expressions_example/public/types.ts new file mode 100644 index 000000000000..ea32b4783283 --- /dev/null +++ b/examples/expressions_example/public/types.ts @@ -0,0 +1,30 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CoreStart, NotificationsStart } from '../../../src/core/public'; +import { ExpressionsSetup, ExpressionsStart } from '../../../src/plugins/expressions/public'; +import { NavigationPublicPluginStart } from '../../../src/plugins/navigation/public'; +import { DeveloperExamplesSetup } from '../../developer_examples/public'; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface ExpressionsExamplePluginSetup {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface ExpressionsExamplePluginStart {} + +export interface ExpressionsExampleSetupDependencies { + expressions: ExpressionsSetup; + developerExamples: DeveloperExamplesSetup; +} + +export interface ExpressionsExampleStartDependencies { + navigation: NavigationPublicPluginStart; + expressions: ExpressionsStart; +} + +export interface ExpressionsExampleServices extends CoreStart { + expressions: ExpressionsStart; + notifications: NotificationsStart; +} diff --git a/src/plugins/expressions/README.md b/src/plugins/expressions/README.md index aca90ea25953..053344c8c28b 100644 --- a/src/plugins/expressions/README.md +++ b/src/plugins/expressions/README.md @@ -5,31 +5,75 @@ string for you, as well as a series of registries for advanced users who might want to incorporate their own functions, types, and renderers into the service for use in their own application. -Expression pipeline is a chain of functions that _pipe_ its output to the -input of the next function. Functions can be configured using arguments provided -by the user. The final output of the expression pipeline can be rendered using -one of the _renderers_ registered in `expressions` plugin. +`Expressions` is a simple custom language designed to write a chain of functions that _pipe_ its output to the +input of the next function. When two or more such functions are chained together, it is an expressions pipeline. Since it is a custom language, any expression can be represented as a string. Functions can be configured using arguments provided. The final output of the expression pipeline can either be rendered using +one of the _renderers_ registered in `expressions` plugin or made to output the result of the final function in the chain. -Expressions power visualizations in Dashboard and Lens, as well as, every -_element_ in Canvas is backed by an expression. +> It is not necessary to chain functions and a single function can be used in isolation. -Below is an example of one Canvas element that fetches data using `opensearchsql` function, -pipes it further to `math` and `metric` functions, and final `render` function -renders the result. +Expressions power visualizations in Dashboard. +Below is an example of an expression that renders a metric visualization that aggregates the average value for the field `AvgTicketPrice` in the index. It does so by first fetching the opensearch dashboards global context, pipes it into the `opensearchaggs` function that fetches the aggregate data and pipes its result to the `metricVis` function that renders a metric visualization for the data. + +``` +opensearchDashboards +| opensearchaggs + index='d3d7af60-4c81-11e8-b3d7-01146121b73d' + aggConfigs='[{"id":"1","type":"avg","params":{"field":"AvgTicketPrice","customLabel":"Avg. Ticket Price"}}]' +| metricVis + metric={visdimension accessor=0 format='number'} +``` + +![image](./expressions_example.png) + +## Anatomy of an expression + +Consider the example below where the expression performs the following. It takes an input, sleeps for 2000ms and then returns the square of the input as its final output + +``` +sleep time=2000 | square +``` + +**Note:** The above example expression functions are only available with the `--run-examples` flag + +The whole string is an expression. `sleep` and `square` are expression functions registered with the expression plugin. `time=2000` is the argument passed to the `sleep` funciton with the value `2000`. `|` is used to denote pipe between the two functions. Every expression can take an input. In the example above, the input provided will be passed on by the sleep function to the square function. + +## Using Expressions + +### Execute Expressions + +One of the two ways an expressions can be used is to execute an expression to return a value. This can be done using the `expressions.execute` or `expressions.run` command. The primary difference being that the `execute` method returns an `ExecutionContract` that tracks the progress of the execution and can be used to interact with the expression. + +```js +const expression = `sleep time=2000 | square`; +const execution = expressions.execute(expression, input); ``` -filters -| opensearchsql - query="SELECT COUNT(timestamp) as total_errors - FROM opensearch_dashboards_sample_data_logs - WHERE tags LIKE '%warning%' OR tags LIKE '%error%'" -| math "total_errors" -| metric "TOTAL ISSUES" - metricFont={font family="'Open Sans', Helvetica, Arial, sans-serif" size=48 align="left" color="#FFFFFF" weight="normal" underline=false italic=false} - labelFont={font family="'Open Sans', Helvetica, Arial, sans-serif" size=30 align="left" color="#FFFFFF" weight="lighter" underline=false italic=false} -| render + +**Note:** The above example expression functions are only available with the `--run-examples` flag + +### Rendering Expressions + +The other way an expression can be used is to render an output using one of the _renderers_ registered in `expressions` plugin. This can be done using a few ways, the easiest of which is to use the `ReactExpressionRenderer` component. + +```jsx +const expressionString = `avatar name="OpenSearch Dashboards" size="xl"`; + +``` + +**Note:** The above example expression functions are only available with the `--run-examples` flag + +## Custom expressions + +Users can extend the service to incorporate their own functions, types, and renderers. Examples of these can be found in `./examples/expressions_example/common/expression_functions` and can be registered using the `registerFunction`, `registertype` and `registerRenderer` api's from the expression setup contract. + +## Playground + +Working with expressions can sometimes be a little tricky. To make this easier we have an example plugin with some examples, a playground to run your own expression functions and explorer to view all the registered expression functions and their propoerties. It can be started up using the `--run-examples` flag and found under the `Developer examples` option in the main menu. + +```sh +yarn start --run-examples ``` -![image](https://user-images.githubusercontent.com/9773803/74162514-3250a880-4c21-11ea-9e68-86f66862a183.png) -[See Canvas documentation about expressions](https://opensearch.org/docs/latest/dashboards/index/). + + diff --git a/src/plugins/expressions/expressions_example.png b/src/plugins/expressions/expressions_example.png new file mode 100644 index 0000000000000000000000000000000000000000..9850f25aba873f6f825645902e086740bc2466a2 GIT binary patch literal 85702 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 H_K*G-&vc3; literal 0 HcmV?d00001 diff --git a/src/plugins/expressions/public/_expression_renderer.scss b/src/plugins/expressions/public/_expression_renderer.scss index 4f030384ed88..c372f3b3bf2a 100644 --- a/src/plugins/expressions/public/_expression_renderer.scss +++ b/src/plugins/expressions/public/_expression_renderer.scss @@ -8,8 +8,13 @@ } .expExpressionRenderer__expression { + display: flex; + flex-direction: column; width: 100%; height: 100%; + overflow: auto; + position: relative; + flex: 1 1 100%; } .expExpressionRenderer-isEmpty, diff --git a/src/plugins/expressions/public/react_expression_renderer.tsx b/src/plugins/expressions/public/react_expression_renderer.tsx index 6d6760756c51..838fa703a750 100644 --- a/src/plugins/expressions/public/react_expression_renderer.tsx +++ b/src/plugins/expressions/public/react_expression_renderer.tsx @@ -184,10 +184,9 @@ export const ReactExpressionRenderer = ({ } }, [state.error]); - const classes = classNames('expExpressionRenderer', { + const classes = classNames('expExpressionRenderer', className, { 'expExpressionRenderer-isEmpty': state.isEmpty, 'expExpressionRenderer-hasError': !!state.error, - className, }); const expressionStyles: React.CSSProperties = {}; diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts index c009707f6d42..f743c37e911b 100644 --- a/src/plugins/expressions/public/render.ts +++ b/src/plugins/expressions/public/render.ts @@ -106,7 +106,7 @@ export class ExpressionRenderHandler { }; } - render = async (data: any, uiState: any = {}) => { + render = async (data: any, uiState?: any) => { if (!data || typeof data !== 'object') { return this.handleRenderError(new Error('invalid data provided to the expression renderer')); }