Fix duplicate breadcrumb and Export Center delete confirmation

BC1 — Fix "Operations > Operations > ..." duplicate breadcrumb:
- Set breadcrumb to empty string on /ops/operations parent route
  and /ops/operations (overview) route, so only the top-level
  "Operations" breadcrumb from /ops renders. Affects 7 pages:
  Feeds, Signals, Jobs, Diagnostics, Notifications, Watchlist, overview.

EC1 — Export Center delete confirmation:
- Replace window.confirm() with app-confirm-dialog variant="danger"
- Names the export profile being deleted in confirmation message
- Follows the destructive action convention from AGENTS.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-03-27 16:46:49 +02:00
parent 9d5f33e450
commit cc9ce3ff5e
3 changed files with 22 additions and 6 deletions

View File

@@ -2,6 +2,7 @@
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
ViewChild,
computed, computed,
inject, inject,
OnDestroy, OnDestroy,
@@ -22,6 +23,7 @@ import { StellaBundleExportButtonComponent } from './stella-bundle-export-button
import { OperatorOnlyDirective } from '../../shared/directives/operator-only.directive'; import { OperatorOnlyDirective } from '../../shared/directives/operator-only.directive';
import { DateFormatService } from '../../core/i18n/date-format.service'; import { DateFormatService } from '../../core/i18n/date-format.service';
import { StellaPageTabsComponent, StellaPageTab } from '../../shared/components/stella-page-tabs/stella-page-tabs.component'; import { StellaPageTabsComponent, StellaPageTab } from '../../shared/components/stella-page-tabs/stella-page-tabs.component';
import { ConfirmDialogComponent } from '../../shared/components/confirm-dialog/confirm-dialog.component';
/** /**
* Export Center Component (Sprint: SPRINT_20251229_016) * Export Center Component (Sprint: SPRINT_20251229_016)
* Manages export profiles and monitors export runs with SSE updates. * Manages export profiles and monitors export runs with SSE updates.
@@ -33,7 +35,7 @@ const EXPORT_CENTER_TABS: StellaPageTab[] = [
@Component({ @Component({
selector: 'app-export-center', selector: 'app-export-center',
imports: [FormsModule, StellaBundleExportButtonComponent, OperatorOnlyDirective, StellaPageTabsComponent], imports: [FormsModule, StellaBundleExportButtonComponent, OperatorOnlyDirective, StellaPageTabsComponent, ConfirmDialogComponent],
template: ` template: `
<div class="export-center"> <div class="export-center">
<header class="page-header"> <header class="page-header">
@@ -350,6 +352,11 @@ const EXPORT_CENTER_TABS: StellaPageTab[] = [
</div> </div>
</div> </div>
} }
<app-confirm-dialog #deleteConfirm
title="Delete Export Profile"
[message]="'Delete profile \\'' + (pendingDeleteProfile()?.name ?? '') + '\\'? This cannot be undone.'"
confirmLabel="Delete" cancelLabel="Cancel" variant="danger"
(confirmed)="executeDeleteProfile()" />
</div> </div>
`, `,
styles: [` styles: [`
@@ -1021,10 +1028,19 @@ export class ExportCenterComponent implements OnInit, OnDestroy {
this.closeModal(); this.closeModal();
} }
readonly pendingDeleteProfile = signal<ExportProfile | null>(null);
@ViewChild('deleteConfirm') deleteConfirm!: ConfirmDialogComponent;
deleteProfile(profile: ExportProfile): void { deleteProfile(profile: ExportProfile): void {
if (confirm(`Delete profile "${profile.name}"?`)) { this.pendingDeleteProfile.set(profile);
this.profiles.update(profiles => profiles.filter(p => p.id !== profile.id)); this.deleteConfirm.open();
} }
executeDeleteProfile(): void {
const profile = this.pendingDeleteProfile();
if (!profile) return;
this.profiles.update(profiles => profiles.filter(p => p.id !== profile.id));
this.pendingDeleteProfile.set(null);
} }
runProfile(profile: ExportProfile): void { runProfile(profile: ExportProfile): void {

View File

@@ -6,7 +6,7 @@ export const OPERATIONS_ROUTES: Routes = [
path: '', path: '',
pathMatch: 'full', pathMatch: 'full',
title: 'Operations', title: 'Operations',
data: { breadcrumb: 'Operations' }, data: { breadcrumb: '' },
loadComponent: () => loadComponent: () =>
import('../features/platform/ops/platform-ops-overview-page.component').then( import('../features/platform/ops/platform-ops-overview-page.component').then(
(m) => m.PlatformOpsOverviewPageComponent, (m) => m.PlatformOpsOverviewPageComponent,

View File

@@ -10,7 +10,7 @@ export const OPS_ROUTES: Routes = [
{ {
path: 'operations', path: 'operations',
title: 'Operations', title: 'Operations',
data: { breadcrumb: 'Operations' }, data: { breadcrumb: '' },
loadChildren: () => import('./operations.routes').then((m) => m.OPERATIONS_ROUTES), loadChildren: () => import('./operations.routes').then((m) => m.OPERATIONS_ROUTES),
}, },
{ {