From 32c2556ec9255862dd56a7a5d3c2ea7772526310 Mon Sep 17 00:00:00 2001 From: breitenbach76 Date: Tue, 9 Jun 2026 00:13:53 +0200 Subject: [PATCH] v16 --- 04_Tablet-Quiz/app/index.html | 266 +++++++++++++++++++++++++++++----- 04_Tablet-Quiz/app/sw.js | 2 +- PROJEKTSTAND.md | 30 +++- 3 files changed, 254 insertions(+), 44 deletions(-) diff --git a/04_Tablet-Quiz/app/index.html b/04_Tablet-Quiz/app/index.html index 397e01a..3253a08 100644 --- a/04_Tablet-Quiz/app/index.html +++ b/04_Tablet-Quiz/app/index.html @@ -253,6 +253,14 @@ .deckCard:hover{transform:translateY(-2px);box-shadow:0 4px 14px rgba(0,0,0,.16)} .deckCard img{display:block;width:100%;height:auto} .cardThumb{display:block;width:150px;border-radius:8px;margin:0 auto 14px;box-shadow:0 2px 10px rgba(0,0,0,.12)} + .deckRow.mainRow,.deckRow.bonusRow{grid-template-columns:repeat(3,1fr)} + .deckCard{position:relative} + .deckCard.mainCard,.deckCard.bonusCard{display:flex;flex-direction:column} + .deckMeta{padding:8px 10px;text-align:left} + .deckMeta b{display:block;font-size:14px;color:var(--ink);line-height:1.25} + .deckMeta span{display:block;font-size:11px;color:var(--muted);margin-top:2px} + .deckCard.svcDone{opacity:.6} + .svcBadge{position:absolute;top:8px;right:8px;background:var(--ok);color:#fff;font-size:11px;font-weight:700;padding:2px 8px;border-radius:999px} .choiceGrid{display:flex;flex-direction:column;gap:8px;margin:10px 0} .choiceGrid.grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:10px} @media(max-width:440px){.choiceGrid.grid2{grid-template-columns:1fr}} @@ -288,7 +296,7 @@
SLC Companion
- v0.6 + v0.7
@@ -415,7 +423,7 @@ const CHANGE_LEGEND = [ "VollstĂ€ndige Bewertung, Business Case, ausfĂŒhrliche Planung & Tests, Kommunikationsplan", "DurchlĂ€uft den vollen Lebenszyklus ab dem Design (alle Gates)"], bsp:"Rechenzentrumsumzug, Austausch eines Kernsystems, organisationsweite Plattformmigration." }, - { idee:"Der Regelfall fĂŒr alles, was nicht vorab genehmigt ist und kein Notfall ist. DurchlĂ€uft den Bewertungs- und Gate-Prozess.", + { idee:"Der Regelfall fĂŒr alles, was nicht vorab genehmigt ist und kein Notfall ist. DurchlĂ€uft einen strukturierten Bewertungs- und Freigabeprozess.", bed:["Änderungsantrag (RfC) wird erfasst", "Risiko- und Impact-Bewertung wird durchgefĂŒhrt", "Freigabe an den Gates durch die SOR (Gate 2 durch den Service Owner) vor Umsetzung", @@ -436,6 +444,37 @@ const CHANGE_LEGEND = [ ]; // Anzeige-Reihenfolge der Change-Arten (Indizes in CHANGE_TYPES): Standard, Emergency, Normal, Major const CT_ORDER = [2, 3, 1, 0]; + +/* Aufgabe 2: Wo wird der Change freigegeben? (Cluster nach Frank; Index parallel zu CHANGE_TYPES) */ +const FREIGABE_OPTIONS = [ + "SOR / DPM / Mission Board", + "Service Owner (SO)", + "Keine Freigabe — Standard (vorab genehmigt)", + "Keine Freigabe — Emergency (nachgelagert)" +]; +const FREIGABE_ORDER = [0, 1, 2, 3]; +const FREIGABE_CORRECT = [0, 1, 2, 3]; // Major→SOR/DPM/MB · Normal→SO · Standard→keine · Emergency→keine +const FREIGABE_GRUND = [ + "Ein Major Change wird in der SOR freigegeben. Reicht deren Ressourcen- und Entscheidungshoheit nicht, wird daraus ein Demand — ĂŒber den DPM ans Mission Board.", + "Ein Normal Change wird vom Service Owner freigegeben und umgesetzt; er berĂŒhrt die SOR nicht (kein Gate 3).", + "Ein Standard Change ist ĂŒber den Standard-Change-Katalog generell vorab autorisiert — keine Einzelfreigabe nötig.", + "Ein Emergency Change wird sofort umgesetzt; die formale Freigabe (Gate 3 / SOR) erfolgt nachgelagert zur Dokumentation." +]; + +/* Bonus-Karten: Service ist bereits live. Welche Phasen sind fĂŒr diese Change-Art + noch relevant — und welche fallen weg? (Index parallel zu CHANGE_TYPES; 0/Major ungenutzt) */ +const BONUS_AUFLOESUNG = [ + null, + { relevant:["Transition (verkĂŒrzt, meist Konfiguration)","Operation"], + wegfall:["Design (Service existiert bereits)","voller Review"], + text:"Der Service lĂ€uft schon — ein neues Design entfĂ€llt. Der Normal Change steigt in der Transition ein (meist der Konfigurationspfad), wird vom Service Owner freigegeben (Gate 2) und geht zurĂŒck in den Betrieb. Ein kompletter Review-Durchlauf ist fĂŒr diese ĂŒberschaubare Änderung nicht nötig." }, + { relevant:["Operation (laufender Betrieb)"], + wegfall:["Design","Transition & Gates","Review"], + text:"Ein Standard Change ist ĂŒber den Katalog vorab autorisiert. Er wird direkt im laufenden Betrieb umgesetzt — keine Design- oder Transition-Phase, keine Gate-Freigabe, kein Review." }, + { relevant:["beschleunigte Umsetzung / Deployment","Operation & Support","nachgelagerte Freigabe + Doku"], + wegfall:["Design","regulĂ€re Vorab-Freigabe an den Gates"], + text:"Beim Emergency Change zĂ€hlt Tempo: Der Fix wird sofort ausgerollt, um die Störung zu beheben. Die formale Freigabe (Gate 3 / SOR) und die Dokumentation erfolgen nachgelagert; danach geht der Service in den normalen Betrieb zurĂŒck." } +]; // Feste, EINMALIG gemischte Deck-Reihenfolge ([service, change]) — bei jedem Start gleich, nicht gruppiert. const DECK_ORDER = [[2,1],[0,3],[4,0],[1,2],[5,3],[3,0],[0,1],[2,3],[4,2],[1,0],[5,1],[3,2], [2,0],[0,2],[4,3],[1,3],[5,0],[3,1],[2,2],[0,0],[4,1],[1,1],[5,2],[3,3]]; @@ -445,7 +484,7 @@ const USE_CASES = [ changes:[ {titel:"Open Source von oben!", text:"Der OB gibt die Richtung vor: Die proprietĂ€re VDI-Lösung soll auf eine Open-Source-Alternative (OpenStack + Thin-Client) umgestellt werden."}, {titel:"Tapetenwechsel", text:"Die Stadt bekommt ein neues Logo — der Desktop-Hintergrund aller virtuellen ArbeitsplĂ€tze muss angepasst werden."}, - {titel:"Quartalspflege", text:"Das turnusmĂ€ĂŸige Firmware-Update der VDI-Host-Hypervisoren steht an — im Standard-Change-Katalog lĂ€ngst hinterlegt."}, + {titel:"Quartalspflege", text:"Das turnusmĂ€ĂŸige Firmware-Update der VDI-Host-Hypervisoren steht an."}, {titel:"Blackout!", text:"Ein Stromausfall reißt ein ganzes VDI-Host-Cluster aus dem Betrieb — die Sitzungen mĂŒssen sofort auf ein Backup-Cluster migriert werden."} ]}, { service:"Managed VPN-Access Service", @@ -453,7 +492,7 @@ const USE_CASES = [ changes:[ {titel:"BrĂŒssel ruft!", text:"Eine neue EU-weite IT-Sicherheitsverordnung zwingt dazu, die gesamte VPN-Architektur neu aufzustellen."}, {titel:"Heimvorteil", text:"Ein neues Intranet-Portal soll in die Split-Tunnel-Liste, damit Mitarbeitende auch aus dem Homeoffice darauf zugreifen."}, - {titel:"Monatsroutine", text:"Das monatliche Firmware-Update der VPN-Appliance steht an — als Standard-Change bereits freigegeben."}, + {titel:"Monatsroutine", text:"Das monatliche Firmware-Update der VPN-Appliance steht an."}, {titel:"Gephisht!", text:"Ein erfolgreicher Phishing-Angriff hat eine VPN-Zertifikatskette kompromittiert — sofort sperren und neu ausstellen."} ]}, { service:"Online-BĂŒrgerportal fĂŒr Meldungen & AntrĂ€ge", @@ -461,7 +500,7 @@ const USE_CASES = [ changes:[ {titel:"Mitreden, Pflicht!", text:"Ein neues Landesgesetz schreibt digitale BĂŒrgerbeteiligung vor — das Portal muss um komplette Beteiligungs-Module erweitert werden."}, {titel:"Rotstift gefragt", text:"Der BĂŒrgerservice meldet einen Rechtschreibfehler in einem statischen Hinweistext, der korrigiert werden muss."}, - {titel:"Patchday", text:"Das monatliche Sicherheits-Patch des Webservers (Apache/Nginx) steht an — im Change-Katalog definiert."}, + {titel:"Patchday", text:"Das monatliche Sicherheits-Patch des Webservers (Apache/Nginx) steht an."}, {titel:"LĂŒcke im Formular!", text:"In einem Eingabe-Formular wird eine kritische XSS-Schwachstelle entdeckt — ein Hotfix muss sofort raus."} ]}, { service:"Zentrales Dokumenten-Management-System (DMS)", @@ -477,7 +516,7 @@ const USE_CASES = [ changes:[ {titel:"Norm-Zwang", text:"Eine bundesweite Vorgabe zu EU-Standards erzwingt die komplette Migration des GIS-Stacks auf konforme Services und Datenmodelle."}, {titel:"Falsch beschriftet", text:"Das Bauamt meldet eine falsche Beschriftung eines Karten-Layers, die korrigiert werden muss."}, - {titel:"GeoServer-Update", text:"Das monatliche Update der GIS-Software (GeoServer 2.23 → 2.24) steht an — im Standard-Change-Katalog."}, + {titel:"GeoServer-Update", text:"Das monatliche Update der GIS-Software (GeoServer 2.23 → 2.24) steht an."}, {titel:"Schnittstelle offen!", text:"An einer Schnittstelle wird eine kritische Schwachstelle entdeckt, die unautorisierten Datenzugriff erlaubt — Dienst sofort abschalten und patchen."} ]}, { service:"Beschaffungs- und Vertrags-System fĂŒr FachĂ€mter", @@ -485,7 +524,7 @@ const USE_CASES = [ changes:[ {titel:"Vergabe neu!", text:"Eine neue EU-Vergaberichtlinie zwingt zur EinfĂŒhrung von E-Invoicing und erweiterten Transparenz-Reports."}, {titel:"Vierstellig, bitte", text:"Das Finanzamt wĂŒnscht eine kleine Anpassung: aus dem Label „Kostenstelle“ wird „Kostenstelle (4-stellig)“."}, - {titel:"Patch-Quartal", text:"Das quartalsweise Sicherheits-Patch des Anwendungsservers steht an — bereits im Change-Katalog."}, + {titel:"Patch-Quartal", text:"Das quartalsweise Sicherheits-Patch des Anwendungsservers steht an."}, {titel:"Upload-Falle!", text:"Im Vertrags-Upload wird eine kritische LĂŒcke entdeckt, ĂŒber die sich Schadcode hochladen lĂ€sst — Endpoint sofort sperren, Hotfix einspielen."} ]} ]; @@ -1056,9 +1095,11 @@ function seedAkte(entryIdx){ /* ====================== STATE ====================== */ const LS_KEY = "slc-companion-proto"; function defaultState(){ - return { view:"deck", service:null, change:null, + return { view:"deck", mode:"main", service:null, change:null, classifyDone:false, classifyWrong:null, + freigabeDone:false, freigabeWrong:null, entryDone:false, entryWrong:null, + bonusReveal:false, bonusDone:{}, servicesDone:{}, index:0, stage:"discuss", quizIndex:0, actStep:0, actReveal:false, actDone:false, arteWrong:null, picks:{}, done:{}, akte:{}, @@ -1157,10 +1198,13 @@ function draw(){ document.body.classList.toggle("runMode", S.view==="run"); if(S.view!=="run"){ document.body.classList.remove("navOpen","akteOpen","rollenOpen"); } renderCardBadge(); - if(S.view==="deck") return renderDeck(); - if(S.view==="classify") return renderClassify(); - if(S.view==="entry") return renderEntry(); - if(S.view==="end") return renderEnd(); + if(S.view==="deck") return renderDeck(); + if(S.view==="classify") return renderClassify(); + if(S.view==="freigabe") return renderFreigabe(); + if(S.view==="entry") return renderEntry(); + if(S.view==="bonusPick") return renderBonusPick(); + if(S.view==="bonus") return renderBonus(); + if(S.view==="end") return renderEnd(); renderRun(); } @@ -1174,19 +1218,25 @@ function renderCardBadge(){ /* ---------- Schritt 1: Action Card ziehen (Raster aller Karten) ---------- */ function renderDeck(){ - const cards = DECK_ORDER.map(([si,ci])=>{ - const c = USE_CASES[si].changes[ci]; - return ``; + const cards = USE_CASES.map((u,si)=>{ + const c = u.changes[0]; + const done = S.servicesDone && S.servicesDone[si]; + return ``; }).join(""); $("#panel").innerHTML = ` -
Schritt 1 · Action Card ziehen
-

Welche Karte habt ihr gezogen?

-

Tippt auf die Action Card, die ihr gezogen habt.

-
${cards}
`; +
Schritt 1 · Service wÀhlen (Main Action Card)
+

Welchen Service fĂŒhrt ihr ein?

+

Jede Main-Karte ist ein Major Change — ihr spielt den Service einmal komplett von Design bis Review durch. Die Varianten (Bonus-Karten) kommen danach.

+
${cards}
`; $("#panel").querySelectorAll(".deckCard").forEach(el=>{ - el.onclick=()=>{ S.service=+el.dataset.s; S.change=+el.dataset.c; - S.classifyDone=false; S.classifyWrong=null; S.entryDone=false; S.entryWrong=null; + el.onclick=()=>{ S.service=+el.dataset.s; S.change=0; S.mode="main"; + S.classifyDone=false; S.classifyWrong=null; + S.freigabeDone=false; S.freigabeWrong=null; + S.entryDone=false; S.entryWrong=null; S.bonusDone={}; S.view="classify"; save(); draw(); }; }); } @@ -1204,7 +1254,7 @@ function renderClassify(){ const hint = S.classifyWrong!=null ? `
Nicht ganz — ĂŒberlegt nochmal und probiert es erneut.
` : ``; $("#panel").innerHTML = ` -
Schritt 2 · Change-Art bestimmen
+
Aufgabe 1 · Change-Art bestimmen
${cardBig}
@@ -1224,7 +1274,7 @@ function renderClassify(){ $("#backDeck").onclick=()=>{ S.view="deck"; save(); draw(); }; } else { $("#panel").innerHTML = ` -
Schritt 3 · Erfolgreiche Kategorisierung
+
Aufgabe 1 · Change-Art ✓
${cardBig}
@@ -1238,14 +1288,64 @@ function renderClassify(){
- +
`; $("#backDeck").onclick=()=>{ S.view="deck"; save(); draw(); }; + $("#toFreigabe").onclick=()=>{ S.view="freigabe"; S.freigabeDone=false; S.freigabeWrong=null; save(); draw(); }; + } +} + +/* ---------- Aufgabe 2: Freigabe-Stelle bestimmen (retry bis richtig) ----- */ +function renderFreigabe(){ + const correct = FREIGABE_CORRECT[S.change]; + const card = acard(S.service,S.change); + const cardBig = `${card.titel}`; + if(!S.freigabeDone){ + const choices = FREIGABE_ORDER.map(i=> + ``).join(""); + const hint = S.freigabeWrong!=null + ? `
Nicht ganz — ĂŒberlegt, wer diese Change-Art freigeben darf, und probiert es erneut.
` : ``; + $("#panel").innerHTML = ` +
Aufgabe 2 · Freigabe bestimmen
+
+ ${cardBig} +
+
Change-Art: ${CHANGE_TYPES[S.change]}
+

An welcher Stelle wird dieser Change freigegeben?

+

Überlegt gemeinsam, wer ĂŒber diese Change-Art entscheidet.

+ ${hint} +
${choices}
+
+
+
`; + $("#panel").querySelectorAll(".choice").forEach(el=>{ + el.onclick=()=>{ const i=+el.dataset.i; + if(i===correct){ S.freigabeWrong=null; S.freigabeDone=true; } else { S.freigabeWrong=i; } + save(); renderFreigabe(); }; + }); + $("#backClassify").onclick=()=>{ S.view="classify"; save(); draw(); }; + } else { + $("#panel").innerHTML = ` +
Aufgabe 2 · Freigabe ✓
+
+ ${cardBig} +
+
✓ Freigabe: ${FREIGABE_OPTIONS[correct]}
+

Warum?

+

${FREIGABE_GRUND[correct]}

+
+
+
+ +
+ +
`; + $("#backClassify").onclick=()=>{ S.view="classify"; save(); draw(); }; $("#toEntry").onclick=()=>{ S.view="entry"; S.entryDone=false; S.entryWrong=null; save(); draw(); }; } } -/* ---------- Schritt 4+5: Einstieg finden (Phase anklicken) -------------- */ +/* ---------- Aufgabe 3: Einstieg finden (Phase anklicken) ---------------- */ function renderEntry(){ const rec = START_EMPFEHLUNG[S.change]; const recIndex = STATIONEN.findIndex(s=>s.id===rec.id); @@ -1259,27 +1359,31 @@ function renderEntry(){ const hint = S.entryWrong ? `
Diese Phase passt nicht zur Change-Art — denkt an die Definition und probiert es erneut.
` : ``; $("#panel").innerHTML = ` -
Schritt 4 · Einstieg finden
+
Aufgabe 3 · Einstieg finden
${cardBig}
-
Change-Art: ${CHANGE_TYPES[S.change]}
-

In welcher Phase startet dieser Change?

-

Klickt auf die Lebenszyklus-Phase, in der dieser Change einsteigt.

+
Change-Art: ${CHANGE_TYPES[S.change]} · Freigabe: ${FREIGABE_OPTIONS[FREIGABE_CORRECT[S.change]]}
+

Wo wĂŒrde die Umsetzung starten — nachdem der Change freigegeben ist?

+

Klickt auf die Lebenszyklus-Phase, in der die Umsetzung beginnt.

${hint}
${zones}
-
`; +
`; $("#panel").querySelectorAll(".phaseZone").forEach(el=>{ el.onclick=()=>{ const ph=el.dataset.ph; if(ph===correctPhase){ S.entryWrong=null; S.entryDone=true; } else { S.entryWrong=ph; } save(); renderEntry(); }; }); - $("#backClassify").onclick=()=>{ S.view="classify"; save(); draw(); }; + $("#backFreigabe").onclick=()=>{ S.view="freigabe"; save(); draw(); }; } else { + const isBonus = S.mode==="bonus"; + const startBtn = isBonus + ? `` + : ``; $("#panel").innerHTML = ` -
Schritt 5 · Los geht's
+
${isBonus?'Aufgabe 3 · Einstieg ✓':"Los geht's"}
${cardBig}
@@ -1290,15 +1394,99 @@ function renderEntry(){
- +
- + ${startBtn}
`; - $("#backClassify").onclick=()=>{ S.view="classify"; save(); draw(); }; - $("#startRun").onclick=()=>{ seedAkte(recIndex); enterStation(recIndex); S.view="run"; save(); draw(); }; + $("#backFreigabe").onclick=()=>{ S.view="freigabe"; save(); draw(); }; + const sr = $("#startRun"); if(sr) sr.onclick=()=>{ seedAkte(recIndex); enterStation(recIndex); S.view="run"; save(); draw(); }; + const tb = $("#toBonusDisc"); if(tb) tb.onclick=()=>{ S.bonusReveal=false; S.view="bonus"; save(); draw(); }; } } +/* ---------- Bonus-Auswahl: Varianten des bereits live gegangenen Service - */ +function renderBonusPick(){ + const u = USE_CASES[S.service]; + const order = [2,3,1]; // Standard, Emergency, Normal (Major war die Main-Karte) + const cards = order.map(ci=>{ + const c = u.changes[ci]; + const done = S.bonusDone && S.bonusDone[ci]; + return ``; + }).join(""); + const allDone = order.every(ci => S.bonusDone && S.bonusDone[ci]); + $("#panel").innerHTML = ` +
Bonus · Varianten · ${u.service}
+

Der Service lĂ€uft jetzt — welche Änderungen kommen im Betrieb?

+

Diese drei Varianten betreffen den bereits eingefĂŒhrten Service. Sie werden nicht komplett durchgespielt — ihr bestimmt nur Change-Art, Freigabe und Einstieg und besprecht, welche Phasen noch relevant sind.

+
${cards}
+
+ +
+ +
`; + $("#panel").querySelectorAll(".bonusCard").forEach(el=>{ + el.onclick=()=>{ S.change=+el.dataset.c; S.mode="bonus"; + S.classifyDone=false; S.classifyWrong=null; + S.freigabeDone=false; S.freigabeWrong=null; + S.entryDone=false; S.entryWrong=null; S.bonusReveal=false; + S.view="classify"; save(); draw(); }; + }); + $("#bonusToDeck").onclick=()=>{ S.view="deck"; save(); draw(); }; + $("#bonusFinish").onclick=()=>{ (S.servicesDone=S.servicesDone||{})[S.service]=true; S.view="deck"; save(); draw(); }; +} + +/* ---------- Bonus-Diskussion + Auflösung -------------------------------- */ +function renderBonus(){ + const a = BONUS_AUFLOESUNG[S.change] || {relevant:[],wegfall:[],text:""}; + const card = acard(S.service,S.change); + const cardBig = `${card.titel}`; + const correctPhase = STATIONEN[STATIONEN.findIndex(s=>s.id===START_EMPFEHLUNG[S.change].id)].phase; + let body; + if(!S.bonusReveal){ + body = ` +
+
Diskussion
+ Der Service ${USE_CASES[S.service].service} lĂ€uft bereits. Diskutiert gemeinsam: + Welche Phasen und AktivitĂ€ten wĂ€ren fĂŒr diesen ${CHANGE_TYPES[S.change]} noch relevant — und welche fallen weg? +
+
+ +
+ +
`; + } else { + const rel = (a.relevant||[]).map(x=>`
  • ${x}
  • `).join(""); + const weg = (a.wegfall||[]).map(x=>`
  • ${x}
  • `).join(""); + body = ` +
    +

    Relevant

      ${rel}
    +

    FĂ€llt weg

      ${weg}
    +

    ${a.text}

    +
    +
    + +
    + +
    `; + } + $("#panel").innerHTML = ` +
    Bonus · ${CHANGE_TYPES[S.change]}
    +
    + ${cardBig} +
    +
    Change-Art: ${CHANGE_TYPES[S.change]} · Freigabe: ${FREIGABE_OPTIONS[FREIGABE_CORRECT[S.change]]} · Einstieg: ${PHASEN[correctPhase].label}
    + ${body} +
    +
    `; + const bb=$("#bonusBack"); if(bb) bb.onclick=()=>{ if(S.bonusReveal){ S.bonusReveal=false; } else { S.view="entry"; } save(); draw(); }; + const br=$("#bonusRevealBtn"); if(br) br.onclick=()=>{ S.bonusReveal=true; save(); draw(); }; + const bd=$("#bonusDoneBtn"); if(bd) bd.onclick=()=>{ (S.bonusDone=S.bonusDone||{})[S.change]=true; S.view="bonusPick"; save(); draw(); }; +} + /* ====================== RENDER: RUN (Station) ====================== */ const GATE_FLOW = { tr_01: ["next","tr_05"], // Entwicklung / Konfiguration (Konfig ueberspringt Build) @@ -1612,9 +1800,9 @@ function renderEnd(){ ${box}
    - +
    `; - $("#endRestart").onclick = ()=>{ S = defaultState(); save(); draw(); }; + $("#toBonus").onclick = ()=>{ S.view="bonusPick"; save(); draw(); }; } /* ====================== INIT ====================== */ diff --git a/04_Tablet-Quiz/app/sw.js b/04_Tablet-Quiz/app/sw.js index 65ebede..c818a76 100644 --- a/04_Tablet-Quiz/app/sw.js +++ b/04_Tablet-Quiz/app/sw.js @@ -1,5 +1,5 @@ /* Service Worker — SLC-Workshop Companion (App-Shell, offline-first) */ -const CACHE = "slc-companion-v18"; +const CACHE = "slc-companion-v19"; const SHELL = ["./", "index.html", "manifest.webmanifest", "icon.svg"]; // Action-Card-Grafiken (cards/s-c.png) fuer Offline vorab cachen (alle 30). const CARDS = []; diff --git a/PROJEKTSTAND.md b/PROJEKTSTAND.md index d728d7b..70b6a33 100644 --- a/PROJEKTSTAND.md +++ b/PROJEKTSTAND.md @@ -4,7 +4,7 @@ Chat). Hier steht, **wo wir stehen, was entschieden wurde, was offen ist** und wie man App lokal startet/deployt. -**Stand:** 2026-06-06 · **Branch:** `feat/redesign-und-companion-app` · **HEAD:** `3647129` +**Stand:** 2026-06-09 · **Branch:** `feat/redesign-und-companion-app` · App **v0.7** **Remote:** `https://git.1789.cloud/patrick/SLC_Game.git` --- @@ -51,9 +51,16 @@ Operations/Service-Owner/Support. Mix aus **Vermittlung** (Lifecycle + Stationen keine Gate-Karte mehr**. ### Companion-App (`04_Tablet-Quiz/app/`) — statische PWA -**Flow:** Karten-Raster (Action Card ziehen) → **Change-Art klassifizieren** (Legende, -„nochmal" bis richtig) → **Phasen-Einstieg** (Lebenszyklus-Phase anklicken, retry) → -**Stationen** → **Abschluss-Screen** („abgeschlossen" oder „abgelehnt"). +**Flow (v0.7 · Main/Bonus, nach Frank-Feedback):** Das Deck zeigt **nur die 6 Main-Karten** +(= Major je Service). Main ziehen → **3 Aufgaben** (1. Change-Art · 2. **Freigabe-Stelle**: +SOR/DPM/MB · SO · keine[Standard] · keine[Emergency] · 3. Einstieg-Phase; je „nochmal" bis +richtig) → **voller Stationen-Durchlauf** → Abschluss → **Bonus-Auswahl** (die 3 Varianten +dieses Service: Standard/Emergency/Normal). Bonus-Karte: dieselben 3 Aufgaben, danach +**Kurz-Auflösung** „welche Phasen sind noch relevant / fallen weg" — **kein voller Walk** +(Service gilt als bereits eingefĂŒhrt) → zurĂŒck zur Bonus-Auswahl → „Service abschließen" +→ nĂ€chster Service (gespielte Services im Deck als ✓ markiert). +> Hintergrund: Nur der **Major** rechtfertigt den vollen SLC; die anderen Change-Arten +> werden nur eingeordnet (Franks Kritik am „kĂŒnstlichen" Durchspielen jeder Karte). - **AktivitĂ€ts-Station, schrittweiser Mikro-Ablauf** (4 Fragen, je einzeln + Auflösung): (1) Was steckt hinter der Überschrift? (2) Beteiligte Rollen → Figuren auf die **Puck-Mulden**; (3) **RACI** → Figuren ins **Aktiv-Feld (R·A·C·I)** (mit RACI-Legende); @@ -96,6 +103,21 @@ Konzept (`00_Konzept/README_konzept.md`), bis RĂŒckkopplung mit Michael:** - Details/Quelle: `00_Konzept/review-phase_arbeitsstand-frank.md`. ## 5. Offene Punkte / nĂ€chste Schritte + +**Frank-Feedback 2026-06-08 (Workshop-Ebene, entscheiden Frank + Patrick):** +- [x] **Main/Bonus-Flow** umgesetzt (nur Major = voller Walk; Bonus = einordnen + Kurz-Auflösung). +- [x] **Aufgabe „Freigabe-Stelle"** ergĂ€nzt (SOR/DPM/MB · SO · keine[Standard/Emergency]). +- [x] **Normal-Legende** „strukturierter Bewertungs- und **Freigabe**prozess" (nicht „Gate-Prozess"). +- [x] **„VerrĂ€ter"-SĂ€tze** aus 5 Standard-Karten raus (Quartalspflege, Monatsroutine, Patchday, + GeoServer-Update, Patch-Quartal). +- [x] **Einstiegs-Frage** umformuliert: „Wo wĂŒrde die Umsetzung starten (nach Freigabe)?". +- [ ] **Wartet auf Frank:** 3 „Normal"-Karten (Rotstift gefragt · Vierstellig, bitte · Falsch + beschriftet) sind eigentlich **Standard** → neue **Normal**-Texte aus Franks Word ĂŒbernehmen. +- [ ] **Wartet auf Frank:** Service-Steckbrief-Beiblatt (6 Services: Was ist der Service, was der + IT-Provider-Anteil) aus Franks Inhalten. +- [ ] **KlĂ€ren (Frank + Patrick):** **Problem-Manager**-Rolle — in App vorhanden (`sp_09/sp_10`), + war Frank neu. Gewollt oder YAML-Artefakt? + - [x] **Figuren-Regel festgezurrt** (zweistufig: Puck = beteiligte Rollen, Aktiv-Feld = RACI). In der App umgesetzt. **Offen:** in `materialliste.md` / `board-layout` / `README_konzept.md` nachziehen.