Skip to content
Merged
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
7 changes: 6 additions & 1 deletion src/pages/common/table-selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export interface TableSelectionProps {
onSelectionChanged: (selectedItems: string[]) => void;
}

const rowSelection = {
...defaultRowSelection,
headerCheckbox: false,
};

const TableSelection: FunctionComponent<TableSelectionProps> = (props) => {
const [selectedRowsLength, setSelectedRowsLength] = useState(0);
const gridRef = useRef<AgGridReact>(null);
Expand Down Expand Up @@ -82,7 +87,7 @@ const TableSelection: FunctionComponent<TableSelectionProps> = (props) => {
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
rowSelection={defaultRowSelection}
rowSelection={rowSelection}
getRowId={getRowId}
onSelectionChanged={handleEquipmentSelectionChanged}
onGridReady={onGridReady}
Expand Down
11 changes: 4 additions & 7 deletions src/pages/groups/groups-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import { useIntl } from 'react-intl';
import { GroupAdd } from '@mui/icons-material';
import { GridButton, GridButtonDelete, GridTable, GridTableRef } from '../../components/Grid';
import { GroupInfos, UserAdminSrv, UserInfos } from '../../services';
import { ColDef, GetRowIdParams, RowClickedEvent, SelectionChangedEvent, TextFilterParams } from 'ag-grid-community';
import { ColDef, GetRowIdParams, RowClickedEvent, TextFilterParams } from 'ag-grid-community';
import { useSnackMessage } from '@gridsuite/commons-ui';
import DeleteConfirmationDialog from '../common/delete-confirmation-dialog';
import { defaultColDef, defaultRowSelection } from '../common/table-config';
import MultiChipCellRenderer from '../common/multi-chip-cell-renderer';
import { useTableSelection } from '../../utils/hooks';

export interface GroupsTableProps {
gridRef: RefObject<GridTableRef<GroupInfos>>;
Expand All @@ -26,18 +27,13 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
const intl = useIntl();
const { snackError } = useSnackMessage();

const [rowsSelection, setRowsSelection] = useState<GroupInfos[]>([]);
const { rowsSelection, onSelectionChanged, onFilterChanged } = useTableSelection<GroupInfos>();
const [showDeletionDialog, setShowDeletionDialog] = useState(false);

function getRowId(params: GetRowIdParams<GroupInfos>): string {
return params.data.name;
}

const onSelectionChanged = useCallback(
(event: SelectionChangedEvent<GroupInfos, {}>) => setRowsSelection(event.api.getSelectedRows() ?? []),
[setRowsSelection]
);

const onAddButton = useCallback(() => props.setOpenAddGroupDialog(true), [props]);

const deleteGroups = useCallback((): Promise<void> | undefined => {
Expand Down Expand Up @@ -114,6 +110,7 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
rowSelection={defaultRowSelection}
onRowClicked={props.onRowClicked}
onSelectionChanged={onSelectionChanged}
onFilterChanged={onFilterChanged}
>
<GridButton
labelId="groups.table.toolbar.add.label"
Expand Down
18 changes: 4 additions & 14 deletions src/pages/profiles/profiles-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,12 @@ import { useIntl } from 'react-intl';
import { ManageAccounts } from '@mui/icons-material';
import { GridButton, GridButtonDelete, GridTable, GridTableRef } from '../../components/Grid';
import { UserAdminSrv, UserProfile } from '../../services';
import {
ColDef,
GetRowIdParams,
ITooltipParams,
RowClickedEvent,
SelectionChangedEvent,
TextFilterParams,
} from 'ag-grid-community';
import { ColDef, GetRowIdParams, ITooltipParams, RowClickedEvent, TextFilterParams } from 'ag-grid-community';
import { useSnackMessage } from '@gridsuite/commons-ui';
import DeleteConfirmationDialog from '../common/delete-confirmation-dialog';
import { defaultColDef, defaultRowSelection } from '../common/table-config';
import ValidityCellRenderer from './validity-cell-renderer';
import { useTableSelection } from '../../utils/hooks';

export interface ProfilesTableProps {
gridRef: RefObject<GridTableRef<UserProfile>>;
Expand All @@ -33,18 +27,13 @@ const ProfilesTable: FunctionComponent<ProfilesTableProps> = (props) => {
const intl = useIntl();
const { snackError } = useSnackMessage();

const [rowsSelection, setRowsSelection] = useState<UserProfile[]>([]);
const { rowsSelection, onSelectionChanged, onFilterChanged } = useTableSelection<UserProfile>();
const [showDeletionDialog, setShowDeletionDialog] = useState(false);

function getRowId(params: GetRowIdParams<UserProfile>): string {
return params.data.id ?? '';
}

const onSelectionChanged = useCallback(
(event: SelectionChangedEvent<UserProfile, {}>) => setRowsSelection(event.api.getSelectedRows() ?? []),
[setRowsSelection]
);

const onAddButton = useCallback(() => props.setOpenAddProfileDialog(true), [props]);

const deleteProfiles = useCallback(() => {
Expand Down Expand Up @@ -134,6 +123,7 @@ const ProfilesTable: FunctionComponent<ProfilesTableProps> = (props) => {
rowSelection={defaultRowSelection}
onRowClicked={props.onRowClicked}
onSelectionChanged={onSelectionChanged}
onFilterChanged={onFilterChanged}
>
<GridButton
labelId="profiles.table.toolbar.add.label"
Expand Down
10 changes: 3 additions & 7 deletions src/pages/users/users-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import {
GetRowIdParams,
ICheckboxCellRendererParams,
RowClickedEvent,
SelectionChangedEvent,
TextFilterParams,
} from 'ag-grid-community';
import { useSnackMessage } from '@gridsuite/commons-ui';
import DeleteConfirmationDialog from '../common/delete-confirmation-dialog';
import { defaultColDef, defaultRowSelection } from '../common/table-config';
import MultiChipCellRenderer from '../common/multi-chip-cell-renderer';
import { useTableSelection } from '../../utils/hooks';

export interface UsersTableProps {
gridRef: RefObject<GridTableRef<UserInfos>>;
Expand All @@ -33,18 +33,13 @@ const UsersTable: FunctionComponent<UsersTableProps> = (props) => {
const intl = useIntl();
const { snackError } = useSnackMessage();

const [rowsSelection, setRowsSelection] = useState<UserInfos[]>([]);
const { rowsSelection, onSelectionChanged, onFilterChanged } = useTableSelection<UserInfos>();
const [showDeletionDialog, setShowDeletionDialog] = useState(false);

function getRowId(params: GetRowIdParams<UserInfos>): string {
return params.data.sub ?? '';
}

const onSelectionChanged = useCallback(
(event: SelectionChangedEvent<UserInfos, {}>) => setRowsSelection(event.api.getSelectedRows() ?? []),
[setRowsSelection]
);

const onAddButton = useCallback(() => props.setOpenAddUserDialog(true), [props]);

const deleteUsers = useCallback(() => {
Expand Down Expand Up @@ -147,6 +142,7 @@ const UsersTable: FunctionComponent<UsersTableProps> = (props) => {
rowSelection={defaultRowSelection}
onRowClicked={props.onRowClicked}
onSelectionChanged={onSelectionChanged}
onFilterChanged={onFilterChanged}
tooltipShowDelay={1000}
>
<GridButton
Expand Down
38 changes: 38 additions & 0 deletions src/utils/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { FilterChangedEvent, GridApi, IRowNode, SelectionChangedEvent } from 'ag-grid-community';
import { useCallback, useState } from 'react';

export function useDebugRender(label: string) {
// uncomment when you want the output in the console
/*if (import.meta.env.DEV) {
Expand All @@ -13,3 +16,38 @@ export function useDebugRender(label: string) {
console.timeStamp?.(label);
}*/
}

/**
* Custom hook to handle table row selection with proper filtering support
* @returns Selection state and handlers for AG Grid's selection and filter changes
*/
export function useTableSelection<T>() {
const [rowsSelection, setRowsSelection] = useState<T[]>([]);

// update visible selections based on current filter state
const updateVisibleSelection = useCallback((api: GridApi) => {
const visibleSelectedRows: T[] = [];
api.forEachNodeAfterFilterAndSort((node: IRowNode) => {
if (node.isSelected() && node.data) {
visibleSelectedRows.push(node.data);
}
});
setRowsSelection(visibleSelectedRows);
}, []);

const onSelectionChanged = useCallback(
(event: SelectionChangedEvent) => {
updateVisibleSelection(event.api);
},
[updateVisibleSelection]
);

const onFilterChanged = useCallback(
(event: FilterChangedEvent) => {
updateVisibleSelection(event.api);
},
[updateVisibleSelection]
);

return { rowsSelection, onSelectionChanged, onFilterChanged };
}
Loading