@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.
Files changed (57) hide show
  1. package/dist/assethandler/ops/NewWorkOrderDialog.js +164 -0
  2. package/dist/assethandler/ops/NewWorkOrderDialog.js.map +1 -0
  3. package/dist/assethandler/ops/ScheduleMaintenanceDialog.js +197 -0
  4. package/dist/assethandler/ops/ScheduleMaintenanceDialog.js.map +1 -0
  5. package/dist/assethandler/pages/AiPredictionsPage.js +112 -54
  6. package/dist/assethandler/pages/AiPredictionsPage.js.map +1 -1
  7. package/dist/assethandler/pages/CmdbBrowserPage.js +195 -36
  8. package/dist/assethandler/pages/CmdbBrowserPage.js.map +1 -1
  9. package/dist/assethandler/pages/DigitalTwinPage.js +162 -31
  10. package/dist/assethandler/pages/DigitalTwinPage.js.map +1 -1
  11. package/dist/assethandler/pages/DiscoveryJobsPage.js +85 -55
  12. package/dist/assethandler/pages/DiscoveryJobsPage.js.map +1 -1
  13. package/dist/assethandler/pages/EsgDashboardPage.js +189 -60
  14. package/dist/assethandler/pages/EsgDashboardPage.js.map +1 -1
  15. package/dist/assethandler/pages/IotDevicesPage.js +206 -38
  16. package/dist/assethandler/pages/IotDevicesPage.js.map +1 -1
  17. package/dist/assethandler/pages/ItilChangeDetailPage.js +221 -114
  18. package/dist/assethandler/pages/ItilChangeDetailPage.js.map +1 -1
  19. package/dist/assethandler/pages/ItilChangeManagementPage.js +86 -61
  20. package/dist/assethandler/pages/ItilChangeManagementPage.js.map +1 -1
  21. package/dist/assethandler/pages/ItilDialogs.js +361 -0
  22. package/dist/assethandler/pages/ItilDialogs.js.map +1 -0
  23. package/dist/assethandler/pages/ItilIncidentDetailPage.js +370 -105
  24. package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
  25. package/dist/assethandler/pages/ItilIncidentManagementPage.js +130 -103
  26. package/dist/assethandler/pages/ItilIncidentManagementPage.js.map +1 -1
  27. package/dist/assethandler/pages/ItilItilhubPage.js +186 -132
  28. package/dist/assethandler/pages/ItilItilhubPage.js.map +1 -1
  29. package/dist/assethandler/pages/ItilProblemDetailPage.js +195 -96
  30. package/dist/assethandler/pages/ItilProblemDetailPage.js.map +1 -1
  31. package/dist/assethandler/pages/ItilProblemManagementPage.js +83 -58
  32. package/dist/assethandler/pages/ItilProblemManagementPage.js.map +1 -1
  33. package/dist/assethandler/pages/KnowledgeBasePage.js +205 -75
  34. package/dist/assethandler/pages/KnowledgeBasePage.js.map +1 -1
  35. package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js +212 -96
  36. package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js.map +1 -1
  37. package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js +70 -38
  38. package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
  39. package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js +470 -116
  40. package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
  41. package/dist/assethandler/pages/OperationsOperationsHubPage.js +154 -102
  42. package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
  43. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +386 -79
  44. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
  45. package/dist/assethandler/pages/ProvenancePage.js +102 -56
  46. package/dist/assethandler/pages/ProvenancePage.js.map +1 -1
  47. package/dist/assethandler/pages/SamLicensesPage.js +186 -36
  48. package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
  49. package/dist/assethandler/pages/SecurityComplianceDetailPage.js +147 -65
  50. package/dist/assethandler/pages/SecurityComplianceDetailPage.js.map +1 -1
  51. package/dist/assethandler/pages/SecurityPolicyDetailPage.js +349 -124
  52. package/dist/assethandler/pages/SecurityPolicyDetailPage.js.map +1 -1
  53. package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js +191 -116
  54. package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js.map +1 -1
  55. package/dist/assethandler/pages/SecuritySecurityHubPage.js +421 -184
  56. package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
  57. package/package.json +1 -1
