Skip to content

Commit a75b1a0

Browse files
authored
Merge pull request #3538 from ANIRUDH-SJ/feat/alert-notif-clean
frontend: AlertNotification: Update Storybook with new stories
2 parents 0bcc9ae + dd7f9e8 commit a75b1a0

6 files changed

+264
-18
lines changed

frontend/src/components/common/AlertNotification.stories.tsx

Lines changed: 148 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,166 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { Button } from '@mui/material';
1718
import { Meta, StoryFn } from '@storybook/react';
18-
import { SnackbarProvider } from 'notistack';
19+
import { SnackbarProvider, useSnackbar } from 'notistack';
20+
import React, { useEffect } from 'react';
21+
import { Provider } from 'react-redux';
22+
import { MemoryRouter } from 'react-router-dom';
23+
import store from '../../redux/stores/store';
1924
import { TestContext } from '../../test';
2025
import { PureAlertNotification, PureAlertNotificationProps } from './AlertNotification';
2126

27+
const SnackbarDisplay: React.FC<{
28+
show: boolean;
29+
message: string;
30+
variant: 'error' | 'success' | 'info' | 'warning';
31+
}> = ({ show, message, variant }) => {
32+
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
33+
const key = 'alert-notification-story';
34+
35+
useEffect(() => {
36+
if (show) {
37+
enqueueSnackbar(message, {
38+
key,
39+
variant,
40+
persist: true,
41+
preventDuplicate: true,
42+
anchorOrigin: { vertical: 'top', horizontal: 'center' },
43+
action: snackbarId => (
44+
<Button
45+
onClick={() => closeSnackbar(snackbarId)}
46+
size="small"
47+
sx={{ color: 'common.white' }}
48+
>
49+
Dismiss (Story Action)
50+
</Button>
51+
),
52+
});
53+
} else {
54+
closeSnackbar(key);
55+
}
56+
return () => closeSnackbar(key);
57+
}, [show, message, variant, enqueueSnackbar, closeSnackbar]);
58+
return null;
59+
};
60+
2261
export default {
2362
title: 'AlertNotification',
2463
component: PureAlertNotification,
25-
argTypes: {
26-
dispatch: { action: 'dispatch' },
27-
},
2864
decorators: [
29-
Story => (
30-
<TestContext>
31-
<SnackbarProvider>
32-
<Story />
33-
</SnackbarProvider>
34-
</TestContext>
65+
(Story, context: { args: StoryArgs }) => (
66+
<Provider store={store}>
67+
<MemoryRouter initialEntries={[context.args.initialRoute || '/cluster/test-cluster/pods']}>
68+
<TestContext routerMap={{ cluster: 'test-cluster' }}>
69+
<SnackbarProvider
70+
maxSnack={3}
71+
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
72+
autoHideDuration={null}
73+
>
74+
<div
75+
style={{
76+
position: 'relative',
77+
minHeight: '100px',
78+
border: '1px dashed lightgray',
79+
padding: '10px',
80+
}}
81+
>
82+
<Story />
83+
{context.args.simulateSnackbar && (
84+
<SnackbarDisplay
85+
show={context.args.simulateSnackbar.show}
86+
message={context.args.simulateSnackbar.message}
87+
variant={context.args.simulateSnackbar.variant}
88+
/>
89+
)}
90+
<div
91+
id="snackbar-container"
92+
style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 1400 }}
93+
></div>
94+
</div>
95+
</SnackbarProvider>
96+
</TestContext>
97+
</MemoryRouter>
98+
</Provider>
3599
),
36100
],
37-
} as Meta;
101+
argTypes: {
102+
checkerFunction: { table: { disable: true } },
103+
initialRoute: { control: 'text' },
104+
simulateOffline: { control: 'boolean' },
105+
simulateSnackbar: { control: 'object' },
106+
},
107+
} as Meta<typeof PureAlertNotification & StoryArgs>;
108+
109+
interface StoryArgs extends PureAlertNotificationProps {
110+
initialRoute?: string;
111+
simulateOffline?: boolean;
112+
simulateSnackbar?: {
113+
show: boolean;
114+
message: string;
115+
variant: 'error' | 'success' | 'info' | 'warning';
116+
};
117+
}
118+
119+
const Template: StoryFn<StoryArgs> = args => {
120+
const { checkerFunction, simulateOffline, ...rest } = args;
121+
let originalOnLine: PropertyDescriptor | undefined;
122+
123+
if (typeof simulateOffline === 'boolean') {
124+
originalOnLine = Object.getOwnPropertyDescriptor(window.navigator, 'onLine');
125+
Object.defineProperty(window.navigator, 'onLine', {
126+
configurable: true,
127+
get: () => !simulateOffline,
128+
});
129+
}
38130

39-
const Template: StoryFn<PureAlertNotificationProps> = args => <PureAlertNotification {...args} />;
131+
useEffect(() => {
132+
return () => {
133+
if (typeof simulateOffline === 'boolean' && originalOnLine) {
134+
Object.defineProperty(window.navigator, 'onLine', originalOnLine);
135+
}
136+
};
137+
}, [simulateOffline, originalOnLine]);
138+
139+
return <PureAlertNotification checkerFunction={checkerFunction} {...rest} />;
140+
};
141+
142+
export const NoErrorInitially = Template.bind({});
143+
NoErrorInitially.args = {
144+
checkerFunction: async () => Promise.resolve({ statusText: 'OK' }),
145+
simulateSnackbar: { show: false, message: '', variant: 'info' },
146+
};
147+
NoErrorInitially.storyName = 'No Error (Checker Resolves)';
148+
149+
export const ErrorOnCheck = Template.bind({});
150+
ErrorOnCheck.args = {
151+
checkerFunction: async () => {
152+
await new Promise(resolve => setTimeout(resolve, 50));
153+
return Promise.reject('Cluster unreachable (Simulated Error)');
154+
},
155+
simulateSnackbar: { show: true, message: 'Lost connection to the cluster.', variant: 'error' },
156+
};
157+
ErrorOnCheck.storyName = 'Error on Check (Checker Rejects)';
158+
159+
export const SimulatingOffline = Template.bind({});
160+
SimulatingOffline.args = {
161+
checkerFunction: async () => Promise.resolve({ statusText: 'OK' }),
162+
simulateOffline: true,
163+
};
164+
SimulatingOffline.storyName = 'Navigator Offline';
40165

