Companion-App: finale Action-Card-Grafiken eingebunden (29/30)
- 29 PNGs als app/cards/s<service>-c<change>.png (PNG-Nr n -> Service floor(n/5),
Change n%5). Karten-Screen zeigt jetzt die finale Grafik statt Text.
- Helfer cardImg()/cardMedia(); Text-Fallback fuer die noch fehlende Karte
s0-c0 ("Open Source von oben!").
- Service Worker cacht die Karten-Grafiken vorab (Offline), CACHE -> v2.
- README-Umsetzungsstand ergaenzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
@ -6,7 +6,9 @@
|
||||||
> (offline-/kioskfähig). Sie führt den kompletten Flow durch (Action Card →
|
> (offline-/kioskfähig). Sie führt den kompletten Flow durch (Action Card →
|
||||||
> Startpunkt → optionale Tour → Station: Diskussion/Quiz/Auflösung → Debrief mit
|
> Startpunkt → optionale Tour → Station: Diskussion/Quiz/Auflösung → Debrief mit
|
||||||
> **Markdown-/JSON-Export**). Inhalte (40 Stationen, 45 Quizfragen, 6 Use-Cases)
|
> **Markdown-/JSON-Export**). Inhalte (40 Stationen, 45 Quizfragen, 6 Use-Cases)
|
||||||
> sind derzeit in `app/index.html` eingebettet. **Deployment:** statisch, siehe
|
> sind derzeit in `app/index.html` eingebettet. Die **finalen Action-Card-Grafiken**
|
||||||
|
> (Freiburg-digital-Layout) liegen in `app/cards/` (`s<service>-c<change>.png`, 29/30 —
|
||||||
|
> `s0-c0` „Open Source von oben!" fehlt noch → Text-Fallback). **Deployment:** statisch, siehe
|
||||||
> [`app/DEPLOY.md`](app/DEPLOY.md). **Lokal testen:** `python -m http.server 8099
|
> [`app/DEPLOY.md`](app/DEPLOY.md). **Lokal testen:** `python -m http.server 8099
|
||||||
> --directory 04_Tablet-Quiz/app` (oder Preview-Config `.claude/launch.json`).
|
> --directory 04_Tablet-Quiz/app` (oder Preview-Config `.claude/launch.json`).
|
||||||
|
|
||||||
|
|
|
||||||
BIN
04_Tablet-Quiz/app/cards/s0-c1.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
04_Tablet-Quiz/app/cards/s0-c2.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
04_Tablet-Quiz/app/cards/s0-c3.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
04_Tablet-Quiz/app/cards/s0-c4.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
04_Tablet-Quiz/app/cards/s1-c0.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
04_Tablet-Quiz/app/cards/s1-c1.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
04_Tablet-Quiz/app/cards/s1-c2.png
Normal file
|
After Width: | Height: | Size: 201 KiB |
BIN
04_Tablet-Quiz/app/cards/s1-c3.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
04_Tablet-Quiz/app/cards/s1-c4.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
04_Tablet-Quiz/app/cards/s2-c0.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
04_Tablet-Quiz/app/cards/s2-c1.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
04_Tablet-Quiz/app/cards/s2-c2.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
04_Tablet-Quiz/app/cards/s2-c3.png
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
04_Tablet-Quiz/app/cards/s2-c4.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
04_Tablet-Quiz/app/cards/s3-c0.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
04_Tablet-Quiz/app/cards/s3-c1.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
04_Tablet-Quiz/app/cards/s3-c2.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
04_Tablet-Quiz/app/cards/s3-c3.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
04_Tablet-Quiz/app/cards/s3-c4.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
04_Tablet-Quiz/app/cards/s4-c0.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
04_Tablet-Quiz/app/cards/s4-c1.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
04_Tablet-Quiz/app/cards/s4-c2.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
04_Tablet-Quiz/app/cards/s4-c3.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
04_Tablet-Quiz/app/cards/s4-c4.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
04_Tablet-Quiz/app/cards/s5-c0.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
04_Tablet-Quiz/app/cards/s5-c1.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
04_Tablet-Quiz/app/cards/s5-c2.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
04_Tablet-Quiz/app/cards/s5-c3.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
04_Tablet-Quiz/app/cards/s5-c4.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
|
|
@ -843,6 +843,13 @@ function cardHtml(si, ci){ const c = acard(si, ci);
|
||||||
return `<div style="font-weight:800;font-size:18px;color:var(--ink);margin-bottom:6px">${c.titel}</div>`
|
return `<div style="font-weight:800;font-size:18px;color:var(--ink);margin-bottom:6px">${c.titel}</div>`
|
||||||
+ `<div>${c.text}</div>`
|
+ `<div>${c.text}</div>`
|
||||||
+ `<div style="color:var(--muted);font-style:italic;margin-top:8px">Was passiert an welchen Stellen?</div>`; }
|
+ `<div style="color:var(--muted);font-style:italic;margin-top:8px">Was passiert an welchen Stellen?</div>`; }
|
||||||
|
// Finale Action-Card-Grafik (cards/s<service>-c<change>.png). Eine fehlt noch
|
||||||
|
// (s0-c0 "Open Source von oben!") -> Text-Fallback.
|
||||||
|
function cardImg(si, ci){ return (si===0 && ci===0) ? null : `cards/s${si}-c${ci}.png`; }
|
||||||
|
function cardMedia(si, ci){ const f = cardImg(si, ci);
|
||||||
|
return f ? `<img class="acImg" src="${f}" alt="Action Card: ${acard(si,ci).titel}"
|
||||||
|
style="display:block;width:100%;max-width:300px;margin:6px auto;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,.12)">`
|
||||||
|
: cardHtml(si, ci); }
|
||||||
|
|
||||||
/* ====================== RENDER: SIDEBAR ====================== */
|
/* ====================== RENDER: SIDEBAR ====================== */
|
||||||
function renderList(){
|
function renderList(){
|
||||||
|
|
@ -897,7 +904,7 @@ function renderCardScreen(){
|
||||||
<label>Service<select id="serviceSel"></select></label>
|
<label>Service<select id="serviceSel"></select></label>
|
||||||
<label>Change-Typ<select id="changeSel"></select></label>
|
<label>Change-Typ<select id="changeSel"></select></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="ctText" id="cardTrigger">${cardHtml(S.service,S.change)}</div>
|
<div class="ctText" id="cardTrigger">${cardMedia(S.service,S.change)}</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="ghost" id="randomCard">🎲 Zufällig ziehen</button>
|
<button class="ghost" id="randomCard">🎲 Zufällig ziehen</button>
|
||||||
<button class="ghost" id="tourBtn">📘 Geführtes Beispiel</button>
|
<button class="ghost" id="tourBtn">📘 Geführtes Beispiel</button>
|
||||||
|
|
@ -909,7 +916,7 @@ function renderCardScreen(){
|
||||||
svc.innerHTML = USE_CASES.map((u,i)=>`<option value="${i}">${u.service}</option>`).join("");
|
svc.innerHTML = USE_CASES.map((u,i)=>`<option value="${i}">${u.service}</option>`).join("");
|
||||||
ch.innerHTML = CHANGE_TYPES.map((c,i)=>`<option value="${i}">${c}</option>`).join("");
|
ch.innerHTML = CHANGE_TYPES.map((c,i)=>`<option value="${i}">${c}</option>`).join("");
|
||||||
svc.value=S.service; ch.value=S.change;
|
svc.value=S.service; ch.value=S.change;
|
||||||
const refresh=()=>{ $("#cardTrigger").innerHTML=cardHtml(S.service,S.change); };
|
const refresh=()=>{ $("#cardTrigger").innerHTML=cardMedia(S.service,S.change); };
|
||||||
svc.onchange=()=>{ S.service=+svc.value; save(); refresh(); };
|
svc.onchange=()=>{ S.service=+svc.value; save(); refresh(); };
|
||||||
ch.onchange=()=>{ S.change=+ch.value; save(); refresh(); };
|
ch.onchange=()=>{ S.change=+ch.value; save(); refresh(); };
|
||||||
$("#randomCard").onclick=()=>{ S.service=Math.floor(Math.random()*USE_CASES.length); S.change=Math.floor(Math.random()*CHANGE_TYPES.length); save(); draw(); };
|
$("#randomCard").onclick=()=>{ S.service=Math.floor(Math.random()*USE_CASES.length); S.change=Math.floor(Math.random()*CHANGE_TYPES.length); save(); draw(); };
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
/* Service Worker — SLC-Workshop Companion (App-Shell, offline-first) */
|
/* Service Worker — SLC-Workshop Companion (App-Shell, offline-first) */
|
||||||
const CACHE = "slc-companion-v1";
|
const CACHE = "slc-companion-v2";
|
||||||
const ASSETS = ["./", "index.html", "manifest.webmanifest", "icon.svg"];
|
const SHELL = ["./", "index.html", "manifest.webmanifest", "icon.svg"];
|
||||||
|
// Action-Card-Grafiken (cards/s<service>-c<change>.png) fuer Offline vorab cachen.
|
||||||
|
const CARDS = [];
|
||||||
|
for (let s = 0; s <= 5; s++) for (let c = 0; c <= 4; c++) {
|
||||||
|
if (s === 0 && c === 0) continue; // s0-c0 fehlt (Text-Fallback)
|
||||||
|
CARDS.push(`cards/s${s}-c${c}.png`);
|
||||||
|
}
|
||||||
|
const ASSETS = SHELL.concat(CARDS);
|
||||||
|
|
||||||
self.addEventListener("install", (e) => {
|
self.addEventListener("install", (e) => {
|
||||||
e.waitUntil(
|
e.waitUntil(
|
||||||
|
|
|
||||||