Statusrapportering og GUI for bygg-køer
Målbildet er å gi brukerne enkel oversikt over egne og andres jobber i kø – med en kompakt statusindikator (nederst til venstre) og en hendelsesfeed (nederst til høyre) med lyd og historikk.
Observert oppførsel (utgangspunkt 2026-03-17, etter sesjon 5)
- Dialog åpen, bygg startet: «Nettsted oppdateres (N sek)…» i dialogheaderen + lydsignal ved start. Fungerer bra.
- Dialog lukket / navigert:
#qe-job-indicatorviser alltid en synlig knapp – «Byggehistorikk» i idle-tilstand, byggestatus under aktive bygg. - Klikk på indikatoren: Åpner jobbhistorikk-dialog med siste 15 bygg for innlogget bruker (GitHub Actions API).
- Ferdig bygg: Lydsignal + automatisk navigering, uavhengig av om dialogen er åpen eller lukket.
Steg 1 – Lydsignal ved ferdig bygg etter navigering ✅ FULLFØRT (2026-03-17)
Rotårsak (løst):
samtuPlaySuccess()ble aldri kalt icheckCompletions()completion-branchen._samtuAudioCtxvarnullpå ny side (opprettes kun under brukergestus på forrige side).
Implementert fix:
checkCompletions()completion-branch kaller nåsamtuPlaySuccess()+ 1800ms forsinkelse før reload._samtuPlayNotes()forsøker å opprette nyAudioContexthvis den ernull(Chrome tillater dette for origins med høy brukerengasjement).samtuShowDoneIndicator()vises alltid som visuell fallback.
Filer endret:
themes/hugo-theme-samt-bu/layouts/partials/custom-footer.html
Steg 2 – Jobbhistorikk og forbedringer ✅ FULLFØRT (2026-03-17, sesjon 5)
2a – Jobbhistorikk-knapp alltid synlig ✅
#qe-job-indicator vises nå permanent (ikke bare under aktive bygg). Idle-tilstand: klokkikon + «Byggehistorikk». Klikk åpner #job-history-dialog med siste 15 bygg for innlogget bruker hentet fra GitHub Actions API.
Implementasjonsdetaljer:
data-building="1"settes på indikatoren vedsamtuShowPendingIndicatorWithTotal(), fjernes vedsamtuShowDoneIndicator()- Bakgrunnspollen (
setIntervalhvert 45. sek) sjekkerqeInd.dataset.buildingi stedet fordisplay !== 'none'– forhindrer at alltid-synlig indikator blokkerer andres-endringer-banner samtuIncrementPending()kaller nåsamtuShowPendingIndicator(newCount)umiddelbart – indikatoren oppdateres i det du klikker Lagre, ikke først etter dialog-lukking/refresh
2b – Minimering fjernet ✅
Minimize-funksjonaliteten (qe-minimize-pill, minimizeQeDialog(), ⊟-knappen) er fjernet. Begrunnelse: pillen forsvant ved navigering og ga bare støy med dobbel status. Cancel-knappen heter igjen «Lukk dette vinduet» etter lagring.
2c – ETag-timeout økt ✅
if (++attempts > 90) → if (++attempts > 180) (3 min maks). Fikser falsk «Build job failed»-signal ved bygg som tar > 90 sek.
Filer endret (sesjon 5):
themes/hugo-theme-samt-bu/layouts/partials/custom-footer.htmlthemes/hugo-theme-samt-bu/layouts/partials/edit-switcher.html
Steg 3 – Sekundtelling, køstatus og avløst-håndtering ✅ FULLFØRT (2026-03-17, sesjon 6)
3a – Sekundtelling for kjørende jobber ✅
Kjørende jobb (status: in_progress) viser nå antall sekunder siden start (f.eks. «47 sek»). Oppdateres live hvert sekund via en re-render-timer i historikk-dialogen (ingen ny API-fetch – beregnes fra run.created_at).
3b – «I kø»-status for ventende jobber ✅
Jobber i kø (status: queued, waiting, pending, requested) viser nå:
- Klokkeikon (grå
fa-clock-o) i stedet for spinner - Teksten «I kø» i stedet for «kjører…» eller et tidsstempel
GitHub Pages-miljøet bruker waiting i tillegg til queued for jobber som venter på concurrency-gruppen. Begge (og pending/requested) behandles nå likt.
3c – Avløst-håndtering ✅
Bakgrunn: GitHub Pages kansellerer automatisk eldre jobber i kø når en nyere jobb med høyere prioritet venter («Canceling since a higher priority waiting request for pages exists»). Skjer ved 3+ raske lagringer.
Implementert:
conclusion: cancelled→ gråfa-check-circle(ikke rødfa-exclamation-circle) + teksten «Avløst»checkCompletions(): teller kansellerte som resolved, rydder hele pending-state når minst én suksess finnes og ingen aktive gjenstår – pending-teller henger aldri lengerstartGhPoll(): kansellert run trigger ikke wah-wah + feilmelding, men holder polling og venter på nytt bygg- Brukerveiledningen (om/hvordan-bidra/) oppdatert med forklaring på avløste jobber og køoppførsel
3d – Live-oppdatering av jobbhistorikk-dialog ✅
loadHistory() splittet i fetchHistory() + renderHistory(runs):
renderHistoryre-rendres hvert sekund fra cache (live elapsed-teller uten API-kall)fetchHistoryre-hentes automatisk hvert 15. sek mens dialogen er åpenopenHistory()/closeHistory()rydder timere korrekt ved åpne/lukke, ESC og klikk utenfor
Filer endret (sesjon 6):
themes/hugo-theme-samt-bu/layouts/partials/custom-footer.html
Steg 2 (opprinnelig) – Rikere statusinformasjon ⚠ RULLET TILBAKE (2026-03-17, sesjon 4)
(Historisk referanse – konsepter kan gjenbrukes)
2a – Elapsed + actor ⚠ RULLET TILBAKE
Utviklet og testet, men rullet tilbake pga. bugs i kombinasjon med 2b/2c. Kode tilgjengelig på commit 9593675 i hugo-theme-samt-bu. Kan rulles frem med git reset --hard 9593675 && git push --force i temaet, etterfulgt av submodule-oppdatering i samt-bu-docs.
Kjente bugs som må løses før re-deploy:
- Race-condition:
pollQeBuild(ETag-poll i dialogen) ogcheckCompletions(GitHub API-poll ved sideinnlasting) kjører parallelt på siste lagrede side. Begge dekrementerer pending-teller,seenCompletedblir feil. - ETag-banner etter eget bygg: Etter at pending-state ryddes og siden lastes inn på nytt, oppdager ETag-poll at siden er endret (av vårt eget bygg) og viser «Siden er oppdatert» som om det er andres endring. Delvis fikset med
sessionStorage._samtuOwnBuildDone, men ikke tilstrekkelig testet. - Stuck count ved flere samtidige bygg: Pending-teller nådde aldri 0 ved 4 raske lagringer i sekvens.
Anbefalt tilnærming ved re-implementering:
- Fjern
seenCompleted-logikken helt fracheckCompletions - Bruk «kø-tom»-strategi: når
inProgress=0 && queued=0 && myCompleted > 0→ alt ferdig, rydd opp og last inn - Sørg for at
checkCompletionsIKKE starter hvis_samtuDialogPollActiveer satt
samtuShowPendingIndicatorWithTotal viser nå:
| Scenario | Tekst |
|---|---|
| 1 endring, kjører | ⟳ Din endring bygges · 45 sek |
| 1 endring, i kø | ⟳ Din endring i kø · 12 sek |
| N endringer, alle kjører | ⟳ N endringer bygges · 1 min |
| N kjører, M i kø | ⟳ N bygges · M i kø · 55 sek |
Elapsed beregnes fra pending.lastSaveAt og oppdateres automatisk hvert 3. sek (samme som poll-syklusen).
2b – Split inProgress/queued ⚠ RULLET TILBAKE (se 2a)
checkCompletions() teller nå inProgress og queued separat (i stedet for totalActive). Fungerer uavhengig av om Cloudflare er på free-tier (1 parallell) eller Pro (5 parallelle) – GitHub Actions API reflekterer sannheten i begge tilfeller.
Ny signatur: samtuShowPendingIndicatorWithTotal(count, inProgress, queued)
2c – Hendelsesfeed + pling (bottom-right)
Konsept: Skille mellom status (bottom-left, pågående tilstand) og hendelser (bottom-right, ting som har skjedd).
Bottom-right – hendelsespill:
- Viser siste hendelse som kompakt pill:
🔔 Erik Hagen endret /om-samt-bu (2 min siden) - Klikk → dropdown med siste 5–10 hendelser (lagret i localStorage)
- Pling-lyd (én note) ved andres hendelse; fanfare ved egen (eksisterende)
- Erstatter dagens grønne
#page-update-banner(som bare viser “Siden er oppdatert” uten kontekst)
Datakilder:
- Egne hendelser: allerede kjent (actor, url, tidspunkt fra pending-state)
- Andres hendelser: ETag-polling oppdager endring → API-kall mot
/actions/runs?status=completed&per_page=3fortriggering_actor.login
Filer som endres:
custom-footer.html: ETag-poll → event-log + plingedit-switcher.html: nytt HTML-element for pill + dropdown
Steg 4 – «Mine»/«Alle»-faner i byggehistorikk-dialog ✅ FULLFØRT (2026-03-17, sesjon 7)
Undertabs i dialog-headeren lar brukeren veksle mellom egne og alle bygg:
- «Mine» (standard): filtrerer på innlogget bruker via
&actor=– samme som før - «Alle»: henter alle 15 siste bygg i repoet, viser actor som sublinje per rad
- Navnecache:
/users/{login}hentes én gang per unik login per sidebesøk, caches i JS-dict. Viserlogin (Full Name)når navn er tilgjengelig – krever at GitHub-profilen har Name-feltet satt - Tab-bytte nullstiller cache og re-fetcher umiddelbart
- Filer endret:
edit-switcher.html(HTML),custom-footer.html(JS)
Merk:
data.namefra GitHub API ernullhvis brukeren ikke har satt navn i sin GitHub-profil (github.com/settings/profile). Visningsnavn i Hugo-innhold (last_editor-feltet) er manuelt satt og ikke koblet til GitHub-profilen.
Steg 5 – Overordnet statusoversikt for alle brukere
Status: Vurderes – settes evt. på roadmap
Sanntidsoversikt over alle aktive bygg på tvers av brukere. Polling av GitHub Actions API + presentasjon av triggering_actor.login per run. Mulig implementasjon: klikk på indikatoren åpner dropdown med alle aktive runs.
Avhengighet: Krever GitHub-token (allerede tilgjengelig for innloggede brukere).
Teknisk kontekst
Nøkkelfunksjoner i custom-footer.html:
| Funksjon | Signatur | Rolle |
|---|---|---|
samtuIncrementPending() | – | Øker pending-teller i localStorage og oppdaterer indikatoren umiddelbart |
samtuDecrementPending() | – | Kalles ved ferdig bygg – reduserer teller |
samtuShowPendingIndicator(count) | – | Shorthand, kaller under med null |
samtuShowPendingIndicatorWithTotal | (count, totalActive) | Oppdaterer #qe-job-indicator med tekst + setter data-building="1" |
samtuShowDoneIndicator() | – | Viser «Endringer publisert – klikk for å laste inn» + fjerner data-building |
samtuPlaySuccess() | – | Spiller seiersfanfare + tale |
samtuUnlockAudio() | – | Låser opp AudioContext under brukergestus |
startGhPoll() | – | GitHub Actions-polling (kjøres på siden der Lagre ble klikket) |
checkCompletions() | – | Resume-polling ved sideinnlasting (kjøres på ny side) |
localStorage-pending-state:
{
"count": 1,
"firstSaveAt": 1710638400000,
"lastSaveAt": 1710638400000,
"seenCompleted": 0,
"actor": "erikhag1git"
}
#qe-job-indicator (bottom-left, alltid synlig): Idle → klokkikon + «Byggehistorikk». Under bygg → spinner + «N endringer bygges». Ferdig → lenke «Endringer publisert – klikk for å laste inn». Klikk åpner #job-history-dialog. Bakgrunnspoll bruker data-building-attributtet for å unngå konflikt med andres-endringer-deteksjon.
#page-update-banner (bottom-right, grønn): ETag-basert bakgrunnspolling hvert 45. sek. Vises kun ved andres endringer (når ingen egne pending). Kandidat for erstatning av hendelsespill i fremtidig steg (se Steg 3).