@burdenoff/microfe-devportal 2026.1113.1 → 2026.1113.2
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/DevportalRoot.js +65 -119
- package/dist/devportal/DevportalRoot.js.map +1 -1
- package/dist/devportal/components/AppCard.js +4 -4
- package/dist/devportal/components/DeveloperSettingsHub.d.ts +6 -0
- package/dist/devportal/components/DeveloperSettingsHub.js +59 -0
- package/dist/devportal/components/DeveloperSettingsHub.js.map +1 -0
- package/dist/devportal/components/SectionNav.d.ts +1 -1
- package/dist/devportal/components/SectionNav.js +60 -36
- package/dist/devportal/components/SectionNav.js.map +1 -1
- package/dist/devportal/pages/AnalyticsDashboardPage.js +186 -179
- package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
- package/dist/devportal/pages/ApiKeysPage.js +113 -111
- package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
- package/dist/devportal/pages/AppLogsPage.js +80 -84
- package/dist/devportal/pages/AppLogsPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationDetailPage.js +529 -504
- package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationsPage.js +68 -67
- package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
- package/dist/devportal/pages/CreateApiKeyPage.js +163 -166
- package/dist/devportal/pages/CreateApiKeyPage.js.map +1 -1
- package/dist/devportal/pages/CreateOAuthClientPage.js +134 -130
- package/dist/devportal/pages/CreateOAuthClientPage.js.map +1 -1
- package/dist/devportal/pages/DelegationsPage.js +11 -11
- package/dist/devportal/pages/DocumentationPage.js +100 -94
- package/dist/devportal/pages/DocumentationPage.js.map +1 -1
- package/dist/devportal/pages/EditApplicationPage.js +379 -377
- package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
- package/dist/devportal/pages/InvitationDecisionPage.js +83 -79
- package/dist/devportal/pages/InvitationDecisionPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientDetailPage.js +76 -76
- package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js +126 -124
- package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationDetailPage.js +19 -19
- package/dist/devportal/pages/OrganizationMembersPage.js +223 -204
- package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
- package/dist/devportal/pages/ResourcesPage.d.ts +6 -0
- package/dist/devportal/pages/ResourcesPage.js +171 -155
- package/dist/devportal/pages/ResourcesPage.js.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.js +13 -13
- package/dist/devportal/pages/SellerItemsPage.js +4 -4
- package/dist/devportal/pages/SettingsPage.js +330 -315
- package/dist/devportal/pages/SettingsPage.js.map +1 -1
- package/dist/devportal/pages/SetupPage.js +5 -5
- package/dist/devportal/pages/WebhookDetailPage.js +6 -6
- package/dist/devportal/pages/WebhooksPage.js +39 -39
- package/dist/devportal/pages/WebhooksPage.js.map +1 -1
- package/dist/devportal/utils/appDetailTabs.d.ts +73 -0
- package/dist/devportal/utils/appDetailTabs.js +62 -0
- package/dist/devportal/utils/appDetailTabs.js.map +1 -0
- package/dist/devportal/utils/developerNav.d.ts +39 -0
- package/dist/devportal/utils/developerNav.js +304 -0
- package/dist/devportal/utils/developerNav.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvitationDecisionPage.js","names":["InvitationDecisionPage","useParams","useDevportal","useGetInvitationByTokenQuery","token","acceptInvitation","accepting","acceptedData","useAcceptInvitationMutation","rejectInvitation","rejecting","rejectedData","useRejectInvitationMutation","invitation","data","acceptedMember","rejected","handleAccept","handleReject","loading","PageLayout","Loader2","error","EmptyState","XCircle","CheckCircle","navigate","basePath","PageSection","Mail","Shield"],"sources":["../../../src/devportal/pages/InvitationDecisionPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useParams } from \"react-router\";\nimport { CheckCircle, Loader2, Mail, Shield, XCircle } from \"lucide-react\";\n\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n useAcceptInvitationMutation,\n useGetInvitationByTokenQuery,\n useRejectInvitationMutation,\n} from \"../hooks\";\n\nexport const InvitationDecisionPage: FC = () => {\n const { token } = useParams<{ token: string }>();\n const { navigate, basePath } = useDevportal();\n\n const { data, loading, error } = useGetInvitationByTokenQuery({\n variables: { token: token ?? \"\" },\n skip: !token,\n fetchPolicy: \"cache-and-network\",\n });\n\n const [acceptInvitation, { loading: accepting, data: acceptedData }] =\n useAcceptInvitationMutation();\n const [rejectInvitation, { loading: rejecting, data: rejectedData }] =\n useRejectInvitationMutation();\n\n const invitation = data?.developerOrgInvitationByToken;\n const acceptedMember = acceptedData?.acceptDeveloperOrgInvitation;\n const rejected = rejectedData?.rejectDeveloperOrgInvitation;\n\n const handleAccept = async () => {\n if (!token) return;\n await acceptInvitation({ variables: { token } });\n };\n\n const handleReject = async () => {\n if (!token) return;\n await rejectInvitation({ variables: { token } });\n };\n\n if (loading && !invitation) {\n return (\n <PageLayout title=\"Developer Team Invitation\">\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !invitation) {\n return (\n <PageLayout title=\"Developer Team Invitation\">\n <EmptyState\n icon={<XCircle size={32} className=\"text-status-error-text\" />}\n title=\"Invitation not available\"\n description={\n error?.message ||\n \"This invitation is invalid, expired, or not available to your signed-in account.\"\n }\n />\n </PageLayout>\n );\n }\n\n if (acceptedMember) {\n return (\n <PageLayout title=\"Invitation accepted\">\n <EmptyState\n icon={<CheckCircle size={32} className=\"text-status-success-text\" />}\n title=\"You joined the developer organization\"\n description={`You now have ${invitation.role.toLowerCase()} access to ${invitation.organization.name}.`}\n action={\n <button\n type=\"button\"\n onClick={() =>\n navigate?.(\n `${basePath}/organizations/${invitation.organization.id}`,\n )\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n Open organization\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n if (rejected) {\n return (\n <PageLayout title=\"Invitation declined\">\n <EmptyState\n icon={<XCircle size={32} className=\"text-status-warning-text\" />}\n title=\"Invitation declined\"\n description={`You declined the invitation to join ${invitation.organization.name}.`}\n action={\n <button\n type=\"button\"\n onClick={() => navigate?.(`${basePath}`)}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-seam px-4 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n Return to Devportal\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Developer Team Invitation\"\n description=\"Review your invitation to join a developer organization\"\n >\n <div className=\"mx-auto max-w-2xl space-y-6\">\n <PageSection title=\"Invitation details\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Organization</p>\n <p className=\"text-lg font-semibold text-text-primary\">\n {invitation.organization.name}\n </p>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-sm text-text-secondary\">Invited email</p>\n <p className=\"flex items-center gap-2 text-text-primary\">\n <Mail size={14} />\n {invitation.invitedEmail}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Role</p>\n <p className=\"flex items-center gap-2 text-text-primary\">\n <Shield size={14} />\n {invitation.role}\n </p>\n </div>\n </div>\n {invitation.message ? (\n <div>\n <p className=\"text-sm text-text-secondary\">Message</p>\n <p className=\"rounded-md bg-bg-sunken px-3 py-2 text-sm text-text-primary whitespace-pre-line\">\n {invitation.message}\n </p>\n </div>\n ) : null}\n <p className=\"text-xs text-text-secondary\">\n Expires on {new Date(invitation.expiresAt).toLocaleString()}\n </p>\n </div>\n </PageSection>\n\n <div className=\"flex flex-wrap gap-3 justify-end\">\n <button\n type=\"button\"\n onClick={() => void handleReject()}\n disabled={accepting || rejecting}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-seam px-4 py-2 text-sm font-medium hover:bg-bg-sunken disabled:opacity-50\"\n >\n {rejecting ? <Loader2 size={14} className=\"animate-spin\" /> : null}\n Decline\n </button>\n <button\n type=\"button\"\n onClick={() => void handleAccept()}\n disabled={accepting || rejecting}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {accepting ? <Loader2 size={14} className=\"animate-spin\" /> : null}\n Accept invitation\n </button>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InvitationDecisionPage.js","names":["InvitationDecisionPage","useParams","tr","useTr","useDevportal","useGetInvitationByTokenQuery","token","acceptInvitation","accepting","acceptedData","useAcceptInvitationMutation","rejectInvitation","rejecting","rejectedData","useRejectInvitationMutation","invitation","data","acceptedMember","rejected","handleAccept","handleReject","invitationTitle","loading","PageLayout","Loader2","error","EmptyState","XCircle","CheckCircle","navigate","basePath","PageSection","Mail","Shield"],"sources":["../../../src/devportal/pages/InvitationDecisionPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useParams } from \"react-router\";\nimport { CheckCircle, Loader2, Mail, Shield, XCircle } from \"lucide-react\";\n\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n useAcceptInvitationMutation,\n useGetInvitationByTokenQuery,\n useRejectInvitationMutation,\n} from \"../hooks\";\nimport { useTr } from \"../utils/i18n\";\n\nexport const InvitationDecisionPage: FC = () => {\n const { token } = useParams<{ token: string }>();\n const tr = useTr();\n const { navigate, basePath } = useDevportal();\n\n const { data, loading, error } = useGetInvitationByTokenQuery({\n variables: { token: token ?? \"\" },\n skip: !token,\n fetchPolicy: \"cache-and-network\",\n });\n\n const [acceptInvitation, { loading: accepting, data: acceptedData }] =\n useAcceptInvitationMutation();\n const [rejectInvitation, { loading: rejecting, data: rejectedData }] =\n useRejectInvitationMutation();\n\n const invitation = data?.developerOrgInvitationByToken;\n const acceptedMember = acceptedData?.acceptDeveloperOrgInvitation;\n const rejected = rejectedData?.rejectDeveloperOrgInvitation;\n\n const handleAccept = async () => {\n if (!token) return;\n await acceptInvitation({ variables: { token } });\n };\n\n const handleReject = async () => {\n if (!token) return;\n await rejectInvitation({ variables: { token } });\n };\n\n const invitationTitle = tr(\n \"devportal.invitation.title\",\n \"Developer Team Invitation\",\n );\n\n if (loading && !invitation) {\n return (\n <PageLayout title={invitationTitle}>\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !invitation) {\n return (\n <PageLayout title={invitationTitle}>\n <EmptyState\n icon={<XCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.invitation.unavailableTitle\",\n \"Invitation not available\",\n )}\n description={\n error?.message ||\n tr(\n \"devportal.invitation.unavailableDescription\",\n \"This invitation is invalid, expired, or not available to your signed-in account.\",\n )\n }\n />\n </PageLayout>\n );\n }\n\n if (acceptedMember) {\n return (\n <PageLayout\n title={tr(\"devportal.invitation.acceptedTitle\", \"Invitation accepted\")}\n >\n <EmptyState\n icon={<CheckCircle size={32} className=\"text-status-success-text\" />}\n title={tr(\n \"devportal.invitation.joinedTitle\",\n \"You joined the developer organization\",\n )}\n description={tr(\n \"devportal.invitation.joinedDescription\",\n \"You now have {{role}} access to {{organization}}.\",\n {\n role: invitation.role.toLowerCase(),\n organization: invitation.organization.name,\n },\n )}\n action={\n <button\n type=\"button\"\n onClick={() =>\n navigate?.(\n `${basePath}/organizations/${invitation.organization.id}`,\n )\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n {tr(\"devportal.invitation.openOrganization\", \"Open organization\")}\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n if (rejected) {\n return (\n <PageLayout\n title={tr(\"devportal.invitation.declinedTitle\", \"Invitation declined\")}\n >\n <EmptyState\n icon={<XCircle size={32} className=\"text-status-warning-text\" />}\n title={tr(\n \"devportal.invitation.declinedTitle\",\n \"Invitation declined\",\n )}\n description={tr(\n \"devportal.invitation.declinedDescription\",\n \"You declined the invitation to join {{organization}}.\",\n { organization: invitation.organization.name },\n )}\n action={\n <button\n type=\"button\"\n onClick={() => navigate?.(`${basePath}`)}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-seam px-4 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n {tr(\n \"devportal.invitation.returnToDevportal\",\n \"Return to Devportal\",\n )}\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={invitationTitle}\n description={tr(\n \"devportal.invitation.reviewDescription\",\n \"Review your invitation to join a developer organization\",\n )}\n >\n <div className=\"mx-auto max-w-2xl space-y-6\">\n <PageSection\n title={tr(\"devportal.invitation.detailsTitle\", \"Invitation details\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.invitation.organization\", \"Organization\")}\n </p>\n <p className=\"text-lg font-semibold text-text-primary\">\n {invitation.organization.name}\n </p>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.invitation.invitedEmail\", \"Invited email\")}\n </p>\n <p className=\"flex items-center gap-2 text-text-primary\">\n <Mail size={14} />\n {invitation.invitedEmail}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.invitation.role\", \"Role\")}\n </p>\n <p className=\"flex items-center gap-2 text-text-primary\">\n <Shield size={14} />\n {invitation.role}\n </p>\n </div>\n </div>\n {invitation.message ? (\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.invitation.message\", \"Message\")}\n </p>\n <p className=\"rounded-md bg-bg-sunken px-3 py-2 text-sm text-text-primary whitespace-pre-line\">\n {invitation.message}\n </p>\n </div>\n ) : null}\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.invitation.expiresOn\", \"Expires on {{date}}\", {\n date: new Date(invitation.expiresAt).toLocaleString(),\n })}\n </p>\n </div>\n </PageSection>\n\n <div className=\"flex flex-wrap gap-3 justify-end\">\n <button\n type=\"button\"\n onClick={() => void handleReject()}\n disabled={accepting || rejecting}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-seam px-4 py-2 text-sm font-medium hover:bg-bg-sunken disabled:opacity-50\"\n >\n {rejecting ? <Loader2 size={14} className=\"animate-spin\" /> : null}\n {tr(\"devportal.invitation.decline\", \"Decline\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleAccept()}\n disabled={accepting || rejecting}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {accepting ? <Loader2 size={14} className=\"animate-spin\" /> : null}\n {tr(\"devportal.invitation.accept\", \"Accept invitation\")}\n </button>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -7,20 +7,20 @@ import { errorMessage as s } from "../utils/errorMessage.js";
|
|
|
7
7
|
import "../components/index.js";
|
|
8
8
|
import { PermissionGuard as ne } from "../components/PermissionGuard.js";
|
|
9
9
|
import { cn as re } from "../utils/cn.js";
|
|
10
|
-
import { nativeCopyText as ie, nativeImpact as ae, nativeNotify as
|
|
10
|
+
import { nativeCopyText as ie, nativeImpact as ae, nativeNotify as oe } from "../../utils/nativeBridge.js";
|
|
11
11
|
import "../hooks/index.js";
|
|
12
|
-
import { useState as
|
|
13
|
-
import { AlertCircle as
|
|
14
|
-
import { useParams as
|
|
15
|
-
import { jsx as
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
12
|
+
import { useState as c } from "react";
|
|
13
|
+
import { AlertCircle as l, ArrowLeft as u, Copy as d, Eye as f, EyeOff as p, Loader2 as m, RefreshCw as h, Trash2 as se } from "lucide-react";
|
|
14
|
+
import { useParams as g } from "react-router";
|
|
15
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
16
|
+
import { AlertDialog as y, AlertDialogAction as b, AlertDialogCancel as x, AlertDialogContent as S, AlertDialogDescription as C, AlertDialogFooter as w, AlertDialogHeader as T, AlertDialogTitle as E, CTAOverflowMenu as D, GlassCard as O } from "@burdenoff/fe-libs/ui";
|
|
17
|
+
import { useI18n as k } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
18
18
|
// src/devportal/pages/OAuthClientDetailPage.tsx
|
|
19
19
|
var A = () => {
|
|
20
|
-
let { clientId: A } =
|
|
20
|
+
let { clientId: A } = g(), { navigate: j, basePath: M } = o(), { t: N } = k(), P = (e, t) => {
|
|
21
21
|
let n = N(e);
|
|
22
22
|
return n === e ? t : n;
|
|
23
|
-
}, [F, I] =
|
|
23
|
+
}, [F, I] = c(!1), [L, R] = c(null), [z, B] = c(!1), [V, H] = c(!1), [U, W] = c(null), G = te(), { data: K, loading: ce, error: q, refetch: J } = ee({
|
|
24
24
|
variables: { id: A || "" },
|
|
25
25
|
skip: !A,
|
|
26
26
|
fetchPolicy: "cache-and-network"
|
|
@@ -42,7 +42,7 @@ var A = () => {
|
|
|
42
42
|
}, $ = async (e) => {
|
|
43
43
|
ae("light");
|
|
44
44
|
let t = await ie(e);
|
|
45
|
-
|
|
45
|
+
oe(t ? "success" : "error");
|
|
46
46
|
}, fe = async () => {
|
|
47
47
|
if (A) {
|
|
48
48
|
W(null);
|
|
@@ -63,48 +63,48 @@ var A = () => {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
|
-
return ce && !K ? /* @__PURE__ */
|
|
66
|
+
return ce && !K ? /* @__PURE__ */ _(e, {
|
|
67
67
|
title: P("devportal.appDetails", "App Details"),
|
|
68
68
|
description: P("devportal.loadingDots", "Loading..."),
|
|
69
69
|
backLink: "/oauth",
|
|
70
70
|
backLabel: P("devportal.backToApps", "Back to Apps"),
|
|
71
|
-
children: /* @__PURE__ */
|
|
71
|
+
children: /* @__PURE__ */ _("div", {
|
|
72
72
|
className: "flex items-center justify-center py-12",
|
|
73
|
-
children: /* @__PURE__ */
|
|
73
|
+
children: /* @__PURE__ */ _(m, { className: "h-8 w-8 animate-spin text-text-secondary" })
|
|
74
74
|
})
|
|
75
|
-
}) : q || !Z ? /* @__PURE__ */
|
|
75
|
+
}) : q || !Z ? /* @__PURE__ */ _(e, {
|
|
76
76
|
title: P("devportal.appDetails", "App Details"),
|
|
77
77
|
description: P("devportal.failedToLoad", "Failed to load"),
|
|
78
78
|
backLink: "/oauth",
|
|
79
79
|
backLabel: P("devportal.backToApps", "Back to Apps"),
|
|
80
|
-
children: /* @__PURE__ */
|
|
80
|
+
children: /* @__PURE__ */ v("div", {
|
|
81
81
|
className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
|
|
82
82
|
children: [
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
-
/* @__PURE__ */
|
|
83
|
+
/* @__PURE__ */ _(l, { className: "mx-auto h-8 w-8 text-status-error-text" }),
|
|
84
|
+
/* @__PURE__ */ _("h3", {
|
|
85
85
|
className: "mt-2 font-medium text-status-error-text",
|
|
86
86
|
children: q ? P("devportal.failedToLoadApp", "Failed to load app") : P("devportal.appNotFound", "App not found")
|
|
87
87
|
}),
|
|
88
|
-
q && /* @__PURE__ */
|
|
88
|
+
q && /* @__PURE__ */ _("p", {
|
|
89
89
|
className: "mt-1 text-sm text-text-secondary",
|
|
90
90
|
children: a(q)
|
|
91
91
|
}),
|
|
92
|
-
/* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ v("button", {
|
|
93
93
|
onClick: () => Q("/oauth"),
|
|
94
94
|
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",
|
|
95
|
-
children: [/* @__PURE__ */
|
|
95
|
+
children: [/* @__PURE__ */ _(u, { size: 16 }), P("devportal.backToApps", "Back to Apps")]
|
|
96
96
|
})
|
|
97
97
|
]
|
|
98
98
|
})
|
|
99
|
-
}) : /* @__PURE__ */
|
|
99
|
+
}) : /* @__PURE__ */ _(ne, {
|
|
100
100
|
authOnly: !0,
|
|
101
|
-
children: /* @__PURE__ */
|
|
101
|
+
children: /* @__PURE__ */ v(e, {
|
|
102
102
|
title: Z.name,
|
|
103
103
|
description: Z.description || P("devportal.oauthAppDetailsAndCredentials", "OAuth App details and credentials"),
|
|
104
104
|
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."),
|
|
105
105
|
backLink: "/oauth",
|
|
106
106
|
backLabel: P("devportal.backToApps", "Back to Apps"),
|
|
107
|
-
actions: /* @__PURE__ */
|
|
107
|
+
actions: /* @__PURE__ */ _(D, {
|
|
108
108
|
primary: {
|
|
109
109
|
label: Z.status === "ACTIVE" ? P("devportal.deactivate", "Deactivate") : P("devportal.activate", "Activate"),
|
|
110
110
|
onSelect: async () => {
|
|
@@ -123,114 +123,114 @@ var A = () => {
|
|
|
123
123
|
},
|
|
124
124
|
actions: [{
|
|
125
125
|
label: G ? P("devportal.deactivate", "Deactivate") : P("devportal.delete", "Delete"),
|
|
126
|
-
icon: /* @__PURE__ */
|
|
126
|
+
icon: /* @__PURE__ */ _(se, { size: 16 }),
|
|
127
127
|
intent: "destructive",
|
|
128
128
|
onSelect: () => B(!0)
|
|
129
129
|
}]
|
|
130
130
|
}),
|
|
131
131
|
children: [
|
|
132
|
-
U && /* @__PURE__ */
|
|
132
|
+
U && /* @__PURE__ */ _("div", {
|
|
133
133
|
role: "alert",
|
|
134
134
|
className: "mb-4 rounded-md bg-status-error-bg px-3 py-2 text-sm text-status-error-text",
|
|
135
135
|
children: U
|
|
136
136
|
}),
|
|
137
|
-
/* @__PURE__ */
|
|
137
|
+
/* @__PURE__ */ v("div", {
|
|
138
138
|
className: "grid gap-6 md:grid-cols-2",
|
|
139
|
-
children: [/* @__PURE__ */
|
|
139
|
+
children: [/* @__PURE__ */ v("div", {
|
|
140
140
|
className: "rounded-card border border-border-seam bg-bg-surface p-6",
|
|
141
|
-
children: [/* @__PURE__ */
|
|
141
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
142
142
|
className: "text-sm font-medium text-text-secondary mb-4",
|
|
143
143
|
children: P("devportal.statusAndConfiguration", "Status & Configuration")
|
|
144
|
-
}), /* @__PURE__ */
|
|
144
|
+
}), /* @__PURE__ */ v("div", {
|
|
145
145
|
className: "space-y-3",
|
|
146
146
|
children: [
|
|
147
|
-
/* @__PURE__ */
|
|
147
|
+
/* @__PURE__ */ v("div", {
|
|
148
148
|
className: "flex justify-between",
|
|
149
|
-
children: [/* @__PURE__ */
|
|
149
|
+
children: [/* @__PURE__ */ _("span", {
|
|
150
150
|
className: "text-sm text-text-secondary",
|
|
151
151
|
children: P("devportal.status", "Status")
|
|
152
|
-
}), /* @__PURE__ */
|
|
152
|
+
}), /* @__PURE__ */ v("div", {
|
|
153
153
|
className: "flex items-center gap-2",
|
|
154
|
-
children: [/* @__PURE__ */
|
|
154
|
+
children: [/* @__PURE__ */ _(t, { active: Z.status === "ACTIVE" }), /* @__PURE__ */ _("span", {
|
|
155
155
|
className: "text-sm font-medium",
|
|
156
156
|
children: Z.status
|
|
157
157
|
})]
|
|
158
158
|
})]
|
|
159
159
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
160
|
+
/* @__PURE__ */ v("div", {
|
|
161
161
|
className: "flex justify-between",
|
|
162
|
-
children: [/* @__PURE__ */
|
|
162
|
+
children: [/* @__PURE__ */ _("span", {
|
|
163
163
|
className: "text-sm text-text-secondary",
|
|
164
164
|
children: P("devportal.type", "Type")
|
|
165
|
-
}), /* @__PURE__ */
|
|
165
|
+
}), /* @__PURE__ */ _("span", {
|
|
166
166
|
className: re("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"),
|
|
167
167
|
children: Z.type
|
|
168
168
|
})]
|
|
169
169
|
}),
|
|
170
|
-
/* @__PURE__ */
|
|
170
|
+
/* @__PURE__ */ v("div", {
|
|
171
171
|
className: "flex justify-between",
|
|
172
|
-
children: [/* @__PURE__ */
|
|
172
|
+
children: [/* @__PURE__ */ _("span", {
|
|
173
173
|
className: "text-sm text-text-secondary",
|
|
174
174
|
children: P("devportal.created", "Created")
|
|
175
|
-
}), /* @__PURE__ */
|
|
175
|
+
}), /* @__PURE__ */ _("span", {
|
|
176
176
|
className: "text-sm",
|
|
177
177
|
children: new Date(Z.createdAt).toLocaleDateString()
|
|
178
178
|
})]
|
|
179
179
|
})
|
|
180
180
|
]
|
|
181
181
|
})]
|
|
182
|
-
}), /* @__PURE__ */
|
|
182
|
+
}), /* @__PURE__ */ v(O, {
|
|
183
183
|
treatment: "glass",
|
|
184
184
|
glow: !0,
|
|
185
185
|
className: "p-6",
|
|
186
|
-
children: [/* @__PURE__ */
|
|
186
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
187
187
|
className: "text-sm font-medium text-text-secondary mb-4",
|
|
188
188
|
children: P("devportal.credentials", "Credentials")
|
|
189
|
-
}), /* @__PURE__ */
|
|
189
|
+
}), /* @__PURE__ */ v("div", {
|
|
190
190
|
className: "space-y-3",
|
|
191
191
|
children: [
|
|
192
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
193
193
|
className: "text-xs text-text-secondary",
|
|
194
194
|
children: P("devportal.clientId", "Client ID")
|
|
195
|
-
}), /* @__PURE__ */
|
|
195
|
+
}), /* @__PURE__ */ v("div", {
|
|
196
196
|
className: "mt-1 flex items-center gap-2",
|
|
197
|
-
children: [/* @__PURE__ */
|
|
197
|
+
children: [/* @__PURE__ */ _("code", {
|
|
198
198
|
className: "flex-1 rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono",
|
|
199
199
|
children: Z.clientId
|
|
200
|
-
}), /* @__PURE__ */
|
|
200
|
+
}), /* @__PURE__ */ _("button", {
|
|
201
201
|
onClick: () => $(Z.clientId),
|
|
202
202
|
className: "rounded p-1.5 hover:bg-bg-sunken transition-colors",
|
|
203
203
|
title: "Copy",
|
|
204
|
-
children: /* @__PURE__ */
|
|
204
|
+
children: /* @__PURE__ */ _(d, { size: 14 })
|
|
205
205
|
})]
|
|
206
206
|
})] }),
|
|
207
|
-
L && /* @__PURE__ */
|
|
207
|
+
L && /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
208
208
|
className: "text-xs text-status-error-text font-medium",
|
|
209
209
|
children: P("devportal.newClientSecretShownOnce", "New Client Secret (shown only once!)")
|
|
210
|
-
}), /* @__PURE__ */
|
|
210
|
+
}), /* @__PURE__ */ v("div", {
|
|
211
211
|
className: "mt-1 flex items-center gap-2",
|
|
212
212
|
children: [
|
|
213
|
-
/* @__PURE__ */
|
|
213
|
+
/* @__PURE__ */ _("code", {
|
|
214
214
|
className: "flex-1 rounded bg-status-error-bg/10 border border-status-error-border/30 px-3 py-1.5 text-sm font-mono",
|
|
215
215
|
children: F ? L : "••••••••••••••••"
|
|
216
216
|
}),
|
|
217
|
-
/* @__PURE__ */
|
|
217
|
+
/* @__PURE__ */ _("button", {
|
|
218
218
|
onClick: () => I(!F),
|
|
219
219
|
className: "rounded p-1.5 hover:bg-bg-sunken transition-colors",
|
|
220
|
-
children:
|
|
220
|
+
children: _(F ? p : f, { size: 14 })
|
|
221
221
|
}),
|
|
222
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ _("button", {
|
|
223
223
|
onClick: () => $(L),
|
|
224
224
|
className: "rounded p-1.5 hover:bg-bg-sunken transition-colors",
|
|
225
|
-
children: /* @__PURE__ */
|
|
225
|
+
children: /* @__PURE__ */ _(d, { size: 14 })
|
|
226
226
|
})
|
|
227
227
|
]
|
|
228
228
|
})] }),
|
|
229
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ v("button", {
|
|
230
230
|
onClick: () => H(!0),
|
|
231
231
|
disabled: Y,
|
|
232
232
|
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",
|
|
233
|
-
children: [/* @__PURE__ */
|
|
233
|
+
children: [/* @__PURE__ */ _(h, {
|
|
234
234
|
size: 14,
|
|
235
235
|
className: Y ? "animate-spin" : ""
|
|
236
236
|
}), P("devportal.rotateSecret", "Rotate Secret")]
|
|
@@ -239,9 +239,9 @@ var A = () => {
|
|
|
239
239
|
})]
|
|
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.scopes", "Scopes"),
|
|
@@ -249,20 +249,20 @@ var A = () => {
|
|
|
249
249
|
Z.scopes.length,
|
|
250
250
|
")"
|
|
251
251
|
]
|
|
252
|
-
}), Z.scopes.length > 0 ? /* @__PURE__ */
|
|
252
|
+
}), Z.scopes.length > 0 ? /* @__PURE__ */ _("div", {
|
|
253
253
|
className: "flex flex-wrap gap-2",
|
|
254
|
-
children: Z.scopes.map((e) => /* @__PURE__ */
|
|
254
|
+
children: Z.scopes.map((e) => /* @__PURE__ */ _("span", {
|
|
255
255
|
className: "rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary",
|
|
256
256
|
children: e
|
|
257
257
|
}, e))
|
|
258
|
-
}) : /* @__PURE__ */
|
|
258
|
+
}) : /* @__PURE__ */ _("p", {
|
|
259
259
|
className: "text-sm text-text-secondary",
|
|
260
260
|
children: P("devportal.noScopesConfigured", "No scopes configured")
|
|
261
261
|
})]
|
|
262
262
|
}),
|
|
263
|
-
/* @__PURE__ */
|
|
263
|
+
/* @__PURE__ */ v("div", {
|
|
264
264
|
className: "rounded-card border border-border-seam bg-bg-surface p-6",
|
|
265
|
-
children: [/* @__PURE__ */
|
|
265
|
+
children: [/* @__PURE__ */ v("h3", {
|
|
266
266
|
className: "text-sm font-medium text-text-secondary mb-3",
|
|
267
267
|
children: [
|
|
268
268
|
P("devportal.redirectUris", "Redirect URIs"),
|
|
@@ -270,31 +270,31 @@ var A = () => {
|
|
|
270
270
|
Z.redirectUris.length,
|
|
271
271
|
")"
|
|
272
272
|
]
|
|
273
|
-
}), Z.redirectUris.length > 0 ? /* @__PURE__ */
|
|
273
|
+
}), Z.redirectUris.length > 0 ? /* @__PURE__ */ _("div", {
|
|
274
274
|
className: "space-y-2",
|
|
275
|
-
children: Z.redirectUris.map((e) => /* @__PURE__ */
|
|
275
|
+
children: Z.redirectUris.map((e) => /* @__PURE__ */ v("div", {
|
|
276
276
|
className: "flex items-center gap-2",
|
|
277
|
-
children: [/* @__PURE__ */
|
|
277
|
+
children: [/* @__PURE__ */ _("code", {
|
|
278
278
|
className: "rounded bg-bg-sunken px-3 py-1.5 text-sm font-mono",
|
|
279
279
|
children: e
|
|
280
|
-
}), /* @__PURE__ */
|
|
280
|
+
}), /* @__PURE__ */ _("button", {
|
|
281
281
|
onClick: () => $(e),
|
|
282
282
|
className: "rounded p-1 hover:bg-bg-sunken transition-colors",
|
|
283
|
-
children: /* @__PURE__ */
|
|
283
|
+
children: /* @__PURE__ */ _(d, { size: 12 })
|
|
284
284
|
})]
|
|
285
285
|
}, e))
|
|
286
|
-
}) : /* @__PURE__ */
|
|
286
|
+
}) : /* @__PURE__ */ _("p", {
|
|
287
287
|
className: "text-sm text-text-secondary",
|
|
288
288
|
children: P("devportal.noRedirectUrisConfigured", "No redirect URIs configured")
|
|
289
289
|
})]
|
|
290
290
|
}),
|
|
291
|
-
/* @__PURE__ */
|
|
291
|
+
/* @__PURE__ */ _(y, {
|
|
292
292
|
open: V,
|
|
293
293
|
onOpenChange: H,
|
|
294
|
-
children: /* @__PURE__ */
|
|
294
|
+
children: /* @__PURE__ */ v(S, { children: [/* @__PURE__ */ v(T, { children: [/* @__PURE__ */ _(E, { children: P("devportal.rotateClientSecretQuestion", "Rotate Client Secret?") }), /* @__PURE__ */ _(C, { children: P("devportal.rotateSecretWarning", "This will invalidate the current client secret. All integrations using the old secret will stop working immediately.") })] }), /* @__PURE__ */ v(w, { children: [/* @__PURE__ */ _(x, {
|
|
295
295
|
disabled: Y,
|
|
296
296
|
children: P("devportal.cancel", "Cancel")
|
|
297
|
-
}), /* @__PURE__ */
|
|
297
|
+
}), /* @__PURE__ */ _(b, {
|
|
298
298
|
onClick: (e) => {
|
|
299
299
|
e.preventDefault(), fe();
|
|
300
300
|
},
|
|
@@ -303,16 +303,16 @@ var A = () => {
|
|
|
303
303
|
children: Y ? P("devportal.rotating", "Rotating...") : P("devportal.rotateSecret", "Rotate Secret")
|
|
304
304
|
})] })] })
|
|
305
305
|
}),
|
|
306
|
-
/* @__PURE__ */
|
|
306
|
+
/* @__PURE__ */ _(y, {
|
|
307
307
|
open: z,
|
|
308
308
|
onOpenChange: B,
|
|
309
|
-
children: /* @__PURE__ */
|
|
309
|
+
children: /* @__PURE__ */ v(S, { children: [/* @__PURE__ */ v(T, { children: [/* @__PURE__ */ _(E, {
|
|
310
310
|
className: "text-status-error-text",
|
|
311
311
|
children: P("devportal.deactivateAppQuestion", "Deactivate App?")
|
|
312
|
-
}), /* @__PURE__ */
|
|
312
|
+
}), /* @__PURE__ */ _(C, { children: P("devportal.deactivateAppWarning", "This will deactivate the app and revoke all tokens. This action cannot be undone easily.") })] }), /* @__PURE__ */ v(w, { children: [/* @__PURE__ */ _(x, {
|
|
313
313
|
disabled: X,
|
|
314
314
|
children: P("devportal.cancel", "Cancel")
|
|
315
|
-
}), /* @__PURE__ */
|
|
315
|
+
}), /* @__PURE__ */ _(b, {
|
|
316
316
|
onClick: (e) => {
|
|
317
317
|
e.preventDefault(), pe();
|
|
318
318
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OAuthClientDetailPage.js","names":["OAuthClientDetailPage","appId","useParams","useDevportal","useI18n","tr","value","t","key","fallback","showSecret","setShowSecret","useState","newSecret","setNewSecret","confirmDelete","setConfirmDelete","confirmRotate","setConfirmRotate","actionError","setActionError","isFluidgrids","useIsFluidgridsVariant","useGetAuthAppQuery","rotateSecret","rotating","useRotateAppSecretMutation","deactivateApp","deactivating","useDeactivateAppMutation","updateApp","useUpdateAuthAppMutation","app","data","handleNavigate","basePath","path","handleCopy","ok","nativeCopyText","text","handleRotateSecret","secret","refetch","err","errorMessage","handleDeactivate","loading","PageLayout","Loader2","error","AlertCircle","getErrorMessage","ArrowLeft","PermissionGuard","CTAOverflowMenu","newStatus","Trash2","ActiveIndicator","cn","GlassCard","Copy","jsx","EyeOff","Eye","RefreshCw","scope","uri","AlertDialog","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction"],"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 {\n useDevportal,\n useIsFluidgridsVariant,\n} from \"../providers/DevportalProvider\";\nimport { errorMessage } from \"../utils/errorMessage\";\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 // A failed rotate / deactivate / status change stays visible (never swallowed).\n const [actionError, setActionError] = useState<string | null>(null);\n // FluidGrids: the \"Delete\" action only deactivates, so it is labelled that way.\n const isFluidgrids = useIsFluidgridsVariant();\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 setActionError(null);\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 (err) {\n setActionError(\n errorMessage(\n err,\n tr(\n \"devportal.oauthActionFailed\",\n \"That did not work. Nothing was changed. Please try again.\",\n ),\n ),\n );\n }\n };\n\n const handleDeactivate = async () => {\n if (!appId) return;\n setActionError(null);\n try {\n await deactivateApp({ variables: { id: appId } });\n setConfirmDelete(false);\n handleNavigate(\"/oauth\");\n } catch (err) {\n setActionError(\n errorMessage(\n err,\n tr(\n \"devportal.oauthActionFailed\",\n \"That did not work. Nothing was changed. Please try again.\",\n ),\n ),\n );\n }\n };\n\n const handleToggleStatus = async () => {\n if (!appId || !app) return;\n setActionError(null);\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 (err) {\n setActionError(\n errorMessage(\n err,\n tr(\n \"devportal.oauthActionFailed\",\n \"That did not work. Nothing was changed. Please try again.\",\n ),\n ),\n );\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: isFluidgrids\n ? tr(\"devportal.deactivate\", \"Deactivate\")\n : tr(\"devportal.delete\", \"Delete\"),\n icon: <Trash2 size={16} />,\n intent: \"destructive\",\n onSelect: () => setConfirmDelete(true),\n },\n ]}\n />\n }\n >\n {actionError && (\n <div\n role=\"alert\"\n className=\"mb-4 rounded-md bg-status-error-bg px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </div>\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":["OAuthClientDetailPage","appId","useParams","useDevportal","useI18n","tr","value","t","key","fallback","showSecret","setShowSecret","useState","newSecret","setNewSecret","confirmDelete","setConfirmDelete","confirmRotate","setConfirmRotate","actionError","setActionError","isFluidgrids","useIsFluidgridsVariant","useGetAuthAppQuery","rotateSecret","rotating","useRotateAppSecretMutation","deactivateApp","deactivating","useDeactivateAppMutation","updateApp","useUpdateAuthAppMutation","app","data","handleNavigate","basePath","path","handleCopy","ok","nativeCopyText","text","handleRotateSecret","secret","refetch","err","errorMessage","handleDeactivate","loading","PageLayout","Loader2","error","AlertCircle","getErrorMessage","ArrowLeft","PermissionGuard","CTAOverflowMenu","newStatus","Trash2","ActiveIndicator","cn","GlassCard","Copy","jsx","EyeOff","Eye","RefreshCw","scope","uri","AlertDialog","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction"],"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 {\n useDevportal,\n useIsFluidgridsVariant,\n} from \"../providers/DevportalProvider\";\nimport { errorMessage } from \"../utils/errorMessage\";\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 // A failed rotate / deactivate / status change stays visible (never swallowed).\n const [actionError, setActionError] = useState<string | null>(null);\n // FluidGrids: the \"Delete\" action only deactivates, so it is labelled that way.\n const isFluidgrids = useIsFluidgridsVariant();\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 setActionError(null);\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 (err) {\n setActionError(\n errorMessage(\n err,\n tr(\n \"devportal.oauthActionFailed\",\n \"That did not work. Nothing was changed. Please try again.\",\n ),\n ),\n );\n }\n };\n\n const handleDeactivate = async () => {\n if (!appId) return;\n setActionError(null);\n try {\n await deactivateApp({ variables: { id: appId } });\n setConfirmDelete(false);\n handleNavigate(\"/oauth\");\n } catch (err) {\n setActionError(\n errorMessage(\n err,\n tr(\n \"devportal.oauthActionFailed\",\n \"That did not work. Nothing was changed. Please try again.\",\n ),\n ),\n );\n }\n };\n\n const handleToggleStatus = async () => {\n if (!appId || !app) return;\n setActionError(null);\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 (err) {\n setActionError(\n errorMessage(\n err,\n tr(\n \"devportal.oauthActionFailed\",\n \"That did not work. Nothing was changed. Please try again.\",\n ),\n ),\n );\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: isFluidgrids\n ? tr(\"devportal.deactivate\", \"Deactivate\")\n : tr(\"devportal.delete\", \"Delete\"),\n icon: <Trash2 size={16} />,\n intent: \"destructive\",\n onSelect: () => setConfirmDelete(true),\n },\n ]}\n />\n }\n >\n {actionError && (\n <div\n role=\"alert\"\n className=\"mb-4 rounded-md bg-status-error-bg px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </div>\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":";;;;;;;;;;;;;;;;;;AAuDA,IAAaA,UAAkC;CAC7C,IAAM,EAAE,UAAUC,MAAUC,EAAgC,GACtD,EAAE,aAAU,gBAAaC,EAAa,GACtC,EAAE,SAAMC,EAAQ,GAChBC,KAAM,GAAa,MAA6B;EACpD,IAAMC,IAAQC,EAAEC,CAAG;EACnB,OAAOF,MAAUE,IAAMC,IAAWH;CACpC,GACM,CAACI,GAAYC,KAAiBC,EAAS,EAAK,GAC5C,CAACC,GAAWC,KAAgBF,EAAwB,IAAI,GACxD,CAACG,GAAeC,KAAoBJ,EAAS,EAAK,GAClD,CAACK,GAAeC,KAAoBN,EAAS,EAAK,GAElD,CAACO,GAAaC,KAAkBR,EAAwB,IAAI,GAE5DS,IAAeC,GAAuB,GAEtC,EAAE,SAAM,aAAS,UAAO,eAAYC,GAAmB;EAC3D,WAAW,EAAE,IAAItB,KAAS,GAAG;EAC7B,MAAM,CAACA;EACP,aAAa;CACf,CAAC,GAEK,CAACuB,IAAc,EAAE,SAASC,OAAcC,EAA2B,GACnE,CAACC,IAAe,EAAE,SAASC,OAAkBC,EAAyB,GACtE,CAACC,MAAaC,EAAyB,GAEvCC,IAAsBC,GAAM,MAC9B;EACE,IAAIA,EAAK,IAAI;EACb,MAAMA,EAAK,IAAI;EACf,aAAaA,EAAK,IAAI,eAAe,KAAA;EACrC,UAAUA,EAAK,IAAI;EACnB,MAAMA,EAAK,IAAI;EACf,QAAQA,EAAK,IAAI;EACjB,QAAQA,EAAK,IAAI,UAAU,CAAC;EAC5B,cAAcA,EAAK,IAAI,gBAAgB,CAAC;EACxC,aAAaA,EAAK,IAAI;EACtB,UAAUA,EAAK,IAAI;EACnB,WAAWA,EAAK,IAAI;EACpB,WAAWA,EAAK,IAAI;CACtB,IACA,MAEEC,KAAkB,MAAiB;EACvC,IAAW,GAAGC,IAAWC,GAAM;CACjC,GAEMC,IAAa,OAAO,MAAiB;EACzC,GAAkB,OAAO;EACzB,IAAMC,IAAK,MAAMC,GAAeC,CAAI;EACpC,GAAkBF,IAAK,YAAY,OAAO;CAC5C,GAEMG,KAAqB,YAAY;EACrC,IAAKxC,GACL;KAAe,IAAI;GACnB,IAAI;IAEF,IAAMyC,KAAS,MADMlB,GAAa,EAAE,WAAW,EAAE,IAAIvB,EAAM,EAAE,CAAC,EAAA,CACxC,MAAM,iBAAiB;IAM7C,AALIyC,MACF5B,EAAa4B,CAAM,GACnB/B,EAAc,EAAI,IAEpBO,EAAiB,EAAK,GACtByB,EAAQ;GACV,SAASC,GAAK;IACZ,EACEC,EACED,GACAvC,EACE,+BACA,2DACF,CACF,CACF;GACF;EApBmB;CAqBrB,GAEMyC,KAAmB,YAAY;EACnC,IAAK7C,GACL;KAAe,IAAI;GACnB,IAAI;IAGF,AAFA,MAAM0B,GAAc,EAAE,WAAW,EAAE,IAAI1B,EAAM,EAAE,CAAC,GAChDe,EAAiB,EAAK,GACtBkB,EAAe,QAAQ;GACzB,SAASU,GAAK;IACZ,EACEC,EACED,GACAvC,EACE,+BACA,2DACF,CACF,CACF;GACF;EAfmB;CAgBrB;CAuEA,OA/CI0C,MAAW,CAACd,IAEZ,kBAACe,GAAD;EACE,OAAO3C,EAAG,wBAAwB,aAAa;EAC/C,aAAaA,EAAG,yBAAyB,YAAY;EACrD,UAAS;EACT,WAAWA,EAAG,wBAAwB,cAAc;EAEpD,UAAA,kBAAC,OAAD;GAAK,WAAU;GACb,UAAA,kBAAC4C,GAAD,EAAS,WAAU,2CAA4C,CAAA;EAC5D,CAAA;CACK,CAAA,IAIZC,KAAS,CAAClB,IAEV,kBAACgB,GAAD;EACE,OAAO3C,EAAG,wBAAwB,aAAa;EAC/C,aAAaA,EAAG,0BAA0B,gBAAgB;EAC1D,UAAS;EACT,WAAWA,EAAG,wBAAwB,cAAc;EAEpD,UAAA,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,kBAAC8C,GAAD,EAAa,WAAU,yCAA0C,CAAA;IACjE,kBAAC,MAAD;KAAI,WAAU;KACX,UAAAD,IACG7C,EAAG,6BAA6B,oBAAoB,IACpDA,EAAG,yBAAyB,eAAe;IAC7C,CAAA;IACH6C,KACC,kBAAC,KAAD;KAAG,WAAU;KACV,UAAAE,EAAgBF,CAAK;IACrB,CAAA;IAEL,kBAAC,UAAD;KACE,eAAehB,EAAe,QAAQ;KACtC,WAAU;KAFZ,UAAA,CAIE,kBAACmB,GAAD,EAAW,MAAM,GAAK,CAAA,GACrBhD,EAAG,wBAAwB,cAAc,CACpC;;GACL;;CACK,CAAA,IAKd,kBAACiD,IAAD;EAAiB,UAAA;EACf,UAAA,kBAACN,GAAD;GACE,OAAOhB,EAAI;GACX,aACEA,EAAI,eACJ3B,EACE,2CACA,mCACF;GAEF,SAASA,EACP,mCACA,qNACF;GACA,UAAS;GACT,WAAWA,EAAG,wBAAwB,cAAc;GACpD,SACE,kBAACkD,GAAD;IACE,SAAS;KACP,OACEvB,EAAI,WAAW,WACX3B,EAAG,wBAAwB,YAAY,IACvCA,EAAG,sBAAsB,UAAU;KACzC,UAAU,YA7FiB;MACrC,IAAI,CAACJ,KAAS,CAAC+B,GAAK;MACpB,EAAe,IAAI;MACnB,IAAMwB,IAAYxB,EAAI,WAAW,WAAW,aAAa;MACzD,IAAI;OAIF,AAHA,MAAMF,GAAU,EACd,WAAW;QAAE,IAAI7B;QAAO,OAAO,EAAE,QAAQuD,EAAU;OAAE,EACvD,CAAC,GACDb,EAAQ;MACV,SAASC,GAAK;OACZ,EACEC,EACED,GACAvC,EACE,+BACA,2DACF,CACF,CACF;MACF;KACF;IA0EU;IACA,SAAS,CACP;KACE,OAAOgB,IACHhB,EAAG,wBAAwB,YAAY,IACvCA,EAAG,oBAAoB,QAAQ;KACnC,MAAM,kBAACoD,IAAD,EAAQ,MAAM,GAAK,CAAA;KACzB,QAAQ;KACR,gBAAgBzC,EAAiB,EAAI;IACvC,CACF;GACD,CAAA;GAlCL,UAAA;IAqCGG,KACC,kBAAC,OAAD;KACE,MAAK;KACL,WAAU;KAET,UAAAA;IACE,CAAA;IAGP,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,MAAD;OAAI,WAAU;OACX,UAAAd,EAAG,oCAAoC,wBAAwB;MAC9D,CAAA,GACJ,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA;QACE,kBAAC,OAAD;SAAK,WAAU;SAAf,UAAA,CACE,kBAAC,QAAD;UAAM,WAAU;UACb,UAAAA,EAAG,oBAAoB,QAAQ;SAC5B,CAAA,GACN,kBAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACE,kBAACqD,GAAD,EAAiB,QAAQ1B,EAAI,WAAW,SAAW,CAAA,GACnD,kBAAC,QAAD;WAAM,WAAU;WAAuB,UAAAA,EAAI;UAAa,CAAA,CACrD;SACF,CAAA,CAAA;;QACL,kBAAC,OAAD;SAAK,WAAU;SAAf,UAAA,CACE,kBAAC,QAAD;UAAM,WAAU;UACb,UAAA3B,EAAG,kBAAkB,MAAM;SACxB,CAAA,GACN,kBAAC,QAAD;UACE,WAAWsD,GACT,2CACA3B,EAAI,SAAS,YACT,+CACAA,EAAI,SAAS,iBACXA,EAAI,SAAS,oBACb,mDACA,sDACR;UAEC,UAAAA,EAAI;SACD,CAAA,CACH;;QACL,kBAAC,OAAD;SAAK,WAAU;SAAf,UAAA,CACE,kBAAC,QAAD;UAAM,WAAU;UACb,UAAA3B,EAAG,qBAAqB,SAAS;SAC9B,CAAA,GACN,kBAAC,QAAD;UAAM,WAAU;UACb,UAAA,IAAI,KAAK2B,EAAI,SAAS,CAAC,CAAC,mBAAmB;SACxC,CAAA,CACH;;OACF;MACF,CAAA,CAAA;KAGL,CAAA,GAAA,kBAAC4B,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;MAA5C,UAAA,CACE,kBAAC,MAAD;OAAI,WAAU;OACX,UAAAvD,EAAG,yBAAyB,aAAa;MACxC,CAAA,GACJ,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA;QACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;SAAO,WAAU;SACd,UAAAA,EAAG,sBAAsB,WAAW;QAChC,CAAA,GACP,kBAAC,OAAD;SAAK,WAAU;SAAf,UAAA,CACE,kBAAC,QAAD;UAAM,WAAU;UACb,UAAA2B,EAAI;SACD,CAAA,GACN,kBAAC,UAAD;UACE,eAAeK,EAAWL,EAAI,QAAQ;UACtC,WAAU;UACV,OAAM;UAEN,UAAA,kBAAC6B,GAAD,EAAM,MAAM,GAAK,CAAA;SACX,CAAA,CACL;QACF,CAAA,CAAA,EAAA,CAAA;QACJhD,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;SAAO,WAAU;SACd,UAAAR,EACC,sCACA,sCACF;QACK,CAAA,GACP,kBAAC,OAAD;SAAK,WAAU;SAAf,UAAA;UACE,kBAAC,QAAD;WAAM,WAAU;WACb,UAAAK,IACGG,IACA;UACA,CAAA;UACN,kBAAC,UAAD;WACE,eAAeF,EAAc,CAACD,CAAU;WACxC,WAAU;WAET,UAAaoD,EAAbpD,IAAcqD,IAAuBC,GAAxB,EAAQ,MAAM,GAAK,CAAoB;UAC/C,CAAA;UACR,kBAAC,UAAD;WACE,eAAe3B,EAAWxB,CAAS;WACnC,WAAU;WAEV,UAAA,kBAACgD,GAAD,EAAM,MAAM,GAAK,CAAA;UACX,CAAA;SACL;QACF,CAAA,CAAA,EAAA,CAAA;QAEP,kBAAC,UAAD;SACE,eAAe3C,EAAiB,EAAI;SACpC,UAAUO;SACV,WAAU;SAHZ,UAAA,CAKE,kBAACwC,GAAD;UACE,MAAM;UACN,WAAWxC,IAAW,iBAAiB;SACxC,CAAA,GACApB,EAAG,0BAA0B,eAAe,CACvC;;OACL;MACI,CAAA,CAAA;KACR,CAAA,CAAA;;IAGL,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;MAAd,UAAA;OACGA,EAAG,oBAAoB,QAAQ;OAAE;OAAG2B,EAAI,OAAO;OAAO;MACrD;KACH,CAAA,GAAAA,EAAI,OAAO,SAAS,IACnB,kBAAC,OAAD;MAAK,WAAU;MACZ,UAAAA,EAAI,OAAO,KAAK,MACf,kBAAC,QAAD;OAEE,WAAU;OAET,UAAAkC;MACG,GAJCA,CAID,CACP;KACE,CAAA,IAEL,kBAAC,KAAD;MAAG,WAAU;MACV,UAAA7D,EAAG,gCAAgC,sBAAsB;KACzD,CAAA,CAEF;;IAGL,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;MAAd,UAAA;OACGA,EAAG,0BAA0B,eAAe;OAAE;OAC9C2B,EAAI,aAAa;OAAO;MACvB;KACH,CAAA,GAAAA,EAAI,aAAa,SAAS,IACzB,kBAAC,OAAD;MAAK,WAAU;MACZ,UAAAA,EAAI,aAAa,KAAK,MACrB,kBAAC,OAAD;OAAe,WAAU;OAAzB,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;QACb,UAAAmC;OACG,CAAA,GACN,kBAAC,UAAD;QACE,eAAe9B,EAAW8B,CAAG;QAC7B,WAAU;QAEV,UAAA,kBAACN,GAAD,EAAM,MAAM,GAAK,CAAA;OACX,CAAA,CACL;MAVK,GAAAM,CAUL,CACN;KACE,CAAA,IAEL,kBAAC,KAAD;MAAG,WAAU;MACV,UAAA9D,EACC,sCACA,6BACF;KACC,CAAA,CAEF;;IAGL,kBAAC+D,GAAD;KAAa,MAAMnD;KAAe,cAAcC;KAC9C,UAAA,kBAACmD,GAAD,EAAA,UAAA,CACE,kBAACC,GAAD,EAAA,UAAA,CACE,kBAACC,GAAD,EAAA,UACGlE,EACC,wCACA,uBACF,EACgB,CAAA,GAClB,kBAACmE,GAAD,EAAA,UACGnE,EACC,iCACA,sHACF,EACsB,CAAA,CACP,EAAA,CAAA,GACnB,kBAACoE,GAAD,EAAA,UAAA,CACE,kBAACC,GAAD;MAAmB,UAAUjD;MAC1B,UAAApB,EAAG,oBAAoB,QAAQ;KACf,CAAA,GACnB,kBAACsE,GAAD;MACE,UAAU,MAAM;OAEd,AADA,EAAE,eAAe,GACjBlC,GAAwB;MAC1B;MACA,UAAUhB;MACV,WAAU;MAET,UAAAA,IACGpB,EAAG,sBAAsB,aAAa,IACtCA,EAAG,0BAA0B,eAAe;KAC/B,CAAA,CACF,EAAA,CAAA,CACD,EAAA,CAAA;IACT,CAAA;IAGb,kBAAC+D,GAAD;KAAa,MAAMrD;KAAe,cAAcC;KAC9C,UAAA,kBAACqD,GAAD,EAAA,UAAA,CACE,kBAACC,GAAD,EAAA,UAAA,CACE,kBAACC,GAAD;MAAkB,WAAU;MACzB,UAAAlE,EAAG,mCAAmC,iBAAiB;KACxC,CAAA,GAClB,kBAACmE,GAAD,EAAA,UACGnE,EACC,kCACA,0FACF,EACsB,CAAA,CACP,EAAA,CAAA,GACnB,kBAACoE,GAAD,EAAA,UAAA,CACE,kBAACC,GAAD;MAAmB,UAAU9C;MAC1B,UAAAvB,EAAG,oBAAoB,QAAQ;KACf,CAAA,GACnB,kBAACsE,GAAD;MACE,UAAU,MAAM;OAEd,AADA,EAAE,eAAe,GACjB7B,GAAsB;MACxB;MACA,UAAUlB;MACV,WAAU;MAET,UAAAA,IACGvB,EAAG,0BAA0B,iBAAiB,IAC9CA,EAAG,wBAAwB,YAAY;KAC1B,CAAA,CACF,EAAA,CAAA,CACD,EAAA,CAAA;IACT,CAAA;GACH;;CACG,CAAA;AAErB"}
|