From cbff6b1eeb17a2bcb7132fd20cf4f97ff85d90ed Mon Sep 17 00:00:00 2001 From: "Jens L." Date: Thu, 15 Jan 2026 21:31:46 +0100 Subject: [PATCH] web/admin: fix switches (#19493) * web/admin: fix switches Signed-off-by: Jens Langhammer * update all forms Signed-off-by: Jens Langhammer * Apply suggestions from code review Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com> Signed-off-by: Jens L. * fix lint Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer Signed-off-by: Jens L. Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com> --- .../ServiceConnectionKubernetesForm.ts | 23 +--- .../policies/password/PasswordPolicyForm.ts | 123 ++++++------------ .../AuthenticatorEmailStageForm.ts | 79 ++++------- web/src/admin/stages/email/EmailStageForm.ts | 109 +++++----------- web/src/admin/stages/prompt/PromptForm.ts | 96 +++++--------- web/src/components/ak-switch-input.ts | 24 +++- web/src/elements/sync/SyncObjectForm.ts | 24 ++-- 7 files changed, 162 insertions(+), 316 deletions(-) diff --git a/web/src/admin/outposts/ServiceConnectionKubernetesForm.ts b/web/src/admin/outposts/ServiceConnectionKubernetesForm.ts index 0a0bcee584..13859e4299 100644 --- a/web/src/admin/outposts/ServiceConnectionKubernetesForm.ts +++ b/web/src/admin/outposts/ServiceConnectionKubernetesForm.ts @@ -70,23 +70,12 @@ export class ServiceConnectionKubernetesForm extends ModelForm< ${msg("Set custom attributes using YAML or JSON.")}

- - - `; + + `; } } diff --git a/web/src/admin/policies/password/PasswordPolicyForm.ts b/web/src/admin/policies/password/PasswordPolicyForm.ts index 88c05b8b9e..414eee505c 100644 --- a/web/src/admin/policies/password/PasswordPolicyForm.ts +++ b/web/src/admin/policies/password/PasswordPolicyForm.ts @@ -1,4 +1,5 @@ import "#elements/forms/FormGroup"; +import "#components/ak-switch-input"; import "#elements/forms/HorizontalFormElement"; import { DEFAULT_CONFIG } from "#common/api/config"; @@ -228,26 +229,14 @@ export class PasswordPolicyForm extends BasePolicyForm { required /> - - -

- ${msg( - "When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.", - )} -

-
+ {

- - - - - -

+ { + const el = ev.target as HTMLInputElement; + this.showStatic = el.checked; + }} + > + { + const el = ev.target as HTMLInputElement; + this.showHIBP = el.checked; + }} + .bighelp=${html`

${msg("For more info see:")} haveibeenpwned.com -

-
- - -

+

`} + > + + { + const el = ev.target as HTMLInputElement; + this.showZxcvbn = el.checked; + }} + .bighelp=${html`

${msg("Password strength estimator created by Dropbox, see:")} dropbox/zxcvbn -

-
+

`} + > + ${this.showStatic ? this.renderStaticRules() : nothing} ${this.showHIBP ? this.renderHIBP() : nothing} ${this.showZxcvbn ? this.renderZxcvbn() : nothing}`; diff --git a/web/src/admin/stages/authenticator_email/AuthenticatorEmailStageForm.ts b/web/src/admin/stages/authenticator_email/AuthenticatorEmailStageForm.ts index 70ca64a5fe..d7c9d6a2e2 100644 --- a/web/src/admin/stages/authenticator_email/AuthenticatorEmailStageForm.ts +++ b/web/src/admin/stages/authenticator_email/AuthenticatorEmailStageForm.ts @@ -3,6 +3,7 @@ import "#elements/forms/FormGroup"; import "#elements/forms/HorizontalFormElement"; import "#elements/forms/Radio"; import "#elements/forms/SearchSelect/index"; +import "#components/ak-switch-input"; import { DEFAULT_CONFIG } from "#common/api/config"; @@ -93,36 +94,18 @@ export class AuthenticatorEmailStageForm extends BaseStageForm - - - - - - + + + + - - -

- ${msg( - "When enabled, global email connection settings will be used and connection settings below will be ignored.", - )} -

-
+ { + const target = ev.target as HTMLInputElement; + this.showConnectionSettings = !target.checked; + }} + label=${msg("Use global connection settings")} + help=${msg( + "When enabled, global email connection settings will be used and connection settings below will be ignored.", + )} + > ${this.renderConnectionSettings()}
diff --git a/web/src/admin/stages/email/EmailStageForm.ts b/web/src/admin/stages/email/EmailStageForm.ts index dcadf46b84..c92adb82f1 100644 --- a/web/src/admin/stages/email/EmailStageForm.ts +++ b/web/src/admin/stages/email/EmailStageForm.ts @@ -2,6 +2,7 @@ import "#components/ak-secret-text-input"; import "#elements/forms/FormGroup"; import "#elements/forms/HorizontalFormElement"; import "#elements/utils/TimeDeltaHelp"; +import "#components/ak-switch-input"; import { DEFAULT_CONFIG } from "#common/api/config"; @@ -81,36 +82,18 @@ export class EmailStageForm extends BaseStageForm { name="password" ?revealed=${!this.instance} > - - - - - - + + + + {
- - -

- ${msg( - "When a user returns from the email successfully, their account will be activated.", - )} -

-
- - -

- ${msg( - "When enabled, global Email connection settings will be used and connection settings below will be ignored.", - )} -

-
+ + { + const target = ev.target as HTMLInputElement; + this.showConnectionSettings = !target.checked; + }} + label=${msg("Use global connection settings")} + help=${msg( + "When enabled, global email connection settings will be used and connection settings below will be ignored.", + )} + > { ${this.renderTypes()} - - - - - -

- ${msg( - `When checked, the placeholder will be evaluated in the same way a property mapping is. - If the evaluation fails, the placeholder itself is returned.`, - )} -

-
+ { + this._shouldRefresh = true; + }} + label=${msg("Required")} + > + { + this._shouldRefresh = true; + }} + label=${msg("Interpret placeholder as expression")} + help=${msg(`When checked, the placeholder will be evaluated in the same way a property mapping is. + If the evaluation fails, the placeholder itself is returned.`)} + > { )}

- - -

- ${msg( - `When checked, the initial value will be evaluated in the same way a property mapping is. - If the evaluation fails, the initial value itself is returned.`, - )} -

-
+ { + this._shouldRefresh = true; + }} + label=${msg("Interpret initial value as expression")} + help=${msg(`When checked, the initial value will be evaluated in the same way a property mapping is. + If the evaluation fails, the initial value itself is returned.`)} + > diff --git a/web/src/components/ak-switch-input.ts b/web/src/components/ak-switch-input.ts index 8248f51742..5f5e5e506c 100644 --- a/web/src/components/ak-switch-input.ts +++ b/web/src/components/ak-switch-input.ts @@ -4,7 +4,7 @@ import { AKElement } from "#elements/Base"; import { IDGenerator } from "@goauthentik/core/id"; -import { html, nothing } from "lit"; +import { html, nothing, TemplateResult } from "lit"; import { customElement, property, query } from "lit/decorators.js"; @customElement("ak-switch-input") @@ -35,14 +35,30 @@ export class AkSwitchInput extends AKElement { @property({ type: String }) help = ""; + /** + * For more complex help instructions, provide a template result. + */ + @property({ type: Object }) + public bighelp!: TemplateResult | TemplateResult[]; + @query("input.pf-c-switch__input[type=checkbox]") checkbox!: HTMLInputElement; #fieldID: string = IDGenerator.randomID(); + protected renderHelp() { + const helpText = this.help.trim(); + + return [ + helpText + ? html`

