mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-24 12:51:10 -05:00
Add secret management guide, client-side performance monitoring, and search accessibility enhancements
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols. - Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage. - Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
This commit is contained in:
@@ -2,8 +2,10 @@
|
||||
{% load account socialaccount %}
|
||||
{% load turnstile_tags %}
|
||||
|
||||
<form
|
||||
class="space-y-6"
|
||||
<form
|
||||
class="space-y-6"
|
||||
role="form"
|
||||
aria-label="{% trans 'Sign in to your account' %}"
|
||||
hx-post="{% url 'account_login' %}"
|
||||
hx-target="this"
|
||||
hx-swap="outerHTML"
|
||||
@@ -11,44 +13,18 @@
|
||||
>
|
||||
{% csrf_token %}
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-error">
|
||||
<div class="alert alert-error" role="alert">
|
||||
<div class="text-sm">{{ form.non_field_errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<label for="id_login" class="form-label">
|
||||
{% trans "Username or Email" %}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="login"
|
||||
id="id_login"
|
||||
required
|
||||
autocomplete="username email"
|
||||
class="form-input"
|
||||
/>
|
||||
{% if form.login.errors %}
|
||||
<p class="form-error">{{ form.login.errors }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<fieldset class="space-y-6">
|
||||
<legend class="sr-only">{% trans "Login credentials" %}</legend>
|
||||
|
||||
<div>
|
||||
<label for="id_password" class="form-label">
|
||||
{% trans "Password" %}
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
id="id_password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
class="form-input"
|
||||
/>
|
||||
{% if form.password.errors %}
|
||||
<p class="form-error">{{ form.password.errors }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include 'forms/partials/form_field.html' with field=form.login label=_("Username or Email") %}
|
||||
|
||||
{% include 'forms/partials/form_field.html' with field=form.password label=_("Password") %}
|
||||
</fieldset>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
@@ -87,7 +63,7 @@
|
||||
|
||||
<div>
|
||||
<button type="submit" class="w-full btn-primary">
|
||||
<i class="mr-2 fas fa-sign-in-alt"></i>
|
||||
<i class="mr-2 fas fa-sign-in-alt" aria-hidden="true"></i>
|
||||
{% trans "Sign In" %}
|
||||
</button>
|
||||
</div>
|
||||
@@ -96,6 +72,6 @@
|
||||
<!-- Loading indicator -->
|
||||
<div id="login-indicator" class="htmx-indicator">
|
||||
<div class="flex items-center justify-center w-full py-4">
|
||||
<div class="w-8 h-8 border-4 rounded-full border-primary border-t-transparent animate-spin"></div>
|
||||
<div class="w-8 h-8 border-4 rounded-full border-primary border-t-transparent animate-spin" role="status" aria-label="Loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,14 +26,16 @@
|
||||
{% if provider.id == 'google' %}
|
||||
<img
|
||||
src="{% static 'images/google-icon.svg' %}"
|
||||
alt="Google"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="w-5 h-5 mr-3"
|
||||
/>
|
||||
<span>Continue with Google</span>
|
||||
{% elif provider.id == 'discord' %}
|
||||
<img
|
||||
src="{% static 'images/discord-icon.svg' %}"
|
||||
alt="Discord"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="w-5 h-5 mr-3"
|
||||
/>
|
||||
<span>Continue with Discord</span>
|
||||
@@ -47,101 +49,51 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form class="space-y-6" method="POST" action="{% url 'account_signup' %}">
|
||||
<form class="space-y-6" method="POST" action="{% url 'account_signup' %}" role="form" aria-label="{% trans 'Create a new account' %}">
|
||||
{% csrf_token %}
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-error">
|
||||
<div class="alert alert-error" role="alert">
|
||||
<div class="text-sm">{{ form.non_field_errors }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<label for="id_username" class="form-label">
|
||||
{% trans "Username" %}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="username"
|
||||
id="id_username"
|
||||
required
|
||||
autocomplete="username"
|
||||
class="form-input"
|
||||
/>
|
||||
{% if form.username.errors %}
|
||||
<p class="form-error">{{ form.username.errors }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<fieldset class="space-y-6">
|
||||
<legend class="sr-only">{% trans "Account information" %}</legend>
|
||||
|
||||
<div>
|
||||
<label for="id_email" class="form-label">{% trans "Email" %}</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="id_email"
|
||||
required
|
||||
autocomplete="email"
|
||||
class="form-input"
|
||||
/>
|
||||
{% if form.email.errors %}
|
||||
<p class="form-error">{{ form.email.errors }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include 'forms/partials/form_field.html' with field=form.username label=_("Username") %}
|
||||
|
||||
<div>
|
||||
<label for="id_password1" class="form-label">
|
||||
{% trans "Password" %}
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="password1"
|
||||
id="id_password1"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
class="form-input"
|
||||
oninput="validatePassword(this.value)"
|
||||
/>
|
||||
{% if form.password1.errors %}
|
||||
<p class="form-error">{{ form.password1.errors }}</p>
|
||||
{% endif %}
|
||||
<div class="mt-3 password-requirements">
|
||||
<ul id="passwordRequirements">
|
||||
<li class="invalid" id="req-length">
|
||||
<i class="text-xs fas fa-circle"></i>
|
||||
<span>Must be at least 8 characters long</span>
|
||||
</li>
|
||||
<li class="invalid" id="req-similar">
|
||||
<i class="text-xs fas fa-circle"></i>
|
||||
<span>Can't be too similar to your personal information</span>
|
||||
</li>
|
||||
<li class="invalid" id="req-common">
|
||||
<i class="text-xs fas fa-circle"></i>
|
||||
<span>Can't be a commonly used password</span>
|
||||
</li>
|
||||
<li class="invalid" id="req-numeric">
|
||||
<i class="text-xs fas fa-circle"></i>
|
||||
<span>Can't be entirely numeric</span>
|
||||
</li>
|
||||
</ul>
|
||||
{% include 'forms/partials/form_field.html' with field=form.email label=_("Email") %}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="space-y-6">
|
||||
<legend class="sr-only">{% trans "Password" %}</legend>
|
||||
|
||||
<div>
|
||||
{% include 'forms/partials/form_field.html' with field=form.password1 label=_("Password") show_help=False %}
|
||||
<div class="mt-3 password-requirements" aria-live="polite">
|
||||
<ul id="passwordRequirements" role="list" aria-label="{% trans 'Password requirements' %}">
|
||||
<li class="invalid" id="req-length">
|
||||
<i class="text-xs fas fa-circle" aria-hidden="true"></i>
|
||||
<span>Must be at least 8 characters long</span>
|
||||
</li>
|
||||
<li class="invalid" id="req-similar">
|
||||
<i class="text-xs fas fa-circle" aria-hidden="true"></i>
|
||||
<span>Can't be too similar to your personal information</span>
|
||||
</li>
|
||||
<li class="invalid" id="req-common">
|
||||
<i class="text-xs fas fa-circle" aria-hidden="true"></i>
|
||||
<span>Can't be a commonly used password</span>
|
||||
</li>
|
||||
<li class="invalid" id="req-numeric">
|
||||
<i class="text-xs fas fa-circle" aria-hidden="true"></i>
|
||||
<span>Can't be entirely numeric</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="id_password2" class="form-label">
|
||||
{% trans "Confirm Password" %}
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="password2"
|
||||
id="id_password2"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
class="form-input"
|
||||
oninput="validatePasswordMatch()"
|
||||
/>
|
||||
{% if form.password2.errors %}
|
||||
<p class="form-error">{{ form.password2.errors }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include 'forms/partials/form_field.html' with field=form.password2 label=_("Confirm Password") %}
|
||||
</fieldset>
|
||||
|
||||
{% turnstile_widget %}
|
||||
{% if redirect_field_value %}
|
||||
@@ -154,7 +106,7 @@
|
||||
|
||||
<div>
|
||||
<button type="submit" class="w-full btn-primary">
|
||||
<i class="mr-2 fas fa-user-plus"></i>
|
||||
<i class="mr-2 fas fa-user-plus" aria-hidden="true"></i>
|
||||
{% trans "Create Account" %}
|
||||
</button>
|
||||
</div>
|
||||
@@ -239,5 +191,21 @@
|
||||
password2Input.classList.remove("border-green-500", "border-red-500");
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners after DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const password1Input = document.getElementById('id_password1');
|
||||
const password2Input = document.getElementById('id_password2');
|
||||
|
||||
if (password1Input) {
|
||||
password1Input.addEventListener('input', function() {
|
||||
validatePassword(this.value);
|
||||
});
|
||||
}
|
||||
|
||||
if (password2Input) {
|
||||
password2Input.addEventListener('input', validatePasswordMatch);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user