feat(boardwalk): expose the admin build id and show a reload banner when a new build is deployed (quick-261028-rqb)

- boardwalk.BuildID hashes the dist tree plus the binary's build info once
  per handler; X-Summer-Build on every response, {prefix}/build.json and the
  summer-admin-build meta carry it
- the SPA reads the booted build, re-checks on focus, visibility and every
  5 minutes, and shows UpdateBanner on a different build
This commit is contained in:
Jakub Zych
2026-10-28 21:19:36 +01:00
parent 4957e5ce25
commit 291b18fb1e
12 changed files with 404 additions and 5 deletions

View File

@@ -0,0 +1,41 @@
<script setup lang="ts">
import { X } from '@lucide/vue'
import { dismissNewBuild, newBuildAvailable } from '../../app/buildUpdate'
import { t } from '../../app/i18n'
import { page } from '../../state/usePreferences'
// New-version banner (buildUpdate.ts): shown while the server answers a build
// different from the one this tab booted with. It never reloads by itself;
// Reload goes through page.reload, so a dirty form's beforeunload prompt
// still asks, and Close hides it until another build is deployed.
</script>
<template>
<!-- Bottom right, 88px up so it clears the sticky form footer, like the toasts. -->
<div
v-if="newBuildAvailable"
data-update-banner
role="status"
aria-live="polite"
class="fixed right-4 bottom-[88px] z-50 flex max-w-[420px] items-center gap-3 rounded-[14px] bg-[#1d2740] py-3 pr-2.5 pl-3.5 text-white shadow-toast"
>
<span class="font-medium">{{ t('backend::lang.version.available') }}</span>
<button
type="button"
data-update-reload
class="shrink-0 rounded-pager bg-accent px-3 py-1.5 font-medium text-on-accent transition-opacity duration-150 ease-out hover:opacity-90"
@click="page.reload()"
>
{{ t('backend::lang.version.reload') }}
</button>
<button
type="button"
data-update-close
:aria-label="t('backend::lang.form.close')"
class="flex size-8 shrink-0 items-center justify-center rounded-pager text-[#c3cbda] transition-colors duration-150 ease-out hover:bg-side-hover hover:text-white"
@click="dismissNewBuild()"
>
<X :size="16" aria-hidden="true" />
</button>
</div>
</template>