From 406ce3d702ac75233190d10ea0b4c3b941fcfd0a Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Thu, 4 Oct 2018 17:38:48 +0200 Subject: [PATCH 01/20] First version of new visualization selection --- .../kibana/public/dashboard/dashboard_app.js | 7 +- .../kibana/public/visualize/index.js | 15 ++ .../visualize/listing/visualize_listing.html | 7 + .../visualize/listing/visualize_listing.js | 26 +- .../listing/visualize_listing_table.js | 5 +- ...ze_constants.js => visualize_constants.ts} | 0 .../public/visualize/wizard/_dialog.scss | 38 +++ .../public/visualize/wizard/_index.scss | 1 + .../kibana/public/visualize/wizard/index.ts | 21 ++ .../public/visualize/wizard/new_vis_modal.tsx | 250 ++++++++++++++++++ .../public/visualize/wizard/show_new_vis.tsx | 50 ++++ .../kibana/public/visualize/wizard/wizard.js | 15 +- .../vis/{vis_category.js => vis_category.ts} | 20 +- src/ui/public/vis/vis_types/vis_type.d.ts | 9 + 14 files changed, 431 insertions(+), 33 deletions(-) rename src/core_plugins/kibana/public/visualize/{visualize_constants.js => visualize_constants.ts} (100%) create mode 100644 src/core_plugins/kibana/public/visualize/wizard/_dialog.scss create mode 100644 src/core_plugins/kibana/public/visualize/wizard/index.ts create mode 100644 src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx create mode 100644 src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx rename src/ui/public/vis/{vis_category.js => vis_category.ts} (87%) diff --git a/src/core_plugins/kibana/public/dashboard/dashboard_app.js b/src/core_plugins/kibana/public/dashboard/dashboard_app.js index 58cad9edd544..7fa1a5cd3f9f 100644 --- a/src/core_plugins/kibana/public/dashboard/dashboard_app.js +++ b/src/core_plugins/kibana/public/dashboard/dashboard_app.js @@ -37,7 +37,6 @@ import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter'; import { DocTitleProvider } from 'ui/doc_title'; import { getTopNavConfig } from './top_nav/get_top_nav_config'; import { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; -import { VisualizeConstants } from '../visualize/visualize_constants'; import { DashboardStateManager } from './dashboard_state_manager'; import { saveDashboard } from './lib'; import { showCloneModal } from './top_nav/show_clone_modal'; @@ -45,6 +44,7 @@ import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; import { DashboardSaveModal } from './top_nav/save_modal'; import { showAddPanel } from './top_nav/show_add_panel'; import { showOptionsPopover } from './top_nav/show_options_popover'; +import { showNewVisModal } from '../visualize/wizard'; import { showShareContextMenu, ShareContextMenuExtensionsRegistryProvider } from 'ui/share'; import { migrateLegacyQuery } from 'ui/utils/migrateLegacyQuery'; import * as filterActions from 'ui/doc_table/actions/filter'; @@ -393,10 +393,7 @@ app.directive('dashboardApp', function ($injector) { }; navActions[TopNavIds.ADD] = () => { const addNewVis = () => { - kbnUrl.change( - `${VisualizeConstants.WIZARD_STEP_1_PAGE_PATH}?${DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM}`); - // Function is called outside of angular. Must apply digest cycle to trigger URL update - $scope.$apply(); + showNewVisModal(visTypes, { editorParams: [DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM] }); }; showAddPanel(dashboardStateManager.addNewPanel, addNewVis, visTypes); diff --git a/src/core_plugins/kibana/public/visualize/index.js b/src/core_plugins/kibana/public/visualize/index.js index a4b220c19760..274e1bbf3383 100644 --- a/src/core_plugins/kibana/public/visualize/index.js +++ b/src/core_plugins/kibana/public/visualize/index.js @@ -40,6 +40,21 @@ uiRoutes template: visualizeListingTemplate, controller: VisualizeListingController, controllerAs: 'listingController', + resolve: { + createNewVis: () => false, + }, + }) + .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, { + template: visualizeListingTemplate, + controller: VisualizeListingController, + controllerAs: 'listingController', + resolve: { + createNewVis: () => true, + }, + }) + // Old path, will be removed in 7.0 + .when('/visualize/step/1', { + redirectTo: VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, }); FeatureCatalogueRegistryProvider.register(() => { diff --git a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.html b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.html index 60d4622862e0..a81f6036b401 100644 --- a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.html +++ b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.html @@ -33,6 +33,13 @@ + + diff --git a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js index 0f8808e11fde..ae3711b1bea9 100644 --- a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js +++ b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js @@ -22,23 +22,41 @@ import 'ui/pager_control'; import 'ui/pager'; import { uiModules } from 'ui/modules'; import { timefilter } from 'ui/timefilter'; +import { VisTypesRegistryProvider } from 'ui/registry/vis_types'; import { VisualizeListingTable } from './visualize_listing_table'; +import { NewVisModal } from '../wizard/new_vis_modal'; const app = uiModules.get('app/visualize', ['ngRoute', 'react']); -app.directive('visualizeListingTable', function (reactDirective) { - return reactDirective(VisualizeListingTable); -}); +app.directive('visualizeListingTable', reactDirective => reactDirective(VisualizeListingTable)); +app.directive('newVisModal', reactDirective => reactDirective(NewVisModal)); -export function VisualizeListingController($injector) { +export function VisualizeListingController($injector, createNewVis) { const Notifier = $injector.get('Notifier'); const Private = $injector.get('Private'); const config = $injector.get('config'); const breadcrumbState = $injector.get('breadcrumbState'); + this.visTypeRegistry = Private(VisTypesRegistryProvider); + timefilter.disableAutoRefreshSelector(); timefilter.disableTimeRangeSelector(); + this.showNewVisModal = false; + + this.createNewVis = () => { + this.showNewVisModal = true; + }; + + this.closeNewVisModal = () => { + this.showNewVisModal = false; + }; + + if (createNewVis) { + // In case the user navigated to the page via the /visualize/new URL we start the dialog immediately + this.createNewVis(); + } + // TODO: Extract this into an external service. const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName; const visualizationService = services.visualizations; diff --git a/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js b/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js index 39af59f46e40..2332b8183be6 100644 --- a/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js +++ b/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js @@ -259,8 +259,8 @@ export class VisualizeListingTable extends Component { this.setState({ selectedRowIds: newSelectedIds }); }; - onCreate() { - window.location = '#/visualize/new'; + onCreate = () => { + this.props.onCreateVis(); } renderToolBarActions() { @@ -322,4 +322,5 @@ export class VisualizeListingTable extends Component { VisualizeListingTable.propTypes = { deleteSelectedItems: PropTypes.func, fetchItems: PropTypes.func, + onCreateVis: PropTypes.func.isRequired, }; diff --git a/src/core_plugins/kibana/public/visualize/visualize_constants.js b/src/core_plugins/kibana/public/visualize/visualize_constants.ts similarity index 100% rename from src/core_plugins/kibana/public/visualize/visualize_constants.js rename to src/core_plugins/kibana/public/visualize/visualize_constants.ts diff --git a/src/core_plugins/kibana/public/visualize/wizard/_dialog.scss b/src/core_plugins/kibana/public/visualize/wizard/_dialog.scss new file mode 100644 index 000000000000..deeccac0d7e2 --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/wizard/_dialog.scss @@ -0,0 +1,38 @@ +.visNewVisDialog { + background: linear-gradient(-25deg, rgba(0,179,164,0.3) 0%,rgba(255,255,255,0) 30%) #FFF; +} + +.visNewVisDialog__types { + width: 400px; + overflow-y: auto; +} + +.visNewVisDialog__description { + width: 380px; + padding: $euiSizeM; +} + +.visNewVisDialog__body { + display: flex; + overflow-y: hidden; +} + +.visNewVisDialog__type:disabled { + opacity: 0.2; + pointer-events: none; +} + +.visNewVisDialog__typeLegacyIcon { + font-size: $euiSizeL; + color: $euiColorSecondary; +} + +.visNewVisDialog__typeImage { + @include size($euiSizeL); +} + +@include euiBreakpoint('xs', 's') { + .visNewVisDialog__types { + width: auto; + } +} diff --git a/src/core_plugins/kibana/public/visualize/wizard/_index.scss b/src/core_plugins/kibana/public/visualize/wizard/_index.scss index 957f378640ea..b12194ed5c36 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/_index.scss +++ b/src/core_plugins/kibana/public/visualize/wizard/_index.scss @@ -1 +1,2 @@ @import './wizard'; +@import './dialog'; diff --git a/src/core_plugins/kibana/public/visualize/wizard/index.ts b/src/core_plugins/kibana/public/visualize/wizard/index.ts new file mode 100644 index 000000000000..7a3fc63af525 --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/wizard/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { NewVisModal } from './new_vis_modal'; +export { showNewVisModal } from './show_new_vis'; diff --git a/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx b/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx new file mode 100644 index 000000000000..0361a9265bf2 --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx @@ -0,0 +1,250 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + EuiFieldSearch, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiKeyPadMenu, + EuiKeyPadMenuItemButton, + EuiModal, + EuiModalBody, + EuiModalHeader, + EuiModalHeaderTitle, + EuiOverlayMask, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; + +import { VisualizeConstants } from '../visualize_constants'; + +import classnames from 'classnames'; +import { sortByOrder } from 'lodash'; +import React, { ChangeEvent } from 'react'; + +import chrome from 'ui/chrome'; +import { memoizeLast } from 'ui/utils/memoize'; +import { VisType } from 'ui/vis'; +import { CATEGORY } from 'ui/vis/vis_category'; + +interface VisTypeListEntry extends VisType { + highlighted: boolean; +} + +interface TypeSelectionProps { + isOpen: boolean; + onClose: () => void; + visTypesRegistry: VisType[]; + editorParams: string[]; +} + +interface TypeSelectionState { + highlightedType: VisType | null; + query: string; +} + +class NewVisModal extends React.Component { + public static defaultProps = { + editorParams: [], + }; + + public state = { + highlightedType: null, + query: '', + }; + + private readonly getFilteredVisTypes = memoizeLast(this.filteredVisTypes); + private readonly isLabsEnabled: boolean; + + constructor(props: TypeSelectionProps) { + super(props); + this.isLabsEnabled = chrome.getUiSettingsClient().get('visualize:enableLabs'); + } + + public render() { + if (!this.props.isOpen) { + return null; + } + + const { highlightedType, query } = this.state; + + const visTypes = this.getFilteredVisTypes(this.props.visTypesRegistry, query); + + return ( + + + + New visualization + + + + + + + + + + + {visTypes.map(this.renderVisType)} + + + + + + + {highlightedType && this.renderDescription(highlightedType)} + {!highlightedType && ( + + +

