@burdenoff/microfe-assethandler 2026.826.18 → 2026.828.1

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 (26) hide show
  1. package/dist/assethandler/AssetHandlerRoot.d.ts.map +1 -1
  2. package/dist/assethandler/AssetHandlerRoot.js +57 -50
  3. package/dist/assethandler/AssetHandlerRoot.js.map +1 -1
  4. package/dist/assethandler/components/RelatedRunbooksPanel.d.ts +27 -0
  5. package/dist/assethandler/components/RelatedRunbooksPanel.d.ts.map +1 -0
  6. package/dist/assethandler/components/RelatedRunbooksPanel.js +153 -0
  7. package/dist/assethandler/components/RelatedRunbooksPanel.js.map +1 -0
  8. package/dist/assethandler/components/index.d.ts +2 -0
  9. package/dist/assethandler/components/index.d.ts.map +1 -1
  10. package/dist/assethandler/components/index.js +1 -0
  11. package/dist/assethandler/pages/AssetsAssetCheckInOutPage.d.ts.map +1 -1
  12. package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js +237 -211
  13. package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js.map +1 -1
  14. package/dist/assethandler/pages/AssetsAssetDetailPage.d.ts.map +1 -1
  15. package/dist/assethandler/pages/AssetsAssetDetailPage.js +372 -367
  16. package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
  17. package/dist/assethandler/pages/ItilIncidentDetailPage.d.ts.map +1 -1
  18. package/dist/assethandler/pages/ItilIncidentDetailPage.js +104 -99
  19. package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
  20. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.d.ts.map +1 -1
  21. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +139 -134
  22. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
  23. package/dist/assethandler/pages/SamLicensesPage.d.ts.map +1 -1
  24. package/dist/assethandler/pages/SamLicensesPage.js +811 -227
  25. package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
  26. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AssetHandlerRoot.d.ts","sourceRoot":"","sources":["../../src/assethandler/AssetHandlerRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAkBhC,OAAO,KAAK,EAAE,qBAAqB,EAAW,MAAM,SAAS,CAAC;AAG9D,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAwKtD,CAAC"}
1
+ {"version":3,"file":"AssetHandlerRoot.d.ts","sourceRoot":"","sources":["../../src/assethandler/AssetHandlerRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAmBhC,OAAO,KAAK,EAAE,qBAAqB,EAAW,MAAM,SAAS,CAAC;AAG9D,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CA+KtD,CAAC"}
@@ -2,156 +2,163 @@ import { AssetHandlerProvider as e } from "./providers/AssetHandlerProvider.js";
2
2
  import { joinPath as t } from "./utils/navigation.js";
3
3
  import { AssetHandlerRoutes as n } from "./AssetHandlerRoutes.js";
4
4
  import { useEffect as r } from "react";
5
- import { BellRing as i, Boxes as a, BrainCircuit as o, Cpu as s, KeyRound as c, Leaf as l, Network as u, Radar as d, ScanLine as f, ShieldCheck as p } from "lucide-react";
6
- import { jsx as m } from "react/jsx-runtime";
7
- import { FeatureFlagProvider as h } from "@burdenoff/fe-libs/shared/feature-flags";
5
+ import { BellRing as i, BookOpen as a, Boxes as o, BrainCircuit as s, Cpu as c, KeyRound as l, Leaf as u, Network as d, Radar as f, ScanLine as p, ShieldCheck as m } from "lucide-react";
6
+ import { jsx as h } from "react/jsx-runtime";
7
+ import { FeatureFlagProvider as g } from "@burdenoff/fe-libs/shared/feature-flags";
8
8
  //#region src/assethandler/AssetHandlerRoot.tsx
9
- var g = (g) => {
10
- let { registerNavItems: _, registerFooterItems: v, basePath: y = "/", brandLabel: b = "AssetHandler", terminology: x, hiddenCategoryIds: S } = g, C = x?.assets || "Assets";
9
+ var _ = (_) => {
10
+ let { registerNavItems: v, registerFooterItems: y, basePath: b = "/", brandLabel: x = "AssetHandler", terminology: S, hiddenCategoryIds: C } = _, w = S?.assets || "Assets";
11
11
  return r(() => {
12
- if (!_) return;
13
- let e = new Set(S ?? []), n = (t) => e.has(t.replace(/^assethandler-/, "")), r = {
12
+ if (!v) return;
13
+ let e = new Set(C ?? []), n = (t) => e.has(t.replace(/^assethandler-/, "")), r = {
14
14
  id: "assethandler",
15
- label: b,
16
- path: y,
17
- icon: /* @__PURE__ */ m(a, { size: 20 }),
15
+ label: x,
16
+ path: b,
17
+ icon: /* @__PURE__ */ h(o, { size: 20 }),
18
18
  order: 82,
19
19
  group: "products",
20
20
  children: [
21
21
  {
22
22
  id: "assethandler-dashboard",
23
23
  label: "Dashboard",
24
- path: y,
24
+ path: b,
25
25
  order: 0
26
26
  },
27
27
  {
28
28
  id: "assethandler-assets",
29
- label: C,
30
- path: t(y, "assets/asset-list"),
29
+ label: w,
30
+ path: t(b, "assets/asset-list"),
31
31
  order: 1
32
32
  },
33
33
  {
34
34
  id: "assethandler-physical-audits",
35
35
  label: "Physical Audits",
36
- path: t(y, "assets/physical-audits"),
37
- icon: /* @__PURE__ */ m(f, { size: 16 }),
36
+ path: t(b, "assets/physical-audits"),
37
+ icon: /* @__PURE__ */ h(p, { size: 16 }),
38
38
  order: 2
39
39
  },
40
40
  {
41
41
  id: "assethandler-operations",
42
42
  label: "Operations",
43
- path: t(y, "operations/operations-hub"),
43
+ path: t(b, "operations/operations-hub"),
44
44
  order: 3
45
45
  },
46
46
  {
47
47
  id: "assethandler-itil",
48
48
  label: "ITIL",
49
- path: t(y, "itil/itilhub"),
49
+ path: t(b, "itil/itilhub"),
50
50
  order: 3
51
51
  },
52
52
  {
53
53
  id: "assethandler-finance",
54
54
  label: "Finance",
55
- path: t(y, "finance/finance-hub"),
55
+ path: t(b, "finance/finance-hub"),
56
56
  order: 4
57
57
  },
58
58
  {
59
59
  id: "assethandler-deadline-alerts",
60
60
  label: "Deadline Alerts",
61
- path: t(y, "analytics/deadline-alerts"),
62
- icon: /* @__PURE__ */ m(i, { size: 16 }),
61
+ path: t(b, "analytics/deadline-alerts"),
62
+ icon: /* @__PURE__ */ h(i, { size: 16 }),
63
63
  order: 5
64
64
  },
65
65
  {
66
66
  id: "assethandler-security",
67
67
  label: "Security",
68
- path: t(y, "security/security-hub"),
68
+ path: t(b, "security/security-hub"),
69
69
  order: 7
70
70
  },
71
71
  {
72
72
  id: "assethandler-iot",
73
73
  label: "IoT Devices",
74
- path: t(y, "advanced/iot-devices"),
75
- icon: /* @__PURE__ */ m(s, { size: 16 }),
74
+ path: t(b, "advanced/iot-devices"),
75
+ icon: /* @__PURE__ */ h(c, { size: 16 }),
76
76
  order: 10
77
77
  },
78
78
  {
79
79
  id: "assethandler-digital-twin",
80
80
  label: "Digital Twin",
81
- path: t(y, "advanced/digital-twin"),
82
- icon: /* @__PURE__ */ m(a, { size: 16 }),
81
+ path: t(b, "advanced/digital-twin"),
82
+ icon: /* @__PURE__ */ h(o, { size: 16 }),
83
83
  order: 11
84
84
  },
85
85
  {
86
86
  id: "assethandler-sam",
87
87
  label: "SAM",
88
- path: t(y, "advanced/sam-licenses"),
89
- icon: /* @__PURE__ */ m(c, { size: 16 }),
88
+ path: t(b, "advanced/sam-licenses"),
89
+ icon: /* @__PURE__ */ h(l, { size: 16 }),
90
90
  order: 12
91
91
  },
92
92
  {
93
93
  id: "assethandler-cmdb",
94
94
  label: "CMDB",
95
- path: t(y, "advanced/cmdb-browser"),
96
- icon: /* @__PURE__ */ m(u, { size: 16 }),
95
+ path: t(b, "advanced/cmdb-browser"),
96
+ icon: /* @__PURE__ */ h(d, { size: 16 }),
97
97
  order: 13
98
98
  },
99
99
  {
100
100
  id: "assethandler-discovery",
101
101
  label: "Discovery",
102
- path: t(y, "advanced/discovery-jobs"),
103
- icon: /* @__PURE__ */ m(d, { size: 16 }),
102
+ path: t(b, "advanced/discovery-jobs"),
103
+ icon: /* @__PURE__ */ h(f, { size: 16 }),
104
104
  order: 14
105
105
  },
106
106
  {
107
107
  id: "assethandler-provenance",
108
108
  label: "Provenance",
109
- path: t(y, "advanced/provenance"),
110
- icon: /* @__PURE__ */ m(p, { size: 16 }),
109
+ path: t(b, "advanced/provenance"),
110
+ icon: /* @__PURE__ */ h(m, { size: 16 }),
111
111
  order: 15
112
112
  },
113
113
  {
114
114
  id: "assethandler-esg",
115
115
  label: "ESG",
116
- path: t(y, "advanced/esg-dashboard"),
117
- icon: /* @__PURE__ */ m(l, { size: 16 }),
116
+ path: t(b, "advanced/esg-dashboard"),
117
+ icon: /* @__PURE__ */ h(u, { size: 16 }),
118
118
  order: 16
119
119
  },
120
+ {
121
+ id: "assethandler-knowledge-base",
122
+ label: "Knowledge Base",
123
+ path: t(b, "advanced/knowledge-base"),
124
+ icon: /* @__PURE__ */ h(a, { size: 16 }),
125
+ order: 17
126
+ },
120
127
  {
121
128
  id: "assethandler-ai",
122
129
  label: "AI Predictions",
123
- path: t(y, "advanced/ai-predictions"),
124
- icon: /* @__PURE__ */ m(o, { size: 16 }),
125
- order: 17
130
+ path: t(b, "advanced/ai-predictions"),
131
+ icon: /* @__PURE__ */ h(s, { size: 16 }),
132
+ order: 18
126
133
  }
127
134
  ]
128
135
  };
129
- return r.children &&= r.children.filter((e) => !n(e.id)), _(r);
136
+ return r.children &&= r.children.filter((e) => !n(e.id)), v(r);
130
137
  }, [
131
- y,
132
- _,
133
138
  b,
134
- C,
135
- S
139
+ v,
140
+ x,
141
+ w,
142
+ C
136
143
  ]), r(() => {
137
- if (v) return v([{
144
+ if (y) return y([{
138
145
  id: "assethandler-status",
139
- label: `${b} Live`,
146
+ label: `${x} Live`,
140
147
  type: "status",
141
148
  section: "left",
142
149
  order: 10
143
150
  }]);
144
- }, [v, b]), /* @__PURE__ */ m(h, {
151
+ }, [y, x]), /* @__PURE__ */ h(g, {
145
152
  workspaceId: null,
146
153
  gateway: "global",
147
154
  defaultEnabled: !0,
148
- children: /* @__PURE__ */ m(e, {
149
- ...g,
150
- children: /* @__PURE__ */ m(n, {})
155
+ children: /* @__PURE__ */ h(e, {
156
+ ..._,
157
+ children: /* @__PURE__ */ h(n, {})
151
158
  })
152
159
  });
153
160
  };
154
161
  //#endregion
155
- export { g as AssetHandlerRoot };
162
+ export { _ as AssetHandlerRoot };
156
163
 
157
164
  //# sourceMappingURL=AssetHandlerRoot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssetHandlerRoot.js","names":[],"sources":["../../src/assethandler/AssetHandlerRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport {\n BrainCircuit,\n BellRing,\n Boxes,\n Cpu,\n KeyRound,\n Leaf,\n Network,\n Radar,\n ScanLine,\n ShieldCheck,\n} from 'lucide-react';\n\nimport { AssetHandlerRoutes } from './AssetHandlerRoutes';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { AssetHandlerProvider } from './providers/AssetHandlerProvider';\nimport type { AssetHandlerRootProps, NavItem } from './types';\nimport { joinPath } from './utils/navigation';\n\nexport const AssetHandlerRoot: FC<AssetHandlerRootProps> = (props) => {\n const {\n registerNavItems,\n registerFooterItems,\n basePath = '/',\n brandLabel = 'AssetHandler',\n terminology,\n hiddenCategoryIds,\n } = props;\n const assetsLabel = terminology?.assets || 'Assets';\n\n useEffect(() => {\n if (!registerNavItems) {\n return;\n }\n\n // Consumers can hide advanced (IT-specific) nav children by passing their\n // id with the \"assethandler-\" prefix stripped, e.g. \"digital-twin\".\n const hidden = new Set(hiddenCategoryIds ?? []);\n const isHidden = (id: string) => hidden.has(id.replace(/^assethandler-/, ''));\n\n const navItem: NavItem = {\n id: 'assethandler',\n label: brandLabel,\n path: basePath,\n icon: <Boxes size={20} />,\n order: 82,\n group: 'products',\n children: [\n {\n id: 'assethandler-dashboard',\n label: 'Dashboard',\n path: basePath,\n order: 0,\n },\n {\n id: 'assethandler-assets',\n label: assetsLabel,\n path: joinPath(basePath, 'assets/asset-list'),\n order: 1,\n },\n {\n id: 'assethandler-physical-audits',\n label: 'Physical Audits',\n path: joinPath(basePath, 'assets/physical-audits'),\n icon: <ScanLine size={16} />,\n order: 2,\n },\n {\n id: 'assethandler-operations',\n label: 'Operations',\n path: joinPath(basePath, 'operations/operations-hub'),\n order: 3,\n },\n {\n id: 'assethandler-itil',\n label: 'ITIL',\n path: joinPath(basePath, 'itil/itilhub'),\n order: 3,\n },\n {\n id: 'assethandler-finance',\n label: 'Finance',\n path: joinPath(basePath, 'finance/finance-hub'),\n order: 4,\n },\n {\n id: 'assethandler-deadline-alerts',\n label: 'Deadline Alerts',\n path: joinPath(basePath, 'analytics/deadline-alerts'),\n icon: <BellRing size={16} />,\n order: 5,\n },\n {\n id: 'assethandler-security',\n label: 'Security',\n path: joinPath(basePath, 'security/security-hub'),\n order: 7,\n },\n {\n id: 'assethandler-iot',\n label: 'IoT Devices',\n path: joinPath(basePath, 'advanced/iot-devices'),\n icon: <Cpu size={16} />,\n order: 10,\n },\n {\n id: 'assethandler-digital-twin',\n label: 'Digital Twin',\n path: joinPath(basePath, 'advanced/digital-twin'),\n icon: <Boxes size={16} />,\n order: 11,\n },\n {\n id: 'assethandler-sam',\n label: 'SAM',\n path: joinPath(basePath, 'advanced/sam-licenses'),\n icon: <KeyRound size={16} />,\n order: 12,\n },\n {\n id: 'assethandler-cmdb',\n label: 'CMDB',\n path: joinPath(basePath, 'advanced/cmdb-browser'),\n icon: <Network size={16} />,\n order: 13,\n },\n {\n id: 'assethandler-discovery',\n label: 'Discovery',\n path: joinPath(basePath, 'advanced/discovery-jobs'),\n icon: <Radar size={16} />,\n order: 14,\n },\n {\n id: 'assethandler-provenance',\n label: 'Provenance',\n path: joinPath(basePath, 'advanced/provenance'),\n icon: <ShieldCheck size={16} />,\n order: 15,\n },\n {\n id: 'assethandler-esg',\n label: 'ESG',\n path: joinPath(basePath, 'advanced/esg-dashboard'),\n icon: <Leaf size={16} />,\n order: 16,\n },\n {\n id: 'assethandler-ai',\n label: 'AI Predictions',\n path: joinPath(basePath, 'advanced/ai-predictions'),\n icon: <BrainCircuit size={16} />,\n order: 17,\n },\n ],\n };\n\n if (navItem.children) {\n navItem.children = navItem.children.filter((child) => !isHidden(child.id));\n }\n\n return registerNavItems(navItem);\n }, [basePath, registerNavItems, brandLabel, assetsLabel, hiddenCategoryIds]);\n\n useEffect(() => {\n if (!registerFooterItems) {\n return;\n }\n\n return registerFooterItems([\n {\n id: 'assethandler-status',\n label: `${brandLabel} Live`,\n type: 'status',\n section: 'left',\n order: 10,\n },\n ]);\n }, [registerFooterItems, brandLabel]);\n\n return (\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <AssetHandlerProvider {...props}>\n <AssetHandlerRoutes />\n </AssetHandlerProvider>\n </FeatureFlagProvider>\n );\n};\n"],"mappings":";;;;;;;;AAqBA,IAAa,KAA+C,MAAU;CACpE,IAAM,EACJ,qBACA,wBACA,cAAW,KACX,gBAAa,gBACb,gBACA,yBACE,GACE,IAAc,GAAa,UAAU;CAwJ3C,OAtJA,QAAgB;EACd,IAAI,CAAC,GACH;EAKF,IAAM,IAAS,IAAI,IAAI,KAAqB,CAAC,CAAC,GACxC,KAAY,MAAe,EAAO,IAAI,EAAG,QAAQ,kBAAkB,EAAE,CAAC,GAEtE,IAAmB;GACvB,IAAI;GACJ,OAAO;GACP,MAAM;GACN,MAAM,kBAAC,GAAD,EAAO,MAAM,GAAK,CAAA;GACxB,OAAO;GACP,OAAO;GACP,UAAU;IACR;KACE,IAAI;KACJ,OAAO;KACP,MAAM;KACN,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,mBAAmB;KAC5C,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,wBAAwB;KACjD,MAAM,kBAAC,GAAD,EAAU,MAAM,GAAK,CAAA;KAC3B,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,2BAA2B;KACpD,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,cAAc;KACvC,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,qBAAqB;KAC9C,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,2BAA2B;KACpD,MAAM,kBAAC,GAAD,EAAU,MAAM,GAAK,CAAA;KAC3B,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,uBAAuB;KAChD,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,sBAAsB;KAC/C,MAAM,kBAAC,GAAD,EAAK,MAAM,GAAK,CAAA;KACtB,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,uBAAuB;KAChD,MAAM,kBAAC,GAAD,EAAO,MAAM,GAAK,CAAA;KACxB,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,uBAAuB;KAChD,MAAM,kBAAC,GAAD,EAAU,MAAM,GAAK,CAAA;KAC3B,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,uBAAuB;KAChD,MAAM,kBAAC,GAAD,EAAS,MAAM,GAAK,CAAA;KAC1B,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,yBAAyB;KAClD,MAAM,kBAAC,GAAD,EAAO,MAAM,GAAK,CAAA;KACxB,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,qBAAqB;KAC9C,MAAM,kBAAC,GAAD,EAAa,MAAM,GAAK,CAAA;KAC9B,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,wBAAwB;KACjD,MAAM,kBAAC,GAAD,EAAM,MAAM,GAAK,CAAA;KACvB,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,MAAM,EAAS,GAAU,yBAAyB;KAClD,MAAM,kBAAC,GAAD,EAAc,MAAM,GAAK,CAAA;KAC/B,OAAO;IACT;GACF;EACF;EAMA,OAJA,AACE,EAAQ,aAAW,EAAQ,SAAS,QAAQ,MAAU,CAAC,EAAS,EAAM,EAAE,CAAC,GAGpE,EAAiB,CAAO;CACjC,GAAG;EAAC;EAAU;EAAkB;EAAY;EAAa;CAAiB,CAAC,GAE3E,QAAgB;EACT,OAIL,OAAO,EAAoB,CACzB;GACE,IAAI;GACJ,OAAO,GAAG,EAAW;GACrB,MAAM;GACN,SAAS;GACT,OAAO;EACT,CACF,CAAC;CACH,GAAG,CAAC,GAAqB,CAAU,CAAC,GAGlC,kBAAC,GAAD;EAAqB,aAAa;EAAM,SAAQ;EAAS,gBAAgB;YACvE,kBAAC,GAAD;GAAsB,GAAI;aACxB,kBAAC,GAAD,CAAqB,CAAA;EACD,CAAA;CACH,CAAA;AAEzB"}
1
+ {"version":3,"file":"AssetHandlerRoot.js","names":[],"sources":["../../src/assethandler/AssetHandlerRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport {\n BookOpen,\n BrainCircuit,\n BellRing,\n Boxes,\n Cpu,\n KeyRound,\n Leaf,\n Network,\n Radar,\n ScanLine,\n ShieldCheck,\n} from 'lucide-react';\n\nimport { AssetHandlerRoutes } from './AssetHandlerRoutes';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { AssetHandlerProvider } from './providers/AssetHandlerProvider';\nimport type { AssetHandlerRootProps, NavItem } from './types';\nimport { joinPath } from './utils/navigation';\n\nexport const AssetHandlerRoot: FC<AssetHandlerRootProps> = (props) => {\n const {\n registerNavItems,\n registerFooterItems,\n basePath = '/',\n brandLabel = 'AssetHandler',\n terminology,\n hiddenCategoryIds,\n } = props;\n const assetsLabel = terminology?.assets || 'Assets';\n\n useEffect(() => {\n if (!registerNavItems) {\n return;\n }\n\n // Consumers can hide advanced (IT-specific) nav children by passing their\n // id with the \"assethandler-\" prefix stripped, e.g. \"digital-twin\".\n const hidden = new Set(hiddenCategoryIds ?? []);\n const isHidden = (id: string) => hidden.has(id.replace(/^assethandler-/, ''));\n\n const navItem: NavItem = {\n id: 'assethandler',\n label: brandLabel,\n path: basePath,\n icon: <Boxes size={20} />,\n order: 82,\n group: 'products',\n children: [\n {\n id: 'assethandler-dashboard',\n label: 'Dashboard',\n path: basePath,\n order: 0,\n },\n {\n id: 'assethandler-assets',\n label: assetsLabel,\n path: joinPath(basePath, 'assets/asset-list'),\n order: 1,\n },\n {\n id: 'assethandler-physical-audits',\n label: 'Physical Audits',\n path: joinPath(basePath, 'assets/physical-audits'),\n icon: <ScanLine size={16} />,\n order: 2,\n },\n {\n id: 'assethandler-operations',\n label: 'Operations',\n path: joinPath(basePath, 'operations/operations-hub'),\n order: 3,\n },\n {\n id: 'assethandler-itil',\n label: 'ITIL',\n path: joinPath(basePath, 'itil/itilhub'),\n order: 3,\n },\n {\n id: 'assethandler-finance',\n label: 'Finance',\n path: joinPath(basePath, 'finance/finance-hub'),\n order: 4,\n },\n {\n id: 'assethandler-deadline-alerts',\n label: 'Deadline Alerts',\n path: joinPath(basePath, 'analytics/deadline-alerts'),\n icon: <BellRing size={16} />,\n order: 5,\n },\n {\n id: 'assethandler-security',\n label: 'Security',\n path: joinPath(basePath, 'security/security-hub'),\n order: 7,\n },\n {\n id: 'assethandler-iot',\n label: 'IoT Devices',\n path: joinPath(basePath, 'advanced/iot-devices'),\n icon: <Cpu size={16} />,\n order: 10,\n },\n {\n id: 'assethandler-digital-twin',\n label: 'Digital Twin',\n path: joinPath(basePath, 'advanced/digital-twin'),\n icon: <Boxes size={16} />,\n order: 11,\n },\n {\n id: 'assethandler-sam',\n label: 'SAM',\n path: joinPath(basePath, 'advanced/sam-licenses'),\n icon: <KeyRound size={16} />,\n order: 12,\n },\n {\n id: 'assethandler-cmdb',\n label: 'CMDB',\n path: joinPath(basePath, 'advanced/cmdb-browser'),\n icon: <Network size={16} />,\n order: 13,\n },\n {\n id: 'assethandler-discovery',\n label: 'Discovery',\n path: joinPath(basePath, 'advanced/discovery-jobs'),\n icon: <Radar size={16} />,\n order: 14,\n },\n {\n id: 'assethandler-provenance',\n label: 'Provenance',\n path: joinPath(basePath, 'advanced/provenance'),\n icon: <ShieldCheck size={16} />,\n order: 15,\n },\n {\n id: 'assethandler-esg',\n label: 'ESG',\n path: joinPath(basePath, 'advanced/esg-dashboard'),\n icon: <Leaf size={16} />,\n order: 16,\n },\n {\n id: 'assethandler-knowledge-base',\n label: 'Knowledge Base',\n path: joinPath(basePath, 'advanced/knowledge-base'),\n icon: <BookOpen size={16} />,\n order: 17,\n },\n {\n id: 'assethandler-ai',\n label: 'AI Predictions',\n path: joinPath(basePath, 'advanced/ai-predictions'),\n icon: <BrainCircuit size={16} />,\n order: 18,\n },\n ],\n };\n\n if (navItem.children) {\n navItem.children = navItem.children.filter((child) => !isHidden(child.id));\n }\n\n return registerNavItems(navItem);\n }, [basePath, registerNavItems, brandLabel, assetsLabel, hiddenCategoryIds]);\n\n useEffect(() => {\n if (!registerFooterItems) {\n return;\n }\n\n return registerFooterItems([\n {\n id: 'assethandler-status',\n label: `${brandLabel} Live`,\n type: 'status',\n section: 'left',\n order: 10,\n },\n ]);\n }, [registerFooterItems, brandLabel]);\n\n return (\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <AssetHandlerProvider {...props}>\n <AssetHandlerRoutes />\n </AssetHandlerProvider>\n </FeatureFlagProvider>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Proactive runbook recall (BOFF-5804).
3
+ *
4
+ * The knowledge base already stores the link between an article and the asset
5
+ * or incident it documents (`KnowledgeArticle.relatedAssetId` /
6
+ * `relatedIncidentId`), and the service exposes both as filters on
7
+ * `knowledgeArticles`. Nothing consumed them until now: a technician looking at
8
+ * a failing asset had no way to know a published fix already existed unless
9
+ * they went to the knowledge base and searched for it by hand.
10
+ *
11
+ * This panel closes that loop. It asks the service for the PUBLISHED articles
12
+ * linked to the record it is mounted on and shows them in place. Drafts are
13
+ * deliberately excluded — an unpublished runbook is not guidance yet.
14
+ *
15
+ * Nothing here is synthesised: with no linked article the panel says so rather
16
+ * than suggesting something unrelated.
17
+ */
18
+ export interface RelatedRunbooksPanelProps {
19
+ /** Show runbooks linked to this asset. */
20
+ relatedAssetId?: string | null;
21
+ /** Show runbooks linked to this incident. */
22
+ relatedIncidentId?: string | null;
23
+ /** What the runbooks are being recalled for, e.g. "AH-0871 — HVAC Unit A3". */
24
+ contextLabel?: string;
25
+ }
26
+ export declare function RelatedRunbooksPanel({ relatedAssetId, relatedIncidentId, contextLabel, }: RelatedRunbooksPanelProps): import("react").JSX.Element | null;
27
+ //# sourceMappingURL=RelatedRunbooksPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelatedRunbooksPanel.d.ts","sourceRoot":"","sources":["../../../src/assethandler/components/RelatedRunbooksPanel.tsx"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,yBAAyB;IACxC,0CAA0C;IAC1C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqDD,wBAAgB,oBAAoB,CAAC,EACnC,cAAc,EACd,iBAAiB,EACjB,YAAY,GACb,EAAE,yBAAyB,sCAgK3B"}
@@ -0,0 +1,153 @@
1
+ import { useAssetHandlerNavigate as e } from "../hooks/useAssetHandlerNavigate.js";
2
+ import { notify as t } from "../utils/toast.js";
3
+ import { useMemo as n, useState as r } from "react";
4
+ import { BookOpen as i, ChevronDown as a, ChevronRight as o, Eye as s, LifeBuoy as c } from "lucide-react";
5
+ import { gql as l } from "@apollo/client";
6
+ import { useMutation as u, useQuery as d } from "@apollo/client/react";
7
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
8
+ import { Button as m, Card as h, CardContent as g, CardHeader as _, CardTitle as v } from "@burdenoff/fe-libs/ui";
9
+ //#region src/assethandler/components/RelatedRunbooksPanel.tsx
10
+ var y = l`
11
+ query AssetHandlerRelatedRunbooks($relatedAssetId: ID, $relatedIncidentId: ID) {
12
+ knowledgeArticles(
13
+ relatedAssetId: $relatedAssetId
14
+ relatedIncidentId: $relatedIncidentId
15
+ status: PUBLISHED
16
+ ) {
17
+ id
18
+ title
19
+ summary
20
+ content
21
+ tags
22
+ views
23
+ updatedAt
24
+ }
25
+ }
26
+ `, b = l`
27
+ mutation AssetHandlerRecordRunbookView($id: ID!) {
28
+ recordKnowledgeArticleView(id: $id) {
29
+ id
30
+ views
31
+ }
32
+ }
33
+ `;
34
+ function x(e) {
35
+ let t = new Date(e);
36
+ return Number.isNaN(t.getTime()) ? "—" : t.toLocaleDateString();
37
+ }
38
+ function S({ relatedAssetId: l, relatedIncidentId: S, contextLabel: C }) {
39
+ let w = e(), [T, E] = r(null), [D, O] = r([]), k = !l && !S, { data: A, loading: j, error: M } = d(y, {
40
+ variables: {
41
+ relatedAssetId: l ?? null,
42
+ relatedIncidentId: S ?? null
43
+ },
44
+ skip: k,
45
+ fetchPolicy: "cache-and-network"
46
+ }), [N] = u(b), P = n(() => A?.knowledgeArticles ?? [], [A?.knowledgeArticles]), F = (e) => e.views + +!!D.includes(e.id), I = (e) => {
47
+ if (T === e.id) {
48
+ E(null);
49
+ return;
50
+ }
51
+ E(e.id), !D.includes(e.id) && N({ variables: { id: e.id } }).then((t) => {
52
+ t.data?.recordKnowledgeArticleView && O((t) => t.includes(e.id) ? t : [...t, e.id]);
53
+ }).catch((e) => {
54
+ t.error("Could not record runbook view", e instanceof Error ? e.message : "The runbook is still available to read.");
55
+ });
56
+ };
57
+ if (k) return null;
58
+ let L = S ? "incident" : "asset";
59
+ return /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(_, { children: [/* @__PURE__ */ p(v, {
60
+ className: "flex flex-wrap items-center gap-2 text-base",
61
+ children: [
62
+ /* @__PURE__ */ f(c, { className: "h-4 w-4" }),
63
+ "Runbooks for this ",
64
+ L,
65
+ P.length > 0 ? /* @__PURE__ */ p("span", {
66
+ className: "text-sm font-normal text-text-secondary",
67
+ children: [P.length, " published"]
68
+ }) : null
69
+ ]
70
+ }), C ? /* @__PURE__ */ f("p", {
71
+ className: "text-xs text-text-secondary",
72
+ children: C
73
+ }) : null] }), /* @__PURE__ */ p(g, {
74
+ className: "space-y-3",
75
+ children: [
76
+ j && P.length === 0 ? /* @__PURE__ */ f("div", {
77
+ className: "space-y-2",
78
+ children: Array.from({ length: 2 }).map((e, t) => /* @__PURE__ */ f("div", { className: "h-14 rounded-lg bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
79
+ }) : null,
80
+ M && P.length === 0 ? /* @__PURE__ */ p("p", {
81
+ className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text",
82
+ children: ["Could not load linked runbooks. ", M.message]
83
+ }) : null,
84
+ !j && !M && P.length === 0 ? /* @__PURE__ */ p("p", {
85
+ className: "rounded-lg border border-dashed border-border-seam p-3 text-sm text-text-secondary",
86
+ children: [
87
+ "No published runbook is linked to this ",
88
+ L,
89
+ " yet. Link one from the knowledge base so the next responder finds the fix here."
90
+ ]
91
+ }) : null,
92
+ P.length > 0 ? /* @__PURE__ */ f("ul", {
93
+ className: "space-y-2",
94
+ children: P.map((e) => {
95
+ let t = T === e.id;
96
+ return /* @__PURE__ */ p("li", {
97
+ className: "rounded-lg border border-border-seam",
98
+ children: [/* @__PURE__ */ p("button", {
99
+ type: "button",
100
+ onClick: () => I(e),
101
+ "aria-expanded": t,
102
+ className: "flex w-full items-start gap-2 p-3 text-left hover:bg-bg-sunken/50",
103
+ children: [f(t ? a : o, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ p("span", {
104
+ className: "min-w-0 flex-1",
105
+ children: [
106
+ /* @__PURE__ */ f("span", {
107
+ className: "block text-sm font-medium text-text-primary",
108
+ children: e.title
109
+ }),
110
+ e.summary ? /* @__PURE__ */ f("span", {
111
+ className: "mt-0.5 block text-xs text-text-secondary",
112
+ children: e.summary
113
+ }) : null,
114
+ /* @__PURE__ */ p("span", {
115
+ className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-text-muted",
116
+ children: [
117
+ /* @__PURE__ */ p("span", { children: ["Updated ", x(e.updatedAt)] }),
118
+ /* @__PURE__ */ p("span", {
119
+ className: "inline-flex items-center gap-1 tabular-nums",
120
+ children: [/* @__PURE__ */ f(s, { className: "h-3 w-3" }), F(e).toLocaleString()]
121
+ }),
122
+ e.tags.map((e) => /* @__PURE__ */ f("span", {
123
+ className: "rounded-full bg-status-neutral-bg-subtle px-2 py-0.5 font-medium text-status-neutral-text",
124
+ children: e
125
+ }, e))
126
+ ]
127
+ })
128
+ ]
129
+ })]
130
+ }), t ? /* @__PURE__ */ f("div", {
131
+ className: "border-t border-border-seam p-3",
132
+ children: /* @__PURE__ */ f("p", {
133
+ className: "whitespace-pre-wrap text-sm leading-6 text-text-secondary",
134
+ children: e.content
135
+ })
136
+ }) : null]
137
+ }, e.id);
138
+ })
139
+ }) : null,
140
+ /* @__PURE__ */ p(m, {
141
+ variant: "outline",
142
+ size: "sm",
143
+ onClick: () => w("/advanced/knowledge-base"),
144
+ className: "w-full sm:w-auto",
145
+ children: [/* @__PURE__ */ f(i, { className: "mr-2 h-4 w-4" }), "Open knowledge base"]
146
+ })
147
+ ]
148
+ })] });
149
+ }
150
+ //#endregion
151
+ export { S as RelatedRunbooksPanel };
152
+
153
+ //# sourceMappingURL=RelatedRunbooksPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelatedRunbooksPanel.js","names":[],"sources":["../../../src/assethandler/components/RelatedRunbooksPanel.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Button, Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { BookOpen, ChevronDown, ChevronRight, Eye, LifeBuoy } from 'lucide-react';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport { notify } from '../utils/toast';\n\n/**\n * Proactive runbook recall (BOFF-5804).\n *\n * The knowledge base already stores the link between an article and the asset\n * or incident it documents (`KnowledgeArticle.relatedAssetId` /\n * `relatedIncidentId`), and the service exposes both as filters on\n * `knowledgeArticles`. Nothing consumed them until now: a technician looking at\n * a failing asset had no way to know a published fix already existed unless\n * they went to the knowledge base and searched for it by hand.\n *\n * This panel closes that loop. It asks the service for the PUBLISHED articles\n * linked to the record it is mounted on and shows them in place. Drafts are\n * deliberately excluded — an unpublished runbook is not guidance yet.\n *\n * Nothing here is synthesised: with no linked article the panel says so rather\n * than suggesting something unrelated.\n */\nexport interface RelatedRunbooksPanelProps {\n /** Show runbooks linked to this asset. */\n relatedAssetId?: string | null;\n /** Show runbooks linked to this incident. */\n relatedIncidentId?: string | null;\n /** What the runbooks are being recalled for, e.g. \"AH-0871 — HVAC Unit A3\". */\n contextLabel?: string;\n}\n\ninterface RunbookArticle {\n id: string;\n title: string;\n summary: string | null;\n content: string;\n tags: string[];\n views: number;\n updatedAt: string;\n}\n\ninterface RelatedRunbooksResult {\n knowledgeArticles: RunbookArticle[];\n}\n\ninterface RecordViewResult {\n recordKnowledgeArticleView: { id: string; views: number };\n}\n\nconst RELATED_RUNBOOKS_QUERY = gql`\n query AssetHandlerRelatedRunbooks($relatedAssetId: ID, $relatedIncidentId: ID) {\n knowledgeArticles(\n relatedAssetId: $relatedAssetId\n relatedIncidentId: $relatedIncidentId\n status: PUBLISHED\n ) {\n id\n title\n summary\n content\n tags\n views\n updatedAt\n }\n }\n`;\n\nconst RECORD_RUNBOOK_VIEW_MUTATION = gql`\n mutation AssetHandlerRecordRunbookView($id: ID!) {\n recordKnowledgeArticleView(id: $id) {\n id\n views\n }\n }\n`;\n\nfunction formatDate(iso: string): string {\n const parsed = new Date(iso);\n if (Number.isNaN(parsed.getTime())) return '—';\n return parsed.toLocaleDateString();\n}\n\nexport function RelatedRunbooksPanel({\n relatedAssetId,\n relatedIncidentId,\n contextLabel,\n}: RelatedRunbooksPanelProps) {\n const navigate = useAssetHandlerNavigate();\n const [openId, setOpenId] = useState<string | null>(null);\n const [viewedIds, setViewedIds] = useState<string[]>([]);\n\n const skip = !relatedAssetId && !relatedIncidentId;\n\n const { data, loading, error } = useQuery<RelatedRunbooksResult>(RELATED_RUNBOOKS_QUERY, {\n variables: {\n relatedAssetId: relatedAssetId ?? null,\n relatedIncidentId: relatedIncidentId ?? null,\n },\n skip,\n fetchPolicy: 'cache-and-network',\n });\n\n const [recordView] = useMutation<RecordViewResult>(RECORD_RUNBOOK_VIEW_MUTATION);\n\n const articles = useMemo(() => data?.knowledgeArticles ?? [], [data?.knowledgeArticles]);\n\n // Views recorded during this mount, so the count the reader sees matches the\n // read they just performed without waiting for the list to refetch.\n const viewsFor = (article: RunbookArticle) =>\n article.views + (viewedIds.includes(article.id) ? 1 : 0);\n\n const toggle = (article: RunbookArticle) => {\n if (openId === article.id) {\n setOpenId(null);\n return;\n }\n setOpenId(article.id);\n if (viewedIds.includes(article.id)) return;\n void recordView({ variables: { id: article.id } })\n .then((result) => {\n if (!result.data?.recordKnowledgeArticleView) return;\n setViewedIds((current) =>\n current.includes(article.id) ? current : [...current, article.id]\n );\n })\n .catch((recordError: unknown) => {\n notify.error(\n 'Could not record runbook view',\n recordError instanceof Error\n ? recordError.message\n : 'The runbook is still available to read.'\n );\n });\n };\n\n if (skip) return null;\n\n const subject = relatedIncidentId ? 'incident' : 'asset';\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2 text-base\">\n <LifeBuoy className=\"h-4 w-4\" />\n Runbooks for this {subject}\n {articles.length > 0 ? (\n <span className=\"text-sm font-normal text-text-secondary\">\n {articles.length} published\n </span>\n ) : null}\n </CardTitle>\n {contextLabel ? <p className=\"text-xs text-text-secondary\">{contextLabel}</p> : null}\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {loading && articles.length === 0 ? (\n <div className=\"space-y-2\">\n {Array.from({ length: 2 }).map((_, i) => (\n <div\n key={i}\n className=\"h-14 rounded-lg bg-bg-sunken motion-safe:animate-vc-shimmer\"\n />\n ))}\n </div>\n ) : null}\n\n {error && articles.length === 0 ? (\n <p className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text\">\n Could not load linked runbooks. {error.message}\n </p>\n ) : null}\n\n {!loading && !error && articles.length === 0 ? (\n <p className=\"rounded-lg border border-dashed border-border-seam p-3 text-sm text-text-secondary\">\n No published runbook is linked to this {subject} yet. Link one from the knowledge base\n so the next responder finds the fix here.\n </p>\n ) : null}\n\n {articles.length > 0 ? (\n <ul className=\"space-y-2\">\n {articles.map((article) => {\n const isOpen = openId === article.id;\n return (\n <li key={article.id} className=\"rounded-lg border border-border-seam\">\n <button\n type=\"button\"\n onClick={() => toggle(article)}\n aria-expanded={isOpen}\n className=\"flex w-full items-start gap-2 p-3 text-left hover:bg-bg-sunken/50\"\n >\n {isOpen ? (\n <ChevronDown className=\"mt-0.5 h-4 w-4 shrink-0 text-text-secondary\" />\n ) : (\n <ChevronRight className=\"mt-0.5 h-4 w-4 shrink-0 text-text-secondary\" />\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-sm font-medium text-text-primary\">\n {article.title}\n </span>\n {article.summary ? (\n <span className=\"mt-0.5 block text-xs text-text-secondary\">\n {article.summary}\n </span>\n ) : null}\n <span className=\"mt-1 flex flex-wrap items-center gap-2 text-xs text-text-muted\">\n <span>Updated {formatDate(article.updatedAt)}</span>\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <Eye className=\"h-3 w-3\" />\n {viewsFor(article).toLocaleString()}\n </span>\n {article.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-status-neutral-bg-subtle px-2 py-0.5 font-medium text-status-neutral-text\"\n >\n {tag}\n </span>\n ))}\n </span>\n </span>\n </button>\n {isOpen ? (\n <div className=\"border-t border-border-seam p-3\">\n <p className=\"whitespace-pre-wrap text-sm leading-6 text-text-secondary\">\n {article.content}\n </p>\n </div>\n ) : null}\n </li>\n );\n })}\n </ul>\n ) : null}\n\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigate('/advanced/knowledge-base')}\n className=\"w-full sm:w-auto\"\n >\n <BookOpen className=\"mr-2 h-4 w-4\" />\n Open knowledge base\n </Button>\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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"}
@@ -4,6 +4,8 @@ export { CommentsPanel } from './CommentsPanel';
4
4
  export type { CommentsPanelProps } from './CommentsPanel';
5
5
  export { ActivityTimeline } from './ActivityTimeline';
6
6
  export type { ActivityTimelineProps } from './ActivityTimeline';
7
+ export { RelatedRunbooksPanel } from './RelatedRunbooksPanel';
8
+ export type { RelatedRunbooksPanelProps } from './RelatedRunbooksPanel';
7
9
  export { Pagination, usePagination } from './Pagination';
8
10
  export type { PaginationProps, UsePaginationResult, UsePaginationOptions, AssetHandlerPaginationInput, } from './Pagination';
9
11
  export { NotFoundState } from './NotFoundState';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/assethandler/components/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/assethandler/components/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAExE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,cAAc,UAAU,CAAC"}
@@ -10,6 +10,7 @@ import "./charts/RadialGauge.js";
10
10
  import "./charts/ProgressMeter.js";
11
11
  import "./charts/index.js";
12
12
  import "./ActivityTimeline.js";
13
+ import "./RelatedRunbooksPanel.js";
13
14
  import "./Pagination.js";
14
15
  import "./NotFoundState.js";
15
16
  import "./ListEmptyState.js";
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsAssetCheckInOutPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/AssetsAssetCheckInOutPage.tsx"],"names":[],"mappings":"AA8MA,wBAAgB,yBAAyB,gCAilBxC"}
1
+ {"version":3,"file":"AssetsAssetCheckInOutPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/AssetsAssetCheckInOutPage.tsx"],"names":[],"mappings":"AAgOA,wBAAgB,yBAAyB,gCA2mBxC"}