[Visualize] Centralize dependencies in kibana_services.ts (#49293)

* Centralize dependencies for Visualize  plugin

* Centralizing dependencies in editor and embeddable

* Remove unused deps, move imports

* Fix dangerouslyGetActiveInjector

* Move loading directive to kibana_services.ts

* Fix exceptions

* Get rid of injectI18n; fix chrome method invocation

* Update unit tests

* Fix TS

* Move data and Embeddable import

* Import VISUALIZE_EMBEDDABLE_TYPE directly

* Fix deps
This commit is contained in:
Maryia Lapata 2019-11-01 11:24:31 +03:00 committed by GitHub
parent 90ddbfd9d4
commit dbc9a52fd8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 366 additions and 261 deletions

View file

@ -23,43 +23,48 @@ import { i18n } from '@kbn/i18n';
import '../saved_visualizations/saved_visualizations';
import './visualization_editor';
import './visualization';
import 'ui/vis/editors/default/sidebar';
import 'ui/visualize';
import 'ui/collapsible_sidebar';
import 'ui/directives/storage';
import { capabilities } from 'ui/capabilities';
import chrome from 'ui/chrome';
import React from 'react';
import angular from 'angular';
import { FormattedMessage } from '@kbn/i18n/react';
import { toastNotifications } from 'ui/notify';
import { docTitle } from 'ui/doc_title';
import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter';
import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
import { migrateAppState } from './lib';
import uiRoutes from 'ui/routes';
import { uiModules } from 'ui/modules';
import editorTemplate from './editor.html';
import { DashboardConstants } from '../../dashboard/dashboard_constants';
import { VisualizeConstants } from '../visualize_constants';
import { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
import { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
import { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
import { timefilter } from 'ui/timefilter';
import { showShareContextMenu, ShareContextMenuExtensionsRegistryProvider } from 'ui/share';
import { getUnhashableStatesProvider } from 'ui/state_management/state_hashing';
import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
import { getEditBreadcrumbs, getCreateBreadcrumbs } from '../breadcrumbs';
import { npStart } from 'ui/new_platform';
import { extractTimeFilter, changeTimeFilter } from '../../../../data/public';
import { start as data } from '../../../../data/public/legacy';
import { start as visualizations } from '../../../../visualizations/public/np_ready/public/legacy';
import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util';
import {
getServices,
angular,
absoluteToParsedUrl,
getUnhashableStatesProvider,
KibanaParsedUrl,
migrateLegacyQuery,
SavedObjectSaveModal,
showShareContextMenu,
showSaveModal,
stateMonitorFactory,
subscribeWithScope,
} from '../kibana_services';
const {
capabilities,
chrome,
chromeLegacy,
data,
docTitle,
FilterBarQueryFilterProvider,
getBasePath,
ShareContextMenuExtensionsRegistryProvider,
toastNotifications,
timefilter,
uiModules,
uiRoutes,
visualizations,
} = getServices();
const { savedQueryService } = data.search.services;
uiRoutes
@ -101,7 +106,7 @@ uiRoutes
savedVis: function (savedVisualizations, redirectWhenMissing, $route) {
return savedVisualizations.get($route.current.params.id)
.then((savedVis) => {
npStart.core.chrome.recentlyAccessed.add(
chrome.recentlyAccessed.add(
savedVis.getFullPath(),
savedVis.title,
savedVis.id);
@ -169,7 +174,7 @@ function VisEditor(
dirty: !savedVis.id
};
$scope.topNavMenu = [...(capabilities.get().visualize.save ? [{
$scope.topNavMenu = [...(capabilities.visualize.save ? [{
id: 'save',
label: i18n.translate('kbn.topNavMenu.saveVisualizationButtonLabel', { defaultMessage: 'save' }),
description: i18n.translate('kbn.visualize.topNavMenu.saveVisualizationButtonAriaLabel', {
@ -238,7 +243,7 @@ function VisEditor(
showShareContextMenu({
anchorElement,
allowEmbed: true,
allowShortUrl: capabilities.get().visualize.createShortUrl,
allowShortUrl: capabilities.visualize.createShortUrl,
getUnhashableStates,
objectId: savedVis.id,
objectType: 'visualization',
@ -355,9 +360,9 @@ function VisEditor(
}
});
$scope.showSaveQuery = capabilities.get().visualize.saveQuery;
$scope.showSaveQuery = capabilities.visualize.saveQuery;
$scope.$watch(() => capabilities.get().visualize.saveQuery, (newCapability) => {
$scope.$watch(() => capabilities.visualize.saveQuery, (newCapability) => {
$scope.showSaveQuery = newCapability;
});
@ -578,7 +583,7 @@ function VisEditor(
if ($scope.isAddToDashMode()) {
const savedVisualizationParsedUrl = new KibanaParsedUrl({
basePath: chrome.getBasePath(),
basePath: getBasePath(),
appId: kbnBaseUrl.slice('/app/'.length),
appPath: kbnUrl.eval(`${VisualizeConstants.EDIT_PATH}/{{id}}`, { id: savedVis.id }),
});
@ -587,15 +592,15 @@ 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.
chrome.trackSubUrlForApp('kibana:visualize', savedVisualizationParsedUrl);
chromeLegacy.trackSubUrlForApp('kibana:visualize', savedVisualizationParsedUrl);
const lastDashboardAbsoluteUrl = npStart.core.chrome.navLinks.get('kibana:dashboard').url;
const dashboardParsedUrl = absoluteToParsedUrl(lastDashboardAbsoluteUrl, chrome.getBasePath());
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.breadcrumbs.set($injector.invoke(getEditBreadcrumbs));
chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs));
savedVis.vis.title = savedVis.title;
savedVis.vis.description = savedVis.description;
// it's needed to save the state to update url string

View file

@ -17,9 +17,9 @@
* under the License.
*/
import { uiModules } from 'ui/modules';
import 'angular-sanitize';
import { start as embeddables } from '../../../../../core_plugins/embeddable_api/public/np_ready/public/legacy';
import { getServices } from '../kibana_services';
const { embeddables, uiModules } = getServices();
uiModules
.get('kibana/directive', ['ngSanitize'])

View file

@ -17,9 +17,9 @@
* under the License.
*/
import { uiModules } from 'ui/modules';
import 'angular-sanitize';
import { VisEditorTypesRegistryProvider } from 'ui/registry/vis_editor_types';
import { getServices, VisEditorTypesRegistryProvider } from '../kibana_services';
const { uiModules } = getServices();
uiModules
.get('kibana/directive', ['ngSanitize'])

View file

@ -19,7 +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';

View file

@ -17,9 +17,14 @@
* under the License.
*/
import chrome from 'ui/chrome';
import { StaticIndexPattern, getFromSavedObject } from 'ui/index_patterns';
import { VisSavedObject } from 'ui/visualize/loader/types';
import {
getServices,
getFromSavedObject,
StaticIndexPattern,
VisSavedObject,
} from '../kibana_services';
const { savedObjectsClient, uiSettings } = getServices();
export async function getIndexPattern(
savedVis: VisSavedObject
@ -28,9 +33,7 @@ export async function getIndexPattern(
return savedVis.vis.indexPattern;
}
const config = chrome.getUiSettingsClient();
const savedObjectsClient = chrome.getSavedObjectsClient();
const defaultIndex = config.get('defaultIndex');
const defaultIndex = uiSettings.get('defaultIndex');
if (savedVis.vis.params.index_pattern) {
const indexPatternObjects = await savedObjectsClient.find({

View file

@ -18,29 +18,28 @@
*/
import _ from 'lodash';
import { StaticIndexPattern } from 'ui/index_patterns';
import { PersistedState } from 'ui/persisted_state';
import { VisualizeLoader } from 'ui/visualize/loader';
import { EmbeddedVisualizeHandler } from 'ui/visualize/loader/embedded_visualize_handler';
import { AppState } from 'ui/state_management/app_state';
import {
VisSavedObject,
VisualizeLoaderParams,
VisualizeUpdateParams,
} from 'ui/visualize/loader/types';
import { Subscription } from 'rxjs';
import * as Rx from 'rxjs';
import { Filter } from '@kbn/es-query';
import { TimeRange, onlyDisabledFiltersChanged } from '../../../../../../plugins/data/public';
import {
EmbeddableInput,
EmbeddableOutput,
Embeddable,
Container,
} from '../../../../../../plugins/embeddable/public';
import { Query } from '../../../../data/public';
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
import {
AppState,
Container,
Embeddable,
EmbeddableInput,
EmbeddableOutput,
PersistedState,
StaticIndexPattern,
VisSavedObject,
VisualizeLoader,
VisualizeLoaderParams,
VisualizeUpdateParams,
} from '../kibana_services';
const getKeys = <T extends {}>(o: T): Array<keyof T> => Object.keys(o) as Array<keyof T>;
export interface VisualizeEmbeddableConfiguration {

View file

@ -17,42 +17,11 @@
* under the License.
*/
import 'ui/registry/field_formats';
import 'uiExports/contextMenuActions';
import 'uiExports/devTools';
import 'uiExports/docViews';
import 'uiExports/embeddableFactories';
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/visEditorTypes';
import 'uiExports/visTypes';
import 'uiExports/visualize';
import { i18n } from '@kbn/i18n';
import { capabilities } from 'ui/capabilities';
import chrome from 'ui/chrome';
import { getVisualizeLoader } from 'ui/visualize/loader';
import { Legacy } from 'kibana';
import { SavedObjectAttributes } from 'kibana/server';
import { npSetup } from 'ui/new_platform';
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';
@ -60,7 +29,25 @@ 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 { VisSavedObject } from '../../../../../ui/public/visualize/loader/types';
import {
getServices,
Container,
EmbeddableFactory,
EmbeddableOutput,
ErrorEmbeddable,
getVisualizeLoader,
VisSavedObject,
} from '../kibana_services';
const {
addBasePath,
capabilities,
embeddable,
getInjector,
uiSettings,
visualizations,
} = getServices();
interface VisualizationAttributes extends SavedObjectAttributes {
visState: string;
@ -110,7 +97,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
if (!visType) {
return false;
}
if (chrome.getUiSettingsClient().get('visualize:enableLabs')) {
if (uiSettings.get('visualize:enableLabs')) {
return true;
}
return visType.stage !== 'experimental';
@ -122,7 +109,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
}
public isEditable() {
return capabilities.get().visualize.save as boolean;
return capabilities.visualize.save as boolean;
}
public getDisplayName() {
@ -136,16 +123,14 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
input: Partial<VisualizeInput> & { id: string },
parent?: Container
): Promise<VisualizeEmbeddable | ErrorEmbeddable | DisabledLabEmbeddable> {
const $injector = await chrome.dangerouslyGetActiveInjector();
const $injector = await getInjector();
const config = $injector.get<Legacy.KibanaConfig>('config');
const savedVisualizations = $injector.get<SavedVisualizations>('savedVisualizations');
try {
const visId = savedObject.id as string;
const editUrl = visId
? chrome.addBasePath(`/app/kibana${savedVisualizations.urlFor(visId)}`)
: '';
const editUrl = visId ? addBasePath(`/app/kibana${savedVisualizations.urlFor(visId)}`) : '';
const loader = await getVisualizeLoader();
const isLabsEnabled = config.get<boolean>('visualize:enableLabs');
@ -179,7 +164,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
input: Partial<VisualizeInput> & { id: string },
parent?: Container
): Promise<VisualizeEmbeddable | ErrorEmbeddable | DisabledLabEmbeddable> {
const $injector = await chrome.dangerouslyGetActiveInjector();
const $injector = await getInjector();
const savedVisualizations = $injector.get<SavedVisualizations>('savedVisualizations');
try {
@ -206,8 +191,5 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
}
VisualizeEmbeddableFactory.createVisualizeEmbeddableFactory().then(embeddableFactory => {
npSetup.plugins.embeddable.registerEmbeddableFactory(
VISUALIZE_EMBEDDABLE_TYPE,
embeddableFactory
);
embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory);
});

View file

@ -20,7 +20,10 @@
import React, { Fragment, PureComponent } from 'react';
import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
import { getServices } from '../kibana_services';
const { docLinks } = getServices();
export class HelpMenu extends PureComponent {
render() {
@ -31,7 +34,7 @@ export class HelpMenu extends PureComponent {
<EuiButton
fill
iconType="popout"
href={`${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/visualize.html`}
href={`${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/visualize.html`}
target="_blank"
>
<FormattedMessage id="kbn.visualize.helpMenu.docLabel" defaultMessage="Visualize documentation" />

View file

@ -22,7 +22,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { HelpMenu } from './help_menu';
export function addHelpMenuToAppChrome(chrome) {
chrome.helpExtension.set(domElement => {
chrome.setHelpExtension(domElement => {
render(<HelpMenu/>, domElement);
return () => {
unmountComponentAtNode(domElement);

View file

@ -21,16 +21,14 @@ import './editor/editor';
import { i18n } from '@kbn/i18n';
import './saved_visualizations/_saved_vis';
import './saved_visualizations/saved_visualizations';
import uiRoutes from 'ui/routes';
import 'ui/capabilities/route_setup';
import visualizeListingTemplate from './listing/visualize_listing.html';
import { VisualizeListingController } from './listing/visualize_listing';
import { VisualizeConstants } from './visualize_constants';
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
import { getLandingBreadcrumbs, getWizardStep1Breadcrumbs } from './breadcrumbs';
// load directives
import '../../../data/public';
import { getServices, FeatureCatalogueCategory } from './kibana_services';
const { FeatureCatalogueRegistryProvider, uiRoutes } = getServices();
uiRoutes
.defaults(/visualize/, {

View file

@ -0,0 +1,132 @@
/*
* 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 '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 { npStart } from 'ui/new_platform';
import angular from 'angular'; // just used in editor.js
import chromeLegacy from 'ui/chrome';
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';
import { ShareContextMenuExtensionsRegistryProvider } from 'ui/share';
import { timefilter } from 'ui/timefilter';
// Saved objects
import { SavedObjectsClientProvider } from 'ui/saved_objects';
// @ts-ignore
import { 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 data } from '../../../data/public/legacy';
import { start as embeddables } from '../../../../core_plugins/embeddable_api/public/np_ready/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,
data,
embeddables,
visualizations,
// legacy
chromeLegacy,
docTitle,
FeatureCatalogueRegistryProvider,
FilterBarQueryFilterProvider,
getInjector: () => {
return chromeLegacy.dangerouslyGetActiveInjector();
},
SavedObjectProvider,
SavedObjectRegistryProvider,
SavedObjectsClientProvider,
ShareContextMenuExtensionsRegistryProvider,
timefilter,
uiModules,
uiRoutes,
wrapInI18nContext,
createUiStatsReporter,
};
export function getServices() {
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';
// @ts-ignore
export { getUnhashableStatesProvider } from 'ui/state_management/state_hashing';
export { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
export { showShareContextMenu } from 'ui/share';
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 { getVisualizeLoader } from 'ui/visualize/loader';
export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
export {
Container,
Embeddable,
EmbeddableFactory,
EmbeddableInput,
EmbeddableOutput,
ErrorEmbeddable,
} from '../../../../../plugins/embeddable/public';
// export types
export { METRIC_TYPE };
export { StaticIndexPattern } from 'ui/index_patterns';
export { AppState } from 'ui/state_management/app_state';
export { VisType } from 'ui/vis';
export { VisualizeLoader } from 'ui/visualize/loader';
export {
VisSavedObject,
VisualizeLoaderParams,
VisualizeUpdateParams,
} from 'ui/visualize/loader/types';
// export const
export { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';

View file

@ -18,7 +18,8 @@
*/
import React from 'react';
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import {
KuiEmptyTablePrompt,
@ -27,7 +28,7 @@ import {
KuiButtonIcon,
} from '@kbn/ui-framework/components';
function NoVisualizationsPromptUi({ onCreateVis, intl }) {
function NoVisualizationsPrompt({ onCreateVis }) {
return (
<KuiEmptyTablePromptPanel>
<KuiEmptyTablePrompt
@ -35,7 +36,7 @@ function NoVisualizationsPromptUi({ onCreateVis, intl }) {
<KuiButton
onClick={onCreateVis}
buttonType="primary"
icon={<KuiButtonIcon type="create"/>}
icon={<KuiButtonIcon type="create" />}
>
<FormattedMessage
id="kbn.visualize.listing.noVisualizations.createVisualizationButtonLabel"
@ -43,8 +44,7 @@ function NoVisualizationsPromptUi({ onCreateVis, intl }) {
/>
</KuiButton>
}
message={intl.formatMessage({
id: 'kbn.visualize.listing.noVisualizationsText',
message={i18n.translate('kbn.visualize.listing.noVisualizationsText', {
defaultMessage: `Looks like you don't have any visualizations. Let's create some!`,
})}
/>
@ -52,4 +52,4 @@ function NoVisualizationsPromptUi({ onCreateVis, intl }) {
);
}
export const NoVisualizationsPrompt = injectI18n(NoVisualizationsPromptUi);
export { NoVisualizationsPrompt };

View file

@ -17,21 +17,27 @@
* under the License.
*/
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
import 'ui/directives/kbn_href';
import { uiModules } from 'ui/modules';
import { timefilter } from 'ui/timefilter';
import chrome from 'ui/chrome';
import { wrapInI18nContext } from 'ui/i18n';
import { toastNotifications } from 'ui/notify';
import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util';
import { SavedObjectsClientProvider } from 'ui/saved_objects';
import { VisualizeListingTable } from './visualize_listing_table';
import { NewVisModal } from '../wizard/new_vis_modal';
import { VisualizeConstants } from '../visualize_constants';
import { start as visualizations } from '../../../../visualizations/public/np_ready/public/legacy';
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))
@ -55,11 +61,11 @@ export function VisualizeListingController($injector, createNewVis) {
this.editItem = ({ editUrl }) => {
// for visualizations the edit and view URLs are the same
window.location = chrome.addBasePath(editUrl);
window.location.href = addBasePath(editUrl);
};
this.getViewUrl = ({ editUrl }) => {
return chrome.addBasePath(editUrl);
return addBasePath(editUrl);
};
this.closeNewVisModal = () => {
@ -101,7 +107,7 @@ export function VisualizeListingController($injector, createNewVis) {
})
)
.then(() => {
chrome.untrackNavLinksForDeletedSavedObjects(selectedItems.map(item => item.id));
chromeLegacy.untrackNavLinksForDeletedSavedObjects(selectedItems.map(item => item.id));
})
.catch(error => {
toastNotifications.addError(error, {
@ -112,7 +118,7 @@ export function VisualizeListingController($injector, createNewVis) {
});
};
chrome.breadcrumbs.set([
chrome.setBreadcrumbs([
{
text: i18n.translate('kbn.visualize.visualizeListingBreadcrumbsTitle', {
defaultMessage: 'Visualize',

View file

@ -19,69 +19,53 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { capabilities } from 'ui/capabilities';
import { TableListView } from './../../table_list_view';
import {
EuiIcon,
EuiBetaBadge,
EuiLink,
EuiButton,
EuiEmptyPrompt,
} from '@elastic/eui';
import { EuiIcon, EuiBetaBadge, EuiLink, EuiButton, EuiEmptyPrompt } from '@elastic/eui';
class VisualizeListingTableUi extends Component {
import { getServices } from '../kibana_services';
const { capabilities } = getServices();
class VisualizeListingTable extends Component {
constructor(props) {
super(props);
}
render() {
const { intl } = this.props;
return (
<TableListView
// we allow users to create visualizations even if they can't save them
// for data exploration purposes
createItem={this.props.createItem}
findItems={this.props.findItems}
deleteItems={capabilities.get().visualize.delete ? this.props.deleteItems : null}
editItem={capabilities.get().visualize.save ? this.props.editItem : null}
deleteItems={capabilities.visualize.delete ? this.props.deleteItems : null}
editItem={capabilities.visualize.save ? this.props.editItem : null}
tableColumns={this.getTableColumns()}
listingLimit={this.props.listingLimit}
selectable={item => item.canDelete}
initialFilter={''}
noItemsFragment={this.getNoItemsMessage()}
entityName={
intl.formatMessage({
id: 'kbn.visualize.listing.table.entityName',
defaultMessage: 'visualization',
})
}
entityNamePlural={
intl.formatMessage({
id: 'kbn.visualize.listing.table.entityNamePlural',
defaultMessage: 'visualizations',
})
}
tableListTitle={
intl.formatMessage({
id: 'kbn.visualize.listing.table.listTitle',
defaultMessage: 'Visualizations',
})
}
entityName={i18n.translate('kbn.visualize.listing.table.entityName', {
defaultMessage: 'visualization',
})}
entityNamePlural={i18n.translate('kbn.visualize.listing.table.entityNamePlural', {
defaultMessage: 'visualizations',
})}
tableListTitle={i18n.translate('kbn.visualize.listing.table.listTitle', {
defaultMessage: 'Visualizations',
})}
/>
);
}
getTableColumns() {
const { intl } = this.props;
const tableColumns = [
{
field: 'title',
name: intl.formatMessage({
id: 'kbn.visualize.listing.table.titleColumnName',
name: i18n.translate('kbn.visualize.listing.table.titleColumnName', {
defaultMessage: 'Title',
}),
sortable: true,
@ -92,35 +76,29 @@ class VisualizeListingTableUi extends Component {
>
{field}
</EuiLink>
)
),
},
{
field: 'typeTitle',
name: intl.formatMessage({
id: 'kbn.visualize.listing.table.typeColumnName',
name: i18n.translate('kbn.visualize.listing.table.typeColumnName', {
defaultMessage: 'Type',
}),
sortable: true,
render: (field, record) => (
render: (field, record) => (
<span>
{this.renderItemTypeIcon(record)}
{record.typeTitle}
{this.getBadge(record)}
</span>
)
),
},
{
field: 'description',
name: intl.formatMessage({
id: 'kbn.dashboard.listing.table.descriptionColumnName',
name: i18n.translate('kbn.dashboard.listing.table.descriptionColumnName', {
defaultMessage: 'Description',
}),
sortable: true,
render: (field, record) => (
<span>
{record.description}
</span>
)
render: (field, record) => <span>{record.description}</span>,
},
];
@ -184,19 +162,13 @@ class VisualizeListingTableUi extends Component {
/>
</div>
);
}
renderItemTypeIcon(item) {
let icon;
if (item.image) {
icon = (
<img
className="visListingTable__typeImage"
aria-hidden="true"
alt=""
src={item.image}
/>
<img className="visListingTable__typeImage" aria-hidden="true" alt="" src={item.image} />
);
} else {
icon = (
@ -214,38 +186,40 @@ class VisualizeListingTableUi extends Component {
getBadge(item) {
if (item.stage === 'beta') {
return (<EuiBetaBadge
className="visListingTable__betaIcon"
label="B"
title={i18n.translate('kbn.visualize.listing.betaTitle', {
defaultMessage: 'Beta',
})}
tooltipContent={
i18n.translate('kbn.visualize.listing.betaTooltip', {
defaultMessage: 'This visualization is in beta and is subject to change. The design and code is less mature than official GA ' +
'features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA ' +
'features',
})
}
/>);
return (
<EuiBetaBadge
className="visListingTable__betaIcon"
label="B"
title={i18n.translate('kbn.visualize.listing.betaTitle', {
defaultMessage: 'Beta',
})}
tooltipContent={i18n.translate('kbn.visualize.listing.betaTooltip', {
defaultMessage:
'This visualization is in beta and is subject to change. The design and code is less mature than official GA ' +
'features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA ' +
'features',
})}
/>
);
} else if (item.stage === 'experimental') {
return (<EuiBetaBadge
className="visListingTable__experimentalIcon"
label="E"
title={i18n.translate('kbn.visualize.listing.experimentalTitle', {
defaultMessage: 'Experimental',
})}
tooltipContent={
i18n.translate('kbn.visualize.listing.experimentalTooltip', {
defaultMessage: 'This visualization might be changed or removed in a future release and is not subject to the support SLA.',
})
}
/>);
return (
<EuiBetaBadge
className="visListingTable__experimentalIcon"
label="E"
title={i18n.translate('kbn.visualize.listing.experimentalTitle', {
defaultMessage: 'Experimental',
})}
tooltipContent={i18n.translate('kbn.visualize.listing.experimentalTooltip', {
defaultMessage:
'This visualization might be changed or removed in a future release and is not subject to the support SLA.',
})}
/>
);
}
}
}
VisualizeListingTableUi.propTypes = {
VisualizeListingTable.propTypes = {
deleteItems: PropTypes.func.isRequired,
findItems: PropTypes.func.isRequired,
createItem: PropTypes.func.isRequired,
@ -254,4 +228,4 @@ VisualizeListingTableUi.propTypes = {
listingLimit: PropTypes.number.isRequired,
};
export const VisualizeListingTable = injectI18n(VisualizeListingTableUi);
export { VisualizeListingTable };

View file

@ -17,7 +17,7 @@
* under the License.
*/
import { VisSavedObject } from 'ui/visualize/loader/types';
import { VisSavedObject } from './kibana_services';
export interface SavedVisualizations {
urlFor: (id: string) => string;

View file

@ -1,26 +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.
*/
export const settingsGet = jest.fn();
jest.doMock('ui/chrome', () => ({
getUiSettingsClient: () => ({
get: settingsGet,
}),
}));

View file

@ -20,14 +20,33 @@
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
import { settingsGet } from './new_vis_modal.test.mocks';
import { NewVisModal } from './new_vis_modal';
import { VisType } from 'ui/vis';
import { VisType } from '../kibana_services';
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';
beforeEach(() => {
jest.clearAllMocks();
});
describe('NewVisModal', () => {
const settingsGet = getServices().uiSettings.get as jest.Mock;
const defaultVisTypeParams = {
hidden: false,
visualization: class Controller {

View file

@ -22,14 +22,15 @@ import React from 'react';
import { EuiModal, EuiOverlayMask } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import chrome from 'ui/chrome';
import { VisType } from 'ui/vis';
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;
@ -54,7 +55,7 @@ class NewVisModal extends React.Component<TypeSelectionProps, TypeSelectionState
constructor(props: TypeSelectionProps) {
super(props);
this.isLabsEnabled = chrome.getUiSettingsClient().get('visualize:enableLabs');
this.isLabsEnabled = uiSettings.get('visualize:enableLabs');
this.state = {
showSearchVisModal: false,
@ -123,7 +124,7 @@ class NewVisModal extends React.Component<TypeSelectionProps, TypeSelectionState
this.trackUiMetric(METRIC_TYPE.CLICK, visType.name);
if ('aliasUrl' in visType) {
window.location = chrome.addBasePath(visType.aliasUrl);
window.location.href = addBasePath(visType.aliasUrl);
return;
}

View file

@ -22,10 +22,10 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import { VisType } from 'ui/vis';
import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
import { VisType } from '../../kibana_services';
interface SearchSelectionProps {
onSearchSelected: (searchId: string, searchType: string) => void;
visType: VisType;

View file

@ -20,14 +20,21 @@
import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { NewVisHelp } from './new_vis_help';
import chrome from 'ui/chrome';
jest.doMock('ui/chrome');
jest.mock('../../kibana_services', () => {
return {
getServices: () => ({
addBasePath: jest.fn((url: string) => `testbasepath${url}`),
}),
};
});
beforeEach(() => {
jest.clearAllMocks();
});
describe('NewVisHelp', () => {
it('should render as expected', () => {
(chrome.addBasePath as unknown) = (url: string) => `testbasepath${url}`;
expect(
shallowWithIntl(
<NewVisHelp
@ -36,7 +43,7 @@ describe('NewVisHelp', () => {
aliasUrl: '/my/fancy/new/thing',
description: 'Some desc',
highlighted: false,
icon: 'wahtever',
icon: 'whatever',
name: 'whatever',
promotion: {
buttonText: 'Do it now!',

View file

@ -20,9 +20,10 @@
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Fragment } from 'react';
import { EuiText, EuiButton } from '@elastic/eui';
import chrome from 'ui/chrome';
import { VisTypeAliasListEntry } from './type_selection';
import { getServices } from '../../kibana_services';
interface Props {
promotedTypes: VisTypeAliasListEntry[];
}
@ -42,7 +43,7 @@ export function NewVisHelp(props: Props) {
<strong>{t.promotion!.description}</strong>
</p>
<EuiButton
href={chrome.addBasePath(t.aliasUrl)}
href={getServices().addBasePath(t.aliasUrl)}
fill
size="s"
iconType="popout"

View file

@ -35,7 +35,7 @@ import {
EuiTitle,
} from '@elastic/eui';
import { memoizeLast } from 'ui/utils/memoize';
import { VisType } from 'ui/vis';
import { VisType } from '../../kibana_services';
import { VisTypeAlias } from '../../../../../visualizations/public';
import { NewVisHelp } from './new_vis_help';
import { VisHelpText } from './vis_help_text';

View file

@ -6,7 +6,7 @@
// @ts-ignore
import { MAP_SAVED_OBJECT_TYPE } from '../../../maps/common/constants';
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/visualize/embeddable';
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/visualize/embeddable/constants';
import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/embeddable/constants';
export const EmbeddableTypes = {