@burdenoff/microfe-devportal 2026.830.1 → 2026.831.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.
- package/dist/devportal/AdminDevportalRoot.d.ts.map +1 -1
- package/dist/devportal/AdminDevportalRoot.js +16 -19
- package/dist/devportal/AdminDevportalRoot.js.map +1 -1
- package/dist/devportal/DevportalRoot.d.ts.map +1 -1
- package/dist/devportal/DevportalRoot.js +36 -39
- package/dist/devportal/DevportalRoot.js.map +1 -1
- package/dist/devportal/components/AppCard.js +41 -41
- package/dist/devportal/components/ConfirmDialog.d.ts.map +1 -1
- package/dist/devportal/components/ConfirmDialog.js +19 -22
- package/dist/devportal/components/ConfirmDialog.js.map +1 -1
- package/dist/devportal/components/DataTable.d.ts.map +1 -1
- package/dist/devportal/components/DataTable.js +31 -34
- package/dist/devportal/components/DataTable.js.map +1 -1
- package/dist/devportal/components/FeatureFlaggedRoute.js +8 -8
- package/dist/devportal/components/FormField.d.ts.map +1 -1
- package/dist/devportal/components/FormField.js +26 -32
- package/dist/devportal/components/FormField.js.map +1 -1
- package/dist/devportal/components/GrantDelegationModal.js +64 -64
- package/dist/devportal/components/GrantDelegationModal.js.map +1 -1
- package/dist/devportal/components/LoadingState.d.ts.map +1 -1
- package/dist/devportal/components/LoadingState.js +5 -8
- package/dist/devportal/components/LoadingState.js.map +1 -1
- package/dist/devportal/components/PageLayout.d.ts.map +1 -1
- package/dist/devportal/components/PageLayout.js +10 -13
- package/dist/devportal/components/PageLayout.js.map +1 -1
- package/dist/devportal/components/PermissionGuard.d.ts.map +1 -1
- package/dist/devportal/components/PermissionGuard.js +11 -14
- package/dist/devportal/components/PermissionGuard.js.map +1 -1
- package/dist/devportal/components/SecretDisplay.d.ts.map +1 -1
- package/dist/devportal/components/SecretDisplay.js +24 -30
- package/dist/devportal/components/SecretDisplay.js.map +1 -1
- package/dist/devportal/components/SectionNav.d.ts.map +1 -1
- package/dist/devportal/components/SectionNav.js +24 -27
- package/dist/devportal/components/SectionNav.js.map +1 -1
- package/dist/devportal/components/StatusBadge.d.ts.map +1 -1
- package/dist/devportal/components/StatusBadge.js +24 -33
- package/dist/devportal/components/StatusBadge.js.map +1 -1
- package/dist/devportal/index.d.ts +1 -0
- package/dist/devportal/index.d.ts.map +1 -1
- package/dist/devportal/index.js +1 -0
- package/dist/devportal/pages/AdminReviewPage.js +172 -172
- package/dist/devportal/pages/AnalyticsDashboardPage.js +43 -43
- package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
- package/dist/devportal/pages/ApiKeysPage.js +119 -119
- package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
- package/dist/devportal/pages/AppLogsPage.js +45 -45
- package/dist/devportal/pages/ApplicationDetailPage.js +607 -607
- package/dist/devportal/pages/ApplicationVersionsPage.js +13 -13
- package/dist/devportal/pages/ApplicationsPage.d.ts.map +1 -1
- package/dist/devportal/pages/ApplicationsPage.js +104 -101
- package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
- package/dist/devportal/pages/CreateApiKeyPage.js +45 -45
- package/dist/devportal/pages/CreateApplicationPage.js +38 -38
- package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
- package/dist/devportal/pages/CreateOAuthClientPage.js +52 -52
- package/dist/devportal/pages/CreateOrganizationPage.js +26 -26
- package/dist/devportal/pages/CreateWebhookPage.d.ts.map +1 -1
- package/dist/devportal/pages/CreateWebhookPage.js +48 -48
- package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
- package/dist/devportal/pages/DashboardPage.d.ts.map +1 -1
- package/dist/devportal/pages/DashboardPage.js +66 -72
- package/dist/devportal/pages/DashboardPage.js.map +1 -1
- package/dist/devportal/pages/DelegationsPage.js +174 -174
- package/dist/devportal/pages/DocumentationPage.js +93 -93
- package/dist/devportal/pages/EditApplicationPage.js +14 -14
- package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
- package/dist/devportal/pages/ListingPreviewPage.js +76 -76
- package/dist/devportal/pages/OAuthClientDetailPage.js +75 -75
- package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js +64 -64
- package/dist/devportal/pages/OrganizationDetailPage.js +189 -189
- package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js +10 -10
- package/dist/devportal/pages/OrganizationsPage.d.ts.map +1 -1
- package/dist/devportal/pages/OrganizationsPage.js +163 -154
- package/dist/devportal/pages/OrganizationsPage.js.map +1 -1
- package/dist/devportal/pages/PublishPage.js +104 -104
- package/dist/devportal/pages/PublishPage.js.map +1 -1
- package/dist/devportal/pages/PublisherProfilePage.js +55 -55
- package/dist/devportal/pages/ResourcesPage.js +60 -60
- package/dist/devportal/pages/RevenueDashboardPage.js +60 -60
- package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.js +83 -83
- package/dist/devportal/pages/SellerItemsPage.js +163 -163
- package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
- package/dist/devportal/pages/SellerOrdersPage.js +63 -63
- package/dist/devportal/pages/SettingsPage.js +21 -21
- package/dist/devportal/pages/SetupPage.js +183 -183
- package/dist/devportal/pages/SetupPage.js.map +1 -1
- package/dist/devportal/pages/StoreSubmissionPage.js +5 -5
- package/dist/devportal/pages/WebhookDetailPage.js +123 -123
- package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
- package/dist/devportal/pages/WebhooksPage.js +118 -118
- package/dist/devportal/pages/WebhooksPage.js.map +1 -1
- package/dist/devportal/utils/i18n.d.ts +9 -2
- package/dist/devportal/utils/i18n.d.ts.map +1 -1
- package/dist/devportal/utils/i18n.js +13 -10
- package/dist/devportal/utils/i18n.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/translations/en.d.ts +1251 -0
- package/dist/translations/en.d.ts.map +1 -0
- package/dist/translations/en.js +1235 -0
- package/dist/translations/en.js.map +1 -0
- package/package.json +2 -2
|
@@ -4,22 +4,22 @@ import { useDeactivateAppMutation as n, useGetAuthAppQuery as r, useRotateAppSec
|
|
|
4
4
|
import { getErrorMessage as ee } from "../hooks/useGraphQL.js";
|
|
5
5
|
import { PageLayout as o } from "../components/PageLayout.js";
|
|
6
6
|
import { ActiveIndicator as te } from "../components/StatusBadge.js";
|
|
7
|
-
import { nativeCopyText as
|
|
8
|
-
import { PermissionGuard as
|
|
7
|
+
import { nativeCopyText as ne, nativeImpact as s, nativeNotify as c } from "../../utils/nativeBridge.js";
|
|
8
|
+
import { PermissionGuard as re } from "../components/PermissionGuard.js";
|
|
9
9
|
import "../components/index.js";
|
|
10
10
|
import "../hooks/index.js";
|
|
11
|
-
import { useState as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
11
|
+
import { useState as l } from "react";
|
|
12
|
+
import { AlertCircle as ie, ArrowLeft as ae, Copy as u, Eye as d, EyeOff as f, Loader2 as p, RefreshCw as m, Trash2 as h } from "lucide-react";
|
|
13
|
+
import { useParams as g } from "react-router";
|
|
14
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
15
|
+
import { useI18n as y } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
16
16
|
import { AlertDialog as b, AlertDialogAction as x, AlertDialogCancel as S, AlertDialogContent as C, AlertDialogDescription as w, AlertDialogFooter as T, AlertDialogHeader as E, AlertDialogTitle as D, CTAOverflowMenu as O, GlassCard as k } from "@burdenoff/fe-libs/ui";
|
|
17
17
|
//#region src/devportal/pages/OAuthClientDetailPage.tsx
|
|
18
18
|
var A = () => {
|
|
19
|
-
let { clientId: A } =
|
|
19
|
+
let { clientId: A } = g(), { navigate: j, basePath: M } = e(), { t: N } = y(), P = (e, t) => {
|
|
20
20
|
let n = N(e);
|
|
21
21
|
return n === e ? t : n;
|
|
22
|
-
}, [F, I] =
|
|
22
|
+
}, [F, I] = l(!1), [L, R] = l(null), [z, B] = l(!1), [V, H] = l(!1), { data: U, loading: W, error: G, refetch: K } = r({
|
|
23
23
|
variables: { id: A || "" },
|
|
24
24
|
skip: !A,
|
|
25
25
|
fetchPolicy: "cache-and-network"
|
|
@@ -39,7 +39,7 @@ var A = () => {
|
|
|
39
39
|
} : null, Q = (e) => {
|
|
40
40
|
j?.(`${M}${e}`);
|
|
41
41
|
}, $ = async (e) => {
|
|
42
|
-
|
|
42
|
+
s("light"), c(await ne(e) ? "success" : "error");
|
|
43
43
|
}, se = async () => {
|
|
44
44
|
if (A) try {
|
|
45
45
|
let e = (await q({ variables: { id: A } })).data?.rotateAppSecret?.clientSecret;
|
|
@@ -50,48 +50,48 @@ var A = () => {
|
|
|
50
50
|
await Y({ variables: { id: A } }), B(!1), Q("/oauth");
|
|
51
51
|
} catch {}
|
|
52
52
|
};
|
|
53
|
-
return W && !U ? /* @__PURE__ */
|
|
53
|
+
return W && !U ? /* @__PURE__ */ _(o, {
|
|
54
54
|
title: P("devportal.appDetails", "App Details"),
|
|
55
55
|
description: P("devportal.loadingDots", "Loading..."),
|
|
56
56
|
backLink: "/oauth",
|
|
57
57
|
backLabel: P("devportal.backToApps", "Back to Apps"),
|
|
58
|
-
children: /* @__PURE__ */
|
|
58
|
+
children: /* @__PURE__ */ _("div", {
|
|
59
59
|
className: "flex items-center justify-center py-12",
|
|
60
|
-
children: /* @__PURE__ */
|
|
60
|
+
children: /* @__PURE__ */ _(p, { className: "h-8 w-8 animate-spin text-text-secondary" })
|
|
61
61
|
})
|
|
62
|
-
}) : G || !Z ? /* @__PURE__ */
|
|
62
|
+
}) : G || !Z ? /* @__PURE__ */ _(o, {
|
|
63
63
|
title: P("devportal.appDetails", "App Details"),
|
|
64
64
|
description: P("devportal.failedToLoad", "Failed to load"),
|
|
65
65
|
backLink: "/oauth",
|
|
66
66
|
backLabel: P("devportal.backToApps", "Back to Apps"),
|
|
67
|
-
children: /* @__PURE__ */
|
|
67
|
+
children: /* @__PURE__ */ v("div", {
|
|
68
68
|
className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
|
|
69
69
|
children: [
|
|
70
|
-
/* @__PURE__ */
|
|
71
|
-
/* @__PURE__ */
|
|
70
|
+
/* @__PURE__ */ _(ie, { className: "mx-auto h-8 w-8 text-status-error-text" }),
|
|
71
|
+
/* @__PURE__ */ _("h3", {
|
|
72
72
|
className: "mt-2 font-medium text-status-error-text",
|
|
73
73
|
children: G ? P("devportal.failedToLoadApp", "Failed to load app") : P("devportal.appNotFound", "App not found")
|
|
74
74
|
}),
|
|
75
|
-
G && /* @__PURE__ */
|
|
75
|
+
G && /* @__PURE__ */ _("p", {
|
|
76
76
|
className: "mt-1 text-sm text-text-secondary",
|
|
77
77
|
children: ee(G)
|
|
78
78
|
}),
|
|
79
|
-
/* @__PURE__ */
|
|
79
|
+
/* @__PURE__ */ v("button", {
|
|
80
80
|
onClick: () => Q("/oauth"),
|
|
81
81
|
className: "mt-4 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",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
82
|
+
children: [/* @__PURE__ */ _(ae, { size: 16 }), P("devportal.backToApps", "Back to Apps")]
|
|
83
83
|
})
|
|
84
84
|
]
|
|
85
85
|
})
|
|
86
|
-
}) : /* @__PURE__ */
|
|
86
|
+
}) : /* @__PURE__ */ _(re, {
|
|
87
87
|
authOnly: !0,
|
|
88
|
-
children: /* @__PURE__ */
|
|
88
|
+
children: /* @__PURE__ */ v(o, {
|
|
89
89
|
title: Z.name,
|
|
90
90
|
description: Z.description || P("devportal.oauthAppDetailsAndCredentials", "OAuth App details and credentials"),
|
|
91
91
|
purpose: P("devportal.oauthAppDetailPurpose", "These are this OAuth app's credentials and the scopes it may request. Copy the client ID for your integration, rotate the secret if it leaks, and keep scopes minimal so users only grant what the app truly needs."),
|
|
92
92
|
backLink: "/oauth",
|
|
93
93
|
backLabel: P("devportal.backToApps", "Back to Apps"),
|
|
94
|
-
actions: /* @__PURE__ */
|
|
94
|
+
actions: /* @__PURE__ */ _(O, {
|
|
95
95
|
primary: {
|
|
96
96
|
label: Z.status === "ACTIVE" ? P("devportal.deactivate", "Deactivate") : P("devportal.activate", "Activate"),
|
|
97
97
|
onSelect: async () => {
|
|
@@ -107,109 +107,109 @@ var A = () => {
|
|
|
107
107
|
},
|
|
108
108
|
actions: [{
|
|
109
109
|
label: P("devportal.delete", "Delete"),
|
|
110
|
-
icon: /* @__PURE__ */
|
|
110
|
+
icon: /* @__PURE__ */ _(h, { size: 16 }),
|
|
111
111
|
intent: "destructive",
|
|
112
112
|
onSelect: () => B(!0)
|
|
113
113
|
}]
|
|
114
114
|
}),
|
|
115
115
|
children: [
|
|
116
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ v("div", {
|
|
117
117
|
className: "grid gap-6 md:grid-cols-2",
|
|
118
|
-
children: [/* @__PURE__ */
|
|
118
|
+
children: [/* @__PURE__ */ v("div", {
|
|
119
119
|
className: "rounded-card border border-border-seam bg-bg-surface p-6",
|
|
120
|
-
children: [/* @__PURE__ */
|
|
120
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
121
121
|
className: "text-sm font-medium text-text-secondary mb-4",
|
|
122
122
|
children: P("devportal.statusAndConfiguration", "Status & Configuration")
|
|
123
|
-
}), /* @__PURE__ */
|
|
123
|
+
}), /* @__PURE__ */ v("div", {
|
|
124
124
|
className: "space-y-3",
|
|
125
125
|
children: [
|
|
126
|
-
/* @__PURE__ */
|
|
126
|
+
/* @__PURE__ */ v("div", {
|
|
127
127
|
className: "flex justify-between",
|
|
128
|
-
children: [/* @__PURE__ */
|
|
128
|
+
children: [/* @__PURE__ */ _("span", {
|
|
129
129
|
className: "text-sm text-text-secondary",
|
|
130
130
|
children: P("devportal.status", "Status")
|
|
131
|
-
}), /* @__PURE__ */
|
|
131
|
+
}), /* @__PURE__ */ v("div", {
|
|
132
132
|
className: "flex items-center gap-2",
|
|
133
|
-
children: [/* @__PURE__ */
|
|
133
|
+
children: [/* @__PURE__ */ _(te, { active: Z.status === "ACTIVE" }), /* @__PURE__ */ _("span", {
|
|
134
134
|
className: "text-sm font-medium",
|
|
135
135
|
children: Z.status
|
|
136
136
|
})]
|
|
137
137
|
})]
|
|
138
138
|
}),
|
|
139
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ v("div", {
|
|
140
140
|
className: "flex justify-between",
|
|
141
|
-
children: [/* @__PURE__ */
|
|
141
|
+
children: [/* @__PURE__ */ _("span", {
|
|
142
142
|
className: "text-sm text-text-secondary",
|
|
143
143
|
children: P("devportal.type", "Type")
|
|
144
|
-
}), /* @__PURE__ */
|
|
144
|
+
}), /* @__PURE__ */ _("span", {
|
|
145
145
|
className: t("rounded px-2 py-0.5 text-xs font-medium", Z.type === "SERVICE" ? "bg-accent-purple-subtle text-accent-purple" : Z.type === "INTEGRATION" || Z.type === "API_INTEGRATION" ? "bg-status-info-bg-subtle text-status-info-text" : "bg-status-success-bg-subtle text-status-success-text"),
|
|
146
146
|
children: Z.type
|
|
147
147
|
})]
|
|
148
148
|
}),
|
|
149
|
-
/* @__PURE__ */
|
|
149
|
+
/* @__PURE__ */ v("div", {
|
|
150
150
|
className: "flex justify-between",
|
|
151
|
-
children: [/* @__PURE__ */
|
|
151
|
+
children: [/* @__PURE__ */ _("span", {
|
|
152
152
|
className: "text-sm text-text-secondary",
|
|
153
153
|
children: P("devportal.created", "Created")
|
|
154
|
-
}), /* @__PURE__ */
|
|
154
|
+
}), /* @__PURE__ */ _("span", {
|
|
155
155
|
className: "text-sm",
|
|
156
156
|
children: new Date(Z.createdAt).toLocaleDateString()
|
|
157
157
|
})]
|
|
158
158
|
})
|
|
159
159
|
]
|
|
160
160
|
})]
|
|
161
|
-
}), /* @__PURE__ */
|
|
161
|
+
}), /* @__PURE__ */ v(k, {
|
|
162
162
|
treatment: "glass",
|
|
163
163
|
glow: !0,
|
|
164
164
|
className: "p-6",
|
|
165
|
-
children: [/* @__PURE__ */
|
|
165
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
166
166
|
className: "text-sm font-medium text-text-secondary mb-4",
|
|
167
167
|
children: P("devportal.credentials", "Credentials")
|
|
168
|
-
}), /* @__PURE__ */
|
|
168
|
+
}), /* @__PURE__ */ v("div", {
|
|
169
169
|
className: "space-y-3",
|
|
170
170
|
children: [
|
|
171
|
-
/* @__PURE__ */
|
|
171
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
172
172
|
className: "text-xs text-text-secondary",
|
|
173
173
|
children: P("devportal.clientId", "Client ID")
|
|
174
|
-
}), /* @__PURE__ */
|
|
174
|
+
}), /* @__PURE__ */ v("div", {
|
|
175
175
|
className: "mt-1 flex items-center gap-2",
|
|
176
|
-
children: [/* @__PURE__ */
|
|
176
|
+
children: [/* @__PURE__ */ _("code", {
|
|
177
177
|
className: "flex-1 rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono",
|
|
178
178
|
children: Z.clientId
|
|
179
|
-
}), /* @__PURE__ */
|
|
179
|
+
}), /* @__PURE__ */ _("button", {
|
|
180
180
|
onClick: () => $(Z.clientId),
|
|
181
181
|
className: "rounded p-1.5 hover:bg-bg-sunken transition-colors",
|
|
182
182
|
title: "Copy",
|
|
183
|
-
children: /* @__PURE__ */
|
|
183
|
+
children: /* @__PURE__ */ _(u, { size: 14 })
|
|
184
184
|
})]
|
|
185
185
|
})] }),
|
|
186
|
-
L && /* @__PURE__ */
|
|
186
|
+
L && /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
187
187
|
className: "text-xs text-status-error-text font-medium",
|
|
188
188
|
children: P("devportal.newClientSecretShownOnce", "New Client Secret (shown only once!)")
|
|
189
|
-
}), /* @__PURE__ */
|
|
189
|
+
}), /* @__PURE__ */ v("div", {
|
|
190
190
|
className: "mt-1 flex items-center gap-2",
|
|
191
191
|
children: [
|
|
192
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ _("code", {
|
|
193
193
|
className: "flex-1 rounded bg-status-error-bg/10 border border-status-error-border/30 px-3 py-1.5 text-sm font-mono",
|
|
194
194
|
children: F ? L : "••••••••••••••••"
|
|
195
195
|
}),
|
|
196
|
-
/* @__PURE__ */
|
|
196
|
+
/* @__PURE__ */ _("button", {
|
|
197
197
|
onClick: () => I(!F),
|
|
198
198
|
className: "rounded p-1.5 hover:bg-bg-sunken transition-colors",
|
|
199
|
-
children:
|
|
199
|
+
children: _(F ? f : d, { size: 14 })
|
|
200
200
|
}),
|
|
201
|
-
/* @__PURE__ */
|
|
201
|
+
/* @__PURE__ */ _("button", {
|
|
202
202
|
onClick: () => $(L),
|
|
203
203
|
className: "rounded p-1.5 hover:bg-bg-sunken transition-colors",
|
|
204
|
-
children: /* @__PURE__ */
|
|
204
|
+
children: /* @__PURE__ */ _(u, { size: 14 })
|
|
205
205
|
})
|
|
206
206
|
]
|
|
207
207
|
})] }),
|
|
208
|
-
/* @__PURE__ */
|
|
208
|
+
/* @__PURE__ */ v("button", {
|
|
209
209
|
onClick: () => H(!0),
|
|
210
210
|
disabled: J,
|
|
211
211
|
className: "mt-2 inline-flex items-center gap-2 rounded-md bg-status-warning-bg-subtle px-3 py-1.5 text-sm font-medium text-status-warning-text hover:bg-status-warning-bg-subtle transition-colors disabled:opacity-50",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
212
|
+
children: [/* @__PURE__ */ _(m, {
|
|
213
213
|
size: 14,
|
|
214
214
|
className: J ? "animate-spin" : ""
|
|
215
215
|
}), P("devportal.rotateSecret", "Rotate Secret")]
|
|
@@ -218,9 +218,9 @@ var A = () => {
|
|
|
218
218
|
})]
|
|
219
219
|
})]
|
|
220
220
|
}),
|
|
221
|
-
/* @__PURE__ */
|
|
221
|
+
/* @__PURE__ */ v("div", {
|
|
222
222
|
className: "rounded-card border border-border-seam bg-bg-surface p-6",
|
|
223
|
-
children: [/* @__PURE__ */
|
|
223
|
+
children: [/* @__PURE__ */ v("h3", {
|
|
224
224
|
className: "text-sm font-medium text-text-secondary mb-3",
|
|
225
225
|
children: [
|
|
226
226
|
P("devportal.scopes", "Scopes"),
|
|
@@ -228,20 +228,20 @@ var A = () => {
|
|
|
228
228
|
Z.scopes.length,
|
|
229
229
|
")"
|
|
230
230
|
]
|
|
231
|
-
}), Z.scopes.length > 0 ? /* @__PURE__ */
|
|
231
|
+
}), Z.scopes.length > 0 ? /* @__PURE__ */ _("div", {
|
|
232
232
|
className: "flex flex-wrap gap-2",
|
|
233
|
-
children: Z.scopes.map((e) => /* @__PURE__ */
|
|
233
|
+
children: Z.scopes.map((e) => /* @__PURE__ */ _("span", {
|
|
234
234
|
className: "rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary",
|
|
235
235
|
children: e
|
|
236
236
|
}, e))
|
|
237
|
-
}) : /* @__PURE__ */
|
|
237
|
+
}) : /* @__PURE__ */ _("p", {
|
|
238
238
|
className: "text-sm text-text-secondary",
|
|
239
239
|
children: P("devportal.noScopesConfigured", "No scopes configured")
|
|
240
240
|
})]
|
|
241
241
|
}),
|
|
242
|
-
/* @__PURE__ */
|
|
242
|
+
/* @__PURE__ */ v("div", {
|
|
243
243
|
className: "rounded-card border border-border-seam bg-bg-surface p-6",
|
|
244
|
-
children: [/* @__PURE__ */
|
|
244
|
+
children: [/* @__PURE__ */ v("h3", {
|
|
245
245
|
className: "text-sm font-medium text-text-secondary mb-3",
|
|
246
246
|
children: [
|
|
247
247
|
P("devportal.redirectUris", "Redirect URIs"),
|
|
@@ -249,31 +249,31 @@ var A = () => {
|
|
|
249
249
|
Z.redirectUris.length,
|
|
250
250
|
")"
|
|
251
251
|
]
|
|
252
|
-
}), Z.redirectUris.length > 0 ? /* @__PURE__ */
|
|
252
|
+
}), Z.redirectUris.length > 0 ? /* @__PURE__ */ _("div", {
|
|
253
253
|
className: "space-y-2",
|
|
254
|
-
children: Z.redirectUris.map((e) => /* @__PURE__ */
|
|
254
|
+
children: Z.redirectUris.map((e) => /* @__PURE__ */ v("div", {
|
|
255
255
|
className: "flex items-center gap-2",
|
|
256
|
-
children: [/* @__PURE__ */
|
|
256
|
+
children: [/* @__PURE__ */ _("code", {
|
|
257
257
|
className: "rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono",
|
|
258
258
|
children: e
|
|
259
|
-
}), /* @__PURE__ */
|
|
259
|
+
}), /* @__PURE__ */ _("button", {
|
|
260
260
|
onClick: () => $(e),
|
|
261
261
|
className: "rounded p-1 hover:bg-bg-sunken transition-colors",
|
|
262
|
-
children: /* @__PURE__ */
|
|
262
|
+
children: /* @__PURE__ */ _(u, { size: 12 })
|
|
263
263
|
})]
|
|
264
264
|
}, e))
|
|
265
|
-
}) : /* @__PURE__ */
|
|
265
|
+
}) : /* @__PURE__ */ _("p", {
|
|
266
266
|
className: "text-sm text-text-secondary",
|
|
267
267
|
children: P("devportal.noRedirectUrisConfigured", "No redirect URIs configured")
|
|
268
268
|
})]
|
|
269
269
|
}),
|
|
270
|
-
/* @__PURE__ */
|
|
270
|
+
/* @__PURE__ */ _(b, {
|
|
271
271
|
open: V,
|
|
272
272
|
onOpenChange: H,
|
|
273
|
-
children: /* @__PURE__ */
|
|
273
|
+
children: /* @__PURE__ */ v(C, { children: [/* @__PURE__ */ v(E, { children: [/* @__PURE__ */ _(D, { children: P("devportal.rotateClientSecretQuestion", "Rotate Client Secret?") }), /* @__PURE__ */ _(w, { children: P("devportal.rotateSecretWarning", "This will invalidate the current client secret. All integrations using the old secret will stop working immediately.") })] }), /* @__PURE__ */ v(T, { children: [/* @__PURE__ */ _(S, {
|
|
274
274
|
disabled: J,
|
|
275
275
|
children: P("devportal.cancel", "Cancel")
|
|
276
|
-
}), /* @__PURE__ */
|
|
276
|
+
}), /* @__PURE__ */ _(x, {
|
|
277
277
|
onClick: (e) => {
|
|
278
278
|
e.preventDefault(), se();
|
|
279
279
|
},
|
|
@@ -282,16 +282,16 @@ var A = () => {
|
|
|
282
282
|
children: J ? P("devportal.rotating", "Rotating...") : P("devportal.rotateSecret", "Rotate Secret")
|
|
283
283
|
})] })] })
|
|
284
284
|
}),
|
|
285
|
-
/* @__PURE__ */
|
|
285
|
+
/* @__PURE__ */ _(b, {
|
|
286
286
|
open: z,
|
|
287
287
|
onOpenChange: B,
|
|
288
|
-
children: /* @__PURE__ */
|
|
288
|
+
children: /* @__PURE__ */ v(C, { children: [/* @__PURE__ */ v(E, { children: [/* @__PURE__ */ _(D, {
|
|
289
289
|
className: "text-status-error-text",
|
|
290
290
|
children: P("devportal.deactivateAppQuestion", "Deactivate App?")
|
|
291
|
-
}), /* @__PURE__ */
|
|
291
|
+
}), /* @__PURE__ */ _(w, { children: P("devportal.deactivateAppWarning", "This will deactivate the app and revoke all tokens. This action cannot be undone easily.") })] }), /* @__PURE__ */ v(T, { children: [/* @__PURE__ */ _(S, {
|
|
292
292
|
disabled: X,
|
|
293
293
|
children: P("devportal.cancel", "Cancel")
|
|
294
|
-
}), /* @__PURE__ */
|
|
294
|
+
}), /* @__PURE__ */ _(x, {
|
|
295
295
|
onClick: (e) => {
|
|
296
296
|
e.preventDefault(), ce();
|
|
297
297
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OAuthClientDetailPage.js","names":[],"sources":["../../../src/devportal/pages/OAuthClientDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport {\n Copy,\n Eye,\n EyeOff,\n Loader2,\n AlertCircle,\n RefreshCw,\n Trash2,\n ArrowLeft,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n CTAOverflowMenu,\n GlassCard,\n} from \"@burdenoff/fe-libs/ui\";\nimport { useParams } from \"react-router\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { ActiveIndicator } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport type { AuthApp } from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport {\n nativeCopyText,\n nativeImpact,\n nativeNotify,\n} from \"../../utils/nativeBridge\";\nimport {\n useGetAuthAppQuery,\n useRotateAppSecretMutation,\n useDeactivateAppMutation,\n useUpdateAuthAppMutation,\n getErrorMessage,\n} from \"../hooks\";\n\n/**\n * OAuth App Detail page\n *\n * Shows details for an auth-svc App (replaces devportal-svc OAuthClient detail).\n * Supports secret rotation, deactivation, and status toggle.\n */\nexport const OAuthClientDetailPage: FC = () => {\n const { clientId: appId } = useParams<{ clientId: string }>();\n const { navigate, basePath } = 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 [showSecret, setShowSecret] = useState(false);\n const [newSecret, setNewSecret] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState(false);\n const [confirmRotate, setConfirmRotate] = useState(false);\n\n const { data, loading, error, refetch } = useGetAuthAppQuery({\n variables: { id: appId || \"\" },\n skip: !appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const [rotateSecret, { loading: rotating }] = useRotateAppSecretMutation();\n const [deactivateApp, { loading: deactivating }] = useDeactivateAppMutation();\n const [updateApp] = useUpdateAuthAppMutation();\n\n const app: AuthApp | null = data?.app\n ? {\n id: data.app.id,\n name: data.app.name,\n description: data.app.description ?? undefined,\n clientId: data.app.clientId,\n type: data.app.type as AuthApp[\"type\"],\n status: data.app.status as AuthApp[\"status\"],\n scopes: data.app.scopes ?? [],\n redirectUris: data.app.redirectUris ?? [],\n ownerUserId: data.app.ownerUserId,\n tenantId: data.app.tenantId,\n createdAt: data.app.createdAt,\n updatedAt: data.app.updatedAt,\n }\n : null;\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const handleCopy = async (text: string) => {\n void nativeImpact(\"light\");\n const ok = await nativeCopyText(text);\n void nativeNotify(ok ? \"success\" : \"error\");\n };\n\n const handleRotateSecret = async () => {\n if (!appId) return;\n try {\n const result = await rotateSecret({ variables: { id: appId } });\n const secret = result.data?.rotateAppSecret?.clientSecret;\n if (secret) {\n setNewSecret(secret);\n setShowSecret(true);\n }\n setConfirmRotate(false);\n refetch();\n } catch {\n // error handled by Apollo\n }\n };\n\n const handleDeactivate = async () => {\n if (!appId) return;\n try {\n await deactivateApp({ variables: { id: appId } });\n setConfirmDelete(false);\n handleNavigate(\"/oauth\");\n } catch {\n // error handled by Apollo\n }\n };\n\n const handleToggleStatus = async () => {\n if (!appId || !app) return;\n const newStatus = app.status === \"ACTIVE\" ? \"INACTIVE\" : \"ACTIVE\";\n try {\n await updateApp({\n variables: { id: appId, input: { status: newStatus } },\n });\n refetch();\n } catch {\n // error handled by Apollo\n }\n };\n\n if (loading && !data) {\n return (\n <PageLayout\n title={tr(\"devportal.appDetails\", \"App Details\")}\n description={tr(\"devportal.loadingDots\", \"Loading...\")}\n backLink=\"/oauth\"\n backLabel={tr(\"devportal.backToApps\", \"Back to Apps\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.appDetails\", \"App Details\")}\n description={tr(\"devportal.failedToLoad\", \"Failed to load\")}\n backLink=\"/oauth\"\n backLabel={tr(\"devportal.backToApps\", \"Back to Apps\")}\n >\n <div className=\"rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center\">\n <AlertCircle className=\"mx-auto h-8 w-8 text-status-error-text\" />\n <h3 className=\"mt-2 font-medium text-status-error-text\">\n {error\n ? tr(\"devportal.failedToLoadApp\", \"Failed to load app\")\n : tr(\"devportal.appNotFound\", \"App not found\")}\n </h3>\n {error && (\n <p className=\"mt-1 text-sm text-text-secondary\">\n {getErrorMessage(error)}\n </p>\n )}\n <button\n onClick={() => handleNavigate(\"/oauth\")}\n className=\"mt-4 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\"\n >\n <ArrowLeft size={16} />\n {tr(\"devportal.backToApps\", \"Back to Apps\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={app.name}\n description={\n app.description ||\n tr(\n \"devportal.oauthAppDetailsAndCredentials\",\n \"OAuth App details and credentials\",\n )\n }\n purpose={tr(\n \"devportal.oauthAppDetailPurpose\",\n \"These are this OAuth app's credentials and the scopes it may request. Copy the client ID for your integration, rotate the secret if it leaks, and keep scopes minimal so users only grant what the app truly needs.\",\n )}\n backLink=\"/oauth\"\n backLabel={tr(\"devportal.backToApps\", \"Back to Apps\")}\n actions={\n <CTAOverflowMenu\n primary={{\n label:\n app.status === \"ACTIVE\"\n ? tr(\"devportal.deactivate\", \"Deactivate\")\n : tr(\"devportal.activate\", \"Activate\"),\n onSelect: handleToggleStatus,\n }}\n actions={[\n {\n label: tr(\"devportal.delete\", \"Delete\"),\n icon: <Trash2 size={16} />,\n intent: \"destructive\",\n onSelect: () => setConfirmDelete(true),\n },\n ]}\n />\n }\n >\n {/* Status & Type */}\n <div className=\"grid gap-6 md:grid-cols-2\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-4\">\n {tr(\"devportal.statusAndConfiguration\", \"Status & Configuration\")}\n </h3>\n <div className=\"space-y-3\">\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr(\"devportal.status\", \"Status\")}\n </span>\n <div className=\"flex items-center gap-2\">\n <ActiveIndicator active={app.status === \"ACTIVE\"} />\n <span className=\"text-sm font-medium\">{app.status}</span>\n </div>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr(\"devportal.type\", \"Type\")}\n </span>\n <span\n className={cn(\n \"rounded px-2 py-0.5 text-xs font-medium\",\n app.type === \"SERVICE\"\n ? \"bg-accent-purple-subtle text-accent-purple\"\n : app.type === \"INTEGRATION\" ||\n app.type === \"API_INTEGRATION\"\n ? \"bg-status-info-bg-subtle text-status-info-text\"\n : \"bg-status-success-bg-subtle text-status-success-text\",\n )}\n >\n {app.type}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr(\"devportal.created\", \"Created\")}\n </span>\n <span className=\"text-sm\">\n {new Date(app.createdAt).toLocaleDateString()}\n </span>\n </div>\n </div>\n </div>\n\n {/* Credentials — primary emphasis zone */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-4\">\n {tr(\"devportal.credentials\", \"Credentials\")}\n </h3>\n <div className=\"space-y-3\">\n <div>\n <label className=\"text-xs text-text-secondary\">\n {tr(\"devportal.clientId\", \"Client ID\")}\n </label>\n <div className=\"mt-1 flex items-center gap-2\">\n <code className=\"flex-1 rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono\">\n {app.clientId}\n </code>\n <button\n onClick={() => handleCopy(app.clientId)}\n className=\"rounded p-1.5 hover:bg-bg-sunken transition-colors\"\n title=\"Copy\"\n >\n <Copy size={14} />\n </button>\n </div>\n </div>\n {newSecret && (\n <div>\n <label className=\"text-xs text-status-error-text font-medium\">\n {tr(\n \"devportal.newClientSecretShownOnce\",\n \"New Client Secret (shown only once!)\",\n )}\n </label>\n <div className=\"mt-1 flex items-center gap-2\">\n <code className=\"flex-1 rounded bg-status-error-bg/10 border border-status-error-border/30 px-3 py-1.5 text-sm font-mono\">\n {showSecret\n ? newSecret\n : \"\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\"}\n </code>\n <button\n onClick={() => setShowSecret(!showSecret)}\n className=\"rounded p-1.5 hover:bg-bg-sunken transition-colors\"\n >\n {showSecret ? <EyeOff size={14} /> : <Eye size={14} />}\n </button>\n <button\n onClick={() => handleCopy(newSecret)}\n className=\"rounded p-1.5 hover:bg-bg-sunken transition-colors\"\n >\n <Copy size={14} />\n </button>\n </div>\n </div>\n )}\n <button\n onClick={() => setConfirmRotate(true)}\n disabled={rotating}\n className=\"mt-2 inline-flex items-center gap-2 rounded-md bg-status-warning-bg-subtle px-3 py-1.5 text-sm font-medium text-status-warning-text hover:bg-status-warning-bg-subtle transition-colors disabled:opacity-50\"\n >\n <RefreshCw\n size={14}\n className={rotating ? \"animate-spin\" : \"\"}\n />\n {tr(\"devportal.rotateSecret\", \"Rotate Secret\")}\n </button>\n </div>\n </GlassCard>\n </div>\n\n {/* Scopes */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-3\">\n {tr(\"devportal.scopes\", \"Scopes\")} ({app.scopes.length})\n </h3>\n {app.scopes.length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {app.scopes.map((scope) => (\n <span\n key={scope}\n className=\"rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\"\n >\n {scope}\n </span>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.noScopesConfigured\", \"No scopes configured\")}\n </p>\n )}\n </div>\n\n {/* Redirect URIs */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-3\">\n {tr(\"devportal.redirectUris\", \"Redirect URIs\")} (\n {app.redirectUris.length})\n </h3>\n {app.redirectUris.length > 0 ? (\n <div className=\"space-y-2\">\n {app.redirectUris.map((uri) => (\n <div key={uri} className=\"flex items-center gap-2\">\n <code className=\"rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono\">\n {uri}\n </code>\n <button\n onClick={() => handleCopy(uri)}\n className=\"rounded p-1 hover:bg-bg-sunken transition-colors\"\n >\n <Copy size={12} />\n </button>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.noRedirectUrisConfigured\",\n \"No redirect URIs configured\",\n )}\n </p>\n )}\n </div>\n\n {/* Confirm Rotate Dialog */}\n <AlertDialog open={confirmRotate} onOpenChange={setConfirmRotate}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {tr(\n \"devportal.rotateClientSecretQuestion\",\n \"Rotate Client Secret?\",\n )}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tr(\n \"devportal.rotateSecretWarning\",\n \"This will invalidate the current client secret. All integrations using the old secret will stop working immediately.\",\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={rotating}>\n {tr(\"devportal.cancel\", \"Cancel\")}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={(e) => {\n e.preventDefault();\n void handleRotateSecret();\n }}\n disabled={rotating}\n className=\"bg-status-warning-bg text-white hover:bg-status-warning-bg/90\"\n >\n {rotating\n ? tr(\"devportal.rotating\", \"Rotating...\")\n : tr(\"devportal.rotateSecret\", \"Rotate Secret\")}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Confirm Deactivate Dialog */}\n <AlertDialog open={confirmDelete} onOpenChange={setConfirmDelete}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle className=\"text-status-error-text\">\n {tr(\"devportal.deactivateAppQuestion\", \"Deactivate App?\")}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tr(\n \"devportal.deactivateAppWarning\",\n \"This will deactivate the app and revoke all tokens. This action cannot be undone easily.\",\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={deactivating}>\n {tr(\"devportal.cancel\", \"Cancel\")}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={(e) => {\n e.preventDefault();\n void handleDeactivate();\n }}\n disabled={deactivating}\n className=\"bg-status-error-bg text-status-error-text hover:bg-status-error-bg/90\"\n >\n {deactivating\n ? tr(\"devportal.deactivating\", \"Deactivating...\")\n : tr(\"devportal.deactivate\", \"Deactivate\")}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OAuthClientDetailPage.js","names":[],"sources":["../../../src/devportal/pages/OAuthClientDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport {\n Copy,\n Eye,\n EyeOff,\n Loader2,\n AlertCircle,\n RefreshCw,\n Trash2,\n ArrowLeft,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n CTAOverflowMenu,\n GlassCard,\n} from \"@burdenoff/fe-libs/ui\";\nimport { useParams } from \"react-router\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { ActiveIndicator } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport type { AuthApp } from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport {\n nativeCopyText,\n nativeImpact,\n nativeNotify,\n} from \"../../utils/nativeBridge\";\nimport {\n useGetAuthAppQuery,\n useRotateAppSecretMutation,\n useDeactivateAppMutation,\n useUpdateAuthAppMutation,\n getErrorMessage,\n} from \"../hooks\";\n\n/**\n * OAuth App Detail page\n *\n * Shows details for an auth-svc App (replaces devportal-svc OAuthClient detail).\n * Supports secret rotation, deactivation, and status toggle.\n */\nexport const OAuthClientDetailPage: FC = () => {\n const { clientId: appId } = useParams<{ clientId: string }>();\n const { navigate, basePath } = 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 [showSecret, setShowSecret] = useState(false);\n const [newSecret, setNewSecret] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState(false);\n const [confirmRotate, setConfirmRotate] = useState(false);\n\n const { data, loading, error, refetch } = useGetAuthAppQuery({\n variables: { id: appId || \"\" },\n skip: !appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const [rotateSecret, { loading: rotating }] = useRotateAppSecretMutation();\n const [deactivateApp, { loading: deactivating }] = useDeactivateAppMutation();\n const [updateApp] = useUpdateAuthAppMutation();\n\n const app: AuthApp | null = data?.app\n ? {\n id: data.app.id,\n name: data.app.name,\n description: data.app.description ?? undefined,\n clientId: data.app.clientId,\n type: data.app.type as AuthApp[\"type\"],\n status: data.app.status as AuthApp[\"status\"],\n scopes: data.app.scopes ?? [],\n redirectUris: data.app.redirectUris ?? [],\n ownerUserId: data.app.ownerUserId,\n tenantId: data.app.tenantId,\n createdAt: data.app.createdAt,\n updatedAt: data.app.updatedAt,\n }\n : null;\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const handleCopy = async (text: string) => {\n void nativeImpact(\"light\");\n const ok = await nativeCopyText(text);\n void nativeNotify(ok ? \"success\" : \"error\");\n };\n\n const handleRotateSecret = async () => {\n if (!appId) return;\n try {\n const result = await rotateSecret({ variables: { id: appId } });\n const secret = result.data?.rotateAppSecret?.clientSecret;\n if (secret) {\n setNewSecret(secret);\n setShowSecret(true);\n }\n setConfirmRotate(false);\n refetch();\n } catch {\n // error handled by Apollo\n }\n };\n\n const handleDeactivate = async () => {\n if (!appId) return;\n try {\n await deactivateApp({ variables: { id: appId } });\n setConfirmDelete(false);\n handleNavigate(\"/oauth\");\n } catch {\n // error handled by Apollo\n }\n };\n\n const handleToggleStatus = async () => {\n if (!appId || !app) return;\n const newStatus = app.status === \"ACTIVE\" ? \"INACTIVE\" : \"ACTIVE\";\n try {\n await updateApp({\n variables: { id: appId, input: { status: newStatus } },\n });\n refetch();\n } catch {\n // error handled by Apollo\n }\n };\n\n if (loading && !data) {\n return (\n <PageLayout\n title={tr(\"devportal.appDetails\", \"App Details\")}\n description={tr(\"devportal.loadingDots\", \"Loading...\")}\n backLink=\"/oauth\"\n backLabel={tr(\"devportal.backToApps\", \"Back to Apps\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.appDetails\", \"App Details\")}\n description={tr(\"devportal.failedToLoad\", \"Failed to load\")}\n backLink=\"/oauth\"\n backLabel={tr(\"devportal.backToApps\", \"Back to Apps\")}\n >\n <div className=\"rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center\">\n <AlertCircle className=\"mx-auto h-8 w-8 text-status-error-text\" />\n <h3 className=\"mt-2 font-medium text-status-error-text\">\n {error\n ? tr(\"devportal.failedToLoadApp\", \"Failed to load app\")\n : tr(\"devportal.appNotFound\", \"App not found\")}\n </h3>\n {error && (\n <p className=\"mt-1 text-sm text-text-secondary\">\n {getErrorMessage(error)}\n </p>\n )}\n <button\n onClick={() => handleNavigate(\"/oauth\")}\n className=\"mt-4 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\"\n >\n <ArrowLeft size={16} />\n {tr(\"devportal.backToApps\", \"Back to Apps\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={app.name}\n description={\n app.description ||\n tr(\n \"devportal.oauthAppDetailsAndCredentials\",\n \"OAuth App details and credentials\",\n )\n }\n purpose={tr(\n \"devportal.oauthAppDetailPurpose\",\n \"These are this OAuth app's credentials and the scopes it may request. Copy the client ID for your integration, rotate the secret if it leaks, and keep scopes minimal so users only grant what the app truly needs.\",\n )}\n backLink=\"/oauth\"\n backLabel={tr(\"devportal.backToApps\", \"Back to Apps\")}\n actions={\n <CTAOverflowMenu\n primary={{\n label:\n app.status === \"ACTIVE\"\n ? tr(\"devportal.deactivate\", \"Deactivate\")\n : tr(\"devportal.activate\", \"Activate\"),\n onSelect: handleToggleStatus,\n }}\n actions={[\n {\n label: tr(\"devportal.delete\", \"Delete\"),\n icon: <Trash2 size={16} />,\n intent: \"destructive\",\n onSelect: () => setConfirmDelete(true),\n },\n ]}\n />\n }\n >\n {/* Status & Type */}\n <div className=\"grid gap-6 md:grid-cols-2\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-4\">\n {tr(\"devportal.statusAndConfiguration\", \"Status & Configuration\")}\n </h3>\n <div className=\"space-y-3\">\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr(\"devportal.status\", \"Status\")}\n </span>\n <div className=\"flex items-center gap-2\">\n <ActiveIndicator active={app.status === \"ACTIVE\"} />\n <span className=\"text-sm font-medium\">{app.status}</span>\n </div>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr(\"devportal.type\", \"Type\")}\n </span>\n <span\n className={cn(\n \"rounded px-2 py-0.5 text-xs font-medium\",\n app.type === \"SERVICE\"\n ? \"bg-accent-purple-subtle text-accent-purple\"\n : app.type === \"INTEGRATION\" ||\n app.type === \"API_INTEGRATION\"\n ? \"bg-status-info-bg-subtle text-status-info-text\"\n : \"bg-status-success-bg-subtle text-status-success-text\",\n )}\n >\n {app.type}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr(\"devportal.created\", \"Created\")}\n </span>\n <span className=\"text-sm\">\n {new Date(app.createdAt).toLocaleDateString()}\n </span>\n </div>\n </div>\n </div>\n\n {/* Credentials — primary emphasis zone */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-4\">\n {tr(\"devportal.credentials\", \"Credentials\")}\n </h3>\n <div className=\"space-y-3\">\n <div>\n <label className=\"text-xs text-text-secondary\">\n {tr(\"devportal.clientId\", \"Client ID\")}\n </label>\n <div className=\"mt-1 flex items-center gap-2\">\n <code className=\"flex-1 rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono\">\n {app.clientId}\n </code>\n <button\n onClick={() => handleCopy(app.clientId)}\n className=\"rounded p-1.5 hover:bg-bg-sunken transition-colors\"\n title=\"Copy\"\n >\n <Copy size={14} />\n </button>\n </div>\n </div>\n {newSecret && (\n <div>\n <label className=\"text-xs text-status-error-text font-medium\">\n {tr(\n \"devportal.newClientSecretShownOnce\",\n \"New Client Secret (shown only once!)\",\n )}\n </label>\n <div className=\"mt-1 flex items-center gap-2\">\n <code className=\"flex-1 rounded bg-status-error-bg/10 border border-status-error-border/30 px-3 py-1.5 text-sm font-mono\">\n {showSecret\n ? newSecret\n : \"\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\"}\n </code>\n <button\n onClick={() => setShowSecret(!showSecret)}\n className=\"rounded p-1.5 hover:bg-bg-sunken transition-colors\"\n >\n {showSecret ? <EyeOff size={14} /> : <Eye size={14} />}\n </button>\n <button\n onClick={() => handleCopy(newSecret)}\n className=\"rounded p-1.5 hover:bg-bg-sunken transition-colors\"\n >\n <Copy size={14} />\n </button>\n </div>\n </div>\n )}\n <button\n onClick={() => setConfirmRotate(true)}\n disabled={rotating}\n className=\"mt-2 inline-flex items-center gap-2 rounded-md bg-status-warning-bg-subtle px-3 py-1.5 text-sm font-medium text-status-warning-text hover:bg-status-warning-bg-subtle transition-colors disabled:opacity-50\"\n >\n <RefreshCw\n size={14}\n className={rotating ? \"animate-spin\" : \"\"}\n />\n {tr(\"devportal.rotateSecret\", \"Rotate Secret\")}\n </button>\n </div>\n </GlassCard>\n </div>\n\n {/* Scopes */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-3\">\n {tr(\"devportal.scopes\", \"Scopes\")} ({app.scopes.length})\n </h3>\n {app.scopes.length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {app.scopes.map((scope) => (\n <span\n key={scope}\n className=\"rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\"\n >\n {scope}\n </span>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.noScopesConfigured\", \"No scopes configured\")}\n </p>\n )}\n </div>\n\n {/* Redirect URIs */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-3\">\n {tr(\"devportal.redirectUris\", \"Redirect URIs\")} (\n {app.redirectUris.length})\n </h3>\n {app.redirectUris.length > 0 ? (\n <div className=\"space-y-2\">\n {app.redirectUris.map((uri) => (\n <div key={uri} className=\"flex items-center gap-2\">\n <code className=\"rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono\">\n {uri}\n </code>\n <button\n onClick={() => handleCopy(uri)}\n className=\"rounded p-1 hover:bg-bg-sunken transition-colors\"\n >\n <Copy size={12} />\n </button>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.noRedirectUrisConfigured\",\n \"No redirect URIs configured\",\n )}\n </p>\n )}\n </div>\n\n {/* Confirm Rotate Dialog */}\n <AlertDialog open={confirmRotate} onOpenChange={setConfirmRotate}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {tr(\n \"devportal.rotateClientSecretQuestion\",\n \"Rotate Client Secret?\",\n )}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tr(\n \"devportal.rotateSecretWarning\",\n \"This will invalidate the current client secret. All integrations using the old secret will stop working immediately.\",\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={rotating}>\n {tr(\"devportal.cancel\", \"Cancel\")}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={(e) => {\n e.preventDefault();\n void handleRotateSecret();\n }}\n disabled={rotating}\n className=\"bg-status-warning-bg text-white hover:bg-status-warning-bg/90\"\n >\n {rotating\n ? tr(\"devportal.rotating\", \"Rotating...\")\n : tr(\"devportal.rotateSecret\", \"Rotate Secret\")}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Confirm Deactivate Dialog */}\n <AlertDialog open={confirmDelete} onOpenChange={setConfirmDelete}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle className=\"text-status-error-text\">\n {tr(\"devportal.deactivateAppQuestion\", \"Deactivate App?\")}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tr(\n \"devportal.deactivateAppWarning\",\n \"This will deactivate the app and revoke all tokens. This action cannot be undone easily.\",\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={deactivating}>\n {tr(\"devportal.cancel\", \"Cancel\")}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={(e) => {\n e.preventDefault();\n void handleDeactivate();\n }}\n disabled={deactivating}\n className=\"bg-status-error-bg text-status-error-text hover:bg-status-error-bg/90\"\n >\n {deactivating\n ? tr(\"devportal.deactivating\", \"Deactivating...\")\n : tr(\"devportal.deactivate\", \"Deactivate\")}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|