Kleine Verbesserungen und Teams, Outlook Integration
- Outlook: Kalender-Abo je Konto (eigene Aufgaben, Meilensteine, Abwesenheiten als .ics), einzurichten unter Einstellungen - Teams: Nachricht in einen Kanal bei neuen Aufgaben, mit Link direkt auf die Aufgabe; einzurichten unter Admin → Teams - Sitzungen nach Bedarf laden: beim Start nur die aktuelle und drei davor, im Verlauf „Weitere laden“ in Fünferschritten - Termin aus Mail: Wahl Aufgabe/Meilenstein, Notiz auch bei Meilensteinen, nur aktiv mit eingerichteter KI - Kalender zeigt die KW, auch statt der Browser-Datumsfelder - Pfeile bei den Abwesenheiten, kleinere Server-Korrekturen Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a2266662ad
commit
4c2e04e78b
19 files changed
+1100
-139
No files matched your search
+109
-9
@@ -596,7 +596,13 @@ function liveWocheNachladen(label, geloescht){
|
||||
// Während eines eigenen Speicherns nicht dazwischenfunken; kurz danach.
|
||||
if(syncInFlight){ setTimeout(() => liveWocheNachladen(label), 1000); return; }
|
||||
const w = label === SANDBOX_WEEK_LABEL ? db.sandboxWeek : (db.weeks || []).find(x => x.label === label);
|
||||
if(!w) return liveAllesNeu();
|
||||
if(!w){
|
||||
// Eine ältere, hier nicht geladene Sitzung (z. B. entsperrt): nur ihren
|
||||
// Eintrag in der Sitzungsliste nachziehen, nicht alles neu laden.
|
||||
const kurz = (db.wochenListe || []).find(x => x.label === label);
|
||||
if(kurz) return wocheVomServer(label).then(f => { if(f) Object.assign(kurz, sitzungKurz(f)); ansichtNachBearbeitung(); }).catch(() => {});
|
||||
return liveAllesNeu();
|
||||
}
|
||||
wocheVomServer(label).then(frisch => {
|
||||
if(!frisch) return liveAllesNeu();
|
||||
if(syncInFlight){ setTimeout(() => liveWocheNachladen(label), 1000); return; }
|
||||
@@ -648,6 +654,102 @@ function handleWeekConflict(week, err){
|
||||
else load();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sitzungen nach Bedarf (Eriks Wunsch: beim Start nur die aktuelle und drei
|
||||
// davor; im Verlauf „Weitere laden“ holt je fünf ältere nach)
|
||||
// ---------------------------------------------------------------------------
|
||||
// db.weeks hält nur die GELADENEN Sitzungen, db.wochenListe ALLE schlank
|
||||
// ({id, label, date, locked, updatedAt}, älteste zuerst). Wer eine nicht
|
||||
// geladene Sitzung braucht (Admin → Sitzungen, Deep-Link auf ein Projekt
|
||||
// einer älteren Sitzung), holt sie über sitzungSicherLaden().
|
||||
const SITZUNGEN_START = 4;
|
||||
const SITZUNGEN_NACHLADEN = 5;
|
||||
|
||||
function wocheAbsichern(w){
|
||||
// Felder absichern, damit alte/kaputte Dokumente nicht crashen
|
||||
if(!Array.isArray(w.people)) w.people = [];
|
||||
if(!Array.isArray(w.projects)) w.projects = [];
|
||||
if(!w.attendance) w.attendance = {};
|
||||
return w;
|
||||
}
|
||||
function sitzungKurz(w){
|
||||
return { id: w.id, label: w.label, date: w.date || '', locked: !!w.locked, updatedAt: w.updatedAt || '' };
|
||||
}
|
||||
|
||||
// sitzungKurzAbgleichen: den schlanken Eintrag einer Sitzung in
|
||||
// db.wochenListe auf den Stand des vollen Objekts bringen (Sperre, Revision).
|
||||
function sitzungKurzAbgleichen(w){
|
||||
const k = (db.wochenListe || []).find(x => x.label === w.label);
|
||||
if(k) Object.assign(k, sitzungKurz(w));
|
||||
}
|
||||
|
||||
// wochenEinfuegen: geladene Sitzungen in db.weeks aufnehmen (ohne Doppel),
|
||||
// sortieren und als Basis fürs Zusammenführen merken.
|
||||
function wochenEinfuegen(liste){
|
||||
(liste || []).forEach(w => {
|
||||
if(!w || typeof w.label !== 'string' || db.weeks.some(x => x.label === w.label)) return;
|
||||
db.weeks.push(wocheAbsichern(w));
|
||||
basisMerken(w);
|
||||
});
|
||||
db.weeks.sort((a, b) => weekSortKey(a.label).localeCompare(weekSortKey(b.label)));
|
||||
}
|
||||
|
||||
// aeltereSitzungenAnzahl: wie viele Sitzungen älter als die älteste geladene
|
||||
// noch nicht geladen sind.
|
||||
function aeltereSitzungenAnzahl(){
|
||||
const liste = db.wochenListe || [];
|
||||
if(!db.weeks.length) return 0;
|
||||
const aelteste = db.weeks[0].label;
|
||||
const idx = liste.findIndex(w => w.label === aelteste);
|
||||
return idx < 0 ? 0 : idx;
|
||||
}
|
||||
|
||||
// weitereSitzungenLaden: holt die nächsten älteren Sitzungen und zeichnet
|
||||
// danach neu — die ganze Ansicht, oder nur, was nachher (Name einer globalen
|
||||
// Funktion) zeichnet. Der Wochenbericht nutzt das, damit ein angefangener
|
||||
// Kommentar nicht durch ein Neuzeichnen verloren geht. Rückgabe: Promise.
|
||||
let weitereLaufen = null;
|
||||
function weitereSitzungenLaden(anzahl, nachher){
|
||||
if(weitereLaufen) return weitereLaufen;
|
||||
if(!db.weeks.length || aeltereSitzungenAnzahl() === 0) return Promise.resolve();
|
||||
const vor = db.weeks[0].label;
|
||||
weitereLaufen = fetch(baseUrl() + '/weeks-aelter?vor=' + encodeURIComponent(vor) + '&anzahl=' + (anzahl || SITZUNGEN_NACHLADEN))
|
||||
.then(r => { if(!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })
|
||||
.then(d => {
|
||||
wochenEinfuegen(d.weeks);
|
||||
if(nachher && typeof window[nachher] === 'function'){ window[nachher](); return; }
|
||||
ansichtAuffrischen();
|
||||
// Kommentar-Verlauf im Projekt-Dashboard hängt an renderPlanInfo().
|
||||
if(typeof currentTab !== 'undefined' && currentTab === 'plan' && typeof renderPlanInfo === 'function') renderPlanInfo();
|
||||
})
|
||||
.catch(err => { console.error('Ältere Sitzungen laden fehlgeschlagen:', err); alert('Ältere Sitzungen konnten nicht geladen werden.'); })
|
||||
.finally(() => { weitereLaufen = null; });
|
||||
return weitereLaufen;
|
||||
}
|
||||
|
||||
// weitereLadenKnopf: Knopf „Weitere laden“ für einen Verlauf — nur, solange
|
||||
// es ältere, nicht geladene Sitzungen gibt. Parameter: nachher (optional,
|
||||
// siehe weitereSitzungenLaden()). Rückgabe: HTML-String ('' sonst).
|
||||
function weitereLadenKnopf(nachher){
|
||||
const n = aeltereSitzungenAnzahl();
|
||||
if(!n) return '';
|
||||
const k = Math.min(n, SITZUNGEN_NACHLADEN);
|
||||
return `<button type="button" class="secondary small verlauf-weitere" onmousedown="event.preventDefault()" onclick="event.stopPropagation(); weitereSitzungenLaden(0${nachher ? ", '" + nachher + "'" : ''})"
|
||||
title="Noch ${n} ältere Sitzung${n === 1 ? '' : 'en'} am Server">Weitere laden (${k} ${k === 1 ? 'Sitzung' : 'Sitzungen'})</button>`;
|
||||
}
|
||||
|
||||
// sitzungSicherLaden: liefert eine Sitzung, lädt sie bei Bedarf einzeln
|
||||
// nach. Rückgabe: Promise<Woche|null>.
|
||||
function sitzungSicherLaden(label){
|
||||
const da = db.weeks.find(w => w.label === label);
|
||||
if(da) return Promise.resolve(da);
|
||||
return wocheVomServer(label).then(w => {
|
||||
if(!w) return null;
|
||||
wochenEinfuegen([w]);
|
||||
return db.weeks.find(x => x.label === label) || null;
|
||||
});
|
||||
}
|
||||
|
||||
// reloadWeekFromServer: lädt alle Sitzungen neu und ersetzt NUR die
|
||||
// übergebene Woche (bzw. entfernt sie, falls sie am Server gelöscht wurde).
|
||||
// Der Dirty-Zustand der konfliktbehafteten Woche wurde bereits von
|
||||
@@ -745,7 +847,9 @@ function load(silent){
|
||||
alert('Ihr Browser unterstützt keine Netzwerk-Anfragen. Bitte verwenden Sie einen aktuellen Browser.');
|
||||
return;
|
||||
}
|
||||
const url = baseUrl() + '/load-all';
|
||||
// Nur die jüngsten SITZUNGEN_START Sitzungen (aktuelle + drei davor);
|
||||
// ältere holt weitereSitzungenLaden() bei Bedarf (Eriks Wunsch).
|
||||
const url = baseUrl() + '/load-all?wochen=' + SITZUNGEN_START;
|
||||
console.log('Loading from', url);
|
||||
// Erst die firmenweiten Einstellungen und Feiertage, dann die Sitzungen:
|
||||
// renderAll() am Ende rechnet bereits damit (Ampel-Schwellen, Balkenskala,
|
||||
@@ -775,13 +879,9 @@ function load(silent){
|
||||
|
||||
db.weeks = (Array.isArray(data.weeks) ? data.weeks : [])
|
||||
.filter(w => w && typeof w.label === 'string')
|
||||
.map(w => {
|
||||
// Felder absichern, damit alte/kaputte Dokumente nicht crashen
|
||||
if(!Array.isArray(w.people)) w.people = [];
|
||||
if(!Array.isArray(w.projects)) w.projects = [];
|
||||
if(!w.attendance) w.attendance = {};
|
||||
return w;
|
||||
});
|
||||
.map(wocheAbsichern);
|
||||
// Alle Sitzungen schlank (Name, Datum, Sperre) — auch die nicht geladenen.
|
||||
db.wochenListe = Array.isArray(data.wochenListe) ? data.wochenListe : db.weeks.map(sitzungKurz);
|
||||
|
||||
// Server-Stand als Basis für späteres Zusammenführen merken.
|
||||
wochenBasis.clear();
|
||||
|
||||
Reference in new issue
Block a user