Skip to content

Commit 8e9b404

Browse files
committed
group dialog with user table
Signed-off-by: David BRAQUART <[email protected]>
1 parent a00e272 commit 8e9b404

File tree

8 files changed

+94
-129
lines changed

8 files changed

+94
-129
lines changed

src/pages/common/table-selection.tsx

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
*/
77

88
import { FunctionComponent, useCallback, useMemo, useRef, useState } from 'react';
9-
import { FormattedMessage, useIntl } from 'react-intl';
9+
import { FormattedMessage } from 'react-intl';
1010
import { CustomAGGrid } from '@gridsuite/commons-ui';
1111
import { Grid, Typography } from '@mui/material';
1212
import { AgGridReact } from 'ag-grid-react';
13-
import { ColDef, GetRowIdParams, GridReadyEvent, RowSelectionOptions } from 'ag-grid-community';
14-
import { defaultColDef } from './table-config';
13+
import { ColDef, GetRowIdParams, GridReadyEvent } from 'ag-grid-community';
14+
import { defaultColDef, defaultRowSelection } from './table-config';
1515

1616
export interface TableSelectionProps {
1717
itemNameTranslationKey: string;
@@ -21,7 +21,6 @@ export interface TableSelectionProps {
2121
}
2222

2323
const TableSelection: FunctionComponent<TableSelectionProps> = (props) => {
24-
const intl = useIntl();
2524
const [selectedRowsLength, setSelectedRowsLength] = useState(0);
2625
const gridRef = useRef<AgGridReact>(null);
2726

@@ -40,27 +39,16 @@ const TableSelection: FunctionComponent<TableSelectionProps> = (props) => {
4039
return props.tableItems.map((str) => ({ id: str }));
4140
}, [props.tableItems]);
4241

43-
const rowSelection: RowSelectionOptions = {
44-
mode: 'multiRow',
45-
enableClickSelection: false,
46-
checkboxes: true,
47-
headerCheckbox: true,
48-
hideDisabledCheckboxes: false,
49-
};
50-
5142
const columnDefs = useMemo(
5243
(): ColDef[] => [
5344
{
5445
field: 'id',
5546
filter: true,
5647
sortable: true,
5748
minWidth: 80,
58-
headerName: intl.formatMessage({
59-
id: props.itemNameTranslationKey,
60-
}),
6149
},
6250
],
63-
[intl, props.itemNameTranslationKey]
51+
[]
6452
);
6553

6654
function getRowId(params: GetRowIdParams): string {
@@ -93,8 +81,8 @@ const TableSelection: FunctionComponent<TableSelectionProps> = (props) => {
9381
rowData={rowData}
9482
columnDefs={columnDefs}
9583
defaultColDef={defaultColDef}
84+
rowSelection={defaultRowSelection}
9685
getRowId={getRowId}
97-
rowSelection={rowSelection}
9886
onSelectionChanged={handleEquipmentSelectionChanged}
9987
onGridReady={onGridReady}
10088
/>

src/pages/groups/groups-page.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,24 @@ const GroupsPage: FunctionComponent = () => {
4040
}, []);
4141

4242
return (
43-
<Grid item container direction="column" spacing={2} component="section">
44-
<Grid item container xs sx={{ width: 1 }}>
45-
<GroupModificationDialog
46-
groupInfos={editingGroup}
47-
open={openGroupModificationDialog}
48-
onClose={handleCloseGroupModificationDialog}
49-
onUpdate={handleUpdateGroupModificationDialog}
50-
/>
51-
<GroupsTable
52-
gridRef={gridRef}
53-
onRowClicked={onRowClicked}
54-
setOpenAddGroupDialog={setOpenAddGroupDialog}
55-
/>
56-
<AddGroupDialog gridRef={gridRef} open={openAddGroupDialog} setOpen={setOpenAddGroupDialog} />
43+
<>
44+
<Grid item container direction="column" spacing={2} component="section">
45+
<Grid item container xs sx={{ width: 1 }}>
46+
<GroupsTable
47+
gridRef={gridRef}
48+
onRowClicked={onRowClicked}
49+
setOpenAddGroupDialog={setOpenAddGroupDialog}
50+
/>
51+
</Grid>
5752
</Grid>
58-
</Grid>
53+
<AddGroupDialog gridRef={gridRef} open={openAddGroupDialog} setOpen={setOpenAddGroupDialog} />
54+
<GroupModificationDialog
55+
groupInfos={editingGroup}
56+
open={openGroupModificationDialog}
57+
onClose={handleCloseGroupModificationDialog}
58+
onUpdate={handleUpdateGroupModificationDialog}
59+
/>
60+
</>
5961
);
6062
};
6163
export default GroupsPage;

src/pages/groups/groups-table.tsx

Lines changed: 4 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,16 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import { FunctionComponent, RefObject, useCallback, useEffect, useMemo, useState } from 'react';
8+
import { FunctionComponent, RefObject, useCallback, useMemo, useState } from 'react';
99
import { useIntl } from 'react-intl';
1010
import { GroupAdd } from '@mui/icons-material';
1111
import { GridButton, GridButtonDelete, GridTable, GridTableRef } from '../../components/Grid';
12-
import { GroupInfos, UpdateGroupInfos, UserAdminSrv, UserInfos } from '../../services';
13-
import {
14-
ColDef,
15-
GetRowIdParams,
16-
ICellEditorParams,
17-
RowClickedEvent,
18-
SelectionChangedEvent,
19-
TextFilterParams,
20-
} from 'ag-grid-community';
12+
import { GroupInfos, UserAdminSrv, UserInfos } from '../../services';
13+
import { ColDef, GetRowIdParams, RowClickedEvent, SelectionChangedEvent, TextFilterParams } from 'ag-grid-community';
2114
import { useSnackMessage } from '@gridsuite/commons-ui';
2215
import DeleteConfirmationDialog from '../common/delete-confirmation-dialog';
2316
import { defaultColDef, defaultRowSelection } from '../common/table-config';
2417
import MultiChipsRendererComponent from '../common/multi-chips-renderer-component';
25-
import MultiSelectEditorComponent from '../common/multi-select-editor-component';
26-
import { UUID } from 'crypto';
2718

2819
export interface GroupsTableProps {
2920
gridRef: RefObject<GridTableRef<GroupInfos>>;
@@ -37,21 +28,6 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
3728

3829
const [rowsSelection, setRowsSelection] = useState<GroupInfos[]>([]);
3930
const [showDeletionDialog, setShowDeletionDialog] = useState(false);
40-
const [usersOptions, setUsersOptions] = useState<string[]>([]);
41-
42-
useEffect(() => {
43-
UserAdminSrv.fetchUsers()
44-
.then((allUsers: UserInfos[]) => {
45-
const users = allUsers?.map((u) => u.sub) || [];
46-
setUsersOptions(users);
47-
})
48-
.catch((error) =>
49-
snackError({
50-
messageTxt: error.message,
51-
headerId: 'groups.table.error.users',
52-
})
53-
);
54-
}, [snackError]);
5531

5632
function getRowId(params: GetRowIdParams<GroupInfos>): string {
5733
return params.data.name;
@@ -84,25 +60,6 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
8460

8561
const deleteGroupsDisabled = useMemo(() => rowsSelection.length <= 0, [rowsSelection.length]);
8662

87-
const updateGroupCallback = useCallback(
88-
(id: UUID, name: string, users: string[]) => {
89-
const newData: UpdateGroupInfos = {
90-
id: id,
91-
name: name,
92-
users: [],
93-
};
94-
UserAdminSrv.udpateGroup(newData)
95-
.catch((error) =>
96-
snackError({
97-
messageTxt: error.message,
98-
headerId: 'groups.table.error.update',
99-
})
100-
)
101-
.then(() => props.gridRef?.current?.context?.refresh?.());
102-
},
103-
[props.gridRef, snackError]
104-
);
105-
10663
const columns = useMemo(
10764
(): ColDef<GroupInfos>[] => [
10865
{
@@ -136,20 +93,10 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
13693
caseSensitive: false,
13794
trimInput: true,
13895
} as TextFilterParams<UserInfos>,
139-
editable: true,
14096
cellRenderer: MultiChipsRendererComponent,
141-
cellEditor: MultiSelectEditorComponent,
142-
cellEditorParams: (params: ICellEditorParams<GroupInfos>) => ({
143-
options: usersOptions,
144-
setValue: (values: string[]) => {
145-
if (params.data?.id) {
146-
updateGroupCallback(params.data.id, params.data.name, values);
147-
}
148-
},
149-
}),
15097
},
15198
],
152-
[intl, usersOptions, updateGroupCallback]
99+
[intl]
153100
);
154101

155102
return (

src/pages/groups/modification/group-modification-dialog.tsx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import ProfileModificationForm, {
8+
import GroupModificationForm, {
99
GROUP_NAME,
1010
GroupModificationFormType,
1111
GroupModificationSchema,
12+
SELECTED_USERS,
1213
} from './group-modification-form';
1314
import { yupResolver } from '@hookform/resolvers/yup';
1415
import { useForm } from 'react-hook-form';
@@ -33,12 +34,21 @@ const GroupModificationDialog: FunctionComponent<GroupModificationDialogProps> =
3334
const formMethods = useForm({
3435
resolver: yupResolver(GroupModificationSchema),
3536
});
36-
const { reset } = formMethods;
37+
const { reset, setValue } = formMethods;
3738
const [userOptions, setUserOptions] = useState<string[]>([]);
39+
const [selectedUsers, setSelectedUsers] = useState<string[]>([]);
3840
const [dataFetchStatus, setDataFetchStatus] = useState<string>(FetchStatus.IDLE);
3941

4042
useEffect(() => {
4143
if (groupInfos && open) {
44+
const sortedUsers = Array.from(groupInfos.users).sort((a, b) => a.localeCompare(b));
45+
reset({
46+
[GROUP_NAME]: groupInfos.name,
47+
[SELECTED_USERS]: JSON.stringify(sortedUsers), // only used to dirty the form
48+
});
49+
setSelectedUsers(groupInfos.users);
50+
51+
// fetch all users
4252
setDataFetchStatus(FetchStatus.FETCHING);
4353
UserAdminSrv.fetchUsers()
4454
.then((allUsers: UserInfos[]) => {
@@ -55,15 +65,18 @@ const GroupModificationDialog: FunctionComponent<GroupModificationDialogProps> =
5565
});
5666
});
5767
}
58-
}, [open, snackError, groupInfos]);
68+
}, [open, snackError, groupInfos, reset]);
5969

60-
useEffect(() => {
61-
if (groupInfos && open) {
62-
reset({
63-
[GROUP_NAME]: groupInfos.name,
70+
const onSelectionChanged = useCallback(
71+
(selectedItems: string[]) => {
72+
setSelectedUsers(selectedItems);
73+
selectedItems.sort((a, b) => a.localeCompare(b));
74+
setValue(SELECTED_USERS, JSON.stringify(selectedItems), {
75+
shouldDirty: true,
6476
});
65-
}
66-
}, [groupInfos, open, reset]);
77+
},
78+
[setValue]
79+
);
6780

6881
const onDialogClose = useCallback(() => {
6982
setDataFetchStatus(FetchStatus.IDLE);
@@ -76,7 +89,7 @@ const GroupModificationDialog: FunctionComponent<GroupModificationDialogProps> =
7689
const newData: UpdateGroupInfos = {
7790
id: groupInfos.id,
7891
name: groupFormData.name,
79-
users: [],
92+
users: selectedUsers,
8093
};
8194
UserAdminSrv.udpateGroup(newData)
8295
.catch((error) =>
@@ -90,7 +103,7 @@ const GroupModificationDialog: FunctionComponent<GroupModificationDialogProps> =
90103
});
91104
}
92105
},
93-
[onUpdate, snackError, groupInfos]
106+
[groupInfos?.id, selectedUsers, snackError, onUpdate]
94107
);
95108

