Fix deprecated wizards (#29453)
* updated wizards Signed-off-by: mfrances <mfrances@redhat.com> * fix broken tests Signed-off-by: mfrances <mfrances@redhat.com> --------- Signed-off-by: mfrances <mfrances@redhat.com>
This commit is contained in:
parent
e284972d7a
commit
bc82e7eb3c
5 changed files with 199 additions and 269 deletions
|
@ -1255,10 +1255,10 @@ describe("Clients test", () => {
|
|||
createClientPage.fillClientData(clientId);
|
||||
cy.checkA11y();
|
||||
|
||||
cy.findByTestId("next").click();
|
||||
createClientPage.continue();
|
||||
cy.checkA11y();
|
||||
|
||||
cy.findByTestId("next").click();
|
||||
createClientPage.continue();
|
||||
cy.checkA11y();
|
||||
});
|
||||
|
||||
|
|
|
@ -55,10 +55,10 @@ export default class CreateClientPage extends CommonPage {
|
|||
#actionDrpDwn = "action-dropdown";
|
||||
#deleteClientBtn = "delete-client";
|
||||
|
||||
#saveBtn = "save";
|
||||
#continueBtn = "next";
|
||||
#backBtn = "back";
|
||||
#cancelBtn = "cancel";
|
||||
#saveBtn = "Save";
|
||||
#continueBtn = "Next";
|
||||
#backBtn = "Back";
|
||||
#cancelBtn = "Cancel";
|
||||
|
||||
//#region General Settings
|
||||
selectClientType(clientType: string) {
|
||||
|
@ -174,25 +174,25 @@ export default class CreateClientPage extends CommonPage {
|
|||
//#endregion
|
||||
|
||||
save() {
|
||||
cy.findByTestId(this.#saveBtn).click();
|
||||
cy.contains("button", this.#saveBtn).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
continue() {
|
||||
cy.findByTestId(this.#continueBtn).click();
|
||||
cy.contains("button", this.#continueBtn).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
back() {
|
||||
cy.findByTestId(this.#backBtn).click();
|
||||
cy.contains("button", this.#backBtn).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
cy.findByTestId(this.#cancelBtn).click();
|
||||
cy.contains("button", this.#cancelBtn).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { AlertVariant, Button, PageSection } from "@patternfly/react-core";
|
||||
import {
|
||||
AlertVariant,
|
||||
PageSection,
|
||||
useWizardContext,
|
||||
Wizard,
|
||||
WizardContextConsumer,
|
||||
WizardFooter,
|
||||
} from "@patternfly/react-core/deprecated";
|
||||
import { useState } from "react";
|
||||
WizardStep,
|
||||
} from "@patternfly/react-core";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
@ -21,6 +22,32 @@ import { CapabilityConfig } from "./CapabilityConfig";
|
|||
import { GeneralSettings } from "./GeneralSettings";
|
||||
import { LoginSettings } from "./LoginSettings";
|
||||
|
||||
const NewClientFooter = (newClientForm: any) => {
|
||||
const { t } = useTranslation();
|
||||
const { trigger } = newClientForm;
|
||||
const { activeStep, goToNextStep, goToPrevStep, close } = useWizardContext();
|
||||
|
||||
const forward = async (onNext: () => void) => {
|
||||
if (!(await trigger())) {
|
||||
return;
|
||||
}
|
||||
onNext?.();
|
||||
};
|
||||
|
||||
return (
|
||||
<WizardFooter
|
||||
activeStep={activeStep}
|
||||
onNext={() => forward(goToNextStep)}
|
||||
onBack={goToPrevStep}
|
||||
onClose={close}
|
||||
isBackDisabled={activeStep.index === 1}
|
||||
backButtonText={t("back")}
|
||||
nextButtonText={t("next")}
|
||||
cancelButtonText={t("cancel")}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default function NewClientForm() {
|
||||
const { adminClient } = useAdminClient();
|
||||
|
||||
|
@ -28,8 +55,6 @@ export default function NewClientForm() {
|
|||
const { realm } = useRealm();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [step, setStep] = useState(0);
|
||||
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const form = useForm<FormFields>({
|
||||
defaultValues: {
|
||||
|
@ -49,7 +74,7 @@ export default function NewClientForm() {
|
|||
},
|
||||
},
|
||||
});
|
||||
const { getValues, watch, trigger } = form;
|
||||
const { getValues, watch } = form;
|
||||
const protocol = watch("protocol");
|
||||
|
||||
const save = async () => {
|
||||
|
@ -66,33 +91,6 @@ export default function NewClientForm() {
|
|||
}
|
||||
};
|
||||
|
||||
const forward = async (onNext?: () => void) => {
|
||||
if (!(await trigger())) {
|
||||
return;
|
||||
}
|
||||
if (!isFinalStep()) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
onNext?.();
|
||||
};
|
||||
|
||||
const isFinalStep = () =>
|
||||
protocol === "openid-connect" ? step === 2 : step === 1;
|
||||
|
||||
const back = () => {
|
||||
setStep(step - 1);
|
||||
};
|
||||
|
||||
const onGoToStep = (newStep: { id?: string | number }) => {
|
||||
if (newStep.id === "generalSettings") {
|
||||
setStep(0);
|
||||
} else if (newStep.id === "capabilityConfig") {
|
||||
setStep(1);
|
||||
} else {
|
||||
setStep(2);
|
||||
}
|
||||
};
|
||||
|
||||
const title = t("createClient");
|
||||
return (
|
||||
<>
|
||||
|
@ -102,75 +100,39 @@ export default function NewClientForm() {
|
|||
<Wizard
|
||||
onClose={() => navigate(toClients({ realm }))}
|
||||
navAriaLabel={`${title} steps`}
|
||||
mainAriaLabel={`${title} content`}
|
||||
steps={[
|
||||
{
|
||||
id: "generalSettings",
|
||||
name: t("generalSettings"),
|
||||
component: <GeneralSettings />,
|
||||
},
|
||||
...(protocol !== "saml"
|
||||
? [
|
||||
{
|
||||
id: "capabilityConfig",
|
||||
name: t("capabilityConfig"),
|
||||
component: <CapabilityConfig protocol={protocol} />,
|
||||
canJumpTo: step >= 1,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
id: "loginSettings",
|
||||
name: t("loginSettings"),
|
||||
component: (
|
||||
<FormAccess isHorizontal role="manage-clients">
|
||||
<LoginSettings protocol={protocol} />
|
||||
</FormAccess>
|
||||
),
|
||||
canJumpTo: step >= 1,
|
||||
},
|
||||
]}
|
||||
footer={
|
||||
<WizardFooter>
|
||||
<WizardContextConsumer>
|
||||
{({ activeStep, onNext, onBack, onClose }) => (
|
||||
<>
|
||||
<Button
|
||||
variant="primary"
|
||||
data-testid={isFinalStep() ? "save" : "next"}
|
||||
type="submit"
|
||||
onClick={() => {
|
||||
forward(onNext);
|
||||
}}
|
||||
>
|
||||
{isFinalStep() ? t("save") : t("next")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
data-testid="back"
|
||||
onClick={() => {
|
||||
back();
|
||||
onBack();
|
||||
}}
|
||||
isDisabled={activeStep.name === t("generalSettings")}
|
||||
>
|
||||
{t("back")}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="cancel"
|
||||
variant="link"
|
||||
onClick={onClose}
|
||||
>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</WizardContextConsumer>
|
||||
</WizardFooter>
|
||||
}
|
||||
onSave={save}
|
||||
onGoToStep={onGoToStep}
|
||||
/>
|
||||
footer={<NewClientFooter {...form} />}
|
||||
>
|
||||
<WizardStep
|
||||
name={t("generalSettings")}
|
||||
id="generalSettings"
|
||||
key="generalSettings"
|
||||
>
|
||||
<GeneralSettings />
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("capabilityConfig")}
|
||||
id="capabilityConfig"
|
||||
key="capabilityConfig"
|
||||
isHidden={protocol === "saml"}
|
||||
>
|
||||
<CapabilityConfig protocol={protocol} />
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("loginSettings")}
|
||||
id="loginSettings"
|
||||
key="loginSettings"
|
||||
footer={{
|
||||
backButtonText: t("back"),
|
||||
nextButtonText: t("save"),
|
||||
cancelButtonText: t("cancel"),
|
||||
}}
|
||||
>
|
||||
<FormAccess isHorizontal role="manage-clients">
|
||||
<LoginSettings protocol={protocol} />
|
||||
</FormAccess>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
</FormProvider>
|
||||
</PageSection>
|
||||
</>
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import { Wizard } from "@patternfly/react-core/deprecated";
|
||||
import {
|
||||
useWizardContext,
|
||||
Wizard,
|
||||
WizardFooter,
|
||||
WizardStep,
|
||||
} from "@patternfly/react-core/";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { KerberosSettingsRequired } from "./kerberos/KerberosSettingsRequired";
|
||||
|
@ -6,36 +11,50 @@ import { SettingsCache } from "./shared/SettingsCache";
|
|||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
const UserFedKerberosFooter = () => {
|
||||
const { t } = useTranslation();
|
||||
const { activeStep, goToNextStep, goToPrevStep, close } = useWizardContext();
|
||||
return (
|
||||
<WizardFooter
|
||||
activeStep={activeStep}
|
||||
onNext={goToNextStep}
|
||||
onBack={goToPrevStep}
|
||||
onClose={close}
|
||||
isBackDisabled={activeStep.index === 1}
|
||||
backButtonText={t("back")}
|
||||
nextButtonText={t("next")}
|
||||
cancelButtonText={t("cancel")}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const UserFederationKerberosWizard = () => {
|
||||
const { t } = useTranslation();
|
||||
const form = useForm<ComponentRepresentation>({ mode: "onChange" });
|
||||
|
||||
const steps = [
|
||||
{
|
||||
name: t("requiredSettings"),
|
||||
component: (
|
||||
return (
|
||||
<Wizard height="100%" footer={<UserFedKerberosFooter />}>
|
||||
<WizardStep
|
||||
name={t("requiredSettings")}
|
||||
id="kerberosRequiredSettingsStep"
|
||||
>
|
||||
<KerberosSettingsRequired
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("cacheSettings"),
|
||||
component: (
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("cacheSettings")}
|
||||
id="cacheSettingsStep"
|
||||
footer={{
|
||||
backButtonText: t("back"),
|
||||
nextButtonText: t("finish"),
|
||||
cancelButtonText: t("cancel"),
|
||||
}}
|
||||
>
|
||||
<SettingsCache form={form} showSectionHeading showSectionDescription />
|
||||
),
|
||||
nextButtonText: t("finish"), // TODO: needs to disable until cache policy is valid
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Wizard
|
||||
// Because this is an inline wizard, this title and description should be put into the page. Specifying them here causes the wizard component to make a header that would be used on a modal.
|
||||
// title={t("addKerberosWizardTitle")}
|
||||
// description={helpText("addKerberosWizardDescription")}
|
||||
steps={steps}
|
||||
/>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
|
||||
import { Button } from "@patternfly/react-core";
|
||||
import {
|
||||
Button,
|
||||
useWizardContext,
|
||||
Wizard,
|
||||
WizardContextConsumer,
|
||||
WizardFooter,
|
||||
} from "@patternfly/react-core/deprecated";
|
||||
WizardFooterWrapper,
|
||||
WizardStep,
|
||||
} from "@patternfly/react-core";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
@ -17,173 +19,120 @@ import { LdapSettingsSearching } from "./ldap/LdapSettingsSearching";
|
|||
import { LdapSettingsSynchronization } from "./ldap/LdapSettingsSynchronization";
|
||||
import { SettingsCache } from "./shared/SettingsCache";
|
||||
|
||||
const UserFedLdapFooter = () => {
|
||||
const { t } = useTranslation();
|
||||
const { activeStep, goToNextStep, goToPrevStep, close } = useWizardContext();
|
||||
return (
|
||||
<WizardFooter
|
||||
activeStep={activeStep}
|
||||
onNext={goToNextStep}
|
||||
onBack={goToPrevStep}
|
||||
onClose={close}
|
||||
isBackDisabled={activeStep.index === 1}
|
||||
backButtonText={t("back")}
|
||||
nextButtonText={t("next")}
|
||||
cancelButtonText={t("cancel")}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const SkipCustomizationFooter = () => {
|
||||
const { goToNextStep, goToPrevStep, close } = useWizardContext();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<WizardFooterWrapper>
|
||||
<Button variant="secondary" onClick={goToPrevStep}>
|
||||
{t("back")}
|
||||
</Button>
|
||||
<Button variant="primary" type="submit" onClick={goToNextStep}>
|
||||
{t("next")}
|
||||
</Button>
|
||||
{/* TODO: validate last step and finish */}
|
||||
<Button variant="link">{t("skipCustomizationAndFinish")}</Button>
|
||||
<Button variant="link" onClick={close}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</WizardFooterWrapper>
|
||||
);
|
||||
};
|
||||
export const UserFederationLdapWizard = () => {
|
||||
const form = useForm<ComponentRepresentation>();
|
||||
const { t } = useTranslation();
|
||||
const isFeatureEnabled = useIsFeatureEnabled();
|
||||
|
||||
const steps = [
|
||||
{
|
||||
name: t("requiredSettings"),
|
||||
id: "ldapRequiredSettingsStep",
|
||||
component: (
|
||||
return (
|
||||
<Wizard height="100%" footer={<UserFedLdapFooter />}>
|
||||
<WizardStep name={t("requiredSettings")} id="ldapRequiredSettingsStep">
|
||||
<LdapSettingsGeneral
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("connectionAndAuthenticationSettings"),
|
||||
id: "ldapConnectionSettingsStep",
|
||||
component: (
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("connectionAndAuthenticationSettings")}
|
||||
id="ldapConnectionSettingsStep"
|
||||
>
|
||||
<LdapSettingsConnection
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("ldapSearchingAndUpdatingSettings"),
|
||||
id: "ldapSearchingSettingsStep",
|
||||
component: (
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("ldapSearchingAndUpdatingSettings")}
|
||||
id="ldapSearchingSettingsStep"
|
||||
>
|
||||
<LdapSettingsSearching
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("synchronizationSettings"),
|
||||
id: "ldapSynchronizationSettingsStep",
|
||||
component: (
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("synchronizationSettings")}
|
||||
id="ldapSynchronizationSettingsStep"
|
||||
footer={<SkipCustomizationFooter />}
|
||||
>
|
||||
<LdapSettingsSynchronization
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("kerberosIntegration"),
|
||||
id: "ldapKerberosIntegrationSettingsStep",
|
||||
component: (
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("kerberosIntegration")}
|
||||
id="ldapKerberosIntegrationSettingsStep"
|
||||
isDisabled={!isFeatureEnabled(Feature.Kerberos)}
|
||||
footer={<SkipCustomizationFooter />}
|
||||
>
|
||||
<LdapSettingsKerberosIntegration
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
isDisabled: !isFeatureEnabled(Feature.Kerberos),
|
||||
},
|
||||
{
|
||||
name: t("cacheSettings"),
|
||||
id: "ldapCacheSettingsStep",
|
||||
component: (
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("cacheSettings")}
|
||||
id="ldapCacheSettingsStep"
|
||||
footer={<SkipCustomizationFooter />}
|
||||
>
|
||||
<SettingsCache form={form} showSectionHeading showSectionDescription />
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("advancedSettings"),
|
||||
id: "ldapAdvancedSettingsStep",
|
||||
component: (
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
name={t("advancedSettings")}
|
||||
id="ldapAdvancedSettingsStep"
|
||||
footer={{
|
||||
backButtonText: t("back"),
|
||||
nextButtonText: t("finish"),
|
||||
cancelButtonText: t("cancel"),
|
||||
}}
|
||||
>
|
||||
<LdapSettingsAdvanced
|
||||
form={form}
|
||||
showSectionHeading
|
||||
showSectionDescription
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const footer = (
|
||||
<WizardFooter>
|
||||
<WizardContextConsumer>
|
||||
{({ activeStep, onNext, onBack, onClose }) => {
|
||||
// First step buttons
|
||||
if (activeStep.id === "ldapRequiredSettingsStep") {
|
||||
return (
|
||||
<>
|
||||
<Button variant="primary" type="submit" onClick={onNext}>
|
||||
{t("next")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={onBack}
|
||||
className="pf-m-disabled"
|
||||
>
|
||||
{t("back")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={onClose}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
// Other required step buttons
|
||||
else if (
|
||||
activeStep.id === "ldapConnectionSettingsStep" ||
|
||||
activeStep.id === "ldapSearchingSettingsStep"
|
||||
) {
|
||||
return (
|
||||
<>
|
||||
<Button variant="primary" type="submit" onClick={onNext}>
|
||||
{t("next")}
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onBack}>
|
||||
{t("back")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={onClose}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
// Last step buttons
|
||||
else if (activeStep.id === "ldapAdvancedSettingsStep") {
|
||||
return (
|
||||
<>
|
||||
{/* TODO: close the wizard and finish */}
|
||||
<Button>{t("finish")}</Button>
|
||||
<Button variant="secondary" onClick={onBack}>
|
||||
{t("back")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={onClose}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
// All the other steps buttons
|
||||
return (
|
||||
<>
|
||||
<Button onClick={onNext}>Next</Button>
|
||||
<Button variant="secondary" onClick={onBack}>
|
||||
Back
|
||||
</Button>
|
||||
{/* TODO: validate last step and finish */}
|
||||
<Button variant="link">{t("skipCustomizationAndFinish")}</Button>
|
||||
<Button variant="link" onClick={onClose}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</WizardContextConsumer>
|
||||
</WizardFooter>
|
||||
);
|
||||
|
||||
return (
|
||||
<Wizard
|
||||
// Because this is an inline wizard, this title and description should be put into the page. Specifying them here causes the wizard component to make a header that would be used on a modal.
|
||||
// title={t("addLdapWizardTitle")}
|
||||
// description={helpText("addLdapWizardDescription")}
|
||||
height="100%"
|
||||
steps={steps}
|
||||
footer={footer}
|
||||
/>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue