@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.
- package/dist/devportal/components/EmptyState.js +14 -8
- package/dist/devportal/components/EmptyState.js.map +1 -1
- package/dist/devportal/components/LoadingState.js.map +1 -1
- package/dist/devportal/components/PageLayout.js +39 -34
- package/dist/devportal/components/PageLayout.js.map +1 -1
- package/dist/devportal/components/StatCard.js +4 -3
- package/dist/devportal/components/StatCard.js.map +1 -1
- package/dist/devportal/components/StatusBadge.js +1 -1
- package/dist/devportal/components/StatusBadge.js.map +1 -1
- package/dist/devportal/pages/ApiKeysPage.js +1 -1
- package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
- package/dist/devportal/pages/AppLogsPage.js +85 -85
- package/dist/devportal/pages/AppLogsPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationVersionsPage.js +7 -7
- package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
- package/dist/devportal/pages/DashboardPage.js +157 -151
- package/dist/devportal/pages/DashboardPage.js.map +1 -1
- package/dist/devportal/pages/DelegationsPage.js +2 -2
- package/dist/devportal/pages/DelegationsPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js +225 -225
- package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationsPage.js +25 -25
- package/dist/devportal/pages/OrganizationsPage.js.map +1 -1
- package/dist/devportal/pages/WebhooksPage.js +1 -1
- package/dist/devportal/pages/WebhooksPage.js.map +1 -1
- 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,
|
|
11
|
-
import { useParams as
|
|
12
|
-
import { jsx as
|
|
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
|
|
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
|
-
},
|
|
22
|
-
let { t: o } = u(), { appId:
|
|
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:
|
|
25
|
-
limit:
|
|
26
|
-
offset: (
|
|
24
|
+
applicationId: C || "",
|
|
25
|
+
limit: y,
|
|
26
|
+
offset: (M - 1) * y
|
|
27
27
|
},
|
|
28
|
-
skip: !
|
|
28
|
+
skip: !C,
|
|
29
29
|
fetchPolicy: "cache-and-network"
|
|
30
|
-
}),
|
|
30
|
+
}), R = P?.application;
|
|
31
31
|
s(() => {
|
|
32
|
-
let e =
|
|
33
|
-
if (!
|
|
32
|
+
let e = R?.name;
|
|
33
|
+
if (!C || !e) return;
|
|
34
34
|
let t = window.__breadcrumbRegistry;
|
|
35
|
-
return t?.register(
|
|
36
|
-
}, [
|
|
37
|
-
let
|
|
38
|
-
let e =
|
|
39
|
-
return
|
|
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
|
-
|
|
42
|
+
D(t.actorId),
|
|
43
43
|
t.resource,
|
|
44
|
-
|
|
44
|
+
S(t.metadata)
|
|
45
45
|
].join(" ").toLowerCase().includes(e) : !0 : !1);
|
|
46
46
|
}, [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
O,
|
|
48
|
+
B,
|
|
49
|
+
A
|
|
50
50
|
]);
|
|
51
|
-
return
|
|
51
|
+
return F && !P ? /* @__PURE__ */ _(i, {
|
|
52
52
|
title: "Application Activity",
|
|
53
53
|
description: "Loading application audit history",
|
|
54
|
-
backLink:
|
|
54
|
+
backLink: C ? `/apps/${C}` : "/apps",
|
|
55
55
|
backLabel: "Back to Application",
|
|
56
|
-
children: /* @__PURE__ */
|
|
56
|
+
children: /* @__PURE__ */ _("div", {
|
|
57
57
|
className: "flex items-center justify-center py-16 text-text-secondary",
|
|
58
|
-
children: /* @__PURE__ */
|
|
58
|
+
children: /* @__PURE__ */ _(m, { className: "h-8 w-8 animate-spin" })
|
|
59
59
|
})
|
|
60
|
-
}) :
|
|
60
|
+
}) : I || !R ? /* @__PURE__ */ _(i, {
|
|
61
61
|
title: "Application Activity",
|
|
62
62
|
description: "Review audit events for this application",
|
|
63
|
-
backLink:
|
|
63
|
+
backLink: C ? `/apps/${C}` : "/apps",
|
|
64
64
|
backLabel: "Back to Application",
|
|
65
|
-
children: /* @__PURE__ */
|
|
66
|
-
icon: /* @__PURE__ */
|
|
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:
|
|
71
|
+
description: I ? r(I) : "Application not found"
|
|
72
72
|
})
|
|
73
|
-
}) : /* @__PURE__ */
|
|
73
|
+
}) : /* @__PURE__ */ v(i, {
|
|
74
74
|
title: "Application Activity",
|
|
75
|
-
description: `Audit events for ${
|
|
76
|
-
backLink: `/apps/${
|
|
75
|
+
description: `Audit events for ${R.name}`,
|
|
76
|
+
backLink: `/apps/${R.id}`,
|
|
77
77
|
backLabel: "Back to Application",
|
|
78
|
-
actions: /* @__PURE__ */
|
|
78
|
+
actions: /* @__PURE__ */ v("div", {
|
|
79
79
|
className: "flex flex-wrap gap-2",
|
|
80
|
-
children: [/* @__PURE__ */
|
|
80
|
+
children: [/* @__PURE__ */ v("button", {
|
|
81
81
|
type: "button",
|
|
82
|
-
onClick: () => void
|
|
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__ */
|
|
85
|
-
}), /* @__PURE__ */
|
|
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(
|
|
89
|
-
n.href = t, n.download = `${
|
|
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__ */
|
|
92
|
+
children: [/* @__PURE__ */ _(f, { size: 16 }), "Export JSON"]
|
|
93
93
|
})]
|
|
94
94
|
}),
|
|
95
95
|
children: [
|
|
96
|
-
/* @__PURE__ */
|
|
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__ */
|
|
99
|
+
/* @__PURE__ */ v("label", {
|
|
100
100
|
className: "grid gap-2 text-sm font-medium",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
101
|
+
children: [/* @__PURE__ */ v("span", {
|
|
102
102
|
className: "flex items-center gap-2 text-text-secondary",
|
|
103
|
-
children: [/* @__PURE__ */
|
|
104
|
-
}), /* @__PURE__ */
|
|
105
|
-
value:
|
|
106
|
-
onChange: (e) =>
|
|
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__ */
|
|
108
|
+
children: [/* @__PURE__ */ _("option", {
|
|
109
109
|
value: "all",
|
|
110
110
|
children: "All actions"
|
|
111
|
-
}),
|
|
111
|
+
}), V.map((e) => /* @__PURE__ */ _("option", {
|
|
112
112
|
value: e,
|
|
113
|
-
children:
|
|
113
|
+
children: x(e)
|
|
114
114
|
}, e))]
|
|
115
115
|
})]
|
|
116
116
|
}),
|
|
117
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ v("label", {
|
|
118
118
|
className: "grid gap-2 text-sm font-medium",
|
|
119
|
-
children: [/* @__PURE__ */
|
|
119
|
+
children: [/* @__PURE__ */ _("span", {
|
|
120
120
|
className: "text-text-secondary",
|
|
121
121
|
children: "Search metadata"
|
|
122
|
-
}), /* @__PURE__ */
|
|
122
|
+
}), /* @__PURE__ */ _("input", {
|
|
123
123
|
type: "text",
|
|
124
|
-
value:
|
|
125
|
-
onChange: (e) =>
|
|
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__ */
|
|
130
|
+
/* @__PURE__ */ v("div", {
|
|
131
131
|
className: "rounded-full bg-bg-sunken px-3 py-2 text-sm text-text-secondary",
|
|
132
|
-
children: [
|
|
132
|
+
children: [z, " total events"]
|
|
133
133
|
})
|
|
134
134
|
]
|
|
135
135
|
}),
|
|
136
|
-
/* @__PURE__ */
|
|
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:
|
|
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__ */
|
|
141
|
+
/* @__PURE__ */ v("div", {
|
|
142
142
|
className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between",
|
|
143
|
-
children: [/* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ v("div", {
|
|
144
144
|
className: "space-y-2",
|
|
145
|
-
children: [/* @__PURE__ */
|
|
145
|
+
children: [/* @__PURE__ */ v("div", {
|
|
146
146
|
className: "flex flex-wrap items-center gap-2",
|
|
147
|
-
children: [/* @__PURE__ */
|
|
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:
|
|
150
|
-
}), /* @__PURE__ */
|
|
149
|
+
children: x(e.action)
|
|
150
|
+
}), /* @__PURE__ */ v("span", {
|
|
151
151
|
className: "text-xs text-text-secondary",
|
|
152
|
-
children: ["Actor ",
|
|
152
|
+
children: ["Actor ", D(e.actorId)]
|
|
153
153
|
})]
|
|
154
|
-
}), /* @__PURE__ */
|
|
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__ */
|
|
162
|
+
}), /* @__PURE__ */ _("time", {
|
|
163
163
|
className: "text-xs text-text-secondary",
|
|
164
|
-
children:
|
|
164
|
+
children: b(e.createdAt)
|
|
165
165
|
})]
|
|
166
166
|
}),
|
|
167
|
-
e.metadata && /* @__PURE__ */
|
|
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:
|
|
169
|
+
children: S(e.metadata)
|
|
170
170
|
}),
|
|
171
|
-
e.changes && /* @__PURE__ */
|
|
171
|
+
e.changes && /* @__PURE__ */ v("details", {
|
|
172
172
|
className: "mt-3 rounded-md border bg-bg-surface p-3",
|
|
173
|
-
children: [/* @__PURE__ */
|
|
173
|
+
children: [/* @__PURE__ */ _("summary", {
|
|
174
174
|
className: "cursor-pointer text-sm font-medium text-text-primary",
|
|
175
175
|
children: "View captured changes"
|
|
176
|
-
}), /* @__PURE__ */
|
|
176
|
+
}), /* @__PURE__ */ _("pre", {
|
|
177
177
|
className: "mt-3 overflow-x-auto text-xs text-text-secondary",
|
|
178
|
-
children:
|
|
178
|
+
children: S(e.changes)
|
|
179
179
|
})]
|
|
180
180
|
})
|
|
181
181
|
]
|
|
182
182
|
}, e.id))
|
|
183
|
-
}) : /* @__PURE__ */
|
|
184
|
-
|
|
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
|
-
|
|
188
|
+
P.auditLogs?.pageInfo?.hasNextPage && /* @__PURE__ */ _("div", {
|
|
189
189
|
className: "flex justify-center",
|
|
190
|
-
children: /* @__PURE__ */
|
|
190
|
+
children: /* @__PURE__ */ v("button", {
|
|
191
191
|
type: "button",
|
|
192
|
-
onClick: () =>
|
|
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__ */
|
|
194
|
+
children: [/* @__PURE__ */ _(h, { size: 16 }), "Next page"]
|
|
195
195
|
})
|
|
196
196
|
})
|
|
197
197
|
]
|
|
198
198
|
});
|
|
199
199
|
};
|
|
200
200
|
//#endregion
|
|
201
|
-
export {
|
|
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
|
|
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__ */ _(
|
|
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__ */ _(
|
|
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
|
-
|
|
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__ */ _(
|
|
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__ */ _(
|
|
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__ */ _(
|
|
412
|
+
/* @__PURE__ */ _(h, { size: 14 }),
|
|
413
413
|
" ",
|
|
414
414
|
j.packageUrl ? "Replace zip" : "Upload zip"
|
|
415
415
|
] })
|