Skip to content

Commit 8c926c3

Browse files
committed
add announcement page
Signed-off-by: Abdelsalem <[email protected]>
1 parent 5ac5528 commit 8c926c3

File tree

14 files changed

+635
-3
lines changed

14 files changed

+635
-3
lines changed

package-lock.json

Lines changed: 92 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121
"@mui/icons-material": "^5.16.14",
2222
"@mui/lab": "5.0.0-alpha.175",
2323
"@mui/material": "^5.16.14",
24+
"@mui/x-date-pickers": "^7.28.3",
2425
"@mui/x-tree-view": "^6.17.0",
2526
"@reduxjs/toolkit": "^2.5.1",
2627
"ag-grid-community": "^33.1.0",
2728
"ag-grid-react": "^33.1.0",
2829
"core-js": "^3.40.0",
30+
"dayjs": "^1.11.13",
2931
"notistack": "^3.0.2",
3032
"oidc-client": "^1.11.5",
3133
"react": "^18.3.1",

src/components/App/app-top-bar.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
useState,
1616
} from 'react';
1717
import { capitalize, Tab, Tabs, useTheme } from '@mui/material';
18-
import { Groups, ManageAccounts, PeopleAlt } from '@mui/icons-material';
18+
import { Groups, ManageAccounts, PeopleAlt, NotificationImportant } from '@mui/icons-material';
1919
import { fetchAppsMetadata, logout, Metadata, TopBar } from '@gridsuite/commons-ui';
2020
import { useParameterState } from '../parameters';
2121
import { APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../../utils/config-params';
@@ -73,6 +73,20 @@ const tabs = new Map<MainPaths, ReactElement>([
7373
))}
7474
/>,
7575
],
76+
[
77+
MainPaths.banners,
78+
<Tab
79+
icon={<NotificationImportant />}
80+
label={<FormattedMessage id="appBar.tabs.warningBanner" />}
81+
href={`/${MainPaths.banners}`}
82+
value={MainPaths.banners}
83+
key={`tab-${MainPaths.banners}`}
84+
iconPosition="start"
85+
LinkComponent={forwardRef<HTMLAnchorElement, AnchorHTMLAttributes<HTMLAnchorElement>>((props, ref) => (
86+
<NavLink ref={ref} to={props.href as To} {...props} />
87+
))}
88+
/>,
89+
],
7690
]);
7791

