Skip to content

Commit 8128b25

Browse files
kibanamachinekqualters-elasticlogeekal
authored
[9.2] [Automatic Migrations] Clear migration completion toast notification on navigation (#239058) (#241397)
# Backport This will backport the following commits from `main` to `9.2`: - [[Automatic Migrations] Clear migration completion toast notification on navigation (#239058)](#239058) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Kevin Qualters","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-10-31T02:58:41Z","message":"[Automatic Migrations] Clear migration completion toast notification on navigation (#239058)\n\n## Summary\n\nissue: https://github.com/elastic/kibana/issues/237466\n\nThis pr changes the way migration service classes call toasts so that\nthey can be dismissed as well when a user navigates to the migration\ntable upon completion.\n\n\nhttps://github.com/user-attachments/assets/dd47e9b4-6c8e-4749-8ae7-4a71b5b4e237\n\n\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [x] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.\n\n---------\n\nCo-authored-by: Jatin Kathuria <[email protected]>","sha":"b622962eb1ac479a503ab279f836f2d8029b4cbf","branchLabelMapping":{"^v9.3.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Threat Hunting:Investigations","backport:version","v9.2.0","v9.3.0"],"title":"[Automatic Migrations] Clear migration completion toast notification on navigation","number":239058,"url":"https://github.com/elastic/kibana/pull/239058","mergeCommit":{"message":"[Automatic Migrations] Clear migration completion toast notification on navigation (#239058)\n\n## Summary\n\nissue: https://github.com/elastic/kibana/issues/237466\n\nThis pr changes the way migration service classes call toasts so that\nthey can be dismissed as well when a user navigates to the migration\ntable upon completion.\n\n\nhttps://github.com/user-attachments/assets/dd47e9b4-6c8e-4749-8ae7-4a71b5b4e237\n\n\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [x] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.\n\n---------\n\nCo-authored-by: Jatin Kathuria <[email protected]>","sha":"b622962eb1ac479a503ab279f836f2d8029b4cbf"}},"sourceBranch":"main","suggestedTargetBranches":["9.2"],"targetPullRequestStates":[{"branch":"9.2","label":"v9.2.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.3.0","branchLabelMappingKey":"^v9.3.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/239058","number":239058,"mergeCommit":{"message":"[Automatic Migrations] Clear migration completion toast notification on navigation (#239058)\n\n## Summary\n\nissue: https://github.com/elastic/kibana/issues/237466\n\nThis pr changes the way migration service classes call toasts so that\nthey can be dismissed as well when a user navigates to the migration\ntable upon completion.\n\n\nhttps://github.com/user-attachments/assets/dd47e9b4-6c8e-4749-8ae7-4a71b5b4e237\n\n\n\n### Checklist\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [x] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.\n\n---------\n\nCo-authored-by: Jatin Kathuria <[email protected]>","sha":"b622962eb1ac479a503ab279f836f2d8029b4cbf"}}]}] BACKPORT--> Co-authored-by: Kevin Qualters <[email protected]> Co-authored-by: Jatin Kathuria <[email protected]>
1 parent 02e6493 commit 8128b25

File tree

6 files changed

+66
-64
lines changed

6 files changed

+66
-64
lines changed

x-pack/solutions/security/plugins/security_solution/public/siem_migrations/dashboards/service/dashboard_migrations_service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import * as api from '../api';
2121
import { getMissingCapabilitiesToast } from '../../common/service/notifications/missing_capabilities_notification';
2222
import { getNoConnectorToast } from '../../common/service/notifications/no_connector_notification';
2323
import { SiemMigrationTaskStatus } from '../../../../common/siem_migrations/constants';
24-
import { getSuccessToast } from './notification/success_notification';
24+
import { raiseSuccessToast } from './notification/success_notification';
2525
import type { CapabilitiesLevel, MissingCapability } from '../../common/service/capabilities';
2626
import { getMissingCapabilitiesChecker } from '../../common/service/capabilities';
2727
import { requiredDashboardMigrationCapabilities } from './capabilities';
@@ -221,7 +221,7 @@ export class SiemDashboardMigrationsService extends SiemMigrationsServiceBase<Da
221221
}
222222

223223
protected sendFinishedMigrationNotification(taskStats: DashboardMigrationStats) {
224-
this.core.notifications.toasts.addSuccess(getSuccessToast(taskStats, this.core));
224+
raiseSuccessToast(taskStats, this.core);
225225
}
226226

227227
/** Deletes a dashboard migration by its ID, refreshing the stats to remove it from the list */

x-pack/solutions/security/plugins/security_solution/public/siem_migrations/dashboards/service/notification/success_notification.tsx

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,41 @@ import {
1313
useNavigation,
1414
NavigationProvider,
1515
} from '@kbn/security-solution-navigation';
16-
import type { ToastInput } from '@kbn/core-notifications-browser';
1716
import { toMountPoint } from '@kbn/react-kibana-mount';
1817
import { FormattedMessage } from '@kbn/i18n-react';
1918
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
2019
import type { DashboardMigrationTaskStats } from '../../../../../common/siem_migrations/model/dashboard_migration.gen';
2120

