Skip to content

Commit 55c25a4

Browse files
committed
[ML] Update apm and security_solution to use useMlHref hook
1 parent 9be734d commit 55c25a4

File tree

9 files changed

+97
-140
lines changed

9 files changed

+97
-140
lines changed

x-pack/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/legacy_jobs_callout.tsx

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,22 @@
55
*/
66

77
import { EuiCallOut, EuiButton } from '@elastic/eui';
8-
import React, { useEffect, useState } from 'react';
8+
import React from 'react';
99
import { i18n } from '@kbn/i18n';
1010
import { useApmPluginContext } from '../../../../hooks/useApmPluginContext';
11+
import { useMlHref } from '../../../../../../ml/public';
1112

1213
export function LegacyJobsCallout() {
1314
const {
1415
core,
1516
plugins: { ml },
1617
} = useApmPluginContext();
17-
18-
const [mlADLink, setMlADLink] = useState(
19-
core.http.basePath.prepend('/app/ml/jobs')
20-
);
21-
22-
useEffect(() => {
23-
let isCancelled = false;
24-
const generateLink = async () => {
25-
if (ml?.urlGenerator !== undefined) {
26-
const href = await ml.urlGenerator.createUrl({
27-
page: 'jobs',
28-
pageState: {
29-
jobId: 'high_mean_response_time',
30-
},
31-
});
32-
if (!isCancelled) {
33-
setMlADLink(href);
34-
}
35-
}
36-
};
37-
generateLink();
38-
return () => {
39-
isCancelled = true;
40-
};
41-
}, [ml?.urlGenerator]);
18+
const mlADLink = useMlHref(ml, core.http.basePath.get(), {
19+
page: 'jobs',
20+
pageState: {
21+
jobId: 'high_mean_response_time',
22+
},
23+
});
4224

4325
return (
4426
<EuiCallOut

x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
*/
66

77
import { EuiLink } from '@elastic/eui';
8-
import React, { useEffect, useState } from 'react';
8+
import React from 'react';
99
import { useLocation } from 'react-router-dom';
1010
import { useApmPluginContext } from '../../../../hooks/useApmPluginContext';
1111
import { getTimepickerRisonData } from '../rison_helpers';
12+
import { useMlHref, ML_PAGES } from '../../../../../../ml/public';
1213

1314
interface MlRisonData {
1415
ml?: {
@@ -24,48 +25,31 @@ interface Props {
2425
}
2526

2627
export function MLLink({ children, path = '', query = {}, external }: Props) {
27-
const { core } = useApmPluginContext();
2828
const location = useLocation();
2929

3030
const {
31+
core,
3132
plugins: { ml },
3233
} = useApmPluginContext();
3334

34-
// default to link to ML Anomaly Detection jobs management page
35-
const [mlADLink, setMlADLink] = useState(
36-
core.http.basePath.prepend('/app/ml/jobs')
37-
);
38-
useEffect(() => {
39-
let isCancelled = false;
40-
const generateLink = async () => {
41-
const { time, refreshInterval } = getTimepickerRisonData(location.search);
42-
let jobIds: string[] = [];
43-
if (query.ml?.jobIds) {
44-
jobIds = query.ml.jobIds;
45-
}
35+
let jobIds: string[] = [];
36+
if (query.ml?.jobIds) {
37+
jobIds = query.ml.jobIds;
38+
}
39+
const { time, refreshInterval } = getTimepickerRisonData(location.search);
4640

47-
if (ml?.urlGenerator !== undefined) {
48-
const href = await ml.urlGenerator.createUrl({
49-
page: 'jobs',
50-
pageState: {
51-
jobId: jobIds,
52-
groupIds: ['apm'],
53-
globalState: {
54-
time,
55-
refreshInterval,
56-
},
57-
},
58-
});
59-
if (!isCancelled) {
60-
setMlADLink(href);
61-
}
62-
}
63-
};
64-
generateLink();
65-
return () => {
66-
isCancelled = true;
67-
};
68-
}, [ml?.urlGenerator, location.search, query]);
41+
// default to link to ML Anomaly Detection jobs management page
42+
const mlADLink = useMlHref(ml, core.http.basePath.get(), {
43+
page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
44+
pageState: {
45+
jobId: jobIds,
46+
groupIds: ['apm'],
47+
globalState: {
48+
time,
49+
refreshInterval,
50+
},
51+
},
52+
});
6953

7054
return (
7155
<EuiLink

x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
*/
66

77
import { useLocation } from 'react-router-dom';
8-
import { useEffect, useState } from 'react';
98
import { useApmPluginContext } from '../../../../hooks/useApmPluginContext';
109
import { getTimepickerRisonData } from '../rison_helpers';
1110
import { RefreshInterval } from '../../../../../../../../src/plugins/data/common/query';
11+
import { useMlHref } from '../../../../../../ml/public';
1212

1313
export function useTimeSeriesExplorerHref({
1414
jobId,
@@ -24,43 +24,26 @@ export function useTimeSeriesExplorerHref({
2424
core,
2525
plugins: { ml },
2626
} = useApmPluginContext();
27-
const [mlAnomalyDetectionHref, setMlAnomalyDetectionHref] = useState(
28-
core.http.basePath.prepend('/app/ml/jobs')
29-
);
3027
const location = useLocation();
28+
const { time, refreshInterval } = getTimepickerRisonData(location.search);
3129

32-
useEffect(() => {
33-
let isCancelled = false;
34-
const generateLink = async () => {
35-
const { time, refreshInterval } = getTimepickerRisonData(location.search);
36-
if (ml?.urlGenerator !== undefined) {
37-
const href = await ml.urlGenerator.createUrl({
38-
page: 'timeseriesexplorer',
39-
pageState: {
40-
jobIds: [jobId],
41-
timeRange: time,
42-
refreshInterval: refreshInterval as RefreshInterval,
43-
zoom: time,
44-
...(serviceName && transactionType
45-
? {
46-
entities: {
47-
'service.name': serviceName,
48-
'transaction.type': transactionType,
49-
},
50-
}
51-
: {}),
52-
},
53-
});
54-
if (!isCancelled) {
55-
setMlAnomalyDetectionHref(href);
56-
}
57-
}
58-
};
59-
generateLink();
60-
return () => {
61-
isCancelled = true;
62-
};
63-
}, [ml?.urlGenerator, location.search, jobId, serviceName, transactionType]);
30+
const mlAnomalyDetectionHref = useMlHref(ml, core.http.basePath.get(), {
31+
page: 'timeseriesexplorer',
32+
pageState: {
33+
jobIds: [jobId],
34+
timeRange: time,
35+
refreshInterval: refreshInterval as RefreshInterval,
36+
zoom: time,
37+
...(serviceName && transactionType
38+
? {
39+
entities: {
40+
'service.name': serviceName,
41+
'transaction.type': transactionType,
42+
},
43+
}
44+
: {}),
45+
},
46+
});
6447

6548
return mlAnomalyDetectionHref;
6649
}

x-pack/plugins/apm/public/context/ApmPluginContext/MockApmPluginContext.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const mockCore = {
5555
http: {
5656
basePath: {
5757
prepend: (path: string) => `/basepath${path}`,
58+
get: () => `/basepath`,
5859
},
5960
},
6061
i18n: {

x-pack/plugins/ml/public/ml_url_generator/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66
export { MlUrlGenerator, registerUrlGenerator } from './ml_url_generator';
7+
export { useMlHref } from './use_ml_href';
8+
export { ML_PAGES } from '../../common/constants/ml_url_generator';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { useEffect, useState } from 'react';
8+
import { MlPluginStart } from '../index';
9+
import { MlUrlGeneratorState } from '../../common/types/ml_url_generator';
10+
export const useMlHref = (
11+
ml: MlPluginStart | undefined,
12+
basePath: string,
13+
params: MlUrlGeneratorState
14+
) => {
15+
const [mlLink, setMlLink] = useState(`${basePath}/app/ml/${params.page}`);
16+
17+
useEffect(() => {
18+
let isCancelled = false;
19+
const generateLink = async () => {
20+
if (ml?.urlGenerator !== undefined) {
21+
const href = await ml.urlGenerator.createUrl(params);
22+
if (!isCancelled) {
23+
setMlLink(href);
24+
}
25+
}
26+
};
27+
generateLink();
28+
return () => {
29+
isCancelled = true;
30+
};
31+
}, [ml?.urlGenerator, params]);
32+
33+
return mlLink;
34+
};

x-pack/plugins/security_solution/kibana.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@
3131
],
3232
"server": true,
3333
"ui": true,
34-
"requiredBundles": ["esUiShared", "ingestManager", "kibanaUtils", "kibanaReact", "lists"]
34+
"requiredBundles": ["esUiShared", "ingestManager", "kibanaUtils", "kibanaReact", "lists", "ml"]
3535
}

x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { useBasePath, useKibana } from '../../../lib/kibana';
2626
import * as i18n from './translations';
2727
import { JobSwitch } from './job_switch';
2828
import { SecurityJob } from '../types';
29+
import { useMlHref, ML_PAGES } from '../../../../../../ml/public';
2930

3031
const JobNameWrapper = styled.div`
3132
margin: 5px 0;
@@ -43,31 +44,16 @@ interface JobNameProps {
4344
}
4445

4546
const JobName = ({ id, description, basePath }: JobNameProps) => {
46-
const [jobUrl, setJobUrl] = useState(`${basePath}/app/ml/jobs`);
4747
const {
4848
services: { ml },
4949
} = useKibana();
5050

51-
useEffect(() => {
52-
let isCancelled = false;
53-
const generateLink = async () => {
54-
if (ml?.urlGenerator !== undefined) {
55-
const href = await ml.urlGenerator.createUrl({
56-
page: 'jobs',
57-
pageState: {
58-
jobId: id,
59-
},
60-
});
61-
if (!isCancelled) {
62-
setJobUrl(href);
63-
}
64-
}
65-
};
66-
generateLink();
67-
return () => {
68-
isCancelled = true;
69-
};
70-
}, [ml?.urlGenerator, id]);
51+
const jobUrl = useMlHref(ml, basePath, {
52+
page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
53+
pageState: {
54+
jobId: id,
55+
},
56+
});
7157

7258
return (
7359
<JobNameWrapper>
@@ -179,26 +165,9 @@ export const NoItemsMessage = React.memo(({ basePath }: { basePath: string }) =>
179165
services: { ml },
180166
} = useKibana();
181167

182-
const [createNewAnomalyDetectionJoUrl, setCreateNewAnomalyDetectionJoUrl] = useState(
183-
`${basePath}/app/ml/jobs/new_job/step/index_or_search`
184-
);
185-
useEffect(() => {
186-
let isCancelled = false;
187-
const generateLink = async () => {
188-
if (ml?.urlGenerator !== undefined) {
189-
const href = await ml.urlGenerator.createUrl({
190-
page: 'jobs/new_job/step/index_or_search',
191-
});
192-
if (!isCancelled) {
193-
setCreateNewAnomalyDetectionJoUrl(href);
194-
}
195-
}
196-
};
197-
generateLink();
198-
return () => {
199-
isCancelled = true;
200-
};
201-
}, [ml?.urlGenerator]);
168+
const createNewAnomalyDetectionJoUrl = useMlHref(ml, basePath, {
169+
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX,
170+
});
202171

203172
return (
204173
<EuiEmptyPrompt

0 commit comments

Comments
 (0)