// ----------------------------- // Projektbereich — Projektangaben (Anzeige und Stammdaten) // ----------------------------- // Dieses Modul füllt die Projektangaben des Projektbereichs. Es unterscheidet // dabei zwei Arten von Angaben, und das ist der Kern der Sache: // // * NUR ANZEIGE — Kommentar der Sitzung (#planStatusEdit) und Fortschritt // je Leistungsphase (#planLphList). Beide entstehen in der wöchentlichen // Besprechung und werden ausschließlich im Wochenbericht erfasst. Neben // jeder von ihnen steht ein Verweis dorthin (setzeBerichtVerweis()), der // hinüberwechselt UND dort dieses Projekt einstellt. // * STAMMDATEN, hier pflegbar — Gruppe (#planGroupSelect) und amtierende // Leistungsphase (#planActiveLpSelect), beide im Bereich "Einstellungen". // // Warum: Dieselben Angaben waren zuvor an DREI Stellen bearbeitbar — // Projektboard, Wochenbericht und hier. Niemand wusste, welche davon die // richtige ist, und zwei Personen konnten dasselbe Feld an verschiedenen // Stellen ändern. Seitdem hat jede Angabe genau einen Ort, an dem sie // entsteht, und überall sonst steht sie zum Lesen samt Weg dorthin. Die // früheren Schreibfunktionen dieses Moduls (planStatusBlur(), setPlanLph(), // setPlanAssign()) sind damit entfallen. // // Die Zuordnung der Beteiligten (p.assign) gehörte früher ebenfalls zu // dieser "nur Anzeige"-Gruppe — auf Eriks ausdrücklichen Wunsch ist sie // seitdem umgekehrt: kein reines Anzeigefeld mehr, sondern ein echtes // Stammdatum, und zwar NUR HIER im Projektbereich editierbar (Bereich // "Einstellungen", gerendert von js/plan/plan-settings.js — // #planAssignMatrix liegt dort im Markup, nicht im Dashboard). Der // Wochenbericht zeigt die Zuordnung seitdem nur noch zum Lesen, mit einem // Verweis hierher. // // BEWUSST NICHT hier: Projektnummer, Bezeichnung, Schlagwörter, Honorar, // beauftragte Leistungsphasen und die Beteiligten-Matrix. Sie sind // Stammdaten und werden von js/plan/plan-settings.js gerendert (Honorar und // beauftragte Phasen geschrieben von setHonorarBetrag()/toggleBeauftragteLp() // aus js/plan/plan-honorar.js, die Beteiligten-Matrix von planCycleAssign()). // // renderPlanInfo() wird von // renderPlanPage() (plan-state.js) nach jedem Laden aufgerufen; Änderungen // speichern direkt über app.savePlan() und rendern danach nur das Infopanel // neu (das GANTT bleibt unberührt). // // Läuft wie alle plan-Module in einem IIFE; Zustand: window.PlanApp // (plan-state.js). (function(){ const app = window.PlanApp; // PLAN_ACTIVE_LPS: Phasen, die als amtierende Leistungsphase wählbar sind — // alle echten Leistungsphasen (inkl. LPH 9), aber ohne die Sammelkategorie // "W+M". Entspricht AUFWAND_LPS in js/load/load.js, hier separat definiert, // weil load.js auf der Projektplan-Seite bewusst nicht geladen wird (siehe // Kopfkommentar in App.html). Bewusst per Filter statt per // Index-Schnitt, damit eine spätere Ergänzung von LPHS nicht stillschweigend // durchs Raster fällt. const PLAN_ACTIVE_LPS = LPHS.filter(l => l !== 'W+M'); // planLpActiveList: liefert die (auf gültige Phasen gefilterte) amtierende // Leistungsphase eines Projekts als Array — Kopie von lpActiveList() in // js/load/load.js, das auf dieser Seite nicht geladen wird. Parameter: p // (Projekt). Rückgabe: Array (leer, wenn keine gesetzt). function planLpActiveList(p){ const a = p && p.aktuelleLP; if(Array.isArray(a)) return a.filter(l => PLAN_ACTIVE_LPS.includes(l)); if(typeof a === 'string' && PLAN_ACTIVE_LPS.includes(a)) return [a]; return []; } // renderPlanInfo: baut das Projektinfo-Panel (Status-Editor, Gruppe, // amtierende Leistungsphase, LPH-Prozentliste) aus app.project auf. Wird // nach jedem Laden (renderPlanPage(), plan-state.js) sowie nach jeder // Änderung hier selbst erneut aufgerufen. Keine Parameter, keine Rückgabe. window.renderPlanInfo = function(){ const p = app.project; const locked = app.isLocked(); // Kommentar, Fortschritt und Zuordnung sind hier NUR ZU SEHEN. // // Sie entstehen in der wöchentlichen Besprechung und werden deshalb im // Wochenbericht gepflegt — an genau einer Stelle. Zuvor waren dieselben // drei Angaben an drei Orten bearbeitbar (Projektboard, Wochenbericht, // Projektbereich); niemand wusste, welcher der richtige ist, und zwei // Personen konnten dasselbe Feld an verschiedenen Stellen pflegen. // Was hier bleibt, sind die Stammdaten des Projekts (Bereich // "Einstellungen", siehe plan-settings.js). const editEl = document.getElementById('planStatusEdit'); if(editEl){ editEl.className = 'status-edit is-ansicht'; editEl.contentEditable = 'false'; const text = sanitizeStatusHtml(p.status || ''); editEl.innerHTML = text || 'Für diese Sitzung ist noch kein Kommentar erfasst.'; } const statusWrap = document.getElementById('planStatusWrap'); if(statusWrap) statusWrap.classList.add('locked-cell'); setzeBerichtVerweis('planStatusVerweis', locked); // Gruppe — Stammdatum, bleibt hier pflegbar const groupSel = document.getElementById('planGroupSelect'); if(groupSel){ groupSel.value = p.group || 'Allgemein'; groupSel.disabled = locked; } // Amtierende Leistungsphase — Stammdatum, bleibt hier pflegbar const aktLp = planLpActiveList(p)[0] || ''; const lpSel = document.getElementById('planActiveLpSelect'); if(lpSel){ lpSel.innerHTML = '' + PLAN_ACTIVE_LPS.map(l => ``).join(''); lpSel.disabled = locked; } // Fortschritt je Leistungsphase — nur Anzeige, ohne Eingabefeld. // Zeigt nur die BEAUFTRAGTEN Leistungsphasen (p.beauftragteLP, siehe // "Einstellungen"), genau wie die Wochenbericht-/Board-Karte // (BOARD_OPTS.nurBeauftragteLph, js/board/board.js) — dieselbe Regel, // hier nur fest statt als opt-in, da das Dashboard keine zweite Fassung // mit allen Phasen kennt. Ist nichts beauftragt (ältere Bestands- // projekte), bleibt es bei der vollständigen Liste, sonst stünde dort // gar nichts. Vorher zeigte diese Liste IMMER alle Leistungsphasen, // unabhängig von den Einstellungen — von Erik gemeldet. const beauftragt = Array.isArray(p.beauftragteLP) ? p.beauftragteLP : []; const sichtbareLphs = beauftragt.length > 0 ? LPHS.filter(l => beauftragt.includes(l)) : LPHS; const lphList = document.getElementById('planLphList'); if(lphList){ if(!p.lph) p.lph = {}; lphList.innerHTML = sichtbareLphs.map(l => { const v = (p.lph[l] !== undefined && p.lph[l] !== '') ? p.lph[l] : ''; const aktiv = l === aktLp; const pct = v !== '' ? Math.min(100, parseFloat(v)||0) : 0; return `
${esc(l)}
${v === '' ? '–' : esc(v) + ' %'}
`; }).join(''); } setzeBerichtVerweis('planLphVerweis', locked); // Beteiligte: siehe js/plan/plan-settings.js (renderPlanSettings()) — // Stammdatum, nicht mehr hier. }; // setzeBerichtVerweis: füllt einen Hinweis-Platz mit dem Weg zur // Bearbeitung. Der Verweis ist ein echter Sprung: Er wechselt in den // Wochenbericht UND wählt dort dieses Projekt aus — ohne das müsste man es // in einer Liste von dreißig wiederfinden. // Parameter: elementId, locked. Keine Rückgabe. function setzeBerichtVerweis(elementId, locked){ const el = document.getElementById(elementId); if(!el) return; if(locked){ el.innerHTML = 'Die Sitzung ist gesperrt.'; return; } const uid = esc(app.project && app.project.projectUid ? app.project.projectUid : ''); el.innerHTML = ``; } // springZumWochenbericht: wechselt in den Wochenbericht und stellt dort // dieses Projekt ein. Beides zusammen, weil ein Sprung, der nur den Bereich // wechselt, die eigentliche Arbeit — das Projekt wiederfinden — beim // Nutzer ließe. Parameter: uid (project_uid). Keine Rückgabe. window.springZumWochenbericht = function(uid){ if(typeof showTab !== 'function') return; // Erst die Auswahl setzen, dann umschalten: showTab('wochenbericht') // rendert den Bereich bereits, und der soll gleich das richtige Projekt // zeigen — sonst blitzte kurz das erste Projekt der Liste auf. // berichtAuswahl ist eine globale let-Bindung aus // js/wochenbericht/wochenbericht.js (klassische Skripte, kein Modul). if(uid) berichtAuswahl = uid; showTab('wochenbericht'); }; // setPlanGroup: ändert die Gruppe des Projekts. Parameter: val (String). // Keine Rückgabe; bei gesperrter Woche abgebrochen. window.setPlanGroup = function(val){ if(app.isLocked()) return; app.project.group = val; app.savePlan(); }; // setPlanActiveLp: setzt bzw. hebt die amtierende Leistungsphase des // Projekts auf. Parameter: val (LPH-Name oder leer). Rendert das // Infopanel neu, damit die Markierung in der LPH-Liste sofort mitzieht. window.setPlanActiveLp = function(val){ if(app.isLocked()) return; if(val) app.project.aktuelleLP = [val]; else delete app.project.aktuelleLP; app.savePlan(); window.renderPlanInfo(); }; // Die Schreibfunktionen setPlanLph()/setPlanAssign()/planStatusBlur() sind // entfallen. Fortschritt und Kommentar werden allein im Wochenbericht // erfasst (siehe den Kopf dieser Datei); hier gab es damit keinen Aufrufer // mehr. Die gleichnamigen Funktionen des Projektboards // (editLph()/saveBoardComment() in js/board/board.js) sind davon // unberührt — dort hängt die Erfassung des Wochenberichts dran. Die // Zuordnung der Beteiligten (ehemals setPlanAssign()) läuft seit ihrer // Verlagerung in die Projekteinstellungen über planCycleAssign() // (js/plan/plan-settings.js) — ebenfalls kein Fall für dieses Modul. })();