@burdenoff/microfe-devportal 2026.1006.1 → 2026.1013.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/DevportalRoutes.js.map +1 -1
- package/dist/devportal/components/FeatureFlaggedRoute.js.map +1 -1
- package/dist/devportal/components/FormField.d.ts.map +1 -1
- package/dist/devportal/components/FormField.js +1 -1
- package/dist/devportal/components/FormField.js.map +1 -1
- package/dist/devportal/pages/AnalyticsDashboardPage.js +2 -2
- package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
- package/dist/devportal/pages/ApiKeysPage.js +1 -1
- package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
- package/dist/devportal/pages/AppLogsPage.js +1 -1
- package/dist/devportal/pages/AppLogsPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationDetailPage.js +1 -1
- package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationsPage.js +2 -2
- package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
- package/dist/devportal/pages/CreateWebhookPage.js +1 -1
- package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.js +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
- package/dist/devportal/pages/SellerItemsPage.js +1 -1
- package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
- package/dist/devportal/pages/SellerOrdersPage.js +2 -2
- package/dist/devportal/pages/SellerOrdersPage.js.map +1 -1
- package/dist/devportal/pages/WebhooksPage.js +1 -1
- package/dist/devportal/pages/WebhooksPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DevportalRoutes.js","names":[],"sources":["../../src/devportal/DevportalRoutes.tsx"],"sourcesContent":["import { Suspense, lazy, useEffect, type ReactNode } from \"react\";\nimport { Routes, Route, Navigate, Outlet, useLocation } from \"react-router\";\nimport { LoadingState } from \"./components/LoadingState\";\nimport { FeatureFlaggedRoute } from \"./components/FeatureFlaggedRoute\";\nimport { TelemetryErrorBoundary } from \"./components/TelemetryErrorBoundary\";\nimport { OrgSwitcher } from \"./components/SectionNav\";\nimport { useDevportal } from \"./providers/DevportalProvider\";\n\n/**\n * Catch-all redirect target for the unmatched `*` route. Uses the\n * DevportalProvider's `basePath` and `navigate` so the redirect works\n * regardless of the integration mode (shell or standalone). Falls back to a\n * relative Navigate when neither is wired, which is the standalone/test path.\n */\nfunction CatchAllRedirect() {\n const { basePath, navigate } = useDevportal();\n useEffect(() => {\n if (basePath && navigate) {\n const target = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n navigate(target || \"/\");\n }\n }, [basePath, navigate]);\n if (basePath && navigate) return null;\n return <Navigate to=\"..\" replace />;\n}\n\n/**\n * Wrap a page element with the per-route feature flag gate and a\n * telemetry-emitting error boundary. The flag name follows\n * `devportal.<page-slug>` convention; when disabled the user sees a\n * graceful fallback instead of a route-level crash.\n *\n * Per `dev/platform/context/feature-flags` and spec\n * `microfrontends/47-FRONTEND-EVENT-BUS.md` (error.boundary emission).\n */\nfunction gated(slug: string, element: ReactNode): ReactNode {\n return (\n <TelemetryErrorBoundary scope={slug}>\n <FeatureFlaggedRoute flag={`devportal.${slug}`}>\n {element}\n </FeatureFlaggedRoute>\n </TelemetryErrorBoundary>\n );\n}\n\n// Eager load the main dashboard page\nimport { DashboardPage } from \"./pages/DashboardPage\";\n\n// Lazy load all other pages\nconst OrganizationsPage = lazy(() =>\n import(\"./pages/OrganizationsPage\").then((m) => ({\n default: m.OrganizationsPage,\n })),\n);\nconst OrganizationDetailPage = lazy(() =>\n import(\"./pages/OrganizationDetailPage\").then((m) => ({\n default: m.OrganizationDetailPage,\n })),\n);\nconst CreateOrganizationPage = lazy(() =>\n import(\"./pages/CreateOrganizationPage\").then((m) => ({\n default: m.CreateOrganizationPage,\n })),\n);\nconst OrganizationMembersPage = lazy(() =>\n import(\"./pages/OrganizationMembersPage\").then((m) => ({\n default: m.OrganizationMembersPage,\n })),\n);\nconst RevenueDashboardPage = lazy(() =>\n import(\"./pages/RevenueDashboardPage\").then((m) => ({\n default: m.RevenueDashboardPage,\n })),\n);\nconst ApplicationsPage = lazy(() =>\n import(\"./pages/ApplicationsPage\").then((m) => ({\n default: m.ApplicationsPage,\n })),\n);\nconst ApplicationDetailPage = lazy(() =>\n import(\"./pages/ApplicationDetailPage\").then((m) => ({\n default: m.ApplicationDetailPage,\n })),\n);\nconst CreateApplicationPage = lazy(() =>\n import(\"./pages/CreateApplicationPage\").then((m) => ({\n default: m.CreateApplicationPage,\n })),\n);\nconst EditApplicationPage = lazy(() =>\n import(\"./pages/EditApplicationPage\").then((m) => ({\n default: m.EditApplicationPage,\n })),\n);\nconst ApplicationVersionsPage = lazy(() =>\n import(\"./pages/ApplicationVersionsPage\").then((m) => ({\n default: m.ApplicationVersionsPage,\n })),\n);\nconst OAuthCallbackPage = lazy(() =>\n import(\"./pages/OAuthCallbackPage\").then((m) => ({\n default: m.OAuthCallbackPage,\n })),\n);\nconst OAuthClientsPage = lazy(() =>\n import(\"./pages/OAuthClientsPage\").then((m) => ({\n default: m.OAuthClientsPage,\n })),\n);\nconst CreateOAuthClientPage = lazy(() =>\n import(\"./pages/CreateOAuthClientPage\").then((m) => ({\n default: m.CreateOAuthClientPage,\n })),\n);\nconst OAuthClientDetailPage = lazy(() =>\n import(\"./pages/OAuthClientDetailPage\").then((m) => ({\n default: m.OAuthClientDetailPage,\n })),\n);\nconst ApiKeysPage = lazy(() =>\n import(\"./pages/ApiKeysPage\").then((m) => ({ default: m.ApiKeysPage })),\n);\nconst CreateApiKeyPage = lazy(() =>\n import(\"./pages/CreateApiKeyPage\").then((m) => ({\n default: m.CreateApiKeyPage,\n })),\n);\nconst WebhooksPage = lazy(() =>\n import(\"./pages/WebhooksPage\").then((m) => ({ default: m.WebhooksPage })),\n);\nconst CreateWebhookPage = lazy(() =>\n import(\"./pages/CreateWebhookPage\").then((m) => ({\n default: m.CreateWebhookPage,\n })),\n);\nconst WebhookDetailPage = lazy(() =>\n import(\"./pages/WebhookDetailPage\").then((m) => ({\n default: m.WebhookDetailPage,\n })),\n);\nconst AnalyticsDashboardPage = lazy(() =>\n import(\"./pages/AnalyticsDashboardPage\").then((m) => ({\n default: m.AnalyticsDashboardPage,\n })),\n);\nconst DocumentationPage = lazy(() =>\n import(\"./pages/DocumentationPage\").then((m) => ({\n default: m.DocumentationPage,\n })),\n);\nconst ResourcesPage = lazy(() =>\n import(\"./pages/ResourcesPage\").then((m) => ({ default: m.ResourcesPage })),\n);\nconst SettingsPage = lazy(() =>\n import(\"./pages/SettingsPage\").then((m) => ({ default: m.SettingsPage })),\n);\nconst PublishPage = lazy(() =>\n import(\"./pages/PublishPage\").then((m) => ({ default: m.PublishPage })),\n);\nconst AppLogsPage = lazy(() =>\n import(\"./pages/AppLogsPage\").then((m) => ({ default: m.AppLogsPage })),\n);\nconst DelegationsPage = lazy(() =>\n import(\"./pages/DelegationsPage\").then((m) => ({\n default: m.DelegationsPage,\n })),\n);\nconst ListingPreviewPage = lazy(() =>\n import(\"./pages/ListingPreviewPage\").then((m) => ({\n default: m.ListingPreviewPage,\n })),\n);\nconst StoreSubmissionPage = lazy(() =>\n import(\"./pages/StoreSubmissionPage\").then((m) => ({\n default: m.StoreSubmissionPage,\n })),\n);\nconst PublisherProfilePage = lazy(() =>\n import(\"./pages/PublisherProfilePage\").then((m) => ({\n default: m.PublisherProfilePage,\n })),\n);\nconst SetupPage = lazy(() =>\n import(\"./pages/SetupPage\").then((m) => ({ default: m.SetupPage })),\n);\nconst InvitationDecisionPage = lazy(() =>\n import(\"./pages/InvitationDecisionPage\").then((m) => ({\n default: m.InvitationDecisionPage,\n })),\n);\nconst SellerDashboardPage = lazy(() =>\n import(\"./pages/SellerDashboardPage\").then((m) => ({\n default: m.SellerDashboardPage,\n })),\n);\nconst SellerItemsPage = lazy(() =>\n import(\"./pages/SellerItemsPage\").then((m) => ({\n default: m.SellerItemsPage,\n })),\n);\nconst CreatePhysicalItemPage = lazy(() =>\n import(\"./pages/CreatePhysicalItemPage\").then((m) => ({\n default: m.CreatePhysicalItemPage,\n })),\n);\nconst SellerOrdersPage = lazy(() =>\n import(\"./pages/SellerOrdersPage\").then((m) => ({\n default: m.SellerOrdersPage,\n })),\n);\nconst EditPhysicalItemPage = lazy(() =>\n import(\"./pages/EditPhysicalItemPage\").then((m) => ({\n default: m.EditPhysicalItemPage,\n })),\n);\n\n/** Layout for app-context routes (/apps/:appId/*) — adds the org context bar. */\nfunction AppLayout() {\n return (\n <>\n <OrgContextBar />\n <Outlet />\n </>\n );\n}\n\n/** Slim org-context bar shown above every devportal page. */\nfunction OrgContextBar() {\n return (\n <div className=\"flex items-center justify-end border-b border-border-subtle bg-bg-surface/40 px-4 py-2\">\n <OrgSwitcher />\n </div>\n );\n}\n\n/**\n * The org switcher only matters on pages that actually read the active-org\n * state it controls (dashboard, apps, webhooks, analytics, revenue, create\n * flows, etc). Pages that are already scoped by their own route param (an\n * org/item detail page) or that list every org regardless of which one is\n * \"active\" (the org list) don't use that state at all, so showing a\n * switcher there is just confusing. Matched by path suffix so it doesn't\n * care which basePath a given product shell mounts devportal under, and\n * works for both the digital (`organizations`) and seller\n * (`seller/organizations`) route families since they share the same pages.\n */\nfunction hideOrgSwitcher(pathname: string): boolean {\n const segments = pathname.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n const thirdLast = segments[segments.length - 3];\n\n // organizations | seller/organizations (list)\n if (last === \"organizations\") return true;\n // organizations/:id | seller/organizations/:id (detail) — not /new\n if (secondLast === \"organizations\" && last !== \"new\") return true;\n // seller/items/:id (item edit) — not /new\n if (thirdLast === \"seller\" && secondLast === \"items\" && last !== \"new\")\n return true;\n\n return false;\n}\n\n/** Layout wrapping org-context devportal routes — adds the org context bar,\n * except on routes that don't depend on the active-org it controls. */\nfunction GlobalLayout() {\n const { pathname } = useLocation();\n return (\n <>\n {!hideOrgSwitcher(pathname) && <OrgContextBar />}\n <Outlet />\n </>\n );\n}\n\n/** Layout for pages that are not org-scoped (OAuth, API Keys, Docs, Resources). */\nfunction PlainLayout() {\n return <Outlet />;\n}\n\nexport function DevportalRoutes() {\n return (\n <Suspense fallback={<LoadingState message=\"Loading page...\" />}>\n <Routes>\n {/* Setup wizard — no SectionNav */}\n <Route path=\"setup\" element={gated(\"setup\", <SetupPage />)} />\n <Route\n path=\"invitations/:token\"\n element={\n <TelemetryErrorBoundary scope=\"invitations.accept\">\n <InvitationDecisionPage />\n </TelemetryErrorBoundary>\n }\n />\n\n {/* App-context routes (/apps/:appId/*) — no SectionNav.\n The app-level tab bar inside ApplicationDetailPage is the nav here. */}\n <Route element={<AppLayout />}>\n <Route\n path=\"apps/:appId\"\n element={gated(\"apps.detail\", <ApplicationDetailPage />)}\n />\n <Route\n path=\"apps/:appId/edit\"\n element={gated(\"apps.edit\", <EditApplicationPage />)}\n />\n <Route\n path=\"apps/:appId/versions\"\n element={gated(\"apps.versions\", <ApplicationVersionsPage />)}\n />\n <Route\n path=\"apps/:appId/publish\"\n element={gated(\"apps.publish\", <PublishPage />)}\n />\n <Route\n path=\"apps/:appId/store-submission\"\n element={gated(\"apps.storeSubmission\", <StoreSubmissionPage />)}\n />\n <Route\n path=\"apps/:appId/listing\"\n element={gated(\"apps.listing\", <ListingPreviewPage />)}\n />\n <Route\n path=\"apps/:appId/logs\"\n element={gated(\"apps.logs\", <AppLogsPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks\"\n element={gated(\"apps.webhooks\", <WebhooksPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/new\"\n element={gated(\"apps.webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/:webhookId\"\n element={gated(\"apps.webhooks.detail\", <WebhookDetailPage />)}\n />\n <Route\n path=\"apps/:appId/analytics\"\n element={gated(\"apps.analytics\", <AnalyticsDashboardPage />)}\n />\n </Route>\n\n {/* All other routes — with SectionNav */}\n <Route element={<GlobalLayout />}>\n {/* Dashboard */}\n <Route index element={gated(\"dashboard\", <DashboardPage />)} />\n\n {/* Organizations */}\n <Route\n path=\"organizations\"\n element={gated(\"organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"organizations/new\"\n element={gated(\"organizations.create\", <CreateOrganizationPage />)}\n />\n <Route\n path=\"organizations/:orgId\"\n element={gated(\"organizations.detail\", <OrganizationDetailPage />)}\n />\n <Route\n path=\"organizations/:orgId/members\"\n element={gated(\n \"organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"organizations/:orgId/revenue\"\n element={gated(\"organizations.revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Applications list and create */}\n <Route path=\"apps\" element={gated(\"apps\", <ApplicationsPage />)} />\n <Route\n path=\"apps/new\"\n element={gated(\"apps.create\", <CreateApplicationPage />)}\n />\n\n {/* Seller routes */}\n <Route\n path=\"seller\"\n element={gated(\"seller.dashboard\", <SellerDashboardPage />)}\n />\n <Route\n path=\"seller/items\"\n element={gated(\"seller.items\", <SellerItemsPage />)}\n />\n <Route\n path=\"seller/items/new\"\n element={gated(\"seller.items.create\", <CreatePhysicalItemPage />)}\n />\n <Route\n path=\"seller/items/:itemId\"\n element={gated(\"seller.items.edit\", <EditPhysicalItemPage />)}\n />\n <Route\n path=\"seller/orders\"\n element={gated(\"seller.orders\", <SellerOrdersPage />)}\n />\n\n {/* Seller organizations — same pages as the regular \"Organizations\"\n routes above, reused as-is. They tell PHYSICAL from DIGITAL by\n route (useIsSellerSection), not by a separate component. See\n DeveloperOrgKind (BOFF-7285). */}\n <Route\n path=\"seller/organizations\"\n element={gated(\"seller.organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"seller/organizations/new\"\n element={gated(\n \"seller.organizations.create\",\n <CreateOrganizationPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId\"\n element={gated(\n \"seller.organizations.detail\",\n <OrganizationDetailPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/members\"\n element={gated(\n \"seller.organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/revenue\"\n element={gated(\n \"seller.organizations.revenue\",\n <RevenueDashboardPage />,\n )}\n />\n\n {/* Delegations */}\n <Route\n path=\"delegations\"\n element={gated(\"delegations\", <DelegationsPage />)}\n />\n\n {/* Global Webhooks */}\n <Route\n path=\"webhooks/new\"\n element={gated(\"webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"webhooks\"\n element={gated(\"webhooks\", <WebhooksPage />)}\n />\n\n {/* Analytics & Revenue */}\n <Route\n path=\"analytics\"\n element={gated(\"analytics\", <AnalyticsDashboardPage />)}\n />\n <Route\n path=\"revenue\"\n element={gated(\"revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Publisher */}\n <Route\n path=\"publisher/profile\"\n element={gated(\"publisher.profile\", <PublisherProfilePage />)}\n />\n\n {/* Settings */}\n <Route\n path=\"settings\"\n element={gated(\"settings\", <SettingsPage />)}\n />\n\n {/* Catch-all redirect to dashboard */}\n <Route path=\"*\" element={<CatchAllRedirect />} />\n </Route>\n\n {/* Non-org-context routes — no OrgContextBar */}\n <Route element={<PlainLayout />}>\n {/* OAuth Clients */}\n <Route path=\"oauth\" element={gated(\"oauth\", <OAuthClientsPage />)} />\n <Route\n path=\"oauth/new\"\n element={gated(\"oauth.create\", <CreateOAuthClientPage />)}\n />\n <Route\n path=\"oauth/callback\"\n element={gated(\"oauth.callback\", <OAuthCallbackPage />)}\n />\n <Route\n path=\"oauth/:clientId\"\n element={gated(\"oauth.detail\", <OAuthClientDetailPage />)}\n />\n\n {/* API Keys */}\n <Route path=\"api-keys\" element={gated(\"apiKeys\", <ApiKeysPage />)} />\n <Route\n path=\"api-keys/new\"\n element={gated(\"apiKeys.create\", <CreateApiKeyPage />)}\n />\n\n {/* Documentation & Resources */}\n <Route path=\"docs\" element={gated(\"docs\", <DocumentationPage />)} />\n <Route\n path=\"resources\"\n element={gated(\"resources\", <ResourcesPage />)}\n />\n </Route>\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DevportalRoutes.js","names":[],"sources":["../../src/devportal/DevportalRoutes.tsx"],"sourcesContent":["import { Suspense, lazy, useEffect, type ReactNode } from \"react\";\nimport { Routes, Route, Navigate, Outlet, useLocation } from \"react-router\";\nimport { LoadingState } from \"./components/LoadingState\";\nimport { FeatureFlaggedRoute } from \"./components/FeatureFlaggedRoute\";\nimport { TelemetryErrorBoundary } from \"./components/TelemetryErrorBoundary\";\nimport { OrgSwitcher } from \"./components/SectionNav\";\nimport { useDevportal } from \"./providers/DevportalProvider\";\n\n/**\n * Catch-all redirect target for the unmatched `*` route. Uses the\n * DevportalProvider's `basePath` and `navigate` so the redirect works\n * regardless of the integration mode (shell or standalone). Falls back to a\n * relative Navigate when neither is wired, which is the standalone/test path.\n */\nfunction CatchAllRedirect() {\n const { basePath, navigate } = useDevportal();\n useEffect(() => {\n if (basePath && navigate) {\n const target = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n navigate(target || \"/\");\n }\n }, [basePath, navigate]);\n if (basePath && navigate) return null;\n return <Navigate to=\"..\" replace />;\n}\n\n/**\n * Wrap a page element with the per-route feature flag gate and a\n * telemetry-emitting error boundary. The flag name follows\n * `devportal.<page-slug>` convention; when disabled the user sees a\n * graceful fallback instead of a route-level crash.\n *\n * Per `dev/platform/context/commercial/feature-flags` and spec\n * `microfrontends/47-FRONTEND-EVENT-BUS.md` (error.boundary emission).\n */\nfunction gated(slug: string, element: ReactNode): ReactNode {\n return (\n <TelemetryErrorBoundary scope={slug}>\n <FeatureFlaggedRoute flag={`devportal.${slug}`}>\n {element}\n </FeatureFlaggedRoute>\n </TelemetryErrorBoundary>\n );\n}\n\n// Eager load the main dashboard page\nimport { DashboardPage } from \"./pages/DashboardPage\";\n\n// Lazy load all other pages\nconst OrganizationsPage = lazy(() =>\n import(\"./pages/OrganizationsPage\").then((m) => ({\n default: m.OrganizationsPage,\n })),\n);\nconst OrganizationDetailPage = lazy(() =>\n import(\"./pages/OrganizationDetailPage\").then((m) => ({\n default: m.OrganizationDetailPage,\n })),\n);\nconst CreateOrganizationPage = lazy(() =>\n import(\"./pages/CreateOrganizationPage\").then((m) => ({\n default: m.CreateOrganizationPage,\n })),\n);\nconst OrganizationMembersPage = lazy(() =>\n import(\"./pages/OrganizationMembersPage\").then((m) => ({\n default: m.OrganizationMembersPage,\n })),\n);\nconst RevenueDashboardPage = lazy(() =>\n import(\"./pages/RevenueDashboardPage\").then((m) => ({\n default: m.RevenueDashboardPage,\n })),\n);\nconst ApplicationsPage = lazy(() =>\n import(\"./pages/ApplicationsPage\").then((m) => ({\n default: m.ApplicationsPage,\n })),\n);\nconst ApplicationDetailPage = lazy(() =>\n import(\"./pages/ApplicationDetailPage\").then((m) => ({\n default: m.ApplicationDetailPage,\n })),\n);\nconst CreateApplicationPage = lazy(() =>\n import(\"./pages/CreateApplicationPage\").then((m) => ({\n default: m.CreateApplicationPage,\n })),\n);\nconst EditApplicationPage = lazy(() =>\n import(\"./pages/EditApplicationPage\").then((m) => ({\n default: m.EditApplicationPage,\n })),\n);\nconst ApplicationVersionsPage = lazy(() =>\n import(\"./pages/ApplicationVersionsPage\").then((m) => ({\n default: m.ApplicationVersionsPage,\n })),\n);\nconst OAuthCallbackPage = lazy(() =>\n import(\"./pages/OAuthCallbackPage\").then((m) => ({\n default: m.OAuthCallbackPage,\n })),\n);\nconst OAuthClientsPage = lazy(() =>\n import(\"./pages/OAuthClientsPage\").then((m) => ({\n default: m.OAuthClientsPage,\n })),\n);\nconst CreateOAuthClientPage = lazy(() =>\n import(\"./pages/CreateOAuthClientPage\").then((m) => ({\n default: m.CreateOAuthClientPage,\n })),\n);\nconst OAuthClientDetailPage = lazy(() =>\n import(\"./pages/OAuthClientDetailPage\").then((m) => ({\n default: m.OAuthClientDetailPage,\n })),\n);\nconst ApiKeysPage = lazy(() =>\n import(\"./pages/ApiKeysPage\").then((m) => ({ default: m.ApiKeysPage })),\n);\nconst CreateApiKeyPage = lazy(() =>\n import(\"./pages/CreateApiKeyPage\").then((m) => ({\n default: m.CreateApiKeyPage,\n })),\n);\nconst WebhooksPage = lazy(() =>\n import(\"./pages/WebhooksPage\").then((m) => ({ default: m.WebhooksPage })),\n);\nconst CreateWebhookPage = lazy(() =>\n import(\"./pages/CreateWebhookPage\").then((m) => ({\n default: m.CreateWebhookPage,\n })),\n);\nconst WebhookDetailPage = lazy(() =>\n import(\"./pages/WebhookDetailPage\").then((m) => ({\n default: m.WebhookDetailPage,\n })),\n);\nconst AnalyticsDashboardPage = lazy(() =>\n import(\"./pages/AnalyticsDashboardPage\").then((m) => ({\n default: m.AnalyticsDashboardPage,\n })),\n);\nconst DocumentationPage = lazy(() =>\n import(\"./pages/DocumentationPage\").then((m) => ({\n default: m.DocumentationPage,\n })),\n);\nconst ResourcesPage = lazy(() =>\n import(\"./pages/ResourcesPage\").then((m) => ({ default: m.ResourcesPage })),\n);\nconst SettingsPage = lazy(() =>\n import(\"./pages/SettingsPage\").then((m) => ({ default: m.SettingsPage })),\n);\nconst PublishPage = lazy(() =>\n import(\"./pages/PublishPage\").then((m) => ({ default: m.PublishPage })),\n);\nconst AppLogsPage = lazy(() =>\n import(\"./pages/AppLogsPage\").then((m) => ({ default: m.AppLogsPage })),\n);\nconst DelegationsPage = lazy(() =>\n import(\"./pages/DelegationsPage\").then((m) => ({\n default: m.DelegationsPage,\n })),\n);\nconst ListingPreviewPage = lazy(() =>\n import(\"./pages/ListingPreviewPage\").then((m) => ({\n default: m.ListingPreviewPage,\n })),\n);\nconst StoreSubmissionPage = lazy(() =>\n import(\"./pages/StoreSubmissionPage\").then((m) => ({\n default: m.StoreSubmissionPage,\n })),\n);\nconst PublisherProfilePage = lazy(() =>\n import(\"./pages/PublisherProfilePage\").then((m) => ({\n default: m.PublisherProfilePage,\n })),\n);\nconst SetupPage = lazy(() =>\n import(\"./pages/SetupPage\").then((m) => ({ default: m.SetupPage })),\n);\nconst InvitationDecisionPage = lazy(() =>\n import(\"./pages/InvitationDecisionPage\").then((m) => ({\n default: m.InvitationDecisionPage,\n })),\n);\nconst SellerDashboardPage = lazy(() =>\n import(\"./pages/SellerDashboardPage\").then((m) => ({\n default: m.SellerDashboardPage,\n })),\n);\nconst SellerItemsPage = lazy(() =>\n import(\"./pages/SellerItemsPage\").then((m) => ({\n default: m.SellerItemsPage,\n })),\n);\nconst CreatePhysicalItemPage = lazy(() =>\n import(\"./pages/CreatePhysicalItemPage\").then((m) => ({\n default: m.CreatePhysicalItemPage,\n })),\n);\nconst SellerOrdersPage = lazy(() =>\n import(\"./pages/SellerOrdersPage\").then((m) => ({\n default: m.SellerOrdersPage,\n })),\n);\nconst EditPhysicalItemPage = lazy(() =>\n import(\"./pages/EditPhysicalItemPage\").then((m) => ({\n default: m.EditPhysicalItemPage,\n })),\n);\n\n/** Layout for app-context routes (/apps/:appId/*) — adds the org context bar. */\nfunction AppLayout() {\n return (\n <>\n <OrgContextBar />\n <Outlet />\n </>\n );\n}\n\n/** Slim org-context bar shown above every devportal page. */\nfunction OrgContextBar() {\n return (\n <div className=\"flex items-center justify-end border-b border-border-subtle bg-bg-surface/40 px-4 py-2\">\n <OrgSwitcher />\n </div>\n );\n}\n\n/**\n * The org switcher only matters on pages that actually read the active-org\n * state it controls (dashboard, apps, webhooks, analytics, revenue, create\n * flows, etc). Pages that are already scoped by their own route param (an\n * org/item detail page) or that list every org regardless of which one is\n * \"active\" (the org list) don't use that state at all, so showing a\n * switcher there is just confusing. Matched by path suffix so it doesn't\n * care which basePath a given product shell mounts devportal under, and\n * works for both the digital (`organizations`) and seller\n * (`seller/organizations`) route families since they share the same pages.\n */\nfunction hideOrgSwitcher(pathname: string): boolean {\n const segments = pathname.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n const thirdLast = segments[segments.length - 3];\n\n // organizations | seller/organizations (list)\n if (last === \"organizations\") return true;\n // organizations/:id | seller/organizations/:id (detail) — not /new\n if (secondLast === \"organizations\" && last !== \"new\") return true;\n // seller/items/:id (item edit) — not /new\n if (thirdLast === \"seller\" && secondLast === \"items\" && last !== \"new\")\n return true;\n\n return false;\n}\n\n/** Layout wrapping org-context devportal routes — adds the org context bar,\n * except on routes that don't depend on the active-org it controls. */\nfunction GlobalLayout() {\n const { pathname } = useLocation();\n return (\n <>\n {!hideOrgSwitcher(pathname) && <OrgContextBar />}\n <Outlet />\n </>\n );\n}\n\n/** Layout for pages that are not org-scoped (OAuth, API Keys, Docs, Resources). */\nfunction PlainLayout() {\n return <Outlet />;\n}\n\nexport function DevportalRoutes() {\n return (\n <Suspense fallback={<LoadingState message=\"Loading page...\" />}>\n <Routes>\n {/* Setup wizard — no SectionNav */}\n <Route path=\"setup\" element={gated(\"setup\", <SetupPage />)} />\n <Route\n path=\"invitations/:token\"\n element={\n <TelemetryErrorBoundary scope=\"invitations.accept\">\n <InvitationDecisionPage />\n </TelemetryErrorBoundary>\n }\n />\n\n {/* App-context routes (/apps/:appId/*) — no SectionNav.\n The app-level tab bar inside ApplicationDetailPage is the nav here. */}\n <Route element={<AppLayout />}>\n <Route\n path=\"apps/:appId\"\n element={gated(\"apps.detail\", <ApplicationDetailPage />)}\n />\n <Route\n path=\"apps/:appId/edit\"\n element={gated(\"apps.edit\", <EditApplicationPage />)}\n />\n <Route\n path=\"apps/:appId/versions\"\n element={gated(\"apps.versions\", <ApplicationVersionsPage />)}\n />\n <Route\n path=\"apps/:appId/publish\"\n element={gated(\"apps.publish\", <PublishPage />)}\n />\n <Route\n path=\"apps/:appId/store-submission\"\n element={gated(\"apps.storeSubmission\", <StoreSubmissionPage />)}\n />\n <Route\n path=\"apps/:appId/listing\"\n element={gated(\"apps.listing\", <ListingPreviewPage />)}\n />\n <Route\n path=\"apps/:appId/logs\"\n element={gated(\"apps.logs\", <AppLogsPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks\"\n element={gated(\"apps.webhooks\", <WebhooksPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/new\"\n element={gated(\"apps.webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/:webhookId\"\n element={gated(\"apps.webhooks.detail\", <WebhookDetailPage />)}\n />\n <Route\n path=\"apps/:appId/analytics\"\n element={gated(\"apps.analytics\", <AnalyticsDashboardPage />)}\n />\n </Route>\n\n {/* All other routes — with SectionNav */}\n <Route element={<GlobalLayout />}>\n {/* Dashboard */}\n <Route index element={gated(\"dashboard\", <DashboardPage />)} />\n\n {/* Organizations */}\n <Route\n path=\"organizations\"\n element={gated(\"organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"organizations/new\"\n element={gated(\"organizations.create\", <CreateOrganizationPage />)}\n />\n <Route\n path=\"organizations/:orgId\"\n element={gated(\"organizations.detail\", <OrganizationDetailPage />)}\n />\n <Route\n path=\"organizations/:orgId/members\"\n element={gated(\n \"organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"organizations/:orgId/revenue\"\n element={gated(\"organizations.revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Applications list and create */}\n <Route path=\"apps\" element={gated(\"apps\", <ApplicationsPage />)} />\n <Route\n path=\"apps/new\"\n element={gated(\"apps.create\", <CreateApplicationPage />)}\n />\n\n {/* Seller routes */}\n <Route\n path=\"seller\"\n element={gated(\"seller.dashboard\", <SellerDashboardPage />)}\n />\n <Route\n path=\"seller/items\"\n element={gated(\"seller.items\", <SellerItemsPage />)}\n />\n <Route\n path=\"seller/items/new\"\n element={gated(\"seller.items.create\", <CreatePhysicalItemPage />)}\n />\n <Route\n path=\"seller/items/:itemId\"\n element={gated(\"seller.items.edit\", <EditPhysicalItemPage />)}\n />\n <Route\n path=\"seller/orders\"\n element={gated(\"seller.orders\", <SellerOrdersPage />)}\n />\n\n {/* Seller organizations — same pages as the regular \"Organizations\"\n routes above, reused as-is. They tell PHYSICAL from DIGITAL by\n route (useIsSellerSection), not by a separate component. See\n DeveloperOrgKind (BOFF-7285). */}\n <Route\n path=\"seller/organizations\"\n element={gated(\"seller.organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"seller/organizations/new\"\n element={gated(\n \"seller.organizations.create\",\n <CreateOrganizationPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId\"\n element={gated(\n \"seller.organizations.detail\",\n <OrganizationDetailPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/members\"\n element={gated(\n \"seller.organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/revenue\"\n element={gated(\n \"seller.organizations.revenue\",\n <RevenueDashboardPage />,\n )}\n />\n\n {/* Delegations */}\n <Route\n path=\"delegations\"\n element={gated(\"delegations\", <DelegationsPage />)}\n />\n\n {/* Global Webhooks */}\n <Route\n path=\"webhooks/new\"\n element={gated(\"webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"webhooks\"\n element={gated(\"webhooks\", <WebhooksPage />)}\n />\n\n {/* Analytics & Revenue */}\n <Route\n path=\"analytics\"\n element={gated(\"analytics\", <AnalyticsDashboardPage />)}\n />\n <Route\n path=\"revenue\"\n element={gated(\"revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Publisher */}\n <Route\n path=\"publisher/profile\"\n element={gated(\"publisher.profile\", <PublisherProfilePage />)}\n />\n\n {/* Settings */}\n <Route\n path=\"settings\"\n element={gated(\"settings\", <SettingsPage />)}\n />\n\n {/* Catch-all redirect to dashboard */}\n <Route path=\"*\" element={<CatchAllRedirect />} />\n </Route>\n\n {/* Non-org-context routes — no OrgContextBar */}\n <Route element={<PlainLayout />}>\n {/* OAuth Clients */}\n <Route path=\"oauth\" element={gated(\"oauth\", <OAuthClientsPage />)} />\n <Route\n path=\"oauth/new\"\n element={gated(\"oauth.create\", <CreateOAuthClientPage />)}\n />\n <Route\n path=\"oauth/callback\"\n element={gated(\"oauth.callback\", <OAuthCallbackPage />)}\n />\n <Route\n path=\"oauth/:clientId\"\n element={gated(\"oauth.detail\", <OAuthClientDetailPage />)}\n />\n\n {/* API Keys */}\n <Route path=\"api-keys\" element={gated(\"apiKeys\", <ApiKeysPage />)} />\n <Route\n path=\"api-keys/new\"\n element={gated(\"apiKeys.create\", <CreateApiKeyPage />)}\n />\n\n {/* Documentation & Resources */}\n <Route path=\"docs\" element={gated(\"docs\", <DocumentationPage />)} />\n <Route\n path=\"resources\"\n element={gated(\"resources\", <ResourcesPage />)}\n />\n </Route>\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeatureFlaggedRoute.js","names":[],"sources":["../../../src/devportal/components/FeatureFlaggedRoute.tsx"],"sourcesContent":["/**\n * FeatureFlaggedRoute\n *\n * Wraps a route's lazy-loaded element with a feature flag gate.\n * When the flag is disabled the user sees a friendly \"feature unavailable\"\n * message; otherwise the wrapped page renders.\n *\n * Default-allow: if the flag service is unreachable or returns nothing,\n * the FeatureFlagProvider's `defaultEnabled` setting controls behaviour\n * (currently `true` — see `DevportalRoot.tsx`).\n *\n * Per `dev/platform/context/feature-flags`.\n */\nimport type { FC, ReactNode } from \"react\";\nimport { useFeatureFlag } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { EmptyState } from \"./EmptyState\";\n\nexport interface FeatureFlaggedRouteProps {\n flag: string;\n children: ReactNode;\n /** Optional override message; defaults to translated \"coming soon\" copy. */\n fallback?: ReactNode;\n}\n\n/**\n * Safely evaluate a feature flag — `useFeatureFlag` itself throws if no\n * `FeatureFlagProvider` is mounted (standalone dev mode). We always call\n * the hook (rules-of-hooks) and rely on the underlying provider's\n * `defaultEnabled` to default-allow.\n */\nconst useFeatureFlagSafe = (flag: string): boolean => {\n try {\n return useFeatureFlag(flag);\n } catch {\n return true;\n }\n};\n\nconst useI18nSafe = (): {\n t: (key: string, fallback?: string) => string;\n} => {\n try {\n const ctx = useI18n();\n return { t: (key, fallback) => ctx.t(key, fallback) };\n } catch {\n return { t: (key, fallback) => fallback ?? key };\n }\n};\n\nexport const FeatureFlaggedRoute: FC<FeatureFlaggedRouteProps> = ({\n flag,\n children,\n fallback,\n}) => {\n const enabled = useFeatureFlagSafe(flag);\n const { t } = useI18nSafe();\n\n if (enabled) return <>{children}</>;\n if (fallback) return <>{fallback}</>;\n\n return (\n <EmptyState\n title={t(\n \"devportal.featureDisabled.title\",\n \"This feature is currently unavailable\",\n )}\n description={t(\n \"devportal.featureDisabled.description\",\n \"Your administrator has disabled this section. Please check back later.\",\n )}\n />\n );\n};\n"],"mappings":";;;;;AA+BA,IAAM,KAAsB,MAA0B;AACpD,KAAI;AACF,SAAO,EAAe,EAAK;SACrB;AACN,SAAO;;GAIL,UAED;AACH,KAAI;EACF,IAAM,IAAM,GAAS;AACrB,SAAO,EAAE,IAAI,GAAK,MAAa,EAAI,EAAE,GAAK,EAAS,EAAE;SAC/C;AACN,SAAO,EAAE,IAAI,GAAK,MAAa,KAAY,GAAK;;GAIvC,KAAqD,EAChE,SACA,aACA,kBACI;CACJ,IAAM,IAAU,EAAmB,EAAK,EAClC,EAAE,SAAM,GAAa;AAK3B,QAHI,IAAgB,kBAAA,GAAA,EAAG,aAAY,CAAA,GAC/B,IAAiB,kBAAA,GAAA,EAAA,UAAG,GAAY,CAAA,GAGlC,kBAAC,GAAD;EACE,OAAO,EACL,mCACA,wCACD;EACD,aAAa,EACX,yCACA,yEACD;EACD,CAAA"}
|
|
1
|
+
{"version":3,"file":"FeatureFlaggedRoute.js","names":[],"sources":["../../../src/devportal/components/FeatureFlaggedRoute.tsx"],"sourcesContent":["/**\n * FeatureFlaggedRoute\n *\n * Wraps a route's lazy-loaded element with a feature flag gate.\n * When the flag is disabled the user sees a friendly \"feature unavailable\"\n * message; otherwise the wrapped page renders.\n *\n * Default-allow: if the flag service is unreachable or returns nothing,\n * the FeatureFlagProvider's `defaultEnabled` setting controls behaviour\n * (currently `true` — see `DevportalRoot.tsx`).\n *\n * Per `dev/platform/context/commercial/feature-flags`.\n */\nimport type { FC, ReactNode } from \"react\";\nimport { useFeatureFlag } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { EmptyState } from \"./EmptyState\";\n\nexport interface FeatureFlaggedRouteProps {\n flag: string;\n children: ReactNode;\n /** Optional override message; defaults to translated \"coming soon\" copy. */\n fallback?: ReactNode;\n}\n\n/**\n * Safely evaluate a feature flag — `useFeatureFlag` itself throws if no\n * `FeatureFlagProvider` is mounted (standalone dev mode). We always call\n * the hook (rules-of-hooks) and rely on the underlying provider's\n * `defaultEnabled` to default-allow.\n */\nconst useFeatureFlagSafe = (flag: string): boolean => {\n try {\n return useFeatureFlag(flag);\n } catch {\n return true;\n }\n};\n\nconst useI18nSafe = (): {\n t: (key: string, fallback?: string) => string;\n} => {\n try {\n const ctx = useI18n();\n return { t: (key, fallback) => ctx.t(key, fallback) };\n } catch {\n return { t: (key, fallback) => fallback ?? key };\n }\n};\n\nexport const FeatureFlaggedRoute: FC<FeatureFlaggedRouteProps> = ({\n flag,\n children,\n fallback,\n}) => {\n const enabled = useFeatureFlagSafe(flag);\n const { t } = useI18nSafe();\n\n if (enabled) return <>{children}</>;\n if (fallback) return <>{fallback}</>;\n\n return (\n <EmptyState\n title={t(\n \"devportal.featureDisabled.title\",\n \"This feature is currently unavailable\",\n )}\n description={t(\n \"devportal.featureDisabled.description\",\n \"Your administrator has disabled this section. Please check back later.\",\n )}\n />\n );\n};\n"],"mappings":";;;;;AA+BA,IAAM,KAAsB,MAA0B;AACpD,KAAI;AACF,SAAO,EAAe,EAAK;SACrB;AACN,SAAO;;GAIL,UAED;AACH,KAAI;EACF,IAAM,IAAM,GAAS;AACrB,SAAO,EAAE,IAAI,GAAK,MAAa,EAAI,EAAE,GAAK,EAAS,EAAE;SAC/C;AACN,SAAO,EAAE,IAAI,GAAK,MAAa,KAAY,GAAK;;GAIvC,KAAqD,EAChE,SACA,aACA,kBACI;CACJ,IAAM,IAAU,EAAmB,EAAK,EAClC,EAAE,SAAM,GAAa;AAK3B,QAHI,IAAgB,kBAAA,GAAA,EAAG,aAAY,CAAA,GAC/B,IAAiB,kBAAA,GAAA,EAAA,UAAG,GAAY,CAAA,GAGlC,kBAAC,GAAD;EACE,OAAO,EACL,mCACA,wCACD;EACD,aAAa,EACX,yCACA,yEACD;EACD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../../../src/devportal/components/FormField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,OAAO,CAAC;AAIf,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,eACR,SACE,cAAc,EACd,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAC1D,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;CACjE;AAED,UAAU,kBACR,SACE,cAAc,EACd,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,WAAW,CAAC;CAAG;AAErE,UAAU,gBACR,SACE,cAAc,EACd,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;IAC5D,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,kBACR,SACE,cAAc,EACd,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CAiC1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAiChD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../../../src/devportal/components/FormField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,EAAE,EACF,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,OAAO,CAAC;AAIf,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,eACR,SACE,cAAc,EACd,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAC1D,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;CACjE;AAED,UAAU,kBACR,SACE,cAAc,EACd,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,WAAW,CAAC;CAAG;AAErE,UAAU,gBACR,SACE,cAAc,EACd,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;IAC5D,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,kBACR,SACE,cAAc,EACd,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CAiC1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAiChD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CA2C5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAgChD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CA2BA,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAoDA,CAAC"}
|
|
@@ -75,7 +75,7 @@ var i = ({ label: e, error: i, hint: a, required: o, className: s, type: c = "te
|
|
|
75
75
|
}),
|
|
76
76
|
/* @__PURE__ */ r("select", {
|
|
77
77
|
id: h,
|
|
78
|
-
className: t("w-full rounded-md border bg-bg-surface px-3 py-2 text-sm", "focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent", a && "border-status-error-bg focus:ring-status-error-bg"),
|
|
78
|
+
className: t("w-full rounded-md border bg-bg-surface px-3 py-2 text-sm", "focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent", "scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary", a && "border-status-error-bg focus:ring-status-error-bg"),
|
|
79
79
|
...f,
|
|
80
80
|
children: [/* @__PURE__ */ n("option", {
|
|
81
81
|
value: "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormField.js","names":[],"sources":["../../../src/devportal/components/FormField.tsx"],"sourcesContent":["import type {\n FC,\n InputHTMLAttributes,\n TextareaHTMLAttributes,\n SelectHTMLAttributes,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ninterface BaseFieldProps {\n label: string;\n error?: string;\n hint?: string;\n required?: boolean;\n className?: string;\n}\n\ninterface InputFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\"> {\n type?: \"text\" | \"email\" | \"password\" | \"number\" | \"url\" | \"tel\";\n}\n\ninterface TextareaFieldProps\n extends\n BaseFieldProps,\n Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\"> {}\n\ninterface SelectFieldProps\n extends\n BaseFieldProps,\n Omit<SelectHTMLAttributes<HTMLSelectElement>, \"className\"> {\n options: Array<{ value: string; label: string }>;\n placeholder?: string;\n}\n\ninterface CheckboxFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\" | \"type\"> {\n description?: string;\n}\n\n/**\n * Text input field with label and error handling\n */\nexport const InputField: FC<InputFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n type = \"text\",\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <input\n id={fieldId}\n type={type}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Textarea field with label and error handling\n */\nexport const TextareaField: FC<TextareaFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n id,\n rows = 4,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <textarea\n id={fieldId}\n rows={rows}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary resize-none\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Select field with label and error handling\n */\nexport const SelectField: FC<SelectFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n options,\n placeholder,\n id,\n ...props\n}) => {\n const tr = useTr();\n const resolvedPlaceholder =\n placeholder ?? tr(\"devportal.selectAnOption\", \"Select an option\");\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <select\n id={fieldId}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n >\n <option value=\"\">{resolvedPlaceholder}</option>\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Checkbox field with label and description\n */\nexport const CheckboxField: FC<CheckboxFieldProps> = ({\n label,\n description,\n error,\n className,\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"flex items-start gap-3\", className)}>\n <input\n id={fieldId}\n type=\"checkbox\"\n className={cn(\n \"mt-1 h-4 w-4 rounded border-border-default text-primary\",\n \"focus:ring-primary\",\n )}\n {...props}\n />\n <div>\n <label htmlFor={fieldId} className=\"text-sm font-medium cursor-pointer\">\n {label}\n </label>\n {description && (\n <p className=\"text-xs text-text-secondary\">{description}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n </div>\n );\n};\n\n/**\n * Multi-select checkbox group\n */\nexport const CheckboxGroup: FC<{\n label: string;\n options: Array<{ value: string; label: string; description?: string }>;\n value: string[];\n onChange: (values: string[]) => void;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, options, value, onChange, error, hint, className }) => {\n const handleChange = (optionValue: string, checked: boolean) => {\n if (checked) {\n onChange([...value, optionValue]);\n } else {\n onChange(value.filter((v) => v !== optionValue));\n }\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"space-y-2\">\n {options.map((option) => (\n <CheckboxField\n key={option.value}\n label={option.label}\n description={option.description}\n checked={value.includes(option.value)}\n onChange={(e) => handleChange(option.value, e.target.checked)}\n />\n ))}\n </div>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Tag input for multiple values\n */\nexport const TagInput: FC<{\n label: string;\n value: string[];\n onChange: (values: string[]) => void;\n placeholder?: string;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, value, onChange, placeholder, error, hint, className }) => {\n const tr = useTr();\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n const input = e.currentTarget;\n const newValue = input.value.trim();\n if (newValue && !value.includes(newValue)) {\n onChange([...value, newValue]);\n input.value = \"\";\n }\n }\n };\n\n const removeTag = (tagToRemove: string) => {\n onChange(value.filter((tag) => tag !== tagToRemove));\n };\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"flex flex-wrap gap-2 rounded-md border bg-bg-surface p-2\">\n {value.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-full bg-action-primary-bg/10 px-2 py-1 text-xs\"\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => removeTag(tag)}\n className=\"hover:text-status-error-text\"\n >\n ×\n </button>\n </span>\n ))}\n <input\n type=\"text\"\n placeholder={\n value.length === 0\n ? placeholder\n : tr(\"devportal.addMore\", \"Add more...\")\n }\n onKeyDown={handleKeyDown}\n className=\"flex-1 min-w-[100px] bg-transparent text-sm outline-none\"\n />\n </div>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormField.js","names":[],"sources":["../../../src/devportal/components/FormField.tsx"],"sourcesContent":["import type {\n FC,\n InputHTMLAttributes,\n TextareaHTMLAttributes,\n SelectHTMLAttributes,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ninterface BaseFieldProps {\n label: string;\n error?: string;\n hint?: string;\n required?: boolean;\n className?: string;\n}\n\ninterface InputFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\"> {\n type?: \"text\" | \"email\" | \"password\" | \"number\" | \"url\" | \"tel\";\n}\n\ninterface TextareaFieldProps\n extends\n BaseFieldProps,\n Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\"> {}\n\ninterface SelectFieldProps\n extends\n BaseFieldProps,\n Omit<SelectHTMLAttributes<HTMLSelectElement>, \"className\"> {\n options: Array<{ value: string; label: string }>;\n placeholder?: string;\n}\n\ninterface CheckboxFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\" | \"type\"> {\n description?: string;\n}\n\n/**\n * Text input field with label and error handling\n */\nexport const InputField: FC<InputFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n type = \"text\",\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <input\n id={fieldId}\n type={type}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Textarea field with label and error handling\n */\nexport const TextareaField: FC<TextareaFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n id,\n rows = 4,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <textarea\n id={fieldId}\n rows={rows}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary resize-none\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Select field with label and error handling\n */\nexport const SelectField: FC<SelectFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n options,\n placeholder,\n id,\n ...props\n}) => {\n const tr = useTr();\n const resolvedPlaceholder =\n placeholder ?? tr(\"devportal.selectAnOption\", \"Select an option\");\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <select\n id={fieldId}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n >\n <option value=\"\">{resolvedPlaceholder}</option>\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Checkbox field with label and description\n */\nexport const CheckboxField: FC<CheckboxFieldProps> = ({\n label,\n description,\n error,\n className,\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"flex items-start gap-3\", className)}>\n <input\n id={fieldId}\n type=\"checkbox\"\n className={cn(\n \"mt-1 h-4 w-4 rounded border-border-default text-primary\",\n \"focus:ring-primary\",\n )}\n {...props}\n />\n <div>\n <label htmlFor={fieldId} className=\"text-sm font-medium cursor-pointer\">\n {label}\n </label>\n {description && (\n <p className=\"text-xs text-text-secondary\">{description}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n </div>\n );\n};\n\n/**\n * Multi-select checkbox group\n */\nexport const CheckboxGroup: FC<{\n label: string;\n options: Array<{ value: string; label: string; description?: string }>;\n value: string[];\n onChange: (values: string[]) => void;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, options, value, onChange, error, hint, className }) => {\n const handleChange = (optionValue: string, checked: boolean) => {\n if (checked) {\n onChange([...value, optionValue]);\n } else {\n onChange(value.filter((v) => v !== optionValue));\n }\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"space-y-2\">\n {options.map((option) => (\n <CheckboxField\n key={option.value}\n label={option.label}\n description={option.description}\n checked={value.includes(option.value)}\n onChange={(e) => handleChange(option.value, e.target.checked)}\n />\n ))}\n </div>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Tag input for multiple values\n */\nexport const TagInput: FC<{\n label: string;\n value: string[];\n onChange: (values: string[]) => void;\n placeholder?: string;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, value, onChange, placeholder, error, hint, className }) => {\n const tr = useTr();\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n const input = e.currentTarget;\n const newValue = input.value.trim();\n if (newValue && !value.includes(newValue)) {\n onChange([...value, newValue]);\n input.value = \"\";\n }\n }\n };\n\n const removeTag = (tagToRemove: string) => {\n onChange(value.filter((tag) => tag !== tagToRemove));\n };\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"flex flex-wrap gap-2 rounded-md border bg-bg-surface p-2\">\n {value.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-full bg-action-primary-bg/10 px-2 py-1 text-xs\"\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => removeTag(tag)}\n className=\"hover:text-status-error-text\"\n >\n ×\n </button>\n </span>\n ))}\n <input\n type=\"text\"\n placeholder={\n value.length === 0\n ? placeholder\n : tr(\"devportal.addMore\", \"Add more...\")\n }\n onKeyDown={handleKeyDown}\n className=\"flex-1 min-w-[100px] bg-transparent text-sm outline-none\"\n />\n </div>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -131,7 +131,7 @@ var ce = {
|
|
|
131
131
|
value: I,
|
|
132
132
|
onChange: (e) => L(e.target.value),
|
|
133
133
|
"aria-label": N("devportal.analytics.selectAppAria", "Select application"),
|
|
134
|
-
className: "rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary",
|
|
134
|
+
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",
|
|
135
135
|
children: K.map((e) => /* @__PURE__ */ T("option", {
|
|
136
136
|
value: e.id,
|
|
137
137
|
children: e.name
|
|
@@ -140,7 +140,7 @@ var ce = {
|
|
|
140
140
|
value: P,
|
|
141
141
|
onChange: (e) => F(e.target.value),
|
|
142
142
|
"aria-label": N("devportal.analytics.selectRangeAria", "Select time range"),
|
|
143
|
-
className: "rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary",
|
|
143
|
+
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",
|
|
144
144
|
children: [
|
|
145
145
|
/* @__PURE__ */ T("option", {
|
|
146
146
|
value: "7d",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsDashboardPage.js","names":[],"sources":["../../../src/devportal/pages/AnalyticsDashboardPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useParams } from \"react-router\";\nimport {\n Activity,\n AlertCircle,\n AlertTriangle,\n BarChart3,\n Clock,\n Loader2,\n Users,\n} from \"lucide-react\";\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Line,\n LineChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { AppListItem } from \"../components/AppCard\";\nimport type { Application } from \"../types\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n type GetAnalyticsDashboardOptionsQuery,\n getErrorMessage,\n useGetAnalyticsDashboardOptionsQuery,\n useGetApplicationAnalyticsDashboardQuery,\n} from \"../hooks\";\nimport { useTr } from \"../utils/i18n\";\n\ntype TimeRange = \"7d\" | \"30d\" | \"90d\";\n\nconst daysByRange: Record<TimeRange, number> = {\n \"7d\": 7,\n \"30d\": 30,\n \"90d\": 90,\n};\n\nconst chartColors = {\n primary: \"var(--color-chart-1)\",\n secondary: \"var(--color-chart-2)\",\n tertiary: \"var(--color-chart-4)\",\n negative: \"var(--color-chart-negative)\",\n};\n\nexport const AnalyticsDashboardPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath, activeOrgId } = useDevportal();\n const tr = useTr();\n const [timeRange, setTimeRange] = useState<TimeRange>(\"30d\");\n const [selectedApplicationId, setSelectedApplicationId] = useState(\n appId || \"\",\n );\n\n const now = useMemo(() => new Date(), []);\n const startDate = useMemo(() => {\n const nextDate = new Date(now);\n nextDate.setDate(nextDate.getDate() - daysByRange[timeRange]);\n return nextDate.toISOString();\n }, [now, timeRange]);\n\n const {\n data: optionsData,\n loading: optionsLoading,\n error: optionsError,\n } = useGetAnalyticsDashboardOptionsQuery({\n skip: !!appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const { data, loading, error } = useGetApplicationAnalyticsDashboardQuery({\n variables: {\n applicationId: selectedApplicationId || appId || \"\",\n period: \"daily\",\n startDate,\n endDate: now.toISOString(),\n },\n skip: !(selectedApplicationId || appId),\n fetchPolicy: \"cache-and-network\",\n });\n\n const allApplications: Application[] =\n optionsData?.applications?.edges?.map(\n (\n edge: GetAnalyticsDashboardOptionsQuery[\"applications\"][\"edges\"][number],\n ) => edge.node as Application,\n ) ?? [];\n // Scope the app picker to the active org when one is selected\n const applications = activeOrgId\n ? allApplications.filter((a) => a.developerOrganizationId === activeOrgId)\n : allApplications;\n const selectedApplication = data?.application;\n\n useEffect(() => {\n const name = selectedApplication?.name;\n const id = appId || selectedApplicationId;\n if (!id || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(id, name);\n return () => reg?.unregister(id);\n }, [appId, selectedApplicationId, selectedApplication?.name]);\n\n const analytics = [...(data?.applicationAnalytics ?? [])].sort(\n (left, right) =>\n new Date(left.date).getTime() - new Date(right.date).getTime(),\n );\n\n const latest = analytics[analytics.length - 1];\n const previous = analytics[analytics.length - 2];\n const chartData = analytics.map((entry) => ({\n date: new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n }),\n apiCalls: entry.apiCalls,\n errors: entry.errors,\n activeUsers: entry.activeUsers,\n newUsers: entry.newUsers,\n sessions: entry.sessions,\n avgResponseTime: entry.avgResponseTime ?? 0,\n }));\n\n const errorRate =\n latest && latest.apiCalls > 0 ? (latest.errors / latest.apiCalls) * 100 : 0;\n const previousErrorRate =\n previous && previous.apiCalls > 0\n ? (previous.errors / previous.apiCalls) * 100\n : 0;\n const responseTrend =\n latest?.avgResponseTime && previous?.avgResponseTime\n ? previous.avgResponseTime - latest.avgResponseTime\n : undefined;\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n if (!appId && optionsLoading && !optionsData) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )}\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (!appId && optionsError) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.analytics.errorLoadApps\",\n \"Unable to load applications\",\n )}\n description={getErrorMessage(optionsError)}\n />\n </PageLayout>\n );\n }\n\n if (!appId && !selectedApplicationId) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.selectAppDescription\",\n \"Select an application to review live usage metrics from the public gateway\",\n )}\n >\n {applications.length > 0 ? (\n <div className=\"space-y-2\">\n {applications.map((application) => (\n <AppListItem\n key={application.id}\n app={application}\n onClick={() => setSelectedApplicationId(application.id)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BarChart3 size={32} />}\n title={tr(\n \"devportal.analytics.noAppsTitle\",\n \"No applications available\",\n )}\n description={tr(\n \"devportal.analytics.noAppsDescription\",\n \"Create an application before viewing analytics.\",\n )}\n />\n )}\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )}\n backLink={\n selectedApplicationId ? `/apps/${selectedApplicationId}` : undefined\n }\n backLabel={tr(\n \"devportal.analytics.backToApplication\",\n \"Back to Application\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.analytics.errorLoadAnalytics\",\n \"Unable to load analytics\",\n )}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={\n appId\n ? tr(\"devportal.analytics.appTitle\", \"Application Analytics\")\n : tr(\"devportal.analytics.title\", \"Analytics\")\n }\n description={\n selectedApplication\n ? `${tr(\"devportal.analytics.liveUsageFor\", \"Live usage and performance for\")} ${selectedApplication.name}`\n : tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )\n }\n purpose={tr(\n \"devportal.analytics.purpose\",\n \"Analytics shows how your apps are actually used — API call volume, active installs, latency, and error rates over time — so you can spot regressions, plan capacity, and prove value to your users. Pick an app and a time range to drill in.\",\n )}\n backLink={\n appId && selectedApplication\n ? `/apps/${selectedApplication.id}`\n : undefined\n }\n backLabel={tr(\n \"devportal.analytics.backToApplication\",\n \"Back to Application\",\n )}\n actions={\n <div className=\"flex flex-wrap gap-2\">\n {!appId && applications.length > 0 && (\n <select\n value={selectedApplicationId}\n onChange={(event) => setSelectedApplicationId(event.target.value)}\n aria-label={tr(\n \"devportal.analytics.selectAppAria\",\n \"Select application\",\n )}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n {applications.map((application) => (\n <option key={application.id} value={application.id}>\n {application.name}\n </option>\n ))}\n </select>\n )}\n <select\n value={timeRange}\n onChange={(event) => setTimeRange(event.target.value as TimeRange)}\n aria-label={tr(\n \"devportal.analytics.selectRangeAria\",\n \"Select time range\",\n )}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"7d\">\n {tr(\"devportal.analytics.range.7d\", \"Last 7 days\")}\n </option>\n <option value=\"30d\">\n {tr(\"devportal.analytics.range.30d\", \"Last 30 days\")}\n </option>\n <option value=\"90d\">\n {tr(\"devportal.analytics.range.90d\", \"Last 90 days\")}\n </option>\n </select>\n </div>\n }\n >\n {loading && !analytics.length ? (\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n ) : analytics.length > 0 ? (\n <>\n <EmphasisPanel className=\"mb-6\">\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.analytics.apiCalls\", \"API Calls\")}\n value={(latest?.apiCalls ?? 0).toLocaleString()}\n icon={<Activity size={20} />}\n />\n <StatCard\n title={tr(\"devportal.analytics.activeUsers\", \"Active Users\")}\n value={(latest?.activeUsers ?? 0).toLocaleString()}\n icon={<Users size={20} />}\n />\n <StatCard\n title={tr(\"devportal.analytics.errorRate\", \"Error Rate\")}\n value={`${errorRate.toFixed(2)}%`}\n icon={<AlertTriangle size={20} />}\n trend={\n previous\n ? {\n value: previousErrorRate - errorRate,\n label: tr(\n \"devportal.analytics.vsPrevious\",\n \"vs previous period\",\n ),\n }\n : undefined\n }\n />\n <StatCard\n title={tr(\n \"devportal.analytics.avgResponseTime\",\n \"Avg Response Time\",\n )}\n value={\n latest?.avgResponseTime\n ? `${latest.avgResponseTime}ms`\n : tr(\"devportal.common.na\", \"N/A\")\n }\n icon={<Clock size={20} />}\n trend={\n typeof responseTrend === \"number\"\n ? {\n value: responseTrend,\n label: tr(\n \"devportal.analytics.fasterThanPrevious\",\n \"faster than previous\",\n ),\n }\n : undefined\n }\n />\n </StatCardGrid>\n </EmphasisPanel>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.analytics.trafficTrend\", \"Traffic trend\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"apiCalls\"\n stroke={chartColors.primary}\n strokeWidth={2}\n dot={false}\n />\n <Line\n type=\"monotone\"\n dataKey=\"errors\"\n stroke={chartColors.negative}\n strokeWidth={2}\n dot={false}\n />\n </LineChart>\n </ResponsiveContainer>\n </GlassCard>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.analytics.userActivity\", \"User activity\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Bar\n dataKey=\"activeUsers\"\n fill={chartColors.primary}\n radius={[6, 6, 0, 0]}\n />\n <Bar\n dataKey=\"newUsers\"\n fill={chartColors.secondary}\n radius={[6, 6, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n </GlassCard>\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\"devportal.analytics.dailyBreakdown\", \"Daily breakdown\")}\n >\n <DataTable\n data={analytics}\n keyField=\"id\"\n columns={[\n {\n key: \"date\",\n header: tr(\"devportal.analytics.date\", \"Date\"),\n render: (entry) =>\n new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n }),\n },\n {\n key: \"apiCalls\",\n header: tr(\"devportal.analytics.apiCalls\", \"API Calls\"),\n render: (entry) => entry.apiCalls.toLocaleString(),\n },\n {\n key: \"errors\",\n header: tr(\"devportal.analytics.errors\", \"Errors\"),\n render: (entry) => entry.errors.toLocaleString(),\n },\n {\n key: \"activeUsers\",\n header: tr(\"devportal.analytics.activeUsers\", \"Active Users\"),\n render: (entry) => entry.activeUsers.toLocaleString(),\n },\n {\n key: \"newUsers\",\n header: tr(\"devportal.analytics.newUsers\", \"New Users\"),\n render: (entry) => entry.newUsers.toLocaleString(),\n },\n {\n key: \"avgResponseTime\",\n header: tr(\"devportal.analytics.avgResponse\", \"Avg Response\"),\n render: (entry) =>\n entry.avgResponseTime\n ? `${entry.avgResponseTime}ms`\n : tr(\"devportal.common.na\", \"N/A\"),\n },\n {\n key: \"sessions\",\n header: tr(\"devportal.analytics.sessions\", \"Sessions\"),\n render: (entry) => entry.sessions.toLocaleString(),\n },\n ]}\n />\n </PageSection>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BarChart3 size={32} />}\n title={tr(\n \"devportal.analytics.noAnalyticsTitle\",\n \"No analytics available yet\",\n )}\n description={tr(\n \"devportal.analytics.noAnalyticsDescription\",\n \"Analytics will appear after this application starts receiving traffic through the public gateway.\",\n )}\n action={\n !appId ? (\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/apps\")}\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 {tr(\n \"devportal.analytics.viewApplications\",\n \"View applications\",\n )}\n </button>\n ) : undefined\n }\n />\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnalyticsDashboardPage.js","names":[],"sources":["../../../src/devportal/pages/AnalyticsDashboardPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useParams } from \"react-router\";\nimport {\n Activity,\n AlertCircle,\n AlertTriangle,\n BarChart3,\n Clock,\n Loader2,\n Users,\n} from \"lucide-react\";\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Line,\n LineChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { AppListItem } from \"../components/AppCard\";\nimport type { Application } from \"../types\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n type GetAnalyticsDashboardOptionsQuery,\n getErrorMessage,\n useGetAnalyticsDashboardOptionsQuery,\n useGetApplicationAnalyticsDashboardQuery,\n} from \"../hooks\";\nimport { useTr } from \"../utils/i18n\";\n\ntype TimeRange = \"7d\" | \"30d\" | \"90d\";\n\nconst daysByRange: Record<TimeRange, number> = {\n \"7d\": 7,\n \"30d\": 30,\n \"90d\": 90,\n};\n\nconst chartColors = {\n primary: \"var(--color-chart-1)\",\n secondary: \"var(--color-chart-2)\",\n tertiary: \"var(--color-chart-4)\",\n negative: \"var(--color-chart-negative)\",\n};\n\nexport const AnalyticsDashboardPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath, activeOrgId } = useDevportal();\n const tr = useTr();\n const [timeRange, setTimeRange] = useState<TimeRange>(\"30d\");\n const [selectedApplicationId, setSelectedApplicationId] = useState(\n appId || \"\",\n );\n\n const now = useMemo(() => new Date(), []);\n const startDate = useMemo(() => {\n const nextDate = new Date(now);\n nextDate.setDate(nextDate.getDate() - daysByRange[timeRange]);\n return nextDate.toISOString();\n }, [now, timeRange]);\n\n const {\n data: optionsData,\n loading: optionsLoading,\n error: optionsError,\n } = useGetAnalyticsDashboardOptionsQuery({\n skip: !!appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const { data, loading, error } = useGetApplicationAnalyticsDashboardQuery({\n variables: {\n applicationId: selectedApplicationId || appId || \"\",\n period: \"daily\",\n startDate,\n endDate: now.toISOString(),\n },\n skip: !(selectedApplicationId || appId),\n fetchPolicy: \"cache-and-network\",\n });\n\n const allApplications: Application[] =\n optionsData?.applications?.edges?.map(\n (\n edge: GetAnalyticsDashboardOptionsQuery[\"applications\"][\"edges\"][number],\n ) => edge.node as Application,\n ) ?? [];\n // Scope the app picker to the active org when one is selected\n const applications = activeOrgId\n ? allApplications.filter((a) => a.developerOrganizationId === activeOrgId)\n : allApplications;\n const selectedApplication = data?.application;\n\n useEffect(() => {\n const name = selectedApplication?.name;\n const id = appId || selectedApplicationId;\n if (!id || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(id, name);\n return () => reg?.unregister(id);\n }, [appId, selectedApplicationId, selectedApplication?.name]);\n\n const analytics = [...(data?.applicationAnalytics ?? [])].sort(\n (left, right) =>\n new Date(left.date).getTime() - new Date(right.date).getTime(),\n );\n\n const latest = analytics[analytics.length - 1];\n const previous = analytics[analytics.length - 2];\n const chartData = analytics.map((entry) => ({\n date: new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n }),\n apiCalls: entry.apiCalls,\n errors: entry.errors,\n activeUsers: entry.activeUsers,\n newUsers: entry.newUsers,\n sessions: entry.sessions,\n avgResponseTime: entry.avgResponseTime ?? 0,\n }));\n\n const errorRate =\n latest && latest.apiCalls > 0 ? (latest.errors / latest.apiCalls) * 100 : 0;\n const previousErrorRate =\n previous && previous.apiCalls > 0\n ? (previous.errors / previous.apiCalls) * 100\n : 0;\n const responseTrend =\n latest?.avgResponseTime && previous?.avgResponseTime\n ? previous.avgResponseTime - latest.avgResponseTime\n : undefined;\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n if (!appId && optionsLoading && !optionsData) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )}\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (!appId && optionsError) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.analytics.errorLoadApps\",\n \"Unable to load applications\",\n )}\n description={getErrorMessage(optionsError)}\n />\n </PageLayout>\n );\n }\n\n if (!appId && !selectedApplicationId) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.selectAppDescription\",\n \"Select an application to review live usage metrics from the public gateway\",\n )}\n >\n {applications.length > 0 ? (\n <div className=\"space-y-2\">\n {applications.map((application) => (\n <AppListItem\n key={application.id}\n app={application}\n onClick={() => setSelectedApplicationId(application.id)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BarChart3 size={32} />}\n title={tr(\n \"devportal.analytics.noAppsTitle\",\n \"No applications available\",\n )}\n description={tr(\n \"devportal.analytics.noAppsDescription\",\n \"Create an application before viewing analytics.\",\n )}\n />\n )}\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.analytics.title\", \"Analytics\")}\n description={tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )}\n backLink={\n selectedApplicationId ? `/apps/${selectedApplicationId}` : undefined\n }\n backLabel={tr(\n \"devportal.analytics.backToApplication\",\n \"Back to Application\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.analytics.errorLoadAnalytics\",\n \"Unable to load analytics\",\n )}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={\n appId\n ? tr(\"devportal.analytics.appTitle\", \"Application Analytics\")\n : tr(\"devportal.analytics.title\", \"Analytics\")\n }\n description={\n selectedApplication\n ? `${tr(\"devportal.analytics.liveUsageFor\", \"Live usage and performance for\")} ${selectedApplication.name}`\n : tr(\n \"devportal.analytics.description\",\n \"Explore live application usage and performance metrics\",\n )\n }\n purpose={tr(\n \"devportal.analytics.purpose\",\n \"Analytics shows how your apps are actually used — API call volume, active installs, latency, and error rates over time — so you can spot regressions, plan capacity, and prove value to your users. Pick an app and a time range to drill in.\",\n )}\n backLink={\n appId && selectedApplication\n ? `/apps/${selectedApplication.id}`\n : undefined\n }\n backLabel={tr(\n \"devportal.analytics.backToApplication\",\n \"Back to Application\",\n )}\n actions={\n <div className=\"flex flex-wrap gap-2\">\n {!appId && applications.length > 0 && (\n <select\n value={selectedApplicationId}\n onChange={(event) => setSelectedApplicationId(event.target.value)}\n aria-label={tr(\n \"devportal.analytics.selectAppAria\",\n \"Select application\",\n )}\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 {applications.map((application) => (\n <option key={application.id} value={application.id}>\n {application.name}\n </option>\n ))}\n </select>\n )}\n <select\n value={timeRange}\n onChange={(event) => setTimeRange(event.target.value as TimeRange)}\n aria-label={tr(\n \"devportal.analytics.selectRangeAria\",\n \"Select time range\",\n )}\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=\"7d\">\n {tr(\"devportal.analytics.range.7d\", \"Last 7 days\")}\n </option>\n <option value=\"30d\">\n {tr(\"devportal.analytics.range.30d\", \"Last 30 days\")}\n </option>\n <option value=\"90d\">\n {tr(\"devportal.analytics.range.90d\", \"Last 90 days\")}\n </option>\n </select>\n </div>\n }\n >\n {loading && !analytics.length ? (\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n ) : analytics.length > 0 ? (\n <>\n <EmphasisPanel className=\"mb-6\">\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.analytics.apiCalls\", \"API Calls\")}\n value={(latest?.apiCalls ?? 0).toLocaleString()}\n icon={<Activity size={20} />}\n />\n <StatCard\n title={tr(\"devportal.analytics.activeUsers\", \"Active Users\")}\n value={(latest?.activeUsers ?? 0).toLocaleString()}\n icon={<Users size={20} />}\n />\n <StatCard\n title={tr(\"devportal.analytics.errorRate\", \"Error Rate\")}\n value={`${errorRate.toFixed(2)}%`}\n icon={<AlertTriangle size={20} />}\n trend={\n previous\n ? {\n value: previousErrorRate - errorRate,\n label: tr(\n \"devportal.analytics.vsPrevious\",\n \"vs previous period\",\n ),\n }\n : undefined\n }\n />\n <StatCard\n title={tr(\n \"devportal.analytics.avgResponseTime\",\n \"Avg Response Time\",\n )}\n value={\n latest?.avgResponseTime\n ? `${latest.avgResponseTime}ms`\n : tr(\"devportal.common.na\", \"N/A\")\n }\n icon={<Clock size={20} />}\n trend={\n typeof responseTrend === \"number\"\n ? {\n value: responseTrend,\n label: tr(\n \"devportal.analytics.fasterThanPrevious\",\n \"faster than previous\",\n ),\n }\n : undefined\n }\n />\n </StatCardGrid>\n </EmphasisPanel>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.analytics.trafficTrend\", \"Traffic trend\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"apiCalls\"\n stroke={chartColors.primary}\n strokeWidth={2}\n dot={false}\n />\n <Line\n type=\"monotone\"\n dataKey=\"errors\"\n stroke={chartColors.negative}\n strokeWidth={2}\n dot={false}\n />\n </LineChart>\n </ResponsiveContainer>\n </GlassCard>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.analytics.userActivity\", \"User activity\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Bar\n dataKey=\"activeUsers\"\n fill={chartColors.primary}\n radius={[6, 6, 0, 0]}\n />\n <Bar\n dataKey=\"newUsers\"\n fill={chartColors.secondary}\n radius={[6, 6, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n </GlassCard>\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\"devportal.analytics.dailyBreakdown\", \"Daily breakdown\")}\n >\n <DataTable\n data={analytics}\n keyField=\"id\"\n columns={[\n {\n key: \"date\",\n header: tr(\"devportal.analytics.date\", \"Date\"),\n render: (entry) =>\n new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n }),\n },\n {\n key: \"apiCalls\",\n header: tr(\"devportal.analytics.apiCalls\", \"API Calls\"),\n render: (entry) => entry.apiCalls.toLocaleString(),\n },\n {\n key: \"errors\",\n header: tr(\"devportal.analytics.errors\", \"Errors\"),\n render: (entry) => entry.errors.toLocaleString(),\n },\n {\n key: \"activeUsers\",\n header: tr(\"devportal.analytics.activeUsers\", \"Active Users\"),\n render: (entry) => entry.activeUsers.toLocaleString(),\n },\n {\n key: \"newUsers\",\n header: tr(\"devportal.analytics.newUsers\", \"New Users\"),\n render: (entry) => entry.newUsers.toLocaleString(),\n },\n {\n key: \"avgResponseTime\",\n header: tr(\"devportal.analytics.avgResponse\", \"Avg Response\"),\n render: (entry) =>\n entry.avgResponseTime\n ? `${entry.avgResponseTime}ms`\n : tr(\"devportal.common.na\", \"N/A\"),\n },\n {\n key: \"sessions\",\n header: tr(\"devportal.analytics.sessions\", \"Sessions\"),\n render: (entry) => entry.sessions.toLocaleString(),\n },\n ]}\n />\n </PageSection>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BarChart3 size={32} />}\n title={tr(\n \"devportal.analytics.noAnalyticsTitle\",\n \"No analytics available yet\",\n )}\n description={tr(\n \"devportal.analytics.noAnalyticsDescription\",\n \"Analytics will appear after this application starts receiving traffic through the public gateway.\",\n )}\n action={\n !appId ? (\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/apps\")}\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 {tr(\n \"devportal.analytics.viewApplications\",\n \"View applications\",\n )}\n </button>\n ) : undefined\n }\n />\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -292,7 +292,7 @@ var v = (e) => {
|
|
|
292
292
|
}), /* @__PURE__ */ g("select", {
|
|
293
293
|
value: C,
|
|
294
294
|
onChange: (e) => ye(e.target.value),
|
|
295
|
-
className: "rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary",
|
|
295
|
+
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",
|
|
296
296
|
children: [
|
|
297
297
|
/* @__PURE__ */ h("option", {
|
|
298
298
|
value: "all",
|