From 387e28a6a419eab942fd4b6088a2523719242d00 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Mon, 11 May 2020 10:12:59 +0200 Subject: [PATCH] [Drilldowns][chore] import dashboard url generator from plugin contract (#64628) Co-authored-by: Elastic Machine --- src/plugins/dashboard/public/index.ts | 2 +- src/plugins/dashboard/public/plugin.tsx | 19 ++++++++--- .../dashboard/public/url_generator.test.ts | 24 ++++++------- src/plugins/dashboard/public/url_generator.ts | 2 +- .../url_generator_service.test.ts | 18 ++++++++-- .../url_generators/url_generator_service.ts | 11 +++--- .../dashboard_enhanced/public/plugin.ts | 2 ++ .../dashboard_drilldowns_services.ts | 11 +++++- .../drilldown.test.tsx | 34 ++++++++----------- .../drilldown.tsx | 9 +++-- 10 files changed, 82 insertions(+), 50 deletions(-) diff --git a/src/plugins/dashboard/public/index.ts b/src/plugins/dashboard/public/index.ts index 44733499cdcba4..e093342f957358 100644 --- a/src/plugins/dashboard/public/index.ts +++ b/src/plugins/dashboard/public/index.ts @@ -31,7 +31,7 @@ export { } from './application'; export { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; -export { DashboardStart } from './plugin'; +export { DashboardStart, DashboardUrlGenerator } from './plugin'; export { DASHBOARD_APP_URL_GENERATOR } from './url_generator'; export function plugin(initializerContext: PluginInitializerContext) { diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index b28822120b31e6..894440cfa9cbbf 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -42,7 +42,11 @@ import { DataPublicPluginSetup, esFilters, } from '../../../plugins/data/public'; -import { SharePluginSetup, SharePluginStart } from '../../../plugins/share/public'; +import { + SharePluginSetup, + SharePluginStart, + UrlGeneratorContract, +} from '../../../plugins/share/public'; import { UiActionsSetup, UiActionsStart } from '../../../plugins/ui_actions/public'; import { Start as InspectorStartContract } from '../../../plugins/inspector/public'; @@ -77,7 +81,7 @@ import { import { DashboardAppLinkGeneratorState, DASHBOARD_APP_URL_GENERATOR, - createDirectAccessDashboardLinkGenerator, + createDashboardUrlGenerator, } from './url_generator'; import { createSavedDashboardLoader } from './saved_dashboards'; import { DashboardConstants } from './dashboard_constants'; @@ -89,6 +93,8 @@ declare module '../../share/public' { } } +export type DashboardUrlGenerator = UrlGeneratorContract; + interface SetupDependencies { data: DataPublicPluginSetup; embeddable: EmbeddableSetup; @@ -111,8 +117,10 @@ interface StartDependencies { } export type Setup = void; + export interface DashboardStart { getSavedDashboardLoader: () => SavedObjectLoader; + dashboardUrlGenerator?: DashboardUrlGenerator; } declare module '../../../plugins/ui_actions/public' { @@ -130,6 +138,8 @@ export class DashboardPlugin private appStateUpdater = new BehaviorSubject(() => ({})); private stopUrlTracking: (() => void) | undefined = undefined; + private dashboardUrlGenerator?: DashboardUrlGenerator; + public setup( core: CoreSetup, { share, uiActions, embeddable, home, kibanaLegacy, data, usageCollection }: SetupDependencies @@ -140,8 +150,8 @@ export class DashboardPlugin const startServices = core.getStartServices(); if (share) { - share.urlGenerators.registerUrlGenerator( - createDirectAccessDashboardLinkGenerator(async () => { + this.dashboardUrlGenerator = share.urlGenerators.registerUrlGenerator( + createDashboardUrlGenerator(async () => { const [coreStart, , selfStart] = await startServices; return { appBasePath: coreStart.application.getUrlForApp('dashboard'), @@ -325,6 +335,7 @@ export class DashboardPlugin }); return { getSavedDashboardLoader: () => savedDashboardLoader, + dashboardUrlGenerator: this.dashboardUrlGenerator, }; } diff --git a/src/plugins/dashboard/public/url_generator.test.ts b/src/plugins/dashboard/public/url_generator.test.ts index 248a3f991d6cbf..68d447c4a13361 100644 --- a/src/plugins/dashboard/public/url_generator.test.ts +++ b/src/plugins/dashboard/public/url_generator.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { createDirectAccessDashboardLinkGenerator } from './url_generator'; +import { createDashboardUrlGenerator } from './url_generator'; import { hashedItemStore } from '../../kibana_utils/public'; // eslint-disable-next-line import { mockStorage } from '../../kibana_utils/public/storage/hashed_item_store/mock'; @@ -55,7 +55,7 @@ describe('dashboard url generator', () => { }); test('creates a link to a saved dashboard', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -67,7 +67,7 @@ describe('dashboard url generator', () => { }); test('creates a link with global time range set up', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -83,7 +83,7 @@ describe('dashboard url generator', () => { }); test('creates a link with filters, time range, refresh interval and query to a saved object', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -123,7 +123,7 @@ describe('dashboard url generator', () => { }); test('if no useHash setting is given, uses the one was start services', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: true, @@ -137,7 +137,7 @@ describe('dashboard url generator', () => { }); test('can override a false useHash ui setting', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -152,7 +152,7 @@ describe('dashboard url generator', () => { }); test('can override a true useHash ui setting', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: true, @@ -195,7 +195,7 @@ describe('dashboard url generator', () => { }; test('attaches filters from destination dashboard', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -224,7 +224,7 @@ describe('dashboard url generator', () => { }); test("doesn't fail if can't retrieve filters from destination dashboard", async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -246,7 +246,7 @@ describe('dashboard url generator', () => { }); test('can enforce empty filters', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -270,7 +270,7 @@ describe('dashboard url generator', () => { }); test('no filters in result url if no filters applied', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, @@ -288,7 +288,7 @@ describe('dashboard url generator', () => { }); test('can turn off preserving filters', async () => { - const generator = createDirectAccessDashboardLinkGenerator(() => + const generator = createDashboardUrlGenerator(() => Promise.resolve({ appBasePath: APP_BASE_PATH, useHashedUrl: false, diff --git a/src/plugins/dashboard/public/url_generator.ts b/src/plugins/dashboard/public/url_generator.ts index 6f121ceb2d3731..9d66f2df65777b 100644 --- a/src/plugins/dashboard/public/url_generator.ts +++ b/src/plugins/dashboard/public/url_generator.ts @@ -75,7 +75,7 @@ export type DashboardAppLinkGeneratorState = UrlGeneratorState<{ preserveSavedFilters?: boolean; }>; -export const createDirectAccessDashboardLinkGenerator = ( +export const createDashboardUrlGenerator = ( getStartServices: () => Promise<{ appBasePath: string; useHashedUrl: boolean; diff --git a/src/plugins/share/public/url_generators/url_generator_service.test.ts b/src/plugins/share/public/url_generators/url_generator_service.test.ts index 4a377db033762f..d256dcf5f7aa0a 100644 --- a/src/plugins/share/public/url_generators/url_generator_service.test.ts +++ b/src/plugins/share/public/url_generators/url_generator_service.test.ts @@ -30,11 +30,11 @@ test('Asking for a generator that does not exist throws an error', () => { }); test('Registering and retrieving a generator', async () => { - setup.registerUrlGenerator({ + const generator = setup.registerUrlGenerator({ id: 'TEST_GENERATOR', createUrl: () => Promise.resolve('myurl'), }); - const generator = start.getUrlGenerator('TEST_GENERATOR'); + expect(generator).toMatchInlineSnapshot(` Object { "createUrl": [Function], @@ -47,6 +47,20 @@ test('Registering and retrieving a generator', async () => { new Error('You cannot call migrate on a non-deprecated generator.') ); expect(await generator.createUrl({})).toBe('myurl'); + + const retrievedGenerator = start.getUrlGenerator('TEST_GENERATOR'); + expect(retrievedGenerator).toMatchInlineSnapshot(` + Object { + "createUrl": [Function], + "id": "TEST_GENERATOR", + "isDeprecated": false, + "migrate": [Function], + } + `); + await expect(generator.migrate({})).rejects.toEqual( + new Error('You cannot call migrate on a non-deprecated generator.') + ); + expect(await generator.createUrl({})).toBe('myurl'); }); test('Registering a generator with a createUrl function that is deprecated throws an error', () => { diff --git a/src/plugins/share/public/url_generators/url_generator_service.ts b/src/plugins/share/public/url_generators/url_generator_service.ts index 332750671cee39..13c1b94acdd07e 100644 --- a/src/plugins/share/public/url_generators/url_generator_service.ts +++ b/src/plugins/share/public/url_generators/url_generator_service.ts @@ -28,7 +28,9 @@ export interface UrlGeneratorsStart { } export interface UrlGeneratorsSetup { - registerUrlGenerator: (generator: UrlGeneratorsDefinition) => void; + registerUrlGenerator: ( + generator: UrlGeneratorsDefinition + ) => UrlGeneratorContract; } export class UrlGeneratorsService implements Plugin { @@ -43,10 +45,9 @@ export class UrlGeneratorsService implements Plugin( generatorOptions: UrlGeneratorsDefinition ) => { - this.urlGenerators.set( - generatorOptions.id, - new UrlGeneratorInternal(generatorOptions, this.getUrlGenerator) - ); + const generator = new UrlGeneratorInternal(generatorOptions, this.getUrlGenerator); + this.urlGenerators.set(generatorOptions.id, generator); + return generator.getPublicContract(); }, }; return setup; diff --git a/x-pack/plugins/dashboard_enhanced/public/plugin.ts b/x-pack/plugins/dashboard_enhanced/public/plugin.ts index 772e032289bcee..c258a4148f84a0 100644 --- a/x-pack/plugins/dashboard_enhanced/public/plugin.ts +++ b/x-pack/plugins/dashboard_enhanced/public/plugin.ts @@ -11,6 +11,7 @@ import { DashboardDrilldownsService } from './services'; import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; import { AdvancedUiActionsSetup, AdvancedUiActionsStart } from '../../advanced_ui_actions/public'; import { DrilldownsSetup, DrilldownsStart } from '../../drilldowns/public'; +import { DashboardStart } from '../../../../src/plugins/dashboard/public'; export interface SetupDependencies { advancedUiActions: AdvancedUiActionsSetup; @@ -25,6 +26,7 @@ export interface StartDependencies { drilldowns: DrilldownsStart; embeddable: EmbeddableStart; share: SharePluginStart; + dashboard: DashboardStart; } // eslint-disable-next-line diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts index 0161836b2c5b97..f5926cd6961c2d 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts @@ -44,6 +44,12 @@ export class DashboardDrilldownsService { { advancedUiActions: uiActions }: SetupDependencies ) { const start = createStartServicesGetter(core.getStartServices); + const getDashboardUrlGenerator = () => { + const urlGenerator = start().plugins.dashboard.dashboardUrlGenerator; + if (!urlGenerator) + throw new Error('dashboardUrlGenerator is required for dashboard to dashboard drilldown'); + return urlGenerator; + }; const actionFlyoutCreateDrilldown = new FlyoutCreateDrilldownAction({ start }); uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, actionFlyoutCreateDrilldown); @@ -51,7 +57,10 @@ export class DashboardDrilldownsService { const actionFlyoutEditDrilldown = new FlyoutEditDrilldownAction({ start }); uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, actionFlyoutEditDrilldown); - const dashboardToDashboardDrilldown = new DashboardToDashboardDrilldown({ start }); + const dashboardToDashboardDrilldown = new DashboardToDashboardDrilldown({ + start, + getDashboardUrlGenerator, + }); uiActions.registerDrilldown(dashboardToDashboardDrilldown); } } diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx index 18ee95cb57b3bc..d8465562f9302f 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx @@ -5,8 +5,7 @@ */ import { DashboardToDashboardDrilldown } from './drilldown'; -import { UrlGeneratorContract } from '../../../../../../../src/plugins/share/public'; -import { savedObjectsServiceMock } from '../../../../../../../src/core/public/mocks'; +import { savedObjectsServiceMock, coreMock } from '../../../../../../../src/core/public/mocks'; import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; import { ActionContext, Config } from './types'; import { @@ -19,15 +18,16 @@ import { import { esFilters } from '../../../../../../../src/plugins/data/public'; // convenient to use real implementation here. -import { createDirectAccessDashboardLinkGenerator } from '../../../../../../../src/plugins/dashboard/public/url_generator'; +import { createDashboardUrlGenerator } from '../../../../../../../src/plugins/dashboard/public/url_generator'; +import { UrlGeneratorsService } from '../../../../../../../src/plugins/share/public/url_generators'; import { VisualizeEmbeddableContract } from '../../../../../../../src/plugins/visualizations/public'; import { RangeSelectTriggerContext, ValueClickTriggerContext, } from '../../../../../../../src/plugins/embeddable/public'; +import { StartDependencies } from '../../../plugin'; import { SavedObjectLoader } from '../../../../../../../src/plugins/saved_objects/public'; import { StartServicesGetter } from '../../../../../../../src/plugins/kibana_utils/public/core'; -import { StartDependencies } from '../../../plugin'; describe('.isConfigValid()', () => { const drilldown = new DashboardToDashboardDrilldown({} as any); @@ -105,23 +105,19 @@ describe('.execute() & getHref', () => { data: { actions: dataPluginActions, }, - share: { - urlGenerators: { - getUrlGenerator: () => - createDirectAccessDashboardLinkGenerator(() => - Promise.resolve({ - appBasePath: 'test', - useHashedUrl: false, - savedDashboardLoader: ({} as unknown) as SavedObjectLoader, - }) - ) as UrlGeneratorContract, - }, - }, }, self: {}, - })) as unknown) as StartServicesGetter< - Pick - >, + })) as unknown) as StartServicesGetter>, + getDashboardUrlGenerator: () => + new UrlGeneratorsService().setup(coreMock.createSetup()).registerUrlGenerator( + createDashboardUrlGenerator(() => + Promise.resolve({ + appBasePath: 'test', + useHashedUrl: false, + savedDashboardLoader: ({} as unknown) as SavedObjectLoader, + }) + ) + ), }); const selectRangeFiltersSpy = jest .spyOn(dataPluginActions, 'createFiltersFromRangeSelectAction') diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx index 848e77384f7f04..6d83b8443a828c 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { reactToUiComponent } from '../../../../../../../src/plugins/kibana_react/public'; -import { DASHBOARD_APP_URL_GENERATOR } from '../../../../../../../src/plugins/dashboard/public'; +import { DashboardUrlGenerator } from '../../../../../../../src/plugins/dashboard/public'; import { ActionContext, Config } from './types'; import { CollectConfigContainer } from './components'; import { DASHBOARD_TO_DASHBOARD_DRILLDOWN } from './constants'; @@ -22,7 +22,8 @@ import { StartServicesGetter } from '../../../../../../../src/plugins/kibana_uti import { StartDependencies } from '../../../plugin'; export interface Params { - start: StartServicesGetter>; + start: StartServicesGetter>; + getDashboardUrlGenerator: () => DashboardUrlGenerator; } export class DashboardToDashboardDrilldown @@ -142,9 +143,7 @@ export class DashboardToDashboardDrilldown } } - const { plugins } = this.params.start(); - - return plugins.share.urlGenerators.getUrlGenerator(DASHBOARD_APP_URL_GENERATOR).createUrl({ + return this.params.getDashboardUrlGenerator().createUrl({ dashboardId: config.dashboardId, query: config.useCurrentFilters ? query : undefined, timeRange,