${helpText}

` + : nothing, + this.bighelp ? this.bighelp : nothing, + ]; + } + render() { const doCheck = this.checked ? this.checked : undefined; - const helpText = this.help.trim(); return html`
@@ -62,9 +78,7 @@ export class AkSwitchInput extends AKElement { ${this.label} - ${helpText - ? html`

${helpText}

` - : nothing} + ${this.renderHelp()}
`; } } diff --git a/web/src/elements/sync/SyncObjectForm.ts b/web/src/elements/sync/SyncObjectForm.ts index 7bf043b1ea..76ead793f6 100644 --- a/web/src/elements/sync/SyncObjectForm.ts +++ b/web/src/elements/sync/SyncObjectForm.ts @@ -2,6 +2,7 @@ import "#elements/events/LogViewer"; import "#admin/common/ak-flow-search/ak-flow-search-no-default"; import "#elements/forms/HorizontalFormElement"; import "#elements/forms/SearchSelect/index"; +import "#components/ak-switch-input"; import { DEFAULT_CONFIG } from "#common/api/config"; @@ -127,22 +128,13 @@ export class SyncObjectForm extends Form { ${this.model === SyncObjectModelEnum.AuthentikCoreModelsGroup ? this.renderSelectGroup() : nothing} - - -

- ${msg( - "When enabled, this sync will still execute mutating requests regardless of the dry-run mode in the provider.", - )} -

-
+ ${this.result ? this.renderResult() : nothing}`; } }