7892
const AppTopBar: FunctionComponent = () => {
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
import { CustomFormProvider, SubmitButton, useSnackMessage } from '@gridsuite/commons-ui';
9+
import Grid from '@mui/material/Grid';
10+
import { FormattedMessage, useIntl } from 'react-intl';
11+
import React, { FunctionComponent, useCallback } from 'react';
12+
import { FormControl, InputLabel, MenuItem, Select, TextField } from '@mui/material';
13+
import { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
14+
import { UserAdminSrv, Announcement } from '../../services';
15+
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
16+
import { useForm } from 'react-hook-form';
17+
import { yupResolver } from '@hookform/resolvers/yup';
18+
import yup from '../../utils/yup-config';
19+
import 'dayjs/locale/fr';
20+
import 'dayjs/locale/en';
21+
import { useParameterState } from '../../components/parameters';
22+
import { PARAM_LANGUAGE } from '../../utils/config-params';
23+
import { getErrorMessage, handleAnnouncementCreationErrors } from '../../utils/error';
24+
25+
export const MESSAGE = 'message';
26+
export const START_DATE = 'startDate';
27+
export const END_DATE = 'endDate';
28+
export const SEVERITY = 'severity';
29+
30+
interface AddAnnouncementProps {
31+
onAnnouncementCreated: () => void;
32+
}
33+
34+
const AddAnnouncementForm: FunctionComponent<AddAnnouncementProps> = ({ onAnnouncementCreated }) => {
35+
const intl = useIntl();
36+
const [languageLocal] = useParameterState(PARAM_LANGUAGE);
37+
const { snackError } = useSnackMessage();
38+
39+
const formSchema = yup
40+
.object()
41+
.shape({
42+
[MESSAGE]: yup.string().trim().required(),
43+
[START_DATE]: yup.string().required(),
44+
[END_DATE]: yup.string().required(),
45+
[SEVERITY]: yup.string().required(),
46+
})
47+
.required();
48+
49+
const formMethods = useForm({
50+
resolver: yupResolver(formSchema),
51+
});
52+
53+
const { register, setValue, handleSubmit, formState } = formMethods;
54+
55+
const onSubmit = useCallback(
56+
(params: any) => {
57+
let startDate = new Date(params.startDate).toISOString();
58+
let endDate = new Date(params.endDate).toISOString();
59+
const newAnnouncement = {
60+
id: crypto.randomUUID(),
61+
message: params.message,
62+
startDate: startDate,
63+
endDate: endDate,
64+
severity: params.severity,
65+
} as Announcement;
66+
UserAdminSrv.addAnnouncement(newAnnouncement)
67+
.then(() => onAnnouncementCreated())
68+
.catch((error) => {
69+
let errorMessage = getErrorMessage(error) ?? '';
70+
if (!handleAnnouncementCreationErrors(errorMessage, snackError)) {
71+
snackError({
72+
headerId: 'errCreateAnnouncement',
73+
messageTxt: errorMessage,
74+
});
75+
}
76+
});
77+
},
78+
[onAnnouncementCreated, snackError]
79+
);
80+
81+
return (
82+
<CustomFormProvider validationSchema={formSchema} {...formMethods}>
83+
<Grid container spacing={1}>
84+
<Grid item xs={4}>
85+
<TextField
86+
{...register('message')}
87+
id="message-input"
88+
label={intl.formatMessage({ id: 'banners.table.message' })}
89+
multiline
90+
rows={4}
91+
fullWidth
92+
inputProps={{ maxLength: 200 }}
93+
/>
94+
</Grid>
95+
<Grid item xs={2}>
96+
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={languageLocal}>
97+
<DateTimePicker
98+
{...register('startDate')}
99+
name={START_DATE}
100+
label={intl.formatMessage({ id: 'banners.table.startDate' })}
101+
onChange={(newValue) => setValue('startDate', newValue)}
102+
/>
103+
</LocalizationProvider>
104+
</Grid>
105+
<Grid item xs={2}>
106+
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={languageLocal}>
107+
<DateTimePicker
108+
{...register('endDate')}
109+
name={END_DATE}
110+
label={intl.formatMessage({ id: 'banners.table.endDate' })}
111+
onChange={(newValue) => setValue('endDate', newValue)}
112+
/>
113+
</LocalizationProvider>
114+
</Grid>
115+
116+
<Grid item xs={2}>
117+
<FormControl fullWidth>
118+
<InputLabel id="severity-input-label">
119+
<FormattedMessage id="banners.table.severity" />
120+
</InputLabel>
121+
<Select
122+
{...register('severity')}
123+
name={SEVERITY}
124+
label={intl.formatMessage({ id: 'banners.table.severity' })}
125+
fullWidth={true}
126+
defaultValue={''}
127+
>
128+
<MenuItem value={UserAdminSrv.AnnouncementSeverity.INFO}>
129+
{intl.formatMessage({ id: 'banners.table.info' })}
130+
</MenuItem>
131+
<MenuItem value={UserAdminSrv.AnnouncementSeverity.WARN}>
132+
{intl.formatMessage({ id: 'banners.table.warn' })}
133+
</MenuItem>
134+
</Select>
135+
</FormControl>
136+
</Grid>
137+
138+
<Grid item xs={2}>
139+
<SubmitButton
140+
variant="outlined"
141+
onClick={handleSubmit(onSubmit)}
142+
fullWidth={true}
143+
disabled={!formState.isValid || formState.isValidating}
144+
/>
145+
</Grid>
146+
</Grid>
147+
</CustomFormProvider>
148+
);
149+
};
150+
151+
export default AddAnnouncementForm;

0 commit comments

Comments
 (0)