Unnötige Datein gelöscht. DB normalisiert

This commit is contained in:
erik committed 2026-08-14 15:03:24 +02:00
1 parent da64472251
commit 4e083bee73
32 files changed
+971 -5542

No files matched your search

+7 -3
View File
@@ -114,16 +114,20 @@
const todos = Array.isArray(plan.todos) ? plan.todos : [];
const milestones = Array.isArray(plan.milestones) ? plan.milestones : [];
const todoIds = todos.map(t => t.id);
const milestoneIds = milestones.map(m => m.id);
// Alle beweglichen Zeilen in aktueller DOM-Reihenfolge
const rows = [...chart.querySelectorAll(DRAGGABLE_GANTT_ROW_SELECTOR)];
const todoRowIds = rows.filter(r => r.classList.contains('gantt-todo')).map(r => r.dataset.todoId).filter(Boolean);
const milestoneRowIds = rows.filter(r => r.classList.contains('gantt-milestone-row')).map(r => r.dataset.milestoneId).filter(Boolean);
// Sicherheitscheck: Anzahl muss stimmen
// Sicherheitscheck: Anzahl muss stimmen. Nicht jedes Meilenstein wird als
// eigene .gantt-milestone-row gerendert – nur die mit einer TODO-basierten
// Position (before:/after:) sind eigene Zeilen. Meilensteine ohne Position
// liegen in der Projektzeile und werden hier nicht umsortiert, deshalb nur
// die positionierten zählen.
if(todoRowIds.length !== todoIds.length) return;
if(milestoneRowIds.length !== milestoneIds.length) return;
const positionedIds = milestones.filter(m => m.position && /^(before|after):/.test(m.position)).map(m => m.id);
if(milestoneRowIds.length !== positionedIds.length) return;
// TODOs neu ordnen
const newTodos = [];
+19 -22
View File
@@ -66,20 +66,17 @@ window.PlanApp = {
// bindToolbarButtons: verbindet die Toolbar-Buttons (TODO hinzufügen,
// Auto-Schedule, Kritischer Pfad) mit ihren globalen Funktionen der
// anderen plan-Module.
// anderen plan-Module. Die Buttons binden ihre Handler bereits über das
// onclick-Attribut in project-plan.html; hier werden nur Lücken gefüllt,
// falls ein Button-Element fehlt.
function bindToolbarButtons(){
const addTodoBtn = document.getElementById('addTodoBtn');
if(addTodoBtn) addTodoBtn.addEventListener('click', () => addTodo());
const autoScheduleBtn = document.getElementById('autoScheduleBtn');
if(autoScheduleBtn) autoScheduleBtn.addEventListener('click', () => autoScheduleTodos());
const criticalPathBtn = document.getElementById('criticalPathBtn');
if(criticalPathBtn) criticalPathBtn.addEventListener('click', () => toggleCriticalPath());
}
// loadPlanData: lädt alle Sitzungen und die globale Personenliste der
// Abteilung über die Server-API, sortiert die Wochen chronologisch und
// sucht daraus die Ziel-Woche bzw. das Ziel-Projekt. Zeigt Fehlermeldungen
// der Reihenfolge nach im Seitenkopf an und startet sonst renderPlanPage().
// Abteilung über die Server-API (JSON-Dokumente), sortiert die Wochen
// chronologisch und sucht daraus die Ziel-Woche bzw. das Ziel-Projekt. Zeigt
// Fehlermeldungen der Reihenfolge nach im Seitenkopf an und startet sonst
// renderPlanPage().
function loadPlanData(){
if(!window.fetch){
document.getElementById('planSubtitle').textContent = 'Netzwerk nicht verfügbar.';
@@ -90,12 +87,15 @@ window.PlanApp = {
.then(r => { if(!r.ok) throw new Error('Server HTTP '+r.status); return r.json(); })
.then(data => {
db = { weeks: [], currentWeek: null, globalPeople: {} };
db.globalPeople[app.department] = parseGlobalPeopleCsv(data.people);
const parsed = (data.sessions || []).map(s => ({ filename: s.filename, rows: parseCsvText(s.content) }));
parsed.forEach(s => {
const w = parseSessionCsv(s.filename, s.rows);
if(w) db.weeks.push(w);
});
db.globalPeople[app.department] = Array.isArray(data.people) ? data.people : [];
db.weeks = (Array.isArray(data.weeks) ? data.weeks : [])
.filter(w => w && typeof w.label === 'string')
.map(w => {
if(!Array.isArray(w.people)) w.people = [];
if(!Array.isArray(w.projects)) w.projects = [];
if(!w.attendance) w.attendance = {};
return w;
});
db.weeks.sort((a,b) => weekSortKey(a.label).localeCompare(weekSortKey(b.label)));
app.week = db.weeks.find(w => w.label === app.weekLabel);
if(!app.week){
@@ -179,18 +179,15 @@ window.PlanApp = {
// Speichern: nur diese Sitzung; globale Personenliste nicht überschreiben
function savePlan(){
if(!app.week || !app.project) return;
const filename = filenameForWeek(app.week.label);
const csv = weekToCsv(app.week);
sendCsvToServer(filename, csv).catch(err => console.error('Speichern fehlgeschlagen:', err));
sendWeekToServer(app.week).catch(err => console.error('Speichern fehlgeschlagen:', err));
}
// saveGlobalPeople: schreibt die globale Personenliste der Abteilung als
// _people.csv auf den Server, aber nur wenn sie nicht leer ist.
// JSON-Array auf den Server, aber nur wenn sie nicht leer ist.
function saveGlobalPeople(){
const people = db.globalPeople[app.department] || [];
if(people.length > 0){
const peopleCsv = globalPeopleToCsv(people);
sendCsvToServer('_people.csv', peopleCsv).catch(err => console.error('Speichern Personen fehlgeschlagen:', err));
sendPeopleToServer(people).catch(err => console.error('Speichern Personen fehlgeschlagen:', err));
}
}