feat(ui): render the CCTV frame preview, source badge and summary from the store

The frame lifecycle keeps its request state in an object instead of the
image's dataset and publishes it; the panel binds the image's src, class
and data attributes and the wrapper's loading and has-frame classes from
it, so preload tokens, kept pixels on a failed refresh and clearing on a
camera change are unchanged. The source badge is the pure
presentCctvSourceBadge(), the live switch and the typed summary are
published too. The video surface still draws into the panel's canvas.
This commit is contained in:
Sameh Khamis committed 2026-10-30 21:54:42 -07:00
1 parent 6c7035f617
commit eef3dec759
10 files changed
+306 -177

No files matched your search

+11 -11
View File
@@ -69,8 +69,6 @@ try {
calDirty: false,
},
});
window.__qaBadgeText =
document.getElementById('cctv-source-badge').textContent;
});
await page.waitForSelector('.weather-coverage.gev-status-badge');
const inventory = await page.evaluate(() => {
@@ -120,20 +118,22 @@ try {
);
for (const state of ['loading', 'error', 'retained', 'ready', 'idle']) {
const result = await page.evaluate((state) => {
const result = await page.evaluate(async (state) => {
const owner = window.__godsEyeView.styleManager._cctvControls;
owner._cctvFrame.dataset.loading = state === 'loading' ? 'true' : '';
owner._cctvFrame.dataset.error = ['error', 'retained'].includes(state)
? 'true'
: '';
owner._cctvFrameWrap.classList.toggle(
'has-frame',
state === 'retained',
);
const frame = owner._frame;
owner._frame = {
...frame,
loading: state === 'loading',
error: ['error', 'retained'].includes(state),
hasFrame: state === 'retained',
};
owner._syncCctvSourceBadge(
owner._cctvState.activeCamera,
state !== 'idle',
);
owner._frame = frame;
// The panel view renders the badge on Vue's next flush.
await new Promise((resolve) => requestAnimationFrame(resolve));
const badge = document.getElementById('cctv-source-badge');
return {
state: badge.dataset.frameState,