Rework alert comments: authors, system events, wider layout

- Add author field ("user" | "system") to AlertComment
- System comments are automatically added when an alert is reopened
  by the engine ("Alert reopened — condition is still active.") or
  manually via the UI ("Manually reopened.")
- Alert detail page redesigned with a two-column layout (3/5 detail,
  2/5 comments) at lg breakpoint
- System comments render as centered event dividers with a gear icon;
  user comments render as avatar + bubble

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-12 11:44:51 -04:00
parent bf83c1a779
commit c86b8ff33a
3 changed files with 167 additions and 70 deletions
+17 -5
View File
@@ -54,7 +54,7 @@ interface StoredAlert {
firstSeen: string;
lastSeen: string;
closedAt: string | null;
comments: Array<{ id: number; body: string; createdAt: string }>;
comments: Array<{ id: number; body: string; createdAt: string; author: "user" | "system" }>;
}
function load(): Store {
@@ -127,13 +127,18 @@ export function upsertAlerts(candidates: AlertCandidate[]): number {
if (isSuppressed) continue;
// Re-open if previously closed (manually or resolved) and not suppressed.
// Preserve firstSeen and comments — this is the same incident continuing,
// not a brand new one.
// Preserve firstSeen and comments — this is the same incident continuing.
if (existing.status === "closed") {
existing.status = "open";
existing.closeReason = null;
existing.closedAt = null;
existing.suppressedUntil = null;
existing.comments.push({
id: store.nextCommentId++,
body: "Alert reopened — condition is still active.",
createdAt: nowISO,
author: "system",
});
}
// Refresh content and lastSeen
@@ -228,18 +233,25 @@ export function reopenAlert(id: number): Alert | null {
alert.closeReason = null;
alert.closedAt = null;
alert.suppressedUntil = null;
alert.comments.push({
id: store.nextCommentId++,
body: "Manually reopened.",
createdAt: new Date().toISOString(),
author: "system",
});
save(store);
return toAlert(alert);
}
export function addComment(alertId: number, body: string): AlertComment | null {
export function addComment(alertId: number, body: string, author: "user" | "system" = "user"): AlertComment | null {
const store = load();
const alert = Object.values(store.alerts).find((a) => a.id === alertId);
if (!alert) return null;
const comment = {
const comment: AlertComment = {
id: store.nextCommentId++,
body,
createdAt: new Date().toISOString(),
author,
};
alert.comments.push(comment);
save(store);
+1
View File
@@ -118,6 +118,7 @@ export interface AlertComment {
id: number;
body: string;
createdAt: string;
author: "user" | "system";
}
export type AlertCloseReason = "manual" | "resolved";