Skip to content

Commit 146bb08

Browse files
change: [M3-9947] - Remove Accordion wrapper from default Alerts tab on Linode details page (#12215)
* Remove Accordion wrapper from Alerts tab on Linode details page * Added changeset: Remove the `Accordion` wrapper from the default Alerts tab and replace it with `Paper` on the Linode details page * Minor fix * console error fix when clearing field manually * Added changeset: Manual clearing of default Alerts fields now resets values to zero, preventing empty string/NaN and ensuring consistency with toggle off * Update changeset * Update `Paper` padding to match ADS spacing
1 parent 4dcfcb6 commit 146bb08

File tree

5 files changed

+136
-115
lines changed

5 files changed

+136
-115
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Changed
3+
---
4+
5+
Remove the `Accordion` wrapper from the default Alerts tab and replace it with `Paper` on the Linode details page ([#12215](https://github.com/linode/manager/pull/12215))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@linode/manager': Fixed
3+
---
4+
5+
Manual clearing of default Alerts fields now resets values to zero, preventing empty string/NaN and ensuring consistency with toggle off state ([#12215](https://github.com/linode/manager/pull/12215))
Lines changed: 85 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {
22
Box,
3-
Divider,
43
fadeIn,
54
FormControlLabel,
65
InputAdornment,
@@ -43,106 +42,103 @@ export const AlertSection = (props: Props) => {
4342
} = props;
4443

4544
return (
46-
<>
45+
<Grid
46+
container
47+
data-qa-alerts-panel
48+
spacing={2}
49+
sx={{
50+
'&:last-of-type': {
51+
marginBottom: 0,
52+
},
53+
'&:last-of-type + hr': {
54+
display: 'none',
55+
},
56+
alignItems: 'flex-start',
57+
flex: 1,
58+
marginBottom: theme.spacing(2),
59+
}}
60+
>
4761
<Grid
48-
container
49-
data-qa-alerts-panel
50-
spacing={2}
62+
size={{
63+
lg: 7,
64+
md: 9,
65+
xs: 12,
66+
}}
5167
sx={{
52-
'&:last-of-type': {
53-
marginBottom: 0,
54-
},
55-
'&:last-of-type + hr': {
56-
display: 'none',
57-
},
58-
alignItems: 'flex-start',
59-
flex: 1,
60-
marginBottom: theme.spacing(2),
68+
display: 'flex',
69+
flexDirection: 'column',
6170
}}
6271
>
63-
<Grid
64-
size={{
65-
lg: 7,
66-
md: 9,
67-
xs: 12,
68-
}}
69-
sx={{
70-
display: 'flex',
71-
flexDirection: 'column',
72-
}}
73-
>
74-
<Box>
75-
<FormControlLabel
76-
control={
77-
<Toggle
78-
checked={state}
79-
disabled={readOnly}
80-
onChange={onStateChange}
81-
/>
82-
}
83-
data-qa-alert={title}
84-
label={title}
85-
sx={{
86-
'& > span:last-child': {
87-
...theme.typography.h3,
88-
},
89-
'.MuiFormControlLabel-label': {
90-
paddingLeft: '12px',
91-
},
92-
}}
93-
/>
94-
</Box>
95-
<Box
72+
<Box>
73+
<FormControlLabel
74+
control={
75+
<Toggle
76+
checked={state}
77+
disabled={readOnly}
78+
onChange={onStateChange}
79+
/>
80+
}
81+
data-qa-alert={title}
82+
label={title}
9683
sx={{
97-
paddingLeft: '70px',
98-
[theme.breakpoints.down('md')]: {
99-
marginTop: '-12px',
84+
'& > span:last-child': {
85+
...theme.typography.h3,
86+
},
87+
'.MuiFormControlLabel-label': {
88+
paddingLeft: '12px',
10089
},
10190
}}
102-
>
103-
<Typography>{copy}</Typography>
104-
</Box>
105-
</Grid>
106-
<Grid
107-
size={{
108-
lg: 5,
109-
md: 3,
110-
xs: 12,
111-
}}
91+
/>
92+
</Box>
93+
<Box
11294
sx={{
113-
paddingBottom: '0',
114-
paddingTop: '0',
95+
paddingLeft: '70px',
11596
[theme.breakpoints.down('md')]: {
116-
paddingLeft: '78px',
97+
marginTop: '-12px',
11798
},
11899
}}
119100
>
120-
<TextField
121-
disabled={!state || readOnly}
122-
error={Boolean(error)}
123-
errorText={error}
124-
InputProps={{
125-
endAdornment: (
126-
<InputAdornment position="end">{endAdornment}</InputAdornment>
127-
),
128-
}}
129-
label={textTitle}
130-
max={Infinity}
131-
min={0}
132-
onChange={onValueChange}
133-
sx={{
134-
'.MuiInput-root': {
135-
animation: `${fadeIn} .3s ease-in-out forwards`,
136-
marginTop: 0,
137-
maxWidth: 150,
138-
},
139-
}}
140-
type="number"
141-
value={value}
142-
/>
143-
</Grid>
101+
<Typography>{copy}</Typography>
102+
</Box>
103+
</Grid>
104+
<Grid
105+
size={{
106+
lg: 5,
107+
md: 3,
108+
xs: 12,
109+
}}
110+
sx={{
111+
paddingBottom: '0',
112+
paddingTop: '0',
113+
[theme.breakpoints.down('md')]: {
114+
paddingLeft: '78px',
115+
},
116+
}}
117+
>
118+
<TextField
119+
disabled={!state || readOnly}
120+
error={Boolean(error)}
121+
errorText={error}
122+
InputProps={{
123+
endAdornment: (
124+
<InputAdornment position="end">{endAdornment}</InputAdornment>
125+
),
126+
}}
127+
label={textTitle}
128+
max={Infinity}
129+
min={0}
130+
onChange={onValueChange}
131+
sx={{
132+
'.MuiInput-root': {
133+
animation: `${fadeIn} .3s ease-in-out forwards`,
134+
marginTop: 0,
135+
maxWidth: 150,
136+
},
137+
}}
138+
type="number"
139+
value={value}
140+
/>
144141
</Grid>
145-
<Divider />
146-
</>
142+
</Grid>
147143
);
148144
};

packages/manager/src/features/Linodes/LinodesDetail/LinodeSettings/LinodeSettingsAlertsPanel.tsx

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useLinodeQuery, useLinodeUpdateMutation } from '@linode/queries';
2-
import { Accordion, ActionsPanel, Notice } from '@linode/ui';
2+
import { ActionsPanel, Divider, Notice, Paper, Typography } from '@linode/ui';
33
import { styled } from '@mui/material/styles';
44
import { useFormik } from 'formik';
55
import { useSnackbar } from 'notistack';
@@ -93,7 +93,10 @@ export const LinodeSettingsAlertsPanel = (props: Props) => {
9393
: 0
9494
),
9595
onValueChange: (e: React.ChangeEvent<HTMLInputElement>) =>
96-
formik.setFieldValue('cpu', e.target.valueAsNumber),
96+
formik.setFieldValue(
97+
'cpu',
98+
!Number.isNaN(e.target.valueAsNumber) ? e.target.valueAsNumber : 0
99+
),
97100
radioInputLabel: 'cpu_usage_state',
98101
state: formik.values.cpu > 0,
99102
textInputLabel: 'cpu_usage_threshold',
@@ -115,7 +118,10 @@ export const LinodeSettingsAlertsPanel = (props: Props) => {
115118
checked ? (linode?.alerts.io ? linode?.alerts.io : 10000) : 0
116119
),
117120
onValueChange: (e: React.ChangeEvent<HTMLInputElement>) =>
118-
formik.setFieldValue('io', e.target.valueAsNumber),
121+
formik.setFieldValue(
122+
'io',
123+
!Number.isNaN(e.target.valueAsNumber) ? e.target.valueAsNumber : 0
124+
),
119125
radioInputLabel: 'disk_io_state',
120126
state: formik.values.io > 0,
121127
textInputLabel: 'disk_io_threshold',
@@ -141,7 +147,10 @@ export const LinodeSettingsAlertsPanel = (props: Props) => {
141147
: 0
142148
),
143149
onValueChange: (e: React.ChangeEvent<HTMLInputElement>) =>
144-
formik.setFieldValue('network_in', e.target.valueAsNumber),
150+
formik.setFieldValue(
151+
'network_in',
152+
!Number.isNaN(e.target.valueAsNumber) ? e.target.valueAsNumber : 0
153+
),
145154
radioInputLabel: 'incoming_traffic_state',
146155
state: formik.values.network_in > 0,
147156
textInputLabel: 'incoming_traffic_threshold',
@@ -167,7 +176,10 @@ export const LinodeSettingsAlertsPanel = (props: Props) => {
167176
: 0
168177
),
169178
onValueChange: (e: React.ChangeEvent<HTMLInputElement>) =>
170-
formik.setFieldValue('network_out', e.target.valueAsNumber),
179+
formik.setFieldValue(
180+
'network_out',
181+
!Number.isNaN(e.target.valueAsNumber) ? e.target.valueAsNumber : 0
182+
),
171183
radioInputLabel: 'outbound_traffic_state',
172184
state: formik.values.network_out > 0,
173185
textInputLabel: 'outbound_traffic_threshold',
@@ -193,7 +205,10 @@ export const LinodeSettingsAlertsPanel = (props: Props) => {
193205
: 0
194206
),
195207
onValueChange: (e: React.ChangeEvent<HTMLInputElement>) =>
196-
formik.setFieldValue('transfer_quota', e.target.valueAsNumber),
208+
formik.setFieldValue(
209+
'transfer_quota',
210+
!Number.isNaN(e.target.valueAsNumber) ? e.target.valueAsNumber : 0
211+
),
197212
radioInputLabel: 'transfer_quota_state',
198213
state: formik.values.transfer_quota > 0,
199214
textInputLabel: 'transfer_quota_threshold',
@@ -203,8 +218,23 @@ export const LinodeSettingsAlertsPanel = (props: Props) => {
203218
},
204219
].filter((thisAlert) => !thisAlert.hidden);
205220

206-
const renderExpansionActions = () => {
207-
return (
221+
const generalError = hasErrorFor('none');
222+
223+
return (
224+
<Paper sx={(theme) => ({ pb: theme.spacingFunction(16) })}>
225+
<Typography
226+
sx={(theme) => ({ mb: theme.spacingFunction(12) })}
227+
variant="h2"
228+
>
229+
Alerts
230+
</Typography>
231+
{generalError && <Notice variant="error">{generalError}</Notice>}
232+
{alertSections.map((p, idx) => (
233+
<React.Fragment key={`alert-${idx}`}>
234+
<AlertSection {...p} readOnly={isReadOnly} />
235+
{idx !== alertSections.length - 1 ? <Divider /> : null}
236+
</React.Fragment>
237+
))}
208238
<StyledActionsPanel
209239
primaryButtonProps={{
210240
'data-testid': 'alerts-save',
@@ -214,22 +244,7 @@ export const LinodeSettingsAlertsPanel = (props: Props) => {
214244
onClick: () => formik.handleSubmit(),
215245
}}
216246
/>
217-
);
218-
};
219-
220-
const generalError = hasErrorFor('none');
221-
222-
return (
223-
<Accordion
224-
actions={renderExpansionActions}
225-
defaultExpanded
226-
heading="Alerts"
227-
>
228-
{generalError && <Notice variant="error">{generalError}</Notice>}
229-
{alertSections.map((p, idx) => (
230-
<AlertSection key={idx} {...p} readOnly={isReadOnly} />
231-
))}
232-
</Accordion>
247+
</Paper>
233248
);
234249
};
235250

packages/ui/src/components/Paper/Paper.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ const StyledPaper = styled(_Paper, {
4141
shouldForwardProp: (prop) => prop !== 'error',
4242
})<Props>(({ theme, ...props }) => ({
4343
borderColor: props.error ? theme.palette.error.dark : undefined,
44-
padding: theme.spacing(3),
45-
paddingTop: 17,
44+
padding: theme.spacingFunction(24),
45+
paddingTop: theme.spacingFunction(16),
4646
}));
4747

4848
const StyledErrorText = styled(FormHelperText)(({ theme }) => ({

0 commit comments

Comments
 (0)