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 = () =>
|
||||
html`<div style="background: #fff; padding: 4em">
|
||||
<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>
|
||||
<ak-password-match-indicator src="#primary-example_repeat"></ak-password-match-indicator>
|
||||
<p style="margin-top:0.5em">
|
||||
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>`;
|
||||
|
|
|
@ -31,10 +31,14 @@ export class PasswordMatchIndicator extends AKElement {
|
|||
* throw an exception.
|
||||
*/
|
||||
@property({ attribute: true })
|
||||
src = "";
|
||||
first = "";
|
||||
|
||||
sourceInput?: HTMLInputElement;
|
||||
otherInput?: HTMLInputElement;
|
||||
@property({ attribute: true })
|
||||
second = "";
|
||||
|
||||
firstElement?: HTMLInputElement;
|
||||
|
||||
secondElement?: HTMLInputElement;
|
||||
|
||||
@state()
|
||||
match = false;
|
||||
|
@ -46,38 +50,38 @@ export class PasswordMatchIndicator extends AKElement {
|
|||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.input.addEventListener("keyup", this.checkPasswordMatch);
|
||||
this.other.addEventListener("keyup", this.checkPasswordMatch);
|
||||
this.firstInput.addEventListener("keyup", this.checkPasswordMatch);
|
||||
this.secondInput.addEventListener("keyup", this.checkPasswordMatch);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.other.removeEventListener("keyup", this.checkPasswordMatch);
|
||||
this.input.removeEventListener("keyup", this.checkPasswordMatch);
|
||||
this.secondInput.removeEventListener("keyup", this.checkPasswordMatch);
|
||||
this.firstInput.removeEventListener("keyup", this.checkPasswordMatch);
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
checkPasswordMatch() {
|
||||
this.match =
|
||||
this.input.value.length > 0 &&
|
||||
this.other.value.length > 0 &&
|
||||
this.input.value === this.other.value;
|
||||
this.firstInput.value.length > 0 &&
|
||||
this.secondInput.value.length > 0 &&
|
||||
this.firstInput.value === this.secondInput.value;
|
||||
}
|
||||
|
||||
get input() {
|
||||
if (this.sourceInput) {
|
||||
return this.sourceInput;
|
||||
get firstInput() {
|
||||
if (this.firstElement) {
|
||||
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() {
|
||||
if (this.otherInput) {
|
||||
return this.otherInput;
|
||||
get secondInput() {
|
||||
if (this.secondElement) {
|
||||
return this.secondElement;
|
||||
}
|
||||
return (this.otherInput = findInput(
|
||||
return (this.secondElement = findInput(
|
||||
this.getRootNode() as 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 { rootInterface } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/password-match-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 { 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) {
|
||||
return html`<input
|
||||
|
@ -20,7 +22,12 @@ export function password(prompt: StagePrompt) {
|
|||
></ak-password-strength-indicator>`;
|
||||
}
|
||||
|
||||
const REPEAT = /_repeat/;
|
||||
|
||||
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">
|
||||
<input
|
||||
style="flex:1 0"
|
||||
|
@ -31,13 +38,14 @@ export function repeatPassword(prompt: StagePrompt) {
|
|||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
/><ak-password-match-indicator
|
||||
src='input[name="${prompt.fieldKey}"]'
|
||||
first="${first}"
|
||||
second="${second}"
|
||||
></ak-password-match-indicator>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -209,7 +217,7 @@ export function renderAkLocale(prompt: StagePrompt) {
|
|||
?selected=${locale.code === prompt.initialValue}
|
||||
>
|
||||
${locale.code.toUpperCase()} - ${locale.label()}
|
||||
</option> `
|
||||
</option> `,
|
||||
);
|
||||
|
||||
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
||||
|
|
Reference in a new issue