Projektleiter-Rolle, Papierkorb, neue Login-Seite und Benutzerverwaltung
- Neue Rolle "Projektleiter": Projekte anlegen und löschen nur noch für Projektleiter und Administratoren (serverseitig in /save-week geprüft) - Papierkorb: gelöschte Projekte 30 Tage durch Admins wiederherstellbar - Benutzerverwaltung: Aktionen im Drei-Punkte-Menü mit Rückfrage im Menü, getrennte Felder für Vor- und Nachname, E-Mail-Vorschlag v.nachname@rauschenberg-ing.de, Benutzername = Anfang der E-Mail, Person-ID aus dem Kürzel - Endgültiges Löschen eines Benutzers entfernt ihn auch aus den Projekten und Aufgaben der aktuellen Sitzung; Dateien bleiben als "Gelöschter Benutzer" - Login-Seite neu (Design "Kalenderwoche") mit Logo als Wasserzeichen; Anmeldung ohne Groß-/Kleinschreibung, auch mit voller E-Mail-Adresse Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
93505e0e48
commit
f4fb3c550b
13 files changed
+1214
-116
No files matched your search
+183
-2
@@ -4030,8 +4030,63 @@ html[data-theme="dark"] .absence-type-fortbildung { background: rgba(255,159,10,
|
||||
Seiten-Huelle (.admin-page/.admin-header/.admin-body) sind mit ihr
|
||||
entfallen, weil der Abschnitt jetzt in der normalen App-Huelle liegt. */
|
||||
.admin-toolbar { margin-bottom: 14px; }
|
||||
td.actions-cell { white-space: nowrap; }
|
||||
td.actions-cell button { margin: 2px; }
|
||||
td.actions-cell { white-space: nowrap; width: 1%; text-align: right; }
|
||||
|
||||
/* Vor- und Nachname nebeneinander (Benutzer anlegen/bearbeiten), auf
|
||||
schmalen Bildschirmen untereinander. */
|
||||
.form-row-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
|
||||
.form-row-pair > .form-row { min-width: 0; }
|
||||
@media (max-width: 480px) { .form-row-pair { grid-template-columns: 1fr; } }
|
||||
|
||||
/* Zeilenaktionen der Benutzerverwaltung: „Bearbeiten" + Drei-Punkte-Menü
|
||||
(js/admin-users.js, openUserActionMenu()). Das Menü hängt an <body> und
|
||||
steht fixed, damit der quer scrollbare Tabellenrahmen es nicht abschneidet. */
|
||||
.user-aktionen { display: inline-flex; gap: 6px; align-items: center; }
|
||||
.user-kebab {
|
||||
width: 30px; height: 30px; padding: 0;
|
||||
display: inline-grid; place-items: center;
|
||||
border: 1px solid transparent; border-radius: var(--r-sm);
|
||||
background: transparent; color: var(--text-muted); cursor: pointer;
|
||||
transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
|
||||
}
|
||||
.user-kebab:hover { background: var(--surface-sunk); color: var(--text); }
|
||||
.user-kebab[aria-expanded="true"] {
|
||||
background: var(--accent-soft); color: var(--accent);
|
||||
border-color: color-mix(in srgb, var(--accent) 35%, transparent);
|
||||
}
|
||||
.user-kebab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.user-kebab svg { display: block; }
|
||||
tr.is-menu-open { background: var(--surface-alt); }
|
||||
|
||||
.user-menu {
|
||||
position: fixed; z-index: 250; min-width: 220px; max-width: 280px;
|
||||
background: var(--surface); border: 1px solid var(--line);
|
||||
border-radius: var(--r-md); box-shadow: var(--sh-3); padding: 5px;
|
||||
transform-origin: top right;
|
||||
animation: user-menu-auf var(--dur) var(--ease-out);
|
||||
}
|
||||
.user-menu.nach-oben { transform-origin: bottom right; animation-name: user-menu-auf-oben; }
|
||||
@keyframes user-menu-auf { from { opacity: 0; transform: scale(.96) translateY(-4px); } to { opacity: 1; transform: none; } }
|
||||
@keyframes user-menu-auf-oben { from { opacity: 0; transform: scale(.96) translateY(4px); } to { opacity: 1; transform: none; } }
|
||||
.user-menu-item {
|
||||
all: unset; box-sizing: border-box;
|
||||
display: flex; gap: 10px; align-items: flex-start; width: 100%;
|
||||
padding: 7px 10px; border-radius: var(--r-sm);
|
||||
color: var(--text); font-size: 13.5px; line-height: 1.35; cursor: pointer;
|
||||
}
|
||||
.user-menu-item:hover:not([aria-disabled="true"]), .user-menu-item:focus-visible { background: var(--surface-sunk); }
|
||||
.user-menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
||||
.user-menu-ic { flex: none; width: 16px; height: 16px; margin-top: 1px; color: var(--text-muted); }
|
||||
.user-menu-text { display: grid; gap: 1px; }
|
||||
.user-menu-sub { font-size: 12px; color: var(--text-subtle); }
|
||||
.user-menu-item.is-danger, .user-menu-item.is-danger .user-menu-ic { color: var(--red); }
|
||||
.user-menu-item.is-danger:hover:not([aria-disabled="true"]),
|
||||
.user-menu-item.is-danger:focus-visible { background: color-mix(in srgb, var(--red) 10%, transparent); }
|
||||
.user-menu-item[aria-disabled="true"], .user-menu-item[aria-disabled="true"] .user-menu-ic { color: var(--text-subtle); cursor: not-allowed; }
|
||||
.user-menu-trenner { border: 0; border-top: 1px solid var(--line-soft); margin: 5px 4px; }
|
||||
.user-menu-confirm { padding: 10px 10px 8px; display: grid; gap: 10px; }
|
||||
.user-menu-confirm p { margin: 0; font-size: 13px; line-height: 1.4; }
|
||||
.user-menu-confirm-row { display: flex; gap: 6px; justify-content: flex-end; }
|
||||
.badge-active { color: var(--green); font-weight: 600; }
|
||||
.badge-inactive { color: var(--text-muted); }
|
||||
.badge-warn { color: var(--amber); font-weight: 600; }
|
||||
@@ -5252,3 +5307,129 @@ td.actions-cell button { margin: 2px; }
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* =========================================================================
|
||||
LOGIN-SEITE (#loginOverlay, Design "Kalenderwoche" — Eriks Wahl B)
|
||||
Links Logo und Formular, rechts die laufende Kalenderwoche als große Zahl
|
||||
mit ihren Arbeitstagen (renderLoginWoche(), js/auth.js). Farben über die
|
||||
App-Tokens; nur die Zahl hat eigene Tokens (Logo-Hellblau im hellen,
|
||||
gedämpft im dunklen Thema). Liegt über allem (z-index 400 > .modal-bg 300).
|
||||
Das Logo ist ein blasses Wasserzeichen über die ganze Seite
|
||||
(.login-wasserzeichen, Variante E), kein eigenes kleines Logo.
|
||||
========================================================================= */
|
||||
.login-seite {
|
||||
--login-zahl: #94b0cc;
|
||||
--login-jahr: #116896;
|
||||
--login-wz: .11;
|
||||
position: fixed; inset: 0; z-index: 400;
|
||||
display: none; overflow-y: auto; overflow-x: hidden;
|
||||
background: var(--bg); color: var(--text);
|
||||
padding: 0 20px;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html:not([data-theme="light"]) .login-seite { --login-zahl: #4f7695; --login-jahr: var(--accent); --login-wz: .07; }
|
||||
}
|
||||
html[data-theme="dark"] .login-seite { --login-zahl: #4f7695; --login-jahr: var(--accent); --login-wz: .07; }
|
||||
|
||||
/* Wasserzeichen: ganzes Zeichen sichtbar, an den Rändern angeschnitten. Die
|
||||
Felder und Tageskacheln haben eigene Flächen und bleiben davor lesbar.
|
||||
Der Rahmen ist genau so groß wie das Fenster und schneidet alles
|
||||
Überstehende ab — sonst ragte das Logo über den Rand und machte die
|
||||
Seite scrollbar. */
|
||||
.login-wz-rahmen { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
|
||||
.login-wasserzeichen {
|
||||
position: absolute; z-index: 0; left: 50%; top: 50%;
|
||||
width: min(1500px, 98vw); height: auto; transform: translate(-44%, -47%);
|
||||
opacity: var(--login-wz); filter: blur(1px);
|
||||
pointer-events: none; user-select: none;
|
||||
}
|
||||
|
||||
.login-raster {
|
||||
position: relative; z-index: 1;
|
||||
width: 100%; max-width: 1180px; min-height: 100%; margin: 0 auto;
|
||||
display: grid; grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
|
||||
gap: clamp(32px, 7vw, 110px); align-items: center;
|
||||
padding-block: calc(48px + env(safe-area-inset-top, 0px)) calc(48px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
.login-titel { margin: 0 0 6px; font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-weight: 500; font-size: 30px; letter-spacing: -.01em; }
|
||||
.login-unter { margin: 0 0 30px; color: var(--text-muted); }
|
||||
|
||||
.login-form { display: grid; gap: 18px; }
|
||||
.login-feld { display: grid; gap: 7px; }
|
||||
.login-feld label { font-size: 13.5px; font-weight: 600; color: var(--text); }
|
||||
.login-feld input {
|
||||
width: 100%; box-sizing: border-box; min-height: 46px; padding: 11px 13px;
|
||||
font: inherit; font-size: 15px; color: var(--text);
|
||||
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
|
||||
transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
|
||||
}
|
||||
.login-feld input::placeholder { color: var(--text-subtle); opacity: 1; }
|
||||
.login-feld input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
|
||||
.login-feld.hat-fehler input { border-color: var(--red); }
|
||||
.login-pw { position: relative; }
|
||||
.login-pw input { padding-right: 96px; }
|
||||
.login-pw-toggle {
|
||||
position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
|
||||
font: inherit; font-size: 12.5px; font-weight: 600; color: var(--accent);
|
||||
background: transparent; border: 0; border-radius: var(--r-md); padding: 7px 10px; cursor: pointer;
|
||||
}
|
||||
.login-pw-toggle:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
|
||||
.login-pw-toggle:focus-visible, .login-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.login-caps { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--amber); }
|
||||
.login-fehler {
|
||||
margin: 0; padding: 10px 12px; border-radius: var(--r-lg); font-size: 13.5px; line-height: 1.45;
|
||||
color: var(--red); background: color-mix(in srgb, var(--red) 10%, transparent);
|
||||
}
|
||||
.login-btn {
|
||||
display: inline-flex; align-items: center; justify-content: center; gap: 10px;
|
||||
width: 100%; min-height: 48px; margin-top: 4px;
|
||||
font: inherit; font-size: 15px; font-weight: 650; color: #fff;
|
||||
background: var(--accent); border: 0; border-radius: var(--r-lg); cursor: pointer;
|
||||
transition: filter var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) { html:not([data-theme="light"]) .login-btn { color: #0b1c26; } }
|
||||
html[data-theme="dark"] .login-btn { color: #0b1c26; }
|
||||
.login-btn:hover { filter: brightness(1.07); }
|
||||
.login-btn:active { transform: scale(var(--press)); }
|
||||
.login-btn:disabled { cursor: progress; filter: saturate(.7); }
|
||||
.login-spinner {
|
||||
display: none; width: 15px; height: 15px; border-radius: 50%;
|
||||
border: 2px solid color-mix(in srgb, currentColor 35%, transparent); border-top-color: currentColor;
|
||||
animation: login-dreh .7s linear infinite;
|
||||
}
|
||||
.login-btn.laedt .login-spinner { display: block; }
|
||||
@keyframes login-dreh { to { transform: rotate(360deg); } }
|
||||
.login-hilfe { margin: 18px 0 0; font-size: 13px; color: var(--text-muted); }
|
||||
|
||||
.login-woche { justify-self: end; text-align: right; animation: login-auf .7s var(--ease-out) both; }
|
||||
@keyframes login-auf { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
|
||||
.login-kw-label, .login-kw-jahr, .login-kw-zahl, .login-tage b { font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
|
||||
.login-kw-label { display: block; font-weight: 500; font-size: 22px; color: var(--text-muted); letter-spacing: .02em; }
|
||||
.login-kw-zahl {
|
||||
display: block; font-weight: 300; font-size: clamp(150px, 21vw, 300px); line-height: .86;
|
||||
letter-spacing: -.05em; color: var(--login-zahl); font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.login-kw-jahr { display: block; font-weight: 500; font-size: 20px; color: var(--login-jahr); }
|
||||
.login-tage { list-style: none; margin: 30px 0 0; padding: 0; display: flex; gap: 8px; justify-content: flex-end; }
|
||||
.login-tage li {
|
||||
display: grid; justify-items: center; gap: 2px; width: 58px; padding: 10px 0 9px;
|
||||
border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--line);
|
||||
}
|
||||
.login-tage li span { font-size: 12px; font-weight: 600; color: var(--text-muted); }
|
||||
.login-tage li b { font-weight: 500; font-size: 20px; font-variant-numeric: tabular-nums; }
|
||||
.login-tage li.ist-heute { background: var(--accent); border-color: var(--accent); }
|
||||
.login-tage li.ist-heute span, .login-tage li.ist-heute b { color: #fff; }
|
||||
@media (prefers-color-scheme: dark) { html:not([data-theme="light"]) .login-tage li.ist-heute span, html:not([data-theme="light"]) .login-tage li.ist-heute b { color: #0b1c26; } }
|
||||
html[data-theme="dark"] .login-tage li.ist-heute span, html[data-theme="dark"] .login-tage li.ist-heute b { color: #0b1c26; }
|
||||
.login-datum { margin: 18px 0 0; color: var(--text-muted); font-size: 15px; }
|
||||
|
||||
@media (max-width: 880px) {
|
||||
.login-raster { grid-template-columns: 1fr; gap: 28px; padding-block: calc(28px + env(safe-area-inset-top, 0px)) 48px; align-content: start; }
|
||||
.login-woche { order: -1; justify-self: start; text-align: left; }
|
||||
.login-kw-zahl { font-size: 110px; }
|
||||
.login-tage { justify-content: flex-start; }
|
||||
.login-tage li { width: auto; flex: 1; max-width: 58px; }
|
||||
.login-wasserzeichen { width: 260vw; top: 0; transform: translate(-30%, -10%); }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) { .login-woche { animation: none; } .login-spinner { animation: none; } }
|
||||
Reference in new issue
Block a user