Aufgaben im Wochenbericht, Meilensteine „Erreicht“, Panels als Planblatt

- Wochenbericht: Abschnitt „Aufgaben“ je Projekt (erledigt seit Vorwoche,
  überfällig, nächste zwei Wochen), rote Zahl in der Tagesordnung,
  Tabelle in der PDF-Akte; Klick öffnet das Aufgaben-Panel
- Meilensteine lassen sich als erreicht markieren (plan_milestones.erreicht);
  nur nicht erreichte vergangene gelten als überfällig
- Aufgabe- und Meilenstein-Panel neu aufgebaut: Stand oben, Lage im
  Terminplan, Angaben als Zeilen

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
erikandClaude Opus 5.5 committed 2026-11-10 10:41:44 +01:00
1 parent 4ac3d8d53d
commit e12936444d
13 files changed
+693 -137

No files matched your search

+144 -107
View File
@@ -38,8 +38,8 @@
<link rel="icon" type="image/png" href="/logo.png">
<link rel="alternate icon" href="/logo.ico">
<link rel="apple-touch-icon" href="/logo.png">
<link rel="stylesheet" href="/styles.css?v=123">
<link rel="stylesheet" href="/plan-styles.css?v=56">
<link rel="stylesheet" href="/styles.css?v=124">
<link rel="stylesheet" href="/plan-styles.css?v=57">
<!-- Glas-Darstellung (public/glas.css, als letztes Stylesheet): greift nur mit
der Klasse html.glas. Gesetzt wird sie hier, vor dem ersten Zeichnen,
damit die Seite nicht erst ohne Glas aufblitzt; abschaltbar je Browser
@@ -1502,41 +1502,67 @@
Art und Titel, Abschnitte Wann / Wo bzw. Wer / Stand / Hängt ab von,
feste Fußleiste. Alle Feld-ids wie zuvor; befüllt und ausgewertet von
js/plan/plan-modals.js. Stile: Block "Seitenpanel" in plan-styles.css. -->
<!-- Seitenpanels Aufgabe und Meilenstein als "Planblatt" (Eriks Wahl,
unslop): Kopf mit Art, Projekt und Stand, darunter die Lage im
Terminplan (todoLageNeu()/msLageBildNeu(), js/plan/plan-modals.js), dann
die Angaben als Zeilen mit Beschriftung. Alle Feld-ids wie zuvor.
Stile: Block "Planblatt" am Ende von plan-styles.css. -->
<div class="modal-bg als-panel" id="milestoneModal" style="display:none">
<div class="modal pd">
<div class="pd-kopf">
<div class="pd-art"><span class="pd-raute" aria-hidden="true"></span><span id="milestoneModalTitle">Meilenstein</span>
<span class="modal-kbd">Esc schließt</span>
<button type="button" class="pd-zu" onclick="closeMilestoneModal()" aria-label="Schließen">×</button></div>
<span class="pd-wo" id="milestoneModalWo"></span>
<span class="modal-kbd"><kbd>Esc</kbd></span>
<button type="button" class="pd-zu" onclick="closeMilestoneModal()" aria-label="Schließen"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg></button></div>
<input type="text" id="milestoneEditName" class="pd-titel" placeholder="z. B. Abgabe Genehmigungsplanung" aria-label="Name des Meilensteins">
<div class="pd-stand">
<div class="segmented pd-seg" id="milestoneEditStand" role="group" aria-label="Stand">
<button type="button" data-stand="offen" aria-pressed="true" onclick="msStandSetzen(false)"><span class="segmented-dot"></span>Offen</button>
<button type="button" data-stand="erreicht" aria-pressed="false" onclick="msStandSetzen(true)"><span class="segmented-dot"></span>Erreicht</button>
</div>
<input type="checkbox" id="milestoneEditErreicht" hidden>
<span class="pd-warnung" id="milestoneEditWarnung" hidden></span>
</div>
<div class="pd-lage" id="msLageBild" aria-label="Lage im Terminplan"></div>
</div>
<div class="pd-inhalt">
<section class="pd-abs">
<h3>Wann</h3>
<!-- sichtbares Anzeigefeld (deutsches Format) + verstecktes ISO-Feld -->
<input type="text" id="milestoneEditDateDisplay" class="range-picker-display" placeholder="Datum wählen…" readonly aria-label="Datum"
onclick="openDatePicker({ anchor: this, inputId: 'milestoneEditDate', displayId: 'milestoneEditDateDisplay' })">
<input type="hidden" id="milestoneEditDate">
</section>
<section class="pd-abs">
<h3>Wo im Terminplan</h3>
<div class="segmented pd-seg" id="milestoneEditLage">
<button type="button" data-lage="zeile" aria-pressed="false" onclick="msLageSetzen('zeile')">Oben, eigene Zeile</button>
<button type="button" data-lage="aufgabe" aria-pressed="false" onclick="msLageSetzen('aufgabe')">Bei einer Aufgabe</button>
<div class="pd-zeile">
<span class="pd-lab">Datum</span>
<div class="pd-wert">
<!-- sichtbares Anzeigefeld (deutsches Format) + verstecktes ISO-Feld -->
<div class="field-inline">
<input type="text" id="milestoneEditDateDisplay" class="range-picker-display" placeholder="Datum wählen…" readonly aria-label="Datum"
onclick="openDatePicker({ anchor: this, inputId: 'milestoneEditDate', displayId: 'milestoneEditDateDisplay', onApply: msLageBildNeu })">
<span class="field-badge pd-kw" id="milestoneEditKw" hidden></span>
</div>
<input type="hidden" id="milestoneEditDate">
</div>
<select id="milestoneEditPosition" aria-label="Position bei einer Aufgabe" onchange="msLageSync()">
<option value="">Oben in der Projektzeile</option>
</select>
</section>
<section class="pd-abs">
<h3>Hängt ab von</h3>
<div id="milestoneEditDependsOn" class="todo-depends-list pd-liste"></div>
</section>
<section class="pd-abs">
<h3>Notiz</h3>
<p class="hint pd-hint pd-mail-hinweis" id="milestoneEditMailHinweis" hidden></p>
<textarea id="milestoneEditNotiz" class="pd-notiz" rows="4" placeholder="Optional, z. B. Hintergrund oder die Mail, aus der der Meilenstein stammt" aria-label="Notiz"></textarea>
</section>
</div>
<div class="pd-zeile">
<span class="pd-lab">Im Terminplan</span>
<div class="pd-wert">
<div class="segmented pd-seg" id="milestoneEditLage">
<button type="button" data-lage="zeile" aria-pressed="false" onclick="msLageSetzen('zeile')">Eigene Zeile oben</button>
<button type="button" data-lage="aufgabe" aria-pressed="false" onclick="msLageSetzen('aufgabe')">Bei einer Aufgabe</button>
</div>
<select id="milestoneEditPosition" aria-label="Position bei einer Aufgabe" onchange="msLageSync()">
<option value="">Oben in der Projektzeile</option>
</select>
</div>
</div>
<div class="pd-zeile">
<span class="pd-lab">Hängt ab von</span>
<div class="pd-wert">
<div id="milestoneEditDependsOn" class="todo-depends-list pd-liste" onchange="msLageBildNeu()"></div>
</div>
</div>
<div class="pd-zeile">
<span class="pd-lab"><label for="milestoneEditNotiz">Notiz</label></span>
<div class="pd-wert">
<p class="hint pd-hint pd-mail-hinweis" id="milestoneEditMailHinweis" hidden></p>
<textarea id="milestoneEditNotiz" class="pd-notiz" rows="3" placeholder="Hintergrund oder die Mail, aus der der Meilenstein stammt"></textarea>
</div>
</div>
</div>
<div class="pd-fuss">
<button type="button" class="pd-loeschen" id="milestoneEditDelete" onclick="deleteMilestoneEdit()">Löschen</button>
@@ -1549,51 +1575,69 @@
<div class="modal pd">
<div class="pd-kopf">
<div class="pd-art"><span class="pd-kasten" aria-hidden="true"></span><span id="todoModalTitle">Aufgabe bearbeiten</span>
<span class="modal-kbd" id="todoModalKbd">Esc · Strg+↵</span>
<button type="button" class="pd-zu" onclick="closeTodoModal()" aria-label="Schließen">×</button></div>
<span class="pd-wo" id="todoModalWo"></span>
<span class="modal-kbd" id="todoModalKbd"><kbd>Esc</kbd> <kbd>Strg</kbd><kbd>↵</kbd></span>
<button type="button" class="pd-zu" onclick="closeTodoModal()" aria-label="Schließen"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg></button></div>
<input type="text" id="todoEditTitle" class="pd-titel" placeholder="Titel der Aufgabe" aria-label="Titel">
<span class="field-error" id="todoEditTitleError" hidden></span>
<div class="pd-stand">
<div class="segmented pd-seg" id="todoEditStatus">
<button type="button" data-status="offen" aria-pressed="false" onclick="setTodoEditStatus('offen')"><span class="segmented-dot"></span>Offen</button>
<button type="button" data-status="arbeit" aria-pressed="false" onclick="setTodoEditStatus('arbeit')"><span class="segmented-dot"></span>In Arbeit</button>
<button type="button" data-status="fertig" aria-pressed="false" onclick="setTodoEditStatus('fertig')"><span class="segmented-dot"></span>Erledigt</button>
</div>
<div class="progress-row" id="todoEditProgressRow">
<input type="range" id="todoEditProgress" min="0" max="100" step="5" value="0" aria-label="Fortschritt"
oninput="onTodoProgressInput(this)">
<output id="todoEditProgressVal">0 %</output>
</div>
</div>
<div class="pd-lage" id="todoLageBild" aria-label="Lage im Terminplan"></div>
</div>
<div class="pd-inhalt">
<!-- Nur im Phasen-Modus ("+ Neu" → "Leistungsphase" oder Bearbeiten
eines Phasenbalkens): Welche Leistungsphase dieser Balken ist. Nur
darüber wird ein Balken zum Phasenkopf, nicht mehr über den Titel. -->
<section class="pd-abs" id="todoEditPhaseAbs" hidden>
<h3>Leistungsphase</h3>
<select id="todoEditLph" aria-label="Leistungsphase" onchange="todoPhaseGewechselt()"></select>
<p class="hint pd-hint">Aufgaben, die im Zeitraum dieser Phase beginnen, stehen im Terminplan darunter.</p>
</section>
<section class="pd-abs">
<h3>Wann</h3>
<div class="field-inline">
<input type="text" id="todoEditRange" class="range-picker-display" placeholder="Start – Ende wählen…" readonly aria-label="Zeitraum"
onclick="openRangePicker({ anchor: this, startInputId: 'todoEditStart', endInputId: 'todoEditEnd', displayId: 'todoEditRange', onApply: refreshTodoDuration })">
<span class="field-badge" id="todoEditDuration" hidden></span>
<div class="pd-zeile" id="todoEditPhaseAbs" hidden>
<span class="pd-lab"><label for="todoEditLph">Leistungsphase</label></span>
<div class="pd-wert">
<select id="todoEditLph" onchange="todoPhaseGewechselt()"></select>
<p class="hint pd-hint">Aufgaben, die im Zeitraum dieser Phase beginnen, stehen im Terminplan darunter.</p>
</div>
<input type="hidden" id="todoEditStart">
<input type="hidden" id="todoEditEnd">
<span class="field-error" id="todoEditRangeError" hidden></span>
<label class="pd-haken"><input type="checkbox" id="todoEditShowInGantt" checked> Im Terminplan als Balken zeigen</label>
<p class="hint pd-hint">Ohne Zeitraum erscheint die Aufgabe nur unter „Aufgaben“, nicht im Terminplan.</p>
</section>
<section class="pd-abs" id="todoEditWerAbs">
<h3>Wer</h3>
<div id="todoEditAssignees" class="person-chips"></div>
<!-- Externe Personen: Kollegen mit Konto, die dem Projekt NICHT
zugeordnet sind (Eriks Wunsch). todoExternHinzufuegen()/
todoExternEntfernen(), js/plan/plan-modals.js -->
<div class="pd-externe">
<div class="pd-externe-kopf">Externe Personen <span class="hint">nicht im Projekt</span></div>
<div id="todoEditExterne" class="person-chips"></div>
<select id="todoEditExterneWahl" aria-label="Externe Person hinzufügen" onchange="todoExternHinzufuegen(this.value)"></select>
</div>
<!-- Aufwand: −/+, Schnellwahl, Umrechnung in Arbeitstage
(todoAufwandAendern()/todoAufwandSetzen()/todoAufwandInfo(), plan-modals.js) -->
<div class="pd-aufwand">
<div class="pd-aufwand-kopf">
<label for="todoEditAufwand">Aufwand</label>
<span>optional · zählt zur Auslastung der Zuständigen</span>
</div>
<div class="pd-zeile">
<span class="pd-lab">Zeitraum</span>
<div class="pd-wert">
<div class="field-inline">
<input type="text" id="todoEditRange" class="range-picker-display" placeholder="Start – Ende wählen…" readonly aria-label="Zeitraum"
onclick="openRangePicker({ anchor: this, startInputId: 'todoEditStart', endInputId: 'todoEditEnd', displayId: 'todoEditRange', onApply: refreshTodoDuration })">
<span class="field-badge" id="todoEditDuration" hidden></span>
</div>
<input type="hidden" id="todoEditStart">
<input type="hidden" id="todoEditEnd">
<span class="field-error" id="todoEditRangeError" hidden></span>
<label class="pd-haken"><input type="checkbox" id="todoEditShowInGantt" checked> Als Balken im Terminplan</label>
</div>
</div>
<div class="pd-zeile" id="todoEditWerAbs">
<span class="pd-lab">Zuständig</span>
<div class="pd-wert">
<div id="todoEditAssignees" class="person-chips"></div>
<!-- Externe Personen: Kollegen mit Konto, die dem Projekt NICHT
zugeordnet sind (Eriks Wunsch). todoExternHinzufuegen()/
todoExternEntfernen(), js/plan/plan-modals.js -->
<div class="pd-externe">
<div class="pd-externe-kopf">Externe Personen <span class="hint">nicht im Projekt</span></div>
<div id="todoEditExterne" class="person-chips"></div>
<select id="todoEditExterneWahl" aria-label="Externe Person hinzufügen" onchange="todoExternHinzufuegen(this.value)"></select>
</div>
</div>
</div>
<!-- Aufwand: −/+, Schnellwahl, Umrechnung in Arbeitstage
(todoAufwandAendern()/todoAufwandSetzen()/todoAufwandInfo(), plan-modals.js) -->
<div class="pd-zeile" id="todoEditAufwandAbs">
<span class="pd-lab"><label for="todoEditAufwand">Aufwand</label></span>
<div class="pd-wert pd-aufwand">
<div class="pd-aufwand-zeile">
<div class="pd-stepper">
<button type="button" class="pd-stepper-knopf" onclick="todoAufwandAendern(-1)" aria-label="Eine Stunde weniger">−</button>
@@ -1611,41 +1655,34 @@
</div>
<span class="pd-aufwand-info" id="todoAufwandInfoText"></span>
</div>
</section>
<section class="pd-abs">
<h3>Stand</h3>
<div class="segmented pd-seg" id="todoEditStatus">
<button type="button" data-status="offen" aria-pressed="false" onclick="setTodoEditStatus('offen')"><span class="segmented-dot"></span>Offen</button>
<button type="button" data-status="arbeit" aria-pressed="false" onclick="setTodoEditStatus('arbeit')"><span class="segmented-dot"></span>In Arbeit</button>
<button type="button" data-status="fertig" aria-pressed="false" onclick="setTodoEditStatus('fertig')"><span class="segmented-dot"></span>Erledigt</button>
</div>
<div class="progress-row" id="todoEditProgressRow">
<input type="range" id="todoEditProgress" min="0" max="100" step="5" value="0" aria-label="Fortschritt"
oninput="onTodoProgressInput(this)">
<output id="todoEditProgressVal">0 %</output>
</div>
</section>
<section class="pd-abs">
<h3>Notiz</h3>
<p class="hint pd-hint pd-mail-hinweis" id="todoEditMailHinweis" hidden></p>
<textarea id="todoEditNotiz" class="pd-notiz" rows="4" placeholder="Optional, z. B. Hintergrund oder die Mail, aus der die Aufgabe stammt" aria-label="Notiz"></textarea>
</section>
<section class="pd-abs">
<details class="fold" id="todoEditDependsFold">
<summary>
<span class="fold-caret">▶</span>
<span>Hängt ab von</span>
<span class="fold-count zero" id="todoEditDependsCount">0</span>
</summary>
<div class="fold-body">
<div class="fold-search">
<span class="fold-search-icon">⌕</span>
<input type="text" id="todoEditDependsSearch" placeholder="Aufgabe oder Meilenstein suchen…" oninput="filterTodoDepends()">
</div>
<div class="pd-zeile">
<span class="pd-lab">Hängt ab von</span>
<div class="pd-wert">
<div class="pd-vorg" id="todoEditDependsSummary"></div>
<details class="fold" id="todoEditDependsFold">
<summary>
<span class="fold-caret"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></span>
<span>Vorgänger ändern</span>
<span class="fold-count zero" id="todoEditDependsCount">0</span>
</summary>
<div class="fold-body">
<div class="fold-search">
<span class="fold-search-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="6"/><line x1="15.5" y1="15.5" x2="20" y2="20"/></svg></span>
<input type="text" id="todoEditDependsSearch" placeholder="Aufgabe oder Meilenstein suchen" oninput="filterTodoDepends()">
</div>
<div id="todoEditDependsOn" class="todo-depends-list flat" onchange="refreshTodoDependsCount()"></div>
</div>
<div id="todoEditDependsOn" class="todo-depends-list flat" onchange="refreshTodoDependsCount()"></div>
</div>
</details>
</section>
</details>
</div>
</div>
<div class="pd-zeile">
<span class="pd-lab"><label for="todoEditNotiz">Notiz</label></span>
<div class="pd-wert">
<p class="hint pd-hint pd-mail-hinweis" id="todoEditMailHinweis" hidden></p>
<textarea id="todoEditNotiz" class="pd-notiz" rows="3" placeholder="Hintergrund oder die Mail, aus der die Aufgabe stammt"></textarea>
</div>
</div>
</div>
<div class="pd-fuss">
<button type="button" class="pd-loeschen" id="todoEditDelete" onclick="deleteTodoEdit()">Löschen</button>
@@ -1963,7 +2000,7 @@
<script src="/js/store.js?v=17"></script>
<script src="/js/weeks.js?v=12"></script>
<script src="/js/board/board.js?v=42"></script>
<script src="/js/wochenbericht/wochenbericht.js?v=29"></script>
<script src="/js/wochenbericht/wochenbericht.js?v=31"></script>
<script src="/js/people/people.js?v=8"></script>
<script src="/js/planung/planung.js?v=3"></script>
<script src="/js/planchecker/planchecker.js?v=1"></script>
@@ -1977,7 +2014,7 @@
<!-- Assistent "Neues Projekt": braucht auftrag.js (Auftragsstatus) und
load.js (faktorFormat), steht deshalb dahinter. -->
<script src="/js/projekt-wizard.js?v=6"></script>
<script src="/js/dashboard/dashboard.js?v=13"></script>
<script src="/js/dashboard/dashboard.js?v=14"></script>
<script src="/js/benachrichtigungen.js?v=5"></script>
<!-- wand.js braucht berechneAuslastung()/loadAmpelColor()/kapazitaetsFaktor()/
stundenFormat() (load.js), classifyProjectChange()/findPreviousWeek()
@@ -1985,7 +2022,7 @@
relativerTag()/tageBis()/initialsFor() (dashboard.js) — alle laden
bereits vorher, die Reihenfolge hier ist also nur Zuordnung zum
Tab-Ordner, keine neue Abhängigkeit nach vorn. -->
<script src="/js/wand/wand.js?v=21"></script>
<script src="/js/wand/wand.js?v=22"></script>
<script src="/js/settings/settings.js?v=14"></script>
<script src="/js/admin/admin.js?v=24"></script>
<script src="/js/admin-users.js?v=10"></script>
@@ -2000,14 +2037,14 @@
js/gantt.js kommen, dessen buildGanttHtml() plan-build-gantt.js
umhuellt. -->
<script src="/js/plan/plan-state.js?v=25"></script>
<script src="/js/plan/plan-sections.js?v=12"></script>
<script src="/js/plan/plan-sections.js?v=13"></script>
<script src="/js/plan/plan-info.js?v=17"></script>
<script src="/js/plan/plan-history.js?v=4"></script>
<script src="/js/plan/plan-build-gantt.js?v=11"></script>
<script src="/js/plan/plan-gantt.js?v=23"></script>
<script src="/js/plan/plan-gantt.js?v=24"></script>
<script src="/js/plan/plan-drag.js?v=8"></script>
<script src="/js/plan/plan-modals.js?v=18"></script>
<script src="/js/plan/plan-tasks.js?v=4"></script>
<script src="/js/plan/plan-modals.js?v=21"></script>
<script src="/js/plan/plan-tasks.js?v=5"></script>
<script src="/js/plan/plan-phasen.js?v=3"></script>
<script src="/js/plan/plan-files.js?v=4"></script>
<script src="/js/plan/plan-protokoll.js?v=21"></script>
@@ -2023,7 +2060,7 @@
<script src="/js/plan/plan-settings.js?v=14"></script>
<script src="/js/plan/plan-schedule.js?v=7"></script>
<script src="/js/tabs-auth.js?v=19"></script>
<script src="/js/pdf.js?v=31"></script>
<script src="/js/pdf.js?v=32"></script>
<script src="/js/backup.js?v=2"></script>
<script src="/js/import.js?v=1"></script>
<script src="/js/init.js?v=14"></script>