@checkstack/healthcheck-frontend 0.21.0 → 0.23.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 +309 -0
- package/package.json +21 -18
- package/src/auto-charts/extension.tsx +15 -2
- package/src/components/CatalogBrowseHealthFiller.tsx +60 -0
- package/src/components/CollectorList.tsx +10 -0
- package/src/components/HealthCheckDrawer.tsx +35 -4
- package/src/components/HealthCheckRunsTable.tsx +38 -4
- package/src/components/HealthCheckSystemOverview.tsx +19 -11
- package/src/components/HealthSignalsFiller.tsx +76 -0
- package/src/components/SystemHealthBadge.tsx +7 -2
- package/src/components/assignments/ExecutionPanel.tsx +91 -1
- package/src/components/assignments/NotificationsPanel.tsx +8 -237
- package/src/components/assignments/environment-selector.logic.test.ts +68 -0
- package/src/components/assignments/environment-selector.logic.ts +69 -0
- package/src/components/editor/CollectorScriptTestRenderer.tsx +115 -0
- package/src/components/editor/CollectorSection.tsx +80 -13
- package/src/components/editor/EditorPanel.tsx +26 -0
- package/src/components/editor/collector-preview-context.logic.test.ts +101 -0
- package/src/components/editor/collector-preview-context.logic.ts +88 -0
- package/src/index.tsx +65 -23
- package/src/pages/AssignmentIDEPage.tsx +88 -1
- package/src/pages/HealthCheckIDEPage.tsx +74 -0
- package/tsconfig.json +9 -0
- package/src/components/HealthCheckMenuItems.tsx +0 -30
package/src/index.tsx
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createFrontendPlugin,
|
|
3
3
|
createSlotExtension,
|
|
4
|
-
UserMenuItemsSlot,
|
|
5
4
|
} from "@checkstack/frontend-api";
|
|
6
|
-
import {
|
|
7
|
-
import { StrategyPickerPage } from "./pages/StrategyPickerPage";
|
|
8
|
-
import { HealthCheckIDEPage } from "./pages/HealthCheckIDEPage";
|
|
9
|
-
import { AssignmentIDEPage } from "./pages/AssignmentIDEPage";
|
|
10
|
-
import { HealthCheckHistoryPage } from "./pages/HealthCheckHistoryPage";
|
|
11
|
-
import { HealthCheckHistoryDetailPage } from "./pages/HealthCheckHistoryDetailPage";
|
|
12
|
-
import { HealthCheckMenuItems } from "./components/HealthCheckMenuItems";
|
|
13
|
-
import { HealthCheckSystemOverview } from "./components/HealthCheckSystemOverview";
|
|
5
|
+
import { Activity } from "lucide-react";
|
|
14
6
|
import { SystemHealthCheckAssignment } from "./components/SystemHealthCheckAssignment";
|
|
15
7
|
import { SystemHealthBadge } from "./components/SystemHealthBadge";
|
|
16
8
|
import { healthCheckAccess } from "@checkstack/healthcheck-common";
|
|
17
|
-
|
|
9
|
+
// Import directly from the extension module, NOT the `./auto-charts` barrel:
|
|
10
|
+
// the barrel statically re-exports AutoChartGrid + SingleRunChartGrid (both
|
|
11
|
+
// pull in recharts), so importing the extension through it would drag recharts
|
|
12
|
+
// into this eagerly-loaded plugin entry. The extension itself lazy-loads the
|
|
13
|
+
// chart grid.
|
|
14
|
+
import { autoChartExtension } from "./auto-charts/extension";
|
|
18
15
|
|
|
19
16
|
import {
|
|
20
17
|
SystemDetailsSlot,
|
|
21
18
|
CatalogSystemActionsSlot,
|
|
22
19
|
SystemStateBadgesSlot,
|
|
20
|
+
CatalogBrowseHealthSlot,
|
|
21
|
+
SystemSignalsSlot,
|
|
23
22
|
} from "@checkstack/catalog-common";
|
|
24
23
|
import {
|
|
25
24
|
healthcheckRoutes,
|
|
@@ -49,43 +48,70 @@ export default createFrontendPlugin({
|
|
|
49
48
|
routes: [
|
|
50
49
|
{
|
|
51
50
|
route: healthcheckRoutes.routes.config,
|
|
52
|
-
|
|
51
|
+
load: () =>
|
|
52
|
+
import("./pages/HealthCheckConfigPage").then((m) => ({
|
|
53
|
+
default: m.HealthCheckConfigPage,
|
|
54
|
+
})),
|
|
53
55
|
title: "Health Checks",
|
|
54
56
|
accessRule: healthCheckAccess.configuration.manage,
|
|
57
|
+
nav: {
|
|
58
|
+
group: "Reliability",
|
|
59
|
+
icon: Activity,
|
|
60
|
+
// Visible to read-only users (the page itself still gates on manage).
|
|
61
|
+
accessRule: healthCheckAccess.configuration.read,
|
|
62
|
+
},
|
|
55
63
|
},
|
|
56
64
|
{
|
|
57
65
|
route: healthcheckRoutes.routes.create,
|
|
58
|
-
|
|
66
|
+
load: () =>
|
|
67
|
+
import("./pages/StrategyPickerPage").then((m) => ({
|
|
68
|
+
default: m.StrategyPickerPage,
|
|
69
|
+
})),
|
|
59
70
|
title: "Create Health Check",
|
|
60
71
|
accessRule: healthCheckAccess.configuration.manage,
|
|
61
72
|
},
|
|
62
73
|
{
|
|
63
74
|
route: healthcheckRoutes.routes.edit,
|
|
64
|
-
|
|
75
|
+
load: () =>
|
|
76
|
+
import("./pages/HealthCheckIDEPage").then((m) => ({
|
|
77
|
+
default: m.HealthCheckIDEPage,
|
|
78
|
+
})),
|
|
65
79
|
title: "Edit Health Check",
|
|
66
80
|
accessRule: healthCheckAccess.configuration.manage,
|
|
67
81
|
},
|
|
68
82
|
{
|
|
69
83
|
route: healthcheckRoutes.routes.assignments,
|
|
70
|
-
|
|
84
|
+
load: () =>
|
|
85
|
+
import("./pages/AssignmentIDEPage").then((m) => ({
|
|
86
|
+
default: m.AssignmentIDEPage,
|
|
87
|
+
})),
|
|
71
88
|
title: "Health Check Assignments",
|
|
72
89
|
accessRule: healthCheckAccess.configuration.manage,
|
|
73
90
|
},
|
|
74
91
|
{
|
|
75
92
|
route: healthcheckRoutes.routes.history,
|
|
76
|
-
|
|
93
|
+
load: () =>
|
|
94
|
+
import("./pages/HealthCheckHistoryPage").then((m) => ({
|
|
95
|
+
default: m.HealthCheckHistoryPage,
|
|
96
|
+
})),
|
|
77
97
|
title: "Health Check History",
|
|
78
98
|
accessRule: healthCheckAccess.configuration.read,
|
|
79
99
|
},
|
|
80
100
|
{
|
|
81
101
|
route: healthcheckRoutes.routes.historyDetail,
|
|
82
|
-
|
|
102
|
+
load: () =>
|
|
103
|
+
import("./pages/HealthCheckHistoryDetailPage").then((m) => ({
|
|
104
|
+
default: m.HealthCheckHistoryDetailPage,
|
|
105
|
+
})),
|
|
83
106
|
title: "Health Check Detail",
|
|
84
107
|
accessRule: healthCheckAccess.details,
|
|
85
108
|
},
|
|
86
109
|
{
|
|
87
110
|
route: healthcheckRoutes.routes.historyRun,
|
|
88
|
-
|
|
111
|
+
load: () =>
|
|
112
|
+
import("./pages/HealthCheckHistoryDetailPage").then((m) => ({
|
|
113
|
+
default: m.HealthCheckHistoryDetailPage,
|
|
114
|
+
})),
|
|
89
115
|
title: "Health Check Run",
|
|
90
116
|
accessRule: healthCheckAccess.details,
|
|
91
117
|
},
|
|
@@ -93,18 +119,34 @@ export default createFrontendPlugin({
|
|
|
93
119
|
// No APIs needed - components use usePluginClient() directly
|
|
94
120
|
apis: [],
|
|
95
121
|
extensions: [
|
|
96
|
-
createSlotExtension(UserMenuItemsSlot, {
|
|
97
|
-
id: "healthcheck.user-menu.items",
|
|
98
|
-
component: HealthCheckMenuItems,
|
|
99
|
-
metadata: { group: "Reliability" },
|
|
100
|
-
}),
|
|
101
122
|
createSlotExtension(SystemStateBadgesSlot, {
|
|
102
123
|
id: "healthcheck.system-health-badge",
|
|
103
124
|
component: SystemHealthBadge,
|
|
104
125
|
}),
|
|
126
|
+
createSlotExtension(CatalogBrowseHealthSlot, {
|
|
127
|
+
id: "healthcheck.catalog.browse-health",
|
|
128
|
+
// Lazy: only loads when the catalog browse/manage view mounts the slot.
|
|
129
|
+
load: () =>
|
|
130
|
+
import("./components/CatalogBrowseHealthFiller").then((m) => ({
|
|
131
|
+
default: m.CatalogBrowseHealthFiller,
|
|
132
|
+
})),
|
|
133
|
+
}),
|
|
134
|
+
createSlotExtension(SystemSignalsSlot, {
|
|
135
|
+
id: "healthcheck.dashboard.signals",
|
|
136
|
+
// Lazy: only loads when the dashboard overview mounts the slot.
|
|
137
|
+
load: () =>
|
|
138
|
+
import("./components/HealthSignalsFiller").then((m) => ({
|
|
139
|
+
default: m.HealthSignalsFiller,
|
|
140
|
+
})),
|
|
141
|
+
}),
|
|
105
142
|
createSlotExtension(SystemDetailsSlot, {
|
|
106
143
|
id: "healthcheck.system-details.overview",
|
|
107
|
-
|
|
144
|
+
// Heavier overview (drawer pulls recharts) — lazy so it stays out of the
|
|
145
|
+
// initial bundle and loads when a system-detail page renders.
|
|
146
|
+
load: () =>
|
|
147
|
+
import("./components/HealthCheckSystemOverview").then((m) => ({
|
|
148
|
+
default: m.HealthCheckSystemOverview,
|
|
149
|
+
})),
|
|
108
150
|
}),
|
|
109
151
|
createSlotExtension(CatalogSystemActionsSlot, {
|
|
110
152
|
id: "healthcheck.catalog.system-actions",
|
|
@@ -15,7 +15,12 @@ import type {
|
|
|
15
15
|
import { PageLayout, IDELayout, useToast, BackLink, Button } from "@checkstack/ui";
|
|
16
16
|
import { Settings, Plus, Bell } from "lucide-react";
|
|
17
17
|
import { extractErrorMessage, resolveRoute } from "@checkstack/common";
|
|
18
|
-
import { catalogRoutes } from "@checkstack/catalog-common";
|
|
18
|
+
import { catalogRoutes, CatalogApi } from "@checkstack/catalog-common";
|
|
19
|
+
import {
|
|
20
|
+
environmentIdsForMode,
|
|
21
|
+
toggleEnvironmentId,
|
|
22
|
+
type EnvironmentSelectorMode,
|
|
23
|
+
} from "../components/assignments/environment-selector.logic";
|
|
19
24
|
import { healthcheckRoutes } from "@checkstack/healthcheck-common";
|
|
20
25
|
import {
|
|
21
26
|
AssignmentTree,
|
|
@@ -68,6 +73,7 @@ const AssignmentIDEPageContent = () => {
|
|
|
68
73
|
const toast = useToast();
|
|
69
74
|
const healthCheckClient = usePluginClient(HealthCheckApi);
|
|
70
75
|
const satelliteClient = usePluginClient(SatelliteApi);
|
|
76
|
+
const catalogClient = usePluginClient(CatalogApi);
|
|
71
77
|
|
|
72
78
|
// --- Data Fetching ---
|
|
73
79
|
|
|
@@ -87,6 +93,14 @@ const AssignmentIDEPageContent = () => {
|
|
|
87
93
|
|
|
88
94
|
const { data: satellitesData } = satelliteClient.listSatellites.useQuery({});
|
|
89
95
|
|
|
96
|
+
// Environments the system currently belongs to — drives the per-assignment
|
|
97
|
+
// environment selector (the fan-out set is a subset of these).
|
|
98
|
+
const { data: systemEnvironments = [] } =
|
|
99
|
+
catalogClient.getSystemEnvironments.useQuery(
|
|
100
|
+
{ systemId: systemId ?? "" },
|
|
101
|
+
{ enabled: !!systemId },
|
|
102
|
+
);
|
|
103
|
+
|
|
90
104
|
// --- UI State ---
|
|
91
105
|
|
|
92
106
|
const [selectedNode, setSelectedNode] = useState<AssignmentNodeId>();
|
|
@@ -239,6 +253,7 @@ const AssignmentIDEPageContent = () => {
|
|
|
239
253
|
enabled: !currentEnabled,
|
|
240
254
|
stateThresholds: assoc.stateThresholds,
|
|
241
255
|
satelliteIds: assoc.satelliteIds,
|
|
256
|
+
environmentIds: assoc.environmentIds,
|
|
242
257
|
includeLocal: assoc.includeLocal,
|
|
243
258
|
notificationPolicy: assoc.notificationPolicy,
|
|
244
259
|
},
|
|
@@ -266,6 +281,7 @@ const AssignmentIDEPageContent = () => {
|
|
|
266
281
|
enabled: assoc.enabled,
|
|
267
282
|
stateThresholds: thresholds,
|
|
268
283
|
satelliteIds: assoc.satelliteIds,
|
|
284
|
+
environmentIds: assoc.environmentIds,
|
|
269
285
|
includeLocal: assoc.includeLocal,
|
|
270
286
|
notificationPolicy: assoc.notificationPolicy,
|
|
271
287
|
},
|
|
@@ -308,6 +324,7 @@ const AssignmentIDEPageContent = () => {
|
|
|
308
324
|
enabled: assoc.enabled,
|
|
309
325
|
stateThresholds: assoc.stateThresholds,
|
|
310
326
|
satelliteIds: assoc.satelliteIds,
|
|
327
|
+
environmentIds: assoc.environmentIds,
|
|
311
328
|
includeLocal: assoc.includeLocal,
|
|
312
329
|
notificationPolicy: policy,
|
|
313
330
|
},
|
|
@@ -343,6 +360,7 @@ const AssignmentIDEPageContent = () => {
|
|
|
343
360
|
enabled: assoc.enabled,
|
|
344
361
|
stateThresholds: assoc.stateThresholds,
|
|
345
362
|
satelliteIds: assoc.satelliteIds,
|
|
363
|
+
environmentIds: assoc.environmentIds,
|
|
346
364
|
includeLocal: assoc.includeLocal,
|
|
347
365
|
notificationPolicy: undefined,
|
|
348
366
|
},
|
|
@@ -391,6 +409,7 @@ const AssignmentIDEPageContent = () => {
|
|
|
391
409
|
enabled: assoc.enabled,
|
|
392
410
|
stateThresholds: assoc.stateThresholds,
|
|
393
411
|
satelliteIds: newIds,
|
|
412
|
+
environmentIds: assoc.environmentIds,
|
|
394
413
|
includeLocal: assoc.includeLocal,
|
|
395
414
|
notificationPolicy: assoc.notificationPolicy,
|
|
396
415
|
},
|
|
@@ -409,12 +428,69 @@ const AssignmentIDEPageContent = () => {
|
|
|
409
428
|
enabled: assoc.enabled,
|
|
410
429
|
stateThresholds: assoc.stateThresholds,
|
|
411
430
|
satelliteIds: assoc.satelliteIds,
|
|
431
|
+
environmentIds: assoc.environmentIds,
|
|
412
432
|
includeLocal: !assoc.includeLocal,
|
|
413
433
|
notificationPolicy: assoc.notificationPolicy,
|
|
414
434
|
},
|
|
415
435
|
});
|
|
416
436
|
};
|
|
417
437
|
|
|
438
|
+
/**
|
|
439
|
+
* Persist `environmentIds` for an assignment, preserving every other
|
|
440
|
+
* operator-managed field. Used by both the mode switch and the per-env
|
|
441
|
+
* toggle in the "specific" mode.
|
|
442
|
+
*/
|
|
443
|
+
const persistEnvironmentIds = (
|
|
444
|
+
configId: string,
|
|
445
|
+
environmentIds: string[] | null,
|
|
446
|
+
) => {
|
|
447
|
+
if (!systemId) return;
|
|
448
|
+
const assoc = associations.find((a) => a.configurationId === configId);
|
|
449
|
+
if (!assoc) return;
|
|
450
|
+
|
|
451
|
+
associateMutation.mutate({
|
|
452
|
+
systemId,
|
|
453
|
+
body: {
|
|
454
|
+
configurationId: configId,
|
|
455
|
+
enabled: assoc.enabled,
|
|
456
|
+
stateThresholds: assoc.stateThresholds,
|
|
457
|
+
satelliteIds: assoc.satelliteIds,
|
|
458
|
+
environmentIds,
|
|
459
|
+
includeLocal: assoc.includeLocal,
|
|
460
|
+
notificationPolicy: assoc.notificationPolicy,
|
|
461
|
+
},
|
|
462
|
+
});
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const handleSetEnvironmentMode = (
|
|
466
|
+
configId: string,
|
|
467
|
+
mode: EnvironmentSelectorMode,
|
|
468
|
+
) => {
|
|
469
|
+
const assoc = associations.find((a) => a.configurationId === configId);
|
|
470
|
+
// Switching to "specific" seeds with the current explicit set if any,
|
|
471
|
+
// otherwise all current environment ids (a sensible starting point).
|
|
472
|
+
const currentSpecific =
|
|
473
|
+
assoc?.environmentIds && assoc.environmentIds.length > 0
|
|
474
|
+
? assoc.environmentIds
|
|
475
|
+
: systemEnvironments.map((e) => e.id);
|
|
476
|
+
persistEnvironmentIds(
|
|
477
|
+
configId,
|
|
478
|
+
environmentIdsForMode({ mode, selectedIds: currentSpecific }),
|
|
479
|
+
);
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
const handleToggleEnvironment = (configId: string, environmentId: string) => {
|
|
483
|
+
const assoc = associations.find((a) => a.configurationId === configId);
|
|
484
|
+
const currentSpecific =
|
|
485
|
+
assoc?.environmentIds && assoc.environmentIds.length > 0
|
|
486
|
+
? assoc.environmentIds
|
|
487
|
+
: [];
|
|
488
|
+
persistEnvironmentIds(
|
|
489
|
+
configId,
|
|
490
|
+
toggleEnvironmentId({ selectedIds: currentSpecific, environmentId }),
|
|
491
|
+
);
|
|
492
|
+
};
|
|
493
|
+
|
|
418
494
|
const handleSaveRetention = (configId: string) => {
|
|
419
495
|
if (!systemId) return;
|
|
420
496
|
const data = retentionData[configId];
|
|
@@ -567,6 +643,17 @@ const AssignmentIDEPageContent = () => {
|
|
|
567
643
|
onToggleSatellite={(satId) =>
|
|
568
644
|
handleToggleSatellite(configId, satId)
|
|
569
645
|
}
|
|
646
|
+
environmentIds={assoc.environmentIds ?? null}
|
|
647
|
+
environments={systemEnvironments.map((e) => ({
|
|
648
|
+
id: e.id,
|
|
649
|
+
name: e.name,
|
|
650
|
+
}))}
|
|
651
|
+
onSetEnvironmentMode={(mode) =>
|
|
652
|
+
handleSetEnvironmentMode(configId, mode)
|
|
653
|
+
}
|
|
654
|
+
onToggleEnvironment={(envId) =>
|
|
655
|
+
handleToggleEnvironment(configId, envId)
|
|
656
|
+
}
|
|
570
657
|
saving={saving}
|
|
571
658
|
isLocked={isLocked}
|
|
572
659
|
/>
|
|
@@ -20,6 +20,11 @@ import { useCollectors } from "../hooks/useCollectors";
|
|
|
20
20
|
import { EditorTree, type TreeNodeId } from "../components/editor/EditorTree";
|
|
21
21
|
import { EditorPanel } from "../components/editor/EditorPanel";
|
|
22
22
|
import { useProvenanceLock, GitOpsLockBanner } from "@checkstack/gitops-frontend";
|
|
23
|
+
import {
|
|
24
|
+
environmentToPreviewFields,
|
|
25
|
+
findSelectedEnvironment,
|
|
26
|
+
} from "@checkstack/catalog-frontend";
|
|
27
|
+
import { buildTemplatePreviewContext } from "../components/editor/collector-preview-context.logic";
|
|
23
28
|
|
|
24
29
|
|
|
25
30
|
// =============================================================================
|
|
@@ -104,6 +109,23 @@ const HealthCheckIDEPageContent = () => {
|
|
|
104
109
|
[systemsData],
|
|
105
110
|
);
|
|
106
111
|
|
|
112
|
+
// Environments for the collector "Preview as" picker. When the editor was
|
|
113
|
+
// opened from a single system (create-from-system), use that system's
|
|
114
|
+
// environments; otherwise the config may later be assigned to many systems,
|
|
115
|
+
// so a global picker over all environments is acceptable.
|
|
116
|
+
const { data: systemEnvironments = [] } =
|
|
117
|
+
catalogClient.getSystemEnvironments.useQuery(
|
|
118
|
+
{ systemId: systemIdFromUrl ?? "" },
|
|
119
|
+
{ enabled: !!systemIdFromUrl },
|
|
120
|
+
);
|
|
121
|
+
const { data: allEnvironments = [] } = catalogClient.listEnvironments.useQuery(
|
|
122
|
+
{},
|
|
123
|
+
{ enabled: !systemIdFromUrl },
|
|
124
|
+
);
|
|
125
|
+
const previewEnvironments = systemIdFromUrl
|
|
126
|
+
? systemEnvironments
|
|
127
|
+
: allEnvironments;
|
|
128
|
+
|
|
107
129
|
// --- Form State ---
|
|
108
130
|
|
|
109
131
|
const [formState, setFormState] = useState<EditorFormState>({
|
|
@@ -122,6 +144,11 @@ const HealthCheckIDEPageContent = () => {
|
|
|
122
144
|
const [selectedSystemIds, setSelectedSystemIds] = useState<string[]>(
|
|
123
145
|
systemIdFromUrl ? [systemIdFromUrl] : [],
|
|
124
146
|
);
|
|
147
|
+
// Selected "Preview as" environment id for collector config templating.
|
|
148
|
+
// Pure editor-local UI state (never persisted) — shared across collectors.
|
|
149
|
+
const [previewEnvironmentId, setPreviewEnvironmentId] = useState<
|
|
150
|
+
string | null
|
|
151
|
+
>(null);
|
|
125
152
|
|
|
126
153
|
// Initialize form from existing configuration (edit mode).
|
|
127
154
|
//
|
|
@@ -282,6 +309,49 @@ const HealthCheckIDEPageContent = () => {
|
|
|
282
309
|
|
|
283
310
|
const isValid = validationIssues.length === 0;
|
|
284
311
|
|
|
312
|
+
// --- Template preview context ---
|
|
313
|
+
|
|
314
|
+
// Build the sample `{ environment, check, system }` context fed to the
|
|
315
|
+
// collector config form so `{{ environment.* }}` previews live. `undefined`
|
|
316
|
+
// until an environment is picked, so the preview line stays hidden. Shape
|
|
317
|
+
// mirrors the backend run-time render context (see `queue-executor.ts`).
|
|
318
|
+
const templatePreviewContext = useMemo<
|
|
319
|
+
Record<string, unknown> | undefined
|
|
320
|
+
>(() => {
|
|
321
|
+
const selectedEnv = findSelectedEnvironment({
|
|
322
|
+
environments: previewEnvironments,
|
|
323
|
+
selectedId: previewEnvironmentId,
|
|
324
|
+
});
|
|
325
|
+
if (!selectedEnv) return;
|
|
326
|
+
|
|
327
|
+
const systemMeta = systemIdFromUrl
|
|
328
|
+
? {
|
|
329
|
+
id: systemIdFromUrl,
|
|
330
|
+
name:
|
|
331
|
+
systems.find((s) => s.id === systemIdFromUrl)?.name ??
|
|
332
|
+
systemIdFromUrl,
|
|
333
|
+
}
|
|
334
|
+
: undefined;
|
|
335
|
+
|
|
336
|
+
return buildTemplatePreviewContext({
|
|
337
|
+
environmentFields: environmentToPreviewFields(selectedEnv),
|
|
338
|
+
check: {
|
|
339
|
+
id: configId ?? "new",
|
|
340
|
+
name: formState.name || "Health check",
|
|
341
|
+
intervalSeconds: formState.intervalSeconds,
|
|
342
|
+
},
|
|
343
|
+
system: systemMeta,
|
|
344
|
+
});
|
|
345
|
+
}, [
|
|
346
|
+
previewEnvironments,
|
|
347
|
+
previewEnvironmentId,
|
|
348
|
+
systemIdFromUrl,
|
|
349
|
+
systems,
|
|
350
|
+
configId,
|
|
351
|
+
formState.name,
|
|
352
|
+
formState.intervalSeconds,
|
|
353
|
+
]);
|
|
354
|
+
|
|
285
355
|
// --- Save ---
|
|
286
356
|
|
|
287
357
|
const associateMutation = healthCheckClient.associateSystem.useMutation();
|
|
@@ -466,6 +536,10 @@ const HealthCheckIDEPageContent = () => {
|
|
|
466
536
|
setSelectedSystemIds(ids);
|
|
467
537
|
setIsDirty(true);
|
|
468
538
|
}}
|
|
539
|
+
previewEnvironments={previewEnvironments}
|
|
540
|
+
previewEnvironmentId={previewEnvironmentId}
|
|
541
|
+
onPreviewEnvironmentChange={setPreviewEnvironmentId}
|
|
542
|
+
templatePreviewContext={templatePreviewContext}
|
|
469
543
|
/>
|
|
470
544
|
{configId && (
|
|
471
545
|
<ExtensionSlot
|
package/tsconfig.json
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
{
|
|
14
14
|
"path": "../catalog-common"
|
|
15
15
|
},
|
|
16
|
+
{
|
|
17
|
+
"path": "../catalog-frontend"
|
|
18
|
+
},
|
|
16
19
|
{
|
|
17
20
|
"path": "../common"
|
|
18
21
|
},
|
|
@@ -31,6 +34,12 @@
|
|
|
31
34
|
{
|
|
32
35
|
"path": "../satellite-common"
|
|
33
36
|
},
|
|
37
|
+
{
|
|
38
|
+
"path": "../script-packages-frontend"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"path": "../secrets-frontend"
|
|
42
|
+
},
|
|
34
43
|
{
|
|
35
44
|
"path": "../signal-frontend"
|
|
36
45
|
},
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Link } from "react-router-dom";
|
|
3
|
-
import { Activity } from "lucide-react";
|
|
4
|
-
import type { UserMenuItemsContext } from "@checkstack/frontend-api";
|
|
5
|
-
import { DropdownMenuItem } from "@checkstack/ui";
|
|
6
|
-
import { resolveRoute } from "@checkstack/common";
|
|
7
|
-
import {
|
|
8
|
-
healthcheckRoutes,
|
|
9
|
-
healthCheckAccess,
|
|
10
|
-
pluginMetadata,
|
|
11
|
-
} from "@checkstack/healthcheck-common";
|
|
12
|
-
|
|
13
|
-
export const HealthCheckMenuItems = ({
|
|
14
|
-
accessRules: userPerms,
|
|
15
|
-
}: UserMenuItemsContext) => {
|
|
16
|
-
const qualifiedId = `${pluginMetadata.pluginId}.${healthCheckAccess.configuration.read.id}`;
|
|
17
|
-
const canRead = userPerms.includes("*") || userPerms.includes(qualifiedId);
|
|
18
|
-
|
|
19
|
-
if (!canRead) {
|
|
20
|
-
return <React.Fragment />;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<Link to={resolveRoute(healthcheckRoutes.routes.config)}>
|
|
25
|
-
<DropdownMenuItem icon={<Activity className="w-4 h-4" />}>
|
|
26
|
-
Health Checks
|
|
27
|
-
</DropdownMenuItem>
|
|
28
|
-
</Link>
|
|
29
|
-
);
|
|
30
|
-
};
|