snapshot: preserve shared confirmation modal standardization

This commit is contained in:
Md Bayazid Bostame
2026-03-26 00:33:02 +01:00
parent 37c2cddf41
commit 4549a867f9
17 changed files with 445 additions and 47 deletions

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: tubco-portal\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-25 23:12+0000\n"
"POT-Creation-Date: 2026-03-25 23:29+0000\n"
"PO-Revision-Date: 2026-03-24 00:00+0000\n"
"Language: en\n"
"MIME-Version: 1.0\n"
@@ -350,11 +350,18 @@ msgstr "Sign in"
msgid "Bitte melden Sie sich mit Ihrem Benutzerkonto an."
msgstr "Please sign in with your user account."
#: workflows/templates/registration/login.html:25
msgid "Anmeldung fehlgeschlagen. Bitte Zugangsdaten prüfen."
msgstr "Login failed. Please check your credentials."
#: workflows/templates/registration/login.html:29
#, fuzzy
#| msgid "Fehlgeschlagen"
msgid "Anmeldung fehlgeschlagen"
msgstr "Failed"
#: workflows/templates/registration/login.html:30
msgid ""
"Benutzername oder Passwort sind nicht korrekt. Bitte versuchen Sie es erneut."
msgstr ""
#: workflows/templates/registration/login.html:35
msgid "Anmelden"
msgstr "Sign in"
@@ -453,6 +460,19 @@ msgstr ""
msgid "Noch keine Audit-Einträge vorhanden."
msgstr "No requests available yet."
#: workflows/templates/workflows/base_shell.html:24
msgid "Bitte bestätigen"
msgstr ""
#: workflows/templates/workflows/base_shell.html:28
#: workflows/templates/workflows/welcome_emails.html:138
msgid "Abbrechen"
msgstr "Cancel"
#: workflows/templates/workflows/base_shell.html:29
msgid "Bestätigen"
msgstr ""
#: workflows/templates/workflows/form_builder.html:4
#: workflows/templates/workflows/form_builder.html:14
#: workflows/templates/workflows/home.html:134
@@ -1795,6 +1815,12 @@ msgstr ""
msgid "Bis"
msgstr ""
#: workflows/templates/workflows/requests_dashboard.html:176
#, fuzzy
#| msgid "Ausgewählte Welcome-Einträge wirklich löschen?"
msgid "Ausgewählte Einträge wirklich löschen?"
msgstr "Delete the selected welcome entries?"
#: workflows/templates/workflows/requests_dashboard.html:179
#: workflows/templates/workflows/welcome_emails.html:78
msgid "ausgewählt"
@@ -1849,10 +1875,20 @@ msgstr "Not relevant"
msgid "Timeline"
msgstr ""
#: workflows/templates/workflows/requests_dashboard.html:276
msgid "Eintrag erneut verarbeiten?"
msgstr ""
#: workflows/templates/workflows/requests_dashboard.html:278
msgid "Erneut versuchen"
msgstr ""
#: workflows/templates/workflows/requests_dashboard.html:281
#, fuzzy
#| msgid "Option wirklich löschen?"
msgid "Eintrag wirklich löschen?"
msgstr "Delete this option?"
#: workflows/templates/workflows/requests_dashboard.html:290
msgid "Noch keine Vorgänge vorhanden."
msgstr "No requests available yet."
@@ -1939,10 +1975,6 @@ msgstr "Sent at"
msgid "Fortsetzen"
msgstr "Resume"
#: workflows/templates/workflows/welcome_emails.html:138
msgid "Abbrechen"
msgstr "Cancel"
#: workflows/templates/workflows/welcome_emails.html:145
msgid "Keine geplanten Welcome E-Mails vorhanden."
msgstr "No scheduled welcome emails available."
@@ -2215,6 +2247,9 @@ msgstr "Introduction was saved as completed."
msgid "Einweisung wurde als Entwurf gespeichert."
msgstr "Introduction was saved as draft."
#~ msgid "Anmeldung fehlgeschlagen. Bitte Zugangsdaten prüfen."
#~ msgstr "Login failed. Please check your credentials."
#, fuzzy
#~| msgid "Nextcloud speichern"
#~ msgid "Nextcloud deaktivieren"

