From 2b1274b773ee3b975bcc55cf2f191c8f886d8b18 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Mon, 2 Nov 2020 15:51:26 +0100 Subject: [PATCH 01/12] send to background UI --- src/dev/storybook/aliases.ts | 1 + .../plugins/data_enhanced/.storybook/main.js | 7 + x-pack/plugins/data_enhanced/kibana.json | 2 +- x-pack/plugins/data_enhanced/public/plugin.ts | 13 +- .../background_session_indicator.stories.tsx | 30 +++ .../background_session_indicator.tsx | 188 ++++++++++++++++++ .../ui/background_session_indicator/index.tsx | 23 +++ .../public/ui/background_session_state.ts | 33 +++ ...connected_background_session_indicator.tsx | 32 +++ 9 files changed, 327 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/data_enhanced/.storybook/main.js create mode 100644 x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.stories.tsx create mode 100644 x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.tsx create mode 100644 x-pack/plugins/data_enhanced/public/ui/background_session_indicator/index.tsx create mode 100644 x-pack/plugins/data_enhanced/public/ui/background_session_state.ts create mode 100644 x-pack/plugins/data_enhanced/public/ui/connected_background_session_indicator.tsx diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 153725fc48e7b4..36c742dc40403c 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -22,6 +22,7 @@ export const storybookAliases = { canvas: 'x-pack/plugins/canvas/storybook', codeeditor: 'src/plugins/kibana_react/public/code_editor/.storybook', dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/.storybook', + data_enhanced: 'x-pack/plugins/data_enhanced/.storybook', embeddable: 'src/plugins/embeddable/.storybook', infra: 'x-pack/plugins/infra/.storybook', security_solution: 'x-pack/plugins/security_solution/.storybook', diff --git a/x-pack/plugins/data_enhanced/.storybook/main.js b/x-pack/plugins/data_enhanced/.storybook/main.js new file mode 100644 index 00000000000000..1818aa44a93993 --- /dev/null +++ b/x-pack/plugins/data_enhanced/.storybook/main.js @@ -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. + */ + +module.exports = require('@kbn/storybook').defaultConfig; diff --git a/x-pack/plugins/data_enhanced/kibana.json b/x-pack/plugins/data_enhanced/kibana.json index 5ded0f8f0dec3a..bc7c8410d3df10 100644 --- a/x-pack/plugins/data_enhanced/kibana.json +++ b/x-pack/plugins/data_enhanced/kibana.json @@ -12,5 +12,5 @@ "optionalPlugins": ["kibanaUtils", "usageCollection"], "server": true, "ui": true, - "requiredBundles": ["kibanaUtils"] + "requiredBundles": ["kibanaUtils", "kibanaReact"] } diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index 43ad4a9ed9b8b3..93564373f6fce5 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -4,12 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public'; import { setAutocompleteService } from './services'; -import { setupKqlQuerySuggestionProvider, KUERY_LANGUAGE_NAME } from './autocomplete'; +import { setupKqlQuerySuggestionProvider, KUERY_LANGUAGE_NAME } from './autocomplete'; import { EnhancedSearchInterceptor } from './search/search_interceptor'; +import { toMountPoint } from '../../../../src/plugins/kibana_react/public'; +import { createConnectedBackgroundSessionIndicator } from './ui/connected_background_session_indicator'; export interface DataEnhancedSetupDependencies { data: DataPublicPluginSetup; @@ -52,6 +55,14 @@ export class DataEnhancedPlugin public start(core: CoreStart, plugins: DataEnhancedStartDependencies) { setAutocompleteService(plugins.data.autocomplete); + + core.chrome.setBreadcrumbsAppendExtension({ + content: toMountPoint( + React.createElement( + createConnectedBackgroundSessionIndicator({ sessionService: plugins.data.search.session }) + ) + ), + }); } public stop() { diff --git a/x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.stories.tsx b/x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.stories.tsx new file mode 100644 index 00000000000000..c94df39793547e --- /dev/null +++ b/x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.stories.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { BackgroundSessionIndicator } from './background_session_indicator'; +import { BackgroundSessionViewState } from '../background_session_state'; + +storiesOf('components/BackgroundSessionIndicator', module).add('default', () => ( + <> +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +)); diff --git a/x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.tsx b/x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.tsx new file mode 100644 index 00000000000000..66940ded77096c --- /dev/null +++ b/x-pack/plugins/data_enhanced/public/ui/background_session_indicator/background_session_indicator.tsx @@ -0,0 +1,188 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { + EuiButtonEmpty, + EuiButtonIcon, + EuiButtonIconProps, + EuiFlexGroup, + EuiFlexItem, + EuiLoadingSpinner, + EuiPopover, + EuiText, + EuiToolTip, +} from '@elastic/eui'; +import { BackgroundSessionViewState } from '../background_session_state'; + +export interface BackgroundSessionIndicatorProps { + state: BackgroundSessionViewState; + onContinueInBackground?: () => {}; + onStopLoading?: () => {}; + onViewBackgroundRequests?: () => {}; + onSaveResults?: () => {}; + onReload?: () => {}; +} + +const backgroundSessionIndicatorViewStateToProps: { + [state in BackgroundSessionViewState]: { + button: Pick & { tooltipText: string }; + popover: { + text: string; + buttons: Array>; + }; + }; +} = { + [BackgroundSessionViewState.Loading]: { + button: { + color: 'subdued', + iconType: 'clock', + 'aria-label': 'Loading results...', + tooltipText: 'Loading results', + }, + popover: { + text: 'Loading', + buttons: [ + ({ onStopLoading = () => {} }) => ( + + Cancel + + ), + ({ onContinueInBackground = () => {} }) => ( + + Continue in background + + ), + ], + }, + }, + [BackgroundSessionViewState.Completed]: { + button: { + color: 'subdued', + iconType: 'checkInCircleFilled', + 'aria-label': 'Results loaded', + tooltipText: 'Results loaded', + }, + popover: { + text: 'Results loaded', + buttons: [ + ({ onSaveResults = () => {} }) => ( + + Save results + + ), + ({ onViewBackgroundRequests = () => {} }) => ( + // TODO: make this a link + + View requests + + ), + ], + }, + }, + [BackgroundSessionViewState.BackgroundLoading]: { + button: { + iconType: EuiLoadingSpinner, + 'aria-label': 'Loading results in the background', + tooltipText: 'Loading results in the background', + }, + popover: { + text: 'Loading in the background', + buttons: [ + ({ onStopLoading = () => {} }) => ( + + Cancel + + ), + ({ onViewBackgroundRequests = () => {} }) => ( + + View requests + + ), + ], + }, + }, + [BackgroundSessionViewState.BackgroundCompleted]: { + button: { + color: 'success', + iconType: 'checkInCircleFilled', + 'aria-label': 'Results loaded in the background', + tooltipText: 'Results loaded in the background', + }, + popover: { + text: 'Loaded in the background', + buttons: [ + ({ onViewBackgroundRequests = () => {} }) => ( + + View background requests + + ), + ], + }, + }, + [BackgroundSessionViewState.Restored]: { + button: { + color: 'warning', + iconType: 'refresh', + 'aria-label': 'Restored older results. The data is not current.', + tooltipText: 'Restored older results. The data is not current.', + }, + popover: { + text: 'The data is not current', + buttons: [ + ({ onReload = () => {} }) => ( + + Reload + + ), + ], + }, + }, +}; + +export const BackgroundSessionIndicator: React.FC = (props) => { + const [isPopoverOpen, setIsPopoverOpen] = React.useState(false); + const onButtonClick = () => setIsPopoverOpen((isOpen) => !isOpen); + const closePopover = () => setIsPopoverOpen(false); + + const { button, popover } = backgroundSessionIndicatorViewStateToProps[props.state]; + + return ( + + + + } + > + + + +

{popover.text}

+
+
+ {popover.buttons.map((Button, index) => ( + +