@burdenoff/microfe-devportal 2026.703.4 → 2026.703.6

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.
@@ -1,79 +1,79 @@
1
1
  import { useDevportal as e } from "../providers/DevportalProvider.js";
2
2
  import { EmptyState as t } from "../components/EmptyState.js";
3
- import { useApproveApplicationMutation as n, useGetApplicationForReviewQuery as r, useGetApplicationsQuery as i, useRejectApplicationMutation as a } from "../../generated/global-operations.js";
4
- import { getErrorMessage as o } from "../hooks/useGraphQL.js";
5
- import { PageLayout as s, PageSection as c } from "../components/PageLayout.js";
6
- import { PermissionGuard as l } from "../components/PermissionGuard.js";
3
+ import { useApproveApplicationMutation as n, useApproveApplicationVersionMutation as r, useGetApplicationForReviewQuery as i, useGetApplicationsQuery as a, useGetApplicationsWithPendingVersionsQuery as o, useRejectApplicationMutation as s, useRejectApplicationVersionMutation as c } from "../../generated/global-operations.js";
4
+ import { getErrorMessage as l } from "../hooks/useGraphQL.js";
5
+ import { PageLayout as u, PageSection as d } from "../components/PageLayout.js";
6
+ import { PermissionGuard as f } from "../components/PermissionGuard.js";
7
7
  import "../components/index.js";
8
- import { DEVPORTAL_PERMISSIONS as u } from "../constants/permissions.js";
9
- import { useDevportalPermission as d } from "../hooks/usePermission.js";
8
+ import { DEVPORTAL_PERMISSIONS as p } from "../constants/permissions.js";
9
+ import { useDevportalPermission as m } from "../hooks/usePermission.js";
10
10
  import "../hooks/index.js";
11
- import { useState as f } from "react";
12
- import { useI18n as p } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
- import { AlertCircle as m, CheckCircle as h, ChevronDown as g, ChevronUp as _, Clock as v, Download as y, Eye as b, FileJson as x, Loader2 as S, Search as C, XCircle as w } from "lucide-react";
14
- import { jsx as T, jsxs as E } from "react/jsx-runtime";
11
+ import { useState as h } from "react";
12
+ import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
+ import { AlertCircle as _, CheckCircle as v, ChevronDown as y, ChevronUp as b, Clock as x, Download as S, Eye as C, FileJson as w, GitBranch as T, Loader2 as E, Search as D, XCircle as O } from "lucide-react";
14
+ import { jsx as k, jsxs as A } from "react/jsx-runtime";
15
15
  //#region src/devportal/pages/AdminReviewPage.tsx
