diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index 33e820a5300c6..659ca36d84090 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -62,6 +62,7 @@ export default function (kibana) { hacks: [ 'plugins/kibana/discover', 'plugins/kibana/dev_tools', + 'plugins/kibana/visualize', ], savedObjectTypes: [ 'plugins/kibana/visualize/saved_visualizations/saved_visualization_register', diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html index 4f41ab5d4fad6..c7fd8600b73bb 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html @@ -35,7 +35,7 @@ --> { + if (!angularModuleInstance) { + angularModuleInstance = createLocalAngularModule(deps.core, deps.navigation); + // global routing stuff + configureAppAngularModule(angularModuleInstance, deps.core as LegacyCoreStart, true); + // custom routing stuff + initVisualizeApp(angularModuleInstance, deps); + } + const $injector = mountVisualizeApp(appBasePath, element); + return () => $injector.get('$rootScope').$destroy(); +}; + +const mainTemplate = (basePath: string) => `
+ +
+
+`; + +const moduleName = 'app/visualize'; + +const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react']; + +function mountVisualizeApp(appBasePath: string, element: HTMLElement) { + const mountpoint = document.createElement('div'); + mountpoint.setAttribute('style', 'height: 100%'); + mountpoint.innerHTML = mainTemplate(appBasePath); + // bootstrap angular into detached element and attach it later to + // make angular-within-angular possible + const $injector = angular.bootstrap(mountpoint, [moduleName]); + // initialize global state handler + element.appendChild(mountpoint); + return $injector; +} + +function createLocalAngularModule(core: AppMountContext['core'], navigation: NavigationStart) { + createLocalI18nModule(); + createLocalPrivateModule(); + createLocalPromiseModule(); + createLocalConfigModule(core); + createLocalKbnUrlModule(); + createLocalStateModule(); + createLocalPersistedStateModule(); + createLocalTopNavModule(navigation); + createLocalConfirmModalModule(); + + const visualizeAngularModule: IModule = angular.module(moduleName, [ + ...thirdPartyAngularDependencies, + 'app/visualize/Config', + 'app/visualize/I18n', + 'app/visualize/Private', + 'app/visualize/PersistedState', + 'app/visualize/TopNav', + 'app/visualize/State', + 'app/visualize/ConfirmModal', + ]); + return visualizeAngularModule; +} + +function createLocalConfirmModalModule() { + angular + .module('app/visualize/ConfirmModal', ['react']) + .factory('confirmModal', confirmModalFactory) + .directive('confirmModal', reactDirective => reactDirective(EuiConfirmModal)); +} + +function createLocalStateModule() { + angular + .module('app/visualize/State', [ + 'app/visualize/Private', + 'app/visualize/Config', + 'app/visualize/KbnUrl', + 'app/visualize/Promise', + 'app/visualize/PersistedState', + ]) + .factory('AppState', function(Private: IPrivate) { + return Private(AppStateProvider); + }) + .service('getAppState', function(Private: IPrivate) { + return Private(AppStateProvider).getAppState; + }) + .service('globalState', function(Private: IPrivate) { + return Private(GlobalStateProvider); + }); +} + +function createLocalPersistedStateModule() { + angular + .module('app/visualize/PersistedState', ['app/visualize/Private', 'app/visualize/Promise']) + .factory('PersistedState', (Private: IPrivate) => { + const Events = Private(EventsProvider); + return class AngularPersistedState extends PersistedState { + constructor(value: any, path: any) { + super(value, path, Events); + } + }; + }); +} + +function createLocalKbnUrlModule() { + angular + .module('app/visualize/KbnUrl', ['app/visualize/Private', 'ngRoute']) + .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider)) + .service('redirectWhenMissing', (Private: IPrivate) => Private(RedirectWhenMissingProvider)); +} + +function createLocalConfigModule(core: AppMountContext['core']) { + angular + .module('app/visualize/Config', ['app/visualize/Private']) + .provider('stateManagementConfig', StateManagementConfigProvider) + .provider('config', () => { + return { + $get: () => ({ + get: core.uiSettings.get.bind(core.uiSettings), + }), + }; + }); +} + +function createLocalPromiseModule() { + angular.module('app/visualize/Promise', []).service('Promise', PromiseServiceCreator); +} + +function createLocalPrivateModule() { + angular.module('app/visualize/Private', []).provider('Private', PrivateProvider); +} + +function createLocalTopNavModule(navigation: NavigationStart) { + angular + .module('app/visualize/TopNav', ['react']) + .directive('kbnTopNav', createTopNavDirective) + .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); +} + +function createLocalI18nModule() { + angular + .module('app/visualize/I18n', []) + .provider('i18n', I18nProvider) + .filter('i18n', i18nFilter) + .directive('i18nId', i18nDirective); +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html index bf9ac9b9bbe36..6190b92c9be3e 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html @@ -39,7 +39,7 @@ show-search-bar="true" show-query-bar="true" show-query-input="showQueryInput()" - show-filter-bar="showFilterBar() && chrome.getVisible()" + show-filter-bar="showFilterBar() && isVisible" show-date-picker="showQueryBarTimePicker()" show-auto-refresh-only="!showQueryBarTimePicker()" query="state.query" @@ -67,7 +67,7 @@ --> savedVisualizations.get($route.current.params)) - .then(savedVis => { - if (savedVis.vis.type.setup) { - return savedVis.vis.type.setup(savedVis) - .catch(() => savedVis); - } - return savedVis; - }) - .catch(redirectWhenMissing({ - '*': '/visualize' - })); - } - } - }) - .when(`${VisualizeConstants.EDIT_PATH}/:id`, { - template: editorTemplate, - k7Breadcrumbs: getEditBreadcrumbs, - resolve: { - savedVis: function (savedVisualizations, redirectWhenMissing, $route, $rootScope, kbnUrl) { - return ensureDefaultIndexPattern(core, npData, $rootScope, kbnUrl) - .then(() => savedVisualizations.get($route.current.params.id)) - .then((savedVis) => { - chrome.recentlyAccessed.add( - savedVis.getFullPath(), - savedVis.title, - savedVis.id - ); - return savedVis; - }) - .then(savedVis => { - if (savedVis.vis.type.setup) { - return savedVis.vis.type.setup(savedVis).catch(() => savedVis); - } - return savedVis; - }) - .catch( - redirectWhenMissing({ - visualization: '/visualize', - search: '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, - 'index-pattern': - '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, - 'index-pattern-field': - '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, - }) - ); - } - } - }); +import { getServices } from '../kibana_services'; -uiModules - .get('app/visualize', [ - 'kibana/url' - ]) - .directive('visualizeApp', function () { +export function initEditorDirective(app, deps) { + app.directive('visualizeApp', function () { return { restrict: 'E', controllerAs: 'visualizeApp', - controller: VisEditor, + controller: VisualizeAppController, }; }); -function VisEditor( + initVisEditorDirective(app, deps); + initVisualizationDirective(app, deps); +} + +function VisualizeAppController( $scope, $element, $route, @@ -154,19 +70,42 @@ function VisEditor( $window, $injector, $timeout, - indexPatterns, kbnUrl, redirectWhenMissing, - Private, Promise, - config, kbnBaseUrl, - localStorage, + getAppState, + globalState, ) { - const queryFilter = Private(FilterBarQueryFilterProvider); - + const { + indexPatterns, + localStorage, + visualizeCapabilities, + share, + data: { + query: { + filterManager, + timefilter: { timefilter }, + }, + }, + toastNotifications, + legacyChrome, + chrome, + getBasePath, + core: { docLinks }, + savedQueryService, + uiSettings, + } = getServices(); + + const filterStateManager = new FilterStateManager(globalState, getAppState, filterManager); + const queryFilter = filterManager; // Retrieve the resolved SavedVis instance. const savedVis = $route.current.locals.savedVis; + const _applyVis = () => { + $scope.$apply(); + }; + // This will trigger a digest cycle. This is needed when vis is updated from a global angular like in visualize_embeddable.js. + savedVis.vis.on('apply', _applyVis); // vis is instance of src/legacy/ui/public/vis/vis.js. // SearchSource is a promise-based stream of search results that can inherit from other search sources. const { vis, searchSource } = savedVis; @@ -177,7 +116,7 @@ function VisEditor( dirty: !savedVis.id }; - $scope.topNavMenu = [...(capabilities.visualize.save ? [{ + $scope.topNavMenu = [...(visualizeCapabilities.save ? [{ id: 'save', label: i18n.translate('kbn.topNavMenu.saveVisualizationButtonLabel', { defaultMessage: 'save' }), description: i18n.translate('kbn.visualize.topNavMenu.saveVisualizationButtonAriaLabel', { @@ -246,7 +185,7 @@ function VisEditor( share.toggleShareContextMenu({ anchorElement, allowEmbed: true, - allowShortUrl: capabilities.visualize.createShortUrl, + allowShortUrl: visualizeCapabilities.createShortUrl, shareableUrl: unhashUrl(window.location.href), objectId: savedVis.id, objectType: 'visualization', @@ -295,7 +234,7 @@ function VisEditor( let stateMonitor; if (savedVis.id) { - docTitle.change(savedVis.title); + chrome.docTitle.change(savedVis.title); } // Extract visualization state with filtered aggs. You can see these filtered aggs in the URL. @@ -306,7 +245,7 @@ function VisEditor( linked: !!savedVis.savedSearchId, query: searchSource.getOwnField('query') || { query: '', - language: localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage') + language: localStorage.get('kibana.userQueryLanguage') || uiSettings.get('search:queryLanguage') }, filters: searchSource.getOwnField('filter') || [], vis: savedVisState @@ -345,9 +284,9 @@ function VisEditor( queryFilter.setFilters(filters); }; - $scope.showSaveQuery = capabilities.visualize.saveQuery; + $scope.showSaveQuery = visualizeCapabilities.saveQuery; - $scope.$watch(() => capabilities.visualize.saveQuery, (newCapability) => { + $scope.$watch(() => visualizeCapabilities.saveQuery, (newCapability) => { $scope.showSaveQuery = newCapability; }); @@ -455,13 +394,15 @@ function VisEditor( } })); - $scope.$on('$destroy', function () { + $scope.$on('$destroy', () => { if ($scope._handler) { $scope._handler.destroy(); } savedVis.destroy(); stateMonitor.destroy(); + filterStateManager.destroy(); subscriptions.unsubscribe(); + $scope.vis.off('apply', _applyVis); }); @@ -503,7 +444,7 @@ function VisEditor( delete $state.savedQuery; $state.query = { query: '', - language: localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage') + language: localStorage.get('kibana.userQueryLanguage') || uiSettings.get('search:queryLanguage') }; queryFilter.removeAll(); $state.save(); @@ -589,14 +530,14 @@ function VisEditor( // Since we aren't reloading the page, only inserting a new browser history item, we need to manually update // the last url for this app, so directly clicking on the Visualize tab will also bring the user to the saved // url, not the unsaved one. - chromeLegacy.trackSubUrlForApp('kibana:visualize', savedVisualizationParsedUrl); + legacyChrome.trackSubUrlForApp('kibana:visualize', savedVisualizationParsedUrl); const lastDashboardAbsoluteUrl = chrome.navLinks.get('kibana:dashboard').url; const dashboardParsedUrl = absoluteToParsedUrl(lastDashboardAbsoluteUrl, getBasePath()); dashboardParsedUrl.addQueryParameter(DashboardConstants.NEW_VISUALIZATION_ID_PARAM, savedVis.id); kbnUrl.change(dashboardParsedUrl.appPath); } else if (savedVis.id === $route.current.params.id) { - docTitle.change(savedVis.lastSavedTitle); + chrome.docTitle.change(savedVis.lastSavedTitle); chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs)); savedVis.vis.title = savedVis.title; savedVis.vis.description = savedVis.description; @@ -661,7 +602,7 @@ function VisEditor( vis.type.feedbackMessage; }; - addHelpMenuToAppChrome(chrome); + addHelpMenuToAppChrome(chrome, docLinks); init(); } diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js index 198fbe19a0b7a..d3651735c1a1d 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js @@ -17,13 +17,8 @@ * under the License. */ -import { getServices } from '../kibana_services'; - -const { embeddables, uiModules } = getServices(); - -uiModules - .get('kibana/directive', ['ngSanitize']) - .directive('visualizationEmbedded', function (Private, $timeout, getAppState) { +export function initVisualizationDirective(app, deps) { + app.directive('visualizationEmbedded', function ($timeout, getAppState) { return { restrict: 'E', @@ -37,7 +32,7 @@ uiModules link: function ($scope, element) { $scope.renderFunction = async () => { if (!$scope._handler) { - $scope._handler = await embeddables.getEmbeddableFactory('visualization').createFromObject($scope.savedObj, { + $scope._handler = await deps.embeddables.getEmbeddableFactory('visualization').createFromObject($scope.savedObj, { timeRange: $scope.timeRange, filters: $scope.filters || [], query: $scope.query, @@ -66,3 +61,4 @@ uiModules } }; }); +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js index ead77e6bc41d5..bc6d4d4c48466 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js @@ -17,15 +17,8 @@ * under the License. */ -import { getServices, VisEditorTypesRegistryProvider } from '../kibana_services'; - -const { uiModules } = getServices(); - -uiModules - .get('kibana/directive', ['ngSanitize']) - .directive('visualizationEditor', function (Private, $timeout, getAppState) { - const editorTypes = Private(VisEditorTypesRegistryProvider); - +export function initVisEditorDirective(app, deps) { + app.directive('visualizationEditor', function ($timeout, getAppState) { return { restrict: 'E', scope: { @@ -38,7 +31,8 @@ uiModules link: function ($scope, element) { const editorType = $scope.savedObj.vis.type.editor; const Editor = typeof editorType === 'function' ? editorType : - editorTypes.find(editor => editor.key === editorType); + deps.editorTypes.find(editor => editor.key === editorType); + const editor = new Editor(element[0], $scope.savedObj); $scope.renderFunction = () => { @@ -62,3 +56,4 @@ uiModules } }; }); +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx b/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx index 065feae045597..d8792a761b186 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx @@ -19,8 +19,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { Embeddable, EmbeddableOutput } from '../../../../../../plugins/embeddable/public'; -import { Embeddable, EmbeddableOutput } from '../kibana_services'; import { DisabledLabVisualization } from './disabled_lab_visualization'; import { VisualizeInput } from './visualize_embeddable'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts b/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts index 9bc9ab99c4aff..7fe3678bb1f77 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts @@ -17,11 +17,10 @@ * under the License. */ -import { getServices, getFromSavedObject, VisSavedObject } from '../kibana_services'; +import { npStart } from 'ui/new_platform'; -import { IIndexPattern } from '../../../../../../plugins/data/public'; - -const { savedObjectsClient, uiSettings } = getServices(); +import { VisSavedObject } from './visualize_embeddable'; +import { indexPatterns, IIndexPattern } from '../../../../../../plugins/data/public'; export async function getIndexPattern( savedVis: VisSavedObject @@ -30,7 +29,8 @@ export async function getIndexPattern( return savedVis.vis.indexPattern; } - const defaultIndex = uiSettings.get('defaultIndex'); + const savedObjectsClient = npStart.core.savedObjects.client; + const defaultIndex = npStart.core.uiSettings.get('defaultIndex'); if (savedVis.vis.params.index_pattern) { const indexPatternObjects = await savedObjectsClient.find({ @@ -39,10 +39,10 @@ export async function getIndexPattern( search: `"${savedVis.vis.params.index_pattern}"`, searchFields: ['title'], }); - const [indexPattern] = indexPatternObjects.savedObjects.map(getFromSavedObject); + const [indexPattern] = indexPatternObjects.savedObjects.map(indexPatterns.getFromSavedObject); return indexPattern; } const savedObject = await savedObjectsClient.get('index-pattern', defaultIndex); - return getFromSavedObject(savedObject); + return indexPatterns.getFromSavedObject(savedObject); } diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts index e5a723a99eafd..7ab60f8867c38 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts @@ -375,6 +375,8 @@ export class VisualizeEmbeddable extends Embeddable { diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx index 15ad9a33232ef..7c9efa280c9f1 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx @@ -17,36 +17,48 @@ * under the License. */ +import 'uiExports/contextMenuActions'; +import 'uiExports/devTools'; +import 'uiExports/docViews'; +import 'uiExports/embeddableActions'; +import 'uiExports/fieldFormatEditors'; +import 'uiExports/fieldFormats'; +import 'uiExports/home'; +import 'uiExports/indexManagement'; +import 'uiExports/inspectorViews'; +import 'uiExports/savedObjectTypes'; +import 'uiExports/search'; +import 'uiExports/shareContextMenuExtensions'; +import 'uiExports/visTypes'; +import 'uiExports/visualize'; + import { i18n } from '@kbn/i18n'; +import chrome from 'ui/chrome'; +import { npStart } from 'ui/new_platform'; + import { Legacy } from 'kibana'; import { SavedObjectAttributes } from 'kibana/server'; +import { + EmbeddableFactory, + ErrorEmbeddable, + Container, + EmbeddableOutput, +} from '../../../../../../plugins/embeddable/public'; +import { start as visualizations } from '../../../../visualizations/public/np_ready/public/legacy'; import { showNewVisModal } from '../wizard'; import { SavedVisualizations } from '../types'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; import { getIndexPattern } from './get_index_pattern'; -import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable'; -import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; -import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; - import { - getServices, - Container, - EmbeddableFactory, - EmbeddableOutput, - ErrorEmbeddable, + VisualizeEmbeddable, + VisualizeInput, + VisualizeOutput, VisSavedObject, -} from '../kibana_services'; - -const { - addBasePath, - capabilities, - embeddable, - getInjector, - uiSettings, - visualizations, -} = getServices(); +} from './visualize_embeddable'; +import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; +import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; interface VisualizationAttributes extends SavedObjectAttributes { visState: string; @@ -96,7 +108,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< if (!visType) { return false; } - if (uiSettings.get('visualize:enableLabs')) { + if (npStart.core.uiSettings.get('visualize:enableLabs')) { return true; } return visType.stage !== 'experimental'; @@ -108,7 +120,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< } public isEditable() { - return capabilities.visualize.save as boolean; + return npStart.core.application.capabilities.visualize.save as boolean; } public getDisplayName() { @@ -122,14 +134,16 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< input: Partial & { id: string }, parent?: Container ): Promise { - const $injector = await getInjector(); + const $injector = await chrome.dangerouslyGetActiveInjector(); const config = $injector.get('config'); const savedVisualizations = $injector.get('savedVisualizations'); try { const visId = savedObject.id as string; - const editUrl = visId ? addBasePath(`/app/kibana${savedVisualizations.urlFor(visId)}`) : ''; + const editUrl = visId + ? npStart.core.http.basePath.prepend(`/app/kibana${savedVisualizations.urlFor(visId)}`) + : ''; const isLabsEnabled = config.get('visualize:enableLabs'); if (!isLabsEnabled && savedObject.vis.type.stage === 'experimental') { @@ -161,7 +175,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< input: Partial & { id: string }, parent?: Container ): Promise { - const $injector = await getInjector(); + const $injector = await chrome.dangerouslyGetActiveInjector(); const savedVisualizations = $injector.get('savedVisualizations'); try { @@ -179,14 +193,15 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< // TODO: This is a bit of a hack to preserve the original functionality. Ideally we will clean this up // to allow for in place creation of visualizations without having to navigate away to a new URL. if (this.visTypes) { - showNewVisModal(this.visTypes, { - editorParams: ['addToDashboard'], - }); + showNewVisModal( + this.visTypes, + { + editorParams: ['addToDashboard'], + }, + npStart.core.http.basePath.prepend, + npStart.core.uiSettings + ); } return undefined; } } - -VisualizeEmbeddableFactory.createVisualizeEmbeddableFactory().then(embeddableFactory => { - embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); -}); diff --git a/src/legacy/core_plugins/kibana/public/visualize/global_state_sync.ts b/src/legacy/core_plugins/kibana/public/visualize/global_state_sync.ts new file mode 100644 index 0000000000000..71156bc38d498 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/global_state_sync.ts @@ -0,0 +1,67 @@ +/* + * 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 { State } from './legacy_imports'; +import { DataPublicPluginStart as DataStart } from '../../../../../plugins/data/public'; + +/** + * Helper function to sync the global state with the various state providers + * when a local angular application mounts. There are three different ways + * global state can be passed into the application: + * * parameter in the URL hash - e.g. shared link + * * in-memory state in the data plugin exports (timefilter and filterManager) - e.g. default values + * + * This function looks up the three sources (earlier in the list means it takes precedence), + * puts it into the globalState object and syncs it with the url. + * + * Currently the legacy chrome takes care of restoring the global state when navigating from + * one app to another - to migrate away from that it will become necessary to also write the current + * state to local storage + */ +export function syncOnMount( + globalState: State, + { + query: { + filterManager, + timefilter: { timefilter }, + }, + }: DataStart +) { + // pull in global state information from the URL + globalState.fetch(); + // remember whether there were info in the URL + const hasGlobalURLState = Boolean(Object.keys(globalState.toObject()).length); + + // sync kibana platform state with the angular global state + if (!globalState.time) { + globalState.time = timefilter.getTime(); + } + if (!globalState.refreshInterval) { + globalState.refreshInterval = timefilter.getRefreshInterval(); + } + if (!globalState.filters && filterManager.getGlobalFilters().length > 0) { + globalState.filters = filterManager.getGlobalFilters(); + } + // only inject cross app global state if there is none in the url itself (that takes precedence) + if (hasGlobalURLState) { + // set flag the global state is set from the URL + globalState.$inheritedGlobalState = true; + } + globalState.save(); +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js index d27003f39d4c0..9c00947d7663c 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js @@ -18,10 +18,8 @@ */ import { i18n } from '@kbn/i18n'; -import { getServices } from '../kibana_services'; -const { docLinks } = getServices(); -export function addHelpMenuToAppChrome(chrome) { +export function addHelpMenuToAppChrome(chrome, docLinks) { chrome.setHelpExtension({ appName: i18n.translate('kbn.visualize.helpMenu.appName', { defaultMessage: 'Visualize', diff --git a/src/legacy/core_plugins/kibana/public/visualize/index.js b/src/legacy/core_plugins/kibana/public/visualize/index.js deleted file mode 100644 index d42c72f67f815..0000000000000 --- a/src/legacy/core_plugins/kibana/public/visualize/index.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 { ensureDefaultIndexPattern } from 'ui/legacy_compat'; -import './editor/editor'; -import { i18n } from '@kbn/i18n'; -import './saved_visualizations/_saved_vis'; -import './saved_visualizations/saved_visualizations'; -import visualizeListingTemplate from './listing/visualize_listing.html'; -import { VisualizeListingController } from './listing/visualize_listing'; -import { VisualizeConstants } from './visualize_constants'; -import { getLandingBreadcrumbs, getWizardStep1Breadcrumbs } from './breadcrumbs'; - -import { getServices, FeatureCatalogueCategory } from './kibana_services'; - -const { FeatureCatalogueRegistryProvider, uiRoutes } = getServices(); - -uiRoutes - .defaults(/visualize/, { - requireUICapability: 'visualize.show', - badge: uiCapabilities => { - if (uiCapabilities.visualize.save) { - return undefined; - } - - return { - text: i18n.translate('kbn.visualize.badge.readOnly.text', { - defaultMessage: 'Read only', - }), - tooltip: i18n.translate('kbn.visualize.badge.readOnly.tooltip', { - defaultMessage: 'Unable to save visualizations', - }), - iconType: 'glasses' - }; - } - }) - .when(VisualizeConstants.LANDING_PAGE_PATH, { - template: visualizeListingTemplate, - k7Breadcrumbs: getLandingBreadcrumbs, - controller: VisualizeListingController, - controllerAs: 'listingController', - resolve: { - createNewVis: () => false, - hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(getServices().core, getServices().npData, $rootScope, kbnUrl) - }, - }) - .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, { - template: visualizeListingTemplate, - k7Breadcrumbs: getWizardStep1Breadcrumbs, - controller: VisualizeListingController, - controllerAs: 'listingController', - resolve: { - createNewVis: () => true, - hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(getServices().core, getServices().npData, $rootScope, kbnUrl) - }, - }); - -FeatureCatalogueRegistryProvider.register(() => { - return { - id: 'visualize', - title: 'Visualize', - description: i18n.translate( - 'kbn.visualize.visualizeDescription', - { - defaultMessage: 'Create visualizations and aggregate data stores in your Elasticsearch indices.', - } - ), - icon: 'visualizeApp', - path: `/app/kibana#${VisualizeConstants.LANDING_PAGE_PATH}`, - showOnHomePage: true, - category: FeatureCatalogueCategory.DATA - }; -}); diff --git a/src/legacy/core_plugins/kibana/public/visualize/index.ts b/src/legacy/core_plugins/kibana/public/visualize/index.ts new file mode 100644 index 0000000000000..5e9f2fdeb8999 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/index.ts @@ -0,0 +1,70 @@ +/* + * 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 'ui/collapsible_sidebar'; // used in default editor +import 'ui/vis/editors/default/sidebar'; + +import { + IPrivate, + legacyChrome, + npSetup, + npStart, + SavedObjectRegistryProvider, + VisEditorTypesRegistryProvider, +} from './legacy_imports'; +import { VisualizePlugin, LegacyAngularInjectedDependencies } from './plugin'; +import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy'; +import { start as navigation } from '../../../navigation/public/legacy'; +import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; + +/** + * Get dependencies relying on the global angular context. + * They also have to get resolved together with the legacy imports above + */ +async function getAngularDependencies(): Promise { + const injector = await legacyChrome.dangerouslyGetActiveInjector(); + + const Private = injector.get('Private'); + + const editorTypes = Private(VisEditorTypesRegistryProvider); + const savedObjectRegistry = Private(SavedObjectRegistryProvider); + + return { + legacyChrome, + editorTypes, + savedObjectRegistry, + savedVisualizations: injector.get('savedVisualizations'), + }; +} + +(() => { + const instance = new VisualizePlugin(); + instance.setup(npSetup.core, { + ...npSetup.plugins, + __LEGACY: { + getAngularDependencies, + }, + }); + instance.start(npStart.core, { + ...npStart.plugins, + embeddables, + navigation, + visualizations, + }); +})(); diff --git a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts index 40d36dab227fa..36a9ecf3fcf8c 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts @@ -17,108 +17,59 @@ * under the License. */ -import 'angular-sanitize'; // used in visualization_editor.js and visualization.js -import 'ui/collapsible_sidebar'; // used in default editor -import 'ui/vis/editors/default/sidebar'; -// load directives -import '../../../data/public'; +import { + ChromeStart, + LegacyCoreStart, + SavedObjectsClientContract, + ToastsStart, + IUiSettingsClient, +} from 'kibana/public'; -import { npStart } from 'ui/new_platform'; -import angular from 'angular'; // just used in editor.js -import chromeLegacy from 'ui/chrome'; +import { NavigationStart } from '../../../navigation/public'; +import { Storage } from '../../../../../plugins/kibana_utils/public'; +import { IEmbeddableStart } from '../../../../../plugins/embeddable/public'; +import { SharePluginStart } from '../../../../../plugins/share/public'; +import { DataPublicPluginStart, IndexPatternsContract } from '../../../../../plugins/data/public'; +import { VisualizationsStart } from '../../../visualizations/public'; +import { SavedVisualizations } from './types'; -import uiRoutes from 'ui/routes'; - -// @ts-ignore -import { docTitle } from 'ui/doc_title'; -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; -import { wrapInI18nContext } from 'ui/i18n'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue'; - -// Saved objects -import { SavedObjectsClientProvider } from 'ui/saved_objects'; -// @ts-ignore -import { SavedObject, SavedObjectProvider } from 'ui/saved_objects/saved_object'; -import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; - -import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public'; -import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; -import { start as embeddables } from '../../../../core_plugins/embeddable_api/public/np_ready/public/legacy'; -import { start as data } from '../../../data/public/legacy'; - -const services = { - // new platform - addBasePath: npStart.core.http.basePath.prepend, - capabilities: npStart.core.application.capabilities, - chrome: npStart.core.chrome, - docLinks: npStart.core.docLinks, - embeddable: npStart.plugins.embeddable, - getBasePath: npStart.core.http.basePath.get, - savedObjectsClient: npStart.core.savedObjects.client, - toastNotifications: npStart.core.notifications.toasts, - uiSettings: npStart.core.uiSettings, - core: npStart.core, - - share: npStart.plugins.share, - npData: npStart.plugins.data, - data, - embeddables, - visualizations, - - // legacy - chromeLegacy, - docTitle, - FeatureCatalogueRegistryProvider, - FilterBarQueryFilterProvider, - getInjector: () => { - return chromeLegacy.dangerouslyGetActiveInjector(); - }, - SavedObjectProvider, - SavedObjectRegistryProvider, - SavedObjectsClientProvider, - timefilter: npStart.plugins.data.query.timefilter.timefilter, - uiModules, - uiRoutes, - wrapInI18nContext, +export interface VisualizeKibanaServices { + addBasePath: (url: string) => string; + chrome: ChromeStart; + core: LegacyCoreStart; + data: DataPublicPluginStart; + editorTypes: any; + embeddables: IEmbeddableStart; + getBasePath: () => string; + indexPatterns: IndexPatternsContract; + legacyChrome: any; + localStorage: Storage; + navigation: NavigationStart; + toastNotifications: ToastsStart; + savedObjectsClient: SavedObjectsClientContract; + savedObjectRegistry: any; + savedQueryService: DataPublicPluginStart['query']['savedQueries']; + savedVisualizations: SavedVisualizations; + share: SharePluginStart; + uiSettings: IUiSettingsClient; + visualizeCapabilities: any; + visualizations: VisualizationsStart; +} - createUiStatsReporter, -}; +let services: VisualizeKibanaServices | null = null; +export function setServices(newServices: VisualizeKibanaServices) { + services = newServices; +} export function getServices() { + if (!services) { + throw new Error( + 'Kibana services not set - are you trying to import this module from outside of the visualize app?' + ); + } return services; } -// export legacy static dependencies -export { angular }; -export { getFromSavedObject } from 'ui/index_patterns'; -export { PersistedState } from 'ui/persisted_state'; -// @ts-ignore -export { VisEditorTypesRegistryProvider } from 'ui/registry/vis_editor_types'; -export { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; -export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; -export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; -export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url'; -export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; -export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; -export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; -export { unhashUrl } from '../../../../../plugins/kibana_utils/public'; -export { - Container, - Embeddable, - EmbeddableFactory, - EmbeddableInput, - EmbeddableOutput, - ErrorEmbeddable, -} from '../../../../../plugins/embeddable/public'; - -// export types -export { METRIC_TYPE }; -export { AppState } from 'ui/state_management/app_state'; -export { VisType } from 'ui/vis'; - -// export const -export { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; - -export { VisSavedObject } from './embeddable/visualize_embeddable'; +export function clearServices() { + services = null; +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_app.js b/src/legacy/core_plugins/kibana/public/visualize/legacy_app.js new file mode 100644 index 0000000000000..f47552e99a5c7 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_app.js @@ -0,0 +1,169 @@ +/* + * 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 { find } from 'lodash'; +import { i18n } from '@kbn/i18n'; + +import editorTemplate from './editor/editor.html'; +import visualizeListingTemplate from './listing/visualize_listing.html'; + +import { initVisualizeAppDirective } from './visualize_app'; +import { VisualizeConstants } from './visualize_constants'; +import { VisualizeListingController } from './listing/visualize_listing'; +import { ensureDefaultIndexPattern, registerTimefilterWithGlobalStateFactory } from './legacy_imports'; +import { syncOnMount } from './global_state_sync'; + +import { + getLandingBreadcrumbs, + getWizardStep1Breadcrumbs, + getCreateBreadcrumbs, + getEditBreadcrumbs +} from './breadcrumbs'; + +export function initVisualizeApp(app, deps) { + initVisualizeAppDirective(app, deps); + + app.run(globalState => { + syncOnMount(globalState, deps.data); + }); + + app.run((globalState, $rootScope) => { + registerTimefilterWithGlobalStateFactory( + deps.data.query.timefilter.timefilter, + globalState, + $rootScope + ); + }); + + app.config(function ($routeProvider) { + const defaults = { + reloadOnSearch: false, + requireUICapability: 'visualize.show', + badge: () => { + if (deps.visualizeCapabilities.save) { + return undefined; + } + + return { + text: i18n.translate('kbn.visualize.badge.readOnly.text', { + defaultMessage: 'Read only', + }), + tooltip: i18n.translate('kbn.visualize.badge.readOnly.tooltip', { + defaultMessage: 'Unable to save visualizations', + }), + iconType: 'glasses', + }; + }, + }; + + $routeProvider + .when(VisualizeConstants.LANDING_PAGE_PATH, { + ...defaults, + template: visualizeListingTemplate, + k7Breadcrumbs: getLandingBreadcrumbs, + controller: VisualizeListingController, + controllerAs: 'listingController', + resolve: { + createNewVis: () => false, + hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl), + }, + }) + .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, { + ...defaults, + template: visualizeListingTemplate, + k7Breadcrumbs: getWizardStep1Breadcrumbs, + controller: VisualizeListingController, + controllerAs: 'listingController', + resolve: { + createNewVis: () => true, + hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl), + }, + }) + .when(VisualizeConstants.CREATE_PATH, { + ...defaults, + template: editorTemplate, + k7Breadcrumbs: getCreateBreadcrumbs, + resolve: { + savedVis: function (redirectWhenMissing, $route, $rootScope, kbnUrl) { + const { core, data, savedVisualizations, visualizations } = deps; + const visTypes = visualizations.types.all(); + const visType = find(visTypes, { name: $route.current.params.type }); + const shouldHaveIndex = visType.requiresSearch && visType.options.showIndexSelection; + const hasIndex = $route.current.params.indexPattern || $route.current.params.savedSearchId; + if (shouldHaveIndex && !hasIndex) { + throw new Error( + i18n.translate('kbn.visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage', { + defaultMessage: 'You must provide either an indexPattern or a savedSearchId', + }) + ); + } + + return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl).then(() => savedVisualizations.get($route.current.params)) + .then(savedVis => { + if (savedVis.vis.type.setup) { + return savedVis.vis.type.setup(savedVis) + .catch(() => savedVis); + } + return savedVis; + }) + .catch(redirectWhenMissing({ + '*': '/visualize' + })); + } + } + }) + .when(`${VisualizeConstants.EDIT_PATH}/:id`, { + ...defaults, + template: editorTemplate, + k7Breadcrumbs: getEditBreadcrumbs, + resolve: { + savedVis: function (redirectWhenMissing, $route, $rootScope, kbnUrl) { + const { chrome, core, data, savedVisualizations } = deps; + return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl) + .then(() => savedVisualizations.get($route.current.params.id)) + .then(savedVis => { + chrome.recentlyAccessed.add( + savedVis.getFullPath(), + savedVis.title, + savedVis.id + ); + return savedVis; + }) + .then(savedVis => { + if (savedVis.vis.type.setup) { + return savedVis.vis.type.setup(savedVis).catch(() => savedVis); + } + return savedVis; + }) + .catch( + redirectWhenMissing({ + 'visualization': '/visualize', + 'search': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, + 'index-pattern': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, + 'index-pattern-field': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id + }) + ); + } + } + }) + .when(`visualize/:tail*?`, { + redirectTo: `/${deps.core.injectedMetadata.getInjectedVar('kbnDefaultAppId')}`, + }); + }); +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts new file mode 100644 index 0000000000000..6adcfd2cc7186 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/** + * The imports in this file are static functions and types which still live in legacy folders and are used + * within dashboard. To consolidate them all in one place, they are re-exported from this file. Eventually + * this list should become empty. Imports from the top level of shimmed or moved plugins can be imported + * directly where they are needed. + */ + +import chrome from 'ui/chrome'; + +export const legacyChrome = chrome; + +// @ts-ignore +export { AppState, AppStateProvider } from 'ui/state_management/app_state'; +export { State } from 'ui/state_management/state'; +// @ts-ignore +export { GlobalStateProvider } from 'ui/state_management/global_state'; +// @ts-ignore +export { StateManagementConfigProvider } from 'ui/state_management/config_provider'; +export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; +export { PersistedState } from 'ui/persisted_state'; + +export { npSetup, npStart } from 'ui/new_platform'; +export { IPrivate } from 'ui/private'; +// @ts-ignore +export { PrivateProvider } from 'ui/private/private'; + +export { SavedObjectRegistryProvider } from 'ui/saved_objects'; +export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; +export { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; +export { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; + +export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; +export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; +// @ts-ignore +export { EventsProvider } from 'ui/events'; +// @ts-ignore +export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; +// @ts-ignore +export { PromiseServiceCreator } from 'ui/promises/promises'; +// @ts-ignore +export { confirmModalFactory } from 'ui/modals/confirm_modal'; +export { configureAppAngularModule, ensureDefaultIndexPattern } from 'ui/legacy_compat'; +export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; +// @ts-ignore +export { VisEditorTypesRegistryProvider } from 'ui/registry/vis_editor_types'; + +// @ts-ignore +export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; +export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; +export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url'; + +// @ts-ignore +export { defaultEditor } from 'ui/vis/editors/default/default'; +export { VisType } from 'ui/vis'; +export { wrapInI18nContext } from 'ui/i18n'; + +export { VisSavedObject } from './embeddable/visualize_embeddable'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html index edb7cccbd46a2..4511ac61f7396 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html +++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html @@ -14,6 +14,8 @@ is-open="listingController.showNewVisModal" on-close="listingController.closeNewVisModal" vis-types-registry="listingController.visTypeRegistry" + add-base-path="listingController.addBasePath" + ui-settings="listingController.uiSettings" > diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js index f9e3a1a90115a..9b02be0581b8d 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js +++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js @@ -24,36 +24,46 @@ import { VisualizeConstants } from '../visualize_constants'; import { i18n } from '@kbn/i18n'; import { getServices } from '../kibana_services'; - -const { - addBasePath, - chrome, - chromeLegacy, - SavedObjectRegistryProvider, - SavedObjectsClientProvider, - timefilter, - toastNotifications, - uiModules, - wrapInI18nContext, - visualizations, -} = getServices(); - -const app = uiModules.get('app/visualize', ['ngRoute', 'react']); -app.directive('visualizeListingTable', reactDirective => - reactDirective(wrapInI18nContext(VisualizeListingTable)) -); -app.directive('newVisModal', reactDirective => reactDirective(wrapInI18nContext(NewVisModal))); +import { wrapInI18nContext } from '../legacy_imports'; + +export function initListingDirective(app) { + app.directive('visualizeListingTable', reactDirective => reactDirective(wrapInI18nContext(VisualizeListingTable))); + app.directive('newVisModal', reactDirective => + reactDirective(wrapInI18nContext(NewVisModal), [ + ['visTypesRegistry', { watchDepth: 'collection' }], + ['onClose', { watchDepth: 'reference' }], + ['addBasePath', { watchDepth: 'reference' }], + ['uiSettings', { watchDepth: 'reference' }], + 'isOpen', + ]) + ); +} export function VisualizeListingController($injector, createNewVis) { - const Private = $injector.get('Private'); - const config = $injector.get('config'); + const { + addBasePath, + chrome, + legacyChrome, + savedObjectRegistry, + savedObjectsClient, + data: { + query: { + timefilter: { timefilter }, + }, + }, + toastNotifications, + uiSettings, + visualizations, + core: { docLinks }, + } = getServices(); const kbnUrl = $injector.get('kbnUrl'); - const savedObjectClient = Private(SavedObjectsClientProvider); timefilter.disableAutoRefreshSelector(); timefilter.disableTimeRangeSelector(); this.showNewVisModal = false; + this.addBasePath = addBasePath; + this.uiSettings = uiSettings; this.createNewVis = () => { this.showNewVisModal = true; @@ -82,14 +92,14 @@ export function VisualizeListingController($injector, createNewVis) { } // TODO: Extract this into an external service. - const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName; + const services = savedObjectRegistry.byLoaderPropertiesName; const visualizationService = services.visualizations; this.visTypeRegistry = visualizations.types; this.fetchItems = filter => { - const isLabsEnabled = config.get('visualize:enableLabs'); + const isLabsEnabled = uiSettings.get('visualize:enableLabs'); return visualizationService - .findListItems(filter, config.get('savedObjects:listingLimit')) + .findListItems(filter, uiSettings.get('savedObjects:listingLimit')) .then(result => { this.totalItems = result.total; @@ -103,11 +113,11 @@ export function VisualizeListingController($injector, createNewVis) { this.deleteSelectedItems = function deleteSelectedItems(selectedItems) { return Promise.all( selectedItems.map(item => { - return savedObjectClient.delete(item.savedObjectType, item.id); + return savedObjectsClient.delete(item.savedObjectType, item.id); }) ) .then(() => { - chromeLegacy.untrackNavLinksForDeletedSavedObjects(selectedItems.map(item => item.id)); + legacyChrome.untrackNavLinksForDeletedSavedObjects(selectedItems.map(item => item.id)); }) .catch(error => { toastNotifications.addError(error, { @@ -126,7 +136,7 @@ export function VisualizeListingController($injector, createNewVis) { }, ]); - this.listingLimit = config.get('savedObjects:listingLimit'); + this.listingLimit = uiSettings.get('savedObjects:listingLimit'); - addHelpMenuToAppChrome(chrome); + addHelpMenuToAppChrome(chrome, docLinks); } diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js index efab03303aa80..890fa64af9693 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js +++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js @@ -27,22 +27,21 @@ import { EuiIcon, EuiBetaBadge, EuiLink, EuiButton, EuiEmptyPrompt } from '@elas import { getServices } from '../kibana_services'; -const { capabilities, toastNotifications, uiSettings } = getServices(); - class VisualizeListingTable extends Component { constructor(props) { super(props); } render() { + const { visualizeCapabilities, uiSettings, toastNotifications } = getServices(); return ( item.canDelete} diff --git a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts new file mode 100644 index 0000000000000..1aa2d70dabea6 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts @@ -0,0 +1,161 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +import { + CoreSetup, + CoreStart, + LegacyCoreStart, + Plugin, + SavedObjectsClientContract, +} from 'kibana/public'; + +import { Storage } from '../../../../../plugins/kibana_utils/public'; +import { DataPublicPluginStart } from '../../../../../plugins/data/public'; +import { IEmbeddableStart } from '../../../../../plugins/embeddable/public'; +import { NavigationStart } from '../../../navigation/public'; +import { SharePluginStart } from '../../../../../plugins/share/public'; +import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public'; +import { VisualizationsStart } from '../../../visualizations/public'; +import { VisualizeEmbeddableFactory } from './embeddable/visualize_embeddable_factory'; +import { VISUALIZE_EMBEDDABLE_TYPE } from './embeddable/constants'; +import { VisualizeConstants } from './visualize_constants'; +import { setServices, VisualizeKibanaServices } from './kibana_services'; +import { + FeatureCatalogueCategory, + HomePublicPluginSetup, +} from '../../../../../plugins/home/public'; +import { defaultEditor, VisEditorTypesRegistryProvider } from './legacy_imports'; +import { SavedVisualizations } from './types'; + +export interface LegacyAngularInjectedDependencies { + legacyChrome: any; + editorTypes: any; + savedObjectRegistry: any; + savedVisualizations: SavedVisualizations; +} + +export interface VisualizePluginStartDependencies { + data: DataPublicPluginStart; + embeddables: IEmbeddableStart; + navigation: NavigationStart; + share: SharePluginStart; + visualizations: VisualizationsStart; +} + +export interface VisualizePluginSetupDependencies { + __LEGACY: { + getAngularDependencies: () => Promise; + }; + home: HomePublicPluginSetup; + kibana_legacy: KibanaLegacySetup; +} + +export class VisualizePlugin implements Plugin { + private startDependencies: { + data: DataPublicPluginStart; + embeddables: IEmbeddableStart; + navigation: NavigationStart; + savedObjectsClient: SavedObjectsClientContract; + share: SharePluginStart; + visualizations: VisualizationsStart; + } | null = null; + + public async setup( + core: CoreSetup, + { home, kibana_legacy, __LEGACY: { getAngularDependencies } }: VisualizePluginSetupDependencies + ) { + kibana_legacy.registerLegacyApp({ + id: 'visualize', + title: 'Visualize', + mount: async ({ core: contextCore }, params) => { + if (this.startDependencies === null) { + throw new Error('not started yet'); + } + + const { + savedObjectsClient, + embeddables, + navigation, + visualizations, + data, + share, + } = this.startDependencies; + + const angularDependencies = await getAngularDependencies(); + const deps: VisualizeKibanaServices = { + ...angularDependencies, + addBasePath: contextCore.http.basePath.prepend, + core: contextCore as LegacyCoreStart, + chrome: contextCore.chrome, + data, + embeddables, + getBasePath: core.http.basePath.get, + indexPatterns: data.indexPatterns, + localStorage: new Storage(localStorage), + navigation, + savedObjectsClient, + savedQueryService: data.query.savedQueries, + share, + toastNotifications: contextCore.notifications.toasts, + uiSettings: contextCore.uiSettings, + visualizeCapabilities: contextCore.application.capabilities.visualize, + visualizations, + }; + setServices(deps); + + const { renderApp } = await import('./application'); + return renderApp(params.element, params.appBasePath, deps); + }, + }); + + home.featureCatalogue.register({ + id: 'visualize', + title: 'Visualize', + description: i18n.translate('kbn.visualize.visualizeDescription', { + defaultMessage: + 'Create visualizations and aggregate data stores in your Elasticsearch indices.', + }), + icon: 'visualizeApp', + path: `/app/kibana#${VisualizeConstants.LANDING_PAGE_PATH}`, + showOnHomePage: true, + category: FeatureCatalogueCategory.DATA, + }); + + VisEditorTypesRegistryProvider.register(defaultEditor); + } + + public start( + { savedObjects: { client: savedObjectsClient } }: CoreStart, + { embeddables, navigation, data, share, visualizations }: VisualizePluginStartDependencies + ) { + this.startDependencies = { + data, + embeddables, + navigation, + savedObjectsClient, + share, + visualizations, + }; + + const embeddableFactory = new VisualizeEmbeddableFactory(visualizations.types); + embeddables.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); + } +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/types.d.ts b/src/legacy/core_plugins/kibana/public/visualize/types.d.ts index c83f7f5a5da8b..b6a3981215384 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/types.d.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/types.d.ts @@ -17,7 +17,7 @@ * under the License. */ -import { VisSavedObject } from './kibana_services'; +import { VisSavedObject } from './legacy_imports'; export interface SavedVisualizations { urlFor: (id: string) => string; diff --git a/src/legacy/core_plugins/kibana/public/visualize/visualize_app.ts b/src/legacy/core_plugins/kibana/public/visualize/visualize_app.ts new file mode 100644 index 0000000000000..c64287a0e63b8 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/visualize_app.ts @@ -0,0 +1,31 @@ +/* + * 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 { IModule } from 'angular'; +import { VisualizeKibanaServices } from './kibana_services'; + +// @ts-ignore +import { initEditorDirective } from './editor/editor'; +// @ts-ignore +import { initListingDirective } from './listing/visualize_listing'; + +export function initVisualizeAppDirective(app: IModule, deps: VisualizeKibanaServices) { + initEditorDirective(app, deps); + initListingDirective(app); +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap index 4aa614b68ea23..5be5f58994887 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap @@ -2,6 +2,7 @@ exports[`NewVisModal filter for visualization types should render as expected 1`] = ` @@ -1287,6 +1307,7 @@ exports[`NewVisModal filter for visualization types should render as expected 1` exports[`NewVisModal should render as expected 1`] = ` diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx index 99d9590e750fd..0dd2091bbfee0 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx @@ -20,33 +20,17 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { NewVisModal } from './new_vis_modal'; -import { VisType } from '../kibana_services'; +import { VisType } from '../legacy_imports'; import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; -jest.mock('../kibana_services', () => { - const mock = { - addBasePath: jest.fn(path => `root${path}`), - uiSettings: { get: jest.fn() }, - createUiStatsReporter: () => jest.fn(), - }; - - return { - getServices: () => mock, - VisType: {}, - METRIC_TYPE: 'metricType', - }; -}); - -import { getServices } from '../kibana_services'; +jest.mock('../legacy_imports', () => ({ + State: () => null, + AppState: () => null, +})); -beforeEach(() => { - jest.clearAllMocks(); -}); +import { NewVisModal } from './new_vis_modal'; describe('NewVisModal', () => { - const settingsGet = getServices().uiSettings.get as jest.Mock; - const defaultVisTypeParams = { hidden: false, visualization: class Controller { @@ -76,17 +60,36 @@ describe('NewVisModal', () => { }, getAliases: () => [], }; + const addBasePath = (url: string) => `testbasepath${url}`; + const settingsGet = jest.fn(); + const uiSettings: any = { get: settingsGet }; + + beforeEach(() => { + jest.clearAllMocks(); + }); it('should render as expected', () => { const wrapper = mountWithIntl( - null} visTypesRegistry={visTypes} /> + null} + visTypesRegistry={visTypes} + addBasePath={addBasePath} + uiSettings={uiSettings} + /> ); expect(wrapper).toMatchSnapshot(); }); it('should show a button for regular visualizations', () => { const wrapper = mountWithIntl( - null} visTypesRegistry={visTypes} /> + null} + visTypesRegistry={visTypes} + addBasePath={addBasePath} + uiSettings={uiSettings} + /> ); expect(wrapper.find('[data-test-subj="visType-vis"]').exists()).toBe(true); }); @@ -95,7 +98,13 @@ describe('NewVisModal', () => { it('should open the editor for visualizations without search', () => { window.location.assign = jest.fn(); const wrapper = mountWithIntl( - null} visTypesRegistry={visTypes} /> + null} + visTypesRegistry={visTypes} + addBasePath={addBasePath} + uiSettings={uiSettings} + /> ); const visButton = wrapper.find('button[data-test-subj="visType-vis"]'); visButton.simulate('click'); @@ -110,6 +119,8 @@ describe('NewVisModal', () => { onClose={() => null} visTypesRegistry={visTypes} editorParams={['foo=true', 'bar=42']} + addBasePath={addBasePath} + uiSettings={uiSettings} /> ); const visButton = wrapper.find('button[data-test-subj="visType-vis"]'); @@ -121,7 +132,13 @@ describe('NewVisModal', () => { describe('filter for visualization types', () => { it('should render as expected', () => { const wrapper = mountWithIntl( - null} visTypesRegistry={visTypes} /> + null} + visTypesRegistry={visTypes} + addBasePath={addBasePath} + uiSettings={uiSettings} + /> ); const searchBox = wrapper.find('input[data-test-subj="filterVisType"]'); searchBox.simulate('change', { target: { value: 'with' } }); @@ -133,7 +150,13 @@ describe('NewVisModal', () => { it('should not show experimental visualizations if visualize:enableLabs is false', () => { settingsGet.mockReturnValue(false); const wrapper = mountWithIntl( - null} visTypesRegistry={visTypes} /> + null} + visTypesRegistry={visTypes} + addBasePath={addBasePath} + uiSettings={uiSettings} + /> ); expect(wrapper.find('[data-test-subj="visType-visExp"]').exists()).toBe(false); }); @@ -141,7 +164,13 @@ describe('NewVisModal', () => { it('should show experimental visualizations if visualize:enableLabs is true', () => { settingsGet.mockReturnValue(true); const wrapper = mountWithIntl( - null} visTypesRegistry={visTypes} /> + null} + visTypesRegistry={visTypes} + addBasePath={addBasePath} + uiSettings={uiSettings} + /> ); expect(wrapper.find('[data-test-subj="visType-visExp"]').exists()).toBe(true); }); diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx index 420f0e5198056..0b46b562f2146 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx @@ -22,20 +22,21 @@ import React from 'react'; import { EuiModal, EuiOverlayMask } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { IUiSettingsClient } from 'kibana/public'; +import { VisType } from '../legacy_imports'; import { VisualizeConstants } from '../visualize_constants'; +import { createUiStatsReporter, METRIC_TYPE } from '../../../../ui_metric/public'; import { SearchSelection } from './search_selection'; import { TypeSelection } from './type_selection'; import { TypesStart, VisTypeAlias } from '../../../../visualizations/public/np_ready/public/types'; -import { getServices, METRIC_TYPE, VisType } from '../kibana_services'; - -const { addBasePath, createUiStatsReporter, uiSettings } = getServices(); - interface TypeSelectionProps { isOpen: boolean; onClose: () => void; visTypesRegistry: TypesStart; editorParams?: string[]; + addBasePath: (path: string) => string; + uiSettings: IUiSettingsClient; } interface TypeSelectionState { @@ -55,7 +56,7 @@ class NewVisModal extends React.Component ); @@ -124,7 +126,7 @@ class NewVisModal extends React.Component void; diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx index fa2ca6747bc40..92320f7bb443a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx @@ -20,7 +20,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { I18nContext } from 'ui/i18n'; +import { I18nProvider } from '@kbn/i18n/react'; +import { IUiSettingsClient } from 'kibana/public'; import { NewVisModal } from './new_vis_modal'; import { TypesStart } from '../../../../visualizations/public/np_ready/public/types'; @@ -30,7 +31,9 @@ interface ShowNewVisModalParams { export function showNewVisModal( visTypeRegistry: TypesStart, - { editorParams = [] }: ShowNewVisModalParams = {} + { editorParams = [] }: ShowNewVisModalParams = {}, + addBasePath: (path: string) => string, + uiSettings: IUiSettingsClient ) { const container = document.createElement('div'); const onClose = () => { @@ -40,14 +43,16 @@ export function showNewVisModal( document.body.appendChild(container); const element = ( - + - + ); ReactDOM.render(element, container); } diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx index 382f475669f5d..3093499a030c8 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx @@ -21,18 +21,6 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { NewVisHelp } from './new_vis_help'; -jest.mock('../../kibana_services', () => { - return { - getServices: () => ({ - addBasePath: jest.fn((url: string) => `testbasepath${url}`), - }), - }; -}); - -beforeEach(() => { - jest.clearAllMocks(); -}); - describe('NewVisHelp', () => { it('should render as expected', () => { expect( @@ -53,6 +41,7 @@ describe('NewVisHelp', () => { stage: 'production', }, ]} + addBasePath={(url: string) => `testbasepath${url}`} /> ) ).toMatchInlineSnapshot(` diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx index 44c36f7d17d55..107cbc0e754b5 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx @@ -22,10 +22,9 @@ import React, { Fragment } from 'react'; import { EuiText, EuiButton } from '@elastic/eui'; import { VisTypeAliasListEntry } from './type_selection'; -import { getServices } from '../../kibana_services'; - interface Props { promotedTypes: VisTypeAliasListEntry[]; + addBasePath: (path: string) => string; } export function NewVisHelp(props: Props) { @@ -43,7 +42,7 @@ export function NewVisHelp(props: Props) { {t.promotion!.description}

string; onVisTypeSelected: (visType: VisType | VisTypeAlias) => void; visTypesRegistry: TypesStart; showExperimental: boolean; @@ -153,6 +154,7 @@ class TypeSelection extends React.Component t.promotion)} + addBasePath={this.props.addBasePath} /> )} diff --git a/src/legacy/ui/public/vis/editors/default/default.js b/src/legacy/ui/public/vis/editors/default/default.js index 43d2962df0a1e..9df866d29a8a2 100644 --- a/src/legacy/ui/public/vis/editors/default/default.js +++ b/src/legacy/ui/public/vis/editors/default/default.js @@ -33,12 +33,11 @@ import { keyCodes } from '@elastic/eui'; import { parentPipelineAggHelper } from 'ui/agg_types/metrics/lib/parent_pipeline_agg_helper'; import { DefaultEditorSize } from '../../editor_size'; -import { VisEditorTypesRegistryProvider } from '../../../registry/vis_editor_types'; import { AggGroupNames } from './agg_groups'; import { start as embeddables } from '../../../../../core_plugins/embeddable_api/public/np_ready/public/legacy'; -const defaultEditor = function ($rootScope, $compile, getAppState) { +const defaultEditor = function ($rootScope, $compile) { return class DefaultEditor { static key = 'default'; @@ -58,7 +57,7 @@ const defaultEditor = function ($rootScope, $compile, getAppState) { } } - render({ uiState, timeRange, filters, query }) { + render({ uiState, timeRange, filters, query, appState }) { let $scope; const updateScope = () => { @@ -161,7 +160,7 @@ const defaultEditor = function ($rootScope, $compile, getAppState) { this._handler = await embeddables.getEmbeddableFactory('visualization').createFromObject(this.savedObj, { uiState: uiState, - appState: getAppState(), + appState, timeRange: timeRange, filters: filters || [], query: query, @@ -195,6 +194,4 @@ const defaultEditor = function ($rootScope, $compile, getAppState) { }; }; -VisEditorTypesRegistryProvider.register(defaultEditor); - export { defaultEditor }; diff --git a/src/legacy/ui/ui_exports/ui_export_defaults.js b/src/legacy/ui/ui_exports/ui_export_defaults.js index 291d9feea3c40..80bee41175771 100644 --- a/src/legacy/ui/ui_exports/ui_export_defaults.js +++ b/src/legacy/ui/ui_exports/ui_export_defaults.js @@ -50,12 +50,6 @@ export const UI_EXPORT_DEFAULTS = { fieldFormatEditors: [ 'ui/field_editor/components/field_format_editor/register' ], - visEditorTypes: [ - 'ui/vis/editors/default/default', - ], - embeddableFactories: [ - 'plugins/kibana/visualize/embeddable/visualize_embeddable_factory', - ], search: [ 'ui/courier/search_strategy/default_search_strategy', ], diff --git a/tasks/config/run.js b/tasks/config/run.js index e4071c8b7d0ab..97a0f381f2aa4 100644 --- a/tasks/config/run.js +++ b/tasks/config/run.js @@ -269,7 +269,6 @@ module.exports = function (grunt) { '--config', 'test/plugin_functional/config.js', '--bail', '--debug', - '--kibana-install-dir', KIBANA_INSTALL_DIR, ], }), diff --git a/x-pack/legacy/plugins/canvas/public/legacy_start.ts b/x-pack/legacy/plugins/canvas/public/legacy_start.ts index 49ec7acd6375d..972427e166afc 100644 --- a/x-pack/legacy/plugins/canvas/public/legacy_start.ts +++ b/x-pack/legacy/plugins/canvas/public/legacy_start.ts @@ -11,7 +11,6 @@ import 'ui/autoload/all'; import 'uiExports/visTypes'; import 'uiExports/visResponseHandlers'; import 'uiExports/visRequestHandlers'; -import 'uiExports/visEditorTypes'; import 'uiExports/savedObjectTypes'; import 'uiExports/spyModes'; import 'uiExports/embeddableFactories'; diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 8093c57d2631a..8c6ddfebcb6cc 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -18,7 +18,6 @@ import 'uiExports/contextMenuActions'; import 'uiExports/visTypes'; import 'uiExports/visResponseHandlers'; import 'uiExports/visRequestHandlers'; -import 'uiExports/visEditorTypes'; import 'uiExports/inspectorViews'; import 'uiExports/interpreter'; import 'uiExports/savedObjectTypes';