Skip to content

Commit

Permalink
[examples] expressions explorer (elastic#88344)
Browse files Browse the repository at this point in the history
  • Loading branch information
ppisljar authored Jan 22, 2021
1 parent 49d95f6 commit d81ab83
Show file tree
Hide file tree
Showing 31 changed files with 1,085 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExpressionsInspectorAdapter](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.md) &gt; [ast](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.ast.md)

## ExpressionsInspectorAdapter.ast property

<b>Signature:</b>

```typescript
get ast(): any;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExpressionsInspectorAdapter](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.md) &gt; [logAST](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.logast.md)

## ExpressionsInspectorAdapter.logAST() method

<b>Signature:</b>

```typescript
logAST(ast: any): void;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| ast | <code>any</code> | |

<b>Returns:</b>

`void`

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExpressionsInspectorAdapter](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.md)

## ExpressionsInspectorAdapter class

<b>Signature:</b>

```typescript
export declare class ExpressionsInspectorAdapter extends EventEmitter
```
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [ast](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.ast.md) | | <code>any</code> | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [logAST(ast)](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.logast.md) | | |
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
| [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) | |
| [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.md) | |
| [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) | |
| [ExpressionsInspectorAdapter](./kibana-plugin-plugins-expressions-public.expressionsinspectoradapter.md) | |
| [ExpressionsPublicPlugin](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.md) | |
| [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) | <code>ExpressionsService</code> class is used for multiple purposes:<!-- -->1. It implements the same Expressions service that can be used on both: (1) server-side and (2) browser-side. 2. It implements the same Expressions service that users can fork/clone, thus have their own instance of the Expressions plugin. 3. <code>ExpressionsService</code> defines the public contracts of \*setup\* and \*start\* Kibana Platform life-cycles for ease-of-use on server-side and browser-side. 4. <code>ExpressionsService</code> creates a bound version of all exported contract functions. 5. Functions are bound the way there are:<!-- -->\`\`\`<!-- -->ts registerFunction = (...args: Parameters<!-- -->&lt;<!-- -->Executor\['registerFunction'\]<!-- -->&gt; ): ReturnType<!-- -->&lt;<!-- -->Executor\['registerFunction'\]<!-- -->&gt; =<!-- -->&gt; this.executor.registerFunction(...args); \`\`\`<!-- -->so that JSDoc appears in developers IDE when they use those <code>plugins.expressions.registerFunction(</code>. |
| [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) | |
Expand Down
8 changes: 8 additions & 0 deletions examples/expressions_explorer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## expressions explorer

This example expressions explorer app shows how to:
- to run expression
- to render expression output
- emit events from expression renderer and handle them

To run this example, use the command `yarn start --run-examples`.
10 changes: 10 additions & 0 deletions examples/expressions_explorer/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"id": "expressionsExplorer",
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": false,
"ui": true,
"requiredPlugins": ["expressions", "inspector", "uiActions", "developerExamples"],
"optionalPlugins": [],
"requiredBundles": []
}
21 changes: 21 additions & 0 deletions examples/expressions_explorer/public/actions/navigate_action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/

import { createAction } from '../../../../src/plugins/ui_actions/public';

export const ACTION_NAVIGATE = 'ACTION_NAVIGATE';

export const createNavigateAction = () =>
createAction({
id: ACTION_NAVIGATE,
type: ACTION_NAVIGATE,
getDisplayName: () => 'Navigate',
execute: async (event: any) => {
window.location.href = event.href;
},
});
15 changes: 15 additions & 0 deletions examples/expressions_explorer/public/actions/navigate_trigger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/

import { Trigger } from '../../../../src/plugins/ui_actions/public';

export const NAVIGATE_TRIGGER_ID = 'NAVIGATE_TRIGGER_ID';

export const navigateTrigger: Trigger = {
id: NAVIGATE_TRIGGER_ID,
};
102 changes: 102 additions & 0 deletions examples/expressions_explorer/public/actions_and_expressions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/

import React, { useState } from 'react';
import {
EuiFlexItem,
EuiFlexGroup,
EuiPageBody,
EuiPageContent,
EuiPageContentBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiPanel,
EuiText,
EuiTitle,
} from '@elastic/eui';
import {
ExpressionsStart,
ReactExpressionRenderer,
ExpressionsInspectorAdapter,
} from '../../../src/plugins/expressions/public';
import { ExpressionEditor } from './editor/expression_editor';
import { UiActionsStart } from '../../../src/plugins/ui_actions/public';
import { NAVIGATE_TRIGGER_ID } from './actions/navigate_trigger';

interface Props {
expressions: ExpressionsStart;
actions: UiActionsStart;
}

export function ActionsExpressionsExample({ expressions, actions }: Props) {
const [expression, updateExpression] = useState(
'button name="click me" href="http://www.google.com"'
);

const expressionChanged = (value: string) => {
updateExpression(value);
};

const inspectorAdapters = {
expression: new ExpressionsInspectorAdapter(),
};

const handleEvents = (event: any) => {
if (event.id !== 'NAVIGATE') return;
// enrich event context with some extra data
event.baseUrl = 'http://www.google.com';

actions.executeTriggerActions(NAVIGATE_TRIGGER_ID, event.value);
};

return (
<EuiPageBody>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>Actions from expression renderers</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody>
<EuiFlexGroup>
<EuiFlexItem>
<EuiText>
Here you can play with sample `button` which takes a url as configuration and
displays a button which emits custom BUTTON_CLICK trigger to which we have attached
a custom action which performs the navigation.
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>

<EuiFlexGroup gutterSize="l">
<EuiFlexItem>
<EuiPanel data-test-subj="expressionEditor" paddingSize="none" role="figure">
<ExpressionEditor value={expression} onChange={expressionChanged} />
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel paddingSize="none" role="figure">
<ReactExpressionRenderer
expression={expression}
debug={true}
inspectorAdapters={inspectorAdapters}
onEvent={handleEvents}
renderError={(message: any) => {
return <div>{message}</div>;
}}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
);
}
78 changes: 78 additions & 0 deletions examples/expressions_explorer/public/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/

import React from 'react';
import ReactDOM from 'react-dom';
import {
EuiPage,
EuiPageHeader,
EuiPageBody,
EuiPageContent,
EuiPageContentBody,
EuiSpacer,
EuiText,
EuiLink,
} from '@elastic/eui';
import { AppMountParameters } from '../../../src/core/public';
import { ExpressionsStart } from '../../../src/plugins/expressions/public';
import { Start as InspectorStart } from '../../../src/plugins/inspector/public';
import { RunExpressionsExample } from './run_expressions';
import { RenderExpressionsExample } from './render_expressions';
import { ActionsExpressionsExample } from './actions_and_expressions';
import { UiActionsStart } from '../../../src/plugins/ui_actions/public';

interface Props {
expressions: ExpressionsStart;
inspector: InspectorStart;
actions: UiActionsStart;
}

const ExpressionsExplorer = ({ expressions, inspector, actions }: Props) => {
return (
<EuiPage>
<EuiPageBody>
<EuiPageHeader>Expressions Explorer</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody>
<EuiText>
<p>
There are a couple of ways to run the expressions. Below some of the options are
demonstrated. You can read more about it{' '}
<EuiLink
href={
'https://github.com/elastic/kibana/blob/master/src/plugins/expressions/README.asciidoc'
}
>
here
</EuiLink>
</p>
</EuiText>

<EuiSpacer />

<RunExpressionsExample expressions={expressions} inspector={inspector} />

<EuiSpacer />

<RenderExpressionsExample expressions={expressions} inspector={inspector} />

<EuiSpacer />

<ActionsExpressionsExample expressions={expressions} actions={actions} />
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
);
};

export const renderApp = (props: Props, { element }: AppMountParameters) => {
ReactDOM.render(<ExpressionsExplorer {...props} />, element);

return () => ReactDOM.unmountComponentAtNode(element);
};
35 changes: 35 additions & 0 deletions examples/expressions_explorer/public/editor/expression_editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/

import React from 'react';
import { EuiCodeEditor } from '@elastic/eui';

interface Props {
value: string;
onChange: (value: string) => void;
}

export function ExpressionEditor({ value, onChange }: Props) {
return (
<EuiCodeEditor
mode="javascript"
theme="github"
width="100%"
value={value}
onChange={onChange}
setOptions={{
fontSize: '14px',
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
}}
onBlur={() => {}}
aria-label="Code Editor"
/>
);
}
50 changes: 50 additions & 0 deletions examples/expressions_explorer/public/functions/button.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
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/

import { i18n } from '@kbn/i18n';
import { ExpressionFunctionDefinition } from '../../../../src/plugins/expressions/common';

interface Arguments {
href: string;
name: string;
}

export type ExpressionFunctionButton = ExpressionFunctionDefinition<
'button',
unknown,
Arguments,
unknown
>;

export const buttonFn: ExpressionFunctionButton = {
name: 'button',
args: {
href: {
help: i18n.translate('expressions.functions.font.args.href', {
defaultMessage: 'Link to which to navigate',
}),
types: ['string'],
required: true,
},
name: {
help: i18n.translate('expressions.functions.font.args.name', {
defaultMessage: 'Name of the button',
}),
types: ['string'],
default: 'button',
},
},
help: 'Configures the button',
fn: (input: unknown, args: Arguments) => {
return {
type: 'render',
as: 'button',
value: args,
};
},
};
Loading

0 comments on commit d81ab83

Please sign in to comment.