Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ML locator #103652

Merged
merged 28 commits into from
Jul 8, 2021
Merged

ML locator #103652

Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d1129fd
fix: 🐛 cast type
streamich Jun 29, 2021
8796c8a
chore: 🤖 remove unused parameter
streamich Jun 29, 2021
09d6487
feat: 🎸 implement ML locator
streamich Jun 29, 2021
da33e69
test: 💍 add locator tests
streamich Jun 29, 2021
e83a843
feat: 🎸 expose ML locator form plugin contract
streamich Jun 29, 2021
0ab2ea2
feat: 🎸 deprecate ml url generator
streamich Jun 29, 2021
41c56aa
feat: 🎸 use locator in useMlHref() React hook
streamich Jun 29, 2021
d4c9ac6
fix: 🐛 remove non-existing property
streamich Jun 29, 2021
e4f5ac9
fix: 🐛 remove unused parameter
streamich Jun 29, 2021
302d91f
feat: 🎸 replace url generator by locator
streamich Jun 29, 2021
cf6f144
refactor: 💡 remove ML url generator and replace by locator
streamich Jun 29, 2021
8259d22
fix: 🐛 correct type check error
streamich Jun 29, 2021
16c0b98
test: 💍 add share plugin mock and use it
streamich Jun 30, 2021
802f7a2
test: 💍 update mock
streamich Jun 30, 2021
11ba91c
Merge branch 'master' into ml-locator-2
streamich Jun 30, 2021
2d7c96a
Remove usage of excludeBasePath
qn895 Jun 30, 2021
10e1486
Fix recently accessed url for create job to data visualizer
qn895 Jun 30, 2021
0178051
Merge remote-tracking branch 'upstream/master' into ml-locator-2
streamich Jul 5, 2021
d356058
refactor: 💡 rename interface
streamich Jul 5, 2021
2efc999
test: 💍 move locator mock into the share plugin
streamich Jul 5, 2021
0e5b0c4
test: 💍 update Jest snapshot
streamich Jul 5, 2021
6cc007b
Merge remote-tracking branch 'upstream/master' into ml-locator-2
streamich Jul 6, 2021
7017469
test: 💍 use shared URL service mock
streamich Jul 6, 2021
d14e4f2
refactor: 💡 update usage after merging latest
streamich Jul 7, 2021
f75149c
Merge remote-tracking branch 'upstream/master' into ml-locator-2
streamich Jul 7, 2021
8b9d73a
Merge remote-tracking branch 'upstream/master' into ml-locator-2
streamich Jul 8, 2021
6d9e1b4
refactor: 💡 use locator instead of generator
streamich Jul 8, 2021
f6aee64
chore: 🤖 remove unused import
streamich Jul 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/plugins/share/public/mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { 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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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]: [
Expand Down Expand Up @@ -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: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/common/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -250,3 +252,7 @@ export type MlUrlGeneratorState =
| CalendarEditUrlState
| FilterEditUrlState
| MlGenericUrlState;

export type MlLocatorParams = MlLocatorState & SerializableState;

export type MlLocator = LocatorPublic<MlLocatorParams>;
5 changes: 2 additions & 3 deletions x-pack/plugins/ml/public/__mocks__/ml_start_deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/ml/public/alerting/register_ml_alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -152,6 +152,6 @@ export function registerNavigation(alerting: AlertingSetup) {
]),
];

return createExplorerUrl('', { jobIds });
return formatExplorerUrl('', { jobIds });
});
}
10 changes: 4 additions & 6 deletions x-pack/plugins/ml/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -202,11 +201,8 @@ class AnnotationsTableUI extends Component {
openSingleMetricView = async (annotation = {}) => {
const {
services: {
application: { navigateToApp },

share: {
urlGenerators: { getUrlGenerator },
},
application: { navigateToUrl },
share,
},
} = this.props.kibana;

Expand Down Expand Up @@ -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) => {
Expand Down
Loading