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
|
||||
activeKey={activeTab2}
|
||||
isSecondary
|
||||
onSelect={(_, key) => setActiveTab2(key as number)}
|
||||
>
|
||||
<Tab
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"client": "Client scope",
|
||||
"assigned": "Assigned type"
|
||||
},
|
||||
"assignedClientScope": "Assigned client scope",
|
||||
"assignedType": "Assigned type",
|
||||
"hideInheritedRoles": "Hide inherited roles",
|
||||
"inherentFrom": "Inherited from",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Button,
|
||||
|
@ -10,18 +10,13 @@ import {
|
|||
DropdownDirection,
|
||||
} from "@patternfly/react-core";
|
||||
import { CaretUpIcon } from "@patternfly/react-icons";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableHeader,
|
||||
TableVariant,
|
||||
} from "@patternfly/react-table";
|
||||
import ClientScopeRepresentation from "keycloak-admin/lib/defs/clientScopeRepresentation";
|
||||
|
||||
import {
|
||||
ClientScopeType,
|
||||
clientScopeTypesDropdown,
|
||||
} from "../../components/client-scope/ClientScopeTypes";
|
||||
import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable";
|
||||
|
||||
export type AddScopeDialogProps = {
|
||||
clientScopes: ClientScopeRepresentation[];
|
||||
|
@ -32,11 +27,7 @@ export type AddScopeDialogProps = {
|
|||
) => 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<Row[]>([]);
|
||||
const [rows, setRows] = useState<ClientScopeRepresentation[]>([]);
|
||||
|
||||
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={[
|
||||
<Dropdown
|
||||
className="keycloak__client-scopes-add__add-dropdown"
|
||||
id="add-dropdown"
|
||||
key="add-dropdown"
|
||||
direction={DropdownDirection.up}
|
||||
isOpen={addToggle}
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
isDisabled={rows.length === 0}
|
||||
onToggle={() => 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 = ({
|
|||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Table
|
||||
variant={TableVariant.compact}
|
||||
cells={[t("common:name"), t("common:description")]}
|
||||
onSelect={(_, isSelected, rowIndex) => {
|
||||
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")}
|
||||
>
|
||||
<TableHeader />
|
||||
<TableBody />
|
||||
</Table>
|
||||
<KeycloakDataTable
|
||||
loader={loader}
|
||||
ariaLabelKey="client-scopes:chooseAMapperType"
|
||||
searchPlaceholderKey="client-scopes:searchFor"
|
||||
canSelectAll
|
||||
onSelect={(rows) => setRows(rows)}
|
||||
columns={[
|
||||
{
|
||||
name: "name",
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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={
|
||||
<Dropdown
|
||||
className="keycloak__client-scopes__searchtype"
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
id="toggle-id"
|
||||
|
@ -245,6 +249,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
|
|||
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={
|
||||
<ListEmptyState
|
||||
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 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<T>({
|
|||
);
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue