@burdenoff/microfe-devportal 2026.611.1 → 2026.614.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/devportal/components/SectionNav.js +105 -41
  2. package/dist/devportal/components/SectionNav.js.map +1 -1
  3. package/dist/devportal/hooks/useGraphQL.js +1 -1
  4. package/dist/devportal/pages/AdminReviewPage.js +36 -36
  5. package/dist/devportal/pages/AnalyticsDashboardPage.js +150 -150
  6. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  7. package/dist/devportal/pages/ApiKeysPage.js +184 -172
  8. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  9. package/dist/devportal/pages/AppLogsPage.js +9 -9
  10. package/dist/devportal/pages/ApplicationDetailPage.js +414 -414
  11. package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
  12. package/dist/devportal/pages/ApplicationVersionsPage.js +44 -44
  13. package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
  14. package/dist/devportal/pages/ApplicationsPage.js +118 -118
  15. package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
  16. package/dist/devportal/pages/CreateApiKeyPage.js +20 -20
  17. package/dist/devportal/pages/CreateApplicationPage.js +32 -32
  18. package/dist/devportal/pages/CreateOAuthClientPage.js +20 -20
  19. package/dist/devportal/pages/CreateOrganizationPage.js +109 -422
  20. package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
  21. package/dist/devportal/pages/CreateWebhookPage.js +25 -25
  22. package/dist/devportal/pages/DashboardPage.js +160 -145
  23. package/dist/devportal/pages/DashboardPage.js.map +1 -1
  24. package/dist/devportal/pages/DelegationsPage.js +22 -22
  25. package/dist/devportal/pages/EditApplicationPage.js +283 -283
  26. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  27. package/dist/devportal/pages/ListingPreviewPage.js +9 -9
  28. package/dist/devportal/pages/OAuthClientDetailPage.js +17 -17
  29. package/dist/devportal/pages/OAuthClientsPage.js +16 -16
  30. package/dist/devportal/pages/OrganizationDetailPage.js +78 -78
  31. package/dist/devportal/pages/OrganizationMembersPage.js +260 -260
  32. package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
  33. package/dist/devportal/pages/OrganizationsPage.js +18 -18
  34. package/dist/devportal/pages/PublishPage.js +16 -16
  35. package/dist/devportal/pages/PublisherProfilePage.js +156 -146
  36. package/dist/devportal/pages/PublisherProfilePage.js.map +1 -1
  37. package/dist/devportal/pages/RevenueDashboardPage.js +528 -322
  38. package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
  39. package/dist/devportal/pages/SettingsPage.js +17 -17
  40. package/dist/devportal/pages/SetupPage.js +99 -99
  41. package/dist/devportal/pages/SetupPage.js.map +1 -1
  42. package/dist/devportal/pages/WebhookDetailPage.js +143 -143
  43. package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
  44. package/dist/devportal/pages/WebhooksPage.js +140 -140
  45. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  46. package/dist/devportal/providers/DevportalProvider.js +46 -33
  47. package/dist/devportal/providers/DevportalProvider.js.map +1 -1
  48. package/dist/devportal/types/index.js.map +1 -1
  49. package/dist/generated/global-operations.js +99 -59
  50. package/dist/generated/global-operations.js.map +1 -1
  51. package/package.json +1 -1
@@ -1,131 +1,195 @@
1
1
  import { useDevportal as e } from "../providers/DevportalProvider.js";
2
2
  import { cn as t } from "../utils/cn.js";
3
- import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
4
- import { AppWindow as r, BarChart3 as i, BookOpen as a, Building2 as o, DollarSign as s, Key as c, KeyRound as l, LayoutDashboard as u, Library as d, Settings as f, Share2 as p, User as m, Webhook as h } from "lucide-react";
5
- import { useLocation as g } from "react-router-dom";
6
- import { jsx as _, jsxs as v } from "react/jsx-runtime";
3
+ import { useGetMyOrganizationsQuery as n } from "../../generated/global-operations.js";
4
+ import "../hooks/useGraphQL.js";
5
+ import { useEffect as r, useRef as i, useState as a } from "react";
6
+ import { useI18n as o } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
+ import { AppWindow as s, BarChart3 as c, BookOpen as l, Building2 as u, Check as d, ChevronDown as f, DollarSign as p, Key as m, KeyRound as h, LayoutDashboard as g, Library as _, Settings as v, Share2 as y, User as b, Webhook as x } from "lucide-react";
8
+ import { useLocation as S } from "react-router-dom";
9
+ import { jsx as C, jsxs as w } from "react/jsx-runtime";
7
10
  //#region src/devportal/components/SectionNav.tsx
8
- var y = [
11
+ var T = [
9
12
  {
10
13
  path: "",
11
14
  i18nKey: "devportal.nav.dashboard",
12
15
  fallback: "Dashboard",
13
- icon: u
16
+ icon: g
14
17
  },
15
18
  {
16
19
  path: "apps",
17
20
  i18nKey: "devportal.nav.apps",
18
21
  fallback: "Apps",
19
- icon: r
22
+ icon: s
20
23
  },
21
24
  {
22
25
  path: "organizations",
23
26
  i18nKey: "devportal.nav.organizations",
24
27
  fallback: "Organizations",
25
- icon: o
28
+ icon: u
26
29
  },
27
30
  {
28
31
  path: "oauth",
29
32
  i18nKey: "devportal.nav.oauth",
30
33
  fallback: "OAuth Clients",
31
- icon: l
34
+ icon: h
32
35
  },
33
36
  {
34
37
  path: "api-keys",
35
38
  i18nKey: "devportal.nav.apiKeys",
36
39
  fallback: "API Keys",
37
- icon: c
40
+ icon: m
38
41
  },
39
42
  {
40
43
  path: "webhooks",
41
44
  i18nKey: "devportal.nav.webhooks",
42
45
  fallback: "Webhooks",
43
- icon: h
46
+ icon: x
44
47
  },
45
48
  {
46
49
  path: "delegations",
47
50
  i18nKey: "devportal.nav.delegations",
48
51
  fallback: "Delegations",
49
- icon: p
52
+ icon: y
50
53
  },
51
54
  {
52
55
  path: "analytics",
53
56
  i18nKey: "devportal.nav.analytics",
54
57
  fallback: "Analytics",
55
- icon: i
58
+ icon: c
56
59
  },
57
60
  {
58
61
  path: "revenue",
59
62
  i18nKey: "devportal.nav.revenue",
60
63
  fallback: "Revenue",
61
- icon: s
64
+ icon: p
62
65
  },
63
66
  {
64
67
  path: "docs",
65
68
  i18nKey: "devportal.nav.docs",
66
69
  fallback: "Docs",
67
- icon: a
70
+ icon: l
68
71
  },
69
72
  {
70
73
  path: "resources",
71
74
  i18nKey: "devportal.nav.resources",
72
75
  fallback: "Resources",
73
- icon: d
76
+ icon: _
74
77
  },
75
78
  {
76
79
  path: "publisher/profile",
77
80
  i18nKey: "devportal.nav.publisher",
78
81
  fallback: "Publisher",
79
- icon: m,
82
+ icon: b,
80
83
  matchPrefixes: ["publisher"]
81
84
  },
82
85
  {
83
86
  path: "settings",
84
87
  i18nKey: "devportal.nav.settings",
85
88
  fallback: "Settings",
86
- icon: f
89
+ icon: v
87
90
  }
88
91
  ];
89
- function b(e, t) {
92
+ function E(e, t) {
90
93
  let n = (e ?? "").replace(/\/$/, "");
91
94
  return t ? `${n}${t.startsWith("/") ? t : `/${t}`}` : n || "/";
92
95
  }
93
- function x(e, t, n) {
94
- let r = b(t, n.path);
96
+ function D(e, t, n) {
97
+ let r = E(t, n.path);
95
98
  return n.path === "" ? e === r || e === `${r}/` : [n.path, ...n.matchPrefixes ?? []].some((n) => {
96
- let r = b(t, n);
99
+ let r = E(t, n);
97
100
  return e === r || e.startsWith(`${r}/`);
98
101
  });
99
102
  }
100
- var S = () => {
101
- let { navigate: r, basePath: i } = e(), { pathname: a } = g(), { t: o } = n(), s = (e, t) => {
102
- let n = o(e);
103
+ var O = () => {
104
+ let { activeOrgId: s, setActiveOrgId: c } = e(), { t: l } = o(), p = (e, t) => {
105
+ let n = l(e);
106
+ return n === e ? t : n;
107
+ }, [m, h] = a(!1), g = i(null), { data: _ } = n({ fetchPolicy: "cache-first" }), v = _?.myDeveloperOrganizations ?? [];
108
+ if (r(() => {
109
+ !s && v.length === 1 && v[0]?.id && c(v[0].id);
110
+ }, [
111
+ v,
112
+ s,
113
+ c
114
+ ]), r(() => {
115
+ let e = (e) => {
116
+ g.current && !g.current.contains(e.target) && h(!1);
117
+ };
118
+ return m && document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
119
+ }, [m]), v.length === 0) return null;
120
+ let y = v.find((e) => e.id === s)?.name ?? p("devportal.nav.selectOrg", "Select org");
121
+ return /* @__PURE__ */ w("div", {
122
+ ref: g,
123
+ className: "relative flex-shrink-0",
124
+ children: [/* @__PURE__ */ w("button", {
125
+ type: "button",
126
+ onClick: () => h((e) => !e),
127
+ className: t("inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors", "bg-card text-foreground border-border hover:bg-accent"),
128
+ "aria-label": p("devportal.nav.switchOrg", "Switch organization"),
129
+ children: [
130
+ /* @__PURE__ */ C(u, {
131
+ size: 13,
132
+ className: "text-primary flex-shrink-0"
133
+ }),
134
+ /* @__PURE__ */ C("span", {
135
+ className: "max-w-[140px] truncate",
136
+ children: y
137
+ }),
138
+ /* @__PURE__ */ C(f, {
139
+ size: 13,
140
+ className: t("transition-transform", m && "rotate-180")
141
+ })
142
+ ]
143
+ }), m && /* @__PURE__ */ C("div", {
144
+ className: "absolute right-0 top-full z-50 mt-1 min-w-[200px] rounded-md border border-border bg-popover shadow-lg py-1",
145
+ children: v.map((e) => /* @__PURE__ */ w("button", {
146
+ type: "button",
147
+ onClick: () => {
148
+ c(e.id), h(!1);
149
+ },
150
+ className: t("flex w-full items-center gap-2 px-3 py-2 text-sm text-left transition-colors hover:bg-accent", e.id === s ? "text-primary font-medium" : "text-foreground"),
151
+ children: [/* @__PURE__ */ C(d, {
152
+ size: 13,
153
+ className: t("flex-shrink-0", e.id === s ? "opacity-100 text-primary" : "opacity-0")
154
+ }), /* @__PURE__ */ C("span", {
155
+ className: "truncate",
156
+ children: e.name
157
+ })]
158
+ }, e.id))
159
+ })]
160
+ });
161
+ }, k = () => {
162
+ let { navigate: n, basePath: r } = e(), { pathname: i } = S(), { t: a } = o(), s = (e, t) => {
163
+ let n = a(e);
103
164
  return n === e ? t : n;
104
165
  };
105
- if (!i || !r) return null;
166
+ if (!r || !n) return null;
106
167
  let c = (e) => {
107
- r(b(i, e));
168
+ n(E(r, e));
108
169
  };
109
- return /* @__PURE__ */ _("nav", {
170
+ return /* @__PURE__ */ C("nav", {
110
171
  "aria-label": s("devportal.nav.sections", "Developer portal sections"),
111
172
  className: "border-b border-border bg-card/40 px-4 py-2",
112
173
  "data-testid": "devportal-section-nav",
113
- children: /* @__PURE__ */ _("ul", {
114
- className: "flex flex-wrap gap-1",
115
- children: y.map((e) => {
116
- let n = x(a, i, e), r = e.icon;
117
- return /* @__PURE__ */ _("li", { children: /* @__PURE__ */ v("button", {
118
- type: "button",
119
- onClick: () => c(e.path),
120
- "aria-current": n ? "page" : void 0,
121
- className: t("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors", n ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"),
122
- children: [/* @__PURE__ */ _(r, { size: 14 }), /* @__PURE__ */ _("span", { children: s(e.i18nKey, e.fallback) })]
123
- }) }, e.path);
124
- })
174
+ children: /* @__PURE__ */ w("div", {
175
+ className: "flex items-center gap-2",
176
+ children: [/* @__PURE__ */ C("ul", {
177
+ className: "flex flex-1 flex-wrap gap-1",
178
+ children: T.map((e) => {
179
+ let n = D(i, r, e), a = e.icon;
180
+ return /* @__PURE__ */ C("li", { children: /* @__PURE__ */ w("button", {
181
+ type: "button",
182
+ onClick: () => c(e.path),
183
+ "aria-current": n ? "page" : void 0,
184
+ className: t("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors", n ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"),
185
+ children: [/* @__PURE__ */ C(a, { size: 14 }), /* @__PURE__ */ C("span", { children: s(e.i18nKey, e.fallback) })]
186
+ }) }, e.path);
187
+ })
188
+ }), /* @__PURE__ */ C(O, {})]
125
189
  })
126
190
  });
127
191
  };
128
192
  //#endregion
129
- export { S as SectionNav };
193
+ export { k as SectionNav };
130
194
 
131
195
  //# sourceMappingURL=SectionNav.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SectionNav.js","names":[],"sources":["../../../src/devportal/components/SectionNav.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useLocation } from \"react-router-dom\";\nimport {\n LayoutDashboard,\n AppWindow,\n Building2,\n KeyRound,\n Key,\n Webhook,\n Share2,\n BarChart3,\n DollarSign,\n BookOpen,\n Library,\n User,\n Settings,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { cn } from \"../utils/cn\";\n\ninterface SectionDef {\n path: string;\n i18nKey: string;\n fallback: string;\n icon: typeof LayoutDashboard;\n /** Additional sub-paths that should mark this section as active. */\n matchPrefixes?: string[];\n}\n\nconst SECTIONS: ReadonlyArray<SectionDef> = [\n {\n path: \"\",\n i18nKey: \"devportal.nav.dashboard\",\n fallback: \"Dashboard\",\n icon: LayoutDashboard,\n },\n {\n path: \"apps\",\n i18nKey: \"devportal.nav.apps\",\n fallback: \"Apps\",\n icon: AppWindow,\n },\n {\n path: \"organizations\",\n i18nKey: \"devportal.nav.organizations\",\n fallback: \"Organizations\",\n icon: Building2,\n },\n {\n path: \"oauth\",\n i18nKey: \"devportal.nav.oauth\",\n fallback: \"OAuth Clients\",\n icon: KeyRound,\n },\n {\n path: \"api-keys\",\n i18nKey: \"devportal.nav.apiKeys\",\n fallback: \"API Keys\",\n icon: Key,\n },\n {\n path: \"webhooks\",\n i18nKey: \"devportal.nav.webhooks\",\n fallback: \"Webhooks\",\n icon: Webhook,\n },\n {\n path: \"delegations\",\n i18nKey: \"devportal.nav.delegations\",\n fallback: \"Delegations\",\n icon: Share2,\n },\n {\n path: \"analytics\",\n i18nKey: \"devportal.nav.analytics\",\n fallback: \"Analytics\",\n icon: BarChart3,\n },\n {\n path: \"revenue\",\n i18nKey: \"devportal.nav.revenue\",\n fallback: \"Revenue\",\n icon: DollarSign,\n },\n {\n path: \"docs\",\n i18nKey: \"devportal.nav.docs\",\n fallback: \"Docs\",\n icon: BookOpen,\n },\n {\n path: \"resources\",\n i18nKey: \"devportal.nav.resources\",\n fallback: \"Resources\",\n icon: Library,\n },\n {\n path: \"publisher/profile\",\n i18nKey: \"devportal.nav.publisher\",\n fallback: \"Publisher\",\n icon: User,\n matchPrefixes: [\"publisher\"],\n },\n {\n path: \"settings\",\n i18nKey: \"devportal.nav.settings\",\n fallback: \"Settings\",\n icon: Settings,\n },\n];\n\nfunction joinBaseAndPath(basePath: string | undefined, path: string): string {\n const base = (basePath ?? \"\").replace(/\\/$/, \"\");\n if (!path) return base || \"/\";\n const suffix = path.startsWith(\"/\") ? path : `/${path}`;\n return `${base}${suffix}`;\n}\n\nfunction isSectionActive(\n pathname: string,\n basePath: string | undefined,\n section: SectionDef,\n): boolean {\n const sectionUrl = joinBaseAndPath(basePath, section.path);\n // Index/dashboard is active only when exactly matched (or with empty extra).\n if (section.path === \"\") {\n return pathname === sectionUrl || pathname === `${sectionUrl}/`;\n }\n const candidates = [section.path, ...(section.matchPrefixes ?? [])];\n return candidates.some((prefix) => {\n const url = joinBaseAndPath(basePath, prefix);\n return pathname === url || pathname.startsWith(`${url}/`);\n });\n}\n\n/**\n * Horizontal section nav rendered above the page content on every devportal\n * route. Gives developers a one-click jump between all top-level sections so\n * routes like OAuth, Delegations, Analytics, Revenue, Docs, Resources,\n * Publisher Profile, and Settings are reachable without typing URLs.\n *\n * Renders nothing when `basePath` is undefined (standalone/dev mode) so it\n * doesn't conflict with whatever harness wraps the MFE there.\n */\nexport const SectionNav: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { pathname } = useLocation();\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\n if (!basePath || !navigate) return null;\n\n const handleClick = (path: string) => {\n navigate(joinBaseAndPath(basePath, path));\n };\n\n return (\n <nav\n aria-label={tr(\"devportal.nav.sections\", \"Developer portal sections\")}\n className=\"border-b border-border bg-card/40 px-4 py-2\"\n data-testid=\"devportal-section-nav\"\n >\n <ul className=\"flex flex-wrap gap-1\">\n {SECTIONS.map((section) => {\n const active = isSectionActive(pathname, basePath, section);\n const Icon = section.icon;\n return (\n <li key={section.path}>\n <button\n type=\"button\"\n onClick={() => handleClick(section.path)}\n aria-current={active ? \"page\" : undefined}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors\",\n active\n ? \"bg-primary text-primary-foreground\"\n : \"text-muted-foreground hover:bg-accent hover:text-foreground\",\n )}\n >\n <Icon size={14} />\n <span>{tr(section.i18nKey, section.fallback)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n </nav>\n );\n};\n\n// Exported for unit tests that want to assert against the canonical list.\nexport const __SECTION_NAV_SECTIONS = SECTIONS;\n"],"mappings":";;;;;;;AA8BA,IAAM,IAAsC;CAC1C;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACN,eAAe,CAAC,YAAY;EAC7B;CACD;EACE,MAAM;EACN,SAAS;EACT,UAAU;EACV,MAAM;EACP;CACF;AAED,SAAS,EAAgB,GAA8B,GAAsB;CAC3E,IAAM,KAAQ,KAAY,IAAI,QAAQ,OAAO,GAAG;AAGhD,QAFK,IAEE,GAAG,IADK,EAAK,WAAW,IAAI,GAAG,IAAO,IAAI,QAD/B,KAAQ;;AAK5B,SAAS,EACP,GACA,GACA,GACS;CACT,IAAM,IAAa,EAAgB,GAAU,EAAQ,KAAK;AAM1D,QAJI,EAAQ,SAAS,KACZ,MAAa,KAAc,MAAa,GAAG,EAAW,KAE5C,CAAC,EAAQ,MAAM,GAAI,EAAQ,iBAAiB,EAAE,CAAE,CACjD,MAAM,MAAW;EACjC,IAAM,IAAM,EAAgB,GAAU,EAAO;AAC7C,SAAO,MAAa,KAAO,EAAS,WAAW,GAAG,EAAI,GAAG;GACzD;;AAYJ,IAAa,UAAuB;CAClC,IAAM,EAAE,aAAU,gBAAa,GAAc,EACvC,EAAE,gBAAa,GAAa,EAC5B,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;;AAGpC,KAAI,CAAC,KAAY,CAAC,EAAU,QAAO;CAEnC,IAAM,KAAe,MAAiB;AACpC,IAAS,EAAgB,GAAU,EAAK,CAAC;;AAG3C,QACE,kBAAC,OAAD;EACE,cAAY,EAAG,0BAA0B,4BAA4B;EACrE,WAAU;EACV,eAAY;YAEZ,kBAAC,MAAD;GAAI,WAAU;aACX,EAAS,KAAK,MAAY;IACzB,IAAM,IAAS,EAAgB,GAAU,GAAU,EAAQ,EACrD,IAAO,EAAQ;AACrB,WACE,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAY,EAAQ,KAAK;KACxC,gBAAc,IAAS,SAAS,KAAA;KAChC,WAAW,EACT,iGACA,IACI,uCACA,8DACL;eATH,CAWE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EAClB,kBAAC,QAAD,EAAA,UAAO,EAAG,EAAQ,SAAS,EAAQ,SAAS,EAAQ,CAAA,CAC7C;QACN,EAfI,EAAQ,KAeZ;KAEP;GACC,CAAA;EACD,CAAA"}
1
+ {"version":3,"file":"SectionNav.js","names":[],"sources":["../../../src/devportal/components/SectionNav.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useLocation } from \"react-router-dom\";\nimport {\n LayoutDashboard,\n AppWindow,\n Building2,\n KeyRound,\n Key,\n Webhook,\n Share2,\n BarChart3,\n DollarSign,\n BookOpen,\n Library,\n User,\n Settings,\n ChevronDown,\n Check,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n useGetMyOrganizationsQuery,\n type GetMyOrganizationsQuery,\n} from \"../hooks/useGraphQL\";\nimport { cn } from \"../utils/cn\";\n\ntype OrgItem = GetMyOrganizationsQuery[\"myDeveloperOrganizations\"][number];\n\ninterface SectionDef {\n path: string;\n i18nKey: string;\n fallback: string;\n icon: typeof LayoutDashboard;\n /** Additional sub-paths that should mark this section as active. */\n matchPrefixes?: string[];\n}\n\nconst SECTIONS: ReadonlyArray<SectionDef> = [\n {\n path: \"\",\n i18nKey: \"devportal.nav.dashboard\",\n fallback: \"Dashboard\",\n icon: LayoutDashboard,\n },\n {\n path: \"apps\",\n i18nKey: \"devportal.nav.apps\",\n fallback: \"Apps\",\n icon: AppWindow,\n },\n {\n path: \"organizations\",\n i18nKey: \"devportal.nav.organizations\",\n fallback: \"Organizations\",\n icon: Building2,\n },\n {\n path: \"oauth\",\n i18nKey: \"devportal.nav.oauth\",\n fallback: \"OAuth Clients\",\n icon: KeyRound,\n },\n {\n path: \"api-keys\",\n i18nKey: \"devportal.nav.apiKeys\",\n fallback: \"API Keys\",\n icon: Key,\n },\n {\n path: \"webhooks\",\n i18nKey: \"devportal.nav.webhooks\",\n fallback: \"Webhooks\",\n icon: Webhook,\n },\n {\n path: \"delegations\",\n i18nKey: \"devportal.nav.delegations\",\n fallback: \"Delegations\",\n icon: Share2,\n },\n {\n path: \"analytics\",\n i18nKey: \"devportal.nav.analytics\",\n fallback: \"Analytics\",\n icon: BarChart3,\n },\n {\n path: \"revenue\",\n i18nKey: \"devportal.nav.revenue\",\n fallback: \"Revenue\",\n icon: DollarSign,\n },\n {\n path: \"docs\",\n i18nKey: \"devportal.nav.docs\",\n fallback: \"Docs\",\n icon: BookOpen,\n },\n {\n path: \"resources\",\n i18nKey: \"devportal.nav.resources\",\n fallback: \"Resources\",\n icon: Library,\n },\n {\n path: \"publisher/profile\",\n i18nKey: \"devportal.nav.publisher\",\n fallback: \"Publisher\",\n icon: User,\n matchPrefixes: [\"publisher\"],\n },\n {\n path: \"settings\",\n i18nKey: \"devportal.nav.settings\",\n fallback: \"Settings\",\n icon: Settings,\n },\n];\n\nfunction joinBaseAndPath(basePath: string | undefined, path: string): string {\n const base = (basePath ?? \"\").replace(/\\/$/, \"\");\n if (!path) return base || \"/\";\n const suffix = path.startsWith(\"/\") ? path : `/${path}`;\n return `${base}${suffix}`;\n}\n\nfunction isSectionActive(\n pathname: string,\n basePath: string | undefined,\n section: SectionDef,\n): boolean {\n const sectionUrl = joinBaseAndPath(basePath, section.path);\n // Index/dashboard is active only when exactly matched (or with empty extra).\n if (section.path === \"\") {\n return pathname === sectionUrl || pathname === `${sectionUrl}/`;\n }\n const candidates = [section.path, ...(section.matchPrefixes ?? [])];\n return candidates.some((prefix) => {\n const url = joinBaseAndPath(basePath, prefix);\n return pathname === url || pathname.startsWith(`${url}/`);\n });\n}\n\n/** Org context switcher shown on the right side of the section nav. */\nconst OrgSwitcher: FC = () => {\n const { activeOrgId, setActiveOrgId } = useDevportal();\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 [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n const { data } = useGetMyOrganizationsQuery({ fetchPolicy: \"cache-first\" });\n const orgs: OrgItem[] = data?.myDeveloperOrganizations ?? [];\n\n // Auto-select when there's exactly one org and nothing is stored yet\n useEffect(() => {\n if (!activeOrgId && orgs.length === 1 && orgs[0]?.id) {\n setActiveOrgId(orgs[0].id);\n }\n }, [orgs, activeOrgId, setActiveOrgId]);\n\n // Close on outside click\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n if (open) document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n if (orgs.length === 0) return null;\n\n const activeOrg = orgs.find((o) => o.id === activeOrgId);\n const label = activeOrg?.name ?? tr(\"devportal.nav.selectOrg\", \"Select org\");\n\n return (\n <div ref={ref} className=\"relative flex-shrink-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors\",\n \"bg-card text-foreground border-border hover:bg-accent\",\n )}\n aria-label={tr(\"devportal.nav.switchOrg\", \"Switch organization\")}\n >\n <Building2 size={13} className=\"text-primary flex-shrink-0\" />\n <span className=\"max-w-[140px] truncate\">{label}</span>\n <ChevronDown\n size={13}\n className={cn(\"transition-transform\", open && \"rotate-180\")}\n />\n </button>\n\n {open && (\n <div className=\"absolute right-0 top-full z-50 mt-1 min-w-[200px] rounded-md border border-border bg-popover shadow-lg py-1\">\n {orgs.map((org) => (\n <button\n key={org.id}\n type=\"button\"\n onClick={() => {\n setActiveOrgId(org.id);\n setOpen(false);\n }}\n className={cn(\n \"flex w-full items-center gap-2 px-3 py-2 text-sm text-left transition-colors hover:bg-accent\",\n org.id === activeOrgId\n ? \"text-primary font-medium\"\n : \"text-foreground\",\n )}\n >\n <Check\n size={13}\n className={cn(\n \"flex-shrink-0\",\n org.id === activeOrgId\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <span className=\"truncate\">{org.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Horizontal section nav rendered above the page content on every devportal\n * route. Gives developers a one-click jump between all top-level sections so\n * routes like OAuth, Delegations, Analytics, Revenue, Docs, Resources,\n * Publisher Profile, and Settings are reachable without typing URLs.\n *\n * Renders nothing when `basePath` is undefined (standalone/dev mode) so it\n * doesn't conflict with whatever harness wraps the MFE there.\n */\nexport const SectionNav: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { pathname } = useLocation();\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\n if (!basePath || !navigate) return null;\n\n const handleClick = (path: string) => {\n navigate(joinBaseAndPath(basePath, path));\n };\n\n return (\n <nav\n aria-label={tr(\"devportal.nav.sections\", \"Developer portal sections\")}\n className=\"border-b border-border bg-card/40 px-4 py-2\"\n data-testid=\"devportal-section-nav\"\n >\n <div className=\"flex items-center gap-2\">\n <ul className=\"flex flex-1 flex-wrap gap-1\">\n {SECTIONS.map((section) => {\n const active = isSectionActive(pathname, basePath, section);\n const Icon = section.icon;\n return (\n <li key={section.path}>\n <button\n type=\"button\"\n onClick={() => handleClick(section.path)}\n aria-current={active ? \"page\" : undefined}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors\",\n active\n ? \"bg-primary text-primary-foreground\"\n : \"text-muted-foreground hover:bg-accent hover:text-foreground\",\n )}\n >\n <Icon size={14} />\n <span>{tr(section.i18nKey, section.fallback)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n <OrgSwitcher />\n </div>\n </nav>\n );\n};\n\n// Exported for unit tests that want to assert against the canonical list.\nexport const __SECTION_NAV_SECTIONS = SECTIONS;\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import "../../generated/global-operations.js";
2
1
  import { CombinedGraphQLErrors as e } from "../../node_modules/@apollo/client/errors/CombinedGraphQLErrors.js";
3
2
  import { ServerError as t } from "../../node_modules/@apollo/client/errors/ServerError.js";
4
3
  import { getMainDefinition as n } from "../../node_modules/@apollo/client/utilities/internal/getMainDefinition.js";
5
4
  import { GraphQLWsLink as r } from "../../node_modules/@apollo/client/link/subscriptions/index.js";
6
5
  import { createClient as i } from "../../node_modules/graphql-ws/dist/client.js";
6
+ import "../../generated/global-operations.js";
7
7
  import { ApolloClient as a, InMemoryCache as o, createHttpLink as s, from as c, split as l } from "@apollo/client/core";
8
8
  import { setContext as u } from "@apollo/client/link/context";
9
9
  import { onError as d } from "@apollo/client/link/error";
@@ -1,11 +1,11 @@
1
1
  import { useDevportal as e } from "../providers/DevportalProvider.js";
2
2
  import { EmptyState as t } from "../components/EmptyState.js";
3
- import { PageLayout as n, PageSection as r } from "../components/PageLayout.js";
4
- import { useApproveApplicationMutation as i, useGetApplicationsQuery as a, useRejectApplicationMutation as o } from "../../generated/global-operations.js";
5
- import { PermissionGuard as s } from "../components/PermissionGuard.js";
3
+ import { useApproveApplicationMutation as n, useGetApplicationsQuery as r, useRejectApplicationMutation as i } from "../../generated/global-operations.js";
4
+ import { getErrorMessage as a } from "../hooks/useGraphQL.js";
5
+ import { PageLayout as o, PageSection as s } from "../components/PageLayout.js";
6
+ import { PermissionGuard as c } from "../components/PermissionGuard.js";
6
7
  import "../components/index.js";
7
- import { DEVPORTAL_PERMISSIONS as c } from "../constants/permissions.js";
8
- import { getErrorMessage as l } from "../hooks/useGraphQL.js";
8
+ import { DEVPORTAL_PERMISSIONS as l } from "../constants/permissions.js";
9
9
  import { useDevportalPermission as u } from "../hooks/usePermission.js";
10
10
  import "../hooks/index.js";
11
11
  import { useState as d } from "react";
@@ -14,10 +14,10 @@ import { AlertCircle as p, CheckCircle as m, ChevronDown as h, ChevronUp as g, C
14
14
  import { jsx as S, jsxs as C } from "react/jsx-runtime";
15
15
  //#region src/devportal/pages/AdminReviewPage.tsx
16
16
  var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
17
- let { navigate: a, basePath: o } = e(), { t: s } = f(), l = (e, t) => {
17
+ let { navigate: a, basePath: o } = e(), { t: s } = f(), c = (e, t) => {
18
18
  let n = s(e);
19
19
  return n === e ? t : n;
20
- }, [p, _] = d(!1), [b, w] = d(""), T = u(c.APP_APPROVE), E = u(c.APP_REJECT);
20
+ }, [p, _] = d(!1), [b, w] = d(""), T = u(l.APP_APPROVE), E = u(l.APP_REJECT);
21
21
  return /* @__PURE__ */ C("div", {
22
22
  className: "rounded-lg border bg-card overflow-hidden",
23
23
  children: [/* @__PURE__ */ C("div", {
@@ -56,19 +56,19 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
56
56
  }),
57
57
  /* @__PURE__ */ S("p", {
58
58
  className: "text-sm text-muted-foreground truncate",
59
- children: t.shortDescription ?? t.description ?? l("devportal.noDescription", "No description")
59
+ children: t.shortDescription ?? t.description ?? c("devportal.noDescription", "No description")
60
60
  }),
61
61
  /* @__PURE__ */ C("p", {
62
62
  className: "text-xs text-muted-foreground mt-0.5",
63
63
  children: [
64
- l("devportal.submitted", "Submitted"),
64
+ c("devportal.submitted", "Submitted"),
65
65
  ":",
66
66
  " ",
67
67
  t.submittedAt ? new Date(t.submittedAt).toLocaleDateString(void 0, {
68
68
  year: "numeric",
69
69
  month: "short",
70
70
  day: "numeric"
71
- }) : l("devportal.unknown", "Unknown")
71
+ }) : c("devportal.unknown", "Unknown")
72
72
  ]
73
73
  })
74
74
  ]
@@ -78,12 +78,12 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
78
78
  children: [/* @__PURE__ */ C("button", {
79
79
  onClick: () => a?.(`${o}/apps/${t.id}`),
80
80
  className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-muted",
81
- title: l("devportal.viewAppDetails", "View app details"),
82
- children: [/* @__PURE__ */ S(v, { size: 14 }), l("devportal.view", "View")]
81
+ title: c("devportal.viewAppDetails", "View app details"),
82
+ children: [/* @__PURE__ */ S(v, { size: 14 }), c("devportal.view", "View")]
83
83
  }), /* @__PURE__ */ C("button", {
84
84
  onClick: () => _((e) => !e),
85
85
  className: "inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-muted",
86
- children: [S(p ? g : h, { size: 14 }), l("devportal.review", "Review")]
86
+ children: [S(p ? g : h, { size: 14 }), c("devportal.review", "Review")]
87
87
  })]
88
88
  })
89
89
  ]
@@ -94,7 +94,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
94
94
  className: "rounded-md border bg-background p-3",
95
95
  children: [/* @__PURE__ */ S("p", {
96
96
  className: "text-xs font-medium text-muted-foreground mb-1",
97
- children: l("devportal.developerNotes", "Developer Notes")
97
+ children: c("devportal.developerNotes", "Developer Notes")
98
98
  }), /* @__PURE__ */ S("p", {
99
99
  className: "text-sm",
100
100
  children: t.reviewNotes
@@ -106,7 +106,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
106
106
  /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("span", {
107
107
  className: "text-muted-foreground",
108
108
  children: [
109
- l("devportal.category", "Category"),
109
+ c("devportal.category", "Category"),
110
110
  ":",
111
111
  " "
112
112
  ]
@@ -114,7 +114,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
114
114
  /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("span", {
115
115
  className: "text-muted-foreground",
116
116
  children: [
117
- l("devportal.pricing", "Pricing"),
117
+ c("devportal.pricing", "Pricing"),
118
118
  ":",
119
119
  " "
120
120
  ]
@@ -122,7 +122,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
122
122
  /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("span", {
123
123
  className: "text-muted-foreground",
124
124
  children: [
125
- l("devportal.website", "Website"),
125
+ c("devportal.website", "Website"),
126
126
  ":",
127
127
  " "
128
128
  ]
@@ -131,12 +131,12 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
131
131
  target: "_blank",
132
132
  rel: "noopener noreferrer",
133
133
  className: "text-primary underline hover:no-underline",
134
- children: l("devportal.link", "Link")
134
+ children: c("devportal.link", "Link")
135
135
  }) : /* @__PURE__ */ S("span", { children: "—" })] }),
136
136
  /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("span", {
137
137
  className: "text-muted-foreground",
138
138
  children: [
139
- l("devportal.privacyPolicy", "Privacy Policy"),
139
+ c("devportal.privacyPolicy", "Privacy Policy"),
140
140
  ":",
141
141
  " "
142
142
  ]
@@ -145,20 +145,20 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
145
145
  target: "_blank",
146
146
  rel: "noopener noreferrer",
147
147
  className: "text-primary underline hover:no-underline",
148
- children: l("devportal.link", "Link")
148
+ children: c("devportal.link", "Link")
149
149
  }) : /* @__PURE__ */ S("span", {
150
150
  className: "text-status-error-text",
151
- children: l("devportal.missing", "Missing")
151
+ children: c("devportal.missing", "Missing")
152
152
  })] })
153
153
  ]
154
154
  }),
155
155
  /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("label", {
156
156
  className: "text-sm font-medium",
157
- children: l("devportal.reviewNotes", "Review Notes")
157
+ children: c("devportal.reviewNotes", "Review Notes")
158
158
  }), /* @__PURE__ */ S("textarea", {
159
159
  value: b,
160
160
  onChange: (e) => w(e.target.value),
161
- placeholder: l("devportal.reviewNotesPlaceholder", "Add feedback for the developer (required for rejection)..."),
161
+ placeholder: c("devportal.reviewNotesPlaceholder", "Add feedback for the developer (required for rejection)..."),
162
162
  rows: 3,
163
163
  className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring resize-none"
164
164
  })] }),
@@ -168,7 +168,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
168
168
  onClick: () => n(t.id, b),
169
169
  disabled: i || !T.allowed,
170
170
  "aria-disabled": i || !T.allowed,
171
- title: T.allowed ? void 0 : l("devportal.common.noPermission", "You do not have permission to perform this action"),
171
+ title: T.allowed ? void 0 : c("devportal.common.noPermission", "You do not have permission to perform this action"),
172
172
  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",
173
173
  children: [i ? /* @__PURE__ */ S(y, {
174
174
  size: 14,
@@ -177,13 +177,13 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
177
177
  }) : /* @__PURE__ */ S(m, {
178
178
  size: 14,
179
179
  "aria-hidden": "true"
180
- }), l("devportal.approve", "Approve")]
180
+ }), c("devportal.approve", "Approve")]
181
181
  }), /* @__PURE__ */ C("button", {
182
182
  onClick: () => r(t.id, b),
183
183
  disabled: i || !b.trim() || !E.allowed,
184
184
  "aria-disabled": i || !b.trim() || !E.allowed,
185
185
  className: "inline-flex items-center gap-2 rounded-md bg-destructive px-4 py-2 text-sm font-medium text-destructive-foreground hover:bg-destructive/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
186
- title: E.allowed ? b.trim() ? void 0 : l("devportal.notesRequiredForRejection", "Notes required for rejection") : l("devportal.common.noPermission", "You do not have permission to perform this action"),
186
+ title: E.allowed ? b.trim() ? void 0 : c("devportal.notesRequiredForRejection", "Notes required for rejection") : c("devportal.common.noPermission", "You do not have permission to perform this action"),
187
187
  children: [i ? /* @__PURE__ */ S(y, {
188
188
  size: 14,
189
189
  className: "animate-spin",
@@ -191,7 +191,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
191
191
  }) : /* @__PURE__ */ S(x, {
192
192
  size: 14,
193
193
  "aria-hidden": "true"
194
- }), l("devportal.reject", "Reject")]
194
+ }), c("devportal.reject", "Reject")]
195
195
  })]
