Skip to content

Commit 1ba4648

Browse files
Added: [DI-29070] - New feature marker in navigation menu and primary breadcrumbs of CloudPulse metrics (#13230)
* Added: [DI-29070] - new feature marker in navigation menu and primary breadcrumbs * Added: [DI-29070] - Changeset * Added: [DI-29069] - new feature chip refined control * Added: [DI-29069] - fix test
1 parent cb8fb31 commit 1ba4648

File tree

7 files changed

+84
-6
lines changed

7 files changed

+84
-6
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Added
3+
---
4+
5+
New feature marker in navigation menu and primary breadcrumbs of `CloudPulse metrics` ([#13230](https://github.com/linode/manager/pull/13230))

packages/manager/cypress/e2e/core/cloudpulse/cloudpulse-navigation.spec.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,17 @@ describe('Moniter navigation', () => {
2222
it('can navigate to metrics landing page', () => {
2323
mockAppendFeatureFlags({
2424
aclp: {
25-
beta: true,
25+
beta: false,
2626
enabled: true,
27+
new: true,
2728
},
2829
}).as('getFeatureFlags');
2930

3031
cy.visitWithLogin('/linodes');
3132
cy.wait('@getFeatureFlags');
32-
33+
cy.get('[data-testid="menu-item-Metrics"]').within(() => {
34+
cy.get('[data-testid="newFeatureChip"]').should('be.visible'); // check for new feature chip
35+
});
3336
cy.get('[data-testid="menu-item-Metrics"]').should('be.visible').click();
3437
cy.url().should('endWith', '/metrics');
3538
});

packages/manager/src/components/PrimaryNav/PrimaryNav.test.tsx

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ describe('PrimaryNav', () => {
228228
aclp: {
229229
beta: true,
230230
enabled: true,
231+
new: true,
231232
},
232233
aclpAlerting: {
233234
accountAlertLimit: 10,
@@ -239,7 +240,7 @@ describe('PrimaryNav', () => {
239240
},
240241
};
241242

242-
const { findAllByTestId, findByText } = renderWithTheme(
243+
const { findAllByTestId, findByText, queryByTestId } = renderWithTheme(
243244
<PrimaryNav {...props} />,
244245
{
245246
flags,
@@ -249,12 +250,57 @@ describe('PrimaryNav', () => {
249250
const monitorMetricsDisplayItem = await findByText('Metrics');
250251
const monitorAlertsDisplayItem = await findByText('Alerts');
251252
const betaChip = await findAllByTestId('betaChip');
253+
const newFeatureChip = queryByTestId('newFeatureChip');
254+
expect(newFeatureChip).toBeNull(); // when beta is true, only beta chip is shown not new chip
252255

253256
expect(monitorMetricsDisplayItem).toBeVisible();
254257
expect(monitorAlertsDisplayItem).toBeVisible();
255258
expect(betaChip).toHaveLength(2);
256259
});
257260

261+
it('shoud show beta chip next to Metrics menu item if the user has the account capability and aclp feature flag has new true', async () => {
262+
const account = accountFactory.build({
263+
capabilities: ['Akamai Cloud Pulse'],
264+
});
265+
266+
queryMocks.useAccount.mockReturnValue({
267+
data: account,
268+
isLoading: false,
269+
error: null,
270+
});
271+
272+
const flags = {
273+
aclp: {
274+
beta: false,
275+
enabled: true,
276+
new: true,
277+
},
278+
aclpAlerting: {
279+
accountAlertLimit: 10,
280+
accountMetricLimit: 10,
281+
alertDefinitions: true,
282+
beta: true,
283+
notificationChannels: false,
284+
recentActivity: false,
285+
},
286+
};
287+
288+
const { findByText, findByTestId } = renderWithTheme(
289+
<PrimaryNav {...props} />,
290+
{
291+
flags,
292+
}
293+
);
294+
295+
const monitorMetricsDisplayItem = await findByText('Metrics');
296+
const monitorAlertsDisplayItem = await findByText('Alerts');
297+
const newFeatureChip = await findByTestId('newFeatureChip');
298+
299+
expect(monitorMetricsDisplayItem).toBeVisible();
300+
expect(monitorAlertsDisplayItem).toBeVisible();
301+
expect(newFeatureChip).toBeVisible();
302+
});
303+
258304
it('should not show Metrics and Alerts menu items if the user has the account capability but the aclp feature flag is not enabled', async () => {
259305
const account = accountFactory.build({
260306
capabilities: ['Akamai Cloud Pulse'],

packages/manager/src/components/PrimaryNav/PrimaryNav.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ export const PrimaryNav = (props: PrimaryNavProps) => {
243243
hide: !isACLPEnabled,
244244
to: '/metrics',
245245
isBeta: flags.aclp?.beta,
246+
isNew: !flags.aclp?.beta && flags.aclp?.new,
246247
},
247248
{
248249
display: 'Alerts',

packages/manager/src/featureFlags.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ interface AclpFlag {
104104
*/
105105
humanizableUnits?: string[];
106106

107+
/**
108+
* This property indicates whether the feature is new or not
109+
*/
110+
new?: boolean;
111+
107112
/**
108113
* This property indicates whether to show widget dimension filters or not
109114
*/

packages/manager/src/features/CloudPulse/Dashboard/CloudPulseDashboardLanding.test.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,15 @@ vi.spyOn(utils, 'getAllDashboards').mockReturnValue({
5050
});
5151
describe('CloudPulseDashboardFilterBuilder component tests', () => {
5252
it('should render error placeholder if dashboard not selected', () => {
53-
renderWithTheme(<CloudPulseDashboardLanding />);
53+
renderWithTheme(<CloudPulseDashboardLanding />, {
54+
flags: {
55+
aclp: {
56+
new: true,
57+
beta: false,
58+
enabled: true,
59+
},
60+
},
61+
});
5462
const text = screen.getByText('metrics');
5563
expect(text).toBeInTheDocument();
5664

@@ -61,6 +69,9 @@ describe('CloudPulseDashboardFilterBuilder component tests', () => {
6169

6270
const messageComponent = screen.getByText(message);
6371
expect(messageComponent).toBeDefined();
72+
73+
const newFeatureChip = screen.getByTestId('newFeatureChip');
74+
expect(newFeatureChip).toBeVisible();
6475
});
6576

6677
it('should render error placeholder if some dashboard is selected and filter config is not present', async () => {

packages/manager/src/features/CloudPulse/Dashboard/CloudPulseDashboardLanding.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { useProfile } from '@linode/queries';
2-
import { Box, Paper } from '@linode/ui';
2+
import { Box, NewFeatureChip, Paper } from '@linode/ui';
33
import { GridLegacy } from '@mui/material';
44
import { DateTime } from 'luxon';
55
import * as React from 'react';
66

77
import { DocumentTitleSegment } from 'src/components/DocumentTitle';
88
import { LandingHeader } from 'src/components/LandingHeader';
99
import { SuspenseLoader } from 'src/components/SuspenseLoader';
10+
import { useFlags } from 'src/hooks/useFlags';
1011

1112
import { GlobalFilters } from '../Overview/GlobalFilters';
1213
import { CloudPulseAppliedFilterRenderer } from '../shared/CloudPulseAppliedFilterRenderer';
@@ -33,6 +34,7 @@ export interface DashboardProp {
3334

3435
export const CloudPulseDashboardLanding = () => {
3536
const { data: profile } = useProfile();
37+
const flags = useFlags();
3638
const [filterData, setFilterData] = React.useState<FilterData>({
3739
id: {},
3840
label: {},
@@ -101,7 +103,12 @@ export const CloudPulseDashboardLanding = () => {
101103
<React.Suspense fallback={<SuspenseLoader />}>
102104
<DocumentTitleSegment segment="Dashboards" />
103105
<LandingHeader
104-
breadcrumbProps={{ pathname: '/metrics' }}
106+
breadcrumbProps={{
107+
pathname: '/metrics',
108+
labelOptions: {
109+
suffixComponent: flags.aclp?.new ? <NewFeatureChip /> : undefined,
110+
},
111+
}}
105112
docsLabel="Docs"
106113
docsLink="https://techdocs.akamai.com/cloud-computing/docs/akamai-cloud-pulse"
107114
/>

0 commit comments

Comments
 (0)