Files
dogfather-universe/workspace/manager-ziele.html
T
DogFatherGitandClaude Opus 5 baf8288433 Korrigieren duerfen jetzt beide: Spicy Media und DogFather
Filipe auf die Rueckfrage, wer fremde Eintraege richtigstellen darf:
„ja spicy und dogfather".

Die Vorlage kannte dort nur DogFather („Vergangene Monate sind
gesperrt ... Ausnahme: DogFather"). Das gilt ab jetzt fuer beide --
und zwar fuer BEIDE Faelle, nicht nur fuer einen:

  * einen fremden Eintrag aendern oder loeschen
  * einen abgeschlossenen Monat dafuer kurz oeffnen

ES IST EINE MENGE UND KEINE ZWEITE LISTE. `darfKorrigieren()` gibt
`siehtAlles()` zurueck -- dieselbe Menge, die schon ueber die
Team-Uebersicht und die Zielzahlen entscheidet. Eine eigene
Aufzaehlung derselben zwei Rollen waere die, die beim naechsten Umbau
auseinanderlaeuft. Und inhaltlich gehoert es zusammen: Wer alle
Zahlen sieht und die Ziele setzt, muss einen Zahlendreher gerade
ruecken koennen; zwei verschiedene Grenzen fuer „darf alles sehen"
und „darf etwas richtigstellen" koennte spaeter niemand mehr
erklaeren.

Der Name der Variablen hiess vorher `istAdmin` -- also die Rechnung
statt ihrer Bedeutung. Jetzt heisst sie, was sie beantwortet.

NACHVOLLZIEHBAR BLEIBT ES UNVERAENDERT: Jede Korrektur an einem
fremden Eintrag und jede Aenderung an einem abgeschlossenen Monat
steht mit Name, Rolle und Zeit im Protokoll -- geprueft wird jetzt
ausdruecklich, dass dort auch `spicy` auftaucht.

GEPRUEFT: 206 Pruefungen, 0 Fehler (vorher 194)

Die Grenze wird in beide Richtungen gemessen, nicht nur in eine:
Spicy aendert wirklich (200, und der neue Wert steht in der
Datenbank), Spicy loescht wirklich -- aber ein Manager und ein
fremder Scout werden weiterhin abgewiesen (403), und danach steht
immer noch der Wert von Spicy da. Ohne diese Gegenproben hiesse
„Spicy darf" moeglicherweise „jeder darf". Loeschen ist eigens
geprueft: PATCH und DELETE sind zwei Routen, und zwei Routen koennen
auseinanderlaufen.

Auch die Freigabe fuer alte Monate wird nach Spicys Korrektur wieder
geschlossen gemessen -- eine geoeffnete Tuer ist kein Erfolg.

EINE MEINER PRUEFUNGEN WAR WIEDER FALSCH, NICHT DER CODE: Ich hatte
erwartet, dass ein Manager mit einer fremden Nummer in der Adresse
„nicht bearbeitbar" bekommt. Er bekommt `true` -- weil er gar keine
fremde Liste bekommt, sondern seine eigene; die Nummer wird fuer ihn
schlicht nicht beachtet. Richtiges Verhalten, falsche Frage. Gemessen
wird jetzt, was zaehlt: dass bei ihm kein einziger fremder Eintrag
ankommt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 17:52:36 +02:00

234 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>Manager-Ziele · Spicy &amp; Dogi</title>
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610021752" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610021752" />
<link rel="stylesheet" href="assets/css/gate.css?v=202610021752" />
<link rel="stylesheet" href="assets/css/start.css?v=202610021752" />
<link rel="stylesheet" href="assets/css/manager-ziele.css?v=202610021752" />
<!-- module.css an VORLETZTER, haus.css an LETZTER Stelle. Die
Reihenfolge ist keine Geschmacksfrage: haus.css setzt nur
Variablen, und bei Variablen entscheidet allein, wer zuletzt
kommt. pruef-css-klassen.mjs misst genau dieses Paar nach. -->
<link rel="stylesheet" href="assets/css/module.css?v=202610021752" />
<link rel="stylesheet" href="assets/css/haus.css?v=202610021752" />
</head>
<body class="start">
<div class="schleier" aria-hidden="true"></div>
<header class="kopfleiste">
<button type="button" class="zurueck-knopf" id="zurueck" hidden>
<svg class="zurueck-knopf__pfeil" viewBox="0 0 24 24" aria-hidden="true">
<path d="M14.5 5.5 8 12l6.5 6.5" />
</svg>
<span class="zurueck-knopf__text">Zurück</span>
</button>
<p class="marke"><span class="marke__text"><a class="zurueck" href="start.html">Creator&nbsp;Workspace</a> · Manager-Ziele</span></p>
<div class="kopfleiste__rechts">
<span class="wer" id="wer">…</span>
<button type="button" class="abmelden" id="abmelden">Abmelden</button>
</div>
</header>
<main class="inhalt inhalt--breit mz-seite">
<section class="kopf-zeile">
<div>
<p class="marke">Manager-Ziele</p>
<h1 class="titel" id="seiten-titel">Dein Monat</h1>
<p class="unterzeile">
Vier feste Aufgaben pro Monat. Trag ein, was du gemacht hast –
der Rest rechnet sich von selbst.
</p>
</div>
</section>
<!-- ==================================================================
DER KOPF: Monat, Gesamtfortschritt, Resttage.
Der Ring steht VOR dem Text und nicht daneben-rechts: Auf einem
Handy ist er damit das Erste, was ins Auge fällt, und man weiß
in einer halben Sekunde, ob noch etwas offen ist.
================================================================== -->
<div class="mz-kopf" id="kopf" hidden>
<div class="mz-ring" id="ring" role="img" aria-label="Fortschritt">
<span class="mz-ring__text">
<span class="mz-ring__zahl" id="ring-zahl">–</span>
<span class="mz-ring__von" id="ring-von"></span>
</span>
</div>
<div class="mz-kopf__text">
<p class="mz-kopf__monat" id="kopf-monat">…</p>
<p class="mz-kopf__stand" id="kopf-stand"></p>
<p class="mz-kopf__rest" id="kopf-rest"></p>
</div>
</div>
<p class="ladefehler" id="ladefehler" hidden>
<span class="ladefehler__satz">Die Seite konnte nicht geladen werden.</span>
<span class="ladefehler__grund" id="ladefehler-grund"></span>
<button type="button" class="ladefehler__knopf" id="nochmal">Erneut versuchen</button>
</p>
<!-- Die vier Aufgabenzeilen. Werden gebaut, nicht geschrieben:
Welche Aufgaben es gibt, sagt der Server (AUFGABEN in
manager-ziele-tabellen.js). Stünden sie hier noch einmal,
wären es zwei Listen, von denen eine veraltet. -->
<ul class="mz-liste" id="liste" aria-live="polite"></ul>
<!-- ==================================================================
DER DAUERHAFTE HINWEIS
Wörtlich aus der Vorlage. Er steht unter den Aufgaben und nicht
darüber: Oben wäre er eine Drohung, bevor man überhaupt
gesehen hat, worum es geht.
================================================================== -->
<p class="mz-merksatz">
Inaktive Manager können nicht mehr berücksichtigt werden, da die
Anforderungen von TikTok stetig wachsen und wir als Firma diesen
nachkommen müssen.
</p>
<!-- ---------- VERLAUF: vergangene Monate, nur lesbar -------------- -->
<section class="mz-block" id="verlauf-block" hidden>
<h2 class="mz-block__titel">Verlauf</h2>
<div id="verlauf" aria-live="polite"></div>
</section>
<!-- ---------- TEAM: nur DogFather und Spicy Media ----------------- -->
<section class="mz-block" id="team-block" hidden>
<h2 class="mz-block__titel">Team-Übersicht</h2>
<div class="mz-steuer">
<label class="mz-feld__schild" for="team-monat">Monat</label>
<select id="team-monat"></select>
<label class="mz-feld__schild" for="team-filter">Zeigen</label>
<select id="team-filter">
<option value="alle">alle</option>
<option value="rot">nur Rot</option>
<option value="orange">Rot und Orange</option>
<option value="offen">alle mit offenen Zielen</option>
</select>
<!-- SORTIEREN AUCH HIER UND NICHT NUR AN DEN SPALTEN.
Auf dem Handy wird die Tabelle zu Karten, und die
Spaltenueberschriften verschwinden dabei (sie wuerden dort
mehr Platz kosten als der Inhalt). Ohne dieses Feld waere
das Sortieren auf einem Telefon schlicht nicht erreichbar
-- eine Funktion, die nur auf dem grossen Bildschirm
existiert, ist eine halbe Funktion.
Die Liste wird von manager-ziele.js gefuellt, damit sie zu
den Aufgaben passt, die der Server nennt. Eine zweite,
hier hingeschriebene Liste waere die, die auseinanderlaeuft. -->
<label class="mz-feld__schild" for="team-sort">Sortieren</label>
<select id="team-sort"></select>
<button type="button" class="schritt" id="team-richtung"
aria-label="Sortierrichtung umdrehen">aufsteigend ▴</button>
<button type="button" class="schritt" id="team-csv">Als CSV laden</button>
<button type="button" class="schritt" id="ziele-auf">Zielzahlen</button>
</div>
<div id="team" aria-live="polite"></div>
</section>
</main>
<!-- ==================================================================
DAS FORMULAR
Ein echtes <dialog>: Es bringt Fokusfang, Escape und den
abdunkelnden Hintergrund mit, ohne dass davon eine Zeile selbst
geschrieben werden muss. Nachgebaute Fenster vergessen davon
immer mindestens eines -- meist den Fokus.
================================================================== -->
<dialog class="dialog" id="form-dialog">
<form class="mz-form" id="form" method="dialog">
<div>
<h2 class="dialog__titel" id="form-titel">Eintragen</h2>
<p class="dialog__unter dialog__unter--still" id="form-unter"></p>
</div>
<label class="mz-feld mz-feld--vorschlag" id="feld-name" hidden>
<span class="mz-feld__schild">TikTok-Name des Creators</span>
<input type="text" id="e-name" maxlength="120" autocomplete="off"
placeholder="z. B. @lunatanzt" />
<ul class="mz-treffer" id="treffer" hidden></ul>
</label>
<label class="mz-feld" id="feld-link" hidden>
<span class="mz-feld__schild">Link zum Video</span>
<input type="url" id="e-link" maxlength="500" inputmode="url"
placeholder="https://www.tiktok.com/@…/video/…" />
</label>
<label class="mz-feld" id="feld-art" hidden>
<span class="mz-feld__schild" id="art-schild">Art</span>
<select id="e-art"></select>
</label>
<div class="mz-feld">
<span class="mz-feld__schild">Datum</span>
<!-- Die drei fertigen Tage werden von manager-ziele.js gefuellt:
welche es gibt, haengt davon ab, welcher Tag heute ist (am
1. des Monats gibt es kein „gestern" in diesem Monat). Eine
feste Liste hier waere an zwei Tagen im Monat falsch. -->
<div class="mz-schnelltage" id="datum-schnell"></div>
<input type="date" id="e-datum" required />
</div>
<label class="mz-feld">
<span class="mz-feld__schild">Notiz (freiwillig)</span>
<textarea id="e-notiz" maxlength="1000" rows="2"></textarea>
</label>
<p class="mz-form__fehler" id="form-fehler" role="alert" aria-live="polite"></p>
<div class="dialog__knoepfe">
<button type="button" class="knopf-still" id="form-abbruch">Abbrechen</button>
<button type="submit" class="knopf" id="form-speichern">Speichern</button>
</div>
</form>
</dialog>
<!-- Die Zielzahlen. Eigener Dialog und keine zweite Seite: Es sind
sechzehn Zahlen, die man einmal im Monat ansieht. -->
<dialog class="dialog dialog--breit" id="ziele-dialog">
<form class="mz-form" id="ziele-form" method="dialog">
<div>
<h2 class="dialog__titel">Zielzahlen je Rolle</h2>
<p class="dialog__unter dialog__unter--still" id="ziele-gilt"></p>
</div>
<div id="ziele-felder"></div>
<p class="mz-form__fehler" id="ziele-fehler" role="alert" aria-live="polite"></p>
<div class="dialog__knoepfe">
<button type="button" class="knopf-still" id="ziele-abbruch">Abbrechen</button>
<button type="submit" class="knopf" id="ziele-speichern">Für nächsten Monat speichern</button>
</div>
</form>
</dialog>
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und
kopf.js liest daraus die Leitungsrollen. Ohne sie stürzt jede
Seite ab, und zwar nur in der Browserkonsole -- die Kopfleiste
kommt trotzdem. -->
<script src="assets/js/bereiche.js?v=202610021752" defer></script>
<!-- wahl.js gehört zu kopf.js: Der Sicht-Umschalter baut daraus seine
Liste. pruef-css-klassen setzt das durch, und zwar auch die
Reihenfolge -- kopf.js fragt beim Aufbau nach dem fertigen
Bedienelement. -->
<script src="assets/js/wahl.js?v=202610021752" defer></script>
<script src="assets/js/nachfrage.js?v=202610021752" defer></script>
<script src="assets/js/installieren.js?v=202610021752" defer></script>
<script src="assets/js/kopf.js?v=202610021752" defer></script>
<script src="assets/js/glocke.js?v=202610021752" defer></script>
<script src="assets/js/manager-ziele.js?v=202610021752" defer></script>
</body>
</html>