Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@gridsuite/commons-ui": "0.101.0",
"@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.102.0.tgz",
"@hookform/resolvers": "^4.0.0",
"@mui/icons-material": "^5.16.14",
"@mui/lab": "5.0.0-alpha.175",
Expand Down
8 changes: 6 additions & 2 deletions src/components/App/app-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
CardErrorBoundary,
cardErrorBoundaryEn,
cardErrorBoundaryFr,
filterEn,
filterFr,
GsLangUser,
GsTheme,
LANG_ENGLISH,
Expand Down Expand Up @@ -115,16 +117,18 @@ const getMuiTheme = (theme: GsTheme, locale: GsLangUser): Theme => {

const messages: Record<GsLangUser, IntlConfig['messages']> = {
en: {
...messages_en,
...filterEn,
...loginEn,
...topBarEn,
...cardErrorBoundaryEn,
...messages_en,
},
fr: {
...messages_fr,
...filterFr,
...loginFr,
...topBarFr,
...cardErrorBoundaryFr,
...messages_fr,
},
};

Expand Down
8 changes: 5 additions & 3 deletions src/components/App/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ import {
NotificationsUrlKeys,
useNotificationsListener,
useSnackMessage,
useYupIntl,
} from '@gridsuite/commons-ui';
import { selectComputedLanguage, selectLanguage, selectTheme } from '../../redux/actions';
import { AppState } from '../../redux/reducer';
import { ConfigParameters, ConfigSrv } from '../../services';
import type { AppState } from '../../redux/reducer';
import type { AppDispatch } from '../../redux/store';
import { type ConfigParameters, ConfigSrv } from '../../services';
import { APP_NAME, COMMON_APP_NAME, PARAM_LANGUAGE, PARAM_THEME } from '../../utils/config-params';
import { getComputedLanguage } from '../../utils/language';
import AppTopBar from './app-top-bar';
import { useDebugRender } from '../../utils/hooks';
import { AppDispatch } from '../../redux/store';

export default function App({ children }: Readonly<PropsWithChildren<{}>>) {
useDebugRender('app');
useYupIntl();
const { snackError } = useSnackMessage();
const dispatch = useDispatch<AppDispatch>();
const user = useSelector((state: AppState) => state.user);
Expand Down
75 changes: 43 additions & 32 deletions src/pages/announcements/add-announcement-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { Grid } from '@mui/material';
import { type DateOrTimeView } from '@mui/x-date-pickers';
import { useIntl } from 'react-intl';
import { SubmitButton, useSnackMessage } from '@gridsuite/commons-ui';
import yup from '../../utils/yup-config';
import { type InferType } from 'yup';
import type { InferType } from 'yup';
import * as yup from 'yup';
import { type SubmitHandler, useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { FormContainer, SelectElement, TextareaAutosizeElement } from 'react-hook-form-mui';
Expand All @@ -28,42 +28,53 @@ export type AddAnnouncementFormProps = {
onAnnouncementCreated?: () => void;
};

const formSchema = yup
.object()
.shape({
[MESSAGE]: yup.string().nullable().trim().min(1).required(),
[START_DATE]: yup.string().nullable().datetime().required(),
[END_DATE]: yup
.string()
.nullable()
.datetime()
.required()
.when(START_DATE, (startDate, schema) =>
schema.test(
'is-after-start',
'End date must be after start date',
(endDate) => !startDate || !endDate || new Date(endDate) > new Date(startDate as unknown as string)
)
),
[SEVERITY]: yup
.string<UserAdminSrv.AnnouncementSeverity>()
.nullable()
.oneOf(Object.values(UserAdminSrv.AnnouncementSeverity))
.required(),
})
.required();
type FormSchema = InferType<typeof formSchema>;

const datetimePickerTransform: NonNullable<DateTimePickerElementProps<FormSchema>['transform']> = {
input: (value) => (value ? new Date(value) : null),
output: (value) => value?.toISOString() ?? '',
};
const pickerView = ['year', 'month', 'day', 'hours', 'minutes'] as const satisfies readonly DateOrTimeView[];

export default function AddAnnouncementForm({ onAnnouncementCreated }: Readonly<AddAnnouncementFormProps>) {
const intl = useIntl();
const { snackError } = useSnackMessage();

const formSchema = useMemo(
() =>
yup
.object()
.shape({
[MESSAGE]: yup.string().nullable().trim().min(1).required(),
[START_DATE]: yup.string().nullable().datetime().required(),
[END_DATE]: yup
.string()
.nullable()
.datetime()
.required()
.when(START_DATE, (startDate, schema) =>
schema.test(
'is-after-start',
intl.formatMessage({ id: 'announcements.form.errForm.startDateAfterEndDateErr' }),
(endDate) =>
!startDate ||
!endDate ||
new Date(endDate) > new Date(startDate as unknown as string)
)
),
[SEVERITY]: yup
.string<UserAdminSrv.AnnouncementSeverity>()
.nullable()
.oneOf(Object.values(UserAdminSrv.AnnouncementSeverity))
.required(),
})
.required(),
[intl]
);

type FormSchema = InferType<typeof formSchema>;
const datetimePickerTransform = useMemo<NonNullable<DateTimePickerElementProps<FormSchema>['transform']>>(
() => ({
input: (value) => (value ? new Date(value) : null),
output: (value) => value?.toISOString() ?? '',
}),
[]
);

const formContext = useForm({
resolver: yupResolver(formSchema),
defaultValues: {
Expand Down
27 changes: 21 additions & 6 deletions src/pages/groups/modification/group-modification-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import GroupModificationForm, {
GROUP_NAME,
GroupModificationFormType,
GroupModificationSchema,
SELECTED_USERS,
} from './group-modification-form';
import GroupModificationForm, { GROUP_NAME, SELECTED_USERS } from './group-modification-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { useForm } from 'react-hook-form';
import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
import { CustomMuiDialog, FetchStatus, useSnackMessage } from '@gridsuite/commons-ui';
import { GroupInfos, UserAdminSrv, UserInfos } from '../../../services';
import type { InferType } from 'yup';
import * as yup from 'yup';
import { useIntl } from 'react-intl';

interface GroupModificationDialogProps {
groupInfos: GroupInfos | undefined;
Expand All @@ -31,6 +29,23 @@ const GroupModificationDialog: FunctionComponent<GroupModificationDialogProps> =
onUpdate,
}) => {
const { snackError } = useSnackMessage();
const intl = useIntl();

const GroupModificationSchema = useMemo(
() =>
yup
.object()
.shape({
[GROUP_NAME]: yup
.string()
.trim()
.required(intl.formatMessage({ id: 'nameEmpty' })),
[SELECTED_USERS]: yup.string().nullable(),
})
.required(),
[intl]
);
type GroupModificationFormType = InferType<typeof GroupModificationSchema>;
const formMethods = useForm({
resolver: yupResolver(GroupModificationSchema),
});
Expand Down
15 changes: 2 additions & 13 deletions src/pages/groups/modification/group-modification-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,13 @@
*/

import { TextInput } from '@gridsuite/commons-ui';
import Grid from '@mui/material/Grid';
import React, { FunctionComponent } from 'react';
import yup from '../../../utils/yup-config';
import { Grid } from '@mui/material';
import { type FunctionComponent } from 'react';
import TableSelection from '../../common/table-selection';

export const GROUP_NAME = 'name';
export const SELECTED_USERS = 'users';

export const GroupModificationSchema = yup
.object()
.shape({
[GROUP_NAME]: yup.string().trim().required('nameEmpty'),
[SELECTED_USERS]: yup.string().nullable(),
})
.required();

export type GroupModificationFormType = yup.InferType<typeof GroupModificationSchema>;

interface GroupModificationFormProps {
usersOptions: string[];
selectedUsers?: string[];
Expand Down
53 changes: 34 additions & 19 deletions src/pages/profiles/modification/profile-modification-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ import ProfileModificationForm, {
USER_QUOTA_CASE_NB,
NETWORK_VISUALIZATION_PARAMETERS_ID,
} from './profile-modification-form';
import yup from '../../../utils/yup-config';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import { useForm } from 'react-hook-form';
import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
import { type FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
import { CustomMuiDialog, FetchStatus, useSnackMessage } from '@gridsuite/commons-ui';
import { UserAdminSrv, UserProfile } from '../../../services';
import { UUID } from 'crypto';
import { UserAdminSrv, type UserProfile } from '../../../services';
import type { UUID } from 'crypto';
import { useIntl } from 'react-intl';

export interface ProfileModificationDialogProps {
profileId: UUID | undefined;
Expand All @@ -39,23 +40,37 @@ const ProfileModificationDialog: FunctionComponent<ProfileModificationDialogProp
onUpdate,
}) => {
const { snackError } = useSnackMessage();
const intl = useIntl();
const [dataFetchStatus, setDataFetchStatus] = useState<string>(FetchStatus.IDLE);

const formSchema = yup
.object()
.shape({
[PROFILE_NAME]: yup.string().trim().required('nameEmpty'),
[LOADFLOW_PARAM_ID]: yup.string().optional(),
[SECURITY_ANALYSIS_PARAM_ID]: yup.string().optional(),
[SENSITIVITY_ANALYSIS_PARAM_ID]: yup.string().optional(),
[SHORTCIRCUIT_PARAM_ID]: yup.string().optional(),
[VOLTAGE_INIT_PARAM_ID]: yup.string().optional(),
[USER_QUOTA_CASE_NB]: yup.number().positive('userQuotaPositive').nullable(),
[USER_QUOTA_BUILD_NB]: yup.number().positive('userQuotaPositive').nullable(),
[SPREADSHEET_CONFIG_COLLECTION_ID]: yup.string().optional(),
[NETWORK_VISUALIZATION_PARAMETERS_ID]: yup.string().optional(),
})
.required();
const formSchema = useMemo(
() =>
yup
.object()
.shape({
[PROFILE_NAME]: yup
.string()
.trim()
.required(intl.formatMessage({ id: 'nameEmpty' })),
[LOADFLOW_PARAM_ID]: yup.string().optional(),
[SECURITY_ANALYSIS_PARAM_ID]: yup.string().optional(),
[SENSITIVITY_ANALYSIS_PARAM_ID]: yup.string().optional(),
[SHORTCIRCUIT_PARAM_ID]: yup.string().optional(),
[VOLTAGE_INIT_PARAM_ID]: yup.string().optional(),
[USER_QUOTA_CASE_NB]: yup
.number()
.positive(intl.formatMessage({ id: 'userQuotaPositive' }))
.nullable(),
[USER_QUOTA_BUILD_NB]: yup
.number()
.positive(intl.formatMessage({ id: 'userQuotaPositive' }))
.nullable(),
[SPREADSHEET_CONFIG_COLLECTION_ID]: yup.string().optional(),
[NETWORK_VISUALIZATION_PARAMETERS_ID]: yup.string().optional(),
})
.required(),
[intl]
);

const formMethods = useForm({
resolver: yupResolver(formSchema),
Expand Down
Loading
Loading