From 3b65f1163d3f4ff17c84b81363877945598cf1ff Mon Sep 17 00:00:00 2001 From: Erik Jan de Wit Date: Wed, 19 Apr 2023 21:35:36 +0200 Subject: [PATCH] issue 19582 (#19749) * fixed paginate subgroups + nav * render matched sub groups and fix pagination when searching --- .../components/group/GroupPickerDialog.tsx | 289 ++++++++++-------- 1 file changed, 168 insertions(+), 121 deletions(-) diff --git a/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx b/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx index 86f8d4e757..ecb8535612 100644 --- a/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx +++ b/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx @@ -61,6 +61,8 @@ export const GroupPickerDialog = ({ const [max, setMax] = useState(10); const [first, setFirst] = useState(0); + const [count, setCount] = useState(0); + const currentGroup = () => navigation[navigation.length - 1]; useFetch( @@ -68,13 +70,14 @@ export const GroupPickerDialog = ({ let group; let groups; let existingUserGroups; + let count = 0; if (!groupId) { groups = await adminClient.groups.find({ first, - max: max + 1, + max: max + (isSearching ? 0 : 1), search: isSearching ? filter : "", }); - } else { + } else if (!navigation.map(({ id }) => id).includes(groupId)) { group = await adminClient.groups.findOne({ id: groupId }); if (!group) { throw new Error(t("common:notFound")); @@ -82,24 +85,32 @@ export const GroupPickerDialog = ({ groups = group.subGroups!; } + if (isSearching) { + count = (await adminClient.groups.count({ search: filter, top: true })) + .count; + } + if (id) { existingUserGroups = await adminClient.users.listGroups({ id, }); } - return { group, groups, existingUserGroups }; + return { group, groups, existingUserGroups, count }; }, - async ({ group: selectedGroup, groups, existingUserGroups }) => { + async ({ group: selectedGroup, groups, existingUserGroups, count }) => { setJoinedGroups(existingUserGroups || []); if (selectedGroup) { setNavigation([...navigation, selectedGroup]); } - groups.forEach((group: SelectableGroup) => { - group.checked = !!selectedRows.find((r) => r.id === group.id); - }); - setGroups(groups); + if (groups) { + groups.forEach((group: SelectableGroup) => { + group.checked = !!selectedRows.find((r) => r.id === group.id); + }); + setGroups(groups); + } + setCount(count); }, [groupId, filter, first, max] ); @@ -111,25 +122,6 @@ export const GroupPickerDialog = ({ ].some((group) => group === row?.id); }; - const hasSubgroups = (group: GroupRepresentation) => - group.subGroups?.length !== 0; - - const expandGroup = ( - group: GroupRepresentation, - name: string - ): GroupRepresentation => { - if (group.name?.includes(name)) { - return group; - } - if (group.subGroups) { - for (const g of group.subGroups) { - const found = expandGroup(g, name); - return found; - } - } - return group; - }; - return ( { setGroupId(undefined); setNavigation([]); + setFirst(0); + setMax(10); }} > {t("groups")} @@ -203,6 +200,8 @@ export const GroupPickerDialog = ({ onClick={() => { setGroupId(group.id); setNavigation([...navigation].slice(0, i)); + setFirst(0); + setMax(10); }} > {group.name} @@ -213,100 +212,40 @@ export const GroupPickerDialog = ({ ))} - {groups.slice(0, max).map((group: SelectableGroup) => ( - { - const g = isSearching ? expandGroup(group, filter) : group; - if (isRowDisabled(g)) return; - if (type === "selectOne") { - setGroupId(g.id); - } else if ( - hasSubgroups(group) && - (e.target as HTMLInputElement).type !== "checkbox" - ) { - setGroupId( - isSearching ? expandGroup(group, filter).id : group.id - ); - setIsSearching(false); - } - }} - > - - {type === "selectMany" && ( - { - group.checked = checked; - let newSelectedRows: SelectableGroup[] = []; - if (!group.checked) { - newSelectedRows = selectedRows.filter( - (r) => r.id !== group.id - ); - } else { - newSelectedRows = [ - ...selectedRows, - isSearching ? expandGroup(group, filter) : group, - ]; - } - - setSelectedRows(newSelectedRows); - }} - aria-labelledby={`select-${group.name}`} - /> - )} - - - {isSearching ? ( - - ) : ( - {group.name} - )} - , - ]} + {groups + .slice(groupId ? first : 0, max + (groupId ? first : 0)) + .map((group: SelectableGroup) => ( + <> + - - {((hasSubgroups(group) && canBrowse) || - type === "selectOne") && ( - - )} - - - - ))} + {isSearching && + group.subGroups?.length !== 0 && + group.subGroups!.map((g) => ( + + ))} + + ))} {groups.length === 0 && !isSearching && ( ); }; + +type GroupRowProps = { + group: SelectableGroup; + type: "selectOne" | "selectMany"; + isRowDisabled: (row?: GroupRepresentation) => boolean; + isSearching: boolean; + setIsSearching: (value: boolean) => void; + onSelect: (groupId: string) => void; + selectedRows: SelectableGroup[]; + setSelectedRows: (groups: SelectableGroup[]) => void; + canBrowse: boolean; +}; + +const GroupRow = ({ + group, + type, + isRowDisabled, + isSearching, + setIsSearching, + onSelect, + selectedRows, + setSelectedRows, + canBrowse, +}: GroupRowProps) => { + const { t } = useTranslation(); + + const hasSubgroups = (group: GroupRepresentation) => + group.subGroups?.length !== 0; + + return ( + { + if (isRowDisabled(group)) return; + if (type === "selectOne") { + onSelect(group.id!); + } else if ( + hasSubgroups(group) && + (e.target as HTMLInputElement).type !== "checkbox" + ) { + onSelect(group.id!); + setIsSearching(false); + } + }} + > + + {type === "selectMany" && ( + { + group.checked = checked; + let newSelectedRows: SelectableGroup[] = []; + if (!group.checked) { + newSelectedRows = selectedRows.filter((r) => r.id !== group.id); + } else { + newSelectedRows = [...selectedRows, group]; + } + + setSelectedRows(newSelectedRows); + }} + aria-labelledby={`select-${group.name}`} + /> + )} + + + {isSearching ? ( + + ) : ( + {group.name} + )} + , + ]} + /> + + {((hasSubgroups(group) && canBrowse) || type === "selectOne") && ( + + )} + + + + ); +};