22-
export const getSuccessToast = (
21+
export const raiseSuccessToast = (
2322
migrationStats: DashboardMigrationTaskStats,
2423
core: CoreStart
25-
): ToastInput => ({
26-
color: 'success',
27-
iconType: 'check',
28-
toastLifeTimeMs: 1000 * 60 * 30, // 30 minutes
29-
title: i18n.translate(
30-
'xpack.securitySolution.siemMigrations.dashboardsService.polling.successTitle',
31-
{
32-
defaultMessage: 'Dashboards translation complete.',
33-
}
34-
),
35-
text: toMountPoint(
36-
<NavigationProvider core={core}>
37-
<SuccessToastContent migrationStats={migrationStats} />
38-
</NavigationProvider>,
39-
core
40-
),
41-
});
24+
): void => {
25+
const toast = core.notifications.toasts.addSuccess({
26+
color: 'success',
27+
iconType: 'check',
28+
toastLifeTimeMs: 1000 * 60 * 30, // 30 minutes
29+
title: i18n.translate(
30+
'xpack.securitySolution.siemMigrations.dashboardsService.polling.successTitle',
31+
{
32+
defaultMessage: 'Dashboards translation complete.',
33+
}
34+
),
35+
text: toMountPoint(
36+
<NavigationProvider core={core}>
37+
<SuccessToastContent
38+
migrationStats={migrationStats}
39+
dismissHandler={() => core.notifications.toasts.remove(toast)}
40+
/>
41+
</NavigationProvider>,
42+
core
43+
),
44+
});
45+
};
4246

