@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.
Files changed (78) hide show
  1. package/dist/devportal/DevportalRoot.js +65 -119
  2. package/dist/devportal/DevportalRoot.js.map +1 -1
  3. package/dist/devportal/components/AppCard.js +72 -69
  4. package/dist/devportal/components/AppCard.js.map +1 -1
  5. package/dist/devportal/components/DeveloperSettingsHub.d.ts +6 -0
  6. package/dist/devportal/components/DeveloperSettingsHub.js +59 -0
  7. package/dist/devportal/components/DeveloperSettingsHub.js.map +1 -0
  8. package/dist/devportal/components/ImageUploadField.js +82 -80
  9. package/dist/devportal/components/ImageUploadField.js.map +1 -1
  10. package/dist/devportal/components/SectionNav.d.ts +1 -1
  11. package/dist/devportal/components/SectionNav.js +60 -36
  12. package/dist/devportal/components/SectionNav.js.map +1 -1
  13. package/dist/devportal/components/StoreImage.d.ts +15 -0
  14. package/dist/devportal/components/StoreImage.js +30 -0
  15. package/dist/devportal/components/StoreImage.js.map +1 -0
  16. package/dist/devportal/components/index.d.ts +1 -0
  17. package/dist/devportal/components/index.js +17 -16
  18. package/dist/devportal/hooks/usePackageUpload.d.ts +46 -4
  19. package/dist/devportal/hooks/usePackageUpload.js +90 -36
  20. package/dist/devportal/hooks/usePackageUpload.js.map +1 -1
  21. package/dist/devportal/pages/AdminReviewPage.js +205 -202
  22. package/dist/devportal/pages/AdminReviewPage.js.map +1 -1
  23. package/dist/devportal/pages/AnalyticsDashboardPage.js +186 -179
  24. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  25. package/dist/devportal/pages/ApiKeysPage.js +113 -111
  26. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  27. package/dist/devportal/pages/AppLogsPage.js +80 -84
  28. package/dist/devportal/pages/AppLogsPage.js.map +1 -1
  29. package/dist/devportal/pages/ApplicationDetailPage.js +529 -504
  30. package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
  31. package/dist/devportal/pages/ApplicationsPage.js +186 -183
  32. package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
  33. package/dist/devportal/pages/CreateApiKeyPage.js +163 -166
  34. package/dist/devportal/pages/CreateApiKeyPage.js.map +1 -1
  35. package/dist/devportal/pages/CreateOAuthClientPage.js +134 -130
  36. package/dist/devportal/pages/CreateOAuthClientPage.js.map +1 -1
  37. package/dist/devportal/pages/CreatePhysicalItemPage.js +2 -2
  38. package/dist/devportal/pages/CreatePhysicalItemPage.js.map +1 -1
  39. package/dist/devportal/pages/DelegationsPage.js +11 -11
  40. package/dist/devportal/pages/DocumentationPage.js +100 -94
  41. package/dist/devportal/pages/DocumentationPage.js.map +1 -1
  42. package/dist/devportal/pages/EditApplicationPage.js +379 -377
  43. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  44. package/dist/devportal/pages/EditPhysicalItemPage.js +312 -307
  45. package/dist/devportal/pages/EditPhysicalItemPage.js.map +1 -1
  46. package/dist/devportal/pages/InvitationDecisionPage.js +83 -79
  47. package/dist/devportal/pages/InvitationDecisionPage.js.map +1 -1
  48. package/dist/devportal/pages/ListingPreviewPage.js +175 -171
  49. package/dist/devportal/pages/ListingPreviewPage.js.map +1 -1
  50. package/dist/devportal/pages/OAuthClientDetailPage.js +76 -76
  51. package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
  52. package/dist/devportal/pages/OAuthClientsPage.js +126 -124
  53. package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
  54. package/dist/devportal/pages/OrganizationDetailPage.js +19 -19
  55. package/dist/devportal/pages/OrganizationMembersPage.js +223 -204
  56. package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
  57. package/dist/devportal/pages/ResourcesPage.d.ts +6 -0
  58. package/dist/devportal/pages/ResourcesPage.js +171 -155
  59. package/dist/devportal/pages/ResourcesPage.js.map +1 -1
  60. package/dist/devportal/pages/SellerDashboardPage.js +117 -115
  61. package/dist/devportal/pages/SellerDashboardPage.js.map +1 -1
  62. package/dist/devportal/pages/SellerItemsPage.js +202 -199
  63. package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
  64. package/dist/devportal/pages/SettingsPage.js +330 -315
  65. package/dist/devportal/pages/SettingsPage.js.map +1 -1
  66. package/dist/devportal/pages/SetupPage.js +5 -5
  67. package/dist/devportal/pages/StoreSubmissionPage.js +133 -131
  68. package/dist/devportal/pages/StoreSubmissionPage.js.map +1 -1
  69. package/dist/devportal/pages/WebhookDetailPage.js +6 -6
  70. package/dist/devportal/pages/WebhooksPage.js +39 -39
  71. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  72. package/dist/devportal/utils/appDetailTabs.d.ts +73 -0
  73. package/dist/devportal/utils/appDetailTabs.js +62 -0
  74. package/dist/devportal/utils/appDetailTabs.js.map +1 -0
  75. package/dist/devportal/utils/developerNav.d.ts +39 -0
  76. package/dist/devportal/utils/developerNav.js +304 -0
  77. package/dist/devportal/utils/developerNav.js.map +1 -0
  78. 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 { useI18n as V } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
24
- import { EmphasisPanel as H, NextSteps as me } from "@burdenoff/fe-libs/ui";
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 } = V(), y = (e, t) => {
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
- ], H = (j?.developerOrganization?.members ?? []).map(q), U = (s ? H.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) => {
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 = H, 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)}`)}`;
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 } = V(), h = (e, t) => {
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(H, { children: /* @__PURE__ */ B(a, {
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 } = V(), o = (e, t) => {
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 } = V(), a = (e, t) => {
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 } = V(), { allowed: _ } = b(y.ORG_UPDATE), v = (e, t) => {
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, H] = 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 ?? {
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), H(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
- } }), H(v("devportal.organizationUpdated", "Organization details updated"));
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), H(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
- } }), H(v("devportal.legalInfoUpdated", "Legal information updated"));
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), H(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
- } }), H(v("devportal.taxInfoUpdated", "Tax information updated"));
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), H(null), De(!0);
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), H(v("devportal.verificationRequested", "Verification request submitted. Our team will review and contact you."));
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,