up
This commit is contained in:
@@ -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/`
|
||||
|
||||
@@ -535,25 +535,24 @@
|
||||
aria-label="Previous page"
|
||||
>
|
||||
← Previous
|
||||
</button>
|
||||
|
||||
<!-- 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 }}"
|
||||
>
|
||||
{{ pageNum + 1 }}
|
||||
</button>
|
||||
}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
</button>
|
||||
|
||||
<!-- Page number buttons (show max 5) -->
|
||||
@for (page of [].constructor(Math.min(5, totalPages())); track $index; let i = $index) {
|
||||
<button
|
||||
type="button"
|
||||
class="pagination-btn pagination-btn--number"
|
||||
[class.active]="currentPage() === getPageNumberForIndex(i)"
|
||||
(click)="goToPage(getPageNumberForIndex(i))"
|
||||
[attr.aria-current]="currentPage() === getPageNumberForIndex(i) ? 'page' : null"
|
||||
aria-label="Page {{ getPageNumberForIndex(i) + 1 }}"
|
||||
>
|
||||
{{ getPageNumberForIndex(i) + 1 }}
|
||||
</button>
|
||||
}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="pagination-btn"
|
||||
[disabled]="!hasNextPage()"
|
||||
(click)="nextPage()"
|
||||
|
||||
@@ -171,12 +171,21 @@ export class EvidencePanelComponent {
|
||||
});
|
||||
|
||||
// Whether there are more pages
|
||||
readonly hasNextPage = computed(() => this.currentPage() < this.totalPages() - 1);
|
||||
readonly hasPreviousPage = computed(() => this.currentPage() > 0);
|
||||
|
||||
// Active filter count for badge
|
||||
readonly activeFilterCount = computed(() => {
|
||||
const f = this.filters();
|
||||
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();
|
||||
let count = 0;
|
||||
if (f.sources.length > 0) count++;
|
||||
if (f.severityBucket !== 'all') count++;
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user