feat(portal-behandel): refresh the werkbak on an interval while it is open (refs #162)
`interval(WERKBAK_REFRESH_MS)` re-reads the existing BFF werkbak endpoint, scoped to the page's lifetime with `takeUntilDestroyed()`. A background read leaves the rows and states on screen alone until it has an answer, so a tick neither flashes the loading state over rows being read nor swaps the list for the failure alert on a blip — only a foreground read (on open, after a decision) speaks for whether the werkbak is readable at all. No new endpoint, dependency or server state: rxjs and the endpoint are both already here (ADR-0032). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { interval } from 'rxjs';
|
||||
import { BffApiV1Service, type WerkbakItem } from 'api-client';
|
||||
import { UtrechtComponentsModule } from 'ui';
|
||||
|
||||
@@ -16,6 +18,11 @@ type Besluit = 'goedkeuren' | 'afwijzen';
|
||||
* Flowable `Beoordelen` tasks, read through the domain) and decides each — goedkeuren or afwijzen. A
|
||||
* decision posts to the BFF, which applies the domain transition and completes the workflow task
|
||||
* (ADR-0013; S-12). After a decision the werkbak refreshes so the handled item drops off the list.
|
||||
*
|
||||
* The page also re-reads itself every {@link WERKBAK_REFRESH_MS} while it is open, so a registration
|
||||
* that reaches beoordeling after the behandelaar opened the werkbak shows up on its own — no reload
|
||||
* (S-26/#162). Polling rather than a pushed stream: nothing notifies the BFF either, so a stream
|
||||
* would poll the domain in the BFF instead and add connection state for the same freshness (ADR-0032).
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-werkbak-page',
|
||||
@@ -33,11 +40,25 @@ export class WerkbakPage {
|
||||
|
||||
constructor() {
|
||||
this.load();
|
||||
// ponytail: a fixed interval, polled while the page lives — it keeps refreshing in a background
|
||||
// tab. Gate on `document.visibilityState` if the request volume ever matters.
|
||||
interval(WERKBAK_REFRESH_MS)
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe(() => this.load({ background: true }));
|
||||
}
|
||||
|
||||
load(): void {
|
||||
this.loading.set(true);
|
||||
this.failed.set(false);
|
||||
/**
|
||||
* Read the werkbak. A `background` read is the interval refresh: it leaves the rows and the states
|
||||
* the behandelaar is looking at alone until it has an answer — no loading flash on every tick, and
|
||||
* a blip does not swap the list for the failure alert (the next tick recovers). Only a foreground
|
||||
* read — on open, or after a decision — speaks for whether the werkbak is readable at all.
|
||||
*/
|
||||
load(options: { background?: boolean } = {}): void {
|
||||
const background = options.background ?? false;
|
||||
if (!background) {
|
||||
this.loading.set(true);
|
||||
this.failed.set(false);
|
||||
}
|
||||
this.bff.getBehandelWerkbak().subscribe({
|
||||
next: (rows: WerkbakItem[]) => {
|
||||
this.items.set(rows);
|
||||
@@ -46,6 +67,7 @@ export class WerkbakPage {
|
||||
},
|
||||
// Surface the failure (e.g. 403 for a non-behandelaar) instead of swallowing it.
|
||||
error: () => {
|
||||
if (background) return;
|
||||
this.items.set([]);
|
||||
this.loading.set(false);
|
||||
this.loaded.set(true);
|
||||
|
||||
Reference in New Issue
Block a user