16
- var D = ({ manifest: e, tr: t }) => {
17
- let [n, r] = f(!1);
18
- return /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ E("button", {
16
+ var j = ({ manifest: e, tr: t }) => {
17
+ let [n, r] = h(!1);
18
+ return /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ A("button", {
19
19
  type: "button",
20
20
  onClick: () => r((e) => !e),
21
21
  className: "inline-flex items-center gap-1.5 text-xs text-text-secondary hover:text-text-primary",
22
- children: [/* @__PURE__ */ T(x, { size: 13 }), n ? t("devportal.hideManifest", "Hide manifest") : t("devportal.viewManifest", "View manifest.json")]
23
- }), n && /* @__PURE__ */ T("pre", {
22
+ children: [/* @__PURE__ */ k(w, { size: 13 }), n ? t("devportal.hideManifest", "Hide manifest") : t("devportal.viewManifest", "View manifest.json")]
23
+ }), n && /* @__PURE__ */ k("pre", {
24
24
  className: "mt-2 max-h-48 overflow-auto rounded-md bg-bg-sunken p-3 text-xs font-mono whitespace-pre-wrap break-all",
25
25
  children: JSON.stringify(e, null, 2)
26
26
  })] });
27
- }, O = ({ app: t, onApprove: n, onReject: i, processing: a }) => {
28
- let { navigate: o, basePath: s } = e(), { t: c } = p(), l = (e, t) => {
27
+ }, M = ({ app: t, onApprove: n, onReject: r, processing: a }) => {
28
+ let { navigate: o, basePath: s } = e(), { t: c } = g(), l = (e, t) => {
29
29
  let n = c(e);
30
30
  return n === e ? t : n;
31
- }, [m, v] = f(!1), [x, C] = f(""), O = d(u.APP_APPROVE), k = d(u.APP_REJECT), { data: A } = r({
31
+ }, [u, d] = h(!1), [f, _] = h(""), x = m(p.APP_APPROVE), w = m(p.APP_REJECT), { data: T } = i({
32
32
  variables: { id: t.id },
33
- skip: !m,
33
+ skip: !u,
34
34
  fetchPolicy: "cache-first"
35
- }), j = A?.application?.versions?.edges?.[0]?.node;
36
- return /* @__PURE__ */ E("div", {
35
+ }), D = T?.application?.versions?.edges?.[0]?.node;
36
+ return /* @__PURE__ */ A("div", {
37
37
  className: "rounded-card border border-border-seam bg-bg-surface overflow-hidden",
38
- children: [/* @__PURE__ */ E("div", {
38
+ children: [/* @__PURE__ */ A("div", {
39
39
  className: "flex items-center gap-4 p-4",
40
40
  children: [
41
- t.iconUrl ? /* @__PURE__ */ T("img", {
41
+ t.iconUrl ? /* @__PURE__ */ k("img", {
42
42
  src: t.iconUrl,
43
43
  alt: t.name,
44
44
  className: "h-12 w-12 rounded-lg object-cover flex-shrink-0"
45
- }) : /* @__PURE__ */ T("div", {
45
+ }) : /* @__PURE__ */ k("div", {
46
46
  className: "h-12 w-12 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0",
47
- children: /* @__PURE__ */ T("span", {
47
+ children: /* @__PURE__ */ k("span", {
48
48
  className: "text-lg font-bold text-text-secondary",
49
49
  children: t.name.charAt(0).toUpperCase()
50
50
  })
51
51
  }),
52
- /* @__PURE__ */ E("div", {
52
+ /* @__PURE__ */ A("div", {
53
53
  className: "flex-1 min-w-0",
54
54
  children: [
55
- /* @__PURE__ */ E("div", {
55
+ /* @__PURE__ */ A("div", {
56
56
  className: "flex items-center gap-2",
57
57
  children: [
58
- /* @__PURE__ */ T("h3", {
58
+ /* @__PURE__ */ k("h3", {
59
59
  className: "font-semibold truncate",
60
60
  children: t.name
61
61
  }),
62
- /* @__PURE__ */ T("span", {
62
+ /* @__PURE__ */ k("span", {
63
63
  className: "inline-flex items-center rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs font-medium text-status-warning-text",
64
64
  children: t.status
65
65
  }),
66
- /* @__PURE__ */ T("span", {
66
+ /* @__PURE__ */ k("span", {
67
67
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
68
68
  children: t.appType.replace(/_/g, " ")
69
69
  })
70
70
  ]
71
71
  }),
72
- /* @__PURE__ */ T("p", {
72
+ /* @__PURE__ */ k("p", {
73
73
  className: "text-sm text-text-secondary truncate",
74
74
  children: t.shortDescription ?? t.description ?? l("devportal.noDescription", "No description")
75
75
  }),
76
- /* @__PURE__ */ E("p", {
76
+ /* @__PURE__ */ A("p", {
77
77
  className: "text-xs text-text-secondary mt-0.5",
78
78
  children: [
79
79
  l("devportal.submitted", "Submitted"),
@@ -88,165 +88,165 @@ var D = ({ manifest: e, tr: t }) => {
88
88
  })
89
89
  ]
90
90
  }),
91
- /* @__PURE__ */ E("div", {
91
+ /* @__PURE__ */ A("div", {
92
92
  className: "flex items-center gap-2 flex-shrink-0",
93
- children: [/* @__PURE__ */ E("button", {
93
+ children: [/* @__PURE__ */ A("button", {
94
94
  onClick: () => o?.(`${s}/apps/${t.id}`),
95
95
  className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-bg-sunken",
96
96
  title: l("devportal.viewAppDetails", "View app details"),
97
- children: [/* @__PURE__ */ T(b, { size: 14 }), l("devportal.view", "View")]
98
- }), /* @__PURE__ */ E("button", {
99
- onClick: () => v((e) => !e),
97
+ children: [/* @__PURE__ */ k(C, { size: 14 }), l("devportal.view", "View")]
98
+ }), /* @__PURE__ */ A("button", {
99
+ onClick: () => d((e) => !e),
100
100
  className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-bg-sunken",
101
- children: [T(m ? _ : g, { size: 14 }), l("devportal.review", "Review")]
101
+ children: [k(u ? b : y, { size: 14 }), l("devportal.review", "Review")]
102
102
  })]
103
103
  })
104
104
  ]
105
- }), m && /* @__PURE__ */ E("div", {
105
+ }), u && /* @__PURE__ */ A("div", {
106
106
  className: "border-t bg-bg-sunken/30 p-4 space-y-4",
107
107
  children: [
108
- t.reviewNotes && /* @__PURE__ */ E("div", {
108
+ t.reviewNotes && /* @__PURE__ */ A("div", {
109
109
  className: "rounded-md border bg-bg-surface p-3",
110
- children: [/* @__PURE__ */ T("p", {
110
+ children: [/* @__PURE__ */ k("p", {
111
111
  className: "text-xs font-medium text-text-secondary mb-1",
112
112
  children: l("devportal.developerNotes", "Developer Notes")
113
- }), /* @__PURE__ */ T("p", {
113
+ }), /* @__PURE__ */ k("p", {
114
114
  className: "text-sm",
115
115
  children: t.reviewNotes
116
116
  })]
117
117
  }),
118
- /* @__PURE__ */ E("div", {
118
+ /* @__PURE__ */ A("div", {
119
119
  className: "grid grid-cols-2 gap-3 text-sm",
120
120
  children: [
121
- /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ E("span", {
121
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ A("span", {
122
122
  className: "text-text-secondary",
123
123
  children: [
124
124
  l("devportal.category", "Category"),
125
125
  ":",
126
126
  " "
127
127
  ]
128
- }), /* @__PURE__ */ T("span", { children: t.category ?? "—" })] }),
129
- /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ E("span", {
128
+ }), /* @__PURE__ */ k("span", { children: t.category ?? "—" })] }),
129
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ A("span", {
130
130
  className: "text-text-secondary",
131
131
  children: [
132
132
  l("devportal.pricing", "Pricing"),
133
133
  ":",
134
134
  " "
135
135
  ]
136
- }), /* @__PURE__ */ T("span", { children: t.pricingType ?? "FREE" })] }),
137
- /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ E("span", {
136
+ }), /* @__PURE__ */ k("span", { children: t.pricingType ?? "FREE" })] }),
137
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ A("span", {
138
138
  className: "text-text-secondary",
139
139
  children: [
140
140
  l("devportal.website", "Website"),
141
141
  ":",
142
142
  " "
143
143
  ]
144
- }), t.websiteUrl ? /* @__PURE__ */ T("a", {
144
+ }), t.websiteUrl ? /* @__PURE__ */ k("a", {
145
145
  href: t.websiteUrl,
146
146
  target: "_blank",
147
147
  rel: "noopener noreferrer",
148
148
  className: "text-primary underline hover:no-underline",
149
149
  children: l("devportal.link", "Link")
150
- }) : /* @__PURE__ */ T("span", { children: "—" })] }),
151
- /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ E("span", {
150
+ }) : /* @__PURE__ */ k("span", { children: "—" })] }),
151
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ A("span", {
152
152
  className: "text-text-secondary",
153
153
  children: [
154
154
  l("devportal.privacyPolicy", "Privacy Policy"),
155
155
  ":",
156
156
  " "
157
157
  ]
158
- }), t.privacyPolicyUrl ? /* @__PURE__ */ T("a", {
158
+ }), t.privacyPolicyUrl ? /* @__PURE__ */ k("a", {
159
159
  href: t.privacyPolicyUrl,
160
160
  target: "_blank",
161
161
  rel: "noopener noreferrer",
162
162
  className: "text-primary underline hover:no-underline",
163
163
  children: l("devportal.link", "Link")
164
- }) : /* @__PURE__ */ T("span", {
164
+ }) : /* @__PURE__ */ k("span", {
165
165
  className: "text-status-error-text",
166
166
  children: l("devportal.missing", "Missing")
167
167
  })] })
168
168
  ]
169
169
  }),
170
- j && /* @__PURE__ */ E("div", {
170
+ D && /* @__PURE__ */ A("div", {
171
171
  className: "rounded-md border bg-bg-surface p-3 space-y-3",
172
172
  children: [
173
- /* @__PURE__ */ E("p", {
173
+ /* @__PURE__ */ A("p", {
174
174
  className: "text-xs font-medium text-text-secondary",
175
175
  children: [
176
176
  l("devportal.latestVersion", "Latest Version"),
177
177
  ":",
178
178
  " ",
179
- /* @__PURE__ */ T("span", {
179
+ /* @__PURE__ */ k("span", {
180
180
  className: "font-mono text-text-primary",
181
- children: j.version
181
+ children: D.version
182
182
  })
183
183
  ]
184
184
  }),
185
- /* @__PURE__ */ T("div", {
185
+ /* @__PURE__ */ k("div", {
186
186
  className: "flex flex-wrap gap-2",
187
- children: j.packageUrl && /* @__PURE__ */ E("a", {
188
- href: j.packageUrl,
187
+ children: D.packageUrl && /* @__PURE__ */ A("a", {
188
+ href: D.packageUrl,
189
189
  download: !0,
190
190
  target: "_blank",
191
191
  rel: "noopener noreferrer",
192
192
  className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-bg-sunken",
193
193
  children: [
194
- /* @__PURE__ */ T(y, { size: 14 }),
194
+ /* @__PURE__ */ k(S, { size: 14 }),
195
195
  l("devportal.downloadPackage", "Download Package"),
196
- j.packageSize && /* @__PURE__ */ E("span", {
196
+ D.packageSize && /* @__PURE__ */ A("span", {
197
197
  className: "text-text-secondary text-xs ml-1",
198
198
  children: [
199
199
  "(",
200
- j.packageSize,
200
+ D.packageSize,
201
201
  ")"
202
202
  ]
203
203
  })
204
204
  ]
205
205
  })
206
206
  }),
207
- j.manifest && /* @__PURE__ */ T(D, {
208
- manifest: j.manifest,
207
+ D.manifest && /* @__PURE__ */ k(j, {
208
+ manifest: D.manifest,
209
209
  tr: l
210
210
  })
211
211
  ]
212
212
  }),
213
- /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("label", {
213
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("label", {
214
214
  className: "text-sm font-medium",
215
215
  children: l("devportal.reviewNotes", "Review Notes")
216
- }), /* @__PURE__ */ T("textarea", {
217
- value: x,
218
- onChange: (e) => C(e.target.value),
216
+ }), /* @__PURE__ */ k("textarea", {
217
+ value: f,
218
+ onChange: (e) => _(e.target.value),
219
219
  placeholder: l("devportal.reviewNotesPlaceholder", "Add feedback for the developer (required for rejection)..."),
220
220
  rows: 3,
221
221
  className: "mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm ring-offset-background placeholder:text-text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] resize-none"
222
222
  })] }),
223
- /* @__PURE__ */ E("div", {
223
+ /* @__PURE__ */ A("div", {
224
224
  className: "flex gap-3",
225
- children: [/* @__PURE__ */ E("button", {
226
- onClick: () => n(t.id, x),
227
- disabled: a || !O.allowed,
228
- "aria-disabled": a || !O.allowed,
229
- title: O.allowed ? void 0 : l("devportal.common.noPermission", "You do not have permission to perform this action"),
225
+ children: [/* @__PURE__ */ A("button", {
226
+ onClick: () => n(t.id, f),
227
+ disabled: a || !x.allowed,
228
+ "aria-disabled": a || !x.allowed,
229
+ title: x.allowed ? void 0 : l("devportal.common.noPermission", "You do not have permission to perform this action"),
230
230
  className: "inline-flex items-center gap-2 rounded-md bg-status-success-bg px-4 py-2 text-sm font-medium text-white hover:bg-status-success-bg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
231
- children: [a ? /* @__PURE__ */ T(S, {
231
+ children: [a ? /* @__PURE__ */ k(E, {
232
232
  size: 14,
233
233
  className: "animate-spin",
234
234
  "aria-hidden": "true"
235
- }) : /* @__PURE__ */ T(h, {
235
+ }) : /* @__PURE__ */ k(v, {
236
236
  size: 14,
237
237
  "aria-hidden": "true"
238
238
  }), l("devportal.approve", "Approve")]
239
- }), /* @__PURE__ */ E("button", {
240
- onClick: () => i(t.id, x),
241
- disabled: a || !x.trim() || !k.allowed,
242
- "aria-disabled": a || !x.trim() || !k.allowed,
239
+ }), /* @__PURE__ */ A("button", {
240
+ onClick: () => r(t.id, f),
241
+ disabled: a || !f.trim() || !w.allowed,
242
+ "aria-disabled": a || !f.trim() || !w.allowed,
243
243
  className: "inline-flex items-center gap-2 rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
244
- title: k.allowed ? x.trim() ? void 0 : l("devportal.notesRequiredForRejection", "Notes required for rejection") : l("devportal.common.noPermission", "You do not have permission to perform this action"),
245
- children: [a ? /* @__PURE__ */ T(S, {
244
+ title: w.allowed ? f.trim() ? void 0 : l("devportal.notesRequiredForRejection", "Notes required for rejection") : l("devportal.common.noPermission", "You do not have permission to perform this action"),
245
+ children: [a ? /* @__PURE__ */ k(E, {
246
246
  size: 14,
247
247
  className: "animate-spin",
248
248
  "aria-hidden": "true"
249
- }) : /* @__PURE__ */ T(w, {
249
+ }) : /* @__PURE__ */ k(O, {
250
250
  size: 14,
251
251
  "aria-hidden": "true"
252
252
  }), l("devportal.reject", "Reject")]
@@ -255,150 +255,391 @@ var D = ({ manifest: e, tr: t }) => {
255
255
  ]
256
256
  })]
257
257
  });
258
- }, k = () => {
259
- let { t: e } = p(), r = (t, n) => {
258
+ }, N = ({ app: t, onApproveVersion: n, onRejectVersion: r, processingVersionIds: i }) => {
259
+ let { navigate: a, basePath: o } = e(), { t: s } = g(), c = (e, t) => {
260
+ let n = s(e);
261
+ return n === e ? t : n;
262
+ }, [l, u] = h(!1), d = t.versions.edges.map((e) => e.node).filter((e) => e.status === "pending_review");
263
+ return d.length === 0 ? null : /* @__PURE__ */ A("div", {
264
+ className: "rounded-card border border-border-seam bg-bg-surface overflow-hidden",
265
+ children: [/* @__PURE__ */ A("div", {
266
+ className: "flex items-center gap-4 p-4",
267
+ children: [
268
+ t.iconUrl ? /* @__PURE__ */ k("img", {
269
+ src: t.iconUrl,
270
+ alt: t.name,
271
+ className: "h-12 w-12 rounded-lg object-cover flex-shrink-0"
272
+ }) : /* @__PURE__ */ k("div", {
273
+ className: "h-12 w-12 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0",
274
+ children: /* @__PURE__ */ k("span", {
275
+ className: "text-lg font-bold text-text-secondary",
276
+ children: t.name.charAt(0).toUpperCase()
277
+ })
278
+ }),
279
+ /* @__PURE__ */ A("div", {
280
+ className: "flex-1 min-w-0",
281
+ children: [/* @__PURE__ */ A("div", {
282
+ className: "flex items-center gap-2",
283
+ children: [/* @__PURE__ */ k("h3", {
284
+ className: "font-semibold truncate",
285
+ children: t.name
286
+ }), /* @__PURE__ */ A("span", {
287
+ className: "inline-flex items-center rounded-full bg-status-info-bg-subtle px-2 py-0.5 text-xs font-medium text-status-info-text",
288
+ children: [
289
+ d.length,
290
+ " version",
291
+ d.length === 1 ? "" : "s",
292
+ " pending"
293
+ ]
294
+ })]
295
+ }), /* @__PURE__ */ k("p", {
296
+ className: "text-sm text-text-secondary truncate",
297
+ children: t.shortDescription ?? t.description ?? c("devportal.noDescription", "No description")
298
+ })]
299
+ }),
300
+ /* @__PURE__ */ A("div", {
301
+ className: "flex items-center gap-2 flex-shrink-0",
302
+ children: [/* @__PURE__ */ A("button", {
303
+ onClick: () => a?.(`${o}/apps/${t.id}`),
304
+ className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-bg-sunken",
305
+ children: [/* @__PURE__ */ k(C, { size: 14 }), c("devportal.view", "View")]
306
+ }), /* @__PURE__ */ A("button", {
307
+ onClick: () => u((e) => !e),
308
+ className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-bg-sunken",
309
+ children: [k(l ? b : y, { size: 14 }), c("devportal.review", "Review")]
310
+ })]
311
+ })
312
+ ]
313
+ }), l && /* @__PURE__ */ k("div", {
314
+ className: "border-t bg-bg-sunken/30 p-4 space-y-4",
315
+ children: d.map((e) => /* @__PURE__ */ k(P, {
316
+ version: e,
317
+ appId: t.id,
318
+ onApprove: n,
319
+ onReject: r,
320
+ processing: i.has(e.id),
321
+ tr: c
322
+ }, e.id))
323
+ })]
324
+ });
325
+ }, P = ({ version: e, appId: t, onApprove: n, onReject: r, processing: i, tr: a }) => {
326
+ let [o, s] = h(""), c = m(p.APP_APPROVE), l = m(p.APP_REJECT);
327
+ return /* @__PURE__ */ A("div", {
328
+ className: "rounded-md border bg-bg-surface p-4 space-y-3",
329
+ children: [
330
+ /* @__PURE__ */ A("div", {
331
+ className: "flex items-center gap-3",
332
+ children: [
333
+ /* @__PURE__ */ k(T, {
334
+ size: 14,
335
+ className: "text-text-secondary flex-shrink-0"
336
+ }),
337
+ /* @__PURE__ */ k("span", {
338
+ className: "font-mono font-semibold text-sm",
339
+ children: e.version
340
+ }),
341
+ e.isLatest && /* @__PURE__ */ k("span", {
342
+ className: "inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
343
+ children: "Latest"
344
+ }),
345
+ /* @__PURE__ */ A("span", {
346
+ className: "text-xs text-text-secondary ml-auto",
347
+ children: [
348
+ a("devportal.submitted", "Submitted"),
349
+ ":",
350
+ " ",
351
+ new Date(e.createdAt).toLocaleDateString(void 0, {
352
+ year: "numeric",
353
+ month: "short",
354
+ day: "numeric"
355
+ })
356
+ ]
357
+ })
358
+ ]
359
+ }),
360
+ e.releaseNotes && /* @__PURE__ */ k("p", {
361
+ className: "text-sm text-text-secondary",
362
+ children: e.releaseNotes
363
+ }),
364
+ /* @__PURE__ */ k("div", {
365
+ className: "flex flex-wrap gap-2",
366
+ children: e.packageUrl && /* @__PURE__ */ A("a", {
367
+ href: e.packageUrl,
368
+ download: !0,
369
+ target: "_blank",
370
+ rel: "noopener noreferrer",
371
+ className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-bg-sunken",
372
+ children: [
373
+ /* @__PURE__ */ k(S, { size: 14 }),
374
+ a("devportal.downloadPackage", "Download Package"),
375
+ e.packageSize && /* @__PURE__ */ A("span", {
376
+ className: "text-text-secondary text-xs ml-1",
377
+ children: [
378
+ "(",
379
+ e.packageSize,
380
+ ")"
381
+ ]
382
+ })
383
+ ]
384
+ })
385
+ }),
386
+ e.manifest && /* @__PURE__ */ k(j, {
387
+ manifest: e.manifest,
388
+ tr: a
389
+ }),
390
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("label", {
391
+ className: "text-sm font-medium",
392
+ children: a("devportal.reviewNotes", "Review Notes")
393
+ }), /* @__PURE__ */ k("textarea", {
394
+ value: o,
395
+ onChange: (e) => s(e.target.value),
396
+ placeholder: a("devportal.reviewNotesPlaceholder", "Add feedback for the developer (required for rejection)..."),
397
+ rows: 2,
398
+ className: "mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm ring-offset-background placeholder:text-text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] resize-none"
399
+ })] }),
400
+ /* @__PURE__ */ A("div", {
401
+ className: "flex gap-3",
402
+ children: [/* @__PURE__ */ A("button", {
403
+ onClick: () => n(e.id, t, o),
404
+ disabled: i || !c.allowed,
405
+ "aria-disabled": i || !c.allowed,
406
+ className: "inline-flex items-center gap-2 rounded-md bg-status-success-bg px-4 py-2 text-sm font-medium text-white hover:bg-status-success-bg/90 disabled:opacity-50 disabled:cursor-not-allowed",
407
+ children: [i ? /* @__PURE__ */ k(E, {
408
+ size: 14,
409
+ className: "animate-spin"
410
+ }) : /* @__PURE__ */ k(v, { size: 14 }), a("devportal.approveVersion", "Approve Version")]
411
+ }), /* @__PURE__ */ A("button", {
412
+ onClick: () => r(e.id, t, o),
413
+ disabled: i || !o.trim() || !l.allowed,
414
+ "aria-disabled": i || !o.trim() || !l.allowed,
415
+ className: "inline-flex items-center gap-2 rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/90 disabled:opacity-50 disabled:cursor-not-allowed",
416
+ children: [i ? /* @__PURE__ */ k(E, {
417
+ size: 14,
418
+ className: "animate-spin"
419
+ }) : /* @__PURE__ */ k(O, { size: 14 }), a("devportal.rejectVersion", "Reject Version")]
420
+ })]
421
+ })
422
+ ]
423
+ });
424
+ }, F = () => {
425
+ let { t: e } = g(), i = (t, n) => {
260
426
  let r = e(t);
261
427
  return r === t ? n : r;
262
- }, [d, g] = f(""), [_, y] = f(/* @__PURE__ */ new Set()), [b, x] = f(null), [w, D] = f(null), k = (e) => y((t) => new Set(t).add(e)), A = (e) => y((t) => {
428
+ }, [m, y] = h(""), [b, S] = h(/* @__PURE__ */ new Set()), [C, w] = h(/* @__PURE__ */ new Set()), [O, j] = h(null), [P, F] = h(null), I = (e) => S((t) => new Set(t).add(e)), L = (e) => S((t) => {
263
429
  let n = new Set(t);
264
430
  return n.delete(e), n;
265
- }), { data: j, loading: M, error: N, refetch: P } = i({
431
+ }), R = (e) => w((t) => new Set(t).add(e)), z = (e) => w((t) => {
432
+ let n = new Set(t);
433
+ return n.delete(e), n;
434
+ }), { data: B, loading: V, error: H, refetch: U } = a({
266
435
  variables: {
267
436
  status: "SUBMITTED",
268
437
  limit: 100
269
438
  },
270
439
  fetchPolicy: "cache-and-network"
271
- }), [F] = n(), [I] = a(), L = j?.applications?.edges?.map((e) => e.node) ?? [], R = d ? L.filter((e) => e.name.toLowerCase().includes(d.toLowerCase()) || (e.shortDescription ?? "").toLowerCase().includes(d.toLowerCase())) : L, z = async (e, t) => {
272
- k(e), x(null), D(null);
440
+ }), { data: W, refetch: G } = o({
441
+ variables: { limit: 100 },
442
+ fetchPolicy: "cache-and-network"
443
+ }), [K] = n(), [q] = s(), [J] = r(), [Y] = c(), X = B?.applications?.edges?.map((e) => e.node) ?? [], Z = W?.applicationsWithPendingVersions?.edges?.map((e) => e.node) ?? [], Q = m ? X.filter((e) => e.name.toLowerCase().includes(m.toLowerCase()) || (e.shortDescription ?? "").toLowerCase().includes(m.toLowerCase())) : X, $ = async (e, t) => {
444
+ I(e), j(null), F(null);
273
445
  try {
274
- let n = await F({ variables: {
446
+ let n = await K({ variables: {
275
447
  id: e,
276
448
  notes: t || void 0
277
449
  } });
278
450
  if (n.error) throw n.error;
279
- D(r("devportal.applicationApprovedSuccess", "Application approved successfully.")), await P();
451
+ F(i("devportal.applicationApprovedSuccess", "Application approved successfully.")), await U();
280
452
  } catch (e) {
281
- x(e instanceof Error ? e.message : r("devportal.failedToApproveApplication", "Failed to approve application"));
453
+ j(e instanceof Error ? e.message : i("devportal.failedToApproveApplication", "Failed to approve application"));
282
454
  } finally {
283
- A(e);
455
+ L(e);
284
456
  }
285
- }, B = async (e, t) => {
457
+ }, ee = async (e, t) => {
286
458
  if (t.trim()) {
287
- k(e), x(null), D(null);
459
+ I(e), j(null), F(null);
288
460
  try {
289
- let n = await I({ variables: {
461
+ let n = await q({ variables: {
290
462
  id: e,
291
463
  notes: t
292
464
  } });
293
465
  if (n.error) throw n.error;
294
- D(r("devportal.applicationRejected", "Application rejected.")), await P();
466
+ F(i("devportal.applicationRejected", "Application rejected.")), await U();
295
467
  } catch (e) {
296
- x(e instanceof Error ? e.message : r("devportal.failedToRejectApplication", "Failed to reject application"));
468
+ j(e instanceof Error ? e.message : i("devportal.failedToRejectApplication", "Failed to reject application"));
297
469
  } finally {
298
- A(e);
470
+ L(e);
471
+ }
472
+ }
473
+ }, te = async (e, t, n) => {
474
+ R(e), j(null), F(null);
475
+ try {
476
+ let t = await J({ variables: {
477
+ id: e,
478
+ notes: n || void 0
479
+ } });
480
+ if (t.error) throw t.error;
481
+ F(i("devportal.versionApprovedSuccess", "Version approved and published.")), await G();
482
+ } catch (e) {
483
+ j(e instanceof Error ? e.message : i("devportal.failedToApproveVersion", "Failed to approve version"));
484
+ } finally {
485
+ z(e);
486
+ }
487
+ }, ne = async (e, t, n) => {
488
+ if (n.trim()) {
489
+ R(e), j(null), F(null);
490
+ try {
491
+ let t = await Y({ variables: {
492
+ id: e,
493
+ reason: n
494
+ } });
495
+ if (t.error) throw t.error;
496
+ F(i("devportal.versionRejectedSuccess", "Version rejected and returned to draft.")), await G();
497
+ } catch (e) {
498
+ j(e instanceof Error ? e.message : i("devportal.failedToRejectVersion", "Failed to reject version"));
499
+ } finally {
500
+ z(e);
299
501
  }
300
502
  }
301
503
  };
302
- return M && !j ? /* @__PURE__ */ T(s, {
303
- title: r("devportal.appReviewQueue", "App Review Queue"),
304
- description: r("devportal.appReviewQueueDescription", "Review submitted applications for approval"),
305
- children: /* @__PURE__ */ T("div", {
504
+ return V && !B ? /* @__PURE__ */ k(u, {
505
+ title: i("devportal.appReviewQueue", "App Review Queue"),
506
+ description: i("devportal.appReviewQueueDescription", "Review submitted applications for approval"),
507
+ children: /* @__PURE__ */ k("div", {
306
508
  className: "flex items-center justify-center py-12",
307
- children: /* @__PURE__ */ T(S, { className: "h-8 w-8 animate-spin text-text-secondary" })
509
+ children: /* @__PURE__ */ k(E, { className: "h-8 w-8 animate-spin text-text-secondary" })
308
510
  })
309
- }) : N ? /* @__PURE__ */ T(s, {
310
- title: r("devportal.appReviewQueue", "App Review Queue"),
311
- description: r("devportal.appReviewQueueDescription", "Review submitted applications for approval"),
312
- children: /* @__PURE__ */ E("div", {
511
+ }) : H ? /* @__PURE__ */ k(u, {
512
+ title: i("devportal.appReviewQueue", "App Review Queue"),
513
+ description: i("devportal.appReviewQueueDescription", "Review submitted applications for approval"),
514
+ children: /* @__PURE__ */ A("div", {
313
515
  className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
314
516
  children: [
315
- /* @__PURE__ */ T(m, { className: "mx-auto h-8 w-8 text-status-error-text" }),
316
- /* @__PURE__ */ T("p", {
517
+ /* @__PURE__ */ k(_, { className: "mx-auto h-8 w-8 text-status-error-text" }),
518
+ /* @__PURE__ */ k("p", {
317
519
  className: "mt-2 text-sm text-text-secondary",
318
- children: o(N)
520
+ children: l(H)
319
521
  }),
320
- /* @__PURE__ */ T("button", {
321
- onClick: () => P(),
522
+ /* @__PURE__ */ k("button", {
523
+ onClick: () => U(),
322
524
  className: "mt-4 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
323
- children: r("devportal.retry", "Retry")
525
+ children: i("devportal.retry", "Retry")
324
526
  })
325
527
  ]
326
528
  })
327
- }) : /* @__PURE__ */ T(l, {
328
- permission: u.REVIEW_MANAGE,
329
- children: /* @__PURE__ */ E(s, {
330
- title: r("devportal.appReviewQueue", "App Review Queue"),
331
- description: r("devportal.appReviewQueueFullDescription", "Review submitted applications for approval or rejection"),
332
- purpose: r("devportal.appReviewQueuePurpose", "The moderation queue for apps developers have submitted to the marketplace. Open each submission to check its listing, permissions, and behaviour against the guidelines, then approve it to go live or reject it with feedback."),
333
- actions: /* @__PURE__ */ T("button", {
334
- onClick: () => P(),
529
+ }) : /* @__PURE__ */ k(f, {
530
+ permission: p.REVIEW_MANAGE,
531
+ children: /* @__PURE__ */ A(u, {
532
+ title: i("devportal.appReviewQueue", "App Review Queue"),
533
+ description: i("devportal.appReviewQueueFullDescription", "Review submitted applications for approval or rejection"),
534
+ purpose: i("devportal.appReviewQueuePurpose", "The moderation queue for apps developers have submitted to the marketplace. Open each submission to check its listing, permissions, and behaviour against the guidelines, then approve it to go live or reject it with feedback."),
535
+ actions: /* @__PURE__ */ k("button", {
536
+ onClick: () => {
537
+ U(), G();
538
+ },
335
539
  className: "rounded-md border px-3 py-1.5 text-sm hover:bg-bg-sunken",
336
- children: r("devportal.refresh", "Refresh")
540
+ children: i("devportal.refresh", "Refresh")
337
541
  }),
338
542
  children: [
339
- /* @__PURE__ */ E("div", {
543
+ /* @__PURE__ */ A("div", {
340
544
  className: "flex items-center gap-6 rounded-card border border-border-seam bg-bg-surface p-4",
341
- children: [/* @__PURE__ */ E("div", {
342
- className: "flex items-center gap-2",
343
- children: [/* @__PURE__ */ T(v, {
344
- size: 18,
345
- className: "text-status-warning-text"
346
- }), /* @__PURE__ */ E("span", {
347
- className: "text-sm font-medium",
348
- children: [
349
- L.length,
350
- " ",
351
- r("devportal.pendingReview", "pending review")
352
- ]
353
- })]
354
- }), _.size > 0 && /* @__PURE__ */ E("div", {
355
- className: "flex items-center gap-2 text-sm text-text-secondary",
356
- children: [/* @__PURE__ */ T(S, {
357
- size: 14,
358
- className: "animate-spin"
359
- }), r("devportal.processing", "Processing...")]
360
- })]
545
+ children: [
546
+ /* @__PURE__ */ A("div", {
547
+ className: "flex items-center gap-2",
548
+ children: [/* @__PURE__ */ k(x, {
549
+ size: 18,
550
+ className: "text-status-warning-text"
551
+ }), /* @__PURE__ */ A("span", {
552
+ className: "text-sm font-medium",
553
+ children: [
554
+ X.length,
555
+ " ",
556
+ i("devportal.pendingReview", "pending review")
557
+ ]
558
+ })]
559
+ }),
560
+ Z.length > 0 && /* @__PURE__ */ A("div", {
561
+ className: "flex items-center gap-2",
562
+ children: [/* @__PURE__ */ k(T, {
563
+ size: 18,
564
+ className: "text-status-info-text"
565
+ }), /* @__PURE__ */ A("span", {
566
+ className: "text-sm font-medium",
567
+ children: [
568
+ Z.length,
569
+ " ",
570
+ i("devportal.withPendingVersions", "with pending versions")
571
+ ]
572
+ })]
573
+ }),
574
+ (b.size > 0 || C.size > 0) && /* @__PURE__ */ A("div", {
575
+ className: "flex items-center gap-2 text-sm text-text-secondary",
576
+ children: [/* @__PURE__ */ k(E, {
577
+ size: 14,
578
+ className: "animate-spin"
579
+ }), i("devportal.processing", "Processing...")]
580
+ })
581
+ ]
361
582
  }),
362
- w && /* @__PURE__ */ E("div", {
583
+ P && /* @__PURE__ */ A("div", {
363
584
  className: "flex items-center gap-2 rounded-lg border border-border-subtle bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text",
364
- children: [/* @__PURE__ */ T(h, { size: 16 }), w]
585
+ children: [/* @__PURE__ */ k(v, { size: 16 }), P]
365
586
  }),
366
- b && /* @__PURE__ */ E("div", {
587
+ O && /* @__PURE__ */ A("div", {
367
588
  className: "flex items-center gap-2 rounded-lg border border-status-error-border/50 bg-status-error-bg/10 px-4 py-3 text-sm text-status-error-text",
368
- children: [/* @__PURE__ */ T(m, { size: 16 }), b]
589
+ children: [/* @__PURE__ */ k(_, { size: 16 }), O]
369
590
  }),
370
- L.length > 0 && /* @__PURE__ */ E("div", {
591
+ X.length > 0 && /* @__PURE__ */ A("div", {
371
592
  className: "relative max-w-sm",
372
- children: [/* @__PURE__ */ T(C, {
593
+ children: [/* @__PURE__ */ k(D, {
373
594
  size: 14,
374
595
  className: "absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary"
375
- }), /* @__PURE__ */ T("input", {
596
+ }), /* @__PURE__ */ k("input", {
376
597
  type: "text",
377
- placeholder: r("devportal.searchSubmittedApps", "Search submitted apps..."),
378
- value: d,
379
- onChange: (e) => g(e.target.value),
598
+ placeholder: i("devportal.searchSubmittedApps", "Search submitted apps..."),
599
+ value: m,
600
+ onChange: (e) => y(e.target.value),
380
601
  className: "w-full rounded-md border bg-bg-surface pl-9 pr-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
381
602
  })]
382
603
  }),
383
- /* @__PURE__ */ T(c, { children: R.length === 0 ? /* @__PURE__ */ T(t, {
384
- illustration: "empty-data",
385
- icon: /* @__PURE__ */ T(h, { size: 32 }),
386
- title: r("devportal.noAppsPendingReview", "No apps pending review"),
387
- description: d ? r("devportal.noAppsMatchSearch", "No apps match your search") : r("devportal.allApplicationsReviewed", "All submitted applications have been reviewed")
388
- }) : /* @__PURE__ */ T("div", {
389
- className: "space-y-3",
390
- children: R.map((e) => /* @__PURE__ */ T(O, {
391
- app: e,
392
- onApprove: z,
393
- onReject: B,
394
- processing: _.has(e.id)
395
- }, e.id))
396
- }) })
604
+ /* @__PURE__ */ k(d, {
605
+ title: i("devportal.newAppSubmissions", "New App Submissions"),
606
+ children: Q.length === 0 ? /* @__PURE__ */ k(t, {
607
+ illustration: "empty-data",
608
+ icon: /* @__PURE__ */ k(v, { size: 32 }),
609
+ title: i("devportal.noAppsPendingReview", "No apps pending review"),
610
+ description: m ? i("devportal.noAppsMatchSearch", "No apps match your search") : i("devportal.allApplicationsReviewed", "All submitted applications have been reviewed")
611
+ }) : /* @__PURE__ */ k("div", {
612
+ className: "space-y-3",
613
+ children: Q.map((e) => /* @__PURE__ */ k(M, {
614
+ app: e,
615
+ onApprove: $,
616
+ onReject: ee,
617
+ processing: b.has(e.id)
618
+ }, e.id))
619
+ })
620
+ }),
621
+ /* @__PURE__ */ k(d, {
622
+ title: i("devportal.versionUpdates", "Version Updates (Published Apps)"),
623
+ children: Z.length === 0 ? /* @__PURE__ */ k(t, {
624
+ illustration: "empty-data",
625
+ icon: /* @__PURE__ */ k(T, { size: 32 }),
626
+ title: i("devportal.noPendingVersions", "No pending version updates"),
627
+ description: i("devportal.allVersionsReviewed", "All version updates from published apps have been reviewed")
628
+ }) : /* @__PURE__ */ k("div", {
629
+ className: "space-y-3",
630
+ children: Z.map((e) => /* @__PURE__ */ k(N, {
631
+ app: e,
632
+ onApproveVersion: te,
633
+ onRejectVersion: ne,
634
+ processingVersionIds: C
635
+ }, e.id))
636
+ })
637
+ })
397
638
  ]
398
639
  })
399
640
  });
400
641
  };
401
642
  //#endregion
402
- export { k as AdminReviewPage };
643
+ export { F as AdminReviewPage };
403
644
 
404
645
  //# sourceMappingURL=AdminReviewPage.js.map