mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
ML locator (#103652)
* fix: 🐛 cast type * chore: 🤖 remove unused parameter * feat: 🎸 implement ML locator * test: 💍 add locator tests * feat: 🎸 expose ML locator form plugin contract * feat: 🎸 deprecate ml url generator * feat: 🎸 use locator in useMlHref() React hook * fix: 🐛 remove non-existing property * fix: 🐛 remove unused parameter * feat: 🎸 replace url generator by locator * refactor: 💡 remove ML url generator and replace by locator * fix: 🐛 correct type check error * test: 💍 add share plugin mock and use it * test: 💍 update mock * Remove usage of excludeBasePath * Fix recently accessed url for create job to data visualizer * refactor: 💡 rename interface * test: 💍 move locator mock into the share plugin * test: 💍 update Jest snapshot * test: 💍 use shared URL service mock * refactor: 💡 update usage after merging latest * refactor: 💡 use locator instead of generator * chore: 🤖 remove unused import Co-authored-by: Quynh Nguyen <quynh.nguyen@elastic.co>
This commit is contained in:
parent
0ef3cbe6ed
commit
15d47ec2c1
92 changed files with 974 additions and 883 deletions
|
@ -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}`;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,4 +6,59 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { SerializableState } from 'src/plugins/kibana_utils/common';
|
||||
import { SharePluginSetup, SharePluginStart } from '.';
|
||||
import { LocatorPublic, UrlService } from '../common/url_service';
|
||||
|
||||
export type Setup = jest.Mocked<SharePluginSetup>;
|
||||
export type Start = jest.Mocked<SharePluginStart>;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
const createLocator = <T extends SerializableState = SerializableState>(): jest.Mocked<
|
||||
LocatorPublic<T>
|
||||
> => ({
|
||||
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,
|
||||
};
|
||||
|
||||
export * from '../common/mocks';
|
||||
|
|
|
@ -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<string, unknown> = {
|
||||
[UI_SETTINGS.TIMEPICKER_QUICK_RANGES]: [
|
||||
|
@ -86,12 +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',
|
||||
useHash: false,
|
||||
}),
|
||||
locator,
|
||||
},
|
||||
data: {
|
||||
query: {
|
||||
|
|
|
@ -39,7 +39,7 @@ export const LogAnalysisModuleListCard: React.FC<{
|
|||
const [viewInMlLink, setViewInMlLink] = useState<string>('');
|
||||
|
||||
const getMlUrl = async () => {
|
||||
if (!ml.urlGenerator) {
|
||||
if (!ml.locator) {
|
||||
toasts.addWarning({
|
||||
title: mountReactNode(
|
||||
<FormattedMessage
|
||||
|
@ -50,7 +50,7 @@ export const LogAnalysisModuleListCard: React.FC<{
|
|||
});
|
||||
return;
|
||||
}
|
||||
setViewInMlLink(await ml.urlGenerator.createUrl({ page: 'jobs', pageState: { jobId } }));
|
||||
setViewInMlLink(await ml.locator.getUrl({ page: 'jobs', pageState: { jobId } }));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -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',
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { MlPages } from '../constants/ml_url_generator';
|
||||
import { MlPages } from '../constants/locator';
|
||||
|
||||
export interface Dictionary<TValue> {
|
||||
[id: string]: TValue;
|
||||
|
|
|
@ -5,21 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { SerializableState } from 'src/plugins/kibana_utils/common';
|
||||
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 { 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';
|
||||
import { ML_PAGES } from '../constants/locator';
|
||||
|
||||
type OptionalPageState = object | undefined;
|
||||
|
||||
export type MLPageState<PageType, PageState> = 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;
|
||||
|
@ -241,7 +243,7 @@ export type ExplorationPageUrlState = {
|
|||
/**
|
||||
* Union type of ML URL state based on page
|
||||
*/
|
||||
export type MlUrlGeneratorState =
|
||||
export type MlLocatorState =
|
||||
| AnomalyDetectionUrlState
|
||||
| ExplorerUrlState
|
||||
| TimeSeriesExplorerUrlState
|
||||
|
@ -250,3 +252,7 @@ export type MlUrlGeneratorState =
|
|||
| CalendarEditUrlState
|
||||
| FilterEditUrlState
|
||||
| MlGenericUrlState;
|
||||
|
||||
export type MlLocatorParams = MlLocatorState & SerializableState;
|
||||
|
||||
export type MlLocator = LocatorPublic<MlLocatorParams>;
|
|
@ -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(),
|
||||
|
|
|
@ -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 });
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<MlSetupDependencies, 'share' | 'indexPatternManagement'> &
|
||||
MlStartDependencies;
|
||||
|
||||
|
@ -55,11 +55,9 @@ export type MlGlobalServices = ReturnType<typeof getMlGlobalServices>;
|
|||
|
||||
const App: FC<AppProps> = ({ 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);
|
||||
};
|
||||
|
||||
|
|
|
@ -47,8 +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 { PLUGIN_ID } from '../../../../../common/constants/app';
|
||||
import { ML_APP_LOCATOR, ML_PAGES } from '../../../../../common/constants/locator';
|
||||
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,11 +201,8 @@ class AnnotationsTableUI extends Component {
|
|||
openSingleMetricView = async (annotation = {}) => {
|
||||
const {
|
||||
services: {
|
||||
application: { navigateToApp },
|
||||
|
||||
share: {
|
||||
urlGenerators: { getUrlGenerator },
|
||||
},
|
||||
application: { navigateToUrl },
|
||||
share,
|
||||
},
|
||||
} = this.props.kibana;
|
||||
|
||||
|
@ -266,32 +262,32 @@ class AnnotationsTableUI extends Component {
|
|||
mlTimeSeriesExplorer.entities = entityCondition;
|
||||
// appState.mlTimeSeriesExplorer = mlTimeSeriesExplorer;
|
||||
|
||||
const mlUrlGenerator = getUrlGenerator(ML_APP_URL_GENERATOR);
|
||||
const singleMetricViewerLink = await mlUrlGenerator.createUrl({
|
||||
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 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: '*',
|
||||
},
|
||||
},
|
||||
...mlTimeSeriesExplorer,
|
||||
},
|
||||
...mlTimeSeriesExplorer,
|
||||
},
|
||||
excludeBasePath: true,
|
||||
});
|
||||
{ absolute: true }
|
||||
);
|
||||
|
||||
addItemToRecentlyAccessed('timeseriesexplorer', job.job_id, singleMetricViewerLink);
|
||||
await navigateToApp(PLUGIN_ID, {
|
||||
path: singleMetricViewerLink,
|
||||
});
|
||||
await navigateToUrl(singleMetricViewerLink);
|
||||
};
|
||||
|
||||
onMouseOverRow = (record) => {
|
||||
|
|
|
@ -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,33 +178,35 @@ class LinksMenuUI extends Component {
|
|||
entityCondition[record.by_field_name] = record.by_field_value;
|
||||
}
|
||||
|
||||
const singleMetricViewerLink = await mlUrlGenerator.createUrl({
|
||||
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');
|
||||
};
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ import { AnomalyResultsViewSelector } from './index';
|
|||
|
||||
jest.mock('../../contexts/kibana', () => {
|
||||
return {
|
||||
useMlUrlGenerator: () => ({
|
||||
createUrl: jest.fn(),
|
||||
}),
|
||||
useMlLocator: () =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('../../../../../../../src/plugins/share/public/mocks').sharePluginMock.createLocator(),
|
||||
useNavigateToPath: () => jest.fn(),
|
||||
};
|
||||
});
|
||||
|
|
|
@ -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<Props> = ({ viewId }) => {
|
||||
const urlGenerator = useMlUrlGenerator();
|
||||
const locator = useMlLocator()!;
|
||||
const navigateToPath = useNavigateToPath();
|
||||
|
||||
const toggleButtonsIcons = useMemo(
|
||||
|
@ -52,7 +52,7 @@ export const AnomalyResultsViewSelector: FC<Props> = ({ 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,
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -10,8 +10,8 @@ import React, { FC, useState, useEffect } from 'react';
|
|||
import { EuiPageHeader } 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';
|
||||
import './main_tabs.scss';
|
||||
|
@ -68,7 +68,7 @@ function getTabs(disableLinks: boolean): Tab[] {
|
|||
}
|
||||
interface TabData {
|
||||
testSubject: string;
|
||||
pathId?: MlUrlGeneratorState['page'];
|
||||
pathId?: MlLocatorParams['page'];
|
||||
name: string;
|
||||
}
|
||||
|
||||
|
@ -126,10 +126,10 @@ export const MainTabs: FC<Props> = ({ 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
|
||||
? {
|
||||
|
@ -140,7 +140,7 @@ export const MainTabs: FC<Props> = ({ 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.
|
||||
|
@ -162,7 +162,7 @@ export const MainTabs: FC<Props> = ({ tabId, disableLinks }) => {
|
|||
tabs={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 {
|
||||
label: tab.name,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -7,47 +7,46 @@
|
|||
|
||||
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';
|
||||
import { LocatorGetUrlParams } from '../../../../../../../src/plugins/share/common/url_service';
|
||||
|
||||
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, getUrlParams?: LocatorGetUrlParams): string => {
|
||||
const [href, setHref] = useState<string>(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, getUrlParams);
|
||||
if (!isCancelled) {
|
||||
setHref(url);
|
||||
}
|
||||
}
|
||||
};
|
||||
generateUrl(params);
|
||||
return () => {
|
||||
isCancelled = true;
|
||||
};
|
||||
}, [params]);
|
||||
}, [params, getUrlParams]);
|
||||
|
||||
return href;
|
||||
};
|
||||
|
||||
export const useCreateAndNavigateToMlLink = (
|
||||
page: MlUrlGeneratorState['page']
|
||||
page: MlLocatorParams['page']
|
||||
): (() => Promise<void>) => {
|
||||
const mlUrlGenerator = useMlUrlGenerator();
|
||||
const mlLocator = useMlLocator();
|
||||
const [globalState] = useUrlState('_g');
|
||||
|
||||
const {
|
||||
|
@ -57,7 +56,7 @@ export const useCreateAndNavigateToMlLink = (
|
|||
} = useMlKibana();
|
||||
|
||||
const redirectToMlPage = useCallback(
|
||||
async (_page: MlUrlGeneratorState['page']) => {
|
||||
async (_page: MlLocatorParams['page']) => {
|
||||
const pageState =
|
||||
globalState?.refreshInterval !== undefined
|
||||
? {
|
||||
|
@ -69,10 +68,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
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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<typeof useMapAction>;
|
||||
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 },
|
||||
});
|
||||
|
|
|
@ -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<typeof useViewAction>;
|
||||
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 },
|
||||
});
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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 },
|
||||
});
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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<Props> = 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<Props> = 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 },
|
||||
});
|
||||
|
|
|
@ -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<Props> = ({ 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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<FileDataVisualizerSpec | null>(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,
|
||||
|
|
|
@ -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<IndexDataVisualizerSpec | null>(
|
||||
|
@ -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,
|
||||
|
|
|
@ -3,20 +3,17 @@
|
|||
exports[`ExplorerNoInfluencersFound snapshot 1`] = `
|
||||
<EuiEmptyPrompt
|
||||
actions={
|
||||
<Link
|
||||
to="/jobs"
|
||||
<EuiButton
|
||||
color="primary"
|
||||
fill={true}
|
||||
href="/jobs"
|
||||
>
|
||||
<EuiButton
|
||||
color="primary"
|
||||
fill={true}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Create job"
|
||||
id="xpack.ml.explorer.createNewJobLinkText"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>
|
||||
</Link>
|
||||
<FormattedMessage
|
||||
defaultMessage="Create job"
|
||||
id="xpack.ml.explorer.createNewJobLinkText"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>
|
||||
}
|
||||
data-test-subj="mlNoJobsFound"
|
||||
iconType="alert"
|
||||
|
|
|
@ -8,18 +8,19 @@
|
|||
/*
|
||||
* 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';
|
||||
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 = () => {
|
||||
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 (
|
||||
<EuiEmptyPrompt
|
||||
iconType="alert"
|
||||
|
@ -32,14 +33,12 @@ export const ExplorerNoJobsFound = () => {
|
|||
</h2>
|
||||
}
|
||||
actions={
|
||||
<Link to={ADJobsManagementUrl}>
|
||||
<EuiButton color="primary" fill>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.explorer.createNewJobLinkText"
|
||||
defaultMessage="Create job"
|
||||
/>
|
||||
</EuiButton>
|
||||
</Link>
|
||||
<EuiButton color="primary" href={ADJobsManagementUrl} fill>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.explorer.createNewJobLinkText"
|
||||
defaultMessage="Create job"
|
||||
/>
|
||||
</EuiButton>
|
||||
}
|
||||
data-test-subj="mlNoJobsFound"
|
||||
/>
|
||||
|
|
|
@ -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,
|
||||
}}
|
||||
|
|
|
@ -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<ExplorerAnomaliesContainerProps> = (
|
|||
showCharts,
|
||||
severity,
|
||||
setSeverity,
|
||||
mlUrlGenerator,
|
||||
mlLocator,
|
||||
timeBuckets,
|
||||
timefilter,
|
||||
onSelectEntity,
|
||||
|
@ -81,7 +81,7 @@ export const ExplorerAnomaliesContainer: FC<ExplorerAnomaliesContainerProps> = (
|
|||
{...{
|
||||
...chartsData,
|
||||
severity: severity.val,
|
||||
mlUrlGenerator,
|
||||
mlLocator,
|
||||
timeBuckets,
|
||||
timefilter,
|
||||
onSelectEntity,
|
||||
|
|
|
@ -65,8 +65,7 @@ function ExplorerChartContainer({
|
|||
severity,
|
||||
tooManyBuckets,
|
||||
wrapLabel,
|
||||
mlUrlGenerator,
|
||||
basePath,
|
||||
mlLocator,
|
||||
timeBuckets,
|
||||
timefilter,
|
||||
onSelectEntity,
|
||||
|
@ -80,11 +79,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 +87,7 @@ function ExplorerChartContainer({
|
|||
return () => {
|
||||
isCancelled = true;
|
||||
};
|
||||
}, [mlUrlGenerator, series]);
|
||||
}, [mlLocator, series]);
|
||||
|
||||
const addToRecentlyAccessed = useCallback(() => {
|
||||
if (recentlyAccessed) {
|
||||
|
@ -163,7 +158,7 @@ function ExplorerChartContainer({
|
|||
iconSide="right"
|
||||
iconType="visLine"
|
||||
size="xs"
|
||||
href={`${basePath}/app/ml${explorerSeriesLink}`}
|
||||
href={explorerSeriesLink}
|
||||
onClick={addToRecentlyAccessed}
|
||||
>
|
||||
<FormattedMessage id="xpack.ml.explorer.charts.viewLabel" defaultMessage="View" />
|
||||
|
@ -235,7 +230,7 @@ export const ExplorerChartsContainerUI = ({
|
|||
tooManyBuckets,
|
||||
kibana,
|
||||
errorMessages,
|
||||
mlUrlGenerator,
|
||||
mlLocator,
|
||||
timeBuckets,
|
||||
timefilter,
|
||||
onSelectEntity,
|
||||
|
@ -245,7 +240,6 @@ export const ExplorerChartsContainerUI = ({
|
|||
const {
|
||||
services: {
|
||||
chrome: { recentlyAccessed },
|
||||
http: { basePath },
|
||||
embeddable: embeddablePlugin,
|
||||
maps: mapsPlugin,
|
||||
},
|
||||
|
@ -293,8 +287,7 @@ export const ExplorerChartsContainerUI = ({
|
|||
severity={severity}
|
||||
tooManyBuckets={tooManyBuckets}
|
||||
wrapLabel={wrapLabel}
|
||||
mlUrlGenerator={mlUrlGenerator}
|
||||
basePath={basePath.get()}
|
||||
mlLocator={mlLocator}
|
||||
timeBuckets={timeBuckets}
|
||||
timefilter={timefilter}
|
||||
onSelectEntity={onSelectEntity}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
/**
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -29,11 +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 { 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;
|
||||
|
@ -86,11 +82,8 @@ export class ForecastsTableUI extends Component {
|
|||
async openSingleMetricView(forecast) {
|
||||
const {
|
||||
services: {
|
||||
application: { navigateToApp },
|
||||
|
||||
share: {
|
||||
urlGenerators: { getUrlGenerator },
|
||||
},
|
||||
application: { navigateToUrl },
|
||||
share,
|
||||
},
|
||||
} = this.props.kibana;
|
||||
|
||||
|
@ -126,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() {
|
||||
|
|
|
@ -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<string>('');
|
||||
|
||||
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 (
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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_APP_LOCATOR, ML_PAGES } from '../../../../../../common/constants/locator';
|
||||
import { RareIcon } from './rare_job_icon';
|
||||
import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator';
|
||||
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()}`);
|
||||
};
|
||||
|
||||
|
|
|
@ -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<PageProps> = ({ moduleId, existingGroupIds }) => {
|
|||
const {
|
||||
services: { notifications },
|
||||
} = useMlKibana();
|
||||
const urlGenerator = useMlUrlGenerator();
|
||||
const locator = useMlLocator();
|
||||
|
||||
// #region State
|
||||
const [jobPrefix, setJobPrefix] = useState<string>('');
|
||||
|
@ -197,19 +197,21 @@ export const Page: FC<PageProps> = ({ 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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Props> = ({ 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);
|
||||
|
|
|
@ -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<Group>;
|
||||
|
||||
|
@ -59,18 +59,20 @@ export const AnomalyDetectionPanel: FC<Props> = ({ 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);
|
||||
|
|
|
@ -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<PageProps> = ({ location, deps }) => {
|
|||
|
||||
const [globalState] = useUrlState('_g');
|
||||
|
||||
const urlGenerator = useMlUrlGenerator();
|
||||
const locator = useMlLocator();
|
||||
const {
|
||||
services: {
|
||||
application: { navigateToUrl },
|
||||
|
@ -51,7 +51,8 @@ const PageWrapper: FC<PageProps> = ({ 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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = () => {
|
||||
|
|
|
@ -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 }) {
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<TimeSeriesExplorerAppState>(ML_PAGES.SINGLE_METRIC_VIEWER);
|
||||
|
|
|
@ -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,35 +241,37 @@ export async function getExploreSeriesLink(mlUrlGenerator, series, timefilter) {
|
|||
});
|
||||
}
|
||||
|
||||
const url = await mlUrlGenerator.createUrl({
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -10,7 +10,7 @@ Object {
|
|||
"tooManyBuckets": false,
|
||||
},
|
||||
"id": "test-explorer-charts-embeddable",
|
||||
"mlUrlGenerator": undefined,
|
||||
"mlLocator": undefined,
|
||||
"onSelectEntity": [Function],
|
||||
"setSeverity": [Function],
|
||||
"severity": Object {
|
||||
|
|
|
@ -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 { MlLocatorParams } from '../../../common/types/locator';
|
||||
|
||||
const RESIZE_THROTTLE_TIME_MS = 500;
|
||||
|
||||
|
@ -55,19 +56,12 @@ export const EmbeddableAnomalyChartsContainer: FC<EmbeddableAnomalyChartsContain
|
|||
)
|
||||
);
|
||||
const [selectedEntities, setSelectedEntities] = useState<EntityField[] | undefined>();
|
||||
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<MlLocatorParams>(ML_APP_LOCATOR)!, [
|
||||
share,
|
||||
]);
|
||||
|
||||
const timeBuckets = useMemo(() => {
|
||||
return new TimeBuckets({
|
||||
|
@ -179,7 +173,7 @@ export const EmbeddableAnomalyChartsContainer: FC<EmbeddableAnomalyChartsContain
|
|||
chartsData={chartsData}
|
||||
severity={severity}
|
||||
setSeverity={setSeverity}
|
||||
mlUrlGenerator={mlUrlGenerator}
|
||||
mlLocator={mlLocator}
|
||||
timeBuckets={timeBuckets}
|
||||
timefilter={timefilter}
|
||||
onSelectEntity={addEntityFieldFilter}
|
||||
|
|
|
@ -54,7 +54,7 @@ export {
|
|||
export { ES_CLIENT_TOTAL_HITS_RELATION } from '../common/types/es_client';
|
||||
|
||||
export { ANOMALY_SEVERITY } from '../common';
|
||||
export { useMlHref, ML_PAGES, MlUrlGenerator } from './ml_url_generator';
|
||||
export { useMlHref, ML_PAGES, MlLocator, MlLocatorDefinition } from './locator';
|
||||
|
||||
// Bundled shared exports
|
||||
// Exported this way so the code doesn't end up in ML's page load bundle
|
||||
|
|
|
@ -16,16 +16,17 @@ import type {
|
|||
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';
|
||||
} from '../../../common/types/locator';
|
||||
import { ML_PAGES } from '../../../common/constants/locator';
|
||||
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 createAnomalyDetectionJobManagementUrl(
|
||||
export function formatAnomalyDetectionJobManagementUrl(
|
||||
appBasePath: string,
|
||||
params: AnomalyDetectionUrlState['pageState']
|
||||
): string {
|
||||
|
@ -69,22 +70,22 @@ export function createAnomalyDetectionJobManagementUrl(
|
|||
return url;
|
||||
}
|
||||
|
||||
export function createAnomalyDetectionCreateJobSelectType(
|
||||
export function formatAnomalyDetectionCreateJobSelectType(
|
||||
appBasePath: string,
|
||||
pageState: MlGenericUrlState['pageState']
|
||||
): string {
|
||||
return createGenericMlUrl(
|
||||
return formatGenericMlUrl(
|
||||
appBasePath,
|
||||
ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE,
|
||||
pageState
|
||||
);
|
||||
}
|
||||
|
||||
export function createAnomalyDetectionCreateJobSelectIndex(
|
||||
export function formatAnomalyDetectionCreateJobSelectIndex(
|
||||
appBasePath: string,
|
||||
pageState: MlGenericUrlState['pageState']
|
||||
): string {
|
||||
return createGenericMlUrl(
|
||||
return formatGenericMlUrl(
|
||||
appBasePath,
|
||||
ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX,
|
||||
pageState
|
||||
|
@ -94,7 +95,7 @@ export function createAnomalyDetectionCreateJobSelectIndex(
|
|||
/**
|
||||
* Creates URL to the Anomaly Explorer page
|
||||
*/
|
||||
export function createExplorerUrl(
|
||||
export function formatExplorerUrl(
|
||||
appBasePath: string,
|
||||
params: ExplorerUrlState['pageState']
|
||||
): string {
|
||||
|
@ -146,7 +147,7 @@ export function createExplorerUrl(
|
|||
/**
|
||||
* Creates URL to the SingleMetricViewer page
|
||||
*/
|
||||
export function createSingleMetricViewerUrl(
|
||||
export function formatSingleMetricViewerUrl(
|
||||
appBasePath: string,
|
||||
params: TimeSeriesExplorerUrlState['pageState']
|
||||
): string {
|
|
@ -6,8 +6,8 @@
|
|||
*/
|
||||
|
||||
import { isEmpty } from 'lodash';
|
||||
import { MlGenericUrlState } from '../../common/types/ml_url_generator';
|
||||
import { setStateToKbnUrl } from '../../../../../src/plugins/kibana_utils/public';
|
||||
import { MlGenericUrlState } from '../../../common/types/locator';
|
||||
import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public';
|
||||
|
||||
export function extractParams<UrlState>(urlState: UrlState) {
|
||||
// page should be guaranteed to exist here but <UrlState> is unknown
|
||||
|
@ -20,7 +20,7 @@ export function extractParams<UrlState>(urlState: UrlState) {
|
|||
* Creates generic index based search ML url
|
||||
* e.g. `jobs/new_job/datavisualizer?index=3da93760-e0af-11ea-9ad3-3bcfc330e42a`
|
||||
*/
|
||||
export function createGenericMlUrl(
|
||||
export function formatGenericMlUrl(
|
||||
appBasePath: string,
|
||||
page: MlGenericUrlState['page'],
|
||||
pageState: MlGenericUrlState['pageState']
|
|
@ -9,6 +9,7 @@
|
|||
* Creates URL to the DataFrameAnalytics page
|
||||
*/
|
||||
import { isEmpty } from 'lodash';
|
||||
import { formatGenericMlUrl } from './common';
|
||||
import {
|
||||
DataFrameAnalyticsExplorationQueryState,
|
||||
DataFrameAnalyticsExplorationUrlState,
|
||||
|
@ -16,14 +17,13 @@ import {
|
|||
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';
|
||||
} 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';
|
||||
|
||||
export function createDataFrameAnalyticsJobManagementUrl(
|
||||
export function formatDataFrameAnalyticsJobManagementUrl(
|
||||
appBasePath: string,
|
||||
mlUrlGeneratorState: DataFrameAnalyticsUrlState['pageState']
|
||||
): string {
|
||||
|
@ -70,7 +70,7 @@ export function createDataFrameAnalyticsJobManagementUrl(
|
|||
/**
|
||||
* Creates URL to the DataFrameAnalytics Exploration page
|
||||
*/
|
||||
export function createDataFrameAnalyticsExplorationUrl(
|
||||
export function formatDataFrameAnalyticsExplorationUrl(
|
||||
appBasePath: string,
|
||||
mlUrlGeneratorState: DataFrameAnalyticsExplorationUrlState['pageState']
|
||||
): string {
|
||||
|
@ -116,17 +116,17 @@ export function createDataFrameAnalyticsExplorationUrl(
|
|||
/**
|
||||
* Creates URL to the DataFrameAnalytics creation wizard
|
||||
*/
|
||||
export function createDataFrameAnalyticsCreateJobUrl(
|
||||
export function formatDataFrameAnalyticsCreateJobUrl(
|
||||
appBasePath: string,
|
||||
pageState: MlGenericUrlState['pageState']
|
||||
): string {
|
||||
return createGenericMlUrl(appBasePath, ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, pageState);
|
||||
return formatGenericMlUrl(appBasePath, ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, pageState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates URL to the DataFrameAnalytics Map page
|
||||
*/
|
||||
export function createDataFrameAnalyticsMapUrl(
|
||||
export function formatDataFrameAnalyticsMapUrl(
|
||||
appBasePath: string,
|
||||
mlUrlGeneratorState: DataFrameAnalyticsExplorationUrlState['pageState']
|
||||
): string {
|
11
x-pack/plugins/ml/public/locator/formatters/index.ts
Normal file
11
x-pack/plugins/ml/public/locator/formatters/index.ts
Normal file
|
@ -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';
|
|
@ -5,11 +5,11 @@
|
|||
* 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';
|
||||
import { CalendarEditUrlState, FilterEditUrlState } from '../../../common/types/locator';
|
||||
import { ML_PAGES } from '../../../common/constants/locator';
|
||||
import { setStateToKbnUrl } from '../../../../../../src/plugins/kibana_utils/public';
|
||||
|
||||
export function createEditCalendarUrl(
|
||||
export function formatEditCalendarUrl(
|
||||
appBasePath: string,
|
||||
pageState: CalendarEditUrlState['pageState']
|
||||
): string {
|
||||
|
@ -27,7 +27,7 @@ export function createEditCalendarUrl(
|
|||
return url;
|
||||
}
|
||||
|
||||
export function createEditFilterUrl(
|
||||
export function formatEditFilterUrl(
|
||||
appBasePath: string,
|
||||
pageState: FilterEditUrlState['pageState']
|
||||
): string {
|
|
@ -5,6 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export { MlUrlGenerator, registerUrlGenerator } from './ml_url_generator';
|
||||
export { ML_PAGES } from '../../common/constants/locator';
|
||||
export * from './ml_locator';
|
||||
export { useMlHref } from './use_ml_href';
|
||||
export { ML_PAGES } from '../../common/constants/ml_url_generator';
|
336
x-pack/plugins/ml/public/locator/ml_locator.test.ts
Normal file
336
x-pack/plugins/ml/public/locator/ml_locator.test.ts
Normal file
|
@ -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/locator';
|
||||
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: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
101
x-pack/plugins/ml/public/locator/ml_locator.ts
Normal file
101
x-pack/plugins/ml/public/locator/ml_locator.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 { LocatorDefinition, KibanaLocation } from '../../../../../src/plugins/share/public';
|
||||
import {
|
||||
DataFrameAnalyticsExplorationUrlState,
|
||||
MlLocatorParams,
|
||||
MlLocator,
|
||||
} from '../../common/types/locator';
|
||||
import { ML_APP_LOCATOR, ML_PAGES } from '../../common/constants/locator';
|
||||
import {
|
||||
formatAnomalyDetectionCreateJobSelectIndex,
|
||||
formatAnomalyDetectionCreateJobSelectType,
|
||||
formatAnomalyDetectionJobManagementUrl,
|
||||
formatExplorerUrl,
|
||||
formatSingleMetricViewerUrl,
|
||||
formatDataFrameAnalyticsCreateJobUrl,
|
||||
formatDataFrameAnalyticsExplorationUrl,
|
||||
formatDataFrameAnalyticsJobManagementUrl,
|
||||
formatDataFrameAnalyticsMapUrl,
|
||||
formatGenericMlUrl,
|
||||
formatEditCalendarUrl,
|
||||
formatEditFilterUrl,
|
||||
} from './formatters';
|
||||
|
||||
export { MlLocatorParams, MlLocator };
|
||||
|
||||
export class MlLocatorDefinition implements LocatorDefinition<MlLocatorParams> {
|
||||
public readonly id = ML_APP_LOCATOR;
|
||||
|
||||
public readonly getLocation = async (params: MlLocatorParams): Promise<KibanaLocation> => {
|
||||
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: {},
|
||||
};
|
||||
};
|
||||
}
|
25
x-pack/plugins/ml/public/locator/use_ml_href.ts
Normal file
25
x-pack/plugins/ml/public/locator/use_ml_href.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { MlPluginStart } from '../index';
|
||||
import { MlLocatorParams } from '../../common/types/locator';
|
||||
|
||||
/**
|
||||
* Provides a URL to ML plugin page
|
||||
* TODO remove basePath parameter
|
||||
*/
|
||||
export const useMlHref = (
|
||||
ml: MlPluginStart | undefined,
|
||||
basePath: string | undefined,
|
||||
params: MlLocatorParams
|
||||
) => {
|
||||
return ml && ml.locator
|
||||
? ml.locator!.useUrl(params)
|
||||
: basePath !== undefined
|
||||
? `${basePath}/app/ml/${params.page}`
|
||||
: '';
|
||||
};
|
|
@ -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<UrlGeneratorContract<typeof ML_APP_URL_GENERATOR>>);
|
|
@ -1,269 +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',
|
||||
useHash: false,
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,124 +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 { 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<MlUrlGeneratorState>;
|
||||
}
|
||||
}
|
||||
|
||||
interface Params {
|
||||
appBasePath: string;
|
||||
useHash: boolean;
|
||||
}
|
||||
|
||||
export class MlUrlGenerator implements UrlGeneratorsDefinition<typeof ML_APP_URL_GENERATOR> {
|
||||
constructor(private readonly params: Params) {}
|
||||
|
||||
public readonly id = ML_APP_URL_GENERATOR;
|
||||
|
||||
public readonly createUrl = async (
|
||||
mlUrlGeneratorParams: MlUrlGeneratorState
|
||||
): Promise<string> => {
|
||||
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:
|
||||
// @ts-ignore // TODO: fix type
|
||||
return createDataFrameAnalyticsMapUrl(appBasePath, mlUrlGeneratorState.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<MlStartDependencies>
|
||||
) {
|
||||
const baseUrl = core.http.basePath.prepend('/app/ml');
|
||||
return share.urlGenerators.registerUrlGenerator(
|
||||
new MlUrlGenerator({
|
||||
appBasePath: baseUrl,
|
||||
useHash: core.uiSettings.get('state:storeInSessionStorage'),
|
||||
})
|
||||
);
|
||||
}
|
|
@ -1,42 +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 { useEffect, useState } from 'react';
|
||||
import { MlPluginStart } from '../index';
|
||||
import { MlUrlGeneratorState } from '../../common/types/ml_url_generator';
|
||||
|
||||
/**
|
||||
* Provides a URL to ML plugin page
|
||||
* TODO remove basePath parameter
|
||||
*/
|
||||
export const useMlHref = (
|
||||
ml: MlPluginStart | undefined,
|
||||
basePath: string | undefined,
|
||||
params: MlUrlGeneratorState
|
||||
) => {
|
||||
const [mlLink, setMlLink] = useState<string | undefined>(
|
||||
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;
|
||||
};
|
|
@ -4,17 +4,35 @@
|
|||
* 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<MlPluginSetup> => {
|
||||
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<MlPluginStart> => {
|
||||
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: {},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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,11 @@ 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 {
|
||||
TriggersAndActionsUIPublicPluginSetup,
|
||||
|
@ -84,7 +78,8 @@ export type MlCoreSetup = CoreSetup<MlStartDependencies, MlPluginStart>;
|
|||
|
||||
export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
||||
private appUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));
|
||||
private urlGenerator: undefined | UrlGeneratorContract<typeof ML_APP_URL_GENERATOR>;
|
||||
|
||||
private locator: undefined | MlLocator;
|
||||
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
|
@ -128,7 +123,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
});
|
||||
|
||||
if (pluginsSetup.share) {
|
||||
this.urlGenerator = registerUrlGenerator(pluginsSetup.share, core);
|
||||
this.locator = pluginsSetup.share.url.locators.create(new MlLocatorDefinition());
|
||||
}
|
||||
|
||||
if (pluginsSetup.management) {
|
||||
|
@ -179,7 +174,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
});
|
||||
|
||||
return {
|
||||
urlGenerator: this.urlGenerator,
|
||||
locator: this.locator,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -192,7 +187,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
});
|
||||
|
||||
return {
|
||||
urlGenerator: this.urlGenerator,
|
||||
locator: this.locator,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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<string | undefined> {
|
||||
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,
|
||||
|
|
|
@ -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 { MockUrlService } from '../../../../../../../../src/plugins/share/common/mocks';
|
||||
|
||||
describe('create_explorer_link', () => {
|
||||
let anomalies = cloneDeep(mockAnomalies);
|
||||
|
@ -21,7 +22,9 @@ describe('create_explorer_link', () => {
|
|||
});
|
||||
|
||||
test('it returns expected link', async () => {
|
||||
const ml = { urlGenerator: new MlUrlGenerator({ appBasePath: '/app/ml', useHash: false }) };
|
||||
const urlService = new MockUrlService();
|
||||
const locator = urlService.locators.create(new MlLocatorDefinition());
|
||||
const ml = { locator };
|
||||
const http = { basePath: { get: jest.fn(() => {}) } };
|
||||
|
||||
await act(async () => {
|
||||
|
|
|
@ -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 { MockUrlService } from 'src/plugins/share/common/mocks';
|
||||
|
||||
const mockUiSettings: Record<string, unknown> = {
|
||||
[DEFAULT_TIME_RANGE]: { from: 'now-15m', to: 'now', mode: 'quick' },
|
||||
|
@ -93,6 +94,8 @@ export const createStartServicesMock = (): StartServices => {
|
|||
const { storage } = createSecuritySolutionStorageMock();
|
||||
const data = dataPluginMock.createStartContract();
|
||||
const security = securityMock.createSetup();
|
||||
const urlService = new MockUrlService();
|
||||
const locator = urlService.locators.create(new MlLocatorDefinition());
|
||||
|
||||
return ({
|
||||
...core,
|
||||
|
@ -139,10 +142,7 @@ export const createStartServicesMock = (): StartServices => {
|
|||
security,
|
||||
storage,
|
||||
ml: {
|
||||
urlGenerator: new MlUrlGenerator({
|
||||
appBasePath: '/app/ml',
|
||||
useHash: false,
|
||||
}),
|
||||
locator,
|
||||
},
|
||||
} as unknown) as StartServices;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue