@wopr-network/platform-ui-core 1.27.7 → 1.27.9
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/next.config.ts +1 -2
- package/package.json +17 -17
- package/src/__tests__/account-switcher.test.tsx +21 -20
- package/src/__tests__/activity-page.test.tsx +2 -6
- package/src/__tests__/add-payment-method-dialog.test.tsx +9 -32
- package/src/__tests__/admin-api.test.ts +1 -6
- package/src/__tests__/admin-gpu-api.test.ts +1 -3
- package/src/__tests__/admin-marketplace-api.test.ts +1 -4
- package/src/__tests__/admin-middleware.test.ts +76 -83
- package/src/__tests__/affiliate-dashboard.test.tsx +3 -3
- package/src/__tests__/api-401-redirect.test.ts +46 -9
- package/src/__tests__/api-client.test.ts +3 -5
- package/src/__tests__/api-config.test.ts +22 -42
- package/src/__tests__/api-fleet-resources.test.ts +1 -2
- package/src/__tests__/api-fleet-trpc.test.ts +2 -8
- package/src/__tests__/api-null-guards.test.ts +3 -1
- package/src/__tests__/audit-log-table-pagination.test.tsx +2 -6
- package/src/__tests__/auth-password-reset.test.tsx +7 -21
- package/src/__tests__/auth-redirect.test.tsx +8 -2
- package/src/__tests__/auth.test.tsx +25 -23
- package/src/__tests__/auto-topup-card.test.tsx +4 -12
- package/src/__tests__/backups-tab.test.tsx +3 -4
- package/src/__tests__/billing-layout-nav-hidden.test.tsx +5 -37
- package/src/__tests__/billing-payment-org-invoices.test.tsx +2 -18
- package/src/__tests__/billing.test.tsx +8 -39
- package/src/__tests__/bot-settings/resources-tab.test.tsx +1 -3
- package/src/__tests__/bot-settings/storage-tab.test.tsx +1 -3
- package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +1 -3
- package/src/__tests__/bot-settings-restart.test.tsx +1 -3
- package/src/__tests__/bot-settings.test.tsx +2 -6
- package/src/__tests__/brand.test.ts +6 -26
- package/src/__tests__/buy-credits-panel.test.tsx +1 -3
- package/src/__tests__/buy-crypto-credits-panel.test.tsx +101 -119
- package/src/__tests__/capability-conflicts.test.ts +2 -8
- package/src/__tests__/capability-resolver.test.tsx +2 -12
- package/src/__tests__/channel-wizard.test.tsx +4 -17
- package/src/__tests__/chat/chat-panel.test.tsx +1 -4
- package/src/__tests__/chat-store.test.ts +5 -15
- package/src/__tests__/command-center.test.tsx +10 -12
- package/src/__tests__/compliance-retention-edit.test.tsx +3 -6
- package/src/__tests__/confirmation-tracker.test.tsx +3 -18
- package/src/__tests__/coupon-input.test.tsx +1 -3
- package/src/__tests__/create-instance.test.tsx +1 -3
- package/src/__tests__/credit-balance.test.tsx +4 -12
- package/src/__tests__/credits.test.tsx +32 -85
- package/src/__tests__/email-verification-banner.test.tsx +2 -6
- package/src/__tests__/error-boundaries.test.tsx +0 -1
- package/src/__tests__/fetch-pricing.test.ts +2 -1
- package/src/__tests__/field-oauth.test.tsx +2 -6
- package/src/__tests__/fixtures/mock-manifests-data.js +1 -3
- package/src/__tests__/fixtures/mock-manifests.ts +2 -4
- package/src/__tests__/fleet-health-timestamp.test.tsx +1 -8
- package/src/__tests__/fleet-health-update.test.tsx +1 -8
- package/src/__tests__/gpu-dashboard.test.tsx +2 -6
- package/src/__tests__/instance-detail.test.tsx +3 -9
- package/src/__tests__/instance-list.test.tsx +1 -5
- package/src/__tests__/layout-snapshots.test.tsx +64 -11
- package/src/__tests__/marketplace-admin.test.tsx +2 -6
- package/src/__tests__/marketplace.test.tsx +11 -35
- package/src/__tests__/merge-api-rates.test.ts +1 -6
- package/src/__tests__/middleware.test.ts +32 -219
- package/src/__tests__/next-config-headers.test.ts +1 -3
- package/src/__tests__/notifications.test.tsx +4 -11
- package/src/__tests__/oauth-buttons.test.tsx +36 -59
- package/src/__tests__/oauth-error-mapping.test.tsx +2 -6
- package/src/__tests__/observability.test.tsx +23 -36
- package/src/__tests__/onboarding-page.test.tsx +4 -6
- package/src/__tests__/org-billing-api.test.tsx +1 -6
- package/src/__tests__/plugin-install-flow.test.tsx +28 -58
- package/src/__tests__/plugin-registry.test.tsx +3 -11
- package/src/__tests__/plugin-tool-sync.test.ts +1 -3
- package/src/__tests__/plugins-catalog-error.test.tsx +2 -6
- package/src/__tests__/plugins-toggle-race.test.tsx +3 -5
- package/src/__tests__/portfolio-chart.test.tsx +2 -6
- package/src/__tests__/promotion-form.test.tsx +2 -6
- package/src/__tests__/promotions-list.test.tsx +1 -3
- package/src/__tests__/provider-key-api.test.ts +2 -1
- package/src/__tests__/resend-verification-button.test.tsx +8 -24
- package/src/__tests__/secrets-audit-pagination.test.tsx +1 -3
- package/src/__tests__/settings.test.tsx +11 -21
- package/src/__tests__/setup-checklist.test.tsx +3 -9
- package/src/__tests__/setup.ts +25 -6
- package/src/__tests__/snapshot-api.test.ts +2 -1
- package/src/__tests__/step-superpowers.test.tsx +1 -3
- package/src/__tests__/tenant-context.test.tsx +1 -6
- package/src/__tests__/tenant-keys-api.test.ts +3 -4
- package/src/__tests__/tenant-table-pagination.test.tsx +2 -6
- package/src/__tests__/terminal-log-cleanup.test.tsx +0 -1
- package/src/__tests__/transaction-history.test.tsx +190 -238
- package/src/__tests__/trpc-types.test.ts +2 -6
- package/src/__tests__/use-chat.test.ts +1 -3
- package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +1 -4
- package/src/__tests__/use-sidecar-bridge.test.tsx +105 -0
- package/src/__tests__/use-webmcp.test.ts +1 -3
- package/src/__tests__/validate-elevenlabs-key.test.ts +2 -1
- package/src/__tests__/verify-page.test.tsx +4 -13
- package/src/__tests__/verify-redirect.test.tsx +2 -6
- package/src/app/(auth)/error.tsx +1 -7
- package/src/app/(auth)/forgot-password/page.tsx +4 -18
- package/src/app/(auth)/login/page.tsx +5 -22
- package/src/app/(auth)/reset-password/page.tsx +2 -12
- package/src/app/(auth)/signup/page.tsx +10 -44
- package/src/app/(auth)/verify/page.tsx +47 -0
- package/src/app/(dashboard)/billing/credits/page.tsx +14 -67
- package/src/app/(dashboard)/billing/error.tsx +2 -10
- package/src/app/(dashboard)/billing/layout.tsx +12 -62
- package/src/app/(dashboard)/billing/payment/page.tsx +17 -68
- package/src/app/(dashboard)/billing/plans/page.tsx +3 -9
- package/src/app/(dashboard)/billing/usage/hosted/page.tsx +8 -25
- package/src/app/(dashboard)/billing/usage/page.tsx +63 -103
- package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +9 -27
- package/src/app/(dashboard)/changesets/[id]/error.tsx +2 -6
- package/src/app/(dashboard)/changesets/error.tsx +1 -7
- package/src/app/(dashboard)/chat/page.tsx +2 -6
- package/src/app/(dashboard)/dashboard/network/page.tsx +5 -19
- package/src/app/(dashboard)/error.tsx +1 -7
- package/src/app/(dashboard)/layout.tsx +15 -36
- package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +14 -51
- package/src/app/(dashboard)/marketplace/error.tsx +1 -7
- package/src/app/(dashboard)/marketplace/page.tsx +6 -27
- package/src/app/(dashboard)/not-found.tsx +2 -5
- package/src/app/(dashboard)/onboarding/page.tsx +5 -22
- package/src/app/(dashboard)/settings/account/page.tsx +1 -6
- package/src/app/(dashboard)/settings/activity/page.tsx +8 -34
- package/src/app/(dashboard)/settings/api-keys/page.tsx +15 -60
- package/src/app/(dashboard)/settings/brain/page.tsx +9 -31
- package/src/app/(dashboard)/settings/error.tsx +2 -10
- package/src/app/(dashboard)/settings/notifications/page.tsx +2 -6
- package/src/app/(dashboard)/settings/org/page.tsx +13 -56
- package/src/app/(dashboard)/settings/page.tsx +1 -0
- package/src/app/(dashboard)/settings/profile/page.tsx +126 -73
- package/src/app/(dashboard)/settings/providers/page.tsx +21 -78
- package/src/app/(dashboard)/settings/secrets/page.tsx +13 -58
- package/src/app/(dashboard)/settings/security/page.tsx +31 -111
- package/src/app/admin/email-templates/email-templates-client.tsx +15 -58
- package/src/app/admin/error.tsx +1 -7
- package/src/app/admin/fleet-updates/error.tsx +1 -7
- package/src/app/admin/fleet-updates/fleet-updates-client.tsx +10 -50
- package/src/app/admin/layout.tsx +4 -0
- package/src/app/admin/payment-methods/page.tsx +9 -38
- package/src/app/admin/products/error.tsx +2 -7
- package/src/app/admin/products/page.tsx +1 -4
- package/src/app/admin/promotions/[id]/page.tsx +9 -38
- package/src/app/admin/promotions/page.tsx +9 -36
- package/src/app/admin/rate-overrides/page.tsx +9 -45
- package/src/app/auth/callback/[provider]/page.tsx +1 -8
- package/src/app/auth/verify/page.tsx +9 -36
- package/src/app/channels/error.tsx +2 -10
- package/src/app/channels/layout.tsx +9 -0
- package/src/app/channels/page.tsx +8 -20
- package/src/app/channels/setup/[plugin]/page.tsx +3 -5
- package/src/app/error.tsx +1 -7
- package/src/app/fleet/error.tsx +1 -7
- package/src/app/fleet/layout.tsx +5 -0
- package/src/app/fleet/settings/page.tsx +1 -3
- package/src/app/global-error.tsx +2 -10
- package/src/app/globals.css +1 -4
- package/src/app/instances/[id]/instance-detail-client.tsx +51 -125
- package/src/app/instances/error.tsx +2 -10
- package/src/app/instances/instance-list-client.tsx +20 -69
- package/src/app/instances/layout.tsx +9 -0
- package/src/app/instances/new/create-instance-client.tsx +10 -31
- package/src/app/layout.tsx +2 -10
- package/src/app/not-found.tsx +1 -3
- package/src/app/page.tsx +1 -2
- package/src/app/plugins/error.tsx +2 -10
- package/src/app/plugins/layout.tsx +5 -0
- package/src/app/plugins/page.tsx +16 -48
- package/src/app/pricing/error.tsx +1 -7
- package/src/app/privacy/page.tsx +93 -150
- package/src/app/status/error.tsx +1 -7
- package/src/app/terms/page.tsx +89 -144
- package/src/components/account-switcher.tsx +25 -52
- package/src/components/admin/accounting-dashboard.tsx +1 -3
- package/src/components/admin/admin-guard.tsx +1 -3
- package/src/components/admin/admin-nav.tsx +1 -3
- package/src/components/admin/affiliate-dashboard.tsx +25 -94
- package/src/components/admin/audit-log-table.tsx +13 -49
- package/src/components/admin/billing-health-dashboard.tsx +7 -25
- package/src/components/admin/bulk-actions-bar.test.tsx +1 -7
- package/src/components/admin/bulk-actions-bar.tsx +1 -3
- package/src/components/admin/bulk-export-dialog.test.tsx +1 -7
- package/src/components/admin/bulk-export-dialog.tsx +6 -32
- package/src/components/admin/bulk-grant-dialog.test.tsx +2 -6
- package/src/components/admin/bulk-grant-dialog.tsx +4 -15
- package/src/components/admin/bulk-preview-dialog.tsx +3 -12
- package/src/components/admin/bulk-reactivate-dialog.tsx +1 -7
- package/src/components/admin/bulk-select-all-banner.tsx +1 -6
- package/src/components/admin/bulk-suspend-dialog.tsx +5 -12
- package/src/components/admin/bulk-undo-toast.tsx +1 -2
- package/src/components/admin/compliance-dashboard.tsx +31 -101
- package/src/components/admin/gpu-dashboard.tsx +21 -70
- package/src/components/admin/grant-credits-dialog.tsx +4 -17
- package/src/components/admin/incident-dashboard.tsx +10 -25
- package/src/components/admin/inference-dashboard.tsx +14 -54
- package/src/components/admin/marketplace-admin.tsx +18 -60
- package/src/components/admin/migrations-dashboard.tsx +9 -42
- package/src/components/admin/onboarding-dashboard.tsx +14 -64
- package/src/components/admin/pool-config-dashboard.tsx +4 -10
- package/src/components/admin/products/fleet-form.tsx +2 -11
- package/src/components/admin/products/nav-editor.tsx +3 -10
- package/src/components/admin/promotions/promotion-form.tsx +9 -42
- package/src/components/admin/roles-dashboard.tsx +7 -34
- package/src/components/admin/suspend-dialog.tsx +4 -11
- package/src/components/admin/tenant-notes-panel.tsx +1 -3
- package/src/components/admin/tenant-row-actions.tsx +4 -20
- package/src/components/admin/tenant-table.tsx +12 -49
- package/src/components/auth/auth-redirect.tsx +11 -3
- package/src/components/auth/email-verification-result-banner.tsx +1 -3
- package/src/components/auth/resend-verification-button.tsx +2 -10
- package/src/components/auth/wopr-wordmark.tsx +1 -3
- package/src/components/billing/add-payment-method-dialog.tsx +1 -2
- package/src/components/billing/affiliate-dashboard.tsx +4 -16
- package/src/components/billing/amount-selector.tsx +1 -3
- package/src/components/billing/auto-topup-card.tsx +2 -11
- package/src/components/billing/buy-credits-panel.tsx +14 -17
- package/src/components/billing/byok-callout.tsx +6 -8
- package/src/components/billing/confirmation-tracker.tsx +4 -14
- package/src/components/billing/credit-balance-badge.tsx +22 -0
- package/src/components/billing/credit-balance.tsx +3 -9
- package/src/components/billing/crypto-checkout.tsx +5 -24
- package/src/components/billing/degraded-state-banner.tsx +1 -3
- package/src/components/billing/deposit-view.tsx +301 -41
- package/src/components/billing/dividend-banner.tsx +1 -3
- package/src/components/billing/dividend-eligibility.tsx +3 -12
- package/src/components/billing/dividend-pool-stats.tsx +6 -20
- package/src/components/billing/first-dividend-dialog.tsx +2 -2
- package/src/components/billing/org-billing-page.tsx +8 -31
- package/src/components/billing/payment-method-picker.tsx +2 -10
- package/src/components/billing/suspension-banner.tsx +2 -7
- package/src/components/billing/transaction-history.tsx +10 -58
- package/src/components/billing/unified-checkout.tsx +547 -0
- package/src/components/bot-settings/backups-tab.tsx +9 -33
- package/src/components/bot-settings/bot-settings-client.tsx +32 -134
- package/src/components/bot-settings/resources-tab.tsx +2 -9
- package/src/components/bot-settings/storage-tab.tsx +19 -48
- package/src/components/bot-settings/vps-info-panel.tsx +3 -11
- package/src/components/bot-settings/vps-upgrade-card.tsx +3 -4
- package/src/components/brand-hydrator.tsx +13 -0
- package/src/components/channel-wizard/field-interactive.tsx +1 -3
- package/src/components/channel-wizard/field-qr.tsx +10 -39
- package/src/components/channel-wizard/step-renderer.tsx +5 -28
- package/src/components/channel-wizard/wizard.tsx +6 -31
- package/src/components/chat/chat-message.tsx +1 -4
- package/src/components/chat/chat-panel.tsx +4 -18
- package/src/components/chat/chat-widget.tsx +3 -14
- package/src/components/dashboard/command-center.tsx +15 -61
- package/src/components/fleet/update-settings-card.tsx +7 -23
- package/src/components/instance-update-banner.tsx +130 -0
- package/src/components/instances/friends-tab.test.tsx +2 -9
- package/src/components/instances/friends-tab.tsx +18 -74
- package/src/components/instances/update-available-badge.tsx +2 -11
- package/src/components/landing/hero.tsx +3 -9
- package/src/components/landing/landing-page.tsx +1 -3
- package/src/components/landing/portfolio-chart.tsx +4 -9
- package/src/components/landing/story-sections.tsx +1 -3
- package/src/components/landing/terminal-sequence.tsx +4 -17
- package/src/components/marketplace/empty-state.tsx +2 -6
- package/src/components/marketplace/first-visit-hero.tsx +1 -3
- package/src/components/marketplace/install-wizard.tsx +20 -77
- package/src/components/marketplace/marketplace-tabs.tsx +1 -4
- package/src/components/marketplace/plugin-card.tsx +2 -9
- package/src/components/marketplace/superpower-content.tsx +1 -3
- package/src/components/marketplace/terminal-search.tsx +2 -8
- package/src/components/oauth-buttons.tsx +29 -14
- package/src/components/observability/fleet-health.tsx +5 -18
- package/src/components/observability/health-overview.tsx +7 -20
- package/src/components/observability/logs-viewer.tsx +8 -32
- package/src/components/observability/metrics-dashboard.tsx +2 -15
- package/src/components/onboarding/fallback-setup.tsx +6 -25
- package/src/components/onboarding/setup-checklist.tsx +18 -51
- package/src/components/onboarding/step-superpowers.tsx +1 -4
- package/src/components/plugin-setup/setup-chat-panel.tsx +6 -22
- package/src/components/pricing/dividend-calculator.tsx +6 -12
- package/src/components/pricing/dividend-stats.tsx +5 -17
- package/src/components/pricing/pricing-page.tsx +17 -36
- package/src/components/settings/create-org-wizard.tsx +2 -5
- package/src/components/sidebar.tsx +7 -42
- package/src/components/sidecar-frame.tsx +78 -0
- package/src/components/status/status-page.tsx +6 -28
- package/src/components/ui/alert-dialog.tsx +8 -25
- package/src/components/ui/badge.tsx +2 -8
- package/src/components/ui/banner.tsx +1 -6
- package/src/components/ui/card.tsx +5 -24
- package/src/components/ui/checkbox.tsx +1 -5
- package/src/components/ui/collapsible.tsx +3 -8
- package/src/components/ui/dialog.tsx +4 -10
- package/src/components/ui/dropdown-menu.tsx +9 -18
- package/src/components/ui/form.tsx +2 -16
- package/src/components/ui/popover.tsx +3 -23
- package/src/components/ui/progress.tsx +1 -5
- package/src/components/ui/radio-group.tsx +3 -15
- package/src/components/ui/select.tsx +4 -17
- package/src/components/ui/sheet.tsx +5 -19
- package/src/components/ui/skeleton.tsx +1 -7
- package/src/components/ui/table.tsx +5 -22
- package/src/components/ui/tabs.tsx +3 -13
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/components/unified-sidebar.tsx +493 -0
- package/src/hooks/__tests__/use-fleet-sse.test.ts +1 -4
- package/src/hooks/__tests__/use-save-queue.test.ts +2 -8
- package/src/hooks/use-credit-balance.ts +27 -0
- package/src/hooks/use-my-org-role.ts +1 -3
- package/src/hooks/use-plugin-registry.ts +8 -14
- package/src/hooks/use-plugin-setup-chat.ts +2 -5
- package/src/hooks/use-sidecar-bridge.tsx +148 -0
- package/src/hooks/use-webmcp.ts +1 -4
- package/src/lib/__tests__/admin-api.test.ts +1 -3
- package/src/lib/__tests__/api-bot-crud.test.ts +8 -18
- package/src/lib/__tests__/api-fetch.test.ts +4 -16
- package/src/lib/__tests__/org-billing-api.test.ts +1 -3
- package/src/lib/__tests__/pricing-data.test.ts +0 -8
- package/src/lib/__tests__/settings-api.test.ts +1 -3
- package/src/lib/admin-affiliate-api.ts +2 -7
- package/src/lib/admin-api.ts +6 -26
- package/src/lib/admin-incident-api.ts +11 -19
- package/src/lib/admin-marketplace-api.ts +1 -5
- package/src/lib/api-config.test.ts +5 -50
- package/src/lib/api.ts +143 -122
- package/src/lib/auth-client.ts +1 -2
- package/src/lib/bot-settings-data.ts +11 -36
- package/src/lib/brand-config.ts +56 -115
- package/src/lib/brand.ts +2 -15
- package/src/lib/chat/use-chat.ts +2 -7
- package/src/lib/cost-comparison-data.test.ts +1 -3
- package/src/lib/cost-comparison-data.ts +1 -4
- package/src/lib/errors.ts +1 -4
- package/src/lib/fetch-utils.test.ts +26 -9
- package/src/lib/fetch-utils.ts +40 -11
- package/src/lib/logger.ts +2 -0
- package/src/lib/marketplace-data.ts +3 -11
- package/src/lib/oauth-errors.ts +2 -4
- package/src/lib/onboarding-data.ts +3 -11
- package/src/lib/org-api.ts +2 -10
- package/src/lib/org-billing-api.ts +5 -19
- package/src/lib/plugin/tool-definitions.ts +1 -2
- package/src/lib/require-auth.ts +57 -0
- package/src/lib/settings-api.ts +1 -4
- package/src/lib/sidecar-routes.ts +43 -0
- package/src/lib/trpc-server.ts +49 -0
- package/src/lib/trpc-types.ts +4 -6
- package/src/lib/trpc.tsx +12 -4
- package/src/lib/validate-redirect-url.ts +1 -4
- package/src/lib/webmcp/marketplace-onboarding-tools.ts +6 -16
- package/src/lib/webmcp/register.ts +1 -4
- package/src/lib/webmcp/tools.ts +2 -9
- package/src/proxy.ts +35 -212
- package/src/types/missing-deps.d.ts +2 -8
- package/tsconfig.json +1 -8
- package/biome.json +0 -52
- package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +0 -741
- package/src/__tests__/billing-byok-callout.test.tsx +0 -76
- package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +0 -112
|
@@ -3,28 +3,10 @@
|
|
|
3
3
|
import { motion } from "framer-motion";
|
|
4
4
|
import { Check } from "lucide-react";
|
|
5
5
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
-
import {
|
|
7
|
-
Area,
|
|
8
|
-
AreaChart,
|
|
9
|
-
CartesianGrid,
|
|
10
|
-
ResponsiveContainer,
|
|
11
|
-
Tooltip,
|
|
12
|
-
XAxis,
|
|
13
|
-
YAxis,
|
|
14
|
-
} from "recharts";
|
|
6
|
+
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
|
|
15
7
|
import { Button } from "@/components/ui/button";
|
|
16
|
-
import type {
|
|
17
|
-
|
|
18
|
-
DailyCostAggregate,
|
|
19
|
-
PageCostAggregate,
|
|
20
|
-
SessionCostSummary,
|
|
21
|
-
} from "@/lib/admin-inference-api";
|
|
22
|
-
import {
|
|
23
|
-
getCacheStats,
|
|
24
|
-
getDailyCost,
|
|
25
|
-
getPageCost,
|
|
26
|
-
getSessionCost,
|
|
27
|
-
} from "@/lib/admin-inference-api";
|
|
8
|
+
import type { CacheStats, DailyCostAggregate, PageCostAggregate, SessionCostSummary } from "@/lib/admin-inference-api";
|
|
9
|
+
import { getCacheStats, getDailyCost, getPageCost, getSessionCost } from "@/lib/admin-inference-api";
|
|
28
10
|
import { cn } from "@/lib/utils";
|
|
29
11
|
|
|
30
12
|
// ---- Time ranges ----
|
|
@@ -88,9 +70,7 @@ function KpiCard({ label, value, subtext, valueClassName, loading, index }: KpiC
|
|
|
88
70
|
{loading ? (
|
|
89
71
|
<div className="h-8 w-24 bg-muted animate-pulse rounded-sm" />
|
|
90
72
|
) : (
|
|
91
|
-
<div className={`text-2xl font-bold tabular-nums ${valueClassName ?? "text-foreground"}`}>
|
|
92
|
-
{value}
|
|
93
|
-
</div>
|
|
73
|
+
<div className={`text-2xl font-bold tabular-nums ${valueClassName ?? "text-foreground"}`}>{value}</div>
|
|
94
74
|
)}
|
|
95
75
|
{subtext && <div className="text-xs text-muted-foreground mt-1">{subtext}</div>}
|
|
96
76
|
</motion.div>
|
|
@@ -112,9 +92,7 @@ function ChartTooltip({
|
|
|
112
92
|
return (
|
|
113
93
|
<div className="bg-card border border-terminal/30 rounded-sm shadow-lg shadow-terminal/5 px-3 py-2">
|
|
114
94
|
<div className="text-xs text-muted-foreground">{label}</div>
|
|
115
|
-
<div className="text-sm font-bold tabular-nums text-foreground">
|
|
116
|
-
${payload[0].value.toFixed(4)}
|
|
117
|
-
</div>
|
|
95
|
+
<div className="text-sm font-bold tabular-nums text-foreground">${payload[0].value.toFixed(4)}</div>
|
|
118
96
|
</div>
|
|
119
97
|
);
|
|
120
98
|
}
|
|
@@ -198,9 +176,7 @@ export function InferenceDashboard() {
|
|
|
198
176
|
|
|
199
177
|
{/* Error state */}
|
|
200
178
|
{error && (
|
|
201
|
-
<div className="mx-6 p-4 bg-card border border-destructive/30 rounded-sm text-destructive text-sm">
|
|
202
|
-
{error}
|
|
203
|
-
</div>
|
|
179
|
+
<div className="mx-6 p-4 bg-card border border-destructive/30 rounded-sm text-destructive text-sm">{error}</div>
|
|
204
180
|
)}
|
|
205
181
|
|
|
206
182
|
{/* KPI Cards */}
|
|
@@ -247,9 +223,7 @@ export function InferenceDashboard() {
|
|
|
247
223
|
transition={{ duration: 0.4, delay: 0.2, ease: "easeOut" }}
|
|
248
224
|
className="mx-6 bg-card border border-border rounded-sm p-4"
|
|
249
225
|
>
|
|
250
|
-
<div className="text-xs uppercase tracking-widest text-muted-foreground mb-3">
|
|
251
|
-
DAILY COST
|
|
252
|
-
</div>
|
|
226
|
+
<div className="text-xs uppercase tracking-widest text-muted-foreground mb-3">DAILY COST</div>
|
|
253
227
|
{loading ? (
|
|
254
228
|
<div className="h-[280px] bg-muted/20 animate-pulse rounded-sm" />
|
|
255
229
|
) : dailyCost.length === 0 ? (
|
|
@@ -294,9 +268,7 @@ export function InferenceDashboard() {
|
|
|
294
268
|
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4 px-6 pb-6">
|
|
295
269
|
{/* Page Cost Table */}
|
|
296
270
|
<div className="bg-card border border-border rounded-sm p-4">
|
|
297
|
-
<div className="text-xs uppercase tracking-widest text-muted-foreground mb-3">
|
|
298
|
-
COST BY PAGE
|
|
299
|
-
</div>
|
|
271
|
+
<div className="text-xs uppercase tracking-widest text-muted-foreground mb-3">COST BY PAGE</div>
|
|
300
272
|
{loading ? (
|
|
301
273
|
<div className="space-y-3">
|
|
302
274
|
{["sk-1", "sk-2", "sk-3", "sk-4", "sk-5"].map((id) => (
|
|
@@ -320,14 +292,10 @@ export function InferenceDashboard() {
|
|
|
320
292
|
>
|
|
321
293
|
<div className="flex-1 text-sm font-medium">{p.page || "/unknown"}</div>
|
|
322
294
|
<div className="w-20 text-right tabular-nums text-sm">{p.callCount}</div>
|
|
323
|
-
<div className="w-24 text-right tabular-nums text-sm">
|
|
324
|
-
${p.avgCostUsd.toFixed(4)}
|
|
325
|
-
</div>
|
|
295
|
+
<div className="w-24 text-right tabular-nums text-sm">${p.avgCostUsd.toFixed(4)}</div>
|
|
326
296
|
<div
|
|
327
297
|
className={`w-24 text-right tabular-nums text-sm font-medium ${
|
|
328
|
-
p.totalCostUsd === maxPageCost && maxPageCost > 0
|
|
329
|
-
? "text-amber-400"
|
|
330
|
-
: "text-foreground"
|
|
298
|
+
p.totalCostUsd === maxPageCost && maxPageCost > 0 ? "text-amber-400" : "text-foreground"
|
|
331
299
|
}`}
|
|
332
300
|
>
|
|
333
301
|
${p.totalCostUsd.toFixed(4)}
|
|
@@ -340,9 +308,7 @@ export function InferenceDashboard() {
|
|
|
340
308
|
|
|
341
309
|
{/* Cache Performance Panel */}
|
|
342
310
|
<div className="bg-card border border-border rounded-sm p-4">
|
|
343
|
-
<div className="text-xs uppercase tracking-widest text-muted-foreground mb-3">
|
|
344
|
-
CACHE PERFORMANCE
|
|
345
|
-
</div>
|
|
311
|
+
<div className="text-xs uppercase tracking-widest text-muted-foreground mb-3">CACHE PERFORMANCE</div>
|
|
346
312
|
{loading ? (
|
|
347
313
|
<div className="space-y-4">
|
|
348
314
|
<div className="h-10 w-24 bg-muted animate-pulse rounded-sm" />
|
|
@@ -353,9 +319,7 @@ export function InferenceDashboard() {
|
|
|
353
319
|
<div className="text-4xl font-bold text-terminal tabular-nums">
|
|
354
320
|
{((cacheStats?.hitRate ?? 0) * 100).toFixed(1)}%
|
|
355
321
|
</div>
|
|
356
|
-
<div className="text-xs text-muted-foreground mb-4">
|
|
357
|
-
of input tokens served from cache
|
|
358
|
-
</div>
|
|
322
|
+
<div className="text-xs text-muted-foreground mb-4">of input tokens served from cache</div>
|
|
359
323
|
|
|
360
324
|
{/* Hit rate bar */}
|
|
361
325
|
<div className="relative mb-4">
|
|
@@ -373,9 +337,7 @@ export function InferenceDashboard() {
|
|
|
373
337
|
style={{ left: "60%" }}
|
|
374
338
|
>
|
|
375
339
|
TARGET: 60%
|
|
376
|
-
{(cacheStats?.hitRate ?? 0) >= 0.6 &&
|
|
377
|
-
<Check className="text-terminal" size={10} />
|
|
378
|
-
)}
|
|
340
|
+
{(cacheStats?.hitRate ?? 0) >= 0.6 && <Check className="text-terminal" size={10} />}
|
|
379
341
|
</div>
|
|
380
342
|
</div>
|
|
381
343
|
|
|
@@ -402,9 +364,7 @@ export function InferenceDashboard() {
|
|
|
402
364
|
</div>
|
|
403
365
|
|
|
404
366
|
{(cacheStats?.hitRate ?? 0) === 0 && (
|
|
405
|
-
<div className="text-xs text-muted-foreground mt-4">
|
|
406
|
-
Awaiting first cached request
|
|
407
|
-
</div>
|
|
367
|
+
<div className="text-xs text-muted-foreground mt-4">Awaiting first cached request</div>
|
|
408
368
|
)}
|
|
409
369
|
</>
|
|
410
370
|
)}
|
|
@@ -18,14 +18,7 @@ import {
|
|
|
18
18
|
import { Input } from "@/components/ui/input";
|
|
19
19
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
20
20
|
import { Switch } from "@/components/ui/switch";
|
|
21
|
-
import {
|
|
22
|
-
Table,
|
|
23
|
-
TableBody,
|
|
24
|
-
TableCell,
|
|
25
|
-
TableHead,
|
|
26
|
-
TableHeader,
|
|
27
|
-
TableRow,
|
|
28
|
-
} from "@/components/ui/table";
|
|
21
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
29
22
|
import { Textarea } from "@/components/ui/textarea";
|
|
30
23
|
import {
|
|
31
24
|
type AdminPlugin,
|
|
@@ -352,9 +345,7 @@ export function MarketplaceAdmin() {
|
|
|
352
345
|
<DialogContent>
|
|
353
346
|
<DialogHeader>
|
|
354
347
|
<DialogTitle>Add Plugin by npm Package</DialogTitle>
|
|
355
|
-
<DialogDescription>
|
|
356
|
-
Paste the npm package name to add it to the discovery queue.
|
|
357
|
-
</DialogDescription>
|
|
348
|
+
<DialogDescription>Paste the npm package name to add it to the discovery queue.</DialogDescription>
|
|
358
349
|
</DialogHeader>
|
|
359
350
|
<Input
|
|
360
351
|
className="font-mono"
|
|
@@ -387,9 +378,7 @@ export function MarketplaceAdmin() {
|
|
|
387
378
|
{queue.length > 0 && (
|
|
388
379
|
<div className="space-y-2">
|
|
389
380
|
<div className="flex items-center gap-2">
|
|
390
|
-
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
|
391
|
-
Discovery Queue
|
|
392
|
-
</h2>
|
|
381
|
+
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">Discovery Queue</h2>
|
|
393
382
|
<Badge
|
|
394
383
|
variant="secondary"
|
|
395
384
|
className="bg-amber-500/15 text-amber-400 border border-amber-500/20 text-xs"
|
|
@@ -403,9 +392,7 @@ export function MarketplaceAdmin() {
|
|
|
403
392
|
<TableRow className="bg-amber-500/5 hover:bg-amber-500/5">
|
|
404
393
|
<TableHead className="text-xs uppercase tracking-wider">Package</TableHead>
|
|
405
394
|
<TableHead className="text-xs uppercase tracking-wider">Category</TableHead>
|
|
406
|
-
<TableHead className="text-xs uppercase tracking-wider text-right">
|
|
407
|
-
Actions
|
|
408
|
-
</TableHead>
|
|
395
|
+
<TableHead className="text-xs uppercase tracking-wider text-right">Actions</TableHead>
|
|
409
396
|
</TableRow>
|
|
410
397
|
</TableHeader>
|
|
411
398
|
<TableBody>
|
|
@@ -421,16 +408,11 @@ export function MarketplaceAdmin() {
|
|
|
421
408
|
<TableCell>
|
|
422
409
|
<div>
|
|
423
410
|
<div className="text-sm font-medium">{plugin.name}</div>
|
|
424
|
-
<div className="text-xs text-muted-foreground font-mono">
|
|
425
|
-
{plugin.npm_package}
|
|
426
|
-
</div>
|
|
411
|
+
<div className="text-xs text-muted-foreground font-mono">{plugin.npm_package}</div>
|
|
427
412
|
</div>
|
|
428
413
|
</TableCell>
|
|
429
414
|
<TableCell>
|
|
430
|
-
<Badge
|
|
431
|
-
variant="outline"
|
|
432
|
-
className={cn("text-xs", categoryBadgeClass(plugin.category))}
|
|
433
|
-
>
|
|
415
|
+
<Badge variant="outline" className={cn("text-xs", categoryBadgeClass(plugin.category))}>
|
|
434
416
|
{plugin.category}
|
|
435
417
|
</Badge>
|
|
436
418
|
</TableCell>
|
|
@@ -470,9 +452,7 @@ export function MarketplaceAdmin() {
|
|
|
470
452
|
|
|
471
453
|
{/* Enabled Plugins */}
|
|
472
454
|
<div className="space-y-2">
|
|
473
|
-
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
|
474
|
-
Enabled Plugins
|
|
475
|
-
</h2>
|
|
455
|
+
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">Enabled Plugins</h2>
|
|
476
456
|
<div className="border border-terminal/10 rounded-sm">
|
|
477
457
|
<Table>
|
|
478
458
|
<TableHeader>
|
|
@@ -489,9 +469,7 @@ export function MarketplaceAdmin() {
|
|
|
489
469
|
{enabled.length === 0 ? (
|
|
490
470
|
<TableRow>
|
|
491
471
|
<TableCell colSpan={6} className="text-center py-8">
|
|
492
|
-
<span className="text-sm text-muted-foreground font-mono">
|
|
493
|
-
> No plugins enabled yet
|
|
494
|
-
</span>
|
|
472
|
+
<span className="text-sm text-muted-foreground font-mono">> No plugins enabled yet</span>
|
|
495
473
|
</TableCell>
|
|
496
474
|
</TableRow>
|
|
497
475
|
) : (
|
|
@@ -515,10 +493,7 @@ export function MarketplaceAdmin() {
|
|
|
515
493
|
<div className="text-sm font-medium">{plugin.name}</div>
|
|
516
494
|
</TableCell>
|
|
517
495
|
<TableCell>
|
|
518
|
-
<Badge
|
|
519
|
-
variant="outline"
|
|
520
|
-
className={cn("text-xs", categoryBadgeClass(plugin.category))}
|
|
521
|
-
>
|
|
496
|
+
<Badge variant="outline" className={cn("text-xs", categoryBadgeClass(plugin.category))}>
|
|
522
497
|
{plugin.category}
|
|
523
498
|
</Badge>
|
|
524
499
|
</TableCell>
|
|
@@ -531,9 +506,7 @@ export function MarketplaceAdmin() {
|
|
|
531
506
|
/>
|
|
532
507
|
</TableCell>
|
|
533
508
|
<TableCell>
|
|
534
|
-
<span className="text-xs text-muted-foreground font-mono">
|
|
535
|
-
v{plugin.version}
|
|
536
|
-
</span>
|
|
509
|
+
<span className="text-xs text-muted-foreground font-mono">v{plugin.version}</span>
|
|
537
510
|
</TableCell>
|
|
538
511
|
<TableCell>
|
|
539
512
|
<Switch
|
|
@@ -596,19 +569,13 @@ export function MarketplaceAdmin() {
|
|
|
596
569
|
{!installStatusLoading && installStatus && (
|
|
597
570
|
<div className="flex items-center gap-2">
|
|
598
571
|
{installStatus.status === "pending" && (
|
|
599
|
-
<Badge
|
|
600
|
-
variant="outline"
|
|
601
|
-
className="border-amber-500/30 text-amber-400 text-xs animate-pulse"
|
|
602
|
-
>
|
|
572
|
+
<Badge variant="outline" className="border-amber-500/30 text-amber-400 text-xs animate-pulse">
|
|
603
573
|
Installing...
|
|
604
574
|
</Badge>
|
|
605
575
|
)}
|
|
606
576
|
{installStatus.status === "installed" && (
|
|
607
577
|
<div className="flex items-center gap-2">
|
|
608
|
-
<Badge
|
|
609
|
-
variant="outline"
|
|
610
|
-
className="border-terminal/30 text-terminal text-xs"
|
|
611
|
-
>
|
|
578
|
+
<Badge variant="outline" className="border-terminal/30 text-terminal text-xs">
|
|
612
579
|
Installed
|
|
613
580
|
</Badge>
|
|
614
581
|
{installStatus.installedAt && (
|
|
@@ -620,16 +587,11 @@ export function MarketplaceAdmin() {
|
|
|
620
587
|
)}
|
|
621
588
|
{installStatus.status === "failed" && (
|
|
622
589
|
<div className="space-y-1">
|
|
623
|
-
<Badge
|
|
624
|
-
variant="outline"
|
|
625
|
-
className="border-destructive/50 text-destructive text-xs"
|
|
626
|
-
>
|
|
590
|
+
<Badge variant="outline" className="border-destructive/50 text-destructive text-xs">
|
|
627
591
|
Install failed
|
|
628
592
|
</Badge>
|
|
629
593
|
{installStatus.installError && (
|
|
630
|
-
<p className="text-xs text-destructive font-mono">
|
|
631
|
-
{installStatus.installError}
|
|
632
|
-
</p>
|
|
594
|
+
<p className="text-xs text-destructive font-mono">{installStatus.installError}</p>
|
|
633
595
|
)}
|
|
634
596
|
<Button
|
|
635
597
|
variant="ghost"
|
|
@@ -683,9 +645,7 @@ export function MarketplaceAdmin() {
|
|
|
683
645
|
|
|
684
646
|
{/* Notes */}
|
|
685
647
|
<div className="space-y-1.5">
|
|
686
|
-
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
687
|
-
Internal Notes
|
|
688
|
-
</h3>
|
|
648
|
+
<h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">Internal Notes</h3>
|
|
689
649
|
<Textarea
|
|
690
650
|
className="min-h-[80px] text-sm bg-black/30 border-border focus:border-terminal"
|
|
691
651
|
placeholder="Add internal notes about this plugin..."
|
|
@@ -723,8 +683,8 @@ export function MarketplaceAdmin() {
|
|
|
723
683
|
<DialogHeader>
|
|
724
684
|
<DialogTitle>Delete Plugin</DialogTitle>
|
|
725
685
|
<DialogDescription>
|
|
726
|
-
Are you sure you want to delete <strong>{selected.name}</strong>? This
|
|
727
|
-
|
|
686
|
+
Are you sure you want to delete <strong>{selected.name}</strong>? This action cannot be
|
|
687
|
+
undone.
|
|
728
688
|
</DialogDescription>
|
|
729
689
|
</DialogHeader>
|
|
730
690
|
<DialogFooter>
|
|
@@ -752,9 +712,7 @@ export function MarketplaceAdmin() {
|
|
|
752
712
|
exit={{ opacity: 0 }}
|
|
753
713
|
className="flex items-center justify-center h-full"
|
|
754
714
|
>
|
|
755
|
-
<span className="text-sm text-muted-foreground font-mono">
|
|
756
|
-
> Select a plugin to preview
|
|
757
|
-
</span>
|
|
715
|
+
<span className="text-sm text-muted-foreground font-mono">> Select a plugin to preview</span>
|
|
758
716
|
</motion.div>
|
|
759
717
|
)}
|
|
760
718
|
</AnimatePresence>
|
|
@@ -1,29 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
AlertCircle,
|
|
5
|
-
CheckCircle2,
|
|
6
|
-
Clock,
|
|
7
|
-
Database,
|
|
8
|
-
History,
|
|
9
|
-
Loader2,
|
|
10
|
-
RotateCcw,
|
|
11
|
-
Search,
|
|
12
|
-
} from "lucide-react";
|
|
3
|
+
import { AlertCircle, CheckCircle2, Clock, Database, History, Loader2, RotateCcw, Search } from "lucide-react";
|
|
13
4
|
import { useCallback, useEffect, useState } from "react";
|
|
14
5
|
import { toast } from "sonner";
|
|
15
6
|
import { Badge } from "@/components/ui/badge";
|
|
16
7
|
import { Button } from "@/components/ui/button";
|
|
17
8
|
import { Input } from "@/components/ui/input";
|
|
18
9
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
19
|
-
import {
|
|
20
|
-
Table,
|
|
21
|
-
TableBody,
|
|
22
|
-
TableCell,
|
|
23
|
-
TableHead,
|
|
24
|
-
TableHeader,
|
|
25
|
-
TableRow,
|
|
26
|
-
} from "@/components/ui/table";
|
|
10
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
27
11
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
28
12
|
import type { MigrationRecord, MigrationRestoreRecord, MigrationSnapshot } from "@/lib/admin-api";
|
|
29
13
|
import {
|
|
@@ -85,10 +69,7 @@ function StatusBadge({ status }: { status: string }) {
|
|
|
85
69
|
);
|
|
86
70
|
default:
|
|
87
71
|
return (
|
|
88
|
-
<Badge
|
|
89
|
-
variant="secondary"
|
|
90
|
-
className="bg-muted text-muted-foreground inline-flex items-center gap-1"
|
|
91
|
-
>
|
|
72
|
+
<Badge variant="secondary" className="bg-muted text-muted-foreground inline-flex items-center gap-1">
|
|
92
73
|
<Clock className="h-3 w-3" />
|
|
93
74
|
pending
|
|
94
75
|
</Badge>
|
|
@@ -133,9 +114,7 @@ function MigrationsList({ migrations }: { migrations: MigrationRecord[] }) {
|
|
|
133
114
|
<TableCell className="text-xs text-muted-foreground tabular-nums">
|
|
134
115
|
{fmtDuration(m.duration_ms)}
|
|
135
116
|
</TableCell>
|
|
136
|
-
<TableCell className="text-xs text-red-400 max-w-xs truncate">
|
|
137
|
-
{m.error ?? "—"}
|
|
138
|
-
</TableCell>
|
|
117
|
+
<TableCell className="text-xs text-red-400 max-w-xs truncate">{m.error ?? "—"}</TableCell>
|
|
139
118
|
</TableRow>
|
|
140
119
|
))
|
|
141
120
|
)}
|
|
@@ -161,10 +140,7 @@ function SnapshotBrowser({ tenantId }: SnapshotBrowserProps) {
|
|
|
161
140
|
if (!tenantId) return;
|
|
162
141
|
setLoading(true);
|
|
163
142
|
try {
|
|
164
|
-
const [snaps, hist] = await Promise.all([
|
|
165
|
-
getMigrationSnapshots(tenantId),
|
|
166
|
-
getMigrationRestoreHistory(tenantId),
|
|
167
|
-
]);
|
|
143
|
+
const [snaps, hist] = await Promise.all([getMigrationSnapshots(tenantId), getMigrationRestoreHistory(tenantId)]);
|
|
168
144
|
setSnapshots(snaps);
|
|
169
145
|
setHistory(hist);
|
|
170
146
|
} catch (err) {
|
|
@@ -179,10 +155,7 @@ function SnapshotBrowser({ tenantId }: SnapshotBrowserProps) {
|
|
|
179
155
|
}, [load]);
|
|
180
156
|
|
|
181
157
|
async function handleRestore(snapshotId: string, snapshotName: string) {
|
|
182
|
-
if (
|
|
183
|
-
!confirm(`Restore snapshot "${snapshotName}" for tenant ${tenantId}? This cannot be undone.`)
|
|
184
|
-
)
|
|
185
|
-
return;
|
|
158
|
+
if (!confirm(`Restore snapshot "${snapshotName}" for tenant ${tenantId}? This cannot be undone.`)) return;
|
|
186
159
|
setRestoring(snapshotId);
|
|
187
160
|
try {
|
|
188
161
|
await restoreMigrationSnapshot(tenantId, snapshotId);
|
|
@@ -297,9 +270,7 @@ function SnapshotBrowser({ tenantId }: SnapshotBrowserProps) {
|
|
|
297
270
|
<TableCell className="text-xs text-muted-foreground">
|
|
298
271
|
{new Date(r.restored_at).toLocaleString()}
|
|
299
272
|
</TableCell>
|
|
300
|
-
<TableCell className="text-xs text-red-400 max-w-xs truncate">
|
|
301
|
-
{r.error ?? "—"}
|
|
302
|
-
</TableCell>
|
|
273
|
+
<TableCell className="text-xs text-red-400 max-w-xs truncate">{r.error ?? "—"}</TableCell>
|
|
303
274
|
</TableRow>
|
|
304
275
|
))
|
|
305
276
|
)}
|
|
@@ -343,9 +314,7 @@ export function MigrationsDashboard() {
|
|
|
343
314
|
<div className="space-y-6 p-6">
|
|
344
315
|
<div>
|
|
345
316
|
<h1 className="text-2xl font-bold">Migrations</h1>
|
|
346
|
-
<p className="text-muted-foreground text-sm">
|
|
347
|
-
Platform migration status and per-tenant snapshot management
|
|
348
|
-
</p>
|
|
317
|
+
<p className="text-muted-foreground text-sm">Platform migration status and per-tenant snapshot management</p>
|
|
349
318
|
</div>
|
|
350
319
|
|
|
351
320
|
<Tabs defaultValue="migrations">
|
|
@@ -392,9 +361,7 @@ export function MigrationsDashboard() {
|
|
|
392
361
|
) : (
|
|
393
362
|
<div className="rounded-lg border border-border border-dashed py-16 text-center">
|
|
394
363
|
<Database className="h-8 w-8 text-muted-foreground mx-auto mb-2" />
|
|
395
|
-
<p className="text-sm text-muted-foreground">
|
|
396
|
-
Enter a tenant ID to browse snapshots.
|
|
397
|
-
</p>
|
|
364
|
+
<p className="text-sm text-muted-foreground">Enter a tenant ID to browse snapshots.</p>
|
|
398
365
|
</div>
|
|
399
366
|
)}
|
|
400
367
|
</TabsContent>
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
BookOpen,
|
|
5
|
-
CheckCircle2,
|
|
6
|
-
Clock,
|
|
7
|
-
Edit2,
|
|
8
|
-
Plus,
|
|
9
|
-
Save,
|
|
10
|
-
TrendingUp,
|
|
11
|
-
Users,
|
|
12
|
-
X,
|
|
13
|
-
} from "lucide-react";
|
|
3
|
+
import { BookOpen, CheckCircle2, Clock, Edit2, Plus, Save, TrendingUp, Users, X } from "lucide-react";
|
|
14
4
|
import { useCallback, useEffect, useState } from "react";
|
|
15
5
|
import { toast } from "sonner";
|
|
16
6
|
import { Badge } from "@/components/ui/badge";
|
|
@@ -20,11 +10,7 @@ import { Skeleton } from "@/components/ui/skeleton";
|
|
|
20
10
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
21
11
|
import { Textarea } from "@/components/ui/textarea";
|
|
22
12
|
import type { OnboardingFunnelStats, OnboardingScript } from "@/lib/admin-api";
|
|
23
|
-
import {
|
|
24
|
-
getOnboardingFunnelStats,
|
|
25
|
-
getOnboardingScripts,
|
|
26
|
-
saveOnboardingScript,
|
|
27
|
-
} from "@/lib/admin-api";
|
|
13
|
+
import { getOnboardingFunnelStats, getOnboardingScripts, saveOnboardingScript } from "@/lib/admin-api";
|
|
28
14
|
import { toUserMessage } from "@/lib/errors";
|
|
29
15
|
|
|
30
16
|
// ---- Utilities ----
|
|
@@ -82,16 +68,8 @@ function FunnelView({ stats }: { stats: OnboardingFunnelStats }) {
|
|
|
82
68
|
value={stats.total_completed.toLocaleString()}
|
|
83
69
|
sub={fmtPct(stats.overall_completion_rate)}
|
|
84
70
|
/>
|
|
85
|
-
<StatCard
|
|
86
|
-
|
|
87
|
-
label="Completion Rate"
|
|
88
|
-
value={fmtPct(stats.overall_completion_rate)}
|
|
89
|
-
/>
|
|
90
|
-
<StatCard
|
|
91
|
-
icon={Clock}
|
|
92
|
-
label="Time to First Bot"
|
|
93
|
-
value={fmtMs(stats.time_to_first_bot_ms)}
|
|
94
|
-
/>
|
|
71
|
+
<StatCard icon={TrendingUp} label="Completion Rate" value={fmtPct(stats.overall_completion_rate)} />
|
|
72
|
+
<StatCard icon={Clock} label="Time to First Bot" value={fmtMs(stats.time_to_first_bot_ms)} />
|
|
95
73
|
</div>
|
|
96
74
|
|
|
97
75
|
<div className="rounded-lg border border-border overflow-hidden">
|
|
@@ -100,14 +78,10 @@ function FunnelView({ stats }: { stats: OnboardingFunnelStats }) {
|
|
|
100
78
|
<tr className="border-b border-border bg-muted/40 text-left">
|
|
101
79
|
<th className="px-4 py-2.5 font-medium text-muted-foreground">Step</th>
|
|
102
80
|
<th className="px-4 py-2.5 font-medium text-muted-foreground text-right">Started</th>
|
|
103
|
-
<th className="px-4 py-2.5 font-medium text-muted-foreground text-right">
|
|
104
|
-
Completed
|
|
105
|
-
</th>
|
|
81
|
+
<th className="px-4 py-2.5 font-medium text-muted-foreground text-right">Completed</th>
|
|
106
82
|
<th className="px-4 py-2.5 font-medium text-muted-foreground text-right">Dropped</th>
|
|
107
83
|
<th className="px-4 py-2.5 font-medium text-muted-foreground text-right">Rate</th>
|
|
108
|
-
<th className="px-4 py-2.5 font-medium text-muted-foreground text-right">
|
|
109
|
-
Avg Duration
|
|
110
|
-
</th>
|
|
84
|
+
<th className="px-4 py-2.5 font-medium text-muted-foreground text-right">Avg Duration</th>
|
|
111
85
|
<th className="px-4 py-2.5 font-medium text-muted-foreground">Funnel</th>
|
|
112
86
|
</tr>
|
|
113
87
|
</thead>
|
|
@@ -125,17 +99,13 @@ function FunnelView({ stats }: { stats: OnboardingFunnelStats }) {
|
|
|
125
99
|
className="border-b border-border last:border-b-0 hover:bg-muted/20 transition-colors"
|
|
126
100
|
>
|
|
127
101
|
<td className="px-4 py-3 font-medium">{step.label}</td>
|
|
128
|
-
<td className="px-4 py-3 text-right tabular-nums">
|
|
129
|
-
{step.started.toLocaleString()}
|
|
130
|
-
</td>
|
|
102
|
+
<td className="px-4 py-3 text-right tabular-nums">{step.started.toLocaleString()}</td>
|
|
131
103
|
<td className="px-4 py-3 text-right tabular-nums text-green-400">
|
|
132
104
|
{step.completed.toLocaleString()}
|
|
133
105
|
</td>
|
|
134
106
|
<td className="px-4 py-3 text-right tabular-nums text-red-400">
|
|
135
107
|
{step.dropped.toLocaleString()}
|
|
136
|
-
{idx > 0 && dropPct > 0 && (
|
|
137
|
-
<span className="text-xs text-muted-foreground ml-1">({dropPct}%)</span>
|
|
138
|
-
)}
|
|
108
|
+
{idx > 0 && dropPct > 0 && <span className="text-xs text-muted-foreground ml-1">({dropPct}%)</span>}
|
|
139
109
|
</td>
|
|
140
110
|
<td className="px-4 py-3 text-right tabular-nums">
|
|
141
111
|
<Badge
|
|
@@ -156,10 +126,7 @@ function FunnelView({ stats }: { stats: OnboardingFunnelStats }) {
|
|
|
156
126
|
</td>
|
|
157
127
|
<td className="px-4 py-3 w-32">
|
|
158
128
|
<div className="h-2 rounded-full bg-muted overflow-hidden">
|
|
159
|
-
<div
|
|
160
|
-
className="h-full rounded-full bg-terminal/70 transition-all"
|
|
161
|
-
style={{ width: `${pct}%` }}
|
|
162
|
-
/>
|
|
129
|
+
<div className="h-full rounded-full bg-terminal/70 transition-all" style={{ width: `${pct}%` }} />
|
|
163
130
|
</div>
|
|
164
131
|
</td>
|
|
165
132
|
</tr>
|
|
@@ -213,11 +180,7 @@ function ScriptEditor({ scripts, onSaved }: ScriptEditorProps) {
|
|
|
213
180
|
}
|
|
214
181
|
setSaving(true);
|
|
215
182
|
try {
|
|
216
|
-
const saved = await saveOnboardingScript(
|
|
217
|
-
editing && selected ? selected.id : null,
|
|
218
|
-
name.trim(),
|
|
219
|
-
content,
|
|
220
|
-
);
|
|
183
|
+
const saved = await saveOnboardingScript(editing && selected ? selected.id : null, name.trim(), content);
|
|
221
184
|
onSaved(saved);
|
|
222
185
|
setEditing(false);
|
|
223
186
|
setSelected(saved);
|
|
@@ -268,9 +231,7 @@ function ScriptEditor({ scripts, onSaved }: ScriptEditorProps) {
|
|
|
268
231
|
New Script
|
|
269
232
|
</Button>
|
|
270
233
|
</div>
|
|
271
|
-
{scripts.length === 0 &&
|
|
272
|
-
<p className="text-sm text-muted-foreground py-4 text-center">No scripts yet.</p>
|
|
273
|
-
)}
|
|
234
|
+
{scripts.length === 0 && <p className="text-sm text-muted-foreground py-4 text-center">No scripts yet.</p>}
|
|
274
235
|
<div className="space-y-2">
|
|
275
236
|
{scripts.map((s) => (
|
|
276
237
|
<button
|
|
@@ -284,10 +245,7 @@ function ScriptEditor({ scripts, onSaved }: ScriptEditorProps) {
|
|
|
284
245
|
<BookOpen className="h-3.5 w-3.5 text-muted-foreground" />
|
|
285
246
|
<span className="text-sm font-medium">{s.name}</span>
|
|
286
247
|
{s.active && (
|
|
287
|
-
<Badge
|
|
288
|
-
variant="secondary"
|
|
289
|
-
className="bg-green-500/15 text-green-400 border-green-500/20 text-xs"
|
|
290
|
-
>
|
|
248
|
+
<Badge variant="secondary" className="bg-green-500/15 text-green-400 border-green-500/20 text-xs">
|
|
291
249
|
active
|
|
292
250
|
</Badge>
|
|
293
251
|
)}
|
|
@@ -332,10 +290,7 @@ export function OnboardingDashboard() {
|
|
|
332
290
|
const load = useCallback(async () => {
|
|
333
291
|
setLoading(true);
|
|
334
292
|
try {
|
|
335
|
-
const [funnelStats, scriptList] = await Promise.all([
|
|
336
|
-
getOnboardingFunnelStats(days),
|
|
337
|
-
getOnboardingScripts(),
|
|
338
|
-
]);
|
|
293
|
+
const [funnelStats, scriptList] = await Promise.all([getOnboardingFunnelStats(days), getOnboardingScripts()]);
|
|
339
294
|
setStats(funnelStats);
|
|
340
295
|
setScripts(scriptList);
|
|
341
296
|
} catch (err) {
|
|
@@ -370,12 +325,7 @@ export function OnboardingDashboard() {
|
|
|
370
325
|
</div>
|
|
371
326
|
<div className="flex gap-1">
|
|
372
327
|
{[7, 30, 90].map((d) => (
|
|
373
|
-
<Button
|
|
374
|
-
key={d}
|
|
375
|
-
size="sm"
|
|
376
|
-
variant={days === d ? "secondary" : "outline"}
|
|
377
|
-
onClick={() => setDays(d)}
|
|
378
|
-
>
|
|
328
|
+
<Button key={d} size="sm" variant={days === d ? "secondary" : "outline"} onClick={() => setDays(d)}>
|
|
379
329
|
{d}d
|
|
380
330
|
</Button>
|
|
381
331
|
))}
|
|
@@ -70,8 +70,8 @@ export function PoolConfigDashboard() {
|
|
|
70
70
|
<h2 className="text-lg font-semibold mb-2">Hot Pool</h2>
|
|
71
71
|
<p className="text-muted-foreground">
|
|
72
72
|
Hot pool is not enabled for this product. Enable the{" "}
|
|
73
|
-
<code className="text-xs bg-muted px-1 py-0.5 rounded">hotPool</code> feature flag in the
|
|
74
|
-
|
|
73
|
+
<code className="text-xs bg-muted px-1 py-0.5 rounded">hotPool</code> feature flag in the boot config to use
|
|
74
|
+
pre-provisioned instances.
|
|
75
75
|
</p>
|
|
76
76
|
</div>
|
|
77
77
|
);
|
|
@@ -81,9 +81,7 @@ export function PoolConfigDashboard() {
|
|
|
81
81
|
<div className="space-y-6 p-6">
|
|
82
82
|
<div>
|
|
83
83
|
<h2 className="text-lg font-semibold">Hot Pool</h2>
|
|
84
|
-
<p className="text-sm text-muted-foreground">
|
|
85
|
-
Pre-provisioned warm containers for instant instance creation.
|
|
86
|
-
</p>
|
|
84
|
+
<p className="text-sm text-muted-foreground">Pre-provisioned warm containers for instant instance creation.</p>
|
|
87
85
|
</div>
|
|
88
86
|
|
|
89
87
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
|
@@ -122,11 +120,7 @@ export function PoolConfigDashboard() {
|
|
|
122
120
|
onChange={(e) => setSizeInput(e.target.value)}
|
|
123
121
|
className="w-24"
|
|
124
122
|
/>
|
|
125
|
-
<Button
|
|
126
|
-
onClick={handleSave}
|
|
127
|
-
disabled={saving || sizeInput === String(config.poolSize)}
|
|
128
|
-
size="sm"
|
|
129
|
-
>
|
|
123
|
+
<Button onClick={handleSave} disabled={saving || sizeInput === String(config.poolSize)} size="sm">
|
|
130
124
|
{saving ? "Saving..." : "Update"}
|
|
131
125
|
</Button>
|
|
132
126
|
<span className="text-xs text-muted-foreground">
|
|
@@ -6,13 +6,7 @@ import { Button } from "@/components/ui/button";
|
|
|
6
6
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
7
7
|
import { Input } from "@/components/ui/input";
|
|
8
8
|
import { Label } from "@/components/ui/label";
|
|
9
|
-
import {
|
|
10
|
-
Select,
|
|
11
|
-
SelectContent,
|
|
12
|
-
SelectItem,
|
|
13
|
-
SelectTrigger,
|
|
14
|
-
SelectValue,
|
|
15
|
-
} from "@/components/ui/select";
|
|
9
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
16
10
|
import { toUserMessage } from "@/lib/errors";
|
|
17
11
|
|
|
18
12
|
interface FleetConfig {
|
|
@@ -124,10 +118,7 @@ export function FleetForm({ initial, onSave }: FleetFormProps) {
|
|
|
124
118
|
|
|
125
119
|
<div className="space-y-1.5">
|
|
126
120
|
<Label htmlFor="fleet-placementStrategy">Placement Strategy</Label>
|
|
127
|
-
<Select
|
|
128
|
-
value={form.placementStrategy}
|
|
129
|
-
onValueChange={(v) => setStr("placementStrategy", v)}
|
|
130
|
-
>
|
|
121
|
+
<Select value={form.placementStrategy} onValueChange={(v) => setStr("placementStrategy", v)}>
|
|
131
122
|
<SelectTrigger id="fleet-placementStrategy">
|
|
132
123
|
<SelectValue placeholder="Select strategy" />
|
|
133
124
|
</SelectTrigger>
|