From 4e6c14037c4d3dde01775a5bf48b83c487ee6fc9 Mon Sep 17 00:00:00 2001 From: master <> Date: Sun, 29 Mar 2026 00:04:23 +0200 Subject: [PATCH] Fix Pack creation: clear cache on refresh, trigger CD, navigate on success PolicyPackStore.refresh() now clears the sessionStorage cache before fetching, so API responses aren't hidden behind stale cached data. PolicyWorkspaceComponent fixes: - Add ChangeDetectorRef.markForCheck() after every async state mutation (OnPush was preventing UI updates from plain field assignments) - Navigate to the new pack on successful creation - Show clearer error when policy gateway is unreachable (status 0) - Clear pack cache before navigation so the new pack appears Co-Authored-By: Claude Opus 4.6 (1M context) --- .../services/policy-pack.store.ts | 9 +++++ .../workspace/policy-workspace.component.ts | 40 +++++++++++++------ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Web/StellaOps.Web/src/app/features/policy-studio/services/policy-pack.store.ts b/src/Web/StellaOps.Web/src/app/features/policy-studio/services/policy-pack.store.ts index 80c12791b..894709d1d 100644 --- a/src/Web/StellaOps.Web/src/app/features/policy-studio/services/policy-pack.store.ts +++ b/src/Web/StellaOps.Web/src/app/features/policy-studio/services/policy-pack.store.ts @@ -32,9 +32,18 @@ export class PolicyPackStore { } refresh(): void { + this.clearCache(); this.fetch(); } + clearCache(): void { + try { + sessionStorage.removeItem(this.cacheKey); + } catch { + /* ignore */ + } + } + private fetch(): void { if (!this.canReadPolicyPacks()) { this.usingFallback = true; diff --git a/src/Web/StellaOps.Web/src/app/features/policy-studio/workspace/policy-workspace.component.ts b/src/Web/StellaOps.Web/src/app/features/policy-studio/workspace/policy-workspace.component.ts index 68e86a24d..690caa0f3 100644 --- a/src/Web/StellaOps.Web/src/app/features/policy-studio/workspace/policy-workspace.component.ts +++ b/src/Web/StellaOps.Web/src/app/features/policy-studio/workspace/policy-workspace.component.ts @@ -1,8 +1,8 @@ import { CommonModule } from '@angular/common'; -import { Component, ChangeDetectionStrategy, inject, signal } from '@angular/core'; +import { Component, ChangeDetectionStrategy, inject, signal, ChangeDetectorRef } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { AuthService, AUTH_SERVICE } from '../../../core/auth'; -import { RouterLink } from '@angular/router'; +import { Router, RouterLink } from '@angular/router'; import { PolicyPackSummary } from '../models/policy.models'; import { PolicyApiService } from '../services/policy-api.service'; @@ -186,29 +186,36 @@ export class PolicyWorkspaceComponent { private readonly packStore = inject(PolicyPackStore); private readonly policyApi = inject(PolicyApiService); private readonly auth = inject(AUTH_SERVICE) as AuthService; + private readonly router = inject(Router); + private readonly cdr = inject(ChangeDetectorRef); constructor() { this.loading = true; this.applyScopes(); this.packStore.getPacks().subscribe((packs) => { - this.packs = [...packs].sort((a, b) => - b.modifiedAt.localeCompare(a.modifiedAt) || a.id.localeCompare(b.id) - ); + this.packs = this.sortPacks(packs); this.loading = false; + this.cdr.markForCheck(); }); } refresh(): void { this.refreshing = true; + this.cdr.markForCheck(); this.packStore.refresh(); this.packStore.getPacks().subscribe((packs) => { - this.packs = [...packs].sort((a, b) => - b.modifiedAt.localeCompare(a.modifiedAt) || a.id.localeCompare(b.id) - ); + this.packs = this.sortPacks(packs); this.refreshing = false; + this.cdr.markForCheck(); }); } + private sortPacks(packs: PolicyPackSummary[]): PolicyPackSummary[] { + return [...packs].sort((a, b) => + b.modifiedAt.localeCompare(a.modifiedAt) || a.id.localeCompare(b.id) + ); + } + createPack(): void { const name = this.newPackName().trim(); if (!name) return; @@ -223,16 +230,23 @@ export class PolicyWorkspaceComponent { content: '', }) .subscribe({ - next: () => { + next: (pack) => { this.newPackName.set(''); this.newPackDesc.set(''); this.creating.set(false); - this.refresh(); + this.packStore.clearCache(); + if (pack?.id) { + void this.router.navigate(['/ops/policy/packs', pack.id]); + } else { + this.refresh(); + } }, error: (err) => { - this.createError.set( - err?.error?.message ?? err?.message ?? 'Failed to create policy pack. Please try again.' - ); + const message = + err?.status === 0 + ? 'Cannot reach the policy service. Check that the policy gateway is running.' + : err?.error?.message ?? err?.message ?? 'Failed to create policy pack. Please try again.'; + this.createError.set(message); this.creating.set(false); }, });