@checkstack/maintenance-frontend 0.4.28 → 0.5.0
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 +42 -0
- package/package.json +2 -2
- package/src/components/SystemMaintenancePanel.tsx +48 -114
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# @checkstack/maintenance-frontend
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- bb1fea0: Redesign system detail page with hero banner, two-column layout, plugin metric tiles, and health check slide-over drawer.
|
|
8
|
+
|
|
9
|
+
### New Components
|
|
10
|
+
|
|
11
|
+
- **MetricTile** (`@checkstack/ui`): Compact stat tile with icon, label, value, variant coloring
|
|
12
|
+
- **Sheet** (`@checkstack/ui`): Slide-over drawer built on Radix Dialog primitives
|
|
13
|
+
|
|
14
|
+
### New Extension Slot
|
|
15
|
+
|
|
16
|
+
- **SystemOverviewMetricsSlot** (`@checkstack/catalog-common`): Plugin-contributed at-a-glance metric tiles in the system detail hero banner
|
|
17
|
+
|
|
18
|
+
### Layout Changes
|
|
19
|
+
|
|
20
|
+
- System detail page now uses a hero banner with breadcrumb, status badges, and metric tile strip
|
|
21
|
+
- Two-column layout: monitoring content (left) and system context (right)
|
|
22
|
+
- Health checks rendered as compact card rows instead of heavy accordions
|
|
23
|
+
- Clicking a health check opens a slide-over drawer with summary tiles, timeline charts, and recent runs
|
|
24
|
+
- Right column uses lightweight borderless sections with dividers instead of heavy Card wrappers
|
|
25
|
+
|
|
26
|
+
### Plugin Extensions
|
|
27
|
+
|
|
28
|
+
- Health check, SLO, Incident, and Maintenance plugins each contribute a metric tile to the hero banner
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [bb1fea0]
|
|
33
|
+
- Updated dependencies [bb1fea0]
|
|
34
|
+
- @checkstack/dashboard-frontend@0.4.0
|
|
35
|
+
- @checkstack/ui@1.4.0
|
|
36
|
+
- @checkstack/catalog-common@1.4.0
|
|
37
|
+
- @checkstack/auth-frontend@0.5.26
|
|
38
|
+
|
|
39
|
+
## 0.4.29
|
|
40
|
+
|
|
41
|
+
### Patch Changes
|
|
42
|
+
|
|
43
|
+
- @checkstack/dashboard-frontend@0.3.35
|
|
44
|
+
|
|
3
45
|
## 0.4.28
|
|
4
46
|
|
|
5
47
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/maintenance-frontend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"checkstack": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"@checkstack/auth-frontend": "0.5.25",
|
|
16
16
|
"@checkstack/catalog-common": "1.3.1",
|
|
17
17
|
"@checkstack/common": "0.6.5",
|
|
18
|
-
"@checkstack/dashboard-frontend": "0.3.
|
|
18
|
+
"@checkstack/dashboard-frontend": "0.3.34",
|
|
19
19
|
"@checkstack/frontend-api": "0.3.9",
|
|
20
20
|
"@checkstack/maintenance-common": "0.4.9",
|
|
21
21
|
"@checkstack/signal-frontend": "0.0.15",
|
|
@@ -9,17 +9,8 @@ import {
|
|
|
9
9
|
maintenanceRoutes,
|
|
10
10
|
MAINTENANCE_UPDATED,
|
|
11
11
|
} from "@checkstack/maintenance-common";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
CardHeader,
|
|
15
|
-
CardTitle,
|
|
16
|
-
CardContent,
|
|
17
|
-
Badge,
|
|
18
|
-
LoadingSpinner,
|
|
19
|
-
Button,
|
|
20
|
-
} from "@checkstack/ui";
|
|
21
|
-
import { Wrench, Clock, Calendar, History, ChevronRight } from "lucide-react";
|
|
22
|
-
import { formatDistanceToNow, format } from "date-fns";
|
|
12
|
+
import { LoadingSpinner, Button } from "@checkstack/ui";
|
|
13
|
+
import { Wrench, History } from "lucide-react";
|
|
23
14
|
|
|
24
15
|
type Props = SlotContext<typeof SystemDetailsSlot>;
|
|
25
16
|
|
|
@@ -49,118 +40,61 @@ export const SystemMaintenancePanel: React.FC<Props> = ({ system }) => {
|
|
|
49
40
|
|
|
50
41
|
if (loading) {
|
|
51
42
|
return (
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
</CardContent>
|
|
56
|
-
</Card>
|
|
43
|
+
<div className="flex items-center justify-center rounded-md border border-border/50 bg-card px-3 py-2">
|
|
44
|
+
<LoadingSpinner />
|
|
45
|
+
</div>
|
|
57
46
|
);
|
|
58
47
|
}
|
|
59
48
|
|
|
60
49
|
if (maintenances.length === 0) {
|
|
61
|
-
// Show a subtle card with just the history button when no active maintenances
|
|
62
50
|
return (
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
</Button>
|
|
80
|
-
</div>
|
|
81
|
-
</CardContent>
|
|
82
|
-
</Card>
|
|
51
|
+
<div className="flex items-center justify-between rounded-md border border-border/50 bg-card px-3 py-2">
|
|
52
|
+
<div className="flex items-center gap-2 text-muted-foreground">
|
|
53
|
+
<Wrench className="h-3.5 w-3.5" />
|
|
54
|
+
<span className="text-sm">No planned maintenances</span>
|
|
55
|
+
</div>
|
|
56
|
+
<Button variant="ghost" size="sm" className="h-7 text-xs" asChild>
|
|
57
|
+
<Link
|
|
58
|
+
to={resolveRoute(maintenanceRoutes.routes.systemHistory, {
|
|
59
|
+
systemId: system.id,
|
|
60
|
+
})}
|
|
61
|
+
>
|
|
62
|
+
<History className="h-3 w-3 mr-1" />
|
|
63
|
+
History
|
|
64
|
+
</Link>
|
|
65
|
+
</Button>
|
|
66
|
+
</div>
|
|
83
67
|
);
|
|
84
68
|
}
|
|
85
69
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
case "in_progress": {
|
|
89
|
-
return <Badge variant="warning">In Progress</Badge>;
|
|
90
|
-
}
|
|
91
|
-
case "scheduled": {
|
|
92
|
-
return <Badge variant="info">Scheduled</Badge>;
|
|
93
|
-
}
|
|
94
|
-
default: {
|
|
95
|
-
return <Badge>{status}</Badge>;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
};
|
|
70
|
+
const active = maintenances.filter((m) => m.status === "in_progress");
|
|
71
|
+
const scheduled = maintenances.filter((m) => m.status === "scheduled");
|
|
99
72
|
|
|
100
73
|
return (
|
|
101
|
-
<
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
to={`${resolveRoute(maintenanceRoutes.routes.detail, {
|
|
127
|
-
maintenanceId: m.id,
|
|
128
|
-
})}?from=${system.id}`}
|
|
129
|
-
className="block p-3 rounded-lg border border-border bg-background hover:bg-muted/50 transition-colors"
|
|
130
|
-
>
|
|
131
|
-
<div className="flex items-start justify-between mb-2">
|
|
132
|
-
<div className="flex items-center gap-2">
|
|
133
|
-
<h4 className="font-medium text-foreground">{m.title}</h4>
|
|
134
|
-
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
|
135
|
-
</div>
|
|
136
|
-
{getStatusBadge(m.status)}
|
|
137
|
-
</div>
|
|
138
|
-
{m.description && (
|
|
139
|
-
<p className="text-sm text-muted-foreground mb-2">
|
|
140
|
-
{m.description}
|
|
141
|
-
</p>
|
|
142
|
-
)}
|
|
143
|
-
<div className="flex gap-4 text-xs text-muted-foreground">
|
|
144
|
-
<div className="flex items-center gap-1">
|
|
145
|
-
<Calendar className="h-3 w-3" />
|
|
146
|
-
<span>{format(new Date(m.startAt), "MMM d, HH:mm")}</span>
|
|
147
|
-
</div>
|
|
148
|
-
<div className="flex items-center gap-1">
|
|
149
|
-
<Clock className="h-3 w-3" />
|
|
150
|
-
<span>
|
|
151
|
-
{m.status === "scheduled"
|
|
152
|
-
? `Starts ${formatDistanceToNow(new Date(m.startAt), {
|
|
153
|
-
addSuffix: true,
|
|
154
|
-
})}`
|
|
155
|
-
: `Ends ${formatDistanceToNow(new Date(m.endAt), {
|
|
156
|
-
addSuffix: true,
|
|
157
|
-
})}`}
|
|
158
|
-
</span>
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
</Link>
|
|
162
|
-
))}
|
|
163
|
-
</CardContent>
|
|
164
|
-
</Card>
|
|
74
|
+
<div className="flex items-center justify-between rounded-md border border-warning/30 bg-warning/5 px-3 py-2">
|
|
75
|
+
<div className="flex items-center gap-2 min-w-0">
|
|
76
|
+
<Wrench className="h-3.5 w-3.5 text-warning shrink-0" />
|
|
77
|
+
<span className="text-sm font-medium truncate">
|
|
78
|
+
{active.length > 0
|
|
79
|
+
? `${active.length} in progress`
|
|
80
|
+
: `${scheduled.length} scheduled`}
|
|
81
|
+
</span>
|
|
82
|
+
{active.length > 0 && scheduled.length > 0 && (
|
|
83
|
+
<span className="text-xs text-muted-foreground">
|
|
84
|
+
+ {scheduled.length} scheduled
|
|
85
|
+
</span>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
<Button variant="ghost" size="sm" className="h-7 text-xs shrink-0" asChild>
|
|
89
|
+
<Link
|
|
90
|
+
to={resolveRoute(maintenanceRoutes.routes.systemHistory, {
|
|
91
|
+
systemId: system.id,
|
|
92
|
+
})}
|
|
93
|
+
>
|
|
94
|
+
<History className="h-3 w-3 mr-1" />
|
|
95
|
+
View
|
|
96
|
+
</Link>
|
|
97
|
+
</Button>
|
|
98
|
+
</div>
|
|
165
99
|
);
|
|
166
100
|
};
|