@burdenoff/microfe-devportal 2026.1112.2 → 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 +72 -69
- package/dist/devportal/components/AppCard.js.map +1 -1
- 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/ImageUploadField.js +82 -80
- package/dist/devportal/components/ImageUploadField.js.map +1 -1
- 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/components/StoreImage.d.ts +15 -0
- package/dist/devportal/components/StoreImage.js +30 -0
- package/dist/devportal/components/StoreImage.js.map +1 -0
- package/dist/devportal/components/index.d.ts +1 -0
- package/dist/devportal/components/index.js +17 -16
- package/dist/devportal/hooks/usePackageUpload.d.ts +46 -4
- package/dist/devportal/hooks/usePackageUpload.js +90 -36
- package/dist/devportal/hooks/usePackageUpload.js.map +1 -1
- package/dist/devportal/pages/AdminReviewPage.js +205 -202
- package/dist/devportal/pages/AdminReviewPage.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 +186 -183
- 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/CreatePhysicalItemPage.js +2 -2
- package/dist/devportal/pages/CreatePhysicalItemPage.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/EditPhysicalItemPage.js +312 -307
- package/dist/devportal/pages/EditPhysicalItemPage.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/ListingPreviewPage.js +175 -171
- package/dist/devportal/pages/ListingPreviewPage.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 +117 -115
- package/dist/devportal/pages/SellerDashboardPage.js.map +1 -1
- package/dist/devportal/pages/SellerItemsPage.js +202 -199
- package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
- 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/StoreSubmissionPage.js +133 -131
- package/dist/devportal/pages/StoreSubmissionPage.js.map +1 -1
- 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":"OAuthClientsPage.js","names":["EmptyState","EmptyState$1","OAuthClientsPage","useDevportal","useI18n","tr","value","t","key","fallback","searchQuery","setSearchQuery","useState","typeFilter","setTypeFilter","useCurrentUserAppsQuery","apps","data","app","handleNavigate","basePath","path","filteredApps","matchesSearch","matchesType","loading","PageLayout","Loader2","error","AlertCircle","getErrorMessage","refetch","columns","cn","Shield","scope","ActiveIndicator","stats","a","PermissionGuard","Plus","Search","EmphasisPanel","GlassCard","DataTable"],"sources":["../../../src/devportal/pages/OAuthClientsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { Plus, Search, Shield, Loader2, AlertCircle } from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { ActiveIndicator } from \"../components/StatusBadge\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport type { AuthApp } from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { useCurrentUserAppsQuery, getErrorMessage } from \"../hooks\";\n\n/**\n * OAuth Apps listing page\n *\n * Displays the current user's OAuth apps from auth-svc.\n * Previously showed devportal-svc OAuthClients per application;\n * now shows all user-owned apps centrally.\n */\nexport const OAuthClientsPage: FC = () => {\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 [searchQuery, setSearchQuery] = useState(\"\");\n const [typeFilter, setTypeFilter] = useState<string>(\"\");\n\n // Fetch apps from auth-svc (user-scoped, no applicationId needed)\n const { data, loading, error, refetch } = useCurrentUserAppsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const apps: AuthApp[] =\n data?.currentUserApps?.apps.map(\n (app: (typeof data.currentUserApps.apps)[number]) => ({\n id: app.id,\n name: app.name,\n description: app.description ?? undefined,\n clientId: app.clientId,\n type: app.type as AuthApp[\"type\"],\n status: app.status as AuthApp[\"status\"],\n scopes: app.scopes ?? [],\n redirectUris: app.redirectUris ?? [],\n ownerUserId: app.ownerUserId,\n tenantId: app.tenantId ?? \"\",\n createdAt: app.createdAt,\n updatedAt: app.updatedAt,\n }),\n ) ?? [];\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n // Filter apps\n const filteredApps = apps.filter((app) => {\n const matchesSearch =\n !searchQuery ||\n app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n app.clientId.toLowerCase().includes(searchQuery.toLowerCase());\n const matchesType = !typeFilter || app.type === typeFilter;\n return matchesSearch && matchesType;\n });\n\n // Loading state\n if (loading && !data) {\n return (\n <PageLayout\n title={tr(\"devportal.oauthApps\", \"OAuth Apps\")}\n description={tr(\n \"devportal.manageOAuthApps\",\n \"Manage your OAuth applications and credentials\",\n )}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n <span className=\"ml-2 text-text-secondary\">\n {tr(\"devportal.loadingApps\", \"Loading apps...\")}\n </span>\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.oauthApps\", \"OAuth Apps\")}\n description={tr(\n \"devportal.manageOAuthApps\",\n \"Manage your OAuth applications and credentials\",\n )}\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 {tr(\"devportal.failedToLoadApps\", \"Failed to load apps\")}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {getErrorMessage(error)}\n </p>\n <button\n onClick={() => refetch()}\n className=\"mt-4 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n {tr(\"devportal.tryAgain\", \"Try Again\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n const columns = [\n {\n key: \"name\",\n header: \"App\",\n render: (app: AuthApp) => (\n <div className=\"flex items-center gap-3\">\n <div\n className={cn(\n \"flex h-10 w-10 items-center justify-center rounded-lg\",\n app.status === \"ACTIVE\"\n ? \"bg-action-primary-bg/10 text-primary\"\n : \"bg-bg-sunken text-text-tertiary\",\n )}\n >\n <Shield size={20} />\n </div>\n <div>\n <div className=\"flex items-center gap-2\">\n <p className=\"font-medium\">{app.name}</p>\n <span\n className={cn(\n \"rounded px-1.5 py-0.5 text-xs\",\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 <code className=\"text-xs text-text-secondary\">{app.clientId}</code>\n </div>\n </div>\n ),\n },\n {\n key: \"scopes\",\n header: \"Scopes\",\n render: (app: AuthApp) => (\n <div className=\"flex flex-wrap gap-1\">\n {app.scopes.slice(0, 3).map((scope) => (\n <span\n key={scope}\n className=\"inline-flex rounded bg-bg-sunken px-1.5 py-0.5 text-xs\"\n >\n {scope}\n </span>\n ))}\n {app.scopes.length > 3 && (\n <span className=\"text-xs text-text-secondary\">\n +{app.scopes.length - 3}\n </span>\n )}\n </div>\n ),\n },\n {\n key: \"redirectUris\",\n header: \"Redirect URIs\",\n render: (app: AuthApp) => (\n <span className=\"text-sm\">\n {app.redirectUris.length} URI\n {app.redirectUris.length !== 1 ? \"s\" : \"\"}\n </span>\n ),\n },\n {\n key: \"status\",\n header: \"Status\",\n render: (app: AuthApp) => (\n <div className=\"flex items-center gap-2\">\n <ActiveIndicator active={app.status === \"ACTIVE\"} />\n <span className=\"text-sm\">{app.status}</span>\n </div>\n ),\n },\n ];\n\n // Stats\n const stats = {\n total: apps.length,\n active: apps.filter((a) => a.status === \"ACTIVE\").length,\n integration: apps.filter(\n (a) => a.type === \"INTEGRATION\" || a.type === \"API_INTEGRATION\",\n ).length,\n service: apps.filter((a) => a.type === \"SERVICE\").length,\n };\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.oauthApps\", \"OAuth Apps\")}\n description={tr(\n \"devportal.manageOAuthApps\",\n \"Manage your OAuth applications and credentials\",\n )}\n purpose={tr(\n \"devportal.oauthAppsPurpose\",\n \"OAuth apps let external services sign in users and call the API on their behalf. Register one here to get a client ID and secret, set redirect URIs, and choose the scopes your integration may request.\",\n )}\n actions={\n <button\n onClick={() => handleNavigate(\"/oauth/new\")}\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 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.createOAuthApp\", \"Create OAuth App\")}\n </button>\n }\n >\n {/* Filters */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex flex-1 items-center gap-4\">\n <div className=\"relative flex-1 max-w-md\">\n <Search\n size={16}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary\"\n />\n <input\n type=\"text\"\n placeholder={tr(\n \"devportal.searchByNameOrClientId\",\n \"Search by name or client ID...\",\n )}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-md border bg-bg-surface pl-9 pr-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </div>\n <select\n value={typeFilter}\n onChange={(e) => setTypeFilter(e.target.value)}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"\">{tr(\"devportal.allTypes\", \"All Types\")}</option>\n <option value=\"SERVICE\">\n {tr(\"devportal.service\", \"Service\")}\n </option>\n <option value=\"INTEGRATION\">\n {tr(\"devportal.integration\", \"Integration\")}\n </option>\n <option value=\"BOT\">{tr(\"devportal.bot\", \"Bot\")}</option>\n <option value=\"WEB_APP\">\n {tr(\"devportal.webApp\", \"Web App\")}\n </option>\n <option value=\"AUTOMATION\">\n {tr(\"devportal.automation\", \"Automation\")}\n </option>\n </select>\n </div>\n </div>\n\n {/* Summary Stats — primary emphasis zone */}\n <EmphasisPanel>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-text-secondary\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.totalApps\", \"Total Apps\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.total}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-status-success-text\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.active\", \"Active\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.active}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-accent-blue\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.integration\", \"Integration\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.integration}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-accent-purple\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.service\", \"Service\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.service}\n </p>\n </GlassCard>\n </div>\n </EmphasisPanel>\n\n <p className=\"text-sm text-text-secondary\">\n {filteredApps.length}{\" \"}\n {filteredApps.length !== 1\n ? tr(\"devportal.appsFound\", \"apps found\")\n : tr(\"devportal.appFound\", \"app found\")}\n </p>\n\n {/* Apps Table */}\n {filteredApps.length > 0 ? (\n <DataTable\n data={filteredApps}\n columns={columns}\n keyField=\"id\"\n onRowClick={(app) => handleNavigate(`/oauth/${app.id}`)}\n />\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title={tr(\"devportal.noOAuthAppsFound\", \"No OAuth apps found\")}\n description={\n searchQuery || typeFilter\n ? tr(\n \"devportal.tryAdjustingFilters\",\n \"Try adjusting your filters\",\n )\n : tr(\n \"devportal.createFirstOAuthApp\",\n \"Create your first OAuth app to enable authentication\",\n )\n }\n action={\n !searchQuery && !typeFilter ? (\n <button\n onClick={() => handleNavigate(\"/oauth/new\")}\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 <Plus size={16} />\n {tr(\"devportal.createOAuthApp\", \"Create OAuth App\")}\n </button>\n ) : undefined\n }\n />\n )}\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OAuthClientsPage.js","names":["EmptyState","EmptyState$1","OAuthClientsPage","useDevportal","isFluidgrids","useIsFluidgridsVariant","useI18n","tr","value","t","key","fallback","oauthTitle","createLabel","searchQuery","setSearchQuery","useState","typeFilter","setTypeFilter","useCurrentUserAppsQuery","apps","data","app","handleNavigate","basePath","path","filteredApps","matchesSearch","matchesType","loading","PageLayout","Loader2","error","AlertCircle","getErrorMessage","refetch","columns","cn","Shield","scope","ActiveIndicator","stats","a","PermissionGuard","Plus","Search","EmphasisPanel","GlassCard","DataTable"],"sources":["../../../src/devportal/pages/OAuthClientsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { Plus, Search, Shield, Loader2, AlertCircle } from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { ActiveIndicator } from \"../components/StatusBadge\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport {\n useDevportal,\n useIsFluidgridsVariant,\n} from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport type { AuthApp } from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { useCurrentUserAppsQuery, getErrorMessage } from \"../hooks\";\n\n/**\n * OAuth Apps listing page\n *\n * Displays the current user's OAuth apps from auth-svc.\n * Previously showed devportal-svc OAuthClients per application;\n * now shows all user-owned apps centrally.\n */\nexport const OAuthClientsPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const isFluidgrids = useIsFluidgridsVariant();\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 oauthTitle = isFluidgrids\n ? tr(\"devportal.oauthApps.v2Title\", \"OAuth apps\")\n : tr(\"devportal.oauthApps\", \"OAuth Apps\");\n const createLabel = isFluidgrids\n ? tr(\"devportal.oauthApps.v2Create\", \"Create OAuth app\")\n : tr(\"devportal.createOAuthApp\", \"Create OAuth App\");\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [typeFilter, setTypeFilter] = useState<string>(\"\");\n\n // Fetch apps from auth-svc (user-scoped, no applicationId needed)\n const { data, loading, error, refetch } = useCurrentUserAppsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const apps: AuthApp[] =\n data?.currentUserApps?.apps.map(\n (app: (typeof data.currentUserApps.apps)[number]) => ({\n id: app.id,\n name: app.name,\n description: app.description ?? undefined,\n clientId: app.clientId,\n type: app.type as AuthApp[\"type\"],\n status: app.status as AuthApp[\"status\"],\n scopes: app.scopes ?? [],\n redirectUris: app.redirectUris ?? [],\n ownerUserId: app.ownerUserId,\n tenantId: app.tenantId ?? \"\",\n createdAt: app.createdAt,\n updatedAt: app.updatedAt,\n }),\n ) ?? [];\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n // Filter apps\n const filteredApps = apps.filter((app) => {\n const matchesSearch =\n !searchQuery ||\n app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n app.clientId.toLowerCase().includes(searchQuery.toLowerCase());\n const matchesType = !typeFilter || app.type === typeFilter;\n return matchesSearch && matchesType;\n });\n\n // Loading state\n if (loading && !data) {\n return (\n <PageLayout\n title={oauthTitle}\n description={tr(\n \"devportal.manageOAuthApps\",\n \"Manage your OAuth applications and credentials\",\n )}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n <span className=\"ml-2 text-text-secondary\">\n {tr(\"devportal.loadingApps\", \"Loading apps...\")}\n </span>\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (error) {\n return (\n <PageLayout\n title={oauthTitle}\n description={tr(\n \"devportal.manageOAuthApps\",\n \"Manage your OAuth applications and credentials\",\n )}\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 {tr(\"devportal.failedToLoadApps\", \"Failed to load apps\")}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {getErrorMessage(error)}\n </p>\n <button\n onClick={() => refetch()}\n className=\"mt-4 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n {tr(\"devportal.tryAgain\", \"Try Again\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n const columns = [\n {\n key: \"name\",\n header: \"App\",\n render: (app: AuthApp) => (\n <div className=\"flex items-center gap-3\">\n <div\n className={cn(\n \"flex h-10 w-10 items-center justify-center rounded-lg\",\n app.status === \"ACTIVE\"\n ? \"bg-action-primary-bg/10 text-primary\"\n : \"bg-bg-sunken text-text-tertiary\",\n )}\n >\n <Shield size={20} />\n </div>\n <div>\n <div className=\"flex items-center gap-2\">\n <p className=\"font-medium\">{app.name}</p>\n <span\n className={cn(\n \"rounded px-1.5 py-0.5 text-xs\",\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 <code className=\"text-xs text-text-secondary\">{app.clientId}</code>\n </div>\n </div>\n ),\n },\n {\n key: \"scopes\",\n header: \"Scopes\",\n render: (app: AuthApp) => (\n <div className=\"flex flex-wrap gap-1\">\n {app.scopes.slice(0, 3).map((scope) => (\n <span\n key={scope}\n className=\"inline-flex rounded bg-bg-sunken px-1.5 py-0.5 text-xs\"\n >\n {scope}\n </span>\n ))}\n {app.scopes.length > 3 && (\n <span className=\"text-xs text-text-secondary\">\n +{app.scopes.length - 3}\n </span>\n )}\n </div>\n ),\n },\n {\n key: \"redirectUris\",\n header: \"Redirect URIs\",\n render: (app: AuthApp) => (\n <span className=\"text-sm\">\n {app.redirectUris.length} URI\n {app.redirectUris.length !== 1 ? \"s\" : \"\"}\n </span>\n ),\n },\n {\n key: \"status\",\n header: \"Status\",\n render: (app: AuthApp) => (\n <div className=\"flex items-center gap-2\">\n <ActiveIndicator active={app.status === \"ACTIVE\"} />\n <span className=\"text-sm\">{app.status}</span>\n </div>\n ),\n },\n ];\n\n // Stats\n const stats = {\n total: apps.length,\n active: apps.filter((a) => a.status === \"ACTIVE\").length,\n integration: apps.filter(\n (a) => a.type === \"INTEGRATION\" || a.type === \"API_INTEGRATION\",\n ).length,\n service: apps.filter((a) => a.type === \"SERVICE\").length,\n };\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={oauthTitle}\n description={tr(\n \"devportal.manageOAuthApps\",\n \"Manage your OAuth applications and credentials\",\n )}\n backLink={isFluidgrids ? \"/settings\" : undefined}\n backLabel={tr(\"devportal.developerSettings.back\", \"Developer settings\")}\n purpose={tr(\n \"devportal.oauthAppsPurpose\",\n \"OAuth apps let external services sign in users and call the API on their behalf. Register one here to get a client ID and secret, set redirect URIs, and choose the scopes your integration may request.\",\n )}\n actions={\n <button\n onClick={() => handleNavigate(\"/oauth/new\")}\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 transition-colors\"\n >\n <Plus size={16} />\n {createLabel}\n </button>\n }\n >\n {/* Filters */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex flex-1 items-center gap-4\">\n <div className=\"relative flex-1 max-w-md\">\n <Search\n size={16}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary\"\n />\n <input\n type=\"text\"\n placeholder={tr(\n \"devportal.searchByNameOrClientId\",\n \"Search by name or client ID...\",\n )}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-md border bg-bg-surface pl-9 pr-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </div>\n <select\n value={typeFilter}\n onChange={(e) => setTypeFilter(e.target.value)}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"\">{tr(\"devportal.allTypes\", \"All Types\")}</option>\n <option value=\"SERVICE\">\n {tr(\"devportal.service\", \"Service\")}\n </option>\n <option value=\"INTEGRATION\">\n {tr(\"devportal.integration\", \"Integration\")}\n </option>\n <option value=\"BOT\">{tr(\"devportal.bot\", \"Bot\")}</option>\n <option value=\"WEB_APP\">\n {tr(\"devportal.webApp\", \"Web App\")}\n </option>\n <option value=\"AUTOMATION\">\n {tr(\"devportal.automation\", \"Automation\")}\n </option>\n </select>\n </div>\n </div>\n\n {/* Summary Stats — primary emphasis zone */}\n <EmphasisPanel>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-text-secondary\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.totalApps\", \"Total Apps\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.total}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-status-success-text\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.active\", \"Active\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.active}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-accent-blue\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.integration\", \"Integration\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.integration}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-accent-purple\">\n <Shield size={16} />\n <span className=\"text-sm\">\n {tr(\"devportal.service\", \"Service\")}\n </span>\n </div>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {stats.service}\n </p>\n </GlassCard>\n </div>\n </EmphasisPanel>\n\n <p className=\"text-sm text-text-secondary\">\n {filteredApps.length}{\" \"}\n {filteredApps.length !== 1\n ? tr(\"devportal.appsFound\", \"apps found\")\n : tr(\"devportal.appFound\", \"app found\")}\n </p>\n\n {/* Apps Table */}\n {filteredApps.length > 0 ? (\n <DataTable\n data={filteredApps}\n columns={columns}\n keyField=\"id\"\n onRowClick={(app) => handleNavigate(`/oauth/${app.id}`)}\n />\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title={tr(\"devportal.noOAuthAppsFound\", \"No OAuth apps found\")}\n description={\n searchQuery || typeFilter\n ? tr(\n \"devportal.tryAdjustingFilters\",\n \"Try adjusting your filters\",\n )\n : tr(\n \"devportal.createFirstOAuthApp\",\n \"Create your first OAuth app to enable authentication\",\n )\n }\n action={\n !searchQuery && !typeFilter ? (\n <button\n onClick={() => handleNavigate(\"/oauth/new\")}\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 <Plus size={16} />\n {createLabel}\n </button>\n ) : undefined\n }\n />\n )}\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
@@ -20,8 +20,8 @@ import { useEffect as D, useState as O } from "react";
|
|
|
20
20
|
import { AlertCircle as ae, AppWindow as k, ArrowRight as oe, BarChart3 as A, Building2 as se, CheckCircle as j, CreditCard as ce, DollarSign as M, ExternalLink as N, Loader2 as P, Plus as F, Search as I, Settings as le, Shield as ue, Trash2 as de, TrendingUp as L, Users as R } from "lucide-react";
|
|
21
21
|
import { useParams as fe } from "react-router";
|
|
22
22
|
import { Fragment as pe, jsx as z, jsxs as B } from "react/jsx-runtime";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
23
|
+
import { EmphasisPanel as V, NextSteps as me } from "@burdenoff/fe-libs/ui";
|
|
24
|
+
import { useI18n as H } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
25
25
|
import { clearGraphqlFetchResponseCache as U, graphqlFetch as W } from "@burdenoff/fe-libs/shared/graphql";
|
|
26
26
|
// src/devportal/pages/OrganizationDetailPage.tsx
|
|
27
27
|
var G = "\n query OrganizationVerificationDetails($id: ID!) {\n developerOrganization(id: $id) {\n id\n verificationMethod\n verificationRequestedAt\n verificationStatus\n verificationRequestNotes\n verificationEvidenceUrl\n verificationDomain\n verificationRequestedBy\n verificationReviewedAt\n verificationReviewedBy\n verificationReviewNotes\n verificationRejectedReason\n }\n }\n", he = "\n mutation RequestOrgVerificationExtended(\n $id: ID!\n $method: String!\n $notes: String\n $evidenceUrl: String\n $domain: String\n ) {\n requestOrgVerification(\n id: $id\n method: $method\n notes: $notes\n evidenceUrl: $evidenceUrl\n domain: $domain\n ) {\n id\n verificationMethod\n verificationRequestedAt\n verificationStatus\n verificationRequestNotes\n verificationEvidenceUrl\n verificationDomain\n verificationRejectedReason\n }\n }\n";
|
|
@@ -130,7 +130,7 @@ var Y = {
|
|
|
130
130
|
period: "monthly"
|
|
131
131
|
},
|
|
132
132
|
skip: !l
|
|
133
|
-
}), h = m?.developerOrgRevenueSummary?.currency ?? "USD", { t: g } =
|
|
133
|
+
}), h = m?.developerOrgRevenueSummary?.currency ?? "USD", { t: g } = H(), y = (e, t) => {
|
|
134
134
|
let n = g(e);
|
|
135
135
|
return n === e ? t : n;
|
|
136
136
|
}, [b, S] = O("overview"), [C, ne] = O(!1), { data: re, previousData: ie, loading: oe, error: A } = E({
|
|
@@ -171,7 +171,7 @@ var Y = {
|
|
|
171
171
|
label: y("devportal.settings", "Settings"),
|
|
172
172
|
icon: le
|
|
173
173
|
}
|
|
174
|
-
],
|
|
174
|
+
], V = (j?.developerOrganization?.members ?? []).map(q), U = (s ? V.find((e) => e.userId === s.id) : void 0)?.role, W = U !== void 0 && Y[U] >= Y.DEVELOPER, G = U !== void 0 && Y[U] >= Y.ADMIN, he = G, ge = G, _e = pe.filter((e) => e.id !== "settings" || G), J = (e) => {
|
|
175
175
|
r?.(`${i}${e}`);
|
|
176
176
|
};
|
|
177
177
|
if (D(() => {
|
|
@@ -221,7 +221,7 @@ var Y = {
|
|
|
221
221
|
]
|
|
222
222
|
})
|
|
223
223
|
});
|
|
224
|
-
let X = K(j.developerOrganization), be =
|
|
224
|
+
let X = K(j.developerOrganization), be = V, Z = N?.applications?.edges?.map((e) => e.node) ?? [], Ce = `/billing/earnings?developerOrgId=${encodeURIComponent(X.id)}&developerOrgName=${encodeURIComponent(X.name)}&returnTo=${encodeURIComponent(`${i}${e(c, X.id)}`)}`;
|
|
225
225
|
return /* @__PURE__ */ B(n, {
|
|
226
226
|
title: X.name,
|
|
227
227
|
description: X.description,
|
|
@@ -357,7 +357,7 @@ var Y = {
|
|
|
357
357
|
]
|
|
358
358
|
});
|
|
359
359
|
}, ve = ({ org: e, apps: t, physicalItems: n, members: o, canCreateApps: s, canViewRevenue: u, currency: d, onNavigate: f, onShowApps: p }) => {
|
|
360
|
-
let { t: m } =
|
|
360
|
+
let { t: m } = H(), h = (e, t) => {
|
|
361
361
|
let n = m(e);
|
|
362
362
|
return n === e ? t : n;
|
|
363
363
|
};
|
|
@@ -365,7 +365,7 @@ var Y = {
|
|
|
365
365
|
className: "grid gap-6 lg:grid-cols-3",
|
|
366
366
|
children: [/* @__PURE__ */ B("div", {
|
|
367
367
|
className: "lg:col-span-2 space-y-6",
|
|
368
|
-
children: [/* @__PURE__ */ z(
|
|
368
|
+
children: [/* @__PURE__ */ z(V, { children: /* @__PURE__ */ B(a, {
|
|
369
369
|
columns: e.kind === "PHYSICAL" ? 2 : u ? 4 : 3,
|
|
370
370
|
children: [
|
|
371
371
|
e.kind !== "PHYSICAL" && /* @__PURE__ */ B(pe, { children: [/* @__PURE__ */ z(i, {
|
|
@@ -489,7 +489,7 @@ var Y = {
|
|
|
489
489
|
})]
|
|
490
490
|
});
|
|
491
491
|
}, ye = ({ org: e, apps: t, physicalItems: n, onNavigate: r, canCreateApps: i }) => {
|
|
492
|
-
let { t: a } =
|
|
492
|
+
let { t: a } = H(), o = (e, t) => {
|
|
493
493
|
let n = a(e);
|
|
494
494
|
return n === e ? t : n;
|
|
495
495
|
}, s = e.kind === "PHYSICAL", u = s ? n : t, d = s ? "/seller/items/new" : "/apps/new", f = s ? o("devportal.createItem", "Create Item") : o("devportal.createApp", "Create App"), [p, m] = O(""), h = p.trim().toLowerCase(), g = h ? u.filter((e) => e.name.toLowerCase().includes(h)) : u, _ = h.length > 0;
|
|
@@ -589,7 +589,7 @@ var Y = {
|
|
|
589
589
|
})
|
|
590
590
|
]
|
|
591
591
|
}), xe = ({ members: e, onNavigate: t, orgId: n, canInviteMembers: r }) => {
|
|
592
|
-
let { t: i } =
|
|
592
|
+
let { t: i } = H(), a = (e, t) => {
|
|
593
593
|
let n = i(e);
|
|
594
594
|
return n === e ? t : n;
|
|
595
595
|
};
|
|
@@ -654,7 +654,7 @@ var Y = {
|
|
|
654
654
|
let e = setTimeout(() => l(!1), 2500);
|
|
655
655
|
return o?.(), () => clearTimeout(e);
|
|
656
656
|
}, [a]);
|
|
657
|
-
let { t: p } =
|
|
657
|
+
let { t: p } = H(), { allowed: _ } = b(y.ORG_UPDATE), v = (e, t) => {
|
|
658
658
|
let n = p(e);
|
|
659
659
|
return n === e ? t : n;
|
|
660
660
|
}, [S, C] = O({
|
|
@@ -671,7 +671,7 @@ var Y = {
|
|
|
671
671
|
}), [T, E] = O({
|
|
672
672
|
taxId: e.taxId ?? "",
|
|
673
673
|
taxCountry: e.taxCountry ?? ""
|
|
674
|
-
}), { locations: te, refetch: ae } = g(), [k, oe] = O(!1), [A, se] = O(null), [ce, M] = O(null), [N, I] = O(null), [L, R] = O(null), [fe,
|
|
674
|
+
}), { locations: te, refetch: ae } = g(), [k, oe] = O(!1), [A, se] = O(null), [ce, M] = O(null), [N, I] = O(null), [L, R] = O(null), [fe, V] = O(null), [me, K] = O(null), [q, Y] = O("manual"), [X, ve] = O(!1), [ye, be] = O(""), [Z, xe] = O(""), [Se, Ce] = O(""), [we, Te] = O(null), [Ee, De] = O(!1), Q = we ?? {
|
|
675
675
|
verificationMethod: e.verificationMethod,
|
|
676
676
|
verificationRequestedAt: e.verificationRequestedAt,
|
|
677
677
|
verificationStatus: e.verificationStatus,
|
|
@@ -706,7 +706,7 @@ var Y = {
|
|
|
706
706
|
}).then((e) => Te(e.data?.developerOrganization ?? null)).catch(() => Te(null));
|
|
707
707
|
}, [e.id, X]);
|
|
708
708
|
let Ie = async () => {
|
|
709
|
-
K(null),
|
|
709
|
+
K(null), V(null);
|
|
710
710
|
try {
|
|
711
711
|
await Ae({ variables: {
|
|
712
712
|
id: e.id,
|
|
@@ -719,12 +719,12 @@ var Y = {
|
|
|
719
719
|
logoUrl: S.logoUrl.trim() || null,
|
|
720
720
|
bannerUrl: S.bannerUrl.trim() || null
|
|
721
721
|
}
|
|
722
|
-
} }),
|
|
722
|
+
} }), V(v("devportal.organizationUpdated", "Organization details updated"));
|
|
723
723
|
} catch (e) {
|
|
724
724
|
K(e instanceof Error ? e.message : v("devportal.failedToUpdateOrganization", "Failed to update organization"));
|
|
725
725
|
}
|
|
726
726
|
}, Le = async () => {
|
|
727
|
-
K(null),
|
|
727
|
+
K(null), V(null);
|
|
728
728
|
try {
|
|
729
729
|
await Me({ variables: {
|
|
730
730
|
id: e.id,
|
|
@@ -732,12 +732,12 @@ var Y = {
|
|
|
732
732
|
legalEntityName: w.legalEntityName.trim() || null,
|
|
733
733
|
legalEntityType: w.legalEntityType.trim() || null
|
|
734
734
|
}
|
|
735
|
-
} }),
|
|
735
|
+
} }), V(v("devportal.legalInfoUpdated", "Legal information updated"));
|
|
736
736
|
} catch (e) {
|
|
737
737
|
K(e instanceof Error ? e.message : v("devportal.failedToUpdateLegalInfo", "Failed to update legal information"));
|
|
738
738
|
}
|
|
739
739
|
}, Re = async () => {
|
|
740
|
-
K(null),
|
|
740
|
+
K(null), V(null);
|
|
741
741
|
try {
|
|
742
742
|
await Pe({ variables: {
|
|
743
743
|
id: e.id,
|
|
@@ -745,7 +745,7 @@ var Y = {
|
|
|
745
745
|
taxId: T.taxId.trim() || null,
|
|
746
746
|
taxCountry: T.taxCountry.trim() || null
|
|
747
747
|
}
|
|
748
|
-
} }),
|
|
748
|
+
} }), V(v("devportal.taxInfoUpdated", "Tax information updated"));
|
|
749
749
|
} catch (e) {
|
|
750
750
|
K(e instanceof Error ? e.message : v("devportal.failedToUpdateTaxInfo", "Failed to update tax information"));
|
|
751
751
|
}
|
|
@@ -1224,7 +1224,7 @@ var Y = {
|
|
|
1224
1224
|
else if (q === "document" && !_e(n)) K(v("devportal.verification.errors.evidenceUrlRequired", "Enter a valid evidence URL starting with http:// or https://"));
|
|
1225
1225
|
else if (q === "manual" && !r) K(v("devportal.verification.errors.notesRequired", "Add notes so the reviewer knows what to verify"));
|
|
1226
1226
|
else {
|
|
1227
|
-
K(null),
|
|
1227
|
+
K(null), V(null), De(!0);
|
|
1228
1228
|
try {
|
|
1229
1229
|
await Ae({ variables: {
|
|
1230
1230
|
id: e.id,
|
|
@@ -1262,7 +1262,7 @@ var Y = {
|
|
|
1262
1262
|
}
|
|
1263
1263
|
});
|
|
1264
1264
|
if (i.errors?.length) throw Error(i.errors[0]?.message || "Verification request failed");
|
|
1265
|
-
ve(!0),
|
|
1265
|
+
ve(!0), V(v("devportal.verificationRequested", "Verification request submitted. Our team will review and contact you."));
|
|
1266
1266
|
let a = await W({
|
|
1267
1267
|
gateway: "global",
|
|
1268
1268
|
query: G,
|