Skip to content

Commit f5708a7

Browse files
committed
dynamically adjust chip limit
Signed-off-by: Ayoub LABIDI <[email protected]>
1 parent 0ac12bb commit f5708a7

File tree

4 files changed

+59
-55
lines changed

4 files changed

+59
-55
lines changed

src/components/Grid/GridTable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export const GridTable: GridTableWithRef = forwardRef(function AgGridToolbar<TDa
7676
);
7777

7878
return (
79-
<Grid container direction="column" justifyContent="flex-start" alignItems="stretch">
79+
<Grid container direction="column" justifyContent="flex-start" alignItems="stretch" width={'100%'}>
8080
<Grid item xs="auto">
8181
<AppBar position="static" color="default">
8282
<Toolbar

src/pages/common/multi-chip-cell-renderer.tsx

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

8-
import { Chip, Grid } from '@mui/material';
8+
import React, { useRef, useState, useEffect } from 'react';
9+
import { Chip, Grid, Tooltip } from '@mui/material';
910
import { mergeSx } from '@gridsuite/commons-ui';
1011

11-
const CHIP_LIMIT_NUMBER: number = 5;
12+
const maxChipWidth = 100;
13+
const counterChipWidth = 25;
1214

1315
const chipStyles = {
1416
default: {
15-
marginTop: '16px',
16-
marginLeft: '8px',
17-
maxWidth: '50%',
17+
marginTop: 2,
18+
marginLeft: 1,
19+
maxWidth: maxChipWidth,
1820
},
1921
withCounter: {
2022
'&.MuiChip-root': {
@@ -29,28 +31,62 @@ export interface MultiChipCellRendererProps {
2931

3032
const MultiChipCellRenderer = (props: MultiChipCellRendererProps) => {
3133
const values: string[] = props.value || [];
34+
const containerRef = useRef<HTMLDivElement>(null);
35+
const [chipLimit, setChipLimit] = useState<number>(5);
36+
37+
useEffect(() => {
38+
const updateChipLimit = () => {
39+
if (!containerRef.current) {
40+
return;
41+
}
42+
const zoomLevel = window.devicePixelRatio;
43+
const adjustedContainerWidth = containerRef.current.clientWidth / zoomLevel;
44+
const maxChips = Math.max(1, Math.floor(adjustedContainerWidth / (maxChipWidth + counterChipWidth)));
45+
setChipLimit(maxChips);
46+
};
47+
48+
updateChipLimit();
49+
const resizeObserver = new ResizeObserver(updateChipLimit);
50+
if (containerRef.current) {
51+
resizeObserver.observe(containerRef.current);
52+
}
53+
return () => resizeObserver.disconnect();
54+
}, [values.length]);
3255

3356
const customChip = (label: string, index: number, chipsNumber: number) => {
34-
if (index < CHIP_LIMIT_NUMBER) {
35-
return <Chip key={label} label={label} size={'small'} sx={chipStyles.default} />;
36-
} else if (index === CHIP_LIMIT_NUMBER) {
57+
if (index < chipLimit) {
58+
return (
59+
<Tooltip title={label} key={`tooltip-${label}`}>
60+
<Chip key={label} label={label} size="small" sx={chipStyles.default} />
61+
</Tooltip>
62+
);
63+
} else if (index === chipLimit) {
64+
const hiddenLabels = values.slice(chipLimit);
65+
const tooltipContent = (
66+
<>
67+
{hiddenLabels.map((hiddenLabel) => (
68+
<div key={`hidden-label-${hiddenLabel}`}>{'- ' + hiddenLabel}</div>
69+
))}
70+
</>
71+
);
72+
3773
return (
38-
<Chip
39-
size="small"
40-
label={`+${chipsNumber - CHIP_LIMIT_NUMBER}`}
41-
key={label}
42-
sx={mergeSx(chipStyles.default, chipStyles.withCounter)}
43-
/>
74+
<Tooltip title={tooltipContent} key="tooltip-counter">
75+
<Chip
76+
size="small"
77+
label={`+${chipsNumber - chipLimit}`}
78+
key="chip-counter"
79+
sx={mergeSx(chipStyles.default, chipStyles.withCounter)}
80+
/>
81+
</Tooltip>
4482
);
4583
}
46-
return undefined;
84+
return null;
4785
};
4886

4987
return (
50-
<Grid container direction="row" spacing={1} wrap="nowrap" sx={{ overflow: 'auto hidden' }}>
51-
{values.map((label: string, index: number) => {
52-
return customChip(label, index, values.length);
53-
})}
88+
<Grid container direction="row" spacing={1} wrap="nowrap" ref={containerRef}>
89+
{values.map((label: string, index: number) => customChip(label, index, values.length))}
5490
</Grid>
5591
);
5692
};

src/pages/groups/groups-table.tsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ import { useIntl } from 'react-intl';
1010
import { GroupAdd } from '@mui/icons-material';
1111
import { GridButton, GridButtonDelete, GridTable, GridTableRef } from '../../components/Grid';
1212
import { GroupInfos, UserAdminSrv, UserInfos } from '../../services';
13-
import {
14-
ColDef,
15-
GetRowIdParams,
16-
ITooltipParams,
17-
RowClickedEvent,
18-
SelectionChangedEvent,
19-
TextFilterParams,
20-
} from 'ag-grid-community';
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';
@@ -88,6 +81,7 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
8881
},
8982
{
9083
field: 'users',
84+
minWidth: 200,
9185
cellDataType: 'text',
9286
flex: 3,
9387
filter: true,
@@ -102,19 +96,6 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
10296
trimInput: true,
10397
} as TextFilterParams<UserInfos>,
10498
cellRenderer: MultiChipCellRenderer,
105-
tooltipValueGetter: (p: ITooltipParams) => {
106-
const items = p.value as string[];
107-
if (items == null || items.length === 0) {
108-
return '';
109-
}
110-
let userWord = intl.formatMessage({
111-
id: 'form.delete.dialog.user',
112-
});
113-
if (items.length > 1) {
114-
userWord = userWord.concat('s');
115-
}
116-
return `${items.length} ${userWord}`;
117-
},
11899
},
119100
],
120101
[intl]

src/pages/users/users-table.tsx

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
ColDef,
1515
GetRowIdParams,
1616
ICheckboxCellRendererParams,
17-
ITooltipParams,
1817
RowClickedEvent,
1918
SelectionChangedEvent,
2019
TextFilterParams,
@@ -100,6 +99,7 @@ const UsersTable: FunctionComponent<UsersTableProps> = (props) => {
10099
},
101100
{
102101
field: 'groups',
102+
minWidth: 200,
103103
cellDataType: 'text',
104104
flex: 4,
105105
filter: true,
@@ -114,19 +114,6 @@ const UsersTable: FunctionComponent<UsersTableProps> = (props) => {
114114
trimInput: true,
115115
} as TextFilterParams<GroupInfos>,
116116
cellRenderer: MultiChipCellRenderer,
117-
tooltipValueGetter: (p: ITooltipParams) => {
118-
const items = p.value as string[];
119-
if (items == null || items.length === 0) {
120-
return '';
121-
}
122-
let groupWord = intl.formatMessage({
123-
id: 'form.delete.dialog.group',
124-
});
125-
if (items.length > 1) {
126-
groupWord = groupWord.concat('s');
127-
}
128-
return `${items.length} ${groupWord}`;
129-
},
130117
},
131118
{
132119
field: 'isAdmin',

0 commit comments

Comments
 (0)