diff --git a/server/pruef-handy-teamdogi.mjs b/server/pruef-handy-teamdogi.mjs index b9c89f3c..6342b19c 100644 --- a/server/pruef-handy-teamdogi.mjs +++ b/server/pruef-handy-teamdogi.mjs @@ -97,6 +97,7 @@ Dauer: rund drei Minuten (4 Rollen × 2 Breiten × ~20 Seiten). ===================================================================== */ +import { tagLokal } from "./helfer-zeit.mjs"; import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, dirname } from "node:path"; @@ -182,7 +183,11 @@ for (const [titel, wer] of [ + " erstellt, frist) VALUES (?,?,?,?,?,?,?)", titel, "Beschreibung mit genug Text, dass die Karte wirklich Höhe bekommt " + "und ein Umbruch entstehen kann.", "offen", wer, idDogi, jetzt, - new Date(Date.now() + 3 * 86400000).toISOString().slice(0, 10)); + /* Ortszeit, nicht UTC: Zwischen 00:00 und 02:00 deutscher Zeit + liegt UTC noch im Vortag -- die Frist waere dann um einen Tag + verschoben, und die Pruefung schluege nachts falsch an. + Gefunden hat das `pruef-struktur`, nicht ich. */ + tagLokal(3)); } for (const [bereich, titel] of [ diff --git a/server/pruef-nachfrage.mjs b/server/pruef-nachfrage.mjs new file mode 100644 index 00000000..e31c5142 --- /dev/null +++ b/server/pruef-nachfrage.mjs @@ -0,0 +1,274 @@ +/* ===================================================================== + pruef-nachfrage.mjs — Nichts verschwindet ohne Nachfrage. + + Filipe, 19.09.2026: „Es darf vor allem keine Stellen geben, an denen + ein Benutzer etwas falsch machen kann, nur weil die Seite es nicht + verständlich genug erklärt." Und: „Fehler möglichst verhindern, + bevor sie entstehen." + + --------------------------------------------------------------------- + WAS DAS PROBLEM WAR + + Das Haus hatte die richtige Bauweise — einen statt + `confirm()` — und begründete sie in `aufgaben.html` sogar ausführlich. + Nur stand sie IN EINER SEITE. Gemessen am 19.09.2026: **30 Stellen** + in 16 Dateien griffen weiterhin zu `confirm()` oder `prompt()`. + + Der Unterschied ist nicht Geschmack. `confirm('Wirklich löschen?')` + stellt die falsche Frage: Es fragt, ob man sicher ist, und nennt + nicht, WAS passiert, was BLEIBT und ob es ZURÜCK geht. Genau das + sind die drei Dinge, die man vor einem Löschen wissen will. + + --------------------------------------------------------------------- + VIER DINGE WERDEN GEPRÜFT + + 1. KEIN NATIVER DIALOG mehr in einer Seiten-Datei. Ausgenommen ist + allein der Notnagel in `nachfrage.js` selbst — für Browser ohne + . (Ein Verbot ohne diese Ausnahme wäre falsch: Ein + iPhone vor Safari 15.4 bekäme sonst gar nichts angezeigt.) + + 2. ANGESCHLOSSEN — jede Seite, deren Skripte `frageNach` benutzen, + lädt auch `nachfrage.js`. Ohne die Datei wäre `frageNach` nicht + definiert, und aus einer Rückfrage würde ein Absturz: Der Knopf + täte stillschweigend nichts. + + ACHTUNG, hier steckte beim Bauen schon eine Falle: Die erste + Fassung dieser Prüfung zählte `nachfrage.js` SELBST als Nutzer + (die Datei enthält das Wort natürlich) — damit war jede Seite + „Nutzer", die Prüfung immer grün und sie bewies nichts. Deshalb + ist die Datei unten ausdrücklich ausgenommen. + + 3. GESTALTET — `.dialog` wird in einer Datei gestaltet, die JEDE + Seite lädt. Vorher stand sie in `aufgaben.css`; auf `dateien.html` + wäre der Dialog ein weißer Systemkasten auf dunkler Seite + gewesen. Das ist keine Schönheitsfrage: Ein Kasten, der aussieht + wie eine Browser-Warnung, wird weggeklickt statt gelesen. + + 4. VOLLSTÄNDIG — jeder Aufruf hat einen `titel` und sagt, was + passiert (`was`). Ein Dialog ohne diese Angabe ist ein + `confirm()` mit mehr Zeilen Code. + + Dazu GEGENPROBEN: Jede Prüfung muss beweisen, dass sie auch + „nicht in Ordnung" sagen kann. + + AUFRUF: node server/pruef-nachfrage.mjs + Läuft in unter zwei Sekunden, ohne Server. + ===================================================================== */ + +import { readFileSync, readdirSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const HIER = dirname(fileURLToPath(import.meta.url)); +const WURZEL = join(HIER, ".."); +const SEITEN_ORDNER = join(WURZEL, "workspace"); +const JS_ORDNER = join(SEITEN_ORDNER, "assets", "js"); +const CSS_ORDNER = join(SEITEN_ORDNER, "assets", "css"); + +/* Die eine Datei, die `confirm`/`prompt` benutzen DARF -- sie ist der + Notnagel fuer Browser ohne . */ +const DER_NOTNAGEL = "nachfrage.js"; + +let ok = 0, fehl = 0; +const pruef = (name, bedingung, zusatz = "") => { + if (bedingung) { ok++; console.log(` OK ${name}`); } + else { fehl++; console.log(` FEHL ${name}${zusatz ? "\n " + zusatz : ""}`); } +}; + +const lies = (p) => readFileSync(p, "utf8"); +const seiten = readdirSync(SEITEN_ORDNER).filter((f) => f.endsWith(".html")); +const skripte = readdirSync(JS_ORDNER).filter((f) => f.endsWith(".js")); + +console.log("\n=== Nachfragen: kein nativer Dialog, und keiner ohne Erklärung ===\n"); + +/* --------------------------------------------------------------------- + 1. KEIN NATIVER DIALOG + ------------------------------------------------------------------ */ + +/** Entfernt Kommentare, bevor gesucht wird. Ohne das zaehlt jeder + * Kommentar, der `confirm()` ERWAEHNT, als Fund -- und davon gibt es + * in diesem Haus absichtlich mehrere (die Begruendungen). */ +function ohneKommentare(js) { + return js.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1"); +} + +const nativ = []; +for (const f of skripte) { + if (f === DER_NOTNAGEL) continue; + const code = ohneKommentare(lies(join(JS_ORDNER, f))); + for (const m of code.matchAll(/(?:^|[^.\w])(confirm|prompt)\s*\(/g)) { + const zeile = code.slice(0, m.index).split("\n").length; + nativ.push(`${f}:${zeile} → ${m[1]}()`); + } +} +pruef("keine Seite benutzt noch confirm() oder prompt()", nativ.length === 0, + nativ.slice(0, 8).join("\n ")); + +/* Und der Notnagel ist da -- sonst haetten Browser ohne gar + nichts. Die ZAHL gehoert in die Bedingung, nicht nur in den Text. */ +const notnagel = lies(join(JS_ORDNER, DER_NOTNAGEL)); +pruef("der Notnagel für alte Browser ist vorhanden", + /HTMLDialogElement/.test(notnagel) && /window\.confirm\(/.test(notnagel)); + +/* --------------------------------------------------------------------- + 2. ANGESCHLOSSEN + ------------------------------------------------------------------ */ + +/** Welche Skripte rufen frageNach auf? OHNE die Datei, die es + * DEFINIERT -- sonst ist die Antwort immer „alle". */ +const nutzer = new Set(); +for (const f of skripte) { + if (f === DER_NOTNAGEL) continue; + if (/\bfrageNach\s*\(/.test(ohneKommentare(lies(join(JS_ORDNER, f))))) nutzer.add(f); +} +pruef("es gibt überhaupt Seiten, die nachfragen", nutzer.size > 0, + `gefunden: ${nutzer.size}`); + +const ohneDatei = [], totesGewicht = [], fragendeSeiten = []; +let mitNutzung = 0; +for (const s of seiten) { + const html = lies(join(SEITEN_ORDNER, s)); + const geladen = [...html.matchAll(/ - - - - + + + + + +Anruf-Probe · Team Dogi + + + + + + + + + + + +
+ ‹ Zurück +
Anruf-Probe
+
+
+ +
+

Warum klingelt es nicht?

+

+ Diese Seite geht der Reihe nach durch, was ein Anruf braucht – und sagt, + an welcher Stelle es hakt. Sie ruft niemanden an. +

+ +
+ + + +

+
+ + + + + + diff --git a/workspace/app.webmanifest b/workspace/app.webmanifest index 84e425dd..ec680cdb 100644 --- a/workspace/app.webmanifest +++ b/workspace/app.webmanifest @@ -22,25 +22,25 @@ }, "icons": [ { - "src": "/assets/img/app-symbole/workspace-192.png?v=202609191915", + "src": "/assets/img/app-symbole/workspace-192.png?v=202609191956", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-512.png?v=202609191915", + "src": "/assets/img/app-symbole/workspace-512.png?v=202609191956", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609191915", + "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609191956", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609191915", + "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609191956", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/workspace/assets/css/aufgaben.css b/workspace/assets/css/aufgaben.css index 70f6d8c0..8c19b86d 100644 --- a/workspace/assets/css/aufgaben.css +++ b/workspace/assets/css/aufgaben.css @@ -269,132 +269,10 @@ /* ---------- Bearbeiten-Dialog ------------------------------------------ */ -/* ===================================================================== - DIALOGE (07.09.2026 überarbeitet) - - Filipe zu zwei davon: "lass alles in dieser kachel viel spezieller und - geiler aussehen" und "dass soll auch viel besser aussehen". - - Er hatte recht, und der Grund war nicht Geschmack: Ein Dialog war - bisher ein grauer Kasten (`background: #0b1018`, ein Rand, fertig) -- - während die Seite dahinter aus beleuchteten Platten mit Schienen, - Körnung und Glanz besteht. Beim Öffnen fiel man aus dem einen - Material ins andere. - - Jetzt trägt er dieselbe Sprache wie alles übrige: - - Leuchtschiene links, im Hausakzent - - Kopfzeile abgesetzt mit einer feinen Fuge - - Körnung und ein fester Glanz von links oben - - Materialstärke: Licht oben, Schatten unten - Und er ist deutlich TIEFER als vorher (#0b1018 war ein helles Grau - gegen das, was jetzt hinter ihm liegt) -- ein Dialog muss sich vom - Untergrund abheben, sonst schwimmt er darin. - - Der Hintergrund dahinter wird STÄRKER abgedunkelt und weicher - gezeichnet: Ein Dialog ist der einzige Ort, an dem ein Weichzeichner - richtig ist -- er soll das Dahinter ausdrücklich zurücktreten - lassen. Genau dafür ist er gemacht, und genau deshalb war er unter - den Kacheln falsch. - ===================================================================== */ -.dialog { - position: relative; - width: min(580px, calc(100vw - 32px)); - padding: 0; - border: 1px solid rgba(150, 186, 220, .16); - /* DIE FASE STATT RUNDER ECKEN (08.09.2026). - - Filipe: "alles was sie sehen soll dan auch nach der neuen struktur - aufgebaut sein" -- und ein Dialog ist das, was man am genauesten - ansieht, weil er alles andere verdeckt. - - Er kann NICHT in die Modulliste von module.css: Die belegt - `::before` und `::after` fuer die Eckwinkel, und beide sind hier - schon vergeben -- an die Leuchtschiene links und den Lichtsaum. - Beides gegen zwei Winkel zu tauschen waere ein Rueckschritt. - Deshalb hier nur der Zuschnitt, von Hand, mit derselben Groesse - `--fase` wie ueberall. Wer die Fase spaeter aendert, aendert sie - hier mit. */ - clip-path: polygon(var(--fase, 18px) 0, 100% 0, 100% 100%, 0 100%, 0 var(--fase, 18px)); - border-radius: 0; - background: - linear-gradient(90deg, - color-mix(in srgb, var(--akzent) 16%, transparent) 0%, - color-mix(in srgb, var(--akzent) 5%, transparent) 14%, - transparent 40%), - linear-gradient(163deg, #141c29 0%, #0a0e17 58%, #070a11 100%); - color: var(--text); - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, .10), - inset 0 -1px 0 rgba(0, 0, 0, .55), - inset 2px 0 0 -1px color-mix(in srgb, var(--akzent) 34%, transparent), - 0 30px 70px -24px rgba(0, 0, 0, .92), - 0 4px 12px -6px rgba(0, 0, 0, .7); - overflow: hidden; -} -/* Die Leuchtschiene -- dieselbe wie an jeder Kachel. */ -.dialog::before { - content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; - border-radius: 4px 0 0 4px; - background: linear-gradient(180deg, - color-mix(in srgb, var(--akzent) 55%, #fff) 0%, - var(--akzent) 26%, - color-mix(in srgb, var(--akzent) 48%, transparent) 100%); - box-shadow: - 0 0 9px 0 color-mix(in srgb, var(--akzent) 55%, transparent), - 3px 0 20px -3px color-mix(in srgb, var(--akzent) 42%, transparent); - z-index: 2; -} -/* Glanz und Körnung. `pointer-events: none` ist Pflicht: Ohne das läge - eine unsichtbare Fläche über dem ganzen Formular, und kein einziges - Feld wäre anklickbar. */ -.dialog::after { - content: ""; position: absolute; inset: 0; pointer-events: none; - border-radius: inherit; - background: - linear-gradient(122deg, - rgba(255, 255, 255, .075) 0%, - rgba(255, 255, 255, .020) 15%, - transparent 34%); - /* Ohne Körnung -- siehe die Begründung in automation.css: Auf einer - Ebene mit der Spiegelung erbt sie deren Deckkraft und wird zum - grauen Schleier. */ - opacity: .55; - z-index: 1; -} -.dialog > * { position: relative; z-index: 2; } - -.dialog::backdrop { - background: rgba(2, 4, 8, .78); - backdrop-filter: blur(6px) saturate(80%); -} .neu--blank { margin: 0; border: 0; background: none; padding: 22px 24px 20px; } -/* Der Kopf steht auf einer eigenen Stufe: Überschrift, darunter der - erklärende Satz, darunter eine feine Fuge. Ohne diese Trennung - verschwimmt die Ansage mit dem ersten Feld -- und genau die Ansage - ist das, was den Dialog erklärt. */ -.dialog__titel { - margin: 0 0 4px; - font-size: 1.24rem; font-weight: 700; letter-spacing: -.015em; - color: #f2f7fd; -} -.dialog__unter { - margin: 0 0 16px; padding-bottom: 16px; - border-bottom: 1px solid rgba(150, 186, 220, .12); - font-size: .87rem; line-height: 1.55; - color: var(--text-leise); -} -/* Hat ein Dialog keine Erklärung, muss die Fuge trotzdem da sein -- - sonst hängt die Überschrift am ersten Feld. */ -.dialog__titel:last-of-type, -.dialog__unter:empty { border-bottom: 0; } -.dialog__unter:empty { - margin: 0 0 16px; padding-bottom: 16px; - border-bottom: 1px solid rgba(150, 186, 220, .12); -} -.dialog__knoepfe { display: flex; gap: 10px; align-items: center; margin-top: 16px; flex-wrap: wrap; } .dialog__knoepfe #b-loeschen { margin-left: auto; } .abmelden--warnung { color: var(--warn); border-color: rgba(255, 154, 162, .35); } @@ -858,13 +736,6 @@ } .abbruch-karte .schritt { font-size: .8rem; padding: 7px 13px; } -/* ---------- Der Dialog --------------------------------------------------- */ - -.dialog__unter { - margin: -4px 0 14px; - font-size: .85rem; color: var(--text-still); - max-width: 60ch; line-height: 1.5; -} #abbruch-grund { width: 100%; diff --git a/workspace/assets/css/leistung.css b/workspace/assets/css/leistung.css index 1dfe9d07..6ab8370d 100644 --- a/workspace/assets/css/leistung.css +++ b/workspace/assets/css/leistung.css @@ -225,9 +225,6 @@ color: var(--text); border-color: var(--rand-hell); } -/* ---------- Der Import --------------------------------------------------- */ - -.dialog--breit { max-width: 720px; } .import-vorschau { margin: 4px 0 14px; padding: 16px; @@ -355,7 +352,6 @@ .anleitung li::marker { color: var(--akzent); font-weight: 700; } .anleitung strong { color: var(--text-leise); } -.dialog__unter--still { font-size: .8rem; color: var(--text-still); } /* ---- EINGEKLAPPTE HILFE (11.09.2026) ------------------------------ Filipe zum Backstage-Fenster: "die sieht so scheisse aus." @@ -426,10 +422,6 @@ } .feld-datei { flex: 1 1 220px; min-width: 0; font-size: .76rem; } -/* Ein Fenster, das laenger ist als der Bildschirm, versteckt seine - eigenen Knoepfe. Gerollt wird INNEN, damit "Uebernehmen" immer - erreichbar bleibt. */ -.dialog--breit .neu { max-height: min(86vh, 900px); overflow-y: auto; } /* ===================================================================== ZEITRÄUME AUS BACKSTAGE — dritte Fassung (16.09.2026) diff --git a/workspace/assets/css/module.css b/workspace/assets/css/module.css index 250b72dc..248dfa84 100644 --- a/workspace/assets/css/module.css +++ b/workspace/assets/css/module.css @@ -559,3 +559,259 @@ der Rundgang sechsmal gemeldet hat. */ .filterreihe__knopf, .k-chip { min-width: 44px; } } + + +/* ===================================================================== + DER DIALOG — hierher verschoben am 19.09.2026 + + Er stand in `aufgaben.css` und `leistung.css`. Das war richtig, + solange nur diese zwei Seiten einen Dialog hatten. Seit es + `nachfrage.js` gibt, kann JEDE Seite nachfragen, bevor etwas weg + ist -- und auf einer Seite, die `aufgaben.css` nicht laedt, waere + der Dialog ungestaltet gewesen: weisser Kasten, Systemschrift, + mitten auf einer dunklen Seite. + + `module.css` laedt auf jeder Seite (vorletzte Datei, direkt vor + `haus.css`). Was mehr als eine Seite benutzt, gehoert hierher. + + In `aufgaben.css` bleibt genau eine Regel: `.dialog__knoepfe + #b-loeschen` -- die haengt an einer ID, die es nur dort gibt. + ===================================================================== */ +/* ===================================================================== + DIALOGE (07.09.2026 überarbeitet) + + Filipe zu zwei davon: "lass alles in dieser kachel viel spezieller und + geiler aussehen" und "dass soll auch viel besser aussehen". + + Er hatte recht, und der Grund war nicht Geschmack: Ein Dialog war + bisher ein grauer Kasten (`background: #0b1018`, ein Rand, fertig) -- + während die Seite dahinter aus beleuchteten Platten mit Schienen, + Körnung und Glanz besteht. Beim Öffnen fiel man aus dem einen + Material ins andere. + + Jetzt trägt er dieselbe Sprache wie alles übrige: + - Leuchtschiene links, im Hausakzent + - Kopfzeile abgesetzt mit einer feinen Fuge + - Körnung und ein fester Glanz von links oben + - Materialstärke: Licht oben, Schatten unten + Und er ist deutlich TIEFER als vorher (#0b1018 war ein helles Grau + gegen das, was jetzt hinter ihm liegt) -- ein Dialog muss sich vom + Untergrund abheben, sonst schwimmt er darin. + + Der Hintergrund dahinter wird STÄRKER abgedunkelt und weicher + gezeichnet: Ein Dialog ist der einzige Ort, an dem ein Weichzeichner + richtig ist -- er soll das Dahinter ausdrücklich zurücktreten + lassen. Genau dafür ist er gemacht, und genau deshalb war er unter + den Kacheln falsch. + ===================================================================== */ +.dialog { + position: relative; + width: min(580px, calc(100vw - 32px)); + padding: 0; + border: 1px solid rgba(150, 186, 220, .16); + /* DIE FASE STATT RUNDER ECKEN (08.09.2026). + + Filipe: "alles was sie sehen soll dan auch nach der neuen struktur + aufgebaut sein" -- und ein Dialog ist das, was man am genauesten + ansieht, weil er alles andere verdeckt. + + Er kann NICHT in die Modulliste von module.css: Die belegt + `::before` und `::after` fuer die Eckwinkel, und beide sind hier + schon vergeben -- an die Leuchtschiene links und den Lichtsaum. + Beides gegen zwei Winkel zu tauschen waere ein Rueckschritt. + Deshalb hier nur der Zuschnitt, von Hand, mit derselben Groesse + `--fase` wie ueberall. Wer die Fase spaeter aendert, aendert sie + hier mit. */ + clip-path: polygon(var(--fase, 18px) 0, 100% 0, 100% 100%, 0 100%, 0 var(--fase, 18px)); + border-radius: 0; + background: + linear-gradient(90deg, + color-mix(in srgb, var(--akzent) 16%, transparent) 0%, + color-mix(in srgb, var(--akzent) 5%, transparent) 14%, + transparent 40%), + linear-gradient(163deg, #141c29 0%, #0a0e17 58%, #070a11 100%); + color: var(--text); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, .10), + inset 0 -1px 0 rgba(0, 0, 0, .55), + inset 2px 0 0 -1px color-mix(in srgb, var(--akzent) 34%, transparent), + 0 30px 70px -24px rgba(0, 0, 0, .92), + 0 4px 12px -6px rgba(0, 0, 0, .7); + overflow: hidden; +} + +/* Die Leuchtschiene -- dieselbe wie an jeder Kachel. */ +.dialog::before { + content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; + border-radius: 4px 0 0 4px; + background: linear-gradient(180deg, + color-mix(in srgb, var(--akzent) 55%, #fff) 0%, + var(--akzent) 26%, + color-mix(in srgb, var(--akzent) 48%, transparent) 100%); + box-shadow: + 0 0 9px 0 color-mix(in srgb, var(--akzent) 55%, transparent), + 3px 0 20px -3px color-mix(in srgb, var(--akzent) 42%, transparent); + z-index: 2; +} + +/* Glanz und Körnung. `pointer-events: none` ist Pflicht: Ohne das läge + eine unsichtbare Fläche über dem ganzen Formular, und kein einziges + Feld wäre anklickbar. */ +.dialog::after { + content: ""; position: absolute; inset: 0; pointer-events: none; + border-radius: inherit; + background: + linear-gradient(122deg, + rgba(255, 255, 255, .075) 0%, + rgba(255, 255, 255, .020) 15%, + transparent 34%); + /* Ohne Körnung -- siehe die Begründung in automation.css: Auf einer + Ebene mit der Spiegelung erbt sie deren Deckkraft und wird zum + grauen Schleier. */ + opacity: .55; + z-index: 1; +} + +.dialog > * { position: relative; z-index: 2; } + +.dialog::backdrop { + background: rgba(2, 4, 8, .78); + backdrop-filter: blur(6px) saturate(80%); +} + +/* Der Kopf steht auf einer eigenen Stufe: Überschrift, darunter der + erklärende Satz, darunter eine feine Fuge. Ohne diese Trennung + verschwimmt die Ansage mit dem ersten Feld -- und genau die Ansage + ist das, was den Dialog erklärt. */ +.dialog__titel { + margin: 0 0 4px; + font-size: 1.24rem; font-weight: 700; letter-spacing: -.015em; + color: #f2f7fd; +} + +.dialog__unter { + margin: 0 0 16px; padding-bottom: 16px; + border-bottom: 1px solid rgba(150, 186, 220, .12); + font-size: .87rem; line-height: 1.55; + color: var(--text-leise); +} + +/* Hat ein Dialog keine Erklärung, muss die Fuge trotzdem da sein -- + sonst hängt die Überschrift am ersten Feld. */ +.dialog__titel:last-of-type, +.dialog__unter:empty { border-bottom: 0; } + +.dialog__unter:empty { + margin: 0 0 16px; padding-bottom: 16px; + border-bottom: 1px solid rgba(150, 186, 220, .12); +} + +.dialog__knoepfe { display: flex; gap: 10px; align-items: center; margin-top: 16px; flex-wrap: wrap; } + +/* ---------- Der Dialog --------------------------------------------------- */ + +.dialog__unter { + margin: -4px 0 14px; + font-size: .85rem; color: var(--text-still); + max-width: 60ch; line-height: 1.5; +} + +/* ---------- Der Import --------------------------------------------------- */ + +.dialog--breit { max-width: 720px; } + +.dialog__unter--still { font-size: .8rem; color: var(--text-still); } + +/* Ein Fenster, das laenger ist als der Bildschirm, versteckt seine + eigenen Knoepfe. Gerollt wird INNEN, damit "Uebernehmen" immer + erreichbar bleibt. */ +.dialog--breit .neu { max-height: min(86vh, 900px); overflow-y: auto; } + +/* ---- Die zwei Zeilen, die confirm() nicht kann --------------------- + `nachfrage.js` baut den Dialog; diese beiden Teile gibt es nur dort. + + Die Endgueltig-Zeile ist der wichtigste Satz im ganzen Dialog -- + sie beantwortet die einzige Frage, die vor einem Loeschen zaehlt. + Deshalb bekommt sie eine eigene Farbe UND ein Zeichen davor: Farbe + allein traegt keine Aussage (Rot-Gruen-Schwaeche, Kontrastmodus), + und im Kontrastmodus wird `color` ohnehin ersetzt. Das Zeichen + bleibt in jedem Fall. */ +.nachfrage__endgueltig { + margin: 0 0 4px; + padding: 8px 10px; + font-size: .86rem; + line-height: 1.45; + color: #ffd9d2; + background: rgba(190, 74, 60, .13); + border-left: 3px solid rgba(214, 96, 80, .62); +} +.nachfrage__endgueltig::before { content: "! "; font-weight: 800; } + +/* Der Fehler IM Dialog (z. B. fehlender Grund). Er darf nicht + aussehen wie der Fehlerstreifen der Seite dahinter -- der ist + verdeckt, dieser hier gehoert zum Formular. Leer nimmt er keinen + Platz weg, sonst rutschten die Knoepfe beim ersten Fehler. */ +.nachfrage__fehler { margin: 0; font-size: .86rem; color: #ffb4a8; } +.nachfrage__fehler:empty { display: none; } + +/* Am Handy klebt der Dialog sonst am oberen Rand und die Knoepfe + liegen unter der Tastatur. Er waechst von unten, wie ein Blatt, + das hochgezogen wird -- das ist dort die gewohnte Richtung. */ +@media (max-width: 560px) { + .nachfrage { margin: auto auto 0; width: 100vw; max-width: 100vw; } +} + +@media (forced-colors: active) { + .nachfrage__endgueltig { border-left: 3px solid CanvasText; background: Canvas; } +} + +/* Der kleine Hinweis unter einem Feld im Nachfrage-Dialog ("Du kannst + bis zu 14 Tage geben"). Er steht UNTER dem Feld, nicht daneben: + daneben rutscht er am Handy weg, und dort liest ihn niemand. */ +.nachfrage__hinweis { margin: 4px 0 0; font-size: .8rem; color: var(--text-still); } +.nachfrage__hinweis:empty { display: none; } + +/* ---- Der Dialog steht auf eigenen Füßen --------------------------- + NACHGEMESSEN AM 19.09.2026, und es war genau derselbe Fehler wie + bei `.dialog` selbst: Das Formular trug erst die Klassen + `neu neu--blank` — und `.neu` gibt seine Abstände NUR in + `aufgaben.css`. Gemessen auf einer Seite ohne diese Datei: + `padding: 0px`. Der Text klebte am Rand, und die Eingabefelder + verloren ihre `height: 44px` — also ausgerechnet die Größe, die + ein Daumen trifft. + + Am Bildschirm sah es trotzdem "irgendwie richtig" aus, weil die + Schrift und die Farben aus `gate.css` kamen. Solche Abhängigkeiten + sieht man nicht, man misst sie. + + Deshalb steht hier alles, was der Dialog braucht — er borgt nichts + mehr aus einer Seitendatei. `.knopf`, `.abmelden` und `.feld-schild` + bleiben: die stehen in `gate.css` bzw. `start.css`, und die lädt + jede Seite. */ +.nachfrage__form { margin: 0; padding: 20px; display: grid; gap: 10px; } +.nachfrage__zeile { display: grid; gap: 5px; } +.nachfrage__form input, +.nachfrage__form textarea { + width: 100%; + box-sizing: border-box; + font: inherit; + color: var(--text); + background: var(--tinte); + border: 1px solid var(--rand); + border-radius: var(--radius, 10px); + padding: 8px 10px; +} +/* 44 Pixel, weil ein Daumen weniger nicht sicher trifft. Dieselbe Zahl + wie überall im Haus -- sie steht hier, damit sie nicht davon abhängt, + welche Seitendatei zufällig geladen ist. */ +.nachfrage__form input { height: 44px; } +.nachfrage__form textarea { min-height: 62px; resize: vertical; } +.nachfrage__form input:focus, +.nachfrage__form textarea:focus { + outline: none; + box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, .75), + 0 0 0 3px rgba(63, 189, 245, .16); +} +/* Die Knöpfe unten bekommen Luft nach oben -- sonst sitzt "Löschen" + direkt unter dem Satz, der davor warnt. */ +.nachfrage .dialog__knoepfe { margin-top: 6px; } diff --git a/workspace/assets/js/ampel.js b/workspace/assets/js/ampel.js index ba0a18a1..343d0979 100644 --- a/workspace/assets/js/ampel.js +++ b/workspace/assets/js/ampel.js @@ -110,9 +110,17 @@ es sonst ab, und das ist richtig so. Hier wird deshalb gleich danach gefragt statt eine Fehlermeldung zu zeigen. */ if (wert === 'verbessern') { - grund = prompt('Was genau soll verbessert werden?\n\n' - + 'Ohne diesen Satz kann der Creator nichts damit anfangen.', grund) || ''; - if (grund.trim().length < 5) return; + const ag = await frageNach({ + titel: 'Noch verbessern', + was: 'Der Creator sieht diesen Satz an seinem Eintrag.', + bleibt: 'Der Eintrag bleibt stehen – er wird nur als „noch ' + + 'verbessern" markiert und kann überarbeitet werden.', + ja: 'Zurückgeben', + grund: 'Was genau soll verbessert werden?', grundPflicht: true, + platzhalter: 'z. B. Das Licht ist zu dunkel – bitte heller nachdrehen.', + }); + if (!ag) return; + grund = ag.grund; } k.disabled = true; try { @@ -204,7 +212,12 @@ weg.type = 'button'; weg.title = 'Eigene Nachricht zurücknehmen'; weg.addEventListener('click', async () => { - if (!confirm('Diese Nachricht zurücknehmen?')) return; + if (!await frageNach({ + titel: 'Nachricht zurücknehmen?', + was: 'Der Text verschwindet für alle, die ihn noch nicht gelesen haben.', + bleibt: 'Wer ihn schon gelesen hat, erinnert sich trotzdem daran.', + endgueltig: true, ja: 'Zurücknehmen', + })) return; try { const a = await hole(`/workspace/api/eintrag/${eintragId}/nachricht/${n.id}`, { method: 'DELETE' }); diff --git a/workspace/assets/js/aufgaben.js b/workspace/assets/js/aufgaben.js index ce9a7c9a..5f2c5ee0 100644 --- a/workspace/assets/js/aufgaben.js +++ b/workspace/assets/js/aufgaben.js @@ -129,7 +129,12 @@ weg.title = 'Rückmeldung entfernen'; weg.setAttribute('aria-label', 'Rückmeldung entfernen'); weg.addEventListener('click', async () => { - if (!confirm('Diese Rückmeldung entfernen?')) return; + if (!await frageNach({ + titel: 'Rückmeldung entfernen?', + was: 'Sie verschwindet aus der Aufgabe.', + bleibt: 'Die Aufgabe selbst bleibt unverändert stehen.', + endgueltig: true, ja: 'Entfernen', + })) return; const r = await hole('/workspace/api/notizen/' + n.id, { method: 'DELETE' }); if (!r.ok) { melde('Entfernen hat nicht geklappt.'); return; } await laden(); @@ -997,11 +1002,15 @@ }); $('b-loeschen').addEventListener('click', async () => { - if (!confirm(`Aufgabe wirklich loeschen? - -"${bearbeitet.titel}" - -Das laesst sich nicht rueckgaengig machen. Erledigte Aufgaben sollten normalerweise stehen bleiben.`)) return; + /* Loeschen ist hier fast nie das Richtige -- deshalb nennt der + Dialog den sanfteren Weg beim Namen, statt nur zu warnen. */ + if (!await frageNach({ + titel: `„${bearbeitet.titel}" löschen?`, + was: 'Die Aufgabe wird samt Rückmeldungen und Verlauf entfernt.', + bleibt: 'Wenn sie nur nicht mehr stören soll: „Abbrechen" legt sie ' + + 'beiseite, ohne etwas wegzuwerfen – dort ist sie später noch da.', + endgueltig: true, ja: 'Endgültig löschen', + })) return; try { const a = await hole(`/workspace/api/aufgaben/${bearbeitet.id}`, { method: 'DELETE' }); if (!a.ok) { $('b-fehler').textContent = 'Loeschen ging nicht.'; return; } diff --git a/workspace/assets/js/bereich.js b/workspace/assets/js/bereich.js index 4c374310..cda22688 100644 --- a/workspace/assets/js/bereich.js +++ b/workspace/assets/js/bereich.js @@ -518,8 +518,13 @@ b.type = 'button'; b.title = 'Schickt Art, Titel und Text als Nachricht in den Chat.'; b.addEventListener('click', async () => { - if (!confirm(`„${e.titel}“ als Nachricht schicken?\n\n` - + 'Die Person bekommt Art, Titel und Text im Chat – einmalig.')) return; + if (!await frageNach({ + titel: `„${e.titel}" als Nachricht schicken?`, + was: 'Die Person bekommt Art, Titel und Text im Chat – einmalig.', + bleibt: 'Der Eintrag bleibt hier stehen. Zurückholen lässt sich ' + + 'die Nachricht nicht, sobald sie unterwegs ist.', + ja: 'Schicken', + })) return; b.disabled = true; const a = await hole(`/workspace/api/bereich/entwicklung/${e.id}/senden`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); @@ -897,9 +902,17 @@ const vomTeam = !!e.erstellt_rolle && e.erstellt_rolle !== 'gast'; if (!lage.team && e.erstellt_von !== ich.id && !vomTeam) { zeile.append(tuKnopf('melden', async () => { - const grund = prompt('Was ist daran nicht in Ordnung?\n\n' - + 'Bitte schreib es in einem Satz – sonst können wir es nicht prüfen.'); - if (grund === null) return; + const a0 = await frageNach({ + titel: 'Diesen Beitrag melden?', + was: 'Das Team sieht sich den Beitrag an. Du bleibst dabei ungenannt.', + bleibt: 'Der Beitrag bleibt vorerst stehen – gemeldet heißt noch ' + + 'nicht entfernt.', + ja: 'Melden', + grund: 'Was ist daran nicht in Ordnung?', grundPflicht: true, + platzhalter: 'Bitte in einem Satz – sonst können wir es nicht prüfen.', + }); + if (!a0) return; + const grund = a0.grund; const a = await hole('/workspace/api/treff/eintrag/' + e.id + '/melden', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grund }), @@ -956,7 +969,13 @@ dass er einer wird, entscheidet ein Mensch. */ if (bereich === 'mitmachen' && e.erstellt_rolle === 'gast') { zeile.append(tuKnopf('zu den Talenten', async () => { - if (!confirm('„' + e.titel + '“ zu den Talenten übernehmen?')) return; + if (!await frageNach({ + titel: '„' + e.titel + '" zu den Talenten übernehmen?', + was: 'Die Person erscheint danach in der Talente-Liste.', + bleibt: 'Der Beitrag hier bleibt stehen. Übernehmen heißt noch ' + + 'keine Zusage – es entscheidet weiterhin ein Mensch.', + ja: 'Übernehmen', + })) return; const a = await hole('/workspace/api/treff/mitmachen/' + e.id + '/uebernehmen', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' }); const j = await a.json().catch(() => ({})); @@ -971,9 +990,17 @@ fuer den eigenen Beitrag, und der braucht keine Begruendung. */ if (e.erstellt_von !== ich.id) { zeile.append(tuKnopf('entfernen', async () => { - const grund = prompt('Warum wird „' + e.titel + '“ entfernt?\n\n' - + 'Der Grund wird festgehalten – die Person hat ein Recht darauf.'); - if (grund === null) return; + const a1 = await frageNach({ + titel: '„' + e.titel + '" entfernen?', + was: 'Der Beitrag verschwindet vom Brett.', + bleibt: 'Der Grund wird festgehalten und der Person mitgeteilt – ' + + 'sie hat ein Recht darauf (DSA Art. 17).', + endgueltig: true, ja: 'Entfernen', + grund: 'Warum wird er entfernt?', grundPflicht: true, + platzhalter: 'z. B. Beleidigende Sprache gegenüber einem anderen Mitglied.', + }); + if (!a1) return; + const grund = a1.grund; /* DER GRUND REIST IN DER ADRESSE, nicht im Koerper -- aus demselben gemessenen Grund wie oben. Er ist kein Geheimnis: Er wird der Person, die den Beitrag @@ -1208,7 +1235,12 @@ if (LEITUNG.has(ich.rolle) || e.erstellt_von === ich.id) { knoepfe.append(tuKnopf('löschen', async () => { - if (!confirm(`„${e.titel}" wirklich löschen?`)) return; + if (!await frageNach({ + titel: `„${e.titel}" löschen?`, + was: 'Der Eintrag verschwindet vom Brett – für alle.', + bleibt: 'Nachrichten, die dazu geschrieben wurden, gehen mit.', + endgueltig: true, ja: 'Löschen', + })) return; const a = await hole(`/workspace/api/bereich/${bereich}/${e.id}`, { method: 'DELETE' }); if (!a.ok) { melde('Löschen hat nicht geklappt.'); return; } await laden(); diff --git a/workspace/assets/js/calls.js b/workspace/assets/js/calls.js index ad719794..397802b9 100644 --- a/workspace/assets/js/calls.js +++ b/workspace/assets/js/calls.js @@ -368,11 +368,13 @@ if (ich?.rolle === 'admin') { const weg = el('div', 'kk__knoepfe'); weg.append(tuKnopf('Protokoll löschen', async () => { - if (!confirm('Protokoll zu „' + c.titel + '" löschen?\n\n' - + 'Der Text ist danach weg und lässt sich nicht wiederholen.\n\n' - + 'Das Gespräch selbst bleibt im Kalender und steht danach ' - + 'wieder unter „Protokoll fehlt".\n\n' - + 'Bereits daraus entstandene Aufgaben bleiben ebenfalls stehen.')) return; + if (!await frageNach({ + titel: 'Protokoll zu „' + c.titel + '" löschen?', + was: 'Der Text ist danach weg und lässt sich nicht wiederholen.', + bleibt: 'Das Gespräch bleibt im Kalender und steht danach wieder ' + + 'unter „Protokoll fehlt". Daraus entstandene Aufgaben bleiben auch.', + endgueltig: true, ja: 'Protokoll löschen', + })) return; const a = await hole('/workspace/api/calls/' + c.id + '/protokoll', { method: 'DELETE' }); if (!a.ok) { melde(sagWas((await a.json().catch(() => ({}))).fehler, 'Löschen ging nicht.')); diff --git a/workspace/assets/js/chat.js b/workspace/assets/js/chat.js index 46b0ec40..ea5b5ffc 100644 --- a/workspace/assets/js/chat.js +++ b/workspace/assets/js/chat.js @@ -1418,8 +1418,12 @@ } async function zuruecknehmen(id) { - if (!window.confirm('Diese Nachricht zurücknehmen? Der Text ist dann weg, ' - + 'im Verlauf bleibt ein Hinweis stehen.')) return; + if (!await frageNach({ + titel: 'Nachricht zurücknehmen?', + was: 'Der Text ist danach weg – auch bei allen anderen.', + bleibt: 'Im Verlauf bleibt ein Hinweis stehen, dass hier etwas stand.', + endgueltig: true, ja: 'Zurücknehmen', + })) return; try { const a = await hole(`/workspace/api/chat/nachrichten/${id}`, { method: 'DELETE' }); if (!a.ok) { melde('Ging nicht.'); return; } @@ -2220,11 +2224,13 @@ $('gespraech-weg').addEventListener('click', async () => { if (!offen) return; const wer = offen.name; - if (!window.confirm( - `Gespräch mit ${wer} wegräumen?\n\n` - + 'Es verschwindet nur bei dir. Der Verlauf beim Gegenüber bleibt ' - + 'vollständig.\n\nSchreibt euch jemand wieder, kommt das Gespräch ' - + 'mit dem Neuen zurück – das Alte bleibt weg.')) return; + if (!await frageNach({ + titel: `Gespräch mit ${wer} wegräumen?`, + was: 'Es verschwindet nur bei dir aus der Liste.', + bleibt: `Der Verlauf bei ${wer} bleibt vollständig. Schreibt ihr euch ` + + 'wieder, kommt das Gespräch mit dem Neuen zurück – das Alte bleibt weg.', + ja: 'Wegräumen', + })) return; try { const a = await hole(`/workspace/api/chat/raeume/${offen.id}`, { method: 'DELETE' }); if (!a.ok) { melde('Ging nicht.'); return; } @@ -2252,13 +2258,14 @@ if (!offen || !offen.darf_aufloesen) return; const wasIstEs = offen.art === 'kanal' ? 'Kanal' : 'Gruppe'; const andere = Math.max(0, (offen.teilnehmer?.length || 1) - 1); - if (!window.confirm( - `${wasIstEs} „${offen.name}" für alle auflösen?\n\n` - + `Der ganze Verlauf wird gelöscht – auch bei ${andere === 1 - ? 'der anderen Person' : `den ${andere} anderen`}, samt aller ` - + 'Anhänge. Das lässt sich nicht rückgängig machen.\n\n' - + 'Wenn du sie nur bei dir loswerden willst, nimm den Knopf ' - + 'daneben – dann behalten die anderen alles.')) return; + if (!await frageNach({ + titel: `${wasIstEs} „${offen.name}" für alle auflösen?`, + was: `Der ganze Verlauf wird gelöscht – auch bei ${andere === 1 + ? 'der anderen Person' : `den ${andere} anderen`}, samt aller Anhänge.`, + bleibt: 'Wenn du sie nur bei dir loswerden willst, nimm den Knopf ' + + 'daneben – dann behalten die anderen alles.', + endgueltig: true, ja: 'Für alle auflösen', + })) return; const knopf = $('raum-aufloesen'); knopf.disabled = true; try { diff --git a/workspace/assets/js/checkliste.js b/workspace/assets/js/checkliste.js index 72fb03e4..46e3fefe 100644 --- a/workspace/assets/js/checkliste.js +++ b/workspace/assets/js/checkliste.js @@ -440,9 +440,17 @@ const neu = stufe === wert ? 'offen' : wert; let grund = stand?.begruendung || ''; if (neu === 'verbessern') { - grund = prompt(`„${p.titel}“\n\nWas genau soll verbessert werden?\n\n` - + 'Ohne diesen Satz kann er nichts damit anfangen.', grund) || ''; - if (grund.trim().length < 5) return; + const ag = await frageNach({ + titel: `„${p.titel}" – noch verbessern`, + was: 'Dein Satz steht danach an diesem Punkt.', + bleibt: 'Der Punkt bleibt offen und kann jederzeit wieder ' + + 'auf „in Ordnung" gesetzt werden.', + ja: 'Zurückgeben', + grund: 'Was genau soll verbessert werden?', grundPflicht: true, + platzhalter: 'z. B. Fehlt noch das Impressum unten auf der Seite.', + }); + if (!ag) return; + grund = ag.grund; } b.disabled = true; try { @@ -549,7 +557,12 @@ weg.type = 'button'; weg.title = 'Eigene Nachricht zurücknehmen'; weg.addEventListener('click', async () => { - if (!confirm('Diese Nachricht zurücknehmen?')) return; + if (!await frageNach({ + titel: 'Nachricht zurücknehmen?', + was: 'Der Text verschwindet aus diesem Punkt.', + bleibt: 'Der Punkt selbst und sein Stand bleiben unverändert.', + endgueltig: true, ja: 'Zurücknehmen', + })) return; try { const a = await hole(`/workspace/api/checkliste/nachricht/${n.id}`, { method: 'DELETE' }); diff --git a/workspace/assets/js/content.js b/workspace/assets/js/content.js index 301c5af1..d3102718 100644 --- a/workspace/assets/js/content.js +++ b/workspace/assets/js/content.js @@ -213,7 +213,12 @@ knoepfe.append(tuKnopf('→ LIVE', 'Als LIVE-Thema vormerken', () => uebernehmen(e, 'live'))); } knoepfe.append(tuKnopf('löschen', 'Dieses Video entfernen', async () => { - if (!confirm(`„${e.titel}" wirklich löschen?`)) return; + if (!await frageNach({ + titel: `„${e.titel}" löschen?`, + was: 'Die Idee verschwindet aus der Planung.', + bleibt: 'Ein schon eingetragener Drehtermin im Kalender bleibt stehen.', + endgueltig: true, ja: 'Löschen', + })) return; const a = await hole(`/workspace/api/bereich/content/${e.id}`, { method: 'DELETE' }); if (!a.ok) { melde('Löschen hat nicht geklappt.'); return; } await laden(); @@ -383,7 +388,13 @@ Ausgeblendet ist nicht dasselbe wie nicht vorhanden. */ if (!darfEintragen()) { ziel.append(z); continue; } z.append(tuKnopf('löschen', 'Säule entfernen, Videos bleiben', async () => { - if (!confirm(`Säule „${s.name}" entfernen? Die Videos bleiben, sie verlieren nur die Zuordnung.`)) return; + if (!await frageNach({ + titel: `Säule „${s.name}" entfernen?`, + was: 'Die Säule verschwindet aus der Auswahl.', + bleibt: 'Alle Videos bleiben – sie stehen danach nur ohne Säule da ' + + 'und lassen sich jederzeit einer anderen zuordnen.', + ja: 'Säule entfernen', + })) return; const a = await hole(`/workspace/api/content/saeulen/${s.id}`, { method: 'DELETE' }); if (!a.ok) { melde('Ging nicht.'); return; } await laden(); diff --git a/workspace/assets/js/dateien.js b/workspace/assets/js/dateien.js index 59433697..9ff6cd1c 100644 --- a/workspace/assets/js/dateien.js +++ b/workspace/assets/js/dateien.js @@ -220,7 +220,12 @@ } if (LEITUNG.has(ich.rolle) || (d.hochgeladen_von === ich.id && d.status !== 'freigegeben')) { knoepfe.append(tuKnopf('löschen', async () => { - if (!confirm(`„${d.name_original}" wirklich löschen?`)) return; + if (!await frageNach({ + titel: `„${d.name_original}" löschen?`, + was: 'Die Datei wird vom Server entfernt.', + bleibt: 'Wer sie schon heruntergeladen hat, behält seine Kopie.', + endgueltig: true, ja: 'Löschen', + })) return; const a = await hole(`/workspace/api/dateien/${d.id}`, { method: 'DELETE' }); if (!a.ok) { melde('Löschen hat nicht geklappt.'); return; } await laden(); diff --git a/workspace/assets/js/hilfe.js b/workspace/assets/js/hilfe.js index f12d5fd9..b01c9a21 100644 --- a/workspace/assets/js/hilfe.js +++ b/workspace/assets/js/hilfe.js @@ -287,8 +287,25 @@ } async function fallSchliessen(id) { - const wort = prompt('Ein Schlusswort? (Kann auch leer bleiben)'); - if (wort === null) return; + /* DER EINZIGE WEG IST VORWAERTS. Gemessen am 19.09.2026: Es gibt + keine Route, die einen geschlossenen Fall wieder oeffnet -- weder + fuer die Leitung noch fuer die meldende Person. Ein Klick hier + ist also endgueltig, und vorher stand darueber nur die Frage + nach einem Schlusswort. Wer sie las, konnte nicht ahnen, dass + damit der Fall zugeht. */ + const antwort = await frageNach({ + titel: 'Diesen Fall abschließen?', + was: 'Der Fall gilt danach als erledigt. Es kann niemand mehr ' + + 'antworten – auch die Person nicht, die ihn gemeldet hat.', + bleibt: 'Der ganze Verlauf bleibt lesbar. Wieder aufmachen lässt ' + + 'sich der Fall aber nicht – dafür müsste er neu gemeldet werden.', + endgueltig: true, + ja: 'Abschließen', + grund: 'Ein Schlusswort für die Person? (darf leer bleiben)', + platzhalter: 'z. B. Wir haben mit beiden gesprochen, es ist geklärt.', + }); + if (!antwort) return; + const wort = antwort.grund; try { const a = await hole('/workspace/api/hilfe/' + id + '/schliessen', { method: 'POST', diff --git a/workspace/assets/js/kalender-abo.js b/workspace/assets/js/kalender-abo.js index ba8d8ced..b8d516ec 100644 --- a/workspace/assets/js/kalender-abo.js +++ b/workspace/assets/js/kalender-abo.js @@ -64,10 +64,13 @@ } async function erzeugen(erneuern) { - if (erneuern && !window.confirm( - 'Neuen Link erzeugen?\n\nDer alte hört im selben Moment auf zu funktionieren. ' - + 'Ein Kalender, der ihn abonniert hat, bekommt danach keine Termine mehr, ' - + 'bis du ihm den neuen gibst.')) return; + if (erneuern && !await frageNach({ + titel: 'Neuen Link erzeugen?', + was: 'Der alte hört im selben Moment auf zu funktionieren.', + bleibt: 'Deine Termine selbst bleiben. Ein Kalender, der den alten Link ' + + 'abonniert hat, bekommt aber keine mehr – bis du ihm den neuen gibst.', + endgueltig: true, ja: 'Neuen Link erzeugen', + })) return; melde(''); try { const a = await hole('/workspace/api/ics', { @@ -83,9 +86,13 @@ } async function abschalten() { - if (!window.confirm( - 'Abschalten?\n\nDeine Termine verschwinden dann aus jedem Kalender, ' - + 'der sie abonniert hat.')) return; + if (!await frageNach({ + titel: 'Kalender-Link abschalten?', + was: 'Deine Termine verschwinden aus jedem Kalender, der sie abonniert hat.', + bleibt: 'Die Termine selbst bleiben hier im Workspace vollständig stehen. ' + + 'Du kannst jederzeit einen neuen Link erzeugen.', + ja: 'Abschalten', + })) return; melde(''); try { const a = await hole('/workspace/api/ics', { method: 'DELETE' }); diff --git a/workspace/assets/js/kalender.js b/workspace/assets/js/kalender.js index d2fb6da3..ff57f878 100644 --- a/workspace/assets/js/kalender.js +++ b/workspace/assets/js/kalender.js @@ -949,11 +949,14 @@ if (s.darf_aendern) { const knoepfe = el('div', 'k-serie__knoepfe'); knoepfe.append(tuKnopf(s.aktiv ? 'abstellen' : 'wieder starten', async () => { - if (s.aktiv && !confirm( - 'Wiederholung „' + s.titel + '" abstellen?\n\n' - + 'Kommende Termine, die noch niemand angefasst hat, werden aus dem ' - + 'Kalender genommen. Vergangene und bearbeitete Termine bleiben stehen.\n\n' - + 'Du kannst sie jederzeit wieder starten.')) return; + if (s.aktiv && !await frageNach({ + titel: 'Wiederholung „' + s.titel + '" abstellen?', + was: 'Kommende Termine, die noch niemand angefasst hat, werden aus ' + + 'dem Kalender genommen.', + bleibt: 'Vergangene und bearbeitete Termine bleiben stehen. Du kannst ' + + 'die Wiederholung jederzeit wieder starten.', + ja: 'Abstellen', + })) return; const a = await hole('/workspace/api/serien/' + s.id, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, @@ -963,10 +966,14 @@ await laden(); })); knoepfe.append(tuKnopf('löschen', async () => { - if (!confirm('Wiederholung „' + s.titel + '" ganz löschen?\n\n' - + 'Die Regel ist damit weg. Kommende, unangetastete Termine werden ' - + 'entfernt; vergangene und bearbeitete bleiben als normale Termine ' - + 'stehen.')) return; + if (!await frageNach({ + titel: 'Wiederholung „' + s.titel + '" ganz löschen?', + was: 'Die Regel ist damit weg. Kommende, noch unangetastete Termine ' + + 'werden entfernt.', + bleibt: 'Vergangene und schon bearbeitete Termine bleiben als ' + + 'normale Termine stehen.', + endgueltig: true, ja: 'Wiederholung löschen', + })) return; const a = await hole('/workspace/api/serien/' + s.id, { method: 'DELETE' }); if (!a.ok) { melde('Löschen ging nicht.'); return; } await laden(); @@ -1221,12 +1228,20 @@ dass NUR dieser eine Tag entfällt. Sonst löscht jemand ihn in der Annahme, die Wiederholung sei damit abgestellt -- und wundert sich nächste Woche. */ - const frage = e.serie_id - ? 'Nur diesen einen Termin am ' + tagLang(e.tag) + ' streichen?\n\n' - + 'Die Wiederholung „' + e.titel + '" läuft weiter. Zum Abstellen ' - + 'den Schalter unter „Läuft von allein" benutzen.' - : 'Termin „' + e.titel + '" löschen?'; - if (!confirm(frage)) return; + + if (!await frageNach({ + titel: e.serie_id + ? 'Nur diesen einen Termin am ' + tagLang(e.tag) + ' streichen?' + : 'Termin „' + e.titel + '" löschen?', + was: e.serie_id + ? 'Nur dieser eine Tag entfällt.' + : 'Der Termin verschwindet aus dem Kalender.', + bleibt: e.serie_id + ? 'Die Wiederholung „' + e.titel + '" läuft weiter. Zum Abstellen ' + + 'den Schalter unter „Läuft von allein" benutzen.' + : 'Alle anderen Termine bleiben stehen.', + endgueltig: true, ja: e.serie_id ? 'Diesen Tag streichen' : 'Löschen', + })) return; const a = await hole('/workspace/api/termine/' + e.id, { method: 'DELETE' }); if (!a.ok) { melde('Löschen ging nicht.'); return; } await laden(); diff --git a/workspace/assets/js/leistung.js b/workspace/assets/js/leistung.js index 6517e302..da4ab7df 100644 --- a/workspace/assets/js/leistung.js +++ b/workspace/assets/js/leistung.js @@ -404,7 +404,13 @@ async function tagLoeschen() { const d = $('tag-dialog'); - if (!window.confirm('Diese Zeile wirklich löschen? Die Zahlen des Tages sind dann weg.')) return; + if (!await frageNach({ + titel: 'Zahlen dieses Tages löschen?', + was: 'Die eingetragenen Zahlen für diesen Tag werden entfernt.', + bleibt: 'Alle anderen Tage bleiben unverändert. Du kannst den Tag ' + + 'jederzeit neu eintragen.', + endgueltig: true, ja: 'Zeile löschen', + })) return; try { const a = await hole(`/workspace/api/leistung/${offenerCreator}/${d.dataset.tag}`, { method: 'DELETE' }); diff --git a/workspace/assets/js/nachfrage.js b/workspace/assets/js/nachfrage.js new file mode 100644 index 00000000..706fb51b --- /dev/null +++ b/workspace/assets/js/nachfrage.js @@ -0,0 +1,326 @@ +/* ===================================================================== + NACHFRAGEN, BEVOR ETWAS WEG IST — window.frageNach() + + Filipe, 19.09.2026: „Es darf vor allem keine Stellen geben, an denen + ein Benutzer etwas falsch machen kann, nur weil die Seite es nicht + verstaendlich genug erklaert." Und: „Fehler moeglichst verhindern, + bevor sie entstehen." + + --------------------------------------------------------------------- + WARUM ES DIESE DATEI GIBT + + Das Haus hatte die richtige Bauweise laengst -- in `aufgaben.html` + steht sie sogar begruendet: ein , kein confirm(), weil + confirm die ganze Seite anhaelt, kein Textfeld aufnimmt und auf + jedem Rechner anders aussieht. + + Nur stand diese Bauweise IN EINER SEITE. Wer auf einer anderen Seite + etwas loeschen liess, hatte sie nicht -- und griff zu confirm(). + Gemessen am 19.09.2026: 30 Stellen im Workspace, in 16 Dateien. + Also wandert sie hierher, wo jede Seite sie hat. + + Das ist dieselbe Lehre wie bei den Fehlermeldungen (`meldung.js`) + und bei den Kachelfarben: Was an 30 Stellen gepflegt werden muss, + wird an 30 Stellen unterschiedlich. Eine Stelle, die alle benutzen, + kann nicht auseinanderlaufen. + + --------------------------------------------------------------------- + WAS EIN GUTER NACHFRAGE-DIALOG SAGT + + confirm('Wirklich loeschen?') stellt die falsche Frage. Es fragt, ob + man sicher ist -- und wer soll das wissen, wenn nicht dasteht, was + danach passiert? Der Dialog hier beantwortet drei Dinge: + + 1. WAS passiert -- "Die Datei wird geloescht." + 2. Was NICHT passiert -- "Der Chat-Verlauf bleibt." + 3. Ob es ZURUECK geht -- "Das laesst sich nicht rueckgaengig machen." + + Punkt 3 ist der wichtigste und in confirm() gar nicht ausdrueckbar. + Deshalb traegt der Bestaetigungsknopf bei `endgueltig: true` eine + sichtbare Warnfarbe UND der Text sagt es noch einmal in Worten -- + Farbe allein traegt keine Aussage (Rot-Gruen-Schwaeche, Kontrastmodus). + + --------------------------------------------------------------------- + DREI AUSGAENGE, wie ueberall im Haus + + vorhanden -> der richtige Dialog + fehlt (alt) -> confirm() als Notnagel, mit DEMSELBEN + Text, damit der Nutzer dieselbe + Auskunft bekommt -- nur haesslicher + Nutzer bricht ab -> false, und zwar immer: bei Esc, beim + Klick daneben und beim "Doch nicht" + + Der mittlere Ausgang ist nicht theoretisch: showModal gibt es erst ab + Safari 15.4. Ein iPhone, das nicht aktualisiert wurde, wuerde ohne + Notnagel gar nichts anzeigen -- und der Knopf taete stillschweigend + nichts. Das waere schlimmer als ein haesslicher Dialog. + + --------------------------------------------------------------------- + AUFRUF + + if (!await frageNach({ + titel: 'Datei loeschen?', + was: 'Die Datei wird vom Server entfernt.', + bleibt:'Die Nachricht im Chat bleibt stehen.', + endgueltig: true, + ja: 'Loeschen', + })) return; + + Mit Grund (gibt dann { grund } statt true zurueck): + + const a = await frageNach({ titel: '...', grund: 'Warum?', + grundPflicht: true }); + if (!a) return; // abgebrochen + ... a.grund ... + ===================================================================== */ + +(function () { + 'use strict'; + + /* Ein einziger Dialog fuer die ganze Seite. Er wird beim ersten + Gebrauch gebaut und danach wiederverwendet -- zwei offene Dialoge + gleichzeitig kann der Browser ohnehin nicht, und ein neuer je + Aufruf wuerde den Fokus verlieren. */ + var dlg = null, feld = null, tippfeld = null, zahlfeld = null, fehlerZeile = null; + + function bauen() { + if (dlg) return dlg; + dlg = document.createElement('dialog'); + dlg.className = 'dialog nachfrage'; + dlg.innerHTML = + '
' + + '

' + + '

' + + '

' + + '' + + '' + + '' + + '' + + '' + + '
' + + '' + + '' + + '
'; + document.body.appendChild(dlg); + feld = dlg.querySelector('#nachfrage-grund'); + tippfeld = dlg.querySelector('#nachfrage-tipp'); + zahlfeld = dlg.querySelector('#nachfrage-zahl'); + fehlerZeile = dlg.querySelector('[data-teil="fehler"]'); + return dlg; + } + + function teil(name) { return dlg.querySelector('[data-teil="' + name + '"]'); } + + /** Setzt Text und blendet die Zeile aus, wenn es keinen gibt. + * Eine leere Zeile, die Platz einnimmt, sieht aus wie ein Fehler. */ + function zeile(name, text) { + var e = teil(name); + e.textContent = text || ''; + e.hidden = !text; + } + + window.frageNach = function frageNach(o) { + o = o || {}; + var titel = o.titel || 'Sicher?'; + var was = o.was || ''; + var bleibt = o.bleibt || ''; + var ja = o.ja || 'Ja, machen'; + var nein = o.nein || 'Doch nicht'; + var endgueltig = !!o.endgueltig; + var grund = o.grund || ''; + var grundPflicht = !!o.grundPflicht; + var platzhalter = o.platzhalter || ''; + /* ABTIPPEN STATT ANKLICKEN. Fuer die Handgriffe, bei denen ein + Fehlklick nicht zu reparieren ist (eine Person loeschen). Wer den + Namen abtippt, hat ihn gelesen -- das ist der eigentliche Zweck, + nicht die Huerde. */ + var tippen = o.tippen || ''; + /* EIN EINZEILIGES FELD, wenn nach einem Namen gefragt wird und + nicht nach einem Grund. Ein Textfeld ueber drei Zeilen fuer einen + Vornamen sieht aus, als erwarte jemand einen Aufsatz. Benutzt + dasselbe Feld wie `tippen` -- beides gleichzeitig kommt nicht vor + und waere auch nicht sinnvoll. */ + var eingabe = o.eingabe || ''; + var eingabeWert = o.eingabeWert || ''; + var eingabeMin = o.eingabeMin === undefined ? 2 : o.eingabeMin; + /* EINE ZAHL IM SELBEN DIALOG. Vorher fragte die Moderation zweimal + hintereinander (Grund, dann Dauer) -- zwei Kaesten nacheinander, + und wer beim zweiten abbrach, hatte den ersten umsonst getippt. + Reihenfolge bleibt: erst WARUM, dann WIE LANGE. Wer zuerst nach + der Dauer gefragt wird, hat die Strafe festgelegt, bevor er sie + begruendet hat. */ + var zahl = o.zahl || ''; + var zahlWert = o.zahlWert === undefined ? '' : String(o.zahlWert); + var zahlMax = o.zahlMax || 0; + var zahlLeer = !!o.zahlLeer; + var zahlHinweis = o.zahlHinweis || ''; + var NIE_ZURUECK = 'Das lässt sich danach nicht mehr rückgängig machen.'; + + /* ---- Ausgang 2: kein -> confirm() mit DEMSELBEN Text ---- + Nicht "Sicher?" -- wer den Notnagel bekommt, soll dieselbe + Auskunft haben wie alle anderen. */ + if (typeof HTMLDialogElement === 'undefined' + || !HTMLDialogElement.prototype.showModal) { + var text = [titel, was, bleibt, endgueltig ? NIE_ZURUECK : ''] + .filter(Boolean).join('\n\n'); + if (!window.confirm(text)) return Promise.resolve(false); + if (tippen) { + var t0 = window.prompt('Zum Bestätigen genau eingeben: ' + tippen, ''); + if (t0 === null || t0.trim() !== tippen) return Promise.resolve(false); + } + var erg = {}; + if (eingabe) { + var e0 = window.prompt(eingabe, eingabeWert); + if (e0 === null || e0.trim().length < eingabeMin) return Promise.resolve(false); + erg.eingabe = e0.trim(); + } + if (grund) { + var g0 = window.prompt(grund, ''); + if (g0 === null) return Promise.resolve(false); + if (grundPflicht && g0.trim().length < 3) return Promise.resolve(false); + erg.grund = g0.trim(); + } + if (zahl) { + var z0 = window.prompt(zahl + (zahlHinweis ? ' (' + zahlHinweis + ')' : ''), + zahlWert); + if (z0 === null) return Promise.resolve(false); + erg.zahl = z0.trim() === '' ? null : Number(z0); + } + return Promise.resolve((grund || zahl || eingabe) ? erg : true); + } + + bauen(); + teil('titel').textContent = titel; + zeile('was', was); + zeile('bleibt', bleibt); + teil('endgueltig').hidden = !endgueltig; + teil('ja').textContent = ja; + teil('nein').textContent = nein; + /* Warnfarbe NUR zusaetzlich zum Satz oben, nie statt seiner. */ + teil('ja').classList.toggle('knopf--warn', endgueltig); + teil('tippzeile').hidden = !(tippen || eingabe); + if (eingabe) { + teil('tippschild').textContent = eingabe; + tippfeld.value = eingabeWert; + tippfeld.placeholder = ''; + } else if (tippen) { + teil('tippschild').textContent = 'Zum Bestätigen genau eingeben: ' + tippen; + tippfeld.value = ''; + /* KEIN Platzhalter mit dem erwarteten Wort. Er sieht in einem + leeren Feld aus wie ein bereits eingetragener Text -- und wer + glaubt, es stehe schon da, drueckt auf "Loeschen" und wundert + sich ueber die Fehlermeldung. Der Name steht ohnehin in der + Beschriftung direkt darueber. */ + tippfeld.placeholder = ''; + } + teil('grundzeile').hidden = !grund; + if (grund) { + teil('grundschild').textContent = grund; + feld.value = ''; + feld.placeholder = platzhalter; + } + teil('zahlzeile').hidden = !zahl; + if (zahl) { + teil('zahlschild').textContent = zahl; + teil('zahlhinweis').textContent = zahlHinweis; + zahlfeld.value = zahlWert; + if (zahlMax) zahlfeld.max = String(zahlMax); else zahlfeld.removeAttribute('max'); + zahlfeld.required = !zahlLeer; + } + fehlerZeile.textContent = ''; + + return new Promise(function (fertig) { + var antwort = false; + var form = dlg.querySelector('form'); + + function aufraeumen() { + dlg.removeEventListener('close', beiSchliessen); + form.removeEventListener('submit', beiJa); + teil('nein').removeEventListener('click', beiNein); + dlg.removeEventListener('click', beiDaneben); + } + function beiSchliessen() { aufraeumen(); fertig(antwort); } + function beiNein() { antwort = false; dlg.close(); } + function beiDaneben(e) { + /* Klick auf den abgedunkelten Rand = abbrechen. Das erwartet + jeder, und ohne es bleibt der Dialog am Handy gefuehlt + haengen, weil dort kein Esc zur Verfuegung steht. */ + if (e.target === dlg) { antwort = false; dlg.close(); } + } + function beiJa(e) { + e.preventDefault(); + if (eingabe && tippfeld.value.trim().length < eingabeMin) { + fehlerZeile.textContent = eingabeMin > 1 + ? 'Bitte mindestens ' + eingabeMin + ' Zeichen eintragen.' + : 'Bitte etwas eintragen.'; + tippfeld.focus(); return; + } + if (tippen && tippfeld.value.trim() !== tippen) { + /* Sagt, WAS nicht stimmt -- "falsch" allein hilft niemandem, + der sich vertippt hat. */ + fehlerZeile.textContent = 'Das stimmt noch nicht. Erwartet wird genau: ' + + tippen; + tippfeld.focus(); + tippfeld.select(); + return; + } + var erg2 = {}; + if (eingabe) erg2.eingabe = tippfeld.value.trim(); + if (grund) { + var g = feld.value.trim(); + if (grundPflicht && g.length < 3) { + fehlerZeile.textContent = 'Bitte kurz sagen, warum.'; + feld.focus(); + return; /* NICHT schliessen -- sonst waere die Eingabe weg */ + } + erg2.grund = g; + } + if (zahl) { + var roh = zahlfeld.value.trim(); + if (roh === '' && !zahlLeer) { + fehlerZeile.textContent = 'Bitte eine Anzahl eintragen.'; + zahlfeld.focus(); return; + } + var n = roh === '' ? null : Number(roh); + if (n !== null && !(n > 0)) { + fehlerZeile.textContent = 'Das ist keine gültige Anzahl.'; + zahlfeld.focus(); return; + } + if (n !== null && zahlMax && n > zahlMax) { + fehlerZeile.textContent = 'Mehr als ' + zahlMax + ' geht hier nicht.'; + zahlfeld.focus(); return; + } + erg2.zahl = n; + } + antwort = (grund || zahl || eingabe) ? erg2 : true; + dlg.close(); + } + + dlg.addEventListener('close', beiSchliessen); + form.addEventListener('submit', beiJa); + teil('nein').addEventListener('click', beiNein); + dlg.addEventListener('click', beiDaneben); + + dlg.showModal(); + /* Der Fokus liegt auf dem harmlosen Knopf, nicht auf "Loeschen". + Wer aus Gewohnheit Enter drueckt, bricht damit ab -- das ist + die richtige Richtung fuer einen Fehlgriff. Ausser es gibt ein + Textfeld, dann gehoert der Fokus dorthin. */ + if (tippen || eingabe) tippfeld.focus(); + else if (grund) feld.focus(); + else teil('nein').focus(); + }); + }; +})(); diff --git a/workspace/assets/js/personen.js b/workspace/assets/js/personen.js index 3c56b5f2..0a32734b 100644 --- a/workspace/assets/js/personen.js +++ b/workspace/assets/js/personen.js @@ -311,8 +311,14 @@ allein sagt nicht, WAS sich ändert -- und es ist der Handgriff, der jemandem den Zugang zu einer ganzen Seite nimmt oder gibt. */ const name = $('rolle-wahl').querySelector('.rollenwahl__knopf[data-an="ja"] .rollenwahl__name')?.textContent || gewaehlt; - if (!confirm(`${rolleFuer.name} wird von "${ROLLENNAME[rolleFuer.rolle] || rolleFuer.rolle}" zu "${name}".\n\n` - + 'Der Zugangscode bleibt derselbe. Offene Sitzungen werden beendet.')) return; + if (!await frageNach({ + titel: `${rolleFuer.name}: Rolle ändern?`, + was: `Von „${ROLLENNAME[rolleFuer.rolle] || rolleFuer.rolle}" zu „${name}".` + + ' Damit ändert sich, welche Seiten die Person öffnen darf.', + bleibt: 'Der Zugangscode bleibt derselbe. Offene Sitzungen werden beendet, ' + + 'danach kann sie sich mit dem alten Code wieder anmelden.', + ja: `Zu „${name}" machen`, + })) return; const a = await hole(`/workspace/api/verwaltung/personen/${rolleFuer.id}/rolle`, { method: 'PUT', @@ -577,18 +583,17 @@ Der Code gilt einmal fuer die ` knoepfe.append(tuKnopf('Neuer Code', async () => { const eigen = p.id === ich.id; - const frage = eigen - /* Der Satz stimmte bis zum 02.09.2026 -- und beschrieb genau die - Falle: Man bestätigte, der Code erschien, und im selben Moment - war die Sitzung weg. Jetzt bleibt sie bestehen, und der Text - sagt, was wirklich passiert. */ - ? 'Neuer Code für dich selbst?\n\n' - + 'Der alte Code gilt danach nicht mehr, und alle ANDEREN Geräte ' - + 'werden abgemeldet.\n\n' - + 'Hier bleibst du angemeldet – der neue Code steht danach auf dem ' - + 'Bildschirm, bis du ihn selbst wegklickst.' - : `Neuer Code für ${p.name}?\n\nDer alte Code gilt dann nicht mehr, offene Sitzungen werden beendet.`; - if (!confirm(frage)) return; + if (!await frageNach({ + titel: eigen ? 'Neuer Code für dich selbst?' : `Neuer Code für ${p.name}?`, + was: 'Der alte Code gilt danach nicht mehr.', + bleibt: eigen + ? 'Alle ANDEREN Geräte werden abgemeldet – hier bleibst du ' + + 'angemeldet. Der neue Code steht danach auf dem Bildschirm, ' + + 'bis du ihn selbst wegklickst.' + : `Offene Sitzungen von ${p.name} werden beendet. Alles andere ` + + 'bleibt unverändert – nur der Code ist neu.', + endgueltig: true, ja: 'Neuen Code erzeugen', + })) return; const a = await hole(`/workspace/api/verwaltung/personen/${p.id}/code`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -601,7 +606,13 @@ Der Code gilt einmal fuer die ` if (p.id !== ich.id) { knoepfe.append(tuKnopf(p.aktiv ? 'Sperren' : 'Entsperren', async () => { - if (p.aktiv && !confirm(`${p.name} sperren?\n\nOffene Sitzungen werden sofort beendet.`)) return; + if (p.aktiv && !await frageNach({ + titel: `${p.name} sperren?`, + was: 'Offene Sitzungen werden sofort beendet. Anmelden geht danach nicht mehr.', + bleibt: 'Alle Daten bleiben stehen – Aufgaben, Nachrichten, Steckbrief. ' + + 'Entsperren geht jederzeit mit demselben Knopf.', + ja: 'Sperren', + })) return; const a = await hole(`/workspace/api/verwaltung/personen/${p.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, @@ -704,43 +715,42 @@ Der Code gilt einmal fuer die ` if (v.hindernis) { melde(v.hindernis); return; } - const zeilen = []; const mit = Object.entries(v.mit).filter(([, n]) => n > 0); const bleibt = Object.entries(v.bleibt).filter(([, n]) => n > 0); - zeilen.push(`„${v.person.name}" wirklich löschen?`, ''); - if (mit.length) { - zeilen.push('Wird MITGELÖSCHT:'); - for (const [was, n] of mit) zeilen.push(` · ${was}: ${n}`); - zeilen.push(''); - } - if (bleibt.length) { - zeilen.push('BLEIBT erhalten, verliert nur die Zuordnung:'); - for (const [was, n] of bleibt) zeilen.push(` · ${was}: ${n}`); - zeilen.push(''); - } - if (v.verliertBetreuung.length) { - zeilen.push(`ACHTUNG: ${v.verliertBetreuung.join(', ')} ` - + `${v.verliertBetreuung.length === 1 ? 'steht' : 'stehen'} danach ohne zuständige Person da.`, ''); - } - if (!mit.length && !bleibt.length && !v.verliertBetreuung.length) { - zeilen.push('An dieser Person hängt nichts.', ''); - } - zeilen.push('Vorher wird automatisch eine Sicherung geschrieben.', '', - `Zum Bestätigen den Namen genau eingeben: ${v.person.name}`); + /* Was mitgeht und was bleibt, sind ZWEI Aussagen -- deshalb stehen + sie im Dialog auch in zwei Zeilen und nicht in einer Liste, die + man von oben nach unten durchliest und in der Mitte aufgibt. */ + const wasWeg = mit.length + ? 'Mitgelöscht wird: ' + mit.map(([w, n]) => `${w} (${n})`).join(', ') + '.' + : 'An dieser Person hängt nichts, was mitgelöscht würde.'; + const wasBleibt = [ + bleibt.length + ? 'Erhalten bleibt, verliert aber die Zuordnung: ' + + bleibt.map(([w, n]) => `${w} (${n})`).join(', ') + '.' + : '', + v.verliertBetreuung.length + ? `${v.verliertBetreuung.join(', ')} ` + + `${v.verliertBetreuung.length === 1 ? 'steht' : 'stehen'} danach ` + + 'ohne zuständige Person da.' + : '', + 'Vorher wird automatisch eine Sicherung geschrieben.', + ].filter(Boolean).join(' '); - const eingabe = prompt(zeilen.join('\n'), ''); - if (eingabe === null) return; - if (eingabe.trim() !== v.person.name) { - melde('Der Name stimmt nicht – es wurde nichts gelöscht.'); - return; - } + if (!await frageNach({ + titel: `„${v.person.name}" löschen?`, + was: wasWeg, + bleibt: wasBleibt, + endgueltig: true, + ja: 'Endgültig löschen', + tippen: v.person.name, + })) return; try { const a = await hole(`/workspace/api/verwaltung/personen/${person.id}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ name: eingabe.trim() }), + body: JSON.stringify({ name: v.person.name }), }); const d = await a.json().catch(() => ({})); if (!a.ok) { melde(sagWas(d.fehler, 'Löschen hat nicht geklappt.')); return; } diff --git a/workspace/assets/js/rechte.js b/workspace/assets/js/rechte.js index e1862f05..a9d0605b 100644 --- a/workspace/assets/js/rechte.js +++ b/workspace/assets/js/rechte.js @@ -109,9 +109,13 @@ sieht sofort jemand. Etwas aufzumachen merkt unter Umständen lange niemand — und genau das ist der Klick, bei dem eine Sekunde Nachdenken etwas wert ist. */ - if (erlaubt && !confirm( - `„${rolle.name}" darf danach ${seite.datei} öffnen.\n\n` - + 'Das gilt sofort, für alle mit dieser Rolle. Sicher?')) return; + if (erlaubt && !await frageNach({ + titel: `„${rolle.name}" darf danach ${seite.datei} öffnen`, + was: 'Das gilt sofort, für alle mit dieser Rolle.', + bleibt: 'Zurücknehmen geht jederzeit mit demselben Schalter – aber bis ' + + 'dahin hat jeder mit dieser Rolle Zugang.', + ja: 'Freigeben', + })) return; knopf.disabled = true; try { @@ -167,8 +171,13 @@ const b = el('button', 'schritt', 'Alles zurück auf Grundstand'); b.type = 'button'; b.addEventListener('click', async () => { - if (!confirm(`${daten.abweichungen} Änderungen zurücknehmen?\n\n` - + 'Danach gilt wieder genau das, was im Code steht.')) return; + if (!await frageNach({ + titel: `${daten.abweichungen} Änderungen zurücknehmen?`, + was: 'Danach gilt wieder genau das, was im Code steht.', + bleibt: 'Die Rechte selbst gehen nicht verloren – nur die von Hand ' + + 'gesetzten Abweichungen. Du kannst sie jederzeit neu setzen.', + ja: 'Auf Grundstand zurück', + })) return; b.disabled = true; const a = await hole('/workspace/api/rechte/abweichungen', { method: 'DELETE' }); b.disabled = false; diff --git a/workspace/assets/js/schulung.js b/workspace/assets/js/schulung.js index e42281e4..d580921d 100644 --- a/workspace/assets/js/schulung.js +++ b/workspace/assets/js/schulung.js @@ -166,9 +166,14 @@ const b = el('button', 'knopf knopf--klein', 'Durchgegangen und bestätigt'); b.type = 'button'; b.addEventListener('click', async () => { - if (!confirm('Bestätigen, dass ihr das Dokument gemeinsam durchgegangen seid?\n\n' - + 'Sobald BEIDE bestätigt haben, ist der Nachweis endgültig und lässt sich ' - + 'nicht mehr ändern.')) return; + if (!await frageNach({ + titel: 'Gemeinsam durchgegangen?', + was: 'Deine Bestätigung wird mit Datum festgehalten.', + bleibt: 'Sobald BEIDE bestätigt haben, ist der Nachweis endgültig ' + + 'und lässt sich nicht mehr ändern. Solange nur du bestätigt ' + + 'hast, ist noch nichts festgeschrieben.', + ja: 'Ja, bestätigen', + })) return; b.disabled = true; b.textContent = 'wird gespeichert …'; try { diff --git a/workspace/assets/js/scouting.js b/workspace/assets/js/scouting.js index 5251b70c..f90eb977 100644 --- a/workspace/assets/js/scouting.js +++ b/workspace/assets/js/scouting.js @@ -329,7 +329,12 @@ const wg = el('button', 'knopf-still knopf-still--warn', 'Löschen'); wg.type = 'button'; wg.addEventListener('click', async () => { - if (!confirm(`„${l.name}" wirklich aus der Pipeline entfernen?`)) return; + if (!await frageNach({ + titel: `„${l.name}" aus der Pipeline entfernen?`, + was: 'Der Lead verschwindet aus der Liste, samt Notizen und Verlauf.', + bleibt: 'Andere Leads bleiben unberührt.', + endgueltig: true, ja: 'Entfernen', + })) return; if (await schicke('/workspace/api/leads/' + l.id, 'DELETE')) { offen.delete(l.id); await laden(); } }); unten.append(wg); @@ -344,7 +349,13 @@ } async function onboarding(l, knopf) { - if (!confirm(`Aus „${l.name}" jetzt einen Creator mit eigenem Zugang anlegen?`)) return; + if (!await frageNach({ + titel: `Aus „${l.name}" einen Creator mit eigenem Zugang anlegen?`, + was: 'Es entsteht ein Konto mit eigenem Zugangscode.', + bleibt: 'Der Lead bleibt in der Pipeline stehen und wird als ' + + 'übernommen markiert.', + ja: 'Creator anlegen', + })) return; knopf.disabled = true; const r = await schicke('/workspace/api/leads/' + l.id + '/onboarding', 'POST', { name: l.name }); knopf.disabled = false; diff --git a/workspace/assets/js/steckbrief.js b/workspace/assets/js/steckbrief.js index 6660186f..5f823ba7 100644 --- a/workspace/assets/js/steckbrief.js +++ b/workspace/assets/js/steckbrief.js @@ -160,7 +160,14 @@ }); $('sb-bild-weg').addEventListener('click', async () => { - if (!confirm('Profilbild entfernen?')) return; + if (!await frageNach({ + titel: 'Profilbild entfernen?', + was: 'Dein Bild verschwindet überall – aus der Liste, aus dem Chat, ' + + 'aus deinem Steckbrief.', + bleibt: 'Alles andere an deinem Steckbrief bleibt stehen. Du kannst ' + + 'jederzeit ein neues Bild hochladen.', + ja: 'Bild entfernen', + })) return; try { const a = await hole('/workspace/api/steckbrief/bild', { method: 'DELETE' }); if (!a.ok) { melde('Entfernen ging nicht.'); return; } diff --git a/workspace/assets/js/talente.js b/workspace/assets/js/talente.js index 3ebac53c..20978fa4 100644 --- a/workspace/assets/js/talente.js +++ b/workspace/assets/js/talente.js @@ -650,12 +650,18 @@ if (!darfAnlegen()) { melde('Zugänge legt DogFather an.'); return null; } const vorschlag = String(k.titel || '').split(/[\s,(–-]+/)[0] || ''; - const name = prompt( - 'Wie soll die Person im Workspace heißen?\n\n' - + 'Das ist der Name, den euer Team sieht. Gleich danach bekommst du ' - + 'einmalig ihren Zugangscode – danach nie wieder.', - vorschlag); - if (name === null) return null; // abgebrochen + const an = await frageNach({ + titel: 'Zugang anlegen', + was: 'Die Person bekommt ein eigenes Konto im Workspace.', + bleibt: 'Gleich danach siehst du einmalig ihren Zugangscode – danach ' + + 'nie wieder. Schreib ihn dir vorher auf oder hab den Chat offen.', + ja: 'Zugang anlegen', + eingabe: 'Wie soll die Person im Workspace heißen?', + eingabeWert: vorschlag, + eingabeMin: 2, + }); + if (!an) return null; // abgebrochen + const name = an.eingabe; if (String(name).trim().length < 2) { melde('Der Name ist zu kurz.'); return null; } let a; diff --git a/workspace/assets/js/treff-moderation.js b/workspace/assets/js/treff-moderation.js index 6b4525fb..090a2757 100644 --- a/workspace/assets/js/treff-moderation.js +++ b/workspace/assets/js/treff-moderation.js @@ -181,10 +181,24 @@ } async function entscheiden(id, status) { - const entscheid = prompt(status === 'erledigt' - ? 'Was hast du getan?\n\nEin Satz genügt – er wird zur Meldung festgehalten.' - : 'Warum ist daran nichts dran?\n\nEin Satz genügt – er wird festgehalten.'); - if (entscheid === null) return; + const ae = await frageNach({ + titel: status === 'erledigt' ? 'Meldung als erledigt schließen' + : 'Meldung als unbegründet schließen', + was: status === 'erledigt' + ? 'Die Meldung gilt danach als bearbeitet.' + : 'Die Meldung gilt danach als geprüft, ohne Folgen für die Person.', + bleibt: 'Dein Satz wird zur Meldung festgehalten und bleibt im Verlauf ' + + 'lesbar. Der Beitrag selbst ändert sich dadurch nicht.', + ja: 'Schließen', + grund: status === 'erledigt' ? 'Was hast du getan?' + : 'Warum ist daran nichts dran?', + grundPflicht: true, + platzhalter: status === 'erledigt' + ? 'z. B. Beitrag entfernt und die Person angeschrieben.' + : 'z. B. Der Beitrag verstößt gegen keine Regel.', + }); + if (!ae) return; + const entscheid = ae.grund; const a = await hole('/workspace/api/treff/meldung/' + id, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, @@ -270,24 +284,36 @@ wird, hat die Strafe schon festgelegt, bevor er sie begründet hat. So steht am Anfang die Frage, was eigentlich passiert ist. */ async function massnahme(m, art, darf) { - const grund = prompt(art === 'hinweis' - ? `Hinweis an ${m.name} – worum geht es?` - : `${art === 'pause' ? 'Pause' : 'Ausschluss'} für ${m.name} – warum?\n\n` - + 'Der Grund wird festgehalten, und die Person hat ein Recht darauf.'); - if (grund === null) return; - - let tage; - if (art !== 'hinweis') { - const hinweis = darf?.frist_tage - ? `Du kannst bis zu ${darf.frist_tage} Tage geben.` - : 'Leer lassen = dauerhaft (nur bei Ausschluss).'; - const ein = prompt(`Für wie viele Tage?\n\n${hinweis}`, - darf?.frist_tage ? String(darf.frist_tage) : '7'); - if (ein === null) return; - tage = ein.trim() === '' ? null : Number(ein); - if (tage !== null && !(tage > 0)) { melde('Das ist keine Anzahl Tage.'); return; } - if (tage === null && art === 'pause') { melde('Eine Pause braucht eine Dauer.'); return; } - } + const istHinweis = art === 'hinweis'; + const wieLang = istHinweis ? null : (darf?.frist_tage || 0); + const a0 = await frageNach({ + titel: istHinweis + ? `Hinweis an ${m.name}` + : `${art === 'pause' ? 'Pause' : 'Ausschluss'} für ${m.name}`, + was: istHinweis + ? 'Die Person bekommt deinen Text zu lesen. Sie darf weiter mitmachen.' + : (art === 'pause' + ? 'Die Person kann für die eingetragene Zeit nichts schreiben.' + : 'Die Person kann nichts mehr schreiben.'), + bleibt: 'Der Grund wird festgehalten und der Person mitgeteilt – sie hat ' + + 'ein Recht darauf. Aufheben geht jederzeit.', + ja: istHinweis ? 'Hinweis schicken' : 'Eintragen', + grund: istHinweis ? 'Worum geht es?' : 'Warum?', grundPflicht: true, + platzhalter: istHinweis + ? 'z. B. Bitte nicht mehrfach dasselbe posten.' + : 'z. B. Wiederholte Beleidigungen trotz Hinweis.', + zahl: istHinweis ? '' : 'Für wie viele Tage?', + zahlWert: wieLang ? String(wieLang) : '7', + zahlMax: wieLang || 0, + /* Leer = dauerhaft, aber NUR beim Ausschluss -- eine Pause ohne + Ende waere ein Ausschluss unter falschem Namen. */ + zahlLeer: art === 'ausschluss' && !wieLang, + zahlHinweis: wieLang ? `Höchstens ${wieLang} Tage.` + : (art === 'ausschluss' ? 'Leer lassen = dauerhaft.' : ''), + }); + if (!a0) return; + const grund = a0.grund; + const tage = istHinweis ? undefined : a0.zahl; const a = await hole('/workspace/api/treff/massnahme', { method: 'POST', @@ -324,7 +350,13 @@ + ' am ' + datum(m.zeitpunkt)], ], laeuft && m.art !== 'hinweis' ? [ knopf('aufheben', async () => { - if (!confirm(`Maßnahme gegen ${m.person_name} aufheben?`)) return; + if (!await frageNach({ + titel: `Maßnahme gegen ${m.person_name} aufheben?`, + was: 'Die Person darf danach sofort wieder mitmachen.', + bleibt: 'Die Maßnahme bleibt im Verlauf sichtbar – sie wird nur ' + + 'beendet, nicht gelöscht.', + ja: 'Aufheben', + })) return; const r = await hole('/workspace/api/treff/massnahme/' + m.id, { method: 'DELETE' }); if (!r.ok) { melde(sagWas((await r.json().catch(() => ({}))).fehler, 'Ging nicht.')); diff --git a/workspace/assets/js/vorlagen.js b/workspace/assets/js/vorlagen.js index 44edf97b..1c1b2e24 100644 --- a/workspace/assets/js/vorlagen.js +++ b/workspace/assets/js/vorlagen.js @@ -146,8 +146,13 @@ : `Alle ${liste.length} Punkte übernehmen`); allesNehmen.type = 'button'; allesNehmen.addEventListener('click', async () => { - if (!confirm(`Wirklich alle ${liste.length} übernehmen? ` - + 'Sie landen als eigene Einträge in der Liste und lassen sich einzeln löschen.')) return; + if (!await frageNach({ + titel: `Alle ${liste.length} übernehmen?`, + was: 'Sie landen als eigene Einträge in deiner Liste.', + bleibt: 'Die Vorlage bleibt unverändert. Jeder übernommene Eintrag ' + + 'lässt sich einzeln wieder löschen.', + ja: `Alle ${liste.length} übernehmen`, + })) return; allesNehmen.disabled = true; allesNehmen.textContent = 'wird übernommen …'; try { diff --git a/workspace/assets/js/wissen.js b/workspace/assets/js/wissen.js index dd5e6035..5959b509 100644 --- a/workspace/assets/js/wissen.js +++ b/workspace/assets/js/wissen.js @@ -251,7 +251,13 @@ const weg = el('button', 'knopf-still knopf-still--warn', 'Löschen'); weg.type = 'button'; weg.addEventListener('click', async () => { - if (!confirm(`„${e.titel}" wirklich löschen?\n\nDie PDF wird dabei auch vom Server entfernt.`)) return; + if (!await frageNach({ + titel: `„${e.titel}" löschen?`, + was: 'Der Eintrag verschwindet aus dem Wissen. Die PDF wird dabei ' + + 'auch vom Server entfernt.', + bleibt: 'Wer sie schon heruntergeladen hat, behält seine Kopie.', + endgueltig: true, ja: 'Löschen', + })) return; const a = await hole('/workspace/api/wissen/' + e.id, { method: 'DELETE' }); if (!a.ok) { melde('Löschen hat nicht geklappt.'); return; } await laden_(); diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index 205ac2af..5c15afe2 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -12,19 +12,19 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - + + + + + + - + @@ -291,12 +291,13 @@ - + + - - - - - + + + + + diff --git a/workspace/automation.html b/workspace/automation.html index 9a151b9d..ee4afeac 100644 --- a/workspace/automation.html +++ b/workspace/automation.html @@ -1,179 +1,179 @@ - - - - - -Automationen · Spicy & Dogi - - - - - - - - - - - - - - - - - - - - -
- -

Creator Workspace · Automationen

-
- … - -
-
- -
- -
-
-

Was von allein passiert

-

Automationen

-

- Alles hier läuft ohne Zutun. Diese Seite zeigt, was gerade greift – - und wo du es abschalten kannst. -

-
-
- - - - -
-
-
-

Lokale KI

-

Vorschläge in Calls, Start-Check und Report

-

Zustand wird geprüft …

-
- -
-
    -
    - - -
    -
    -

    Was gerade anliegt

    - – -
    -

    - Dieselben Hinweise wie auf der Übersicht, hier vollständig. Sie führen keine - eigene Liste – jeder verschwindet, sobald die Sache erledigt ist. -

    -

    Wird geprüft …

    -
    - - -
    -
    -
    -

    Sicherung & Zustand

    -

    Wird geprüft …

    -

    -
    - -
    -
      -
      -

      Vorhandene Sicherungen

      - -
      -
      -
      - -
      -
      -

      Läuft dauerhaft im Hintergrund

      -
      -
      -
      - - -
      -
      -

      Was gelöscht wird – und was bleibt

      - -
      -

      - Personenbezogene Daten werden nicht aufgehoben, weil Platz da ist, sondern - solange es einen Grund gibt. Läuft täglich von selbst. -

      -

      Wird geladen …

      -
      - -
      - -
      -

      Zuletzt automatisch passiert

      - -
      -

      Aus dem Protokoll – damit nachvollziehbar bleibt, was ohne Zutun geschah.

      -

      Wird geladen …

      -
      - -
      - - - - - - - - - - + + + + + +Automationen · Spicy & Dogi + + + + + + + + + + + + + + + + + + + + +
      + +

      Creator Workspace · Automationen

      +
      + … + +
      +
      + +
      + +
      +
      +

      Was von allein passiert

      +

      Automationen

      +

      + Alles hier läuft ohne Zutun. Diese Seite zeigt, was gerade greift – + und wo du es abschalten kannst. +

      +
      +
      + + + + +
      +
      +
      +

      Lokale KI

      +

      Vorschläge in Calls, Start-Check und Report

      +

      Zustand wird geprüft …

      +
      + +
      +
        +
        + + +
        +
        +

        Was gerade anliegt

        + – +
        +

        + Dieselben Hinweise wie auf der Übersicht, hier vollständig. Sie führen keine + eigene Liste – jeder verschwindet, sobald die Sache erledigt ist. +

        +

        Wird geprüft …

        +
        + + +
        +
        +
        +

        Sicherung & Zustand

        +

        Wird geprüft …

        +

        +
        + +
        +
          +
          +

          Vorhandene Sicherungen

          + +
          +
          +
          + +
          +
          +

          Läuft dauerhaft im Hintergrund

          +
          +
          +
          + + +
          +
          +

          Was gelöscht wird – und was bleibt

          + +
          +

          + Personenbezogene Daten werden nicht aufgehoben, weil Platz da ist, sondern + solange es einen Grund gibt. Läuft täglich von selbst. +

          +

          Wird geladen …

          +
          + +
          + +
          +

          Zuletzt automatisch passiert

          + +
          +

          Aus dem Protokoll – damit nachvollziehbar bleibt, was ohne Zutun geschah.

          +

          Wird geladen …

          +
          + +
          + + + + + + + + + + diff --git a/workspace/befinden.html b/workspace/befinden.html index 25444fa0..9b4fa851 100644 --- a/workspace/befinden.html +++ b/workspace/befinden.html @@ -1,140 +1,140 @@ - - - - - -Wie geht's dir? · Spicy & Dogi - - - - - - - - - - - - - - - - - -
          - -

          Team Dogi · Wie geht's dir?

          -
          - … - -
          -
          - -
          - - - -
          -
          -

          Für dich

          -

          Wie geht's dir?

          - -

          - Ein paar Fragen über dich. Deine Antworten liest niemand – auch - DogFather nicht. -

          -

          - Das Einzige, was nach außen dringt: ob es im Team gerade - jemandem zu viel ist. Ohne Namen, ohne Frage, ohne Datum – - und erst ab drei Personen im Team, weil es darunter dasselbe wäre - wie ein Name. -

          -
          -
          - - - - - - -
          -

          wird geladen …

          -
          - - - - - - - -
          - - - - - - - - - + + + + + +Wie geht's dir? · Spicy & Dogi + + + + + + + + + + + + + + + + + +
          + +

          Team Dogi · Wie geht's dir?

          +
          + … + +
          +
          + +
          + + + +
          +
          +

          Für dich

          +

          Wie geht's dir?

          + +

          + Ein paar Fragen über dich. Deine Antworten liest niemand – auch + DogFather nicht. +

          +

          + Das Einzige, was nach außen dringt: ob es im Team gerade + jemandem zu viel ist. Ohne Namen, ohne Frage, ohne Datum – + und erst ab drei Personen im Team, weil es darunter dasselbe wäre + wie ein Name. +

          +
          +
          + + + + + + +
          +

          wird geladen …

          +
          + + + + + + + +
          + + + + + + + + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 71632899..475b40b4 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -12,24 +12,24 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - + + + + + + - - + + - + @@ -251,16 +251,17 @@ - + + - - - - - - - - - + + + + + + + + + diff --git a/workspace/bewerben.html b/workspace/bewerben.html index 414c42f1..258d3731 100644 --- a/workspace/bewerben.html +++ b/workspace/bewerben.html @@ -1,118 +1,118 @@ - - - - - -Anfrage · Der Treff - - - - - - - - - - - - - - - - - - - - -
          - -

          Der Treff · Anfrage

          -
          - … - -
          -
          - -
          - - - -
          -
          -

          Mitmachen

          - -

          Anfrage stellen

          -

          - Ein paar Fragen - ehrlich beantwortet ist mehr wert als - vollständig. Du kannst zwischendurch aufhören und später - weitermachen: Deine Antworten bleiben so lange in diesem - Browser. Zu uns kommen sie erst, wenn du abschickst. -

          -
          -
          - - - -

          einen Moment …

          - - - - - - -
          - - - - - - - - - - + + + + + +Anfrage · Der Treff + + + + + + + + + + + + + + + + + + + + +
          + +

          Der Treff · Anfrage

          +
          + … + +
          +
          + +
          + + + +
          +
          +

          Mitmachen

          + +

          Anfrage stellen

          +

          + Ein paar Fragen - ehrlich beantwortet ist mehr wert als + vollständig. Du kannst zwischendurch aufhören und später + weitermachen: Deine Antworten bleiben so lange in diesem + Browser. Zu uns kommen sie erst, wenn du abschickst. +

          +
          +
          + + + +

          einen Moment …

          + + + + + + +
          + + + + + + + + + + diff --git a/workspace/bewerbungen.html b/workspace/bewerbungen.html index 09bf8ddd..0cb786f5 100644 --- a/workspace/bewerbungen.html +++ b/workspace/bewerbungen.html @@ -1,91 +1,91 @@ - - - - - -Anfragen · Nachwuchs - - - - - - - - - - - - - - - - - - - -
          - -

          Talente · Anfragen

          -
          - … - -
          -
          - -
          - - - -
          -
          -

          Entwicklung & Nachwuchs

          -

          Anfragen

          -

          - Wer sich selbst gemeldet hat. Nimmst du an, entsteht daraus ein - Eintrag bei den Talenten – auf der Stufe „Angesprochen“, denn wer - sich meldet, hat die erste Frage schon beantwortet. -

          -
          -
          - - - - - - -

          einen Moment …

          - -
          - -
          - - - - - - - - - - + + + + + +Anfragen · Nachwuchs + + + + + + + + + + + + + + + + + + + +
          + +

          Talente · Anfragen

          +
          + … + +
          +
          + +
          + + + +
          +
          +

          Entwicklung & Nachwuchs

          +

          Anfragen

          +

          + Wer sich selbst gemeldet hat. Nimmst du an, entsteht daraus ein + Eintrag bei den Talenten – auf der Stufe „Angesprochen“, denn wer + sich meldet, hat die erste Frage schon beantwortet. +

          +
          +
          + + + + + + +

          einen Moment …

          + +
          + +
          + + + + + + + + + + diff --git a/workspace/calls.html b/workspace/calls.html index ba1e8358..ba1ba080 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -89,13 +89,14 @@ - + + - - - - - - + + + + + + diff --git a/workspace/chat.html b/workspace/chat.html index b38a095a..43260586 100644 --- a/workspace/chat.html +++ b/workspace/chat.html @@ -12,26 +12,26 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - - + + + - + @@ -367,16 +367,17 @@
          - - - - - + + + + + + - - + + diff --git a/workspace/content.html b/workspace/content.html index eb93855b..b5967ed4 100644 --- a/workspace/content.html +++ b/workspace/content.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -179,14 +179,15 @@ - + + - - - - - - - + + + + + + + diff --git a/workspace/crew-index.html b/workspace/crew-index.html index f90f3344..40dce9a7 100644 --- a/workspace/crew-index.html +++ b/workspace/crew-index.html @@ -1,355 +1,355 @@ - - - - - -Anmeldung · DogFather Universe - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          - - - -
          -

          - DogFather - × - Team Dogi -

          -

          Team Dogi

          -

          Team Dogi und der Treff. Zugang nur mit persönlichem Code.

          -
          - -
          -

          Womit meldest du dich an?

          - - - - - - - - - - -
          - - - - - - -
          - - -
          - - -
          - - - - - -
          - - -

          Noch keinen Code? Frag im Live nach – Team Dogi gibt ihn dir persönlich.

          - -

          - Verschlüsselte Verbindung · Zugriffe werden protokolliert -

          -
          -
          - - - - - - + + + + + +Anmeldung · DogFather Universe + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          + + + +
          +

          + DogFather + × + Team Dogi +

          +

          Team Dogi

          +

          Team Dogi und der Treff. Zugang nur mit persönlichem Code.

          +
          + +
          +

          Womit meldest du dich an?

          + + + + + + + + + + +
          + + + + + + +
          + + +
          + + +
          + + + + + +
          + + +

          Noch keinen Code? Frag im Live nach – Team Dogi gibt ihn dir persönlich.

          + +

          + Verschlüsselte Verbindung · Zugriffe werden protokolliert +

          +
          +
          + + + + + + diff --git a/workspace/crew.webmanifest b/workspace/crew.webmanifest index e87e62b8..00e21686 100644 --- a/workspace/crew.webmanifest +++ b/workspace/crew.webmanifest @@ -22,25 +22,25 @@ }, "icons": [ { - "src": "/assets/img/app-symbole/crew-192.png?v=202609191915", + "src": "/assets/img/app-symbole/crew-192.png?v=202609191956", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/crew-512.png?v=202609191915", + "src": "/assets/img/app-symbole/crew-512.png?v=202609191956", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609191915", + "src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609191956", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609191915", + "src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609191956", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/workspace/dateien.html b/workspace/dateien.html index 5278489a..adb71af0 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -108,12 +108,13 @@ - + + - - - - - + + + + + diff --git a/workspace/entwicklung.html b/workspace/entwicklung.html index baefe57d..b754b17c 100644 --- a/workspace/entwicklung.html +++ b/workspace/entwicklung.html @@ -1,116 +1,116 @@ - - - - - -Eure Aufgaben · Spicy & Dogi - - - - - - - - - - - - - - - - - -
          - -

          Team Dogi · Eure Aufgaben

          -
          - … - -
          -
          - -
          - -
          -
          -

          Entwicklung & Nachwuchs

          - -

          Eure Aufgaben

          -

          - Anklicken statt tippen. Keine Noten, keine Punktzahl – ein Gesprächsanlass. -

          -
          -
          - - - - - - - - - - - - - - - - - -
          - - - - - - - - - + + + + + +Eure Aufgaben · Spicy & Dogi + + + + + + + + + + + + + + + + + +
          + +

          Team Dogi · Eure Aufgaben

          +
          + … + +
          +
          + +
          + +
          +
          +

          Entwicklung & Nachwuchs

          + +

          Eure Aufgaben

          +

          + Anklicken statt tippen. Keine Noten, keine Punktzahl – ein Gesprächsanlass. +

          +
          +
          + + + + + + + + + + + + + + + + + +
          + + + + + + + + + diff --git a/workspace/hilfe.html b/workspace/hilfe.html index 5d6414b4..c6c1dd1c 100644 --- a/workspace/hilfe.html +++ b/workspace/hilfe.html @@ -7,13 +7,13 @@ - - - - - - - + + + + + + + @@ -141,11 +141,12 @@ - + + - - - - + + + + diff --git a/workspace/index.html b/workspace/index.html index 362bda77..bc9d510e 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -1,417 +1,417 @@ - - - - - -Anmeldung · Spicy & Dogi - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          - - - -
          -

          - SpicyMedia - × - DogFather -

          -

          Creator Workspace

          -

          Privater Bereich für die Manager, Scouts und Creator von Spicy Media.

          -
          - -
          -

          Womit meldest du dich an?

          - - - - - - - - - - - - - -
          - -
          - - -
          - - -
          - - - - - -
          - - -

          Noch keinen Code? Den bekommst du von deinem Manager oder von DogFather.

          - -

          - Verschlüsselte Verbindung · Zugriffe werden protokolliert -

          -
          -
          - - - - - - + + + + + +Anmeldung · Spicy & Dogi + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          + + + +
          +

          + SpicyMedia + × + DogFather +

          +

          Creator Workspace

          +

          Privater Bereich für die Manager, Scouts und Creator von Spicy Media.

          +
          + +
          +

          Womit meldest du dich an?

          + + + + + + + + + + + + + +
          + +
          + + +
          + + +
          + + + + + +
          + + +

          Noch keinen Code? Den bekommst du von deinem Manager oder von DogFather.

          + +

          + Verschlüsselte Verbindung · Zugriffe werden protokolliert +

          +
          +
          + + + + + + diff --git a/workspace/kalender.html b/workspace/kalender.html index e9fce857..44b8c256 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -377,13 +377,14 @@ - + + - - - - - - + + + + + + diff --git a/workspace/leistung.html b/workspace/leistung.html index e298f266..6ad5ba5b 100644 --- a/workspace/leistung.html +++ b/workspace/leistung.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -444,11 +444,12 @@
          - - - - - - + + + + + + + diff --git a/workspace/personen.html b/workspace/personen.html index 246f8dba..62809ef3 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -449,12 +449,13 @@ - + + - - - - - + + + + + diff --git a/workspace/profil.html b/workspace/profil.html index 39caec3b..842bf4c0 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -214,13 +214,14 @@ - + + - - - - - - + + + + + + diff --git a/workspace/rechte.html b/workspace/rechte.html index 03e65909..bcc38bcf 100644 --- a/workspace/rechte.html +++ b/workspace/rechte.html @@ -7,14 +7,14 @@ - - - - - - - - + + + + + + + + @@ -134,10 +134,11 @@ Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen, die seit dem 07.09. jede Seite danach absucht. --> - - - - - + + + + + + diff --git a/workspace/report.html b/workspace/report.html index 7c9c96d3..aeee091e 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -1,118 +1,118 @@ - - - - - -Reports & Review · Spicy & Dogi - - - - - - - - - - - - - - - - - - - - -
          - -

          Creator Workspace · Review

          -
          - … - -
          -
          - -
          - -
          -
          -

          Reports

          -

          Review & nächste Schritte

          -

          Fortschritt wird nicht gefühlt, sondern nachvollziehbar gemacht.

          -
          -
          - -
          - - -
          -
          -
          - - - -

          Report wird erstellt …

          - - - - -
          - - - - - - - - - - - + + + + + +Reports & Review · Spicy & Dogi + + + + + + + + + + + + + + + + + + + + +
          + +

          Creator Workspace · Review

          +
          + … + +
          +
          + +
          + +
          +
          +

          Reports

          +

          Review & nächste Schritte

          +

          Fortschritt wird nicht gefühlt, sondern nachvollziehbar gemacht.

          +
          +
          + +
          + + +
          +
          +
          + + + +

          Report wird erstellt …

          + + + + +
          + + + + + + + + + + + diff --git a/workspace/scouting.html b/workspace/scouting.html index e155eea7..96b4e710 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -173,12 +173,13 @@ - + + - - - - - + + + + + diff --git a/workspace/start.html b/workspace/start.html index 84075943..d671d5c0 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -1,689 +1,689 @@ - - - - - -Creator Workspace · Spicy & Dogi - - - - - - - - - - - - - - - - - - - - -
          -

          Spicy & Dogi · Creator Workspace

          -
          - … - -
          -
          - - -
          - -
          - - - -

          - … - -

          -
          - - - - - - -
          - - - - -

          Willkommen

          - -
          - -
          - - - - - - Spicy Media - - -

          Die Zentrale

          -

          - … - -

          - - - -
          - - -
          -
          - - - - -
          - - - - - - - - - -
          - --:-- - -- -
          -
          -
          -
          -
          - - - - -
          -

          Dein Tag

          - -
          -
          -

          Was ist dran

          - -
          -
            - - -
            - -
            - -
              - -
              -
              - - -
              -

              Deine Aufgaben

              -
                - - -
                - - -
                - - -

                - „Was ist dran" führt keine eigene Liste, sondern zeigt, was in den Bereichen - schon liegt – ein Punkt verschwindet von selbst, sobald die Sache erledigt ist. - Angezeigt wird nur, was du ohnehin sehen darfst. -

                -
                - - - - - - - - - - + + + + + +Creator Workspace · Spicy & Dogi + + + + + + + + + + + + + + + + + + + + +
                +

                Spicy & Dogi · Creator Workspace

                +
                + … + +
                +
                + + +
                + +
                + + + +

                + … + +

                +
                + + + + + + +
                + + + + +

                Willkommen

                + +
                + +
                + + + + + + Spicy Media + + +

                Die Zentrale

                +

                + … + +

                + + + +
                + + +
                +
                + + + + +
                + + + + + + + + + +
                + --:-- + -- +
                +
                +
                +
                +
                + + + + +
                +

                Dein Tag

                + +
                +
                +

                Was ist dran

                + +
                +
                  + + +
                  + +
                  + +
                    + +
                    +
                    + + +
                    +

                    Deine Aufgaben

                    +
                      + + +
                      + + +
                      + + +

                      + „Was ist dran" führt keine eigene Liste, sondern zeigt, was in den Bereichen + schon liegt – ein Punkt verschwindet von selbst, sobald die Sache erledigt ist. + Angezeigt wird nur, was du ohnehin sehen darfst. +

                      +
                      + + + + + + + + + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index 38f48fdf..3b7c1bd4 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -1,97 +1,97 @@ - - - - - -Start-Check · Spicy & Dogi - - - - - - - - - - - - - - - - - - - - -
                      - -

                      Creator Workspace · Start-Check

                      -
                      - … - -
                      -
                      - -
                      - -
                      -
                      -

                      Onboarding · Erstanalyse

                      -

                      Start-Check

                      -

                      - Ausgangslage verstehen – und daraus konkrete Arbeitspakete bauen. -

                      -
                      -
                      - -
                      -
                      - - - - - -

                      Start-Check wird geladen …

                      - -
                      - - - - - - - - - - - + + + + + +Start-Check · Spicy & Dogi + + + + + + + + + + + + + + + + + + + + +
                      + +

                      Creator Workspace · Start-Check

                      +
                      + … + +
                      +
                      + +
                      + +
                      +
                      +

                      Onboarding · Erstanalyse

                      +

                      Start-Check

                      +

                      + Ausgangslage verstehen – und daraus konkrete Arbeitspakete bauen. +

                      +
                      +
                      + +
                      +
                      + + + + + +

                      Start-Check wird geladen …

                      + +
                      + + + + + + + + + + + diff --git a/workspace/steckbrief.html b/workspace/steckbrief.html index d40541f4..1c39d587 100644 --- a/workspace/steckbrief.html +++ b/workspace/steckbrief.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -150,13 +150,14 @@ - + + - - - - - - + + + + + + diff --git a/workspace/talente.html b/workspace/talente.html index 95dd64ad..dedc5fec 100644 --- a/workspace/talente.html +++ b/workspace/talente.html @@ -7,18 +7,18 @@ - - - - - - + + + + + + - - - + + + @@ -111,11 +111,12 @@ - + + - - - - + + + + diff --git a/workspace/team.html b/workspace/team.html index c21bc602..37b0a3d5 100644 --- a/workspace/team.html +++ b/workspace/team.html @@ -1,121 +1,121 @@ - - - - - -Team · Spicy & Dogi - - - - - - - - - - - - - - - - - - -
                      - -

                      Creator Workspace · Team

                      -
                      - … - -
                      -
                      - -
                      - - - -
                      -
                      -
                      -

                      Rund um das Team

                      -

                      Manager & Scouts

                      -

                      - Wer betreut wen, wo staut sich etwas, wo fehlt jemand. -

                      -
                      -

                      - Termine, Chats und Dateien kommen hier nicht vor – weder Inhalte - noch Zahlen. Das ist eine Arbeitslage, keine Überwachung. -

                      -
                      -
                      - - - - - - - - - - - - - - -

                      Die Arbeitslage wird geladen …

                      - -
                      - - - - - - - - - - + + + + + +Team · Spicy & Dogi + + + + + + + + + + + + + + + + + + +
                      + +

                      Creator Workspace · Team

                      +
                      + … + +
                      +
                      + +
                      + + + +
                      +
                      +
                      +

                      Rund um das Team

                      +

                      Manager & Scouts

                      +

                      + Wer betreut wen, wo staut sich etwas, wo fehlt jemand. +

                      +
                      +

                      + Termine, Chats und Dateien kommen hier nicht vor – weder Inhalte + noch Zahlen. Das ist eine Arbeitslage, keine Überwachung. +

                      +
                      +
                      + + + + + + + + + + + + + + +

                      Die Arbeitslage wird geladen …

                      + +
                      + + + + + + + + + + diff --git a/workspace/teamlage.html b/workspace/teamlage.html index 5704b73a..41f687d3 100644 --- a/workspace/teamlage.html +++ b/workspace/teamlage.html @@ -1,93 +1,93 @@ - - - - - -Dein Team · Spicy & Dogi - - - - - - - - - - - - - - - - - - - -
                      - -

                      Creator Workspace · Dein Team

                      -
                      - … - -
                      -
                      - -
                      - - -
                      -
                      -
                      -

                      Zusammen

                      -

                      Was auf dich wartet

                      -

                      …

                      -

                      - Was hier steht, ist eine Merkliste für euch beide – keine Bewertung - von Menschen. „Offen“ heißt: darüber habt ihr noch nicht gesprochen. - Eingeschätzt wird dort, wo die Punkte stehen; jede Zahl führt dorthin. -

                      -
                      -
                      - -
                      - -
                      - -
                      - - - - - - - - - + + + + + +Dein Team · Spicy & Dogi + + + + + + + + + + + + + + + + + + + +
                      + +

                      Creator Workspace · Dein Team

                      +
                      + … + +
                      +
                      + +
                      + + +
                      +
                      +
                      +

                      Zusammen

                      +

                      Was auf dich wartet

                      +

                      …

                      +

                      + Was hier steht, ist eine Merkliste für euch beide – keine Bewertung + von Menschen. „Offen“ heißt: darüber habt ihr noch nicht gesprochen. + Eingeschätzt wird dort, wo die Punkte stehen; jede Zahl führt dorthin. +

                      +
                      +
                      + +
                      + +
                      + +
                      + + + + + + + + + diff --git a/workspace/teilen.html b/workspace/teilen.html index 59e0af9d..cf02aaee 100644 --- a/workspace/teilen.html +++ b/workspace/teilen.html @@ -1,122 +1,122 @@ - - - - - -Video übernehmen · Spicy & Dogi - - - - - - - - - - - - - - - - -
                      - -

                      Team Dogi · Video übernehmen

                      -
                      - … - -
                      -
                      - -
                      - - - -
                      -
                      -

                      Geteilt

                      -

                      Video übernehmen

                      -

                      - Titel und Coverbild werden von TikTok geholt – du musst nichts abtippen. -

                      -
                      -
                      - - - -
                      -

                      einen Moment …

                      - - - - - - - - - - - - - - -
                      - -
                      - - - - - - - - - + + + + + +Video übernehmen · Spicy & Dogi + + + + + + + + + + + + + + + + +
                      + +

                      Team Dogi · Video übernehmen

                      +
                      + … + +
                      +
                      + +
                      + + + +
                      +
                      +

                      Geteilt

                      +

                      Video übernehmen

                      +

                      + Titel und Coverbild werden von TikTok geholt – du musst nichts abtippen. +

                      +
                      +
                      + + + +
                      +

                      einen Moment …

                      + + + + + + + + + + + + + + +
                      + +
                      + + + + + + + + + diff --git a/workspace/treff-moderation.html b/workspace/treff-moderation.html index c348f4c2..25e98a69 100644 --- a/workspace/treff-moderation.html +++ b/workspace/treff-moderation.html @@ -7,14 +7,14 @@ - - - - - - - - + + + + + + + + @@ -126,11 +126,12 @@ - + + - - - - + + + + diff --git a/workspace/treff-regeln.html b/workspace/treff-regeln.html index 0d3de22f..a15cf1e9 100644 --- a/workspace/treff-regeln.html +++ b/workspace/treff-regeln.html @@ -1,231 +1,231 @@ - - - - - -Die Regeln · Der Treff - - - - - - - - - - - - - - - - - - -
                      - -

                      Der Treff · Regeln

                      -
                      - … - -
                      -
                      - -
                      - -
                      -
                      -

                      Der Treff

                      - -

                      Die Regeln

                      -

                      - Kurz, in normaler Sprache, und alles, was hier steht, gilt auch. -

                      -
                      -
                      - - - - -
                      -

                      Schön, dass du da bist

                      -
                      -

                      - Der Treff ist der Ort rund um DogFather: Hier steht, was gerade gilt, - was ansteht, und hier redet ihr miteinander. Er ist nicht öffentlich – - du bist hier, weil dir jemand einen Code gegeben hat. -

                      -

                      - Gib diesen Code nicht weiter. Er gehört zu dir, und was damit - geschrieben wird, steht unter deinem Namen. -

                      -
                      -
                      - -
                      -

                      Die fünf Regeln

                      -
                      -
                        -
                      1. Sei anständig. Keine Beleidigungen, keine Angriffe - auf Menschen, keine Hetze. Streiten über eine Sache ist in Ordnung – - über einen Menschen nicht.
                      2. -
                      3. Keine privaten Daten. Keine Adressen, keine - Telefonnummern, keine Klarnamen von anderen. Auch nicht von dir - selbst, es liest mehr mit, als du denkst.
                      4. -
                      5. Nichts Fremdes hochladen. Was du einstellst, muss - von dir sein oder dir gehören.
                      6. -
                      7. Keine Werbung, kein Verkauf. Auch nicht für - andere Streams.
                      8. -
                      9. Was hier passiert, bleibt hier. Keine - Bildschirmfotos nach draußen.
                      10. -
                      -
                      -
                      - -
                      -

                      Wie du weiterkommst

                      -
                      -

                      - In der ersten Zeit kannst du lesen und bei Wünschen mitstimmen. - Das ist kein Misstrauen gegen dich – es ist eines gegen - Wegwerf-Zugänge. -

                      -
                        -
                      • wird geladen …
                      • -
                      -
                      -
                      - -
                      -

                      Wenn etwas nicht stimmt

                      -
                      -

                      - An jedem Beitrag, der nicht von dir ist, steht melden. - Schreib in einem Satz, was daran nicht in Ordnung ist – ohne das - können wir es nicht prüfen. -

                      -

                      - Wir sehen uns jede Meldung an. Wird ein Beitrag entfernt, halten wir - fest, warum – und die Person, die ihn geschrieben hat, - erfährt den Grund. Das ist keine Höflichkeit, sondern - Artikel 17 des Digital Services Act. -

                      -

                      - Du erreichst uns außerdem direkt: Schreib es auf das Brett - Der Treff oder sag es jemandem aus dem Team. -

                      -

                      - Häufige Fragen und Antworten stehen auf dem Brett - Regeln & Hilfe. -

                      -
                      -
                      - -
                      -

                      Was passiert, wenn jemand sich nicht daran hält

                      -
                      -

                      Wir gehen der Reihe nach vor, und niemand fliegt ohne Ansage:

                      -
                        -
                      1. Hinweis. Jemand sagt dir, was nicht ging.
                      2. -
                      3. Pause. Ein paar Tage nichts schreiben. Lesen - geht weiter.
                      4. -
                      5. Ende. Der Zugang wird geschlossen.
                      6. -
                      -

                      …

                      -
                      -
                      - -
                      -

                      Das Kleingedruckte – kurz

                      -
                      -

                      …

                      -

                      - Was gespeichert wird: dein Name, dein Zugangscode - (verschlüsselt, niemand kann ihn lesen), was du schreibst, und wann - du dich anmeldest. Mehr nicht – kein Standort, keine Werbe-IDs, - keine Weitergabe an Dritte. -

                      -

                      - Du willst weg? Sag Bescheid. Dein Zugang wird - geschlossen und deine Beiträge werden entfernt. -

                      -

                      - Der Treff ist ein kleiner, geschlossener Bereich. Es gibt keine - Direktnachrichten zwischen Mitgliedern – absichtlich: Ein - öffentlicher Raum lässt sich moderieren, ein privater nicht. -

                      -
                      -
                      - - - -
                      -
                      -

                      Was ist über mich gespeichert?

                      - -
                      -

                      - Alles, was dieser Workspace über dich weiß, als Datei zum Mitnehmen. - Zugangsgeheimnisse sind nicht dabei, und wo andere Menschen vorkommen, - stehen sie nicht mit Namen darin – ihre Daten gehören ihnen. -

                      - -
                      - -
                      - - - - - - - - - - + + + + + +Die Regeln · Der Treff + + + + + + + + + + + + + + + + + + +
                      + +

                      Der Treff · Regeln

                      +
                      + … + +
                      +
                      + +
                      + +
                      +
                      +

                      Der Treff

                      + +

                      Die Regeln

                      +

                      + Kurz, in normaler Sprache, und alles, was hier steht, gilt auch. +

                      +
                      +
                      + + + + +
                      +

                      Schön, dass du da bist

                      +
                      +

                      + Der Treff ist der Ort rund um DogFather: Hier steht, was gerade gilt, + was ansteht, und hier redet ihr miteinander. Er ist nicht öffentlich – + du bist hier, weil dir jemand einen Code gegeben hat. +

                      +

                      + Gib diesen Code nicht weiter. Er gehört zu dir, und was damit + geschrieben wird, steht unter deinem Namen. +

                      +
                      +
                      + +
                      +

                      Die fünf Regeln

                      +
                      +
                        +
                      1. Sei anständig. Keine Beleidigungen, keine Angriffe + auf Menschen, keine Hetze. Streiten über eine Sache ist in Ordnung – + über einen Menschen nicht.
                      2. +
                      3. Keine privaten Daten. Keine Adressen, keine + Telefonnummern, keine Klarnamen von anderen. Auch nicht von dir + selbst, es liest mehr mit, als du denkst.
                      4. +
                      5. Nichts Fremdes hochladen. Was du einstellst, muss + von dir sein oder dir gehören.
                      6. +
                      7. Keine Werbung, kein Verkauf. Auch nicht für + andere Streams.
                      8. +
                      9. Was hier passiert, bleibt hier. Keine + Bildschirmfotos nach draußen.
                      10. +
                      +
                      +
                      + +
                      +

                      Wie du weiterkommst

                      +
                      +

                      + In der ersten Zeit kannst du lesen und bei Wünschen mitstimmen. + Das ist kein Misstrauen gegen dich – es ist eines gegen + Wegwerf-Zugänge. +

                      +
                        +
                      • wird geladen …
                      • +
                      +
                      +
                      + +
                      +

                      Wenn etwas nicht stimmt

                      +
                      +

                      + An jedem Beitrag, der nicht von dir ist, steht melden. + Schreib in einem Satz, was daran nicht in Ordnung ist – ohne das + können wir es nicht prüfen. +

                      +

                      + Wir sehen uns jede Meldung an. Wird ein Beitrag entfernt, halten wir + fest, warum – und die Person, die ihn geschrieben hat, + erfährt den Grund. Das ist keine Höflichkeit, sondern + Artikel 17 des Digital Services Act. +

                      +

                      + Du erreichst uns außerdem direkt: Schreib es auf das Brett + Der Treff oder sag es jemandem aus dem Team. +

                      +

                      + Häufige Fragen und Antworten stehen auf dem Brett + Regeln & Hilfe. +

                      +
                      +
                      + +
                      +

                      Was passiert, wenn jemand sich nicht daran hält

                      +
                      +

                      Wir gehen der Reihe nach vor, und niemand fliegt ohne Ansage:

                      +
                        +
                      1. Hinweis. Jemand sagt dir, was nicht ging.
                      2. +
                      3. Pause. Ein paar Tage nichts schreiben. Lesen + geht weiter.
                      4. +
                      5. Ende. Der Zugang wird geschlossen.
                      6. +
                      +

                      …

                      +
                      +
                      + +
                      +

                      Das Kleingedruckte – kurz

                      +
                      +

                      …

                      +

                      + Was gespeichert wird: dein Name, dein Zugangscode + (verschlüsselt, niemand kann ihn lesen), was du schreibst, und wann + du dich anmeldest. Mehr nicht – kein Standort, keine Werbe-IDs, + keine Weitergabe an Dritte. +

                      +

                      + Du willst weg? Sag Bescheid. Dein Zugang wird + geschlossen und deine Beiträge werden entfernt. +

                      +

                      + Der Treff ist ein kleiner, geschlossener Bereich. Es gibt keine + Direktnachrichten zwischen Mitgliedern – absichtlich: Ein + öffentlicher Raum lässt sich moderieren, ein privater nicht. +

                      +
                      +
                      + + + +
                      +
                      +

                      Was ist über mich gespeichert?

                      + +
                      +

                      + Alles, was dieser Workspace über dich weiß, als Datei zum Mitnehmen. + Zugangsgeheimnisse sind nicht dabei, und wo andere Menschen vorkommen, + stehen sie nicht mit Namen darin – ihre Daten gehören ihnen. +

                      + +
                      + +
                      + + + + + + + + + + diff --git a/workspace/uebersicht.html b/workspace/uebersicht.html index 358e997d..be63f308 100644 --- a/workspace/uebersicht.html +++ b/workspace/uebersicht.html @@ -1,161 +1,161 @@ - - - - - -Dashboard · Spicy & Dogi - - - - - - - - - - - - - - - - - - - - - -
                      - -

                      Creator Workspace · Dashboard

                      -
                      - … - -
                      -
                      - -
                      - -
                      -
                      -

                      Alles zentral

                      -

                      Dashboard

                      -

                      - Eine Karte je Creator – mit einem Blick sehen, wo es hakt und wo es läuft. -

                      -
                      - - -
                      - - - - - -
                      -

                      Creator anlegen

                      -

                      - Der Zugangscode erscheint genau einmal – danach ist er weg und - kann nur neu gesetzt werden. -

                      - -
                      - - -
                      - - - - - - - - -
                      - - -
                      -
                      -
                      - - - - - - - -

                      Übersicht wird geladen …

                      - - - -
                      - - - - - - - - - - - + + + + + +Dashboard · Spicy & Dogi + + + + + + + + + + + + + + + + + + + + + +
                      + +

                      Creator Workspace · Dashboard

                      +
                      + … + +
                      +
                      + +
                      + +
                      +
                      +

                      Alles zentral

                      +

                      Dashboard

                      +

                      + Eine Karte je Creator – mit einem Blick sehen, wo es hakt und wo es läuft. +

                      +
                      + + +
                      + + + + + +
                      +

                      Creator anlegen

                      +

                      + Der Zugangscode erscheint genau einmal – danach ist er weg und + kann nur neu gesetzt werden. +

                      + +
                      + + +
                      + + + + + + + + +
                      + + +
                      +
                      +
                      + + + + + + + +

                      Übersicht wird geladen …

                      + + + +
                      + + + + + + + + + + + diff --git a/workspace/unsere-seiten.html b/workspace/unsere-seiten.html index 5c4fecbb..8a6349f1 100644 --- a/workspace/unsere-seiten.html +++ b/workspace/unsere-seiten.html @@ -1,227 +1,227 @@ - - - - - -Unsere Seiten · Der Treff - - - - - - - - - - - - - - - - -
                      - -

                      Der Treff · Unsere Seiten

                      -
                      - … - -
                      -
                      - -
                      - -
                      -
                      -

                      Der Treff · Unsere Seiten

                      -

                      Unsere Seiten

                      -

                      - Was es außerhalb vom Treff noch gibt — und wo dein Rabatt wartet. -

                      -
                      -
                      - - - -
                      - - -
                      - - - -
                      - -
                      -

                      Die Website

                      -

                      DogFather Universe

                      -
                      -
                      -

                      - Die Heimat von DogFather als Streamer, der HasiDog-Community - und seiner Arbeit als Manager bei Spicy Media. -

                      - - -
                        -
                      • Der Streamplan – wann was läuft
                      • -
                      • HasiDog: die Community rund um Dogi
                      • -
                      • Die Zeitreise durch alles Bisherige
                      • -
                      • Stimmen von Leuten, die dabei waren
                      • -
                      - -

                      - dogfather-universe.com - Seite öffnen → -

                      -
                      - - -
                      - - -
                      - -
                      -

                      Der Shop

                      - -

                      Van's DIY & Bastelbedarf

                      -
                      -
                      -

                      - VanVans eigener Laden: handgemachte Häkelwerke, Plushies, - Schmuck und Bastelzubehör. -

                      - - -
                      -

                      - 10 % - für alle aus der Community -

                      - -

                      - Beim Bestellen im Feld für den Gutscheincode eintragen. - Gilt nicht auf bereits reduzierte Artikel. -

                      -
                      - -

                      - vans-diy-bastelbedarf.com - Shop öffnen → -

                      -
                      - -
                      - -

                      - Beide Seiten öffnen sich in einem neuen Fenster — der Treff bleibt - also offen. -

                      - -
                      - - - - - - - - - + + + + + +Unsere Seiten · Der Treff + + + + + + + + + + + + + + + + +
                      + +

                      Der Treff · Unsere Seiten

                      +
                      + … + +
                      +
                      + +
                      + +
                      +
                      +

                      Der Treff · Unsere Seiten

                      +

                      Unsere Seiten

                      +

                      + Was es außerhalb vom Treff noch gibt — und wo dein Rabatt wartet. +

                      +
                      +
                      + + + +
                      + + +
                      + + + +
                      + +
                      +

                      Die Website

                      +

                      DogFather Universe

                      +
                      +
                      +

                      + Die Heimat von DogFather als Streamer, der HasiDog-Community + und seiner Arbeit als Manager bei Spicy Media. +

                      + + +
                        +
                      • Der Streamplan – wann was läuft
                      • +
                      • HasiDog: die Community rund um Dogi
                      • +
                      • Die Zeitreise durch alles Bisherige
                      • +
                      • Stimmen von Leuten, die dabei waren
                      • +
                      + +

                      + dogfather-universe.com + Seite öffnen → +

                      +
                      + + +
                      + + +
                      + +
                      +

                      Der Shop

                      + +

                      Van's DIY & Bastelbedarf

                      +
                      +
                      +

                      + VanVans eigener Laden: handgemachte Häkelwerke, Plushies, + Schmuck und Bastelzubehör. +

                      + + +
                      +

                      + 10 % + für alle aus der Community +

                      + +

                      + Beim Bestellen im Feld für den Gutscheincode eintragen. + Gilt nicht auf bereits reduzierte Artikel. +

                      +
                      + +

                      + vans-diy-bastelbedarf.com + Shop öffnen → +

                      +
                      + +
                      + +

                      + Beide Seiten öffnen sich in einem neuen Fenster — der Treff bleibt + also offen. +

                      + +
                      + + + + + + + + + diff --git a/workspace/werdegang.html b/workspace/werdegang.html index 18e97d29..42b109f8 100644 --- a/workspace/werdegang.html +++ b/workspace/werdegang.html @@ -1,154 +1,154 @@ - - - - - -Entwicklung · Spicy & Dogi - - - - - - - - - - - - - - - - - - -
                      - -

                      Team Dogi · Entwicklung

                      -
                      - … - -
                      -
                      - -
                      - - - -
                      -
                      -

                      Entwicklung & Nachwuchs

                      -

                      Entwicklung

                      -

                      - Wie sich jemand über die Zeit bewegt. Keine Note, kein Vergleich – - jede Karte nur mit sich selbst. -

                      -
                      -
                      - - - - - - - - - - - - - -
                      - - - - - - - - - + + + + + +Entwicklung · Spicy & Dogi + + + + + + + + + + + + + + + + + + +
                      + +

                      Team Dogi · Entwicklung

                      +
                      + … + +
                      +
                      + +
                      + + + +
                      +
                      +

                      Entwicklung & Nachwuchs

                      +

                      Entwicklung

                      +

                      + Wie sich jemand über die Zeit bewegt. Keine Note, kein Vergleich – + jede Karte nur mit sich selbst. +

                      +
                      +
                      + + + + + + + + + + + + + +
                      + + + + + + + + + diff --git a/workspace/wissen.html b/workspace/wissen.html index 9de6d094..e2523fb2 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -190,12 +190,13 @@ - + + - - - - - + + + + +