96109
const isDataReady = useMemo(() => dataFetchStatus === FetchStatus.FETCH_SUCCESS, [dataFetchStatus]);
@@ -106,8 +119,15 @@ const GroupModificationDialog: FunctionComponent<GroupModificationDialogProps> =
106119
titleId={'groups.form.modification.title'}
107120
removeOptional={true}
108121
isDataFetching={isDataFetching}
122+
unscrollableFullHeight
109123
>
110-
{isDataReady && <ProfileModificationForm usersOptions={userOptions} />}
124+
{isDataReady && (
125+
<GroupModificationForm
126+
usersOptions={userOptions}
127+
selectedUsers={selectedUsers}
128+
onSelectionChanged={onSelectionChanged}
129+
/>
130+
)}
111131
</CustomMuiDialog>
112132
);
113133
};

src/pages/groups/modification/group-modification-form.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,45 @@ import { TextInput } from '@gridsuite/commons-ui';
99
import Grid from '@mui/material/Grid';
1010
import React, { FunctionComponent } from 'react';
1111
import yup from '../../../utils/yup-config';
12+
import TableSelection from 'pages/common/table-selection';
1213

1314
export const GROUP_NAME = 'name';
15+
export const SELECTED_USERS = 'users';
1416

1517
export const GroupModificationSchema = yup
1618
.object()
1719
.shape({
1820
[GROUP_NAME]: yup.string().trim().required('nameEmpty'),
21+
[SELECTED_USERS]: yup.string().nullable(),
1922
})
2023
.required();
2124

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

2427
interface GroupModificationFormProps {
2528
usersOptions: string[];
29+
selectedUsers?: string[];
30+
onSelectionChanged: (selectedItems: string[]) => void;
2631
}
2732

28-
const GroupModificationForm: FunctionComponent<GroupModificationFormProps> = ({ usersOptions }) => {
33+
const GroupModificationForm: FunctionComponent<GroupModificationFormProps> = ({
34+
usersOptions,
35+
selectedUsers,
36+
onSelectionChanged,
37+
}) => {
2938
return (
30-
<Grid container spacing={2} marginTop={'auto'}>
39+
<Grid item container spacing={2} marginTop={0} style={{ height: '100%' }}>
3140
<Grid item xs={12}>
3241
<TextInput name={GROUP_NAME} label={'groups.table.id'} clearable={true} />
3342
</Grid>
43+
<Grid item xs={12} style={{ height: '85%' }}>
44+
<TableSelection
45+
itemNameTranslationKey={'groups.table.users'}
46+
tableItems={usersOptions}
47+
tableSelectedItems={selectedUsers}
48+
onSelectionChanged={onSelectionChanged}
49+
/>
50+
</Grid>
3451
</Grid>
3552
);
3653
};

0 commit comments

Comments
 (0)