@burdenoff/microfe-devportal 2026.625.2 → 2026.625.3

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 (28) hide show
  1. package/dist/devportal/components/EmptyState.js +14 -8
  2. package/dist/devportal/components/EmptyState.js.map +1 -1
  3. package/dist/devportal/components/LoadingState.js.map +1 -1
  4. package/dist/devportal/components/PageLayout.js +39 -34
  5. package/dist/devportal/components/PageLayout.js.map +1 -1
  6. package/dist/devportal/components/StatCard.js +4 -3
  7. package/dist/devportal/components/StatCard.js.map +1 -1
  8. package/dist/devportal/components/StatusBadge.js +1 -1
  9. package/dist/devportal/components/StatusBadge.js.map +1 -1
  10. package/dist/devportal/pages/ApiKeysPage.js +1 -1
  11. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  12. package/dist/devportal/pages/AppLogsPage.js +85 -85
  13. package/dist/devportal/pages/AppLogsPage.js.map +1 -1
  14. package/dist/devportal/pages/ApplicationVersionsPage.js +7 -7
  15. package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
  16. package/dist/devportal/pages/DashboardPage.js +157 -151
  17. package/dist/devportal/pages/DashboardPage.js.map +1 -1
  18. package/dist/devportal/pages/DelegationsPage.js +2 -2
  19. package/dist/devportal/pages/DelegationsPage.js.map +1 -1
  20. package/dist/devportal/pages/OAuthClientsPage.js +1 -1
  21. package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
  22. package/dist/devportal/pages/OrganizationMembersPage.js +225 -225
  23. package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
  24. package/dist/devportal/pages/OrganizationsPage.js +25 -25
  25. package/dist/devportal/pages/OrganizationsPage.js.map +1 -1
  26. package/dist/devportal/pages/WebhooksPage.js +1 -1
  27. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  28. package/package.json +2 -2
@@ -7,151 +7,151 @@ import "../hooks/index.js";
7
7
  import o from "../../node_modules/date-fns/format.js";
8
8
  import { useEffect as s, useMemo as c, useState as l } from "react";
9
9
  import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
- import { AlertCircle as d, Download as f, FileClock as p, Filter as m, Loader2 as h, RefreshCw as g } from "lucide-react";
11
- import { useParams as _ } from "react-router-dom";
12
- import { jsx as v, jsxs as y } from "react/jsx-runtime";
10
+ import { AlertCircle as d, Download as f, Filter as p, Loader2 as m, RefreshCw as h } from "lucide-react";
11
+ import { useParams as g } from "react-router-dom";
12
+ import { jsx as _, jsxs as v } from "react/jsx-runtime";
13
13
  //#region src/devportal/pages/AppLogsPage.tsx
