Files
electric-cherry/src/lib/ui/status.ts
T
2026-10-17 21:30:43 -04:00

94 lines
3.9 KiB
TypeScript

export type StatusTone = 'neutral' | 'online' | 'warning' | 'danger' | 'info';
export type StatusShape = 'hollow' | 'circle' | 'triangle' | 'square' | 'ring';
export interface StatusPresentation {
label: string;
tone: StatusTone;
shape: StatusShape;
}
/** A second visual cue keeps state readable without relying on color. */
export const statusShapes: Record<StatusTone, StatusShape> = {
neutral: 'hollow',
online: 'circle',
warning: 'triangle',
danger: 'square',
info: 'ring'
};
const states: Record<string, [string, StatusTone]> = {
'moderation-current': ['Policy current', 'online'],
'moderation-pending': ['Policy pending', 'warning'],
'moderation-offline': ['Offline', 'danger'],
'moderation-unavailable': ['Unavailable', 'warning'],
'moderation-active': ['Active', 'warning'],
'moderation-revoked': ['Revoked', 'neutral'],
'moderation-open': ['Open', 'info'],
'moderation-in_review': ['In progress', 'info'],
'moderation-closed': ['Closed', 'neutral'],
'moderation-escalated': ['Escalated', 'warning'],
'moderation-resolved': ['Resolved', 'online'],
'moderation-dismissed': ['Dismissed', 'neutral'],
'moderation-warning_issued': ['Warning issued', 'online'],
'moderation-restriction_applied': ['Restriction applied', 'online'],
'moderation-no_action': ['No action needed', 'neutral'],
'moderation-duplicate': ['Duplicate', 'neutral'],
'moderation-appeal_upheld': ['Appeal upheld', 'online'],
'moderation-appeal_denied': ['Appeal denied', 'neutral'],
'moderation-queued': ['Queued', 'neutral'],
'moderation-delivered': ['Delivered; awaiting confirmation', 'info'],
'moderation-confirmed': ['Confirmed', 'online'],
'moderation-failed': ['Failed', 'danger'],
'moderation-expired': ['Expired', 'neutral'],
'moderation-unknown': ['Outcome unknown', 'warning'],
provisioning: ['Provisioning', 'info'],
online: ['Online', 'online'],
offline: ['Offline', 'danger'],
stale: ['Not responding', 'warning'],
starting: ['Starting', 'info'],
'host-offline': ['Host offline', 'danger'],
'not-responding': ['Not responding', 'warning'],
stopped: ['Stopped', 'neutral'],
unknown: ['Unknown', 'neutral'],
queued: ['Queued', 'neutral'],
pending: ['Queued for restart', 'neutral'],
running: ['In progress', 'info'],
active: ['In progress', 'info'],
deploying: ['Installing files', 'info'],
restarting: ['Restarting', 'info'],
observing: ['Collecting test evidence', 'info'],
'rolling-back': ['Rolling back', 'info'],
'awaiting-empty': ['Waiting for empty lobby', 'neutral'],
waiting: ['Waiting', 'neutral'],
'awaiting-health': ['Verifying health', 'info'],
'awaiting-match': ['Waiting for a match', 'neutral'],
ready: ['Ready', 'online'],
'ready-promote': ['Ready to promote', 'online'],
done: ['Completed', 'online'],
passed: ['Test passed', 'online'],
tested: ['Test passed', 'online'],
promoted: ['Promoted', 'online'],
'rolled-back': ['Rolled back', 'neutral'],
cancelled: ['Cancelled', 'neutral'],
failed: ['Failed', 'danger'],
'test-failed': ['Test failed', 'danger'],
interrupted: ['Interrupted', 'danger'],
warning: ['Completed with warnings', 'warning'],
held: ['On hold', 'neutral'],
skipped: ['Withdrawn', 'neutral'],
manual: ['Manual action needed', 'warning'],
paused: ['Paused', 'warning'],
inconclusive: ['Missing evidence', 'warning'],
untested: ['Needs testing', 'neutral'],
testing: ['Beta active', 'info'],
empty: ['No versions', 'neutral'],
attention: ['Needs attention', 'warning']
};
export function statusPresentation(state: string): StatusPresentation {
const result = states[state];
const [label, tone] = result ?? [
(state.charAt(0).toUpperCase() + state.slice(1)).replaceAll('-', ' ') || 'Unknown',
'neutral'
];
return { label, tone, shape: statusShapes[tone] };
}