Convert realms settings general tab to new form controls (#28464)
Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
a0cf09e899
commit
3fda2c0444
2 changed files with 212 additions and 271 deletions
|
@ -1,3 +1,4 @@
|
|||
import Select from "../../../../forms/Select";
|
||||
import CommonPage from "../../../CommonPage";
|
||||
import ListingPage from "../../ListingPage";
|
||||
import RealmSettingsEventsTab from "./tabs/RealmSettingsEventsTab";
|
||||
|
@ -66,7 +67,7 @@ export default class RealmSettingsPage extends CommonPage {
|
|||
"#kc-l-supported-locales-select-multi-typeahead-typeahead";
|
||||
supportedLocalesToggle = "#kc-l-supported-locales";
|
||||
emailSaveBtn = "email-tab-save";
|
||||
managedAccessSwitch = "user-managed-access-switch";
|
||||
managedAccessSwitch = "userManagedAccessAllowed";
|
||||
userRegSwitch = "user-reg-switch";
|
||||
forgotPwdSwitch = "forgot-pw-switch";
|
||||
rememberMeSwitch = "remember-me-switch";
|
||||
|
@ -235,10 +236,6 @@ export default class RealmSettingsPage extends CommonPage {
|
|||
#selectScopeButton = "addValue";
|
||||
#deleteClientRolesConditionBtn = "delete-client-roles-condition";
|
||||
#deleteClientScopesConditionBtn = "delete-client-scopes-condition";
|
||||
#realmDisplayName = "#kc-display-name";
|
||||
#frontEndURL = "#kc-frontend-url";
|
||||
#requireSSL = "#kc-require-ssl";
|
||||
#unmanagedAttributes = "#kc-user-profile-unmanaged-attribute-policy";
|
||||
#fromDisplayName = "smtpServer.fromDisplayName";
|
||||
#replyToEmail = "smtpServer.replyTo";
|
||||
#port = "smtpServer.port";
|
||||
|
@ -262,6 +259,22 @@ export default class RealmSettingsPage extends CommonPage {
|
|||
this.#realmName = realmName;
|
||||
}
|
||||
|
||||
#getRealmDisplayName() {
|
||||
return cy.findByTestId("displayName");
|
||||
}
|
||||
|
||||
#getFrontEndURL() {
|
||||
return cy.findByTestId("attributes.frontendUrl");
|
||||
}
|
||||
|
||||
#getSSLRequired() {
|
||||
return cy.get("#sslRequired");
|
||||
}
|
||||
|
||||
#getUnmanagedAttributes() {
|
||||
return cy.get("#unmanagedAttributePolicy");
|
||||
}
|
||||
|
||||
goToEventsTab() {
|
||||
this.tabUtils().clickTab(RealmSettingsTab.Events);
|
||||
return this.#realmSettingsEventsTab;
|
||||
|
@ -311,29 +324,28 @@ export default class RealmSettingsPage extends CommonPage {
|
|||
}
|
||||
|
||||
getDisplayName(name: string) {
|
||||
cy.get(this.#realmDisplayName).should("have.value", name);
|
||||
this.#getRealmDisplayName().should("have.value", name);
|
||||
return this;
|
||||
}
|
||||
|
||||
getFrontendURL(url: string) {
|
||||
cy.get(this.#frontEndURL).should("have.value", url);
|
||||
this.#getFrontEndURL().should("have.value", url);
|
||||
return this;
|
||||
}
|
||||
|
||||
getRequireSSL(option: string) {
|
||||
cy.get(this.#requireSSL).contains(option);
|
||||
|
||||
Select.assertSelectedItem(this.#getSSLRequired(), option);
|
||||
return this;
|
||||
}
|
||||
|
||||
getUnmanagedAttributes(option: string) {
|
||||
cy.get(this.#unmanagedAttributes).contains(option);
|
||||
|
||||
Select.assertSelectedItem(this.#getUnmanagedAttributes(), option);
|
||||
return this;
|
||||
}
|
||||
|
||||
fillDisplayName(displayName: string) {
|
||||
cy.get(this.#realmDisplayName).clear().type(displayName);
|
||||
this.#getRealmDisplayName().clear();
|
||||
this.#getRealmDisplayName().type(displayName);
|
||||
}
|
||||
|
||||
clearRealmId() {
|
||||
|
@ -355,27 +367,20 @@ export default class RealmSettingsPage extends CommonPage {
|
|||
}
|
||||
|
||||
fillFrontendURL(url: string) {
|
||||
cy.get(this.#frontEndURL).clear().type(url);
|
||||
this.clearFrontendURL();
|
||||
this.#getFrontEndURL().type(url);
|
||||
}
|
||||
|
||||
clearFrontendURL() {
|
||||
cy.get(this.#frontEndURL).clear();
|
||||
this.#getFrontEndURL().clear();
|
||||
}
|
||||
|
||||
fillRequireSSL(option: string) {
|
||||
cy.get(this.#requireSSL)
|
||||
.click()
|
||||
.get(".pf-c-select__menu-item")
|
||||
.contains(option)
|
||||
.click();
|
||||
Select.selectItem(this.#getSSLRequired(), option);
|
||||
}
|
||||
|
||||
fillUnmanagedAttributes(option: string) {
|
||||
cy.get(this.#unmanagedAttributes)
|
||||
.click()
|
||||
.get(".pf-c-select__menu-item")
|
||||
.contains(option)
|
||||
.click();
|
||||
Select.selectItem(this.#getUnmanagedAttributes(), option);
|
||||
}
|
||||
|
||||
setDefaultLocale(locale: string) {
|
||||
|
|
|
@ -1,37 +1,34 @@
|
|||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import {
|
||||
UnmanagedAttributePolicy,
|
||||
UserProfileConfig,
|
||||
} from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
ClipboardCopy,
|
||||
FormGroup,
|
||||
PageSection,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Stack,
|
||||
StackItem,
|
||||
Switch,
|
||||
} from "@patternfly/react-core";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HelpItem } from "ui-shared";
|
||||
import { HelpItem, SelectControl, TextControl } from "ui-shared";
|
||||
|
||||
import { adminClient } from "../admin-client";
|
||||
import { DefaultSwitchControl } from "../components/SwitchControl";
|
||||
import { FormattedLink } from "../components/external-link/FormattedLink";
|
||||
import { FormAccess } from "../components/form/FormAccess";
|
||||
import { KeyValueInput } from "../components/key-value-form/KeyValueInput";
|
||||
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
|
||||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import {
|
||||
addTrailingSlash,
|
||||
convertAttributeNameToForm,
|
||||
convertToFormValues,
|
||||
} from "../util";
|
||||
import {
|
||||
UnmanagedAttributePolicy,
|
||||
UserProfileConfig,
|
||||
} from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata";
|
||||
import { useFetch } from "../utils/useFetch";
|
||||
import { UIRealmRepresentation } from "./RealmSettingsTabs";
|
||||
|
||||
|
@ -40,36 +37,66 @@ type RealmSettingsGeneralTabProps = {
|
|||
save: (realm: UIRealmRepresentation) => void;
|
||||
};
|
||||
|
||||
type FormFields = Omit<RealmRepresentation, "groups">;
|
||||
|
||||
export const RealmSettingsGeneralTab = ({
|
||||
realm,
|
||||
save,
|
||||
}: RealmSettingsGeneralTabProps) => {
|
||||
const { realm: realmName } = useRealm();
|
||||
const [userProfileConfig, setUserProfileConfig] =
|
||||
useState<UserProfileConfig>();
|
||||
|
||||
useFetch(
|
||||
() => adminClient.users.getProfile({ realm: realmName }),
|
||||
(config) => setUserProfileConfig(config),
|
||||
[],
|
||||
);
|
||||
|
||||
if (!userProfileConfig) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<RealmSettingsGeneralTabForm
|
||||
realm={realm}
|
||||
save={save}
|
||||
userProfileConfig={userProfileConfig}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
type RealmSettingsGeneralTabFormProps = {
|
||||
realm: UIRealmRepresentation;
|
||||
save: (realm: UIRealmRepresentation) => void;
|
||||
userProfileConfig: UserProfileConfig;
|
||||
};
|
||||
|
||||
type FormFields = Omit<RealmRepresentation, "groups"> & {
|
||||
unmanagedAttributePolicy: UnmanagedAttributePolicy;
|
||||
};
|
||||
|
||||
const REQUIRE_SSL_TYPES = ["all", "external", "none"];
|
||||
|
||||
const UNMANAGED_ATTRIBUTE_POLICIES = [
|
||||
UnmanagedAttributePolicy.Disabled,
|
||||
UnmanagedAttributePolicy.Enabled,
|
||||
UnmanagedAttributePolicy.AdminView,
|
||||
UnmanagedAttributePolicy.AdminEdit,
|
||||
];
|
||||
|
||||
function RealmSettingsGeneralTabForm({
|
||||
realm,
|
||||
save,
|
||||
userProfileConfig,
|
||||
}: RealmSettingsGeneralTabFormProps) {
|
||||
const { t } = useTranslation();
|
||||
const { realm: realmName } = useRealm();
|
||||
const form = useForm<FormFields>();
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
formState: { isDirty, errors },
|
||||
} = form;
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const requireSslTypes = ["all", "external", "none"];
|
||||
|
||||
const [userProfileConfig, setUserProfileConfig] =
|
||||
useState<UserProfileConfig>();
|
||||
const unmanagedAttributePolicies = [
|
||||
UnmanagedAttributePolicy.Disabled,
|
||||
UnmanagedAttributePolicy.Enabled,
|
||||
UnmanagedAttributePolicy.AdminView,
|
||||
UnmanagedAttributePolicy.AdminEdit,
|
||||
];
|
||||
const [isUnmanagedAttributeOpen, setIsUnmanagedAttributeOpen] =
|
||||
useState(false);
|
||||
|
||||
const setupForm = () => {
|
||||
convertToFormValues(realm, setValue);
|
||||
|
@ -85,244 +112,153 @@ export const RealmSettingsGeneralTab = ({
|
|||
}
|
||||
};
|
||||
|
||||
useFetch(
|
||||
() => adminClient.users.getProfile({ realm: realmName }),
|
||||
(config) => setUserProfileConfig(config),
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(setupForm, []);
|
||||
|
||||
const onSubmit = handleSubmit(({ unmanagedAttributePolicy, ...data }) => {
|
||||
const upConfig = { ...userProfileConfig };
|
||||
|
||||
if (unmanagedAttributePolicy === UnmanagedAttributePolicy.Disabled) {
|
||||
delete upConfig.unmanagedAttributePolicy;
|
||||
} else {
|
||||
upConfig.unmanagedAttributePolicy = unmanagedAttributePolicy;
|
||||
}
|
||||
|
||||
save({ ...data, upConfig });
|
||||
});
|
||||
|
||||
return (
|
||||
<PageSection variant="light">
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
role="manage-realm"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={handleSubmit((data) => {
|
||||
if (
|
||||
UnmanagedAttributePolicy.Disabled ===
|
||||
userProfileConfig?.unmanagedAttributePolicy
|
||||
) {
|
||||
userProfileConfig.unmanagedAttributePolicy = undefined;
|
||||
}
|
||||
save({ ...data, upConfig: userProfileConfig });
|
||||
})}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("realmId")}
|
||||
fieldId="kc-realm-id"
|
||||
isRequired
|
||||
validated={errors.realm ? "error" : "default"}
|
||||
helperTextInvalid={errors.realm?.message}
|
||||
<FormProvider {...form}>
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
role="manage-realm"
|
||||
className="pf-u-mt-lg"
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<Controller
|
||||
name="realm"
|
||||
control={control}
|
||||
rules={{
|
||||
required: { value: true, message: t("required") },
|
||||
}}
|
||||
defaultValue=""
|
||||
render={({ field }) => (
|
||||
<ClipboardCopy data-testid="realmName" onChange={field.onChange}>
|
||||
{field.value}
|
||||
</ClipboardCopy>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={t("displayName")} fieldId="kc-display-name">
|
||||
<KeycloakTextInput
|
||||
id="kc-display-name"
|
||||
{...register("displayName")}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={t("htmlDisplayName")} fieldId="kc-html-display-name">
|
||||
<KeycloakTextInput
|
||||
id="kc-html-display-name"
|
||||
{...register("displayNameHtml")}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("frontendUrl")}
|
||||
fieldId="kc-frontend-url"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("frontendUrlHelp")}
|
||||
fieldLabelId="frontendUrl"
|
||||
<FormGroup
|
||||
label={t("realmId")}
|
||||
fieldId="kc-realm-id"
|
||||
isRequired
|
||||
validated={errors.realm ? "error" : "default"}
|
||||
helperTextInvalid={errors.realm?.message}
|
||||
>
|
||||
<Controller
|
||||
name="realm"
|
||||
control={control}
|
||||
rules={{
|
||||
required: { value: true, message: t("required") },
|
||||
}}
|
||||
defaultValue=""
|
||||
render={({ field }) => (
|
||||
<ClipboardCopy
|
||||
data-testid="realmName"
|
||||
onChange={field.onChange}
|
||||
>
|
||||
{field.value}
|
||||
</ClipboardCopy>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
</FormGroup>
|
||||
<TextControl name="displayName" label={t("displayName")} />
|
||||
<TextControl name="displayNameHtml" label={t("htmlDisplayName")} />
|
||||
<TextControl
|
||||
name={convertAttributeNameToForm("attributes.frontendUrl")}
|
||||
type="url"
|
||||
id="kc-frontend-url"
|
||||
{...register(convertAttributeNameToForm("attributes.frontendUrl"))}
|
||||
label={t("htmlDisplayName")}
|
||||
labelIcon={t("frontendUrlHelp")}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("requireSsl")}
|
||||
fieldId="kc-require-ssl"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("requireSslHelp")}
|
||||
fieldLabelId="requireSsl"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
<SelectControl
|
||||
name="sslRequired"
|
||||
defaultValue="none"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Select
|
||||
toggleId="kc-require-ssl"
|
||||
onToggle={() => setOpen(!open)}
|
||||
onSelect={(_, value) => {
|
||||
field.onChange(value as string);
|
||||
setOpen(false);
|
||||
}}
|
||||
selections={field.value}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("requireSsl")}
|
||||
isOpen={open}
|
||||
>
|
||||
{requireSslTypes.map((sslType) => (
|
||||
<SelectOption
|
||||
selected={sslType === field.value}
|
||||
key={sslType}
|
||||
value={sslType}
|
||||
>
|
||||
{t(`sslType.${sslType}`)}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
label={t("requireSsl")}
|
||||
labelIcon={t("requireSslHelp")}
|
||||
controller={{
|
||||
defaultValue: "none",
|
||||
}}
|
||||
options={REQUIRE_SSL_TYPES.map((sslType) => ({
|
||||
key: sslType,
|
||||
value: t(`sslType.${sslType}`),
|
||||
}))}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("acrToLoAMapping")}
|
||||
fieldId="acrToLoAMapping"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("acrToLoAMappingHelp")}
|
||||
fieldLabelId="acrToLoAMapping"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<FormProvider {...form}>
|
||||
<FormGroup
|
||||
label={t("acrToLoAMapping")}
|
||||
fieldId="acrToLoAMapping"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("acrToLoAMappingHelp")}
|
||||
fieldLabelId="acrToLoAMapping"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<KeyValueInput
|
||||
label={t("acrToLoAMapping")}
|
||||
name={convertAttributeNameToForm("attributes.acr.loa.map")}
|
||||
/>
|
||||
</FormProvider>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
hasNoPaddingTop
|
||||
label={t("userManagedAccess")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("userManagedAccessHelp")}
|
||||
fieldLabelId="userManagedAccess"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-user-managed-access"
|
||||
>
|
||||
<Controller
|
||||
</FormGroup>
|
||||
<DefaultSwitchControl
|
||||
name="userManagedAccessAllowed"
|
||||
control={control}
|
||||
defaultValue={false}
|
||||
render={({ field }) => (
|
||||
<Switch
|
||||
id="kc-user-managed-access"
|
||||
data-testid="user-managed-access-switch"
|
||||
label={t("on")}
|
||||
labelOff={t("off")}
|
||||
isChecked={field.value}
|
||||
onChange={field.onChange}
|
||||
aria-label={t("userManagedAccess")}
|
||||
/>
|
||||
)}
|
||||
label={t("userManagedAccess")}
|
||||
labelIcon={t("userManagedAccessHelp")}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("unmanagedAttributes")}
|
||||
fieldId="kc-user-profile-unmanaged-attribute-policy"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("unmanagedAttributesHelpText")}
|
||||
fieldLabelId="unmanagedAttributes"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Select
|
||||
toggleId="kc-user-profile-unmanaged-attribute-policy"
|
||||
onToggle={() =>
|
||||
setIsUnmanagedAttributeOpen(!isUnmanagedAttributeOpen)
|
||||
}
|
||||
onSelect={(_, value) => {
|
||||
if (userProfileConfig) {
|
||||
userProfileConfig.unmanagedAttributePolicy =
|
||||
value as UnmanagedAttributePolicy;
|
||||
setUserProfileConfig(userProfileConfig);
|
||||
}
|
||||
setIsUnmanagedAttributeOpen(false);
|
||||
<SelectControl
|
||||
name="unmanagedAttributePolicy"
|
||||
label={t("unmanagedAttributes")}
|
||||
labelIcon={t("unmanagedAttributesHelpText")}
|
||||
controller={{
|
||||
defaultValue: UNMANAGED_ATTRIBUTE_POLICIES[0],
|
||||
}}
|
||||
selections={userProfileConfig?.unmanagedAttributePolicy}
|
||||
variant={SelectVariant.single}
|
||||
isOpen={isUnmanagedAttributeOpen}
|
||||
aria-label={t("selectUnmanagedAttributePolicy")}
|
||||
>
|
||||
{unmanagedAttributePolicies.map((policy) => (
|
||||
<SelectOption key={policy} value={policy}>
|
||||
{t(`unmanagedAttributePolicy.${policy}`)}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("endpoints")}
|
||||
labelIcon={
|
||||
<HelpItem helpText={t("endpointsHelp")} fieldLabelId="endpoints" />
|
||||
}
|
||||
fieldId="kc-endpoints"
|
||||
>
|
||||
<Stack>
|
||||
<StackItem>
|
||||
<FormattedLink
|
||||
href={`${addTrailingSlash(
|
||||
adminClient.baseUrl,
|
||||
)}realms/${realmName}/.well-known/openid-configuration`}
|
||||
title={t("openIDEndpointConfiguration")}
|
||||
options={UNMANAGED_ATTRIBUTE_POLICIES.map((policy) => ({
|
||||
key: policy,
|
||||
value: t(`unmanagedAttributePolicy.${policy}`),
|
||||
}))}
|
||||
/>
|
||||
<FormGroup
|
||||
label={t("endpoints")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("endpointsHelp")}
|
||||
fieldLabelId="endpoints"
|
||||
/>
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<FormattedLink
|
||||
href={`${addTrailingSlash(
|
||||
adminClient.baseUrl,
|
||||
)}realms/${realmName}/protocol/saml/descriptor`}
|
||||
title={t("samlIdentityProviderMetadata")}
|
||||
/>
|
||||
</StackItem>
|
||||
</Stack>
|
||||
</FormGroup>
|
||||
|
||||
<ActionGroup>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
data-testid="general-tab-save"
|
||||
isDisabled={!isDirty}
|
||||
}
|
||||
fieldId="kc-endpoints"
|
||||
>
|
||||
{t("save")}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="general-tab-revert"
|
||||
variant="link"
|
||||
onClick={setupForm}
|
||||
>
|
||||
{t("revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
<Stack>
|
||||
<StackItem>
|
||||
<FormattedLink
|
||||
href={`${addTrailingSlash(
|
||||
adminClient.baseUrl,
|
||||
)}realms/${realmName}/.well-known/openid-configuration`}
|
||||
title={t("openIDEndpointConfiguration")}
|
||||
/>
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<FormattedLink
|
||||
href={`${addTrailingSlash(
|
||||
adminClient.baseUrl,
|
||||
)}realms/${realmName}/protocol/saml/descriptor`}
|
||||
title={t("samlIdentityProviderMetadata")}
|
||||
/>
|
||||
</StackItem>
|
||||
</Stack>
|
||||
</FormGroup>
|
||||
<ActionGroup>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
data-testid="general-tab-save"
|
||||
isDisabled={!isDirty}
|
||||
>
|
||||
{t("save")}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="general-tab-revert"
|
||||
variant="link"
|
||||
onClick={setupForm}
|
||||
>
|
||||
{t("revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
</FormProvider>
|
||||
</PageSection>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue