fix issue by introducing toolbar for fedrated user (#1417)
* fix issue by introducing toolbar for fedrated user fixes: #1416 * code review
This commit is contained in:
parent
56eb774dd3
commit
d0c6bc4cc1
1 changed files with 102 additions and 62 deletions
|
@ -4,23 +4,29 @@ import {
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
DropdownItem,
|
DropdownItem,
|
||||||
|
EmptyState,
|
||||||
|
InputGroup,
|
||||||
KebabToggle,
|
KebabToggle,
|
||||||
Label,
|
Label,
|
||||||
PageSection,
|
PageSection,
|
||||||
Text,
|
Text,
|
||||||
TextContent,
|
TextContent,
|
||||||
|
TextInput,
|
||||||
|
Toolbar,
|
||||||
|
ToolbarContent,
|
||||||
ToolbarItem,
|
ToolbarItem,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import {
|
import {
|
||||||
ExclamationCircleIcon,
|
ExclamationCircleIcon,
|
||||||
InfoCircleIcon,
|
InfoCircleIcon,
|
||||||
|
SearchIcon,
|
||||||
WarningTriangleIcon,
|
WarningTriangleIcon,
|
||||||
} from "@patternfly/react-icons";
|
} from "@patternfly/react-icons";
|
||||||
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link, useHistory, useRouteMatch } from "react-router-dom";
|
import { Link, useHistory } from "react-router-dom";
|
||||||
import { useAlerts } from "../components/alert/Alerts";
|
import { useAlerts } from "../components/alert/Alerts";
|
||||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||||
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
||||||
|
@ -32,6 +38,7 @@ import { emptyFormatter } from "../util";
|
||||||
import { toUser } from "./routes/User";
|
import { toUser } from "./routes/User";
|
||||||
import "./user-section.css";
|
import "./user-section.css";
|
||||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||||
|
import { toAddUser } from "./routes/AddUser";
|
||||||
|
|
||||||
type BruteUser = UserRepresentation & {
|
type BruteUser = UserRepresentation & {
|
||||||
brute?: Record<string, object>;
|
brute?: Record<string, object>;
|
||||||
|
@ -43,8 +50,8 @@ export const UsersSection = () => {
|
||||||
const { addAlert, addError } = useAlerts();
|
const { addAlert, addError } = useAlerts();
|
||||||
const { realm: realmName } = useRealm();
|
const { realm: realmName } = useRealm();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { url } = useRouteMatch();
|
|
||||||
const [listUsers, setListUsers] = useState(false);
|
const [listUsers, setListUsers] = useState(false);
|
||||||
|
const [searchUser, setSearchUser] = useState<string>();
|
||||||
const [realm, setRealm] = useState<RealmRepresentation>();
|
const [realm, setRealm] = useState<RealmRepresentation>();
|
||||||
const [kebabOpen, setKebabOpen] = useState(false);
|
const [kebabOpen, setKebabOpen] = useState(false);
|
||||||
const [selectedRows, setSelectedRows] = useState<UserRepresentation[]>([]);
|
const [selectedRows, setSelectedRows] = useState<UserRepresentation[]>([]);
|
||||||
|
@ -87,7 +94,7 @@ export const UsersSection = () => {
|
||||||
max: max!,
|
max: max!,
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchParam = search || "";
|
const searchParam = search || searchUser || "";
|
||||||
if (searchParam) {
|
if (searchParam) {
|
||||||
params.search = searchParam;
|
params.search = searchParam;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +193,60 @@ export const UsersSection = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToCreate = () => history.push(`${url}/add-user`);
|
const goToCreate = () => history.push(toAddUser({ realm: realmName }));
|
||||||
|
|
||||||
|
const toolbar = (
|
||||||
|
<>
|
||||||
|
<ToolbarItem>
|
||||||
|
<Button data-testid="add-user" onClick={goToCreate}>
|
||||||
|
{t("addUser")}
|
||||||
|
</Button>
|
||||||
|
</ToolbarItem>
|
||||||
|
{!realm?.bruteForceProtected ? (
|
||||||
|
<ToolbarItem>
|
||||||
|
<Button
|
||||||
|
variant={ButtonVariant.plain}
|
||||||
|
onClick={toggleDeleteDialog}
|
||||||
|
isDisabled={selectedRows.length === 0}
|
||||||
|
>
|
||||||
|
{t("deleteUser")}
|
||||||
|
</Button>
|
||||||
|
</ToolbarItem>
|
||||||
|
) : (
|
||||||
|
<ToolbarItem>
|
||||||
|
<Dropdown
|
||||||
|
toggle={<KebabToggle onToggle={(open) => setKebabOpen(open)} />}
|
||||||
|
isOpen={kebabOpen}
|
||||||
|
isPlain
|
||||||
|
dropdownItems={[
|
||||||
|
<DropdownItem
|
||||||
|
key="deleteUser"
|
||||||
|
component="button"
|
||||||
|
isDisabled={selectedRows.length === 0}
|
||||||
|
onClick={() => {
|
||||||
|
toggleDeleteDialog();
|
||||||
|
setKebabOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("deleteUser")}
|
||||||
|
</DropdownItem>,
|
||||||
|
|
||||||
|
<DropdownItem
|
||||||
|
key="unlock"
|
||||||
|
component="button"
|
||||||
|
onClick={() => {
|
||||||
|
toggleUnlockUsersDialog();
|
||||||
|
setKebabOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("unlockAllUsers")}
|
||||||
|
</DropdownItem>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</ToolbarItem>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -208,9 +268,43 @@ export const UsersSection = () => {
|
||||||
onSelect={(rows) => setSelectedRows([...rows])}
|
onSelect={(rows) => setSelectedRows([...rows])}
|
||||||
emptyState={
|
emptyState={
|
||||||
!listUsers ? (
|
!listUsers ? (
|
||||||
<TextContent className="kc-search-users-text">
|
<>
|
||||||
<Text>{t("searchForUserDescription")}</Text>
|
<Toolbar>
|
||||||
</TextContent>
|
<ToolbarContent>
|
||||||
|
<ToolbarItem>
|
||||||
|
<InputGroup>
|
||||||
|
<TextInput
|
||||||
|
name="search-input"
|
||||||
|
type="search"
|
||||||
|
aria-label={t("search")}
|
||||||
|
placeholder={t("users:searchForUser")}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSearchUser(value);
|
||||||
|
}}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant={ButtonVariant.control}
|
||||||
|
aria-label={t("common:search")}
|
||||||
|
onClick={refresh}
|
||||||
|
>
|
||||||
|
<SearchIcon />
|
||||||
|
</Button>
|
||||||
|
</InputGroup>
|
||||||
|
</ToolbarItem>
|
||||||
|
{toolbar}
|
||||||
|
</ToolbarContent>
|
||||||
|
</Toolbar>
|
||||||
|
<EmptyState data-testid="empty-state" variant="large">
|
||||||
|
<TextContent className="kc-search-users-text">
|
||||||
|
<Text>{t("searchForUserDescription")}</Text>
|
||||||
|
</TextContent>
|
||||||
|
</EmptyState>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<ListEmptyState
|
<ListEmptyState
|
||||||
message={t("noUsersFound")}
|
message={t("noUsersFound")}
|
||||||
|
@ -220,61 +314,7 @@ export const UsersSection = () => {
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
toolbarItem={
|
toolbarItem={toolbar}
|
||||||
<>
|
|
||||||
<ToolbarItem>
|
|
||||||
<Button data-testid="add-user" onClick={goToCreate}>
|
|
||||||
{t("addUser")}
|
|
||||||
</Button>
|
|
||||||
</ToolbarItem>
|
|
||||||
{!realm?.bruteForceProtected && (
|
|
||||||
<ToolbarItem>
|
|
||||||
<Button
|
|
||||||
variant={ButtonVariant.plain}
|
|
||||||
onClick={toggleDeleteDialog}
|
|
||||||
isDisabled={selectedRows.length === 0}
|
|
||||||
>
|
|
||||||
{t("deleteUser")}
|
|
||||||
</Button>
|
|
||||||
</ToolbarItem>
|
|
||||||
)}
|
|
||||||
{realm?.bruteForceProtected && (
|
|
||||||
<ToolbarItem>
|
|
||||||
<Dropdown
|
|
||||||
toggle={
|
|
||||||
<KebabToggle onToggle={() => setKebabOpen(!kebabOpen)} />
|
|
||||||
}
|
|
||||||
isOpen={kebabOpen}
|
|
||||||
isPlain
|
|
||||||
dropdownItems={[
|
|
||||||
<DropdownItem
|
|
||||||
key="deleteUser"
|
|
||||||
component="button"
|
|
||||||
isDisabled={selectedRows.length === 0}
|
|
||||||
onClick={() => {
|
|
||||||
toggleDeleteDialog();
|
|
||||||
setKebabOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("deleteUser")}
|
|
||||||
</DropdownItem>,
|
|
||||||
|
|
||||||
<DropdownItem
|
|
||||||
key="unlock"
|
|
||||||
component="button"
|
|
||||||
onClick={() => {
|
|
||||||
toggleUnlockUsersDialog();
|
|
||||||
setKebabOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("unlockAllUsers")}
|
|
||||||
</DropdownItem>,
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</ToolbarItem>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
title: t("common:delete"),
|
title: t("common:delete"),
|
||||||
|
|
Loading…
Reference in a new issue