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
**Status:** DOING
**Status:** DONE
**Priority:** P1 - HIGH
**Module:** Web (Angular)
**Working Directory:** `src/Web/StellaOps.Web/src/app/features/triage/`

View File

@@ -539,16 +539,15 @@
<!-- Page number buttons (show max 5) -->
@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
type="button"
class="pagination-btn pagination-btn--number"
[class.active]="currentPage() === pageNum"
(click)="goToPage(pageNum)"
[attr.aria-current]="currentPage() === pageNum ? 'page' : null"
aria-label="Page {{ pageNum + 1 }}"
[class.active]="currentPage() === getPageNumberForIndex(i)"
(click)="goToPage(getPageNumberForIndex(i))"
[attr.aria-current]="currentPage() === getPageNumberForIndex(i) ? 'page' : null"
aria-label="Page {{ getPageNumberForIndex(i) + 1 }}"
>
{{ pageNum + 1 }}
{{ getPageNumberForIndex(i) + 1 }}
</button>
}

View File

@@ -174,6 +174,15 @@ export class EvidencePanelComponent {
readonly hasNextPage = computed(() => this.currentPage() < this.totalPages() - 1);
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
readonly activeFilterCount = computed(() => {
const f = this.filters();

View File

@@ -30,7 +30,7 @@ import {
type 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',
'compact-graph',
'textual-proof',

View File

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