Termin aus Mail, Rollen & Rechte, Abwesenheiten, Glas-Darstellung und Pi-Betrieb

- Termin aus Mail: Mailtext oder .eml per Drag & Drop/Strg+V auf Terminplan
  oder Aufgaben, KI schlägt Aufgaben vor, Prüfung im Aufgaben-Panel; neues
  Notizfeld je Aufgabe (plan_todos.notiz)
- Terminplan: Meilensteine ohne Aufgabenbezug je in eigener Zeile,
  "+ Neu"-Menü klappt neben schmaler Seitenleiste nach rechts, Leistungsphasen
- Rollen & Rechte, Abwesenheiten-Seite, Benachrichtigungen, Rundgang
- Glas-Darstellung, Logo als Favicon
- Pi-Betrieb: PDF-Arbeit im Kindprozess, Wächter, Einrichtungs- und
  Prüfskript inkl. WLAN-Wächter

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
erikandClaude Opus 5.5 committed 2026-10-29 14:16:52 +01:00
1 parent f4fb3c550b
commit b7e0bd0d92
56 files changed
+12265 -2974

No files matched your search

+26 -13
View File
@@ -36,7 +36,6 @@ window.PlanApp = {
week: null, // planWeek
project: null, // planProject
pxPerDay: 14, // Zoomstufe GANTT (null = an Containerbreite anpassen)
criticalPathActive: false, // Hervorhebung des kritischen Pfads im GANTT aktiv
// Drag-Zustände
todoDrag: null, // Drag-and-Drop von TODO/Meilenstein-Zeilen
ganttDrag: null, // Balken/Meilenstein/Urlaub verschieben
@@ -122,6 +121,9 @@ window.PlanApp = {
app.projNr = '';
app.projName = app.project.name || '';
renderPlanPage();
// showTab() hat die Adresse schon vor diesem Aufruf geschrieben, als
// der Name noch fehlte (/Projektplan/?…) — jetzt mit Namen nachziehen.
if(typeof updateRouteUrl === 'function') updateRouteUrl('plan');
return true;
}
@@ -177,10 +179,21 @@ window.PlanApp = {
return app.project.plan;
}
// isLocked: liefert true, wenn die aktuelle Woche gesperrt ist (dann sind
// Bearbeitungen im Plan gesperrt). Rückgabe: Boolescher Wert.
// isLocked: liefert true, wenn der TERMINPLAN nicht bearbeitet werden darf
// — gesperrte Sitzung oder fehlendes Recht „Terminplan bearbeiten“ (bei
// einem Planung-Plan: „Planung“; Rollen & Rechte). Rückgabe: Boolean.
function isLocked(){
return !!app.week.locked;
return !!app.week.locked || !hatRecht(isSandboxPlan() ? 'wz.planung' : 'proj.plan');
}
// stammGesperrt: dasselbe für Projekteinstellungen, Gruppe, amtierende
// Leistungsphase und Honorar (Recht „Stammdaten und Beteiligte“).
function stammGesperrt(){
return !!app.week.locked || !hatRecht(isSandboxPlan() ? 'wz.planung' : 'proj.stamm');
}
// protokolleGesperrt: Protokolle (Recht „Protokolle bearbeiten“), in einer
// gesperrten Sitzung wie bisher gesperrt.
function protokolleGesperrt(){
return !!app.week.locked || !hatRecht('proj.protokolle');
}
// isSandboxPlan: liefert true, wenn der aktuell geöffnete Plan zur
@@ -238,8 +251,6 @@ window.PlanApp = {
// Bereichs), lädt bei vorhandener Projektnummer die Protokollliste.
if(typeof initPlanProtokoll === 'function') initPlanProtokoll();
// Verlauf über alle Sitzungen (Kommentar-Historie) — siehe js/plan/plan-history.js.
renderPlanHistory();
// Einstellungen-Bereich (Honorar, beauftragte Leistungsphasen,
// Projektangaben) — siehe js/plan/plan-settings.js.
@@ -247,10 +258,12 @@ window.PlanApp = {
// Schaltflächen, die neue Aufgaben/Meilensteine erzeugen — in gesperrten
// Sitzungen nicht möglich. Die Liste enthält die Knöpfe beider Bereiche:
// Terminplan (…Btn) und Aufgaben (…BtnList), siehe App.html.
// Terminplan (…Btn), Aufgaben (…BtnList) und Leistungsphasen (…BtnPhasen),
// siehe App.html.
const locked = isLocked();
['addMilestoneBtn', 'addTodoBtn', 'templateBtn', 'honorarBtn', 'protokollTodosBtn', 'autoScheduleBtn',
'addTodoBtnList', 'addMilestoneBtnList', 'templateBtnList', 'honorarBtnList', 'protokollTodosBtnList', 'autoScheduleBtnList']
['addMilestoneBtn', 'addPhaseBtn', 'addTodoBtn', 'templateBtn', 'honorarBtn', 'protokollTodosBtn',
'addTodoBtnList', 'addMilestoneBtnList', 'templateBtnList', 'protokollTodosBtnList', 'autoScheduleBtnList',
'honorarBtnPhasen', 'addPhaseBtnPhasen']
.forEach(id => {
const btn = document.getElementById(id);
if(btn) btn.style.display = locked ? 'none' : '';
@@ -263,10 +276,8 @@ window.PlanApp = {
document.querySelectorAll('#planNav .plan-nav-item[data-section="dateien"], #planNav .plan-nav-item[data-section="leistung"], #planNav .plan-nav-item[data-section="protokolle"]')
.forEach(btn => { btn.style.display = sandbox ? 'none' : ''; });
// Gantt-PDF-Export (js/pdf.js, exportSandboxPlanPDF()) gibt es nur für
// Sandbox-Pläne der Planung — ein echtes Projekt hat kein Äquivalent.
const sandboxPdfBtn = document.getElementById('sandboxPdfBtn');
if(sandboxPdfBtn) sandboxPdfBtn.style.display = sandbox ? '' : 'none';
// Gantt-PDF-Export (js/pdf.js, exportSandboxPlanPDF()) gilt für
// Planung-Pläne UND echte Projekte, der Knopf ist immer sichtbar.
// GANTT inkl. TODOs (rendert am Ende auch Aufgabenliste und Dashboard mit)
fitPlanGanttRange();
@@ -394,6 +405,8 @@ window.PlanApp = {
// (plan-drag, plan-modals, plan-schedule) sie direkt nutzen können.
app.ensurePlanLocal = ensurePlanLocal;
app.isLocked = isLocked;
app.stammGesperrt = stammGesperrt;
app.protokolleGesperrt = protokolleGesperrt;
app.isSandboxPlan = isSandboxPlan;
app.removeDependencyRefs = removeDependencyRefs;
app.renderProjectAssignees = renderProjectAssignees;