View File

@@ -5,10 +5,10 @@ h1 { margin: 12px 0 6px; color: #000078; }
.flash, .msg { border-radius: 10px; padding: 10px 12px; margin: 0 0 12px; border: 1px solid #d6e1ef; background: #f8fbff; color: #1f3a5f; }
.flash.error, .msg.error { border-color: #fecaca; background: #fff1f2; color: #991b1b; }
.flash.success { border-color: #bfe6c9; background: #edf9f1; color: #116634; }
.card { border: 1px solid #d8e3f0; border-radius: 12px; background: #fbfdff; padding: 12px; margin-bottom: 14px; }
.card { border: 1px solid #d8e3f0; border-radius: 12px; background: #fbfdff; padding: 12px; margin-bottom: 14px; transition: border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 220ms cubic-bezier(0.2, 0.8, 0.2, 1), transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1); }
.grid { display: grid; grid-template-columns: repeat(2, minmax(240px, 1fr)); gap: 10px; }
label { display: block; margin-bottom: 4px; font-size: 12px; color: #334155; font-weight: 700; }
input, select, textarea { width: 100%; box-sizing: border-box; border: 1px solid #cbd5e1; border-radius: 8px; padding: 8px 9px; background: #fff; }
input, select, textarea { width: 100%; box-sizing: border-box; border: 1px solid #cbd5e1; border-radius: 8px; padding: 8px 9px; background: #fff; transition: border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1), background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1); }
textarea { min-height: 120px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.actions { margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap; }
.toggle-row { margin-top: 10px; display: inline-flex; align-items: center; gap: 10px; padding: 8px 10px 8px 12px; border: 1px solid #d8e3f0; border-radius: 999px; background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(246,249,255,0.94)); box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 6px 14px rgba(16, 32, 57, 0.05); }
@@ -24,8 +24,9 @@ textarea { min-height: 120px; font-family: ui-monospace, SFMono-Regular, Menlo,
.hint { margin-top: 6px; color: #64748b; font-size: 12px; }
.toolbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.switch { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.switch .tab { border: 1px solid #c9d6e7; border-radius: 999px; padding: 8px 14px; text-decoration: none; color: #1f2f49; font-weight: 700; background: #f6f9ff; }
.switch .tab { border: 1px solid #c9d6e7; border-radius: 999px; padding: 8px 14px; text-decoration: none; color: #1f2f49; font-weight: 700; background: #f6f9ff; transition: background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1); }
.switch .tab.active { background: #000078; color: #fff; border-color: #000078; }
.switch .tab:hover { transform: translateY(-1px); box-shadow: 0 8px 16px rgba(16, 32, 57, 0.06); }
.check-row { margin-top: 8px; display: flex; gap: 12px; flex-wrap: wrap; }
.check-row label { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; }
.check-row input[type="checkbox"] { width: auto; }

View File

@@ -4,6 +4,10 @@
--app-brand-blue: #000078;
--app-panel: rgba(255, 255, 255, 0.9);
--app-shadow: 0 22px 48px rgba(18, 34, 56, 0.14);
--motion-fast: 160ms;
--motion-base: 200ms;
--motion-slow: 260ms;
--motion-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}
.app-header {
@@ -19,6 +23,10 @@
border-radius: 28px;
background: linear-gradient(180deg, rgba(255,255,255,0.95), rgba(248,251,255,0.84));
box-shadow: var(--app-shadow);
transition:
box-shadow var(--motion-base) var(--motion-ease),
border-color var(--motion-base) var(--motion-ease),
background-color var(--motion-base) var(--motion-ease);
}
.app-header-in-shell {
@@ -38,6 +46,11 @@
min-width: 0;
align-items: center;
text-decoration: none;
transition: transform var(--motion-base) var(--motion-ease), opacity var(--motion-base) var(--motion-ease);
}
.app-brand:hover {
transform: translateY(-1px);
}
.app-brand-logo {
@@ -45,6 +58,12 @@
max-width: 100%;
height: auto;
display: block;
transition: transform var(--motion-base) var(--motion-ease), filter var(--motion-base) var(--motion-ease);
}
.app-brand:hover .app-brand-logo {
transform: translateY(-1px);
filter: saturate(1.02);
}
.app-header-actions {
@@ -71,6 +90,12 @@
font-size: 12px;
font-weight: 700;
cursor: pointer;
transition:
background-color var(--motion-fast) var(--motion-ease),
border-color var(--motion-fast) var(--motion-ease),
color var(--motion-fast) var(--motion-ease),
transform var(--motion-fast) var(--motion-ease),
box-shadow var(--motion-fast) var(--motion-ease);
}
.app-lang-btn.active {
@@ -79,6 +104,15 @@
color: #fff;
}
.app-lang-btn:hover {
transform: translateY(-1px);
}
.app-lang-btn:focus-visible {
outline: none;
box-shadow: 0 0 0 4px rgba(0, 0, 120, 0.10);
}
.shell,
.wrap,
.top-wrap {
@@ -99,3 +133,83 @@
justify-content: flex-start;
}
}
.confirm-modal[hidden] {
display: none;
}
.confirm-modal {
position: fixed;
inset: 0;
z-index: 1200;
}
.confirm-backdrop {
position: absolute;
inset: 0;
background: rgba(16, 32, 57, 0.42);
backdrop-filter: blur(4px);
animation: confirmFadeIn var(--motion-base) var(--motion-ease);
}
.confirm-dialog {
position: relative;
width: min(480px, calc(100% - 32px));
margin: min(18vh, 120px) auto 0;
padding: 18px;
border: 1px solid rgba(217, 227, 238, 0.94);
border-radius: 22px;
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(247,250,255,0.96));
box-shadow: 0 24px 56px rgba(18, 34, 56, 0.20);
animation: confirmPopIn var(--motion-slow) var(--motion-ease);
}
.confirm-dialog-head h2 {
margin: 0;
font-size: 20px;
color: #18345f;
letter-spacing: -0.02em;
}
.confirm-message {
margin: 10px 0 0;
color: #52647a;
font-size: 14px;
line-height: 1.55;
}
.confirm-actions {
margin-top: 18px;
display: flex;
justify-content: flex-end;
gap: 8px;
flex-wrap: wrap;
}
body.confirm-open {
overflow: hidden;
}
@keyframes confirmFadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes confirmPopIn {
from {
opacity: 0;
transform: translateY(10px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@media (prefers-reduced-motion: reduce) {
:root {
--motion-fast: 1ms;
--motion-base: 1ms;
--motion-slow: 1ms;
}
}

View File

@@ -20,7 +20,13 @@
font-size: 14px;
line-height: 1.2;
cursor: pointer;
transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.08s ease;
transition:
background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
filter 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.btn:focus-visible {
@@ -34,7 +40,7 @@
}
.btn:active:not(:disabled) {
transform: translateY(1px);
transform: translateY(0);
}
.btn-primary {
@@ -44,7 +50,9 @@
}
.btn-primary:hover:not(:disabled) {
filter: brightness(0.95);
filter: brightness(0.97);
transform: translateY(-1px);
box-shadow: 0 10px 20px rgba(0, 0, 120, 0.12);
}
.btn-secondary {
@@ -55,4 +63,6 @@
.btn-secondary:hover:not(:disabled) {
background: #f8fafc;
transform: translateY(-1px);
box-shadow: 0 8px 18px rgba(18, 34, 56, 0.08);
}

View File

@@ -95,6 +95,10 @@
background: rgba(255,255,255,0.92);
border-radius: 22px;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
transition:
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.hero-card {
@@ -169,6 +173,12 @@
min-height: 38px;
display: inline-flex;
align-items: center;
transition:
background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.status-pill-neutral {
@@ -385,6 +395,10 @@
flex-direction: column;
justify-content: space-between;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
transition:
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.app-card::before {
@@ -395,6 +409,17 @@
height: 118px;
border-radius: 50%;
background: rgba(31, 79, 214, 0.08);
transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.app-card:hover {
transform: translateY(-3px);
border-color: rgba(196, 208, 225, 1);
box-shadow: 0 14px 28px rgba(16, 32, 57, 0.10), inset 0 1px 0 rgba(255,255,255,0.92);
}
.app-card:hover::before {
transform: scale(1.06);
}
.app-card.primary {
@@ -468,6 +493,11 @@
font-weight: 800;
letter-spacing: 0.03em;
text-transform: uppercase;
transition:
background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.card-actions {
@@ -490,6 +520,10 @@
padding: 14px;
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(247,250,255,0.96));
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
transition:
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.admin-card::before {
@@ -500,6 +534,17 @@
height: 84px;
border-radius: 50%;
background: rgba(31, 79, 214, 0.06);
transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.admin-card:hover {
transform: translateY(-2px);
border-color: rgba(196, 208, 225, 1);
box-shadow: 0 12px 24px rgba(16, 32, 57, 0.08), inset 0 1px 0 rgba(255,255,255,0.92);
}
.admin-card:hover::before {
transform: scale(1.05);
}
.admin-card h3 {

View File

@@ -51,6 +51,12 @@ body {
margin-bottom: 12px;
}
.field.has-error input {
border-color: #e3a3a3;
background: #fffafa;
box-shadow: 0 0 0 4px rgba(185, 28, 28, 0.06);
}
.field label {
display: block;
font-weight: 700;
@@ -67,19 +73,44 @@ body {
min-height: 44px;
font: inherit;
background: #fff;
transition: border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1), background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.field input:focus {
outline: none;
border-color: rgba(0, 0, 120, 0.3);
box-shadow: 0 0 0 4px rgba(0, 0, 120, 0.08);
}
.btn {
width: 100%;
}
.errorlist {
color: #b91c1c;
margin: 0 0 10px;
padding: 10px 12px;
border-radius: 10px;
border: 1px solid #f0c8c8;
background: #fff3f3;
.login-alert {
margin: 0 0 12px;
padding: 12px 14px;
border-radius: 12px;
border: 1px solid #d6e1ef;
background: #f8fbff;
display: grid;
gap: 4px;
font-size: 14px;
}
.login-alert strong {
font-size: 14px;
line-height: 1.2;
}
.login-alert span {
color: #5f6f85;
line-height: 1.45;
}
.login-alert-error {
color: #991b1b;
border-color: #f0c8c8;
background: linear-gradient(180deg, #fff7f7, #fff1f1);
}
@media (max-width: 760px) {

View File

@@ -101,6 +101,10 @@
background: var(--panel);
border-radius: 22px;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
transition:
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.hero-card {
@@ -256,6 +260,17 @@
height: 110px;
border-radius: 50%;
background: rgba(31, 79, 214, 0.08);
transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.stat-card:hover {
transform: translateY(-2px);
border-color: rgba(196, 208, 225, 1);
box-shadow: 0 14px 30px rgba(18, 33, 56, 0.08), inset 0 1px 0 rgba(255,255,255,0.92);
}
.stat-card:hover::before {
transform: scale(1.05);
}
.stat-card.red::before { background: rgba(163, 32, 32, 0.08); }
@@ -461,6 +476,10 @@
color: var(--ink);
background: rgba(255,255,255,0.98);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.98);
transition:
border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.search-box input:focus,
@@ -626,6 +645,11 @@
padding: 15px 14px;
vertical-align: middle;
box-shadow: 0 8px 22px rgba(26, 51, 89, 0.035);
transition:
background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
tbody td:first-child {
@@ -686,6 +710,12 @@
border: 1px solid rgba(217, 227, 238, 0.96);
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,251,255,0.96));
box-shadow: inset 0 1px 0 rgba(255,255,255,0.94);
transition:
background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.kind-pill {
@@ -725,6 +755,7 @@
text-decoration: none;
font-weight: 600;
word-break: break-word;
transition: color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.mail-link:hover { text-decoration: underline; }
@@ -750,6 +781,7 @@
.doc-link:hover {
background: linear-gradient(180deg, rgba(248,251,255,0.99), rgba(238,244,255,0.98));
border-color: rgba(0, 0, 120, 0.18);
transform: translateY(-1px);
}
.actions-cell { white-space: normal; }
@@ -781,6 +813,16 @@
font-weight: 800;
color: #18345f;
background: rgba(255,255,255,0.65);
transition:
background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1),
transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.intro-toggle:hover {
transform: translateY(-1px);
box-shadow: 0 8px 18px rgba(18, 33, 56, 0.06);
}
.intro-toggle::after {

View File

@@ -0,0 +1,92 @@
(function () {
const modal = document.getElementById('app-confirm-modal');
if (!modal) return;
const messageNode = document.getElementById('app-confirm-message');
const acceptBtn = document.getElementById('app-confirm-accept');
const cancelBtn = document.getElementById('app-confirm-cancel');
const closeNodes = modal.querySelectorAll('[data-confirm-close]');
let resolver = null;
let lastActive = null;
function close(result) {
modal.hidden = true;
modal.setAttribute('aria-hidden', 'true');
document.body.classList.remove('confirm-open');
if (resolver) {
resolver(result);
resolver = null;
}
if (lastActive && typeof lastActive.focus === 'function') {
lastActive.focus();
}
}
function open(message) {
lastActive = document.activeElement;
messageNode.textContent = message || '';
modal.hidden = false;
modal.setAttribute('aria-hidden', 'false');
document.body.classList.add('confirm-open');
acceptBtn.focus();
return new Promise(function (resolve) {
resolver = resolve;
});
}
window.AppConfirm = { open: open };
acceptBtn.addEventListener('click', function () { close(true); });
cancelBtn.addEventListener('click', function () { close(false); });
closeNodes.forEach(function (node) {
node.addEventListener('click', function () { close(false); });
});
document.addEventListener('keydown', function (event) {
if (modal.hidden) return;
if (event.key === 'Escape') {
event.preventDefault();
close(false);
}
});
document.addEventListener('submit', function (event) {
const form = event.target;
const message = form.dataset.confirm;
if (!message || form.dataset.confirmBypass === '1') return;
event.preventDefault();
open(message).then(function (confirmed) {
if (!confirmed) return;
form.dataset.confirmBypass = '1';
if (typeof form.requestSubmit === 'function') {
form.requestSubmit();
} else {
form.submit();
}
window.setTimeout(function () {
delete form.dataset.confirmBypass;
}, 0);
});
}, true);
document.addEventListener('click', function (event) {
const button = event.target.closest('button[data-confirm], input[type="submit"][data-confirm]');
if (!button || button.dataset.confirmBypass === '1') return;
const form = button.form;
if (!form) return;
event.preventDefault();
event.stopPropagation();
open(button.dataset.confirm).then(function (confirmed) {
if (!confirmed) return;
button.dataset.confirmBypass = '1';
if (typeof form.requestSubmit === 'function') {
form.requestSubmit(button);
} else {
button.click();
}
window.setTimeout(function () {
delete button.dataset.confirmBypass;
}, 0);
});
}, true);
})();

View File

@@ -29,24 +29,35 @@
});
rowChecks.forEach((c) => c.addEventListener('change', syncState));
bulkForm.addEventListener('submit', syncState);
window.confirmBulkAction = function () {
bulkForm.addEventListener('submit', function (event) {
syncState();
const count = currentSelected().length;
if (!count) {
alert(bulkForm.dataset.alertEmpty || 'Bitte mindestens einen Welcome-Eintrag auswählen.');
return false;
event.preventDefault();
const emptyMessage = bulkForm.dataset.alertEmpty || 'Bitte mindestens einen Welcome-Eintrag auswählen.';
if (window.AppConfirm) {
window.AppConfirm.open(emptyMessage);
} else {
window.alert(emptyMessage);
}
return;
}
if (bulkForm.dataset.confirmBypass === '1') return;
event.preventDefault();
const action = bulkAction.value;
let message = bulkForm.dataset.confirmSend || 'Ausgewählte Welcome-Einträge sofort senden?';
if (action === 'delete') {
return confirm(bulkForm.dataset.confirmDelete || 'Ausgewählte Welcome-Einträge wirklich löschen?');
message = bulkForm.dataset.confirmDelete || 'Ausgewählte Welcome-Einträge wirklich löschen?';
} else if (action === 'pause') {
message = bulkForm.dataset.confirmPause || 'Ausgewählte Welcome-Einträge pausieren?';
}
if (action === 'pause') {
return confirm(bulkForm.dataset.confirmPause || 'Ausgewählte Welcome-Einträge pausieren?');
}
return confirm(bulkForm.dataset.confirmSend || 'Ausgewählte Welcome-Einträge sofort senden?');
};
window.AppConfirm.open(message).then(function (confirmed) {
if (!confirmed) return;
bulkForm.dataset.confirmBypass = '1';
bulkForm.requestSubmit();
window.setTimeout(function () { delete bulkForm.dataset.confirmBypass; }, 0);
});
});
syncState();
})();

View File

@@ -21,11 +21,17 @@
<form method="post" action="/accounts/login/">
{% csrf_token %}
{% if form.errors %}
<div class="errorlist">{% trans "Anmeldung fehlgeschlagen. Bitte Zugangsdaten prüfen." %}</div>
{% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
<div class="field">{{ form.username.label_tag }}{{ form.username }}</div>
<div class="field">{{ form.password.label_tag }}{{ form.password }}</div>
{% if form.errors %}
<div class="login-alert login-alert-error" role="alert" aria-live="assertive">
<strong>{% trans "Anmeldung fehlgeschlagen" %}</strong>
<span>{% trans "Benutzername oder Passwort sind nicht korrekt. Bitte versuchen Sie es erneut." %}</span>
</div>
{% endif %}
<div class="field{% if form.errors %} has-error{% endif %}">{{ form.username.label_tag }}{{ form.username }}</div>
<div class="field{% if form.errors %} has-error{% endif %}">{{ form.password.label_tag }}{{ form.password }}</div>
<button class="btn btn-primary" type="submit">{% trans "Anmelden" %}</button>
</form>
</div>

View File

@@ -17,6 +17,20 @@
{% block shell_header %}{% endblock %}
{% block shell_body %}{% endblock %}
</div>
<div class="confirm-modal" id="app-confirm-modal" hidden aria-hidden="true">
<div class="confirm-backdrop" data-confirm-close="1"></div>
<div class="confirm-dialog" role="dialog" aria-modal="true" aria-labelledby="app-confirm-title" aria-describedby="app-confirm-message">
<div class="confirm-dialog-head">
<h2 id="app-confirm-title">{% trans "Bitte bestätigen" %}</h2>
</div>
<p class="confirm-message" id="app-confirm-message"></p>
<div class="confirm-actions">
<button class="btn btn-secondary" type="button" id="app-confirm-cancel">{% trans "Abbrechen" %}</button>
<button class="btn btn-primary" type="button" id="app-confirm-accept">{% trans "Bestätigen" %}</button>
</div>
</div>
</div>
<script src="{% static 'workflows/js/confirm_dialog.js' %}"></script>
{% block extra_scripts %}{% endblock %}
</body>
</html>

View File

@@ -108,7 +108,7 @@
<td><input type="text" name="value_{{ item.id }}" value="{{ item.value }}" /></td>
<td><input type="checkbox" name="active_{{ item.id }}" {% if item.is_active %}checked{% endif %} /></td>
<td>
<button class="btn btn-secondary" type="submit" name="delete_option_id" value="{{ item.id }}" onclick="return confirm('{% trans 'Option wirklich löschen?' %}');">{% trans "Löschen" %}</button>
<button class="btn btn-secondary" type="submit" name="delete_option_id" value="{{ item.id }}" data-confirm="{% trans 'Option wirklich löschen?' %}">{% trans "Löschen" %}</button>
</td>
</tr>
{% empty %}
@@ -164,4 +164,3 @@
</form>
</section>
{% endblock %}

View File

@@ -103,7 +103,7 @@
<td><input type="text" name="value_{{ item.id }}" value="{{ item.condition_value }}" placeholder="{% trans 'z. B. HR Works' %}" /></td>
<td><input type="checkbox" name="active_{{ item.id }}" {% if item.is_active %}checked{% endif %} /></td>
<td class="actions">
<button class="btn btn-secondary" type="submit" name="delete_item_id" value="{{ item.id }}" onclick="return confirm('{% trans 'Checklistenpunkt wirklich löschen?' %}');">{% trans "Löschen" %}</button>
<button class="btn btn-secondary" type="submit" name="delete_item_id" value="{{ item.id }}" data-confirm="{% trans 'Checklistenpunkt wirklich löschen?' %}">{% trans "Löschen" %}</button>
</td>
</tr>
{% empty %}

View File

@@ -81,7 +81,7 @@
<div class="actions">
<button class="btn btn-secondary" type="submit" name="session_action" value="save">{% trans "Als Entwurf speichern" %}</button>
<button class="btn btn-primary" type="submit" name="session_action" value="complete">{% trans "Als abgeschlossen markieren" %}</button>
<button class="btn btn-secondary" type="submit" name="session_action" value="reset" onclick="return confirm('{% trans 'Einweisung wirklich zurücksetzen?' %}');">{% trans "Alles zurücksetzen" %}</button>
<button class="btn btn-secondary" type="submit" name="session_action" value="reset" data-confirm="{% trans 'Einweisung wirklich zurücksetzen?' %}">{% trans "Alles zurücksetzen" %}</button>
</div>
</div>
</form>
@@ -102,4 +102,3 @@
</div>
</div>
{% endblock %}

View File

@@ -173,7 +173,7 @@
</div>
{% if request.user.is_staff %}
<div class="control-stack">
<form method="post" action="/requests/" id="bulk-delete-form" onsubmit="return confirm('Ausgewählte Einträge wirklich löschen?');">
<form method="post" action="/requests/" id="bulk-delete-form" data-confirm="{% trans 'Ausgewählte Einträge wirklich löschen?' %}">
{% csrf_token %}
<div class="bulk-toolbar">
<span class="bulk-info"><span id="selected-count">0</span> {% trans "ausgewählt" %}</span>
@@ -273,12 +273,12 @@
<td class="actions-cell">
<a class="btn btn-secondary" href="/requests/timeline/{{ row.kind_slug }}/{{ row.id }}/">{% trans "Timeline" %}</a>
{% if row.status_key == 'failed' %}
<form method="post" action="/requests/retry/{{ row.kind_slug }}/{{ row.id }}/" class="inline-delete" onsubmit="return confirm('Eintrag erneut verarbeiten?');">
<form method="post" action="/requests/retry/{{ row.kind_slug }}/{{ row.id }}/" class="inline-delete" data-confirm="{% trans 'Eintrag erneut verarbeiten?' %}">
{% csrf_token %}
<button class="btn btn-secondary" type="submit">{% trans "Erneut versuchen" %}</button>
</form>
{% endif %}
<form method="post" action="/requests/" class="inline-delete" onsubmit="return confirm('Eintrag wirklich löschen?');">
<form method="post" action="/requests/" class="inline-delete" data-confirm="{% trans 'Eintrag wirklich löschen?' %}">
{% csrf_token %}
<button class="btn btn-secondary" type="submit" name="single_delete" value="{{ row.kind_slug }}:{{ row.id }}">{% trans "Löschen" %}</button>
</form>

View File

@@ -62,7 +62,7 @@
</div>
</form>
<form class="bulk-bar" id="welcome-bulk-form" method="post" action="/admin-tools/welcome-emails/bulk-action/" onsubmit="return confirmBulkAction();" data-alert-empty="{% trans 'Bitte mindestens einen Welcome-Eintrag auswählen.' %}" data-confirm-delete="{% trans 'Ausgewählte Welcome-Einträge wirklich löschen?' %}" data-confirm-pause="{% trans 'Ausgewählte Welcome-Einträge pausieren?' %}" data-confirm-send="{% trans 'Ausgewählte Welcome-Einträge sofort senden?' %}">
<form class="bulk-bar" id="welcome-bulk-form" method="post" action="/admin-tools/welcome-emails/bulk-action/" data-alert-empty="{% trans 'Bitte mindestens einen Welcome-Eintrag auswählen.' %}" data-confirm-delete="{% trans 'Ausgewählte Welcome-Einträge wirklich löschen?' %}" data-confirm-pause="{% trans 'Ausgewählte Welcome-Einträge pausieren?' %}" data-confirm-send="{% trans 'Ausgewählte Welcome-Einträge sofort senden?' %}">
{% csrf_token %}
<label style="display:inline-flex; align-items:center; gap:6px; margin:0;">
<input type="checkbox" id="select-all-welcome" />
@@ -151,4 +151,3 @@
{% block extra_scripts %}
<script src="{% static 'workflows/js/welcome_emails.js' %}"></script>
{% endblock %}