Port role form to new form controls (#27626)
Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
ea4155bbcd
commit
0adc842ac7
6 changed files with 129 additions and 155 deletions
|
@ -94,7 +94,7 @@ export default class ProviderPage {
|
||||||
#rolesTab = "rolesTab";
|
#rolesTab = "rolesTab";
|
||||||
#createRoleBtn = "no-roles-for-this-client-empty-action";
|
#createRoleBtn = "no-roles-for-this-client-empty-action";
|
||||||
#roleSaveBtn = "save";
|
#roleSaveBtn = "save";
|
||||||
#roleNameField = "#kc-name";
|
#roleNameField = "name";
|
||||||
|
|
||||||
#groupName = "aa-uf-mappers-group";
|
#groupName = "aa-uf-mappers-group";
|
||||||
#clientName = "aa-uf-mappers-client";
|
#clientName = "aa-uf-mappers-client";
|
||||||
|
@ -310,7 +310,7 @@ export default class ProviderPage {
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.findByTestId(this.#createRoleBtn).click();
|
cy.findByTestId(this.#createRoleBtn).click();
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.get(this.#roleNameField).clear().type(roleName);
|
cy.findByTestId(this.#roleNameField).clear().type(roleName);
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.findByTestId(this.#roleSaveBtn).click();
|
cy.findByTestId(this.#roleSaveBtn).click();
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
class CreateRealmRolePage {
|
class CreateRealmRolePage {
|
||||||
#realmRoleNameInput = "#kc-name";
|
#realmRoleNameInput = "name";
|
||||||
#realmRoleNameError = "#kc-name-helper";
|
#realmRoleNameError = "#name-helper";
|
||||||
#realmRoleDescriptionInput = "#kc-description";
|
#realmRoleDescriptionInput = "description";
|
||||||
#saveBtn = "save";
|
#saveBtn = "save";
|
||||||
#cancelBtn = "cancel";
|
#cancelBtn = "cancel";
|
||||||
|
|
||||||
//#region General Settings
|
//#region General Settings
|
||||||
fillRealmRoleData(name: string, description = "") {
|
fillRealmRoleData(name: string, description = "") {
|
||||||
cy.get(this.#realmRoleNameInput).clear();
|
cy.findByTestId(this.#realmRoleNameInput).clear();
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
cy.get(this.#realmRoleNameInput).type(name);
|
cy.findByTestId(this.#realmRoleNameInput).type(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (description !== "") {
|
if (description !== "") {
|
||||||
|
@ -36,7 +36,7 @@ class CreateRealmRolePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNameDisabled() {
|
checkNameDisabled() {
|
||||||
cy.get(this.#realmRoleNameInput).should(
|
cy.findByTestId(this.#realmRoleNameInput).should(
|
||||||
"have.attr",
|
"have.attr",
|
||||||
"readonly",
|
"readonly",
|
||||||
"readonly",
|
"readonly",
|
||||||
|
@ -45,13 +45,16 @@ class CreateRealmRolePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDescription(description: string) {
|
checkDescription(description: string) {
|
||||||
cy.get(this.#realmRoleDescriptionInput).should("have.value", description);
|
cy.findByTestId(this.#realmRoleDescriptionInput).should(
|
||||||
|
"have.value",
|
||||||
|
description,
|
||||||
|
);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDescription(description: string) {
|
updateDescription(description: string) {
|
||||||
cy.get(this.#realmRoleDescriptionInput).clear();
|
cy.findByTestId(this.#realmRoleDescriptionInput).clear();
|
||||||
cy.get(this.#realmRoleDescriptionInput).type(description);
|
cy.findByTestId(this.#realmRoleDescriptionInput).type(description);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||||
import { AlertVariant } from "@patternfly/react-core";
|
import { AlertVariant } from "@patternfly/react-core";
|
||||||
import { SubmitHandler, useForm } from "react-hook-form";
|
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
@ -54,16 +54,17 @@ export default function CreateClientRole() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoleForm
|
<FormProvider {...form}>
|
||||||
form={form}
|
<RoleForm
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
cancelLink={toClient({
|
cancelLink={toClient({
|
||||||
realm,
|
realm,
|
||||||
clientId: clientId!,
|
clientId: clientId!,
|
||||||
tab: "roles",
|
tab: "roles",
|
||||||
})}
|
})}
|
||||||
role="manage-clients"
|
role="manage-clients"
|
||||||
editMode={false}
|
editMode={false}
|
||||||
/>
|
/>
|
||||||
|
</FormProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
import {
|
import { ActionGroup, Button, PageSection } from "@patternfly/react-core";
|
||||||
ActionGroup,
|
import { SubmitHandler, useFormContext, useWatch } from "react-hook-form";
|
||||||
Button,
|
|
||||||
FormGroup,
|
|
||||||
PageSection,
|
|
||||||
ValidatedOptions,
|
|
||||||
} from "@patternfly/react-core";
|
|
||||||
import { SubmitHandler, UseFormReturn, useWatch } from "react-hook-form";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link, To } from "react-router-dom";
|
import { Link, To } from "react-router-dom";
|
||||||
|
import { TextAreaControl, TextControl } from "ui-shared";
|
||||||
|
|
||||||
import { FormAccess } from "../form/FormAccess";
|
import { FormAccess } from "../form/FormAccess";
|
||||||
import { 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";
|
import { ViewHeader } from "../view-header/ViewHeader";
|
||||||
|
|
||||||
export type RoleFormProps = {
|
export type RoleFormProps = {
|
||||||
form: UseFormReturn<AttributeForm>;
|
|
||||||
onSubmit: SubmitHandler<AttributeForm>;
|
onSubmit: SubmitHandler<AttributeForm>;
|
||||||
cancelLink: To;
|
cancelLink: To;
|
||||||
role: "manage-realm" | "manage-clients";
|
role: "manage-realm" | "manage-clients";
|
||||||
|
@ -24,18 +16,13 @@ export type RoleFormProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RoleForm = ({
|
export const RoleForm = ({
|
||||||
form: {
|
|
||||||
register,
|
|
||||||
control,
|
|
||||||
handleSubmit,
|
|
||||||
formState: { errors },
|
|
||||||
},
|
|
||||||
onSubmit,
|
onSubmit,
|
||||||
cancelLink,
|
cancelLink,
|
||||||
role,
|
role,
|
||||||
editMode,
|
editMode,
|
||||||
}: RoleFormProps) => {
|
}: RoleFormProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { control, handleSubmit } = useFormContext<AttributeForm>();
|
||||||
|
|
||||||
const roleName = useWatch({
|
const roleName = useWatch({
|
||||||
control,
|
control,
|
||||||
|
@ -53,54 +40,30 @@ export const RoleForm = ({
|
||||||
role={role}
|
role={role}
|
||||||
className="pf-u-mt-lg"
|
className="pf-u-mt-lg"
|
||||||
>
|
>
|
||||||
<FormGroup
|
<TextControl
|
||||||
|
name="name"
|
||||||
label={t("roleName")}
|
label={t("roleName")}
|
||||||
fieldId="kc-name"
|
rules={{
|
||||||
validated={
|
required: !editMode ? t("required") : undefined,
|
||||||
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
validate(value) {
|
||||||
}
|
if (!value?.trim()) {
|
||||||
helperTextInvalid={t("required")}
|
return t("required");
|
||||||
isRequired={!editMode}
|
}
|
||||||
>
|
},
|
||||||
<KeycloakTextInput
|
}}
|
||||||
id="kc-name"
|
readOnly={editMode}
|
||||||
isReadOnly={editMode}
|
/>
|
||||||
{...register("name", {
|
<TextAreaControl
|
||||||
required: !editMode,
|
name="description"
|
||||||
validate: (value) => {
|
|
||||||
if (!value?.trim()) {
|
|
||||||
return t("required").toString();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("description")}
|
label={t("description")}
|
||||||
fieldId="kc-description"
|
rules={{
|
||||||
validated={
|
maxLength: {
|
||||||
errors.description
|
value: 255,
|
||||||
? ValidatedOptions.error
|
message: t("maxLength", { length: 255 }),
|
||||||
: ValidatedOptions.default
|
},
|
||||||
}
|
}}
|
||||||
helperTextInvalid={errors.description?.message}
|
isDisabled={roleName?.includes("default-roles") ?? false}
|
||||||
>
|
/>
|
||||||
<KeycloakTextArea
|
|
||||||
id="kc-description"
|
|
||||||
validated={
|
|
||||||
errors.description
|
|
||||||
? ValidatedOptions.error
|
|
||||||
: ValidatedOptions.default
|
|
||||||
}
|
|
||||||
isDisabled={roleName?.includes("default-roles")}
|
|
||||||
{...register("description", {
|
|
||||||
maxLength: {
|
|
||||||
value: 255,
|
|
||||||
message: t("maxLength", { length: 255 }),
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<ActionGroup>
|
<ActionGroup>
|
||||||
<Button data-testid="save" type="submit" variant="primary">
|
<Button data-testid="save" type="submit" variant="primary">
|
||||||
{t("save")}
|
{t("save")}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||||
import { AlertVariant } from "@patternfly/react-core";
|
import { AlertVariant } from "@patternfly/react-core";
|
||||||
import { SubmitHandler, useForm } from "react-hook-form";
|
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
@ -45,12 +45,13 @@ export default function CreateRealmRole() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoleForm
|
<FormProvider {...form}>
|
||||||
form={form}
|
<RoleForm
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
cancelLink={toRealmRoles({ realm })}
|
cancelLink={toRealmRoles({ realm })}
|
||||||
role="manage-realm"
|
role="manage-realm"
|
||||||
editMode={false}
|
editMode={false}
|
||||||
/>
|
/>
|
||||||
|
</FormProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,12 @@ import {
|
||||||
TabTitleText,
|
TabTitleText,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { SubmitHandler, useForm, useWatch } from "react-hook-form";
|
import {
|
||||||
|
FormProvider,
|
||||||
|
SubmitHandler,
|
||||||
|
useForm,
|
||||||
|
useWatch,
|
||||||
|
} from "react-hook-form";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useLocation, useMatch, useNavigate } from "react-router-dom";
|
import { useLocation, useMatch, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
@ -333,71 +338,72 @@ export default function RealmRoleTabs() {
|
||||||
divider={false}
|
divider={false}
|
||||||
/>
|
/>
|
||||||
<PageSection variant="light" className="pf-u-p-0">
|
<PageSection variant="light" className="pf-u-p-0">
|
||||||
<RoutableTabs isBox mountOnEnter defaultLocation={toTab("details")}>
|
<FormProvider {...form}>
|
||||||
<Tab
|
<RoutableTabs isBox mountOnEnter defaultLocation={toTab("details")}>
|
||||||
title={<TabTitleText>{t("details")}</TabTitleText>}
|
|
||||||
{...detailsTab}
|
|
||||||
>
|
|
||||||
<RoleForm
|
|
||||||
form={form}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
role={clientRoleMatch ? "manage-clients" : "manage-realm"}
|
|
||||||
cancelLink={
|
|
||||||
clientRoleMatch
|
|
||||||
? toClient({ realm: realmName, clientId, tab: "roles" })
|
|
||||||
: toRealmRoles({ realm: realmName })
|
|
||||||
}
|
|
||||||
editMode
|
|
||||||
/>
|
|
||||||
</Tab>
|
|
||||||
{composites && (
|
|
||||||
<Tab
|
<Tab
|
||||||
data-testid="associatedRolesTab"
|
title={<TabTitleText>{t("details")}</TabTitleText>}
|
||||||
title={<TabTitleText>{t("associatedRolesText")}</TabTitleText>}
|
{...detailsTab}
|
||||||
{...associatedRolesTab}
|
|
||||||
>
|
>
|
||||||
<RoleMapping
|
<RoleForm
|
||||||
name={roleName!}
|
onSubmit={onSubmit}
|
||||||
id={id}
|
role={clientRoleMatch ? "manage-clients" : "manage-realm"}
|
||||||
type="roles"
|
cancelLink={
|
||||||
isManager
|
clientRoleMatch
|
||||||
save={(rows) => addComposites(rows.map((r) => r.role))}
|
? toClient({ realm: realmName, clientId, tab: "roles" })
|
||||||
/>
|
: toRealmRoles({ realm: realmName })
|
||||||
</Tab>
|
|
||||||
)}
|
|
||||||
{!isDefaultRole(roleName) && (
|
|
||||||
<Tab
|
|
||||||
data-testid="attributesTab"
|
|
||||||
className="kc-attributes-tab"
|
|
||||||
title={<TabTitleText>{t("attributes")}</TabTitleText>}
|
|
||||||
{...attributesTab}
|
|
||||||
>
|
|
||||||
<AttributesForm
|
|
||||||
form={form}
|
|
||||||
save={onSubmit}
|
|
||||||
reset={() =>
|
|
||||||
setValue("attributes", attributes, { shouldDirty: false })
|
|
||||||
}
|
}
|
||||||
|
editMode
|
||||||
/>
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
)}
|
{composites && (
|
||||||
{!isDefaultRole(roleName) && (
|
<Tab
|
||||||
<Tab
|
data-testid="associatedRolesTab"
|
||||||
title={<TabTitleText>{t("usersInRole")}</TabTitleText>}
|
title={<TabTitleText>{t("associatedRolesText")}</TabTitleText>}
|
||||||
{...usersInRoleTab}
|
{...associatedRolesTab}
|
||||||
>
|
>
|
||||||
<UsersInRoleTab data-cy="users-in-role-tab" />
|
<RoleMapping
|
||||||
</Tab>
|
name={roleName!}
|
||||||
)}
|
id={id}
|
||||||
{isFeatureEnabled(Feature.AdminFineGrainedAuthz) && (
|
type="roles"
|
||||||
<Tab
|
isManager
|
||||||
title={<TabTitleText>{t("permissions")}</TabTitleText>}
|
save={(rows) => addComposites(rows.map((r) => r.role))}
|
||||||
{...permissionsTab}
|
/>
|
||||||
>
|
</Tab>
|
||||||
<PermissionsTab id={id} type="roles" />
|
)}
|
||||||
</Tab>
|
{!isDefaultRole(roleName) && (
|
||||||
)}
|
<Tab
|
||||||
</RoutableTabs>
|
data-testid="attributesTab"
|
||||||
|
className="kc-attributes-tab"
|
||||||
|
title={<TabTitleText>{t("attributes")}</TabTitleText>}
|
||||||
|
{...attributesTab}
|
||||||
|
>
|
||||||
|
<AttributesForm
|
||||||
|
form={form}
|
||||||
|
save={onSubmit}
|
||||||
|
reset={() =>
|
||||||
|
setValue("attributes", attributes, { shouldDirty: false })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Tab>
|
||||||
|
)}
|
||||||
|
{!isDefaultRole(roleName) && (
|
||||||
|
<Tab
|
||||||
|
title={<TabTitleText>{t("usersInRole")}</TabTitleText>}
|
||||||
|
{...usersInRoleTab}
|
||||||
|
>
|
||||||
|
<UsersInRoleTab data-cy="users-in-role-tab" />
|
||||||
|
</Tab>
|
||||||
|
)}
|
||||||
|
{isFeatureEnabled(Feature.AdminFineGrainedAuthz) && (
|
||||||
|
<Tab
|
||||||
|
title={<TabTitleText>{t("permissions")}</TabTitleText>}
|
||||||
|
{...permissionsTab}
|
||||||
|
>
|
||||||
|
<PermissionsTab id={id} type="roles" />
|
||||||
|
</Tab>
|
||||||
|
)}
|
||||||
|
</RoutableTabs>
|
||||||
|
</FormProvider>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue