@burdenoff/microfe-assethandler 2026.714.2 → 2026.719.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 (29) hide show
  1. package/dist/assethandler/AssetHandlerRoutes.d.ts.map +1 -1
  2. package/dist/assethandler/AssetHandlerRoutes.js +9 -17
  3. package/dist/assethandler/AssetHandlerRoutes.js.map +1 -1
  4. package/dist/assethandler/ops/NewWorkOrderDialog.d.ts.map +1 -1
  5. package/dist/assethandler/ops/NewWorkOrderDialog.js +110 -74
  6. package/dist/assethandler/ops/NewWorkOrderDialog.js.map +1 -1
  7. package/dist/assethandler/pages/AssetsAssetCreatePage.d.ts.map +1 -1
  8. package/dist/assethandler/pages/AssetsAssetCreatePage.js +189 -126
  9. package/dist/assethandler/pages/AssetsAssetCreatePage.js.map +1 -1
  10. package/dist/assethandler/pages/AssetsAssetDetailPage.d.ts.map +1 -1
  11. package/dist/assethandler/pages/AssetsAssetDetailPage.js +312 -251
  12. package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
  13. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.d.ts.map +1 -1
  14. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +286 -222
  15. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
  16. package/dist/stories/ListEmptyState.stories.d.ts +10 -0
  17. package/dist/stories/ListEmptyState.stories.d.ts.map +1 -0
  18. package/dist/stories/SectionHeader.stories.d.ts +10 -0
  19. package/dist/stories/SectionHeader.stories.d.ts.map +1 -0
  20. package/dist/stories/StatTile.stories.d.ts +10 -0
  21. package/dist/stories/StatTile.stories.d.ts.map +1 -0
  22. package/dist/utils/pageContext.d.ts.map +1 -1
  23. package/dist/utils/pageContext.js +26 -18
  24. package/dist/utils/pageContext.js.map +1 -1
  25. package/package.json +16 -3
  26. package/dist/assethandler/pages/EsgDashboardPage.js +0 -423
  27. package/dist/assethandler/pages/EsgDashboardPage.js.map +0 -1
  28. package/dist/assethandler/pages/KnowledgeBasePage.js +0 -521
  29. package/dist/assethandler/pages/KnowledgeBasePage.js.map +0 -1
