Reduced state held and fixed reset (#4213)

This commit is contained in:
Erik Jan de Wit 2023-01-18 12:58:13 +01:00 committed by GitHub
parent 6277c0bc06
commit 45b2a8da62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 52 deletions

View file

@ -251,7 +251,7 @@ describe("Realm roles test", () => {
keyValue.fillKeyValue({ key: "one", value: "1" }).validateRows(2);
keyValue.save();
masthead.checkNotificationMessage("The role has been saved", true);
keyValue.validateRows(1);
keyValue.validateRows(2);
});
it("should add attribute multiple", () => {
@ -262,14 +262,14 @@ describe("Realm roles test", () => {
.fillKeyValue({ key: "two", value: "2" }, 1)
.fillKeyValue({ key: "three", value: "3" }, 2)
.save()
.validateRows(3);
.validateRows(4);
});
it("should delete attribute", () => {
listingPage.itemExist(editRoleName).goToItemDetails(editRoleName);
createRealmRolePage.goToAttributesTab();
keyValue.deleteRow(1).save().validateRows(2);
keyValue.deleteRow(1).save().validateRows(3);
});
});
});

View file

@ -5,12 +5,12 @@ import {
PageSection,
ValidatedOptions,
} from "@patternfly/react-core";
import type { SubmitHandler, UseFormMethods } from "react-hook-form";
import { SubmitHandler, useWatch, UseFormMethods } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link, To } from "react-router-dom-v5-compat";
import { FormAccess } from "../form-access/FormAccess";
import type { AttributeForm } from "../key-value-form/AttributeForm";
import { AttributeForm } from "../key-value-form/AttributeForm";
import { KeycloakTextArea } from "../keycloak-text-area/KeycloakTextArea";
import { KeycloakTextInput } from "../keycloak-text-input/KeycloakTextInput";
import { ViewHeader } from "../view-header/ViewHeader";
@ -24,7 +24,7 @@ export type RoleFormProps = {
};
export const RoleForm = ({
form: { handleSubmit, errors, register, getValues },
form: { register, control, handleSubmit, errors },
onSubmit,
cancelLink,
role,
@ -32,6 +32,12 @@ export const RoleForm = ({
}: RoleFormProps) => {
const { t } = useTranslation("roles");
const roleName = useWatch<string | undefined>({
control,
defaultValue: undefined,
name: "name",
});
return (
<>
{!editMode && <ViewHeader titleKey={t("createRole")} />}
@ -86,7 +92,7 @@ export const RoleForm = ({
? ValidatedOptions.error
: ValidatedOptions.default
}
isDisabled={getValues().name?.includes("default-roles")}
isDisabled={roleName?.includes("default-roles")}
/>
</FormGroup>
<ActionGroup>

View file

@ -8,9 +8,8 @@ import {
Tab,
TabTitleText,
} from "@patternfly/react-core";
import { omit } from "lodash-es";
import { useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { SubmitHandler, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { useLocation, useMatch, useNavigate } from "react-router-dom-v5-compat";
@ -30,6 +29,7 @@ import {
import {
arrayToKeyValue,
keyValueToArray,
KeyValueType,
} from "../components/key-value-form/key-value-convert";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import { PermissionsTab } from "../components/permission-tab/PermissionTab";
@ -54,11 +54,10 @@ export default function RealmRoleTabs() {
const form = useForm<AttributeForm>({
mode: "onChange",
});
const { setValue, reset } = form;
const { control, reset, setValue } = form;
const navigate = useNavigate();
const { adminClient } = useAdminClient();
const [role, setRole] = useState<AttributeForm>();
const { id, clientId } = useParams<ClientRoleParams>();
const { pathname } = useLocation();
@ -66,12 +65,11 @@ export default function RealmRoleTabs() {
const { realm: realmName } = useRealm();
const [key, setKey] = useState(0);
const [attributes, setAttributes] = useState<KeyValueType[] | undefined>();
const { profileInfo } = useServerInfo();
const refresh = () => {
setKey(key + 1);
};
const refresh = () => setKey(key + 1);
const { addAlert, addError } = useAlerts();
@ -84,6 +82,18 @@ export default function RealmRoleTabs() {
};
};
const roleName = useWatch<string | undefined>({
control,
defaultValue: undefined,
name: "name",
});
const composites = useWatch<boolean>({
control,
defaultValue: false,
name: "composite",
});
const [realm, setRealm] = useState<RealmRepresentation>();
useFetch(
@ -103,36 +113,20 @@ export default function RealmRoleTabs() {
const convertedRole = convert(role);
reset(convertedRole);
setAttributes(convertedRole.attributes);
setRealm(realm);
setRole(convertedRole);
},
[key]
);
const onSubmit: SubmitHandler<AttributeForm> = async (formValues) => {
try {
if (
formValues.attributes &&
formValues.attributes[formValues.attributes.length - 1]?.key === ""
) {
setValue(
"attributes",
formValues.attributes.slice(0, formValues.attributes.length - 1)
);
}
const { attributes, ...rest } = formValues;
let roleRepresentation: RoleRepresentation = rest;
const roleRepresentation: RoleRepresentation = rest;
roleRepresentation.name = roleRepresentation.name?.trim();
if (attributes) {
roleRepresentation.attributes = keyValueToArray(attributes);
}
roleRepresentation = {
...omit(role!, "attributes"),
...roleRepresentation,
};
if (!clientId) {
await adminClient.roles.updateById({ id }, roleRepresentation);
} else {
@ -142,7 +136,7 @@ export default function RealmRoleTabs() {
);
}
setRole(convert(roleRepresentation));
setAttributes(attributes);
addAlert(t("roleSaveSuccess"), AlertVariant.success);
} catch (error) {
addError("roles:roleSaveError", error);
@ -201,7 +195,7 @@ export default function RealmRoleTabs() {
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: "roles:roleDeleteConfirm",
messageKey: t("roles:roleDeleteConfirmDialog", {
selectedRoleName: role?.name || t("createRole"),
selectedRoleName: roleName || t("createRole"),
}),
continueButtonLabel: "common:delete",
continueButtonVariant: ButtonVariant.danger,
@ -212,7 +206,7 @@ export default function RealmRoleTabs() {
} else {
await adminClient.clients.delRole({
id: clientId,
roleName: role!.name!,
roleName: roleName!,
});
}
addAlert(t("roleDeletedSuccess"), AlertVariant.success);
@ -266,14 +260,14 @@ export default function RealmRoleTabs() {
] = useConfirmDialog({
titleKey: t("roles:removeAllAssociatedRoles") + "?",
messageKey: t("roles:removeAllAssociatedRolesConfirmDialog", {
name: role?.name || t("createRole"),
name: roleName || t("createRole"),
}),
continueButtonLabel: "common:delete",
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
try {
const additionalRoles = await adminClient.roles.getCompositeRoles({
id: role!.id!,
id,
});
await adminClient.roles.delCompositeRoles({ id }, additionalRoles);
addAlert(
@ -296,7 +290,7 @@ export default function RealmRoleTabs() {
const addComposites = async (composites: RoleRepresentation[]) => {
try {
await adminClient.roles.createComposite(
{ roleId: role?.id!, realm: realm!.realm },
{ roleId: id, realm: realm!.realm },
composites
);
refresh();
@ -307,9 +301,10 @@ export default function RealmRoleTabs() {
}
};
const isDefaultRole = (name: string) => realm?.defaultRole!.name === name;
const isDefaultRole = (name: string | undefined) =>
realm?.defaultRole!.name === name;
if (!realm || !role) {
if (!realm) {
return <KeycloakSpinner />;
}
@ -321,17 +316,17 @@ export default function RealmRoleTabs() {
<AddRoleMappingModal
id={id}
type="roles"
name={role.name}
name={roleName}
onAssign={(rows) => addComposites(rows.map((r) => r.role))}
onClose={() => setOpen(false)}
/>
)}
<ViewHeader
titleKey={role.name!}
titleKey={roleName!}
badges={[
{
id: "composite-role-badge",
text: role.composite ? t("composite") : "",
text: composites ? t("composite") : "",
readonly: true,
},
]}
@ -354,25 +349,25 @@ export default function RealmRoleTabs() {
? toClient({ realm: realmName, clientId, tab: "roles" })
: toRealmRoles({ realm: realmName })
}
editMode={true}
editMode
/>
</Tab>
{role.composite && (
{composites && (
<Tab
data-testid="associatedRolesTab"
title={<TabTitleText>{t("associatedRolesText")}</TabTitleText>}
{...associatedRolesTab}
>
<RoleMapping
name={role.name!}
id={role.id!}
name={roleName!}
id={id}
type="roles"
isManager
save={(rows) => addComposites(rows.map((r) => r.role))}
/>
</Tab>
)}
{!isDefaultRole(role.name!) && (
{!isDefaultRole(roleName) && (
<Tab
data-testid="attributesTab"
className="kc-attributes-tab"
@ -382,11 +377,13 @@ export default function RealmRoleTabs() {
<AttributesForm
form={form}
save={onSubmit}
reset={() => reset(role)}
reset={() =>
setValue("attributes", attributes, { shouldDirty: false })
}
/>
</Tab>
)}
{!isDefaultRole(role.name!) && (
{!isDefaultRole(roleName) && (
<Tab
title={<TabTitleText>{t("usersInRole")}</TabTitleText>}
{...usersInRoleTab}
@ -401,7 +398,7 @@ export default function RealmRoleTabs() {
title={<TabTitleText>{t("common:permissions")}</TabTitleText>}
{...permissionsTab}
>
<PermissionsTab id={role.id} type="roles" />
<PermissionsTab id={id} type="roles" />
</Tab>
)}
</RoutableTabs>