@burdenoff/microfe-vibecontrols 2026.623.1 → 2026.623.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/actions/ActionCard.js +2 -2
- package/dist/components/actions/ActionCard.js.map +1 -1
- package/dist/components/actions/ActionTypeBadge.js +1 -1
- package/dist/components/actions/ActionTypeBadge.js.map +1 -1
- package/dist/components/actions/ExecutionHistory.js +1 -1
- package/dist/components/actions/ExecutionHistory.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerAdminBar.js +1 -1
- package/dist/components/agent-manager/AgentManagerAdminBar.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerChatPane.js +2 -2
- package/dist/components/agent-manager/AgentManagerChatPane.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerInputArea.js +4 -4
- package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerLayout.js +1 -1
- package/dist/components/agent-manager/AgentManagerLayout.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerMessageItem.js +1 -1
- package/dist/components/agent-manager/AgentManagerMessageItem.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerSidebar.js +5 -5
- package/dist/components/agent-manager/AgentManagerSidebar.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerTab.js +1 -1
- package/dist/components/agent-manager/AgentManagerTab.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerTabBar.js +1 -1
- package/dist/components/agent-manager/AgentManagerTabBar.js.map +1 -1
- package/dist/components/agent-manager/BridleConfigPanel.js +24 -24
- package/dist/components/agent-manager/BridleConfigPanel.js.map +1 -1
- package/dist/components/agent-manager/PluginInstallModal.js +1 -1
- package/dist/components/agent-manager/PluginInstallModal.js.map +1 -1
- package/dist/components/agent-manager/ProfilesPanel.js +5 -5
- package/dist/components/agent-manager/ProfilesPanel.js.map +1 -1
- package/dist/components/agent-manager/controls/AutonomySelector.js +1 -1
- package/dist/components/agent-manager/controls/AutonomySelector.js.map +1 -1
- package/dist/components/agent-manager/controls/SdkSelector.js +1 -1
- package/dist/components/agent-manager/controls/SdkSelector.js.map +1 -1
- package/dist/components/agent-manager/controls/VoiceToggle.js +1 -1
- package/dist/components/agent-manager/controls/VoiceToggle.js.map +1 -1
- package/dist/components/agent-manager/detail/SessionConfigPanel.js +6 -6
- package/dist/components/agent-manager/detail/SessionConfigPanel.js.map +1 -1
- package/dist/components/agent-manager/detail/SessionLogsPanel.js +5 -5
- package/dist/components/agent-manager/detail/SessionLogsPanel.js.map +1 -1
- package/dist/components/agent-manager/detail/SessionToolsPanel.js +1 -1
- package/dist/components/agent-manager/detail/SessionToolsPanel.js.map +1 -1
- package/dist/components/agent-manager/dialogs/NewSessionDialog.js +2 -2
- package/dist/components/agent-manager/dialogs/NewSessionDialog.js.map +1 -1
- package/dist/components/agent-manager/dialogs/RenameSessionDialog.js +1 -1
- package/dist/components/agent-manager/dialogs/RenameSessionDialog.js.map +1 -1
- package/dist/components/agents/AgentCard.js +14 -11
- package/dist/components/agents/AgentCard.js.map +1 -1
- package/dist/components/ai/AIContextsTab.js +1 -1
- package/dist/components/ai/AIContextsTab.js.map +1 -1
- package/dist/components/ai/AIOverviewTab.js +4 -4
- package/dist/components/ai/AIOverviewTab.js.map +1 -1
- package/dist/components/ai/AIPlanPanel.js +4 -4
- package/dist/components/ai/AIPlanPanel.js.map +1 -1
- package/dist/components/ai/AIPlaygroundTab.js +1 -1
- package/dist/components/ai/AIPlaygroundTab.js.map +1 -1
- package/dist/components/ai/AIPromptsTab.js +2 -2
- package/dist/components/ai/AIPromptsTab.js.map +1 -1
- package/dist/components/ai/AIProviderCredentialsCard.js +4 -4
- package/dist/components/ai/AIProviderCredentialsCard.js.map +1 -1
- package/dist/components/ai/AIQueueTab.js +4 -4
- package/dist/components/ai/AIQueueTab.js.map +1 -1
- package/dist/components/ai/AISessionsTab.js +4 -4
- package/dist/components/ai/AISessionsTab.js.map +1 -1
- package/dist/components/ai/AITasksTab.js +1 -1
- package/dist/components/ai/AITasksTab.js.map +1 -1
- package/dist/components/ai/ClaudeCredentialsCard.js +3 -3
- package/dist/components/ai/ClaudeCredentialsCard.js.map +1 -1
- package/dist/components/ai/PluginHarnessPicker.js +3 -3
- package/dist/components/ai/PluginHarnessPicker.js.map +1 -1
- package/dist/components/analytics/AnalyticsBreakdownChart.js +8 -8
- package/dist/components/analytics/AnalyticsBreakdownChart.js.map +1 -1
- package/dist/components/analytics/AnalyticsTimeSeriesChart.js +5 -5
- package/dist/components/analytics/AnalyticsTimeSeriesChart.js.map +1 -1
- package/dist/components/audit/AuditDeleteDialog.js +2 -2
- package/dist/components/audit/AuditDeleteDialog.js.map +1 -1
- package/dist/components/audit/AuditExportButton.js +5 -5
- package/dist/components/audit/AuditExportButton.js.map +1 -1
- package/dist/components/audit/AuditLogDetail.js +9 -9
- package/dist/components/audit/AuditLogDetail.js.map +1 -1
- package/dist/components/audit/AuditLogFilters.js +1 -1
- package/dist/components/audit/AuditLogFilters.js.map +1 -1
- package/dist/components/audit/AuditLogStats.js +1 -1
- package/dist/components/audit/AuditLogStats.js.map +1 -1
- package/dist/components/audit/AuditLogTable.js +28 -28
- package/dist/components/audit/AuditLogTable.js.map +1 -1
- package/dist/components/catalog/CatalogCard.js +3 -3
- package/dist/components/catalog/CatalogCard.js.map +1 -1
- package/dist/components/catalog/CatalogForm.js +1 -1
- package/dist/components/catalog/CatalogForm.js.map +1 -1
- package/dist/components/common/ActionAgentTargetNotice.js +6 -6
- package/dist/components/common/ActionAgentTargetNotice.js.map +1 -1
- package/dist/components/common/CommandEditor.js +1 -1
- package/dist/components/common/CommandEditor.js.map +1 -1
- package/dist/components/docs/DocsPageTree.js +1 -1
- package/dist/components/docs/DocsPageTree.js.map +1 -1
- package/dist/components/docs/DocsPreviewPanel.js +1 -1
- package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
- package/dist/components/docs/DocsRevisionHistory.js +4 -4
- package/dist/components/docs/DocsRevisionHistory.js.map +1 -1
- package/dist/components/docs/DocsSettingsPanel.js +7 -7
- package/dist/components/docs/DocsSettingsPanel.js.map +1 -1
- package/dist/components/docs/DocsTabPanel.js +1 -1
- package/dist/components/docs/DocsTabPanel.js.map +1 -1
- package/dist/components/graph/ConnectionPermissionsDialog.js +2 -2
- package/dist/components/graph/ConnectionPermissionsDialog.js.map +1 -1
- package/dist/components/graph/MeshDeployWizard.js +3 -3
- package/dist/components/graph/MeshDeployWizard.js.map +1 -1
- package/dist/components/graph/MeshRequestPanel.js +2 -2
- package/dist/components/graph/MeshRequestPanel.js.map +1 -1
- package/dist/components/idp-components/ComponentCard.js +5 -5
- package/dist/components/idp-components/ComponentCard.js.map +1 -1
- package/dist/components/idp-components/ComponentForm.js +1 -1
- package/dist/components/idp-components/ComponentForm.js.map +1 -1
- package/dist/components/idp-components/DependencyGraphTab.js +7 -7
- package/dist/components/idp-components/DependencyGraphTab.js.map +1 -1
- package/dist/components/logs/LogViewer.js +14 -14
- package/dist/components/logs/LogViewer.js.map +1 -1
- package/dist/components/notes/NoteCard.js +1 -1
- package/dist/components/notes/NoteCard.js.map +1 -1
- package/dist/components/notes/NoteEditor.js +2 -2
- package/dist/components/notes/NoteEditor.js.map +1 -1
- package/dist/components/notes/NoteList.js +1 -1
- package/dist/components/notes/NoteList.js.map +1 -1
- package/dist/components/notes/NotesTabPanel.js +1 -1
- package/dist/components/notes/NotesTabPanel.js.map +1 -1
- package/dist/components/scorecard/ScorecardEmptyState.js +1 -1
- package/dist/components/scorecard/ScorecardEmptyState.js.map +1 -1
- package/dist/components/scorecard/ScorecardPanel.js +3 -3
- package/dist/components/scorecard/ScorecardPanel.js.map +1 -1
- package/dist/components/security/SecurityScanList.js +11 -11
- package/dist/components/security/SecurityScanList.js.map +1 -1
- package/dist/components/sessions/SessionCard.js +26 -19
- package/dist/components/sessions/SessionCard.js.map +1 -1
- package/dist/components/sessions/SessionStatusBadge.js +7 -7
- package/dist/components/sessions/SessionStatusBadge.js.map +1 -1
- package/dist/components/shared/AgentSelector.js +4 -4
- package/dist/components/shared/AgentSelector.js.map +1 -1
- package/dist/components/shared/AgentSetupBanner.js +4 -4
- package/dist/components/shared/AgentSetupBanner.js.map +1 -1
- package/dist/components/shared/Card.js +4 -4
- package/dist/components/shared/Card.js.map +1 -1
- package/dist/components/shared/ErrorState.js +15 -9
- package/dist/components/shared/ErrorState.js.map +1 -1
- package/dist/components/shared/FilterDropdown.js +2 -2
- package/dist/components/shared/FilterDropdown.js.map +1 -1
- package/dist/components/shared/PageSkeleton.js +6 -6
- package/dist/components/shared/PageSkeleton.js.map +1 -1
- package/dist/components/shared/SearchInput.js +1 -1
- package/dist/components/shared/SearchInput.js.map +1 -1
- package/dist/components/shared/StatCard.js +7 -7
- package/dist/components/shared/StatCard.js.map +1 -1
- package/dist/components/templates/PublishTemplateForm.js +2 -2
- package/dist/components/templates/PublishTemplateForm.js.map +1 -1
- package/dist/components/templates/TemplateCard.js +5 -5
- package/dist/components/templates/TemplateCard.js.map +1 -1
- package/dist/components/templates/TemplateWizard.js +2 -2
- package/dist/components/templates/TemplateWizard.js.map +1 -1
- package/dist/components/tunnels/DomainVerificationBadge.js +4 -4
- package/dist/components/tunnels/DomainVerificationBadge.js.map +1 -1
- package/dist/components/tunnels/ProviderBadge.js +1 -1
- package/dist/components/tunnels/ProviderBadge.js.map +1 -1
- package/dist/components/tunnels/TunnelCard.js +16 -16
- package/dist/components/tunnels/TunnelCard.js.map +1 -1
- package/dist/components/tunnels/TunnelCreateWizard.js +1 -1
- package/dist/components/tunnels/TunnelCreateWizard.js.map +1 -1
- package/dist/components/tunnels/TunnelPublicAccessPanel.js +1 -1
- package/dist/components/tunnels/TunnelPublicAccessPanel.js.map +1 -1
- package/dist/components/tunnels/TunnelStatusBadge.js +4 -4
- package/dist/components/tunnels/TunnelStatusBadge.js.map +1 -1
- package/dist/components/vibecalendar/LogsDrawer.js +2 -2
- package/dist/components/vibecalendar/LogsDrawer.js.map +1 -1
- package/dist/components/vibecalendar/ScheduleTaskModal.js +5 -5
- package/dist/components/vibecalendar/ScheduleTaskModal.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalAgendaView.js +2 -2
- package/dist/components/vibecalendar/VibeCalAgendaView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalDayView.js +3 -3
- package/dist/components/vibecalendar/VibeCalDayView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalMonthView.js +1 -1
- package/dist/components/vibecalendar/VibeCalMonthView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalWeekView.js +4 -4
- package/dist/components/vibecalendar/VibeCalWeekView.js.map +1 -1
- package/dist/components/vibecalendar/VibeCalendarHeader.js +4 -4
- package/dist/components/vibecalendar/VibeCalendarHeader.js.map +1 -1
- package/dist/components/vibecalendar/VibeTaskBlock.js +2 -2
- package/dist/components/vibecalendar/VibeTaskBlock.js.map +1 -1
- package/dist/components/vibecalendar/types.js +7 -7
- package/dist/components/vibecalendar/types.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckButtonForm.js +9 -9
- package/dist/components/vibedeck/VibeDeckButtonForm.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckButtonTile.js +6 -6
- package/dist/components/vibedeck/VibeDeckButtonTile.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckExecutionLog.js +10 -10
- package/dist/components/vibedeck/VibeDeckExecutionLog.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckForm.js +8 -8
- package/dist/components/vibedeck/VibeDeckForm.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckGrid.js +2 -2
- package/dist/components/vibedeck/VibeDeckGrid.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js +2 -2
- package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckSwitcher.js +8 -8
- package/dist/components/vibedeck/VibeDeckSwitcher.js.map +1 -1
- package/dist/components/vibes/VibeCard.js +22 -18
- package/dist/components/vibes/VibeCard.js.map +1 -1
- package/dist/components/vibes/VibeList.js +16 -12
- package/dist/components/vibes/VibeList.js.map +1 -1
- package/dist/pages/ActionsPage.js +4 -3
- package/dist/pages/ActionsPage.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +9 -9
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/AgentsLandingPage.js +4 -4
- package/dist/pages/AgentsLandingPage.js.map +1 -1
- package/dist/pages/AgentsPage.js +14 -14
- package/dist/pages/AgentsPage.js.map +1 -1
- package/dist/pages/AnalyticsPage.js +8 -8
- package/dist/pages/AnalyticsPage.js.map +1 -1
- package/dist/pages/CatalogDetailPage.js +11 -11
- package/dist/pages/CatalogDetailPage.js.map +1 -1
- package/dist/pages/CatalogPage.js +12 -9
- package/dist/pages/CatalogPage.js.map +1 -1
- package/dist/pages/ComponentDetailPage.js +7 -7
- package/dist/pages/ComponentDetailPage.js.map +1 -1
- package/dist/pages/ComponentsPage.js +12 -9
- package/dist/pages/ComponentsPage.js.map +1 -1
- package/dist/pages/EnvTopologyPage.js +2 -2
- package/dist/pages/EnvTopologyPage.js.map +1 -1
- package/dist/pages/GettingStartedPage.js +12 -12
- package/dist/pages/GettingStartedPage.js.map +1 -1
- package/dist/pages/HealthPage.js +12 -12
- package/dist/pages/HealthPage.js.map +1 -1
- package/dist/pages/LogsPage.js +4 -4
- package/dist/pages/LogsPage.js.map +1 -1
- package/dist/pages/NoteDetailsPage.js +5 -5
- package/dist/pages/NoteDetailsPage.js.map +1 -1
- package/dist/pages/OverviewPage.js +76 -43
- package/dist/pages/OverviewPage.js.map +1 -1
- package/dist/pages/PluginsCatalogPage.js +7 -4
- package/dist/pages/PluginsCatalogPage.js.map +1 -1
- package/dist/pages/ScheduledJobDetailPage.js +7 -7
- package/dist/pages/ScheduledJobDetailPage.js.map +1 -1
- package/dist/pages/SessionDetailsPage.js +21 -21
- package/dist/pages/SessionDetailsPage.js.map +1 -1
- package/dist/pages/SessionsPage.js +20 -20
- package/dist/pages/SessionsPage.js.map +1 -1
- package/dist/pages/SettingsPage.js +64 -52
- package/dist/pages/SettingsPage.js.map +1 -1
- package/dist/pages/SharedSessionPage.js +21 -21
- package/dist/pages/SharedSessionPage.js.map +1 -1
- package/dist/pages/SharedVibeDeckPage.js +5 -5
- package/dist/pages/SharedVibeDeckPage.js.map +1 -1
- package/dist/pages/TargetDetailsPage.js +56 -65
- package/dist/pages/TargetDetailsPage.js.map +1 -1
- package/dist/pages/TargetsPage.js +4 -4
- package/dist/pages/TargetsPage.js.map +1 -1
- package/dist/pages/TemplateDetailPage.js +10 -10
- package/dist/pages/TemplateDetailPage.js.map +1 -1
- package/dist/pages/TemplatesPage.js +6 -5
- package/dist/pages/TemplatesPage.js.map +1 -1
- package/dist/pages/VibeAuditPage.js +3 -3
- package/dist/pages/VibeAuditPage.js.map +1 -1
- package/dist/pages/VibeCalendarPage.js +3 -3
- package/dist/pages/VibeCalendarPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +3 -3
- package/dist/pages/VibeDeckPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +15 -15
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/VibeTaskDetailPage.js +5 -5
- package/dist/pages/VibeTaskDetailPage.js.map +1 -1
- package/dist/pages/VibesPage.js +18 -18
- package/dist/pages/VibesPage.js.map +1 -1
- package/dist/pages/WebhooksPage.js +11 -11
- package/dist/pages/WebhooksPage.js.map +1 -1
- package/dist/pages/ai/AIBookmarksPage.js +1 -1
- package/dist/pages/ai/AIBookmarksPage.js.map +1 -1
- package/dist/pages/ai/AISessionDetailPage.js +6 -6
- package/dist/pages/ai/AISessionDetailPage.js.map +1 -1
- package/dist/pages/tunnels/AuditTab.js +1 -1
- package/dist/pages/tunnels/AuditTab.js.map +1 -1
- package/dist/pages/tunnels/DomainsTab.js +1 -1
- package/dist/pages/tunnels/DomainsTab.js.map +1 -1
- package/dist/pages/tunnels/ProvidersTab.js +1 -1
- package/dist/pages/tunnels/ProvidersTab.js.map +1 -1
- package/dist/pages/tunnels/SessionsTab.js +1 -1
- package/dist/pages/tunnels/SessionsTab.js.map +1 -1
- package/dist/pages/tunnels/TunnelDetailsPage.js +3 -3
- package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
- package/dist/pages/tunnels/UsageTab.js +1 -1
- package/dist/pages/tunnels/UsageTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelDomainsTab.js +16 -16
- package/dist/pages/tunnels/tabs/TunnelDomainsTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelOverviewTab.js +1 -1
- package/dist/pages/tunnels/tabs/TunnelOverviewTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelSessionsTab.js +52 -49
- package/dist/pages/tunnels/tabs/TunnelSessionsTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelSettingsTab.js +9 -9
- package/dist/pages/tunnels/tabs/TunnelSettingsTab.js.map +1 -1
- package/package.json +1 -1
|
@@ -21,14 +21,14 @@ function f({ tunnel: f, canCreate: p, canUpdate: m }) {
|
|
|
21
21
|
return /* @__PURE__ */ d("div", {
|
|
22
22
|
className: "max-w-4xl",
|
|
23
23
|
children: [p && /* @__PURE__ */ d("section", {
|
|
24
|
-
className: "rounded-
|
|
24
|
+
className: "rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 p-5 mb-6",
|
|
25
25
|
children: [
|
|
26
26
|
/* @__PURE__ */ u("h3", {
|
|
27
|
-
className: "text-sm font-semibold text-text-primary mb-3",
|
|
27
|
+
className: "text-sm font-semibold text-text-primary tracking-tight mb-3",
|
|
28
28
|
children: h("vibecontrols.tunnels.domains.attachCustomDomain", "Attach a custom domain")
|
|
29
29
|
}),
|
|
30
30
|
/* @__PURE__ */ u("p", {
|
|
31
|
-
className: "text-xs text-text-secondary mb-
|
|
31
|
+
className: "text-xs text-text-secondary mb-4",
|
|
32
32
|
children: "Register a user-owned FQDN. You'll be asked to create a TXT record to prove ownership before the domain can be attached."
|
|
33
33
|
}),
|
|
34
34
|
/* @__PURE__ */ d("div", {
|
|
@@ -39,24 +39,24 @@ function f({ tunnel: f, canCreate: p, canUpdate: m }) {
|
|
|
39
39
|
value: _,
|
|
40
40
|
onChange: (e) => v(e.target.value),
|
|
41
41
|
placeholder: "preview.example.com",
|
|
42
|
-
className: "flex-1 rounded-
|
|
42
|
+
className: "flex-1 rounded-input border border-border-subtle bg-bg-sunken px-3 py-2 text-sm text-text-primary placeholder:text-text-placeholder transition-colors focus:border-border-strong focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]"
|
|
43
43
|
}), /* @__PURE__ */ u("button", {
|
|
44
44
|
type: "button",
|
|
45
45
|
disabled: S || !_.trim(),
|
|
46
46
|
onClick: () => void E(),
|
|
47
|
-
className: "rounded-
|
|
47
|
+
className: "rounded-button bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bgHover transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
48
48
|
children: S ? h("vibecontrols.tunnels.domains.adding", "Adding...") : h("vibecontrols.tunnels.domains.addDomain", "Add domain")
|
|
49
49
|
})]
|
|
50
50
|
}),
|
|
51
51
|
y && /* @__PURE__ */ u("p", {
|
|
52
|
-
className: "mt-2 text-xs text-status-error-
|
|
52
|
+
className: "mt-2 text-xs text-status-error-text",
|
|
53
53
|
children: y
|
|
54
54
|
})
|
|
55
55
|
]
|
|
56
56
|
}), /* @__PURE__ */ u("div", {
|
|
57
|
-
className: "rounded-
|
|
57
|
+
className: "rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 overflow-x-auto",
|
|
58
58
|
children: D.length === 0 ? /* @__PURE__ */ u("div", {
|
|
59
|
-
className: "p-
|
|
59
|
+
className: "p-5 text-sm text-text-muted",
|
|
60
60
|
children: "No domains attached. Add one above or reserve a *.vibetunnels.com subdomain from the Tunnels tab."
|
|
61
61
|
}) : /* @__PURE__ */ d("table", {
|
|
62
62
|
className: "min-w-[480px] w-full text-sm",
|
|
@@ -64,26 +64,26 @@ function f({ tunnel: f, canCreate: p, canUpdate: m }) {
|
|
|
64
64
|
className: "border-b border-border-subtle bg-bg-sunken",
|
|
65
65
|
children: [
|
|
66
66
|
/* @__PURE__ */ u("th", {
|
|
67
|
-
className: "px-4 py-2 text-left text-xs font-medium text-text-muted",
|
|
67
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
68
68
|
children: "Domain"
|
|
69
69
|
}),
|
|
70
70
|
/* @__PURE__ */ u("th", {
|
|
71
|
-
className: "px-4 py-2 text-left text-xs font-medium text-text-muted whitespace-nowrap",
|
|
71
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-text-muted whitespace-nowrap",
|
|
72
72
|
children: "Status"
|
|
73
73
|
}),
|
|
74
74
|
/* @__PURE__ */ u("th", {
|
|
75
|
-
className: "px-4 py-2 text-left text-xs font-medium text-text-muted whitespace-nowrap",
|
|
75
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-text-muted whitespace-nowrap",
|
|
76
76
|
children: "Type"
|
|
77
77
|
}),
|
|
78
78
|
/* @__PURE__ */ u("th", {
|
|
79
|
-
className: "px-4 py-2 text-right text-xs font-medium text-text-muted whitespace-nowrap",
|
|
79
|
+
className: "px-4 py-2.5 text-right text-xs font-medium uppercase tracking-wide text-text-muted whitespace-nowrap",
|
|
80
80
|
children: "Actions"
|
|
81
81
|
})
|
|
82
82
|
]
|
|
83
83
|
}) }), /* @__PURE__ */ u("tbody", {
|
|
84
84
|
className: "divide-y divide-border-subtle",
|
|
85
85
|
children: D.map((e) => /* @__PURE__ */ d(c, { children: [/* @__PURE__ */ d("tr", {
|
|
86
|
-
className: "align-middle",
|
|
86
|
+
className: "align-middle hover:bg-bg-sunken transition-colors",
|
|
87
87
|
children: [
|
|
88
88
|
/* @__PURE__ */ u("td", {
|
|
89
89
|
className: "px-4 py-3",
|
|
@@ -110,7 +110,7 @@ function f({ tunnel: f, canCreate: p, canUpdate: m }) {
|
|
|
110
110
|
children: [m && e.verificationStatus === o.Pending && /* @__PURE__ */ u("button", {
|
|
111
111
|
type: "button",
|
|
112
112
|
onClick: () => void T({ variables: { domainId: e.id } }),
|
|
113
|
-
className: "rounded-
|
|
113
|
+
className: "rounded-button border border-border-subtle px-3 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken hover:border-border-strong transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
114
114
|
children: "Verify"
|
|
115
115
|
}), m && /* @__PURE__ */ u("button", {
|
|
116
116
|
type: "button",
|
|
@@ -118,7 +118,7 @@ function f({ tunnel: f, canCreate: p, canUpdate: m }) {
|
|
|
118
118
|
tunnelId: f.id,
|
|
119
119
|
domainId: e.id
|
|
120
120
|
} }),
|
|
121
|
-
className: "rounded-
|
|
121
|
+
className: "rounded-button border border-border-subtle px-3 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken hover:border-border-strong transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
122
122
|
children: "Detach"
|
|
123
123
|
})]
|
|
124
124
|
})
|
|
@@ -128,7 +128,7 @@ function f({ tunnel: f, canCreate: p, canUpdate: m }) {
|
|
|
128
128
|
colSpan: 4,
|
|
129
129
|
className: "px-4 pb-3 pt-0",
|
|
130
130
|
children: /* @__PURE__ */ d("div", {
|
|
131
|
-
className: "rounded-
|
|
131
|
+
className: "rounded-button border border-border-subtle bg-bg-sunken p-3 text-xs text-text-secondary",
|
|
132
132
|
children: [/* @__PURE__ */ u("div", { children: "Create this TXT record to verify:" }), /* @__PURE__ */ d("div", {
|
|
133
133
|
className: "font-mono text-text-primary mt-1 break-all",
|
|
134
134
|
children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TunnelDomainsTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelDomainsTab.tsx"],"sourcesContent":["import { Fragment, useState } from 'react';\nimport type { GetTunnelQuery } from '@/generated/wspace-operations';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport {\n useRegisterCustomTunnelDomainMutation,\n useAttachTunnelDomainMutation,\n useDetachTunnelDomainMutation,\n useVerifyTunnelDomainMutation,\n useGetTunnelQuery,\n} from '@/generated/wspace-operations';\nimport { TunnelDomainVerificationStatus } from '@/generated/wspace-types';\nimport { DomainVerificationBadge } from '@/components/tunnels/DomainVerificationBadge';\n\ntype TunnelDetails = NonNullable<GetTunnelQuery['tunnel']>;\n\nexport function TunnelDomainsTab({\n tunnel,\n canCreate,\n canUpdate,\n}: {\n tunnel: TunnelDetails;\n canCreate: boolean;\n canUpdate: boolean;\n}) {\n const tr = useTr();\n const { refetch } = useGetTunnelQuery({ variables: { id: tunnel.id } });\n const [newHostname, setNewHostname] = useState('');\n const [addError, setAddError] = useState<string | null>(null);\n\n const [registerDomain, { loading: adding }] = useRegisterCustomTunnelDomainMutation({\n onCompleted: async (result) => {\n await refetch();\n if (result.registerCustomTunnelDomain.id) {\n await attachDomain({\n variables: {\n tunnelId: tunnel.id,\n domainId: result.registerCustomTunnelDomain.id,\n },\n });\n }\n setNewHostname('');\n setAddError(null);\n },\n onError: (err) => setAddError(err.message),\n });\n const [attachDomain] = useAttachTunnelDomainMutation({\n onCompleted: () => void refetch(),\n });\n const [detachDomain] = useDetachTunnelDomainMutation({\n onCompleted: () => void refetch(),\n });\n const [verifyDomain] = useVerifyTunnelDomainMutation({\n onCompleted: () => void refetch(),\n });\n\n const handleAdd = async () => {\n const trimmed = newHostname.trim().toLowerCase();\n if (!trimmed) return;\n await registerDomain({ variables: { input: { hostname: trimmed } } });\n };\n\n const domains = tunnel.domains ?? [];\n\n return (\n <div className=\"max-w-4xl\">\n {canCreate && (\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 mb-6\">\n <h3 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tr('vibecontrols.tunnels.domains.attachCustomDomain', 'Attach a custom domain')}\n </h3>\n <p className=\"text-xs text-text-secondary mb-3\">\n Register a user-owned FQDN. You'll be asked to create a TXT record to prove ownership\n before the domain can be attached.\n </p>\n <div className=\"flex gap-2\">\n <input\n aria-label=\"preview.example.com\"\n type=\"text\"\n value={newHostname}\n onChange={(e) => setNewHostname(e.target.value)}\n placeholder=\"preview.example.com\"\n className=\"flex-1 rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-border-focus focus:outline-none\"\n />\n <button\n type=\"button\"\n disabled={adding || !newHostname.trim()}\n onClick={() => void handleAdd()}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-fg hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {adding\n ? tr('vibecontrols.tunnels.domains.adding', 'Adding...')\n : tr('vibecontrols.tunnels.domains.addDomain', 'Add domain')}\n </button>\n </div>\n {addError && <p className=\"mt-2 text-xs text-status-error-fg\">{addError}</p>}\n </section>\n )}\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface overflow-x-auto\">\n {domains.length === 0 ? (\n <div className=\"p-4 text-sm text-text-muted\">\n No domains attached. Add one above or reserve a *.vibetunnels.com subdomain from the\n Tunnels tab.\n </div>\n ) : (\n <table className=\"min-w-[480px] w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken\">\n <th className=\"px-4 py-2 text-left text-xs font-medium text-text-muted\">Domain</th>\n <th className=\"px-4 py-2 text-left text-xs font-medium text-text-muted whitespace-nowrap\">\n Status\n </th>\n <th className=\"px-4 py-2 text-left text-xs font-medium text-text-muted whitespace-nowrap\">\n Type\n </th>\n <th className=\"px-4 py-2 text-right text-xs font-medium text-text-muted whitespace-nowrap\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border-subtle\">\n {domains.map((domain) => (\n <Fragment key={domain.id}>\n <tr className=\"align-middle\">\n <td className=\"px-4 py-3\">\n <div className=\"font-mono text-sm text-text-primary break-all min-w-[140px]\">\n {domain.hostname}\n </div>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <DomainVerificationBadge status={domain.verificationStatus} />\n </td>\n <td className=\"px-4 py-3 text-xs text-text-muted whitespace-nowrap\">\n {domain.type}\n {domain.isPrimary && <span className=\"ml-1\">• primary</span>}\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap text-right\">\n <div className=\"flex gap-2 justify-end\">\n {canUpdate &&\n domain.verificationStatus === TunnelDomainVerificationStatus.Pending && (\n <button\n type=\"button\"\n onClick={() =>\n void verifyDomain({ variables: { domainId: domain.id } })\n }\n className=\"rounded-md border border-border-default px-3 py-1 text-xs text-text-primary hover:bg-bg-elevated\"\n >\n Verify\n </button>\n )}\n {canUpdate && (\n <button\n type=\"button\"\n onClick={() =>\n void detachDomain({\n variables: { tunnelId: tunnel.id, domainId: domain.id },\n })\n }\n className=\"rounded-md border border-border-default px-3 py-1 text-xs text-text-primary hover:bg-bg-elevated\"\n >\n Detach\n </button>\n )}\n </div>\n </td>\n </tr>\n {domain.verificationStatus === TunnelDomainVerificationStatus.Pending &&\n domain.challengeRecordName &&\n domain.challengeToken && (\n <tr>\n <td colSpan={4} className=\"px-4 pb-3 pt-0\">\n <div className=\"rounded-md bg-bg-sunken p-2 text-xs text-text-secondary\">\n <div>Create this TXT record to verify:</div>\n <div className=\"font-mono text-text-primary mt-1 break-all\">\n {domain.challengeRecordName} IN TXT "{domain.challengeToken}\n "\n </div>\n </div>\n </td>\n </tr>\n )}\n </Fragment>\n ))}\n </tbody>\n </table>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAeA,SAAgB,EAAiB,EAC/B,WACA,cACA,gBAKC;CACD,IAAM,IAAK,GAAO,EACZ,EAAE,eAAY,EAAkB,EAAE,WAAW,EAAE,IAAI,EAAO,IAAI,EAAE,CAAC,EACjE,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAU,KAAe,EAAwB,KAAK,EAEvD,CAAC,GAAgB,EAAE,SAAS,OAAY,EAAsC;EAClF,aAAa,OAAO,MAAW;AAW7B,GAVA,MAAM,GAAS,EACX,EAAO,2BAA2B,MACpC,MAAM,EAAa,EACjB,WAAW;IACT,UAAU,EAAO;IACjB,UAAU,EAAO,2BAA2B;IAC7C,EACF,CAAC,EAEJ,EAAe,GAAG,EAClB,EAAY,KAAK;;EAEnB,UAAU,MAAQ,EAAY,EAAI,QAAQ;EAC3C,CAAC,EACI,CAAC,KAAgB,EAA8B,EACnD,mBAAmB,KAAK,GAAS,EAClC,CAAC,EACI,CAAC,KAAgB,EAA8B,EACnD,mBAAmB,KAAK,GAAS,EAClC,CAAC,EACI,CAAC,KAAgB,EAA8B,EACnD,mBAAmB,KAAK,GAAS,EAClC,CAAC,EAEI,IAAY,YAAY;EAC5B,IAAM,IAAU,EAAY,MAAM,CAAC,aAAa;AAC3C,OACL,MAAM,EAAe,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,GAAS,EAAE,EAAE,CAAC;IAGjE,IAAU,EAAO,WAAW,EAAE;AAEpC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KACC,kBAAC,WAAD;GAAS,WAAU;aAAnB;IACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,mDAAmD,yBAAyB;KAC7E,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eAAmC;KAG5C,CAAA;IACJ,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,SAAD;MACE,cAAW;MACX,MAAK;MACL,OAAO;MACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;MAC/C,aAAY;MACZ,WAAU;MACV,CAAA,EACF,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,KAAU,CAAC,EAAY,MAAM;MACvC,eAAe,KAAK,GAAW;MAC/B,WAAU;gBAET,IACG,EAAG,uCAAuC,YAAY,GACtD,EAAG,0CAA0C,aAAa;MACvD,CAAA,CACL;;IACL,KAAY,kBAAC,KAAD;KAAG,WAAU;eAAqC;KAAa,CAAA;IACpE;MAGZ,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAQ,WAAW,IAClB,kBAAC,OAAD;IAAK,WAAU;cAA8B;IAGvC,CAAA,GAEN,kBAAC,SAAD;IAAO,WAAU;cAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;KAAI,WAAU;eAAd;MACE,kBAAC,MAAD;OAAI,WAAU;iBAA0D;OAAW,CAAA;MACnF,kBAAC,MAAD;OAAI,WAAU;iBAA4E;OAErF,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBAA4E;OAErF,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBAA6E;OAEtF,CAAA;MACF;QACC,CAAA,EACR,kBAAC,SAAD;KAAO,WAAU;eACd,EAAQ,KAAK,MACZ,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAAd;OACE,kBAAC,MAAD;QAAI,WAAU;kBACZ,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAO;SACJ,CAAA;QACH,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBACZ,kBAAC,GAAD,EAAyB,QAAQ,EAAO,oBAAsB,CAAA;QAC3D,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAAd,CACG,EAAO,MACP,EAAO,aAAa,kBAAC,QAAD;SAAM,WAAU;mBAAO;SAAgB,CAAA,CACzD;;OACL,kBAAC,MAAD;QAAI,WAAU;kBACZ,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACG,KACC,EAAO,uBAAuB,EAA+B,WAC3D,kBAAC,UAAD;UACE,MAAK;UACL,eACE,KAAK,EAAa,EAAE,WAAW,EAAE,UAAU,EAAO,IAAI,EAAE,CAAC;UAE3D,WAAU;oBACX;UAEQ,CAAA,EAEZ,KACC,kBAAC,UAAD;UACE,MAAK;UACL,eACE,KAAK,EAAa,EAChB,WAAW;WAAE,UAAU,EAAO;WAAI,UAAU,EAAO;WAAI,EACxD,CAAC;UAEJ,WAAU;oBACX;UAEQ,CAAA,CAEP;;QACH,CAAA;OACF;SACJ,EAAO,uBAAuB,EAA+B,WAC5D,EAAO,uBACP,EAAO,kBACL,kBAAC,MAAD,EAAA,UACE,kBAAC,MAAD;MAAI,SAAS;MAAG,WAAU;gBACxB,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD,EAAA,UAAK,qCAAuC,CAAA,EAC5C,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACG,EAAO;SAAoB;SAAe,EAAO;SAAe;SAE7D;UACF;;MACH,CAAA,EACF,CAAA,CAEA,EAAA,EA3DI,EAAO,GA2DX,CACX;KACI,CAAA,CACF;;GAEN,CAAA,CACF"}
|
|
1
|
+
{"version":3,"file":"TunnelDomainsTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelDomainsTab.tsx"],"sourcesContent":["import { Fragment, useState } from 'react';\nimport type { GetTunnelQuery } from '@/generated/wspace-operations';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport {\n useRegisterCustomTunnelDomainMutation,\n useAttachTunnelDomainMutation,\n useDetachTunnelDomainMutation,\n useVerifyTunnelDomainMutation,\n useGetTunnelQuery,\n} from '@/generated/wspace-operations';\nimport { TunnelDomainVerificationStatus } from '@/generated/wspace-types';\nimport { DomainVerificationBadge } from '@/components/tunnels/DomainVerificationBadge';\n\ntype TunnelDetails = NonNullable<GetTunnelQuery['tunnel']>;\n\nexport function TunnelDomainsTab({\n tunnel,\n canCreate,\n canUpdate,\n}: {\n tunnel: TunnelDetails;\n canCreate: boolean;\n canUpdate: boolean;\n}) {\n const tr = useTr();\n const { refetch } = useGetTunnelQuery({ variables: { id: tunnel.id } });\n const [newHostname, setNewHostname] = useState('');\n const [addError, setAddError] = useState<string | null>(null);\n\n const [registerDomain, { loading: adding }] = useRegisterCustomTunnelDomainMutation({\n onCompleted: async (result) => {\n await refetch();\n if (result.registerCustomTunnelDomain.id) {\n await attachDomain({\n variables: {\n tunnelId: tunnel.id,\n domainId: result.registerCustomTunnelDomain.id,\n },\n });\n }\n setNewHostname('');\n setAddError(null);\n },\n onError: (err) => setAddError(err.message),\n });\n const [attachDomain] = useAttachTunnelDomainMutation({\n onCompleted: () => void refetch(),\n });\n const [detachDomain] = useDetachTunnelDomainMutation({\n onCompleted: () => void refetch(),\n });\n const [verifyDomain] = useVerifyTunnelDomainMutation({\n onCompleted: () => void refetch(),\n });\n\n const handleAdd = async () => {\n const trimmed = newHostname.trim().toLowerCase();\n if (!trimmed) return;\n await registerDomain({ variables: { input: { hostname: trimmed } } });\n };\n\n const domains = tunnel.domains ?? [];\n\n return (\n <div className=\"max-w-4xl\">\n {canCreate && (\n <section className=\"rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 p-5 mb-6\">\n <h3 className=\"text-sm font-semibold text-text-primary tracking-tight mb-3\">\n {tr('vibecontrols.tunnels.domains.attachCustomDomain', 'Attach a custom domain')}\n </h3>\n <p className=\"text-xs text-text-secondary mb-4\">\n Register a user-owned FQDN. You'll be asked to create a TXT record to prove ownership\n before the domain can be attached.\n </p>\n <div className=\"flex gap-2\">\n <input\n aria-label=\"preview.example.com\"\n type=\"text\"\n value={newHostname}\n onChange={(e) => setNewHostname(e.target.value)}\n placeholder=\"preview.example.com\"\n className=\"flex-1 rounded-input border border-border-subtle bg-bg-sunken px-3 py-2 text-sm text-text-primary placeholder:text-text-placeholder transition-colors focus:border-border-strong focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n <button\n type=\"button\"\n disabled={adding || !newHostname.trim()}\n onClick={() => void handleAdd()}\n className=\"rounded-button bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bgHover transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n {adding\n ? tr('vibecontrols.tunnels.domains.adding', 'Adding...')\n : tr('vibecontrols.tunnels.domains.addDomain', 'Add domain')}\n </button>\n </div>\n {addError && <p className=\"mt-2 text-xs text-status-error-text\">{addError}</p>}\n </section>\n )}\n\n <div className=\"rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 overflow-x-auto\">\n {domains.length === 0 ? (\n <div className=\"p-5 text-sm text-text-muted\">\n No domains attached. Add one above or reserve a *.vibetunnels.com subdomain from the\n Tunnels tab.\n </div>\n ) : (\n <table className=\"min-w-[480px] w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken\">\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n Domain\n </th>\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-text-muted whitespace-nowrap\">\n Status\n </th>\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-text-muted whitespace-nowrap\">\n Type\n </th>\n <th className=\"px-4 py-2.5 text-right text-xs font-medium uppercase tracking-wide text-text-muted whitespace-nowrap\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border-subtle\">\n {domains.map((domain) => (\n <Fragment key={domain.id}>\n <tr className=\"align-middle hover:bg-bg-sunken transition-colors\">\n <td className=\"px-4 py-3\">\n <div className=\"font-mono text-sm text-text-primary break-all min-w-[140px]\">\n {domain.hostname}\n </div>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <DomainVerificationBadge status={domain.verificationStatus} />\n </td>\n <td className=\"px-4 py-3 text-xs text-text-muted whitespace-nowrap\">\n {domain.type}\n {domain.isPrimary && <span className=\"ml-1\">• primary</span>}\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap text-right\">\n <div className=\"flex gap-2 justify-end\">\n {canUpdate &&\n domain.verificationStatus === TunnelDomainVerificationStatus.Pending && (\n <button\n type=\"button\"\n onClick={() =>\n void verifyDomain({ variables: { domainId: domain.id } })\n }\n className=\"rounded-button border border-border-subtle px-3 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken hover:border-border-strong transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n Verify\n </button>\n )}\n {canUpdate && (\n <button\n type=\"button\"\n onClick={() =>\n void detachDomain({\n variables: { tunnelId: tunnel.id, domainId: domain.id },\n })\n }\n className=\"rounded-button border border-border-subtle px-3 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken hover:border-border-strong transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n Detach\n </button>\n )}\n </div>\n </td>\n </tr>\n {domain.verificationStatus === TunnelDomainVerificationStatus.Pending &&\n domain.challengeRecordName &&\n domain.challengeToken && (\n <tr>\n <td colSpan={4} className=\"px-4 pb-3 pt-0\">\n <div className=\"rounded-button border border-border-subtle bg-bg-sunken p-3 text-xs text-text-secondary\">\n <div>Create this TXT record to verify:</div>\n <div className=\"font-mono text-text-primary mt-1 break-all\">\n {domain.challengeRecordName} IN TXT "{domain.challengeToken}\n "\n </div>\n </div>\n </td>\n </tr>\n )}\n </Fragment>\n ))}\n </tbody>\n </table>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -130,7 +130,7 @@ function i({ tunnel: i, canUpdate: a, onChanged: o }) {
|
|
|
130
130
|
onChanged: o
|
|
131
131
|
}),
|
|
132
132
|
i.lastError && /* @__PURE__ */ r("section", {
|
|
133
|
-
className: "md:col-span-2 rounded-
|
|
133
|
+
className: "md:col-span-2 rounded-card border border-status-error-border bg-status-error-bg-subtle p-4 text-sm text-status-error-text",
|
|
134
134
|
children: [
|
|
135
135
|
/* @__PURE__ */ n("strong", { children: "Last error:" }),
|
|
136
136
|
" ",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TunnelOverviewTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelOverviewTab.tsx"],"sourcesContent":["import type { GetTunnelQuery } from '@/generated/wspace-operations';\nimport { TunnelPublicAccessPanel } from '@/components/tunnels/TunnelPublicAccessPanel';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ntype TunnelDetails = NonNullable<GetTunnelQuery['tunnel']>;\n\nexport function TunnelOverviewTab({\n tunnel,\n canUpdate,\n onChanged,\n}: {\n tunnel: TunnelDetails;\n canUpdate: boolean;\n onChanged: () => void;\n}) {\n const tr = useTr();\n const sessionCount = tunnel.activeSessions?.length ?? 0;\n const domainCount = tunnel.domains?.length ?? 0;\n const publicUrl = tunnel.primaryDomain?.hostname\n ? `https://${tunnel.primaryDomain.hostname}`\n : null;\n return (\n <div className=\"grid gap-6 md:grid-cols-2 max-w-4xl\">\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tr('vibecontrols.tunnels.overview.configuration', 'Configuration')}\n </h3>\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-muted\">Slug</dt>\n <dd className=\"text-text-primary font-mono\">{tunnel.slug}</dd>\n <dt className=\"text-text-muted\">Provider</dt>\n <dd className=\"text-text-primary\">{tunnel.providerKey}</dd>\n <dt className=\"text-text-muted\">Protocol</dt>\n <dd className=\"text-text-primary\">{tunnel.protocol}</dd>\n <dt className=\"text-text-muted\">TLS mode</dt>\n <dd className=\"text-text-primary\">{tunnel.tlsMode}</dd>\n <dt className=\"text-text-muted\">Local target</dt>\n <dd className=\"text-text-primary font-mono\">\n {tunnel.localHost}:{tunnel.localPort}\n </dd>\n <dt className=\"text-text-muted\">Basic auth</dt>\n <dd className=\"text-text-primary\">\n {tunnel.hasBasicAuth ? (tunnel.basicAuthUser ?? 'configured') : 'off'}\n </dd>\n </dl>\n </section>\n\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tr('vibecontrols.tunnels.overview.activity', 'Activity')}\n </h3>\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-muted\">Active sessions</dt>\n <dd className=\"text-text-primary\">{sessionCount}</dd>\n <dt className=\"text-text-muted\">Attached domains</dt>\n <dd className=\"text-text-primary\">{domainCount}</dd>\n <dt className=\"text-text-muted\">Primary hostname</dt>\n <dd className=\"text-text-primary font-mono\">{tunnel.primaryDomain?.hostname ?? '—'}</dd>\n <dt className=\"text-text-muted\">Agent</dt>\n <dd className=\"text-text-primary font-mono\">{tunnel.agentId ?? '—'}</dd>\n <dt className=\"text-text-muted\">Created</dt>\n <dd className=\"text-text-primary\">{new Date(tunnel.createdAt).toLocaleString()}</dd>\n </dl>\n </section>\n\n <TunnelPublicAccessPanel\n tunnelId={tunnel.id}\n tunnelStatus={tunnel.status}\n publicAccessExpiresAt={tunnel.publicAccessExpiresAt}\n publicUrl={publicUrl}\n canUpdate={canUpdate}\n onChanged={onChanged}\n />\n\n {tunnel.lastError && (\n <section className=\"md:col-span-2 rounded-
|
|
1
|
+
{"version":3,"file":"TunnelOverviewTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelOverviewTab.tsx"],"sourcesContent":["import type { GetTunnelQuery } from '@/generated/wspace-operations';\nimport { TunnelPublicAccessPanel } from '@/components/tunnels/TunnelPublicAccessPanel';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ntype TunnelDetails = NonNullable<GetTunnelQuery['tunnel']>;\n\nexport function TunnelOverviewTab({\n tunnel,\n canUpdate,\n onChanged,\n}: {\n tunnel: TunnelDetails;\n canUpdate: boolean;\n onChanged: () => void;\n}) {\n const tr = useTr();\n const sessionCount = tunnel.activeSessions?.length ?? 0;\n const domainCount = tunnel.domains?.length ?? 0;\n const publicUrl = tunnel.primaryDomain?.hostname\n ? `https://${tunnel.primaryDomain.hostname}`\n : null;\n return (\n <div className=\"grid gap-6 md:grid-cols-2 max-w-4xl\">\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tr('vibecontrols.tunnels.overview.configuration', 'Configuration')}\n </h3>\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-muted\">Slug</dt>\n <dd className=\"text-text-primary font-mono\">{tunnel.slug}</dd>\n <dt className=\"text-text-muted\">Provider</dt>\n <dd className=\"text-text-primary\">{tunnel.providerKey}</dd>\n <dt className=\"text-text-muted\">Protocol</dt>\n <dd className=\"text-text-primary\">{tunnel.protocol}</dd>\n <dt className=\"text-text-muted\">TLS mode</dt>\n <dd className=\"text-text-primary\">{tunnel.tlsMode}</dd>\n <dt className=\"text-text-muted\">Local target</dt>\n <dd className=\"text-text-primary font-mono\">\n {tunnel.localHost}:{tunnel.localPort}\n </dd>\n <dt className=\"text-text-muted\">Basic auth</dt>\n <dd className=\"text-text-primary\">\n {tunnel.hasBasicAuth ? (tunnel.basicAuthUser ?? 'configured') : 'off'}\n </dd>\n </dl>\n </section>\n\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tr('vibecontrols.tunnels.overview.activity', 'Activity')}\n </h3>\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-muted\">Active sessions</dt>\n <dd className=\"text-text-primary\">{sessionCount}</dd>\n <dt className=\"text-text-muted\">Attached domains</dt>\n <dd className=\"text-text-primary\">{domainCount}</dd>\n <dt className=\"text-text-muted\">Primary hostname</dt>\n <dd className=\"text-text-primary font-mono\">{tunnel.primaryDomain?.hostname ?? '—'}</dd>\n <dt className=\"text-text-muted\">Agent</dt>\n <dd className=\"text-text-primary font-mono\">{tunnel.agentId ?? '—'}</dd>\n <dt className=\"text-text-muted\">Created</dt>\n <dd className=\"text-text-primary\">{new Date(tunnel.createdAt).toLocaleString()}</dd>\n </dl>\n </section>\n\n <TunnelPublicAccessPanel\n tunnelId={tunnel.id}\n tunnelStatus={tunnel.status}\n publicAccessExpiresAt={tunnel.publicAccessExpiresAt}\n publicUrl={publicUrl}\n canUpdate={canUpdate}\n onChanged={onChanged}\n />\n\n {tunnel.lastError && (\n <section className=\"md:col-span-2 rounded-card border border-status-error-border bg-status-error-bg-subtle p-4 text-sm text-status-error-text\">\n <strong>Last error:</strong> {tunnel.lastError}\n </section>\n )}\n </div>\n );\n}\n"],"mappings":";;;;AAMA,SAAgB,EAAkB,EAChC,WACA,cACA,gBAKC;CACD,IAAM,IAAK,GAAO,EACZ,IAAe,EAAO,gBAAgB,UAAU,GAChD,IAAc,EAAO,SAAS,UAAU,GACxC,IAAY,EAAO,eAAe,WACpC,WAAW,EAAO,cAAc,aAChC;AACJ,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,WAAD;IAAS,WAAU;cAAnB,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,+CAA+C,gBAAgB;KAChE,CAAA,EACL,kBAAC,MAAD;KAAI,WAAU;eAAd;MACE,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAS,CAAA;MACzC,kBAAC,MAAD;OAAI,WAAU;iBAA+B,EAAO;OAAU,CAAA;MAC9D,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAa,CAAA;MAC7C,kBAAC,MAAD;OAAI,WAAU;iBAAqB,EAAO;OAAiB,CAAA;MAC3D,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAa,CAAA;MAC7C,kBAAC,MAAD;OAAI,WAAU;iBAAqB,EAAO;OAAc,CAAA;MACxD,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAa,CAAA;MAC7C,kBAAC,MAAD;OAAI,WAAU;iBAAqB,EAAO;OAAa,CAAA;MACvD,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAiB,CAAA;MACjD,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACG,EAAO;QAAU;QAAE,EAAO;QACxB;;MACL,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAe,CAAA;MAC/C,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAO,eAAgB,EAAO,iBAAiB,eAAgB;OAC7D,CAAA;MACF;OACG;;GAEV,kBAAC,WAAD;IAAS,WAAU;cAAnB,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,0CAA0C,WAAW;KACtD,CAAA,EACL,kBAAC,MAAD;KAAI,WAAU;eAAd;MACE,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAoB,CAAA;MACpD,kBAAC,MAAD;OAAI,WAAU;iBAAqB;OAAkB,CAAA;MACrD,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAqB,CAAA;MACrD,kBAAC,MAAD;OAAI,WAAU;iBAAqB;OAAiB,CAAA;MACpD,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAqB,CAAA;MACrD,kBAAC,MAAD;OAAI,WAAU;iBAA+B,EAAO,eAAe,YAAY;OAAS,CAAA;MACxF,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAU,CAAA;MAC1C,kBAAC,MAAD;OAAI,WAAU;iBAA+B,EAAO,WAAW;OAAS,CAAA;MACxE,kBAAC,MAAD;OAAI,WAAU;iBAAkB;OAAY,CAAA;MAC5C,kBAAC,MAAD;OAAI,WAAU;iBAAqB,IAAI,KAAK,EAAO,UAAU,CAAC,gBAAgB;OAAM,CAAA;MACjF;OACG;;GAEV,kBAAC,GAAD;IACE,UAAU,EAAO;IACjB,cAAc,EAAO;IACrB,uBAAuB,EAAO;IACnB;IACA;IACA;IACX,CAAA;GAED,EAAO,aACN,kBAAC,WAAD;IAAS,WAAU;cAAnB;KACE,kBAAC,UAAD,EAAA,UAAQ,eAAoB,CAAA;;KAAE,EAAO;KAC7B;;GAER"}
|
|
@@ -22,79 +22,82 @@ function l({ tunnelId: l, canExecute: u }) {
|
|
|
22
22
|
title: d("vibecontrols.tunnels.sessions.emptySessionsTitle", "No sessions"),
|
|
23
23
|
description: d("vibecontrols.tunnels.sessions.emptySessionsDescription", "Sessions appear here once a tunnel is started.")
|
|
24
24
|
}) : /* @__PURE__ */ s("div", {
|
|
25
|
-
className: "rounded-
|
|
25
|
+
className: "rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 max-w-4xl overflow-x-auto",
|
|
26
26
|
children: /* @__PURE__ */ c("table", {
|
|
27
27
|
className: "w-full text-sm",
|
|
28
28
|
children: [/* @__PURE__ */ s("thead", {
|
|
29
|
-
className: "border-b border-border-subtle bg-bg-sunken text-text-
|
|
29
|
+
className: "border-b border-border-subtle bg-bg-sunken text-text-muted",
|
|
30
30
|
children: /* @__PURE__ */ c("tr", { children: [
|
|
31
31
|
/* @__PURE__ */ s("th", {
|
|
32
|
-
className: "px-4 py-
|
|
32
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide",
|
|
33
33
|
children: "Fingerprint"
|
|
34
34
|
}),
|
|
35
35
|
/* @__PURE__ */ s("th", {
|
|
36
|
-
className: "px-4 py-
|
|
36
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide",
|
|
37
37
|
children: "Status"
|
|
38
38
|
}),
|
|
39
39
|
/* @__PURE__ */ s("th", {
|
|
40
|
-
className: "px-4 py-
|
|
40
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide",
|
|
41
41
|
children: "Issued"
|
|
42
42
|
}),
|
|
43
43
|
/* @__PURE__ */ s("th", {
|
|
44
|
-
className: "px-4 py-
|
|
44
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide",
|
|
45
45
|
children: "Expires"
|
|
46
46
|
}),
|
|
47
47
|
/* @__PURE__ */ s("th", {
|
|
48
|
-
className: "px-4 py-
|
|
48
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide",
|
|
49
49
|
children: "Bytes"
|
|
50
50
|
}),
|
|
51
51
|
/* @__PURE__ */ s("th", {
|
|
52
|
-
className: "px-4 py-
|
|
52
|
+
className: "px-4 py-2.5 text-right text-xs font-medium uppercase tracking-wide",
|
|
53
53
|
children: "Actions"
|
|
54
54
|
})
|
|
55
55
|
] })
|
|
56
|
-
}), /* @__PURE__ */ s("tbody", {
|
|
57
|
-
className: "
|
|
58
|
-
children:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
56
|
+
}), /* @__PURE__ */ s("tbody", {
|
|
57
|
+
className: "divide-y divide-border-subtle",
|
|
58
|
+
children: _.map((e) => /* @__PURE__ */ c("tr", {
|
|
59
|
+
className: "hover:bg-bg-sunken transition-colors",
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ s("td", {
|
|
62
|
+
className: "px-4 py-3 font-mono text-xs text-text-primary",
|
|
63
|
+
children: e.tokenFingerprint
|
|
64
|
+
}),
|
|
65
|
+
/* @__PURE__ */ s("td", {
|
|
66
|
+
className: "px-4 py-3 text-text-secondary",
|
|
67
|
+
children: e.status
|
|
68
|
+
}),
|
|
69
|
+
/* @__PURE__ */ s("td", {
|
|
70
|
+
className: "px-4 py-3 text-text-muted tabular-nums",
|
|
71
|
+
children: new Date(e.issuedAt).toLocaleString()
|
|
72
|
+
}),
|
|
73
|
+
/* @__PURE__ */ s("td", {
|
|
74
|
+
className: "px-4 py-3 text-text-muted tabular-nums",
|
|
75
|
+
children: new Date(e.expiresAt).toLocaleString()
|
|
76
|
+
}),
|
|
77
|
+
/* @__PURE__ */ c("td", {
|
|
78
|
+
className: "px-4 py-3 text-text-muted tabular-nums",
|
|
79
|
+
children: [
|
|
80
|
+
"↓ ",
|
|
81
|
+
e.bytesIn,
|
|
82
|
+
" / ↑ ",
|
|
83
|
+
e.bytesOut
|
|
84
|
+
]
|
|
85
|
+
}),
|
|
86
|
+
/* @__PURE__ */ s("td", {
|
|
87
|
+
className: "px-4 py-3 text-right",
|
|
88
|
+
children: u && (e.status === a.Issued || e.status === a.Connected) && /* @__PURE__ */ s("button", {
|
|
89
|
+
type: "button",
|
|
90
|
+
onClick: () => void g({ variables: {
|
|
91
|
+
sessionId: e.id,
|
|
92
|
+
reason: "revoked from UI"
|
|
93
|
+
} }),
|
|
94
|
+
className: "rounded-button border border-border-subtle px-3 py-1 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle hover:border-status-error-border transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
95
|
+
children: d("vibecontrols.tunnels.sessions.revoke", "Revoke")
|
|
96
|
+
})
|
|
94
97
|
})
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
+
]
|
|
99
|
+
}, e.id))
|
|
100
|
+
})]
|
|
98
101
|
})
|
|
99
102
|
});
|
|
100
103
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TunnelSessionsTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelSessionsTab.tsx"],"sourcesContent":["import {\n useListTunnelSessionsQuery,\n useRevokeTunnelSessionMutation,\n} from '@/generated/wspace-operations';\nimport { TunnelSessionStatus } from '@/generated/wspace-types';\nimport { LoadingState } from '@/components/shared/LoadingState';\nimport { ErrorState } from '@/components/shared/ErrorState';\nimport { EmptyState } from '@/components/shared/EmptyState';\nimport { useTr } from '../../../shared/hooks/useTr';\n\nexport function TunnelSessionsTab({\n tunnelId,\n canExecute,\n}: {\n tunnelId: string;\n canExecute: boolean;\n}) {\n const tr = useTr();\n const { data, loading, error, refetch } = useListTunnelSessionsQuery({\n variables: { tunnelId, pagination: { limit: 50 } },\n fetchPolicy: 'cache-and-network',\n });\n const [revoke] = useRevokeTunnelSessionMutation({\n onCompleted: () => void refetch(),\n });\n\n const sessions = data?.tunnelSessions?.items ?? [];\n\n if (loading && !data) return <LoadingState message=\"Loading sessions\" />;\n if (error)\n return (\n <ErrorState\n title=\"Failed to load sessions\"\n message={error.message}\n onRetry={() => refetch()}\n />\n );\n if (sessions.length === 0)\n return (\n <EmptyState\n title={tr('vibecontrols.tunnels.sessions.emptySessionsTitle', 'No sessions')}\n description={tr(\n 'vibecontrols.tunnels.sessions.emptySessionsDescription',\n 'Sessions appear here once a tunnel is started.'\n )}\n />\n );\n\n return (\n <div className=\"rounded-
|
|
1
|
+
{"version":3,"file":"TunnelSessionsTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelSessionsTab.tsx"],"sourcesContent":["import {\n useListTunnelSessionsQuery,\n useRevokeTunnelSessionMutation,\n} from '@/generated/wspace-operations';\nimport { TunnelSessionStatus } from '@/generated/wspace-types';\nimport { LoadingState } from '@/components/shared/LoadingState';\nimport { ErrorState } from '@/components/shared/ErrorState';\nimport { EmptyState } from '@/components/shared/EmptyState';\nimport { useTr } from '../../../shared/hooks/useTr';\n\nexport function TunnelSessionsTab({\n tunnelId,\n canExecute,\n}: {\n tunnelId: string;\n canExecute: boolean;\n}) {\n const tr = useTr();\n const { data, loading, error, refetch } = useListTunnelSessionsQuery({\n variables: { tunnelId, pagination: { limit: 50 } },\n fetchPolicy: 'cache-and-network',\n });\n const [revoke] = useRevokeTunnelSessionMutation({\n onCompleted: () => void refetch(),\n });\n\n const sessions = data?.tunnelSessions?.items ?? [];\n\n if (loading && !data) return <LoadingState message=\"Loading sessions\" />;\n if (error)\n return (\n <ErrorState\n title=\"Failed to load sessions\"\n message={error.message}\n onRetry={() => refetch()}\n />\n );\n if (sessions.length === 0)\n return (\n <EmptyState\n title={tr('vibecontrols.tunnels.sessions.emptySessionsTitle', 'No sessions')}\n description={tr(\n 'vibecontrols.tunnels.sessions.emptySessionsDescription',\n 'Sessions appear here once a tunnel is started.'\n )}\n />\n );\n\n return (\n <div className=\"rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 max-w-4xl overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead className=\"border-b border-border-subtle bg-bg-sunken text-text-muted\">\n <tr>\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide\">\n Fingerprint\n </th>\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide\">\n Status\n </th>\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide\">\n Issued\n </th>\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide\">\n Expires\n </th>\n <th className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide\">\n Bytes\n </th>\n <th className=\"px-4 py-2.5 text-right text-xs font-medium uppercase tracking-wide\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border-subtle\">\n {sessions.map((s: any) => (\n <tr key={s.id} className=\"hover:bg-bg-sunken transition-colors\">\n <td className=\"px-4 py-3 font-mono text-xs text-text-primary\">\n {s.tokenFingerprint}\n </td>\n <td className=\"px-4 py-3 text-text-secondary\">{s.status}</td>\n <td className=\"px-4 py-3 text-text-muted tabular-nums\">\n {new Date(s.issuedAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-3 text-text-muted tabular-nums\">\n {new Date(s.expiresAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-3 text-text-muted tabular-nums\">\n ↓ {s.bytesIn} / ↑ {s.bytesOut}\n </td>\n <td className=\"px-4 py-3 text-right\">\n {canExecute &&\n (s.status === TunnelSessionStatus.Issued ||\n s.status === TunnelSessionStatus.Connected) && (\n <button\n type=\"button\"\n onClick={() =>\n void revoke({\n variables: { sessionId: s.id, reason: 'revoked from UI' },\n })\n }\n className=\"rounded-button border border-border-subtle px-3 py-1 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle hover:border-status-error-border transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n {tr('vibecontrols.tunnels.sessions.revoke', 'Revoke')}\n </button>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAUA,SAAgB,EAAkB,EAChC,aACA,iBAIC;CACD,IAAM,IAAK,GAAO,EACZ,EAAE,SAAM,YAAS,UAAO,eAAY,EAA2B;EACnE,WAAW;GAAE;GAAU,YAAY,EAAE,OAAO,IAAI;GAAE;EAClD,aAAa;EACd,CAAC,EACI,CAAC,KAAU,EAA+B,EAC9C,mBAAmB,KAAK,GAAS,EAClC,CAAC,EAEI,IAAW,GAAM,gBAAgB,SAAS,EAAE;AAsBlD,QApBI,KAAW,CAAC,IAAa,kBAAC,GAAD,EAAc,SAAQ,oBAAqB,CAAA,GACpE,IAEA,kBAAC,GAAD;EACE,OAAM;EACN,SAAS,EAAM;EACf,eAAe,GAAS;EACxB,CAAA,GAEF,EAAS,WAAW,IAEpB,kBAAC,GAAD;EACE,OAAO,EAAG,oDAAoD,cAAc;EAC5E,aAAa,EACX,0DACA,iDACD;EACD,CAAA,GAIJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,SAAD;GAAO,WAAU;aAAjB,CACE,kBAAC,SAAD;IAAO,WAAU;cACf,kBAAC,MAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBAAoE;MAE7E,CAAA;KACL,kBAAC,MAAD;MAAI,WAAU;gBAAoE;MAE7E,CAAA;KACL,kBAAC,MAAD;MAAI,WAAU;gBAAoE;MAE7E,CAAA;KACL,kBAAC,MAAD;MAAI,WAAU;gBAAoE;MAE7E,CAAA;KACL,kBAAC,MAAD;MAAI,WAAU;gBAAoE;MAE7E,CAAA;KACL,kBAAC,MAAD;MAAI,WAAU;gBAAqE;MAE9E,CAAA;KACF,EAAA,CAAA;IACC,CAAA,EACR,kBAAC,SAAD;IAAO,WAAU;cACd,EAAS,KAAK,MACb,kBAAC,MAAD;KAAe,WAAU;eAAzB;MACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE;OACA,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBAAiC,EAAE;OAAY,CAAA;MAC7D,kBAAC,MAAD;OAAI,WAAU;iBACX,IAAI,KAAK,EAAE,SAAS,CAAC,gBAAgB;OACnC,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBACX,IAAI,KAAK,EAAE,UAAU,CAAC,gBAAgB;OACpC,CAAA;MACL,kBAAC,MAAD;OAAI,WAAU;iBAAd;QAAuD;QAClD,EAAE;QAAQ;QAAM,EAAE;QAClB;;MACL,kBAAC,MAAD;OAAI,WAAU;iBACX,MACE,EAAE,WAAW,EAAoB,UAChC,EAAE,WAAW,EAAoB,cACjC,kBAAC,UAAD;QACE,MAAK;QACL,eACE,KAAK,EAAO,EACV,WAAW;SAAE,WAAW,EAAE;SAAI,QAAQ;SAAmB,EAC1D,CAAC;QAEJ,WAAU;kBAET,EAAG,wCAAwC,SAAS;QAC9C,CAAA;OAEV,CAAA;MACF;OA/BI,EAAE,GA+BN,CACL;IACI,CAAA,CACF;;EACJ,CAAA"}
|
|
@@ -10,46 +10,46 @@ function s({ tunnel: s, canUpdate: c, canDelete: l, onDeleted: u }) {
|
|
|
10
10
|
className: "max-w-3xl space-y-6",
|
|
11
11
|
children: [
|
|
12
12
|
c && /* @__PURE__ */ o("section", {
|
|
13
|
-
className: "rounded-
|
|
13
|
+
className: "rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 p-5",
|
|
14
14
|
children: [
|
|
15
15
|
/* @__PURE__ */ a("h3", {
|
|
16
|
-
className: "text-sm font-semibold text-text-primary mb-2",
|
|
16
|
+
className: "text-sm font-semibold text-text-primary tracking-tight mb-2",
|
|
17
17
|
children: d("vibecontrols.tunnels.settings.rotateCredentials", "Rotate credentials")
|
|
18
18
|
}),
|
|
19
19
|
/* @__PURE__ */ a("p", {
|
|
20
|
-
className: "text-xs text-text-secondary mb-
|
|
20
|
+
className: "text-xs text-text-secondary mb-4",
|
|
21
21
|
children: "Rotates basic-auth passwords and revokes every active session for this tunnel. The tunnel will restart automatically if currently active."
|
|
22
22
|
}),
|
|
23
23
|
/* @__PURE__ */ a("button", {
|
|
24
24
|
type: "button",
|
|
25
25
|
disabled: h,
|
|
26
26
|
onClick: () => void m({ variables: { id: s.id } }),
|
|
27
|
-
className: "rounded-
|
|
27
|
+
className: "rounded-button border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken hover:border-border-strong transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
28
28
|
children: h ? d("vibecontrols.tunnels.settings.rotating", "Rotating...") : d("vibecontrols.tunnels.settings.rotateNow", "Rotate now")
|
|
29
29
|
})
|
|
30
30
|
]
|
|
31
31
|
}),
|
|
32
32
|
l && /* @__PURE__ */ o("section", {
|
|
33
|
-
className: "rounded-
|
|
33
|
+
className: "rounded-card border border-status-error-border bg-status-error-bg-subtle shadow-elevation-1 p-5",
|
|
34
34
|
children: [
|
|
35
35
|
/* @__PURE__ */ a("h3", {
|
|
36
|
-
className: "text-sm font-semibold text-status-error-
|
|
36
|
+
className: "text-sm font-semibold text-status-error-text tracking-tight mb-2",
|
|
37
37
|
children: d("vibecontrols.tunnels.settings.deleteTunnel", "Delete tunnel")
|
|
38
38
|
}),
|
|
39
39
|
/* @__PURE__ */ a("p", {
|
|
40
|
-
className: "text-xs text-text-secondary mb-
|
|
40
|
+
className: "text-xs text-text-secondary mb-4",
|
|
41
41
|
children: "Permanently removes the tunnel, its sessions, and any managed subdomain reservations. Custom domains remain in the workspace and can be reattached."
|
|
42
42
|
}),
|
|
43
43
|
/* @__PURE__ */ a("button", {
|
|
44
44
|
type: "button",
|
|
45
45
|
onClick: () => p(!0),
|
|
46
|
-
className: "rounded-
|
|
46
|
+
className: "rounded-button bg-action-danger-bg px-4 py-2 text-sm font-medium text-action-danger-text hover:bg-action-danger-bgHover transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
47
47
|
children: d("vibecontrols.tunnels.settings.deleteTunnelBtn", "Delete tunnel")
|
|
48
48
|
})
|
|
49
49
|
]
|
|
50
50
|
}),
|
|
51
51
|
!c && !l && /* @__PURE__ */ a("section", {
|
|
52
|
-
className: "rounded-
|
|
52
|
+
className: "rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 p-5 text-sm text-text-secondary",
|
|
53
53
|
children: d("vibecontrols.tunnels.settings.noPermission", "No tunnel settings actions available.")
|
|
54
54
|
}),
|
|
55
55
|
/* @__PURE__ */ a(r, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TunnelSettingsTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelSettingsTab.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { GetTunnelQuery } from '@/generated/wspace-operations';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport {\n useRotateTunnelCredentialsMutation,\n useDeleteTunnelMutation,\n} from '@/generated/wspace-operations';\nimport { ConfirmDialog } from '@/components/shared/ConfirmDialog';\n\ntype TunnelDetails = NonNullable<GetTunnelQuery['tunnel']>;\n\nexport function TunnelSettingsTab({\n tunnel,\n canUpdate,\n canDelete,\n onDeleted,\n}: {\n tunnel: TunnelDetails;\n canUpdate: boolean;\n canDelete: boolean;\n onDeleted: () => void;\n}) {\n const tr = useTr();\n const [confirmDelete, setConfirmDelete] = useState(false);\n\n const [rotateCredentials, { loading: rotating }] = useRotateTunnelCredentialsMutation();\n const [deleteTunnel, { loading: deleting }] = useDeleteTunnelMutation({\n onCompleted: onDeleted,\n });\n\n return (\n <div className=\"max-w-3xl space-y-6\">\n {canUpdate && (\n <section className=\"rounded-
|
|
1
|
+
{"version":3,"file":"TunnelSettingsTab.js","names":[],"sources":["../../../../src/pages/tunnels/tabs/TunnelSettingsTab.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { GetTunnelQuery } from '@/generated/wspace-operations';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport {\n useRotateTunnelCredentialsMutation,\n useDeleteTunnelMutation,\n} from '@/generated/wspace-operations';\nimport { ConfirmDialog } from '@/components/shared/ConfirmDialog';\n\ntype TunnelDetails = NonNullable<GetTunnelQuery['tunnel']>;\n\nexport function TunnelSettingsTab({\n tunnel,\n canUpdate,\n canDelete,\n onDeleted,\n}: {\n tunnel: TunnelDetails;\n canUpdate: boolean;\n canDelete: boolean;\n onDeleted: () => void;\n}) {\n const tr = useTr();\n const [confirmDelete, setConfirmDelete] = useState(false);\n\n const [rotateCredentials, { loading: rotating }] = useRotateTunnelCredentialsMutation();\n const [deleteTunnel, { loading: deleting }] = useDeleteTunnelMutation({\n onCompleted: onDeleted,\n });\n\n return (\n <div className=\"max-w-3xl space-y-6\">\n {canUpdate && (\n <section className=\"rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 p-5\">\n <h3 className=\"text-sm font-semibold text-text-primary tracking-tight mb-2\">\n {tr('vibecontrols.tunnels.settings.rotateCredentials', 'Rotate credentials')}\n </h3>\n <p className=\"text-xs text-text-secondary mb-4\">\n Rotates basic-auth passwords and revokes every active session for this tunnel. The\n tunnel will restart automatically if currently active.\n </p>\n <button\n type=\"button\"\n disabled={rotating}\n onClick={() => void rotateCredentials({ variables: { id: tunnel.id } })}\n className=\"rounded-button border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken hover:border-border-strong transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n {rotating\n ? tr('vibecontrols.tunnels.settings.rotating', 'Rotating...')\n : tr('vibecontrols.tunnels.settings.rotateNow', 'Rotate now')}\n </button>\n </section>\n )}\n\n {canDelete && (\n <section className=\"rounded-card border border-status-error-border bg-status-error-bg-subtle shadow-elevation-1 p-5\">\n <h3 className=\"text-sm font-semibold text-status-error-text tracking-tight mb-2\">\n {tr('vibecontrols.tunnels.settings.deleteTunnel', 'Delete tunnel')}\n </h3>\n <p className=\"text-xs text-text-secondary mb-4\">\n Permanently removes the tunnel, its sessions, and any managed subdomain reservations.\n Custom domains remain in the workspace and can be reattached.\n </p>\n <button\n type=\"button\"\n onClick={() => setConfirmDelete(true)}\n className=\"rounded-button bg-action-danger-bg px-4 py-2 text-sm font-medium text-action-danger-text hover:bg-action-danger-bgHover transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n {tr('vibecontrols.tunnels.settings.deleteTunnelBtn', 'Delete tunnel')}\n </button>\n </section>\n )}\n\n {!canUpdate && !canDelete && (\n <section className=\"rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 p-5 text-sm text-text-secondary\">\n {tr(\n 'vibecontrols.tunnels.settings.noPermission',\n 'No tunnel settings actions available.'\n )}\n </section>\n )}\n\n <ConfirmDialog\n isOpen={confirmDelete}\n onClose={() => setConfirmDelete(false)}\n onConfirm={() => void deleteTunnel({ variables: { id: tunnel.id } })}\n title=\"Delete tunnel\"\n message={`Delete \"${tunnel.name}\"? This cannot be undone.`}\n confirmLabel=\"Delete\"\n variant=\"danger\"\n isLoading={deleting}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;AAWA,SAAgB,EAAkB,EAChC,WACA,cACA,cACA,gBAMC;CACD,IAAM,IAAK,GAAO,EACZ,CAAC,GAAe,KAAoB,EAAS,GAAM,EAEnD,CAAC,GAAmB,EAAE,SAAS,OAAc,GAAoC,EACjF,CAAC,GAAc,EAAE,SAAS,OAAc,EAAwB,EACpE,aAAa,GACd,CAAC;AAEF,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACG,KACC,kBAAC,WAAD;IAAS,WAAU;cAAnB;KACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,mDAAmD,qBAAqB;MACzE,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBAAmC;MAG5C,CAAA;KACJ,kBAAC,UAAD;MACE,MAAK;MACL,UAAU;MACV,eAAe,KAAK,EAAkB,EAAE,WAAW,EAAE,IAAI,EAAO,IAAI,EAAE,CAAC;MACvE,WAAU;gBAET,IACG,EAAG,0CAA0C,cAAc,GAC3D,EAAG,2CAA2C,aAAa;MACxD,CAAA;KACD;;GAGX,KACC,kBAAC,WAAD;IAAS,WAAU;cAAnB;KACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,8CAA8C,gBAAgB;MAC/D,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBAAmC;MAG5C,CAAA;KACJ,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAiB,GAAK;MACrC,WAAU;gBAET,EAAG,iDAAiD,gBAAgB;MAC9D,CAAA;KACD;;GAGX,CAAC,KAAa,CAAC,KACd,kBAAC,WAAD;IAAS,WAAU;cAChB,EACC,8CACA,wCACD;IACO,CAAA;GAGZ,kBAAC,GAAD;IACE,QAAQ;IACR,eAAe,EAAiB,GAAM;IACtC,iBAAiB,KAAK,EAAa,EAAE,WAAW,EAAE,IAAI,EAAO,IAAI,EAAE,CAAC;IACpE,OAAM;IACN,SAAS,WAAW,EAAO,KAAK;IAChC,cAAa;IACb,SAAQ;IACR,WAAW;IACX,CAAA;GACE"}
|