web: resetting the form is not working yet...

I vehemently dislike the object-oriented "reset" command; every wizard should start with
an absolutely fresh copy of the data upon entry.  Refactoring the wizard to re-build its
content from the inside is the correct way to go, but I don't have a good mental image
of how to make the ModalButton and the component it invokes interact cleanly, which
frustrates the hell out of me.
This commit is contained in:
Ken Sternberg 2023-09-02 09:08:06 -07:00
parent 217505d0c9
commit c889801bb3
5 changed files with 39 additions and 24 deletions

View File

@ -1,6 +1,7 @@
import { type AkWizardMain } from "@goauthentik/app/components/ak-wizard-main/ak-wizard-main"; import { type AkWizardMain } from "@goauthentik/app/components/ak-wizard-main/ak-wizard-main";
import { merge } from "@goauthentik/common/merge"; import { merge } from "@goauthentik/common/merge";
import "@goauthentik/components/ak-wizard-main"; import "@goauthentik/components/ak-wizard-main";
import { CloseWizard } from "@goauthentik/components/ak-wizard-main/commonWizardButtons";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter"; import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter";
@ -15,8 +16,14 @@ import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import applicationWizardContext from "./ak-application-wizard-context-name"; import applicationWizardContext from "./ak-application-wizard-context-name";
import { steps } from "./steps"; import { newSteps } from "./steps";
import { OneOfProvider, WizardState, WizardStateEvent } from "./types"; import { OneOfProvider, WizardState, WizardStateUpdate } from "./types";
const freshWizardState = () => ({
providerModel: "",
app: {},
provider: {},
});
@customElement("ak-application-wizard") @customElement("ak-application-wizard")
export class ApplicationWizard extends CustomListenerElement(AKElement) { export class ApplicationWizard extends CustomListenerElement(AKElement) {
@ -25,11 +32,7 @@ export class ApplicationWizard extends CustomListenerElement(AKElement) {
} }
@state() @state()
wizardState: WizardState = { wizardState: WizardState = freshWizardState();
providerModel: "",
app: {},
provider: {},
};
/** /**
* Providing a context at the root element * Providing a context at the root element
@ -40,7 +43,7 @@ export class ApplicationWizard extends CustomListenerElement(AKElement) {
}); });
@state() @state()
steps = steps; steps = newSteps();
@property() @property()
prompt = msg("Create"); prompt = msg("Create");
@ -49,15 +52,15 @@ export class ApplicationWizard extends CustomListenerElement(AKElement) {
wizardRef: Ref<AkWizardMain> = createRef(); wizardRef: Ref<AkWizardMain> = createRef();
get step() {
return this.wizardRef.value?.currentStep ?? -1;
}
constructor() { constructor() {
super(); super();
this.handleUpdate = this.handleUpdate.bind(this); this.handleUpdate = this.handleUpdate.bind(this);
} }
get step() {
return this.wizardRef.value?.currentStep ?? -1;
}
connectedCallback() { connectedCallback() {
super.connectedCallback(); super.connectedCallback();
new ContextRoot().attach(this.parentElement!); new ContextRoot().attach(this.parentElement!);
@ -88,11 +91,25 @@ export class ApplicationWizard extends CustomListenerElement(AKElement) {
throw new Error("Could not find Authentication Method page?"); throw new Error("Could not find Authentication Method page?");
} }
method.disabled = false; method.disabled = false;
return true;
} }
// And this is where all the special cases go... // And this is where all the special cases go...
handleUpdate(event: CustomEvent<WizardStateEvent>) { handleUpdate(event: CustomEvent<WizardStateUpdate>) {
if (event.detail.status === "submitted") {
const submitStep = this.steps.find(({ id }) => id === "submit");
if (!submitStep) {
throw new Error("Could not find submit step?");
}
submitStep.buttons = [CloseWizard];
this.steps = [...this.steps];
return;
}
const update = event.detail.update; const update = event.detail.update;
if (!update) {
return;
}
if (this.maybeProviderSwap(update.providerModel)) { if (this.maybeProviderSwap(update.providerModel)) {
this.steps = [...this.steps]; this.steps = [...this.steps];
@ -100,7 +117,7 @@ export class ApplicationWizard extends CustomListenerElement(AKElement) {
if (event.detail.status === "valid" && this.steps[this.step + 1]) { if (event.detail.status === "valid" && this.steps[this.step + 1]) {
this.steps[this.step + 1].disabled = false; this.steps[this.step + 1].disabled = false;
this.steps = [...this.steps]; this.steps = [...this.steps];
} }
this.wizardState = merge(this.wizardState, update) as WizardState; this.wizardState = merge(this.wizardState, update) as WizardState;

View File

@ -26,6 +26,7 @@ import type { ModelRequest } from "@goauthentik/api";
import BasePanel from "../BasePanel"; import BasePanel from "../BasePanel";
import providerModelsList from "../auth-method-choice/ak-application-wizard-authentication-method-choice.choices"; import providerModelsList from "../auth-method-choice/ak-application-wizard-authentication-method-choice.choices";
import { type WizardStateUpdate } from "../types";
function cleanApplication(app: Partial<ApplicationRequest>): ApplicationRequest { function cleanApplication(app: Partial<ApplicationRequest>): ApplicationRequest {
return { return {
@ -100,6 +101,7 @@ export class ApplicationWizardCommitApplication extends BasePanel {
const network = new CoreApi(DEFAULT_CONFIG).coreTransactionalApplicationsUpdate({ const network = new CoreApi(DEFAULT_CONFIG).coreTransactionalApplicationsUpdate({
transactionApplicationRequest: data, transactionApplicationRequest: data,
}); });
Promise.allSettled([network, timeout]).then(([network_resolution]) => { Promise.allSettled([network, timeout]).then(([network_resolution]) => {
if (network_resolution.status === "rejected") { if (network_resolution.status === "rejected") {
this.commitState = errorState; this.commitState = errorState;
@ -112,9 +114,9 @@ export class ApplicationWizardCommitApplication extends BasePanel {
this.errors = network_resolution.value.logs; this.errors = network_resolution.value.logs;
return; return;
} }
this.response = network_resolution.value; this.response = network_resolution.value;
this.dispatchCustomEvent(EVENT_REFRESH); this.dispatchCustomEvent(EVENT_REFRESH);
this.dispatchWizardUpdate({ status: "submitted"});
this.commitState = doneState; this.commitState = doneState;
} }
}); });

View File

@ -14,11 +14,11 @@ import "./commit/ak-application-wizard-commit-application";
import "./methods/ak-application-wizard-authentication-method"; import "./methods/ak-application-wizard-authentication-method";
type NamedStep = WizardStep & { type NamedStep = WizardStep & {
id: string, id: string;
valid: boolean, valid: boolean;
}; };
export const steps: NamedStep[] = [ export const newSteps = (): NamedStep[] => [
{ {
id: "application", id: "application",
label: "Application Details", label: "Application Details",

View File

@ -25,6 +25,6 @@ export interface WizardState {
type StatusType = "invalid" | "valid" | "submitted" | "failed"; type StatusType = "invalid" | "valid" | "submitted" | "failed";
export type WizardStateUpdate = { export type WizardStateUpdate = {
update: Partial<WizardState>, update?: Partial<WizardState>,
status?: StatusType, status?: StatusType,
}; };

View File

@ -154,11 +154,6 @@ export class AkWizardMain extends CustomListenerElement(AKElement) {
return; return;
} }
case "next": { case "next": {
console.log(this.nextStep,
this.steps[this.nextStep],
!this.steps[this.nextStep].disabled,
this.validated);
if ( if (
this.nextStep && this.nextStep &&
this.steps[this.nextStep] && this.steps[this.nextStep] &&
@ -170,6 +165,7 @@ export class AkWizardMain extends CustomListenerElement(AKElement) {
return; return;
} }
case "close": { case "close": {
this.currentStep = 0;
this.frame.open = false; this.frame.open = false;
} }
} }