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 { 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 { BffApiV1Service, type WerkbakItem } from 'api-client';
|
||||||
import { UtrechtComponentsModule } from 'ui';
|
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
|
* 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
|
* 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.
|
* (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({
|
@Component({
|
||||||
selector: 'app-werkbak-page',
|
selector: 'app-werkbak-page',
|
||||||
@@ -33,11 +40,25 @@ export class WerkbakPage {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.load();
|
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 {
|
/**
|
||||||
|
* 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.loading.set(true);
|
||||||
this.failed.set(false);
|
this.failed.set(false);
|
||||||
|
}
|
||||||
this.bff.getBehandelWerkbak().subscribe({
|
this.bff.getBehandelWerkbak().subscribe({
|
||||||
next: (rows: WerkbakItem[]) => {
|
next: (rows: WerkbakItem[]) => {
|
||||||
this.items.set(rows);
|
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.
|
// Surface the failure (e.g. 403 for a non-behandelaar) instead of swallowing it.
|
||||||
error: () => {
|
error: () => {
|
||||||
|
if (background) return;
|
||||||
this.items.set([]);
|
this.items.set([]);
|
||||||
this.loading.set(false);
|
this.loading.set(false);
|
||||||
this.loaded.set(true);
|
this.loaded.set(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user