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:
erikandClaude Opus 5.5 committed 2026-10-30 08:23:02 +01:00
1 parent a2266662ad
commit 4c2e04e78b
19 files changed
+1100 -139

No files matched your search

+42
View File
@@ -99,8 +99,21 @@ window.PlanApp = {
// showTab('plan') gerufen (und von dort aus auch nach jedem erneuten
// Laden, siehe load() in js/store.js). Rückgabe: true, wenn das Projekt
// gefunden und gerendert wurde.
// startAufgabe: Link mit ?aufgabe=<id> (z. B. aus einer Teams-Nachricht):
// diese Aufgabe nach dem Öffnen des Projekts gleich im Aufgaben-Panel
// zeigen — einmalig, beim ersten passenden Öffnen.
let startAufgabe = '';
try { startAufgabe = new URLSearchParams(window.location.search).get('aufgabe') || ''; } catch(e){ /* egal */ }
window.openPlanView = function(){
app.showPlanNav();
// Ein Aufgaben-Link stammt aus der Sitzung, in der zugewiesen wurde. Ist
// inzwischen eine neuere da, dort öffnen — Aufgaben behalten über den
// Sitzungswechsel ihre id (ensureCurrentWeekRollover()).
if(startAufgabe && app.weekLabel !== SANDBOX_WEEK_LABEL && Array.isArray(db.wochenListe) && db.wochenListe.length){
const juengste = db.wochenListe[db.wochenListe.length - 1].label;
if(juengste && juengste !== app.weekLabel) app.weekLabel = juengste;
}
// Planung-Sandbox: eigener, einfacherer Zweig — eine feste, reservierte
// "Sitzung" (db.sandboxWeek, nie Teil von db.weeks, siehe js/store.js)
@@ -143,6 +156,19 @@ window.PlanApp = {
}
app.week = db.weeks.find(w => w.label === app.weekLabel) || null;
if(!app.week){
// Eine ältere Sitzung, die beim Start nicht mitgeladen wurde (nur die
// jüngsten, js/store.js): einzeln nachholen und dann neu öffnen.
const bekannt = (db.wochenListe || []).some(w => w.label === app.weekLabel);
if(bekannt && typeof sitzungSicherLaden === 'function'){
const t = document.getElementById('planSubtitle');
if(t) t.textContent = 'Sitzung ' + app.weekLabel + ' wird geladen…';
const label = app.weekLabel;
sitzungSicherLaden(label).then(w => {
if(w && app.weekLabel === label && currentTab === 'plan') showTab('plan');
else if(!w) planFail('Nicht gefunden', 'Sitzung "' + label + '" konnte nicht geladen werden.');
}).catch(() => planFail('Nicht gefunden', 'Sitzung "' + label + '" konnte nicht geladen werden.'));
return false;
}
planFail('Nicht gefunden', 'Sitzung "' + app.weekLabel + '" konnte nicht geladen werden.');
return false;
}
@@ -286,6 +312,22 @@ window.PlanApp = {
// js/plan/plan-sections.js. Steht bewusst am Ende: erst wenn alle
// Bereiche befüllt sind, wird einer davon eingeblendet.
app.initPlanSections();
if(startAufgabe){
const id = startAufgabe;
startAufgabe = '';
// Adresszeile auf die tatsächlich geöffnete Sitzung bringen (der Link
// nannte evtl. eine ältere, siehe openPlanView()).
if(typeof updateRouteUrl === 'function') updateRouteUrl('plan');
const idx = (plan.todos || []).findIndex(t => String(t.id) === id);
if(idx < 0){ showToast('Die Aufgabe aus dem Link gibt es in diesem Projekt nicht mehr.'); return; }
if(location.hash !== '#aufgaben') showPlanSection('aufgaben');
// Panel erst nach dem Zeichnen öffnen (das Gantt misst seine Breite).
setTimeout(() => {
if(isLocked()){ showToast('Aufgabe: ' + (plan.todos[idx].title || '') + ' — diese Sitzung ist gesperrt.'); return; }
openTodoModal(idx);
}, 50);
}
}
// Entfernt eine gelöschte ID aus allen dependsOn-Listen (TODOs und Meilensteine)