@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":"SettingsPage.js","names":["EmptyState","EmptyState$1","formatDate","value","neverLabel","parsed","SettingsPage","useDevportal","tr","useTr","useGetDeveloperPortalSettingsOverviewQuery","handleNavigate","basePath","path","title","description","loading","data","PageLayout","Loader2","error","AlertCircle","getErrorMessage","profile","organizations","org","apiKeys","totalApiKeyCount","latestApiKey","totalRevenue","sum","organization","PageSection","EmphasisPanel","UserCircle2","VerifiedBadge","Settings","KeyRound","Workflow","Building2","ExternalLink","Webhook","Shield","Mail"],"sources":["../../../src/devportal/pages/SettingsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Building2,\n ExternalLink,\n KeyRound,\n Mail,\n Settings,\n Shield,\n UserCircle2,\n Webhook,\n Workflow,\n Loader2,\n AlertCircle,\n} from \"lucide-react\";\nimport { EmphasisPanel } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { VerifiedBadge } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n getErrorMessage,\n useGetDeveloperPortalSettingsOverviewQuery,\n} from \"../hooks\";\nimport { useTr } from \"../utils/i18n\";\n\nconst formatDate = (\n value: string | null | undefined,\n neverLabel: string,\n): string => {\n if (!value) return neverLabel;\n\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return neverLabel;\n\n return parsed.toLocaleDateString();\n};\n\nexport const SettingsPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const tr = useTr();\n const { data, loading, error } = useGetDeveloperPortalSettingsOverviewQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const neverLabel = tr(\"devportal.settings.never\", \"Never\");\n const title = tr(\"devportal.settings.title\", \"Settings\");\n const description = tr(\n \"devportal.settings.description\",\n \"Review your developer portal account, credentials, and support options\",\n );\n\n if (loading && !data) {\n return (\n <PageLayout title={title} description={description}>\n <div\n className=\"flex items-center justify-center py-16 text-text-secondary\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={tr(\"devportal.common.loading\", \"Loading\")}\n >\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title={title} description={description}>\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\"devportal.settings.errorTitle\", \"Unable to load settings\")}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n const profile = data?.myDeveloperProfile;\n // This overview is scoped to the regular (digital) devportal — exclude\n // PHYSICAL orgs so seller-portal orgs don't inflate the \"Developer\n // organizations\" count/revenue shown here. See DeveloperOrgKind (BOFF-7285).\n type SettingsOrganization = NonNullable<\n typeof data\n >[\"myDeveloperOrganizations\"][number];\n const organizations = (data?.myDeveloperOrganizations ?? []).filter(\n (org: SettingsOrganization) => org.kind !== \"PHYSICAL\",\n );\n const apiKeys = data?.myApiKeys?.apiKeys ?? [];\n const totalApiKeyCount = data?.myApiKeys?.totalCount ?? apiKeys.length;\n const latestApiKey = apiKeys[0];\n const totalRevenue = organizations.reduce(\n (sum: number, organization: (typeof organizations)[number]) =>\n sum + (organization.totalRevenue ?? 0),\n 0,\n );\n\n return (\n <PageLayout\n title={title}\n description={description}\n purpose={tr(\n \"devportal.settings.purpose\",\n \"A quick health-check of your developer account — your profile, how many API keys and organizations you have, and where to get support. Use it to spot missing setup before it blocks publishing or billing.\",\n )}\n >\n <div className=\"grid gap-6 xl:grid-cols-[minmax(0,2fr)_minmax(320px,1fr)]\">\n <div className=\"space-y-6\">\n <PageSection title={tr(\"devportal.settings.profile\", \"Profile\")}>\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <UserCircle2\n className=\"h-5 w-5 text-primary\"\n aria-hidden=\"true\"\n />\n <h2 className=\"text-lg font-semibold\">\n {tr(\n \"devportal.settings.developerProfile\",\n \"Developer profile\",\n )}\n </h2>\n {profile?.isVerified && <VerifiedBadge verified />}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {profile?.companyName ||\n tr(\n \"devportal.settings.noCompanyName\",\n \"No company name set yet\",\n )}\n </p>\n {profile?.bio && (\n <p className=\"max-w-2xl text-sm text-text-secondary\">\n {profile.bio}\n </p>\n )}\n <div className=\"flex flex-wrap gap-2 pt-1 text-xs text-text-secondary\">\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.applicationCount ?? 0}{\" \"}\n {tr(\n \"devportal.settings.publishedAssetsTracked\",\n \"published assets tracked\",\n )}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.totalInstalls ?? 0}{\" \"}\n {tr(\"devportal.settings.installs\", \"installs\")}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {tr(\"devportal.settings.emailUpdates\", \"Email updates\")}{\" \"}\n {profile?.emailNotifications\n ? tr(\"devportal.common.enabled\", \"enabled\")\n : tr(\"devportal.common.disabled\", \"disabled\")}\n </span>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/publisher/profile\")}\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 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Settings size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.manageProfile\", \"Manage profile\")}\n </button>\n </div>\n </EmphasisPanel>\n </PageSection>\n\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.settings.credentials\", \"Credentials\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/api-keys\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <KeyRound size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.apiKeys\", \"API Keys\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {totalApiKeyCount}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {latestApiKey\n ? `${tr(\"devportal.settings.lastUsed\", \"Last used\")} ${formatDate(latestApiKey.lastUsedAt, neverLabel)}`\n : tr(\n \"devportal.settings.noApiKeys\",\n \"No API keys created yet\",\n )}\n </p>\n </button>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/oauth\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <Workflow size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.settings.oauthApps\", \"OAuth Apps\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {tr(\"devportal.common.open\", \"Open\")}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.oauthDescription\",\n \"Manage OAuth clients on the dedicated credentials page.\",\n )}\n </p>\n </button>\n </div>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.organizations\", \"Organizations\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Building2 size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.developerOrganizations\",\n \"Developer organizations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {organizations.length}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n ${totalRevenue.toLocaleString()}{\" \"}\n {tr(\n \"devportal.settings.lifetimeRevenue\",\n \"lifetime revenue across all teams\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\n \"devportal.settings.viewOrganizations\",\n \"View organizations\",\n )}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\n \"devportal.settings.deliveryAutomation\",\n \"Delivery & automation\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <div className=\"flex items-center gap-2 text-primary\">\n <Webhook size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.webhookOperations\",\n \"Webhook operations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.webhookOperationsDescription\",\n \"Configure application webhooks from each application detail page. Delivery history and retry status are available per app.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/webhooks\")}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\"devportal.settings.openWebhooks\", \"Open webhooks\")}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </div>\n </PageSection>\n </div>\n\n <div className=\"space-y-6\">\n <PageSection\n title={tr(\n \"devportal.settings.securitySupport\",\n \"Security & support\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Shield size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.settings.securityPosture\", \"Security posture\")}\n </span>\n </div>\n <ul className=\"mt-4 space-y-3 text-sm text-text-secondary\">\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote1\",\n \"API keys and OAuth apps are managed through the public global gateway.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote2\",\n \"Webhook testing and delivery history are available per application.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote3\",\n \"Profile verification status is reflected directly from your developer profile.\",\n )}\n </li>\n </ul>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.settings.recentCredentialActivity\",\n \"Recent credential activity\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n {latestApiKey ? (\n <div className=\"space-y-4 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <p className=\"font-medium\">{latestApiKey.name}</p>\n <p className=\"text-text-secondary\">\n {latestApiKey.prefix}\n </p>\n </div>\n <span className=\"inline-flex items-center rounded-full bg-status-success-bg-subtle px-2.5 py-1 text-xs font-medium text-status-success-text\">\n {tr(\"devportal.common.active\", \"Active\")}\n </span>\n </div>\n <dl className=\"grid gap-3 text-text-secondary\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.created\", \"Created\")}</dt>\n <dd>{formatDate(latestApiKey.createdAt, neverLabel)}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.expires\", \"Expires\")}</dt>\n <dd>{formatDate(latestApiKey.expiresAt, neverLabel)}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.settings.lastUsed\", \"Last used\")}</dt>\n <dd>{formatDate(latestApiKey.lastUsedAt, neverLabel)}</dd>\n </div>\n </dl>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<KeyRound size={24} />}\n title={tr(\n \"devportal.settings.noCredentialActivity\",\n \"No credential activity yet\",\n )}\n description={tr(\n \"devportal.settings.noCredentialActivityDescription\",\n \"Create an API key or OAuth app to manage credentials from here.\",\n )}\n />\n )}\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.accountActions\", \"Account actions\")}\n >\n <div className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-6\">\n <h2 className=\"font-semibold text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpTitle\",\n \"Need help with account changes?\",\n )}\n </h2>\n <p className=\"mt-2 text-sm text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpDescription\",\n \"Destructive account operations are handled through support so the team can verify ownership and preserve billing history, audit trails, and marketplace assets.\",\n )}\n </p>\n <a\n href=\"mailto:support@burdenoff.com?subject=Developer%20portal%20account%20support\"\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border border-status-warning-border bg-bg-surface px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Mail size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.contactSupport\", \"Contact support\")}\n </a>\n </div>\n </PageSection>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SettingsPage.js","names":["_Fragment","EmptyState","EmptyState$1","formatDate","value","neverLabel","parsed","HealthCheckFold","tr","useTr","fold","OptionalFields","Fragment","SettingsPage","useDevportal","isFluidgrids","useIsFluidgridsVariant","useGetDeveloperPortalSettingsOverviewQuery","handleNavigate","basePath","path","title","description","hub","DeveloperSettingsHub","loading","data","PageLayout","Loader2","error","AlertCircle","getErrorMessage","profile","organizations","org","apiKeys","totalApiKeyCount","latestApiKey","totalRevenue","sum","organization","PageSection","EmphasisPanel","UserCircle2","VerifiedBadge","Settings","KeyRound","Workflow","Building2","ExternalLink","Webhook","Shield","Mail"],"sources":["../../../src/devportal/pages/SettingsPage.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport {\n Building2,\n ExternalLink,\n KeyRound,\n Mail,\n Settings,\n Shield,\n UserCircle2,\n Webhook,\n Workflow,\n Loader2,\n AlertCircle,\n} from \"lucide-react\";\nimport { EmphasisPanel, OptionalFields } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { VerifiedBadge } from \"../components/StatusBadge\";\nimport { DeveloperSettingsHub } from \"../components/DeveloperSettingsHub\";\nimport {\n useDevportal,\n useIsFluidgridsVariant,\n} from \"../providers/DevportalProvider\";\nimport {\n getErrorMessage,\n useGetDeveloperPortalSettingsOverviewQuery,\n} from \"../hooks\";\nimport { useTr } from \"../utils/i18n\";\n\nconst formatDate = (\n value: string | null | undefined,\n neverLabel: string,\n): string => {\n if (!value) return neverLabel;\n\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return neverLabel;\n\n return parsed.toLocaleDateString();\n};\n\n/** FluidGrids: the health check sits one click deeper, remembered once opened. */\nconst HealthCheckFold: FC<{ fold: boolean; children: ReactNode }> = ({\n fold,\n children,\n}) => {\n const tr = useTr();\n if (!fold) return <>{children}</>;\n return (\n <OptionalFields\n storageKey=\"devportal.settings.healthCheck\"\n title={tr(\"devportal.developerSettings.healthTitle\", \"Account check\")}\n description={tr(\n \"devportal.developerSettings.healthDescription\",\n \"Your developer profile, credentials, organizations and support options.\",\n )}\n >\n {children}\n </OptionalFields>\n );\n};\n\nexport const SettingsPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const tr = useTr();\n const isFluidgrids = useIsFluidgridsVariant();\n const { data, loading, error } = useGetDeveloperPortalSettingsOverviewQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const neverLabel = tr(\"devportal.settings.never\", \"Never\");\n // FluidGrids: this page is the Developer settings hub (links first, the\n // account health check one click deeper). Other apps keep the old page.\n const title = isFluidgrids\n ? tr(\"devportal.developerSettings.title\", \"Developer settings\")\n : tr(\"devportal.settings.title\", \"Settings\");\n const description = isFluidgrids\n ? tr(\n \"devportal.developerSettings.description\",\n \"API keys, OAuth apps, webhooks, apps acting for you, app logs, analytics and docs in one place\",\n )\n : tr(\n \"devportal.settings.description\",\n \"Review your developer portal account, credentials, and support options\",\n );\n const hub = isFluidgrids ? (\n <div className=\"mb-6\">\n <DeveloperSettingsHub />\n </div>\n ) : null;\n\n if (loading && !data) {\n return (\n <PageLayout title={title} description={description}>\n {hub}\n <div\n className=\"flex items-center justify-center py-16 text-text-secondary\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={tr(\"devportal.common.loading\", \"Loading\")}\n >\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title={title} description={description}>\n {hub}\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\"devportal.settings.errorTitle\", \"Unable to load settings\")}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n const profile = data?.myDeveloperProfile;\n // This overview is scoped to the regular (digital) devportal — exclude\n // PHYSICAL orgs so seller-portal orgs don't inflate the \"Developer\n // organizations\" count/revenue shown here. See DeveloperOrgKind (BOFF-7285).\n type SettingsOrganization = NonNullable<\n typeof data\n >[\"myDeveloperOrganizations\"][number];\n const organizations = (data?.myDeveloperOrganizations ?? []).filter(\n (org: SettingsOrganization) => org.kind !== \"PHYSICAL\",\n );\n const apiKeys = data?.myApiKeys?.apiKeys ?? [];\n const totalApiKeyCount = data?.myApiKeys?.totalCount ?? apiKeys.length;\n const latestApiKey = apiKeys[0];\n const totalRevenue = organizations.reduce(\n (sum: number, organization: (typeof organizations)[number]) =>\n sum + (organization.totalRevenue ?? 0),\n 0,\n );\n\n return (\n <PageLayout\n title={title}\n description={description}\n purpose={tr(\n \"devportal.settings.purpose\",\n \"A quick health-check of your developer account — your profile, how many API keys and organizations you have, and where to get support. Use it to spot missing setup before it blocks publishing or billing.\",\n )}\n >\n {hub}\n <HealthCheckFold fold={isFluidgrids}>\n <div className=\"grid gap-6 xl:grid-cols-[minmax(0,2fr)_minmax(320px,1fr)]\">\n <div className=\"space-y-6\">\n <PageSection title={tr(\"devportal.settings.profile\", \"Profile\")}>\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <UserCircle2\n className=\"h-5 w-5 text-primary\"\n aria-hidden=\"true\"\n />\n <h2 className=\"text-lg font-semibold\">\n {tr(\n \"devportal.settings.developerProfile\",\n \"Developer profile\",\n )}\n </h2>\n {profile?.isVerified && <VerifiedBadge verified />}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {profile?.companyName ||\n tr(\n \"devportal.settings.noCompanyName\",\n \"No company name set yet\",\n )}\n </p>\n {profile?.bio && (\n <p className=\"max-w-2xl text-sm text-text-secondary\">\n {profile.bio}\n </p>\n )}\n <div className=\"flex flex-wrap gap-2 pt-1 text-xs text-text-secondary\">\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.applicationCount ?? 0}{\" \"}\n {tr(\n \"devportal.settings.publishedAssetsTracked\",\n \"published assets tracked\",\n )}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.totalInstalls ?? 0}{\" \"}\n {tr(\"devportal.settings.installs\", \"installs\")}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {tr(\"devportal.settings.emailUpdates\", \"Email updates\")}{\" \"}\n {profile?.emailNotifications\n ? tr(\"devportal.common.enabled\", \"enabled\")\n : tr(\"devportal.common.disabled\", \"disabled\")}\n </span>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/publisher/profile\")}\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 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Settings size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.manageProfile\", \"Manage profile\")}\n </button>\n </div>\n </EmphasisPanel>\n </PageSection>\n\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.settings.credentials\", \"Credentials\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/api-keys\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <KeyRound size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.apiKeys\", \"API Keys\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {totalApiKeyCount}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {latestApiKey\n ? `${tr(\"devportal.settings.lastUsed\", \"Last used\")} ${formatDate(latestApiKey.lastUsedAt, neverLabel)}`\n : tr(\n \"devportal.settings.noApiKeys\",\n \"No API keys created yet\",\n )}\n </p>\n </button>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/oauth\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <Workflow size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.settings.oauthApps\", \"OAuth Apps\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {tr(\"devportal.common.open\", \"Open\")}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.oauthDescription\",\n \"Manage OAuth clients on the dedicated credentials page.\",\n )}\n </p>\n </button>\n </div>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.organizations\", \"Organizations\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Building2 size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.developerOrganizations\",\n \"Developer organizations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {organizations.length}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n ${totalRevenue.toLocaleString()}{\" \"}\n {tr(\n \"devportal.settings.lifetimeRevenue\",\n \"lifetime revenue across all teams\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\n \"devportal.settings.viewOrganizations\",\n \"View organizations\",\n )}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\n \"devportal.settings.deliveryAutomation\",\n \"Delivery & automation\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <div className=\"flex items-center gap-2 text-primary\">\n <Webhook size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.webhookOperations\",\n \"Webhook operations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.webhookOperationsDescription\",\n \"Configure application webhooks from each application detail page. Delivery history and retry status are available per app.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/webhooks\")}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\"devportal.settings.openWebhooks\", \"Open webhooks\")}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </div>\n </PageSection>\n </div>\n\n <div className=\"space-y-6\">\n <PageSection\n title={tr(\n \"devportal.settings.securitySupport\",\n \"Security & support\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Shield size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.securityPosture\",\n \"Security posture\",\n )}\n </span>\n </div>\n <ul className=\"mt-4 space-y-3 text-sm text-text-secondary\">\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote1\",\n \"API keys and OAuth apps are managed through the public global gateway.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote2\",\n \"Webhook testing and delivery history are available per application.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote3\",\n \"Profile verification status is reflected directly from your developer profile.\",\n )}\n </li>\n </ul>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.settings.recentCredentialActivity\",\n \"Recent credential activity\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n {latestApiKey ? (\n <div className=\"space-y-4 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <p className=\"font-medium\">{latestApiKey.name}</p>\n <p className=\"text-text-secondary\">\n {latestApiKey.prefix}\n </p>\n </div>\n <span className=\"inline-flex items-center rounded-full bg-status-success-bg-subtle px-2.5 py-1 text-xs font-medium text-status-success-text\">\n {tr(\"devportal.common.active\", \"Active\")}\n </span>\n </div>\n <dl className=\"grid gap-3 text-text-secondary\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.created\", \"Created\")}</dt>\n <dd>\n {formatDate(latestApiKey.createdAt, neverLabel)}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.expires\", \"Expires\")}</dt>\n <dd>\n {formatDate(latestApiKey.expiresAt, neverLabel)}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>\n {tr(\"devportal.settings.lastUsed\", \"Last used\")}\n </dt>\n <dd>\n {formatDate(latestApiKey.lastUsedAt, neverLabel)}\n </dd>\n </div>\n </dl>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<KeyRound size={24} />}\n title={tr(\n \"devportal.settings.noCredentialActivity\",\n \"No credential activity yet\",\n )}\n description={tr(\n \"devportal.settings.noCredentialActivityDescription\",\n \"Create an API key or OAuth app to manage credentials from here.\",\n )}\n />\n )}\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.accountActions\", \"Account actions\")}\n >\n <div className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-6\">\n <h2 className=\"font-semibold text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpTitle\",\n \"Need help with account changes?\",\n )}\n </h2>\n <p className=\"mt-2 text-sm text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpDescription\",\n \"Destructive account operations are handled through support so the team can verify ownership and preserve billing history, audit trails, and marketplace assets.\",\n )}\n </p>\n <a\n href=\"mailto:support@burdenoff.com?subject=Developer%20portal%20account%20support\"\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border border-status-warning-border bg-bg-surface px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Mail size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.contactSupport\", \"Contact support\")}\n </a>\n </div>\n </PageSection>\n </div>\n </div>\n </HealthCheckFold>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -11,8 +11,8 @@ import { ELIGIBILITY_RULES as c, reviewRequirementsFor as oe } from "../utils/de
|
|
|
11
11
|
import { useState as l } from "react";
|
|
12
12
|
import { AppWindow as u, ArrowRight as se, BookOpen as ce, Box as le, Building2 as d, Check as f, ChevronRight as p, GitFork as ue, Key as de, ListChecks as m, Puzzle as h, Rocket as g, ShieldCheck as _ } from "lucide-react";
|
|
13
13
|
import { jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { Illustration as fe, PagePurpose as pe } from "@burdenoff/fe-libs/ui";
|
|
15
|
+
import { useI18n as me } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
16
16
|
// src/devportal/pages/SetupPage.tsx
|
|
17
17
|
function b(e) {
|
|
18
18
|
return e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
@@ -61,7 +61,7 @@ var S = [
|
|
|
61
61
|
})
|
|
62
62
|
});
|
|
63
63
|
}, C = () => {
|
|
64
|
-
let { navigate: a, basePath: c, currentUser: _ } = i(), { t: S } =
|
|
64
|
+
let { navigate: a, basePath: c, currentUser: _ } = i(), { t: S } = me(), C = ee(), E = (e, t) => {
|
|
65
65
|
let n = S(e);
|
|
66
66
|
return n === e ? t : n;
|
|
67
67
|
}, D = (e) => a?.(`${c}${e}`), [O, k] = l("org"), [A, _e] = l(null), [j, ve] = l(null), [ye, be] = l(null), [M, xe] = l(""), [N, P] = l(""), [F, Se] = l(""), [I, L] = l({}), [R, Ce] = l(!1), [z, B] = l(null), [we, { loading: Te }] = ie(), [Ee, { loading: De }] = re(), V = Te || De, [Oe] = ne(), ke = () => {
|
|
@@ -170,11 +170,11 @@ var S = [
|
|
|
170
170
|
}),
|
|
171
171
|
O === "org" && /* @__PURE__ */ y("div", {
|
|
172
172
|
className: "mb-8 flex flex-col items-center gap-3 text-center",
|
|
173
|
-
children: [/* @__PURE__ */ v(
|
|
173
|
+
children: [/* @__PURE__ */ v(fe, {
|
|
174
174
|
name: "onboarding",
|
|
175
175
|
alt: E("devportal.setup.illustrationAlt", "Getting started with the developer portal"),
|
|
176
176
|
size: "md"
|
|
177
|
-
}), /* @__PURE__ */ v(
|
|
177
|
+
}), /* @__PURE__ */ v(pe, {
|
|
178
178
|
className: "justify-center",
|
|
179
179
|
children: E("devportal.setup.purposeWithReview", "Three quick steps to start building: create the organization that owns your apps, register your first app, then submit it for review. Your developer profile is created with your organization. You can change everything later.")
|
|
180
180
|
})]
|
|
@@ -17,11 +17,11 @@ import { useEffect as v, useMemo as ae, useState as y } from "react";
|
|
|
17
17
|
import { AlertCircle as oe, CheckCircle as b, Clock as se, ExternalLink as ce, Loader2 as le, Pause as x, Play as S, Send as C, Trash2 as ue, Webhook as de, XCircle as fe } from "lucide-react";
|
|
18
18
|
import { useParams as w } from "react-router";
|
|
19
19
|
import { jsx as T, jsxs as E } from "react/jsx-runtime";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
20
|
+
import { CTAOverflowMenu as D, EmphasisPanel as O, NextSteps as k } from "@burdenoff/fe-libs/ui";
|
|
21
|
+
import { useI18n as A } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
22
22
|
// src/devportal/pages/WebhookDetailPage.tsx
|
|
23
23
|
var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
|
|
24
|
-
let { appId: M, webhookId: N } = w(), { navigate: P, basePath: F } = p(), { t: I } =
|
|
24
|
+
let { appId: M, webhookId: N } = w(), { navigate: P, basePath: F } = p(), { t: I } = A(), L = (e, t) => {
|
|
25
25
|
let n = I(e);
|
|
26
26
|
return n === e ? t : n;
|
|
27
27
|
}, { allowed: R } = _(g.WEBHOOK_UPDATE), { allowed: z } = _(g.WEBHOOK_DELETE), [B, V] = y(!1), [pe, H] = y(!1), [U, W] = y(null), [me, G] = y(!1), { data: K } = ee({
|
|
@@ -106,7 +106,7 @@ var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
|
|
|
106
106
|
purpose: L("devportal.webhookDetailPurpose", "This endpoint receives the events you subscribed to, signed with your secret. Check the delivery history to confirm your server is responding with 2xx, send a test event, and pause it if your endpoint is down so deliveries are not lost to repeated failures."),
|
|
107
107
|
backLink: `/apps/${Q}/webhooks`,
|
|
108
108
|
backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
|
|
109
|
-
actions: /* @__PURE__ */ T(
|
|
109
|
+
actions: /* @__PURE__ */ T(D, {
|
|
110
110
|
primary: {
|
|
111
111
|
label: L("devportal.test", "Test"),
|
|
112
112
|
icon: /* @__PURE__ */ T(C, { size: 16 }),
|
|
@@ -128,7 +128,7 @@ var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
|
|
|
128
128
|
}]
|
|
129
129
|
}),
|
|
130
130
|
children: [
|
|
131
|
-
/* @__PURE__ */ T(
|
|
131
|
+
/* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(c, {
|
|
132
132
|
columns: 4,
|
|
133
133
|
children: [
|
|
134
134
|
/* @__PURE__ */ T(s, {
|
|
@@ -153,7 +153,7 @@ var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
|
|
|
153
153
|
})
|
|
154
154
|
]
|
|
155
155
|
}) }),
|
|
156
|
-
/* @__PURE__ */ T(
|
|
156
|
+
/* @__PURE__ */ T(k, {
|
|
157
157
|
storageKey: `devportal-webhook-${X.id}`,
|
|
158
158
|
steps: [{
|
|
159
159
|
id: "test",
|
|
@@ -4,22 +4,22 @@ import { StatusBadge as n } from "../components/StatusBadge.js";
|
|
|
4
4
|
import { useGetApplicationQuery as r, useGetApplicationsQuery as i, useGetWebhooksQuery as a } from "../../generated/global-operations.js";
|
|
5
5
|
import { getErrorMessage as o } from "../hooks/useGraphQL.js";
|
|
6
6
|
import { EmptyState as s } from "../components/EmptyState.js";
|
|
7
|
-
import { AppListItem as
|
|
7
|
+
import { AppListItem as ee } from "../components/AppCard.js";
|
|
8
8
|
import "../components/index.js";
|
|
9
|
-
import { useDevportal as
|
|
10
|
-
import { PermissionGuard as
|
|
11
|
-
import { DEVPORTAL_PERMISSIONS as
|
|
12
|
-
import { useDevportalPermission as
|
|
9
|
+
import { useDevportal as c } from "../providers/DevportalProvider.js";
|
|
10
|
+
import { PermissionGuard as l } from "../components/PermissionGuard.js";
|
|
11
|
+
import { DEVPORTAL_PERMISSIONS as u } from "../constants/permissions.js";
|
|
12
|
+
import { useDevportalPermission as d } from "../hooks/usePermission.js";
|
|
13
13
|
import { cn as f } from "../utils/cn.js";
|
|
14
14
|
import "../hooks/index.js";
|
|
15
|
-
import { useEffect as
|
|
16
|
-
import { AlertCircle as
|
|
15
|
+
import { useEffect as p, useState as m } from "react";
|
|
16
|
+
import { AlertCircle as h, AlertTriangle as te, AppWindow as ne, CheckCircle as g, Loader2 as _, PauseCircle as v, Plus as y, Search as b, Webhook as x, XCircle as S } from "lucide-react";
|
|
17
17
|
import { useParams as C } from "react-router";
|
|
18
18
|
import { jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
19
|
-
import { useI18n as re } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
20
19
|
import { EmphasisPanel as E, GlassCard as D } from "@burdenoff/fe-libs/ui";
|
|
20
|
+
import { useI18n as O } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
21
21
|
// src/devportal/pages/WebhooksPage.tsx
|
|
22
|
-
function
|
|
22
|
+
function k(e) {
|
|
23
23
|
return {
|
|
24
24
|
id: e.id,
|
|
25
25
|
applicationId: e.applicationId,
|
|
@@ -43,31 +43,31 @@ function O(e) {
|
|
|
43
43
|
updatedAt: e.updatedAt
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
var
|
|
47
|
-
let { appId:
|
|
46
|
+
var A = () => {
|
|
47
|
+
let { appId: A } = C(), { navigate: re, basePath: ie, activeOrgId: M } = c(), { t: ae } = O(), N = (e, t) => {
|
|
48
48
|
let n = ae(e);
|
|
49
49
|
return n === e ? t : n;
|
|
50
|
-
}, P =
|
|
51
|
-
variables: { id:
|
|
52
|
-
skip: !
|
|
50
|
+
}, P = d(u.WEBHOOK_CREATE), [F, I] = m(""), [L, R] = m(""), { data: z } = r({
|
|
51
|
+
variables: { id: A ?? "" },
|
|
52
|
+
skip: !A,
|
|
53
53
|
fetchPolicy: "cache-first"
|
|
54
54
|
});
|
|
55
|
-
|
|
55
|
+
p(() => {
|
|
56
56
|
let e = z?.application?.name;
|
|
57
|
-
if (!
|
|
57
|
+
if (!A || !e) return;
|
|
58
58
|
let t = window.__breadcrumbRegistry;
|
|
59
|
-
return t?.register(
|
|
60
|
-
}, [
|
|
59
|
+
return t?.register(A, e), () => t?.unregister(A);
|
|
60
|
+
}, [A, z?.application?.name]);
|
|
61
61
|
let { data: B, loading: V, error: H, refetch: U } = i({
|
|
62
62
|
variables: { limit: 100 },
|
|
63
|
-
skip: !!
|
|
63
|
+
skip: !!A,
|
|
64
64
|
fetchPolicy: "cache-and-network"
|
|
65
65
|
}), { data: W, loading: G, error: K, refetch: q } = a({
|
|
66
|
-
variables: { applicationId:
|
|
67
|
-
skip: !
|
|
66
|
+
variables: { applicationId: A || "" },
|
|
67
|
+
skip: !A,
|
|
68
68
|
fetchPolicy: "cache-and-network"
|
|
69
|
-
}), J = W?.webhooks?.map(
|
|
70
|
-
|
|
69
|
+
}), J = W?.webhooks?.map(k) ?? [], Y = B?.applications?.edges?.map((e) => e.node) ?? [], X = M ? Y.filter((e) => e.developerOrganizationId === M) : Y, Z = (e) => {
|
|
70
|
+
re?.(`${ie}${e}`);
|
|
71
71
|
}, Q = J.filter((e) => {
|
|
72
72
|
let t = !F || e.name.toLowerCase().includes(F.toLowerCase()) || e.url.toLowerCase().includes(F.toLowerCase()), n = !L || e.status === L;
|
|
73
73
|
return t && n;
|
|
@@ -85,7 +85,7 @@ var k = () => {
|
|
|
85
85
|
size: 16,
|
|
86
86
|
className: "text-status-error-text"
|
|
87
87
|
});
|
|
88
|
-
case "DISABLED": return /* @__PURE__ */ w(
|
|
88
|
+
case "DISABLED": return /* @__PURE__ */ w(te, {
|
|
89
89
|
size: 16,
|
|
90
90
|
className: "text-text-tertiary"
|
|
91
91
|
});
|
|
@@ -95,13 +95,13 @@ var k = () => {
|
|
|
95
95
|
let t = e.successCount + e.failureCount;
|
|
96
96
|
return t === 0 ? 100 : Math.round(e.successCount / t * 100);
|
|
97
97
|
};
|
|
98
|
-
if (!
|
|
98
|
+
if (!A) {
|
|
99
99
|
let t = X.filter((e) => {
|
|
100
100
|
if (!F) return !0;
|
|
101
101
|
let t = F.toLowerCase();
|
|
102
102
|
return e.name.toLowerCase().includes(t) || (e.slug ?? "").toLowerCase().includes(t);
|
|
103
103
|
});
|
|
104
|
-
return /* @__PURE__ */ w(
|
|
104
|
+
return /* @__PURE__ */ w(l, {
|
|
105
105
|
authOnly: !0,
|
|
106
106
|
children: /* @__PURE__ */ w(e, {
|
|
107
107
|
title: N("devportal.webhooks", "Webhooks"),
|
|
@@ -136,7 +136,7 @@ var k = () => {
|
|
|
136
136
|
}) : H ? /* @__PURE__ */ T("div", {
|
|
137
137
|
className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
|
|
138
138
|
children: [
|
|
139
|
-
/* @__PURE__ */ w(
|
|
139
|
+
/* @__PURE__ */ w(h, { className: "mx-auto h-8 w-8 text-status-error-text" }),
|
|
140
140
|
/* @__PURE__ */ w("h3", {
|
|
141
141
|
className: "mt-2 font-medium text-status-error-text",
|
|
142
142
|
children: "Failed to load applications"
|
|
@@ -153,7 +153,7 @@ var k = () => {
|
|
|
153
153
|
]
|
|
154
154
|
}) : t.length > 0 ? /* @__PURE__ */ w("div", {
|
|
155
155
|
className: "space-y-2",
|
|
156
|
-
children: t.map((e) => /* @__PURE__ */ w(
|
|
156
|
+
children: t.map((e) => /* @__PURE__ */ w(ee, {
|
|
157
157
|
app: e,
|
|
158
158
|
onClick: () => Z(`/apps/${e.id}/webhooks`)
|
|
159
159
|
}, e.id))
|
|
@@ -176,7 +176,7 @@ var k = () => {
|
|
|
176
176
|
if (G && !W) return /* @__PURE__ */ w(e, {
|
|
177
177
|
title: N("devportal.webhooks", "Webhooks"),
|
|
178
178
|
description: N("devportal.manageWebhooksApp", "Manage webhooks for this application"),
|
|
179
|
-
backLink: `/apps/${
|
|
179
|
+
backLink: `/apps/${A}`,
|
|
180
180
|
backLabel: N("devportal.backToApplication", "Back to Application"),
|
|
181
181
|
children: /* @__PURE__ */ T("div", {
|
|
182
182
|
className: "flex items-center justify-center py-12",
|
|
@@ -189,12 +189,12 @@ var k = () => {
|
|
|
189
189
|
if (K) return /* @__PURE__ */ w(e, {
|
|
190
190
|
title: N("devportal.webhooks", "Webhooks"),
|
|
191
191
|
description: N("devportal.manageWebhooksApp", "Manage webhooks for this application"),
|
|
192
|
-
backLink: `/apps/${
|
|
192
|
+
backLink: `/apps/${A}`,
|
|
193
193
|
backLabel: N("devportal.backToApplication", "Back to Application"),
|
|
194
194
|
children: /* @__PURE__ */ T("div", {
|
|
195
195
|
className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
|
|
196
196
|
children: [
|
|
197
|
-
/* @__PURE__ */ w(
|
|
197
|
+
/* @__PURE__ */ w(h, { className: "mx-auto h-8 w-8 text-status-error-text" }),
|
|
198
198
|
/* @__PURE__ */ w("h3", {
|
|
199
199
|
className: "mt-2 font-medium text-status-error-text",
|
|
200
200
|
children: N("devportal.failedToLoadWebhooks", "Failed to load webhooks")
|
|
@@ -307,7 +307,7 @@ var k = () => {
|
|
|
307
307
|
header: "Last Triggered",
|
|
308
308
|
render: (e) => /* @__PURE__ */ w("span", {
|
|
309
309
|
className: "text-sm text-text-secondary",
|
|
310
|
-
children: e.lastTriggeredAt ?
|
|
310
|
+
children: e.lastTriggeredAt ? j(e.lastTriggeredAt) : "Never"
|
|
311
311
|
})
|
|
312
312
|
}
|
|
313
313
|
], $ = {
|
|
@@ -316,16 +316,16 @@ var k = () => {
|
|
|
316
316
|
failed: J.filter((e) => e.status === "FAILED").length,
|
|
317
317
|
paused: J.filter((e) => e.status === "PAUSED").length
|
|
318
318
|
};
|
|
319
|
-
return /* @__PURE__ */ w(
|
|
319
|
+
return /* @__PURE__ */ w(l, {
|
|
320
320
|
authOnly: !0,
|
|
321
321
|
children: /* @__PURE__ */ T(e, {
|
|
322
322
|
title: N("devportal.webhooks", "Webhooks"),
|
|
323
323
|
description: N("devportal.manageWebhooksApp", "Manage webhooks for this application"),
|
|
324
324
|
purpose: N("devportal.webhooksAppPurpose", "These webhooks deliver this application's events to your endpoints. Add a URL, choose which events to subscribe to, and send a test delivery to confirm your server receives and verifies the signed payload."),
|
|
325
|
-
backLink: `/apps/${
|
|
325
|
+
backLink: `/apps/${A}`,
|
|
326
326
|
backLabel: N("devportal.backToApplication", "Back to Application"),
|
|
327
327
|
actions: /* @__PURE__ */ T("button", {
|
|
328
|
-
onClick: () => Z(`/apps/${
|
|
328
|
+
onClick: () => Z(`/apps/${A}/webhooks/new`),
|
|
329
329
|
disabled: !P.allowed,
|
|
330
330
|
"aria-disabled": !P.allowed,
|
|
331
331
|
title: P.allowed ? void 0 : N("devportal.common.noPermission", "You do not have permission to perform this action"),
|
|
@@ -455,13 +455,13 @@ var k = () => {
|
|
|
455
455
|
data: Q,
|
|
456
456
|
columns: ce,
|
|
457
457
|
keyField: "id",
|
|
458
|
-
onRowClick: (e) => Z(`/apps/${
|
|
458
|
+
onRowClick: (e) => Z(`/apps/${A}/webhooks/${e.id}`)
|
|
459
459
|
}) : /* @__PURE__ */ w(s, {
|
|
460
460
|
illustration: "empty-notifications",
|
|
461
461
|
title: N("devportal.noWebhooksFound", "No webhooks found"),
|
|
462
462
|
description: F || L ? N("devportal.tryAdjustingFilters", "Try adjusting your filters") : N("devportal.createFirstWebhook", "Create your first webhook to receive real-time event notifications"),
|
|
463
463
|
action: !F && !L ? /* @__PURE__ */ T("button", {
|
|
464
|
-
onClick: () => Z(`/apps/${
|
|
464
|
+
onClick: () => Z(`/apps/${A}/webhooks/new`),
|
|
465
465
|
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",
|
|
466
466
|
children: [/* @__PURE__ */ w(y, { size: 16 }), N("devportal.createWebhook", "Create Webhook")]
|
|
467
467
|
}) : void 0
|
|
@@ -470,10 +470,10 @@ var k = () => {
|
|
|
470
470
|
})
|
|
471
471
|
});
|
|
472
472
|
};
|
|
473
|
-
function
|
|
473
|
+
function j(e) {
|
|
474
474
|
let t = new Date(e), n = (/* @__PURE__ */ new Date()).getTime() - t.getTime(), r = Math.floor(n / 6e4), i = Math.floor(r / 60), a = Math.floor(i / 24);
|
|
475
475
|
return r < 1 ? "Just now" : r < 60 ? `${r}m ago` : i < 24 ? `${i}h ago` : a < 7 ? `${a}d ago` : t.toLocaleDateString();
|
|
476
476
|
}
|
|
477
|
-
export {
|
|
477
|
+
export { A as WebhooksPage };
|
|
478
478
|
|
|
479
479
|
//# sourceMappingURL=WebhooksPage.js.map
|