code auf einzelne Datein aufgeteilt
This commit is contained in:
1 parent
7451e0bf78
commit
8c94fc91f6
30 files changed
+5765
-27
No files matched your search
@@ -0,0 +1,178 @@
|
||||
// -----------------------------
|
||||
// Projektübersicht — Daten laden, Speichern, Abteilung wechseln
|
||||
// -----------------------------
|
||||
// Diese Datei bildet die Schnittstelle zum Server: Sie lädt alle Sitzungs-CSVs
|
||||
// beim Start, speichert den kompletten Datenbestand (alle Wochen + globale
|
||||
// Personenliste) und verwaltet den Wechsel zwischen Abteilungen (ELT/HLS/ARCH).
|
||||
// Sie wird von `Test.html` nach `js/csv.js` und `js/server.js` geladen und stellt
|
||||
// die globalen Funktionen `save()`, `syncAllToServer()`, `switchDepartment()`,
|
||||
// `load()`, `seed()` und `demoProj()` bereit. Aufrufer sind u.a. `js/weeks.js`,
|
||||
// `js/board.js`, `js/people.js`, `js/projects.js` und `js/load.js`; das Speichern
|
||||
// ist über `saveSyncTimer` (in `js/globals.js` deklariert) um 500 ms debounced.
|
||||
|
||||
// save: synchronisiert die aktuellen Daten als CSV-Dateien zum Server.
|
||||
// Jede Sitzung wird als eigene CSV-Datei gespeichert. Personen und Rollen werden
|
||||
// in der Sitzungscsv selbst abgelegt.
|
||||
function save(){
|
||||
scheduleSessionSync();
|
||||
}
|
||||
|
||||
// scheduleSessionSync: plant den Speichervorgang für alle Wochen und Personen
|
||||
// über einen 500-ms-Timer (Debounce). Bei erneutem Aufruf wird ein laufender
|
||||
// Timer zurückgesetzt, damit aufeinanderfolgende Änderungen in einem Sync enden.
|
||||
function scheduleSessionSync(){
|
||||
if(saveSyncTimer){ clearTimeout(saveSyncTimer); }
|
||||
saveSyncTimer = setTimeout(() => { syncAllToServer(); saveSyncTimer = null; }, 500);
|
||||
}
|
||||
|
||||
// syncAllToServer: schreibt die gesamte Datenbank als CSV-Dateien zum Server.
|
||||
// Zuerst wird die globale Personenliste (`_people.csv`) gespeichert, danach jede
|
||||
// Sitzung einzeln über `filenameForWeek()`/`weekToCsv()` und `sendCsvToServer()`.
|
||||
// Gibt nichts zurück; Fehler werden nur per console.error protokolliert.
|
||||
function syncAllToServer(){
|
||||
// Zuerst globale Personenliste speichern
|
||||
saveGlobalPeopleToServer();
|
||||
// Dann jede Sitzung speichern
|
||||
db.weeks.forEach(w => {
|
||||
const filename = filenameForWeek(w.label);
|
||||
const csv = weekToCsv(w);
|
||||
sendCsvToServer(filename, csv)
|
||||
.then(res => { if(res && res.ok) console.log('Sitzung gespeichert:', filename); })
|
||||
.catch(err => { console.error('Sitzung konnte nicht gespeichert werden:', filename, err.message || err); });
|
||||
});
|
||||
}
|
||||
|
||||
// saveGlobalPeopleToServer: serialisiert die globale Personenliste der aktuellen
|
||||
// Abteilung per `globalPeopleToCsv()` und speichert sie als `_people.csv`.
|
||||
// Leere Personenlisten werden übersprungen (kein Schreibvorgang).
|
||||
function saveGlobalPeopleToServer(){
|
||||
const people = db.globalPeople[currentDepartment] || [];
|
||||
if(people.length === 0) return;
|
||||
const csv = globalPeopleToCsv(people);
|
||||
sendCsvToServer('_people.csv', csv)
|
||||
.then(res => { if(res && res.ok) console.log('Globale Personenliste gespeichert'); })
|
||||
.catch(err => { console.error('Globale Personenliste konnte nicht gespeichert werden:', err.message || err); });
|
||||
}
|
||||
|
||||
// switchDepartment: wechselt die aktive Abteilung (z.B. "ELT") und lädt deren
|
||||
// Daten neu. Parameter `dept` ist der Abteilungsschlüssel aus `DEPARTMENTS`.
|
||||
// Aktualisiert Tab-Markierung und Seitentitel und ruft anschließend `load()`.
|
||||
// Gibt nichts zurück.
|
||||
function switchDepartment(dept){
|
||||
if(!DEPARTMENTS[dept]) return;
|
||||
currentDepartment = dept;
|
||||
saveUiState();
|
||||
|
||||
// UI-Status der Abteilungs-Tabs aktualisieren
|
||||
document.querySelectorAll('.dept-tab').forEach(btn => {
|
||||
btn.classList.toggle('active', btn.dataset.dept === dept);
|
||||
});
|
||||
|
||||
// Seitentitel anpassen
|
||||
const info = DEPARTMENTS[dept];
|
||||
document.title = 'Projektübersicht ' + info.label;
|
||||
const titleEl = document.getElementById('pageTitle');
|
||||
if(titleEl) titleEl.textContent = info.icon + ' Projektübersicht ' + info.label;
|
||||
|
||||
// Datenbank leeren und neu laden
|
||||
db = { weeks: [], currentWeek: null, globalPeople: db.globalPeople || {} };
|
||||
load();
|
||||
}
|
||||
|
||||
// load: liest alle CSV-Dateien der aktuellen Abteilung über `/load-all` vom
|
||||
// Server ein, parst Personen und Sitzungen (mit `parseSessionCsv()`) und baut
|
||||
// daraus `db.weeks` auf. Sortiert nach `weekSortKey()`, wendet `applyAutoLock()`
|
||||
// an und rendert die Ansicht. Kein Parameter, keine Rückgabe; bei Fehlern oder
|
||||
// fehlenden Daten werden Beispieldaten über `seed()` geladen.
|
||||
function load(){
|
||||
if(!window.fetch){
|
||||
alert('Ihr Browser unterstützt keine Netzwerk-Anfragen. Bitte verwenden Sie einen aktuellen Browser.');
|
||||
seed(); return;
|
||||
}
|
||||
const url = baseUrl() + '/load-all' + departmentParam();
|
||||
console.log('Loading from', url);
|
||||
fetch(url)
|
||||
.then(r => { if(!r.ok) throw new Error('Server HTTP '+r.status); return r.json(); })
|
||||
.then(data => {
|
||||
// Globale Personenliste laden
|
||||
db.globalPeople[currentDepartment] = parseGlobalPeopleCsv(data.people);
|
||||
|
||||
const parsedSessions = (data.sessions || []).map(s => ({ filename: s.filename, rows: parseCsvText(s.content) }));
|
||||
|
||||
db.weeks = [];
|
||||
parsedSessions.forEach(s => {
|
||||
const w = parseSessionCsv(s.filename, s.rows);
|
||||
if(w) db.weeks.push(w);
|
||||
});
|
||||
|
||||
if(db.weeks.length === 0){
|
||||
console.warn('Server lieferte 0 Sitzungsdateien. Es werden Beispieldaten (seed) angezeigt. Pruefen Sie, ob der Ordner sessions/ mitkopiert wurde.');
|
||||
seed();
|
||||
}
|
||||
else {
|
||||
db.weeks.sort((a,b) => weekSortKey(a.label).localeCompare(weekSortKey(b.label)));
|
||||
applyAutoLock();
|
||||
const latest = db.weeks[db.weeks.length - 1];
|
||||
if(!db.currentWeek || !db.weeks.some(w => w.id === db.currentWeek)){
|
||||
db.currentWeek = latest.id;
|
||||
}
|
||||
console.log(`Server-Load erfolgreich: ${db.weeks.length} Sitzung(en).`);
|
||||
}
|
||||
// Geschützte Tabs dürfen nicht ohne Passwort angezeigt werden, auch wenn
|
||||
// sie im UI-State gespeichert waren.
|
||||
if(currentTab === 'projects' || currentTab === 'people') currentTab = DEFAULT_TAB;
|
||||
renderAll();
|
||||
showTab(currentTab, true);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Laden vom Server fehlgeschlagen:', err);
|
||||
const serverUrl = baseUrl();
|
||||
const msg = 'Server unter ' + serverUrl + ' nicht erreichbar.\n\n' +
|
||||
'Mögliche Ursachen:\n' +
|
||||
'- Der Server wurde nicht gestartet\n' +
|
||||
'- Der Server läuft auf einem anderen Port (Standard: 3003)\n' +
|
||||
'- Firewall/Antivirus blockiert ' + serverUrl + '\n\n' +
|
||||
'Es werden jetzt die Beispieldaten angezeigt.';
|
||||
alert(msg);
|
||||
seed(); renderAll();
|
||||
});
|
||||
}
|
||||
|
||||
// seed: initialisiert Beispiel-Daten (Personen + eine Woche mit Projekten).
|
||||
// Wird als Fallback verwendet, wenn der Server nicht erreichbar ist oder keine
|
||||
// Sitzungsdateien liefert.
|
||||
function seed(){
|
||||
const people = [
|
||||
{id:personIdForName('AP'), name:"AP", fullName:"Anton Peters", role:["Planung"]},
|
||||
{id:personIdForName('SK'), name:"SK", fullName:"Stefan Krause", role:["Planung"]},
|
||||
{id:personIdForName('AK'), name:"AK", fullName:"Alexander Klein", role:["Planung"]},
|
||||
{id:personIdForName('ED'), name:"ED", fullName:"Eva Dreyer", role:["Planung"]},
|
||||
{id:personIdForName('SE'), name:"SE", fullName:"Stefan Eschweiler", role:["Planung"]},
|
||||
{id:personIdForName('THK'), name:"THK", fullName:"Thorsten H. Klein", role:["Projektleitung"]},
|
||||
{id:personIdForName('SP'), name:"SP", fullName:"Sven Peschke", role:["Projektleitung"]},
|
||||
{id:personIdForName('SG'), name:"SG", fullName:"Sandra Gloag", role:["Projektleitung"]},
|
||||
{id:personIdForName('TW'), name:"TW", fullName:"Thorsten Wörster", role:["Projektleitung"]},
|
||||
{id:personIdForName('RR'), name:"RR", fullName:"Robert Rahn", role:["Bauüberwachung"]},
|
||||
{id:personIdForName('MK'), name:"MK", fullName:"Martin Kluge", role:["Bauüberwachung"]},
|
||||
{id:personIdForName('HR'), name:"HR", fullName:"Hartwig Rauch", role:["Bauüberwachung"]},
|
||||
];
|
||||
db.globalPeople[currentDepartment] = JSON.parse(JSON.stringify(people));
|
||||
|
||||
const wid = uid();
|
||||
db.weeks = [{
|
||||
id: wid, label:"KW 30 / 2026", date:"2026-07-24", attendance:{}, people, projects: [
|
||||
demoProj("18-4007","Janusz-Korczak-Gesamtsch. Bottrop","Aktive Projekte","LPH5 als Vorabzug raus. NW-Räume vorauss. August.",{"LPH 1":100,"LPH 2":100,"LPH 3":100,"LPH 5":100,"LPH 6":100,"LPH 7":100,"LPH 8":95}),
|
||||
demoProj("21-4030","NSHV Köln Immobilienprüfung in Hof","Aktive Projekte","Thorsten W. klärt und übernimmt Schriftverkehr. LV liegt zur Sichtung bei T.W.",{"LPH 1":100,"LPH 2":100,"LPH 3":100,"LPH 5":100,"LPH 6":100}),
|
||||
demoProj("22-4056","Gymnasium Hemer","Aktive Projekte","",{"LPH 1":100,"LPH 2":100,"LPH 3":100,"LPH 5":100,"LPH 6":100,"LPH 7":100,"LPH 8":90}),
|
||||
demoProj("22-4066","DSW 21 – Umbau E-Mobilität","Aktive Projekte","Elt-Montagen ab KW 33.",{"LPH 1":100,"LPH 2":100,"LPH 3":100,"LPH 5":100,"LPH 6":100,"LPH 7":100,"LPH 8":20}),
|
||||
demoProj("24-4043","S-K ODL-Heim Sanierung Krefeld","Aktive Projekte","Voraussichtlich LV-Abgabe.",{"LPH 1":100,"LPH 2":100,"LPH 3":100,"LPH 5":100}),
|
||||
]
|
||||
}];
|
||||
db.currentWeek = wid;
|
||||
save();
|
||||
}
|
||||
|
||||
// demoProj: Helfer zum Erzeugen eines Projekt-Objekts (für seed/Tests)
|
||||
function demoProj(nr,name,group,status,lph){
|
||||
return {id:uid(), nr, name, group, status, lph: {...lph}, assign:{}, plan: null, aufwandProLP: undefined, aktuelleLP: undefined};
|
||||
}
|
||||
Reference in new issue
Block a user