Skip to content

Commit d93d786

Browse files
upcoming: [M3-10102] - VM Host Maintenance Copy Updates to Banners (linode#12397)
* upcoming: [M3-10102] - Copy updates to banners and new icons * upcoming: [M3-10102] - Remove icons * Added changeset: Copy updates to VM Host Maintenance Banners * Update platform maintenance banner * Add unit test for LinodePlatformMaintenanceBanner --------- Co-authored-by: Jaalah Ramos <[email protected]>
1 parent 134c296 commit d93d786

File tree

6 files changed

+121
-18
lines changed

6 files changed

+121
-18
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
Copy updates to VM Host Maintenance Banners ([#12397](https://github.com/linode/manager/pull/12397))

packages/manager/src/components/MaintenanceBanner/MaintenanceBannerV2.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,19 @@ import { useAllAccountMaintenanceQuery } from '@linode/queries';
22
import { Notice, Typography } from '@linode/ui';
33
import { pluralize } from '@linode/utilities';
44
import React from 'react';
5-
import { useLocation } from 'react-router-dom';
65

76
import { PENDING_MAINTENANCE_FILTER } from 'src/features/Account/Maintenance/utilities';
87
import { isPlatformMaintenance } from 'src/hooks/usePlatformMaintenance';
98

109
import { Link } from '../Link';
1110

12-
export const MaintenanceBannerV2 = () => {
11+
export const MaintenanceBannerV2 = ({ pathname }: { pathname?: string }) => {
1312
const { data: allMaintenance } = useAllAccountMaintenanceQuery(
1413
{},
1514
PENDING_MAINTENANCE_FILTER
1615
);
1716

18-
const location = useLocation();
19-
20-
const hideAccountMaintenanceLink =
21-
location.pathname === '/account/maintenance';
17+
const hideAccountMaintenanceLink = pathname === '/account/maintenance';
2218

2319
// Filter out platform maintenance, since that is handled separately
2420
const linodeMaintenance =

packages/manager/src/components/PlatformMaintenanceBanner/LinodePlatformMaintenanceBanner.test.tsx

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const queryMocks = vi.hoisted(() => ({
1010
useNotificationsQuery: vi.fn().mockReturnValue({}),
1111
useAllAccountMaintenanceQuery: vi.fn().mockReturnValue({}),
1212
useLinodeQuery: vi.fn().mockReturnValue({}),
13+
useLocation: vi.fn(),
1314
}));
1415

1516
vi.mock('@linode/queries', async () => {
@@ -20,8 +21,17 @@ vi.mock('@linode/queries', async () => {
2021
};
2122
});
2223

24+
vi.mock('react-router-dom', async () => {
25+
const actual = await vi.importActual('react-router-dom');
26+
return {
27+
...actual,
28+
useLocation: queryMocks.useLocation,
29+
};
30+
});
31+
2332
beforeEach(() => {
2433
vi.stubEnv('TZ', 'UTC');
34+
queryMocks.useLocation.mockReturnValue({ pathname: '/linodes' });
2535
});
2636

2737
describe('LinodePlatformMaintenanceBanner', () => {
@@ -123,4 +133,86 @@ describe('LinodePlatformMaintenanceBanner', () => {
123133
)
124134
).toBeVisible();
125135
});
136+
137+
it('renders linode label as a link when not on linode detail page', () => {
138+
const mockPlatformMaintenance = accountMaintenanceFactory.buildList(1, {
139+
type: 'reboot',
140+
entity: { type: 'linode', id: 123 },
141+
reason: 'Your Linode needs a critical security update',
142+
when: '2020-01-01T00:00:00',
143+
start_time: '2020-01-01T00:00:00',
144+
});
145+
146+
queryMocks.useAllAccountMaintenanceQuery.mockReturnValue({
147+
data: mockPlatformMaintenance,
148+
});
149+
150+
queryMocks.useLinodeQuery.mockReturnValue({
151+
data: linodeFactory.build({
152+
id: 123,
153+
label: 'test-linode',
154+
}),
155+
});
156+
157+
queryMocks.useNotificationsQuery.mockReturnValue({
158+
data: notificationFactory.buildList(1, {
159+
type: 'security_reboot_maintenance_scheduled',
160+
label: 'Platform Maintenance Scheduled',
161+
}),
162+
});
163+
164+
// Mock location to be on a different page
165+
queryMocks.useLocation.mockReturnValue({ pathname: '/linodes' });
166+
167+
const { getByRole } = renderWithTheme(
168+
<LinodePlatformMaintenanceBanner linodeId={123} />
169+
);
170+
171+
const link = getByRole('link', { name: 'test-linode' });
172+
expect(link).toBeVisible();
173+
expect(link).toHaveAttribute('href', '/linodes/123');
174+
});
175+
176+
it('renders linode label as plain text when on linode detail page', () => {
177+
const mockPlatformMaintenance = accountMaintenanceFactory.buildList(1, {
178+
type: 'reboot',
179+
entity: { type: 'linode', id: 123 },
180+
reason: 'Your Linode needs a critical security update',
181+
when: '2020-01-01T00:00:00',
182+
start_time: '2020-01-01T00:00:00',
183+
});
184+
185+
queryMocks.useAllAccountMaintenanceQuery.mockReturnValue({
186+
data: mockPlatformMaintenance,
187+
});
188+
189+
queryMocks.useLinodeQuery.mockReturnValue({
190+
data: linodeFactory.build({
191+
id: 123,
192+
label: 'test-linode',
193+
}),
194+
});
195+
196+
queryMocks.useNotificationsQuery.mockReturnValue({
197+
data: notificationFactory.buildList(1, {
198+
type: 'security_reboot_maintenance_scheduled',
199+
label: 'Platform Maintenance Scheduled',
200+
}),
201+
});
202+
203+
// Mock location to be on the linode detail page
204+
queryMocks.useLocation.mockReturnValue({ pathname: '/linodes/123' });
205+
206+
const { container, queryByRole } = renderWithTheme(
207+
<LinodePlatformMaintenanceBanner linodeId={123} />
208+
);
209+
210+
// Should show the label as plain text within the Typography component
211+
expect(container.textContent).toContain('test-linode');
212+
213+
// Should not have a link
214+
expect(
215+
queryByRole('link', { name: 'test-linode' })
216+
).not.toBeInTheDocument();
217+
});
126218
});

packages/manager/src/components/PlatformMaintenanceBanner/LinodePlatformMaintenanceBanner.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useLinodeQuery } from '@linode/queries';
22
import { Notice } from '@linode/ui';
33
import { Box, Button, Stack, Typography } from '@linode/ui';
44
import React from 'react';
5+
import { useLocation } from 'react-router-dom';
56

67
import { PowerActionsDialog } from 'src/features/Linodes/PowerActionsDialogOrDrawer';
78
import { usePlatformMaintenance } from 'src/hooks/usePlatformMaintenance';
@@ -15,6 +16,7 @@ export const LinodePlatformMaintenanceBanner = (props: {
1516
linodeId: Linode['id'];
1617
}) => {
1718
const { linodeId } = props;
19+
const location = useLocation();
1820

1921
const { linodesWithPlatformMaintenance, platformMaintenanceByLinode } =
2022
usePlatformMaintenance();
@@ -46,16 +48,22 @@ export const LinodePlatformMaintenanceBanner = (props: {
4648

4749
const startTime = getMaintenanceStartTime(earliestMaintenance);
4850

51+
const hideLinodeLink = location.pathname === `/linodes/${linodeId}`;
52+
4953
return (
5054
<>
5155
<Notice forceImportantIconVerticalCenter variant="warning">
5256
<Stack alignItems="center" direction="row" gap={1}>
5357
<Box flex={1}>
5458
<Typography>
5559
Linode{' '}
56-
<Link to={`/linodes/${linodeId}`}>
57-
{linode?.label ?? linodeId}
58-
</Link>{' '}
60+
{hideLinodeLink ? (
61+
`${linode?.label ?? linodeId}`
62+
) : (
63+
<Link to={`/linodes/${linodeId}`}>
64+
{linode?.label ?? linodeId}
65+
</Link>
66+
)}{' '}
5967
needs to be rebooted for critical platform maintenance.{' '}
6068
{startTime && (
6169
<>

packages/manager/src/components/PlatformMaintenanceBanner/PlatformMaintenanceBanner.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Notice, Typography } from '@linode/ui';
22
import React from 'react';
3-
import { useLocation } from 'react-router-dom';
43

54
import { usePlatformMaintenance } from 'src/hooks/usePlatformMaintenance';
65

@@ -13,13 +12,15 @@ import { Link } from '../Link';
1312
* them separately from the standard MaintenanceBanner.
1413
*/
1514

16-
export const PlatformMaintenanceBanner = () => {
15+
export const PlatformMaintenanceBanner = ({
16+
pathname,
17+
}: {
18+
pathname?: string;
19+
}) => {
1720
const { accountHasPlatformMaintenance, linodesWithPlatformMaintenance } =
1821
usePlatformMaintenance();
1922

20-
const location = useLocation();
21-
const hideAccountMaintenanceLink =
22-
location.pathname === '/account/maintenance';
23+
const hideAccountMaintenanceLink = pathname === '/account/maintenance';
2324

2425
if (!accountHasPlatformMaintenance) return null;
2526

@@ -37,7 +38,7 @@ export const PlatformMaintenanceBanner = () => {
3738
{!hideAccountMaintenanceLink && (
3839
<>
3940
{' '}
40-
See which Linodes are scheduled for reboot on the{' '}
41+
See which Linodes are <strong>scheduled</strong> for reboot on the{' '}
4142
<Link to="/account/maintenance">Account Maintenance</Link> page.
4243
</>
4344
)}

packages/manager/src/features/Account/AccountLanding.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useAccount, useProfile } from '@linode/queries';
2-
import { useMatch, useNavigate } from '@tanstack/react-router';
2+
import { useLocation, useMatch, useNavigate } from '@tanstack/react-router';
33
import * as React from 'react';
44

55
import { DocumentTitleSegment } from 'src/components/DocumentTitle';
@@ -52,6 +52,7 @@ const MaintenanceLanding = React.lazy(
5252

5353
export const AccountLanding = () => {
5454
const navigate = useNavigate();
55+
const location = useLocation();
5556
const match = useMatch({
5657
strict: false,
5758
});
@@ -173,8 +174,8 @@ export const AccountLanding = () => {
173174

174175
return (
175176
<React.Fragment>
176-
<PlatformMaintenanceBanner />
177-
<MaintenanceBannerV2 />
177+
<PlatformMaintenanceBanner pathname={location.pathname} />
178+
<MaintenanceBannerV2 pathname={location.pathname} />
178179
<DocumentTitleSegment segment="Account Settings" />
179180
<LandingHeader {...landingHeaderProps} spacingBottom={4} />
180181

0 commit comments

Comments
 (0)