@burdenoff/microfe-assethandler 2026.703.6 → 2026.703.7
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/dist/assethandler/ops/NewWorkOrderDialog.js +164 -0
- package/dist/assethandler/ops/NewWorkOrderDialog.js.map +1 -0
- package/dist/assethandler/ops/ScheduleMaintenanceDialog.js +197 -0
- package/dist/assethandler/ops/ScheduleMaintenanceDialog.js.map +1 -0
- package/dist/assethandler/pages/AiPredictionsPage.js +112 -54
- package/dist/assethandler/pages/AiPredictionsPage.js.map +1 -1
- package/dist/assethandler/pages/CmdbBrowserPage.js +195 -36
- package/dist/assethandler/pages/CmdbBrowserPage.js.map +1 -1
- package/dist/assethandler/pages/DigitalTwinPage.js +162 -31
- package/dist/assethandler/pages/DigitalTwinPage.js.map +1 -1
- package/dist/assethandler/pages/DiscoveryJobsPage.js +85 -55
- package/dist/assethandler/pages/DiscoveryJobsPage.js.map +1 -1
- package/dist/assethandler/pages/EsgDashboardPage.js +189 -60
- package/dist/assethandler/pages/EsgDashboardPage.js.map +1 -1
- package/dist/assethandler/pages/IotDevicesPage.js +206 -38
- package/dist/assethandler/pages/IotDevicesPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeDetailPage.js +221 -114
- package/dist/assethandler/pages/ItilChangeDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeManagementPage.js +86 -61
- package/dist/assethandler/pages/ItilChangeManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilDialogs.js +361 -0
- package/dist/assethandler/pages/ItilDialogs.js.map +1 -0
- package/dist/assethandler/pages/ItilIncidentDetailPage.js +370 -105
- package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilIncidentManagementPage.js +130 -103
- package/dist/assethandler/pages/ItilIncidentManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilItilhubPage.js +186 -132
- package/dist/assethandler/pages/ItilItilhubPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemDetailPage.js +195 -96
- package/dist/assethandler/pages/ItilProblemDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemManagementPage.js +83 -58
- package/dist/assethandler/pages/ItilProblemManagementPage.js.map +1 -1
- package/dist/assethandler/pages/KnowledgeBasePage.js +205 -75
- package/dist/assethandler/pages/KnowledgeBasePage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js +212 -96
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js +70 -38
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js +470 -116
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsOperationsHubPage.js +154 -102
- package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +386 -79
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ProvenancePage.js +102 -56
- package/dist/assethandler/pages/ProvenancePage.js.map +1 -1
- package/dist/assethandler/pages/SamLicensesPage.js +186 -36
- package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js +147 -65
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js +349 -124
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js +191 -116
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityHubPage.js +421 -184
- package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { useAssetHandlerStore as e } from "../store/assethandlerStore.js";
|
|
2
|
+
import { notify as t } from "../utils/toast.js";
|
|
3
|
+
import { Pagination as n, usePagination as r } from "../components/Pagination.js";
|
|
4
|
+
import "../components/index.js";
|
|
5
|
+
import { useState as i } from "react";
|
|
6
|
+
import { BrainCircuit as a } from "lucide-react";
|
|
7
|
+
import { gql as o } from "@apollo/client";
|
|
8
|
+
import { useMutation as s, useQuery as c } from "@apollo/client/react";
|
|
9
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
10
|
+
import { Button as d, EmphasisPanel as f, GradientText as p, IllustratedEmptyState as m, Label as h, PagePurpose as g, Select as _, SelectContent as v, SelectItem as y, SelectTrigger as b, SelectValue as x } from "@burdenoff/fe-libs/ui";
|
|
7
11
|
//#region src/assethandler/pages/AiPredictionsPage.tsx
|
|
8
|
-
var
|
|
12
|
+
var S = o`
|
|
9
13
|
query AssetHandlerAiPredictions {
|
|
10
14
|
aiPredictions {
|
|
11
15
|
id
|
|
@@ -18,88 +22,130 @@ var d = n`
|
|
|
18
22
|
modelVersion
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
|
-
`,
|
|
25
|
+
`, C = o`
|
|
22
26
|
mutation AssetHandlerRequestAiPrediction($input: RequestAIPredictionInput!) {
|
|
23
27
|
requestAIPrediction(input: $input) {
|
|
24
28
|
id
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
31
|
+
`, w = [
|
|
32
|
+
{
|
|
33
|
+
value: "maintenance-risk",
|
|
34
|
+
label: "Maintenance risk"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
value: "failure-forecast",
|
|
38
|
+
label: "Failure forecast"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
value: "utilization-forecast",
|
|
42
|
+
label: "Utilization forecast"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
value: "anomaly-detection",
|
|
46
|
+
label: "Anomaly detection"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
value: "end-of-life",
|
|
50
|
+
label: "End-of-life projection"
|
|
51
|
+
}
|
|
52
|
+
], T = (e) => w.find((t) => t.value === e)?.label ?? e.replace(/-/g, " ");
|
|
53
|
+
function E() {
|
|
54
|
+
let o = e((e) => e.assets), [E, D] = i(""), [O, k] = i("maintenance-risk"), { data: A, loading: j, refetch: M } = c(S, { fetchPolicy: "cache-and-network" }), [N, { loading: P }] = s(C, {
|
|
55
|
+
onCompleted: () => {
|
|
56
|
+
t.success("Prediction requested", "The model result will appear below shortly."), M();
|
|
57
|
+
},
|
|
58
|
+
onError: (e) => t.error("Could not run prediction", e.message)
|
|
59
|
+
}), F = A?.aiPredictions ?? [], I = r(F, { pageSize: 8 });
|
|
60
|
+
return /* @__PURE__ */ u("div", {
|
|
33
61
|
className: "space-y-4 p-4",
|
|
34
62
|
children: [
|
|
35
|
-
/* @__PURE__ */
|
|
63
|
+
/* @__PURE__ */ u("h1", {
|
|
36
64
|
className: "flex items-center gap-2 text-2xl font-semibold",
|
|
37
65
|
children: [
|
|
38
|
-
/* @__PURE__ */ a
|
|
66
|
+
/* @__PURE__ */ l(a, { className: "h-6 w-6" }),
|
|
39
67
|
" ",
|
|
40
|
-
/* @__PURE__ */
|
|
68
|
+
/* @__PURE__ */ l(p, { children: "AI Predictions" })
|
|
41
69
|
]
|
|
42
70
|
}),
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
-
/* @__PURE__ */
|
|
71
|
+
/* @__PURE__ */ l(g, { children: "Forecast failures before they happen. Pick an asset and a model to get a risk score, confidence level and a concrete recommendation — so you can schedule preventive maintenance instead of reacting to breakdowns. Use it to prioritise which high-value or aging assets to service next." }),
|
|
72
|
+
/* @__PURE__ */ u(f, { children: [/* @__PURE__ */ l("h2", {
|
|
45
73
|
className: "text-sm font-semibold mb-3",
|
|
46
74
|
children: "Run a prediction"
|
|
47
|
-
}), /* @__PURE__ */
|
|
75
|
+
}), /* @__PURE__ */ u("form", {
|
|
48
76
|
className: "grid gap-3 md:grid-cols-3",
|
|
49
77
|
onSubmit: (e) => {
|
|
50
|
-
e.preventDefault(),
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
78
|
+
if (e.preventDefault(), !E) {
|
|
79
|
+
t.warning("Asset required", "Select an asset to run a prediction against.");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
N({ variables: { input: {
|
|
83
|
+
assetId: E,
|
|
84
|
+
predictionType: O
|
|
58
85
|
} } });
|
|
59
86
|
},
|
|
60
87
|
children: [
|
|
61
|
-
/* @__PURE__ */
|
|
62
|
-
className: "
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
/* @__PURE__ */ u("div", {
|
|
89
|
+
className: "space-y-2",
|
|
90
|
+
children: [/* @__PURE__ */ l(h, { children: "Asset" }), /* @__PURE__ */ u(_, {
|
|
91
|
+
value: E,
|
|
92
|
+
onValueChange: D,
|
|
93
|
+
children: [/* @__PURE__ */ l(b, { children: /* @__PURE__ */ l(x, { placeholder: "Select an asset" }) }), /* @__PURE__ */ l(v, { children: o.map((e) => /* @__PURE__ */ u(y, {
|
|
94
|
+
value: e.id,
|
|
95
|
+
children: [
|
|
96
|
+
e.assetTag,
|
|
97
|
+
" — ",
|
|
98
|
+
e.name
|
|
99
|
+
]
|
|
100
|
+
}, e.id)) })]
|
|
101
|
+
})]
|
|
66
102
|
}),
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
-
className: "
|
|
69
|
-
children: "Prediction Type
|
|
103
|
+
/* @__PURE__ */ u("div", {
|
|
104
|
+
className: "space-y-2",
|
|
105
|
+
children: [/* @__PURE__ */ l(h, { children: "Prediction Type" }), /* @__PURE__ */ u(_, {
|
|
106
|
+
value: O,
|
|
107
|
+
onValueChange: (e) => k(e),
|
|
108
|
+
children: [/* @__PURE__ */ l(b, { children: /* @__PURE__ */ l(x, {}) }), /* @__PURE__ */ l(v, { children: w.map((e) => /* @__PURE__ */ l(y, {
|
|
109
|
+
value: e.value,
|
|
110
|
+
children: e.label
|
|
111
|
+
}, e.value)) })]
|
|
112
|
+
})]
|
|
70
113
|
}),
|
|
71
|
-
/* @__PURE__ */
|
|
72
|
-
className: "
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
114
|
+
/* @__PURE__ */ l("div", {
|
|
115
|
+
className: "flex items-end",
|
|
116
|
+
children: /* @__PURE__ */ l(d, {
|
|
117
|
+
className: "w-full",
|
|
118
|
+
disabled: P,
|
|
119
|
+
type: "submit",
|
|
120
|
+
children: P ? "Running…" : "Run Prediction"
|
|
121
|
+
})
|
|
76
122
|
})
|
|
77
123
|
]
|
|
78
124
|
})] }),
|
|
79
|
-
/* @__PURE__ */
|
|
125
|
+
/* @__PURE__ */ u("div", {
|
|
80
126
|
className: "grid gap-3 md:grid-cols-2",
|
|
81
127
|
children: [
|
|
82
|
-
|
|
128
|
+
j && F.length === 0 ? /* @__PURE__ */ l("div", {
|
|
83
129
|
className: "space-y-2 px-4 py-4",
|
|
84
|
-
children: Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */
|
|
130
|
+
children: Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */ l("div", { className: "h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
|
|
85
131
|
}) : null,
|
|
86
|
-
!
|
|
132
|
+
!j && F.length === 0 ? /* @__PURE__ */ l(m, {
|
|
87
133
|
illustration: "empty-data",
|
|
88
134
|
title: "No AI predictions available yet",
|
|
89
|
-
description: "
|
|
135
|
+
description: "Run a prediction above to generate a risk score and recommendation."
|
|
90
136
|
}) : null,
|
|
91
|
-
|
|
137
|
+
I.pageItems.map((e) => /* @__PURE__ */ u("article", {
|
|
92
138
|
className: "rounded-lg border p-4",
|
|
93
139
|
children: [
|
|
94
|
-
/* @__PURE__ */
|
|
140
|
+
/* @__PURE__ */ u("p", {
|
|
95
141
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
96
142
|
children: [
|
|
97
|
-
e.predictionType,
|
|
143
|
+
T(e.predictionType),
|
|
98
144
|
" • ",
|
|
99
145
|
e.assetId
|
|
100
146
|
]
|
|
101
147
|
}),
|
|
102
|
-
/* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ u("h2", {
|
|
103
149
|
className: "mt-1 text-base font-semibold",
|
|
104
150
|
children: [
|
|
105
151
|
"Risk score ",
|
|
@@ -107,7 +153,7 @@ function p() {
|
|
|
107
153
|
"%"
|
|
108
154
|
]
|
|
109
155
|
}),
|
|
110
|
-
/* @__PURE__ */
|
|
156
|
+
/* @__PURE__ */ u("p", {
|
|
111
157
|
className: "mt-1 text-sm text-text-secondary",
|
|
112
158
|
children: [
|
|
113
159
|
"Confidence ",
|
|
@@ -115,11 +161,11 @@ function p() {
|
|
|
115
161
|
"%"
|
|
116
162
|
]
|
|
117
163
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
164
|
+
/* @__PURE__ */ l("p", {
|
|
119
165
|
className: "mt-2 text-sm",
|
|
120
166
|
children: e.recommendation
|
|
121
167
|
}),
|
|
122
|
-
/* @__PURE__ */
|
|
168
|
+
/* @__PURE__ */ u("p", {
|
|
123
169
|
className: "mt-2 text-xs text-text-secondary",
|
|
124
170
|
children: [
|
|
125
171
|
e.modelVersion,
|
|
@@ -130,11 +176,23 @@ function p() {
|
|
|
130
176
|
]
|
|
131
177
|
}, e.id))
|
|
132
178
|
]
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ l(n, {
|
|
181
|
+
page: I.page,
|
|
182
|
+
pageCount: I.pageCount,
|
|
183
|
+
rangeStart: I.rangeStart,
|
|
184
|
+
rangeEnd: I.rangeEnd,
|
|
185
|
+
totalItems: I.totalItems,
|
|
186
|
+
canPrev: I.canPrev,
|
|
187
|
+
canNext: I.canNext,
|
|
188
|
+
onPrev: I.prevPage,
|
|
189
|
+
onNext: I.nextPage,
|
|
190
|
+
itemLabel: "predictions"
|
|
133
191
|
})
|
|
134
192
|
]
|
|
135
193
|
});
|
|
136
194
|
}
|
|
137
195
|
//#endregion
|
|
138
|
-
export {
|
|
196
|
+
export { E as AiPredictionsPage };
|
|
139
197
|
|
|
140
198
|
//# sourceMappingURL=AiPredictionsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiPredictionsPage.js","names":[],"sources":["../../../src/assethandler/pages/AiPredictionsPage.tsx"],"sourcesContent":["import { BrainCircuit } from 'lucide-react';\nimport {\n GradientText,\n IllustratedEmptyState,\n EmphasisPanel,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\n\nconst AI_PREDICTIONS_QUERY = gql`\n query AssetHandlerAiPredictions {\n aiPredictions {\n id\n assetId\n predictionType\n score\n confidence\n recommendation\n generatedAt\n modelVersion\n }\n }\n`;\n\nconst REQUEST_AI_PREDICTION_MUTATION = gql`\n mutation AssetHandlerRequestAiPrediction($input: RequestAIPredictionInput!) {\n requestAIPrediction(input: $input) {\n id\n }\n }\n`;\n\nexport function AiPredictionsPage() {\n const [assetId, setAssetId] = useState('AST-001');\n\n const { data, loading, refetch } = useQuery<{\n aiPredictions: Array<{\n id: string;\n assetId: string;\n predictionType: string;\n score: number;\n confidence: number;\n recommendation: string;\n generatedAt: string;\n modelVersion: string;\n }>;\n }>(AI_PREDICTIONS_QUERY, { fetchPolicy: 'cache-and-network' });\n\n const [requestPrediction, { loading: requesting }] = useMutation(REQUEST_AI_PREDICTION_MUTATION, {\n onCompleted: () => {\n void refetch();\n },\n });\n\n const predictions = data?.aiPredictions ?? [];\n\n return (\n <div className=\"space-y-4 p-4\">\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <BrainCircuit className=\"h-6 w-6\" /> <GradientText>AI Predictions</GradientText>\n </h1>\n <PagePurpose>\n Forecast failures before they happen. Enter an asset and run a model to get a risk score,\n confidence level and a concrete recommendation — so you can schedule preventive maintenance\n instead of reacting to breakdowns. Use it to prioritise which high-value or aging assets to\n service next.\n </PagePurpose>\n <EmphasisPanel>\n <h2 className=\"text-sm font-semibold mb-3\">Run a prediction</h2>\n <form\n className=\"grid gap-3 md:grid-cols-3\"\n onSubmit={(event) => {\n event.preventDefault();\n void requestPrediction({\n variables: {\n input: {\n assetId,\n predictionType: 'maintenance-risk',\n featureVector: {\n runtimeHours: 10240,\n lastIncidentDaysAgo: 9,\n temperatureVariance: 0.23,\n },\n },\n },\n });\n }}\n >\n <input\n className=\"rounded-md border px-3 py-2\"\n value={assetId}\n onChange={(event) => setAssetId(event.target.value)}\n aria-label=\"Asset ID\"\n />\n <div className=\"text-sm text-text-secondary\">Prediction Type: maintenance-risk</div>\n <button\n className=\"rounded-md bg-action-primary-bg px-3 py-2 text-action-primary-text\"\n disabled={requesting}\n type=\"submit\"\n >\n {requesting ? 'Running...' : 'Run Prediction'}\n </button>\n </form>\n </EmphasisPanel>\n <div className=\"grid gap-3 md:grid-cols-2\">\n {loading && predictions.length === 0 ? (\n <div className=\"space-y-2 px-4 py-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n ) : null}\n {!loading && predictions.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No AI predictions available yet\"\n description=\"AI-generated predictions for your assets will appear here.\"\n />\n ) : null}\n {predictions.map((prediction) => (\n <article key={prediction.id} className=\"rounded-lg border p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {prediction.predictionType} • {prediction.assetId}\n </p>\n <h2 className=\"mt-1 text-base font-semibold\">\n Risk score {(prediction.score * 100).toFixed(1)}%\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Confidence {(prediction.confidence * 100).toFixed(1)}%\n </p>\n <p className=\"mt-2 text-sm\">{prediction.recommendation}</p>\n <p className=\"mt-2 text-xs text-text-secondary\">\n {prediction.modelVersion} • {new Date(prediction.generatedAt).toLocaleString()}\n </p>\n </article>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAWA,IAAM,IAAuB,CAAG;;;;;;;;;;;;;GAe1B,IAAiC,CAAG;;;;;;;AAQ1C,SAAgB,IAAoB;CAClC,IAAM,CAAC,GAAS,KAAc,EAAS,UAAU,EAE3C,EAAE,SAAM,YAAS,eAAY,EAWhC,GAAsB,EAAE,aAAa,qBAAqB,CAAC,EAExD,CAAC,GAAmB,EAAE,SAAS,OAAgB,EAAY,GAAgC,EAC/F,mBAAmB;AACZ,KAAS;IAEjB,CAAC,EAEI,IAAc,GAAM,iBAAiB,EAAE;AAE7C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,MAAD;IAAI,WAAU;cAAd;KACE,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA;;KAAC,kBAAC,GAAD,EAAA,UAAc,kBAA6B,CAAA;KAC7E;;GACL,kBAAC,GAAD,EAAA,UAAa,mSAKC,CAAA;GACd,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cAA6B;IAAqB,CAAA,EAChE,kBAAC,QAAD;IACE,WAAU;IACV,WAAW,MAAU;AAEd,KADL,EAAM,gBAAgB,EACjB,EAAkB,EACrB,WAAW,EACT,OAAO;MACL;MACA,gBAAgB;MAChB,eAAe;OACb,cAAc;OACd,qBAAqB;OACrB,qBAAqB;OACtB;MACF,EACF,EACF,CAAC;;cAhBN;KAmBE,kBAAC,SAAD;MACE,WAAU;MACV,OAAO;MACP,WAAW,MAAU,EAAW,EAAM,OAAO,MAAM;MACnD,cAAW;MACX,CAAA;KACF,kBAAC,OAAD;MAAK,WAAU;gBAA8B;MAAuC,CAAA;KACpF,kBAAC,UAAD;MACE,WAAU;MACV,UAAU;MACV,MAAK;gBAEJ,IAAa,eAAe;MACtB,CAAA;KACJ;MACO,EAAA,CAAA;GAChB,kBAAC,OAAD;IAAK,WAAU;cAAf;KACG,KAAW,EAAY,WAAW,IACjC,kBAAC,OAAD;MAAK,WAAU;gBACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,OAAD,EAAa,WAAU,8DAA+D,EAA5E,EAA4E,CACtF;MACE,CAAA,GACJ;KACH,CAAC,KAAW,EAAY,WAAW,IAClC,kBAAC,GAAD;MACE,cAAa;MACb,OAAM;MACN,aAAY;MACZ,CAAA,GACA;KACH,EAAY,KAAK,MAChB,kBAAC,WAAD;MAA6B,WAAU;gBAAvC;OACE,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG,EAAW;SAAe;SAAI,EAAW;SACxC;;OACJ,kBAAC,MAAD;QAAI,WAAU;kBAAd;SAA6C;UAC9B,EAAW,QAAQ,KAAK,QAAQ,EAAE;SAAC;SAC7C;;OACL,kBAAC,KAAD;QAAG,WAAU;kBAAb;SAAgD;UACjC,EAAW,aAAa,KAAK,QAAQ,EAAE;SAAC;SACnD;;OACJ,kBAAC,KAAD;QAAG,WAAU;kBAAgB,EAAW;QAAmB,CAAA;OAC3D,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG,EAAW;SAAa;SAAI,IAAI,KAAK,EAAW,YAAY,CAAC,gBAAgB;SAC5E;;OACI;QAdI,EAAW,GAcf,CACV;KACE;;GACF"}
|
|
1
|
+
{"version":3,"file":"AiPredictionsPage.js","names":[],"sources":["../../../src/assethandler/pages/AiPredictionsPage.tsx"],"sourcesContent":["import type React from 'react';\nimport { BrainCircuit } from 'lucide-react';\nimport {\n Button,\n GradientText,\n IllustratedEmptyState,\n EmphasisPanel,\n PagePurpose,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { Pagination, usePagination } from '../components';\nimport { notify } from '../utils/toast';\n\nconst AI_PREDICTIONS_QUERY = gql`\n query AssetHandlerAiPredictions {\n aiPredictions {\n id\n assetId\n predictionType\n score\n confidence\n recommendation\n generatedAt\n modelVersion\n }\n }\n`;\n\nconst REQUEST_AI_PREDICTION_MUTATION = gql`\n mutation AssetHandlerRequestAiPrediction($input: RequestAIPredictionInput!) {\n requestAIPrediction(input: $input) {\n id\n }\n }\n`;\n\ninterface AiPrediction {\n id: string;\n assetId: string;\n predictionType: string;\n score: number;\n confidence: number;\n recommendation: string;\n generatedAt: string;\n modelVersion: string;\n}\n\n// Prediction model families exposed by the AI service. Values follow the\n// service's kebab-case convention (matches persisted `predictionType`).\nconst PREDICTION_TYPES = [\n { value: 'maintenance-risk', label: 'Maintenance risk' },\n { value: 'failure-forecast', label: 'Failure forecast' },\n { value: 'utilization-forecast', label: 'Utilization forecast' },\n { value: 'anomaly-detection', label: 'Anomaly detection' },\n { value: 'end-of-life', label: 'End-of-life projection' },\n] as const;\n\nconst humanizePredictionType = (value: string): string =>\n PREDICTION_TYPES.find((t) => t.value === value)?.label ?? value.replace(/-/g, ' ');\n\nexport function AiPredictionsPage() {\n const assets = useAssetHandlerStore((s) => s.assets);\n const [assetId, setAssetId] = useState('');\n const [predictionType, setPredictionType] =\n useState<(typeof PREDICTION_TYPES)[number]['value']>('maintenance-risk');\n\n const { data, loading, refetch } = useQuery<{ aiPredictions: AiPrediction[] }>(\n AI_PREDICTIONS_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n\n const [requestPrediction, { loading: requesting }] = useMutation(REQUEST_AI_PREDICTION_MUTATION, {\n onCompleted: () => {\n notify.success('Prediction requested', 'The model result will appear below shortly.');\n void refetch();\n },\n onError: (error) => notify.error('Could not run prediction', error.message),\n });\n\n const predictions = data?.aiPredictions ?? [];\n const pagination = usePagination(predictions, { pageSize: 8 });\n\n const handleRun = (event: React.FormEvent) => {\n event.preventDefault();\n if (!assetId) {\n notify.warning('Asset required', 'Select an asset to run a prediction against.');\n return;\n }\n void requestPrediction({\n variables: { input: { assetId, predictionType } },\n });\n };\n\n return (\n <div className=\"space-y-4 p-4\">\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <BrainCircuit className=\"h-6 w-6\" /> <GradientText>AI Predictions</GradientText>\n </h1>\n <PagePurpose>\n Forecast failures before they happen. Pick an asset and a model to get a risk score,\n confidence level and a concrete recommendation — so you can schedule preventive maintenance\n instead of reacting to breakdowns. Use it to prioritise which high-value or aging assets to\n service next.\n </PagePurpose>\n <EmphasisPanel>\n <h2 className=\"text-sm font-semibold mb-3\">Run a prediction</h2>\n <form className=\"grid gap-3 md:grid-cols-3\" onSubmit={handleRun}>\n <div className=\"space-y-2\">\n <Label>Asset</Label>\n <Select value={assetId} onValueChange={setAssetId}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select an asset\" />\n </SelectTrigger>\n <SelectContent>\n {assets.map((asset) => (\n <SelectItem key={asset.id} value={asset.id}>\n {asset.assetTag} — {asset.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Prediction Type</Label>\n <Select\n value={predictionType}\n onValueChange={(v) => setPredictionType(v as typeof predictionType)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {PREDICTION_TYPES.map((t) => (\n <SelectItem key={t.value} value={t.value}>\n {t.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex items-end\">\n <Button className=\"w-full\" disabled={requesting} type=\"submit\">\n {requesting ? 'Running…' : 'Run Prediction'}\n </Button>\n </div>\n </form>\n </EmphasisPanel>\n <div className=\"grid gap-3 md:grid-cols-2\">\n {loading && predictions.length === 0 ? (\n <div className=\"space-y-2 px-4 py-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n ) : null}\n {!loading && predictions.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No AI predictions available yet\"\n description=\"Run a prediction above to generate a risk score and recommendation.\"\n />\n ) : null}\n {pagination.pageItems.map((prediction) => (\n <article key={prediction.id} className=\"rounded-lg border p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {humanizePredictionType(prediction.predictionType)} • {prediction.assetId}\n </p>\n <h2 className=\"mt-1 text-base font-semibold\">\n Risk score {(prediction.score * 100).toFixed(1)}%\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Confidence {(prediction.confidence * 100).toFixed(1)}%\n </p>\n <p className=\"mt-2 text-sm\">{prediction.recommendation}</p>\n <p className=\"mt-2 text-xs text-text-secondary\">\n {prediction.modelVersion} • {new Date(prediction.generatedAt).toLocaleString()}\n </p>\n </article>\n ))}\n </div>\n <Pagination\n page={pagination.page}\n pageCount={pagination.pageCount}\n rangeStart={pagination.rangeStart}\n rangeEnd={pagination.rangeEnd}\n totalItems={pagination.totalItems}\n canPrev={pagination.canPrev}\n canNext={pagination.canNext}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"predictions\"\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { notify as e } from "../utils/toast.js";
|
|
2
|
+
import { Pagination as t, usePagination as n } from "../components/Pagination.js";
|
|
3
|
+
import "../components/index.js";
|
|
4
|
+
import { useState as r } from "react";
|
|
5
|
+
import { Network as i, Plus as a } from "lucide-react";
|
|
6
|
+
import { gql as o } from "@apollo/client";
|
|
7
|
+
import { useMutation as s, useQuery as c } from "@apollo/client/react";
|
|
8
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
9
|
+
import { Button as d, GlassCard as f, GradientText as p, IllustratedEmptyState as m, Input as h, Label as g, PagePurpose as _, ResponsiveDialog as v, ResponsiveDialogContent as y, ResponsiveDialogDescription as b, ResponsiveDialogFooter as x, ResponsiveDialogHeader as S, ResponsiveDialogTitle as C, Select as w, SelectContent as T, SelectItem as E, SelectTrigger as D, SelectValue as O } from "@burdenoff/fe-libs/ui";
|
|
6
10
|
//#region src/assethandler/pages/CmdbBrowserPage.tsx
|
|
7
|
-
var
|
|
11
|
+
var k = o`
|
|
8
12
|
query AssetHandlerConfigurationItems {
|
|
9
13
|
configurationItems {
|
|
10
14
|
id
|
|
@@ -17,64 +21,219 @@ var l = t`
|
|
|
17
21
|
updatedAt
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
`, A = o`
|
|
25
|
+
mutation AssetHandlerUpsertConfigurationItem($input: UpsertConfigurationItemInput!) {
|
|
26
|
+
upsertConfigurationItem(input: $input) {
|
|
27
|
+
id
|
|
28
|
+
ciNumber
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
`, j = [
|
|
32
|
+
"SERVER",
|
|
33
|
+
"SERVICE",
|
|
34
|
+
"DATABASE",
|
|
35
|
+
"NETWORK",
|
|
36
|
+
"APPLICATION",
|
|
37
|
+
"STORAGE"
|
|
38
|
+
], M = [
|
|
39
|
+
"ACTIVE",
|
|
40
|
+
"INACTIVE",
|
|
41
|
+
"MAINTENANCE",
|
|
42
|
+
"RETIRED"
|
|
43
|
+
], N = [
|
|
44
|
+
"PRODUCTION",
|
|
45
|
+
"STAGING",
|
|
46
|
+
"DEVELOPMENT",
|
|
47
|
+
"DR"
|
|
48
|
+
];
|
|
49
|
+
function P({ open: t, onOpenChange: n, onSaved: i }) {
|
|
50
|
+
let [a, o] = r(""), [c, f] = r(""), [p, m] = r("SERVER"), [_, k] = r("ACTIVE"), [P, F] = r("PRODUCTION"), [I, L] = r(""), R = () => {
|
|
51
|
+
o(""), f(""), m("SERVER"), k("ACTIVE"), F("PRODUCTION"), L("");
|
|
52
|
+
}, [z, { loading: B }] = s(A, {
|
|
53
|
+
onCompleted: (t) => {
|
|
54
|
+
e.success("Configuration item saved", `${t.upsertConfigurationItem.ciNumber} is now in the CMDB.`), R(), n(!1), i();
|
|
55
|
+
},
|
|
56
|
+
onError: (t) => e.error("Could not save configuration item", t.message)
|
|
57
|
+
});
|
|
58
|
+
return /* @__PURE__ */ l(v, {
|
|
59
|
+
open: t,
|
|
60
|
+
onOpenChange: n,
|
|
61
|
+
children: /* @__PURE__ */ u(y, { children: [
|
|
62
|
+
/* @__PURE__ */ u(S, { children: [/* @__PURE__ */ l(C, { children: "New Configuration Item" }), /* @__PURE__ */ l(b, { children: "Register a configuration item in the CMDB and map it to your estate." })] }),
|
|
63
|
+
/* @__PURE__ */ u("div", {
|
|
64
|
+
className: "space-y-4",
|
|
28
65
|
children: [
|
|
29
|
-
/* @__PURE__ */
|
|
30
|
-
|
|
31
|
-
|
|
66
|
+
/* @__PURE__ */ u("div", {
|
|
67
|
+
className: "grid gap-4 md:grid-cols-2",
|
|
68
|
+
children: [/* @__PURE__ */ u("div", {
|
|
69
|
+
className: "space-y-2",
|
|
70
|
+
children: [/* @__PURE__ */ l(g, { children: "CI Number *" }), /* @__PURE__ */ l(h, {
|
|
71
|
+
placeholder: "e.g., CI-1042",
|
|
72
|
+
value: a,
|
|
73
|
+
onChange: (e) => o(e.target.value)
|
|
74
|
+
})]
|
|
75
|
+
}), /* @__PURE__ */ u("div", {
|
|
76
|
+
className: "space-y-2",
|
|
77
|
+
children: [/* @__PURE__ */ l(g, { children: "Name *" }), /* @__PURE__ */ l(h, {
|
|
78
|
+
value: c,
|
|
79
|
+
onChange: (e) => f(e.target.value)
|
|
80
|
+
})]
|
|
81
|
+
})]
|
|
82
|
+
}),
|
|
83
|
+
/* @__PURE__ */ u("div", {
|
|
84
|
+
className: "grid gap-4 md:grid-cols-3",
|
|
85
|
+
children: [
|
|
86
|
+
/* @__PURE__ */ u("div", {
|
|
87
|
+
className: "space-y-2",
|
|
88
|
+
children: [/* @__PURE__ */ l(g, { children: "Type" }), /* @__PURE__ */ u(w, {
|
|
89
|
+
value: p,
|
|
90
|
+
onValueChange: (e) => m(e),
|
|
91
|
+
children: [/* @__PURE__ */ l(D, { children: /* @__PURE__ */ l(O, {}) }), /* @__PURE__ */ l(T, { children: j.map((e) => /* @__PURE__ */ l(E, {
|
|
92
|
+
value: e,
|
|
93
|
+
children: e
|
|
94
|
+
}, e)) })]
|
|
95
|
+
})]
|
|
96
|
+
}),
|
|
97
|
+
/* @__PURE__ */ u("div", {
|
|
98
|
+
className: "space-y-2",
|
|
99
|
+
children: [/* @__PURE__ */ l(g, { children: "Status" }), /* @__PURE__ */ u(w, {
|
|
100
|
+
value: _,
|
|
101
|
+
onValueChange: (e) => k(e),
|
|
102
|
+
children: [/* @__PURE__ */ l(D, { children: /* @__PURE__ */ l(O, {}) }), /* @__PURE__ */ l(T, { children: M.map((e) => /* @__PURE__ */ l(E, {
|
|
103
|
+
value: e,
|
|
104
|
+
children: e
|
|
105
|
+
}, e)) })]
|
|
106
|
+
})]
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ u("div", {
|
|
109
|
+
className: "space-y-2",
|
|
110
|
+
children: [/* @__PURE__ */ l(g, { children: "Environment" }), /* @__PURE__ */ u(w, {
|
|
111
|
+
value: P,
|
|
112
|
+
onValueChange: (e) => F(e),
|
|
113
|
+
children: [/* @__PURE__ */ l(D, { children: /* @__PURE__ */ l(O, {}) }), /* @__PURE__ */ l(T, { children: N.map((e) => /* @__PURE__ */ l(E, {
|
|
114
|
+
value: e,
|
|
115
|
+
children: e
|
|
116
|
+
}, e)) })]
|
|
117
|
+
})]
|
|
118
|
+
})
|
|
119
|
+
]
|
|
120
|
+
}),
|
|
121
|
+
/* @__PURE__ */ u("div", {
|
|
122
|
+
className: "space-y-2",
|
|
123
|
+
children: [/* @__PURE__ */ l(g, { children: "Owner" }), /* @__PURE__ */ l(h, {
|
|
124
|
+
placeholder: "e.g., Platform team",
|
|
125
|
+
value: I,
|
|
126
|
+
onChange: (e) => L(e.target.value)
|
|
127
|
+
})]
|
|
128
|
+
})
|
|
32
129
|
]
|
|
33
130
|
}),
|
|
34
|
-
/* @__PURE__ */
|
|
35
|
-
|
|
131
|
+
/* @__PURE__ */ u(x, { children: [/* @__PURE__ */ l(d, {
|
|
132
|
+
variant: "outline",
|
|
133
|
+
onClick: () => n(!1),
|
|
134
|
+
disabled: B,
|
|
135
|
+
children: "Cancel"
|
|
136
|
+
}), /* @__PURE__ */ l(d, {
|
|
137
|
+
onClick: () => {
|
|
138
|
+
if (!a.trim() || !c.trim()) {
|
|
139
|
+
e.warning("Missing details", "CI number and name are required.");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
z({ variables: { input: {
|
|
143
|
+
ciNumber: a.trim(),
|
|
144
|
+
name: c.trim(),
|
|
145
|
+
ciType: p,
|
|
146
|
+
status: _,
|
|
147
|
+
environment: P,
|
|
148
|
+
owner: I.trim() || null
|
|
149
|
+
} } });
|
|
150
|
+
},
|
|
151
|
+
disabled: B,
|
|
152
|
+
children: B ? "Saving…" : "Save item"
|
|
153
|
+
})] })
|
|
154
|
+
] })
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function F() {
|
|
158
|
+
let [e, o] = r(!1), { data: s, loading: h, refetch: g } = c(k, { fetchPolicy: "cache-and-network" }), v = s?.configurationItems ?? [], y = n(v, { pageSize: 12 });
|
|
159
|
+
return /* @__PURE__ */ u("div", {
|
|
160
|
+
className: "space-y-4 p-4",
|
|
161
|
+
children: [
|
|
162
|
+
/* @__PURE__ */ u("div", {
|
|
163
|
+
className: "flex flex-wrap items-center justify-between gap-3",
|
|
164
|
+
children: [/* @__PURE__ */ u("h1", {
|
|
165
|
+
className: "flex items-center gap-2 text-2xl font-semibold",
|
|
166
|
+
children: [
|
|
167
|
+
/* @__PURE__ */ l(i, { className: "h-6 w-6" }),
|
|
168
|
+
" ",
|
|
169
|
+
/* @__PURE__ */ l(p, { children: "CMDB Browser" })
|
|
170
|
+
]
|
|
171
|
+
}), /* @__PURE__ */ u(d, {
|
|
172
|
+
onClick: () => o(!0),
|
|
173
|
+
children: [/* @__PURE__ */ l(a, { className: "mr-2 h-4 w-4" }), "New Item"]
|
|
174
|
+
})]
|
|
175
|
+
}),
|
|
176
|
+
/* @__PURE__ */ l(_, { children: "Your configuration management database (CMDB): a living map of every configuration item — servers, services, network gear and how they depend on each other. Use it to understand blast radius before a change, trace what an incident touches, and keep asset relationships accurate." }),
|
|
177
|
+
/* @__PURE__ */ l(P, {
|
|
178
|
+
open: e,
|
|
179
|
+
onOpenChange: o,
|
|
180
|
+
onSaved: () => void g()
|
|
181
|
+
}),
|
|
182
|
+
/* @__PURE__ */ u(f, {
|
|
36
183
|
treatment: "glass",
|
|
37
184
|
glow: !0,
|
|
38
185
|
className: "overflow-hidden border-border-seam",
|
|
39
186
|
children: [
|
|
40
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ u("div", {
|
|
41
188
|
className: "grid grid-cols-5 gap-3 border-b px-4 py-3 text-xs font-semibold uppercase tracking-wide text-text-secondary",
|
|
42
189
|
children: [
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
-
/* @__PURE__ */
|
|
45
|
-
/* @__PURE__ */
|
|
46
|
-
/* @__PURE__ */
|
|
47
|
-
/* @__PURE__ */
|
|
190
|
+
/* @__PURE__ */ l("span", { children: "CI Number" }),
|
|
191
|
+
/* @__PURE__ */ l("span", { children: "Name" }),
|
|
192
|
+
/* @__PURE__ */ l("span", { children: "Type" }),
|
|
193
|
+
/* @__PURE__ */ l("span", { children: "Status" }),
|
|
194
|
+
/* @__PURE__ */ l("span", { children: "Environment" })
|
|
48
195
|
]
|
|
49
196
|
}),
|
|
50
|
-
|
|
197
|
+
h && v.length === 0 ? /* @__PURE__ */ l("div", {
|
|
51
198
|
className: "space-y-2 px-4 py-4",
|
|
52
|
-
children: Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */
|
|
199
|
+
children: Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */ l("div", { className: "h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
|
|
53
200
|
}) : null,
|
|
54
|
-
!
|
|
201
|
+
!h && v.length === 0 ? /* @__PURE__ */ l(m, {
|
|
55
202
|
illustration: "empty-data",
|
|
56
203
|
title: "No configuration items found",
|
|
57
|
-
description: "
|
|
204
|
+
description: "Add a configuration item to start mapping your estate."
|
|
58
205
|
}) : null,
|
|
59
|
-
|
|
206
|
+
y.pageItems.map((e) => /* @__PURE__ */ u("div", {
|
|
60
207
|
className: "grid grid-cols-5 gap-3 border-b px-4 py-3 text-sm last:border-b-0",
|
|
61
208
|
children: [
|
|
62
|
-
/* @__PURE__ */
|
|
209
|
+
/* @__PURE__ */ l("span", {
|
|
63
210
|
className: "font-medium",
|
|
64
211
|
children: e.ciNumber
|
|
65
212
|
}),
|
|
66
|
-
/* @__PURE__ */
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
-
/* @__PURE__ */
|
|
69
|
-
/* @__PURE__ */
|
|
213
|
+
/* @__PURE__ */ l("span", { children: e.name }),
|
|
214
|
+
/* @__PURE__ */ l("span", { children: e.ciType }),
|
|
215
|
+
/* @__PURE__ */ l("span", { children: e.status }),
|
|
216
|
+
/* @__PURE__ */ l("span", { children: e.environment ?? "n/a" })
|
|
70
217
|
]
|
|
71
218
|
}, e.id))
|
|
72
219
|
]
|
|
220
|
+
}),
|
|
221
|
+
/* @__PURE__ */ l(t, {
|
|
222
|
+
page: y.page,
|
|
223
|
+
pageCount: y.pageCount,
|
|
224
|
+
rangeStart: y.rangeStart,
|
|
225
|
+
rangeEnd: y.rangeEnd,
|
|
226
|
+
totalItems: y.totalItems,
|
|
227
|
+
canPrev: y.canPrev,
|
|
228
|
+
canNext: y.canNext,
|
|
229
|
+
onPrev: y.prevPage,
|
|
230
|
+
onNext: y.nextPage,
|
|
231
|
+
itemLabel: "items"
|
|
73
232
|
})
|
|
74
233
|
]
|
|
75
234
|
});
|
|
76
235
|
}
|
|
77
236
|
//#endregion
|
|
78
|
-
export {
|
|
237
|
+
export { F as CmdbBrowserPage };
|
|
79
238
|
|
|
80
239
|
//# sourceMappingURL=CmdbBrowserPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CmdbBrowserPage.js","names":[],"sources":["../../../src/assethandler/pages/CmdbBrowserPage.tsx"],"sourcesContent":["import { Network } from 'lucide-react';\nimport { GradientText, IllustratedEmptyState, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\n\nconst CONFIGURATION_ITEMS_QUERY = gql`\n query AssetHandlerConfigurationItems {\n configurationItems {\n id\n ciNumber\n name\n ciType\n status\n environment\n owner\n updatedAt\n }\n }\n`;\n\nexport function CmdbBrowserPage() {\n const { data, loading } = useQuery<{\n configurationItems: Array<{\n id: string;\n ciNumber: string;\n name: string;\n ciType: string;\n status: string;\n environment: string | null;\n owner: string | null;\n updatedAt: string;\n }>;\n }>(CONFIGURATION_ITEMS_QUERY, { fetchPolicy: 'cache-and-network' });\n\n const cis = data?.configurationItems ?? [];\n\n return (\n <div className=\"space-y-4 p-4\">\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <Network className=\"h-6 w-6\" /> <GradientText>CMDB Browser</GradientText>\n </h1>\n <PagePurpose>\n Your configuration management database (CMDB): a living map of every configuration item —\n servers, services, network gear and how they depend on each other. Use it to understand\n blast radius before a change, trace what an incident touches, and keep asset relationships\n accurate.\n </PagePurpose>\n <GlassCard treatment=\"glass\" glow className=\"overflow-hidden border-border-seam\">\n <div className=\"grid grid-cols-5 gap-3 border-b px-4 py-3 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n <span>CI Number</span>\n <span>Name</span>\n <span>Type</span>\n <span>Status</span>\n <span>Environment</span>\n </div>\n {loading && cis.length === 0 ? (\n <div className=\"space-y-2 px-4 py-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n ) : null}\n {!loading && cis.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No configuration items found\"\n description=\"Configuration items will appear here once discovered.\"\n />\n ) : null}\n {cis.map((ci) => (\n <div\n key={ci.id}\n className=\"grid grid-cols-5 gap-3 border-b px-4 py-3 text-sm last:border-b-0\"\n >\n <span className=\"font-medium\">{ci.ciNumber}</span>\n <span>{ci.name}</span>\n <span>{ci.ciType}</span>\n <span>{ci.status}</span>\n <span>{ci.environment ?? 'n/a'}</span>\n </div>\n ))}\n </GlassCard>\n </div>\n );\n}\n"],"mappings":";;;;;;AAKA,IAAM,IAA4B,CAAG;;;;;;;;;;;;;;AAerC,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,eAAY,EAWvB,GAA2B,EAAE,aAAa,qBAAqB,CAAC,EAE7D,IAAM,GAAM,sBAAsB,EAAE;AAE1C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,MAAD;IAAI,WAAU;cAAd;KACE,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;;KAAC,kBAAC,GAAD,EAAA,UAAc,gBAA2B,CAAA;KACtE;;GACL,kBAAC,GAAD,EAAA,UAAa,0RAKC,CAAA;GACd,kBAAC,GAAD;IAAW,WAAU;IAAQ,MAAA;IAAK,WAAU;cAA5C;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,QAAD,EAAA,UAAM,aAAgB,CAAA;OACtB,kBAAC,QAAD,EAAA,UAAM,QAAW,CAAA;OACjB,kBAAC,QAAD,EAAA,UAAM,QAAW,CAAA;OACjB,kBAAC,QAAD,EAAA,UAAM,UAAa,CAAA;OACnB,kBAAC,QAAD,EAAA,UAAM,eAAkB,CAAA;OACpB;;KACL,KAAW,EAAI,WAAW,IACzB,kBAAC,OAAD;MAAK,WAAU;gBACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,OAAD,EAAa,WAAU,8DAA+D,EAA5E,EAA4E,CACtF;MACE,CAAA,GACJ;KACH,CAAC,KAAW,EAAI,WAAW,IAC1B,kBAAC,GAAD;MACE,cAAa;MACb,OAAM;MACN,aAAY;MACZ,CAAA,GACA;KACH,EAAI,KAAK,MACR,kBAAC,OAAD;MAEE,WAAU;gBAFZ;OAIE,kBAAC,QAAD;QAAM,WAAU;kBAAe,EAAG;QAAgB,CAAA;OAClD,kBAAC,QAAD,EAAA,UAAO,EAAG,MAAY,CAAA;OACtB,kBAAC,QAAD,EAAA,UAAO,EAAG,QAAc,CAAA;OACxB,kBAAC,QAAD,EAAA,UAAO,EAAG,QAAc,CAAA;OACxB,kBAAC,QAAD,EAAA,UAAO,EAAG,eAAe,OAAa,CAAA;OAClC;QARC,EAAG,GAQJ,CACN;KACQ;;GACR"}
|
|
1
|
+
{"version":3,"file":"CmdbBrowserPage.js","names":[],"sources":["../../../src/assethandler/pages/CmdbBrowserPage.tsx"],"sourcesContent":["import { Network, Plus } from 'lucide-react';\nimport { useState } from 'react';\nimport {\n Button,\n GradientText,\n IllustratedEmptyState,\n GlassCard,\n PagePurpose,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Pagination, usePagination } from '../components';\nimport { notify } from '../utils/toast';\n\nconst CONFIGURATION_ITEMS_QUERY = gql`\n query AssetHandlerConfigurationItems {\n configurationItems {\n id\n ciNumber\n name\n ciType\n status\n environment\n owner\n updatedAt\n }\n }\n`;\n\nconst UPSERT_CONFIGURATION_ITEM_MUTATION = gql`\n mutation AssetHandlerUpsertConfigurationItem($input: UpsertConfigurationItemInput!) {\n upsertConfigurationItem(input: $input) {\n id\n ciNumber\n }\n }\n`;\n\ninterface ConfigurationItem {\n id: string;\n ciNumber: string;\n name: string;\n ciType: string;\n status: string;\n environment: string | null;\n owner: string | null;\n updatedAt: string;\n}\n\ninterface UpsertConfigurationItemResult {\n upsertConfigurationItem: { id: string; ciNumber: string };\n}\n\nconst CI_TYPES = ['SERVER', 'SERVICE', 'DATABASE', 'NETWORK', 'APPLICATION', 'STORAGE'] as const;\nconst CI_STATUSES = ['ACTIVE', 'INACTIVE', 'MAINTENANCE', 'RETIRED'] as const;\nconst CI_ENVIRONMENTS = ['PRODUCTION', 'STAGING', 'DEVELOPMENT', 'DR'] as const;\n\nfunction NewConfigurationItemDialog({\n open,\n onOpenChange,\n onSaved,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSaved: () => void;\n}) {\n const [ciNumber, setCiNumber] = useState('');\n const [name, setName] = useState('');\n const [ciType, setCiType] = useState<(typeof CI_TYPES)[number]>('SERVER');\n const [status, setStatus] = useState<(typeof CI_STATUSES)[number]>('ACTIVE');\n const [environment, setEnvironment] = useState<(typeof CI_ENVIRONMENTS)[number]>('PRODUCTION');\n const [owner, setOwner] = useState('');\n\n const reset = () => {\n setCiNumber('');\n setName('');\n setCiType('SERVER');\n setStatus('ACTIVE');\n setEnvironment('PRODUCTION');\n setOwner('');\n };\n\n const [upsertItem, { loading }] = useMutation<UpsertConfigurationItemResult>(\n UPSERT_CONFIGURATION_ITEM_MUTATION,\n {\n onCompleted: (data) => {\n notify.success(\n 'Configuration item saved',\n `${data.upsertConfigurationItem.ciNumber} is now in the CMDB.`\n );\n reset();\n onOpenChange(false);\n onSaved();\n },\n onError: (error) => notify.error('Could not save configuration item', error.message),\n }\n );\n\n const handleSubmit = () => {\n if (!ciNumber.trim() || !name.trim()) {\n notify.warning('Missing details', 'CI number and name are required.');\n return;\n }\n void upsertItem({\n variables: {\n input: {\n ciNumber: ciNumber.trim(),\n name: name.trim(),\n ciType,\n status,\n environment,\n owner: owner.trim() || null,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Configuration Item</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Register a configuration item in the CMDB and map it to your estate.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>CI Number *</Label>\n <Input\n placeholder=\"e.g., CI-1042\"\n value={ciNumber}\n onChange={(e) => setCiNumber(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Name *</Label>\n <Input value={name} onChange={(e) => setName(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\n <div className=\"space-y-2\">\n <Label>Type</Label>\n <Select value={ciType} onValueChange={(v) => setCiType(v as typeof ciType)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CI_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {t}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CI_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Environment</Label>\n <Select\n value={environment}\n onValueChange={(v) => setEnvironment(v as typeof environment)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CI_ENVIRONMENTS.map((e) => (\n <SelectItem key={e} value={e}>\n {e}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Owner</Label>\n <Input\n placeholder=\"e.g., Platform team\"\n value={owner}\n onChange={(e) => setOwner(e.target.value)}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? 'Saving…' : 'Save item'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\nexport function CmdbBrowserPage() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const { data, loading, refetch } = useQuery<{ configurationItems: ConfigurationItem[] }>(\n CONFIGURATION_ITEMS_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n\n const cis = data?.configurationItems ?? [];\n const pagination = usePagination(cis, { pageSize: 12 });\n\n return (\n <div className=\"space-y-4 p-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <Network className=\"h-6 w-6\" /> <GradientText>CMDB Browser</GradientText>\n </h1>\n <Button onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-2 h-4 w-4\" />\n New Item\n </Button>\n </div>\n <PagePurpose>\n Your configuration management database (CMDB): a living map of every configuration item —\n servers, services, network gear and how they depend on each other. Use it to understand\n blast radius before a change, trace what an incident touches, and keep asset relationships\n accurate.\n </PagePurpose>\n\n <NewConfigurationItemDialog\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSaved={() => void refetch()}\n />\n\n <GlassCard treatment=\"glass\" glow className=\"overflow-hidden border-border-seam\">\n <div className=\"grid grid-cols-5 gap-3 border-b px-4 py-3 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n <span>CI Number</span>\n <span>Name</span>\n <span>Type</span>\n <span>Status</span>\n <span>Environment</span>\n </div>\n {loading && cis.length === 0 ? (\n <div className=\"space-y-2 px-4 py-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n ) : null}\n {!loading && cis.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No configuration items found\"\n description=\"Add a configuration item to start mapping your estate.\"\n />\n ) : null}\n {pagination.pageItems.map((ci) => (\n <div\n key={ci.id}\n className=\"grid grid-cols-5 gap-3 border-b px-4 py-3 text-sm last:border-b-0\"\n >\n <span className=\"font-medium\">{ci.ciNumber}</span>\n <span>{ci.name}</span>\n <span>{ci.ciType}</span>\n <span>{ci.status}</span>\n <span>{ci.environment ?? 'n/a'}</span>\n </div>\n ))}\n </GlassCard>\n <Pagination\n page={pagination.page}\n pageCount={pagination.pageCount}\n rangeStart={pagination.rangeStart}\n rangeEnd={pagination.rangeEnd}\n totalItems={pagination.totalItems}\n canPrev={pagination.canPrev}\n canNext={pagination.canNext}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"items\"\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AA2BA,IAAM,IAA4B,CAAG;;;;;;;;;;;;;GAe/B,IAAqC,CAAG;;;;;;;GAwBxC,IAAW;CAAC;CAAU;CAAW;CAAY;CAAW;CAAe;CAAU,EACjF,IAAc;CAAC;CAAU;CAAY;CAAe;CAAU,EAC9D,IAAkB;CAAC;CAAc;CAAW;CAAe;CAAK;AAEtE,SAAS,EAA2B,EAClC,SACA,iBACA,cAKC;CACD,IAAM,CAAC,GAAU,KAAe,EAAS,GAAG,EACtC,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAQ,KAAa,EAAoC,SAAS,EACnE,CAAC,GAAQ,KAAa,EAAuC,SAAS,EACtE,CAAC,GAAa,KAAkB,EAA2C,aAAa,EACxF,CAAC,GAAO,KAAY,EAAS,GAAG,EAEhC,UAAc;AAMlB,EALA,EAAY,GAAG,EACf,EAAQ,GAAG,EACX,EAAU,SAAS,EACnB,EAAU,SAAS,EACnB,EAAe,aAAa,EAC5B,EAAS,GAAG;IAGR,CAAC,GAAY,EAAE,gBAAa,EAChC,GACA;EACE,cAAc,MAAS;AAOrB,GANA,EAAO,QACL,4BACA,GAAG,EAAK,wBAAwB,SAAS,sBAC1C,EACD,GAAO,EACP,EAAa,GAAM,EACnB,GAAS;;EAEX,UAAU,MAAU,EAAO,MAAM,qCAAqC,EAAM,QAAQ;EACrF,CACF;AAqBD,QACE,kBAAC,GAAD;EAAwB;EAAoB;YAC1C,kBAAC,GAAD,EAAA,UAAA;GACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAuB,0BAA8C,CAAA,EACrE,kBAAC,GAAD,EAAA,UAA6B,wEAEC,CAAA,CACP,EAAA,CAAA;GACzB,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAA,UAAO,eAAmB,CAAA,EAC1B,kBAAC,GAAD;QACE,aAAY;QACZ,OAAO;QACP,WAAW,MAAM,EAAY,EAAE,OAAO,MAAM;QAC5C,CAAA,CACE;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAA,UAAO,UAAc,CAAA,EACrB,kBAAC,GAAD;QAAO,OAAO;QAAM,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;QAAI,CAAA,CAC5D;SACF;;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAA,UAAO,QAAY,CAAA,EACnB,kBAAC,GAAD;SAAQ,OAAO;SAAQ,gBAAgB,MAAM,EAAU,EAAmB;mBAA1E,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAe,CAAA,EACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAS,KAAK,MACb,kBAAC,GAAD;UAAoB,OAAO;oBACxB;UACU,EAFI,EAEJ,CACb,EACY,CAAA,CACT;WACL;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAA,UAAO,UAAc,CAAA,EACrB,kBAAC,GAAD;SAAQ,OAAO;SAAQ,gBAAgB,MAAM,EAAU,EAAmB;mBAA1E,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAe,CAAA,EACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAY,KAAK,MAChB,kBAAC,GAAD;UAAoB,OAAO;oBACxB;UACU,EAFI,EAEJ,CACb,EACY,CAAA,CACT;WACL;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAA,UAAO,eAAmB,CAAA,EAC1B,kBAAC,GAAD;SACE,OAAO;SACP,gBAAgB,MAAM,EAAe,EAAwB;mBAF/D,CAIE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAe,CAAA,EACD,CAAA,EAChB,kBAAC,GAAD,EAAA,UACG,EAAgB,KAAK,MACpB,kBAAC,GAAD;UAAoB,OAAO;oBACxB;UACU,EAFI,EAEJ,CACb,EACY,CAAA,CACT;WACL;;OACF;;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAA,UAAO,SAAa,CAAA,EACpB,kBAAC,GAAD;OACE,aAAY;OACZ,OAAO;OACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;OACzC,CAAA,CACE;;KACF;;GACN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;IAAQ,SAAQ;IAAU,eAAe,EAAa,GAAM;IAAE,UAAU;cAAS;IAExE,CAAA,EACT,kBAAC,GAAD;IAAQ,eA1GW;AACzB,SAAI,CAAC,EAAS,MAAM,IAAI,CAAC,EAAK,MAAM,EAAE;AACpC,QAAO,QAAQ,mBAAmB,mCAAmC;AACrE;;AAEG,OAAW,EACd,WAAW,EACT,OAAO;MACL,UAAU,EAAS,MAAM;MACzB,MAAM,EAAK,MAAM;MACjB;MACA;MACA;MACA,OAAO,EAAM,MAAM,IAAI;MACxB,EACF,EACF,CAAC;;IA0FmC,UAAU;cACtC,IAAU,YAAY;IAChB,CAAA,CACc,EAAA,CAAA;GACD,EAAA,CAAA;EACT,CAAA;;AAIvB,SAAgB,IAAkB;CAChC,IAAM,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,EAAE,SAAM,YAAS,eAAY,EACjC,GACA,EAAE,aAAa,qBAAqB,CACrC,EAEK,IAAM,GAAM,sBAAsB,EAAE,EACpC,IAAa,EAAc,GAAK,EAAE,UAAU,IAAI,CAAC;AAEvD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAAd;MACE,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;;MAAC,kBAAC,GAAD,EAAA,UAAc,gBAA2B,CAAA;MACtE;QACL,kBAAC,GAAD;KAAQ,eAAe,EAAc,GAAK;eAA1C,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,WAE1B;OACL;;GACN,kBAAC,GAAD,EAAA,UAAa,0RAKC,CAAA;GAEd,kBAAC,GAAD;IACE,MAAM;IACN,cAAc;IACd,eAAe,KAAK,GAAS;IAC7B,CAAA;GAEF,kBAAC,GAAD;IAAW,WAAU;IAAQ,MAAA;IAAK,WAAU;cAA5C;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,QAAD,EAAA,UAAM,aAAgB,CAAA;OACtB,kBAAC,QAAD,EAAA,UAAM,QAAW,CAAA;OACjB,kBAAC,QAAD,EAAA,UAAM,QAAW,CAAA;OACjB,kBAAC,QAAD,EAAA,UAAM,UAAa,CAAA;OACnB,kBAAC,QAAD,EAAA,UAAM,eAAkB,CAAA;OACpB;;KACL,KAAW,EAAI,WAAW,IACzB,kBAAC,OAAD;MAAK,WAAU;gBACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,OAAD,EAAa,WAAU,8DAA+D,EAA5E,EAA4E,CACtF;MACE,CAAA,GACJ;KACH,CAAC,KAAW,EAAI,WAAW,IAC1B,kBAAC,GAAD;MACE,cAAa;MACb,OAAM;MACN,aAAY;MACZ,CAAA,GACA;KACH,EAAW,UAAU,KAAK,MACzB,kBAAC,OAAD;MAEE,WAAU;gBAFZ;OAIE,kBAAC,QAAD;QAAM,WAAU;kBAAe,EAAG;QAAgB,CAAA;OAClD,kBAAC,QAAD,EAAA,UAAO,EAAG,MAAY,CAAA;OACtB,kBAAC,QAAD,EAAA,UAAO,EAAG,QAAc,CAAA;OACxB,kBAAC,QAAD,EAAA,UAAO,EAAG,QAAc,CAAA;OACxB,kBAAC,QAAD,EAAA,UAAO,EAAG,eAAe,OAAa,CAAA;OAClC;QARC,EAAG,GAQJ,CACN;KACQ;;GACZ,kBAAC,GAAD;IACE,MAAM,EAAW;IACjB,WAAW,EAAW;IACtB,YAAY,EAAW;IACvB,UAAU,EAAW;IACrB,YAAY,EAAW;IACvB,SAAS,EAAW;IACpB,SAAS,EAAW;IACpB,QAAQ,EAAW;IACnB,QAAQ,EAAW;IACnB,WAAU;IACV,CAAA;GACE"}
|