diff --git a/src/clients/ClientDetails.tsx b/src/clients/ClientDetails.tsx index 4a3866abd2..bac2c6510d 100644 --- a/src/clients/ClientDetails.tsx +++ b/src/clients/ClientDetails.tsx @@ -312,7 +312,6 @@ export const ClientDetails = () => { > setActiveTab2(key as number)} > void; }; -type Row = { - selected: boolean; - scope: ClientScopeRepresentation; - cells: (string | undefined)[]; -}; +import "./client-scopes.css"; export const AddScopeDialog = ({ clientScopes, @@ -46,26 +37,14 @@ export const AddScopeDialog = ({ }: AddScopeDialogProps) => { const { t } = useTranslation("clients"); const [addToggle, setAddToggle] = useState(false); - const [rows, setRows] = useState([]); + const [rows, setRows] = useState([]); - useEffect(() => { - setRows( - clientScopes.map((scope) => { - return { - selected: false, - scope, - cells: [scope.name, scope.description], - }; - }) - ); - }, [clientScopes]); + const loader = () => Promise.resolve(clientScopes); const action = (scope: ClientScopeType) => { - const scopes = rows - .filter((row) => row.selected) - .map((row) => { - return { scope: row.scope, type: scope }; - }); + const scopes = rows.map((row) => { + return { scope: row, type: scope }; + }); onAdd(scopes); setAddToggle(false); toggleDialog(); @@ -79,12 +58,14 @@ export const AddScopeDialog = ({ onClose={toggleDialog} actions={[ setAddToggle(!addToggle)} isPrimary toggleIndicator={CaretUpIcon} @@ -100,12 +81,7 @@ export const AddScopeDialog = ({ key="cancel" variant={ButtonVariant.secondary} onClick={() => { - setRows( - rows.map((row) => { - row.selected = false; - return row; - }) - ); + setRows([]); toggleDialog(); }} > @@ -113,28 +89,21 @@ export const AddScopeDialog = ({ , ]} > - { - if (rowIndex === -1) { - setRows( - rows.map((row) => { - row.selected = isSelected; - return row; - }) - ); - } else { - rows[rowIndex].selected = isSelected; - setRows([...rows]); - } - }} - rows={rows} - aria-label={t("chooseAMapperType")} - > - - -
+ setRows(rows)} + columns={[ + { + name: "name", + }, + { + name: "description", + }, + ]} + /> ); }; diff --git a/src/clients/scopes/ClientScopes.tsx b/src/clients/scopes/ClientScopes.tsx index 8a3e500c83..15b777a7cd 100644 --- a/src/clients/scopes/ClientScopes.tsx +++ b/src/clients/scopes/ClientScopes.tsx @@ -27,6 +27,8 @@ import { import { useAlerts } from "../../components/alert/Alerts"; import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable"; +import "./client-scopes.css"; + export type ClientScopesProps = { clientId: string; protocol: string; @@ -197,9 +199,11 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => { loader={loader} ariaLabelKey="clients:clientScopeList" searchPlaceholderKey="clients:searchByName" + canSelectAll onSelect={(rows) => setSelectedRows([...rows])} searchTypeComponent={ { key="add-dropdown" isOpen={addToggle} selections={[]} + isDisabled={selectedRows.length === 0} placeholderText={t("changeTypeTo")} onToggle={() => setAddToggle(!addToggle)} onSelect={async (_, value) => { @@ -323,6 +328,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => { columns={[ { name: "name", + displayKey: "clients:assignedClientScope", }, { name: "type", @@ -331,6 +337,24 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => { }, { name: "description" }, ]} + actions={[ + { + title: t("common:remove"), + onRowClick: async (row) => { + try { + await removeScope(adminClient, clientId, row, row.type); + addAlert(t("clientScopeRemoveSuccess"), AlertVariant.success); + refresh(); + } catch (error) { + addAlert( + t("clientScopeRemoveError", { error }), + AlertVariant.danger + ); + } + return true; + }, + }, + ]} emptyState={ ({ const refresh = () => setKey(new Date().getTime()); const handleError = useErrorHandler(); + useEffect(() => { + if (canSelectAll) { + const checkboxes = document + .getElementsByClassName("pf-c-table__check") + .item(0); + if (checkboxes) { + const checkAllCheckbox = checkboxes.children!.item( + 0 + )! as HTMLInputElement; + checkAllCheckbox.indeterminate = + selected.length > 0 && + selected.length < (filteredData || rows)!.length; + } + } + }, [selected]); + useEffect(() => { return asyncStateFetch( async () => { @@ -242,25 +258,26 @@ export function KeycloakDataTable({ ); const _onSelect = (isSelected: boolean, rowIndex: number) => { + const data = filteredData || rows; if (rowIndex === -1) { setRows( - rows!.map((row) => { + data!.map((row) => { row.selected = isSelected; return row; }) ); } else { - rows![rowIndex].selected = isSelected; + data![rowIndex].selected = isSelected; setRows([...rows!]); } const difference = _.differenceBy( selected, - rows!.map((row) => row.data), + data!.map((row) => row.data), "id" ); const selectedRows = [ ...difference, - ...rows!.filter((row) => row.selected).map((row) => row.data), + ...data!.filter((row) => row.selected).map((row) => row.data), ]; setSelected(selectedRows); onSelect!(selectedRows);