@wopr-network/platform-ui-core 1.27.8 → 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 +4 -14
- 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
|
@@ -70,9 +70,7 @@ export default function ChannelSetupPage({ params }: { params: Promise<{ plugin:
|
|
|
70
70
|
<div className="flex h-full items-center justify-center">
|
|
71
71
|
<div className="text-center">
|
|
72
72
|
<h1 className="text-2xl font-bold">Channel Not Found</h1>
|
|
73
|
-
<p className="mt-2 text-muted-foreground">
|
|
74
|
-
No manifest found for “{plugin}”.
|
|
75
|
-
</p>
|
|
73
|
+
<p className="mt-2 text-muted-foreground">No manifest found for “{plugin}”.</p>
|
|
76
74
|
</div>
|
|
77
75
|
</div>
|
|
78
76
|
);
|
|
@@ -87,8 +85,8 @@ export default function ChannelSetupPage({ params }: { params: Promise<{ plugin:
|
|
|
87
85
|
</div>
|
|
88
86
|
<h1 className="text-lg font-semibold uppercase tracking-wider">NO INSTANCE CONTEXT</h1>
|
|
89
87
|
<p className="text-sm text-muted-foreground">
|
|
90
|
-
Channel setup requires a bot instance. Navigate to your instance and connect a channel
|
|
91
|
-
|
|
88
|
+
Channel setup requires a bot instance. Navigate to your instance and connect a channel from the Channels
|
|
89
|
+
tab.
|
|
92
90
|
</p>
|
|
93
91
|
<Button variant="terminal" asChild>
|
|
94
92
|
<Link href="/instances">VIEW INSTANCES</Link>
|
package/src/app/error.tsx
CHANGED
|
@@ -8,13 +8,7 @@ import { logger } from "@/lib/logger";
|
|
|
8
8
|
|
|
9
9
|
const log = logger("error-boundary");
|
|
10
10
|
|
|
11
|
-
export default function GlobalError({
|
|
12
|
-
error,
|
|
13
|
-
reset,
|
|
14
|
-
}: {
|
|
15
|
-
error: Error & { digest?: string };
|
|
16
|
-
reset: () => void;
|
|
17
|
-
}) {
|
|
11
|
+
export default function GlobalError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
|
|
18
12
|
const [showDetails, setShowDetails] = useState(false);
|
|
19
13
|
const isDev = process.env.NODE_ENV === "development";
|
|
20
14
|
|
package/src/app/fleet/error.tsx
CHANGED
|
@@ -8,13 +8,7 @@ import { logger } from "@/lib/logger";
|
|
|
8
8
|
|
|
9
9
|
const log = logger("error-boundary:fleet");
|
|
10
10
|
|
|
11
|
-
export default function FleetError({
|
|
12
|
-
error,
|
|
13
|
-
reset,
|
|
14
|
-
}: {
|
|
15
|
-
error: Error & { digest?: string };
|
|
16
|
-
reset: () => void;
|
|
17
|
-
}) {
|
|
11
|
+
export default function FleetError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
|
|
18
12
|
const [showDetails, setShowDetails] = useState(false);
|
|
19
13
|
const isDev = process.env.NODE_ENV === "development";
|
|
20
14
|
|
package/src/app/fleet/layout.tsx
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { Sidebar } from "@/components/sidebar";
|
|
4
|
+
import { useRequireAuth } from "@/lib/require-auth";
|
|
2
5
|
|
|
3
6
|
export default function FleetLayout({
|
|
4
7
|
children,
|
|
5
8
|
}: Readonly<{
|
|
6
9
|
children: React.ReactNode;
|
|
7
10
|
}>) {
|
|
11
|
+
const { isPending, isAuthed } = useRequireAuth();
|
|
12
|
+
if (isPending || !isAuthed) return null;
|
|
8
13
|
return (
|
|
9
14
|
<div className="flex h-screen">
|
|
10
15
|
<Sidebar />
|
|
@@ -9,9 +9,7 @@ export default function FleetSettingsPage() {
|
|
|
9
9
|
<Settings2 className="h-6 w-6 text-muted-foreground" />
|
|
10
10
|
Fleet Settings
|
|
11
11
|
</h1>
|
|
12
|
-
<p className="text-muted-foreground mt-1">
|
|
13
|
-
Configure update behavior and maintenance windows for your fleet.
|
|
14
|
-
</p>
|
|
12
|
+
<p className="text-muted-foreground mt-1">Configure update behavior and maintenance windows for your fleet.</p>
|
|
15
13
|
</div>
|
|
16
14
|
<UpdateSettingsCard />
|
|
17
15
|
</div>
|
package/src/app/global-error.tsx
CHANGED
|
@@ -7,13 +7,7 @@ import { logger } from "@/lib/logger";
|
|
|
7
7
|
|
|
8
8
|
const log = logger("global-error");
|
|
9
9
|
|
|
10
|
-
export default function GlobalError({
|
|
11
|
-
error,
|
|
12
|
-
reset,
|
|
13
|
-
}: {
|
|
14
|
-
error: Error & { digest?: string };
|
|
15
|
-
reset: () => void;
|
|
16
|
-
}) {
|
|
10
|
+
export default function GlobalError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
|
|
17
11
|
const [showDetails, setShowDetails] = useState(false);
|
|
18
12
|
const isDev = process.env.NODE_ENV === "development";
|
|
19
13
|
|
|
@@ -43,9 +37,7 @@ export default function GlobalError({
|
|
|
43
37
|
<div className="flex items-center gap-3">
|
|
44
38
|
<AlertTriangleIcon className="size-6 text-red-500" />
|
|
45
39
|
<div>
|
|
46
|
-
<p className="text-xs font-semibold uppercase tracking-widest text-neutral-500">
|
|
47
|
-
{brandName()}
|
|
48
|
-
</p>
|
|
40
|
+
<p className="text-xs font-semibold uppercase tracking-widest text-neutral-500">{brandName()}</p>
|
|
49
41
|
<h1 className="text-xl font-semibold text-neutral-100">Something went wrong</h1>
|
|
50
42
|
</div>
|
|
51
43
|
</div>
|
package/src/app/globals.css
CHANGED
|
@@ -256,10 +256,7 @@
|
|
|
256
256
|
|
|
257
257
|
/* Grid dot overlay — uses terminal color for brand-agnostic theming */
|
|
258
258
|
.bg-grid-dots {
|
|
259
|
-
background-image: radial-gradient(
|
|
260
|
-
color-mix(in srgb, var(--terminal, #00ff41) 8%, transparent) 1px,
|
|
261
|
-
transparent 1px
|
|
262
|
-
);
|
|
259
|
+
background-image: radial-gradient(color-mix(in srgb, var(--terminal, #00ff41) 8%, transparent) 1px, transparent 1px);
|
|
263
260
|
background-size: 24px 24px;
|
|
264
261
|
}
|
|
265
262
|
|
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
ArrowDownToLine,
|
|
5
|
-
ArrowLeft,
|
|
6
|
-
Check,
|
|
7
|
-
Loader2,
|
|
8
|
-
Lock,
|
|
9
|
-
Pencil,
|
|
10
|
-
Plus,
|
|
11
|
-
Trash2,
|
|
12
|
-
X,
|
|
13
|
-
} from "lucide-react";
|
|
3
|
+
import { ArrowDownToLine, ArrowLeft, Check, Loader2, Lock, Pencil, Plus, Trash2, X } from "lucide-react";
|
|
14
4
|
import Link from "next/link";
|
|
15
5
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
16
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
17
7
|
import { FriendsTab } from "@/components/instances/friends-tab";
|
|
18
8
|
import { HealthOverview } from "@/components/observability/health-overview";
|
|
19
9
|
import { LogsViewer } from "@/components/observability/logs-viewer";
|
|
@@ -44,14 +34,7 @@ import { Input } from "@/components/ui/input";
|
|
|
44
34
|
import { Separator } from "@/components/ui/separator";
|
|
45
35
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
46
36
|
import { Switch } from "@/components/ui/switch";
|
|
47
|
-
import {
|
|
48
|
-
Table,
|
|
49
|
-
TableBody,
|
|
50
|
-
TableCell,
|
|
51
|
-
TableHead,
|
|
52
|
-
TableHeader,
|
|
53
|
-
TableRow,
|
|
54
|
-
} from "@/components/ui/table";
|
|
37
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
55
38
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
56
39
|
import { Textarea } from "@/components/ui/textarea";
|
|
57
40
|
import { useImageStatus } from "@/hooks/use-image-status";
|
|
@@ -70,13 +53,32 @@ import {
|
|
|
70
53
|
updateInstanceConfig,
|
|
71
54
|
updateInstanceSecrets,
|
|
72
55
|
} from "@/lib/api";
|
|
56
|
+
import { getBrandConfig } from "@/lib/brand-config";
|
|
73
57
|
import { toUserMessage } from "@/lib/errors";
|
|
74
58
|
import { cn } from "@/lib/utils";
|
|
75
59
|
|
|
60
|
+
const ALL_INSTANCE_TABS = [
|
|
61
|
+
"overview",
|
|
62
|
+
"health",
|
|
63
|
+
"metrics",
|
|
64
|
+
"logs",
|
|
65
|
+
"plugins",
|
|
66
|
+
"channels",
|
|
67
|
+
"friends",
|
|
68
|
+
"sessions",
|
|
69
|
+
"snapshots",
|
|
70
|
+
"config",
|
|
71
|
+
] as const;
|
|
72
|
+
|
|
76
73
|
export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
77
74
|
const router = useRouter();
|
|
78
75
|
const searchParams = useSearchParams();
|
|
79
76
|
const defaultTab = searchParams.get("tab") ?? "overview";
|
|
77
|
+
const brand = getBrandConfig();
|
|
78
|
+
const visibleTabs = useMemo(
|
|
79
|
+
() => ALL_INSTANCE_TABS.filter((t) => !brand.hiddenInstanceTabs.includes(t)),
|
|
80
|
+
[brand.hiddenInstanceTabs],
|
|
81
|
+
);
|
|
80
82
|
const [instance, setInstance] = useState<InstanceDetail | null>(null);
|
|
81
83
|
const [loading, setLoading] = useState(true);
|
|
82
84
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -98,7 +100,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
98
100
|
const [destroyOpen, setDestroyOpen] = useState(false);
|
|
99
101
|
const [destroyConfirmText, setDestroyConfirmText] = useState("");
|
|
100
102
|
const [destroying, setDestroying] = useState(false);
|
|
101
|
-
const { updateAvailable
|
|
103
|
+
const { updateAvailable } = useImageStatus(instanceId);
|
|
102
104
|
const [pulling, setPulling] = useState(false);
|
|
103
105
|
const [confirmPull, setConfirmPull] = useState(false);
|
|
104
106
|
const [togglingPlugin, setTogglingPlugin] = useState<string | null>(null);
|
|
@@ -109,9 +111,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
109
111
|
const [secretsStatus, setSecretsStatus] = useState<"idle" | "saved" | "error">("idle");
|
|
110
112
|
const [secretsError, setSecretsError] = useState<string | null>(null);
|
|
111
113
|
const nextSecretId = useRef(0);
|
|
112
|
-
const [newSecretRows, setNewSecretRows] = useState<{ id: number; key: string; value: string }[]>(
|
|
113
|
-
[],
|
|
114
|
-
);
|
|
114
|
+
const [newSecretRows, setNewSecretRows] = useState<{ id: number; key: string; value: string }[]>([]);
|
|
115
115
|
const secretsLoaded = useRef(false);
|
|
116
116
|
const [renaming, setRenaming] = useState(false);
|
|
117
117
|
const [renameValue, setRenameValue] = useState("");
|
|
@@ -254,9 +254,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
// Check for new rows whose key duplicates an existing secret key.
|
|
257
|
-
const duplicates = newSecretRows
|
|
258
|
-
.map((row) => row.key.trim())
|
|
259
|
-
.filter((k) => k && secretKeys.includes(k));
|
|
257
|
+
const duplicates = newSecretRows.map((row) => row.key.trim()).filter((k) => k && secretKeys.includes(k));
|
|
260
258
|
if (duplicates.length > 0) {
|
|
261
259
|
setSecretsStatus("error");
|
|
262
260
|
setSecretsError(
|
|
@@ -412,11 +410,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
412
410
|
disabled={renameSaving}
|
|
413
411
|
aria-label="Confirm rename"
|
|
414
412
|
>
|
|
415
|
-
{renameSaving ?
|
|
416
|
-
<Loader2 className="size-4 animate-spin" />
|
|
417
|
-
) : (
|
|
418
|
-
<Check className="size-4" />
|
|
419
|
-
)}
|
|
413
|
+
{renameSaving ? <Loader2 className="size-4 animate-spin" /> : <Check className="size-4" />}
|
|
420
414
|
</Button>
|
|
421
415
|
<Button
|
|
422
416
|
variant="ghost"
|
|
@@ -433,12 +427,10 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
433
427
|
{instance.name}
|
|
434
428
|
<span
|
|
435
429
|
className={cn("size-2 rounded-full", {
|
|
436
|
-
"bg-emerald-500 animate-[pulse-dot_2s_ease-in-out_infinite]":
|
|
437
|
-
instance.status === "running",
|
|
430
|
+
"bg-emerald-500 animate-[pulse-dot_2s_ease-in-out_infinite]": instance.status === "running",
|
|
438
431
|
"bg-zinc-400": instance.status === "stopped",
|
|
439
432
|
"bg-yellow-500": instance.status === "degraded",
|
|
440
|
-
"bg-red-500 animate-[pulse-dot_0.8s_ease-in-out_infinite]":
|
|
441
|
-
instance.status === "error",
|
|
433
|
+
"bg-red-500 animate-[pulse-dot_0.8s_ease-in-out_infinite]": instance.status === "error",
|
|
442
434
|
})}
|
|
443
435
|
/>
|
|
444
436
|
<Button
|
|
@@ -456,14 +448,9 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
456
448
|
)}
|
|
457
449
|
<div className="flex items-center gap-3 text-sm text-muted-foreground">
|
|
458
450
|
<StatusBadge status={instance.status} />
|
|
459
|
-
{imageStatusError
|
|
460
|
-
<span className="text-xs text-destructive">{imageStatusError}</span>
|
|
461
|
-
)}
|
|
451
|
+
{/* imageStatusError silenced — non-critical, fails for non-GHCR registries */}
|
|
462
452
|
{updateAvailable && (
|
|
463
|
-
<Badge
|
|
464
|
-
variant="outline"
|
|
465
|
-
className="gap-1.5 bg-amber-500/15 text-amber-500 border-amber-500/25"
|
|
466
|
-
>
|
|
453
|
+
<Badge variant="outline" className="gap-1.5 bg-amber-500/15 text-amber-500 border-amber-500/25">
|
|
467
454
|
<span
|
|
468
455
|
className={cn(
|
|
469
456
|
"size-1.5 rounded-full bg-amber-500",
|
|
@@ -527,18 +514,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
527
514
|
{/* Tabs */}
|
|
528
515
|
<Tabs value={activeTab} onValueChange={setActiveTab}>
|
|
529
516
|
<TabsList className="bg-transparent border-b border-border rounded-none p-0 h-auto gap-0">
|
|
530
|
-
{
|
|
531
|
-
"overview",
|
|
532
|
-
"health",
|
|
533
|
-
"metrics",
|
|
534
|
-
"logs",
|
|
535
|
-
"plugins",
|
|
536
|
-
"channels",
|
|
537
|
-
"friends",
|
|
538
|
-
"sessions",
|
|
539
|
-
"snapshots",
|
|
540
|
-
"config",
|
|
541
|
-
].map((tab) => (
|
|
517
|
+
{visibleTabs.map((tab) => (
|
|
542
518
|
<TabsTrigger
|
|
543
519
|
key={tab}
|
|
544
520
|
value={tab}
|
|
@@ -602,10 +578,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
602
578
|
</TableHeader>
|
|
603
579
|
<TableBody>
|
|
604
580
|
{instance.plugins.map((plugin) => (
|
|
605
|
-
<TableRow
|
|
606
|
-
key={plugin.id}
|
|
607
|
-
className="transition-colors hover:bg-muted/50 even:bg-muted/20"
|
|
608
|
-
>
|
|
581
|
+
<TableRow key={plugin.id} className="transition-colors hover:bg-muted/50 even:bg-muted/20">
|
|
609
582
|
<TableCell className="font-medium">{plugin.name}</TableCell>
|
|
610
583
|
<TableCell className="text-muted-foreground">{plugin.version}</TableCell>
|
|
611
584
|
<TableCell>
|
|
@@ -649,10 +622,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
649
622
|
</TableHeader>
|
|
650
623
|
<TableBody>
|
|
651
624
|
{instance.channelDetails.map((ch) => (
|
|
652
|
-
<TableRow
|
|
653
|
-
key={ch.id}
|
|
654
|
-
className="transition-colors hover:bg-muted/50 even:bg-muted/20"
|
|
655
|
-
>
|
|
625
|
+
<TableRow key={ch.id} className="transition-colors hover:bg-muted/50 even:bg-muted/20">
|
|
656
626
|
<TableCell className="font-medium">{ch.name}</TableCell>
|
|
657
627
|
<TableCell className="text-muted-foreground">{ch.type}</TableCell>
|
|
658
628
|
<TableCell>
|
|
@@ -689,10 +659,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
689
659
|
</TableHeader>
|
|
690
660
|
<TableBody>
|
|
691
661
|
{instance.sessions.map((sess) => (
|
|
692
|
-
<TableRow
|
|
693
|
-
key={sess.id}
|
|
694
|
-
className="transition-colors hover:bg-muted/50 even:bg-muted/20"
|
|
695
|
-
>
|
|
662
|
+
<TableRow key={sess.id} className="transition-colors hover:bg-muted/50 even:bg-muted/20">
|
|
696
663
|
<TableCell className="font-mono text-sm">{sess.id}</TableCell>
|
|
697
664
|
<TableCell>{sess.userId}</TableCell>
|
|
698
665
|
<TableCell>{sess.messageCount}</TableCell>
|
|
@@ -750,10 +717,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
750
717
|
</TableHeader>
|
|
751
718
|
<TableBody>
|
|
752
719
|
{snapshots.map((snap) => (
|
|
753
|
-
<TableRow
|
|
754
|
-
key={snap.id}
|
|
755
|
-
className="transition-colors hover:bg-muted/50 even:bg-muted/20"
|
|
756
|
-
>
|
|
720
|
+
<TableRow key={snap.id} className="transition-colors hover:bg-muted/50 even:bg-muted/20">
|
|
757
721
|
<TableCell className="font-medium">
|
|
758
722
|
{snap.name ?? <span className="text-muted-foreground italic">unnamed</span>}
|
|
759
723
|
</TableCell>
|
|
@@ -767,18 +731,10 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
767
731
|
</TableCell>
|
|
768
732
|
<TableCell className="text-right">
|
|
769
733
|
<div className="flex justify-end gap-1">
|
|
770
|
-
<Button
|
|
771
|
-
size="sm"
|
|
772
|
-
variant="outline"
|
|
773
|
-
onClick={() => setConfirmRestore(snap)}
|
|
774
|
-
>
|
|
734
|
+
<Button size="sm" variant="outline" onClick={() => setConfirmRestore(snap)}>
|
|
775
735
|
Restore
|
|
776
736
|
</Button>
|
|
777
|
-
<Button
|
|
778
|
-
size="sm"
|
|
779
|
-
variant="destructive"
|
|
780
|
-
onClick={() => setConfirmDelete(snap)}
|
|
781
|
-
>
|
|
737
|
+
<Button size="sm" variant="destructive" onClick={() => setConfirmDelete(snap)}>
|
|
782
738
|
Delete
|
|
783
739
|
</Button>
|
|
784
740
|
</div>
|
|
@@ -803,11 +759,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
803
759
|
{confirmRestore ? new Date(confirmRestore.createdAt).toLocaleString() : ""}.
|
|
804
760
|
</p>
|
|
805
761
|
<DialogFooter>
|
|
806
|
-
<Button
|
|
807
|
-
variant="outline"
|
|
808
|
-
onClick={() => setConfirmRestore(null)}
|
|
809
|
-
disabled={restoring}
|
|
810
|
-
>
|
|
762
|
+
<Button variant="outline" onClick={() => setConfirmRestore(null)} disabled={restoring}>
|
|
811
763
|
Cancel
|
|
812
764
|
</Button>
|
|
813
765
|
<Button
|
|
@@ -831,11 +783,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
831
783
|
</DialogDescription>
|
|
832
784
|
</DialogHeader>
|
|
833
785
|
<DialogFooter>
|
|
834
|
-
<Button
|
|
835
|
-
variant="outline"
|
|
836
|
-
onClick={() => setConfirmDelete(null)}
|
|
837
|
-
disabled={deleting}
|
|
838
|
-
>
|
|
786
|
+
<Button variant="outline" onClick={() => setConfirmDelete(null)} disabled={deleting}>
|
|
839
787
|
Cancel
|
|
840
788
|
</Button>
|
|
841
789
|
<Button
|
|
@@ -877,15 +825,9 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
877
825
|
</div>
|
|
878
826
|
<div className="flex items-center justify-end gap-3">
|
|
879
827
|
{saving && <span className="text-sm text-muted-foreground">Saving...</span>}
|
|
880
|
-
{configStatus === "saved" && !saving &&
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
{configStatus === "invalid" && (
|
|
884
|
-
<span className="text-sm text-red-500">Invalid JSON</span>
|
|
885
|
-
)}
|
|
886
|
-
{configStatus === "error" && configError && (
|
|
887
|
-
<span className="text-sm text-red-500">{configError}</span>
|
|
888
|
-
)}
|
|
828
|
+
{configStatus === "saved" && !saving && <span className="text-sm text-emerald-500">Config saved</span>}
|
|
829
|
+
{configStatus === "invalid" && <span className="text-sm text-red-500">Invalid JSON</span>}
|
|
830
|
+
{configStatus === "error" && configError && <span className="text-sm text-red-500">{configError}</span>}
|
|
889
831
|
<Button
|
|
890
832
|
disabled={saving || configStatus === "invalid"}
|
|
891
833
|
onClick={async () => {
|
|
@@ -906,10 +848,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
906
848
|
try {
|
|
907
849
|
const env: Record<string, string> = {};
|
|
908
850
|
for (const [k, v] of Object.entries(parsed as Record<string, unknown>)) {
|
|
909
|
-
if (
|
|
910
|
-
v === null ||
|
|
911
|
-
(typeof v !== "string" && typeof v !== "number" && typeof v !== "boolean")
|
|
912
|
-
) {
|
|
851
|
+
if (v === null || (typeof v !== "string" && typeof v !== "number" && typeof v !== "boolean")) {
|
|
913
852
|
throw new Error(`Value for key "${k}" must be a string, number, or boolean`);
|
|
914
853
|
}
|
|
915
854
|
env[k] = String(v);
|
|
@@ -934,9 +873,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
934
873
|
<div className="flex items-center justify-between">
|
|
935
874
|
<div>
|
|
936
875
|
<h3 className="text-sm font-medium">Secrets</h3>
|
|
937
|
-
<p className="text-xs text-muted-foreground">
|
|
938
|
-
Write-only. Stored values are never displayed.
|
|
939
|
-
</p>
|
|
876
|
+
<p className="text-xs text-muted-foreground">Write-only. Stored values are never displayed.</p>
|
|
940
877
|
</div>
|
|
941
878
|
<Button
|
|
942
879
|
size="sm"
|
|
@@ -989,9 +926,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
989
926
|
type="password"
|
|
990
927
|
placeholder="Enter new value..."
|
|
991
928
|
value={secretValues[key] ?? ""}
|
|
992
|
-
onChange={(e) =>
|
|
993
|
-
setSecretValues((prev) => ({ ...prev, [key]: e.target.value }))
|
|
994
|
-
}
|
|
929
|
+
onChange={(e) => setSecretValues((prev) => ({ ...prev, [key]: e.target.value }))}
|
|
995
930
|
className="font-mono text-sm bg-transparent border-border focus:ring-terminal/50 focus:border-terminal/50"
|
|
996
931
|
/>
|
|
997
932
|
</TableCell>
|
|
@@ -1006,9 +941,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
1006
941
|
value={row.key}
|
|
1007
942
|
onChange={(e) =>
|
|
1008
943
|
setNewSecretRows((prev) =>
|
|
1009
|
-
prev.map((r) =>
|
|
1010
|
-
r.id === row.id ? { ...r, key: e.target.value } : r,
|
|
1011
|
-
),
|
|
944
|
+
prev.map((r) => (r.id === row.id ? { ...r, key: e.target.value } : r)),
|
|
1012
945
|
)
|
|
1013
946
|
}
|
|
1014
947
|
className="font-mono text-sm bg-transparent"
|
|
@@ -1021,9 +954,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
1021
954
|
value={row.value}
|
|
1022
955
|
onChange={(e) =>
|
|
1023
956
|
setNewSecretRows((prev) =>
|
|
1024
|
-
prev.map((r) =>
|
|
1025
|
-
r.id === row.id ? { ...r, value: e.target.value } : r,
|
|
1026
|
-
),
|
|
957
|
+
prev.map((r) => (r.id === row.id ? { ...r, value: e.target.value } : r)),
|
|
1027
958
|
)
|
|
1028
959
|
}
|
|
1029
960
|
className="font-mono text-sm bg-transparent"
|
|
@@ -1033,9 +964,7 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
1033
964
|
<Button
|
|
1034
965
|
size="sm"
|
|
1035
966
|
variant="ghost"
|
|
1036
|
-
onClick={() =>
|
|
1037
|
-
setNewSecretRows((prev) => prev.filter((r) => r.id !== row.id))
|
|
1038
|
-
}
|
|
967
|
+
onClick={() => setNewSecretRows((prev) => prev.filter((r) => r.id !== row.id))}
|
|
1039
968
|
>
|
|
1040
969
|
<Trash2 className="size-3.5 text-muted-foreground hover:text-destructive" />
|
|
1041
970
|
</Button>
|
|
@@ -1078,9 +1007,8 @@ export function InstanceDetailClient({ instanceId }: { instanceId: string }) {
|
|
|
1078
1007
|
<DialogHeader>
|
|
1079
1008
|
<DialogTitle>Destroy {instance.name} permanently?</DialogTitle>
|
|
1080
1009
|
<DialogDescription>
|
|
1081
|
-
This action is permanent and cannot be undone. The instance and all its data will be
|
|
1082
|
-
|
|
1083
|
-
confirm.
|
|
1010
|
+
This action is permanent and cannot be undone. The instance and all its data will be destroyed. Type{" "}
|
|
1011
|
+
<strong className="text-foreground">{instance.name}</strong> to confirm.
|
|
1084
1012
|
</DialogDescription>
|
|
1085
1013
|
</DialogHeader>
|
|
1086
1014
|
|
|
@@ -1161,9 +1089,7 @@ function MetricCard({
|
|
|
1161
1089
|
return (
|
|
1162
1090
|
<Card className="py-4">
|
|
1163
1091
|
<CardHeader className="pb-1">
|
|
1164
|
-
<CardTitle className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
1165
|
-
{title}
|
|
1166
|
-
</CardTitle>
|
|
1092
|
+
<CardTitle className="text-xs font-medium uppercase tracking-wider text-muted-foreground">{title}</CardTitle>
|
|
1167
1093
|
</CardHeader>
|
|
1168
1094
|
<CardContent className="space-y-2">
|
|
1169
1095
|
<div className="flex items-center gap-2">
|
|
@@ -8,13 +8,7 @@ import { logger } from "@/lib/logger";
|
|
|
8
8
|
|
|
9
9
|
const log = logger("error-boundary:instances");
|
|
10
10
|
|
|
11
|
-
export default function InstancesError({
|
|
12
|
-
error,
|
|
13
|
-
reset,
|
|
14
|
-
}: {
|
|
15
|
-
error: Error & { digest?: string };
|
|
16
|
-
reset: () => void;
|
|
17
|
-
}) {
|
|
11
|
+
export default function InstancesError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
|
|
18
12
|
const [showDetails, setShowDetails] = useState(false);
|
|
19
13
|
const isDev = process.env.NODE_ENV === "development";
|
|
20
14
|
|
|
@@ -32,9 +26,7 @@ export default function InstancesError({
|
|
|
32
26
|
</div>
|
|
33
27
|
</CardHeader>
|
|
34
28
|
<CardContent className="space-y-4">
|
|
35
|
-
<p className="text-muted-foreground">
|
|
36
|
-
Failed to load instance data. The API may be temporarily unavailable.
|
|
37
|
-
</p>
|
|
29
|
+
<p className="text-muted-foreground">Failed to load instance data. The API may be temporarily unavailable.</p>
|
|
38
30
|
{isDev && (
|
|
39
31
|
<Button
|
|
40
32
|
type="button"
|