Agentur: Eintraege gehoeren allen -- und Events bekommen ein eigenes Formular
Gemessen am 07.09.2026, bevor irgendetwas geaendert wurde: Von drei Agentur-Eintraegen sah eine Creatorin genau EINEN -- den, der ihr zugeordnet war. Ein Event fuer alle traf weder `creator_id = ich` noch `erstellt_von = ich`; die Agentur-Seite war fuer jeden Creator leer. Nicht kaputt, nicht fehlerhaft: leer, so wie eine Seite aussieht, auf der noch nichts steht. Die Pruefung dazu war gruen. Sie legte ihre Testeintraege mit `creator_id: idLuna` an und pruefte damit einen Fall, den es im Alltag nicht gibt. - Bereichseinstellung `fuerAlle` + `ohneCreatorBezug`, daraus abgeleitet sichtbarEintrag(). BEWUSST neben sichtbar() statt darin: an derselben Funktion haengen Aufgaben, Dateien, Termine und Calls -- wer dort "1=1" einschleust, gibt nebenbei fremde Akten frei. Eine Gegenprobe mit einer zweiten Creatorin haelt das fest. - Die Zuordnung bietet nur noch "Agentur" an. Der Server verwirft eine Zuordnung ausserdem selbst -- inklusive des frei getippten Namens, und zwar NACH externPruefen: davor haette der Name den Riegel wieder aufgemacht. - "Event & Kampagne" heisst jetzt "Agentur-Events" und hat ein eigenes Formular: Von/Bis, Titel, Beschreibung, Aufgaben (Punkte und Preise), Regeln. Die Karte zeigt den Zustand als WORT (laeuft bis / startet / vorbei seit), nicht nur als Farbe. - Drei neue Spalten -- und sie stehen auch im Tabellenneubau vom 06.09. Der laeuft NACH dem Spaltennachtrag und haette sie samt Inhalt weggeworfen, ohne Fehler und mit stimmender Zeilenzahl. - Creator sehen weiterhin alles und tragen weiterhin nichts ein (403). Die Unterzeile sagt jetzt "alles, was hier steht" statt "alles, was zu dir gehoert" -- eine vollstaendige Liste soll sich nicht wie ein Ausschnitt lesen. pruef-agentur: 61 Pruefungen (vorher 40), alle gruen. Zwei eigene Fehler nebenbei gefunden und behoben: eine Beschriftung mit 11,2 px (Grenze 11,5) und ein Testdatum aus UTC statt Ortszeit. Zusaetzlich gruen: css-klassen, struktur, formulare, barrierefrei-workspace, handy. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+244
-5
@@ -122,11 +122,16 @@ function anlegen(d, name, rolle, code) {
|
|||||||
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
|
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
|
||||||
}
|
}
|
||||||
|
|
||||||
let idDogi, idLuna;
|
/* Mia kam am 07.09.2026 dazu, und sie ist kein Beiwerk: Sie legt nichts
|
||||||
|
an, ihr gehoert nichts, sie betreut niemanden. Genau deshalb beweist
|
||||||
|
erst SIE, dass ein Agentur-Eintrag wirklich fuer alle sichtbar ist --
|
||||||
|
bei Luna allein bliebe offen, ob es an ihr oder an der Regel lag. */
|
||||||
|
let idDogi, idLuna, idMia;
|
||||||
{
|
{
|
||||||
const d = new DatabaseSync(DB);
|
const d = new DatabaseSync(DB);
|
||||||
idDogi = anlegen(d, "Filipe", "admin", "CODE-DOGI-0001");
|
idDogi = anlegen(d, "Filipe", "admin", "CODE-DOGI-0001");
|
||||||
idLuna = anlegen(d, "Luna", "creator", "CODE-CREA-0001");
|
idLuna = anlegen(d, "Luna", "creator", "CODE-CREA-0001");
|
||||||
|
idMia = anlegen(d, "Mia", "creator", "CODE-CREA-0002");
|
||||||
d.close();
|
d.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,6 +267,24 @@ ok(/Bereich 'agentur' freigeschaltet/.test(ausgabe),
|
|||||||
ok(mitExtern?.creator_extern === "Gastauftritt Mia",
|
ok(mitExtern?.creator_extern === "Gastauftritt Mia",
|
||||||
`die Spalte "creator_extern" ebenfalls ("${mitExtern?.creator_extern}")`);
|
`die Spalte "creator_extern" ebenfalls ("${mitExtern?.creator_extern}")`);
|
||||||
|
|
||||||
|
/* DIE DREI EVENT-SPALTEN MUESSEN DEN TAUSCH UEBERLEBEN (07.09.2026).
|
||||||
|
|
||||||
|
Sie entstehen frueher als diese Umstellung (Spalten-Nachtrag in
|
||||||
|
workspace.js), und der Neubau hier schreibt eine feste Spaltenliste
|
||||||
|
ab. Wer sie dort vergisst, verliert sie samt Inhalt -- ohne
|
||||||
|
Fehlermeldung, und die Zeilenzahl stimmte weiterhin. Genau dieser
|
||||||
|
Weg wird hier wirklich gegangen: Die Tabelle stand vorher im ALTEN
|
||||||
|
Bauplan, ohne diese Spalten.
|
||||||
|
|
||||||
|
`PRAGMA table_info` und nicht "SELECT laeuft durch": Eine fehlende
|
||||||
|
Spalte faellt beim SELECT zwar auch auf -- aber erst irgendwann,
|
||||||
|
beim naechsten Event, in einem 503. */
|
||||||
|
const spalten = d.prepare("PRAGMA table_info(eintraege)").all().map((s) => s.name);
|
||||||
|
const fehlend = ["event_ende", "event_aufgaben", "event_regeln"].filter((s) => !spalten.includes(s));
|
||||||
|
ok(fehlend.length === 0,
|
||||||
|
fehlend.length ? `nach der Umstellung fehlen: ${fehlend.join(", ")}`
|
||||||
|
: "die drei Event-Spalten haben die Umstellung ueberlebt");
|
||||||
|
|
||||||
/* Der Index muss nach dem Tausch wieder da sein -- er wird beim DROP
|
/* Der Index muss nach dem Tausch wieder da sein -- er wird beim DROP
|
||||||
mit entfernt. Ohne ihn laeuft alles weiter, nur langsam, und
|
mit entfernt. Ohne ihn laeuft alles weiter, nur langsam, und
|
||||||
niemand merkt es je. */
|
niemand merkt es je. */
|
||||||
@@ -312,6 +335,7 @@ async function anmelden(rolle, code) {
|
|||||||
}
|
}
|
||||||
const keksDogi = await anmelden("admin", "CODE-DOGI-0001");
|
const keksDogi = await anmelden("admin", "CODE-DOGI-0001");
|
||||||
const keksLuna = await anmelden("creator", "CODE-CREA-0001");
|
const keksLuna = await anmelden("creator", "CODE-CREA-0001");
|
||||||
|
const keksMia = await anmelden("creator", "CODE-CREA-0002");
|
||||||
|
|
||||||
async function ruf(art, weg, keks, koerper) {
|
async function ruf(art, weg, keks, koerper) {
|
||||||
const a = await fetch(BASIS + weg, {
|
const a = await fetch(BASIS + weg, {
|
||||||
@@ -340,11 +364,29 @@ const ARTEN = ["kampagne", "schulung", "anliegen", "zustaendig"];
|
|||||||
"Bewertung ist aus — hier wird zusammengearbeitet, nicht benotet");
|
"Bewertung ist aus — hier wird zusammengearbeitet, nicht benotet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ANGELEGT WIE IM ECHTEN BETRIEB: OHNE ZUORDNUNG (07.09.2026).
|
||||||
|
|
||||||
|
Hier stand `creator_id: idLuna` -- und damit prueften die Zeilen
|
||||||
|
weiter unten einen Fall, den es im Alltag nicht gibt. Ein Agentur-
|
||||||
|
Event gehoert niemandem einzeln; Filipe legt es fuer alle an, das
|
||||||
|
Feld bleibt leer. Weil die Pruefung es aber jedes Mal Luna zuwies,
|
||||||
|
sah Luna es auch -- und die Zeile "sie sieht ihre 4 Eintraege" war
|
||||||
|
grün.
|
||||||
|
|
||||||
|
In Wirklichkeit war die Agentur-Seite fuer JEDEN Creator leer: Ein
|
||||||
|
Eintrag ohne creator_id traf weder `creator_id = ich` noch
|
||||||
|
`erstellt_von = ich`. Gemessen am 07.09.2026, bevor es repariert
|
||||||
|
wurde: von drei Eintraegen sah die Creatorin genau den einen, den
|
||||||
|
die Pruefung ihr zugeschoben hatte.
|
||||||
|
|
||||||
|
Das ist die dritte Sorte Fehler aus CLAUDE.md -- nicht uebersprungen,
|
||||||
|
nicht kaputt: gelaufen, gruen, und am Thema vorbei. Deshalb wird ab
|
||||||
|
jetzt der Weg gegangen, den es wirklich gibt. */
|
||||||
let angelegt = 0;
|
let angelegt = 0;
|
||||||
for (const art of ARTEN) {
|
for (const art of ARTEN) {
|
||||||
const { status } = await ruf("POST", "/workspace/api/bereich/agentur", keksDogi, {
|
const { status } = await ruf("POST", "/workspace/api/bereich/agentur", keksDogi, {
|
||||||
art, titel: `Test ${art}`, text: "Inhalt", datum: heute,
|
art, titel: `Test ${art}`, text: "Inhalt", datum: heute,
|
||||||
dringlichkeit: "mittel", creator_id: idLuna,
|
dringlichkeit: "mittel",
|
||||||
});
|
});
|
||||||
if (status === 200 || status === 201) angelegt++;
|
if (status === 200 || status === 201) angelegt++;
|
||||||
else ok(false, `Art "${art}" liess sich nicht anlegen (HTTP ${status})`);
|
else ok(false, `Art "${art}" liess sich nicht anlegen (HTTP ${status})`);
|
||||||
@@ -360,13 +402,141 @@ ok(angelegt === ARTEN.length, `alle ${angelegt} Arten lassen sich anlegen`);
|
|||||||
ok(status >= 400, `eine erfundene Art wird abgelehnt (HTTP ${status})`);
|
ok(status >= 400, `eine erfundene Art wird abgelehnt (HTTP ${status})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Der Creator SIEHT seinen Agentur-Bereich -- er ist der Grund, warum
|
/* =======================================================================
|
||||||
es ihn gibt. */
|
4b. FUER ALLE, NICHT FUER EINEN
|
||||||
|
|
||||||
|
Die Agentur ist der einzige Bereich, in dem ein Eintrag ALLEN gilt.
|
||||||
|
Geprueft wird deshalb beides: dass jeder Creator alles sieht -- und
|
||||||
|
dass diese Ausnahme NICHT auf die Betreuungsbereiche abfaerbt. Der
|
||||||
|
zweite Teil ist der wichtigere: Eine Sichtbarkeitsregel, die man an
|
||||||
|
der falschen Stelle aufmacht, gibt fremde Akten frei, und man sieht
|
||||||
|
es der Zeile nicht an.
|
||||||
|
======================================================================= */
|
||||||
|
melde("\n=== Fuer alle, nicht fuer einen ===");
|
||||||
{
|
{
|
||||||
const { status, daten } = await ruf("GET", "/workspace/api/bereich/agentur", keksLuna);
|
const { status, daten } = await ruf("GET", "/workspace/api/bereich/agentur", keksLuna);
|
||||||
ok(status === 200, `Luna darf den Bereich oeffnen (HTTP ${status})`);
|
ok(status === 200, `Luna darf den Bereich oeffnen (HTTP ${status})`);
|
||||||
ok((daten?.eintraege || []).length === ARTEN.length,
|
ok((daten?.eintraege || []).length === ARTEN.length,
|
||||||
`sie sieht ihre ${(daten?.eintraege || []).length} Eintraege`);
|
`sie sieht alle ${(daten?.eintraege || []).length} Eintraege — obwohl keiner ihr zugeordnet ist`);
|
||||||
|
ok((daten?.eintraege || []).every((e) => e.creator_id === null),
|
||||||
|
"und keiner davon traegt eine Creator-Zuordnung");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Mia ist eine ZWEITE Creatorin, die nichts angelegt hat und der
|
||||||
|
nichts gehoert. Wenn die Regel nur ueber `erstellt_von` gestolpert
|
||||||
|
waere, saehe Luna vielleicht etwas und Mia nichts. */
|
||||||
|
const { daten } = await ruf("GET", "/workspace/api/bereich/agentur", keksMia);
|
||||||
|
ok((daten?.eintraege || []).length === ARTEN.length,
|
||||||
|
`auch Mia sieht alle ${(daten?.eintraege || []).length} — sie hat mit keinem davon etwas zu tun`);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Eine ausdrueckliche Zuordnung muss der Server verwerfen. Sonst
|
||||||
|
genuegt ein Aufruf an der Oberflaeche vorbei -- oder ein spaeteres
|
||||||
|
Formular, das das Feld wieder mitschickt --, und das Event ist
|
||||||
|
fuer alle anderen wieder unsichtbar. */
|
||||||
|
await ruf("POST", "/workspace/api/bereich/agentur", keksDogi, {
|
||||||
|
art: "kampagne", titel: "Versuch mit Zuordnung", datum: heute, creator_id: idLuna,
|
||||||
|
});
|
||||||
|
const { daten } = await ruf("GET", "/workspace/api/bereich/agentur", keksMia);
|
||||||
|
const e = (daten?.eintraege || []).find((x) => x.titel === "Versuch mit Zuordnung");
|
||||||
|
ok(!!e, "ein Eintrag, der ausdruecklich Luna zugewiesen wurde, ist trotzdem fuer Mia da");
|
||||||
|
ok(e?.creator_id === null, `und seine Zuordnung wurde verworfen (creator_id = ${e?.creator_id})`);
|
||||||
|
/* Und derselbe Riegel fuer den freien Namen -- er wird an einer
|
||||||
|
ANDEREN Stelle gesetzt (externPruefen) und waere sonst das Loch
|
||||||
|
neben der geschlossenen Tuer. */
|
||||||
|
await ruf("POST", "/workspace/api/bereich/agentur", keksDogi, {
|
||||||
|
art: "kampagne", titel: "Versuch mit Namen", datum: heute, creator_extern: "Marke XY",
|
||||||
|
});
|
||||||
|
const { daten: d2 } = await ruf("GET", "/workspace/api/bereich/agentur", keksMia);
|
||||||
|
const n = (d2?.eintraege || []).find((x) => x.titel === "Versuch mit Namen");
|
||||||
|
ok(n?.creator_extern === null || n?.creator_extern === undefined,
|
||||||
|
`auch ein frei getippter Name wird verworfen (creator_extern = ${JSON.stringify(n?.creator_extern)})`);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* DIE ENTSCHEIDENDE GEGENPROBE.
|
||||||
|
|
||||||
|
Die Ausnahme haette man auch in sichtbar() einbauen koennen -- eine
|
||||||
|
Zeile weniger, und dieselbe Wirkung fuer die Agentur. Nur haengen
|
||||||
|
an derselben Funktion auch Aufgaben, Dateien, Termine und Calls.
|
||||||
|
Diese Pruefung ist der Grund, warum das auffiele. */
|
||||||
|
await ruf("POST", "/workspace/api/bereich/technik", keksDogi, {
|
||||||
|
art: "problem", titel: "Nur fuer Mia", datum: heute, creator_id: idMia,
|
||||||
|
});
|
||||||
|
const { daten } = await ruf("GET", "/workspace/api/bereich/technik", keksLuna);
|
||||||
|
const fremd = (daten?.eintraege || []).filter((e) => e.titel === "Nur fuer Mia");
|
||||||
|
ok(fremd.length === 0,
|
||||||
|
`Luna sieht Mias Technik-Eintrag NICHT — die Agentur-Ausnahme faerbt nicht ab (${fremd.length} gefunden)`);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Sehen ja, schreiben nein -- ausdruecklicher Wunsch: "die sollen
|
||||||
|
alles sehen was wir eintragen aber nicht eintragen koennen". */
|
||||||
|
const { status } = await ruf("POST", "/workspace/api/bereich/agentur", keksLuna, {
|
||||||
|
art: "kampagne", titel: "Von Luna", datum: heute,
|
||||||
|
});
|
||||||
|
ok(status === 403, `Luna darf hier NICHTS eintragen (HTTP ${status})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
4c. AGENTUR-EVENTS: Zeitraum, Aufgaben, Regeln
|
||||||
|
======================================================================= */
|
||||||
|
melde("\n=== Agentur-Events ===");
|
||||||
|
{
|
||||||
|
/* ORTSZEIT, nicht UTC. `new Date(...).toISOString().slice(0,10)` waere
|
||||||
|
zwischen Mitternacht und zwei Uhr einen Tag daneben -- und weil der
|
||||||
|
Server den Zeitraum gegen `heute` (Ortszeit) prueft, waere diese
|
||||||
|
Pruefung nachts rot, ohne dass sich etwas geaendert haette.
|
||||||
|
Gefunden von pruef-struktur, das genau danach sucht. Mittags
|
||||||
|
gerechnet, damit auch eine Zeitumstellung im Zeitraum nichts
|
||||||
|
verschiebt. */
|
||||||
|
const ende = (() => {
|
||||||
|
const d = new Date(`${heute}T12:00:00`);
|
||||||
|
d.setDate(d.getDate() + 14);
|
||||||
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
||||||
|
})();
|
||||||
|
const { status } = await ruf("POST", "/workspace/api/bereich/agentur", keksDogi, {
|
||||||
|
art: "kampagne", titel: "Sommer-Aktion", text: "Beschreibung", datum: heute,
|
||||||
|
event_ende: ende, event_aufgaben: "1 Punkt je Live-Stunde", event_regeln: "Nur eigenes Konto",
|
||||||
|
});
|
||||||
|
ok(status === 201, `ein Event mit Zeitraum, Aufgaben und Regeln laesst sich anlegen (HTTP ${status})`);
|
||||||
|
|
||||||
|
const { daten } = await ruf("GET", "/workspace/api/bereich/agentur", keksLuna);
|
||||||
|
const e = (daten?.eintraege || []).find((x) => x.titel === "Sommer-Aktion");
|
||||||
|
ok(e?.event_ende === ende, `das Ende kommt beim Creator an (${e?.event_ende})`);
|
||||||
|
ok(e?.event_aufgaben === "1 Punkt je Live-Stunde", "die Aufgaben kommen an");
|
||||||
|
ok(e?.event_regeln === "Nur eigenes Konto", "die Regeln kommen an");
|
||||||
|
|
||||||
|
/* GEGENPROBEN. Ohne sie hiesse "es laesst sich anlegen" nur, dass der
|
||||||
|
Server irgendetwas annimmt. */
|
||||||
|
const verdreht = await ruf("POST", "/workspace/api/bereich/agentur", keksDogi, {
|
||||||
|
art: "kampagne", titel: "Verdreht", datum: ende, event_ende: heute });
|
||||||
|
ok(verdreht.status === 400, `ein Ende VOR dem Beginn wird abgelehnt (HTTP ${verdreht.status})`);
|
||||||
|
|
||||||
|
const unsinn = await ruf("POST", "/workspace/api/bereich/agentur", keksDogi, {
|
||||||
|
art: "kampagne", titel: "Unsinn", datum: heute, event_ende: "31.12.2026" });
|
||||||
|
ok(unsinn.status === 400, `ein Datum in falscher Schreibweise wird abgelehnt (HTTP ${unsinn.status})`);
|
||||||
|
|
||||||
|
/* Beim AENDERN gilt dasselbe -- und zwar auch dann, wenn nur EINE
|
||||||
|
der beiden Seiten mitgeschickt wird. Genau hier waere die Pruefung
|
||||||
|
sonst blind: pruefe() sieht nur, was im Aufruf steht. */
|
||||||
|
const { daten: d3 } = await ruf("GET", "/workspace/api/bereich/agentur", keksDogi);
|
||||||
|
const id = (d3?.eintraege || []).find((x) => x.titel === "Sommer-Aktion")?.id;
|
||||||
|
const nurEnde = await ruf("PATCH", `/workspace/api/bereich/agentur/${id}`, keksDogi,
|
||||||
|
{ event_ende: "2020-01-01" });
|
||||||
|
ok(nurEnde.status === 400,
|
||||||
|
`auch beim Aendern nur des Endes schlaegt der verdrehte Zeitraum an (HTTP ${nurEnde.status})`);
|
||||||
|
const nurBeginn = await ruf("PATCH", `/workspace/api/bereich/agentur/${id}`, keksDogi,
|
||||||
|
{ datum: "2099-01-01" });
|
||||||
|
ok(nurBeginn.status === 400,
|
||||||
|
`und ebenso, wenn nur der Beginn nach hinten geschoben wird (HTTP ${nurBeginn.status})`);
|
||||||
|
|
||||||
|
/* Die Event-Felder gehoeren der Agentur. In einem anderen Bereich
|
||||||
|
muessen sie stillschweigend verfallen -- sonst haengt eines Tages
|
||||||
|
ein Preisausschreiben an einem Schutzvorfall. */
|
||||||
|
await ruf("POST", "/workspace/api/bereich/schutz", keksDogi, {
|
||||||
|
art: "vorfall", titel: "Kein Event", datum: heute, event_regeln: "darf nicht ankommen" });
|
||||||
|
const { daten: d4 } = await ruf("GET", "/workspace/api/bereich/schutz", keksDogi);
|
||||||
|
const v = (d4?.eintraege || []).find((x) => x.titel === "Kein Event");
|
||||||
|
ok(!v?.event_regeln, `im Schutz-Bereich verfallen die Event-Felder (${JSON.stringify(v?.event_regeln)})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =======================================================================
|
/* =======================================================================
|
||||||
@@ -451,6 +621,75 @@ melde("\n=== Die Kachel ===");
|
|||||||
fehlend.length ? `diese Eintraege fehlen auf der Seite: ${fehlend.join(", ")}`
|
fehlend.length ? `diese Eintraege fehlen auf der Seite: ${fehlend.join(", ")}`
|
||||||
: `alle vier Titel stehen da: ${kartenTitel.join(" · ")}`);
|
: `alle vier Titel stehen da: ${kartenTitel.join(" · ")}`);
|
||||||
|
|
||||||
|
/* ---- Das Event auf dem Bildschirm --------------------------------
|
||||||
|
Bis hierher ist bewiesen, dass die Daten stimmen. Das sagt noch
|
||||||
|
nichts darueber, ob jemand sie SIEHT: Zeitraum, Aufgaben und
|
||||||
|
Regeln koennen vollstaendig in der Antwort stehen und trotzdem
|
||||||
|
nirgends gezeichnet werden -- ein vergessener Aufruf in karte()
|
||||||
|
reicht, und niemand merkt es, weil die Karte ja da ist. */
|
||||||
|
const event = await seite.$$eval(".eintrag-karte", (karten) => {
|
||||||
|
const k = karten.find((x) => x.querySelector(".eintrag-titel")?.textContent.trim() === "Sommer-Aktion");
|
||||||
|
if (!k) return null;
|
||||||
|
return {
|
||||||
|
stand: k.dataset.event,
|
||||||
|
marke: k.querySelector(".event-zeitraum__marke")?.textContent.trim(),
|
||||||
|
spanne: k.querySelector(".event-zeitraum__spanne")?.textContent.trim(),
|
||||||
|
schilder: [...k.querySelectorAll(".event-block__schild")].map((s) => s.textContent.trim()),
|
||||||
|
texte: [...k.querySelectorAll(".event-block__text")].map((s) => s.textContent.trim()),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
ok(!!event, "die Event-Karte Sommer-Aktion steht auf der Seite");
|
||||||
|
ok(event?.stand === "laeuft", `sie ist als laufend gekennzeichnet ("${event?.stand}")`);
|
||||||
|
ok(/läuft bis/.test(event?.marke || ""),
|
||||||
|
`der Zustand steht als WORT da, nicht nur als Farbe ("${event?.marke}")`);
|
||||||
|
ok(/–/.test(event?.spanne || ""), `und der Zeitraum als Spanne ("${event?.spanne}")`);
|
||||||
|
ok(event?.schilder.join(",") === "Aufgaben,Regeln",
|
||||||
|
`beide Bloecke sind beschriftet (${event?.schilder.join(", ")})`);
|
||||||
|
ok(event?.texte.includes("1 Punkt je Live-Stunde") && event?.texte.includes("Nur eigenes Konto"),
|
||||||
|
"und tragen wirklich ihren Inhalt");
|
||||||
|
|
||||||
|
/* GEGENPROBE dazu: Eine Karte, die KEIN Event ist, darf nichts davon
|
||||||
|
haben. Sonst bewiese der Block oben nur, dass die Elemente
|
||||||
|
existieren -- nicht, dass sie zur richtigen Art gehoeren. */
|
||||||
|
const schulung = await seite.$$eval(".eintrag-karte", (karten) => {
|
||||||
|
const k = karten.find((x) => x.querySelector(".eintrag-titel")?.textContent.trim() === "Test schulung");
|
||||||
|
return k ? { event: k.dataset.event ?? null, bloecke: k.querySelectorAll(".event-block").length } : null;
|
||||||
|
});
|
||||||
|
ok(schulung && !schulung.event && schulung.bloecke === 0,
|
||||||
|
`eine Schulung bekommt weder Zustand noch Event-Bloecke (${JSON.stringify(schulung)})`);
|
||||||
|
|
||||||
|
/* ---- Die Zuordnung bietet nur "Agentur" an ------------------------
|
||||||
|
Der Ausgangspunkt des ganzen Umbaus: Hier stand die Creator-Liste,
|
||||||
|
und ein versehentlicher Klick darauf machte das Event fuer alle
|
||||||
|
anderen unsichtbar. */
|
||||||
|
await seite.click("#neu-oeffnen");
|
||||||
|
await seite.waitForTimeout(400);
|
||||||
|
const wahl = await seite.$$eval("#f-creator option", (o) => o.map((x) => x.textContent.trim()));
|
||||||
|
ok(wahl.length === 1 && wahl[0] === "Agentur",
|
||||||
|
`die Zuordnung bietet genau eine Wahl an: ${JSON.stringify(wahl)}`);
|
||||||
|
const hinweis = await seite.$eval("#hinweis-creator", (e) => e.textContent.trim()).catch(() => "");
|
||||||
|
ok(/allen/.test(hinweis), `und sagt, was das bedeutet ("${hinweis}")`);
|
||||||
|
|
||||||
|
/* ---- Das Formular wechselt mit der Art ---------------------------
|
||||||
|
Beim Oeffnen steht die erste Art (Agentur-Events) drin, also
|
||||||
|
muessen die Event-Felder sichtbar sein. Wechselt man auf Schulung,
|
||||||
|
muessen sie verschwinden -- und geleert werden, sonst faehrt ein
|
||||||
|
unsichtbares Enddatum an einer Schulung mit. */
|
||||||
|
const sichtbar = (id) => seite.$eval(id, (e) => !e.hidden);
|
||||||
|
ok(await sichtbar("#feld-ende") && await sichtbar("#feld-aufgaben") && await sichtbar("#feld-regeln"),
|
||||||
|
"bei Agentur-Events stehen Zeitraum, Aufgaben und Regeln im Formular");
|
||||||
|
const schild = await seite.$eval("#schild-titel", (e) => e.textContent.trim());
|
||||||
|
ok(schild === "Titel des Events", `und die Beschriftung passt zur Art ("${schild}")`);
|
||||||
|
|
||||||
|
await seite.fill("#f-ende", "2030-01-01");
|
||||||
|
await seite.selectOption("#f-art", "schulung");
|
||||||
|
await seite.waitForTimeout(300);
|
||||||
|
ok(!(await sichtbar("#feld-ende")) && !(await sichtbar("#feld-aufgaben")),
|
||||||
|
"bei Schulung verschwinden sie wieder");
|
||||||
|
const restEnde = await seite.$eval("#f-ende", (e) => e.value);
|
||||||
|
ok(restEnde === "",
|
||||||
|
`und das Enddatum faehrt nicht unsichtbar mit (Wert: "${restEnde}")`);
|
||||||
|
|
||||||
/* GEGENPROBE zum Selektor: Ein erfundener Bereich darf NICHT wie ein
|
/* GEGENPROBE zum Selektor: Ein erfundener Bereich darf NICHT wie ein
|
||||||
echter aussehen -- weder in der Ueberschrift noch mit Eintraegen.
|
echter aussehen -- weder in der Ueberschrift noch mit Eintraegen.
|
||||||
Die Anwendung schickt einen dorthin zurueck, wo er hingehoert. */
|
Die Anwendung schickt einen dorthin zurueck, wo er hingehoert. */
|
||||||
|
|||||||
@@ -101,19 +101,45 @@ export const BEREICHE = {
|
|||||||
sieht man den Unterschied in einer Liste nicht.
|
sieht man den Unterschied in einer Liste nicht.
|
||||||
Bewertung: nein. Hier wird nichts benotet; es ist ein
|
Bewertung: nein. Hier wird nichts benotet; es ist ein
|
||||||
Zusammenarbeits-Bereich, kein Analysebereich. */
|
Zusammenarbeits-Bereich, kein Analysebereich. */
|
||||||
|
/* FUER ALLE, NICHT FUER EINEN (07.09.2026).
|
||||||
|
|
||||||
|
Die anderen fuenf Bereiche sind Betreuungsakten: Dort steht etwas
|
||||||
|
UEBER einen Creator, und nur er und seine Betreuung sehen es. Die
|
||||||
|
Agentur ist das Gegenteil -- ein Event, eine Schulung, eine
|
||||||
|
Zustaendigkeit gilt fuer alle gleichzeitig.
|
||||||
|
|
||||||
|
Bis heute lief sie trotzdem unter der Akten-Regel, und das hatte
|
||||||
|
eine Folge, die niemandem auffiel: Ein Event ohne Creator-Zuordnung
|
||||||
|
traf weder `creator_id = ich` noch `erstellt_von = ich` -- fuer
|
||||||
|
jeden Creator war die Agentur-Seite schlicht LEER. Nicht "kaputt",
|
||||||
|
nicht "Fehler": leer, so wie eine Seite aussieht, auf der noch
|
||||||
|
nichts steht. Gemessen am 07.09.2026: Von drei Eintraegen sah die
|
||||||
|
Creatorin genau den einen, der ihr zugeordnet war.
|
||||||
|
|
||||||
|
Zwei Schalter, weil es zwei verschiedene Fragen sind:
|
||||||
|
fuerAlle -- jeder sieht jeden Eintrag dieses Bereichs
|
||||||
|
ohneCreatorBezug -- ein Eintrag gehoert hier NIEMANDEM einzeln */
|
||||||
agentur: {
|
agentur: {
|
||||||
name: "Agentur",
|
name: "Agentur",
|
||||||
arten: {
|
arten: {
|
||||||
kampagne: "Event & Kampagne",
|
kampagne: "Agentur-Events",
|
||||||
schulung: "Schulung",
|
schulung: "Schulung",
|
||||||
anliegen: "Anliegen an die Agentur",
|
anliegen: "Anliegen an die Agentur",
|
||||||
zustaendig: "Zuständigkeit",
|
zustaendig: "Zuständigkeit",
|
||||||
},
|
},
|
||||||
bewertung: false,
|
bewertung: false,
|
||||||
dringlichkeit: true,
|
dringlichkeit: true,
|
||||||
|
fuerAlle: true,
|
||||||
|
ohneCreatorBezug: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Aus den Bereichseinstellungen abgeleitet, nicht danebengeschrieben.
|
||||||
|
Eine zweite Liste waere beim naechsten Bereich auseinandergelaufen --
|
||||||
|
und zwar still. */
|
||||||
|
const BEREICHE_FUER_ALLE = Object.entries(BEREICHE)
|
||||||
|
.filter(([, e]) => e.fuerAlle).map(([k]) => k);
|
||||||
|
|
||||||
const DRINGLICHKEITEN = ["hoch", "mittel", "niedrig"];
|
const DRINGLICHKEITEN = ["hoch", "mittel", "niedrig"];
|
||||||
const STATUS = ["offen", "erledigt"];
|
const STATUS = ["offen", "erledigt"];
|
||||||
const TITEL_MAX = 160;
|
const TITEL_MAX = 160;
|
||||||
@@ -256,10 +282,41 @@ export function sichtbar(person) {
|
|||||||
: { wo: "e.erstellt_von = ?", werte: [person.id] };
|
: { wo: "e.erstellt_von = ?", werte: [person.id] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dieselbe Regel, aber mit der Ausnahme fuer Bereiche, die allen
|
||||||
|
gehoeren.
|
||||||
|
|
||||||
|
BEWUSST EINE EIGENE FUNKTION, NICHT EINE AENDERUNG AN sichtbar():
|
||||||
|
sichtbar() beantwortet auch Fragen zu Aufgaben, Dateien, Terminen und
|
||||||
|
Calls (siehe die Aufrufe in workspace-aufgaben.js,
|
||||||
|
workspace-dateien.js, workspace-kalender.js, workspace-calls.js). Wer
|
||||||
|
dort "1=1" einschleust, weil er an Agentur-Eintraege dachte, oeffnet
|
||||||
|
nebenbei fremde Dateien und fremde Termine -- ein Loch, das man dem
|
||||||
|
Code nicht ansieht, weil an der geaenderten Stelle nichts davon
|
||||||
|
steht.
|
||||||
|
|
||||||
|
Nur Eintraege gehen hier durch, und nur die aus einem Bereich mit
|
||||||
|
`fuerAlle`. Der Rest faellt woertlich auf die alte Regel zurueck.
|
||||||
|
|
||||||
|
`praefix` ist da, weil die Suche dieselbe Tabelle unter demselben
|
||||||
|
Kuerzel "e" fuehrt -- geht das eines Tages auseinander, faellt es
|
||||||
|
beim Aufruf auf, nicht erst im Betrieb. */
|
||||||
|
export function sichtbarEintrag(person, praefix = "e") {
|
||||||
|
const regel = sichtbar(person);
|
||||||
|
if (!regel) return regel;
|
||||||
|
if (regel.wo === "1=1") return regel; // DogFather sieht ohnehin alles
|
||||||
|
if (!BEREICHE_FUER_ALLE.length) return regel;
|
||||||
|
const liste = BEREICHE_FUER_ALLE.map(() => "?").join(", ");
|
||||||
|
return {
|
||||||
|
wo: `(${praefix}.bereich IN (${liste}) OR ${regel.wo})`,
|
||||||
|
werte: [...BEREICHE_FUER_ALLE, ...regel.werte],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const SPALTEN = `
|
const SPALTEN = `
|
||||||
e.id, e.bereich, e.art, e.titel, e.text, e.datum, e.bewertung,
|
e.id, e.bereich, e.art, e.titel, e.text, e.datum, e.bewertung,
|
||||||
e.dringlichkeit, e.status, e.creator_id, e.erstellt, e.erstellt_von, e.geaendert,
|
e.dringlichkeit, e.status, e.creator_id, e.erstellt, e.erstellt_von, e.geaendert,
|
||||||
e.hook, e.format, e.saeule_id, e.geplant,
|
e.hook, e.format, e.saeule_id, e.geplant,
|
||||||
|
e.event_ende, e.event_aufgaben, e.event_regeln,
|
||||||
e.creator_extern,
|
e.creator_extern,
|
||||||
${externSql("pc.name", "e.creator_extern")} AS creator_name,
|
${externSql("pc.name", "e.creator_extern")} AS creator_name,
|
||||||
pe.name AS erstellt_name,
|
pe.name AS erstellt_name,
|
||||||
@@ -289,7 +346,7 @@ bereicheRouter.get("/workspace/api/bereich/:bereich", (req, res) => {
|
|||||||
const einstellung = BEREICHE[bereich];
|
const einstellung = BEREICHE[bereich];
|
||||||
if (!einstellung) return res.status(404).json({ fehler: "nicht_gefunden" });
|
if (!einstellung) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||||
|
|
||||||
const regel = sichtbar(req.sicht || req.person);
|
const regel = sichtbarEintrag(req.sicht || req.person);
|
||||||
if (!regel) return res.status(404).json({ fehler: "nicht_gefunden" });
|
if (!regel) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||||
|
|
||||||
const eintraege = db().prepare(`
|
const eintraege = db().prepare(`
|
||||||
@@ -389,6 +446,35 @@ function pruefe(bereich, körper, { neu }) {
|
|||||||
} else aus.geplant = g;
|
} else aus.geplant = g;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* ---- Agentur-Events: Zeitraum, Aufgaben, Regeln -------------------
|
||||||
|
Nur im Agentur-Bereich, nach demselben Muster wie die vier
|
||||||
|
Content-Felder darueber: anderswo werden sie stillschweigend
|
||||||
|
verworfen. Sonst haenge eines Tages ein Preisausschreiben an einem
|
||||||
|
Schutzvorfall. */
|
||||||
|
if (bereich === "agentur") {
|
||||||
|
if (körper.event_ende !== undefined) {
|
||||||
|
const e = String(körper.event_ende ?? "").trim();
|
||||||
|
if (!e) aus.event_ende = null;
|
||||||
|
else if (!/^\d{4}-\d{2}-\d{2}$/.test(e) || Number.isNaN(Date.parse(e))) {
|
||||||
|
fehler.push("Das Ende des Zeitraums ist ungültig.");
|
||||||
|
} else aus.event_ende = e;
|
||||||
|
}
|
||||||
|
for (const [feld, name] of [["event_aufgaben", "Die Aufgaben"], ["event_regeln", "Die Regeln"]]) {
|
||||||
|
if (körper[feld] === undefined) continue;
|
||||||
|
const t = String(körper[feld] ?? "").trim();
|
||||||
|
if (t.length > TEXT_MAX) fehler.push(`${name} sind zu lang.`);
|
||||||
|
else aus[feld] = t || null;
|
||||||
|
}
|
||||||
|
/* "Bis" vor "von" ist kein Zeitraum, sondern ein Tippfehler -- und
|
||||||
|
einer, den man einer Liste nicht ansieht: Der Eintrag stuende da,
|
||||||
|
liefe aber schon abgelaufen ein. Geprueft wird gegen das Datum,
|
||||||
|
das GERADE gesetzt wird; beim Aendern nur einer der beiden Seiten
|
||||||
|
ergaenzt der Aufrufer die andere mit (siehe PATCH). */
|
||||||
|
if (aus.event_ende && aus.datum && aus.event_ende < aus.datum) {
|
||||||
|
fehler.push("Das Ende liegt vor dem Beginn.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (körper.creator_id !== undefined) {
|
if (körper.creator_id !== undefined) {
|
||||||
const w = körper.creator_id;
|
const w = körper.creator_id;
|
||||||
if (w === null || w === "") aus.creator_id = null;
|
if (w === null || w === "") aus.creator_id = null;
|
||||||
@@ -405,6 +491,27 @@ function pruefe(bereich, körper, { neu }) {
|
|||||||
Konto; sichtbar bleibt er ueber erstellt_von (siehe sichtbar()). */
|
Konto; sichtbar bleibt er ueber erstellt_von (siehe sichtbar()). */
|
||||||
externPruefen(körper, aus, "creator", fehler);
|
externPruefen(körper, aus, "creator", fehler);
|
||||||
|
|
||||||
|
/* Ein Agentur-Eintrag gehoert NIEMANDEM einzeln (07.09.2026).
|
||||||
|
|
||||||
|
Er gilt fuer alle, und genau deshalb sieht ihn auch jeder (siehe
|
||||||
|
`fuerAlle` oben). Eine Zuordnung waere hier nicht bloss unnoetig,
|
||||||
|
sie waere irrefuehrend: Ein Event mit dem Namen einer Creatorin
|
||||||
|
daneben liest sich, als sei es ihres. Die Oberflaeche bietet
|
||||||
|
deshalb nur noch "Agentur" an -- und diese Zeilen sorgen dafuer,
|
||||||
|
dass ein Aufruf an der Oberflaeche vorbei zum selben Ergebnis
|
||||||
|
kommt. Eine Regel, die nur im Formular steht, ist keine Regel.
|
||||||
|
|
||||||
|
GANZ ZUM SCHLUSS, und das ist der Punkt: Der freie Name wird eine
|
||||||
|
Zeile darueber gesetzt. Stuende dieser Riegel vorher -- der
|
||||||
|
naheliegende Ort, gleich bei der Creator-Zuordnung --, haette
|
||||||
|
externPruefen ihn danach wieder aufgemacht, und ein getippter Name
|
||||||
|
stuende trotz allem am Event. Zwei richtige Regeln, falsche
|
||||||
|
Reihenfolge, kein Fehler zu sehen. */
|
||||||
|
if (einstellung.ohneCreatorBezug) {
|
||||||
|
aus.creator_id = null;
|
||||||
|
aus.creator_extern = null;
|
||||||
|
}
|
||||||
|
|
||||||
return { aus, fehler };
|
return { aus, fehler };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,12 +564,14 @@ bereicheRouter.post("/workspace/api/bereich/:bereich", gleicheHerkunft, (req, re
|
|||||||
const { lastInsertRowid } = db().prepare(`
|
const { lastInsertRowid } = db().prepare(`
|
||||||
INSERT INTO eintraege
|
INSERT INTO eintraege
|
||||||
(bereich, art, titel, text, datum, bewertung, dringlichkeit, status,
|
(bereich, art, titel, text, datum, bewertung, dringlichkeit, status,
|
||||||
creator_id, creator_extern, erstellt, erstellt_von, hook, format, saeule_id, geplant)
|
creator_id, creator_extern, erstellt, erstellt_von, hook, format, saeule_id, geplant,
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(
|
event_ende, event_aufgaben, event_regeln)
|
||||||
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(
|
||||||
bereich, aus.art, aus.titel, aus.text ?? null, aus.datum,
|
bereich, aus.art, aus.titel, aus.text ?? null, aus.datum,
|
||||||
aus.bewertung ?? null, aus.dringlichkeit ?? "mittel", aus.status ?? "offen",
|
aus.bewertung ?? null, aus.dringlichkeit ?? "mittel", aus.status ?? "offen",
|
||||||
aus.creator_id ?? null, aus.creator_extern ?? null, jetzt(), req.person.id,
|
aus.creator_id ?? null, aus.creator_extern ?? null, jetzt(), req.person.id,
|
||||||
aus.hook ?? null, aus.format ?? null, aus.saeule_id ?? null, aus.geplant ?? null);
|
aus.hook ?? null, aus.format ?? null, aus.saeule_id ?? null, aus.geplant ?? null,
|
||||||
|
aus.event_ende ?? null, aus.event_aufgaben ?? null, aus.event_regeln ?? null);
|
||||||
|
|
||||||
protokolliere("eintrag_angelegt", {
|
protokolliere("eintrag_angelegt", {
|
||||||
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),
|
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),
|
||||||
@@ -478,7 +587,7 @@ bereicheRouter.post("/workspace/api/bereich/:bereich", gleicheHerkunft, (req, re
|
|||||||
/* ---------- Ändern und Löschen ------------------------------------------- */
|
/* ---------- Ändern und Löschen ------------------------------------------- */
|
||||||
|
|
||||||
function holen(req, id) {
|
function holen(req, id) {
|
||||||
const regel = sichtbar(req.person);
|
const regel = sichtbarEintrag(req.person);
|
||||||
if (!regel) return null;
|
if (!regel) return null;
|
||||||
return db().prepare(`SELECT e.* ${VERBUND} WHERE ${regel.wo} AND e.id = ?`)
|
return db().prepare(`SELECT e.* ${VERBUND} WHERE ${regel.wo} AND e.id = ?`)
|
||||||
.get(...regel.werte, id);
|
.get(...regel.werte, id);
|
||||||
@@ -497,6 +606,21 @@ bereicheRouter.patch("/workspace/api/bereich/:bereich/:id", gleicheHerkunft, (re
|
|||||||
if (fehler.length) return res.status(400).json({ fehler: fehler.join(" ") });
|
if (fehler.length) return res.status(400).json({ fehler: fehler.join(" ") });
|
||||||
if (!istLeitung(req.person)) delete aus.creator_id;
|
if (!istLeitung(req.person)) delete aus.creator_id;
|
||||||
|
|
||||||
|
/* Zeitraum beim AENDERN -- genauso wichtig wie beim Anlegen und
|
||||||
|
leichter zu uebersehen: pruefe() sieht nur die Felder, die im
|
||||||
|
Aufruf stehen. Wer nur das Ende verschiebt, schickt kein `datum`
|
||||||
|
mit; die Pruefung dort haette nichts zu vergleichen und liesse
|
||||||
|
jedes Ende durch. Deshalb hier gegen den GESPEICHERTEN Wert, und
|
||||||
|
zwar in beide Richtungen -- man kann den Zeitraum auch dadurch
|
||||||
|
verdrehen, dass man den Beginn nach hinten schiebt. */
|
||||||
|
if (bereich === "agentur" && (aus.event_ende !== undefined || aus.datum !== undefined)) {
|
||||||
|
const von = aus.datum !== undefined ? aus.datum : eintrag.datum;
|
||||||
|
const bis = aus.event_ende !== undefined ? aus.event_ende : eintrag.event_ende;
|
||||||
|
if (von && bis && bis < von) {
|
||||||
|
return res.status(400).json({ fehler: "Das Ende liegt vor dem Beginn." });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Beim Aendern gilt dieselbe Regel -- sonst waere die Pruefung beim
|
/* Beim Aendern gilt dieselbe Regel -- sonst waere die Pruefung beim
|
||||||
Anlegen wertlos: Man legt ohne Saeule an und haengt sie danach an. */
|
Anlegen wertlos: Man legt ohne Saeule an und haengt sie danach an. */
|
||||||
if (aus.saeule_id !== undefined) {
|
if (aus.saeule_id !== undefined) {
|
||||||
|
|||||||
@@ -136,7 +136,20 @@ hinweisRouter.get("/workspace/api/hinweise", (req, res) => {
|
|||||||
WHERE ${d.wo} AND d.status = 'review'`, d.werte));
|
WHERE ${d.wo} AND d.status = 'review'`, d.werte));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- Betreuungsbereiche ---------- */
|
/* ---------- Betreuungsbereiche ----------
|
||||||
|
HIER BLEIBT ES ABSICHTLICH BEI sichtbar() (07.09.2026).
|
||||||
|
|
||||||
|
Seit heute gibt es daneben sichtbarEintrag(), das Agentur-
|
||||||
|
Eintraege fuer alle sichtbar macht. Hier waere das falsch, und
|
||||||
|
zwar aus zwei Gruenden: Der Hinweis fuehrt fest nach
|
||||||
|
`bereich.html?b=live` -- ein Creator bekaeme also eine Zahl aus
|
||||||
|
der Agentur und landete beim Klick in einem Bereich, in dem
|
||||||
|
nichts davon steht. Und ein dringender Agentur-Punkt ist die
|
||||||
|
Aufgabe der Agentur, nicht seine; ein Hinweis, den man nicht
|
||||||
|
abarbeiten kann, ist Laerm.
|
||||||
|
|
||||||
|
Wer das eines Tages umstellen will, muss zuerst das Sprungziel
|
||||||
|
mitwandern lassen. */
|
||||||
const e = sichtbarEintraege(person);
|
const e = sichtbarEintraege(person);
|
||||||
if (e) {
|
if (e) {
|
||||||
dazu("bereiche_dringend", "warnung",
|
dazu("bereiche_dringend", "warnung",
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ import {
|
|||||||
import { sichtbar as sichtbarAufgaben } from "./workspace-aufgaben.js";
|
import { sichtbar as sichtbarAufgaben } from "./workspace-aufgaben.js";
|
||||||
import { sichtbar as sichtbarTermine } from "./workspace-kalender.js";
|
import { sichtbar as sichtbarTermine } from "./workspace-kalender.js";
|
||||||
import { sichtbar as sichtbarDateien } from "./workspace-dateien.js";
|
import { sichtbar as sichtbarDateien } from "./workspace-dateien.js";
|
||||||
import { sichtbar as sichtbarEintraege, BEREICHE } from "./workspace-bereiche.js";
|
/* sichtbarEintrag, NICHT sichtbar: Sonst faende ein Creator ueber die
|
||||||
|
Suche kein einziges Agentur-Event -- obwohl es auf der Agentur-Seite
|
||||||
|
vor ihm steht. Eine Suche, die weniger findet als die Seite zeigt,
|
||||||
|
liest sich wie "gibt es nicht". */
|
||||||
|
import { sichtbarEintrag as sichtbarEintraege, BEREICHE } from "./workspace-bereiche.js";
|
||||||
|
|
||||||
export const sucheRouter = express.Router();
|
export const sucheRouter = express.Router();
|
||||||
|
|
||||||
|
|||||||
+41
-3
@@ -246,6 +246,28 @@ function umstellungen(d) {
|
|||||||
["aufgaben", "abgebrochen_am", "TEXT"],
|
["aufgaben", "abgebrochen_am", "TEXT"],
|
||||||
["aufgaben", "abbruch_von", "INTEGER REFERENCES personen(id) ON DELETE SET NULL"],
|
["aufgaben", "abbruch_von", "INTEGER REFERENCES personen(id) ON DELETE SET NULL"],
|
||||||
["aufgaben", "status_vorher", "TEXT"],
|
["aufgaben", "status_vorher", "TEXT"],
|
||||||
|
|
||||||
|
/* AGENTUR-EVENTS (07.09.2026).
|
||||||
|
|
||||||
|
Ein Event ist kein Notizzettel mit Ueberschrift und Text. Wer
|
||||||
|
mitmachen soll, muss vier Dinge finden, ohne zu fragen: bis wann
|
||||||
|
es laeuft, was zu tun ist, was es zu gewinnen gibt und was
|
||||||
|
verboten ist. Genau daran scheitern Aktionen -- nicht am Aufruf,
|
||||||
|
sondern an den Rueckfragen danach.
|
||||||
|
|
||||||
|
Der BEGINN ist `datum` (gibt es schon, ist NOT NULL). Neu ist
|
||||||
|
das Ende und die beiden Textfelder. `event_`-Vorsatz, weil es im
|
||||||
|
Workspace bereits eine Tabelle `aufgaben` gibt -- eine Spalte
|
||||||
|
`aufgaben` auf `eintraege` waere beim Lesen von Code jedes Mal
|
||||||
|
eine Verwechslung.
|
||||||
|
|
||||||
|
ADD COLUMN und kein Tabellenneubau: Es aendert sich kein CHECK,
|
||||||
|
also darf die Tabelle stehen bleiben. Der Neubau vom 06.09. war
|
||||||
|
noetig, weil dort der erlaubte Wertebereich von `bereich` wuchs
|
||||||
|
-- und er ist der Weg, bei dem man Inhalte verlieren kann. */
|
||||||
|
["eintraege", "event_ende", "TEXT"],
|
||||||
|
["eintraege", "event_aufgaben", "TEXT"],
|
||||||
|
["eintraege", "event_regeln", "TEXT"],
|
||||||
]) {
|
]) {
|
||||||
try {
|
try {
|
||||||
const vorhanden = d.prepare(`PRAGMA table_info(${tabelle})`).all().map((s) => s.name);
|
const vorhanden = d.prepare(`PRAGMA table_info(${tabelle})`).all().map((s) => s.name);
|
||||||
@@ -501,15 +523,31 @@ function umstellungen(d) {
|
|||||||
format TEXT,
|
format TEXT,
|
||||||
saeule_id INTEGER,
|
saeule_id INTEGER,
|
||||||
geplant TEXT,
|
geplant TEXT,
|
||||||
creator_extern TEXT
|
creator_extern TEXT,
|
||||||
|
/* Die drei Event-Spalten MUESSEN hier mit stehen (07.09.2026).
|
||||||
|
|
||||||
|
Der Spalten-Nachtrag weiter oben laeuft frueher als dieser
|
||||||
|
Neubau. Auf einer Datenbank, die noch den alten CHECK hat
|
||||||
|
-- eine Sicherung von vor dem 06.09., in einen heutigen
|
||||||
|
Stand eingespielt --, waeren die drei Spalten also erst
|
||||||
|
angelegt und hier sofort wieder weggeworfen worden: mit
|
||||||
|
allem, was drinsteht, ohne Fehlermeldung, und die
|
||||||
|
Zeilenzahl haette weiterhin gestimmt. Genau die
|
||||||
|
Verlustart, vor der der Kommentar zu dieser Umstellung
|
||||||
|
warnt. */
|
||||||
|
event_ende TEXT,
|
||||||
|
event_aufgaben TEXT,
|
||||||
|
event_regeln TEXT
|
||||||
);
|
);
|
||||||
INSERT INTO eintraege_neu
|
INSERT INTO eintraege_neu
|
||||||
(id, bereich, art, titel, text, datum, bewertung, dringlichkeit, status,
|
(id, bereich, art, titel, text, datum, bewertung, dringlichkeit, status,
|
||||||
creator_id, erstellt, erstellt_von, geaendert,
|
creator_id, erstellt, erstellt_von, geaendert,
|
||||||
hook, format, saeule_id, geplant, creator_extern)
|
hook, format, saeule_id, geplant, creator_extern,
|
||||||
|
event_ende, event_aufgaben, event_regeln)
|
||||||
SELECT id, bereich, art, titel, text, datum, bewertung, dringlichkeit, status,
|
SELECT id, bereich, art, titel, text, datum, bewertung, dringlichkeit, status,
|
||||||
creator_id, erstellt, erstellt_von, geaendert,
|
creator_id, erstellt, erstellt_von, geaendert,
|
||||||
hook, format, saeule_id, geplant, creator_extern
|
hook, format, saeule_id, geplant, creator_extern,
|
||||||
|
event_ende, event_aufgaben, event_regeln
|
||||||
FROM eintraege;
|
FROM eintraege;
|
||||||
DROP TABLE eintraege;
|
DROP TABLE eintraege;
|
||||||
ALTER TABLE eintraege_neu RENAME TO eintraege;
|
ALTER TABLE eintraege_neu RENAME TO eintraege;
|
||||||
|
|||||||
@@ -298,3 +298,102 @@
|
|||||||
.ampel .schritt { margin-left: 0; }
|
.ampel .schritt { margin-left: 0; }
|
||||||
.ampel__knopf { flex: 1 1 auto; text-align: center; }
|
.ampel__knopf { flex: 1 1 auto; text-align: center; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
AGENTUR-EVENTS (07.09.2026)
|
||||||
|
|
||||||
|
Ein Event ist die einzige Eintragsart, die eine LAUFZEIT hat. Alles
|
||||||
|
andere in diesen Bereichen ist ein Vermerk zu einem Tag; ein Event
|
||||||
|
ist eine Einladung, an der man teilnehmen kann -- oder eben nicht
|
||||||
|
mehr. Deshalb ist der Zustand (kommt / läuft / vorbei) das Erste auf
|
||||||
|
der Karte und nicht eine Fussnote.
|
||||||
|
|
||||||
|
Farbe wird hier als AUSKUNFT eingesetzt, nicht als Schmuck: gedecktes
|
||||||
|
Grün heisst "du kannst mitmachen", Bernstein "noch nicht", Grau
|
||||||
|
"vorbei". Die Farben stammen aus derselben Familie wie die Ampel
|
||||||
|
(--k-gut / --k-mittel), damit nicht zwei Bedeutungssysteme
|
||||||
|
nebeneinander laufen. Und weil Farbe allein nie ausreicht, steht der
|
||||||
|
Zustand zusaetzlich als WORT da ("läuft bis 30.09.2026").
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
.event-zeitraum {
|
||||||
|
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
|
||||||
|
margin: 2px 0 10px;
|
||||||
|
font-size: .82rem;
|
||||||
|
}
|
||||||
|
.event-zeitraum__marke {
|
||||||
|
--f: var(--k-neutral);
|
||||||
|
display: inline-flex; align-items: center; gap: 6px;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border: 1px solid color-mix(in srgb, var(--f) 34%, transparent);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: color-mix(in srgb, var(--f) 12%, transparent);
|
||||||
|
color: color-mix(in srgb, var(--f) 82%, #fff);
|
||||||
|
font-weight: 600; letter-spacing: .01em;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
/* Der Punkt davor ist reine Zierde und darf deshalb NICHT vorgelesen
|
||||||
|
werden -- ein Screenreader saehe sonst ein Aufzaehlungszeichen mitten
|
||||||
|
im Satz. */
|
||||||
|
.event-zeitraum__marke::before {
|
||||||
|
content: ""; width: 7px; height: 7px; border-radius: 50%;
|
||||||
|
background: var(--f); flex: none;
|
||||||
|
}
|
||||||
|
.event-zeitraum[data-stand="laeuft"] .event-zeitraum__marke { --f: var(--k-gut); }
|
||||||
|
.event-zeitraum[data-stand="kommt"] .event-zeitraum__marke { --f: var(--k-mittel); }
|
||||||
|
.event-zeitraum[data-stand="vorbei"] .event-zeitraum__marke { --f: var(--k-neutral); }
|
||||||
|
.event-zeitraum__spanne {
|
||||||
|
color: var(--text-leise);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ein vorbeigelaufenes Event bleibt lesbar, tritt aber zurueck. Kein
|
||||||
|
display:none -- was gelaufen ist, will man nachschlagen koennen.
|
||||||
|
Gedaempft wird nur die Flaeche, nicht die Schrift: Text unter 4.5:1
|
||||||
|
waere nicht mehr lesbar, und "alt" ist kein Grund, jemanden
|
||||||
|
auszuschliessen. */
|
||||||
|
.eintrag-karte[data-event="vorbei"] { opacity: .82; }
|
||||||
|
|
||||||
|
.event-block {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid var(--rand);
|
||||||
|
border-radius: var(--radius-klein);
|
||||||
|
background: rgba(255, 255, 255, .022);
|
||||||
|
}
|
||||||
|
.event-block__schild {
|
||||||
|
margin: 0 0 4px;
|
||||||
|
/* .74rem = 11.84 px, nicht .7rem. Die Schriftgroessen-Pruefung zieht
|
||||||
|
die Grenze bei 11.5 px, und sie hat recht: In Grossbuchstaben mit
|
||||||
|
Sperrung wirkt eine Schrift kleiner, als die Zahl sagt -- und das
|
||||||
|
hier ist die Beschriftung, an der man die Regeln vom Aufgabenteil
|
||||||
|
unterscheidet. */
|
||||||
|
font-size: .74rem; font-weight: 700;
|
||||||
|
letter-spacing: .09em; text-transform: uppercase;
|
||||||
|
color: var(--text-still);
|
||||||
|
}
|
||||||
|
.event-block__text {
|
||||||
|
margin: 0;
|
||||||
|
font-size: .87rem; line-height: 1.6; color: var(--text);
|
||||||
|
/* pre-line, nicht pre-wrap: Zeilenumbrueche bleiben (die Aufzaehlung
|
||||||
|
ist der Sinn dieser Felder), aber eine versehentlich eingefuegte
|
||||||
|
Einrueckung aus einer Chatnachricht reisst die Karte nicht auf. */
|
||||||
|
white-space: pre-line;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hinweis unter einem Formularfeld -- erklaert das Feld, statt es
|
||||||
|
kommentarlos wegzunehmen. */
|
||||||
|
.feld-hinweis {
|
||||||
|
margin: 5px 0 0;
|
||||||
|
font-size: .76rem; line-height: 1.45;
|
||||||
|
color: var(--text-still);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 560px) {
|
||||||
|
/* Auf dem Handy untereinander: Marke und Spanne nebeneinander
|
||||||
|
ergaeben bei "vorbei seit 30.09.2026" einen Umbruch mitten im
|
||||||
|
Datum. */
|
||||||
|
.event-zeitraum { gap: 6px; }
|
||||||
|
.event-zeitraum__spanne { flex-basis: 100%; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,6 +51,32 @@
|
|||||||
const melde = (t) => { $('fehler').textContent = t || ''; };
|
const melde = (t) => { $('fehler').textContent = t || ''; };
|
||||||
const datum = (iso) => (iso ? iso.slice(0, 10).split('-').reverse().join('.') : '—');
|
const datum = (iso) => (iso ? iso.slice(0, 10).split('-').reverse().join('.') : '—');
|
||||||
|
|
||||||
|
/* ---------- Agentur-Events ---------------------------------------------
|
||||||
|
Ein Event ist kein Eintrag mit Ueberschrift und Text, sondern eine
|
||||||
|
Aktion mit Zeitraum, Aufgaben und Regeln. Welche Art das ist, sagt
|
||||||
|
der Server (die Arten kommen aus workspace-bereiche.js) -- die
|
||||||
|
Kennung steht hier trotzdem woertlich, weil das Formular je Art
|
||||||
|
anders aussieht und es dafuer keine allgemeine Regel gibt. Sie
|
||||||
|
steht an EINER Stelle, damit sie sich nicht verteilt. */
|
||||||
|
const EVENT_BEREICH = 'agentur';
|
||||||
|
const EVENT_ART = 'kampagne';
|
||||||
|
const istEventArt = (art) => bereich === EVENT_BEREICH && art === EVENT_ART;
|
||||||
|
|
||||||
|
/* Laeuft das Event noch, kommt es erst, ist es vorbei?
|
||||||
|
Der Vergleich laeuft auf den ISO-Zeichenketten, nicht auf Date --
|
||||||
|
"2026-09-12" < "2026-09-30" ist als Text schon richtig, und ein
|
||||||
|
Date() haette hier eine Zeitzone erfunden, die niemand gemeint hat.
|
||||||
|
Ohne Ende gilt der Beginntag als der ganze Zeitraum. */
|
||||||
|
function eventStand(e) {
|
||||||
|
const heute = window.heuteLokal ? window.heuteLokal() : new Date().toISOString().slice(0, 10);
|
||||||
|
const von = (e.datum || '').slice(0, 10);
|
||||||
|
const bis = (e.event_ende || von).slice(0, 10);
|
||||||
|
if (!von) return null;
|
||||||
|
if (heute < von) return { schluessel: 'kommt', text: 'startet ' + datum(von) };
|
||||||
|
if (heute > bis) return { schluessel: 'vorbei', text: 'vorbei seit ' + datum(bis) };
|
||||||
|
return { schluessel: 'laeuft', text: von === bis ? 'heute' : 'läuft bis ' + datum(bis) };
|
||||||
|
}
|
||||||
|
|
||||||
async function hole(pfad, optionen = {}) {
|
async function hole(pfad, optionen = {}) {
|
||||||
const a = await fetch(pfad, { credentials: 'same-origin', ...optionen });
|
const a = await fetch(pfad, { credentials: 'same-origin', ...optionen });
|
||||||
if (a.status === 401) { location.assign('/workspace/'); throw new Error('abgemeldet'); }
|
if (a.status === 401) { location.assign('/workspace/'); throw new Error('abgemeldet'); }
|
||||||
@@ -91,10 +117,45 @@
|
|||||||
}
|
}
|
||||||
k.append(kopf);
|
k.append(kopf);
|
||||||
|
|
||||||
|
/* ---- Agentur-Event: Zeitraum, Aufgaben, Regeln -------------------
|
||||||
|
Die Reihenfolge ist nicht beliebig. Wer auf ein Event schaut,
|
||||||
|
fragt in genau dieser Folge: Laeuft das ueberhaupt noch? Was
|
||||||
|
muss ich tun? Was gilt dabei? Steht der Zeitraum unten im Fuss
|
||||||
|
-- da, wo bei allen anderen Karten das Datum steht --, liest man
|
||||||
|
erst die Aufgaben und danach, dass es seit einer Woche vorbei
|
||||||
|
ist. */
|
||||||
|
const stand = istEventArt(e.art) ? eventStand(e) : null;
|
||||||
|
if (stand) {
|
||||||
|
k.dataset.event = stand.schluessel;
|
||||||
|
const zeile = el('p', 'event-zeitraum');
|
||||||
|
zeile.dataset.stand = stand.schluessel;
|
||||||
|
zeile.append(el('span', 'event-zeitraum__marke', stand.text));
|
||||||
|
zeile.append(el('span', 'event-zeitraum__spanne',
|
||||||
|
e.event_ende && e.event_ende !== e.datum
|
||||||
|
? `${datum(e.datum)} – ${datum(e.event_ende)}`
|
||||||
|
: datum(e.datum)));
|
||||||
|
k.append(zeile);
|
||||||
|
}
|
||||||
|
|
||||||
if (e.text) k.append(el('p', 'eintrag-text', e.text));
|
if (e.text) k.append(el('p', 'eintrag-text', e.text));
|
||||||
|
|
||||||
|
if (stand) {
|
||||||
|
for (const [feld, name] of [['event_aufgaben', 'Aufgaben'], ['event_regeln', 'Regeln']]) {
|
||||||
|
if (!e[feld]) continue;
|
||||||
|
const block = el('div', 'event-block');
|
||||||
|
block.append(el('h4', 'event-block__schild', name));
|
||||||
|
/* Zeilenumbrueche bleiben stehen (white-space: pre-line im CSS).
|
||||||
|
Eine Aufzaehlung, die zu einem Absatz zusammenlaeuft, ist
|
||||||
|
genau das, was diese beiden Felder verhindern sollen. */
|
||||||
|
block.append(el('p', 'event-block__text', e[feld]));
|
||||||
|
k.append(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const fuss = el('div', 'eintrag-fuss');
|
const fuss = el('div', 'eintrag-fuss');
|
||||||
fuss.append(el('span', null, datum(e.datum)));
|
/* Beim Event steht der Zeitraum schon oben -- das Datum hier waere
|
||||||
|
dieselbe Zahl ein zweites Mal. */
|
||||||
|
if (!stand) fuss.append(el('span', null, datum(e.datum)));
|
||||||
if (LEITUNG.has(ich.rolle) && e.creator_name) fuss.append(el('span', null, '· ' + e.creator_name));
|
if (LEITUNG.has(ich.rolle) && e.creator_name) fuss.append(el('span', null, '· ' + e.creator_name));
|
||||||
if (e.erstellt_name) fuss.append(el('span', null, '· von ' + e.erstellt_name));
|
if (e.erstellt_name) fuss.append(el('span', null, '· von ' + e.erstellt_name));
|
||||||
if (e.status === 'erledigt') fuss.append(el('span', null, '· erledigt'));
|
if (e.status === 'erledigt') fuss.append(el('span', null, '· erledigt'));
|
||||||
@@ -276,6 +337,44 @@
|
|||||||
|
|
||||||
/* ---------- Neuer Eintrag ---------------------------------------------- */
|
/* ---------- Neuer Eintrag ---------------------------------------------- */
|
||||||
|
|
||||||
|
/* Das Formular sieht bei einem Agentur-Event anders aus als bei allem
|
||||||
|
anderen -- nicht "zusaetzlich", sondern anders: Aus "Überschrift"
|
||||||
|
wird der Titel des Events, aus "Text" die Beschreibung, aus dem
|
||||||
|
Datum ein Zeitraum, und Dringlichkeit hat hier nichts zu suchen
|
||||||
|
(ein Event ist nicht dringend, es hat einen Termin).
|
||||||
|
|
||||||
|
Umgeschaltet wird bei JEDEM Artwechsel und beim Oeffnen. Nur beim
|
||||||
|
Oeffnen zu schalten waere der bequeme Fehler: Man oeffnet mit
|
||||||
|
"Schulung", waehlt "Agentur-Events" und fuellt ein Formular aus,
|
||||||
|
das noch nach der alten Art fragt. */
|
||||||
|
function formularAnpassen() {
|
||||||
|
const event = istEventArt($('f-art').value);
|
||||||
|
|
||||||
|
$('feld-ende').hidden = !event;
|
||||||
|
$('feld-aufgaben').hidden = !event;
|
||||||
|
$('feld-regeln').hidden = !event;
|
||||||
|
if (einstellung?.dringlichkeit) $('feld-dringlich').hidden = event;
|
||||||
|
|
||||||
|
$('schild-datum').textContent = event ? 'Von' : 'Datum';
|
||||||
|
$('schild-titel').textContent = event ? 'Titel des Events' : 'Überschrift';
|
||||||
|
/* textContent wuerde das <span class="leise"> mit erschlagen --
|
||||||
|
deshalb nur der erste Textknoten, das kleine "(optional)" bleibt
|
||||||
|
stehen. */
|
||||||
|
const textSchild = $('schild-text').firstChild;
|
||||||
|
if (textSchild) textSchild.nodeValue = event ? 'Beschreibung ' : 'Text ';
|
||||||
|
|
||||||
|
/* Leeren, was gerade unsichtbar wird. Sonst reicht ein Wechsel von
|
||||||
|
"Agentur-Events" auf "Schulung", und das Ende des Zeitraums
|
||||||
|
faehrt unsichtbar mit -- der Server nimmt es an, weil es zum
|
||||||
|
Bereich gehoert, und an der Schulung stuende ein Enddatum, das
|
||||||
|
niemand eingetragen hat und niemand sieht. */
|
||||||
|
if (!event) {
|
||||||
|
$('f-ende').value = '';
|
||||||
|
$('f-aufgaben').value = '';
|
||||||
|
$('f-regeln').value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const umschalten = (auf) => {
|
const umschalten = (auf) => {
|
||||||
/* Auch hier die Regel, nicht nur einmal beim Aufbau: Diese Funktion
|
/* Auch hier die Regel, nicht nur einmal beim Aufbau: Diese Funktion
|
||||||
ist die einzige Stelle, die das Formular je wieder sichtbar macht.
|
ist die einzige Stelle, die das Formular je wieder sichtbar macht.
|
||||||
@@ -288,11 +387,17 @@
|
|||||||
};
|
};
|
||||||
$('neu-oeffnen').addEventListener('click', () => {
|
$('neu-oeffnen').addEventListener('click', () => {
|
||||||
$('f-datum').value = window.heuteLokal();
|
$('f-datum').value = window.heuteLokal();
|
||||||
|
formularAnpassen();
|
||||||
umschalten(true);
|
umschalten(true);
|
||||||
});
|
});
|
||||||
$('neu-abbrechen').addEventListener('click', () => {
|
$('neu-abbrechen').addEventListener('click', () => {
|
||||||
$('neu').reset(); $('neu-fehler').textContent = ''; umschalten(false);
|
$('neu').reset(); $('neu-fehler').textContent = ''; formularAnpassen(); umschalten(false);
|
||||||
});
|
});
|
||||||
|
/* "change" und nicht "input": Die Auswahl wird ueber wahl.js zu einer
|
||||||
|
Knopfliste umgebaut, und die meldet ihre Wahl als change-Ereignis
|
||||||
|
am urspruenglichen <select> -- ohne dieses Ereignis merkte das
|
||||||
|
Formular vom Artwechsel nichts. */
|
||||||
|
$('f-art').addEventListener('change', formularAnpassen);
|
||||||
|
|
||||||
$('neu').addEventListener('submit', async (e) => {
|
$('neu').addEventListener('submit', async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -304,9 +409,19 @@
|
|||||||
text: $('f-text').value,
|
text: $('f-text').value,
|
||||||
datum: $('f-datum').value,
|
datum: $('f-datum').value,
|
||||||
};
|
};
|
||||||
if (einstellung.dringlichkeit) daten.dringlichkeit = $('f-dringlich').value;
|
const event = istEventArt(daten.art);
|
||||||
|
if (einstellung.dringlichkeit && !event) daten.dringlichkeit = $('f-dringlich').value;
|
||||||
if (einstellung.bewertung) daten.bewertung = $('f-bewertung').value || null;
|
if (einstellung.bewertung) daten.bewertung = $('f-bewertung').value || null;
|
||||||
if (LEITUNG.has(ich.rolle)) {
|
if (event) {
|
||||||
|
daten.event_ende = $('f-ende').value || null;
|
||||||
|
daten.event_aufgaben = $('f-aufgaben').value || null;
|
||||||
|
daten.event_regeln = $('f-regeln').value || null;
|
||||||
|
}
|
||||||
|
/* Im Agentur-Bereich gehoert ein Eintrag allen -- es gibt nichts
|
||||||
|
zuzuordnen, also wird auch nichts mitgeschickt. Der Server setzt
|
||||||
|
beides ohnehin auf leer (ohneCreatorBezug); hier zu schweigen
|
||||||
|
spart die stille Annahme, das Formular haette etwas zu sagen. */
|
||||||
|
if (LEITUNG.has(ich.rolle) && !einstellung.ohneCreatorBezug) {
|
||||||
daten.creator_id = $('f-creator').value || null;
|
daten.creator_id = $('f-creator').value || null;
|
||||||
daten.creator_extern = $('f-creator').dataset.extern || null;
|
daten.creator_extern = $('f-creator').dataset.extern || null;
|
||||||
}
|
}
|
||||||
@@ -365,8 +480,16 @@
|
|||||||
if (!darfEintragen()) {
|
if (!darfEintragen()) {
|
||||||
$('neu-oeffnen').hidden = true;
|
$('neu-oeffnen').hidden = true;
|
||||||
$('neu').hidden = true;
|
$('neu').hidden = true;
|
||||||
$('unterzeile').textContent =
|
/* Zwei verschiedene Saetze, weil es zwei verschiedene Wahrheiten
|
||||||
(UNTERZEILE[bereich] || '') + ' Hier trägt deine Betreuung ein – du siehst alles, was zu dir gehört.';
|
sind. In den Betreuungsbereichen sieht ein Creator, was ZU IHM
|
||||||
|
gehoert -- in der Agentur sieht er ALLES. Stuende hier weiter
|
||||||
|
"was zu dir gehört", laese sich eine vollstaendige Liste wie
|
||||||
|
ein Ausschnitt, und die naheliegende Frage waere: Was sehe ich
|
||||||
|
hier eigentlich nicht? */
|
||||||
|
$('unterzeile').textContent = (UNTERZEILE[bereich] || '')
|
||||||
|
+ (einstellung.fuerAlle
|
||||||
|
? ' Eingetragen wird von der Agentur – du siehst alles, was hier steht.'
|
||||||
|
: ' Hier trägt deine Betreuung ein – du siehst alles, was zu dir gehört.');
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [wert, name] of Object.entries(einstellung.arten)) {
|
for (const [wert, name] of Object.entries(einstellung.arten)) {
|
||||||
@@ -379,6 +502,32 @@
|
|||||||
|
|
||||||
if (LEITUNG.has(ich.rolle)) {
|
if (LEITUNG.has(ich.rolle)) {
|
||||||
$('feld-creator').hidden = false;
|
$('feld-creator').hidden = false;
|
||||||
|
|
||||||
|
/* AGENTUR: EINE EINZIGE WAHL, UND DIE HEISST "AGENTUR" (07.09.2026).
|
||||||
|
|
||||||
|
Hier stand dieselbe Creator-Liste wie ueberall -- und sie war
|
||||||
|
eine Falle. Wer ein Event fuer alle anlegt und dabei aus
|
||||||
|
Gewohnheit einen Namen anklickt, hat es damit UNSICHTBAR
|
||||||
|
gemacht: fuer alle anderen Creator, ohne Warnung, ohne dass es
|
||||||
|
der Liste danach anzusehen waere.
|
||||||
|
|
||||||
|
Kein Feld auszublenden waere die halbe Loesung gewesen: Dann
|
||||||
|
fragt man sich, wem der Eintrag gehoert. Eine Liste mit genau
|
||||||
|
einer Wahl beantwortet die Frage, statt sie wegzunehmen.
|
||||||
|
|
||||||
|
Die Personenwahl (freier Name, Suchfeld) wird hier bewusst
|
||||||
|
NICHT aufgesetzt -- sie erlaubt getippte Namen, und genau das
|
||||||
|
soll es hier nicht geben. */
|
||||||
|
if (einstellung.ohneCreatorBezug) {
|
||||||
|
$('schild-creator').textContent = 'Gilt für';
|
||||||
|
$('f-creator').textContent = '';
|
||||||
|
const o = document.createElement('option');
|
||||||
|
o.value = ''; o.textContent = 'Agentur';
|
||||||
|
$('f-creator').append(o);
|
||||||
|
const hinweis = $('hinweis-creator');
|
||||||
|
hinweis.textContent = 'Agentur-Einträge gehören allen – jeder im Workspace sieht sie.';
|
||||||
|
hinweis.hidden = false;
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
const { personen } = await (await hole('/workspace/api/personen')).json();
|
const { personen } = await (await hole('/workspace/api/personen')).json();
|
||||||
for (const p of personen.filter((p) => p.rolle === 'creator')) {
|
for (const p of personen.filter((p) => p.rolle === 'creator')) {
|
||||||
@@ -389,6 +538,8 @@
|
|||||||
} catch { /* Zuordnung bleibt leer */ }
|
} catch { /* Zuordnung bleibt leer */ }
|
||||||
window.personenwahl?.('f-creator', { hinweis: "Kein Konto im Workspace – der Eintrag gehört dann zu keiner Person und taucht in personenbezogenen Auswertungen nicht auf. Sichtbar bleibt er für dich." });
|
window.personenwahl?.('f-creator', { hinweis: "Kein Konto im Workspace – der Eintrag gehört dann zu keiner Person und taucht in personenbezogenen Auswertungen nicht auf. Sichtbar bleibt er für dich." });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
formularAnpassen();
|
||||||
|
|
||||||
/* Kommt jemand vom Bericht mit "nur die offenen", wird der Filter
|
/* Kommt jemand vom Bericht mit "nur die offenen", wird der Filter
|
||||||
VOR dem ersten Laden gesetzt -- sonst baut die Seite alles auf,
|
VOR dem ersten Laden gesetzt -- sonst baut die Seite alles auf,
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -211,10 +211,10 @@
|
|||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/aufgaben.js?v=202609070159" defer></script>
|
<script src="assets/js/aufgaben.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/automation.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/automation.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -134,10 +134,10 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/automation.js?v=202609070159" defer></script>
|
<script src="assets/js/automation.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+43
-17
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/bereich.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/bereich.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -59,9 +59,16 @@
|
|||||||
<select id="f-art"></select>
|
<select id="f-art"></select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="feld-schild" for="f-datum">Datum</label>
|
<label class="feld-schild" for="f-datum" id="schild-datum">Datum</label>
|
||||||
<input id="f-datum" type="date" />
|
<input id="f-datum" type="date" />
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Nur bei Agentur-Events: das Ende des Zeitraums. Der Beginn ist
|
||||||
|
das Feld darueber -- ein zweites Datumsfeld daneben liest sich
|
||||||
|
als Spanne, ein Feld "Zeitraum" mit Text darin nicht. -->
|
||||||
|
<div id="feld-ende" hidden>
|
||||||
|
<label class="feld-schild" for="f-ende">Bis</label>
|
||||||
|
<input id="f-ende" type="date" />
|
||||||
|
</div>
|
||||||
<div id="feld-dringlich" hidden>
|
<div id="feld-dringlich" hidden>
|
||||||
<label class="feld-schild" for="f-dringlich">Dringlichkeit</label>
|
<label class="feld-schild" for="f-dringlich">Dringlichkeit</label>
|
||||||
<select id="f-dringlich">
|
<select id="f-dringlich">
|
||||||
@@ -82,18 +89,37 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="feld-creator" hidden>
|
<div id="feld-creator" hidden>
|
||||||
<label class="feld-schild" for="f-creator">Creator</label>
|
<label class="feld-schild" for="f-creator" id="schild-creator">Creator</label>
|
||||||
<select id="f-creator"><option value="">—</option></select>
|
<select id="f-creator"><option value="">—</option></select>
|
||||||
|
<p class="feld-hinweis" id="hinweis-creator" hidden></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="neu__zeile">
|
<div class="neu__zeile">
|
||||||
<label class="feld-schild" for="f-titel">Überschrift</label>
|
<label class="feld-schild" for="f-titel" id="schild-titel">Überschrift</label>
|
||||||
<input id="f-titel" maxlength="160" required />
|
<input id="f-titel" maxlength="160" required />
|
||||||
</div>
|
</div>
|
||||||
<div class="neu__zeile">
|
<div class="neu__zeile">
|
||||||
<label class="feld-schild" for="f-text">Text <span class="leise">(optional)</span></label>
|
<label class="feld-schild" for="f-text" id="schild-text">Text <span class="leise">(optional)</span></label>
|
||||||
<textarea id="f-text" rows="4" maxlength="6000"></textarea>
|
<textarea id="f-text" rows="4" maxlength="6000"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- ==== Nur bei Agentur-Events ====================================
|
||||||
|
Zwei Felder, die den Unterschied zwischen einem Aufruf und einer
|
||||||
|
Aktion ausmachen, an der jemand teilnehmen kann: WAS ist zu tun
|
||||||
|
(und was springt dabei heraus) und WAS GILT dabei. Beides stand
|
||||||
|
bisher irgendwo im Fliesstext oder gar nicht -- und jede
|
||||||
|
Rueckfrage dazu kostet eine Nachricht. -->
|
||||||
|
<div class="neu__zeile" id="feld-aufgaben" hidden>
|
||||||
|
<label class="feld-schild" for="f-aufgaben">Aufgaben
|
||||||
|
<span class="leise">– womit sammelt man Punkte, was gibt es zu gewinnen</span></label>
|
||||||
|
<textarea id="f-aufgaben" rows="5" maxlength="6000"
|
||||||
|
placeholder="z. B. · 1 Punkt je Live-Stunde · 3 Punkte je neuem Abo · Platz 1 gewinnt …"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="neu__zeile" id="feld-regeln" hidden>
|
||||||
|
<label class="feld-schild" for="f-regeln">Regeln
|
||||||
|
<span class="leise">– was zählt, was nicht, bis wann</span></label>
|
||||||
|
<textarea id="f-regeln" rows="5" maxlength="6000"
|
||||||
|
placeholder="z. B. · Nur Streams auf dem eigenen Konto · Punkte zählen bis 23:59 am letzten Tag"></textarea>
|
||||||
|
</div>
|
||||||
<p class="fehler" id="neu-fehler" role="alert" aria-live="polite"></p>
|
<p class="fehler" id="neu-fehler" role="alert" aria-live="polite"></p>
|
||||||
<div class="neu__knoepfe">
|
<div class="neu__knoepfe">
|
||||||
<button type="submit" class="knopf knopf--klein" id="neu-speichern">Eintragen</button>
|
<button type="submit" class="knopf knopf--klein" id="neu-speichern">Eintragen</button>
|
||||||
@@ -117,14 +143,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/checkliste.js?v=202609070159" defer></script>
|
<script src="assets/js/checkliste.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/ampel.js?v=202609070159" defer></script>
|
<script src="assets/js/ampel.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/schulung.js?v=202609070159" defer></script>
|
<script src="assets/js/schulung.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/vorlagen.js?v=202609070159" defer></script>
|
<script src="assets/js/vorlagen.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereich.js?v=202609070159" defer></script>
|
<script src="assets/js/bereich.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+10
-10
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/calls.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/calls.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -76,11 +76,11 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202609070159" defer></script>
|
<script src="assets/js/ki.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/calls.js?v=202609070159" defer></script>
|
<script src="assets/js/calls.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+8
-8
@@ -9,16 +9,16 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<!-- aufgaben.css bringt die Dialog- und Formularstile mit (.dialog,
|
<!-- aufgaben.css bringt die Dialog- und Formularstile mit (.dialog,
|
||||||
.neu__zeile, .dialog__knoepfe). Sie stehen dort seit dem
|
.neu__zeile, .dialog__knoepfe). Sie stehen dort seit dem
|
||||||
Aufgabenbrett; sie hierher zu kopieren hiesse, sie an zwei Stellen
|
Aufgabenbrett; sie hierher zu kopieren hiesse, sie an zwei Stellen
|
||||||
zu pflegen. Dieselbe Lösung nutzen kalender.html und content.html.
|
zu pflegen. Dieselbe Lösung nutzen kalender.html und content.html.
|
||||||
Gemeldet von pruef-css-klassen.mjs, bevor jemand einen ungestylten
|
Gemeldet von pruef-css-klassen.mjs, bevor jemand einen ungestylten
|
||||||
Dialog zu sehen bekam. -->
|
Dialog zu sehen bekam. -->
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/chat.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/chat.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -154,9 +154,9 @@
|
|||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="assets/js/bereiche.js?v=202609070159"></script>
|
<script src="assets/js/bereiche.js?v=202609070231"></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159"></script>
|
<script src="assets/js/kopf.js?v=202609070231"></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159"></script>
|
<script src="assets/js/glocke.js?v=202609070231"></script>
|
||||||
<script src="assets/js/chat.js?v=202609070159"></script>
|
<script src="assets/js/chat.js?v=202609070231"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+11
-11
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/content.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/content.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -166,12 +166,12 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/checkliste.js?v=202609070159" defer></script>
|
<script src="assets/js/checkliste.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/vorlagen.js?v=202609070159" defer></script>
|
<script src="assets/js/vorlagen.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/content.js?v=202609070159" defer></script>
|
<script src="assets/js/content.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/dateien.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/dateien.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -95,10 +95,10 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/dateien.js?v=202609070159" defer></script>
|
<script src="assets/js/dateien.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="gate">
|
<body class="gate">
|
||||||
@@ -173,6 +173,6 @@
|
|||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="assets/js/gate.js?v=202609070159" defer></script>
|
<script src="assets/js/gate.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+10
-10
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/kalender.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/kalender.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -257,11 +257,11 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kalender.js?v=202609070159" defer></script>
|
<script src="assets/js/kalender.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kalender-abo.js?v=202609070159" defer></script>
|
<script src="assets/js/kalender-abo.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/leistung.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/leistung.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -199,10 +199,10 @@
|
|||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159"></script>
|
<script src="assets/js/wahl.js?v=202609070231"></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159"></script>
|
<script src="assets/js/bereiche.js?v=202609070231"></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159"></script>
|
<script src="assets/js/kopf.js?v=202609070231"></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159"></script>
|
<script src="assets/js/glocke.js?v=202609070231"></script>
|
||||||
<script src="assets/js/leistung.js?v=202609070159"></script>
|
<script src="assets/js/leistung.js?v=202609070231"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/personen.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/personen.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -123,10 +123,10 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/personen.js?v=202609070159" defer></script>
|
<script src="assets/js/personen.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+10
-10
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/profil.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/profil.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -201,11 +201,11 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/steckbrief.js?v=202609070159" defer></script>
|
<script src="assets/js/steckbrief.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/profil.js?v=202609070159" defer></script>
|
<script src="assets/js/profil.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+10
-10
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/report.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/report.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -93,11 +93,11 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202609070159" defer></script>
|
<script src="assets/js/ki.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/report.js?v=202609070159" defer></script>
|
<script src="assets/js/report.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/scouting.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/scouting.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/scouting.js?v=202609070159" defer></script>
|
<script src="assets/js/scouting.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -160,10 +160,10 @@
|
|||||||
</p>
|
</p>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/start.js?v=202609070159" defer></script>
|
<script src="assets/js/start.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+10
-10
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -72,11 +72,11 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202609070159" defer></script>
|
<script src="assets/js/ki.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/startcheck.js?v=202609070159" defer></script>
|
<script src="assets/js/startcheck.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/profil.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/profil.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -113,10 +113,10 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/steckbrief.js?v=202609070159" defer></script>
|
<script src="assets/js/steckbrief.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -82,10 +82,10 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/uebersicht.js?v=202609070159" defer></script>
|
<script src="assets/js/uebersicht.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
<meta name="theme-color" content="#0674b9" />
|
<meta name="theme-color" content="#0674b9" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609070231" />
|
||||||
<link rel="stylesheet" href="assets/css/wissen.css?v=202609070159" />
|
<link rel="stylesheet" href="assets/css/wissen.css?v=202609070231" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -177,10 +177,10 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202609070159" defer></script>
|
<script src="assets/js/wahl.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202609070159" defer></script>
|
<script src="assets/js/bereiche.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202609070159" defer></script>
|
<script src="assets/js/kopf.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202609070159" defer></script>
|
<script src="assets/js/glocke.js?v=202609070231" defer></script>
|
||||||
<script src="assets/js/wissen.js?v=202609070159" defer></script>
|
<script src="assets/js/wissen.js?v=202609070231" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user