use the path of the last group to display (#34303)

fixes: #34229

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
Erik Jan de Wit 2024-10-25 15:29:19 +02:00 committed by GitHub
parent 2e56896b05
commit b01552fe0d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,7 +3,11 @@ import {
GroupQuery, GroupQuery,
SubGroupQuery, SubGroupQuery,
} from "@keycloak/keycloak-admin-client/lib/resources/groups"; } from "@keycloak/keycloak-admin-client/lib/resources/groups";
import { PaginatingTableToolbar, useFetch } from "@keycloak/keycloak-ui-shared"; import {
ListEmptyState,
PaginatingTableToolbar,
useFetch,
} from "@keycloak/keycloak-ui-shared";
import { import {
Breadcrumb, Breadcrumb,
BreadcrumbItem, BreadcrumbItem,
@ -19,10 +23,9 @@ import {
ModalVariant, ModalVariant,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { AngleRightIcon } from "@patternfly/react-icons"; import { AngleRightIcon } from "@patternfly/react-icons";
import { Fragment, useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { ListEmptyState } from "@keycloak/keycloak-ui-shared";
import { GroupPath } from "./GroupPath"; import { GroupPath } from "./GroupPath";
import "./group-picker-dialog.css"; import "./group-picker-dialog.css";
@ -62,7 +65,6 @@ export const GroupPickerDialog = ({
const [filter, setFilter] = useState(""); const [filter, setFilter] = useState("");
const [joinedGroups, setJoinedGroups] = useState<GroupRepresentation[]>([]); const [joinedGroups, setJoinedGroups] = useState<GroupRepresentation[]>([]);
const [groupId, setGroupId] = useState<string>(); const [groupId, setGroupId] = useState<string>();
const [isSearching, setIsSearching] = useState(false);
const [max, setMax] = useState(10); const [max, setMax] = useState(10);
const [first, setFirst] = useState(0); const [first, setFirst] = useState(0);
@ -82,7 +84,7 @@ export const GroupPickerDialog = ({
first, first,
max: max + 1, max: max + 1,
}; };
if (isSearching) { if (filter !== "") {
args.search = filter; args.search = filter;
} }
groups = await adminClient.groups.find(args); groups = await adminClient.groups.find(args);
@ -121,7 +123,7 @@ export const GroupPickerDialog = ({
group.checked = !!selectedRows.find((r) => r.id === group.id); group.checked = !!selectedRows.find((r) => r.id === group.id);
}); });
setGroups(groups); setGroups(groups);
if (isSearching || !groupId) { if (filter !== "" || !groupId) {
setCount(groups.length); setCount(groups.length);
} }
}, },
@ -137,7 +139,7 @@ export const GroupPickerDialog = ({
return ( return (
<Modal <Modal
variant={isSearching ? ModalVariant.medium : ModalVariant.small} variant={filter !== "" ? ModalVariant.medium : ModalVariant.small}
title={t(text.title, { title={t(text.title, {
group1: filterGroups?.[0]?.name, group1: filterGroups?.[0]?.name,
group2: navigation.length ? currentGroup().name : t("root"), group2: navigation.length ? currentGroup().name : t("root"),
@ -178,7 +180,6 @@ export const GroupPickerDialog = ({
inputGroupName={"search"} inputGroupName={"search"}
inputGroupOnEnter={(search) => { inputGroupOnEnter={(search) => {
setFilter(search); setFilter(search);
setIsSearching(search !== "");
setFirst(0); setFirst(0);
setMax(10); setMax(10);
setNavigation([]); setNavigation([]);
@ -222,57 +223,47 @@ export const GroupPickerDialog = ({
))} ))}
</Breadcrumb> </Breadcrumb>
<DataList aria-label={t("groups")} isCompact> <DataList aria-label={t("groups")} isCompact>
{groups.slice(0, max).map((group: SelectableGroup) => ( {filter == ""
<Fragment key={group.id}> ? groups.slice(0, max).map((group: SelectableGroup) => (
{(!isSearching ||
group.name
?.toLocaleUpperCase()
.includes(filter.toLocaleUpperCase())) && (
<GroupRow <GroupRow
key={group.id} key={group.id}
group={group} group={group}
isRowDisabled={isRowDisabled} isRowDisabled={isRowDisabled}
onSelect={(groupId) => { onSelect={(group) => {
setGroupId(groupId); setGroupId(group.id);
setFirst(0); setFirst(0);
}} }}
type={type} type={type}
isSearching={isSearching} isSearching={filter !== ""}
setIsSearching={setIsSearching} setIsSearching={(boolean) => setFilter(boolean ? "" : filter)}
selectedRows={selectedRows} selectedRows={selectedRows}
setSelectedRows={setSelectedRows} setSelectedRows={setSelectedRows}
canBrowse={canBrowse} canBrowse={canBrowse}
/> />
)} ))
{isSearching && : groups
group.subGroups?.map((g) => ( ?.map((g) => deepGroup(g))
.map((g) => (
<GroupRow <GroupRow
key={g.id} key={g.id}
group={g} group={g}
isRowDisabled={isRowDisabled} isRowDisabled={isRowDisabled}
onSelect={(groupId) => {
setGroupId(groupId);
setFirst(0);
}}
type={type} type={type}
isSearching={isSearching} isSearching
setIsSearching={setIsSearching}
selectedRows={selectedRows} selectedRows={selectedRows}
setSelectedRows={setSelectedRows} setSelectedRows={setSelectedRows}
canBrowse={canBrowse} canBrowse={false}
/> />
))} ))}
</Fragment>
))}
</DataList> </DataList>
{groups.length === 0 && !isSearching && ( {groups.length === 0 && filter === "" && (
<ListEmptyState <ListEmptyState
hasIcon={false} hasIcon={false}
message={t("moveGroupEmpty")} message={t("moveGroupEmpty")}
instructions={isMove ? t("moveGroupEmptyInstructions") : undefined} instructions={isMove ? t("moveGroupEmptyInstructions") : undefined}
/> />
)} )}
{groups.length === 0 && isSearching && ( {groups.length === 0 && filter !== "" && (
<ListEmptyState <ListEmptyState
message={t("noSearchResults")} message={t("noSearchResults")}
instructions={t("noSearchResultsInstructions")} instructions={t("noSearchResultsInstructions")}
@ -283,13 +274,22 @@ export const GroupPickerDialog = ({
); );
}; };
const deepGroup = (group: GroupRepresentation): GroupRepresentation => {
let result = group;
if (group.subGroups?.length === 1) {
result = deepGroup(group.subGroups[0]);
}
return result;
};
type GroupRowProps = { type GroupRowProps = {
group: SelectableGroup; group: SelectableGroup;
type: "selectOne" | "selectMany"; type: "selectOne" | "selectMany";
isRowDisabled: (row?: GroupRepresentation) => boolean; isRowDisabled: (row?: GroupRepresentation) => boolean;
isSearching: boolean; isSearching: boolean;
setIsSearching: (value: boolean) => void; setIsSearching?: (value: boolean) => void;
onSelect: (groupId: string) => void; onSelect?: (group: GroupRepresentation) => void;
selectedRows: SelectableGroup[]; selectedRows: SelectableGroup[];
setSelectedRows: (groups: SelectableGroup[]) => void; setSelectedRows: (groups: SelectableGroup[]) => void;
canBrowse: boolean; canBrowse: boolean;
@ -315,13 +315,13 @@ const GroupRow = ({
id={group.id} id={group.id}
onClick={(e) => { onClick={(e) => {
if (type === "selectOne") { if (type === "selectOne") {
onSelect(group.id!); onSelect?.(group);
} else if ( } else if (
(e.target as HTMLInputElement).type !== "checkbox" && (e.target as HTMLInputElement).type !== "checkbox" &&
group.subGroupCount !== 0 group.subGroupCount !== 0
) { ) {
onSelect(group.id!); onSelect?.(group);
setIsSearching(false); setIsSearching?.(false);
} }
}} }}
> >