14
- var b = 25, x = (e) => o(new Date(e), "MMM d, yyyy HH:mm:ss"), S = (e) => e.replace(/_/g, " ").toLowerCase().replace(/\b\w/g, (e) => e.toUpperCase()), C = (e) => {
14
+ var y = 25, b = (e) => o(new Date(e), "MMM d, yyyy HH:mm:ss"), x = (e) => e.replace(/_/g, " ").toLowerCase().replace(/\b\w/g, (e) => e.toUpperCase()), S = (e) => {
15
15
  if (!e) return "";
16
16
  try {
17
17
  return JSON.stringify(e, null, 2);
18
18
  } catch {
19
19
  return "";
20
20
  }
21
- }, w = () => {
22
- let { t: o } = u(), { appId: w } = _(), { navigate: T, basePath: E, currentUser: D } = e(), O = (e) => D?.id === e && D.email ? D.email : e, [k, A] = l("all"), [j, M] = l(""), [N, P] = l(1), { data: F, loading: I, error: L, refetch: R } = n({
21
+ }, C = () => {
22
+ let { t: o } = u(), { appId: C } = g(), { navigate: w, basePath: T, currentUser: E } = e(), D = (e) => E?.id === e && E.email ? E.email : e, [O, k] = l("all"), [A, j] = l(""), [M, N] = l(1), { data: P, loading: F, error: I, refetch: L } = n({
23
23
  variables: {
24
- applicationId: w || "",
25
- limit: b,
26
- offset: (N - 1) * b
24
+ applicationId: C || "",
25
+ limit: y,
26
+ offset: (M - 1) * y
27
27
  },
28
- skip: !w,
28
+ skip: !C,
29
29
  fetchPolicy: "cache-and-network"
30
- }), z = F?.application;
30
+ }), R = P?.application;
31
31
  s(() => {
32
- let e = z?.name;
33
- if (!w || !e) return;
32
+ let e = R?.name;
33
+ if (!C || !e) return;
34
34
  let t = window.__breadcrumbRegistry;
35
- return t?.register(w, e), () => t?.unregister(w);
36
- }, [w, z?.name]);
37
- let B = F?.auditLogs?.totalCount ?? 0, V = F?.auditLogs?.edges?.map((e) => e.node) ?? [], H = c(() => Array.from(new Set(V.map((e) => e.action))).sort((e, t) => e.localeCompare(t)), [V]), U = c(() => {
38
- let e = j.trim().toLowerCase();
39
- return V.filter((t) => k === "all" || t.action === k ? e ? [
35
+ return t?.register(C, e), () => t?.unregister(C);
36
+ }, [C, R?.name]);
37
+ let z = P?.auditLogs?.totalCount ?? 0, B = P?.auditLogs?.edges?.map((e) => e.node) ?? [], V = c(() => Array.from(new Set(B.map((e) => e.action))).sort((e, t) => e.localeCompare(t)), [B]), H = c(() => {
38
+ let e = A.trim().toLowerCase();
39
+ return B.filter((t) => O === "all" || t.action === O ? e ? [
40
40
  t.action,
41
41
  t.actorId,
42
- O(t.actorId),
42
+ D(t.actorId),
43
43
  t.resource,
44
- C(t.metadata)
44
+ S(t.metadata)
45
45
  ].join(" ").toLowerCase().includes(e) : !0 : !1);
46
46
  }, [
47
- k,
48
- V,
49
- j
47
+ O,
48
+ B,
49
+ A
50
50
  ]);
51
- return I && !F ? /* @__PURE__ */ v(i, {
51
+ return F && !P ? /* @__PURE__ */ _(i, {
52
52
  title: "Application Activity",
53
53
  description: "Loading application audit history",
54
- backLink: w ? `/apps/${w}` : "/apps",
54
+ backLink: C ? `/apps/${C}` : "/apps",
55
55
  backLabel: "Back to Application",
56
- children: /* @__PURE__ */ v("div", {
56
+ children: /* @__PURE__ */ _("div", {
57
57
  className: "flex items-center justify-center py-16 text-text-secondary",
58
- children: /* @__PURE__ */ v(h, { className: "h-8 w-8 animate-spin" })
58
+ children: /* @__PURE__ */ _(m, { className: "h-8 w-8 animate-spin" })
59
59
  })
60
- }) : L || !z ? /* @__PURE__ */ v(i, {
60
+ }) : I || !R ? /* @__PURE__ */ _(i, {
61
61
  title: "Application Activity",
62
62
  description: "Review audit events for this application",
63
- backLink: w ? `/apps/${w}` : "/apps",
63
+ backLink: C ? `/apps/${C}` : "/apps",
64
64
  backLabel: "Back to Application",
65
- children: /* @__PURE__ */ v(t, {
66
- icon: /* @__PURE__ */ v(d, {
65
+ children: /* @__PURE__ */ _(t, {
66
+ icon: /* @__PURE__ */ _(d, {
67
67
  size: 32,
68
68
  className: "text-status-error-text"
69
69
  }),
70
70
  title: "Unable to load activity",
71
- description: L ? r(L) : "Application not found"
71
+ description: I ? r(I) : "Application not found"
72
72
  })
73
- }) : /* @__PURE__ */ y(i, {
73
+ }) : /* @__PURE__ */ v(i, {
74
74
  title: "Application Activity",
75
- description: `Audit events for ${z.name}`,
76
- backLink: `/apps/${z.id}`,
75
+ description: `Audit events for ${R.name}`,
76
+ backLink: `/apps/${R.id}`,
77
77
  backLabel: "Back to Application",
78
- actions: /* @__PURE__ */ y("div", {
78
+ actions: /* @__PURE__ */ v("div", {
79
79
  className: "flex flex-wrap gap-2",
80
- children: [/* @__PURE__ */ y("button", {
80
+ children: [/* @__PURE__ */ v("button", {
81
81
  type: "button",
82
- onClick: () => void R(),
82
+ onClick: () => void L(),
83
83
  className: "inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent",
84
- children: [/* @__PURE__ */ v(g, { size: 16 }), "Refresh"]
85
- }), /* @__PURE__ */ y("button", {
84
+ children: [/* @__PURE__ */ _(h, { size: 16 }), "Refresh"]
85
+ }), /* @__PURE__ */ v("button", {
86
86
  type: "button",
87
87
  onClick: () => {
88
- let e = new Blob([JSON.stringify(U, null, 2)], { type: "application/json" }), t = URL.createObjectURL(e), n = document.createElement("a");
89
- n.href = t, n.download = `${z?.slug || w || "application"}-audit-log.json`, n.click(), URL.revokeObjectURL(t);
88
+ let e = new Blob([JSON.stringify(H, null, 2)], { type: "application/json" }), t = URL.createObjectURL(e), n = document.createElement("a");
89
+ n.href = t, n.download = `${R?.slug || C || "application"}-audit-log.json`, n.click(), URL.revokeObjectURL(t);
90
90
  },
91
91
  className: "inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent",
92
- children: [/* @__PURE__ */ v(f, { size: 16 }), "Export JSON"]
92
+ children: [/* @__PURE__ */ _(f, { size: 16 }), "Export JSON"]
93
93
  })]
94
94
  }),
95
95
  children: [
96
- /* @__PURE__ */ y("div", {
96
+ /* @__PURE__ */ v("div", {
97
97
  className: "grid gap-4 rounded-card border border-border-seam bg-bg-surface p-4 lg:grid-cols-[220px_minmax(0,1fr)_auto] lg:items-center",
98
98
  children: [
99
- /* @__PURE__ */ y("label", {
99
+ /* @__PURE__ */ v("label", {
100
100
  className: "grid gap-2 text-sm font-medium",
101
- children: [/* @__PURE__ */ y("span", {
101
+ children: [/* @__PURE__ */ v("span", {
102
102
  className: "flex items-center gap-2 text-text-secondary",
103
- children: [/* @__PURE__ */ v(m, { size: 16 }), "Filter by action"]
104
- }), /* @__PURE__ */ y("select", {
105
- value: k,
106
- onChange: (e) => A(e.target.value),
103
+ children: [/* @__PURE__ */ _(p, { size: 16 }), "Filter by action"]
104
+ }), /* @__PURE__ */ v("select", {
105
+ value: O,
106
+ onChange: (e) => k(e.target.value),
107
107
  className: "rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary",
108
- children: [/* @__PURE__ */ v("option", {
108
+ children: [/* @__PURE__ */ _("option", {
109
109
  value: "all",
110
110
  children: "All actions"
111
- }), H.map((e) => /* @__PURE__ */ v("option", {
111
+ }), V.map((e) => /* @__PURE__ */ _("option", {
112
112
  value: e,
113
- children: S(e)
113
+ children: x(e)
114
114
  }, e))]
115
115
  })]
116
116
  }),
117
- /* @__PURE__ */ y("label", {
117
+ /* @__PURE__ */ v("label", {
118
118
  className: "grid gap-2 text-sm font-medium",
119
- children: [/* @__PURE__ */ v("span", {
119
+ children: [/* @__PURE__ */ _("span", {
120
120
  className: "text-text-secondary",
121
121
  children: "Search metadata"
122
- }), /* @__PURE__ */ v("input", {
122
+ }), /* @__PURE__ */ _("input", {
123
123
  type: "text",
124
- value: j,
125
- onChange: (e) => M(e.target.value),
124
+ value: A,
125
+ onChange: (e) => j(e.target.value),
126
126
  placeholder: "Search actor, action, or metadata",
127
127
  className: "rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
128
128
  })]
129
129
  }),
130
- /* @__PURE__ */ y("div", {
130
+ /* @__PURE__ */ v("div", {
131
131
  className: "rounded-full bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
132
- children: [B, " total events"]
132
+ children: [z, " total events"]
133
133
  })
134
134
  ]
135
135
  }),
136
- /* @__PURE__ */ v(a, { children: U.length > 0 ? /* @__PURE__ */ v("div", {
136
+ /* @__PURE__ */ _(a, { children: H.length > 0 ? /* @__PURE__ */ _("div", {
137
137
  className: "space-y-3 rounded-card border border-border-seam bg-bg-surface p-4",
138
- children: U.map((e) => /* @__PURE__ */ y("article", {
138
+ children: H.map((e) => /* @__PURE__ */ v("article", {
139
139
  className: "rounded-card border border-border-seam bg-bg-surface p-4",
140
140
  children: [
141
- /* @__PURE__ */ y("div", {
141
+ /* @__PURE__ */ v("div", {
142
142
  className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between",
143
- children: [/* @__PURE__ */ y("div", {
143
+ children: [/* @__PURE__ */ v("div", {
144
144
  className: "space-y-2",
145
- children: [/* @__PURE__ */ y("div", {
145
+ children: [/* @__PURE__ */ v("div", {
146
146
  className: "flex flex-wrap items-center gap-2",
147
- children: [/* @__PURE__ */ v("span", {
147
+ children: [/* @__PURE__ */ _("span", {
148
148
  className: "rounded-full bg-action-primary-bg/10 px-2.5 py-1 text-xs font-medium text-primary",
149
- children: S(e.action)
150
- }), /* @__PURE__ */ y("span", {
149
+ children: x(e.action)
150
+ }), /* @__PURE__ */ v("span", {
151
151
  className: "text-xs text-text-secondary",
152
- children: ["Actor ", O(e.actorId)]
152
+ children: ["Actor ", D(e.actorId)]
153
153
  })]
154
- }), /* @__PURE__ */ y("p", {
154
+ }), /* @__PURE__ */ v("p", {
155
155
  className: "text-sm text-text-secondary",
156
156
  children: [
157
157
  "Resource: ",
@@ -159,45 +159,45 @@ var b = 25, x = (e) => o(new Date(e), "MMM d, yyyy HH:mm:ss"), S = (e) => e.repl
159
159
  e.resourceId ? ` · ${e.resourceId}` : ""
160
160
  ]
161
161
  })]
162
- }), /* @__PURE__ */ v("time", {
162
+ }), /* @__PURE__ */ _("time", {
163
163
  className: "text-xs text-text-secondary",
164
- children: x(e.createdAt)
164
+ children: b(e.createdAt)
165
165
  })]
166
166
  }),
167
- e.metadata && /* @__PURE__ */ v("pre", {
167
+ e.metadata && /* @__PURE__ */ _("pre", {
168
168
  className: "mt-3 overflow-x-auto rounded-md bg-bg-sunken p-3 text-xs text-text-primary",
169
- children: C(e.metadata)
169
+ children: S(e.metadata)
170
170
  }),
171
- e.changes && /* @__PURE__ */ y("details", {
171
+ e.changes && /* @__PURE__ */ v("details", {
172
172
  className: "mt-3 rounded-md border bg-bg-surface p-3",
173
- children: [/* @__PURE__ */ v("summary", {
173
+ children: [/* @__PURE__ */ _("summary", {
174
174
  className: "cursor-pointer text-sm font-medium text-text-primary",
175
175
  children: "View captured changes"
176
- }), /* @__PURE__ */ v("pre", {
176
+ }), /* @__PURE__ */ _("pre", {
177
177
  className: "mt-3 overflow-x-auto text-xs text-text-secondary",
178
- children: C(e.changes)
178
+ children: S(e.changes)
179
179
  })]
180
180
  })
181
181
  ]
182
182
  }, e.id))
183
- }) : /* @__PURE__ */ v(t, {
184
- icon: /* @__PURE__ */ v(p, { size: 24 }),
183
+ }) : /* @__PURE__ */ _(t, {
184
+ illustration: "empty-data",
185
185
  title: "No audit events found",
186
186
  description: "Events will appear here after application or webhook actions are performed through the public gateway."
187
187
  }) }),
188
- F.auditLogs?.pageInfo?.hasNextPage && /* @__PURE__ */ v("div", {
188
+ P.auditLogs?.pageInfo?.hasNextPage && /* @__PURE__ */ _("div", {
189
189
  className: "flex justify-center",
190
- children: /* @__PURE__ */ y("button", {
190
+ children: /* @__PURE__ */ v("button", {
191
191
  type: "button",
192
- onClick: () => P((e) => e + 1),
192
+ onClick: () => N((e) => e + 1),
193
193
  className: "inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent",
194
- children: [/* @__PURE__ */ v(g, { size: 16 }), "Next page"]
194
+ children: [/* @__PURE__ */ _(h, { size: 16 }), "Next page"]
195
195
  })
196
196
  })
197
197
  ]
198
198
  });
199
199
  };
200
200
  //#endregion
201
- export { w as AppLogsPage };
201
+ export { C as AppLogsPage };
202
202
 
203
203
  //# sourceMappingURL=AppLogsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppLogsPage.js","names":[],"sources":["../../../src/devportal/pages/AppLogsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n Download,\n Filter,\n Loader2,\n RefreshCw,\n AlertCircle,\n FileClock,\n} from \"lucide-react\";\nimport { format } from \"date-fns\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n type GetApplicationAuditLogsQuery,\n getErrorMessage,\n useGetApplicationAuditLogsQuery,\n} from \"../hooks\";\n\nconst PAGE_SIZE = 25;\ntype AuditLogEntry =\n GetApplicationAuditLogsQuery[\"auditLogs\"][\"edges\"][number][\"node\"];\n\nconst formatTimestamp = (value: string) =>\n format(new Date(value), \"MMM d, yyyy HH:mm:ss\");\n\nconst formatAction = (value: string) =>\n value\n .replace(/_/g, \" \")\n .toLowerCase()\n .replace(/\\b\\w/g, (character) => character.toUpperCase());\n\nconst metadataPreview = (metadata: unknown): string => {\n if (!metadata) return \"\";\n\n try {\n return JSON.stringify(metadata, null, 2);\n } catch {\n return \"\";\n }\n};\n\nexport const AppLogsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath, currentUser } = useDevportal();\n const resolveActorLabel = (actorId: string): string => {\n if (currentUser?.id === actorId && currentUser.email)\n return currentUser.email;\n return actorId;\n };\n const [actionFilter, setActionFilter] = useState(\"all\");\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [page, setPage] = useState(1);\n\n const { data, loading, error, refetch } = useGetApplicationAuditLogsQuery({\n variables: {\n applicationId: appId || \"\",\n limit: PAGE_SIZE,\n offset: (page - 1) * PAGE_SIZE,\n },\n skip: !appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const application = data?.application;\n\n useEffect(() => {\n const name = application?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, application?.name]);\n\n const totalCount = data?.auditLogs?.totalCount ?? 0;\n const auditLogs: AuditLogEntry[] =\n data?.auditLogs?.edges?.map(\n (edge: GetApplicationAuditLogsQuery[\"auditLogs\"][\"edges\"][number]) =>\n edge.node,\n ) ?? [];\n\n const availableActions = useMemo(\n () =>\n Array.from(\n new Set(auditLogs.map((entry: AuditLogEntry) => entry.action)),\n ).sort((left, right) => left.localeCompare(right)),\n [auditLogs],\n );\n\n const filteredLogs = useMemo(() => {\n const normalizedQuery = searchQuery.trim().toLowerCase();\n\n return auditLogs.filter((entry: AuditLogEntry) => {\n const matchesAction =\n actionFilter === \"all\" || entry.action === actionFilter;\n if (!matchesAction) return false;\n\n if (!normalizedQuery) return true;\n\n const haystack = [\n entry.action,\n entry.actorId,\n resolveActorLabel(entry.actorId),\n entry.resource,\n metadataPreview(entry.metadata),\n ]\n .join(\" \")\n .toLowerCase();\n\n return haystack.includes(normalizedQuery);\n });\n }, [actionFilter, auditLogs, searchQuery]);\n\n const exportPayload = () => {\n const blob = new Blob([JSON.stringify(filteredLogs, null, 2)], {\n type: \"application/json\",\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `${application?.slug || appId || \"application\"}-audit-log.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n };\n\n if (loading && !data) {\n return (\n <PageLayout\n title=\"Application Activity\"\n description=\"Loading application audit history\"\n backLink={appId ? `/apps/${appId}` : \"/apps\"}\n backLabel=\"Back to Application\"\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !application) {\n return (\n <PageLayout\n title=\"Application Activity\"\n description=\"Review audit events for this application\"\n backLink={appId ? `/apps/${appId}` : \"/apps\"}\n backLabel=\"Back to Application\"\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title=\"Unable to load activity\"\n description={error ? getErrorMessage(error) : \"Application not found\"}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Application Activity\"\n description={`Audit events for ${application.name}`}\n backLink={`/apps/${application.id}`}\n backLabel=\"Back to Application\"\n actions={\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => void refetch()}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent\"\n >\n <RefreshCw size={16} />\n Refresh\n </button>\n <button\n type=\"button\"\n onClick={exportPayload}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent\"\n >\n <Download size={16} />\n Export JSON\n </button>\n </div>\n }\n >\n <div className=\"grid gap-4 rounded-card border border-border-seam bg-bg-surface p-4 lg:grid-cols-[220px_minmax(0,1fr)_auto] lg:items-center\">\n <label className=\"grid gap-2 text-sm font-medium\">\n <span className=\"flex items-center gap-2 text-text-secondary\">\n <Filter size={16} />\n Filter by action\n </span>\n <select\n value={actionFilter}\n onChange={(event) => setActionFilter(event.target.value)}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"all\">All actions</option>\n {availableActions.map((action) => (\n <option key={action} value={action}>\n {formatAction(action)}\n </option>\n ))}\n </select>\n </label>\n\n <label className=\"grid gap-2 text-sm font-medium\">\n <span className=\"text-text-secondary\">Search metadata</span>\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(event) => setSearchQuery(event.target.value)}\n placeholder=\"Search actor, action, or metadata\"\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </label>\n\n <div className=\"rounded-full bg-bg-sunken px-3 py-2 text-sm text-text-secondary\">\n {totalCount} total events\n </div>\n </div>\n\n <PageSection>\n {filteredLogs.length > 0 ? (\n <div className=\"space-y-3 rounded-card border border-border-seam bg-bg-surface p-4\">\n {filteredLogs.map((entry: AuditLogEntry) => (\n <article\n key={entry.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4\"\n >\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-action-primary-bg/10 px-2.5 py-1 text-xs font-medium text-primary\">\n {formatAction(entry.action)}\n </span>\n <span className=\"text-xs text-text-secondary\">\n Actor {resolveActorLabel(entry.actorId)}\n </span>\n </div>\n <p className=\"text-sm text-text-secondary\">\n Resource: {entry.resource}\n {entry.resourceId ? ` · ${entry.resourceId}` : \"\"}\n </p>\n </div>\n\n <time className=\"text-xs text-text-secondary\">\n {formatTimestamp(entry.createdAt)}\n </time>\n </div>\n\n {entry.metadata && (\n <pre className=\"mt-3 overflow-x-auto rounded-md bg-bg-sunken p-3 text-xs text-text-primary\">\n {metadataPreview(entry.metadata)}\n </pre>\n )}\n\n {entry.changes && (\n <details className=\"mt-3 rounded-md border bg-bg-surface p-3\">\n <summary className=\"cursor-pointer text-sm font-medium text-text-primary\">\n View captured changes\n </summary>\n <pre className=\"mt-3 overflow-x-auto text-xs text-text-secondary\">\n {metadataPreview(entry.changes)}\n </pre>\n </details>\n )}\n </article>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<FileClock size={24} />}\n title=\"No audit events found\"\n description=\"Events will appear here after application or webhook actions are performed through the public gateway.\"\n />\n )}\n </PageSection>\n\n {data.auditLogs?.pageInfo?.hasNextPage && (\n <div className=\"flex justify-center\">\n <button\n type=\"button\"\n onClick={() => setPage((previous) => previous + 1)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent\"\n >\n <RefreshCw size={16} />\n Next page\n </button>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AppLogsPage.js","names":[],"sources":["../../../src/devportal/pages/AppLogsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n Download,\n Filter,\n Loader2,\n RefreshCw,\n AlertCircle,\n FileClock,\n} from \"lucide-react\";\nimport { format } from \"date-fns\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n type GetApplicationAuditLogsQuery,\n getErrorMessage,\n useGetApplicationAuditLogsQuery,\n} from \"../hooks\";\n\nconst PAGE_SIZE = 25;\ntype AuditLogEntry =\n GetApplicationAuditLogsQuery[\"auditLogs\"][\"edges\"][number][\"node\"];\n\nconst formatTimestamp = (value: string) =>\n format(new Date(value), \"MMM d, yyyy HH:mm:ss\");\n\nconst formatAction = (value: string) =>\n value\n .replace(/_/g, \" \")\n .toLowerCase()\n .replace(/\\b\\w/g, (character) => character.toUpperCase());\n\nconst metadataPreview = (metadata: unknown): string => {\n if (!metadata) return \"\";\n\n try {\n return JSON.stringify(metadata, null, 2);\n } catch {\n return \"\";\n }\n};\n\nexport const AppLogsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath, currentUser } = useDevportal();\n const resolveActorLabel = (actorId: string): string => {\n if (currentUser?.id === actorId && currentUser.email)\n return currentUser.email;\n return actorId;\n };\n const [actionFilter, setActionFilter] = useState(\"all\");\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [page, setPage] = useState(1);\n\n const { data, loading, error, refetch } = useGetApplicationAuditLogsQuery({\n variables: {\n applicationId: appId || \"\",\n limit: PAGE_SIZE,\n offset: (page - 1) * PAGE_SIZE,\n },\n skip: !appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const application = data?.application;\n\n useEffect(() => {\n const name = application?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, application?.name]);\n\n const totalCount = data?.auditLogs?.totalCount ?? 0;\n const auditLogs: AuditLogEntry[] =\n data?.auditLogs?.edges?.map(\n (edge: GetApplicationAuditLogsQuery[\"auditLogs\"][\"edges\"][number]) =>\n edge.node,\n ) ?? [];\n\n const availableActions = useMemo(\n () =>\n Array.from(\n new Set(auditLogs.map((entry: AuditLogEntry) => entry.action)),\n ).sort((left, right) => left.localeCompare(right)),\n [auditLogs],\n );\n\n const filteredLogs = useMemo(() => {\n const normalizedQuery = searchQuery.trim().toLowerCase();\n\n return auditLogs.filter((entry: AuditLogEntry) => {\n const matchesAction =\n actionFilter === \"all\" || entry.action === actionFilter;\n if (!matchesAction) return false;\n\n if (!normalizedQuery) return true;\n\n const haystack = [\n entry.action,\n entry.actorId,\n resolveActorLabel(entry.actorId),\n entry.resource,\n metadataPreview(entry.metadata),\n ]\n .join(\" \")\n .toLowerCase();\n\n return haystack.includes(normalizedQuery);\n });\n }, [actionFilter, auditLogs, searchQuery]);\n\n const exportPayload = () => {\n const blob = new Blob([JSON.stringify(filteredLogs, null, 2)], {\n type: \"application/json\",\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `${application?.slug || appId || \"application\"}-audit-log.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n };\n\n if (loading && !data) {\n return (\n <PageLayout\n title=\"Application Activity\"\n description=\"Loading application audit history\"\n backLink={appId ? `/apps/${appId}` : \"/apps\"}\n backLabel=\"Back to Application\"\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !application) {\n return (\n <PageLayout\n title=\"Application Activity\"\n description=\"Review audit events for this application\"\n backLink={appId ? `/apps/${appId}` : \"/apps\"}\n backLabel=\"Back to Application\"\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title=\"Unable to load activity\"\n description={error ? getErrorMessage(error) : \"Application not found\"}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Application Activity\"\n description={`Audit events for ${application.name}`}\n backLink={`/apps/${application.id}`}\n backLabel=\"Back to Application\"\n actions={\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => void refetch()}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent\"\n >\n <RefreshCw size={16} />\n Refresh\n </button>\n <button\n type=\"button\"\n onClick={exportPayload}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent\"\n >\n <Download size={16} />\n Export JSON\n </button>\n </div>\n }\n >\n <div className=\"grid gap-4 rounded-card border border-border-seam bg-bg-surface p-4 lg:grid-cols-[220px_minmax(0,1fr)_auto] lg:items-center\">\n <label className=\"grid gap-2 text-sm font-medium\">\n <span className=\"flex items-center gap-2 text-text-secondary\">\n <Filter size={16} />\n Filter by action\n </span>\n <select\n value={actionFilter}\n onChange={(event) => setActionFilter(event.target.value)}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"all\">All actions</option>\n {availableActions.map((action) => (\n <option key={action} value={action}>\n {formatAction(action)}\n </option>\n ))}\n </select>\n </label>\n\n <label className=\"grid gap-2 text-sm font-medium\">\n <span className=\"text-text-secondary\">Search metadata</span>\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(event) => setSearchQuery(event.target.value)}\n placeholder=\"Search actor, action, or metadata\"\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </label>\n\n <div className=\"rounded-full bg-bg-sunken px-3 py-2 text-sm text-text-secondary\">\n {totalCount} total events\n </div>\n </div>\n\n <PageSection>\n {filteredLogs.length > 0 ? (\n <div className=\"space-y-3 rounded-card border border-border-seam bg-bg-surface p-4\">\n {filteredLogs.map((entry: AuditLogEntry) => (\n <article\n key={entry.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4\"\n >\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-action-primary-bg/10 px-2.5 py-1 text-xs font-medium text-primary\">\n {formatAction(entry.action)}\n </span>\n <span className=\"text-xs text-text-secondary\">\n Actor {resolveActorLabel(entry.actorId)}\n </span>\n </div>\n <p className=\"text-sm text-text-secondary\">\n Resource: {entry.resource}\n {entry.resourceId ? ` · ${entry.resourceId}` : \"\"}\n </p>\n </div>\n\n <time className=\"text-xs text-text-secondary\">\n {formatTimestamp(entry.createdAt)}\n </time>\n </div>\n\n {entry.metadata && (\n <pre className=\"mt-3 overflow-x-auto rounded-md bg-bg-sunken p-3 text-xs text-text-primary\">\n {metadataPreview(entry.metadata)}\n </pre>\n )}\n\n {entry.changes && (\n <details className=\"mt-3 rounded-md border bg-bg-surface p-3\">\n <summary className=\"cursor-pointer text-sm font-medium text-text-primary\">\n View captured changes\n </summary>\n <pre className=\"mt-3 overflow-x-auto text-xs text-text-secondary\">\n {metadataPreview(entry.changes)}\n </pre>\n </details>\n )}\n </article>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No audit events found\"\n description=\"Events will appear here after application or webhook actions are performed through the public gateway.\"\n />\n )}\n </PageSection>\n\n {data.auditLogs?.pageInfo?.hasNextPage && (\n <div className=\"flex justify-center\">\n <button\n type=\"button\"\n onClick={() => setPage((previous) => previous + 1)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent\"\n >\n <RefreshCw size={16} />\n Next page\n </button>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -16,7 +16,7 @@ import ce from "../../node_modules/date-fns/format.js";
16
16
  import { usePackageUpload as le } from "../hooks/usePackageUpload.js";
17
17
  import { useCallback as ue, useEffect as de, useMemo as l, useRef as fe, useState as u } from "react";
18
18
  import { useI18n as pe } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
19
- import { AlertCircle as d, Archive as me, CheckCircle as f, Clock as he, FileJson as ge, Loader2 as p, Package as m, Plus as h, Upload as _e } from "lucide-react";
19
+ import { AlertCircle as d, Archive as me, CheckCircle as f, Clock as he, FileJson as ge, Loader2 as p, Package as _e, Plus as m, Upload as h } from "lucide-react";
20
20
  import { useParams as ve } from "react-router-dom";
21
21
  import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
22
22
  //#region src/devportal/pages/ApplicationVersionsPage.tsx
@@ -116,7 +116,7 @@ var y = () => {
116
116
  }) : t === "DEPRECATED" ? /* @__PURE__ */ _(me, {
117
117
  size: 16,
118
118
  className: "text-text-secondary"
119
- }) : /* @__PURE__ */ _(m, {
119
+ }) : /* @__PURE__ */ _(_e, {
120
120
  size: 16,
121
121
  className: "text-accent-blue"
122
122
  });
@@ -167,7 +167,7 @@ var y = () => {
167
167
  disabled: !x,
168
168
  "aria-disabled": !x,
169
169
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
170
- children: [/* @__PURE__ */ _(h, { size: 16 }), b("devportal.newVersion", "New Version")]
170
+ children: [/* @__PURE__ */ _(m, { size: 16 }), b("devportal.newVersion", "New Version")]
171
171
  }),
172
172
  children: [
173
173
  F && /* @__PURE__ */ v("div", {
@@ -332,13 +332,13 @@ var y = () => {
332
332
  }
333
333
  ]
334
334
  }) : /* @__PURE__ */ _(t, {
335
- icon: /* @__PURE__ */ _(m, { size: 32 }),
335
+ illustration: "empty-data",
336
336
  title: b("devportal.noVersionsYet", "No versions yet"),
337
337
  description: b("devportal.noVersionsYetDescription", "Create your first version to start distributing your app"),
338
338
  action: /* @__PURE__ */ v("button", {
339
339
  onClick: () => A(!0),
340
340
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
341
- children: [/* @__PURE__ */ _(h, { size: 16 }), b("devportal.createVersion", "Create Version")]
341
+ children: [/* @__PURE__ */ _(m, { size: 16 }), b("devportal.createVersion", "Create Version")]
342
342
  })
343
343
  }),
344
344
  k && /* @__PURE__ */ _(o, {
@@ -374,7 +374,7 @@ var y = () => {
374
374
  type: "button",
375
375
  onClick: () => P("file"),
376
376
  className: `inline-flex items-center gap-1.5 rounded px-3 py-1 text-xs font-medium transition-colors ${N === "file" ? "bg-action-primary-bg text-action-primary-text" : "hover:bg-bg-sunken"}`,
377
- children: [/* @__PURE__ */ _(_e, { size: 12 }), " Upload zip"]
377
+ children: [/* @__PURE__ */ _(h, { size: 12 }), " Upload zip"]
378
378
  }), /* @__PURE__ */ v("button", {
379
379
  type: "button",
380
380
  onClick: () => P("manifest"),
@@ -409,7 +409,7 @@ var y = () => {
409
409
  Ce,
410
410
  "%"
411
411
  ] }) : /* @__PURE__ */ v(g, { children: [
412
- /* @__PURE__ */ _(_e, { size: 14 }),
412
+ /* @__PURE__ */ _(h, { size: 14 }),
413
413
  " ",
414
414
  j.packageUrl ? "Replace zip" : "Upload zip"
415
415
  ] })