196
196
  })
197
197
  ]
@@ -204,13 +204,13 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
204
204
  }, [h, g] = d(""), [v, x] = d(/* @__PURE__ */ new Set()), [T, E] = d(null), [D, O] = d(null), k = (e) => x((t) => new Set(t).add(e)), A = (e) => x((t) => {
205
205
  let n = new Set(t);
206
206
  return n.delete(e), n;
207
- }), { data: j, loading: M, error: N, refetch: P } = a({
207
+ }), { data: j, loading: M, error: N, refetch: P } = r({
208
208
  variables: {
209
209
  status: "SUBMITTED",
210
210
  limit: 100
211
211
  },
212
212
  fetchPolicy: "cache-and-network"
213
- }), [F] = i(), [I] = o(), L = j?.applications?.edges?.map((e) => e.node) ?? [], R = h ? L.filter((e) => e.name.toLowerCase().includes(h.toLowerCase()) || (e.shortDescription ?? "").toLowerCase().includes(h.toLowerCase())) : L, z = async (e, t) => {
213
+ }), [F] = n(), [I] = i(), L = j?.applications?.edges?.map((e) => e.node) ?? [], R = h ? L.filter((e) => e.name.toLowerCase().includes(h.toLowerCase()) || (e.shortDescription ?? "").toLowerCase().includes(h.toLowerCase())) : L, z = async (e, t) => {
214
214
  k(e), E(null), O(null);
215
215
  try {
216
216
  let n = await F({ variables: {
@@ -241,14 +241,14 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
241
241
  }
242
242
  }
243
243
  };
244
- return M && !j ? /* @__PURE__ */ S(n, {
244
+ return M && !j ? /* @__PURE__ */ S(o, {
245
245
  title: u("devportal.appReviewQueue", "App Review Queue"),
246
246
  description: u("devportal.appReviewQueueDescription", "Review submitted applications for approval"),
247
247
  children: /* @__PURE__ */ S("div", {
248
248
  className: "flex items-center justify-center py-12",
249
249
  children: /* @__PURE__ */ S(y, { className: "h-8 w-8 animate-spin text-muted-foreground" })
250
250
  })
251
- }) : N ? /* @__PURE__ */ S(n, {
251
+ }) : N ? /* @__PURE__ */ S(o, {
252
252
  title: u("devportal.appReviewQueue", "App Review Queue"),
253
253
  description: u("devportal.appReviewQueueDescription", "Review submitted applications for approval"),
254
254
  children: /* @__PURE__ */ C("div", {
@@ -257,7 +257,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
257
257
  /* @__PURE__ */ S(p, { className: "mx-auto h-8 w-8 text-destructive" }),
258
258
  /* @__PURE__ */ S("p", {
259
259
  className: "mt-2 text-sm text-muted-foreground",
260
- children: l(N)
260
+ children: a(N)
261
261
  }),
262
262
  /* @__PURE__ */ S("button", {
263
263
  onClick: () => P(),
@@ -266,9 +266,9 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
266
266
  })
267
267
  ]
268
268
  })
269
- }) : /* @__PURE__ */ S(s, {
270
- permission: c.REVIEW_MANAGE,
271
- children: /* @__PURE__ */ C(n, {
269
+ }) : /* @__PURE__ */ S(c, {
270
+ permission: l.REVIEW_MANAGE,
271
+ children: /* @__PURE__ */ C(o, {
272
272
  title: u("devportal.appReviewQueue", "App Review Queue"),
273
273
  description: u("devportal.appReviewQueueFullDescription", "Review submitted applications for approval or rejection"),
274
274
  actions: /* @__PURE__ */ S("button", {
@@ -321,7 +321,7 @@ var w = ({ app: t, onApprove: n, onReject: r, processing: i }) => {
321
321
  className: "w-full rounded-md border bg-background pl-9 pr-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
322
322
  })]
323
323
  }),
324
- /* @__PURE__ */ S(r, { children: R.length === 0 ? /* @__PURE__ */ S(t, {
324
+ /* @__PURE__ */ S(s, { children: R.length === 0 ? /* @__PURE__ */ S(t, {
325
325
  icon: /* @__PURE__ */ S(m, { size: 32 }),
326
326
  title: u("devportal.noAppsPendingReview", "No apps pending review"),
327
327
  description: h ? u("devportal.noAppsMatchSearch", "No apps match your search") : u("devportal.allApplicationsReviewed", "All submitted applications have been reviewed")