@checkstack/maintenance-frontend 0.4.29 → 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 CHANGED
@@ -1,5 +1,41 @@
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
+
3
39
  ## 0.4.29
4
40
 
5
41
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/maintenance-frontend",
3
- "version": "0.4.29",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "src/index.tsx",
6
6
  "checkstack": {
@@ -9,17 +9,8 @@ import {
9
9
  maintenanceRoutes,
10
10
  MAINTENANCE_UPDATED,
11
11
  } from "@checkstack/maintenance-common";
12
- import {
13
- Card,
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
- <Card>
53
- <CardContent className="p-6 flex justify-center">
54
- <LoadingSpinner />
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
- <Card className="border-border/50">
64
- <CardContent className="p-4">
65
- <div className="flex items-center justify-between">
66
- <div className="flex items-center gap-2 text-muted-foreground">
67
- <Wrench className="h-4 w-4" />
68
- <span className="text-sm">No active maintenances</span>
69
- </div>
70
- <Button variant="ghost" size="sm" asChild>
71
- <Link
72
- to={resolveRoute(maintenanceRoutes.routes.systemHistory, {
73
- systemId: system.id,
74
- })}
75
- >
76
- <History className="h-4 w-4 mr-1" />
77
- View History
78
- </Link>
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 getStatusBadge = (status: string) => {
87
- switch (status) {
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
- <Card className="border-warning/30 bg-warning/5">
102
- <CardHeader className="border-b border-border bg-warning/10">
103
- <div className="flex items-center justify-between">
104
- <div className="flex items-center gap-2">
105
- <Wrench className="h-5 w-5 text-warning" />
106
- <CardTitle className="text-lg font-semibold">
107
- Planned Maintenance
108
- </CardTitle>
109
- </div>
110
- <Button variant="ghost" size="sm" asChild>
111
- <Link
112
- to={resolveRoute(maintenanceRoutes.routes.systemHistory, {
113
- systemId: system.id,
114
- })}
115
- >
116
- <History className="h-4 w-4 mr-1" />
117
- View History
118
- </Link>
119
- </Button>
120
- </div>
121
- </CardHeader>
122
- <CardContent className="p-4 space-y-3">
123
- {maintenances.map((m) => (
124
- <Link
125
- key={m.id}
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
  };