@@ -1,521 +0,0 @@
1
- import { useAssetHandlerNavigate as e } from "../hooks/useAssetHandlerNavigate.js";
2
- import { cn as t } from "../utils/cn.js";
3
- import { notify as n } from "../utils/toast.js";
4
- import { seriesColor as r } from "../components/charts/chartTheme.js";
5
- import { BarsChart as i } from "../components/charts/BarsChart.js";
6
- import { DonutChart as a } from "../components/charts/DonutChart.js";
7
- import { Pagination as o, usePagination as s } from "../components/Pagination.js";
8
- import { ChartCard as c } from "../components/ChartCard.js";
9
- import { SectionHeader as l } from "../components/SectionHeader.js";
10
- import "../components/index.js";
11
- import { useMemo as u, useState as d } from "react";
12
- import { BookOpen as f, ExternalLink as p, Eye as m, Link2 as h, Plus as g, Search as _, User as v } from "lucide-react";
13
- import { gql as y } from "@apollo/client";
14
- import { useMutation as b, useQuery as x } from "@apollo/client/react";
15
- import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
16
- import { Button as T, GlassCard as E, IllustratedEmptyState as D, Input as O, Label as k, PagePurpose as ee, ResponsiveDialog as A, ResponsiveDialogContent as j, ResponsiveDialogDescription as M, ResponsiveDialogFooter as N, ResponsiveDialogHeader as P, ResponsiveDialogTitle as F, Select as I, SelectContent as L, SelectItem as R, SelectTrigger as z, SelectValue as B, Textarea as V } from "@burdenoff/fe-libs/ui";
17
- //#region src/assethandler/pages/KnowledgeBasePage.tsx
18
- var H = y`
19
- query AssetHandlerKnowledgeArticles {
20
- knowledgeArticles {
21
- id
22
- title
23
- slug
24
- summary
25
- content
26
- status
27
- tags
28
- views
29
- createdBy
30
- updatedBy
31
- publishedAt
32
- createdAt
33
- updatedAt
34
- relatedAssetId
35
- relatedIncidentId
36
- }
37
- }
38
- `, U = y`
39
- mutation AssetHandlerCreateKnowledgeArticle($input: CreateKnowledgeArticleInput!) {
40
- createKnowledgeArticle(input: $input) {
41
- id
42
- title
43
- }
44
- }
45
- `, W = [
46
- "DRAFT",
47
- "PUBLISHED",
48
- "ARCHIVED"
49
- ], G = {
50
- PUBLISHED: {
51
- label: "Published",
52
- className: "bg-status-success-bg-subtle text-status-success-text"
53
- },
54
- DRAFT: {
55
- label: "Draft",
56
- className: "bg-bg-sunken text-text-secondary"
57
- },
58
- ARCHIVED: {
59
- label: "Archived",
60
- className: "bg-status-warning-bg-subtle text-status-warning-text"
61
- }
62
- }, K = (e) => e.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""), q = (e) => e ? new Date(e).toLocaleDateString(void 0, {
63
- year: "numeric",
64
- month: "short",
65
- day: "numeric"
66
- }) : "—";
67
- function te(e) {
68
- if (e.summary && e.summary.trim()) return e.summary.trim();
69
- let t = e.content.replace(/\s+/g, " ").trim();
70
- return t.length > 160 ? `${t.slice(0, 160)}…` : t;
71
- }
72
- function ne(e) {
73
- return (e.replace(/[^a-zA-Z0-9]/g, "").slice(0, 2) || "?").toUpperCase();
74
- }
75
- function J({ status: e }) {
76
- let n = G[e] ?? {
77
- label: e,
78
- className: "bg-bg-sunken text-text-secondary"
79
- };
80
- return /* @__PURE__ */ C("span", {
81
- className: t("inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium", n.className),
82
- children: n.label
83
- });
84
- }
85
- function re({ open: e, onOpenChange: t, onPublished: r }) {
86
- let [i, a] = d(""), [o, s] = d(""), [c, l] = d(!1), [u, f] = d(""), [p, m] = d(""), [h, g] = d(""), [_, v] = d("PUBLISHED"), y = () => {
87
- a(""), s(""), l(!1), f(""), m(""), g(""), v("PUBLISHED");
88
- }, [x, { loading: S }] = b(U, {
89
- onCompleted: (e) => {
90
- n.success("Article published", `${e.createKnowledgeArticle.title} is now available.`), y(), t(!1), r();
91
- },
92
- onError: (e) => n.error("Could not publish article", e.message)
93
- }), E = (e) => {
94
- a(e), c || s(K(e));
95
- };
96
- return /* @__PURE__ */ C(A, {
97
- open: e,
98
- onOpenChange: t,
99
- children: /* @__PURE__ */ w(j, {
100
- className: "max-h-[85vh] overflow-y-auto sm:max-w-2xl",
101
- children: [
102
- /* @__PURE__ */ w(P, { children: [/* @__PURE__ */ C(F, { children: "New Article" }), /* @__PURE__ */ C(M, { children: "Capture a runbook or fix so your team can find it later." })] }),
103
- /* @__PURE__ */ w("div", {
104
- className: "space-y-4",
105
- children: [
106
- /* @__PURE__ */ w("div", {
107
- className: "grid gap-4 md:grid-cols-2",
108
- children: [/* @__PURE__ */ w("div", {
109
- className: "space-y-2",
110
- children: [/* @__PURE__ */ C(k, { children: "Title *" }), /* @__PURE__ */ C(O, {
111
- value: i,
112
- onChange: (e) => E(e.target.value)
113
- })]
114
- }), /* @__PURE__ */ w("div", {
115
- className: "space-y-2",
116
- children: [/* @__PURE__ */ C(k, { children: "Slug *" }), /* @__PURE__ */ C(O, {
117
- value: o,
118
- onChange: (e) => {
119
- l(!0), s(e.target.value);
120
- }
121
- })]
122
- })]
123
- }),
124
- /* @__PURE__ */ w("div", {
125
- className: "space-y-2",
126
- children: [/* @__PURE__ */ C(k, { children: "Summary" }), /* @__PURE__ */ C(O, {
127
- placeholder: "One-line description",
128
- value: u,
129
- onChange: (e) => f(e.target.value)
130
- })]
131
- }),
132
- /* @__PURE__ */ w("div", {
133
- className: "space-y-2",
134
- children: [/* @__PURE__ */ C(k, { children: "Body *" }), /* @__PURE__ */ C(V, {
135
- placeholder: "Write the full article body — steps, context, links…",
136
- value: p,
137
- onChange: (e) => m(e.target.value),
138
- rows: 8
139
- })]
140
- }),
141
- /* @__PURE__ */ w("div", {
142
- className: "grid gap-4 md:grid-cols-2",
143
- children: [/* @__PURE__ */ w("div", {
144
- className: "space-y-2",
145
- children: [/* @__PURE__ */ C(k, { children: "Category tags" }), /* @__PURE__ */ C(O, {
146
- placeholder: "Runbooks, Fixes, Procedures…",
147
- value: h,
148
- onChange: (e) => g(e.target.value)
149
- })]
150
- }), /* @__PURE__ */ w("div", {
151
- className: "space-y-2",
152
- children: [/* @__PURE__ */ C(k, { children: "Status" }), /* @__PURE__ */ w(I, {
153
- value: _,
154
- onValueChange: (e) => v(e),
155
- children: [/* @__PURE__ */ C(z, { children: /* @__PURE__ */ C(B, {}) }), /* @__PURE__ */ C(L, { children: W.map((e) => /* @__PURE__ */ C(R, {
156
- value: e,
157
- children: e
158
- }, e)) })]
159
- })]
160
- })]
161
- })
162
- ]
163
- }),
164
- /* @__PURE__ */ w(N, { children: [/* @__PURE__ */ C(T, {
165
- variant: "outline",
166
- onClick: () => t(!1),
167
- disabled: S,
168
- children: "Cancel"
169
- }), /* @__PURE__ */ C(T, {
170
- onClick: () => {
171
- if (!i.trim() || !o.trim()) {
172
- n.warning("Missing details", "Title and slug are required.");
173
- return;
174
- }
175
- if (!p.trim()) {
176
- n.warning("Body required", "Write the article body before publishing.");
177
- return;
178
- }
179
- let e = h.split(",").map((e) => e.trim()).filter((e) => e.length > 0);
180
- x({ variables: { input: {
181
- title: i.trim(),
182
- slug: o.trim(),
183
- summary: u.trim() || null,
184
- content: p.trim(),
185
- tags: e,
186
- status: _
187
- } } });
188
- },
189
- disabled: S,
190
- children: S ? "Publishing…" : "Publish article"
191
- })] })
192
- ]
193
- })
194
- });
195
- }
196
- function ie({ article: t, onOpenChange: n }) {
197
- let r = e();
198
- return /* @__PURE__ */ C(A, {
199
- open: !!t,
200
- onOpenChange: n,
201
- children: /* @__PURE__ */ C(j, {
202
- className: "max-h-[85vh] overflow-y-auto sm:max-w-2xl",
203
- children: t ? /* @__PURE__ */ w(S, { children: [
204
- /* @__PURE__ */ w(P, { children: [
205
- /* @__PURE__ */ w("div", {
206
- className: "flex flex-wrap items-center gap-2",
207
- children: [/* @__PURE__ */ C(J, { status: t.status }), t.tags.map((e) => /* @__PURE__ */ C("span", {
208
- className: "rounded-full bg-action-primary-bg/10 px-2 py-0.5 text-xs font-medium text-primary",
209
- children: e
210
- }, e))]
211
- }),
212
- /* @__PURE__ */ C(F, {
213
- className: "mt-1",
214
- children: t.title
215
- }),
216
- /* @__PURE__ */ w(M, { children: [
217
- "Updated ",
218
- q(t.updatedAt),
219
- " · ",
220
- t.views.toLocaleString(),
221
- " views"
222
- ] })
223
- ] }),
224
- /* @__PURE__ */ C("div", {
225
- className: "whitespace-pre-wrap text-sm leading-relaxed text-text-primary",
226
- children: t.content
227
- }),
228
- t.relatedAssetId || t.relatedIncidentId ? /* @__PURE__ */ w("div", {
229
- className: "mt-4 space-y-2 border-t border-border-seam pt-4",
230
- children: [/* @__PURE__ */ w("h4", {
231
- className: "flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-text-secondary",
232
- children: [/* @__PURE__ */ C(h, { className: "h-3.5 w-3.5" }), "Linked records"]
233
- }), /* @__PURE__ */ w("div", {
234
- className: "flex flex-wrap gap-2",
235
- children: [t.relatedAssetId ? /* @__PURE__ */ w(T, {
236
- variant: "outline",
237
- size: "sm",
238
- onClick: () => {
239
- n(!1), r(`/assets/${t.relatedAssetId}`);
240
- },
241
- children: ["View linked asset", /* @__PURE__ */ C(p, { className: "ml-1.5 h-3.5 w-3.5" })]
242
- }) : null, t.relatedIncidentId ? /* @__PURE__ */ w(T, {
243
- variant: "outline",
244
- size: "sm",
245
- onClick: () => {
246
- n(!1), r(`/itil/incidents/${t.relatedIncidentId}`);
247
- },
248
- children: ["View linked incident", /* @__PURE__ */ C(p, { className: "ml-1.5 h-3.5 w-3.5" })]
249
- }) : null]
250
- })]
251
- }) : null
252
- ] }) : null
253
- })
254
- });
255
- }
256
- function Y() {
257
- let [e, n] = d(!1), [p, h] = d(""), [y, b] = d("ALL"), [S, A] = d("ALL"), [j, M] = d("recent"), [N, P] = d(null), { data: F, loading: V, refetch: U } = x(H, { fetchPolicy: "cache-and-network" }), K = u(() => F?.knowledgeArticles ?? [], [F?.knowledgeArticles]), Y = u(() => {
258
- let e = /* @__PURE__ */ new Map();
259
- for (let t of K) for (let n of t.tags) e.set(n, (e.get(n) ?? 0) + 1);
260
- return [...e.entries()].sort((e, t) => t[1] - e[1]);
261
- }, [K]), X = u(() => {
262
- let e = p.trim().toLowerCase();
263
- return [...K.filter((t) => y !== "ALL" && !t.tags.includes(y) || S !== "ALL" && t.status !== S ? !1 : e ? [
264
- t.title,
265
- t.summary ?? "",
266
- t.content,
267
- t.tags.join(" ")
268
- ].join(" ").toLowerCase().includes(e) : !0)].sort((e, t) => j === "views" ? t.views - e.views : new Date(t.updatedAt).getTime() - new Date(e.updatedAt).getTime());
269
- }, [
270
- K,
271
- p,
272
- y,
273
- S,
274
- j
275
- ]), Z = u(() => {
276
- let e = K.reduce((e, t) => (e[t.status] = (e[t.status] ?? 0) + 1, e), {});
277
- return Object.entries(e).map(([e, t], n) => ({
278
- name: G[e]?.label ?? e,
279
- value: t,
280
- color: r(n)
281
- }));
282
- }, [K]), Q = u(() => [...K].filter((e) => e.views > 0).sort((e, t) => t.views - e.views).slice(0, 6).map((e) => ({
283
- name: e.title,
284
- views: e.views
285
- })), [K]), $ = s(X, {
286
- pageSize: 9,
287
- resetKey: `${p}|${y}|${S}|${j}`
288
- });
289
- return /* @__PURE__ */ w("div", {
290
- className: "space-y-5 p-4 sm:p-6",
291
- children: [
292
- /* @__PURE__ */ C(l, {
293
- hero: !0,
294
- icon: f,
295
- title: "Knowledge Base",
296
- description: "Turn one-off fixes and runbooks into repeatable, searchable operational knowledge.",
297
- actions: /* @__PURE__ */ w(T, {
298
- className: "w-full sm:w-auto",
299
- onClick: () => n(!0),
300
- children: [/* @__PURE__ */ C(g, { className: "mr-2 h-4 w-4" }), "New Article"]
301
- })
302
- }),
303
- /* @__PURE__ */ C(ee, { children: "Capture the fixes and runbooks your team relies on so the next person doesn't start from scratch. Link articles to incidents and assets, then search them when troubleshooting." }),
304
- /* @__PURE__ */ C(re, {
305
- open: e,
306
- onOpenChange: n,
307
- onPublished: () => void U()
308
- }),
309
- /* @__PURE__ */ C(ie, {
310
- article: N,
311
- onOpenChange: (e) => !e && P(null)
312
- }),
313
- /* @__PURE__ */ w("div", {
314
- className: "relative",
315
- children: [/* @__PURE__ */ C(_, { className: "absolute left-3.5 top-1/2 h-4.5 w-4.5 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ C(O, {
316
- className: "h-12 pl-11 text-base",
317
- placeholder: "Search runbooks, fixes and procedures…",
318
- value: p,
319
- onChange: (e) => h(e.target.value),
320
- "aria-label": "Search knowledge articles"
321
- })]
322
- }),
323
- K.length > 0 && (Z.length > 0 || Q.length > 0) ? /* @__PURE__ */ w("div", {
324
- className: "grid gap-4 lg:grid-cols-2",
325
- children: [/* @__PURE__ */ C(c, {
326
- title: "Publishing status",
327
- subtitle: "Articles by status",
328
- children: /* @__PURE__ */ C(a, {
329
- data: Z,
330
- height: 200,
331
- centerLabel: "Articles",
332
- centerValue: K.length,
333
- ariaLabel: "Articles by status"
334
- })
335
- }), /* @__PURE__ */ C(c, {
336
- title: "Most consulted",
337
- subtitle: "Top articles by views",
338
- children: /* @__PURE__ */ C(i, {
339
- data: Q,
340
- xKey: "name",
341
- series: [{
342
- key: "views",
343
- label: "Views"
344
- }],
345
- orientation: "horizontal",
346
- height: 200,
347
- categoryWidth: 150,
348
- emptyLabel: "No views recorded yet",
349
- ariaLabel: "Top articles by views"
350
- })
351
- })]
352
- }) : null,
353
- /* @__PURE__ */ w("div", {
354
- className: "grid gap-5 lg:grid-cols-[200px_1fr]",
355
- children: [/* @__PURE__ */ w("aside", {
356
- className: "space-y-3",
357
- children: [
358
- /* @__PURE__ */ w("div", {
359
- className: "flex items-center justify-between gap-2",
360
- children: [/* @__PURE__ */ C("h3", {
361
- className: "text-sm font-semibold text-text-primary",
362
- children: "Category"
363
- }), /* @__PURE__ */ w(I, {
364
- value: j,
365
- onValueChange: (e) => M(e),
366
- children: [/* @__PURE__ */ C(z, {
367
- className: "h-8 w-[130px] text-xs lg:hidden",
368
- children: /* @__PURE__ */ C(B, {})
369
- }), /* @__PURE__ */ w(L, { children: [/* @__PURE__ */ C(R, {
370
- value: "recent",
371
- children: "Recently updated"
372
- }), /* @__PURE__ */ C(R, {
373
- value: "views",
374
- children: "Most viewed"
375
- })] })]
376
- })]
377
- }),
378
- /* @__PURE__ */ w("div", {
379
- className: "flex gap-2 overflow-x-auto pb-1 lg:flex-col lg:overflow-visible lg:pb-0",
380
- children: [/* @__PURE__ */ w("button", {
381
- type: "button",
382
- onClick: () => b("ALL"),
383
- className: t("shrink-0 rounded-md px-3 py-1.5 text-left text-sm font-medium transition-colors lg:w-full", y === "ALL" ? "bg-action-primary-bg/10 text-primary" : "text-text-secondary hover:text-text-primary"),
384
- children: ["All articles", /* @__PURE__ */ C("span", {
385
- className: "ml-1.5 text-xs text-text-muted tabular-nums",
386
- children: K.length
387
- })]
388
- }), Y.map(([e, n]) => /* @__PURE__ */ w("button", {
389
- type: "button",
390
- onClick: () => b(e),
391
- className: t("flex shrink-0 items-center justify-between gap-2 rounded-md px-3 py-1.5 text-left text-sm font-medium transition-colors lg:w-full", y === e ? "bg-action-primary-bg/10 text-primary" : "text-text-secondary hover:text-text-primary"),
392
- children: [/* @__PURE__ */ C("span", {
393
- className: "truncate",
394
- children: e
395
- }), /* @__PURE__ */ C("span", {
396
- className: "text-xs text-text-muted tabular-nums",
397
- children: n
398
- })]
399
- }, e))]
400
- }),
401
- /* @__PURE__ */ w("div", {
402
- className: "hidden space-y-1.5 border-t border-border-seam pt-3 lg:block",
403
- children: [
404
- /* @__PURE__ */ C(k, {
405
- className: "text-xs",
406
- children: "Status"
407
- }),
408
- /* @__PURE__ */ w(I, {
409
- value: S,
410
- onValueChange: A,
411
- children: [/* @__PURE__ */ C(z, {
412
- className: "h-9",
413
- children: /* @__PURE__ */ C(B, {})
414
- }), /* @__PURE__ */ w(L, { children: [/* @__PURE__ */ C(R, {
415
- value: "ALL",
416
- children: "All statuses"
417
- }), W.map((e) => /* @__PURE__ */ C(R, {
418
- value: e,
419
- children: e
420
- }, e))] })]
421
- }),
422
- /* @__PURE__ */ C(k, {
423
- className: "text-xs",
424
- children: "Sort"
425
- }),
426
- /* @__PURE__ */ w(I, {
427
- value: j,
428
- onValueChange: (e) => M(e),
429
- children: [/* @__PURE__ */ C(z, {
430
- className: "h-9",
431
- children: /* @__PURE__ */ C(B, {})
432
- }), /* @__PURE__ */ w(L, { children: [/* @__PURE__ */ C(R, {
433
- value: "recent",
434
- children: "Recently updated"
435
- }), /* @__PURE__ */ C(R, {
436
- value: "views",
437
- children: "Most viewed"
438
- })] })]
439
- })
440
- ]
441
- })
442
- ]
443
- }), /* @__PURE__ */ w("div", { children: [
444
- V && K.length === 0 ? /* @__PURE__ */ C("div", {
445
- className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3",
446
- children: Array.from({ length: 6 }).map((e, t) => /* @__PURE__ */ C("div", { className: "h-40 rounded-xl bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
447
- }) : null,
448
- !V && X.length === 0 ? /* @__PURE__ */ C(D, {
449
- illustration: p || y !== "ALL" || S !== "ALL" ? "empty-search" : "empty-data",
450
- title: p || y !== "ALL" || S !== "ALL" ? "No articles match your filters" : "No knowledge articles found",
451
- description: p || y !== "ALL" || S !== "ALL" ? "Try a different term, category or status." : "Publish an article to start building your knowledge base."
452
- }) : null,
453
- /* @__PURE__ */ C("div", {
454
- className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3",
455
- children: $.pageItems.map((e) => /* @__PURE__ */ C(E, {
456
- treatment: "glass",
457
- className: "border-border-seam",
458
- children: /* @__PURE__ */ w("button", {
459
- type: "button",
460
- onClick: () => P(e),
461
- className: "flex h-full w-full flex-col gap-3 p-4 text-left",
462
- children: [
463
- /* @__PURE__ */ w("div", {
464
- className: "flex flex-wrap items-center gap-1.5",
465
- children: [/* @__PURE__ */ C(J, { status: e.status }), e.tags.slice(0, 1).map((e) => /* @__PURE__ */ C("span", {
466
- className: "rounded-full bg-action-primary-bg/10 px-2 py-0.5 text-xs font-medium text-primary",
467
- children: e
468
- }, e))]
469
- }),
470
- /* @__PURE__ */ C("h2", {
471
- className: "line-clamp-2 text-base font-semibold text-text-primary",
472
- children: e.title
473
- }),
474
- /* @__PURE__ */ C("p", {
475
- className: "line-clamp-2 flex-1 text-sm text-text-secondary",
476
- children: te(e)
477
- }),
478
- /* @__PURE__ */ w("div", {
479
- className: "flex items-center justify-between gap-2 border-t border-border-seam/60 pt-3",
480
- children: [/* @__PURE__ */ w("div", {
481
- className: "flex min-w-0 items-center gap-2",
482
- children: [/* @__PURE__ */ C("span", {
483
- className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-[10px] font-semibold text-text-secondary",
484
- children: e.updatedBy ? ne(e.updatedBy) : /* @__PURE__ */ C(v, { className: "h-3 w-3" })
485
- }), /* @__PURE__ */ w("span", {
486
- className: "truncate text-xs text-text-secondary",
487
- children: ["Updated ", q(e.updatedAt)]
488
- })]
489
- }), /* @__PURE__ */ w("span", {
490
- className: "flex shrink-0 items-center gap-1 text-xs text-text-muted tabular-nums",
491
- children: [/* @__PURE__ */ C(m, { className: "h-3.5 w-3.5" }), e.views.toLocaleString()]
492
- })]
493
- })
494
- ]
495
- })
496
- }, e.id))
497
- }),
498
- /* @__PURE__ */ C("div", {
499
- className: "mt-4",
500
- children: /* @__PURE__ */ C(o, {
501
- page: $.page,
502
- pageCount: $.pageCount,
503
- rangeStart: $.rangeStart,
504
- rangeEnd: $.rangeEnd,
505
- totalItems: $.totalItems,
506
- canPrev: $.canPrev,
507
- canNext: $.canNext,
508
- onPrev: $.prevPage,
509
- onNext: $.nextPage,
510
- itemLabel: "articles"
511
- })
512
- })
513
- ] })]
514
- })
515
- ]
516
- });
517
- }
518
- //#endregion
519
- export { Y as KnowledgeBasePage };
520
-
521
- //# sourceMappingURL=KnowledgeBasePage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"KnowledgeBasePage.js","names":[],"sources":["../../../src/assethandler/pages/KnowledgeBasePage.tsx"],"sourcesContent":["import { BookOpen, Plus, Search, Eye, User, Link2, ExternalLink } from 'lucide-react';\nimport {\n Button,\n IllustratedEmptyState,\n GlassCard,\n PagePurpose,\n Input,\n Label,\n Textarea,\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 { useMemo, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Pagination,\n usePagination,\n SectionHeader,\n ChartCard,\n DonutChart,\n BarsChart,\n seriesColor,\n type DonutSlice,\n} from '../components';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport { cn } from '../utils/cn';\nimport { notify } from '../utils/toast';\n\nconst KNOWLEDGE_ARTICLES_QUERY = gql`\n query AssetHandlerKnowledgeArticles {\n knowledgeArticles {\n id\n title\n slug\n summary\n content\n status\n tags\n views\n createdBy\n updatedBy\n publishedAt\n createdAt\n updatedAt\n relatedAssetId\n relatedIncidentId\n }\n }\n`;\n\nconst CREATE_KNOWLEDGE_ARTICLE_MUTATION = gql`\n mutation AssetHandlerCreateKnowledgeArticle($input: CreateKnowledgeArticleInput!) {\n createKnowledgeArticle(input: $input) {\n id\n title\n }\n }\n`;\n\ninterface KnowledgeArticle {\n id: string;\n title: string;\n slug: string;\n summary: string | null;\n content: string;\n status: string;\n tags: string[];\n views: number;\n createdBy: string;\n updatedBy: string;\n publishedAt: string | null;\n createdAt: string;\n updatedAt: string;\n relatedAssetId: string | null;\n relatedIncidentId: string | null;\n}\n\ninterface CreateKnowledgeArticleResult {\n createKnowledgeArticle: { id: string; title: string };\n}\n\nconst ARTICLE_STATUSES = ['DRAFT', 'PUBLISHED', 'ARCHIVED'] as const;\n\nconst STATUS_META: Record<string, { label: string; className: string }> = {\n PUBLISHED: {\n label: 'Published',\n className: 'bg-status-success-bg-subtle text-status-success-text',\n },\n DRAFT: { label: 'Draft', className: 'bg-bg-sunken text-text-secondary' },\n ARCHIVED: {\n label: 'Archived',\n className: 'bg-status-warning-bg-subtle text-status-warning-text',\n },\n};\n\nconst slugify = (value: string): string =>\n value\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\nconst formatDate = (value: string | null): string =>\n value\n ? new Date(value).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n })\n : '—';\n\n/** A 2-line excerpt: the summary if present, otherwise the opening of the body. */\nfunction excerptOf(article: KnowledgeArticle): string {\n if (article.summary && article.summary.trim()) return article.summary.trim();\n const body = article.content.replace(/\\s+/g, ' ').trim();\n return body.length > 160 ? `${body.slice(0, 160)}…` : body;\n}\n\n/** Short avatar initials from an actor id (best-effort, no fabricated names). */\nfunction initialsOf(actor: string): string {\n const clean = actor.replace(/[^a-zA-Z0-9]/g, '');\n return (clean.slice(0, 2) || '?').toUpperCase();\n}\n\nfunction StatusPill({ status }: { status: string }) {\n const meta = STATUS_META[status] ?? {\n label: status,\n className: 'bg-bg-sunken text-text-secondary',\n };\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n meta.className\n )}\n >\n {meta.label}\n </span>\n );\n}\n\nfunction PublishArticleDialog({\n open,\n onOpenChange,\n onPublished,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onPublished: () => void;\n}) {\n const [title, setTitle] = useState('');\n const [slug, setSlug] = useState('');\n const [slugTouched, setSlugTouched] = useState(false);\n const [summary, setSummary] = useState('');\n const [content, setContent] = useState('');\n const [tags, setTags] = useState('');\n const [status, setStatus] = useState<(typeof ARTICLE_STATUSES)[number]>('PUBLISHED');\n\n const reset = () => {\n setTitle('');\n setSlug('');\n setSlugTouched(false);\n setSummary('');\n setContent('');\n setTags('');\n setStatus('PUBLISHED');\n };\n\n const [createArticle, { loading }] = useMutation<CreateKnowledgeArticleResult>(\n CREATE_KNOWLEDGE_ARTICLE_MUTATION,\n {\n onCompleted: (data) => {\n notify.success(\n 'Article published',\n `${data.createKnowledgeArticle.title} is now available.`\n );\n reset();\n onOpenChange(false);\n onPublished();\n },\n onError: (error) => notify.error('Could not publish article', error.message),\n }\n );\n\n const handleTitleChange = (next: string) => {\n setTitle(next);\n if (!slugTouched) setSlug(slugify(next));\n };\n\n const handleSubmit = () => {\n if (!title.trim() || !slug.trim()) {\n notify.warning('Missing details', 'Title and slug are required.');\n return;\n }\n if (!content.trim()) {\n notify.warning('Body required', 'Write the article body before publishing.');\n return;\n }\n const parsedTags = tags\n .split(',')\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n void createArticle({\n variables: {\n input: {\n title: title.trim(),\n slug: slug.trim(),\n summary: summary.trim() || null,\n content: content.trim(),\n tags: parsedTags,\n status,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-h-[85vh] overflow-y-auto sm:max-w-2xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Article</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Capture a runbook or fix so your team can find it later.\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>Title *</Label>\n <Input value={title} onChange={(e) => handleTitleChange(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Slug *</Label>\n <Input\n value={slug}\n onChange={(e) => {\n setSlugTouched(true);\n setSlug(e.target.value);\n }}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Summary</Label>\n <Input\n placeholder=\"One-line description\"\n value={summary}\n onChange={(e) => setSummary(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Body *</Label>\n <Textarea\n placeholder=\"Write the full article body — steps, context, links…\"\n value={content}\n onChange={(e) => setContent(e.target.value)}\n rows={8}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Category tags</Label>\n <Input\n placeholder=\"Runbooks, Fixes, Procedures…\"\n value={tags}\n onChange={(e) => setTags(e.target.value)}\n />\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 {ARTICLE_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\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 ? 'Publishing…' : 'Publish article'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\nfunction ArticleReader({\n article,\n onOpenChange,\n}: {\n article: KnowledgeArticle | null;\n onOpenChange: (open: boolean) => void;\n}) {\n const navigate = useAssetHandlerNavigate();\n return (\n <ResponsiveDialog open={Boolean(article)} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-h-[85vh] overflow-y-auto sm:max-w-2xl\">\n {article ? (\n <>\n <ResponsiveDialogHeader>\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusPill status={article.status} />\n {article.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-2 py-0.5 text-xs font-medium text-primary\"\n >\n {tag}\n </span>\n ))}\n </div>\n <ResponsiveDialogTitle className=\"mt-1\">{article.title}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Updated {formatDate(article.updatedAt)} · {article.views.toLocaleString()} views\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"whitespace-pre-wrap text-sm leading-relaxed text-text-primary\">\n {article.content}\n </div>\n {article.relatedAssetId || article.relatedIncidentId ? (\n <div className=\"mt-4 space-y-2 border-t border-border-seam pt-4\">\n <h4 className=\"flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n <Link2 className=\"h-3.5 w-3.5\" />\n Linked records\n </h4>\n <div className=\"flex flex-wrap gap-2\">\n {article.relatedAssetId ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n onOpenChange(false);\n navigate(`/assets/${article.relatedAssetId}`);\n }}\n >\n View linked asset\n <ExternalLink className=\"ml-1.5 h-3.5 w-3.5\" />\n </Button>\n ) : null}\n {article.relatedIncidentId ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n onOpenChange(false);\n navigate(`/itil/incidents/${article.relatedIncidentId}`);\n }}\n >\n View linked incident\n <ExternalLink className=\"ml-1.5 h-3.5 w-3.5\" />\n </Button>\n ) : null}\n </div>\n </div>\n ) : null}\n </>\n ) : null}\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\ntype SortKey = 'recent' | 'views';\n\nexport function KnowledgeBasePage() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [search, setSearch] = useState('');\n const [category, setCategory] = useState<string>('ALL');\n const [statusFilter, setStatusFilter] = useState<string>('ALL');\n const [sort, setSort] = useState<SortKey>('recent');\n const [reading, setReading] = useState<KnowledgeArticle | null>(null);\n\n const { data, loading, refetch } = useQuery<{ knowledgeArticles: KnowledgeArticle[] }>(\n KNOWLEDGE_ARTICLES_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n\n const articles = useMemo(() => data?.knowledgeArticles ?? [], [data?.knowledgeArticles]);\n\n const categories = useMemo(() => {\n const counts = new Map<string, number>();\n for (const a of articles) {\n for (const tag of a.tags) counts.set(tag, (counts.get(tag) ?? 0) + 1);\n }\n return [...counts.entries()].sort((a, b) => b[1] - a[1]);\n }, [articles]);\n\n const filtered = useMemo(() => {\n const term = search.trim().toLowerCase();\n const list = articles.filter((article) => {\n if (category !== 'ALL' && !article.tags.includes(category)) return false;\n if (statusFilter !== 'ALL' && article.status !== statusFilter) return false;\n if (!term) return true;\n const haystack = [\n article.title,\n article.summary ?? '',\n article.content,\n article.tags.join(' '),\n ]\n .join(' ')\n .toLowerCase();\n return haystack.includes(term);\n });\n return [...list].sort((a, b) =>\n sort === 'views'\n ? b.views - a.views\n : new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()\n );\n }, [articles, search, category, statusFilter, sort]);\n\n const statusMix = useMemo<DonutSlice[]>(() => {\n const counts = articles.reduce<Record<string, number>>((acc, a) => {\n acc[a.status] = (acc[a.status] ?? 0) + 1;\n return acc;\n }, {});\n return Object.entries(counts).map(([status, value], i) => ({\n name: STATUS_META[status]?.label ?? status,\n value,\n color: seriesColor(i),\n }));\n }, [articles]);\n\n const topByViews = useMemo(\n () =>\n [...articles]\n .filter((a) => a.views > 0)\n .sort((a, b) => b.views - a.views)\n .slice(0, 6)\n .map((a) => ({ name: a.title, views: a.views })),\n [articles]\n );\n\n const pagination = usePagination(filtered, {\n pageSize: 9,\n resetKey: `${search}|${category}|${statusFilter}|${sort}`,\n });\n\n return (\n <div className=\"space-y-5 p-4 sm:p-6\">\n <SectionHeader\n hero\n icon={BookOpen}\n title=\"Knowledge Base\"\n description=\"Turn one-off fixes and runbooks into repeatable, searchable operational knowledge.\"\n actions={\n <Button className=\"w-full sm:w-auto\" onClick={() => setDialogOpen(true)}>\n <Plus className=\"mr-2 h-4 w-4\" />\n New Article\n </Button>\n }\n />\n <PagePurpose>\n Capture the fixes and runbooks your team relies on so the next person doesn&apos;t start\n from scratch. Link articles to incidents and assets, then search them when troubleshooting.\n </PagePurpose>\n\n <PublishArticleDialog\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onPublished={() => void refetch()}\n />\n <ArticleReader article={reading} onOpenChange={(open) => !open && setReading(null)} />\n\n <div className=\"relative\">\n <Search className=\"absolute left-3.5 top-1/2 h-4.5 w-4.5 -translate-y-1/2 text-text-secondary\" />\n <Input\n className=\"h-12 pl-11 text-base\"\n placeholder=\"Search runbooks, fixes and procedures…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n aria-label=\"Search knowledge articles\"\n />\n </div>\n\n {articles.length > 0 && (statusMix.length > 0 || topByViews.length > 0) ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Publishing status\" subtitle=\"Articles by status\">\n <DonutChart\n data={statusMix}\n height={200}\n centerLabel=\"Articles\"\n centerValue={articles.length}\n ariaLabel=\"Articles by status\"\n />\n </ChartCard>\n <ChartCard title=\"Most consulted\" subtitle=\"Top articles by views\">\n <BarsChart\n data={topByViews}\n xKey=\"name\"\n series={[{ key: 'views', label: 'Views' }]}\n orientation=\"horizontal\"\n height={200}\n categoryWidth={150}\n emptyLabel=\"No views recorded yet\"\n ariaLabel=\"Top articles by views\"\n />\n </ChartCard>\n </div>\n ) : null}\n\n <div className=\"grid gap-5 lg:grid-cols-[200px_1fr]\">\n {/* Category facet rail */}\n <aside className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-2\">\n <h3 className=\"text-sm font-semibold text-text-primary\">Category</h3>\n <Select value={sort} onValueChange={(v) => setSort(v as SortKey)}>\n <SelectTrigger className=\"h-8 w-[130px] text-xs lg:hidden\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"recent\">Recently updated</SelectItem>\n <SelectItem value=\"views\">Most viewed</SelectItem>\n </SelectContent>\n </Select>\n </div>\n {/* Mobile: horizontal chips; desktop: vertical list */}\n <div className=\"flex gap-2 overflow-x-auto pb-1 lg:flex-col lg:overflow-visible lg:pb-0\">\n <button\n type=\"button\"\n onClick={() => setCategory('ALL')}\n className={cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-left text-sm font-medium transition-colors lg:w-full',\n category === 'ALL'\n ? 'bg-action-primary-bg/10 text-primary'\n : 'text-text-secondary hover:text-text-primary'\n )}\n >\n All articles\n <span className=\"ml-1.5 text-xs text-text-muted tabular-nums\">{articles.length}</span>\n </button>\n {categories.map(([tag, count]) => (\n <button\n key={tag}\n type=\"button\"\n onClick={() => setCategory(tag)}\n className={cn(\n 'flex shrink-0 items-center justify-between gap-2 rounded-md px-3 py-1.5 text-left text-sm font-medium transition-colors lg:w-full',\n category === tag\n ? 'bg-action-primary-bg/10 text-primary'\n : 'text-text-secondary hover:text-text-primary'\n )}\n >\n <span className=\"truncate\">{tag}</span>\n <span className=\"text-xs text-text-muted tabular-nums\">{count}</span>\n </button>\n ))}\n </div>\n <div className=\"hidden space-y-1.5 border-t border-border-seam pt-3 lg:block\">\n <Label className=\"text-xs\">Status</Label>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger className=\"h-9\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ALL\">All statuses</SelectItem>\n {ARTICLE_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Label className=\"text-xs\">Sort</Label>\n <Select value={sort} onValueChange={(v) => setSort(v as SortKey)}>\n <SelectTrigger className=\"h-9\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"recent\">Recently updated</SelectItem>\n <SelectItem value=\"views\">Most viewed</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </aside>\n\n {/* Article grid */}\n <div>\n {loading && articles.length === 0 ? (\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div\n key={i}\n className=\"h-40 rounded-xl bg-bg-sunken motion-safe:animate-vc-shimmer\"\n />\n ))}\n </div>\n ) : null}\n {!loading && filtered.length === 0 ? (\n <IllustratedEmptyState\n illustration={\n search || category !== 'ALL' || statusFilter !== 'ALL'\n ? 'empty-search'\n : 'empty-data'\n }\n title={\n search || category !== 'ALL' || statusFilter !== 'ALL'\n ? 'No articles match your filters'\n : 'No knowledge articles found'\n }\n description={\n search || category !== 'ALL' || statusFilter !== 'ALL'\n ? 'Try a different term, category or status.'\n : 'Publish an article to start building your knowledge base.'\n }\n />\n ) : null}\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3\">\n {pagination.pageItems.map((article) => (\n <GlassCard key={article.id} treatment=\"glass\" className=\"border-border-seam\">\n <button\n type=\"button\"\n onClick={() => setReading(article)}\n className=\"flex h-full w-full flex-col gap-3 p-4 text-left\"\n >\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusPill status={article.status} />\n {article.tags.slice(0, 1).map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-2 py-0.5 text-xs font-medium text-primary\"\n >\n {tag}\n </span>\n ))}\n </div>\n <h2 className=\"line-clamp-2 text-base font-semibold text-text-primary\">\n {article.title}\n </h2>\n <p className=\"line-clamp-2 flex-1 text-sm text-text-secondary\">\n {excerptOf(article)}\n </p>\n <div className=\"flex items-center justify-between gap-2 border-t border-border-seam/60 pt-3\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-[10px] font-semibold text-text-secondary\">\n {article.updatedBy ? (\n initialsOf(article.updatedBy)\n ) : (\n <User className=\"h-3 w-3\" />\n )}\n </span>\n <span className=\"truncate text-xs text-text-secondary\">\n Updated {formatDate(article.updatedAt)}\n </span>\n </div>\n <span className=\"flex shrink-0 items-center gap-1 text-xs text-text-muted tabular-nums\">\n <Eye className=\"h-3.5 w-3.5\" />\n {article.views.toLocaleString()}\n </span>\n </div>\n </button>\n </GlassCard>\n ))}\n </div>\n <div className=\"mt-4\">\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=\"articles\"\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}