mirror of https://github.com/zulip/zulip.git
password: Add password limit indicator to form.
Adds a password limit indicator to the password field in both the registration form and the password reset form. This indicator displays the remaining number of characters allowed, helping users comply with the maximum password length requirement. Fixes: #27922.
This commit is contained in:
parent
e0bd3713cc
commit
f28ec726f6
|
@ -143,12 +143,14 @@ Form is validated both client-side using jquery-validation (see signup.js) and s
|
|||
</div>
|
||||
{% elif password_required %}
|
||||
<div class="input-box password-div">
|
||||
<div class="password-label-container">
|
||||
<span><label for="id_password">{{ _('Password') }}</label></span>
|
||||
<span id="password-limit-indicator" class="limit-indicator" data-tippy-content="{{ _('Maximum password length: 100 characters') }}" data-tippy-placement="top"></span>
|
||||
</div>
|
||||
<input id="id_password" class="required" type="password" name="password" autocomplete="new-password"
|
||||
value="{% if form.password.value() %}{{ form.password.value() }}{% endif %}"
|
||||
maxlength="{{ MAX_PASSWORD_LENGTH }}"
|
||||
data-min-length="{{password_min_length}}"
|
||||
data-min-guesses="{{password_min_guesses}}" required />
|
||||
<label for="id_password" class="inline-block">{{ _('Password') }}</label>
|
||||
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
|
||||
{% if full_name %}
|
||||
<span class="help-inline">
|
||||
|
@ -252,7 +254,7 @@ Form is validated both client-side using jquery-validation (see signup.js) and s
|
|||
</div>
|
||||
{% endif %}
|
||||
<div class="register-button-box">
|
||||
<button class="register-button" type="submit">
|
||||
<button class="register-button" id="signup-button" type="submit">
|
||||
<span>{{ _('Sign up') }}</span>
|
||||
<object class="loader" type="image/svg+xml" data="{{ static('images/loading/loader-white.svg') }}"></object>
|
||||
</button>
|
||||
|
|
|
@ -28,10 +28,12 @@
|
|||
</div>
|
||||
|
||||
<div class="input-box password-div">
|
||||
<label for="id_new_password1" class="">{{ _('Password') }}</label>
|
||||
<div class="password-label-container">
|
||||
<span><label for="id_new_password1" class="">{{ _('Password') }}</label></span>
|
||||
<span id="reset-password-limit-indicator" class="limit-indicator" data-tippy-content="{{ _('Maximum password length: 100 characters') }}" data-tippy-placement="top"></span>
|
||||
</div>
|
||||
<input id="id_new_password1" class="required" type="password" name="new_password1" autocomplete="new-password"
|
||||
value="{% if form.new_password1.value() %}{{ form.new_password1.value() }}{% endif %}"
|
||||
maxlength="100"
|
||||
data-min-length="{{password_min_length}}"
|
||||
data-min-guesses="{{password_min_guesses}}" autofocus required />
|
||||
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
|
||||
|
@ -52,7 +54,7 @@
|
|||
<label for="id_new_password2" class="">{{ _('Confirm password') }}</label>
|
||||
<input id="id_new_password2" class="required" type="password" name="new_password2" autocomplete="off"
|
||||
value="{% if form.new_password2.value() %}{{ form.new_password2.value() }}{% endif %}"
|
||||
maxlength="100" required />
|
||||
required />
|
||||
<i class="fa fa-eye-slash password_visibility_toggle" role="button" tabindex="0"></i>
|
||||
{% if form.new_password2.errors %}
|
||||
{% for error in form.new_password2.errors %}
|
||||
|
@ -63,7 +65,7 @@
|
|||
|
||||
<div class="input-box m-t-30">
|
||||
<div class="centered-button">
|
||||
<button type="submit" class="" value="Submit">Submit</button>
|
||||
<button type="submit" id="reset-button" class="" value="Submit">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -6,3 +6,4 @@ import "../portico/tippyjs.ts";
|
|||
import "../../third/bootstrap/css/bootstrap.portico.css";
|
||||
import "../../styles/portico/portico_styles.css";
|
||||
import "tippy.js/dist/tippy.css";
|
||||
import "../../styles/app_variables.css";
|
||||
|
|
|
@ -2,6 +2,7 @@ import $ from "jquery";
|
|||
import assert from "minimalistic-assert";
|
||||
import {z} from "zod";
|
||||
|
||||
import render_compose_limit_indicator from "../../templates/compose_limit_indicator.hbs";
|
||||
import * as common from "../common.ts";
|
||||
import {$t} from "../i18n.ts";
|
||||
import {password_quality, password_warning} from "../password_quality.ts";
|
||||
|
@ -342,3 +343,49 @@ $(() => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
const $password_elem: JQuery<HTMLInputElement> = $("input#id_password");
|
||||
const $new_password1_elem: JQuery<HTMLInputElement> = $("input#id_new_password1");
|
||||
|
||||
if ($password_elem.length) {
|
||||
$password_elem.on("input", () => {
|
||||
check_overflow_password($password_elem);
|
||||
});
|
||||
}
|
||||
|
||||
if ($new_password1_elem.length) {
|
||||
$new_password1_elem.on("input", () => {
|
||||
check_overflow_password($new_password1_elem);
|
||||
});
|
||||
}
|
||||
|
||||
export function check_overflow_password($password_elem: JQuery<HTMLInputElement>): void {
|
||||
const password = $password_elem.val() ?? "";
|
||||
const max_length = 100;
|
||||
const remaining_characters = max_length - password.length;
|
||||
|
||||
const $indicator = $password_elem.closest(".input-box").find(".limit-indicator");
|
||||
const $button = $password_elem.closest("form").find("button[type='submit']");
|
||||
|
||||
const password_too_long = password.length > max_length;
|
||||
$button.prop("disabled", password_too_long);
|
||||
|
||||
// Update the limit indicator
|
||||
if (password_too_long) {
|
||||
$indicator.addClass("over_limit");
|
||||
$indicator.html(
|
||||
render_compose_limit_indicator({
|
||||
remaining_characters,
|
||||
}),
|
||||
);
|
||||
} else if (remaining_characters <= 20) {
|
||||
$indicator.removeClass("over_limit");
|
||||
$indicator.html(
|
||||
render_compose_limit_indicator({
|
||||
remaining_characters,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
$indicator.text("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1461,3 +1461,34 @@ button#register_auth_button_gitlab {
|
|||
margin-top: 5px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#signup-button,
|
||||
#reset-button {
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
#reset-password-limit-indicator,
|
||||
#password-limit-indicator {
|
||||
&:not(:empty) {
|
||||
font-size: 16px;
|
||||
color: var(--color-limit-indicator);
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
margin-right: 5px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&.over_limit {
|
||||
color: var(--color-limit-indicator-over-limit);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.password-label-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue