This commit is contained in:
StellaOps Bot
2025-12-15 09:15:03 +02:00
parent d59cc816c1
commit 0cb5c9abfb
5 changed files with 56 additions and 45 deletions

View File

@@ -1,6 +1,6 @@
# Sprint 4601_0001_0001 · Keyboard Shortcuts for Triage UI # Sprint 4601_0001_0001 · Keyboard Shortcuts for Triage UI
**Status:** DOING **Status:** DONE
**Priority:** P1 - HIGH **Priority:** P1 - HIGH
**Module:** Web (Angular) **Module:** Web (Angular)
**Working Directory:** `src/Web/StellaOps.Web/src/app/features/triage/` **Working Directory:** `src/Web/StellaOps.Web/src/app/features/triage/`

View File

@@ -539,16 +539,15 @@
<!-- Page number buttons (show max 5) --> <!-- Page number buttons (show max 5) -->
@for (page of [].constructor(Math.min(5, totalPages())); track $index; let i = $index) { @for (page of [].constructor(Math.min(5, totalPages())); track $index; let i = $index) {
@let pageNum = currentPage() < 2 ? i : Math.min(currentPage() - 2 + i, totalPages() - 1);
<button <button
type="button" type="button"
class="pagination-btn pagination-btn--number" class="pagination-btn pagination-btn--number"
[class.active]="currentPage() === pageNum" [class.active]="currentPage() === getPageNumberForIndex(i)"
(click)="goToPage(pageNum)" (click)="goToPage(getPageNumberForIndex(i))"
[attr.aria-current]="currentPage() === pageNum ? 'page' : null" [attr.aria-current]="currentPage() === getPageNumberForIndex(i) ? 'page' : null"
aria-label="Page {{ pageNum + 1 }}" aria-label="Page {{ getPageNumberForIndex(i) + 1 }}"
> >
{{ pageNum + 1 }} {{ getPageNumberForIndex(i) + 1 }}
</button> </button>
} }

View File

@@ -174,6 +174,15 @@ export class EvidencePanelComponent {
readonly hasNextPage = computed(() => this.currentPage() < this.totalPages() - 1); readonly hasNextPage = computed(() => this.currentPage() < this.totalPages() - 1);
readonly hasPreviousPage = computed(() => this.currentPage() > 0); readonly hasPreviousPage = computed(() => this.currentPage() > 0);
getPageNumberForIndex(i: number): number {
const totalPages = this.totalPages();
if (totalPages <= 0) return 0;
const current = this.currentPage();
const base = current < 2 ? i : current - 2 + i;
return Math.min(base, totalPages - 1);
}
// Active filter count for badge // Active filter count for badge
readonly activeFilterCount = computed(() => { readonly activeFilterCount = computed(() => {
const f = this.filters(); const f = this.filters();

View File

@@ -30,7 +30,7 @@ import {
type TabId = 'overview' | 'reachability' | 'policy' | 'attestations'; type TabId = 'overview' | 'reachability' | 'policy' | 'attestations';
const TAB_ORDER: readonly TabId[] = ['overview', 'reachability', 'policy', 'attestations']; const TAB_ORDER: readonly TabId[] = ['overview', 'reachability', 'policy', 'attestations'];
const REACHABILITY_VIEW_ORDER: readonly Array<'path-list' | 'compact-graph' | 'textual-proof'> = [ const REACHABILITY_VIEW_ORDER: readonly ('path-list' | 'compact-graph' | 'textual-proof')[] = [
'path-list', 'path-list',
'compact-graph', 'compact-graph',
'textual-proof', 'textual-proof',

View File

@@ -159,25 +159,28 @@ export class VexDecisionModalComponent {
}); });
constructor() { constructor() {
effect(() => { effect(
const existing = this.existingDecision(); () => {
if (existing) { const existing = this.existingDecision();
this.status.set(existing.status); if (existing) {
this.justificationType.set(existing.justificationType); this.status.set(existing.status);
this.justificationText.set(existing.justificationText ?? ''); this.justificationType.set(existing.justificationType);
this.environmentsText.set(existing.scope?.environments?.join(', ') ?? ''); this.justificationText.set(existing.justificationText ?? '');
this.projectsText.set(existing.scope?.projects?.join(', ') ?? ''); this.environmentsText.set(existing.scope?.environments?.join(', ') ?? '');
this.notBefore.set(toLocalDateTimeValue(existing.validFor?.notBefore ?? new Date().toISOString())); this.projectsText.set(existing.scope?.projects?.join(', ') ?? '');
this.notAfter.set(toLocalDateTimeValue(existing.validFor?.notAfter ?? '')); this.notBefore.set(toLocalDateTimeValue(existing.validFor?.notBefore ?? new Date().toISOString()));
this.evidenceRefs.set(existing.evidenceRefs ?? []); this.notAfter.set(toLocalDateTimeValue(existing.validFor?.notAfter ?? ''));
return; this.evidenceRefs.set(existing.evidenceRefs ?? []);
} return;
}
const initialStatus = this.initialStatus(); const initialStatus = this.initialStatus();
if (initialStatus) { if (initialStatus) {
this.status.set(initialStatus); this.status.set(initialStatus);
} }
}); },
{ allowSignalWrites: true }
);
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {