fixing uxd issues (#477)
* fixing uxd issues * add select all checkbox * added intermidate "style" to select all checkbox
This commit is contained in:
parent
dd19613557
commit
2417c285e3
6 changed files with 80 additions and 62 deletions
|
@ -312,7 +312,6 @@ export const ClientDetails = () => {
|
||||||
>
|
>
|
||||||
<Tabs
|
<Tabs
|
||||||
activeKey={activeTab2}
|
activeKey={activeTab2}
|
||||||
isSecondary
|
|
||||||
onSelect={(_, key) => setActiveTab2(key as number)}
|
onSelect={(_, key) => setActiveTab2(key as number)}
|
||||||
>
|
>
|
||||||
<Tab
|
<Tab
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
"client": "Client scope",
|
"client": "Client scope",
|
||||||
"assigned": "Assigned type"
|
"assigned": "Assigned type"
|
||||||
},
|
},
|
||||||
|
"assignedClientScope": "Assigned client scope",
|
||||||
"assignedType": "Assigned type",
|
"assignedType": "Assigned type",
|
||||||
"hideInheritedRoles": "Hide inherited roles",
|
"hideInheritedRoles": "Hide inherited roles",
|
||||||
"inherentFrom": "Inherited from",
|
"inherentFrom": "Inherited from",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
@ -10,18 +10,13 @@ import {
|
||||||
DropdownDirection,
|
DropdownDirection,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import { CaretUpIcon } from "@patternfly/react-icons";
|
import { CaretUpIcon } from "@patternfly/react-icons";
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableHeader,
|
|
||||||
TableVariant,
|
|
||||||
} from "@patternfly/react-table";
|
|
||||||
import ClientScopeRepresentation from "keycloak-admin/lib/defs/clientScopeRepresentation";
|
import ClientScopeRepresentation from "keycloak-admin/lib/defs/clientScopeRepresentation";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ClientScopeType,
|
ClientScopeType,
|
||||||
clientScopeTypesDropdown,
|
clientScopeTypesDropdown,
|
||||||
} from "../../components/client-scope/ClientScopeTypes";
|
} from "../../components/client-scope/ClientScopeTypes";
|
||||||
|
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||||
|
|
||||||
export type AddScopeDialogProps = {
|
export type AddScopeDialogProps = {
|
||||||
clientScopes: ClientScopeRepresentation[];
|
clientScopes: ClientScopeRepresentation[];
|
||||||
|
@ -32,11 +27,7 @@ export type AddScopeDialogProps = {
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Row = {
|
import "./client-scopes.css";
|
||||||
selected: boolean;
|
|
||||||
scope: ClientScopeRepresentation;
|
|
||||||
cells: (string | undefined)[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AddScopeDialog = ({
|
export const AddScopeDialog = ({
|
||||||
clientScopes,
|
clientScopes,
|
||||||
|
@ -46,26 +37,14 @@ export const AddScopeDialog = ({
|
||||||
}: AddScopeDialogProps) => {
|
}: AddScopeDialogProps) => {
|
||||||
const { t } = useTranslation("clients");
|
const { t } = useTranslation("clients");
|
||||||
const [addToggle, setAddToggle] = useState(false);
|
const [addToggle, setAddToggle] = useState(false);
|
||||||
const [rows, setRows] = useState<Row[]>([]);
|
const [rows, setRows] = useState<ClientScopeRepresentation[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
const loader = () => Promise.resolve(clientScopes);
|
||||||
setRows(
|
|
||||||
clientScopes.map((scope) => {
|
|
||||||
return {
|
|
||||||
selected: false,
|
|
||||||
scope,
|
|
||||||
cells: [scope.name, scope.description],
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}, [clientScopes]);
|
|
||||||
|
|
||||||
const action = (scope: ClientScopeType) => {
|
const action = (scope: ClientScopeType) => {
|
||||||
const scopes = rows
|
const scopes = rows.map((row) => {
|
||||||
.filter((row) => row.selected)
|
return { scope: row, type: scope };
|
||||||
.map((row) => {
|
});
|
||||||
return { scope: row.scope, type: scope };
|
|
||||||
});
|
|
||||||
onAdd(scopes);
|
onAdd(scopes);
|
||||||
setAddToggle(false);
|
setAddToggle(false);
|
||||||
toggleDialog();
|
toggleDialog();
|
||||||
|
@ -79,12 +58,14 @@ export const AddScopeDialog = ({
|
||||||
onClose={toggleDialog}
|
onClose={toggleDialog}
|
||||||
actions={[
|
actions={[
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
className="keycloak__client-scopes-add__add-dropdown"
|
||||||
id="add-dropdown"
|
id="add-dropdown"
|
||||||
key="add-dropdown"
|
key="add-dropdown"
|
||||||
direction={DropdownDirection.up}
|
direction={DropdownDirection.up}
|
||||||
isOpen={addToggle}
|
isOpen={addToggle}
|
||||||
toggle={
|
toggle={
|
||||||
<DropdownToggle
|
<DropdownToggle
|
||||||
|
isDisabled={rows.length === 0}
|
||||||
onToggle={() => setAddToggle(!addToggle)}
|
onToggle={() => setAddToggle(!addToggle)}
|
||||||
isPrimary
|
isPrimary
|
||||||
toggleIndicator={CaretUpIcon}
|
toggleIndicator={CaretUpIcon}
|
||||||
|
@ -100,12 +81,7 @@ export const AddScopeDialog = ({
|
||||||
key="cancel"
|
key="cancel"
|
||||||
variant={ButtonVariant.secondary}
|
variant={ButtonVariant.secondary}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setRows(
|
setRows([]);
|
||||||
rows.map((row) => {
|
|
||||||
row.selected = false;
|
|
||||||
return row;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
toggleDialog();
|
toggleDialog();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -113,28 +89,21 @@ export const AddScopeDialog = ({
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Table
|
<KeycloakDataTable
|
||||||
variant={TableVariant.compact}
|
loader={loader}
|
||||||
cells={[t("common:name"), t("common:description")]}
|
ariaLabelKey="client-scopes:chooseAMapperType"
|
||||||
onSelect={(_, isSelected, rowIndex) => {
|
searchPlaceholderKey="client-scopes:searchFor"
|
||||||
if (rowIndex === -1) {
|
canSelectAll
|
||||||
setRows(
|
onSelect={(rows) => setRows(rows)}
|
||||||
rows.map((row) => {
|
columns={[
|
||||||
row.selected = isSelected;
|
{
|
||||||
return row;
|
name: "name",
|
||||||
})
|
},
|
||||||
);
|
{
|
||||||
} else {
|
name: "description",
|
||||||
rows[rowIndex].selected = isSelected;
|
},
|
||||||
setRows([...rows]);
|
]}
|
||||||
}
|
/>
|
||||||
}}
|
|
||||||
rows={rows}
|
|
||||||
aria-label={t("chooseAMapperType")}
|
|
||||||
>
|
|
||||||
<TableHeader />
|
|
||||||
<TableBody />
|
|
||||||
</Table>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,8 @@ import {
|
||||||
import { useAlerts } from "../../components/alert/Alerts";
|
import { useAlerts } from "../../components/alert/Alerts";
|
||||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||||
|
|
||||||
|
import "./client-scopes.css";
|
||||||
|
|
||||||
export type ClientScopesProps = {
|
export type ClientScopesProps = {
|
||||||
clientId: string;
|
clientId: string;
|
||||||
protocol: string;
|
protocol: string;
|
||||||
|
@ -197,9 +199,11 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
|
||||||
loader={loader}
|
loader={loader}
|
||||||
ariaLabelKey="clients:clientScopeList"
|
ariaLabelKey="clients:clientScopeList"
|
||||||
searchPlaceholderKey="clients:searchByName"
|
searchPlaceholderKey="clients:searchByName"
|
||||||
|
canSelectAll
|
||||||
onSelect={(rows) => setSelectedRows([...rows])}
|
onSelect={(rows) => setSelectedRows([...rows])}
|
||||||
searchTypeComponent={
|
searchTypeComponent={
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
className="keycloak__client-scopes__searchtype"
|
||||||
toggle={
|
toggle={
|
||||||
<DropdownToggle
|
<DropdownToggle
|
||||||
id="toggle-id"
|
id="toggle-id"
|
||||||
|
@ -245,6 +249,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
|
||||||
key="add-dropdown"
|
key="add-dropdown"
|
||||||
isOpen={addToggle}
|
isOpen={addToggle}
|
||||||
selections={[]}
|
selections={[]}
|
||||||
|
isDisabled={selectedRows.length === 0}
|
||||||
placeholderText={t("changeTypeTo")}
|
placeholderText={t("changeTypeTo")}
|
||||||
onToggle={() => setAddToggle(!addToggle)}
|
onToggle={() => setAddToggle(!addToggle)}
|
||||||
onSelect={async (_, value) => {
|
onSelect={async (_, value) => {
|
||||||
|
@ -323,6 +328,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
name: "name",
|
name: "name",
|
||||||
|
displayKey: "clients:assignedClientScope",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "type",
|
name: "type",
|
||||||
|
@ -331,6 +337,24 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
|
||||||
},
|
},
|
||||||
{ name: "description" },
|
{ 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={
|
emptyState={
|
||||||
<ListEmptyState
|
<ListEmptyState
|
||||||
message={t("clients:emptyClientScopes")}
|
message={t("clients:emptyClientScopes")}
|
||||||
|
|
8
src/clients/scopes/client-scopes.css
Normal file
8
src/clients/scopes/client-scopes.css
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
.keycloak__client-scopes__searchtype button {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keycloak__client-scopes-add__add-dropdown {
|
||||||
|
margin-right: var(--pf-global--spacer--md);
|
||||||
|
}
|
|
@ -153,6 +153,22 @@ export function KeycloakDataTable<T>({
|
||||||
const refresh = () => setKey(new Date().getTime());
|
const refresh = () => setKey(new Date().getTime());
|
||||||
const handleError = useErrorHandler();
|
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(() => {
|
useEffect(() => {
|
||||||
return asyncStateFetch(
|
return asyncStateFetch(
|
||||||
async () => {
|
async () => {
|
||||||
|
@ -242,25 +258,26 @@ export function KeycloakDataTable<T>({
|
||||||
);
|
);
|
||||||
|
|
||||||
const _onSelect = (isSelected: boolean, rowIndex: number) => {
|
const _onSelect = (isSelected: boolean, rowIndex: number) => {
|
||||||
|
const data = filteredData || rows;
|
||||||
if (rowIndex === -1) {
|
if (rowIndex === -1) {
|
||||||
setRows(
|
setRows(
|
||||||
rows!.map((row) => {
|
data!.map((row) => {
|
||||||
row.selected = isSelected;
|
row.selected = isSelected;
|
||||||
return row;
|
return row;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
rows![rowIndex].selected = isSelected;
|
data![rowIndex].selected = isSelected;
|
||||||
setRows([...rows!]);
|
setRows([...rows!]);
|
||||||
}
|
}
|
||||||
const difference = _.differenceBy(
|
const difference = _.differenceBy(
|
||||||
selected,
|
selected,
|
||||||
rows!.map((row) => row.data),
|
data!.map((row) => row.data),
|
||||||
"id"
|
"id"
|
||||||
);
|
);
|
||||||
const selectedRows = [
|
const selectedRows = [
|
||||||
...difference,
|
...difference,
|
||||||
...rows!.filter((row) => row.selected).map((row) => row.data),
|
...data!.filter((row) => row.selected).map((row) => row.data),
|
||||||
];
|
];
|
||||||
setSelected(selectedRows);
|
setSelected(selectedRows);
|
||||||
onSelect!(selectedRows);
|
onSelect!(selectedRows);
|
||||||
|
|
Loading…
Reference in a new issue