@@ -1,11 +1,15 @@
1
- import { useState as e } from "react";
2
- import { BrainCircuit as t } from "lucide-react";
3
- import { gql as n } from "@apollo/client";
4
- import { useMutation as r, useQuery as i } from "@apollo/client/react";
5
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
- import { EmphasisPanel as s, GradientText as c, IllustratedEmptyState as l, PagePurpose as u } from "@burdenoff/fe-libs/ui";
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 d = n`
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
- `, f = n`
25
+ `, C = o`
22
26
  mutation AssetHandlerRequestAiPrediction($input: RequestAIPredictionInput!) {
23
27
  requestAIPrediction(input: $input) {
24
28
  id
25
29
  }
26
30
  }
27
- `;
28
- function p() {
29
- let [n, p] = e("AST-001"), { data: m, loading: h, refetch: g } = i(d, { fetchPolicy: "cache-and-network" }), [_, { loading: v }] = r(f, { onCompleted: () => {
30
- g();
31
- } }), y = m?.aiPredictions ?? [];
32
- return /* @__PURE__ */ o("div", {
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__ */ o("h1", {
63
+ /* @__PURE__ */ u("h1", {
36
64
  className: "flex items-center gap-2 text-2xl font-semibold",
37
65
  children: [
38
- /* @__PURE__ */ a(t, { className: "h-6 w-6" }),
66
+ /* @__PURE__ */ l(a, { className: "h-6 w-6" }),
39
67
  " ",
40
- /* @__PURE__ */ a(c, { children: "AI Predictions" })
68
+ /* @__PURE__ */ l(p, { children: "AI Predictions" })
41
69
  ]
42
70
  }),
43
- /* @__PURE__ */ a(u, { children: "Forecast failures before they happen. Enter an asset and run 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." }),
44
- /* @__PURE__ */ o(s, { children: [/* @__PURE__ */ a("h2", {
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__ */ o("form", {
75
+ }), /* @__PURE__ */ u("form", {
48
76
  className: "grid gap-3 md:grid-cols-3",
49
77
  onSubmit: (e) => {
50
- e.preventDefault(), _({ variables: { input: {
51
- assetId: n,
52
- predictionType: "maintenance-risk",
53
- featureVector: {
54
- runtimeHours: 10240,
55
- lastIncidentDaysAgo: 9,
56
- temperatureVariance: .23
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__ */ a("input", {
62
- className: "rounded-md border px-3 py-2",
63
- value: n,
64
- onChange: (e) => p(e.target.value),
65
- "aria-label": "Asset ID"
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__ */ a("div", {
68
- className: "text-sm text-text-secondary",
69
- children: "Prediction Type: maintenance-risk"
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__ */ a("button", {
72
- className: "rounded-md bg-action-primary-bg px-3 py-2 text-action-primary-text",
73
- disabled: v,
74
- type: "submit",
75
- children: v ? "Running..." : "Run Prediction"
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__ */ o("div", {
125
+ /* @__PURE__ */ u("div", {
80
126
  className: "grid gap-3 md:grid-cols-2",
81
127
  children: [
82
- h && y.length === 0 ? /* @__PURE__ */ a("div", {
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__ */ a("div", { className: "h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
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
- !h && y.length === 0 ? /* @__PURE__ */ a(l, {
132
+ !j && F.length === 0 ? /* @__PURE__ */ l(m, {
87
133
  illustration: "empty-data",
88
134
  title: "No AI predictions available yet",
89
- description: "AI-generated predictions for your assets will appear here."
135
+ description: "Run a prediction above to generate a risk score and recommendation."
90
136
  }) : null,
91
- y.map((e) => /* @__PURE__ */ o("article", {
137
+ I.pageItems.map((e) => /* @__PURE__ */ u("article", {
92
138
  className: "rounded-lg border p-4",
93
139
  children: [
94
- /* @__PURE__ */ o("p", {
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__ */ o("h2", {
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__ */ o("p", {
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__ */ a("p", {
164
+ /* @__PURE__ */ l("p", {
119
165
  className: "mt-2 text-sm",
120
166
  children: e.recommendation
121
167
  }),
122
- /* @__PURE__ */ o("p", {
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 { p as AiPredictionsPage };
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 { Network as e } from "lucide-react";
2
- import { gql as t } from "@apollo/client";
3
- import { useQuery as n } from "@apollo/client/react";
4
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
- import { GlassCard as a, GradientText as o, IllustratedEmptyState as s, PagePurpose as c } from "@burdenoff/fe-libs/ui";
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 l = t`
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
- function u() {
22
- let { data: t, loading: u } = n(l, { fetchPolicy: "cache-and-network" }), d = t?.configurationItems ?? [];
23
- return /* @__PURE__ */ i("div", {
24
- className: "space-y-4 p-4",
25
- children: [
26
- /* @__PURE__ */ i("h1", {
27
- className: "flex items-center gap-2 text-2xl font-semibold",
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__ */ r(e, { className: "h-6 w-6" }),
30
- " ",
31
- /* @__PURE__ */ r(o, { children: "CMDB Browser" })
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__ */ r(c, { 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." }),
35
- /* @__PURE__ */ i(a, {
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__ */ i("div", {
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__ */ r("span", { children: "CI Number" }),
44
- /* @__PURE__ */ r("span", { children: "Name" }),
45
- /* @__PURE__ */ r("span", { children: "Type" }),
46
- /* @__PURE__ */ r("span", { children: "Status" }),
47
- /* @__PURE__ */ r("span", { children: "Environment" })
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
- u && d.length === 0 ? /* @__PURE__ */ r("div", {
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__ */ r("div", { className: "h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
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
- !u && d.length === 0 ? /* @__PURE__ */ r(s, {
201
+ !h && v.length === 0 ? /* @__PURE__ */ l(m, {
55
202
  illustration: "empty-data",
56
203
  title: "No configuration items found",
57
- description: "Configuration items will appear here once discovered."
204
+ description: "Add a configuration item to start mapping your estate."
58
205
  }) : null,
59
- d.map((e) => /* @__PURE__ */ i("div", {
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__ */ r("span", {
209
+ /* @__PURE__ */ l("span", {
63
210
  className: "font-medium",
64
211
  children: e.ciNumber
65
212
  }),
66
- /* @__PURE__ */ r("span", { children: e.name }),
67
- /* @__PURE__ */ r("span", { children: e.ciType }),
68
- /* @__PURE__ */ r("span", { children: e.status }),
69
- /* @__PURE__ */ r("span", { children: e.environment ?? "n/a" })
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 { u as CmdbBrowserPage };
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"}