Select a visualization type

+
+ + +

+ Start creating your visualization by selecting a type for that visualization. +

+
+
+ )} +
+
+
+
+ ); + } + + private renderDescription(visType: VisType) { + return ( + + +

{visType.title}

+
+ + {visType.description} +
+ ); + } + + private renderVisType = (visType: VisTypeListEntry) => { + let stage = {}; + if (visType.stage === 'experimental') { + stage = { + betaBadgeLabel: 'Experimental', + betaBadgeTooltipContent: 'This visualization is yet experimental.', + }; + } else if (visType.stage === 'lab') { + stage = { + betaBadgeLabel: 'Lab', + betaBadgeTooltipContent: 'This visualization is in an early experimental lab state.', + }; + } + const isDisabled = this.state.query !== '' && !visType.highlighted; + const legacyIconClass = classnames( + 'kuiIcon', + 'visNewVisDialog__typeLegacyIcon', + visType.legacyIcon + ); + return ( + this.onSelectVisType(visType)} + onFocus={() => this.highlightType(visType)} + onMouseEnter={() => this.highlightType(visType)} + onMouseLeave={() => this.highlightType(null)} + onBlur={() => this.highlightType(null)} + className="visNewVisDialog__type" + data-test-subj={`visType-${visType.name}`} + disabled={isDisabled} + {...stage} + > + {visType.image && ( + + )} + {!visType.image && visType.legacyIcon && } + {!visType.image && + !visType.legacyIcon && ( + + ); + }; + + private onSelectVisType(visType: VisTypeListEntry) { + const baseUrl = + visType.requiresSearch && visType.options.showIndexSelection + ? `#${VisualizeConstants.WIZARD_STEP_2_PAGE_PATH}?` + : `#${VisualizeConstants.CREATE_PATH}?`; + const params = [`type=${encodeURIComponent(visType.name)}`, ...this.props.editorParams]; + location.href = `${baseUrl}${params.join('&')}`; + this.props.onClose(); + } + + private onQueryChange = (ev: ChangeEvent) => { + this.setState({ + query: ev.target.value, + }); + }; + + private highlightType(visType: VisType | null) { + this.setState({ + highlightedType: visType, + }); + } + + private filteredVisTypes(visTypes: VisType[], query: string): VisTypeListEntry[] { + const types = visTypes.filter(type => { + // Filter out all lab visualizations if lab mode is not enabled + if (!this.isLabsEnabled && type.stage === 'lab') { + return false; + } + + // Filter out visualizations in the hidden category + if (type.category === CATEGORY.HIDDEN) { + return false; + } + + return true; + }); + + let entries: VisTypeListEntry[]; + if (!query) { + entries = types.map(type => ({ ...type, highlighted: false })); + } else { + const q = query.toLowerCase(); + entries = types.map(type => { + const matchesQuery = + type.name.toLowerCase().includes(q) || + type.title.toLowerCase().includes(q) || + (typeof type.description === 'string' && type.description.toLowerCase().includes(q)); + return { ...type, highlighted: matchesQuery }; + }); + } + + return sortByOrder(entries, ['highlighted', 'title'], ['desc', 'asc']); + } +} + +export { NewVisModal }; diff --git a/src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx b/src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx new file mode 100644 index 000000000000..bc16802db593 --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { VisType } from 'ui/vis'; +import { NewVisModal } from './new_vis_modal'; + +interface ShowNewVisModalParams { + editorParams?: string[]; +} + +export function showNewVisModal( + visTypeRegistry: VisType[], + { editorParams = [] }: ShowNewVisModalParams = {} +) { + const container = document.createElement('div'); + const onClose = () => { + ReactDOM.unmountComponentAtNode(container); + document.body.removeChild(container); + }; + + document.body.appendChild(container); + const element = ( + + ); + ReactDOM.render(element, container); +} diff --git a/src/core_plugins/kibana/public/visualize/wizard/wizard.js b/src/core_plugins/kibana/public/visualize/wizard/wizard.js index 218561a7003a..a67f83afbb31 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/wizard.js +++ b/src/core_plugins/kibana/public/visualize/wizard/wizard.js @@ -29,7 +29,6 @@ import { VisualizeConstants } from '../visualize_constants'; import routes from 'ui/routes'; import { VisTypesRegistryProvider } from 'ui/registry/vis_types'; import { uiModules } from 'ui/modules'; -import visualizeWizardStep1Template from './step_1.html'; import visualizeWizardStep2Template from './step_2.html'; import { SavedObjectsClientProvider } from 'ui/saved_objects'; import { timefilter } from 'ui/timefilter'; @@ -40,25 +39,17 @@ const module = uiModules.get('app/visualize', ['kibana/courier']); /** Wizard Step 1 /********/ -// Redirect old route to new route. -routes.when('/visualize/step/1', { - redirectTo: VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, -}); - -routes.when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, { - template: visualizeWizardStep1Template, - controller: 'VisualizeWizardStep1', -}); - module.controller('VisualizeWizardStep1', function ($scope, $route, kbnUrl, Private, config) { timefilter.disableAutoRefreshSelector(); timefilter.disableTimeRangeSelector(); + const visTypes = Private(VisTypesRegistryProvider); + const addToDashMode = $route.current.params[DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM]; kbnUrl.removeParam(DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM); - const visTypes = Private(VisTypesRegistryProvider); const isLabsEnabled = config.get('visualize:enableLabs'); + // TODO: unused $scope.toggleLabView = () => { $route.current.params.lab = !$route.current.params.lab; $route.updateParams($route.current.params); diff --git a/src/ui/public/vis/vis_category.js b/src/ui/public/vis/vis_category.ts similarity index 87% rename from src/ui/public/vis/vis_category.js rename to src/ui/public/vis/vis_category.ts index c2074f5ae248..07b27a175537 100644 --- a/src/ui/public/vis/vis_category.js +++ b/src/ui/public/vis/vis_category.ts @@ -23,16 +23,16 @@ * in the vis creation wizard. */ -const CATEGORY = { - BASIC: 'basic', - DATA: 'data', - GRAPHIC: 'graphic', - MAP: 'map', - OTHER: 'other', - TIME: 'time', +enum CATEGORY { + BASIC = 'basic', + DATA = 'data', + GRAPHIC = 'graphic', + MAP = 'map', + OTHER = 'other', + TIME = 'time', // Hidden is a specific category and doesn't need a display name below - HIDDEN: 'hidden' -}; + HIDDEN = 'hidden', +} const CATEGORY_DISPLAY_NAMES = { [CATEGORY.BASIC]: 'Basic Charts', @@ -40,7 +40,7 @@ const CATEGORY_DISPLAY_NAMES = { [CATEGORY.GRAPHIC]: 'Graphic', [CATEGORY.MAP]: 'Maps', [CATEGORY.OTHER]: 'Other', - [CATEGORY.TIME]: 'Time Series' + [CATEGORY.TIME]: 'Time Series', }; export { CATEGORY, CATEGORY_DISPLAY_NAMES }; diff --git a/src/ui/public/vis/vis_types/vis_type.d.ts b/src/ui/public/vis/vis_types/vis_type.d.ts index 5537e50a6d12..e8aeae8f9965 100644 --- a/src/ui/public/vis/vis_types/vis_type.d.ts +++ b/src/ui/public/vis/vis_types/vis_type.d.ts @@ -17,8 +17,10 @@ * under the License. */ +import { IconType } from '@elastic/eui'; import { RequestHandler, ResponseHandler, Vis } from '..'; import { Status } from '../update_status'; +import { CATEGORY } from '../vis_category'; export class VisualizationController { constructor(element: HTMLElement, vis: Vis); @@ -28,11 +30,18 @@ export class VisualizationController { } export interface VisType { + name: string; title: string; + description?: string; visualization: typeof VisualizationController; isAccessible?: boolean; requestHandler: string | RequestHandler; responseHandler: string | ResponseHandler; + icon?: IconType; + image?: string; + stage: 'experimental' | 'production' | 'lab'; + category?: CATEGORY; + requiresSearch: boolean; // Since we haven't typed everything here yet, we basically "any" the rest // of that interface. This should be removed as soon as this type definition From fb76163b409ed3699919516148ea53f5201d58cd Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Mon, 15 Oct 2018 15:36:19 +0200 Subject: [PATCH 02/20] Extract some components --- .../visualize/listing/visualize_listing.js | 4 +- .../wizard/components/new_vis_help.tsx | 30 ++++++++++++++ .../wizard/components/vis_help_text.tsx | 41 +++++++++++++++++++ .../public/visualize/wizard/new_vis_modal.tsx | 39 ++++++++---------- .../public/visualize/wizard/show_new_vis.tsx | 15 ++++--- 5 files changed, 101 insertions(+), 28 deletions(-) create mode 100644 src/core_plugins/kibana/public/visualize/wizard/components/new_vis_help.tsx create mode 100644 src/core_plugins/kibana/public/visualize/wizard/components/vis_help_text.tsx diff --git a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js index ae3711b1bea9..25f265aa951a 100644 --- a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js +++ b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js @@ -27,9 +27,11 @@ import { VisTypesRegistryProvider } from 'ui/registry/vis_types'; import { VisualizeListingTable } from './visualize_listing_table'; import { NewVisModal } from '../wizard/new_vis_modal'; +import { injectI18nProvider } from '@kbn/i18n/react'; + const app = uiModules.get('app/visualize', ['ngRoute', 'react']); app.directive('visualizeListingTable', reactDirective => reactDirective(VisualizeListingTable)); -app.directive('newVisModal', reactDirective => reactDirective(NewVisModal)); +app.directive('newVisModal', reactDirective => reactDirective(injectI18nProvider(NewVisModal))); export function VisualizeListingController($injector, createNewVis) { const Notifier = $injector.get('Notifier'); diff --git a/src/core_plugins/kibana/public/visualize/wizard/components/new_vis_help.tsx b/src/core_plugins/kibana/public/visualize/wizard/components/new_vis_help.tsx new file mode 100644 index 000000000000..c2c18b24d75d --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/wizard/components/new_vis_help.tsx @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; + +import { EuiText } from '@elastic/eui'; + +export const NewVisHelp = () => ( + +

Start creating your visualization by selecting a type for that visualization.

+

Different kind of visualizations fulfill different purposes.

+

And an even more elaborate description...

+
+); diff --git a/src/core_plugins/kibana/public/visualize/wizard/components/vis_help_text.tsx b/src/core_plugins/kibana/public/visualize/wizard/components/vis_help_text.tsx new file mode 100644 index 000000000000..273a5995e8bc --- /dev/null +++ b/src/core_plugins/kibana/public/visualize/wizard/components/vis_help_text.tsx @@ -0,0 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; + +import { EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; + +import { VisType } from 'ui/vis'; + +interface VisHelpTextProps { + visType: VisType; +} + +export const VisHelpText = (props: VisHelpTextProps) => { + const { visType } = props; + return ( + + +

{visType.title}

+
+ + {visType.description} +
+ ); +}; diff --git a/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx b/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx index 0361a9265bf2..e416337745a5 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx +++ b/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx @@ -30,11 +30,14 @@ import { EuiModalHeaderTitle, EuiOverlayMask, EuiSpacer, - EuiText, EuiTitle, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + import { VisualizeConstants } from '../visualize_constants'; +import { NewVisHelp } from './components/new_vis_help'; +import { VisHelpText } from './components/vis_help_text'; import classnames from 'classnames'; import { sortByOrder } from 'lodash'; @@ -92,7 +95,12 @@ class NewVisModal extends React.Component - New visualization + + + @@ -114,18 +122,19 @@ class NewVisModal extends React.Component - {highlightedType && this.renderDescription(highlightedType)} + {highlightedType && } {!highlightedType && ( -

Select a visualization type

+

+ +

- -

- Start creating your visualization by selecting a type for that visualization. -

-
+
)}
@@ -135,18 +144,6 @@ class NewVisModal extends React.Component - -

{visType.title}

-
- - {visType.description} - - ); - } - private renderVisType = (visType: VisTypeListEntry) => { let stage = {}; if (visType.stage === 'experimental') { diff --git a/src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx b/src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx index bc16802db593..fe4d28900c11 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx +++ b/src/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx @@ -20,6 +20,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { I18nProvider } from '@kbn/i18n/react'; import { VisType } from 'ui/vis'; import { NewVisModal } from './new_vis_modal'; @@ -39,12 +40,14 @@ export function showNewVisModal( document.body.appendChild(container); const element = ( - + + + ); ReactDOM.render(element, container); } From 67305ef8a9f7fc5f2f37a86397207f2659b5c2ed Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Mon, 15 Oct 2018 15:59:33 +0200 Subject: [PATCH 03/20] Remove visualization category --- .../development-create-visualization.asciidoc | 4 +- .../input_control_vis/public/register_vis.js | 2 - .../kbn_vislib_vis_types/public/area.js | 2 - .../kbn_vislib_vis_types/public/gauge.js | 2 - .../kbn_vislib_vis_types/public/goal.js | 2 - .../kbn_vislib_vis_types/public/heatmap.js | 2 - .../kbn_vislib_vis_types/public/histogram.js | 2 - .../public/horizontal_bar.js | 2 - .../kbn_vislib_vis_types/public/line.js | 2 - .../kbn_vislib_vis_types/public/pie.js | 2 - .../public/visualize/wizard/new_vis_modal.tsx | 3 +- .../kibana/public/visualize/wizard/wizard.js | 152 ------------------ .../markdown_vis/public/markdown_vis.js | 2 - .../metric_vis/public/metric_vis.js | 2 - .../metrics/public/kbn_vis_types/index.js | 2 - .../region_map/public/region_map_vis.js | 2 - .../table_vis/public/table_vis.js | 2 - .../tagcloud/public/tag_cloud_vis.js | 2 - .../tile_map/public/tile_map_vis.js | 2 - src/core_plugins/timelion/public/vis/index.js | 2 - src/core_plugins/vega/public/vega_type.js | 2 - src/ui/public/vis/vis_category.ts | 46 ------ src/ui/public/vis/vis_types/base_vis_type.js | 5 +- src/ui/public/vis/vis_types/vis_type.d.ts | 3 +- 24 files changed, 5 insertions(+), 244 deletions(-) delete mode 100644 src/ui/public/vis/vis_category.ts diff --git a/docs/development/visualize/development-create-visualization.asciidoc b/docs/development/visualize/development-create-visualization.asciidoc index 24b5b44b9603..7f6a56771afd 100644 --- a/docs/development/visualize/development-create-visualization.asciidoc +++ b/docs/development/visualize/development-create-visualization.asciidoc @@ -31,7 +31,6 @@ You should also register the visualization with `VisTypesRegistryProvider`. ["source","js"] ----------- -import { CATEGORY } from 'ui/vis/vis_category'; import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { VisTypesRegistryProvider } from 'ui/registry/vis_types'; @@ -43,7 +42,6 @@ const MyNewVisType = (Private) => { title: 'My New Vis', icon: 'my_icon', description: 'Cool new chart', - category: CATEGORY.OTHER ... }); } @@ -59,7 +57,7 @@ The list of common parameters: - *image*: instead of an icon you can provide a SVG image (imported) - *legacyIcon*: (DEPRECATED) provide a class name (e.g. for a font awesome icon) - *description*: description of your visualization as shown in kibana -- *category*: the category your visualization falls into (one of `ui/vis/vis_category` values) +- *hidden*: if set to true, will hide the type from showing up in the visualization wizard - *visConfig*: object holding visualization parameters - *visConfig.defaults*: object holding default visualization configuration - *visualization*: A constructor function for a Visualization. diff --git a/src/core_plugins/input_control_vis/public/register_vis.js b/src/core_plugins/input_control_vis/public/register_vis.js index 889ad1f64559..0f9be258a595 100644 --- a/src/core_plugins/input_control_vis/public/register_vis.js +++ b/src/core_plugins/input_control_vis/public/register_vis.js @@ -18,7 +18,6 @@ */ import './vis.less'; -import { CATEGORY } from 'ui/vis/vis_category'; import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { VisTypesRegistryProvider } from 'ui/registry/vis_types'; import { VisController } from './vis_controller'; @@ -41,7 +40,6 @@ function InputControlVisProvider(Private) { description: i18n.translate('inputControl.register.controlsDescription', { defaultMessage: 'Create interactive controls for easy dashboard manipulation.' }), - category: CATEGORY.OTHER, stage: 'lab', requiresUpdateStatus: [Status.PARAMS, Status.TIME], feedbackMessage: defaultFeedbackMessage, diff --git a/src/core_plugins/kbn_vislib_vis_types/public/area.js b/src/core_plugins/kbn_vislib_vis_types/public/area.js index 4fc5b79a5f54..26558aa93792 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/area.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/area.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import pointSeriesTemplate from './editors/point_series.html'; export default function PointSeriesVisType(Private) { @@ -30,7 +29,6 @@ export default function PointSeriesVisType(Private) { title: 'Area', icon: 'visArea', description: 'Emphasize the quantity beneath a line chart', - category: CATEGORY.BASIC, visConfig: { defaults: { type: 'area', diff --git a/src/core_plugins/kbn_vislib_vis_types/public/gauge.js b/src/core_plugins/kbn_vislib_vis_types/public/gauge.js index 09b9262fcabc..42e43c820ed0 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/gauge.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/gauge.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import gaugeTemplate from './editors/gauge.html'; import { vislibColorMaps } from 'ui/vislib/components/color/colormaps'; @@ -32,7 +31,6 @@ export default function GaugeVisType(Private) { icon: 'visGauge', description: `Gauges indicate the status of a metric. Use it to show how a metric's value relates to reference threshold values.`, - category: CATEGORY.DATA, visConfig: { defaults: { type: 'gauge', diff --git a/src/core_plugins/kbn_vislib_vis_types/public/goal.js b/src/core_plugins/kbn_vislib_vis_types/public/goal.js index 1a52764387d3..42dacc1d0352 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/goal.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/goal.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import gaugeTemplate from './editors/gauge.html'; import { vislibColorMaps } from 'ui/vislib/components/color/colormaps'; @@ -31,7 +30,6 @@ export default function GoalVisType(Private) { title: 'Goal', icon: 'visGoal', description: 'A goal chart indicates how close you are to your final goal.', - category: CATEGORY.DATA, visConfig: { defaults: { addTooltip: true, diff --git a/src/core_plugins/kbn_vislib_vis_types/public/heatmap.js b/src/core_plugins/kbn_vislib_vis_types/public/heatmap.js index e124283a083e..68a46177cd4c 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/heatmap.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/heatmap.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import heatmapTemplate from './editors/heatmap.html'; import { vislibColorMaps } from 'ui/vislib/components/color/colormaps'; @@ -31,7 +30,6 @@ export default function HeatmapVisType(Private) { title: 'Heat Map', icon: 'visHeatmap', description: 'Shade cells within a matrix', - category: CATEGORY.BASIC, visConfig: { defaults: { type: 'heatmap', diff --git a/src/core_plugins/kbn_vislib_vis_types/public/histogram.js b/src/core_plugins/kbn_vislib_vis_types/public/histogram.js index 68a269ec1c42..c9db055d530c 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/histogram.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/histogram.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import pointSeriesTemplate from './editors/point_series.html'; export default function PointSeriesVisType(Private) { @@ -30,7 +29,6 @@ export default function PointSeriesVisType(Private) { title: 'Vertical Bar', icon: 'visBarVertical', description: 'Assign a continuous variable to each axis', - category: CATEGORY.BASIC, visConfig: { defaults: { type: 'histogram', diff --git a/src/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js b/src/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js index b679256924b2..464f70acaf02 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import pointSeriesTemplate from './editors/point_series.html'; export default function PointSeriesVisType(Private) { @@ -30,7 +29,6 @@ export default function PointSeriesVisType(Private) { title: 'Horizontal Bar', icon: 'visBarHorizontal', description: 'Assign a continuous variable to each axis', - category: CATEGORY.BASIC, visConfig: { defaults: { type: 'histogram', diff --git a/src/core_plugins/kbn_vislib_vis_types/public/line.js b/src/core_plugins/kbn_vislib_vis_types/public/line.js index c6cae6698207..787b30cc84c8 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/line.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/line.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import pointSeriesTemplate from './editors/point_series.html'; export default function PointSeriesVisType(Private) { @@ -30,7 +29,6 @@ export default function PointSeriesVisType(Private) { title: 'Line', icon: 'visLine', description: 'Emphasize trends', - category: CATEGORY.BASIC, visConfig: { defaults: { type: 'line', diff --git a/src/core_plugins/kbn_vislib_vis_types/public/pie.js b/src/core_plugins/kbn_vislib_vis_types/public/pie.js index 665d065fa83c..2f3fa03d8a5a 100644 --- a/src/core_plugins/kbn_vislib_vis_types/public/pie.js +++ b/src/core_plugins/kbn_vislib_vis_types/public/pie.js @@ -19,7 +19,6 @@ import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { CATEGORY } from 'ui/vis/vis_category'; import pieTemplate from './editors/pie.html'; export default function HistogramVisType(Private) { @@ -30,7 +29,6 @@ export default function HistogramVisType(Private) { title: 'Pie', icon: 'visPie', description: 'Compare parts of a whole', - category: CATEGORY.BASIC, visConfig: { defaults: { type: 'pie', diff --git a/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx b/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx index e416337745a5..7694c0f29bb6 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx +++ b/src/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx @@ -46,7 +46,6 @@ import React, { ChangeEvent } from 'react'; import chrome from 'ui/chrome'; import { memoizeLast } from 'ui/utils/memoize'; import { VisType } from 'ui/vis'; -import { CATEGORY } from 'ui/vis/vis_category'; interface VisTypeListEntry extends VisType { highlighted: boolean; @@ -219,7 +218,7 @@ class NewVisModal extends React.Component
+
+

+ + Start creating your visualization by selecting a type for that visualization. + +

+
+ + + + + + + From 1994bd6f9441967cba027cf4883e38134b43cc99 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Thu, 22 Nov 2018 09:38:03 +0100 Subject: [PATCH 17/20] Create VisTypeIcon --- .../__snapshots__/new_vis_modal.test.tsx.snap | 98 +++++++++++++------ .../wizard/type_selection/type_selection.tsx | 17 +--- .../wizard/type_selection/vis_type_icon.tsx | 54 ++++++++++ 3 files changed, 122 insertions(+), 47 deletions(-) create mode 100644 src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_type_icon.tsx diff --git a/src/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap index 5176e542cbce..ab45dcb85070 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap +++ b/src/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap @@ -540,22 +540,28 @@ exports[`NewVisModal should render as expected 1`] = `
- + > + + + +

- + > + + + +

- {visType.image && ( - - )} - {!visType.image && visType.legacyIcon && } - {!visType.image && - !visType.legacyIcon && ( -

From 8a97754c8b7ba40ab5d8d2dbc33141d4ffd37188 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Thu, 22 Nov 2018 09:48:07 +0100 Subject: [PATCH 19/20] Change experimental wording --- .../public/visualize/wizard/type_selection/vis_help_text.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx b/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx index acf630ecc1cc..9213972bc7f0 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx +++ b/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx @@ -41,7 +41,8 @@ export const VisHelpText = ({ visType }: VisHelpTextProps) => { From d698e3fe5a6994f4c693cc1320ae7abebee1aac7 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Thu, 22 Nov 2018 10:50:50 +0100 Subject: [PATCH 20/20] Use regular quotes for i18n engine --- .../public/visualize/wizard/type_selection/vis_help_text.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx b/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx index 9213972bc7f0..249931733dc2 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx +++ b/src/core_plugins/kibana/public/visualize/wizard/type_selection/vis_help_text.tsx @@ -41,8 +41,8 @@ export const VisHelpText = ({ visType }: VisHelpTextProps) => {