web: password quality indicators
Resolves issue 5165 This commit updates the password match indicator so that the user, and not the component, makes decisions about the names of the initial and confirmation inputs.
This commit is contained in:
parent
1c85dc512f
commit
0d94373f10
|
@ -9,6 +9,11 @@ export default {
|
||||||
export const Primary = () =>
|
export const Primary = () =>
|
||||||
html`<div style="background: #fff; padding: 4em">
|
html`<div style="background: #fff; padding: 4em">
|
||||||
<p>Type some text: <input id="primary-example" style="color:#000" /></p>
|
<p>Type some text: <input id="primary-example" style="color:#000" /></p>
|
||||||
<p>Type some other text: <input id="primary-example_repeat" style="color:#000" /></p>
|
<p style="margin-top:0.5em">
|
||||||
<ak-password-match-indicator src="#primary-example_repeat"></ak-password-match-indicator>
|
Type some other text: <input id="primary-example_repeat" style="color:#000" />
|
||||||
|
<ak-password-match-indicator
|
||||||
|
first="#primary-example"
|
||||||
|
second="#primary-example_repeat"
|
||||||
|
></ak-password-match-indicator>
|
||||||
|
</p>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
|
@ -31,10 +31,14 @@ export class PasswordMatchIndicator extends AKElement {
|
||||||
* throw an exception.
|
* throw an exception.
|
||||||
*/
|
*/
|
||||||
@property({ attribute: true })
|
@property({ attribute: true })
|
||||||
src = "";
|
first = "";
|
||||||
|
|
||||||
sourceInput?: HTMLInputElement;
|
@property({ attribute: true })
|
||||||
otherInput?: HTMLInputElement;
|
second = "";
|
||||||
|
|
||||||
|
firstElement?: HTMLInputElement;
|
||||||
|
|
||||||
|
secondElement?: HTMLInputElement;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
match = false;
|
match = false;
|
||||||
|
@ -46,38 +50,38 @@ export class PasswordMatchIndicator extends AKElement {
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this.input.addEventListener("keyup", this.checkPasswordMatch);
|
this.firstInput.addEventListener("keyup", this.checkPasswordMatch);
|
||||||
this.other.addEventListener("keyup", this.checkPasswordMatch);
|
this.secondInput.addEventListener("keyup", this.checkPasswordMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
this.other.removeEventListener("keyup", this.checkPasswordMatch);
|
this.secondInput.removeEventListener("keyup", this.checkPasswordMatch);
|
||||||
this.input.removeEventListener("keyup", this.checkPasswordMatch);
|
this.firstInput.removeEventListener("keyup", this.checkPasswordMatch);
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPasswordMatch() {
|
checkPasswordMatch() {
|
||||||
this.match =
|
this.match =
|
||||||
this.input.value.length > 0 &&
|
this.firstInput.value.length > 0 &&
|
||||||
this.other.value.length > 0 &&
|
this.secondInput.value.length > 0 &&
|
||||||
this.input.value === this.other.value;
|
this.firstInput.value === this.secondInput.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get input() {
|
get firstInput() {
|
||||||
if (this.sourceInput) {
|
if (this.firstElement) {
|
||||||
return this.sourceInput;
|
return this.firstElement;
|
||||||
}
|
}
|
||||||
return (this.sourceInput = findInput(this.getRootNode() as Element, ELEMENT, this.src));
|
return (this.firstElement = findInput(this.getRootNode() as Element, ELEMENT, this.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
get other() {
|
get secondInput() {
|
||||||
if (this.otherInput) {
|
if (this.secondElement) {
|
||||||
return this.otherInput;
|
return this.secondElement;
|
||||||
}
|
}
|
||||||
return (this.otherInput = findInput(
|
return (this.secondElement = findInput(
|
||||||
this.getRootNode() as Element,
|
this.getRootNode() as Element,
|
||||||
ELEMENT,
|
ELEMENT,
|
||||||
this.src.replace(/_repeat/, ""),
|
this.second,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { rootInterface } from "@goauthentik/elements/Base";
|
|
||||||
import { LOCALES } from "@goauthentik/common/ui/locale";
|
import { LOCALES } from "@goauthentik/common/ui/locale";
|
||||||
|
import { rootInterface } from "@goauthentik/elements/Base";
|
||||||
import "@goauthentik/elements/password-match-indicator";
|
import "@goauthentik/elements/password-match-indicator";
|
||||||
import "@goauthentik/elements/password-strength-indicator";
|
import "@goauthentik/elements/password-strength-indicator";
|
||||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
||||||
import { TemplateResult, html } from "lit";
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { StagePrompt, CapabilitiesEnum, PromptTypeEnum } from "@goauthentik/api";
|
import { TemplateResult, html } from "lit";
|
||||||
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||||
|
|
||||||
|
import { CapabilitiesEnum, PromptTypeEnum, StagePrompt } from "@goauthentik/api";
|
||||||
|
|
||||||
export function password(prompt: StagePrompt) {
|
export function password(prompt: StagePrompt) {
|
||||||
return html`<input
|
return html`<input
|
||||||
|
@ -20,7 +22,12 @@ export function password(prompt: StagePrompt) {
|
||||||
></ak-password-strength-indicator>`;
|
></ak-password-strength-indicator>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const REPEAT = /_repeat/;
|
||||||
|
|
||||||
export function repeatPassword(prompt: StagePrompt) {
|
export function repeatPassword(prompt: StagePrompt) {
|
||||||
|
const first = `input[name="${prompt.fieldKey}"]`;
|
||||||
|
const second = `input[name="${prompt.fieldKey.replace(REPEAT, "")}"]`;
|
||||||
|
|
||||||
return html` <div style="display:flex; flex-direction:row; gap: 0.5em; align-content: center">
|
return html` <div style="display:flex; flex-direction:row; gap: 0.5em; align-content: center">
|
||||||
<input
|
<input
|
||||||
style="flex:1 0"
|
style="flex:1 0"
|
||||||
|
@ -31,13 +38,14 @@ export function repeatPassword(prompt: StagePrompt) {
|
||||||
class="pf-c-form-control"
|
class="pf-c-form-control"
|
||||||
?required=${prompt.required}
|
?required=${prompt.required}
|
||||||
/><ak-password-match-indicator
|
/><ak-password-match-indicator
|
||||||
src='input[name="${prompt.fieldKey}"]'
|
first="${first}"
|
||||||
|
second="${second}"
|
||||||
></ak-password-match-indicator>
|
></ak-password-match-indicator>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderPassword(prompt: StagePrompt) {
|
export function renderPassword(prompt: StagePrompt) {
|
||||||
return /_repeat$/.test(prompt.fieldKey) ? repeatPassword(prompt) : password(prompt);
|
return REPEAT.test(prompt.fieldKey) ? repeatPassword(prompt) : password(prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderText(prompt: StagePrompt) {
|
export function renderText(prompt: StagePrompt) {
|
||||||
|
@ -209,7 +217,7 @@ export function renderAkLocale(prompt: StagePrompt) {
|
||||||
?selected=${locale.code === prompt.initialValue}
|
?selected=${locale.code === prompt.initialValue}
|
||||||
>
|
>
|
||||||
${locale.code.toUpperCase()} - ${locale.label()}
|
${locale.code.toUpperCase()} - ${locale.label()}
|
||||||
</option> `
|
</option> `,
|
||||||
);
|
);
|
||||||
|
|
||||||
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
||||||
|
|
Reference in a new issue