Skip to content

Commit

Permalink
ML locator (elastic#103652)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
2 people authored and kibanamachine committed Jul 8, 2021
1 parent 9337283 commit fe9c33b
Show file tree
Hide file tree
Showing 92 changed files with 975 additions and 884 deletions.
2 changes: 1 addition & 1 deletion src/plugins/share/common/url_service/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
},
});
}
Expand Down
55 changes: 55 additions & 0 deletions src/plugins/share/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
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

0 comments on commit fe9c33b

Please sign in to comment.