43-
const SuccessToastContent: React.FC<{ migrationStats: DashboardMigrationTaskStats }> = ({
44-
migrationStats,
45-
}) => {
47+
const SuccessToastContent: React.FC<{
48+
migrationStats: DashboardMigrationTaskStats;
49+
dismissHandler: () => void;
50+
}> = ({ migrationStats, dismissHandler }) => {
4651
const { navigateTo, getAppUrl } = useNavigation();
4752

4853
const navParams = useMemo(() => {
@@ -56,8 +61,9 @@ const SuccessToastContent: React.FC<{ migrationStats: DashboardMigrationTaskStat
5661
deepLinkId: SecurityPageName.siemMigrationsDashboards,
5762
path: migrationStats.id,
5863
});
64+
dismissHandler();
5965
},
60-
[navigateTo, migrationStats.id]
66+
[navigateTo, migrationStats.id, dismissHandler]
6167
);
6268
const url = useMemo(() => getAppUrl(navParams), [getAppUrl, navParams]);
6369

x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/service/notification/success_notification.test.tsx

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77

88
import React from 'react';
99
import { render } from '@testing-library/react';
10-
import { coreMock } from '@kbn/core/public/mocks';
1110
import { useNavigation } from '@kbn/security-solution-navigation';
12-
import { SuccessToastContent, getSuccessToast } from './success_notification';
11+
import { SuccessToastContent } from './success_notification';
1312
import { getRuleMigrationStatsMock } from '../../__mocks__';
1413
import { TestProviders } from '../../../../common/mock';
1514

@@ -34,7 +33,7 @@ describe('Success Notification', () => {
3433
it('renders the component with correct text and button', () => {
3534
const { getByText, getByRole } = render(
3635
<TestProviders>
37-
<SuccessToastContent migration={getRuleMigrationStatsMock()} />
36+
<SuccessToastContent migration={getRuleMigrationStatsMock()} dismissHandler={jest.fn()} />
3837
</TestProviders>
3938
);
4039

@@ -52,7 +51,7 @@ describe('Success Notification', () => {
5251
it('calls navigateTo when the button is clicked', () => {
5352
const { getByRole } = render(
5453
<TestProviders>
55-
<SuccessToastContent migration={getRuleMigrationStatsMock()} />
54+
<SuccessToastContent migration={getRuleMigrationStatsMock()} dismissHandler={jest.fn()} />
5655
</TestProviders>
5756
);
5857

@@ -65,19 +64,4 @@ describe('Success Notification', () => {
6564
});
6665
});
6766
});
68-
69-
describe('getSuccessToast', () => {
70-
it('returns a toast object with the correct properties', () => {
71-
const migration = getRuleMigrationStatsMock();
72-
const toast = getSuccessToast(migration, coreMock.createStart());
73-
74-
expect(toast).toEqual({
75-
color: 'success',
76-
iconType: 'check',
77-
text: expect.any(Function),
78-
title: 'Rules translation complete.',
79-
toastLifeTimeMs: 1800000,
80-
});
81-
});
82-
});
8367
});

x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/service/notification/success_notification.tsx

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,45 @@ import {
1313
useNavigation,
1414
NavigationProvider,
1515
} from '@kbn/security-solution-navigation';
16-
import type { ToastInput } from '@kbn/core-notifications-browser';
1716
import { toMountPoint } from '@kbn/react-kibana-mount';
1817
import { FormattedMessage } from '@kbn/i18n-react';
1918
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
2019
import type { RuleMigrationStats } from '../../types';
2120

22-
export const getSuccessToast = (migration: RuleMigrationStats, core: CoreStart): ToastInput => ({
23-
color: 'success',
24-
iconType: 'check',
25-
toastLifeTimeMs: 1000 * 60 * 30, // 30 minutes
26-
title: i18n.translate('xpack.securitySolution.siemMigrations.rulesService.polling.successTitle', {
27-
defaultMessage: 'Rules translation complete.',
28-
}),
29-
text: toMountPoint(
30-
<NavigationProvider core={core}>
31-
<SuccessToastContent migration={migration} />
32-
</NavigationProvider>,
33-
core
34-
),
35-
});
21+
export const raiseSuccessToast = (migration: RuleMigrationStats, core: CoreStart) => {
22+
const toast = core.notifications.toasts.addSuccess({
23+
color: 'success',
24+
iconType: 'check',
25+
toastLifeTimeMs: 1000 * 60 * 30, // 30 minutes
26+
title: i18n.translate(
27+
'xpack.securitySolution.siemMigrations.rulesService.polling.successTitle',
28+
{
29+
defaultMessage: 'Rules translation complete.',
30+
}
31+
),
32+
text: toMountPoint(
33+
<NavigationProvider core={core}>
34+
<SuccessToastContent
35+
migration={migration}
36+
dismissHandler={() => core.notifications.toasts.remove(toast)}
37+
/>
38+
</NavigationProvider>,
39+
core
40+
),
41+
});
42+
};
3643

37-
export const SuccessToastContent: React.FC<{ migration: RuleMigrationStats }> = ({ migration }) => {
44+
export const SuccessToastContent: React.FC<{
45+
migration: RuleMigrationStats;
46+
dismissHandler: () => void;
47+
}> = ({ migration, dismissHandler }) => {
3848
const navigation = { deepLinkId: SecurityPageName.siemMigrationsRules, path: migration.id };
3949

4050
const { navigateTo, getAppUrl } = useNavigation();
4151
const onClick: React.MouseEventHandler = (ev) => {
4252
ev.preventDefault();
4353
navigateTo(navigation);
54+
dismissHandler();
4455
};
4556
const url = getAppUrl(navigation);
4657

x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/service/rule_migrations_service.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { SiemRulesMigrationsService } from './rule_migrations_service';
3535
import type { CreateRuleMigrationRulesRequestBody } from '../../../../common/siem_migrations/model/api/rules/rule_migration.gen';
3636
import { TASK_STATS_POLLING_SLEEP_SECONDS } from '../../common/constants';
3737
import { getMissingCapabilitiesChecker } from '../../common/service';
38+
import { raiseSuccessToast } from './notification/success_notification';
3839

3940
// --- Mocks for external modules ---
4041

@@ -67,7 +68,7 @@ jest.mock('../../../common/hooks/use_license', () => ({
6768
}));
6869

6970
jest.mock('./notification/success_notification', () => ({
70-
getSuccessToast: jest.fn().mockReturnValue({ title: 'Success' }),
71+
raiseSuccessToast: jest.fn(),
7172
}));
7273

7374
jest.mock('../../common/service/notifications/no_connector_notification', () => ({
@@ -369,7 +370,7 @@ describe('SiemRulesMigrationsService', () => {
369370
expect(getStatsMock).toHaveBeenCalledTimes(2);
370371

371372
// Expect that a success toast was added when the migration finished.
372-
expect(mockNotifications.toasts.addSuccess).toHaveBeenCalled();
373+
expect(raiseSuccessToast).toHaveBeenCalled();
373374

374375
// Restore real timers.
375376
jest.useRealTimers();

x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/service/rule_migrations_service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
getNoConnectorToast,
2727
} from '../../common/service';
2828
import type { GetMigrationStatsParams, GetMigrationsStatsAllParams } from '../../common/types';
29-
import { getSuccessToast } from './notification/success_notification';
29+
import { raiseSuccessToast } from './notification/success_notification';
3030
import { START_STOP_POLLING_SLEEP_SECONDS } from '../../common/constants';
3131

3232
const CREATE_MIGRATION_BODY_BATCH_SIZE = 50;
@@ -238,6 +238,6 @@ export class SiemRulesMigrationsService extends SiemMigrationsServiceBase<RuleMi
238238
}
239239

240240
protected sendFinishedMigrationNotification(taskStats: RuleMigrationStats) {
241-
this.core.notifications.toasts.addSuccess(getSuccessToast(taskStats, this.core));
241+
raiseSuccessToast(taskStats, this.core);
242242
}
243243
}

0 commit comments

Comments
 (0)