Skip to content

Commit 1af91ff

Browse files
qn895kibanamachine
andauthored
[7.10] [ML] Fix regression with some links not opening in new tab (#80785) (#80981)
Co-authored-by: Kibana Machine <[email protected]> Co-authored-by: Kibana Machine <[email protected]>
1 parent e0849e2 commit 1af91ff

File tree

9 files changed

+204
-181
lines changed

9 files changed

+204
-181
lines changed

x-pack/plugins/ml/public/application/app.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import { AppMountParameters, CoreStart, HttpStart } from 'kibana/public';
1212

1313
import { Storage } from '../../../../../src/plugins/kibana_utils/public';
1414

15-
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
15+
import {
16+
KibanaContextProvider,
17+
RedirectAppLinks,
18+
} from '../../../../../src/plugins/kibana_react/public';
1619
import { setDependencyCache, clearCache } from './util/dependency_cache';
1720
import { setLicenseCache } from './license';
1821
import { MlSetupDependencies, MlStartDependencies } from '../plugin';
@@ -21,7 +24,6 @@ import { MlRouter } from './routing';
2124
import { mlApiServicesProvider } from './services/ml_api_service';
2225
import { HttpService } from './services/http_service';
2326
import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../common/constants/ml_url_generator';
24-
2527
export type MlDependencies = Omit<MlSetupDependencies, 'share' | 'indexPatternManagement'> &
2628
MlStartDependencies;
2729

@@ -80,13 +82,17 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams }) => {
8082

8183
const I18nContext = coreStart.i18n.Context;
8284
return (
83-
<I18nContext>
84-
<KibanaContextProvider
85-
services={{ ...services, mlServices: getMlGlobalServices(coreStart.http) }}
86-
>
87-
<MlRouter pageDeps={pageDeps} />
88-
</KibanaContextProvider>
89-
</I18nContext>
85+
/** RedirectAppLinks intercepts all <a> tags to use navigateToUrl
86+
* avoiding full page reload **/
87+
<RedirectAppLinks application={coreStart.application}>
88+
<I18nContext>
89+
<KibanaContextProvider
90+
services={{ ...services, mlServices: getMlGlobalServices(coreStart.http) }}
91+
>
92+
<MlRouter pageDeps={pageDeps} />
93+
</KibanaContextProvider>
94+
</I18nContext>
95+
</RedirectAppLinks>
9096
);
9197
};
9298

x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import { formatHumanReadableDateTimeSeconds } from '../../../../common/util/date
3030
import { getIndexPatternIdFromName } from '../../util/index_utils';
3131
import { replaceStringTokens } from '../../util/string_utils';
3232
import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../../../common/constants/ml_url_generator';
33-
import { PLUGIN_ID } from '../../../../common/constants/app';
3433
/*
3534
* Component for rendering the links menu inside a cell in the anomalies table.
3635
*/
@@ -147,8 +146,6 @@ class LinksMenuUI extends Component {
147146
viewSeries = async () => {
148147
const {
149148
services: {
150-
application: { navigateToApp },
151-
152149
share: {
153150
urlGenerators: { getUrlGenerator },
154151
},
@@ -185,7 +182,7 @@ class LinksMenuUI extends Component {
185182
}
186183

187184
const singleMetricViewerLink = await mlUrlGenerator.createUrl({
188-
excludeBasePath: true,
185+
excludeBasePath: false,
189186
page: ML_PAGES.SINGLE_METRIC_VIEWER,
190187
pageState: {
191188
jobIds: [record.job_id],
@@ -211,9 +208,7 @@ class LinksMenuUI extends Component {
211208
},
212209
},
213210
});
214-
await navigateToApp(PLUGIN_ID, {
215-
path: singleMetricViewerLink,
216-
});
211+
window.open(singleMetricViewerLink, '_blank');
217212
};
218213

219214
viewExamples = () => {

x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx

Lines changed: 83 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import React, { FC, useState, useEffect, useCallback } from 'react';
7+
import React, { FC, useState, useEffect } from 'react';
88
import moment from 'moment';
99
import { FormattedMessage } from '@kbn/i18n/react';
1010
import { EuiFlexGroup, EuiFlexItem, EuiCard, EuiIcon } from '@elastic/eui';
1111
import { ml } from '../../../../services/ml_api_service';
1212
import { isFullLicense } from '../../../../license';
1313
import { checkPermission } from '../../../../capabilities/check_capabilities';
1414
import { mlNodesAvailable } from '../../../../ml_nodes_check/check_ml_nodes';
15-
import { useMlKibana, useMlUrlGenerator, useNavigateToPath } from '../../../../contexts/kibana';
15+
import { useMlKibana, useMlUrlGenerator } from '../../../../contexts/kibana';
1616
import { ML_PAGES } from '../../../../../../common/constants/ml_url_generator';
1717
import { MlCommonGlobalState } from '../../../../../../common/types/ml_url_generator';
1818
import {
@@ -45,12 +45,16 @@ export const ResultsLinks: FC<Props> = ({
4545
const [globalState, setGlobalState] = useState<MlCommonGlobalState | undefined>();
4646

4747
const [discoverLink, setDiscoverLink] = useState('');
48+
const [indexManagementLink, setIndexManagementLink] = useState('');
49+
const [indexPatternManagementLink, setIndexPatternManagementLink] = useState('');
50+
const [dataVisualizerLink, setDataVisualizerLink] = useState('');
51+
const [createJobsSelectTypePage, setCreateJobsSelectTypePage] = useState('');
52+
4853
const mlUrlGenerator = useMlUrlGenerator();
49-
const navigateToPath = useNavigateToPath();
5054

5155
const {
5256
services: {
53-
application: { navigateToApp, navigateToUrl },
57+
application: { getUrlForApp },
5458
share: {
5559
urlGenerators: { getUrlGenerator },
5660
},
@@ -84,35 +88,52 @@ export const ResultsLinks: FC<Props> = ({
8488
setDiscoverLink(discoverUrl);
8589
}
8690
};
91+
92+
const getDataVisualizerLink = async (): Promise<void> => {
93+
const _dataVisualizerLink = await mlUrlGenerator.createUrl({
94+
page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER,
95+
pageState: {
96+
index: indexPatternId,
97+
globalState,
98+
},
99+
});
100+
if (!unmounted) {
101+
setDataVisualizerLink(_dataVisualizerLink);
102+
}
103+
};
104+
const getADCreateJobsSelectTypePage = async (): Promise<void> => {
105+
const _createJobsSelectTypePage = await mlUrlGenerator.createUrl({
106+
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE,
107+
pageState: {
108+
index: indexPatternId,
109+
globalState,
110+
},
111+
});
112+
if (!unmounted) {
113+
setCreateJobsSelectTypePage(_createJobsSelectTypePage);
114+
}
115+
};
116+
87117
getDiscoverUrl();
118+
getDataVisualizerLink();
119+
getADCreateJobsSelectTypePage();
120+
121+
if (!unmounted) {
122+
setIndexManagementLink(
123+
getUrlForApp('management', { path: '/data/index_management/indices' })
124+
);
125+
setIndexPatternManagementLink(
126+
getUrlForApp('management', {
127+
path: `/kibana/indexPatterns${createIndexPattern ? `/patterns/${indexPatternId}` : ''}`,
128+
})
129+
);
130+
}
88131

89132
return () => {
90133
unmounted = true;
91134
};
92135
}, [indexPatternId, getUrlGenerator]);
93136

94-
const openInDataVisualizer = useCallback(async () => {
95-
const path = await mlUrlGenerator.createUrl({
96-
page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER,
97-
pageState: {
98-
index: indexPatternId,
99-
globalState,
100-
},
101-
});
102-
await navigateToPath(path);
103-
}, [indexPatternId, globalState]);
104-
105-
const redirectToADCreateJobsSelectTypePage = useCallback(async () => {
106-
const path = await mlUrlGenerator.createUrl({
107-
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE,
108-
pageState: {
109-
index: indexPatternId,
110-
globalState,
111-
},
112-
});
113-
await navigateToPath(path);
114-
}, [indexPatternId, globalState]);
115-
116137
useEffect(() => {
117138
setShowCreateJobLink(checkPermission('canCreateJob') && mlNodesAvailable());
118139
updateTimeValues();
@@ -148,23 +169,6 @@ export const ResultsLinks: FC<Props> = ({
148169
}
149170
}
150171

151-
function openInDiscover(e: React.MouseEvent<HTMLButtonElement>) {
152-
e.preventDefault();
153-
navigateToUrl(discoverLink);
154-
}
155-
156-
function openIndexManagement(e: React.MouseEvent<HTMLButtonElement>) {
157-
e.preventDefault();
158-
navigateToApp('management', { path: '/data/index_management/indices' });
159-
}
160-
161-
function openIndexPatternManagement(e: React.MouseEvent<HTMLButtonElement>) {
162-
e.preventDefault();
163-
navigateToApp('management', {
164-
path: `/kibana/indexPatterns${createIndexPattern ? `/patterns/${indexPatternId}` : ''}`,
165-
});
166-
}
167-
168172
return (
169173
<EuiFlexGroup gutterSize="l">
170174
{createIndexPattern && discoverLink && (
@@ -178,15 +182,16 @@ export const ResultsLinks: FC<Props> = ({
178182
/>
179183
}
180184
description=""
181-
onClick={openInDiscover}
185+
href={discoverLink}
182186
/>
183187
</EuiFlexItem>
184188
)}
185189

186190
{isFullLicense() === true &&
187191
timeFieldName !== undefined &&
188192
showCreateJobLink &&
189-
createIndexPattern && (
193+
createIndexPattern &&
194+
createJobsSelectTypePage && (
190195
<EuiFlexItem>
191196
<EuiCard
192197
icon={<EuiIcon size="xxl" type={`machineLearningApp`} />}
@@ -197,12 +202,12 @@ export const ResultsLinks: FC<Props> = ({
197202
/>
198203
}
199204
description=""
200-
onClick={redirectToADCreateJobsSelectTypePage}
205+
href={createJobsSelectTypePage}
201206
/>
202207
</EuiFlexItem>
203208
)}
204209

205-
{createIndexPattern && (
210+
{createIndexPattern && dataVisualizerLink && (
206211
<EuiFlexItem>
207212
<EuiCard
208213
icon={<EuiIcon size="xxl" type={`dataVisualizer`} />}
@@ -213,38 +218,42 @@ export const ResultsLinks: FC<Props> = ({
213218
/>
214219
}
215220
description=""
216-
onClick={openInDataVisualizer}
221+
href={dataVisualizerLink}
217222
/>
218223
</EuiFlexItem>
219224
)}
220225

221-
<EuiFlexItem>
222-
<EuiCard
223-
icon={<EuiIcon size="xxl" type={`managementApp`} />}
224-
title={
225-
<FormattedMessage
226-
id="xpack.ml.fileDatavisualizer.resultsLinks.indexManagementTitle"
227-
defaultMessage="Index Management"
228-
/>
229-
}
230-
description=""
231-
onClick={openIndexManagement}
232-
/>
233-
</EuiFlexItem>
226+
{indexManagementLink && (
227+
<EuiFlexItem>
228+
<EuiCard
229+
icon={<EuiIcon size="xxl" type={`managementApp`} />}
230+
title={
231+
<FormattedMessage
232+
id="xpack.ml.fileDatavisualizer.resultsLinks.indexManagementTitle"
233+
defaultMessage="Index Management"
234+
/>
235+
}
236+
description=""
237+
href={indexManagementLink}
238+
/>
239+
</EuiFlexItem>
240+
)}
234241

235-
<EuiFlexItem>
236-
<EuiCard
237-
icon={<EuiIcon size="xxl" type={`managementApp`} />}
238-
title={
239-
<FormattedMessage
240-
id="xpack.ml.fileDatavisualizer.resultsLinks.indexPatternManagementTitle"
241-
defaultMessage="Index Pattern Management"
242-
/>
243-
}
244-
description=""
245-
onClick={openIndexPatternManagement}
246-
/>
247-
</EuiFlexItem>
242+
{indexPatternManagementLink && (
243+
<EuiFlexItem>
244+
<EuiCard
245+
icon={<EuiIcon size="xxl" type={`managementApp`} />}
246+
title={
247+
<FormattedMessage
248+
id="xpack.ml.fileDatavisualizer.resultsLinks.indexPatternManagementTitle"
249+
defaultMessage="Index Pattern Management"
250+
/>
251+
}
252+
description=""
253+
href={indexPatternManagementLink}
254+
/>
255+
</EuiFlexItem>
256+
)}
248257
<EuiFlexItem>
249258
<EuiCard
250259
icon={<EuiIcon size="xxl" type={`filebeatApp`} />}

x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import { FormattedMessage } from '@kbn/i18n/react';
3030
import { MlTooltipComponent } from '../../components/chart_tooltip';
3131
import { withKibana } from '../../../../../../../src/plugins/kibana_react/public';
3232
import { ML_APP_URL_GENERATOR } from '../../../../common/constants/ml_url_generator';
33-
import { PLUGIN_ID } from '../../../../common/constants/app';
3433
import { addItemToRecentlyAccessed } from '../../util/recently_accessed';
3534

3635
const textTooManyBuckets = i18n.translate('xpack.ml.explorer.charts.tooManyBucketsDescription', {
@@ -55,21 +54,12 @@ function getChartId(series) {
5554
}
5655

5756
// Wrapper for a single explorer chart
58-
function ExplorerChartContainer({
59-
series,
60-
severity,
61-
tooManyBuckets,
62-
wrapLabel,
63-
navigateToApp,
64-
mlUrlGenerator,
65-
}) {
57+
function ExplorerChartContainer({ series, severity, tooManyBuckets, wrapLabel, mlUrlGenerator }) {
6658
const redirectToSingleMetricViewer = useCallback(async () => {
6759
const singleMetricViewerLink = await getExploreSeriesLink(mlUrlGenerator, series);
6860
addItemToRecentlyAccessed('timeseriesexplorer', series.jobId, singleMetricViewerLink);
6961

70-
await navigateToApp(PLUGIN_ID, {
71-
path: singleMetricViewerLink,
72-
});
62+
window.open(singleMetricViewerLink, '_blank');
7363
}, [mlUrlGenerator]);
7464

7565
const { detectorLabel, entityFields } = series;

x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/extract_job_details.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import React from 'react';
88
import { detectorToString } from '../../../../util/string_utils';
99
import { formatValues, filterObjects } from './format_values';
1010
import { i18n } from '@kbn/i18n';
11-
import { Link } from 'react-router-dom';
11+
import { EuiLink } from '@elastic/eui';
1212

13-
export function extractJobDetails(job) {
13+
export function extractJobDetails(job, basePath) {
1414
if (Object.keys(job).length === 0) {
1515
return {};
1616
}
@@ -61,7 +61,9 @@ export function extractJobDetails(job) {
6161
if (job.calendars) {
6262
calendars.items = job.calendars.map((c) => [
6363
'',
64-
<Link to={`/settings/calendars_list/edit_calendar/${c}?_g=()`}>{c}</Link>,
64+
<EuiLink href={basePath.prepend(`/app/ml/settings/calendars_list/edit_calendar/${c}?_g=()`)}>
65+
{c}
66+
</EuiLink>,
6567
]);
6668
// remove the calendars list from the general section
6769
// so not to show it twice.

0 commit comments

Comments
 (0)