BulkTriageViewComponent

Streamlined interface for triaging multiple findings at once with bucket-based organization.

Overview

The BulkTriageViewComponent provides a triage-focused view with bucket summary cards, one-click bucket selection, and bulk actions.

Selector

<app-bulk-triage-view />

Inputs

InputTypeDefaultDescription
findingsScoredFinding[][]Array of scored findings
selectedIdsSet<string>new Set()Currently selected finding IDs
processingbooleanfalseWhether an action is in progress

Outputs

OutputTypeDescription
selectionChangeEventEmitter<string[]>Emits when selection changes
actionRequestEventEmitter<BulkActionRequest>Emits when an action is triggered
actionCompleteEventEmitter<BulkActionResult>Emits when an action completes

Action Types

type BulkActionType = 'acknowledge' | 'suppress' | 'assign' | 'escalate';

interface BulkActionRequest {
  action: BulkActionType;
  findingIds: string[];
  assignee?: string;      // For 'assign' action
  reason?: string;        // For 'suppress' action
}

interface BulkActionResult {
  action: BulkActionType;
  findingIds: string[];
  success: boolean;
  error?: string;
}

UI Sections

Bucket Summary Cards

Four cards showing findings grouped by priority bucket:

Each card displays:

Action Bar

Appears when findings are selected:

Progress Overlay

Shown during bulk operations:

Modals

Usage Examples

Basic Usage

<app-bulk-triage-view
  [findings]="scoredFindings"
  [selectedIds]="selectedIds"
  (selectionChange)="onSelectionChange($event)"
  (actionRequest)="onActionRequest($event)"
/>

Full Implementation

@Component({
  selector: 'app-triage-page',
  template: `
    <app-bulk-triage-view
      [findings]="findings()"
      [selectedIds]="selectedIds()"
      [processing]="processing()"
      (selectionChange)="updateSelection($event)"
      (actionRequest)="handleAction($event)"
      (actionComplete)="onActionComplete($event)"
    />
  `
})
export class TriagePageComponent {
  findings = signal<ScoredFinding[]>([]);
  selectedIds = signal<Set<string>>(new Set());
  processing = signal(false);

  private triageService = inject(TriageService);

  updateSelection(ids: string[]): void {
    this.selectedIds.set(new Set(ids));
  }

  async handleAction(request: BulkActionRequest): Promise<void> {
    this.processing.set(true);

    try {
      switch (request.action) {
        case 'acknowledge':
          await this.triageService.acknowledge(request.findingIds);
          break;
        case 'suppress':
          await this.triageService.suppress(request.findingIds, request.reason!);
          break;
        case 'assign':
          await this.triageService.assign(request.findingIds, request.assignee!);
          break;
        case 'escalate':
          await this.triageService.escalate(request.findingIds);
          break;
      }

      this.selectedIds.set(new Set());
      await this.refreshFindings();
    } finally {
      this.processing.set(false);
    }
  }
}

With Toast Notifications

<app-bulk-triage-view
  [findings]="findings"
  [selectedIds]="selectedIds"
  (actionComplete)="showToast($event)"
/>
showToast(result: BulkActionResult): void {
  if (result.success) {
    this.toast.success(
      `${result.action} completed for ${result.findingIds.length} findings`
    );
  } else {
    this.toast.error(`Action failed: ${result.error}`);
  }
}

Bucket Selection

Select All in Bucket

Click “Select All” on a bucket card to select all findings in that bucket.

Toggle Bucket

Clicking “Select All” when all bucket items are selected will deselect them.

Partial Selection

When some items in a bucket are selected, the button shows a partial indicator.

Action Descriptions

ActionIconDescription
AcknowledgeCheckmarkMark findings as reviewed
SuppressEye-offSuppress with reason (opens modal)
AssignUserAssign to team member (opens modal)
EscalateAlertMark for urgent attention

Undo Capability

The component maintains an undo stack for recent actions:

Accessibility

Keyboard Navigation

KeyAction
TabNavigate between elements
Enter/SpaceActivate buttons
EscapeClose modals

Styling

app-bulk-triage-view {
  --bucket-card-padding: 16px;
  --bucket-card-radius: 8px;
  --action-bar-bg: #f9fafb;
  --modal-max-width: 400px;
}

/* Bucket colors */
.bucket-card.act-now { --bucket-color: #DC2626; }
.bucket-card.schedule-next { --bucket-color: #D97706; }
.bucket-card.investigate { --bucket-color: #2563EB; }
.bucket-card.watchlist { --bucket-color: #6B7280; }

Responsive Behavior

BreakpointLayout
> 640px4 bucket cards in row
<= 640px2x2 grid, action labels hidden