Style the change password module
Add a template override for Contao's changePassword module with the same card, explanatory copy and corporate design as the lost password module. The card rules keyed off .mod_lostPassword.block, which does not scale to a third auth module. Move them to a .survey-auth-module class that the overrides put on the wrapper themselves, so another auth module needs one line and no new CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+22
-1
@@ -467,7 +467,14 @@ Wichtige Settings:
|
||||
### Gestaltung
|
||||
|
||||
- Alle Auth-Styles liegen zentral in `public/css/auth-module.css`, global eingebunden über `contao/config/config.php` (`$GLOBALS['TL_CSS']`).
|
||||
- Das Passwort-vergessen-Modul (`.mod_lostPassword.block`) verwendet bewusst dieselbe zentrierte Karte wie das Login-Modul: gleiche Breite, Radien, Farbverläufe, Schriften und Button-Optik.
|
||||
- Das Kartenlayout hängt **nicht** an einzelnen Contao-Modultypen, sondern an der Klasse `.survey-auth-module`. Die Template-Overrides setzen sie selbst auf den Modul-Wrapper:
|
||||
|
||||
```twig
|
||||
{% set wrapperAttributes = attrs().addClass('survey-auth-module') %}
|
||||
```
|
||||
|
||||
`block_searchable.html.twig` merged das in die Wrapper-Attribute. Ein weiteres Auth-Modul braucht damit nur diese eine Zeile und keine neuen CSS-Regeln. Aktuell nutzen sie `mod_lostPassword`, `mod_changePassword` und die Meldungsansichten über `mod_message`.
|
||||
- Passwort vergessen und Passwort ändern verwenden bewusst dieselbe zentrierte Karte wie das Login-Modul: gleiche Breite, Radien, Farbverläufe, Schriften und Button-Optik.
|
||||
- Der Link `Passwort vergessen?` im Login ist rechtsbündig und im Corporate Design (Blau, Hover Orange, Chevron `›`). Auf Mobil wird er zentriert.
|
||||
- Fehler- und Bestätigungsmeldungen (auch das Contao-Template `mod_message`, das der Kern bei ungültigem/abgelaufenem Token einsetzt) werden als farbige Hinweisboxen dargestellt.
|
||||
|
||||
@@ -481,6 +488,19 @@ Wichtige Settings:
|
||||
- mit Token: Texte aus `survey.auth.set_password.*`
|
||||
- Die Texte liegen in `translations/messages.de.yaml` bzw. `messages.en.yaml` unter `survey.auth`, sind also nicht im Template hartkodiert.
|
||||
|
||||
### Passwort-Änderung erzwingen
|
||||
|
||||
Die Erweiterung `terminal42/contao-password-validation` bringt das Feld `tl_member.pwChange` und die Startseiten-Einstellung `tl_page.pwChangePage` mit. Ist `pwChange` gesetzt, leitet sie das Mitglied nach dem Login auf die dort hinterlegte Seite.
|
||||
|
||||
Aufbau in dieser Installation:
|
||||
|
||||
- Startseite (tl_page ID 1) → `pwChangePage` = Seite `Passwort ändern` (ID 10, Alias `passwort-aendern`)
|
||||
- Dort liegt das Contao-Kernmodul `changePassword` (tl_module ID 11)
|
||||
- Dessen Weiterleitungsseite (`jumpTo`) ist `Passwort wurde geändert` (ID 11, Alias `passwort-wurde-geaendert`)
|
||||
|
||||
- Template-Override: `contao/templates/frontend/mod_changePassword.html.twig`, gleicher Aufbau wie das Passwort-vergessen-Modul. Texte unter `survey.auth.change_password.*`.
|
||||
- Der Bestätigungstext auf Seite 11 liegt als normales Contao-Textelement mit der Klasse `survey-auth-note` und ist damit redaktionell pflegbar. Der Button führt bewusst **zur Umfragenliste** und nicht zur Anmeldung, weil das Mitglied an dieser Stelle bereits eingeloggt ist.
|
||||
|
||||
### E-Mail-Versand
|
||||
|
||||
- Der Versand läuft über einen benannten Mailer-Transport `ksb`, konfiguriert in der Projektinstallation (`config/config.yaml`), nicht im Bundle:
|
||||
@@ -583,6 +603,7 @@ Mitglieder-Login / Passwort vergessen:
|
||||
|
||||
- `public/css/auth-module.css`
|
||||
- `contao/templates/frontend/mod_lostPassword.html.twig`
|
||||
- `contao/templates/frontend/mod_changePassword.html.twig`
|
||||
- `contao/templates/frontend/mod_message.html.twig`
|
||||
- `src/EventListener/CorporateMailListener.php`
|
||||
- `src/Resources/views/email/corporate.html.twig`
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{% extends '@Contao/block_unsearchable.html.twig' %}
|
||||
{% trans_default_domain 'messages' %}
|
||||
|
||||
{# Der Modul-Wrapper bekommt die gemeinsame Auth-Klasse, an der das Kartenlayout haengt. #}
|
||||
{% set wrapperAttributes = attrs().addClass('survey-auth-module') %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="survey-auth-card">
|
||||
|
||||
<div class="survey-auth-intro">
|
||||
<h2 class="survey-auth-intro-headline">{{ 'survey.auth.change_password.headline'|trans }}</h2>
|
||||
<p class="survey-auth-intro-text">{{ 'survey.auth.change_password.intro'|trans }}</p>
|
||||
<p class="survey-auth-hint">{{ 'survey.auth.change_password.hint'|trans }}</p>
|
||||
</div>
|
||||
|
||||
{% if message|default %}
|
||||
<p class="confirm message">{{ message }}</p>
|
||||
{% endif %}
|
||||
|
||||
<form id="{{ formId }}" method="post">
|
||||
<div class="formbody">
|
||||
<input type="hidden" name="FORM_SUBMIT" value="{{ formId }}">
|
||||
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
|
||||
{{ fields|raw }}
|
||||
<div class="widget widget-submit">
|
||||
<button type="submit" class="submit">{{ slabel }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,6 +1,9 @@
|
||||
{% extends '@Contao/block_unsearchable.html.twig' %}
|
||||
{% trans_default_domain 'messages' %}
|
||||
|
||||
{# Der Modul-Wrapper bekommt die gemeinsame Auth-Klasse, an der das Kartenlayout haengt. #}
|
||||
{% set wrapperAttributes = attrs().addClass('survey-auth-module') %}
|
||||
|
||||
{# Schritt 2: Der Nutzer kommt ueber den Link aus der E-Mail und vergibt ein neues Passwort. #}
|
||||
{% set surveyAuthScope = (app.request.query.get('token')|default('')) starts with 'pw-' ? 'set_password' : 'lost_password' %}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
Sackgasse landet.
|
||||
#}
|
||||
{% set surveyIsAuthMessage = 'mod_lostPassword' in (class|default('')) %}
|
||||
{% if surveyIsAuthMessage %}
|
||||
{% set wrapperAttributes = attrs().addClass('survey-auth-module') %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
+56
-52
@@ -268,11 +268,15 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
Passwort-vergessen-Modul (Contao "lostPassword")
|
||||
Gleiches Kartenlayout wie das Login-Modul, mittig zentriert.
|
||||
Auth-Module im gleichen Kartenlayout wie das Login-Modul.
|
||||
|
||||
Die Klasse .survey-auth-module setzen die Template-Overrides selbst auf den
|
||||
Modul-Wrapper (Contao "lostPassword", "changePassword" und die Meldungs-
|
||||
ansichten via mod_message). So haengen die Kartenregeln nicht an einzelnen
|
||||
Contao-Modultypen und ein weiteres Auth-Modul braucht nur die Klasse.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
.mod_lostPassword.block {
|
||||
.survey-auth-module {
|
||||
max-width: min(100%, 36rem);
|
||||
margin: clamp(1.5rem, 4vw, 3rem) auto;
|
||||
padding: clamp(1.5rem, 2.6vw, 2.4rem);
|
||||
@@ -288,19 +292,19 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
color: var(--survey-auth-ink);
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-card {
|
||||
.survey-auth-module .survey-auth-card {
|
||||
display: grid;
|
||||
gap: 1.35rem;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-intro {
|
||||
.survey-auth-module .survey-auth-intro {
|
||||
display: grid;
|
||||
gap: 0.55rem;
|
||||
padding-bottom: 1.1rem;
|
||||
border-bottom: 1px solid rgba(162, 168, 180, 0.28);
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-intro-headline {
|
||||
.survey-auth-module .survey-auth-intro-headline {
|
||||
margin: 0;
|
||||
font-family: "Blogger Sans", sans-serif;
|
||||
font-size: clamp(1.35rem, 2.4vw, 1.7rem);
|
||||
@@ -309,14 +313,14 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
color: var(--survey-auth-blue);
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-intro-text {
|
||||
.survey-auth-module .survey-auth-intro-text {
|
||||
margin: 0;
|
||||
font-size: 1.02rem;
|
||||
line-height: 1.5;
|
||||
color: var(--survey-auth-ink);
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-hint {
|
||||
.survey-auth-module .survey-auth-hint {
|
||||
margin: 0;
|
||||
padding-left: 0.85rem;
|
||||
border-left: 3px solid var(--survey-auth-green);
|
||||
@@ -325,23 +329,23 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
color: var(--survey-auth-muted);
|
||||
}
|
||||
|
||||
.mod_lostPassword.block form,
|
||||
.mod_lostPassword.block .formbody {
|
||||
.survey-auth-module form,
|
||||
.survey-auth-module .formbody {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .formbody {
|
||||
.survey-auth-module .formbody {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .widget {
|
||||
.survey-auth-module .widget {
|
||||
display: grid;
|
||||
gap: 0.45rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block label {
|
||||
.survey-auth-module label {
|
||||
font-family: "Blogger Sans", sans-serif;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
@@ -349,12 +353,12 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block label .mandatory {
|
||||
.survey-auth-module label .mandatory {
|
||||
margin-left: 0.15rem;
|
||||
color: var(--survey-auth-orange);
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .invisible {
|
||||
.survey-auth-module .invisible {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
@@ -367,12 +371,12 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block input.text,
|
||||
.mod_lostPassword.block input.password,
|
||||
.mod_lostPassword.block input.captcha,
|
||||
.mod_lostPassword.block input[type="text"],
|
||||
.mod_lostPassword.block input[type="email"],
|
||||
.mod_lostPassword.block input[type="password"] {
|
||||
.survey-auth-module input.text,
|
||||
.survey-auth-module input.password,
|
||||
.survey-auth-module input.captcha,
|
||||
.survey-auth-module input[type="text"],
|
||||
.survey-auth-module input[type="email"],
|
||||
.survey-auth-module input[type="password"] {
|
||||
width: 100%;
|
||||
min-height: 3.2rem;
|
||||
padding: 0.8rem 0.95rem;
|
||||
@@ -386,12 +390,12 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
transition: border-color 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block input.text:focus,
|
||||
.mod_lostPassword.block input.password:focus,
|
||||
.mod_lostPassword.block input.captcha:focus,
|
||||
.mod_lostPassword.block input[type="text"]:focus,
|
||||
.mod_lostPassword.block input[type="email"]:focus,
|
||||
.mod_lostPassword.block input[type="password"]:focus {
|
||||
.survey-auth-module input.text:focus,
|
||||
.survey-auth-module input.password:focus,
|
||||
.survey-auth-module input.captcha:focus,
|
||||
.survey-auth-module input[type="text"]:focus,
|
||||
.survey-auth-module input[type="email"]:focus,
|
||||
.survey-auth-module input[type="password"]:focus {
|
||||
outline: none;
|
||||
border-color: rgba(0, 100, 173, 0.72);
|
||||
box-shadow: 0 0 0 4px rgba(0, 100, 173, 0.12);
|
||||
@@ -399,26 +403,26 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
}
|
||||
|
||||
/* Sicherheitsfrage: Rechenaufgabe als Hinweistext unter dem Feld */
|
||||
.mod_lostPassword.block .widget-captcha .captcha_text {
|
||||
.survey-auth-module .widget-captcha .captcha_text {
|
||||
order: 3;
|
||||
font-size: 0.9rem;
|
||||
color: var(--survey-auth-muted);
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .widget-captcha input.captcha {
|
||||
.survey-auth-module .widget-captcha input.captcha {
|
||||
max-width: 9rem;
|
||||
}
|
||||
|
||||
/* Zweiter Schritt: Passwortbestaetigung liegt als eigenes Feld direkt darunter */
|
||||
.mod_lostPassword.block .widget-password + .widget-password {
|
||||
/* Passwortbestaetigung liegt als eigenes Feld direkt darunter */
|
||||
.survey-auth-module .widget-password + .widget-password {
|
||||
margin-top: -0.15rem;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .widget-submit {
|
||||
.survey-auth-module .widget-submit {
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block button.submit {
|
||||
.survey-auth-module button.submit {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -437,8 +441,8 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block button.submit:hover,
|
||||
.mod_lostPassword.block button.submit:focus {
|
||||
.survey-auth-module button.submit:hover,
|
||||
.survey-auth-module button.submit:focus {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 18px 34px rgba(0, 100, 173, 0.28);
|
||||
filter: saturate(1.05);
|
||||
@@ -446,9 +450,9 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
}
|
||||
|
||||
/* Fehler- und Bestaetigungsmeldungen (auch das Contao-Template mod_message) */
|
||||
.mod_lostPassword.block p.error,
|
||||
.mod_lostPassword.block p.confirm,
|
||||
.mod_lostPassword.block p.message {
|
||||
.survey-auth-module p.error,
|
||||
.survey-auth-module p.confirm,
|
||||
.survey-auth-module p.message {
|
||||
margin: 0;
|
||||
padding: 0.85rem 1rem;
|
||||
border-radius: 1rem;
|
||||
@@ -457,24 +461,24 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block p.error {
|
||||
.survey-auth-module p.error {
|
||||
border-color: rgba(236, 124, 50, 0.4);
|
||||
background: rgba(236, 124, 50, 0.12);
|
||||
color: #a4501a;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block p.confirm {
|
||||
.survey-auth-module p.confirm {
|
||||
border-color: rgba(0, 174, 151, 0.4);
|
||||
background: rgba(0, 174, 151, 0.12);
|
||||
color: #00705f;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-back {
|
||||
.survey-auth-module .survey-auth-back {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-back a {
|
||||
.survey-auth-module .survey-auth-back a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
@@ -488,14 +492,14 @@ nav.mod_customnav.block:has(a[href*="/abmelden"]) .level_1 > li > a:focus {
|
||||
transition: color 0.18s ease, border-color 0.18s ease;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-back a::before {
|
||||
.survey-auth-module .survey-auth-back a::before {
|
||||
content: "\2039";
|
||||
font-size: 1.05em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block .survey-auth-back a:hover,
|
||||
.mod_lostPassword.block .survey-auth-back a:focus {
|
||||
.survey-auth-module .survey-auth-back a:hover,
|
||||
.survey-auth-module .survey-auth-back a:focus {
|
||||
color: var(--survey-auth-orange);
|
||||
border-color: rgba(236, 124, 50, 0.55);
|
||||
outline: none;
|
||||
@@ -583,14 +587,14 @@ a.survey-auth-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Meldungsseiten des Passwort-vergessen-Moduls (Contao-Template mod_message) */
|
||||
.mod_lostPassword.block .survey-auth-actions {
|
||||
/* Meldungsseiten der Auth-Module (Contao-Template mod_message) */
|
||||
.survey-auth-module .survey-auth-actions {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Hilfetexte und Feldfehler im Passwort-vergessen-Modul */
|
||||
.mod_lostPassword.block p.help {
|
||||
/* Hilfetexte und Feldfehler in den Auth-Modulen */
|
||||
.survey-auth-module p.help {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.4;
|
||||
@@ -610,12 +614,12 @@ a.survey-auth-button:focus {
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.mod_lostPassword.block {
|
||||
.survey-auth-module {
|
||||
padding: 1.2rem;
|
||||
border-radius: 1.35rem;
|
||||
}
|
||||
|
||||
.mod_lostPassword.block button.submit {
|
||||
.survey-auth-module button.submit {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -629,7 +633,7 @@ a.survey-auth-button:focus {
|
||||
}
|
||||
|
||||
.mod_login.block.login .password-reset,
|
||||
.mod_lostPassword.block .survey-auth-back {
|
||||
.survey-auth-module .survey-auth-back {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +172,10 @@ survey:
|
||||
headline: "Neues Passwort vergeben"
|
||||
intro: "Bitte vergeben Sie jetzt Ihr neues Passwort für die Umfrageplattform. Anschließend können Sie sich damit sofort anmelden."
|
||||
hint: "Wählen Sie ein Passwort, das Sie nicht bereits an anderer Stelle verwenden."
|
||||
change_password:
|
||||
headline: "Neues Passwort vergeben"
|
||||
intro: "Bitte vergeben Sie ein neues Passwort für Ihren Zugang zur Umfrageplattform. Geben Sie dazu zuerst Ihr aktuelles Passwort ein und anschließend zweimal das neue."
|
||||
hint: "Wählen Sie ein Passwort, das Sie nicht bereits an anderer Stelle verwenden."
|
||||
back_to_login: "Zurück zur Anmeldung"
|
||||
email:
|
||||
cta_password: "Neues Passwort festlegen"
|
||||
|
||||
@@ -172,6 +172,10 @@ survey:
|
||||
headline: "Set a new password"
|
||||
intro: "Please choose your new password for the survey platform. You can log in with it right away."
|
||||
hint: "Please pick a password that you do not already use elsewhere."
|
||||
change_password:
|
||||
headline: "Set a new password"
|
||||
intro: "Please choose a new password for your survey platform account. Enter your current password first, then the new one twice."
|
||||
hint: "Please pick a password that you do not already use elsewhere."
|
||||
back_to_login: "Back to login"
|
||||
email:
|
||||
cta_password: "Set a new password"
|
||||
|
||||
Reference in New Issue
Block a user