41-
export const Error = Template.bind({});
42-
Error.args = {
43-
checkerFunction: () => Promise.reject('offline'),
166+
export const OnExcludedRoute = Template.bind({});
167+
OnExcludedRoute.args = {
168+
checkerFunction: async () => Promise.reject('Cluster unreachable (Simulated Error)'),
169+
initialRoute: '/c/test-cluster/login',
44170
};
171+
OnExcludedRoute.storyName = 'On Excluded Route (e.g., Login)';
45172

46-
export const NoError = Template.bind({});
47-
NoError.args = {
48-
checkerFunction: () => Promise.resolve({ statusText: 'OK' }),
173+
export const OnNonClusterRoute = Template.bind({});
174+
OnNonClusterRoute.args = {
175+
checkerFunction: async () => Promise.reject('Cluster unreachable (Simulated Error)'),
176+
initialRoute: '/settings/plugins',
177+
simulateSnackbar: { show: false, message: '', variant: 'info' },
49178
};
179+
OnNonClusterRoute.storyName = 'On Non-Cluster Route (e.g., Global Settings)';
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<body>
2+
<div>
3+
<div
4+
style="position: relative; min-height: 100px; border: 1px dashed lightgray; padding: 10px;"
5+
>
6+
<div
7+
id="snackbar-container"
8+
style="position: absolute; top: 0px; left: 0px; right: 0px; z-index: 1400;"
9+
/>
10+
</div>
11+
<div
12+
class="notistack-SnackbarContainer go3118922589 go4034260886 go1141946668"
13+
>
14+
<div
15+
class="go1475592160 go1671063245"
16+
style="pointer-events: all; overflow: visible; min-height: 0px; transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;"
17+
>
18+
<div
19+
class="notistack-CollapseWrapper"
20+
style="display: flex; width: 100%;"
21+
>
22+
<div
23+
class="notistack-Snackbar go3963613292"
24+
>
25+
<div
26+
aria-describedby="notistack-snackbar"
27+
class="go1888806478 notistack-MuiContent notistack-MuiContent-error go167266335 go3651055292 go3162094071"
28+
role="alert"
29+
style="webkit-transform: none; transform: none; webkit-transition: -webkit-transform 225ms cubic-bezier(0.0, 0, 0.2, 1) 0ms; transition: transform 225ms cubic-bezier(0.0, 0, 0.2, 1) 0ms;"
30+
>
31+
<div
32+
class="go946087465"
33+
id="notistack-snackbar"
34+
>
35+
<svg
36+
focusable="false"
37+
style="font-size: 20px; margin-inline-end: 8px; user-select: none; width: 1em; height: 1em; display: inline-block; fill: currentColor; flex-shrink: 0;"
38+
viewBox="0 0 24 24"
39+
>
40+
<path
41+
d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,
42+
6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,
43+
13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z"
44+
/>
45+
</svg>
46+
Lost connection to the cluster.
47+
</div>
48+
<div
49+
class="go703367398"
50+
>
51+
<button
52+
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButton-colorPrimary MuiButton-disableElevation MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButton-colorPrimary MuiButton-disableElevation css-ropn2u-MuiButtonBase-root-MuiButton-root"
53+
tabindex="0"
54+
type="button"
55+
>
56+
Dismiss (Story Action)
57+
<span
58+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
59+
/>
60+
</button>
61+
</div>
62+
</div>
63+
</div>
64+
</div>
65+
</div>
66+
</div>
67+
</div>
68+
</body>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<body>
2+
<div>
3+
<div
4+
style="position: relative; min-height: 100px; border: 1px dashed lightgray; padding: 10px;"
5+
>
6+
<div
7+
id="snackbar-container"
8+
style="position: absolute; top: 0px; left: 0px; right: 0px; z-index: 1400;"
9+
/>
10+
</div>
11+
</div>
12+
</body>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<body>
2+
<div>
3+
<div
4+
style="position: relative; min-height: 100px; border: 1px dashed lightgray; padding: 10px;"
5+
>
6+
<div
7+
id="snackbar-container"
8+
style="position: absolute; top: 0px; left: 0px; right: 0px; z-index: 1400;"
9+
/>
10+
</div>
11+
</div>
12+
</body>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<body>
2+
<div>
3+
<div
4+
style="position: relative; min-height: 100px; border: 1px dashed lightgray; padding: 10px;"
5+
>
6+
<div
7+
id="snackbar-container"
8+
style="position: absolute; top: 0px; left: 0px; right: 0px; z-index: 1400;"
9+
/>
10+
</div>
11+
</div>
12+
</body>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<body>
2+
<div>
3+
<div
4+
style="position: relative; min-height: 100px; border: 1px dashed lightgray; padding: 10px;"
5+
>
6+
<div
7+
id="snackbar-container"
8+
style="position: absolute; top: 0px; left: 0px; right: 0px; z-index: 1400;"
9+
/>
10+
</div>
11+
</div>
12+
</body>

0 commit comments

Comments
 (0)