Skip to content

Commit

Permalink
[Canvas] Disable datasource UI when expression contains an expression…
Browse files Browse the repository at this point in the history
… argument (#79369) (#79523)

* Disable datasource UI when expression contains an expression argument

* Removing unnecessary type coercion
  • Loading branch information
poffdeluxe authored Oct 5, 2020
1 parent 91eee70 commit ecaee18
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
*/

import React from 'react';
import { EuiText } from '@elastic/eui';
import { EuiCallOut, EuiText } from '@elastic/eui';
import { templateFromReactComponent } from '../../../public/lib/template_from_react_component';
import { DataSourceStrings } from '../../../i18n';

const { DemoData: strings } = DataSourceStrings;

const DemodataDatasource = () => (
<EuiText size="s">
<p>{strings.getDescription()}</p>
</EuiText>
<EuiCallOut title={strings.getHeading()} iconType="iInCircle">
<EuiText size="s">
<p>{strings.getDescription()}</p>
</EuiText>
</EuiCallOut>
);

export const demodata = () => ({
Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/canvas/i18n/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.datasourceDatasourceComponent.changeButtonLabel', {
defaultMessage: 'Change element data source',
}),
getExpressionArgDescription: () =>
i18n.translate('xpack.canvas.datasourceDatasourceComponent.expressionArgDescription', {
defaultMessage:
'The datasource has an argument controlled by an expression. Use the expression editor to modify the datasource.',
}),
getPreviewButtonLabel: () =>
i18n.translate('xpack.canvas.datasourceDatasourceComponent.previewButtonLabel', {
defaultMessage: 'Preview data',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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 { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react';
import { EuiCallOut, EuiText } from '@elastic/eui';
import React from 'react';
// @ts-expect-error untyped local
import { DatasourceComponent } from '../datasource_component';
import { templateFromReactComponent } from '../../../../public/lib/template_from_react_component';
// @ts-expect-error untyped local
import { Datasource } from '../../../../public/expression_types/datasource';

const TestDatasource = ({ args }: any) => (
<EuiCallOut title="My Test Data Source" iconType="iInCircle">
<EuiText size="s">
<p>Hello! I am a datasource with a query arg of: {args.query}</p>
</EuiText>
</EuiCallOut>
);

const testDatasource = () => ({
name: 'test',
displayName: 'Test Datasource',
help: 'This is a test data source',
image: 'training',
template: templateFromReactComponent(TestDatasource),
});

const wrappedTestDatasource = new Datasource(testDatasource());

const args = {
query: ['select * from kibana'],
};

storiesOf('components/datasource/DatasourceComponent', module)
.addParameters({
info: {
inline: true,
styles: {
infoBody: {
margin: 20,
},
infoStory: {
margin: '40px 60px',
width: '320px',
},
},
},
})
.add('simple datasource', () => (
<DatasourceComponent
args={args}
datasources={[wrappedTestDatasource]}
datasource={wrappedTestDatasource}
datasourceDef={{}}
stateArgs={args}
stateDatasource={wrappedTestDatasource}
selectDatasouce={action('selectDatasouce')}
setDatasourceAst={action('setDatasourceAst')}
updateArgs={action('updateArgs')}
resetArgs={action('resetArgs')}
selecting={false}
setSelecting={action('setSelecting')}
previewing={false}
setPreviewing={action('setPreviewing')}
isInvalid={false}
setInvalid={action('setInvalid')}
/>
))
.add('datasource with expression arguments', () => (
<DatasourceComponent
args={{ query: [{ name: 'expression' }] }}
datasources={[wrappedTestDatasource]}
datasource={wrappedTestDatasource}
datasourceDef={{}}
stateArgs={{ query: [{ name: 'expression' }] }}
stateDatasource={wrappedTestDatasource}
selectDatasouce={action('selectDatasouce')}
setDatasourceAst={action('setDatasourceAst')}
updateArgs={action('updateArgs')}
resetArgs={action('resetArgs')}
selecting={false}
setSelecting={action('setSelecting')}
previewing={false}
setPreviewing={action('setPreviewing')}
isInvalid={false}
setInvalid={action('setInvalid')}
/>
));
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ import {
EuiHorizontalRule,
} from '@elastic/eui';
import { isEqual } from 'lodash';
import { ComponentStrings, DataSourceStrings } from '../../../i18n';
import { ComponentStrings } from '../../../i18n';
import { getDefaultIndex } from '../../lib/es_service';
import { DatasourceSelector } from './datasource_selector';
import { DatasourcePreview } from './datasource_preview';

const { DatasourceDatasourceComponent: strings } = ComponentStrings;
const { DemoData: demoDataStrings } = DataSourceStrings;

export class DatasourceComponent extends PureComponent {
static propTypes = {
Expand Down Expand Up @@ -133,14 +132,17 @@ export class DatasourceComponent extends PureComponent {
/>
) : null;

const datasourceRender = stateDatasource.render({
args: stateArgs,
updateArgs,
datasourceDef,
isInvalid,
setInvalid,
defaultIndex,
});
const datasourceRender = () =>
stateDatasource.render({
args: stateArgs,
updateArgs,
datasourceDef,
isInvalid,
setInvalid,
defaultIndex,
});

const hasExpressionArgs = Object.values(stateArgs).some((a) => a && typeof a[0] === 'object');

return (
<Fragment>
Expand All @@ -157,26 +159,34 @@ export class DatasourceComponent extends PureComponent {
{stateDatasource.displayName}
</EuiButtonEmpty>
<EuiSpacer size="s" />
{stateDatasource.name === 'demodata' ? (
<EuiCallOut title={demoDataStrings.getHeading()} iconType="iInCircle">
{datasourceRender}
</EuiCallOut>
{!hasExpressionArgs ? (
<>
{datasourceRender()}
<EuiHorizontalRule margin="m" />
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButtonEmpty size="s" onClick={() => setPreviewing(true)}>
{strings.getPreviewButtonLabel()}
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
disabled={isInvalid}
size="s"
onClick={this.save}
fill
color="secondary"
>
{strings.getSaveButtonLabel()}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</>
) : (
datasourceRender
<EuiCallOut color="warning">
<p>{strings.getExpressionArgDescription()}</p>
</EuiCallOut>
)}
<EuiHorizontalRule margin="m" />
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButtonEmpty size="s" onClick={() => setPreviewing(true)}>
{strings.getPreviewButtonLabel()}
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton disabled={isInvalid} size="s" onClick={this.save} fill color="secondary">
{strings.getSaveButtonLabel()}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</div>

{datasourcePreview}
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/canvas/storybook/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ module.exports = async ({ config: storybookConfig }) => {
/(lib)?\/ui_metric/,
path.resolve(__dirname, '../tasks/mocks/uiMetric')
),
new webpack.NormalModuleReplacementPlugin(
/lib\/es_service/,
path.resolve(__dirname, '../tasks/mocks/esService')
),
],
resolve: {
extensions: ['.ts', '.tsx', '.scss', '.mjs', '.html'],
Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/canvas/tasks/mocks/esService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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 function getDefaultIndex() {
return Promise.resolve('default-index');
}

0 comments on commit ecaee18

Please sign in to comment.