From d1129fd075528742d36823e029e8b6b2e06b0dc8 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 10:15:36 +0200 Subject: [PATCH 01/23] =?UTF-8?q?fix:=20=F0=9F=90=9B=20cast=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ml/public/ml_url_generator/ml_url_generator.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts index 94a3f1e232924c..89823896330eff 100644 --- a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts +++ b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts @@ -13,7 +13,10 @@ import type { } from '../../../../../src/plugins/share/public'; import type { MlStartDependencies } from '../plugin'; import { ML_PAGES, ML_APP_URL_GENERATOR } from '../../common/constants/ml_url_generator'; -import type { MlUrlGeneratorState } from '../../common/types/ml_url_generator'; +import type { + DataFrameAnalyticsExplorationUrlState, + MlUrlGeneratorState, +} from '../../common/types/ml_url_generator'; import { createAnomalyDetectionJobManagementUrl, createAnomalyDetectionCreateJobSelectType, @@ -74,8 +77,10 @@ export class MlUrlGenerator implements UrlGeneratorsDefinition Date: Tue, 29 Jun 2021 10:16:49 +0200 Subject: [PATCH 02/23] =?UTF-8?q?chore:=20=F0=9F=A4=96=20remove=20unused?= =?UTF-8?q?=20parameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts index 89823896330eff..b5c130a64990d4 100644 --- a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts +++ b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts @@ -41,7 +41,6 @@ declare module '../../../../../src/plugins/share/public' { interface Params { appBasePath: string; - useHash: boolean; } export class MlUrlGenerator implements UrlGeneratorsDefinition { @@ -123,7 +122,6 @@ export function registerUrlGenerator( return share.urlGenerators.registerUrlGenerator( new MlUrlGenerator({ appBasePath: baseUrl, - useHash: core.uiSettings.get('state:storeInSessionStorage'), }) ); } From 09d6487b0d7788bc705a937c8a68af933ae608d3 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 11:35:00 +0200 Subject: [PATCH 03/23] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20implement=20ML=20l?= =?UTF-8?q?ocator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../locator/formatters/anomaly_detection.ts | 223 ++++++++++++++++++ .../ml/public/locator/formatters/common.ts | 59 +++++ .../formatters/data_frame_analytics.ts | 171 ++++++++++++++ .../ml/public/locator/formatters/index.ts | 11 + .../ml/public/locator/formatters/settings.tsx | 46 ++++ .../plugins/ml/public/locator/ml_locator.ts | 109 +++++++++ 6 files changed, 619 insertions(+) create mode 100644 x-pack/plugins/ml/public/locator/formatters/anomaly_detection.ts create mode 100644 x-pack/plugins/ml/public/locator/formatters/common.ts create mode 100644 x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts create mode 100644 x-pack/plugins/ml/public/locator/formatters/index.ts create mode 100644 x-pack/plugins/ml/public/locator/formatters/settings.tsx create mode 100644 x-pack/plugins/ml/public/locator/ml_locator.ts diff --git a/x-pack/plugins/ml/public/locator/formatters/anomaly_detection.ts b/x-pack/plugins/ml/public/locator/formatters/anomaly_detection.ts new file mode 100644 index 00000000000000..05f9d8dde13c91 --- /dev/null +++ b/x-pack/plugins/ml/public/locator/formatters/anomaly_detection.ts @@ -0,0 +1,223 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isEmpty } from 'lodash'; +import type { + AnomalyDetectionUrlState, + ExplorerAppState, + ExplorerGlobalState, + ExplorerUrlState, + MlCommonGlobalState, + MlGenericUrlState, + TimeSeriesExplorerAppState, + TimeSeriesExplorerGlobalState, + TimeSeriesExplorerUrlState, +} from '../../../common/types/ml_url_generator'; +import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { formatGenericMlUrl } from './common'; +import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public'; +import { getGroupQueryText, getJobQueryText } from '../../../common/util/string_utils'; +import { AppPageState, ListingPageUrlState } from '../../../common/types/common'; + +/** + * Creates URL to the Anomaly Detection Job management page + */ +export function formatAnomalyDetectionJobManagementUrl( + appBasePath: string, + params: AnomalyDetectionUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE}`; + if (!params || isEmpty(params)) { + return url; + } + const { jobId, groupIds, globalState } = params; + if (jobId || groupIds) { + const queryTextArr = []; + if (jobId) { + queryTextArr.push(getJobQueryText(jobId)); + } + if (groupIds) { + queryTextArr.push(getGroupQueryText(groupIds)); + } + const jobsListState: Partial = { + ...(queryTextArr.length > 0 ? { queryText: queryTextArr.join(' ') } : {}), + }; + + const queryState: AppPageState = { + [ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE]: jobsListState, + }; + + url = setStateToKbnUrl>( + '_a', + queryState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + + if (globalState) { + url = setStateToKbnUrl>( + '_g', + globalState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + return url; +} + +export function formatAnomalyDetectionCreateJobSelectType( + appBasePath: string, + pageState: MlGenericUrlState['pageState'] +): string { + return formatGenericMlUrl( + appBasePath, + ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, + pageState + ); +} + +export function formatAnomalyDetectionCreateJobSelectIndex( + appBasePath: string, + pageState: MlGenericUrlState['pageState'] +): string { + return formatGenericMlUrl( + appBasePath, + ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX, + pageState + ); +} + +/** + * Creates URL to the Anomaly Explorer page + */ +export function formatExplorerUrl( + appBasePath: string, + params: ExplorerUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.ANOMALY_EXPLORER}`; + + if (!params) { + return url; + } + const { + refreshInterval, + timeRange, + jobIds, + query, + mlExplorerSwimlane = {}, + mlExplorerFilter = {}, + globalState, + } = params; + const appState: Partial = { + mlExplorerSwimlane, + mlExplorerFilter, + }; + let queryState: Partial = {}; + if (globalState) queryState = globalState; + if (query) appState.query = query; + if (jobIds) { + queryState.ml = { + jobIds, + }; + } + if (refreshInterval) queryState.refreshInterval = refreshInterval; + if (timeRange) queryState.time = timeRange; + + url = setStateToKbnUrl>( + '_g', + queryState, + { useHash: false, storeInHashQuery: false }, + url + ); + url = setStateToKbnUrl>>( + '_a', + { [ML_PAGES.ANOMALY_EXPLORER]: appState }, + { useHash: false, storeInHashQuery: false }, + url + ); + + return url; +} + +/** + * Creates URL to the SingleMetricViewer page + */ +export function formatSingleMetricViewerUrl( + appBasePath: string, + params: TimeSeriesExplorerUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.SINGLE_METRIC_VIEWER}`; + if (!params) { + return url; + } + const { + timeRange, + jobIds, + refreshInterval, + query, + detectorIndex, + forecastId, + entities, + globalState, + functionDescription, + zoom, + } = params; + + let queryState: Partial = {}; + if (globalState) queryState = globalState; + + if (jobIds) { + queryState.ml = { + jobIds, + }; + } + if (refreshInterval) queryState.refreshInterval = refreshInterval; + if (timeRange) queryState.time = timeRange; + + const appState: Partial = {}; + const mlTimeSeriesExplorer: Partial = {}; + + if (forecastId !== undefined) { + mlTimeSeriesExplorer.forecastId = forecastId; + } + + if (detectorIndex !== undefined) { + mlTimeSeriesExplorer.detectorIndex = detectorIndex; + } + if (entities !== undefined) { + mlTimeSeriesExplorer.entities = entities; + } + if (functionDescription !== undefined) { + mlTimeSeriesExplorer.functionDescription = functionDescription; + } + + if (zoom !== undefined) { + mlTimeSeriesExplorer.zoom = zoom; + } + + appState.mlTimeSeriesExplorer = mlTimeSeriesExplorer; + + if (query) + appState.query = { + query_string: query, + }; + url = setStateToKbnUrl>( + '_g', + queryState, + { useHash: false, storeInHashQuery: false }, + url + ); + url = setStateToKbnUrl>>( + '_a', + { [ML_PAGES.SINGLE_METRIC_VIEWER]: appState }, + { useHash: false, storeInHashQuery: false }, + url + ); + + return url; +} diff --git a/x-pack/plugins/ml/public/locator/formatters/common.ts b/x-pack/plugins/ml/public/locator/formatters/common.ts new file mode 100644 index 00000000000000..6faed7ee2917e3 --- /dev/null +++ b/x-pack/plugins/ml/public/locator/formatters/common.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isEmpty } from 'lodash'; +import { MlGenericUrlState } from '../../../common/types/ml_url_generator'; +import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public'; + +export function extractParams(urlState: UrlState) { + // page should be guaranteed to exist here but is unknown + // @ts-ignore + const { page, ...params } = urlState; + return { page, params }; +} + +/** + * Creates generic index based search ML url + * e.g. `jobs/new_job/datavisualizer?index=3da93760-e0af-11ea-9ad3-3bcfc330e42a` + */ +export function formatGenericMlUrl( + appBasePath: string, + page: MlGenericUrlState['page'], + pageState: MlGenericUrlState['pageState'] +): string { + let url = `${appBasePath}/${page}`; + + if (pageState) { + const { globalState, appState, index, savedSearchId, ...restParams } = pageState; + if (index !== undefined && savedSearchId === undefined) { + url = `${url}?index=${index}`; + } + if (index === undefined && savedSearchId !== undefined) { + url = `${url}?savedSearchId=${savedSearchId}`; + } + + if (!isEmpty(restParams)) { + Object.keys(restParams).forEach((key) => { + url = setStateToKbnUrl( + key, + restParams[key], + { useHash: false, storeInHashQuery: false }, + url + ); + }); + } + + if (globalState) { + url = setStateToKbnUrl('_g', globalState, { useHash: false, storeInHashQuery: false }, url); + } + if (appState) { + url = setStateToKbnUrl('_a', appState, { useHash: false, storeInHashQuery: false }, url); + } + } + + return url; +} diff --git a/x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts b/x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts new file mode 100644 index 00000000000000..844eeb4ca435a8 --- /dev/null +++ b/x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts @@ -0,0 +1,171 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * Creates URL to the DataFrameAnalytics page + */ +import { isEmpty } from 'lodash'; +import { formatGenericMlUrl } from './common'; +import { + DataFrameAnalyticsExplorationQueryState, + DataFrameAnalyticsExplorationUrlState, + DataFrameAnalyticsUrlState, + ExplorationPageUrlState, + MlGenericUrlState, + MlCommonGlobalState, +} from '../../../common/types/ml_url_generator'; +import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public'; +import { getGroupQueryText, getJobQueryText } from '../../../common/util/string_utils'; +import { AppPageState, ListingPageUrlState } from '../../../common/types/common'; + +export function formatDataFrameAnalyticsJobManagementUrl( + appBasePath: string, + mlUrlGeneratorState: DataFrameAnalyticsUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE}`; + + if (mlUrlGeneratorState) { + const { jobId, groupIds, globalState } = mlUrlGeneratorState; + if (jobId || groupIds) { + const queryTextArr = []; + if (jobId) { + queryTextArr.push(getJobQueryText(jobId)); + } + if (groupIds) { + queryTextArr.push(getGroupQueryText(groupIds)); + } + const jobsListState: Partial = { + ...(queryTextArr.length > 0 ? { queryText: queryTextArr.join(' ') } : {}), + }; + + const queryState: AppPageState = { + [ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE]: jobsListState, + }; + + url = setStateToKbnUrl>( + '_a', + queryState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + if (globalState) { + url = setStateToKbnUrl>( + '_g', + globalState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + } + + return url; +} + +/** + * Creates URL to the DataFrameAnalytics Exploration page + */ +export function formatDataFrameAnalyticsExplorationUrl( + appBasePath: string, + mlUrlGeneratorState: DataFrameAnalyticsExplorationUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION}`; + + if (mlUrlGeneratorState) { + const { jobId, analysisType, queryText, globalState } = mlUrlGeneratorState; + + const queryState: DataFrameAnalyticsExplorationQueryState = { + ml: { + jobId, + analysisType, + }, + ...globalState, + }; + + const appState = { + [ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION]: { + ...(queryText ? { queryText } : {}), + }, + }; + + if (!isEmpty(appState[ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION])) { + url = setStateToKbnUrl>( + '_a', + appState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + + url = setStateToKbnUrl( + '_g', + queryState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + + return url; +} + +/** + * Creates URL to the DataFrameAnalytics creation wizard + */ +export function formatDataFrameAnalyticsCreateJobUrl( + appBasePath: string, + pageState: MlGenericUrlState['pageState'] +): string { + return formatGenericMlUrl(appBasePath, ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, pageState); +} + +/** + * Creates URL to the DataFrameAnalytics Map page + */ +export function formatDataFrameAnalyticsMapUrl( + appBasePath: string, + mlUrlGeneratorState: DataFrameAnalyticsExplorationUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.DATA_FRAME_ANALYTICS_MAP}`; + + if (mlUrlGeneratorState) { + const { jobId, modelId, analysisType, globalState, queryText } = mlUrlGeneratorState; + + const queryState: DataFrameAnalyticsExplorationQueryState = { + ml: { + jobId, + modelId, + analysisType, + }, + ...globalState, + }; + + const appState = { + [ML_PAGES.DATA_FRAME_ANALYTICS_MAP]: { + ...(queryText ? { queryText } : {}), + }, + }; + + if (!isEmpty(appState[ML_PAGES.DATA_FRAME_ANALYTICS_MAP])) { + url = setStateToKbnUrl>( + '_a', + appState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + + url = setStateToKbnUrl( + '_g', + queryState, + { useHash: false, storeInHashQuery: false }, + url + ); + } + + return url; +} diff --git a/x-pack/plugins/ml/public/locator/formatters/index.ts b/x-pack/plugins/ml/public/locator/formatters/index.ts new file mode 100644 index 00000000000000..4b8dc38d51968f --- /dev/null +++ b/x-pack/plugins/ml/public/locator/formatters/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './common'; +export * from './anomaly_detection'; +export * from './data_frame_analytics'; +export * from './settings'; diff --git a/x-pack/plugins/ml/public/locator/formatters/settings.tsx b/x-pack/plugins/ml/public/locator/formatters/settings.tsx new file mode 100644 index 00000000000000..d253b0d9bce81d --- /dev/null +++ b/x-pack/plugins/ml/public/locator/formatters/settings.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CalendarEditUrlState, FilterEditUrlState } from '../../../common/types/ml_url_generator'; +import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public'; + +export function formatEditCalendarUrl( + appBasePath: string, + pageState: CalendarEditUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.CALENDARS_EDIT}`; + if (pageState) { + const { globalState, calendarId } = pageState; + if (calendarId !== undefined) { + url = `${url}/${calendarId}`; + } + if (globalState) { + url = setStateToKbnUrl('_g', globalState, { useHash: false, storeInHashQuery: false }, url); + } + } + + return url; +} + +export function formatEditFilterUrl( + appBasePath: string, + pageState: FilterEditUrlState['pageState'] +): string { + let url = `${appBasePath}/${ML_PAGES.FILTER_LISTS_EDIT}`; + if (pageState) { + const { globalState, filterId } = pageState; + if (filterId !== undefined) { + url = `${url}/${filterId}`; + } + if (globalState) { + url = setStateToKbnUrl('_g', globalState, { useHash: false, storeInHashQuery: false }, url); + } + } + + return url; +} diff --git a/x-pack/plugins/ml/public/locator/ml_locator.ts b/x-pack/plugins/ml/public/locator/ml_locator.ts new file mode 100644 index 00000000000000..11f3874ac93085 --- /dev/null +++ b/x-pack/plugins/ml/public/locator/ml_locator.ts @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SerializableState } from 'src/plugins/kibana_utils/common'; +import type { + LocatorDefinition, + LocatorPublic, + KibanaLocation, +} from '../../../../../src/plugins/share/public'; +import type { + DataFrameAnalyticsExplorationUrlState, + MlUrlGeneratorState, +} from '../../common/types/ml_url_generator'; +import { ML_PAGES } from '../../common/constants/ml_url_generator'; +import { + formatAnomalyDetectionCreateJobSelectIndex, + formatAnomalyDetectionCreateJobSelectType, + formatAnomalyDetectionJobManagementUrl, + formatExplorerUrl, + formatSingleMetricViewerUrl, + formatDataFrameAnalyticsCreateJobUrl, + formatDataFrameAnalyticsExplorationUrl, + formatDataFrameAnalyticsJobManagementUrl, + formatDataFrameAnalyticsMapUrl, + formatGenericMlUrl, + formatEditCalendarUrl, + formatEditFilterUrl, +} from './formatters'; + +export type MlLocatorParams = MlUrlGeneratorState & SerializableState; + +export type MlLocator = LocatorPublic; + +export const ML_APP_LOCATOR = 'ML_APP_LOCATOR'; + +export class MlLocatorDefinition implements LocatorDefinition { + public readonly id = ML_APP_LOCATOR; + + public readonly getLocation = async (params: MlLocatorParams): Promise => { + let path: string = ''; + + switch (params.page) { + case ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE: + path = formatAnomalyDetectionJobManagementUrl('', params.pageState); + break; + case ML_PAGES.ANOMALY_EXPLORER: + path = formatExplorerUrl('', params.pageState); + break; + case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE: + path = formatAnomalyDetectionCreateJobSelectType('', params.pageState); + break; + case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX: + path = formatAnomalyDetectionCreateJobSelectIndex('', params.pageState); + break; + case ML_PAGES.SINGLE_METRIC_VIEWER: + path = formatSingleMetricViewerUrl('', params.pageState); + break; + case ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE: + path = formatDataFrameAnalyticsJobManagementUrl('', params.pageState); + break; + case ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB: + path = formatDataFrameAnalyticsCreateJobUrl('', params.pageState); + break; + case ML_PAGES.DATA_FRAME_ANALYTICS_MAP: + path = formatDataFrameAnalyticsMapUrl( + '', + params.pageState as DataFrameAnalyticsExplorationUrlState['pageState'] + ); + break; + case ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION: + path = formatDataFrameAnalyticsExplorationUrl('', params.pageState); + break; + case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB: + case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED: + case ML_PAGES.DATA_VISUALIZER: + case ML_PAGES.DATA_VISUALIZER_FILE: + case ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER: + case ML_PAGES.DATA_VISUALIZER_INDEX_SELECT: + case ML_PAGES.OVERVIEW: + case ML_PAGES.SETTINGS: + case ML_PAGES.FILTER_LISTS_MANAGE: + case ML_PAGES.FILTER_LISTS_NEW: + case ML_PAGES.CALENDARS_MANAGE: + case ML_PAGES.CALENDARS_NEW: + case ML_PAGES.ACCESS_DENIED: + path = formatGenericMlUrl('', params.page, params.pageState); + break; + case ML_PAGES.FILTER_LISTS_EDIT: + path = formatEditFilterUrl('', params.pageState); + break; + case ML_PAGES.CALENDARS_EDIT: + path = formatEditCalendarUrl('', params.pageState); + break; + + default: + throw new Error('Page type is not provided or unknown'); + } + + return { + app: 'ml', + path, + state: {}, + }; + }; +} From da33e694cb2ea6cbaaa786e7f60c1203c7e4e09b Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 12:00:35 +0200 Subject: [PATCH 04/23] =?UTF-8?q?test:=20=F0=9F=92=8D=20add=20locator=20te?= =?UTF-8?q?sts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ml/public/locator/ml_locator.test.ts | 336 ++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 x-pack/plugins/ml/public/locator/ml_locator.test.ts diff --git a/x-pack/plugins/ml/public/locator/ml_locator.test.ts b/x-pack/plugins/ml/public/locator/ml_locator.test.ts new file mode 100644 index 00000000000000..b0c3f051915551 --- /dev/null +++ b/x-pack/plugins/ml/public/locator/ml_locator.test.ts @@ -0,0 +1,336 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MlLocatorDefinition } from './ml_locator'; +import { ML_PAGES } from '../../common/constants/ml_url_generator'; +import { ANALYSIS_CONFIG_TYPE } from '../../common/constants/data_frame_analytics'; + +describe('MlUrlGenerator', () => { + const definition = new MlLocatorDefinition(); + + describe('AnomalyDetection', () => { + it('should throw an error in case the page is not provided', async () => { + expect.assertions(1); + + await definition.getLocation({ jobIds: ['test-job'] } as any).catch((e) => { + expect(e.message).toEqual('Page type is not provided or unknown'); + }); + }); + + describe('Job Management Page', () => { + it('should generate valid URL for the Anomaly Detection job management page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: '/jobs', + state: {}, + }); + }); + + it('should generate valid URL for the Anomaly Detection job management page for job', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + pageState: { + jobId: 'fq_single_1', + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: "/jobs?_a=(jobs:(queryText:'id:fq_single_1'))", + state: {}, + }); + }); + + it('should generate valid URL for the Anomaly Detection job management page for groupIds', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + pageState: { + groupIds: ['farequote', 'categorization'], + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: "/jobs?_a=(jobs:(queryText:'groups:(farequote%20or%20categorization)'))", + state: {}, + }); + }); + + it('should generate valid URL for the page for selecting the type of anomaly detection job to create', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, + pageState: { + index: `3da93760-e0af-11ea-9ad3-3bcfc330e42a`, + globalState: { + time: { + from: 'now-30m', + to: 'now', + }, + }, + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + '/jobs/new_job/step/job_type?index=3da93760-e0af-11ea-9ad3-3bcfc330e42a&_g=(time:(from:now-30m,to:now))', + state: {}, + }); + }); + }); + + describe('Anomaly Explorer Page', () => { + it('should generate valid URL for the Anomaly Explorer page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.ANOMALY_EXPLORER, + pageState: { + jobIds: ['fq_single_1'], + mlExplorerSwimlane: { viewByFromPage: 2, viewByPerPage: 20 }, + refreshInterval: { + pause: false, + value: 0, + }, + timeRange: { + from: '2019-02-07T00:00:00.000Z', + to: '2020-08-13T17:15:00.000Z', + mode: 'absolute', + }, + query: { + analyze_wildcard: true, + query: '*', + }, + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + "/explorer?_g=(ml:(jobIds:!(fq_single_1)),refreshInterval:(pause:!f,value:0),time:(from:'2019-02-07T00:00:00.000Z',mode:absolute,to:'2020-08-13T17:15:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:(viewByFromPage:2,viewByPerPage:20),query:(analyze_wildcard:!t,query:'*')))", + state: {}, + }); + }); + + it('should generate valid URL for the Anomaly Explorer page for multiple jobIds', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.ANOMALY_EXPLORER, + pageState: { + jobIds: ['fq_single_1', 'logs_categorization_1'], + timeRange: { + from: '2019-02-07T00:00:00.000Z', + to: '2020-08-13T17:15:00.000Z', + mode: 'absolute', + }, + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + "/explorer?_g=(ml:(jobIds:!(fq_single_1,logs_categorization_1)),time:(from:'2019-02-07T00:00:00.000Z',mode:absolute,to:'2020-08-13T17:15:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))", + state: {}, + }); + }); + }); + + describe('Single Metric Viewer Page', () => { + it('should generate valid URL for the Single Metric Viewer page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.SINGLE_METRIC_VIEWER, + pageState: { + jobIds: ['logs_categorization_1'], + refreshInterval: { + pause: false, + value: 0, + }, + timeRange: { + from: '2020-07-12T00:39:02.912Z', + to: '2020-07-22T15:52:18.613Z', + mode: 'absolute', + }, + query: { + analyze_wildcard: true, + query: '*', + }, + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + "/timeseriesexplorer?_g=(ml:(jobIds:!(logs_categorization_1)),refreshInterval:(pause:!f,value:0),time:(from:'2020-07-12T00:39:02.912Z',mode:absolute,to:'2020-07-22T15:52:18.613Z'))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(),query:(query_string:(analyze_wildcard:!t,query:'*'))))", + state: {}, + }); + }); + + it('should generate valid URL for the Single Metric Viewer page with extra settings', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.SINGLE_METRIC_VIEWER, + pageState: { + jobIds: ['logs_categorization_1'], + detectorIndex: 0, + entities: { mlcategory: '2' }, + refreshInterval: { + pause: false, + value: 0, + }, + timeRange: { + from: '2020-07-12T00:39:02.912Z', + to: '2020-07-22T15:52:18.613Z', + mode: 'absolute', + }, + zoom: { + from: '2020-07-20T23:58:29.367Z', + to: '2020-07-21T11:00:13.173Z', + }, + query: { + analyze_wildcard: true, + query: '*', + }, + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + "/timeseriesexplorer?_g=(ml:(jobIds:!(logs_categorization_1)),refreshInterval:(pause:!f,value:0),time:(from:'2020-07-12T00:39:02.912Z',mode:absolute,to:'2020-07-22T15:52:18.613Z'))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(detectorIndex:0,entities:(mlcategory:'2'),zoom:(from:'2020-07-20T23:58:29.367Z',to:'2020-07-21T11:00:13.173Z')),query:(query_string:(analyze_wildcard:!t,query:'*'))))", + state: {}, + }); + }); + }); + + describe('DataFrameAnalytics', () => { + describe('JobManagement Page', () => { + it('should generate valid URL for the Data Frame Analytics job management page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: '/data_frame_analytics', + state: {}, + }); + }); + + it('should generate valid URL for the Data Frame Analytics job management page with jobId', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE, + pageState: { + jobId: 'grid_regression_1', + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + "/data_frame_analytics?_a=(data_frame_analytics:(queryText:'id:grid_regression_1'))", + state: {}, + }); + }); + + it('should generate valid URL for the Data Frame Analytics job management page with groupIds', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE, + pageState: { + groupIds: ['group_1', 'group_2'], + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + "/data_frame_analytics?_a=(data_frame_analytics:(queryText:'groups:(group_1%20or%20group_2)'))", + state: {}, + }); + }); + }); + + describe('ExplorationPage', () => { + it('should generate valid URL for the Data Frame Analytics exploration page for job', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION, + pageState: { + jobId: 'grid_regression_1', + analysisType: ANALYSIS_CONFIG_TYPE.REGRESSION, + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + '/data_frame_analytics/exploration?_g=(ml:(analysisType:regression,jobId:grid_regression_1))', + state: {}, + }); + }); + }); + }); + + describe('DataVisualizer', () => { + it('should generate valid URL for the Data Visualizer page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_VISUALIZER, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: '/datavisualizer', + state: {}, + }); + }); + + it('should generate valid URL for the File Data Visualizer import page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_VISUALIZER_FILE, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: '/filedatavisualizer', + state: {}, + }); + }); + + it('should generate valid URL for the Index Data Visualizer select index pattern or saved search page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_VISUALIZER_INDEX_SELECT, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: '/datavisualizer_index_select', + state: {}, + }); + }); + + it('should generate valid URL for the Index Data Visualizer Viewer page', async () => { + const location = await definition.getLocation({ + page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, + pageState: { + index: '3da93760-e0af-11ea-9ad3-3bcfc330e42a', + globalState: { + time: { + from: 'now-30m', + to: 'now', + }, + }, + }, + }); + + expect(location).toMatchObject({ + app: 'ml', + path: + '/jobs/new_job/datavisualizer?index=3da93760-e0af-11ea-9ad3-3bcfc330e42a&_g=(time:(from:now-30m,to:now))', + state: {}, + }); + }); + }); + }); +}); From e83a843bde763917a2679824a9de11b2e5fb0b4a Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 14:12:22 +0200 Subject: [PATCH 05/23] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20expose=20ML=20loca?= =?UTF-8?q?tor=20form=20plugin=20contract?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- x-pack/plugins/ml/public/locator/index.ts | 8 ++++++++ x-pack/plugins/ml/public/mocks.ts | 20 ++++++++++++++++++++ x-pack/plugins/ml/public/plugin.ts | 9 +++++++++ 3 files changed, 37 insertions(+) create mode 100644 x-pack/plugins/ml/public/locator/index.ts diff --git a/x-pack/plugins/ml/public/locator/index.ts b/x-pack/plugins/ml/public/locator/index.ts new file mode 100644 index 00000000000000..3e346375235c0e --- /dev/null +++ b/x-pack/plugins/ml/public/locator/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './ml_locator'; diff --git a/x-pack/plugins/ml/public/mocks.ts b/x-pack/plugins/ml/public/mocks.ts index 6b55cb3b6b6502..c3344f4fe3c618 100644 --- a/x-pack/plugins/ml/public/mocks.ts +++ b/x-pack/plugins/ml/public/mocks.ts @@ -9,12 +9,32 @@ import { MlPluginSetup, MlPluginStart } from './plugin'; const createSetupContract = (): jest.Mocked => { return { urlGenerator: createMlUrlGeneratorMock(), + locator: { + getLocation: jest.fn(), + getUrl: jest.fn(), + useUrl: jest.fn(), + navigate: jest.fn(), + extract: jest.fn(), + inject: jest.fn(), + telemetry: jest.fn(), + migrations: {}, + }, }; }; const createStartContract = (): jest.Mocked => { return { urlGenerator: createMlUrlGeneratorMock(), + locator: { + getLocation: jest.fn(), + getUrl: jest.fn(), + useUrl: jest.fn(), + navigate: jest.fn(), + extract: jest.fn(), + inject: jest.fn(), + telemetry: jest.fn(), + migrations: {}, + }, }; }; diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 917619a67fea92..9aace572492b97 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -43,6 +43,7 @@ import { setDependencyCache } from './application/util/dependency_cache'; import { registerFeature } from './register_feature'; // Not importing from `ml_url_generator/index` here to avoid importing unnecessary code import { registerUrlGenerator } from './ml_url_generator/ml_url_generator'; +import { MlLocatorDefinition, MlLocator } from './locator'; import type { MapsStartApi } from '../../maps/public'; import { TriggersAndActionsUIPublicPluginSetup, @@ -84,7 +85,9 @@ export type MlCoreSetup = CoreSetup; export class MlPlugin implements Plugin { private appUpdater$ = new BehaviorSubject(() => ({})); + private urlGenerator: undefined | UrlGeneratorContract; + private locator: undefined | MlLocator; constructor(private initializerContext: PluginInitializerContext) {} @@ -131,6 +134,10 @@ export class MlPlugin implements Plugin { this.urlGenerator = registerUrlGenerator(pluginsSetup.share, core); } + if (pluginsSetup.share) { + this.locator = pluginsSetup.share.url.locators.create(new MlLocatorDefinition()); + } + if (pluginsSetup.management) { registerManagementSection(pluginsSetup.management, core).enable(); } @@ -180,6 +187,7 @@ export class MlPlugin implements Plugin { return { urlGenerator: this.urlGenerator, + locator: this.locator, }; } @@ -193,6 +201,7 @@ export class MlPlugin implements Plugin { return { urlGenerator: this.urlGenerator, + locator: this.locator, }; } From 0ab2ea293ec3905516446e37e53256c751376693 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 14:16:05 +0200 Subject: [PATCH 06/23] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20deprecate=20ml=20u?= =?UTF-8?q?rl=20generator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- x-pack/plugins/ml/public/plugin.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 9aace572492b97..920d6e8b66633a 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -86,6 +86,9 @@ export type MlCoreSetup = CoreSetup; export class MlPlugin implements Plugin { private appUpdater$ = new BehaviorSubject(() => ({})); + /** + * @deprecated Use locator instead. + */ private urlGenerator: undefined | UrlGeneratorContract; private locator: undefined | MlLocator; @@ -186,6 +189,9 @@ export class MlPlugin implements Plugin { }); return { + /** + * @deprecated Use locator instead. + */ urlGenerator: this.urlGenerator, locator: this.locator, }; @@ -200,6 +206,9 @@ export class MlPlugin implements Plugin { }); return { + /** + * @deprecated Use locator instead. + */ urlGenerator: this.urlGenerator, locator: this.locator, }; From 41c56aac92ef799c7974484d561b6d331cccc690 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 14:58:52 +0200 Subject: [PATCH 07/23] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20use=20locator=20in?= =?UTF-8?q?=20useMlHref()=20React=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- x-pack/plugins/ml/common/types/locator.ts | 11 +++++++ .../ml/public/ml_url_generator/use_ml_href.ts | 31 +++++-------------- 2 files changed, 18 insertions(+), 24 deletions(-) create mode 100644 x-pack/plugins/ml/common/types/locator.ts diff --git a/x-pack/plugins/ml/common/types/locator.ts b/x-pack/plugins/ml/common/types/locator.ts new file mode 100644 index 00000000000000..d3324627802b20 --- /dev/null +++ b/x-pack/plugins/ml/common/types/locator.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SerializableState } from 'src/plugins/kibana_utils/common'; +import type { MlUrlGeneratorState } from './ml_url_generator'; + +export type MlLocatorParams = MlUrlGeneratorState & SerializableState; diff --git a/x-pack/plugins/ml/public/ml_url_generator/use_ml_href.ts b/x-pack/plugins/ml/public/ml_url_generator/use_ml_href.ts index fd69da67378cab..fab668b9464d83 100644 --- a/x-pack/plugins/ml/public/ml_url_generator/use_ml_href.ts +++ b/x-pack/plugins/ml/public/ml_url_generator/use_ml_href.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { useEffect, useState } from 'react'; import { MlPluginStart } from '../index'; -import { MlUrlGeneratorState } from '../../common/types/ml_url_generator'; +import { MlLocatorParams } from '../../common/types/locator'; /** * Provides a URL to ML plugin page @@ -16,27 +15,11 @@ import { MlUrlGeneratorState } from '../../common/types/ml_url_generator'; export const useMlHref = ( ml: MlPluginStart | undefined, basePath: string | undefined, - params: MlUrlGeneratorState + params: MlLocatorParams ) => { - const [mlLink, setMlLink] = useState( - basePath !== undefined ? `${basePath}/app/ml/${params.page}` : undefined - ); - - useEffect(() => { - let isCancelled = false; - const generateLink = async () => { - if (ml?.urlGenerator !== undefined) { - const href = await ml.urlGenerator.createUrl(params); - if (!isCancelled) { - setMlLink(href); - } - } - }; - generateLink(); - return () => { - isCancelled = true; - }; - }, [ml?.urlGenerator, params]); - - return mlLink; + return ml && ml.locator + ? ml.locator!.useUrl(params) + : basePath !== undefined + ? `${basePath}/app/ml/${params.page}` + : ''; }; From d4c9ac61c2370304fd2adcbd6a1699de2fb3df40 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 14:59:35 +0200 Subject: [PATCH 08/23] =?UTF-8?q?fix:=20=F0=9F=90=9B=20remove=20non-existi?= =?UTF-8?q?ng=20property?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/ml/public/ml_url_generator/ml_url_generator.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts index 00db93a7650d10..f7848e2eb8c4f2 100644 --- a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts +++ b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts @@ -12,7 +12,6 @@ import { ANALYSIS_CONFIG_TYPE } from '../../common/constants/data_frame_analytic describe('MlUrlGenerator', () => { const urlGenerator = new MlUrlGenerator({ appBasePath: '/app/ml', - useHash: false, }); describe('AnomalyDetection', () => { From e4f5ac9d008c43a1356ae366e1fbdc859be162c5 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 15:08:56 +0200 Subject: [PATCH 09/23] =?UTF-8?q?fix:=20=F0=9F=90=9B=20remove=20unused=20p?= =?UTF-8?q?arameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apm/public/context/apm_plugin/mock_apm_plugin_context.tsx | 1 - .../common/components/ml/links/create_explorer_link.test.tsx | 2 +- .../public/common/lib/kibana/kibana_react.mock.ts | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx b/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx index bcc1932dde7cbd..9a33260c7923a0 100644 --- a/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx +++ b/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx @@ -90,7 +90,6 @@ const mockPlugin = { ml: { urlGenerator: new MlUrlGenerator({ appBasePath: '/app/ml', - useHash: false, }), }, data: { diff --git a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx index 42d209f7eef39e..efd27865f7a832 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx @@ -21,7 +21,7 @@ describe('create_explorer_link', () => { }); test('it returns expected link', async () => { - const ml = { urlGenerator: new MlUrlGenerator({ appBasePath: '/app/ml', useHash: false }) }; + const ml = { urlGenerator: new MlUrlGenerator({ appBasePath: '/app/ml' }) }; const http = { basePath: { get: jest.fn(() => {}) } }; await act(async () => { diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index b7283eadd722d2..e6551947a735e4 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -141,7 +141,6 @@ export const createStartServicesMock = (): StartServices => { ml: { urlGenerator: new MlUrlGenerator({ appBasePath: '/app/ml', - useHash: false, }), }, } as unknown) as StartServices; From 302d91f9629d6a08d24a3bcb0ba9ca3ce871b100 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 15:47:45 +0200 Subject: [PATCH 10/23] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20replace=20url=20ge?= =?UTF-8?q?nerator=20by=20locator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../log_analysis_setup/setup_flyout/module_list_card.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx index ec360560f8c1df..5931e1cbe49ee7 100644 --- a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx @@ -39,7 +39,7 @@ export const LogAnalysisModuleListCard: React.FC<{ const [viewInMlLink, setViewInMlLink] = useState(''); const getMlUrl = async () => { - if (!ml.urlGenerator) { + if (!ml.locator) { toasts.addWarning({ title: mountReactNode( { From cf6f144642ea95f8aa5769f957c83511e693b1df Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 21:07:57 +0200 Subject: [PATCH 11/23] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20remove=20ML=20?= =?UTF-8?q?url=20generator=20and=20replace=20by=20locator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apm_plugin/mock_apm_plugin_context.tsx | 15 +- .../{ml_url_generator.ts => locator.ts} | 2 +- x-pack/plugins/ml/common/types/common.ts | 2 +- x-pack/plugins/ml/common/types/locator.ts | 249 +++++++++++++++- .../ml/common/types/ml_url_generator.ts | 252 ---------------- .../ml/public/alerting/register_ml_alerts.ts | 4 +- x-pack/plugins/ml/public/application/app.tsx | 10 +- .../annotations_table/annotations_table.js | 11 +- .../components/anomalies_table/links_menu.js | 12 +- .../anomaly_results_view_selector.tsx | 8 +- .../job_selector_table/job_selector_table.js | 2 +- .../components/navigation_menu/main_tabs.tsx | 14 +- .../components/rule_editor/scope_section.js | 2 +- .../application/contexts/kibana/index.ts | 2 +- .../contexts/kibana/use_create_url.ts | 38 ++- .../back_to_list_panel/back_to_list_panel.tsx | 2 +- .../view_results_panel/view_results_panel.tsx | 2 +- .../expandable_section/expandable_section.tsx | 2 +- .../hooks/use_exploration_url_state.ts | 4 +- .../components/action_map/use_map_action.tsx | 8 +- .../action_view/use_view_action.tsx | 8 +- .../components/analytics_list/use_columns.tsx | 2 +- .../models_management/models_list.tsx | 11 +- .../pages/analytics_management/page.tsx | 2 +- .../pages/job_map/components/controls.tsx | 12 +- .../pages/job_map/job_map.tsx | 8 +- .../explorer_no_jobs_found.js | 2 +- .../public/application/explorer/explorer.js | 12 +- .../explorer_anomalies_container.tsx | 8 +- .../explorer_charts_container.js | 14 +- .../explorer/explorer_dashboard_service.ts | 2 +- .../explorer/hooks/use_explorer_url_state.ts | 4 +- .../explorer/hooks/use_selected_cells.test.ts | 2 +- .../explorer/hooks/use_selected_cells.ts | 2 +- .../forecasts_table/forecasts_table.js | 5 +- .../components/jobs_list/job_id_link.tsx | 25 +- .../new_job_button/new_job_button.js | 2 +- .../application/jobs/jobs_list/jobs.tsx | 2 +- .../calendars/calendars_selection.tsx | 2 +- .../jobs/new_job/pages/job_type/page.tsx | 2 +- .../jobs/new_job/recognize/page.tsx | 30 +- .../components/analytics_panel/actions.tsx | 2 +- .../analytics_panel/analytics_panel.tsx | 9 +- .../anomaly_detection_panel.tsx | 12 +- .../analytics_job_exploration.tsx | 9 +- .../routes/datavisualizer/index_based.tsx | 2 +- .../routes/new_job/index_or_search.tsx | 2 +- .../routing/routes/new_job/wizard.tsx | 2 +- .../routes/settings/calendar_new_edit.tsx | 2 +- .../routes/settings/filter_list_new_edit.tsx | 2 +- .../routing/routes/timeseriesexplorer.tsx | 2 +- .../application/routing/use_resolver.ts | 2 +- .../settings/anomaly_detection_settings.tsx | 2 +- .../edit/calendar_form/calendar_form.js | 2 +- .../settings/calendars/edit/new_calendar.js | 2 +- .../settings/calendars/list/table/table.js | 2 +- .../filter_lists/edit/edit_filter_list.js | 2 +- .../settings/filter_lists/list/table.js | 2 +- .../timeseriesexplorer_no_jobs_found.tsx | 9 +- .../hooks/use_timeseriesexplorer_url_state.ts | 4 +- .../ml/public/application/util/chart_utils.js | 6 +- .../ml/public/application/util/url_state.tsx | 2 +- .../embeddable_anomaly_charts_container.tsx | 18 +- x-pack/plugins/ml/public/index.ts | 2 +- .../locator/formatters/anomaly_detection.ts | 4 +- .../ml/public/locator/formatters/common.ts | 2 +- .../formatters/data_frame_analytics.ts | 4 +- .../ml/public/locator/formatters/settings.tsx | 4 +- x-pack/plugins/ml/public/locator/index.ts | 2 + .../ml/public/locator/ml_locator.test.ts | 2 +- .../plugins/ml/public/locator/ml_locator.ts | 22 +- .../use_ml_href.ts | 0 .../__mocks__/ml_url_generator.ts | 17 -- .../anomaly_detection_urls_generator.ts | 222 --------------- .../ml/public/ml_url_generator/common.ts | 59 ---- .../data_frame_analytics_urls_generator.ts | 171 ----------- .../ml/public/ml_url_generator/index.ts | 10 - .../ml_url_generator/ml_url_generator.test.ts | 268 ------------------ .../ml_url_generator/ml_url_generator.ts | 127 --------- .../settings_urls_generator.tsx | 46 --- x-pack/plugins/ml/public/mocks.ts | 4 +- x-pack/plugins/ml/public/plugin.ts | 25 +- .../search_deep_links.ts | 2 +- .../open_in_anomaly_explorer_action.tsx | 10 +- .../ml/links/create_explorer_link.test.tsx | 12 +- .../common/lib/kibana/kibana_react.mock.ts | 14 +- 86 files changed, 482 insertions(+), 1442 deletions(-) rename x-pack/plugins/ml/common/constants/{ml_url_generator.ts => locator.ts} (97%) delete mode 100644 x-pack/plugins/ml/common/types/ml_url_generator.ts rename x-pack/plugins/ml/public/{ml_url_generator => locator}/use_ml_href.ts (100%) delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/anomaly_detection_urls_generator.ts delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/common.ts delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/data_frame_analytics_urls_generator.ts delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/index.ts delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts delete mode 100644 x-pack/plugins/ml/public/ml_url_generator/settings_urls_generator.tsx diff --git a/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx b/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx index 9a33260c7923a0..a356f2962b3c6d 100644 --- a/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx +++ b/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx @@ -7,12 +7,13 @@ import React, { ReactNode } from 'react'; import { Observable, of } from 'rxjs'; +import { UrlService } from '../../../../../../src/plugins/share/common/url_service'; import { createObservabilityRuleTypeRegistryMock } from '../../../../observability/public'; import { ApmPluginContext, ApmPluginContextValue } from './apm_plugin_context'; import { ConfigSchema } from '../..'; import { UI_SETTINGS } from '../../../../../../src/plugins/data/common'; import { createCallApmApi } from '../../services/rest/createCallApmApi'; -import { MlUrlGenerator } from '../../../../ml/public'; +import { MlLocatorDefinition } from '../../../../ml/public'; const uiSettings: Record = { [UI_SETTINGS.TIMEPICKER_QUICK_RANGES]: [ @@ -86,11 +87,17 @@ const mockConfig: ConfigSchema = { profilingEnabled: false, }; +const urlService = new UrlService({ + navigate: async () => {}, + getUrl: async ({ app, path }, { absolute }) => { + return `${absolute ? 'http://localhost:8888' : ''}/app/${app}${path}`; + }, +}); +const locator = urlService.locators.create(new MlLocatorDefinition()); + const mockPlugin = { ml: { - urlGenerator: new MlUrlGenerator({ - appBasePath: '/app/ml', - }), + locator, }, data: { query: { diff --git a/x-pack/plugins/ml/common/constants/ml_url_generator.ts b/x-pack/plugins/ml/common/constants/locator.ts similarity index 97% rename from x-pack/plugins/ml/common/constants/ml_url_generator.ts rename to x-pack/plugins/ml/common/constants/locator.ts index bb0684309201cf..2949cdde1d47bd 100644 --- a/x-pack/plugins/ml/common/constants/ml_url_generator.ts +++ b/x-pack/plugins/ml/common/constants/locator.ts @@ -5,7 +5,7 @@ * 2.0. */ -export const ML_APP_URL_GENERATOR = 'ML_APP_URL_GENERATOR'; +export const ML_APP_LOCATOR = 'ML_APP_LOCATOR'; export const ML_PAGES = { ANOMALY_DETECTION_JOBS_MANAGE: 'jobs', diff --git a/x-pack/plugins/ml/common/types/common.ts b/x-pack/plugins/ml/common/types/common.ts index fdeffe14ddaf71..6a4bbc303ae58b 100644 --- a/x-pack/plugins/ml/common/types/common.ts +++ b/x-pack/plugins/ml/common/types/common.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { MlPages } from '../constants/ml_url_generator'; +import { MlPages } from '../constants/locator'; export interface Dictionary { [id: string]: TValue; diff --git a/x-pack/plugins/ml/common/types/locator.ts b/x-pack/plugins/ml/common/types/locator.ts index d3324627802b20..780787da53fca4 100644 --- a/x-pack/plugins/ml/common/types/locator.ts +++ b/x-pack/plugins/ml/common/types/locator.ts @@ -6,6 +6,253 @@ */ import type { SerializableState } from 'src/plugins/kibana_utils/common'; -import type { MlUrlGeneratorState } from './ml_url_generator'; +import type { LocatorPublic } from 'src/plugins/share/public'; +import type { RefreshInterval, TimeRange } from '../../../../../src/plugins/data/common/query'; +import type { JobId } from './anomaly_detection_jobs/job'; +import type { DataFrameAnalysisConfigType } from './data_frame_analytics'; +import type { SearchQueryLanguage } from '../constants/search'; +import type { ListingPageUrlState } from './common'; +import type { InfluencersFilterQuery } from './es_client'; +import { ML_PAGES } from '../constants/locator'; + +type OptionalPageState = object | undefined; + +export type MLPageState = PageState extends OptionalPageState + ? { page: PageType; pageState?: PageState; excludeBasePath?: boolean } + : PageState extends object + ? { page: PageType; pageState: PageState; excludeBasePath?: boolean } + : { page: PageType; excludeBasePath?: boolean }; + +export interface MlCommonGlobalState { + time?: TimeRange; + refreshInterval?: RefreshInterval; +} +export interface MlCommonAppState { + [key: string]: any; +} + +export interface MlIndexBasedSearchState { + index?: string; + savedSearchId?: string; +} + +export interface MlGenericUrlPageState extends MlIndexBasedSearchState { + globalState?: MlCommonGlobalState; + appState?: MlCommonAppState; + [key: string]: any; +} + +export type MlGenericUrlState = MLPageState< + | typeof ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER + | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB + | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED + | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE + | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX + | typeof ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB + | typeof ML_PAGES.OVERVIEW + | typeof ML_PAGES.CALENDARS_MANAGE + | typeof ML_PAGES.CALENDARS_NEW + | typeof ML_PAGES.FILTER_LISTS_MANAGE + | typeof ML_PAGES.FILTER_LISTS_NEW + | typeof ML_PAGES.SETTINGS + | typeof ML_PAGES.ACCESS_DENIED + | typeof ML_PAGES.DATA_VISUALIZER + | typeof ML_PAGES.DATA_VISUALIZER_FILE + | typeof ML_PAGES.DATA_VISUALIZER_INDEX_SELECT, + MlGenericUrlPageState | undefined +>; + +export interface AnomalyDetectionQueryState { + jobId?: JobId | string[]; + groupIds?: string[]; + globalState?: MlCommonGlobalState; +} + +export type AnomalyDetectionUrlState = MLPageState< + typeof ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + AnomalyDetectionQueryState | undefined +>; +export interface ExplorerAppState { + mlExplorerSwimlane: { + selectedType?: 'overall' | 'viewBy'; + selectedLanes?: string[]; + /** + * @deprecated legacy query param variable, use `selectedLanes` + */ + selectedLane?: string[] | string; + /** + * It's possible to have only "from" time boundaries, e.g. in the Watcher URL + */ + selectedTimes?: [number, number] | number; + /** + * @deprecated legacy query param variable, use `selectedTimes` + */ + selectedTime?: [number, number] | number; + showTopFieldValues?: boolean; + viewByFieldName?: string; + viewByPerPage?: number; + viewByFromPage?: number; + /** + * Indicated severity threshold for both swim lanes + */ + severity?: number; + }; + mlExplorerFilter: { + influencersFilterQuery?: InfluencersFilterQuery; + filterActive?: boolean; + filteredFields?: Array; + queryString?: string; + }; + query?: any; + mlShowCharts?: boolean; +} +export interface ExplorerGlobalState { + ml: { jobIds: JobId[] }; + time?: TimeRange; + refreshInterval?: RefreshInterval; +} + +export interface ExplorerUrlPageState { + /** + * Job IDs + */ + jobIds?: JobId[]; + /** + * Optionally set the time range in the time picker. + */ + timeRange?: TimeRange; + /** + * Optionally set the refresh interval. + */ + refreshInterval?: RefreshInterval; + /** + * Optionally set the query. + */ + query?: any; + /** + * Optional state for the swim lane + */ + mlExplorerSwimlane?: ExplorerAppState['mlExplorerSwimlane']; + mlExplorerFilter?: ExplorerAppState['mlExplorerFilter']; + globalState?: MlCommonGlobalState; +} + +export type ExplorerUrlState = MLPageState; + +export interface TimeSeriesExplorerGlobalState { + ml: { + jobIds: JobId[]; + }; + time?: TimeRange; + refreshInterval?: RefreshInterval; +} + +export interface TimeSeriesExplorerParams { + forecastId?: string; + detectorIndex?: number; + entities?: Record; + zoom?: { + from?: string; + to?: string; + }; + functionDescription?: string; +} +export interface TimeSeriesExplorerAppState { + mlTimeSeriesExplorer?: TimeSeriesExplorerParams; + query?: any; +} + +export interface TimeSeriesExplorerPageState + extends TimeSeriesExplorerParams, + Pick, + Pick { + jobIds?: JobId[]; + timeRange?: TimeRange; + globalState?: MlCommonGlobalState; +} + +export type TimeSeriesExplorerUrlState = MLPageState< + typeof ML_PAGES.SINGLE_METRIC_VIEWER, + TimeSeriesExplorerPageState +>; + +export interface DataFrameAnalyticsQueryState { + analysisType?: DataFrameAnalysisConfigType; + jobId?: JobId | JobId[]; + modelId?: string; + groupIds?: string[]; + globalState?: MlCommonGlobalState; +} + +export type DataFrameAnalyticsUrlState = MLPageState< + | typeof ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE + | typeof ML_PAGES.DATA_FRAME_ANALYTICS_MAP + | typeof ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, + DataFrameAnalyticsQueryState | undefined +>; + +export interface DataFrameAnalyticsExplorationQueryState { + ml: { + jobId: JobId; + analysisType: DataFrameAnalysisConfigType; + defaultIsTraining?: boolean; + modelId?: string; + }; +} + +export type DataFrameAnalyticsExplorationUrlState = MLPageState< + typeof ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION, + { + jobId: JobId; + analysisType: DataFrameAnalysisConfigType; + globalState?: MlCommonGlobalState; + queryText?: string; + modelId?: string; + } +>; + +export type CalendarEditUrlState = MLPageState< + typeof ML_PAGES.CALENDARS_EDIT, + { + calendarId: string; + globalState?: MlCommonGlobalState; + } +>; + +export type FilterEditUrlState = MLPageState< + typeof ML_PAGES.FILTER_LISTS_EDIT, + { + filterId: string; + globalState?: MlCommonGlobalState; + } +>; + +export type ExpandablePanels = + | 'analysis' + | 'evaluation' + | 'feature_importance' + | 'results' + | 'splom'; + +export type ExplorationPageUrlState = { + queryText: string; + queryLanguage: SearchQueryLanguage; +} & Pick & + { [key in ExpandablePanels]: boolean }; + +/** + * Union type of ML URL state based on page + */ +export type MlUrlGeneratorState = + | AnomalyDetectionUrlState + | ExplorerUrlState + | TimeSeriesExplorerUrlState + | DataFrameAnalyticsUrlState + | DataFrameAnalyticsExplorationUrlState + | CalendarEditUrlState + | FilterEditUrlState + | MlGenericUrlState; export type MlLocatorParams = MlUrlGeneratorState & SerializableState; + +export type MlLocator = LocatorPublic; diff --git a/x-pack/plugins/ml/common/types/ml_url_generator.ts b/x-pack/plugins/ml/common/types/ml_url_generator.ts deleted file mode 100644 index 9c7145c848264f..00000000000000 --- a/x-pack/plugins/ml/common/types/ml_url_generator.ts +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { RefreshInterval, TimeRange } from '../../../../../src/plugins/data/common/query'; -import type { JobId } from './anomaly_detection_jobs/job'; -import { ML_PAGES } from '../constants/ml_url_generator'; -import type { DataFrameAnalysisConfigType } from './data_frame_analytics'; -import type { SearchQueryLanguage } from '../constants/search'; -import type { ListingPageUrlState } from './common'; -import type { InfluencersFilterQuery } from './es_client'; - -type OptionalPageState = object | undefined; - -export type MLPageState = PageState extends OptionalPageState - ? { page: PageType; pageState?: PageState; excludeBasePath?: boolean } - : PageState extends object - ? { page: PageType; pageState: PageState; excludeBasePath?: boolean } - : { page: PageType; excludeBasePath?: boolean }; - -export interface MlCommonGlobalState { - time?: TimeRange; - refreshInterval?: RefreshInterval; -} -export interface MlCommonAppState { - [key: string]: any; -} - -export interface MlIndexBasedSearchState { - index?: string; - savedSearchId?: string; -} - -export interface MlGenericUrlPageState extends MlIndexBasedSearchState { - globalState?: MlCommonGlobalState; - appState?: MlCommonAppState; - [key: string]: any; -} - -export type MlGenericUrlState = MLPageState< - | typeof ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER - | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB - | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED - | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE - | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX - | typeof ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB - | typeof ML_PAGES.OVERVIEW - | typeof ML_PAGES.CALENDARS_MANAGE - | typeof ML_PAGES.CALENDARS_NEW - | typeof ML_PAGES.FILTER_LISTS_MANAGE - | typeof ML_PAGES.FILTER_LISTS_NEW - | typeof ML_PAGES.SETTINGS - | typeof ML_PAGES.ACCESS_DENIED - | typeof ML_PAGES.DATA_VISUALIZER - | typeof ML_PAGES.DATA_VISUALIZER_FILE - | typeof ML_PAGES.DATA_VISUALIZER_INDEX_SELECT, - MlGenericUrlPageState | undefined ->; - -export interface AnomalyDetectionQueryState { - jobId?: JobId | string[]; - groupIds?: string[]; - globalState?: MlCommonGlobalState; -} - -export type AnomalyDetectionUrlState = MLPageState< - typeof ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - AnomalyDetectionQueryState | undefined ->; -export interface ExplorerAppState { - mlExplorerSwimlane: { - selectedType?: 'overall' | 'viewBy'; - selectedLanes?: string[]; - /** - * @deprecated legacy query param variable, use `selectedLanes` - */ - selectedLane?: string[] | string; - /** - * It's possible to have only "from" time boundaries, e.g. in the Watcher URL - */ - selectedTimes?: [number, number] | number; - /** - * @deprecated legacy query param variable, use `selectedTimes` - */ - selectedTime?: [number, number] | number; - showTopFieldValues?: boolean; - viewByFieldName?: string; - viewByPerPage?: number; - viewByFromPage?: number; - /** - * Indicated severity threshold for both swim lanes - */ - severity?: number; - }; - mlExplorerFilter: { - influencersFilterQuery?: InfluencersFilterQuery; - filterActive?: boolean; - filteredFields?: Array; - queryString?: string; - }; - query?: any; - mlShowCharts?: boolean; -} -export interface ExplorerGlobalState { - ml: { jobIds: JobId[] }; - time?: TimeRange; - refreshInterval?: RefreshInterval; -} - -export interface ExplorerUrlPageState { - /** - * Job IDs - */ - jobIds?: JobId[]; - /** - * Optionally set the time range in the time picker. - */ - timeRange?: TimeRange; - /** - * Optionally set the refresh interval. - */ - refreshInterval?: RefreshInterval; - /** - * Optionally set the query. - */ - query?: any; - /** - * Optional state for the swim lane - */ - mlExplorerSwimlane?: ExplorerAppState['mlExplorerSwimlane']; - mlExplorerFilter?: ExplorerAppState['mlExplorerFilter']; - globalState?: MlCommonGlobalState; -} - -export type ExplorerUrlState = MLPageState; - -export interface TimeSeriesExplorerGlobalState { - ml: { - jobIds: JobId[]; - }; - time?: TimeRange; - refreshInterval?: RefreshInterval; -} - -export interface TimeSeriesExplorerParams { - forecastId?: string; - detectorIndex?: number; - entities?: Record; - zoom?: { - from?: string; - to?: string; - }; - functionDescription?: string; -} -export interface TimeSeriesExplorerAppState { - mlTimeSeriesExplorer?: TimeSeriesExplorerParams; - query?: any; -} - -export interface TimeSeriesExplorerPageState - extends TimeSeriesExplorerParams, - Pick, - Pick { - jobIds?: JobId[]; - timeRange?: TimeRange; - globalState?: MlCommonGlobalState; -} - -export type TimeSeriesExplorerUrlState = MLPageState< - typeof ML_PAGES.SINGLE_METRIC_VIEWER, - TimeSeriesExplorerPageState ->; - -export interface DataFrameAnalyticsQueryState { - analysisType?: DataFrameAnalysisConfigType; - jobId?: JobId | JobId[]; - modelId?: string; - groupIds?: string[]; - globalState?: MlCommonGlobalState; -} - -export type DataFrameAnalyticsUrlState = MLPageState< - | typeof ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE - | typeof ML_PAGES.DATA_FRAME_ANALYTICS_MAP - | typeof ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, - DataFrameAnalyticsQueryState | undefined ->; - -export interface DataFrameAnalyticsExplorationQueryState { - ml: { - jobId: JobId; - analysisType: DataFrameAnalysisConfigType; - defaultIsTraining?: boolean; - modelId?: string; - }; -} - -export type DataFrameAnalyticsExplorationUrlState = MLPageState< - typeof ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION, - { - jobId: JobId; - analysisType: DataFrameAnalysisConfigType; - globalState?: MlCommonGlobalState; - queryText?: string; - modelId?: string; - } ->; - -export type CalendarEditUrlState = MLPageState< - typeof ML_PAGES.CALENDARS_EDIT, - { - calendarId: string; - globalState?: MlCommonGlobalState; - } ->; - -export type FilterEditUrlState = MLPageState< - typeof ML_PAGES.FILTER_LISTS_EDIT, - { - filterId: string; - globalState?: MlCommonGlobalState; - } ->; - -export type ExpandablePanels = - | 'analysis' - | 'evaluation' - | 'feature_importance' - | 'results' - | 'splom'; - -export type ExplorationPageUrlState = { - queryText: string; - queryLanguage: SearchQueryLanguage; -} & Pick & - { [key in ExpandablePanels]: boolean }; - -/** - * Union type of ML URL state based on page - */ -export type MlUrlGeneratorState = - | AnomalyDetectionUrlState - | ExplorerUrlState - | TimeSeriesExplorerUrlState - | DataFrameAnalyticsUrlState - | DataFrameAnalyticsExplorationUrlState - | CalendarEditUrlState - | FilterEditUrlState - | MlGenericUrlState; diff --git a/x-pack/plugins/ml/public/alerting/register_ml_alerts.ts b/x-pack/plugins/ml/public/alerting/register_ml_alerts.ts index 5454f4da319222..b1640ab7aba7d9 100644 --- a/x-pack/plugins/ml/public/alerting/register_ml_alerts.ts +++ b/x-pack/plugins/ml/public/alerting/register_ml_alerts.ts @@ -12,7 +12,7 @@ import type { MlAnomalyDetectionAlertParams } from '../../common/types/alerts'; import type { TriggersAndActionsUIPublicPluginSetup } from '../../../triggers_actions_ui/public'; import type { PluginSetupContract as AlertingSetup } from '../../../alerting/public'; import { PLUGIN_ID } from '../../common/constants/app'; -import { createExplorerUrl } from '../ml_url_generator/anomaly_detection_urls_generator'; +import { formatExplorerUrl } from '../locator/formatters/anomaly_detection'; import { validateLookbackInterval, validateTopNBucket } from './validators'; export function registerMlAlerts( @@ -152,6 +152,6 @@ export function registerNavigation(alerting: AlertingSetup) { ]), ]; - return createExplorerUrl('', { jobIds }); + return formatExplorerUrl('', { jobIds }); }); } diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 222d23acb40a74..fd1703e907ee19 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -24,7 +24,7 @@ import { MlSetupDependencies, MlStartDependencies } from '../plugin'; import { MlRouter } from './routing'; import { mlApiServicesProvider } from './services/ml_api_service'; import { HttpService } from './services/http_service'; -import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../common/constants/ml_url_generator'; +import { ML_APP_LOCATOR, ML_PAGES } from '../../common/constants/locator'; export type MlDependencies = Omit & MlStartDependencies; @@ -55,11 +55,9 @@ export type MlGlobalServices = ReturnType; const App: FC = ({ coreStart, deps, appMountParams }) => { const redirectToMlAccessDeniedPage = async () => { - const accessDeniedPageUrl = await deps.share.urlGenerators - .getUrlGenerator(ML_APP_URL_GENERATOR) - .createUrl({ - page: ML_PAGES.ACCESS_DENIED, - }); + const accessDeniedPageUrl = await deps.share.url.locators.get(ML_APP_LOCATOR)!.getUrl({ + page: ML_PAGES.ACCESS_DENIED, + }); await coreStart.application.navigateToUrl(accessDeniedPageUrl); }; diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js index 20d3f8e03ddbc9..9dcd1a1a9e6833 100644 --- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js +++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js @@ -47,7 +47,7 @@ import { ANNOTATION_EVENT_DELAYED_DATA, } from '../../../../../common/constants/annotations'; import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public'; -import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_APP_LOCATOR, ML_PAGES } from '../../../../../common/constants/locator'; import { PLUGIN_ID } from '../../../../../common/constants/app'; import { timeFormatter } from '../../../../../common/util/date_utils'; import { MlAnnotationUpdatesContext } from '../../../contexts/ml/ml_annotation_updates_context'; @@ -203,10 +203,7 @@ class AnnotationsTableUI extends Component { const { services: { application: { navigateToApp }, - - share: { - urlGenerators: { getUrlGenerator }, - }, + share, }, } = this.props.kibana; @@ -266,8 +263,8 @@ class AnnotationsTableUI extends Component { mlTimeSeriesExplorer.entities = entityCondition; // appState.mlTimeSeriesExplorer = mlTimeSeriesExplorer; - const mlUrlGenerator = getUrlGenerator(ML_APP_URL_GENERATOR); - const singleMetricViewerLink = await mlUrlGenerator.createUrl({ + const mlLocator = share.url.locators.get(ML_APP_LOCATOR); + const singleMetricViewerLink = await mlLocator.getUrl({ page: ML_PAGES.SINGLE_METRIC_VIEWER, pageState: { timeRange, diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js index 262daae9d6469c..26c91a2ebec324 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js @@ -30,7 +30,7 @@ import { getUrlForRecord, openCustomUrlWindow } from '../../util/custom_url_util import { formatHumanReadableDateTimeSeconds } from '../../../../common/util/date_utils'; import { getIndexPatternIdFromName } from '../../util/index_utils'; import { replaceStringTokens } from '../../util/string_utils'; -import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { ML_APP_LOCATOR, ML_PAGES } from '../../../../common/constants/locator'; /* * Component for rendering the links menu inside a cell in the anomalies table. */ @@ -146,13 +146,9 @@ class LinksMenuUI extends Component { viewSeries = async () => { const { - services: { - share: { - urlGenerators: { getUrlGenerator }, - }, - }, + services: { share }, } = this.props.kibana; - const mlUrlGenerator = getUrlGenerator(ML_APP_URL_GENERATOR); + const mlLocator = share.url.locators.get(ML_APP_LOCATOR); const record = this.props.anomaly.source; const bounds = this.props.bounds; @@ -182,7 +178,7 @@ class LinksMenuUI extends Component { entityCondition[record.by_field_name] = record.by_field_value; } - const singleMetricViewerLink = await mlUrlGenerator.createUrl({ + const singleMetricViewerLink = await mlLocator.getUrl({ excludeBasePath: false, page: ML_PAGES.SINGLE_METRIC_VIEWER, pageState: { diff --git a/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.tsx b/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.tsx index 1ec43bd8fa1cad..4ad4e09d01e1b4 100644 --- a/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.tsx +++ b/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.tsx @@ -12,8 +12,8 @@ import { EuiButtonGroup } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useUrlState } from '../../util/url_state'; -import { useMlUrlGenerator, useNavigateToPath } from '../../contexts/kibana'; -import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { useMlLocator, useNavigateToPath } from '../../contexts/kibana'; +import { ML_PAGES } from '../../../../common/constants/locator'; interface Props { viewId: typeof ML_PAGES.SINGLE_METRIC_VIEWER | typeof ML_PAGES.ANOMALY_EXPLORER; @@ -22,7 +22,7 @@ interface Props { // Component for rendering a set of buttons for switching between the Anomaly Detection results views. export const AnomalyResultsViewSelector: FC = ({ viewId }) => { - const urlGenerator = useMlUrlGenerator(); + const locator = useMlLocator()!; const navigateToPath = useNavigateToPath(); const toggleButtonsIcons = useMemo( @@ -52,7 +52,7 @@ export const AnomalyResultsViewSelector: FC = ({ viewId }) => { const [globalState] = useUrlState('_g'); const onChangeView = async (newViewId: Props['viewId']) => { - const url = await urlGenerator.createUrl({ + const url = await locator.getUrl({ page: newViewId, pageState: { globalState, diff --git a/x-pack/plugins/ml/public/application/components/job_selector/job_selector_table/job_selector_table.js b/x-pack/plugins/ml/public/application/components/job_selector/job_selector_table/job_selector_table.js index f4795f35269b9e..13bc6214e57999 100644 --- a/x-pack/plugins/ml/public/application/components/job_selector/job_selector_table/job_selector_table.js +++ b/x-pack/plugins/ml/public/application/components/job_selector/job_selector_table/job_selector_table.js @@ -24,7 +24,7 @@ import { import { LEFT_ALIGNMENT, CENTER_ALIGNMENT, SortableProperties } from '@elastic/eui/lib/services'; import { i18n } from '@kbn/i18n'; import { useMlKibana } from '../../../contexts/kibana'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { PLUGIN_ID } from '../../../../../common/constants/app'; const JOB_FILTER_FIELDS = ['job_id', 'groups']; diff --git a/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx b/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx index 0f381fb7acee91..9b8b0cb6bf2948 100644 --- a/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx +++ b/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx @@ -10,8 +10,8 @@ import React, { FC, useState, useEffect } from 'react'; import { EuiTabs, EuiTab } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { TabId } from './navigation_menu'; -import { useMlKibana, useMlUrlGenerator, useNavigateToPath } from '../../contexts/kibana'; -import { MlUrlGeneratorState } from '../../../../common/types/ml_url_generator'; +import { useMlKibana, useMlLocator, useNavigateToPath } from '../../contexts/kibana'; +import { MlLocatorParams } from '../../../../common/types/locator'; import { useUrlState } from '../../util/url_state'; import { ML_APP_NAME } from '../../../../common/constants/app'; @@ -67,7 +67,7 @@ function getTabs(disableLinks: boolean): Tab[] { } interface TabData { testSubject: string; - pathId?: MlUrlGeneratorState['page']; + pathId?: MlLocatorParams['page']; name: string; } @@ -125,10 +125,10 @@ export const MainTabs: FC = ({ tabId, disableLinks }) => { } const tabs = getTabs(disableLinks); - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator(); const navigateToPath = useNavigateToPath(); - const redirectToTab = async (defaultPathId: MlUrlGeneratorState['page']) => { + const redirectToTab = async (defaultPathId: MlLocatorParams['page']) => { const pageState = globalState?.refreshInterval !== undefined ? { @@ -139,7 +139,7 @@ export const MainTabs: FC = ({ tabId, disableLinks }) => { : undefined; // TODO - Fix ts so passing pageState won't default to MlGenericUrlState when pageState is passed in // @ts-ignore - const path = await mlUrlGenerator.createUrl({ + const path = await mlLocator.getUrl({ page: defaultPathId, // only retain the refreshInterval part of globalState // appState will not be considered. @@ -158,7 +158,7 @@ export const MainTabs: FC = ({ tabId, disableLinks }) => { {tabs.map((tab: Tab) => { const { id, disabled } = tab; const testSubject = TAB_DATA[id].testSubject; - const defaultPathId = (TAB_DATA[id].pathId || id) as MlUrlGeneratorState['page']; + const defaultPathId = (TAB_DATA[id].pathId || id) as MlLocatorParams['page']; return disabled ? (
diff --git a/x-pack/plugins/ml/public/application/components/rule_editor/scope_section.js b/x-pack/plugins/ml/public/application/components/rule_editor/scope_section.js index 8f2c126a95117d..99683e90898f1b 100644 --- a/x-pack/plugins/ml/public/application/components/rule_editor/scope_section.js +++ b/x-pack/plugins/ml/public/application/components/rule_editor/scope_section.js @@ -18,7 +18,7 @@ import { ScopeExpression } from './scope_expression'; import { checkPermission } from '../../capabilities/check_capabilities'; import { getScopeFieldDefaults } from './utils'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../common/constants/locator'; import { useMlUrlGenerator, useNavigateToPath } from '../../contexts/kibana'; function NoFilterListsCallOut() { diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/index.ts b/x-pack/plugins/ml/public/application/contexts/kibana/index.ts index 466641775cb570..7331ebe34e915a 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/index.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/index.ts @@ -10,5 +10,5 @@ export { useNavigateToPath, NavigateToPath } from './use_navigate_to_path'; export { useUiSettings } from './use_ui_settings_context'; export { useTimefilter } from './use_timefilter'; export { useNotifications } from './use_notifications_context'; -export { useMlUrlGenerator, useMlLink } from './use_create_url'; +export { useMlLocator, useMlLink } from './use_create_url'; export { useMlApiContext } from './use_ml_api_context'; diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts b/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts index b524e19e722560..c84b9848dfcaeb 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts @@ -7,32 +7,30 @@ import { useCallback, useEffect, useState } from 'react'; import { useMlKibana } from './kibana_context'; -import { ML_APP_URL_GENERATOR } from '../../../../common/constants/ml_url_generator'; -import { MlUrlGeneratorState } from '../../../../common/types/ml_url_generator'; +import { ML_APP_LOCATOR } from '../../../../common/constants/locator'; +import { MlLocatorParams } from '../../../../common/types/locator'; import { useUrlState } from '../../util/url_state'; -export const useMlUrlGenerator = () => { +export const useMlLocator = () => { const { - services: { - share: { - urlGenerators: { getUrlGenerator }, - }, - }, + services: { share }, } = useMlKibana(); - return getUrlGenerator(ML_APP_URL_GENERATOR); + return share.url.locators.get(ML_APP_LOCATOR); }; -export const useMlLink = (params: MlUrlGeneratorState): string => { +export const useMlLink = (params: MlLocatorParams): string => { const [href, setHref] = useState(params.page); - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator(); useEffect(() => { let isCancelled = false; - const generateUrl = async (_params: MlUrlGeneratorState) => { - const url = await mlUrlGenerator.createUrl(_params); - if (!isCancelled) { - setHref(url); + const generateUrl = async (_params: MlLocatorParams) => { + if (mlLocator) { + const url = await mlLocator.getUrl(_params); + if (!isCancelled) { + setHref(url); + } } }; generateUrl(params); @@ -45,9 +43,9 @@ export const useMlLink = (params: MlUrlGeneratorState): string => { }; export const useCreateAndNavigateToMlLink = ( - page: MlUrlGeneratorState['page'] + page: MlLocatorParams['page'] ): (() => Promise) => { - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator(); const [globalState] = useUrlState('_g'); const { @@ -57,7 +55,7 @@ export const useCreateAndNavigateToMlLink = ( } = useMlKibana(); const redirectToMlPage = useCallback( - async (_page: MlUrlGeneratorState['page']) => { + async (_page: MlLocatorParams['page']) => { const pageState = globalState?.refreshInterval !== undefined ? { @@ -69,10 +67,10 @@ export const useCreateAndNavigateToMlLink = ( // TODO: fix ts only interpreting it as MlUrlGenericState if pageState is passed // @ts-ignore - const url = await mlUrlGenerator.createUrl({ page: _page, pageState }); + const url = await mlLocator.getUrl({ page: _page, pageState }); await navigateToUrl(url); }, - [mlUrlGenerator, navigateToUrl] + [mlLocator, navigateToUrl] ); // returns the onClick callback diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/back_to_list_panel/back_to_list_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/back_to_list_panel/back_to_list_panel.tsx index 8b407b3c8a6a52..61e5c6ff602e38 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/back_to_list_panel/back_to_list_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/back_to_list_panel/back_to_list_panel.tsx @@ -9,7 +9,7 @@ import React, { FC, Fragment } from 'react'; import { EuiCard, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useMlLink } from '../../../../../contexts/kibana'; -import { ML_PAGES } from '../../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../../common/constants/locator'; export const BackToListPanel: FC = () => { const analyticsManagementPageLink = useMlLink({ diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/view_results_panel/view_results_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/view_results_panel/view_results_panel.tsx index c138b222dad469..6b6eb396959765 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/view_results_panel/view_results_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/view_results_panel/view_results_panel.tsx @@ -9,7 +9,7 @@ import React, { FC, Fragment } from 'react'; import { EuiCard, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useMlLink } from '../../../../../contexts/kibana'; -import { ML_PAGES } from '../../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../../common/constants/locator'; import { DataFrameAnalysisConfigType } from '../../../../../../../common/types/data_frame_analytics'; interface Props { jobId: string; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx index 135f47a959950c..09cfca47520bc5 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section.tsx @@ -22,7 +22,7 @@ import { getDefaultExplorationPageUrlState, useExplorationUrlState, } from '../../hooks/use_exploration_url_state'; -import { ExpandablePanels } from '../../../../../../../common/types/ml_url_generator'; +import { ExpandablePanels } from '../../../../../../../common/types/locator'; interface HeaderItem { // id is used as the React key and to construct a data-test-subj diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_exploration_url_state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_exploration_url_state.ts index 3b8d7c4f051f0c..dac1a85211c209 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_exploration_url_state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_exploration_url_state.ts @@ -6,9 +6,9 @@ */ import { usePageUrlState } from '../../../../util/url_state'; -import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../common/constants/locator'; +import { ExplorationPageUrlState } from '../../../../../../common/types/locator'; import { SEARCH_QUERY_LANGUAGE } from '../../../../../../common/constants/search'; -import { ExplorationPageUrlState } from '../../../../../../common/types/ml_url_generator'; import { isPopulatedObject } from '../../../../../../common/util/object_utils'; export function getDefaultExplorationPageUrlState( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx index 0acbf5c61aa342..94568b4f59809e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx @@ -6,20 +6,20 @@ */ import React, { useCallback, useMemo } from 'react'; -import { useMlUrlGenerator, useNavigateToPath } from '../../../../../contexts/kibana'; +import { useMlLocator, useNavigateToPath } from '../../../../../contexts/kibana'; import { DataFrameAnalyticsListAction, DataFrameAnalyticsListRow } from '../analytics_list/common'; -import { ML_PAGES } from '../../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../../common/constants/locator'; import { getViewLinkStatus } from '../action_view/get_view_link_status'; import { mapActionButtonText, MapButton } from './map_button'; export type MapAction = ReturnType; export const useMapAction = () => { - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator()!; const navigateToPath = useNavigateToPath(); const clickHandler = useCallback(async (item: DataFrameAnalyticsListRow) => { - const path = await mlUrlGenerator.createUrl({ + const path = await mlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_MAP, pageState: { jobId: item.id }, }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx index 9b1d80abdaf7ad..67af4f567e0f60 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx @@ -8,22 +8,22 @@ import React, { useCallback, useMemo } from 'react'; import { getAnalysisType } from '../../../../common/analytics'; -import { useMlUrlGenerator, useNavigateToPath } from '../../../../../contexts/kibana'; +import { useMlLocator, useNavigateToPath } from '../../../../../contexts/kibana'; import { DataFrameAnalyticsListAction, DataFrameAnalyticsListRow } from '../analytics_list/common'; import { getViewLinkStatus } from './get_view_link_status'; import { viewActionButtonText, ViewButton } from './view_button'; import { DataFrameAnalysisConfigType } from '../../../../../../../common/types/data_frame_analytics'; -import { ML_PAGES } from '../../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../../common/constants/locator'; export type ViewAction = ReturnType; export const useViewAction = () => { - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator()!; const navigateToPath = useNavigateToPath(); const redirectToTab = async (jobId: string, analysisType: DataFrameAnalysisConfigType) => { - const path = await mlUrlGenerator.createUrl({ + const path = await mlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION, pageState: { jobId, analysisType }, }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx index cb0e2b0092c557..664acce325e9a6 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx @@ -32,7 +32,7 @@ import { } from './common'; import { useActions } from './use_actions'; import { useMlLink } from '../../../../../contexts/kibana'; -import { ML_PAGES } from '../../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../../common/constants/locator'; import type { SpacesPluginStart } from '../../../../../../../../spaces/public'; import { JobSpacesList } from '../../../../../components/job_spaces_list'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/models_list.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/models_list.tsx index b9803f1ea26e01..e054a195ac0155 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/models_list.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/models_list.tsx @@ -30,7 +30,7 @@ import { ModelsTableToConfigMapping } from './index'; import { DeleteModelsModal } from './delete_models_modal'; import { useMlKibana, - useMlUrlGenerator, + useMlLocator, useNavigateToPath, useNotifications, } from '../../../../../contexts/kibana'; @@ -47,7 +47,7 @@ import { refreshAnalyticsList$, useRefreshAnalyticsList, } from '../../../../common'; -import { ML_PAGES } from '../../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../../common/constants/locator'; import { DataFrameAnalysisConfigType } from '../../../../../../../common/types/data_frame_analytics'; import { timeFormatter } from '../../../../../../../common/util/date_utils'; import { ListingPageUrlState } from '../../../../../../../common/types/common'; @@ -83,7 +83,7 @@ export const ModelsList: FC = () => { application: { navigateToUrl, capabilities }, }, } = useMlKibana(); - const urlGenerator = useMlUrlGenerator(); + const urlLocator = useMlLocator()!; const [pageState, updatePageState] = usePageUrlState( ML_PAGES.DATA_FRAME_ANALYTICS_MODELS_MANAGE, @@ -105,7 +105,6 @@ export const ModelsList: FC = () => { {} ); - const mlUrlGenerator = useMlUrlGenerator(); const navigateToPath = useNavigateToPath(); const isBuiltInModel = useCallback( @@ -300,7 +299,7 @@ export const ModelsList: FC = () => { item.metadata?.analytics_config.analysis ) as DataFrameAnalysisConfigType; - const url = await urlGenerator.createUrl({ + const url = await urlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION, pageState: { jobId: item.metadata?.analytics_config.id as string, @@ -329,7 +328,7 @@ export const ModelsList: FC = () => { isPrimary: true, available: (item) => !!item.metadata?.analytics_config?.id, onClick: async (item) => { - const path = await mlUrlGenerator.createUrl({ + const path = await urlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_MAP, pageState: { modelId: item.model_id }, }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx index f32e60dcf3cc1d..8118a7eb76f10d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx @@ -36,7 +36,7 @@ import { JobMap } from '../job_map'; import { usePageUrlState } from '../../../util/url_state'; import { ListingPageUrlState } from '../../../../../common/types/common'; import { DataFrameAnalyticsListColumn } from './components/analytics_list/common'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { HelpMenu } from '../../../components/help_menu'; import { useMlKibana } from '../../../contexts/kibana'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/controls.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/controls.tsx index eb4aa8e4f09fe0..7d77fcc91fa46b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/controls.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/controls.tsx @@ -30,13 +30,9 @@ import { EuiDescriptionListProps } from '@elastic/eui/src/components/description import { CytoscapeContext } from './cytoscape'; import { formatHumanReadableDateTimeSeconds } from '../../../../../../common/util/date_utils'; import { JOB_MAP_NODE_TYPES } from '../../../../../../common/constants/data_frame_analytics'; -import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../common/constants/locator'; import { checkPermission } from '../../../../capabilities/check_capabilities'; -import { - useMlUrlGenerator, - useNotifications, - useNavigateToPath, -} from '../../../../contexts/kibana'; +import { useMlLocator, useNotifications, useNavigateToPath } from '../../../../contexts/kibana'; import { getIndexPatternIdFromName } from '../../../../util/index_utils'; import { useNavigateToWizardWithClonedJob } from '../../analytics_management/components/action_clone/clone_action_name'; import { @@ -98,7 +94,7 @@ export const Controls: FC = React.memo( openDeleteJobCheckModal, } = deleteAction; const { toasts } = useNotifications(); - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator()!; const navigateToPath = useNavigateToPath(); const navigateToWizardWithClonedJob = useNavigateToWizardWithClonedJob(); @@ -119,7 +115,7 @@ export const Controls: FC = React.memo( const indexId = getIndexPatternIdFromName(nodeLabel); if (indexId) { - const path = await mlUrlGenerator.createUrl({ + const path = await mlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, pageState: { index: indexId }, }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx index 61ac19a31af0c1..a415b18fff4c2a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/job_map.tsx @@ -10,9 +10,9 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { Cytoscape, Controls, JobMapLegend } from './components'; -import { useMlKibana, useMlUrlGenerator } from '../../../contexts/kibana'; +import { useMlKibana, useMlLocator } from '../../../contexts/kibana'; import { JOB_MAP_NODE_TYPES } from '../../../../../common/constants/data_frame_analytics'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { useCurrentEuiTheme, EuiThemeType } from '../../../components/color_range_legend'; import { useRefDimensions } from './components/use_ref_dimensions'; import { useFetchAnalyticsMapData } from './use_fetch_analytics_map_data'; @@ -64,11 +64,11 @@ export const JobMap: FC = ({ analyticsId, modelId }) => { application: { navigateToUrl }, }, } = useMlKibana(); - const urlGenerator = useMlUrlGenerator(); + const locator = useMlLocator()!; const { euiTheme } = useCurrentEuiTheme(); const redirectToAnalyticsManagementPage = async () => { - const url = await urlGenerator.createUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE }); + const url = await locator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE }); await navigateToUrl(url); }; diff --git a/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js b/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js index ec97b1a00c091a..466852ed88840c 100644 --- a/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js +++ b/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js @@ -12,7 +12,7 @@ import { Link } from 'react-router-dom'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiEmptyPrompt, EuiButton } from '@elastic/eui'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { useMlLink } from '../../../contexts/kibana/use_create_url'; export const ExplorerNoJobsFound = () => { diff --git a/x-pack/plugins/ml/public/application/explorer/explorer.js b/x-pack/plugins/ml/public/application/explorer/explorer.js index 4b241c47a267b0..a11a42b9b65b2c 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer.js @@ -73,7 +73,7 @@ import { AnomaliesMap } from './anomalies_map'; import { getToastNotifications } from '../util/dependency_cache'; import { ANOMALY_DETECTION_DEFAULT_TIME_RANGE } from '../../../common/constants/settings'; import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; -import { ML_APP_URL_GENERATOR } from '../../../common/constants/ml_url_generator'; +import { ML_APP_LOCATOR } from '../../../common/constants/locator'; import { AnomalyContextMenu } from './anomaly_context_menu'; import { isDefined } from '../../../common/types/guards'; @@ -230,13 +230,9 @@ export class ExplorerUI extends React.Component { updateLanguage = (language) => this.setState({ language }); render() { - const { - share: { - urlGenerators: { getUrlGenerator }, - }, - } = this.props.kibana.services; + const { share } = this.props.kibana.services; - const mlUrlGenerator = getUrlGenerator(ML_APP_URL_GENERATOR); + const mlLocator = share.url.locators.get(ML_APP_LOCATOR); const { showCharts, @@ -502,7 +498,7 @@ export class ExplorerUI extends React.Component { ...chartsData, severity, timefilter, - mlUrlGenerator, + mlLocator, timeBuckets, onSelectEntity: this.applyFilter, }} diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_anomalies_container.tsx b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_anomalies_container.tsx index a11e24f2451a6c..44e6d9ed3dd85b 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_anomalies_container.tsx +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_anomalies_container.tsx @@ -15,11 +15,11 @@ import { SelectSeverityUI, TableSeverity, } from '../../components/controls/select_severity/select_severity'; -import type { UrlGeneratorContract } from '../../../../../../../src/plugins/share/public'; import type { TimeBuckets } from '../../util/time_buckets'; import type { TimefilterContract } from '../../../../../../../src/plugins/data/public'; import type { EntityFieldOperation } from '../../../../common/util/anomaly_utils'; import type { ExplorerChartsData } from './explorer_charts_container_service'; +import type { MlLocator } from '../../../../common/types/locator'; interface ExplorerAnomaliesContainerProps { id: string; @@ -27,7 +27,7 @@ interface ExplorerAnomaliesContainerProps { showCharts: boolean; severity: TableSeverity; setSeverity: (severity: TableSeverity) => void; - mlUrlGenerator: UrlGeneratorContract<'ML_APP_URL_GENERATOR'>; + mlLocator: MlLocator; timeBuckets: TimeBuckets; timefilter: TimefilterContract; onSelectEntity: (fieldName: string, fieldValue: string, operation: EntityFieldOperation) => void; @@ -48,7 +48,7 @@ export const ExplorerAnomaliesContainer: FC = ( showCharts, severity, setSeverity, - mlUrlGenerator, + mlLocator, timeBuckets, timefilter, onSelectEntity, @@ -81,7 +81,7 @@ export const ExplorerAnomaliesContainer: FC = ( {...{ ...chartsData, severity: severity.val, - mlUrlGenerator, + mlLocator, timeBuckets, timefilter, onSelectEntity, diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js index c37d8b6d51c72f..22628c726b23bb 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js @@ -65,7 +65,7 @@ function ExplorerChartContainer({ severity, tooManyBuckets, wrapLabel, - mlUrlGenerator, + mlLocator, basePath, timeBuckets, timefilter, @@ -80,11 +80,7 @@ function ExplorerChartContainer({ let isCancelled = false; const generateLink = async () => { if (!isCancelled && series.functionDescription !== ML_JOB_AGGREGATION.LAT_LONG) { - const singleMetricViewerLink = await getExploreSeriesLink( - mlUrlGenerator, - series, - timefilter - ); + const singleMetricViewerLink = await getExploreSeriesLink(mlLocator, series, timefilter); setExplorerSeriesLink(singleMetricViewerLink); } }; @@ -92,7 +88,7 @@ function ExplorerChartContainer({ return () => { isCancelled = true; }; - }, [mlUrlGenerator, series]); + }, [mlLocator, series]); const addToRecentlyAccessed = useCallback(() => { if (recentlyAccessed) { @@ -235,7 +231,7 @@ export const ExplorerChartsContainerUI = ({ tooManyBuckets, kibana, errorMessages, - mlUrlGenerator, + mlLocator, timeBuckets, timefilter, onSelectEntity, @@ -293,7 +289,7 @@ export const ExplorerChartsContainerUI = ({ severity={severity} tooManyBuckets={tooManyBuckets} wrapLabel={wrapLabel} - mlUrlGenerator={mlUrlGenerator} + mlLocator={mlLocator} basePath={basePath.get()} timeBuckets={timeBuckets} timefilter={timefilter} diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_dashboard_service.ts b/x-pack/plugins/ml/public/application/explorer/explorer_dashboard_service.ts index 7721532b34338f..f858c40b323152 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_dashboard_service.ts +++ b/x-pack/plugins/ml/public/application/explorer/explorer_dashboard_service.ts @@ -22,7 +22,7 @@ import { ExplorerChartsData } from './explorer_charts/explorer_charts_container_ import { EXPLORER_ACTION } from './explorer_constants'; import { AppStateSelectedCells } from './explorer_utils'; import { explorerReducer, getExplorerDefaultState, ExplorerState } from './reducers'; -import { ExplorerAppState } from '../../../common/types/ml_url_generator'; +import { ExplorerAppState } from '../../../common/types/locator'; export const ALLOW_CELL_RANGE_SELECTION = true; diff --git a/x-pack/plugins/ml/public/application/explorer/hooks/use_explorer_url_state.ts b/x-pack/plugins/ml/public/application/explorer/hooks/use_explorer_url_state.ts index 0f50dc2ae9c32e..f77a730f10a128 100644 --- a/x-pack/plugins/ml/public/application/explorer/hooks/use_explorer_url_state.ts +++ b/x-pack/plugins/ml/public/application/explorer/hooks/use_explorer_url_state.ts @@ -6,8 +6,8 @@ */ import { usePageUrlState } from '../../util/url_state'; -import { ExplorerAppState } from '../../../../common/types/ml_url_generator'; -import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { ExplorerAppState } from '../../../../common/types/locator'; +import { ML_PAGES } from '../../../../common/constants/locator'; export function useExplorerUrlState() { /** diff --git a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts index 54ecd9d065d147..724d85d91e30a2 100644 --- a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts +++ b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts @@ -8,7 +8,7 @@ import moment from 'moment'; import { renderHook } from '@testing-library/react-hooks'; import { useSelectedCells } from './use_selected_cells'; -import { ExplorerAppState } from '../../../../common/types/ml_url_generator'; +import { ExplorerAppState } from '../../../../common/types/locator'; import { TimefilterContract } from '../../../../../../../src/plugins/data/public'; import { useTimefilter } from '../../contexts/kibana'; diff --git a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts index 3c29af69a05356..1840ffc7235d5b 100644 --- a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts +++ b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts @@ -8,7 +8,7 @@ import { useCallback, useEffect, useMemo } from 'react'; import { SWIMLANE_TYPE } from '../explorer_constants'; import { AppStateSelectedCells } from '../explorer_utils'; -import { ExplorerAppState } from '../../../../common/types/ml_url_generator'; +import { ExplorerAppState } from '../../../../common/types/locator'; import { useTimefilter } from '../../contexts/kibana'; export const useSelectedCells = ( diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js index ab9a3cad769bad..019aa5ec5e5e81 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js @@ -29,10 +29,7 @@ import { isTimeSeriesViewJob, } from '../../../../../../../common/util/job_utils'; import { withKibana } from '../../../../../../../../../../src/plugins/kibana_react/public'; -import { - ML_APP_URL_GENERATOR, - ML_PAGES, -} from '../../../../../../../common/constants/ml_url_generator'; +import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../../../../../../common/constants/locator'; import { PLUGIN_ID } from '../../../../../../../common/constants/app'; import { timeFormatter } from '../../../../../../../common/util/date_utils'; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/job_id_link.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/job_id_link.tsx index b1ffaa551caa53..2296d77274a393 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/job_id_link.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/job_id_link.tsx @@ -7,9 +7,9 @@ import React, { useEffect, useState } from 'react'; import { EuiLink } from '@elastic/eui'; -import { useMlUrlGenerator } from '../../../../contexts/kibana'; -import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator'; -import { AnomalyDetectionQueryState } from '../../../../../../common/types/ml_url_generator'; +import { useMlLocator } from '../../../../contexts/kibana'; +import { ML_PAGES } from '../../../../../../common/constants/locator'; +import { AnomalyDetectionQueryState } from '../../../../../../common/types/locator'; // @ts-ignore import { JobGroup } from '../job_group'; @@ -28,7 +28,7 @@ function isGroupIdLink(props: JobIdLink | GroupIdLink): props is GroupIdLink { return (props as GroupIdLink).groupId !== undefined; } export const AnomalyDetectionJobIdLink = (props: AnomalyDetectionJobIdLinkProps) => { - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator(); const [href, setHref] = useState(''); useEffect(() => { @@ -40,19 +40,22 @@ export const AnomalyDetectionJobIdLink = (props: AnomalyDetectionJobIdLinkProps) } else { pageState.jobId = props.id; } - const url = await mlUrlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - pageState, - }); - if (!isCancelled) { - setHref(url); + if (mlLocator) { + const url = await mlLocator.getUrl({ + page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + // TODO: Fix this any. + pageState: pageState as any, + }); + if (!isCancelled) { + setHref(url); + } } }; generateLink(); return () => { isCancelled = true; }; - }, [props, mlUrlGenerator]); + }, [props, mlLocator]); if (isGroupIdLink(props)) { return ( diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/new_job_button/new_job_button.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/new_job_button/new_job_button.js index f3072a216e9222..a6ed115880265f 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/new_job_button/new_job_button.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/new_job_button/new_job_button.js @@ -13,7 +13,7 @@ import React from 'react'; import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url'; -import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../common/constants/locator'; export function NewJobButton() { const buttonEnabled = checkPermission('canCreateJob') && mlNodesAvailable(); diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/jobs.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/jobs.tsx index 5cc75bc7ce2617..2d4cdc99a7eb9d 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/jobs.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/jobs.tsx @@ -10,7 +10,7 @@ import { NavigationMenu } from '../../components/navigation_menu'; // @ts-ignore import { JobsListView } from './components/jobs_list_view/index'; import { usePageUrlState } from '../../util/url_state'; -import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../common/constants/locator'; import { ListingPageUrlState } from '../../../../common/types/common'; import { HelpMenu } from '../../components/help_menu'; import { useMlKibana } from '../../contexts/kibana'; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/calendars/calendars_selection.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/calendars/calendars_selection.tsx index 78a888617fff71..2fd87676ecf800 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/calendars/calendars_selection.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/calendars/calendars_selection.tsx @@ -27,7 +27,7 @@ import { PLUGIN_ID } from '../../../../../../../../../../../common/constants/app import { Calendar } from '../../../../../../../../../../../common/types/calendars'; import { useMlKibana } from '../../../../../../../../../contexts/kibana'; import { GLOBAL_CALENDAR } from '../../../../../../../../../../../common/constants/calendars'; -import { ML_PAGES } from '../../../../../../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../../../../../../common/constants/locator'; export const CalendarsSelection: FC = () => { const { diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx index 782a23be87dec9..9cde490925e9f2 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx @@ -28,7 +28,7 @@ import { addItemToRecentlyAccessed } from '../../../../util/recently_accessed'; import { timeBasedIndexCheck } from '../../../../util/index_utils'; import { LinkCard } from '../../../../components/link_card'; import { CategorizationIcon } from './categorization_job_icon'; -import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../common/constants/locator'; import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url'; export const Page: FC = () => { diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx index 69fe66b4ca190b..478af8e981b088 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx @@ -23,7 +23,7 @@ import { } from '@elastic/eui'; import { merge } from 'lodash'; import moment from 'moment'; -import { useMlKibana, useMlUrlGenerator } from '../../../contexts/kibana'; +import { useMlKibana, useMlLocator } from '../../../contexts/kibana'; import { ml } from '../../../services/ml_api_service'; import { useMlContext } from '../../../contexts/ml'; import { @@ -41,7 +41,7 @@ import { checkForSavedObjects } from './resolvers'; import { JobSettingsForm, JobSettingsFormValues } from './components/job_settings_form'; import { TimeRange } from '../common/components'; import { JobId } from '../../../../../common/types/anomaly_detection_jobs'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { TIME_FORMAT } from '../../../../../common/constants/time_format'; import { JobsAwaitingNodeWarning } from '../../../components/jobs_awaiting_node_warning'; import { isPopulatedObject } from '../../../../../common/util/object_utils'; @@ -77,7 +77,7 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => { const { services: { notifications }, } = useMlKibana(); - const urlGenerator = useMlUrlGenerator(); + const locator = useMlLocator(); // #region State const [jobPrefix, setJobPrefix] = useState(''); @@ -197,19 +197,21 @@ export const Page: FC = ({ moduleId, existingGroupIds }) => { ); setKibanaObjects(merge(kibanaObjects, kibanaResponse)); - const url = await urlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_EXPLORER, - pageState: { - jobIds: jobsResponse.filter(({ success }) => success).map(({ id }) => id), - timeRange: { - from: moment(resultTimeRange.start).format(TIME_FORMAT), - to: moment(resultTimeRange.end).format(TIME_FORMAT), - mode: 'absolute', + if (locator) { + const url = await locator.getUrl({ + page: ML_PAGES.ANOMALY_EXPLORER, + pageState: { + jobIds: jobsResponse.filter(({ success }) => success).map(({ id }) => id), + timeRange: { + from: moment(resultTimeRange.start).format(TIME_FORMAT), + to: moment(resultTimeRange.end).format(TIME_FORMAT), + mode: 'absolute', + }, }, - }, - }); + }); + setResultsUrl(url); + } - setResultsUrl(url); const failedJobsCount = jobsResponse.reduce( (count, { success }) => (success ? count : count + 1), 0 diff --git a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx index fad3d812d129af..795bc2314664e0 100644 --- a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx @@ -12,7 +12,7 @@ import { useMlLink } from '../../../contexts/kibana'; import { getAnalysisType } from '../../../data_frame_analytics/common/analytics'; import { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common'; import { getViewLinkStatus } from '../../../data_frame_analytics/pages/analytics_management/components/action_view/get_view_link_status'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { DataFrameAnalysisConfigType } from '../../../../../common/types/data_frame_analytics'; interface Props { diff --git a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx index 3a67b413dbdf6f..70655a3999e796 100644 --- a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx @@ -24,8 +24,8 @@ import { AnalyticsTable } from './table'; import { getAnalyticsFactory } from '../../../data_frame_analytics/pages/analytics_management/services/analytics_service'; import { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common'; import { AnalyticStatsBarStats, StatsBar } from '../../../components/stats_bar'; -import { useMlUrlGenerator, useNavigateToPath } from '../../../contexts/kibana'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { useMlLocator, useNavigateToPath } from '../../../contexts/kibana'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { SourceSelection } from '../../../data_frame_analytics/pages/analytics_management/components/source_selection'; interface Props { @@ -41,11 +41,12 @@ export const AnalyticsPanel: FC = ({ jobCreationDisabled, setLazyJobCount const [isInitialized, setIsInitialized] = useState(false); const [isSourceIndexModalVisible, setIsSourceIndexModalVisible] = useState(false); - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator(); const navigateToPath = useNavigateToPath(); const redirectToDataFrameAnalyticsManagementPage = async () => { - const path = await mlUrlGenerator.createUrl({ + if (!mlLocator) return; + const path = await mlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE, }); await navigateToPath(path, true); diff --git a/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx b/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx index 14ae1f01cbf789..73d14b8d625908 100644 --- a/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx @@ -17,13 +17,13 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import moment from 'moment'; -import { useMlKibana, useMlUrlGenerator, useNavigateToPath } from '../../../contexts/kibana'; +import { useMlKibana, useMlLocator, useNavigateToPath } from '../../../contexts/kibana'; import { AnomalyDetectionTable } from './table'; import { ml } from '../../../services/ml_api_service'; import { getGroupsFromJobs, getStatsBarData, getJobsWithTimerange } from './utils'; import { Dictionary } from '../../../../../common/types/common'; import { MlSummaryJobs, MlSummaryJob } from '../../../../../common/types/anomaly_detection_jobs'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; export type GroupsDictionary = Dictionary; @@ -59,18 +59,20 @@ export const AnomalyDetectionPanel: FC = ({ jobCreationDisabled, setLazyJ const { services: { notifications }, } = useMlKibana(); - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator(); const navigateToPath = useNavigateToPath(); const redirectToJobsManagementPage = async () => { - const path = await mlUrlGenerator.createUrl({ + if (!mlLocator) return; + const path = await mlLocator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, }); await navigateToPath(path, true); }; const redirectToCreateJobSelectIndexPage = async () => { - const path = await mlUrlGenerator.createUrl({ + if (!mlLocator) return; + const path = await mlLocator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX, }); await navigateToPath(path, true); diff --git a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx b/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx index d0ac5be86b232e..98603f69f382f7 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_exploration.tsx @@ -9,14 +9,14 @@ import React, { FC } from 'react'; import { i18n } from '@kbn/i18n'; -import { NavigateToPath, useMlKibana, useMlUrlGenerator } from '../../../contexts/kibana'; +import { NavigateToPath, useMlKibana, useMlLocator } from '../../../contexts/kibana'; import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { basicResolvers } from '../../resolvers'; import { Page } from '../../../data_frame_analytics/pages/analytics_exploration'; import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { DataFrameAnalysisConfigType } from '../../../../../common/types/data_frame_analytics'; import { useUrlState } from '../../../util/url_state'; @@ -43,7 +43,7 @@ const PageWrapper: FC = ({ location, deps }) => { const [globalState] = useUrlState('_g'); - const urlGenerator = useMlUrlGenerator(); + const locator = useMlLocator(); const { services: { application: { navigateToUrl }, @@ -51,7 +51,8 @@ const PageWrapper: FC = ({ location, deps }) => { } = useMlKibana(); const redirectToAnalyticsManagementPage = async () => { - const url = await urlGenerator.createUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE }); + if (!locator) return; + const url = await locator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE }); await navigateToUrl(url); }; diff --git a/x-pack/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx b/x-pack/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx index 27676820c0472a..b9e866d2e00d06 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/datavisualizer/index_based.tsx @@ -21,7 +21,7 @@ import { checkGetJobsCapabilitiesResolver } from '../../../capabilities/check_ca import { loadIndexPatterns } from '../../../util/index_utils'; import { checkMlNodesAvailable } from '../../../ml_nodes_check'; import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { useCreateAndNavigateToMlLink } from '../../../contexts/kibana/use_create_url'; export const indexBasedRouteFactory = ( diff --git a/x-pack/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx b/x-pack/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx index 28dabb7af6b3d0..5d903bd865911e 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/new_job/index_or_search.tsx @@ -20,7 +20,7 @@ import { checkBasicLicense } from '../../../license'; import { loadIndexPatterns } from '../../../util/index_utils'; import { checkGetJobsCapabilitiesResolver } from '../../../capabilities/check_capabilities'; import { checkMlNodesAvailable } from '../../../ml_nodes_check'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { useCreateAndNavigateToMlLink } from '../../../contexts/kibana/use_create_url'; enum MODE { diff --git a/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx b/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx index 726ec328d1cb20..9942c4a5653a8b 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx @@ -24,7 +24,7 @@ import { import { checkCreateJobsCapabilitiesResolver } from '../../../capabilities/check_capabilities'; import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; import { useCreateAndNavigateToMlLink } from '../../../contexts/kibana/use_create_url'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; interface WizardPageProps extends PageProps { jobType: JOB_TYPE; diff --git a/x-pack/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx b/x-pack/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx index 3bb605268c2b61..18c4d43b564d7b 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx @@ -23,7 +23,7 @@ import { checkMlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes'; import { NewCalendar } from '../../../settings/calendars'; import { breadcrumbOnClickFactory, getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; import { useCreateAndNavigateToMlLink } from '../../../contexts/kibana/use_create_url'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; enum MODE { NEW, diff --git a/x-pack/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx b/x-pack/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx index bdcf5bb1ddaee1..e12a33b48439cf 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx @@ -24,7 +24,7 @@ import { EditFilterList } from '../../../settings/filter_lists'; import { breadcrumbOnClickFactory, getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; import { useCreateAndNavigateToMlLink } from '../../../contexts/kibana/use_create_url'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; enum MODE { NEW, diff --git a/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx b/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx index c06094b44f4a02..ef669a7703c1f0 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx @@ -43,7 +43,7 @@ import { useToastNotificationService } from '../../services/toast_notification_s import { AnnotationUpdatesService } from '../../services/annotations_service'; import { MlAnnotationUpdatesContext } from '../../contexts/ml/ml_annotation_updates_context'; import { useTimeSeriesExplorerUrlState } from '../../timeseriesexplorer/hooks/use_timeseriesexplorer_url_state'; -import type { TimeSeriesExplorerAppState } from '../../../../common/types/ml_url_generator'; +import type { TimeSeriesExplorerAppState } from '../../../../common/types/locator'; import type { TimeRangeBounds } from '../../util/time_buckets'; export const timeSeriesExplorerRouteFactory = ( diff --git a/x-pack/plugins/ml/public/application/routing/use_resolver.ts b/x-pack/plugins/ml/public/application/routing/use_resolver.ts index 070ff41c2778a8..62450106d0dfbe 100644 --- a/x-pack/plugins/ml/public/application/routing/use_resolver.ts +++ b/x-pack/plugins/ml/public/application/routing/use_resolver.ts @@ -19,7 +19,7 @@ import { ResolverResults, Resolvers } from './resolvers'; import { MlContextValue } from '../contexts/ml'; import { useNotifications } from '../contexts/kibana'; import { useCreateAndNavigateToMlLink } from '../contexts/kibana/use_create_url'; -import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../common/constants/locator'; /** * Hook to resolve route specific requirements diff --git a/x-pack/plugins/ml/public/application/settings/anomaly_detection_settings.tsx b/x-pack/plugins/ml/public/application/settings/anomaly_detection_settings.tsx index d883ebe034b72d..c85e85b2ce361a 100644 --- a/x-pack/plugins/ml/public/application/settings/anomaly_detection_settings.tsx +++ b/x-pack/plugins/ml/public/application/settings/anomaly_detection_settings.tsx @@ -26,7 +26,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { AnomalyDetectionSettingsContext } from './anomaly_detection_settings_context'; import { useNotifications } from '../contexts/kibana'; import { ml } from '../services/ml_api_service'; -import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../common/constants/locator'; import { useCreateAndNavigateToMlLink } from '../contexts/kibana/use_create_url'; export const AnomalyDetectionSettings: FC = () => { diff --git a/x-pack/plugins/ml/public/application/settings/calendars/edit/calendar_form/calendar_form.js b/x-pack/plugins/ml/public/application/settings/calendars/edit/calendar_form/calendar_form.js index da131e2e998fa6..1e05a6a0b18fd6 100644 --- a/x-pack/plugins/ml/public/application/settings/calendars/edit/calendar_form/calendar_form.js +++ b/x-pack/plugins/ml/public/application/settings/calendars/edit/calendar_form/calendar_form.js @@ -26,7 +26,7 @@ import { EventsTable } from '../events_table'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../common/constants/locator'; import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url'; function EditHeader({ calendarId, description }) { diff --git a/x-pack/plugins/ml/public/application/settings/calendars/edit/new_calendar.js b/x-pack/plugins/ml/public/application/settings/calendars/edit/new_calendar.js index 42d8b32691c205..8e6690570ca320 100644 --- a/x-pack/plugins/ml/public/application/settings/calendars/edit/new_calendar.js +++ b/x-pack/plugins/ml/public/application/settings/calendars/edit/new_calendar.js @@ -21,7 +21,7 @@ import { ImportModal } from './import_modal'; import { ml } from '../../../services/ml_api_service'; import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { GLOBAL_CALENDAR } from '../../../../../common/constants/calendars'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { getDocLinks } from '../../../util/dependency_cache'; import { HelpMenu } from '../../../components/help_menu'; diff --git a/x-pack/plugins/ml/public/application/settings/calendars/list/table/table.js b/x-pack/plugins/ml/public/application/settings/calendars/list/table/table.js index f5d3e7e1b46ca8..58efe99b240277 100644 --- a/x-pack/plugins/ml/public/application/settings/calendars/list/table/table.js +++ b/x-pack/plugins/ml/public/application/settings/calendars/list/table/table.js @@ -15,7 +15,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { GLOBAL_CALENDAR } from '../../../../../../common/constants/calendars'; import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url'; -import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../../common/constants/locator'; export const CalendarsListTable = ({ calendarsList, diff --git a/x-pack/plugins/ml/public/application/settings/filter_lists/edit/edit_filter_list.js b/x-pack/plugins/ml/public/application/settings/filter_lists/edit/edit_filter_list.js index 8a208a00f46579..00058517fccdcf 100644 --- a/x-pack/plugins/ml/public/application/settings/filter_lists/edit/edit_filter_list.js +++ b/x-pack/plugins/ml/public/application/settings/filter_lists/edit/edit_filter_list.js @@ -35,7 +35,7 @@ import { ItemsGrid } from '../../../components/items_grid'; import { NavigationMenu } from '../../../components/navigation_menu'; import { isValidFilterListId, saveFilterList } from './utils'; import { ml } from '../../../services/ml_api_service'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; import { getDocLinks } from '../../../util/dependency_cache'; import { HelpMenu } from '../../../components/help_menu'; diff --git a/x-pack/plugins/ml/public/application/settings/filter_lists/list/table.js b/x-pack/plugins/ml/public/application/settings/filter_lists/list/table.js index 43fa8aecf73c94..61af4cc141426c 100644 --- a/x-pack/plugins/ml/public/application/settings/filter_lists/list/table.js +++ b/x-pack/plugins/ml/public/application/settings/filter_lists/list/table.js @@ -28,7 +28,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { DeleteFilterListModal } from '../components/delete_filter_list_modal'; import { useCreateAndNavigateToMlLink } from '../../../contexts/kibana/use_create_url'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../../common/constants/locator'; function UsedByIcon({ usedBy }) { // Renders a tick or cross in the 'usedBy' column to indicate whether diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseriesexplorer_no_jobs_found/timeseriesexplorer_no_jobs_found.tsx b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseriesexplorer_no_jobs_found/timeseriesexplorer_no_jobs_found.tsx index 4e74cba473b8da..df98d3dea2124d 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseriesexplorer_no_jobs_found/timeseriesexplorer_no_jobs_found.tsx +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseriesexplorer_no_jobs_found/timeseriesexplorer_no_jobs_found.tsx @@ -13,15 +13,16 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiEmptyPrompt, EuiButton } from '@elastic/eui'; -import { useMlUrlGenerator, useNavigateToPath } from '../../../contexts/kibana'; -import { ML_PAGES } from '../../../../../common/constants/ml_url_generator'; +import { useMlLocator, useNavigateToPath } from '../../../contexts/kibana'; +import { ML_PAGES } from '../../../../../common/constants/locator'; export const TimeseriesexplorerNoJobsFound = () => { - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator(); const navigateToPath = useNavigateToPath(); const redirectToJobsManagementPage = async () => { - const path = await mlUrlGenerator.createUrl({ + if (!mlLocator) return; + const path = await mlLocator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, }); await navigateToPath(path, true); diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/hooks/use_timeseriesexplorer_url_state.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/hooks/use_timeseriesexplorer_url_state.ts index d2d3377b1366e9..614888fc005add 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/hooks/use_timeseriesexplorer_url_state.ts +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/hooks/use_timeseriesexplorer_url_state.ts @@ -6,8 +6,8 @@ */ import { usePageUrlState } from '../../util/url_state'; -import { TimeSeriesExplorerAppState } from '../../../../common/types/ml_url_generator'; -import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { TimeSeriesExplorerAppState } from '../../../../common/types/locator'; +import { ML_PAGES } from '../../../../common/constants/locator'; export function useTimeSeriesExplorerUrlState() { return usePageUrlState(ML_PAGES.SINGLE_METRIC_VIEWER); diff --git a/x-pack/plugins/ml/public/application/util/chart_utils.js b/x-pack/plugins/ml/public/application/util/chart_utils.js index 9b5cab41f24e25..157b275cd38697 100644 --- a/x-pack/plugins/ml/public/application/util/chart_utils.js +++ b/x-pack/plugins/ml/public/application/util/chart_utils.js @@ -10,7 +10,7 @@ import { calculateTextWidth } from './string_utils'; import { MULTI_BUCKET_IMPACT } from '../../../common/constants/multi_bucket_impact'; import moment from 'moment'; import { CHART_TYPE } from '../explorer/explorer_constants'; -import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../common/constants/locator'; export const LINE_CHART_ANOMALY_RADIUS = 7; export const MULTI_BUCKET_SYMBOL_SIZE = 100; // In square pixels for use with d3 symbol.size @@ -219,7 +219,7 @@ export function getChartType(config) { return chartType; } -export async function getExploreSeriesLink(mlUrlGenerator, series, timefilter) { +export async function getExploreSeriesLink(mlLocator, series, timefilter) { // Open the Single Metric dashboard over the same overall bounds and // zoomed in to the same time as the current chart. const bounds = timefilter.getActiveBounds(); @@ -241,7 +241,7 @@ export async function getExploreSeriesLink(mlUrlGenerator, series, timefilter) { }); } - const url = await mlUrlGenerator.createUrl({ + const url = await mlLocator.getUrl({ page: ML_PAGES.SINGLE_METRIC_VIEWER, pageState: { jobIds: [series.jobId], diff --git a/x-pack/plugins/ml/public/application/util/url_state.tsx b/x-pack/plugins/ml/public/application/util/url_state.tsx index 725d01d3a2b2b4..7b20b841a9d9e7 100644 --- a/x-pack/plugins/ml/public/application/util/url_state.tsx +++ b/x-pack/plugins/ml/public/application/util/url_state.tsx @@ -14,7 +14,7 @@ import { useHistory, useLocation } from 'react-router-dom'; import { Dictionary } from '../../../common/types/common'; import { getNestedProperty } from './object_utils'; -import { MlPages } from '../../../common/constants/ml_url_generator'; +import { MlPages } from '../../../common/constants/locator'; type Accessor = '_a' | '_g'; export type SetUrlState = ( diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx index 489f2ad08aeafb..222b3fc9b78e96 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx @@ -20,12 +20,13 @@ import type { import type { EntityField, EntityFieldOperation } from '../../../common/util/anomaly_utils'; import { ExplorerAnomaliesContainer } from '../../application/explorer/explorer_charts/explorer_anomalies_container'; -import { ML_APP_URL_GENERATOR } from '../../../common/constants/ml_url_generator'; +import { ML_APP_LOCATOR } from '../../../common/constants/locator'; import { optionValueToThreshold } from '../../application/components/controls/select_severity/select_severity'; import { ANOMALY_THRESHOLD } from '../../../common'; import { UI_SETTINGS } from '../../../../../../src/plugins/data/common'; import { TimeBuckets } from '../../application/util/time_buckets'; import { EXPLORER_ENTITY_FIELD_SELECTION_TRIGGER } from '../../ui_actions/triggers'; +import { MlLocator } from '../../../common/types/locator'; const RESIZE_THROTTLE_TIME_MS = 500; @@ -55,19 +56,10 @@ export const EmbeddableAnomalyChartsContainer: FC(); - const [ - { uiSettings }, - { - data: dataServices, - share: { - urlGenerators: { getUrlGenerator }, - }, - uiActions, - }, - ] = services; + const [{ uiSettings }, { data: dataServices, share, uiActions }] = services; const { timefilter } = dataServices.query.timefilter; - const mlUrlGenerator = useMemo(() => getUrlGenerator(ML_APP_URL_GENERATOR), [getUrlGenerator]); + const mlLocator = useMemo(() => share.url.locators.get(ML_APP_LOCATOR)! as MlLocator, [share]); const timeBuckets = useMemo(() => { return new TimeBuckets({ @@ -179,7 +171,7 @@ export const EmbeddableAnomalyChartsContainer: FC(urlState: UrlState) { diff --git a/x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts b/x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts index 844eeb4ca435a8..72d3b12e9da573 100644 --- a/x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts +++ b/x-pack/plugins/ml/public/locator/formatters/data_frame_analytics.ts @@ -17,8 +17,8 @@ import { ExplorationPageUrlState, MlGenericUrlState, MlCommonGlobalState, -} from '../../../common/types/ml_url_generator'; -import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +} from '../../../common/types/locator'; +import { ML_PAGES } from '../../../common/constants/locator'; import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public'; import { getGroupQueryText, getJobQueryText } from '../../../common/util/string_utils'; import { AppPageState, ListingPageUrlState } from '../../../common/types/common'; diff --git a/x-pack/plugins/ml/public/locator/formatters/settings.tsx b/x-pack/plugins/ml/public/locator/formatters/settings.tsx index d253b0d9bce81d..7855c6b07351ee 100644 --- a/x-pack/plugins/ml/public/locator/formatters/settings.tsx +++ b/x-pack/plugins/ml/public/locator/formatters/settings.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import { CalendarEditUrlState, FilterEditUrlState } from '../../../common/types/ml_url_generator'; -import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { CalendarEditUrlState, FilterEditUrlState } from '../../../common/types/locator'; +import { ML_PAGES } from '../../../common/constants/locator'; import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public'; export function formatEditCalendarUrl( diff --git a/x-pack/plugins/ml/public/locator/index.ts b/x-pack/plugins/ml/public/locator/index.ts index 3e346375235c0e..eb5b0ce1898300 100644 --- a/x-pack/plugins/ml/public/locator/index.ts +++ b/x-pack/plugins/ml/public/locator/index.ts @@ -5,4 +5,6 @@ * 2.0. */ +export { ML_PAGES } from '../../common/constants/locator'; export * from './ml_locator'; +export { useMlHref } from './use_ml_href'; diff --git a/x-pack/plugins/ml/public/locator/ml_locator.test.ts b/x-pack/plugins/ml/public/locator/ml_locator.test.ts index b0c3f051915551..97bb6cb2966f2b 100644 --- a/x-pack/plugins/ml/public/locator/ml_locator.test.ts +++ b/x-pack/plugins/ml/public/locator/ml_locator.test.ts @@ -6,7 +6,7 @@ */ import { MlLocatorDefinition } from './ml_locator'; -import { ML_PAGES } from '../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../common/constants/locator'; import { ANALYSIS_CONFIG_TYPE } from '../../common/constants/data_frame_analytics'; describe('MlUrlGenerator', () => { diff --git a/x-pack/plugins/ml/public/locator/ml_locator.ts b/x-pack/plugins/ml/public/locator/ml_locator.ts index 11f3874ac93085..5e41864c96e293 100644 --- a/x-pack/plugins/ml/public/locator/ml_locator.ts +++ b/x-pack/plugins/ml/public/locator/ml_locator.ts @@ -5,17 +5,13 @@ * 2.0. */ -import { SerializableState } from 'src/plugins/kibana_utils/common'; -import type { - LocatorDefinition, - LocatorPublic, - KibanaLocation, -} from '../../../../../src/plugins/share/public'; -import type { +import type { LocatorDefinition, KibanaLocation } from '../../../../../src/plugins/share/public'; +import { DataFrameAnalyticsExplorationUrlState, - MlUrlGeneratorState, -} from '../../common/types/ml_url_generator'; -import { ML_PAGES } from '../../common/constants/ml_url_generator'; + MlLocatorParams, + MlLocator, +} from '../../common/types/locator'; +import { ML_APP_LOCATOR, ML_PAGES } from '../../common/constants/locator'; import { formatAnomalyDetectionCreateJobSelectIndex, formatAnomalyDetectionCreateJobSelectType, @@ -31,11 +27,7 @@ import { formatEditFilterUrl, } from './formatters'; -export type MlLocatorParams = MlUrlGeneratorState & SerializableState; - -export type MlLocator = LocatorPublic; - -export const ML_APP_LOCATOR = 'ML_APP_LOCATOR'; +export { MlLocatorParams, MlLocator }; export class MlLocatorDefinition implements LocatorDefinition { public readonly id = ML_APP_LOCATOR; diff --git a/x-pack/plugins/ml/public/ml_url_generator/use_ml_href.ts b/x-pack/plugins/ml/public/locator/use_ml_href.ts similarity index 100% rename from x-pack/plugins/ml/public/ml_url_generator/use_ml_href.ts rename to x-pack/plugins/ml/public/locator/use_ml_href.ts diff --git a/x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts b/x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts deleted file mode 100644 index e5c6a2345e1679..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ML_APP_URL_GENERATOR } from '../../../common/constants/ml_url_generator'; -import { UrlGeneratorContract } from '../../../../../../src/plugins/share/public'; - -export const createMlUrlGeneratorMock = () => - ({ - id: ML_APP_URL_GENERATOR, - isDeprecated: false, - createUrl: jest.fn(), - migrate: jest.fn(), - } as jest.Mocked>); diff --git a/x-pack/plugins/ml/public/ml_url_generator/anomaly_detection_urls_generator.ts b/x-pack/plugins/ml/public/ml_url_generator/anomaly_detection_urls_generator.ts deleted file mode 100644 index 156bf8952dd5d9..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/anomaly_detection_urls_generator.ts +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { isEmpty } from 'lodash'; -import type { - AnomalyDetectionUrlState, - ExplorerAppState, - ExplorerGlobalState, - ExplorerUrlState, - MlCommonGlobalState, - MlGenericUrlState, - TimeSeriesExplorerAppState, - TimeSeriesExplorerGlobalState, - TimeSeriesExplorerUrlState, -} from '../../common/types/ml_url_generator'; -import { ML_PAGES } from '../../common/constants/ml_url_generator'; -import { createGenericMlUrl } from './common'; -import { setStateToKbnUrl } from '../../../../../src/plugins/kibana_utils/public'; -import { getGroupQueryText, getJobQueryText } from '../../common/util/string_utils'; -import { AppPageState, ListingPageUrlState } from '../../common/types/common'; -/** - * Creates URL to the Anomaly Detection Job management page - */ -export function createAnomalyDetectionJobManagementUrl( - appBasePath: string, - params: AnomalyDetectionUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE}`; - if (!params || isEmpty(params)) { - return url; - } - const { jobId, groupIds, globalState } = params; - if (jobId || groupIds) { - const queryTextArr = []; - if (jobId) { - queryTextArr.push(getJobQueryText(jobId)); - } - if (groupIds) { - queryTextArr.push(getGroupQueryText(groupIds)); - } - const jobsListState: Partial = { - ...(queryTextArr.length > 0 ? { queryText: queryTextArr.join(' ') } : {}), - }; - - const queryState: AppPageState = { - [ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE]: jobsListState, - }; - - url = setStateToKbnUrl>( - '_a', - queryState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - - if (globalState) { - url = setStateToKbnUrl>( - '_g', - globalState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - return url; -} - -export function createAnomalyDetectionCreateJobSelectType( - appBasePath: string, - pageState: MlGenericUrlState['pageState'] -): string { - return createGenericMlUrl( - appBasePath, - ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, - pageState - ); -} - -export function createAnomalyDetectionCreateJobSelectIndex( - appBasePath: string, - pageState: MlGenericUrlState['pageState'] -): string { - return createGenericMlUrl( - appBasePath, - ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX, - pageState - ); -} - -/** - * Creates URL to the Anomaly Explorer page - */ -export function createExplorerUrl( - appBasePath: string, - params: ExplorerUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.ANOMALY_EXPLORER}`; - - if (!params) { - return url; - } - const { - refreshInterval, - timeRange, - jobIds, - query, - mlExplorerSwimlane = {}, - mlExplorerFilter = {}, - globalState, - } = params; - const appState: Partial = { - mlExplorerSwimlane, - mlExplorerFilter, - }; - let queryState: Partial = {}; - if (globalState) queryState = globalState; - if (query) appState.query = query; - if (jobIds) { - queryState.ml = { - jobIds, - }; - } - if (refreshInterval) queryState.refreshInterval = refreshInterval; - if (timeRange) queryState.time = timeRange; - - url = setStateToKbnUrl>( - '_g', - queryState, - { useHash: false, storeInHashQuery: false }, - url - ); - url = setStateToKbnUrl>>( - '_a', - { [ML_PAGES.ANOMALY_EXPLORER]: appState }, - { useHash: false, storeInHashQuery: false }, - url - ); - - return url; -} - -/** - * Creates URL to the SingleMetricViewer page - */ -export function createSingleMetricViewerUrl( - appBasePath: string, - params: TimeSeriesExplorerUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.SINGLE_METRIC_VIEWER}`; - if (!params) { - return url; - } - const { - timeRange, - jobIds, - refreshInterval, - query, - detectorIndex, - forecastId, - entities, - globalState, - functionDescription, - zoom, - } = params; - - let queryState: Partial = {}; - if (globalState) queryState = globalState; - - if (jobIds) { - queryState.ml = { - jobIds, - }; - } - if (refreshInterval) queryState.refreshInterval = refreshInterval; - if (timeRange) queryState.time = timeRange; - - const appState: Partial = {}; - const mlTimeSeriesExplorer: Partial = {}; - - if (forecastId !== undefined) { - mlTimeSeriesExplorer.forecastId = forecastId; - } - - if (detectorIndex !== undefined) { - mlTimeSeriesExplorer.detectorIndex = detectorIndex; - } - if (entities !== undefined) { - mlTimeSeriesExplorer.entities = entities; - } - if (functionDescription !== undefined) { - mlTimeSeriesExplorer.functionDescription = functionDescription; - } - - if (zoom !== undefined) { - mlTimeSeriesExplorer.zoom = zoom; - } - - appState.mlTimeSeriesExplorer = mlTimeSeriesExplorer; - - if (query) - appState.query = { - query_string: query, - }; - url = setStateToKbnUrl>( - '_g', - queryState, - { useHash: false, storeInHashQuery: false }, - url - ); - url = setStateToKbnUrl>>( - '_a', - { [ML_PAGES.SINGLE_METRIC_VIEWER]: appState }, - { useHash: false, storeInHashQuery: false }, - url - ); - - return url; -} diff --git a/x-pack/plugins/ml/public/ml_url_generator/common.ts b/x-pack/plugins/ml/public/ml_url_generator/common.ts deleted file mode 100644 index 8df45f47cc8aa4..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/common.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { isEmpty } from 'lodash'; -import { MlGenericUrlState } from '../../common/types/ml_url_generator'; -import { setStateToKbnUrl } from '../../../../../src/plugins/kibana_utils/public'; - -export function extractParams(urlState: UrlState) { - // page should be guaranteed to exist here but is unknown - // @ts-ignore - const { page, ...params } = urlState; - return { page, params }; -} - -/** - * Creates generic index based search ML url - * e.g. `jobs/new_job/datavisualizer?index=3da93760-e0af-11ea-9ad3-3bcfc330e42a` - */ -export function createGenericMlUrl( - appBasePath: string, - page: MlGenericUrlState['page'], - pageState: MlGenericUrlState['pageState'] -): string { - let url = `${appBasePath}/${page}`; - - if (pageState) { - const { globalState, appState, index, savedSearchId, ...restParams } = pageState; - if (index !== undefined && savedSearchId === undefined) { - url = `${url}?index=${index}`; - } - if (index === undefined && savedSearchId !== undefined) { - url = `${url}?savedSearchId=${savedSearchId}`; - } - - if (!isEmpty(restParams)) { - Object.keys(restParams).forEach((key) => { - url = setStateToKbnUrl( - key, - restParams[key], - { useHash: false, storeInHashQuery: false }, - url - ); - }); - } - - if (globalState) { - url = setStateToKbnUrl('_g', globalState, { useHash: false, storeInHashQuery: false }, url); - } - if (appState) { - url = setStateToKbnUrl('_a', appState, { useHash: false, storeInHashQuery: false }, url); - } - } - - return url; -} diff --git a/x-pack/plugins/ml/public/ml_url_generator/data_frame_analytics_urls_generator.ts b/x-pack/plugins/ml/public/ml_url_generator/data_frame_analytics_urls_generator.ts deleted file mode 100644 index c0890e600aaad1..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/data_frame_analytics_urls_generator.ts +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/** - * Creates URL to the DataFrameAnalytics page - */ -import { isEmpty } from 'lodash'; -import { - DataFrameAnalyticsExplorationQueryState, - DataFrameAnalyticsExplorationUrlState, - DataFrameAnalyticsUrlState, - ExplorationPageUrlState, - MlGenericUrlState, - MlCommonGlobalState, -} from '../../common/types/ml_url_generator'; -import { createGenericMlUrl } from './common'; -import { ML_PAGES } from '../../common/constants/ml_url_generator'; -import { setStateToKbnUrl } from '../../../../../src/plugins/kibana_utils/public'; -import { getGroupQueryText, getJobQueryText } from '../../common/util/string_utils'; -import { AppPageState, ListingPageUrlState } from '../../common/types/common'; - -export function createDataFrameAnalyticsJobManagementUrl( - appBasePath: string, - mlUrlGeneratorState: DataFrameAnalyticsUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE}`; - - if (mlUrlGeneratorState) { - const { jobId, groupIds, globalState } = mlUrlGeneratorState; - if (jobId || groupIds) { - const queryTextArr = []; - if (jobId) { - queryTextArr.push(getJobQueryText(jobId)); - } - if (groupIds) { - queryTextArr.push(getGroupQueryText(groupIds)); - } - const jobsListState: Partial = { - ...(queryTextArr.length > 0 ? { queryText: queryTextArr.join(' ') } : {}), - }; - - const queryState: AppPageState = { - [ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE]: jobsListState, - }; - - url = setStateToKbnUrl>( - '_a', - queryState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - if (globalState) { - url = setStateToKbnUrl>( - '_g', - globalState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - } - - return url; -} - -/** - * Creates URL to the DataFrameAnalytics Exploration page - */ -export function createDataFrameAnalyticsExplorationUrl( - appBasePath: string, - mlUrlGeneratorState: DataFrameAnalyticsExplorationUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION}`; - - if (mlUrlGeneratorState) { - const { jobId, analysisType, queryText, globalState } = mlUrlGeneratorState; - - const queryState: DataFrameAnalyticsExplorationQueryState = { - ml: { - jobId, - analysisType, - }, - ...globalState, - }; - - const appState = { - [ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION]: { - ...(queryText ? { queryText } : {}), - }, - }; - - if (!isEmpty(appState[ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION])) { - url = setStateToKbnUrl>( - '_a', - appState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - - url = setStateToKbnUrl( - '_g', - queryState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - - return url; -} - -/** - * Creates URL to the DataFrameAnalytics creation wizard - */ -export function createDataFrameAnalyticsCreateJobUrl( - appBasePath: string, - pageState: MlGenericUrlState['pageState'] -): string { - return createGenericMlUrl(appBasePath, ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, pageState); -} - -/** - * Creates URL to the DataFrameAnalytics Map page - */ -export function createDataFrameAnalyticsMapUrl( - appBasePath: string, - mlUrlGeneratorState: DataFrameAnalyticsExplorationUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.DATA_FRAME_ANALYTICS_MAP}`; - - if (mlUrlGeneratorState) { - const { jobId, modelId, analysisType, globalState, queryText } = mlUrlGeneratorState; - - const queryState: DataFrameAnalyticsExplorationQueryState = { - ml: { - jobId, - modelId, - analysisType, - }, - ...globalState, - }; - - const appState = { - [ML_PAGES.DATA_FRAME_ANALYTICS_MAP]: { - ...(queryText ? { queryText } : {}), - }, - }; - - if (!isEmpty(appState[ML_PAGES.DATA_FRAME_ANALYTICS_MAP])) { - url = setStateToKbnUrl>( - '_a', - appState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - - url = setStateToKbnUrl( - '_g', - queryState, - { useHash: false, storeInHashQuery: false }, - url - ); - } - - return url; -} diff --git a/x-pack/plugins/ml/public/ml_url_generator/index.ts b/x-pack/plugins/ml/public/ml_url_generator/index.ts deleted file mode 100644 index d4b92cf9f72148..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export { MlUrlGenerator, registerUrlGenerator } from './ml_url_generator'; -export { useMlHref } from './use_ml_href'; -export { ML_PAGES } from '../../common/constants/ml_url_generator'; diff --git a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts deleted file mode 100644 index f7848e2eb8c4f2..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.test.ts +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { MlUrlGenerator } from './ml_url_generator'; -import { ML_PAGES } from '../../common/constants/ml_url_generator'; -import { ANALYSIS_CONFIG_TYPE } from '../../common/constants/data_frame_analytics'; - -describe('MlUrlGenerator', () => { - const urlGenerator = new MlUrlGenerator({ - appBasePath: '/app/ml', - }); - - describe('AnomalyDetection', () => { - describe('Job Management Page', () => { - it('should generate valid URL for the Anomaly Detection job management page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - }); - expect(url).toBe('/app/ml/jobs'); - }); - - it('should generate valid URL for the Anomaly Detection job management page for job', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - pageState: { - jobId: 'fq_single_1', - }, - }); - expect(url).toBe("/app/ml/jobs?_a=(jobs:(queryText:'id:fq_single_1'))"); - }); - - it('should generate valid URL for the Anomaly Detection job management page for groupIds', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - pageState: { - groupIds: ['farequote', 'categorization'], - }, - }); - expect(url).toBe( - "/app/ml/jobs?_a=(jobs:(queryText:'groups:(farequote%20or%20categorization)'))" - ); - }); - - it('should generate valid URL for the page for selecting the type of anomaly detection job to create', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, - pageState: { - index: `3da93760-e0af-11ea-9ad3-3bcfc330e42a`, - globalState: { - time: { - from: 'now-30m', - to: 'now', - }, - }, - }, - }); - expect(url).toBe( - '/app/ml/jobs/new_job/step/job_type?index=3da93760-e0af-11ea-9ad3-3bcfc330e42a&_g=(time:(from:now-30m,to:now))' - ); - }); - }); - - describe('Anomaly Explorer Page', () => { - it('should generate valid URL for the Anomaly Explorer page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_EXPLORER, - pageState: { - jobIds: ['fq_single_1'], - mlExplorerSwimlane: { viewByFromPage: 2, viewByPerPage: 20 }, - refreshInterval: { - pause: false, - value: 0, - }, - timeRange: { - from: '2019-02-07T00:00:00.000Z', - to: '2020-08-13T17:15:00.000Z', - mode: 'absolute', - }, - query: { - analyze_wildcard: true, - query: '*', - }, - }, - }); - expect(url).toBe( - "/app/ml/explorer?_g=(ml:(jobIds:!(fq_single_1)),refreshInterval:(pause:!f,value:0),time:(from:'2019-02-07T00:00:00.000Z',mode:absolute,to:'2020-08-13T17:15:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:(viewByFromPage:2,viewByPerPage:20),query:(analyze_wildcard:!t,query:'*')))" - ); - }); - it('should generate valid URL for the Anomaly Explorer page for multiple jobIds', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.ANOMALY_EXPLORER, - pageState: { - jobIds: ['fq_single_1', 'logs_categorization_1'], - timeRange: { - from: '2019-02-07T00:00:00.000Z', - to: '2020-08-13T17:15:00.000Z', - mode: 'absolute', - }, - }, - }); - expect(url).toBe( - "/app/ml/explorer?_g=(ml:(jobIds:!(fq_single_1,logs_categorization_1)),time:(from:'2019-02-07T00:00:00.000Z',mode:absolute,to:'2020-08-13T17:15:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))" - ); - }); - }); - - describe('Single Metric Viewer Page', () => { - it('should generate valid URL for the Single Metric Viewer page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.SINGLE_METRIC_VIEWER, - pageState: { - jobIds: ['logs_categorization_1'], - refreshInterval: { - pause: false, - value: 0, - }, - timeRange: { - from: '2020-07-12T00:39:02.912Z', - to: '2020-07-22T15:52:18.613Z', - mode: 'absolute', - }, - query: { - analyze_wildcard: true, - query: '*', - }, - }, - }); - expect(url).toBe( - "/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(logs_categorization_1)),refreshInterval:(pause:!f,value:0),time:(from:'2020-07-12T00:39:02.912Z',mode:absolute,to:'2020-07-22T15:52:18.613Z'))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(),query:(query_string:(analyze_wildcard:!t,query:'*'))))" - ); - }); - - it('should generate valid URL for the Single Metric Viewer page with extra settings', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.SINGLE_METRIC_VIEWER, - pageState: { - jobIds: ['logs_categorization_1'], - detectorIndex: 0, - entities: { mlcategory: '2' }, - refreshInterval: { - pause: false, - value: 0, - }, - timeRange: { - from: '2020-07-12T00:39:02.912Z', - to: '2020-07-22T15:52:18.613Z', - mode: 'absolute', - }, - zoom: { - from: '2020-07-20T23:58:29.367Z', - to: '2020-07-21T11:00:13.173Z', - }, - query: { - analyze_wildcard: true, - query: '*', - }, - }, - }); - expect(url).toBe( - "/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(logs_categorization_1)),refreshInterval:(pause:!f,value:0),time:(from:'2020-07-12T00:39:02.912Z',mode:absolute,to:'2020-07-22T15:52:18.613Z'))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(detectorIndex:0,entities:(mlcategory:'2'),zoom:(from:'2020-07-20T23:58:29.367Z',to:'2020-07-21T11:00:13.173Z')),query:(query_string:(analyze_wildcard:!t,query:'*'))))" - ); - }); - }); - }); - - describe('DataFrameAnalytics', () => { - describe('JobManagement Page', () => { - it('should generate valid URL for the Data Frame Analytics job management page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE, - }); - expect(url).toBe('/app/ml/data_frame_analytics'); - }); - it('should generate valid URL for the Data Frame Analytics job management page with jobId', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE, - pageState: { - jobId: 'grid_regression_1', - }, - }); - expect(url).toBe( - "/app/ml/data_frame_analytics?_a=(data_frame_analytics:(queryText:'id:grid_regression_1'))" - ); - }); - - it('should generate valid URL for the Data Frame Analytics job management page with groupIds', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE, - pageState: { - groupIds: ['group_1', 'group_2'], - }, - }); - expect(url).toBe( - "/app/ml/data_frame_analytics?_a=(data_frame_analytics:(queryText:'groups:(group_1%20or%20group_2)'))" - ); - }); - }); - - describe('ExplorationPage', () => { - it('should generate valid URL for the Data Frame Analytics exploration page for job', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION, - pageState: { - jobId: 'grid_regression_1', - analysisType: ANALYSIS_CONFIG_TYPE.REGRESSION, - }, - }); - expect(url).toBe( - '/app/ml/data_frame_analytics/exploration?_g=(ml:(analysisType:regression,jobId:grid_regression_1))' - ); - }); - }); - }); - - describe('DataVisualizer', () => { - it('should generate valid URL for the Data Visualizer page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_VISUALIZER, - }); - expect(url).toBe('/app/ml/datavisualizer'); - }); - - it('should generate valid URL for the File Data Visualizer import page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_VISUALIZER_FILE, - }); - expect(url).toBe('/app/ml/filedatavisualizer'); - }); - - it('should generate valid URL for the Index Data Visualizer select index pattern or saved search page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_VISUALIZER_INDEX_SELECT, - }); - expect(url).toBe('/app/ml/datavisualizer_index_select'); - }); - - it('should generate valid URL for the Index Data Visualizer Viewer page', async () => { - const url = await urlGenerator.createUrl({ - page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, - pageState: { - index: '3da93760-e0af-11ea-9ad3-3bcfc330e42a', - globalState: { - time: { - from: 'now-30m', - to: 'now', - }, - }, - }, - }); - expect(url).toBe( - '/app/ml/jobs/new_job/datavisualizer?index=3da93760-e0af-11ea-9ad3-3bcfc330e42a&_g=(time:(from:now-30m,to:now))' - ); - }); - }); - - it('should throw an error in case the page is not provided', async () => { - expect.assertions(1); - - // @ts-ignore - await urlGenerator.createUrl({ jobIds: ['test-job'] }).catch((e) => { - expect(e.message).toEqual('Page type is not provided or unknown'); - }); - }); -}); diff --git a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts b/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts deleted file mode 100644 index b5c130a64990d4..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/ml_url_generator.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { CoreSetup } from 'kibana/public'; -import type { - SharePluginSetup, - UrlGeneratorsDefinition, - UrlGeneratorState, -} from '../../../../../src/plugins/share/public'; -import type { MlStartDependencies } from '../plugin'; -import { ML_PAGES, ML_APP_URL_GENERATOR } from '../../common/constants/ml_url_generator'; -import type { - DataFrameAnalyticsExplorationUrlState, - MlUrlGeneratorState, -} from '../../common/types/ml_url_generator'; -import { - createAnomalyDetectionJobManagementUrl, - createAnomalyDetectionCreateJobSelectType, - createAnomalyDetectionCreateJobSelectIndex, - createExplorerUrl, - createSingleMetricViewerUrl, -} from './anomaly_detection_urls_generator'; -import { - createDataFrameAnalyticsJobManagementUrl, - createDataFrameAnalyticsCreateJobUrl, - createDataFrameAnalyticsExplorationUrl, - createDataFrameAnalyticsMapUrl, -} from './data_frame_analytics_urls_generator'; -import { createGenericMlUrl } from './common'; -import { createEditCalendarUrl, createEditFilterUrl } from './settings_urls_generator'; - -declare module '../../../../../src/plugins/share/public' { - export interface UrlGeneratorStateMapping { - [ML_APP_URL_GENERATOR]: UrlGeneratorState; - } -} - -interface Params { - appBasePath: string; -} - -export class MlUrlGenerator implements UrlGeneratorsDefinition { - constructor(private readonly params: Params) {} - - public readonly id = ML_APP_URL_GENERATOR; - - public readonly createUrl = async ( - mlUrlGeneratorParams: MlUrlGeneratorState - ): Promise => { - const { excludeBasePath, ...mlUrlGeneratorState } = mlUrlGeneratorParams; - const appBasePath = excludeBasePath === true ? '' : this.params.appBasePath; - - switch (mlUrlGeneratorState.page) { - case ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE: - return createAnomalyDetectionJobManagementUrl(appBasePath, mlUrlGeneratorState.pageState); - case ML_PAGES.ANOMALY_EXPLORER: - return createExplorerUrl(appBasePath, mlUrlGeneratorState.pageState); - case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE: - return createAnomalyDetectionCreateJobSelectType( - appBasePath, - mlUrlGeneratorState.pageState - ); - case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX: - return createAnomalyDetectionCreateJobSelectIndex( - appBasePath, - mlUrlGeneratorState.pageState - ); - case ML_PAGES.SINGLE_METRIC_VIEWER: - return createSingleMetricViewerUrl(appBasePath, mlUrlGeneratorState.pageState); - case ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE: - return createDataFrameAnalyticsJobManagementUrl(appBasePath, mlUrlGeneratorState.pageState); - case ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB: - return createDataFrameAnalyticsCreateJobUrl(appBasePath, mlUrlGeneratorState.pageState); - case ML_PAGES.DATA_FRAME_ANALYTICS_MAP: - return createDataFrameAnalyticsMapUrl( - appBasePath, - mlUrlGeneratorState.pageState as DataFrameAnalyticsExplorationUrlState['pageState'] - ); - case ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION: - return createDataFrameAnalyticsExplorationUrl(appBasePath, mlUrlGeneratorState.pageState); - case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB: - case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED: - case ML_PAGES.DATA_VISUALIZER: - case ML_PAGES.DATA_VISUALIZER_FILE: - case ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER: - case ML_PAGES.DATA_VISUALIZER_INDEX_SELECT: - case ML_PAGES.OVERVIEW: - case ML_PAGES.SETTINGS: - case ML_PAGES.FILTER_LISTS_MANAGE: - case ML_PAGES.FILTER_LISTS_NEW: - case ML_PAGES.CALENDARS_MANAGE: - case ML_PAGES.CALENDARS_NEW: - case ML_PAGES.ACCESS_DENIED: - return createGenericMlUrl( - appBasePath, - mlUrlGeneratorState.page, - mlUrlGeneratorState.pageState - ); - case ML_PAGES.FILTER_LISTS_EDIT: - return createEditFilterUrl(appBasePath, mlUrlGeneratorState.pageState); - case ML_PAGES.CALENDARS_EDIT: - return createEditCalendarUrl(appBasePath, mlUrlGeneratorState.pageState); - - default: - throw new Error('Page type is not provided or unknown'); - } - }; -} - -/** - * Registers the URL generator - */ -export function registerUrlGenerator( - share: SharePluginSetup, - core: CoreSetup -) { - const baseUrl = core.http.basePath.prepend('/app/ml'); - return share.urlGenerators.registerUrlGenerator( - new MlUrlGenerator({ - appBasePath: baseUrl, - }) - ); -} diff --git a/x-pack/plugins/ml/public/ml_url_generator/settings_urls_generator.tsx b/x-pack/plugins/ml/public/ml_url_generator/settings_urls_generator.tsx deleted file mode 100644 index eb23e95bb8e59b..00000000000000 --- a/x-pack/plugins/ml/public/ml_url_generator/settings_urls_generator.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CalendarEditUrlState, FilterEditUrlState } from '../../common/types/ml_url_generator'; -import { ML_PAGES } from '../../common/constants/ml_url_generator'; -import { setStateToKbnUrl } from '../../../../../src/plugins/kibana_utils/public'; - -export function createEditCalendarUrl( - appBasePath: string, - pageState: CalendarEditUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.CALENDARS_EDIT}`; - if (pageState) { - const { globalState, calendarId } = pageState; - if (calendarId !== undefined) { - url = `${url}/${calendarId}`; - } - if (globalState) { - url = setStateToKbnUrl('_g', globalState, { useHash: false, storeInHashQuery: false }, url); - } - } - - return url; -} - -export function createEditFilterUrl( - appBasePath: string, - pageState: FilterEditUrlState['pageState'] -): string { - let url = `${appBasePath}/${ML_PAGES.FILTER_LISTS_EDIT}`; - if (pageState) { - const { globalState, filterId } = pageState; - if (filterId !== undefined) { - url = `${url}/${filterId}`; - } - if (globalState) { - url = setStateToKbnUrl('_g', globalState, { useHash: false, storeInHashQuery: false }, url); - } - } - - return url; -} diff --git a/x-pack/plugins/ml/public/mocks.ts b/x-pack/plugins/ml/public/mocks.ts index c3344f4fe3c618..c48e56974f4882 100644 --- a/x-pack/plugins/ml/public/mocks.ts +++ b/x-pack/plugins/ml/public/mocks.ts @@ -4,11 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { createMlUrlGeneratorMock } from './ml_url_generator/__mocks__/ml_url_generator'; + import { MlPluginSetup, MlPluginStart } from './plugin'; const createSetupContract = (): jest.Mocked => { return { - urlGenerator: createMlUrlGeneratorMock(), locator: { getLocation: jest.fn(), getUrl: jest.fn(), @@ -24,7 +23,6 @@ const createSetupContract = (): jest.Mocked => { const createStartContract = (): jest.Mocked => { return { - urlGenerator: createMlUrlGeneratorMock(), locator: { getLocation: jest.fn(), getUrl: jest.fn(), diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 920d6e8b66633a..1c2cc32063e888 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -17,11 +17,7 @@ import { BehaviorSubject } from 'rxjs'; import { take } from 'rxjs/operators'; import type { ManagementSetup } from 'src/plugins/management/public'; -import type { - SharePluginSetup, - SharePluginStart, - UrlGeneratorContract, -} from 'src/plugins/share/public'; +import type { SharePluginSetup, SharePluginStart } from 'src/plugins/share/public'; import type { DataPublicPluginStart } from 'src/plugins/data/public'; import type { HomePublicPluginSetup } from 'src/plugins/home/public'; import type { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public'; @@ -36,13 +32,10 @@ import type { LicensingPluginSetup } from '../../licensing/public'; import type { SecurityPluginSetup } from '../../security/public'; import { PLUGIN_ICON_SOLUTION, PLUGIN_ID } from '../common/constants/app'; -import { ML_APP_URL_GENERATOR } from '../common/constants/ml_url_generator'; import { isFullLicense, isMlEnabled } from '../common/license'; import { setDependencyCache } from './application/util/dependency_cache'; import { registerFeature } from './register_feature'; -// Not importing from `ml_url_generator/index` here to avoid importing unnecessary code -import { registerUrlGenerator } from './ml_url_generator/ml_url_generator'; import { MlLocatorDefinition, MlLocator } from './locator'; import type { MapsStartApi } from '../../maps/public'; import { @@ -86,10 +79,6 @@ export type MlCoreSetup = CoreSetup; export class MlPlugin implements Plugin { private appUpdater$ = new BehaviorSubject(() => ({})); - /** - * @deprecated Use locator instead. - */ - private urlGenerator: undefined | UrlGeneratorContract; private locator: undefined | MlLocator; constructor(private initializerContext: PluginInitializerContext) {} @@ -133,10 +122,6 @@ export class MlPlugin implements Plugin { }, }); - if (pluginsSetup.share) { - this.urlGenerator = registerUrlGenerator(pluginsSetup.share, core); - } - if (pluginsSetup.share) { this.locator = pluginsSetup.share.url.locators.create(new MlLocatorDefinition()); } @@ -189,10 +174,6 @@ export class MlPlugin implements Plugin { }); return { - /** - * @deprecated Use locator instead. - */ - urlGenerator: this.urlGenerator, locator: this.locator, }; } @@ -206,10 +187,6 @@ export class MlPlugin implements Plugin { }); return { - /** - * @deprecated Use locator instead. - */ - urlGenerator: this.urlGenerator, locator: this.locator, }; } diff --git a/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts b/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts index e6ffa3b530858d..693731562ee821 100644 --- a/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts +++ b/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { AppDeepLink } from 'src/core/public'; -import { ML_PAGES } from '../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../common/constants/locator'; const OVERVIEW_LINK_DEEP_LINK: AppDeepLink = { id: 'mlOverviewDeepLink', diff --git a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx index 7353502f95b47a..f844eb0d5d601d 100644 --- a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { createAction } from '../../../../../src/plugins/ui_actions/public'; import { MlCoreSetup } from '../plugin'; -import { ML_APP_URL_GENERATOR } from '../../common/constants/ml_url_generator'; +import { ML_APP_LOCATOR } from '../../common/constants/locator'; import { ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE, ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, @@ -18,7 +18,7 @@ import { SwimLaneDrilldownContext, } from '../embeddables'; import { ENTITY_FIELD_OPERATIONS } from '../../common/util/anomaly_utils'; -import { ExplorerAppState } from '../../common/types/ml_url_generator'; +import { ExplorerAppState } from '../../common/types/locator'; export const OPEN_IN_ANOMALY_EXPLORER_ACTION = 'openInAnomalyExplorerAction'; @@ -36,7 +36,7 @@ export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getSta }, async getHref(context): Promise { const [, pluginsStart] = await getStartServices(); - const urlGenerator = pluginsStart.share.urlGenerators.getUrlGenerator(ML_APP_URL_GENERATOR); + const locator = pluginsStart.share.url.locators.get(ML_APP_LOCATOR)!; if (isSwimLaneEmbeddable(context)) { const { embeddable, data } = context; @@ -44,7 +44,7 @@ export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getSta const { jobIds, timeRange, viewBy } = embeddable.getInput(); const { perPage, fromPage } = embeddable.getOutput(); - return urlGenerator.createUrl({ + return locator.getUrl({ page: 'explorer', pageState: { jobIds, @@ -98,7 +98,7 @@ export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getSta }; } } - return urlGenerator.createUrl({ + return locator.getUrl({ page: 'explorer', pageState: { jobIds, diff --git a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx index efd27865f7a832..013e5dcc500c7f 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx @@ -11,7 +11,8 @@ import { mockAnomalies } from '../mock'; import { cloneDeep } from 'lodash/fp'; import { ExplorerLink } from './create_explorer_link'; import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public/context'; -import { MlUrlGenerator } from '../../../../../../ml/public/ml_url_generator'; +import { MlLocatorDefinition } from '../../../../../../ml/public/locator'; +import { UrlService } from '../../../../../../../../src/plugins/share/common/url_service'; describe('create_explorer_link', () => { let anomalies = cloneDeep(mockAnomalies); @@ -21,7 +22,14 @@ describe('create_explorer_link', () => { }); test('it returns expected link', async () => { - const ml = { urlGenerator: new MlUrlGenerator({ appBasePath: '/app/ml' }) }; + const urlService = new UrlService({ + navigate: async () => {}, + getUrl: async ({ app, path }, { absolute }) => { + return `${absolute ? 'http://localhost:8888' : ''}/app/${app}${path}`; + }, + }); + const locator = urlService.locators.create(new MlLocatorDefinition()); + const ml = { locator }; const http = { basePath: { get: jest.fn(() => {}) } }; await act(async () => { diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index e6551947a735e4..231604e851e19d 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -37,8 +37,9 @@ import { } from '../../../../common/constants'; import { StartServices } from '../../../types'; import { createSecuritySolutionStorageMock } from '../../mock/mock_local_storage'; -import { MlUrlGenerator } from '../../../../../ml/public'; +import { MlLocatorDefinition } from '../../../../../ml/public'; import { EuiTheme } from '../../../../../../../src/plugins/kibana_react/common'; +import { UrlService } from 'src/plugins/share/common/url_service'; const mockUiSettings: Record = { [DEFAULT_TIME_RANGE]: { from: 'now-15m', to: 'now', mode: 'quick' }, @@ -93,6 +94,13 @@ export const createStartServicesMock = (): StartServices => { const { storage } = createSecuritySolutionStorageMock(); const data = dataPluginMock.createStartContract(); const security = securityMock.createSetup(); + const urlService = new UrlService({ + navigate: async () => {}, + getUrl: async ({ app, path }, { absolute }) => { + return `${absolute ? 'http://localhost:8888' : ''}/app/${app}${path}`; + }, + }); + const locator = urlService.locators.create(new MlLocatorDefinition()); return ({ ...core, @@ -139,9 +147,7 @@ export const createStartServicesMock = (): StartServices => { security, storage, ml: { - urlGenerator: new MlUrlGenerator({ - appBasePath: '/app/ml', - }), + locator, }, } as unknown) as StartServices; }; From 8259d227f459a845873b714fe05dc3b16eccb789 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 29 Jun 2021 21:10:30 +0200 Subject: [PATCH 12/23] =?UTF-8?q?fix:=20=F0=9F=90=9B=20correct=20type=20ch?= =?UTF-8?q?eck=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../anomaly_charts/embeddable_anomaly_charts_container.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx index 222b3fc9b78e96..3222ab582f1090 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/embeddable_anomaly_charts_container.tsx @@ -26,7 +26,7 @@ import { ANOMALY_THRESHOLD } from '../../../common'; import { UI_SETTINGS } from '../../../../../../src/plugins/data/common'; import { TimeBuckets } from '../../application/util/time_buckets'; import { EXPLORER_ENTITY_FIELD_SELECTION_TRIGGER } from '../../ui_actions/triggers'; -import { MlLocator } from '../../../common/types/locator'; +import { MlLocatorParams } from '../../../common/types/locator'; const RESIZE_THROTTLE_TIME_MS = 500; @@ -59,7 +59,9 @@ export const EmbeddableAnomalyChartsContainer: FC share.url.locators.get(ML_APP_LOCATOR)! as MlLocator, [share]); + const mlLocator = useMemo(() => share.url.locators.get(ML_APP_LOCATOR)!, [ + share, + ]); const timeBuckets = useMemo(() => { return new TimeBuckets({ From 16c0b98a513b409a97b5ce788e7f8d410601265e Mon Sep 17 00:00:00 2001 From: streamich Date: Wed, 30 Jun 2021 08:11:29 +0200 Subject: [PATCH 13/23] =?UTF-8?q?test:=20=F0=9F=92=8D=20add=20share=20plug?= =?UTF-8?q?in=20mock=20and=20use=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/share/public/mocks.ts | 47 +++++++++++++++++++ .../ml/public/__mocks__/ml_start_deps.ts | 5 +- ...ble_anomaly_charts_container.test.tsx.snap | 2 +- 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/plugins/share/public/mocks.ts diff --git a/src/plugins/share/public/mocks.ts b/src/plugins/share/public/mocks.ts new file mode 100644 index 00000000000000..2a978f8eca4037 --- /dev/null +++ b/src/plugins/share/public/mocks.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SharePluginSetup, SharePluginStart } from '.'; +import { UrlService } from '../common/url_service'; + +export type Setup = jest.Mocked; +export type Start = jest.Mocked; + +const url = new UrlService({ + navigate: async () => {}, + getUrl: async ({ app, path }, { absolute }) => { + return `${absolute ? 'http://localhost:8888' : ''}/app/${app}${path}`; + }, +}); + +const createSetupContract = (): Setup => { + const setupContract: Setup = { + register: jest.fn(), + urlGenerators: { + registerUrlGenerator: jest.fn(), + }, + url, + }; + return setupContract; +}; + +const createStartContract = (): Start => { + const startContract: Start = { + url, + urlGenerators: { + getUrlGenerator: jest.fn(), + }, + toggleShareContextMenu: jest.fn(), + }; + return startContract; +}; + +export const sharePluginMock = { + createSetupContract, + createStartContract, +}; diff --git a/x-pack/plugins/ml/public/__mocks__/ml_start_deps.ts b/x-pack/plugins/ml/public/__mocks__/ml_start_deps.ts index f16ba275246704..4bbbe10df7f6c3 100644 --- a/x-pack/plugins/ml/public/__mocks__/ml_start_deps.ts +++ b/x-pack/plugins/ml/public/__mocks__/ml_start_deps.ts @@ -8,14 +8,13 @@ import { uiActionsPluginMock } from '../../../../../src/plugins/ui_actions/public/mocks'; import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; import { kibanaLegacyPluginMock } from '../../../../../src/plugins/kibana_legacy/public/mocks'; +import { sharePluginMock } from '../../../../../src/plugins/share/public/mocks'; import { embeddablePluginMock } from '../../../../../src/plugins/embeddable/public/mocks'; import { triggersActionsUiMock } from '../../../triggers_actions_ui/public/mocks'; export const createMlStartDepsMock = () => ({ data: dataPluginMock.createStartContract(), - share: { - urlGenerators: { getUrlGenerator: jest.fn() }, - }, + share: sharePluginMock.createStartContract(), kibanaLegacy: kibanaLegacyPluginMock.createStartContract(), uiActions: uiActionsPluginMock.createStartContract(), spaces: jest.fn(), diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/__snapshots__/embeddable_anomaly_charts_container.test.tsx.snap b/x-pack/plugins/ml/public/embeddables/anomaly_charts/__snapshots__/embeddable_anomaly_charts_container.test.tsx.snap index e0246439abe57f..52318c80d5d08d 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/__snapshots__/embeddable_anomaly_charts_container.test.tsx.snap +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/__snapshots__/embeddable_anomaly_charts_container.test.tsx.snap @@ -10,7 +10,7 @@ Object { "tooManyBuckets": false, }, "id": "test-explorer-charts-embeddable", - "mlUrlGenerator": undefined, + "mlLocator": undefined, "onSelectEntity": [Function], "setSeverity": [Function], "severity": Object { From 802f7a2054b9fd5033e84a6455fddd9ba523d012 Mon Sep 17 00:00:00 2001 From: streamich Date: Wed, 30 Jun 2021 08:14:06 +0200 Subject: [PATCH 14/23] =?UTF-8?q?test:=20=F0=9F=92=8D=20update=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../anomaly_results_view_selector.test.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx b/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx index 789a0199d07501..84ad7dc7ca9992 100644 --- a/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx +++ b/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx @@ -16,8 +16,15 @@ import { AnomalyResultsViewSelector } from './index'; jest.mock('../../contexts/kibana', () => { return { - useMlUrlGenerator: () => ({ - createUrl: jest.fn(), + useMlLocator: () => ({ + getLocation: jest.fn(), + getUrl: jest.fn(), + useUrl: jest.fn(), + navigate: jest.fn(), + extract: jest.fn(), + inject: jest.fn(), + telemetry: jest.fn(), + migrations: {}, }), useNavigateToPath: () => jest.fn(), }; From 2d7c96a6544201b3b32380cd6021766ef56e8aaf Mon Sep 17 00:00:00 2001 From: Quynh Nguyen Date: Wed, 30 Jun 2021 12:50:45 -0500 Subject: [PATCH 15/23] Remove usage of excludeBasePath --- x-pack/plugins/ml/common/types/locator.ts | 6 +- .../annotations_table/annotations_table.js | 43 +++++++------ .../components/anomalies_table/links_menu.js | 52 ++++++++-------- .../contexts/kibana/use_create_url.ts | 7 ++- .../explorer_no_jobs_found.js | 25 ++++---- .../explorer_charts_container.js | 5 +- .../forecasts_table/forecasts_table.js | 60 +++++++++---------- .../ml/public/application/util/chart_utils.js | 54 +++++++++-------- .../application/util/recently_accessed.ts | 1 - 9 files changed, 124 insertions(+), 129 deletions(-) diff --git a/x-pack/plugins/ml/common/types/locator.ts b/x-pack/plugins/ml/common/types/locator.ts index 780787da53fca4..033df249fccce8 100644 --- a/x-pack/plugins/ml/common/types/locator.ts +++ b/x-pack/plugins/ml/common/types/locator.ts @@ -18,10 +18,10 @@ import { ML_PAGES } from '../constants/locator'; type OptionalPageState = object | undefined; export type MLPageState = PageState extends OptionalPageState - ? { page: PageType; pageState?: PageState; excludeBasePath?: boolean } + ? { page: PageType; pageState?: PageState } : PageState extends object - ? { page: PageType; pageState: PageState; excludeBasePath?: boolean } - : { page: PageType; excludeBasePath?: boolean }; + ? { page: PageType; pageState: PageState } + : { page: PageType }; export interface MlCommonGlobalState { time?: TimeRange; diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js index 9dcd1a1a9e6833..7d461c4ec8572a 100644 --- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js +++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js @@ -48,7 +48,6 @@ import { } from '../../../../../common/constants/annotations'; import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { ML_APP_LOCATOR, ML_PAGES } from '../../../../../common/constants/locator'; -import { PLUGIN_ID } from '../../../../../common/constants/app'; import { timeFormatter } from '../../../../../common/util/date_utils'; import { MlAnnotationUpdatesContext } from '../../../contexts/ml/ml_annotation_updates_context'; import { DatafeedChartFlyout } from '../../../jobs/jobs_list/components/datafeed_chart_flyout'; @@ -202,7 +201,7 @@ class AnnotationsTableUI extends Component { openSingleMetricView = async (annotation = {}) => { const { services: { - application: { navigateToApp }, + application: { navigateToUrl }, share, }, } = this.props.kibana; @@ -264,31 +263,31 @@ class AnnotationsTableUI extends Component { // appState.mlTimeSeriesExplorer = mlTimeSeriesExplorer; const mlLocator = share.url.locators.get(ML_APP_LOCATOR); - const singleMetricViewerLink = await mlLocator.getUrl({ - page: ML_PAGES.SINGLE_METRIC_VIEWER, - pageState: { - timeRange, - refreshInterval: { - display: 'Off', - pause: true, - value: 0, - }, - jobIds: [job.job_id], - query: { - query_string: { - analyze_wildcard: true, - query: '*', + const singleMetricViewerLink = await mlLocator.getUrl( + { + page: ML_PAGES.SINGLE_METRIC_VIEWER, + pageState: { + timeRange, + refreshInterval: { + display: 'Off', + pause: true, + value: 0, + }, + jobIds: [job.job_id], + query: { + query_string: { + analyze_wildcard: true, + query: '*', + }, }, + ...mlTimeSeriesExplorer, }, - ...mlTimeSeriesExplorer, }, - excludeBasePath: true, - }); + { absolute: true } + ); addItemToRecentlyAccessed('timeseriesexplorer', job.job_id, singleMetricViewerLink); - await navigateToApp(PLUGIN_ID, { - path: singleMetricViewerLink, - }); + await navigateToUrl(singleMetricViewerLink); }; onMouseOverRow = (record) => { diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js index 26c91a2ebec324..1c4760db5d640d 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js @@ -178,33 +178,35 @@ class LinksMenuUI extends Component { entityCondition[record.by_field_name] = record.by_field_value; } - const singleMetricViewerLink = await mlLocator.getUrl({ - excludeBasePath: false, - page: ML_PAGES.SINGLE_METRIC_VIEWER, - pageState: { - jobIds: [record.job_id], - refreshInterval: { - display: 'Off', - pause: true, - value: 0, - }, - timeRange: { - from: from, - to: to, - mode: 'absolute', - }, - zoom: { - from: zoomFrom, - to: zoomTo, - }, - detectorIndex: record.detector_index, - entities: entityCondition, - query_string: { - analyze_wildcard: true, - query: '*', + const singleMetricViewerLink = await mlLocator.getUrl( + { + page: ML_PAGES.SINGLE_METRIC_VIEWER, + pageState: { + jobIds: [record.job_id], + refreshInterval: { + display: 'Off', + pause: true, + value: 0, + }, + timeRange: { + from: from, + to: to, + mode: 'absolute', + }, + zoom: { + from: zoomFrom, + to: zoomTo, + }, + detectorIndex: record.detector_index, + entities: entityCondition, + query_string: { + analyze_wildcard: true, + query: '*', + }, }, }, - }); + { absolute: true } + ); window.open(singleMetricViewerLink, '_blank'); }; diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts b/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts index c84b9848dfcaeb..c8810545a57d51 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts @@ -10,6 +10,7 @@ import { useMlKibana } from './kibana_context'; import { ML_APP_LOCATOR } from '../../../../common/constants/locator'; import { MlLocatorParams } from '../../../../common/types/locator'; import { useUrlState } from '../../util/url_state'; +import { LocatorGetUrlParams } from '../../../../../../../src/plugins/share/common/url_service'; export const useMlLocator = () => { const { @@ -19,7 +20,7 @@ export const useMlLocator = () => { return share.url.locators.get(ML_APP_LOCATOR); }; -export const useMlLink = (params: MlLocatorParams): string => { +export const useMlLink = (params: MlLocatorParams, getUrlParams?: LocatorGetUrlParams): string => { const [href, setHref] = useState(params.page); const mlLocator = useMlLocator(); @@ -27,7 +28,7 @@ export const useMlLink = (params: MlLocatorParams): string => { let isCancelled = false; const generateUrl = async (_params: MlLocatorParams) => { if (mlLocator) { - const url = await mlLocator.getUrl(_params); + const url = await mlLocator.getUrl(_params, getUrlParams); if (!isCancelled) { setHref(url); } @@ -37,7 +38,7 @@ export const useMlLink = (params: MlLocatorParams): string => { return () => { isCancelled = true; }; - }, [params]); + }, [params, getUrlParams]); return href; }; diff --git a/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js b/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js index 466852ed88840c..854caedd1a25f7 100644 --- a/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js +++ b/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/explorer_no_jobs_found.js @@ -8,7 +8,6 @@ /* * React component for rendering EuiEmptyPrompt when no jobs were found. */ -import { Link } from 'react-router-dom'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiEmptyPrompt, EuiButton } from '@elastic/eui'; @@ -16,10 +15,12 @@ import { ML_PAGES } from '../../../../../common/constants/locator'; import { useMlLink } from '../../../contexts/kibana/use_create_url'; export const ExplorerNoJobsFound = () => { - const ADJobsManagementUrl = useMlLink({ - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - excludeBasePath: true, - }); + const ADJobsManagementUrl = useMlLink( + { + page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + }, + { absolute: true } + ); return ( { } actions={ - - - - - + + + } data-test-subj="mlNoJobsFound" /> diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js index 22628c726b23bb..c714b388c826f3 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js @@ -66,7 +66,6 @@ function ExplorerChartContainer({ tooManyBuckets, wrapLabel, mlLocator, - basePath, timeBuckets, timefilter, onSelectEntity, @@ -159,7 +158,7 @@ function ExplorerChartContainer({ iconSide="right" iconType="visLine" size="xs" - href={`${basePath}/app/ml${explorerSeriesLink}`} + href={explorerSeriesLink} onClick={addToRecentlyAccessed} > @@ -241,7 +240,6 @@ export const ExplorerChartsContainerUI = ({ const { services: { chrome: { recentlyAccessed }, - http: { basePath }, embeddable: embeddablePlugin, maps: mapsPlugin, }, @@ -290,7 +288,6 @@ export const ExplorerChartsContainerUI = ({ tooManyBuckets={tooManyBuckets} wrapLabel={wrapLabel} mlLocator={mlLocator} - basePath={basePath.get()} timeBuckets={timeBuckets} timefilter={timefilter} onSelectEntity={onSelectEntity} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js index 019aa5ec5e5e81..9dac1a6a0d2612 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js @@ -29,8 +29,7 @@ import { isTimeSeriesViewJob, } from '../../../../../../../common/util/job_utils'; import { withKibana } from '../../../../../../../../../../src/plugins/kibana_react/public'; -import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../../../../../../common/constants/locator'; -import { PLUGIN_ID } from '../../../../../../../common/constants/app'; +import { ML_APP_LOCATOR, ML_PAGES } from '../../../../../../../common/constants/locator'; import { timeFormatter } from '../../../../../../../common/util/date_utils'; const MAX_FORECASTS = 500; @@ -83,11 +82,8 @@ export class ForecastsTableUI extends Component { async openSingleMetricView(forecast) { const { services: { - application: { navigateToApp }, - - share: { - urlGenerators: { getUrlGenerator }, - }, + application: { navigateToUrl }, + share, }, } = this.props.kibana; @@ -123,39 +119,39 @@ export class ForecastsTableUI extends Component { }; } - const mlUrlGenerator = getUrlGenerator(ML_APP_URL_GENERATOR); - const singleMetricViewerForecastLink = await mlUrlGenerator.createUrl({ - page: ML_PAGES.SINGLE_METRIC_VIEWER, - pageState: { - timeRange: { - from, - to, - mode: 'absolute', - }, - refreshInterval: { - display: 'Off', - pause: true, - value: 0, - }, - jobIds: [this.props.job.job_id], - query: { - query_string: { - analyze_wildcard: true, - query: '*', + const mlLocator = share.url.locators.get(ML_APP_LOCATOR); + const singleMetricViewerForecastLink = await mlLocator.getUrl( + { + page: ML_PAGES.SINGLE_METRIC_VIEWER, + pageState: { + timeRange: { + from, + to, + mode: 'absolute', }, + refreshInterval: { + display: 'Off', + pause: true, + value: 0, + }, + jobIds: [this.props.job.job_id], + query: { + query_string: { + analyze_wildcard: true, + query: '*', + }, + }, + ...mlTimeSeriesExplorer, }, - ...mlTimeSeriesExplorer, }, - excludeBasePath: true, - }); + { absolute: true } + ); addItemToRecentlyAccessed( 'timeseriesexplorer', this.props.job.job_id, singleMetricViewerForecastLink ); - await navigateToApp(PLUGIN_ID, { - path: singleMetricViewerForecastLink, - }); + await navigateToUrl(singleMetricViewerForecastLink); } render() { diff --git a/x-pack/plugins/ml/public/application/util/chart_utils.js b/x-pack/plugins/ml/public/application/util/chart_utils.js index 157b275cd38697..c8e7285d8a34df 100644 --- a/x-pack/plugins/ml/public/application/util/chart_utils.js +++ b/x-pack/plugins/ml/public/application/util/chart_utils.js @@ -241,35 +241,37 @@ export async function getExploreSeriesLink(mlLocator, series, timefilter) { }); } - const url = await mlLocator.getUrl({ - page: ML_PAGES.SINGLE_METRIC_VIEWER, - pageState: { - jobIds: [series.jobId], - refreshInterval: { - display: 'Off', - pause: true, - value: 0, - }, - timeRange: { - from: from, - to: to, - mode: 'absolute', - }, - zoom: { - from: zoomFrom, - to: zoomTo, - }, - detectorIndex: series.detectorIndex, - entities: entityCondition, - query: { - query_string: { - analyze_wildcard: true, - query: '*', + const url = await mlLocator.getUrl( + { + page: ML_PAGES.SINGLE_METRIC_VIEWER, + pageState: { + jobIds: [series.jobId], + refreshInterval: { + display: 'Off', + pause: true, + value: 0, + }, + timeRange: { + from: from, + to: to, + mode: 'absolute', + }, + zoom: { + from: zoomFrom, + to: zoomTo, + }, + detectorIndex: series.detectorIndex, + entities: entityCondition, + query: { + query_string: { + analyze_wildcard: true, + query: '*', + }, }, }, }, - excludeBasePath: true, - }); + { absolute: true } + ); return url; } diff --git a/x-pack/plugins/ml/public/application/util/recently_accessed.ts b/x-pack/plugins/ml/public/application/util/recently_accessed.ts index 88f78946bf7b4c..4ab3b3d9a73275 100644 --- a/x-pack/plugins/ml/public/application/util/recently_accessed.ts +++ b/x-pack/plugins/ml/public/application/util/recently_accessed.ts @@ -44,7 +44,6 @@ export function addItemToRecentlyAccessed( return; } - url = url.startsWith('/') ? `/app/ml${url}` : `/app/ml/${page}/${url}`; const recentlyAccessed = recentlyAccessedService ?? getRecentlyAccessed(); recentlyAccessed.add(url, `ML - ${itemId} - ${pageLabel}`, id); } From 10e148600d6d3a656b61b7c5eba0ef40a4fd459e Mon Sep 17 00:00:00 2001 From: Quynh Nguyen Date: Wed, 30 Jun 2021 13:49:18 -0500 Subject: [PATCH 16/23] Fix recently accessed url for create job to data visualizer --- .../jobs/new_job/pages/job_type/page.tsx | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx index 85c1880204c6a2..dd6eb80fee4a05 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx @@ -19,7 +19,7 @@ import { EuiLink, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { useNavigateToPath } from '../../../../contexts/kibana'; +import { useMlKibana, useNavigateToPath } from '../../../../contexts/kibana'; import { useMlContext } from '../../../../contexts/ml'; import { isSavedSearchSavedObject } from '../../../../../../common/types/kibana'; @@ -28,11 +28,15 @@ import { addItemToRecentlyAccessed } from '../../../../util/recently_accessed'; import { timeBasedIndexCheck } from '../../../../util/index_utils'; import { LinkCard } from '../../../../components/link_card'; import { CategorizationIcon } from './categorization_job_icon'; -import { ML_PAGES } from '../../../../../../common/constants/locator'; +import { ML_APP_LOCATOR, ML_PAGES } from '../../../../../../common/constants/locator'; import { RareIcon } from './rare_job_icon'; import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url'; export const Page: FC = () => { + const { + services: { share }, + } = useMlKibana(); + const mlContext = useMlContext(); const navigateToPath = useNavigateToPath(); const onSelectDifferentIndex = useCreateAndNavigateToMlLink( @@ -85,11 +89,25 @@ export const Page: FC = () => { : `?savedSearchId=${currentSavedSearch.id}`; }; - const addSelectionToRecentlyAccessed = () => { + const addSelectionToRecentlyAccessed = async () => { const title = !isSavedSearchSavedObject(currentSavedSearch) ? currentIndexPattern.title : (currentSavedSearch.attributes.title as string); - addItemToRecentlyAccessed('jobs/new_job/datavisualizer', title, ''); + const mlLocator = share.url.locators.get(ML_APP_LOCATOR)!; + + const dataVisualizerLink = await mlLocator.getUrl( + { + page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, + pageState: { + ...(currentSavedSearch?.id + ? { savedSearchId: currentSavedSearch.id } + : { index: currentIndexPattern.id }), + }, + }, + { absolute: true } + ); + + addItemToRecentlyAccessed(ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, title, dataVisualizerLink); navigateToPath(`/jobs/new_job/datavisualizer${getUrlParams()}`); }; From d3560582148fa7bd36fa01b225e84d3f3d7c9a18 Mon Sep 17 00:00:00 2001 From: streamich Date: Mon, 5 Jul 2021 16:47:41 +0200 Subject: [PATCH 17/23] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20rename=20inter?= =?UTF-8?q?face?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- x-pack/plugins/ml/common/types/locator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/common/types/locator.ts b/x-pack/plugins/ml/common/types/locator.ts index 033df249fccce8..9d294e1323f72d 100644 --- a/x-pack/plugins/ml/common/types/locator.ts +++ b/x-pack/plugins/ml/common/types/locator.ts @@ -243,7 +243,7 @@ export type ExplorationPageUrlState = { /** * Union type of ML URL state based on page */ -export type MlUrlGeneratorState = +export type MlLocatorState = | AnomalyDetectionUrlState | ExplorerUrlState | TimeSeriesExplorerUrlState @@ -253,6 +253,6 @@ export type MlUrlGeneratorState = | FilterEditUrlState | MlGenericUrlState; -export type MlLocatorParams = MlUrlGeneratorState & SerializableState; +export type MlLocatorParams = MlLocatorState & SerializableState; export type MlLocator = LocatorPublic; From 2efc999a9b6f241a4e83343c183aab00fcf6350e Mon Sep 17 00:00:00 2001 From: streamich Date: Mon, 5 Jul 2021 16:59:08 +0200 Subject: [PATCH 18/23] =?UTF-8?q?test:=20=F0=9F=92=8D=20move=20locator=20m?= =?UTF-8?q?ock=20into=20the=20share=20plugin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/share/public/mocks.ts | 17 ++++++++++++++++- .../anomaly_results_view_selector.test.tsx | 13 +++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/plugins/share/public/mocks.ts b/src/plugins/share/public/mocks.ts index 2a978f8eca4037..66c9a611a32d35 100644 --- a/src/plugins/share/public/mocks.ts +++ b/src/plugins/share/public/mocks.ts @@ -6,8 +6,9 @@ * Side Public License, v 1. */ +import { SerializableState } from 'src/plugins/kibana_utils/common'; import { SharePluginSetup, SharePluginStart } from '.'; -import { UrlService } from '../common/url_service'; +import { LocatorPublic, UrlService } from '../common/url_service'; export type Setup = jest.Mocked; export type Start = jest.Mocked; @@ -41,7 +42,21 @@ const createStartContract = (): Start => { return startContract; }; +const createLocator = (): jest.Mocked< + LocatorPublic +> => ({ + getLocation: jest.fn(), + getUrl: jest.fn(), + useUrl: jest.fn(), + navigate: jest.fn(), + extract: jest.fn(), + inject: jest.fn(), + telemetry: jest.fn(), + migrations: {}, +}); + export const sharePluginMock = { createSetupContract, createStartContract, + createLocator, }; diff --git a/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx b/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx index 84ad7dc7ca9992..2edf800d87bb79 100644 --- a/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx +++ b/x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.test.tsx @@ -16,16 +16,9 @@ import { AnomalyResultsViewSelector } from './index'; jest.mock('../../contexts/kibana', () => { return { - useMlLocator: () => ({ - getLocation: jest.fn(), - getUrl: jest.fn(), - useUrl: jest.fn(), - navigate: jest.fn(), - extract: jest.fn(), - inject: jest.fn(), - telemetry: jest.fn(), - migrations: {}, - }), + useMlLocator: () => + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('../../../../../../../src/plugins/share/public/mocks').sharePluginMock.createLocator(), useNavigateToPath: () => jest.fn(), }; }); From 0e5b0c4375ad2c42cbcd01eb71a457c444febbd9 Mon Sep 17 00:00:00 2001 From: streamich Date: Mon, 5 Jul 2021 17:00:37 +0200 Subject: [PATCH 19/23] =?UTF-8?q?test:=20=F0=9F=92=8D=20update=20Jest=20sn?= =?UTF-8?q?apshot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../explorer_no_jobs_found.test.js.snap | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/__snapshots__/explorer_no_jobs_found.test.js.snap b/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/__snapshots__/explorer_no_jobs_found.test.js.snap index 826f7b707cfdf6..8c874d8b03e796 100644 --- a/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/__snapshots__/explorer_no_jobs_found.test.js.snap +++ b/x-pack/plugins/ml/public/application/explorer/components/explorer_no_jobs_found/__snapshots__/explorer_no_jobs_found.test.js.snap @@ -3,20 +3,17 @@ exports[`ExplorerNoInfluencersFound snapshot 1`] = ` - - - - + + } data-test-subj="mlNoJobsFound" iconType="alert" From 701746958bfed995bbdb190b515dd4e651723aec Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 6 Jul 2021 15:17:06 +0200 Subject: [PATCH 20/23] =?UTF-8?q?test:=20=F0=9F=92=8D=20use=20shared=20URL?= =?UTF-8?q?=20service=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/share/common/url_service/mocks.ts | 2 +- .../components/ml/links/create_explorer_link.test.tsx | 9 ++------- .../public/common/lib/kibana/kibana_react.mock.ts | 8 ++------ 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/plugins/share/common/url_service/mocks.ts b/src/plugins/share/common/url_service/mocks.ts index be86cfe4017133..a4966e5a7b6e65 100644 --- a/src/plugins/share/common/url_service/mocks.ts +++ b/src/plugins/share/common/url_service/mocks.ts @@ -16,7 +16,7 @@ export class MockUrlService extends UrlService { super({ navigate: async () => {}, getUrl: async ({ app, path }, { absolute }) => { - return `${absolute ? 'https://example.com' : ''}/app/${app}${path}`; + return `${absolute ? 'http://localhost:8888' : ''}/app/${app}${path}`; }, }); } diff --git a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx index 013e5dcc500c7f..a0eaa79440859f 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx @@ -12,7 +12,7 @@ import { cloneDeep } from 'lodash/fp'; import { ExplorerLink } from './create_explorer_link'; import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public/context'; import { MlLocatorDefinition } from '../../../../../../ml/public/locator'; -import { UrlService } from '../../../../../../../../src/plugins/share/common/url_service'; +import { MockUrlService } from '../../../../../../../../src/plugins/share/common/mocks'; describe('create_explorer_link', () => { let anomalies = cloneDeep(mockAnomalies); @@ -22,12 +22,7 @@ describe('create_explorer_link', () => { }); test('it returns expected link', async () => { - const urlService = new UrlService({ - navigate: async () => {}, - getUrl: async ({ app, path }, { absolute }) => { - return `${absolute ? 'http://localhost:8888' : ''}/app/${app}${path}`; - }, - }); + const urlService = new MockUrlService(); const locator = urlService.locators.create(new MlLocatorDefinition()); const ml = { locator }; const http = { basePath: { get: jest.fn(() => {}) } }; diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index 231604e851e19d..5950616ace1616 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -40,6 +40,7 @@ import { createSecuritySolutionStorageMock } from '../../mock/mock_local_storage import { MlLocatorDefinition } from '../../../../../ml/public'; import { EuiTheme } from '../../../../../../../src/plugins/kibana_react/common'; import { UrlService } from 'src/plugins/share/common/url_service'; +import { MockUrlService } from 'src/plugins/share/common/mocks'; const mockUiSettings: Record = { [DEFAULT_TIME_RANGE]: { from: 'now-15m', to: 'now', mode: 'quick' }, @@ -94,12 +95,7 @@ export const createStartServicesMock = (): StartServices => { const { storage } = createSecuritySolutionStorageMock(); const data = dataPluginMock.createStartContract(); const security = securityMock.createSetup(); - const urlService = new UrlService({ - navigate: async () => {}, - getUrl: async ({ app, path }, { absolute }) => { - return `${absolute ? 'http://localhost:8888' : ''}/app/${app}${path}`; - }, - }); + const urlService = new MockUrlService(); const locator = urlService.locators.create(new MlLocatorDefinition()); return ({ From d14e4f21cf84383d76afcd38c1bff2189f808819 Mon Sep 17 00:00:00 2001 From: streamich Date: Wed, 7 Jul 2021 13:16:04 +0200 Subject: [PATCH 21/23] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20update=20usage?= =?UTF-8?q?=20after=20merging=20latest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index_based/index_data_visualizer.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index 60b6c90370b61d..0faf5b775d23eb 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -7,10 +7,10 @@ import React, { FC, Fragment, useEffect, useState, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; -import { useMlKibana, useTimefilter, useMlUrlGenerator } from '../../contexts/kibana'; +import { useMlKibana, useTimefilter, useMlLocator } from '../../contexts/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; import { HelpMenu } from '../../components/help_menu'; -import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../common/constants/locator'; import { isFullLicense } from '../../license'; import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes'; import { checkPermission } from '../../capabilities/check_capabilities'; @@ -33,7 +33,7 @@ export const IndexDataVisualizerPage: FC = () => { }, }, } = useMlKibana(); - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator()!; getMlNodeCount(); const [IndexDataVisualizer, setIndexDataVisualizer] = useState( @@ -64,7 +64,7 @@ export const IndexDataVisualizerPage: FC = () => { icon: 'createAdvancedJob', type: 'file', getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { - return await mlUrlGenerator.createUrl({ + return await mlLocator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED, pageState: { index: indexPatternId, @@ -101,7 +101,7 @@ export const IndexDataVisualizerPage: FC = () => { icon: 'classificationJob', type: 'file', getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { - return await mlUrlGenerator.createUrl({ + return await mlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, pageState: { index: indexPatternId, From 6d9e1b49a64c14ec489addd351d32d288cece3f5 Mon Sep 17 00:00:00 2001 From: streamich Date: Thu, 8 Jul 2021 13:06:20 +0200 Subject: [PATCH 22/23] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20use=20locator?= =?UTF-8?q?=20instead=20of=20generator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datavisualizer/file_based/file_datavisualizer.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index 37fd0a20865f7c..5fe519f25efb69 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -10,9 +10,9 @@ import { i18n } from '@kbn/i18n'; import { useTimefilter } from '../../contexts/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; import { HelpMenu } from '../../components/help_menu'; -import { useMlKibana, useMlUrlGenerator } from '../../contexts/kibana'; +import { useMlKibana, useMlLocator } from '../../contexts/kibana'; -import { ML_PAGES } from '../../../../common/constants/ml_url_generator'; +import { ML_PAGES } from '../../../../common/constants/locator'; import { isFullLicense } from '../../license'; import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes'; import { checkPermission } from '../../capabilities/check_capabilities'; @@ -34,7 +34,7 @@ export const FileDataVisualizerPage: FC = () => { }, }, } = useMlKibana(); - const mlUrlGenerator = useMlUrlGenerator(); + const mlLocator = useMlLocator()!; getMlNodeCount(); const [FileDataVisualizer, setFileDataVisualizer] = useState(null); @@ -50,7 +50,7 @@ export const FileDataVisualizerPage: FC = () => { icon: 'machineLearningApp', type: 'file', getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { - return await mlUrlGenerator.createUrl({ + return await mlLocator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, pageState: { index: indexPatternId, @@ -81,7 +81,7 @@ export const FileDataVisualizerPage: FC = () => { icon: 'dataVisualizer', type: 'file', getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { - return await mlUrlGenerator.createUrl({ + return await mlLocator.getUrl({ page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, pageState: { index: indexPatternId, From f6aee6493d7aca694482b84074f2915501e9868d Mon Sep 17 00:00:00 2001 From: streamich Date: Thu, 8 Jul 2021 14:16:16 +0200 Subject: [PATCH 23/23] =?UTF-8?q?chore:=20=F0=9F=A4=96=20remove=20unused?= =?UTF-8?q?=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../public/common/lib/kibana/kibana_react.mock.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index 5950616ace1616..5fd83b72af09bc 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -39,7 +39,6 @@ import { StartServices } from '../../../types'; import { createSecuritySolutionStorageMock } from '../../mock/mock_local_storage'; import { MlLocatorDefinition } from '../../../../../ml/public'; import { EuiTheme } from '../../../../../../../src/plugins/kibana_react/common'; -import { UrlService } from 'src/plugins/share/common/url_service'; import { MockUrlService } from 'src/plugins/share/common/mocks'; const mockUiSettings: Record = {