@checkstack/incident-frontend 0.3.10 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# @checkstack/incident-frontend
|
|
2
2
|
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [090143b]
|
|
8
|
+
- @checkstack/ui@0.5.1
|
|
9
|
+
- @checkstack/dashboard-frontend@0.3.11
|
|
10
|
+
- @checkstack/auth-frontend@0.5.6
|
|
11
|
+
|
|
12
|
+
## 0.4.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- cce5453: Add notification suppression for incidents
|
|
17
|
+
|
|
18
|
+
- Added `suppressNotifications` field to incidents, allowing active incidents to optionally suppress health check notifications
|
|
19
|
+
- When enabled, health status change notifications will not be sent for affected systems while the incident is active (not resolved)
|
|
20
|
+
- Mirrors the existing maintenance notification suppression pattern
|
|
21
|
+
- Added toggle UI in the IncidentEditor dialog
|
|
22
|
+
- Added `hasActiveIncidentWithSuppression` RPC endpoint for service-to-service queries
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- 223081d: Add icon support to PageLayout and improve mobile responsiveness
|
|
27
|
+
|
|
28
|
+
**PageLayout Icons:**
|
|
29
|
+
|
|
30
|
+
- Added required `icon` prop to `PageLayout` and `PageHeader` components that accepts a Lucide icon component reference
|
|
31
|
+
- Icons are rendered with consistent `h-6 w-6 text-primary` styling
|
|
32
|
+
- Updated all page components to include appropriate icons in their headers
|
|
33
|
+
|
|
34
|
+
**Mobile Layout Improvements:**
|
|
35
|
+
|
|
36
|
+
- Standardized responsive padding in main app shell (`p-3` on mobile, `p-6` on desktop)
|
|
37
|
+
- Added `CardHeaderRow` component for mobile-safe card headers with proper wrapping
|
|
38
|
+
- Improved `DateRangeFilter` responsive behavior with vertical stacking on mobile
|
|
39
|
+
- Migrated pages to use `PageLayout` for consistent responsive behavior
|
|
40
|
+
|
|
41
|
+
- Updated dependencies [cce5453]
|
|
42
|
+
- Updated dependencies [223081d]
|
|
43
|
+
- @checkstack/incident-common@0.4.0
|
|
44
|
+
- @checkstack/ui@0.5.0
|
|
45
|
+
- @checkstack/auth-frontend@0.5.5
|
|
46
|
+
- @checkstack/dashboard-frontend@0.3.10
|
|
47
|
+
|
|
3
48
|
## 0.3.10
|
|
4
49
|
|
|
5
50
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -57,6 +57,7 @@ export const IncidentEditor: React.FC<Props> = ({
|
|
|
57
57
|
const [selectedSystemIds, setSelectedSystemIds] = useState<Set<string>>(
|
|
58
58
|
new Set(),
|
|
59
59
|
);
|
|
60
|
+
const [suppressNotifications, setSuppressNotifications] = useState(false);
|
|
60
61
|
|
|
61
62
|
// Status update fields
|
|
62
63
|
const [updates, setUpdates] = useState<IncidentUpdate[]>([]);
|
|
@@ -105,11 +106,13 @@ export const IncidentEditor: React.FC<Props> = ({
|
|
|
105
106
|
setDescription(incident.description ?? "");
|
|
106
107
|
setSeverity(incident.severity);
|
|
107
108
|
setSelectedSystemIds(new Set(incident.systemIds));
|
|
109
|
+
setSuppressNotifications(incident.suppressNotifications);
|
|
108
110
|
} else {
|
|
109
111
|
setTitle("");
|
|
110
112
|
setDescription("");
|
|
111
113
|
setSeverity("major");
|
|
112
114
|
setSelectedSystemIds(new Set());
|
|
115
|
+
setSuppressNotifications(false);
|
|
113
116
|
setUpdates([]);
|
|
114
117
|
setShowUpdateForm(false);
|
|
115
118
|
}
|
|
@@ -143,6 +146,7 @@ export const IncidentEditor: React.FC<Props> = ({
|
|
|
143
146
|
title,
|
|
144
147
|
description: description || undefined,
|
|
145
148
|
severity,
|
|
149
|
+
suppressNotifications,
|
|
146
150
|
systemIds: [...selectedSystemIds],
|
|
147
151
|
});
|
|
148
152
|
} else {
|
|
@@ -150,6 +154,7 @@ export const IncidentEditor: React.FC<Props> = ({
|
|
|
150
154
|
title,
|
|
151
155
|
description,
|
|
152
156
|
severity,
|
|
157
|
+
suppressNotifications,
|
|
153
158
|
systemIds: [...selectedSystemIds],
|
|
154
159
|
});
|
|
155
160
|
}
|
|
@@ -253,6 +258,31 @@ export const IncidentEditor: React.FC<Props> = ({
|
|
|
253
258
|
{selectedSystemIds.size} system(s) selected
|
|
254
259
|
</p>
|
|
255
260
|
</div>
|
|
261
|
+
|
|
262
|
+
{/* Notification Suppression Toggle */}
|
|
263
|
+
<div className="border rounded-md p-4 bg-muted/30">
|
|
264
|
+
<div
|
|
265
|
+
className="flex items-center gap-3 cursor-pointer"
|
|
266
|
+
onClick={() => setSuppressNotifications(!suppressNotifications)}
|
|
267
|
+
>
|
|
268
|
+
<Checkbox
|
|
269
|
+
id="suppress-notifications"
|
|
270
|
+
checked={suppressNotifications}
|
|
271
|
+
/>
|
|
272
|
+
<div className="flex-1">
|
|
273
|
+
<Label
|
|
274
|
+
htmlFor="suppress-notifications"
|
|
275
|
+
className="cursor-pointer font-medium"
|
|
276
|
+
>
|
|
277
|
+
Suppress health notifications
|
|
278
|
+
</Label>
|
|
279
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
280
|
+
When enabled, health status change notifications will not be
|
|
281
|
+
sent for affected systems while this incident is active.
|
|
282
|
+
</p>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
256
286
|
</div>
|
|
257
287
|
|
|
258
288
|
{/* Status Updates Section - Only show when editing */}
|
|
@@ -56,11 +56,11 @@ const IncidentConfigPageContent: React.FC = () => {
|
|
|
56
56
|
const toast = useToast();
|
|
57
57
|
|
|
58
58
|
const { allowed: canManage, loading: accessLoading } = accessApi.useAccess(
|
|
59
|
-
incidentAccess.incident.manage
|
|
59
|
+
incidentAccess.incident.manage,
|
|
60
60
|
);
|
|
61
61
|
|
|
62
62
|
const [statusFilter, setStatusFilter] = useState<IncidentStatus | "all">(
|
|
63
|
-
"all"
|
|
63
|
+
"all",
|
|
64
64
|
);
|
|
65
65
|
const [showResolved, setShowResolved] = useState(false);
|
|
66
66
|
|
|
@@ -84,7 +84,7 @@ const IncidentConfigPageContent: React.FC = () => {
|
|
|
84
84
|
} = incidentClient.listIncidents.useQuery(
|
|
85
85
|
statusFilter === "all"
|
|
86
86
|
? { includeResolved: showResolved }
|
|
87
|
-
: { status: statusFilter, includeResolved: showResolved }
|
|
87
|
+
: { status: statusFilter, includeResolved: showResolved },
|
|
88
88
|
);
|
|
89
89
|
|
|
90
90
|
// Fetch systems with useQuery
|
|
@@ -205,6 +205,7 @@ const IncidentConfigPageContent: React.FC = () => {
|
|
|
205
205
|
<PageLayout
|
|
206
206
|
title="Incident Management"
|
|
207
207
|
subtitle="Track and manage incidents affecting your systems"
|
|
208
|
+
icon={AlertTriangle}
|
|
208
209
|
loading={accessLoading}
|
|
209
210
|
allowed={canManage}
|
|
210
211
|
actions={
|
|
@@ -18,6 +18,7 @@ import { CatalogApi } from "@checkstack/catalog-common";
|
|
|
18
18
|
import {
|
|
19
19
|
Card,
|
|
20
20
|
CardHeader,
|
|
21
|
+
CardHeaderRow,
|
|
21
22
|
CardTitle,
|
|
22
23
|
CardContent,
|
|
23
24
|
Button,
|
|
@@ -54,7 +55,7 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
54
55
|
const toast = useToast();
|
|
55
56
|
|
|
56
57
|
const { allowed: canManage } = accessApi.useAccess(
|
|
57
|
-
incidentAccess.incident.manage
|
|
58
|
+
incidentAccess.incident.manage,
|
|
58
59
|
);
|
|
59
60
|
|
|
60
61
|
const [showUpdateForm, setShowUpdateForm] = useState(false);
|
|
@@ -66,7 +67,7 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
66
67
|
refetch: refetchIncident,
|
|
67
68
|
} = incidentClient.getIncident.useQuery(
|
|
68
69
|
{ id: incidentId ?? "" },
|
|
69
|
-
{ enabled: !!incidentId }
|
|
70
|
+
{ enabled: !!incidentId },
|
|
70
71
|
);
|
|
71
72
|
|
|
72
73
|
// Fetch systems with useQuery
|
|
@@ -138,6 +139,7 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
138
139
|
<PageLayout
|
|
139
140
|
title={incident.title}
|
|
140
141
|
subtitle="Incident details and status history"
|
|
142
|
+
icon={AlertTriangle}
|
|
141
143
|
loading={false}
|
|
142
144
|
allowed={true}
|
|
143
145
|
actions={
|
|
@@ -147,7 +149,7 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
147
149
|
navigate(
|
|
148
150
|
resolveRoute(incidentRoutes.routes.systemHistory, {
|
|
149
151
|
systemId: sourceSystemId,
|
|
150
|
-
})
|
|
152
|
+
}),
|
|
151
153
|
)
|
|
152
154
|
}
|
|
153
155
|
>
|
|
@@ -160,12 +162,12 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
160
162
|
{/* Incident Info Card */}
|
|
161
163
|
<Card>
|
|
162
164
|
<CardHeader className="border-b border-border">
|
|
163
|
-
<
|
|
165
|
+
<CardHeaderRow>
|
|
164
166
|
<div className="flex items-center gap-2">
|
|
165
167
|
<AlertTriangle className="h-5 w-5 text-muted-foreground" />
|
|
166
168
|
<CardTitle>Incident Details</CardTitle>
|
|
167
169
|
</div>
|
|
168
|
-
<div className="flex items-center gap-2">
|
|
170
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
169
171
|
{getIncidentSeverityBadge(incident.severity)}
|
|
170
172
|
{getIncidentStatusBadge(incident.status)}
|
|
171
173
|
{canResolve && (
|
|
@@ -180,7 +182,7 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
180
182
|
</Button>
|
|
181
183
|
)}
|
|
182
184
|
</div>
|
|
183
|
-
</
|
|
185
|
+
</CardHeaderRow>
|
|
184
186
|
</CardHeader>
|
|
185
187
|
<CardContent className="p-6 space-y-4">
|
|
186
188
|
{incident.description && (
|
|
@@ -236,7 +238,7 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
236
238
|
{/* Status Updates Timeline */}
|
|
237
239
|
<Card>
|
|
238
240
|
<CardHeader className="border-b border-border">
|
|
239
|
-
<
|
|
241
|
+
<CardHeaderRow>
|
|
240
242
|
<div className="flex items-center gap-2">
|
|
241
243
|
<MessageSquare className="h-5 w-5 text-muted-foreground" />
|
|
242
244
|
<CardTitle>Status Updates</CardTitle>
|
|
@@ -251,7 +253,7 @@ const IncidentDetailPageContent: React.FC = () => {
|
|
|
251
253
|
Add Update
|
|
252
254
|
</Button>
|
|
253
255
|
)}
|
|
254
|
-
</
|
|
256
|
+
</CardHeaderRow>
|
|
255
257
|
</CardHeader>
|
|
256
258
|
<CardContent className="p-6">
|
|
257
259
|
{/* Add Update Form */}
|
|
@@ -12,15 +12,13 @@ import {
|
|
|
12
12
|
import { CatalogApi, catalogRoutes } from "@checkstack/catalog-common";
|
|
13
13
|
import {
|
|
14
14
|
Card,
|
|
15
|
-
CardHeader,
|
|
16
|
-
CardTitle,
|
|
17
15
|
CardContent,
|
|
18
16
|
Badge,
|
|
19
|
-
|
|
17
|
+
PageLayout,
|
|
20
18
|
EmptyState,
|
|
21
19
|
BackLink,
|
|
22
20
|
} from "@checkstack/ui";
|
|
23
|
-
import {
|
|
21
|
+
import { Clock, ChevronRight, AlertTriangle } from "lucide-react";
|
|
24
22
|
import { formatDistanceToNow } from "date-fns";
|
|
25
23
|
|
|
26
24
|
const SystemIncidentHistoryPageContent: React.FC = () => {
|
|
@@ -35,7 +33,7 @@ const SystemIncidentHistoryPageContent: React.FC = () => {
|
|
|
35
33
|
refetch: refetchIncidents,
|
|
36
34
|
} = incidentClient.listIncidents.useQuery(
|
|
37
35
|
{ systemId, includeResolved: true },
|
|
38
|
-
{ enabled: !!systemId }
|
|
36
|
+
{ enabled: !!systemId },
|
|
39
37
|
);
|
|
40
38
|
|
|
41
39
|
// Fetch systems with useQuery
|
|
@@ -91,36 +89,25 @@ const SystemIncidentHistoryPageContent: React.FC = () => {
|
|
|
91
89
|
}
|
|
92
90
|
};
|
|
93
91
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
// Actions for the page header
|
|
93
|
+
const headerActions = system && (
|
|
94
|
+
<BackLink
|
|
95
|
+
to={resolveRoute(catalogRoutes.routes.systemDetail, {
|
|
96
|
+
systemId: system.id,
|
|
97
|
+
})}
|
|
98
|
+
>
|
|
99
|
+
Back to {system.name}
|
|
100
|
+
</BackLink>
|
|
101
|
+
);
|
|
101
102
|
|
|
102
103
|
return (
|
|
103
|
-
<
|
|
104
|
+
<PageLayout
|
|
105
|
+
title={`Incident History${system ? ` - ${system.name}` : ""}`}
|
|
106
|
+
icon={AlertTriangle}
|
|
107
|
+
loading={loading}
|
|
108
|
+
actions={headerActions}
|
|
109
|
+
>
|
|
104
110
|
<Card>
|
|
105
|
-
<CardHeader className="border-b border-border">
|
|
106
|
-
<div className="flex items-center justify-between">
|
|
107
|
-
<div className="flex items-center gap-2">
|
|
108
|
-
<AlertTriangle className="h-5 w-5 text-muted-foreground" />
|
|
109
|
-
<CardTitle>
|
|
110
|
-
Incident History{system ? ` - ${system.name}` : ""}
|
|
111
|
-
</CardTitle>
|
|
112
|
-
</div>
|
|
113
|
-
{system && (
|
|
114
|
-
<BackLink
|
|
115
|
-
to={resolveRoute(catalogRoutes.routes.systemDetail, {
|
|
116
|
-
systemId: system.id,
|
|
117
|
-
})}
|
|
118
|
-
>
|
|
119
|
-
Back to {system.name}
|
|
120
|
-
</BackLink>
|
|
121
|
-
)}
|
|
122
|
-
</div>
|
|
123
|
-
</CardHeader>
|
|
124
111
|
<CardContent className="p-0">
|
|
125
112
|
{incidents.length === 0 ? (
|
|
126
113
|
<EmptyState
|
|
@@ -172,10 +159,10 @@ const SystemIncidentHistoryPageContent: React.FC = () => {
|
|
|
172
159
|
)}
|
|
173
160
|
</CardContent>
|
|
174
161
|
</Card>
|
|
175
|
-
</
|
|
162
|
+
</PageLayout>
|
|
176
163
|
);
|
|
177
164
|
};
|
|
178
165
|
|
|
179
166
|
export const SystemIncidentHistoryPage = wrapInSuspense(
|
|
180
|
-
SystemIncidentHistoryPageContent
|
|
167
|
+
SystemIncidentHistoryPageContent,
|
|
181
168
|
);
|