@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
|
@@ -11,15 +11,15 @@ var c = {
|
|
|
11
11
|
DENIED: "warning",
|
|
12
12
|
ERROR: "error"
|
|
13
13
|
}, l = {
|
|
14
|
-
CREATE: "bg-status-success-bg text-status-success-text",
|
|
15
|
-
UPDATE: "bg-status-info-bg text-status-info-text",
|
|
16
|
-
DELETE: "bg-status-error-bg text-status-error-text",
|
|
17
|
-
EXECUTE: "bg-
|
|
18
|
-
EXPORT: "bg-status-warning-bg text-status-warning-text",
|
|
19
|
-
SHARE: "bg-status-success-bg text-status-success-text",
|
|
20
|
-
REVOKE: "bg-status-warning-bg text-status-warning-text",
|
|
14
|
+
CREATE: "bg-status-success-bg-subtle text-status-success-text",
|
|
15
|
+
UPDATE: "bg-status-info-bg-subtle text-status-info-text",
|
|
16
|
+
DELETE: "bg-status-error-bg-subtle text-status-error-text",
|
|
17
|
+
EXECUTE: "bg-[var(--color-accent-soft)] text-text-primary",
|
|
18
|
+
EXPORT: "bg-status-warning-bg-subtle text-status-warning-text",
|
|
19
|
+
SHARE: "bg-status-success-bg-subtle text-status-success-text",
|
|
20
|
+
REVOKE: "bg-status-warning-bg-subtle text-status-warning-text",
|
|
21
21
|
ARCHIVE: "bg-bg-muted text-text-secondary",
|
|
22
|
-
RESTORE: "bg-status-info-bg text-status-info-text"
|
|
22
|
+
RESTORE: "bg-status-info-bg-subtle text-status-info-text"
|
|
23
23
|
};
|
|
24
24
|
function u(e) {
|
|
25
25
|
return new Date(e).toLocaleString("en-US", {
|
|
@@ -44,7 +44,7 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
44
44
|
children: f.map((n) => {
|
|
45
45
|
let f = x.has(n.id);
|
|
46
46
|
return /* @__PURE__ */ s("article", {
|
|
47
|
-
className: `rounded-lg border border-border-
|
|
47
|
+
className: `rounded-lg border border-border-default p-4 transition-colors ${b === n.id ? "bg-bg-sunken" : "bg-bg-surface"}`,
|
|
48
48
|
children: [
|
|
49
49
|
/* @__PURE__ */ s("div", {
|
|
50
50
|
className: "flex items-start justify-between gap-3",
|
|
@@ -73,7 +73,7 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
73
73
|
]
|
|
74
74
|
})]
|
|
75
75
|
}), /* @__PURE__ */ s("span", {
|
|
76
|
-
className: `inline-flex shrink-0 items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${l[n.action] || "bg-bg-
|
|
76
|
+
className: `inline-flex shrink-0 items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${l[n.action] || "bg-bg-surface text-text-secondary"}`,
|
|
77
77
|
children: [n.command ? /* @__PURE__ */ o(i, { size: 12 }) : null, n.action]
|
|
78
78
|
})]
|
|
79
79
|
}),
|
|
@@ -93,12 +93,12 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
93
93
|
children: [/* @__PURE__ */ s("button", {
|
|
94
94
|
type: "button",
|
|
95
95
|
onClick: () => v(n.id),
|
|
96
|
-
className: "inline-flex items-center gap-1 rounded-md border border-border-
|
|
96
|
+
className: "inline-flex items-center gap-1 rounded-md border border-border-default px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-surface",
|
|
97
97
|
children: ["View details", /* @__PURE__ */ o(r, { size: 14 })]
|
|
98
98
|
}), /* @__PURE__ */ o("button", {
|
|
99
99
|
type: "button",
|
|
100
100
|
onClick: () => y(n.id),
|
|
101
|
-
className: "rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text",
|
|
101
|
+
className: "rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text",
|
|
102
102
|
title: O("audit.deleteAuditLog", "Delete audit log"),
|
|
103
103
|
children: /* @__PURE__ */ o(a, { size: 14 })
|
|
104
104
|
})]
|
|
@@ -108,14 +108,14 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
108
108
|
})
|
|
109
109
|
}),
|
|
110
110
|
/* @__PURE__ */ o("div", {
|
|
111
|
-
className: "hidden overflow-x-auto rounded-
|
|
111
|
+
className: "hidden overflow-x-auto rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 md:block",
|
|
112
112
|
children: /* @__PURE__ */ s("table", {
|
|
113
113
|
className: "w-full min-w-[860px] text-sm",
|
|
114
114
|
children: [/* @__PURE__ */ o("thead", { children: /* @__PURE__ */ s("tr", {
|
|
115
|
-
className: "border-b border-border-
|
|
115
|
+
className: "border-b border-border-subtle bg-bg-sunken",
|
|
116
116
|
children: [
|
|
117
117
|
/* @__PURE__ */ o("th", {
|
|
118
|
-
className: "px-4 py-3 text-left font-medium text-text-
|
|
118
|
+
className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
119
119
|
children: /* @__PURE__ */ o(t, {
|
|
120
120
|
checked: S,
|
|
121
121
|
indeterminate: C,
|
|
@@ -124,38 +124,38 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
124
124
|
})
|
|
125
125
|
}),
|
|
126
126
|
/* @__PURE__ */ o("th", {
|
|
127
|
-
className: "px-4 py-3 text-left font-medium text-text-
|
|
127
|
+
className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
128
128
|
children: O("audit.time", "Time")
|
|
129
129
|
}),
|
|
130
130
|
/* @__PURE__ */ o("th", {
|
|
131
|
-
className: "px-4 py-3 text-left font-medium text-text-
|
|
131
|
+
className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
132
132
|
children: O("audit.action", "Action")
|
|
133
133
|
}),
|
|
134
134
|
/* @__PURE__ */ o("th", {
|
|
135
|
-
className: "px-4 py-3 text-left font-medium text-text-
|
|
135
|
+
className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
136
136
|
children: O("audit.resource", "Resource")
|
|
137
137
|
}),
|
|
138
138
|
/* @__PURE__ */ o("th", {
|
|
139
|
-
className: "px-4 py-3 text-left font-medium text-text-
|
|
139
|
+
className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
140
140
|
children: O("audit.name", "Name")
|
|
141
141
|
}),
|
|
142
142
|
/* @__PURE__ */ o("th", {
|
|
143
|
-
className: "px-4 py-3 text-left font-medium text-text-
|
|
143
|
+
className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
144
144
|
children: O("audit.actor", "Actor")
|
|
145
145
|
}),
|
|
146
146
|
/* @__PURE__ */ o("th", {
|
|
147
|
-
className: "px-4 py-3 text-left font-medium text-text-
|
|
147
|
+
className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
148
148
|
children: O("audit.status", "Status")
|
|
149
149
|
}),
|
|
150
150
|
/* @__PURE__ */ o("th", {
|
|
151
|
-
className: "px-4 py-3 text-right font-medium text-text-
|
|
151
|
+
className: "px-4 py-3 text-right text-xs font-medium uppercase tracking-wide text-text-muted",
|
|
152
152
|
children: O("audit.actions", "Actions")
|
|
153
153
|
})
|
|
154
154
|
]
|
|
155
155
|
}) }), /* @__PURE__ */ o("tbody", { children: f.map((n) => {
|
|
156
156
|
let f = x.has(n.id);
|
|
157
157
|
return /* @__PURE__ */ s("tr", {
|
|
158
|
-
className: `border-b border-border-
|
|
158
|
+
className: `border-b border-border-subtle transition-colors hover:bg-bg-sunken ${b === n.id ? "bg-bg-sunken" : ""}`,
|
|
159
159
|
children: [
|
|
160
160
|
/* @__PURE__ */ o("td", {
|
|
161
161
|
className: "px-4 py-3 align-top",
|
|
@@ -172,7 +172,7 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
172
172
|
/* @__PURE__ */ o("td", {
|
|
173
173
|
className: "px-4 py-3",
|
|
174
174
|
children: /* @__PURE__ */ s("span", {
|
|
175
|
-
className: `inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${l[n.action] || "bg-bg-
|
|
175
|
+
className: `inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${l[n.action] || "bg-bg-surface text-text-secondary"}`,
|
|
176
176
|
children: [n.command ? /* @__PURE__ */ o(i, { size: 12 }) : null, n.action]
|
|
177
177
|
})
|
|
178
178
|
}),
|
|
@@ -205,13 +205,13 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
205
205
|
children: [/* @__PURE__ */ o("button", {
|
|
206
206
|
type: "button",
|
|
207
207
|
onClick: () => v(n.id),
|
|
208
|
-
className: "rounded p-1 text-text-secondary transition-colors hover:bg-bg-
|
|
208
|
+
className: "rounded p-1 text-text-secondary transition-colors hover:bg-bg-surface hover:text-text-primary",
|
|
209
209
|
title: O("audit.viewAuditLog", "View details"),
|
|
210
210
|
children: /* @__PURE__ */ o(r, { size: 14 })
|
|
211
211
|
}), /* @__PURE__ */ o("button", {
|
|
212
212
|
type: "button",
|
|
213
213
|
onClick: () => y(n.id),
|
|
214
|
-
className: "rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text",
|
|
214
|
+
className: "rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text",
|
|
215
215
|
title: O("audit.deleteAuditLog", "Delete audit log"),
|
|
216
216
|
children: /* @__PURE__ */ o(a, { size: 14 })
|
|
217
217
|
})]
|
|
@@ -241,7 +241,7 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
241
241
|
type: "button",
|
|
242
242
|
disabled: h === 0,
|
|
243
243
|
onClick: () => _(h - 1),
|
|
244
|
-
className: "rounded border border-border-
|
|
244
|
+
className: "rounded border border-border-default px-3 py-1 transition-colors hover:bg-bg-surface disabled:opacity-50",
|
|
245
245
|
children: O("audit.previous", "Previous")
|
|
246
246
|
}),
|
|
247
247
|
/* @__PURE__ */ s("span", { children: [
|
|
@@ -257,7 +257,7 @@ function f({ items: f, total: p, hasMore: m, page: h, pageSize: g, onPageChange:
|
|
|
257
257
|
type: "button",
|
|
258
258
|
disabled: !m,
|
|
259
259
|
onClick: () => _(h + 1),
|
|
260
|
-
className: "rounded border border-border-
|
|
260
|
+
className: "rounded border border-border-default px-3 py-1 transition-colors hover:bg-bg-surface disabled:opacity-50",
|
|
261
261
|
children: O("audit.next", "Next")
|
|
262
262
|
})
|
|
263
263
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditLogTable.js","names":[],"sources":["../../../src/components/audit/AuditLogTable.tsx"],"sourcesContent":["import { ChevronRight, Terminal, Trash2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { StatusBadge } from '@/components/shared';\nimport { SelectionCheckbox } from '@/components/shared/SelectionCheckbox';\nimport type { VibeAuditLogFieldsFragment } from '@/generated/wspace-operations';\n\ninterface AuditLogTableProps {\n items: VibeAuditLogFieldsFragment[];\n total: number;\n hasMore: boolean;\n page: number;\n pageSize: number;\n onPageChange: (page: number) => void;\n onSelectLog: (id: string) => void;\n onDeleteLog: (id: string) => void;\n selectedLogId: string | null;\n selectedLogIds: Set<string>;\n allVisibleSelected: boolean;\n partiallySelected: boolean;\n onToggleLogSelection: (id: string, checked: boolean) => void;\n onToggleAllVisible: (checked: boolean) => void;\n}\n\nconst statusVariantMap: Record<string, 'success' | 'error' | 'warning' | 'info'> = {\n SUCCESS: 'success',\n FAILURE: 'error',\n DENIED: 'warning',\n ERROR: 'error',\n};\n\nconst actionColors: Record<string, string> = {\n CREATE: 'bg-status-success-bg text-status-success-text',\n UPDATE: 'bg-status-info-bg text-status-info-text',\n DELETE: 'bg-status-error-bg text-status-error-text',\n EXECUTE: 'bg-action-primary-bg/15 text-action-primary-text',\n EXPORT: 'bg-status-warning-bg text-status-warning-text',\n SHARE: 'bg-status-success-bg text-status-success-text',\n REVOKE: 'bg-status-warning-bg text-status-warning-text',\n ARCHIVE: 'bg-bg-muted text-text-secondary',\n RESTORE: 'bg-status-info-bg text-status-info-text',\n};\n\nfunction formatDate(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleString('en-US', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction formatResourceType(type: string): string {\n return type\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (character) => character.toUpperCase());\n}\n\nexport function AuditLogTable({\n items,\n total,\n hasMore,\n page,\n pageSize,\n onPageChange,\n onSelectLog,\n onDeleteLog,\n selectedLogId,\n selectedLogIds,\n allVisibleSelected,\n partiallySelected,\n onToggleLogSelection,\n onToggleAllVisible,\n}: AuditLogTableProps) {\n const { t } = useI18n();\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n\n const tr = (key: string, fallback: string) => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n return (\n <div>\n <div className=\"space-y-3 md:hidden\">\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <article\n key={item.id}\n className={`rounded-lg border border-border-primary p-4 transition-colors ${\n selectedLogId === item.id ? 'bg-bg-secondary/50' : 'bg-bg-surface'\n }`}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n className=\"mt-1\"\n />\n <div className=\"min-w-0\">\n <p className=\"text-xs text-text-secondary\">{formatDate(item.createdAt)}</p>\n <p className=\"mt-1 truncate font-medium text-text-primary\">\n {item.resourceName || item.description || '-'}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </p>\n </div>\n </div>\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-secondary text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </div>\n <div className=\"mt-3 flex items-center justify-between gap-3\">\n <p className=\"min-w-0 truncate text-xs capitalize text-text-secondary\">\n {(item.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n {item.resourceName ? ` · ${item.resourceName}` : ''}\n </p>\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </div>\n <div className=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-primary px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-secondary\"\n >\n View details\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </article>\n );\n })}\n </div>\n\n <div className=\"hidden overflow-x-auto rounded-lg border border-border-primary md:block\">\n <table className=\"w-full min-w-[860px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-primary bg-bg-secondary/50\">\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={onToggleAllVisible}\n ariaLabel=\"Select all visible audit logs\"\n />\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.time', 'Time')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.action', 'Action')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.resource', 'Resource')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.name', 'Name')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.actor', 'Actor')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.status', 'Status')}\n </th>\n <th className=\"px-4 py-3 text-right font-medium text-text-secondary\">\n {tr('audit.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <tr\n key={item.id}\n className={`border-b border-border-primary/50 transition-colors hover:bg-bg-secondary/30 ${\n selectedLogId === item.id ? 'bg-bg-secondary/50' : ''\n }`}\n >\n <td className=\"px-4 py-3 align-top\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n />\n </td>\n <td className=\"whitespace-nowrap px-4 py-3 text-xs text-text-secondary\">\n {formatDate(item.createdAt)}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-secondary text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </td>\n <td className=\"px-4 py-3 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </td>\n <td\n className=\"max-w-[220px] truncate px-4 py-3\"\n title={item.resourceName || item.description || ''}\n >\n {item.resourceName || item.description || '-'}\n </td>\n <td\n className=\"max-w-[140px] truncate px-4 py-3 text-xs capitalize text-text-secondary\"\n title={item.actorId}\n >\n {(item.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n </td>\n <td className=\"px-4 py-3\">\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </td>\n <td className=\"px-4 py-3 text-right\">\n <div className=\"flex items-center justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-bg-secondary hover:text-text-primary\"\n title={tr('audit.viewAuditLog', 'View details')}\n >\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n <div className=\"mt-4 flex flex-col gap-3 text-sm text-text-secondary sm:flex-row sm:items-center sm:justify-between\">\n <span>\n {tr('audit.showing', 'Showing')} {page * pageSize + 1}-\n {Math.min((page + 1) * pageSize, total)} {tr('audit.of', 'of')} {total}\n </span>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n disabled={page === 0}\n onClick={() => onPageChange(page - 1)}\n className=\"rounded border border-border-primary px-3 py-1 transition-colors hover:bg-bg-secondary disabled:opacity-50\"\n >\n {tr('audit.previous', 'Previous')}\n </button>\n <span>\n {tr('audit.page', 'Page')} {page + 1} {tr('audit.of', 'of')} {totalPages}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => onPageChange(page + 1)}\n className=\"rounded border border-border-primary px-3 py-1 transition-colors hover:bg-bg-secondary disabled:opacity-50\"\n >\n {tr('audit.next', 'Next')}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuditLogTable.js","names":[],"sources":["../../../src/components/audit/AuditLogTable.tsx"],"sourcesContent":["import { ChevronRight, Terminal, Trash2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { StatusBadge } from '@/components/shared';\nimport { SelectionCheckbox } from '@/components/shared/SelectionCheckbox';\nimport type { VibeAuditLogFieldsFragment } from '@/generated/wspace-operations';\n\ninterface AuditLogTableProps {\n items: VibeAuditLogFieldsFragment[];\n total: number;\n hasMore: boolean;\n page: number;\n pageSize: number;\n onPageChange: (page: number) => void;\n onSelectLog: (id: string) => void;\n onDeleteLog: (id: string) => void;\n selectedLogId: string | null;\n selectedLogIds: Set<string>;\n allVisibleSelected: boolean;\n partiallySelected: boolean;\n onToggleLogSelection: (id: string, checked: boolean) => void;\n onToggleAllVisible: (checked: boolean) => void;\n}\n\nconst statusVariantMap: Record<string, 'success' | 'error' | 'warning' | 'info'> = {\n SUCCESS: 'success',\n FAILURE: 'error',\n DENIED: 'warning',\n ERROR: 'error',\n};\n\nconst actionColors: Record<string, string> = {\n CREATE: 'bg-status-success-bg-subtle text-status-success-text',\n UPDATE: 'bg-status-info-bg-subtle text-status-info-text',\n DELETE: 'bg-status-error-bg-subtle text-status-error-text',\n EXECUTE: 'bg-[var(--color-accent-soft)] text-text-primary',\n EXPORT: 'bg-status-warning-bg-subtle text-status-warning-text',\n SHARE: 'bg-status-success-bg-subtle text-status-success-text',\n REVOKE: 'bg-status-warning-bg-subtle text-status-warning-text',\n ARCHIVE: 'bg-bg-muted text-text-secondary',\n RESTORE: 'bg-status-info-bg-subtle text-status-info-text',\n};\n\nfunction formatDate(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleString('en-US', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction formatResourceType(type: string): string {\n return type\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (character) => character.toUpperCase());\n}\n\nexport function AuditLogTable({\n items,\n total,\n hasMore,\n page,\n pageSize,\n onPageChange,\n onSelectLog,\n onDeleteLog,\n selectedLogId,\n selectedLogIds,\n allVisibleSelected,\n partiallySelected,\n onToggleLogSelection,\n onToggleAllVisible,\n}: AuditLogTableProps) {\n const { t } = useI18n();\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n\n const tr = (key: string, fallback: string) => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n return (\n <div>\n <div className=\"space-y-3 md:hidden\">\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <article\n key={item.id}\n className={`rounded-lg border border-border-default p-4 transition-colors ${\n selectedLogId === item.id ? 'bg-bg-sunken' : 'bg-bg-surface'\n }`}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n className=\"mt-1\"\n />\n <div className=\"min-w-0\">\n <p className=\"text-xs text-text-secondary\">{formatDate(item.createdAt)}</p>\n <p className=\"mt-1 truncate font-medium text-text-primary\">\n {item.resourceName || item.description || '-'}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </p>\n </div>\n </div>\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-surface text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </div>\n <div className=\"mt-3 flex items-center justify-between gap-3\">\n <p className=\"min-w-0 truncate text-xs capitalize text-text-secondary\">\n {(item.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n {item.resourceName ? ` · ${item.resourceName}` : ''}\n </p>\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </div>\n <div className=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-default px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-surface\"\n >\n View details\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </article>\n );\n })}\n </div>\n\n <div className=\"hidden overflow-x-auto rounded-card border border-border-subtle bg-bg-surface shadow-elevation-1 md:block\">\n <table className=\"w-full min-w-[860px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken\">\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={onToggleAllVisible}\n ariaLabel=\"Select all visible audit logs\"\n />\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n {tr('audit.time', 'Time')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n {tr('audit.action', 'Action')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n {tr('audit.resource', 'Resource')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n {tr('audit.name', 'Name')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n {tr('audit.actor', 'Actor')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wide text-text-muted\">\n {tr('audit.status', 'Status')}\n </th>\n <th className=\"px-4 py-3 text-right text-xs font-medium uppercase tracking-wide text-text-muted\">\n {tr('audit.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <tr\n key={item.id}\n className={`border-b border-border-subtle transition-colors hover:bg-bg-sunken ${\n selectedLogId === item.id ? 'bg-bg-sunken' : ''\n }`}\n >\n <td className=\"px-4 py-3 align-top\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n />\n </td>\n <td className=\"whitespace-nowrap px-4 py-3 text-xs text-text-secondary\">\n {formatDate(item.createdAt)}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-surface text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </td>\n <td className=\"px-4 py-3 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </td>\n <td\n className=\"max-w-[220px] truncate px-4 py-3\"\n title={item.resourceName || item.description || ''}\n >\n {item.resourceName || item.description || '-'}\n </td>\n <td\n className=\"max-w-[140px] truncate px-4 py-3 text-xs capitalize text-text-secondary\"\n title={item.actorId}\n >\n {(item.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n </td>\n <td className=\"px-4 py-3\">\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </td>\n <td className=\"px-4 py-3 text-right\">\n <div className=\"flex items-center justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-bg-surface hover:text-text-primary\"\n title={tr('audit.viewAuditLog', 'View details')}\n >\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n <div className=\"mt-4 flex flex-col gap-3 text-sm text-text-secondary sm:flex-row sm:items-center sm:justify-between\">\n <span>\n {tr('audit.showing', 'Showing')} {page * pageSize + 1}-\n {Math.min((page + 1) * pageSize, total)} {tr('audit.of', 'of')} {total}\n </span>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n disabled={page === 0}\n onClick={() => onPageChange(page - 1)}\n className=\"rounded border border-border-default px-3 py-1 transition-colors hover:bg-bg-surface disabled:opacity-50\"\n >\n {tr('audit.previous', 'Previous')}\n </button>\n <span>\n {tr('audit.page', 'Page')} {page + 1} {tr('audit.of', 'of')} {totalPages}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => onPageChange(page + 1)}\n className=\"rounded border border-border-default px-3 py-1 transition-colors hover:bg-bg-surface disabled:opacity-50\"\n >\n {tr('audit.next', 'Next')}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -13,12 +13,12 @@ var g = {
|
|
|
13
13
|
INTERNAL: {
|
|
14
14
|
icon: i,
|
|
15
15
|
label: "Internal",
|
|
16
|
-
className: "bg-status-warning-bg text-status-warning-text"
|
|
16
|
+
className: "bg-status-warning-bg-subtle text-status-warning-text"
|
|
17
17
|
},
|
|
18
18
|
PUBLIC: {
|
|
19
19
|
icon: o,
|
|
20
20
|
label: "Public",
|
|
21
|
-
className: "bg-status-success-bg text-status-success-text"
|
|
21
|
+
className: "bg-status-success-bg-subtle text-status-success-text"
|
|
22
22
|
}
|
|
23
23
|
}, _ = ({ catalog: i, onOpen: a, onEdit: o, onArchive: _, className: v = "" }) => {
|
|
24
24
|
let { t: y } = t(), b = (e, t) => {
|
|
@@ -47,7 +47,7 @@ var g = {
|
|
|
47
47
|
children: [/* @__PURE__ */ h("div", {
|
|
48
48
|
className: "flex items-start gap-2 sm:gap-3 min-w-0 flex-1",
|
|
49
49
|
children: [/* @__PURE__ */ m("div", {
|
|
50
|
-
className: "flex-shrink-0 size-8 sm:w-10 sm:h-10 rounded-lg bg-
|
|
50
|
+
className: "flex-shrink-0 size-8 sm:w-10 sm:h-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center",
|
|
51
51
|
children: /* @__PURE__ */ m(r, { className: "size-4 sm:w-5 sm:h-5 text-action-primary-bg" })
|
|
52
52
|
}), /* @__PURE__ */ h("div", {
|
|
53
53
|
className: "min-w-0 flex-1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogCard.js","names":[],"sources":["../../../src/components/catalog/CatalogCard.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport {\n BookOpen,\n Eye,\n EyeOff,\n Globe,\n Tag,\n MoreVertical,\n Settings,\n Archive,\n Layers,\n Zap,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport interface CatalogCardData {\n id: string;\n name: string;\n description: string | null;\n visibility: 'PRIVATE' | 'INTERNAL' | 'PUBLIC';\n componentCount: number;\n vibeCount: number;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CatalogCardProps {\n catalog: CatalogCardData;\n onOpen?: (catalog: CatalogCardData) => void;\n onEdit?: (catalog: CatalogCardData) => void;\n onArchive?: (catalog: CatalogCardData) => void;\n className?: string;\n}\n\nconst visibilityConfig = {\n PRIVATE: { icon: EyeOff, label: 'Private', className: 'bg-bg-sunken text-text-secondary' },\n INTERNAL: {\n icon: Eye,\n label: 'Internal',\n className: 'bg-status-warning-bg text-status-warning-text',\n },\n PUBLIC: {\n icon: Globe,\n label: 'Public',\n className: 'bg-status-success-bg text-status-success-text',\n },\n};\n\nexport const CatalogCard: FC<CatalogCardProps> = ({\n catalog,\n onOpen,\n onEdit,\n onArchive,\n className = '',\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const [showMenu, setShowMenu] = useState(false);\n\n const visConfig = visibilityConfig[catalog.visibility] ?? visibilityConfig.PRIVATE;\n const VisIcon = visConfig.icon;\n\n return (\n <motion.div\n whileHover={{ y: -2, transition: { duration: 0.15, ease: [0.4, 0, 0.2, 1] } }}\n whileTap={{ scale: 0.98 }}\n className={`bg-bg-surface border border-border-default rounded-lg p-4 hover:border-border-strong hover:shadow-md transition-all cursor-pointer ${className}`}\n onClick={() => onOpen?.(catalog)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-2 sm:gap-3 min-w-0 flex-1\">\n <div className=\"flex-shrink-0 size-8 sm:w-10 sm:h-10 rounded-lg bg-
|
|
1
|
+
{"version":3,"file":"CatalogCard.js","names":[],"sources":["../../../src/components/catalog/CatalogCard.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport {\n BookOpen,\n Eye,\n EyeOff,\n Globe,\n Tag,\n MoreVertical,\n Settings,\n Archive,\n Layers,\n Zap,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport interface CatalogCardData {\n id: string;\n name: string;\n description: string | null;\n visibility: 'PRIVATE' | 'INTERNAL' | 'PUBLIC';\n componentCount: number;\n vibeCount: number;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CatalogCardProps {\n catalog: CatalogCardData;\n onOpen?: (catalog: CatalogCardData) => void;\n onEdit?: (catalog: CatalogCardData) => void;\n onArchive?: (catalog: CatalogCardData) => void;\n className?: string;\n}\n\nconst visibilityConfig = {\n PRIVATE: { icon: EyeOff, label: 'Private', className: 'bg-bg-sunken text-text-secondary' },\n INTERNAL: {\n icon: Eye,\n label: 'Internal',\n className: 'bg-status-warning-bg-subtle text-status-warning-text',\n },\n PUBLIC: {\n icon: Globe,\n label: 'Public',\n className: 'bg-status-success-bg-subtle text-status-success-text',\n },\n};\n\nexport const CatalogCard: FC<CatalogCardProps> = ({\n catalog,\n onOpen,\n onEdit,\n onArchive,\n className = '',\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const [showMenu, setShowMenu] = useState(false);\n\n const visConfig = visibilityConfig[catalog.visibility] ?? visibilityConfig.PRIVATE;\n const VisIcon = visConfig.icon;\n\n return (\n <motion.div\n whileHover={{ y: -2, transition: { duration: 0.15, ease: [0.4, 0, 0.2, 1] } }}\n whileTap={{ scale: 0.98 }}\n className={`bg-bg-surface border border-border-default rounded-lg p-4 hover:border-border-strong hover:shadow-md transition-all cursor-pointer ${className}`}\n onClick={() => onOpen?.(catalog)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-2 sm:gap-3 min-w-0 flex-1\">\n <div className=\"flex-shrink-0 size-8 sm:w-10 sm:h-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center\">\n <BookOpen className=\"size-4 sm:w-5 sm:h-5 text-action-primary-bg\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold text-text-primary truncate text-sm sm:text-base\">\n {catalog.name}\n </h3>\n <div className=\"flex items-center gap-2 mt-0.5\">\n <span\n className={`inline-flex items-center gap-1 px-1.5 py-0.5 text-xs rounded ${visConfig.className}`}\n >\n <VisIcon className=\"size-3\" />\n {tr(`catalog.visibility.${catalog.visibility.toLowerCase()}`, visConfig.label)}\n </span>\n </div>\n </div>\n </div>\n {(onEdit || onArchive) && (\n <div className=\"relative flex-shrink-0\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu(!showMenu);\n }}\n className=\"p-1 sm:p-1.5 rounded hover:bg-bg-sunken transition-colors\"\n >\n <MoreVertical className=\"size-4 text-text-secondary\" />\n </button>\n <AnimatePresence>\n {showMenu && (\n <motion.div\n initial={{ opacity: 0, scale: 0.95, y: -4 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, y: -4 }}\n transition={{ duration: 0.15 }}\n className=\"absolute right-0 mt-1 w-40 bg-bg-surface border border-border-default rounded-lg shadow-lg z-10\"\n >\n {onEdit && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onEdit(catalog);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken rounded-t-lg\"\n >\n <Settings className=\"size-4\" />\n {tr('common.edit', 'Edit')}\n </motion.button>\n )}\n {onArchive && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onArchive(catalog);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken rounded-b-lg\"\n >\n <Archive className=\"size-4\" />\n {tr('common.archive', 'Archive')}\n </motion.button>\n )}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )}\n </div>\n\n {catalog.description && (\n <p className=\"mt-2 text-sm text-text-secondary line-clamp-2\">{catalog.description}</p>\n )}\n\n {/* Stats row */}\n <div className=\"mt-3 flex items-center gap-4 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1\">\n <Layers className=\"size-3.5\" />\n {catalog.componentCount} {tr('catalog.components', 'components')}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <Zap className=\"size-3.5\" />\n {catalog.vibeCount} {tr('catalog.vibes', 'vibes')}\n </span>\n </div>\n\n {catalog.tags.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1\">\n {catalog.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\"\n >\n <Tag className=\"size-3\" />\n {tag}\n </span>\n ))}\n {catalog.tags.length > 3 && (\n <span className=\"px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\">\n +{catalog.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </motion.div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ var o = ({ isOpen: o, onClose: s, onSubmit: c, initialData: l, title: u, extraSe
|
|
|
29
29
|
className: "space-y-4",
|
|
30
30
|
children: [
|
|
31
31
|
x && /* @__PURE__ */ i("div", {
|
|
32
|
-
className: "p-3 bg-status-error-bg text-status-error-text text-sm rounded-md",
|
|
32
|
+
className: "p-3 bg-status-error-bg-subtle text-status-error-text text-sm rounded-md",
|
|
33
33
|
children: x
|
|
34
34
|
}),
|
|
35
35
|
/* @__PURE__ */ a("div", { children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogForm.js","names":[],"sources":["../../../src/components/catalog/CatalogForm.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport type { FC, ReactNode } from 'react';\nimport { X } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport interface CatalogFormData {\n name: string;\n description: string;\n visibility: 'PRIVATE' | 'INTERNAL' | 'PUBLIC';\n owner: string;\n tags: string[];\n}\n\nexport interface CatalogFormProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (data: CatalogFormData) => Promise<void>;\n initialData?: Partial<CatalogFormData>;\n title?: string;\n /** Optional extra content (e.g. a draft EntityTagPicker) rendered above the footer. */\n extraSection?: ReactNode;\n}\n\nexport const CatalogForm: FC<CatalogFormProps> = ({\n isOpen,\n onClose,\n onSubmit,\n initialData,\n title,\n extraSection,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const nameRef = useRef<HTMLInputElement>(null);\n const descriptionRef = useRef<HTMLTextAreaElement>(null);\n const visibilityRef = useRef<HTMLSelectElement>(null);\n const ownerRef = useRef<HTMLInputElement>(null);\n const tagsRef = useRef<HTMLInputElement>(null);\n\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [fieldErrors, setFieldErrors] = useState<{ name?: string }>({});\n\n if (!isOpen) return null;\n\n const handleSubmit = async () => {\n const name = nameRef.current?.value?.trim();\n if (!name) {\n setFieldErrors({ name: tr('catalog.nameRequired', 'Name is required') });\n setError(tr('catalog.fillRequired', 'Please fill in all required fields'));\n return;\n }\n setFieldErrors({});\n\n const data: CatalogFormData = {\n name,\n description: descriptionRef.current?.value?.trim() || '',\n visibility: (visibilityRef.current?.value as CatalogFormData['visibility']) || 'PRIVATE',\n owner: ownerRef.current?.value?.trim() || '',\n tags: tagsRef.current?.value\n ? tagsRef.current.value\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n : [],\n };\n\n setLoading(true);\n setError(null);\n try {\n await onSubmit(data);\n onClose();\n } catch (err) {\n setError(\n err instanceof Error ? err.message : tr('catalog.failedSave', 'Failed to save catalog')\n );\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-50 p-4\">\n <div className=\"bg-bg-surface rounded-lg p-6 w-full max-w-lg\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {title || tr('catalog.createCatalog', 'Create Catalog')}\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors text-text-secondary\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n <div className=\"space-y-4\">\n {error && (\n <div className=\"p-3 bg-status-error-bg text-status-error-text text-sm rounded-md\">\n {error}\n </div>\n )}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.nameLabel', 'Name *')}\n </label>\n <input\n aria-label=\"control\"\n ref={nameRef}\n type=\"text\"\n defaultValue={initialData?.name || ''}\n placeholder={tr('catalog.namePlaceholder', 'My Catalog')}\n onChange={() =>\n fieldErrors.name && setFieldErrors((e) => ({ ...e, name: undefined }))\n }\n className={`w-full px-3 py-2 bg-bg-sunken border rounded-md text-text-primary placeholder:text-text-placeholder ${fieldErrors.name ? 'border-status-error-border' : 'border-border-default'}`}\n />\n {fieldErrors.name && (\n <p className=\"mt-1 text-xs text-status-error-text\">{fieldErrors.name}</p>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.descriptionLabel', 'Description')}\n </label>\n <textarea\n aria-label=\"control\"\n ref={descriptionRef}\n defaultValue={initialData?.description || ''}\n placeholder={tr('catalog.descriptionPlaceholder', 'Describe this catalog...')}\n rows={3}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder resize-none\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.visibilityLabel', 'Visibility')}\n </label>\n <select\n ref={visibilityRef}\n defaultValue={initialData?.visibility || 'PRIVATE'}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n >\n <option value=\"PRIVATE\">{tr('catalog.visibilityPrivate', 'Private')}</option>\n <option value=\"INTERNAL\">{tr('catalog.visibilityInternal', 'Internal')}</option>\n <option value=\"PUBLIC\">{tr('catalog.visibilityPublic', 'Public')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.ownerLabel', 'Owner')}\n </label>\n <input\n aria-label=\"control\"\n ref={ownerRef}\n type=\"text\"\n defaultValue={initialData?.owner || ''}\n placeholder={tr('catalog.ownerPlaceholder', 'team-name')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.tagsLabel', 'Tags (comma-separated)')}\n </label>\n <input\n aria-label=\"control\"\n ref={tagsRef}\n type=\"text\"\n defaultValue={initialData?.tags?.join(', ') || ''}\n placeholder={tr('catalog.tagsPlaceholder', 'frontend, microservice, api')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n </div>\n {extraSection && (\n <div className=\"mt-4 border-t border-border-default pt-4\">{extraSection}</div>\n )}\n <div className=\"flex flex-col sm:flex-row justify-end gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={onClose}\n disabled={loading}\n className=\"px-4 py-2 text-text-primary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={loading}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {loading\n ? tr('common.saving', 'Saving...')\n : initialData?.name\n ? tr('common.save', 'Save')\n : tr('catalog.createCatalog', 'Create Catalog')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CatalogForm.js","names":[],"sources":["../../../src/components/catalog/CatalogForm.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport type { FC, ReactNode } from 'react';\nimport { X } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport interface CatalogFormData {\n name: string;\n description: string;\n visibility: 'PRIVATE' | 'INTERNAL' | 'PUBLIC';\n owner: string;\n tags: string[];\n}\n\nexport interface CatalogFormProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (data: CatalogFormData) => Promise<void>;\n initialData?: Partial<CatalogFormData>;\n title?: string;\n /** Optional extra content (e.g. a draft EntityTagPicker) rendered above the footer. */\n extraSection?: ReactNode;\n}\n\nexport const CatalogForm: FC<CatalogFormProps> = ({\n isOpen,\n onClose,\n onSubmit,\n initialData,\n title,\n extraSection,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const nameRef = useRef<HTMLInputElement>(null);\n const descriptionRef = useRef<HTMLTextAreaElement>(null);\n const visibilityRef = useRef<HTMLSelectElement>(null);\n const ownerRef = useRef<HTMLInputElement>(null);\n const tagsRef = useRef<HTMLInputElement>(null);\n\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [fieldErrors, setFieldErrors] = useState<{ name?: string }>({});\n\n if (!isOpen) return null;\n\n const handleSubmit = async () => {\n const name = nameRef.current?.value?.trim();\n if (!name) {\n setFieldErrors({ name: tr('catalog.nameRequired', 'Name is required') });\n setError(tr('catalog.fillRequired', 'Please fill in all required fields'));\n return;\n }\n setFieldErrors({});\n\n const data: CatalogFormData = {\n name,\n description: descriptionRef.current?.value?.trim() || '',\n visibility: (visibilityRef.current?.value as CatalogFormData['visibility']) || 'PRIVATE',\n owner: ownerRef.current?.value?.trim() || '',\n tags: tagsRef.current?.value\n ? tagsRef.current.value\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n : [],\n };\n\n setLoading(true);\n setError(null);\n try {\n await onSubmit(data);\n onClose();\n } catch (err) {\n setError(\n err instanceof Error ? err.message : tr('catalog.failedSave', 'Failed to save catalog')\n );\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-50 p-4\">\n <div className=\"bg-bg-surface rounded-lg p-6 w-full max-w-lg\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {title || tr('catalog.createCatalog', 'Create Catalog')}\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors text-text-secondary\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n <div className=\"space-y-4\">\n {error && (\n <div className=\"p-3 bg-status-error-bg-subtle text-status-error-text text-sm rounded-md\">\n {error}\n </div>\n )}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.nameLabel', 'Name *')}\n </label>\n <input\n aria-label=\"control\"\n ref={nameRef}\n type=\"text\"\n defaultValue={initialData?.name || ''}\n placeholder={tr('catalog.namePlaceholder', 'My Catalog')}\n onChange={() =>\n fieldErrors.name && setFieldErrors((e) => ({ ...e, name: undefined }))\n }\n className={`w-full px-3 py-2 bg-bg-sunken border rounded-md text-text-primary placeholder:text-text-placeholder ${fieldErrors.name ? 'border-status-error-border' : 'border-border-default'}`}\n />\n {fieldErrors.name && (\n <p className=\"mt-1 text-xs text-status-error-text\">{fieldErrors.name}</p>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.descriptionLabel', 'Description')}\n </label>\n <textarea\n aria-label=\"control\"\n ref={descriptionRef}\n defaultValue={initialData?.description || ''}\n placeholder={tr('catalog.descriptionPlaceholder', 'Describe this catalog...')}\n rows={3}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder resize-none\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.visibilityLabel', 'Visibility')}\n </label>\n <select\n ref={visibilityRef}\n defaultValue={initialData?.visibility || 'PRIVATE'}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n >\n <option value=\"PRIVATE\">{tr('catalog.visibilityPrivate', 'Private')}</option>\n <option value=\"INTERNAL\">{tr('catalog.visibilityInternal', 'Internal')}</option>\n <option value=\"PUBLIC\">{tr('catalog.visibilityPublic', 'Public')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.ownerLabel', 'Owner')}\n </label>\n <input\n aria-label=\"control\"\n ref={ownerRef}\n type=\"text\"\n defaultValue={initialData?.owner || ''}\n placeholder={tr('catalog.ownerPlaceholder', 'team-name')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('catalog.tagsLabel', 'Tags (comma-separated)')}\n </label>\n <input\n aria-label=\"control\"\n ref={tagsRef}\n type=\"text\"\n defaultValue={initialData?.tags?.join(', ') || ''}\n placeholder={tr('catalog.tagsPlaceholder', 'frontend, microservice, api')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n </div>\n {extraSection && (\n <div className=\"mt-4 border-t border-border-default pt-4\">{extraSection}</div>\n )}\n <div className=\"flex flex-col sm:flex-row justify-end gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={onClose}\n disabled={loading}\n className=\"px-4 py-2 text-text-primary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={loading}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {loading\n ? tr('common.saving', 'Saving...')\n : initialData?.name\n ? tr('common.save', 'Save')\n : tr('catalog.createCatalog', 'Create Catalog')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -8,10 +8,10 @@ import { useNavigate as l } from "react-router-dom";
|
|
|
8
8
|
import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/common/ActionAgentTargetNotice.tsx
|
|
10
10
|
var p = {
|
|
11
|
-
info: "border-
|
|
12
|
-
success: "border-status-success-border bg-status-success-bg text-status-success-text",
|
|
13
|
-
warning: "border-status-warning-border bg-status-warning-bg text-status-warning-text",
|
|
14
|
-
error: "border-status-error-border bg-status-error-bg text-status-error-text"
|
|
11
|
+
info: "border-border-subtle bg-bg-sunken text-text-secondary",
|
|
12
|
+
success: "border-status-success-border bg-status-success-bg-subtle text-status-success-text",
|
|
13
|
+
warning: "border-status-warning-border bg-status-warning-bg-subtle text-status-warning-text",
|
|
14
|
+
error: "border-status-error-border bg-status-error-bg-subtle text-status-error-text"
|
|
15
15
|
};
|
|
16
16
|
function m({ action: m, className: h = "" }) {
|
|
17
17
|
let g = n(), _ = l(), v = m.actionType === "COMMAND" || m.actionType === "SCRIPT", { data: y } = e({
|
|
@@ -44,7 +44,7 @@ function m({ action: m, className: h = "" }) {
|
|
|
44
44
|
x
|
|
45
45
|
]), T = () => _("/vibecontrols/agents"), E = (e) => _(`/vibecontrols/agents/${encodeURIComponent(e)}`), D = () => _(`/vibecontrols/actions?editAction=${encodeURIComponent(m.id)}`);
|
|
46
46
|
if (w.mode === "no-agent") return m.actionType === "WEBHOOK" ? /* @__PURE__ */ f("div", {
|
|
47
|
-
className: `flex items-center gap-2 rounded-
|
|
47
|
+
className: `flex items-center gap-2 rounded-card border border-border-subtle bg-bg-sunken px-3 py-2 text-xs text-text-secondary ${h}`,
|
|
48
48
|
children: [/* @__PURE__ */ d(c, {
|
|
49
49
|
size: 14,
|
|
50
50
|
className: "flex-shrink-0"
|
|
@@ -90,7 +90,7 @@ function m({ action: m, className: h = "" }) {
|
|
|
90
90
|
})] });
|
|
91
91
|
}
|
|
92
92
|
return /* @__PURE__ */ d("div", {
|
|
93
|
-
className: `rounded-
|
|
93
|
+
className: `rounded-card border px-3 py-2.5 text-xs ${p[k]} ${h}`,
|
|
94
94
|
children: /* @__PURE__ */ f("div", {
|
|
95
95
|
className: "flex items-start gap-2",
|
|
96
96
|
children: [A, /* @__PURE__ */ f("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionAgentTargetNotice.js","names":[],"sources":["../../../src/components/common/ActionAgentTargetNotice.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { AlertTriangle, ArrowUpRight, ServerCog } from 'lucide-react';\n\nimport {\n useListAgentsQuery,\n useVibecontrolsAgentHealthProbesQuery,\n} from '@/generated/wspace-operations';\nimport type { AgentHealthProbe } from '@/utils/agentStatus';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { AgentStatusBadge } from '../agents/AgentStatusBadge';\nimport {\n resolveAgentTarget,\n type AgentTargetActionLike,\n type AgentTargetAgentLike,\n} from './actionAgentTarget';\n\ninterface ActionAgentTargetNoticeProps {\n /** The action being linked. Needs id + type + agent targeting fields. */\n action: AgentTargetActionLike & { id: string };\n className?: string;\n}\n\ntype Tone = 'info' | 'success' | 'warning' | 'error';\n\nconst TONE_CLASS: Record<Tone, string> = {\n info: 'border-status-info-border bg-status-info-bg text-status-info-text',\n success: 'border-status-success-border bg-status-success-bg text-status-success-text',\n warning: 'border-status-warning-border bg-status-warning-bg text-status-warning-text',\n error: 'border-status-error-border bg-status-error-bg text-status-error-text',\n};\n\n/**\n * Shown when an action is being linked to another surface (vibe-deck button,\n * scheduler, …). It tells the user which agent the action will run on and, when\n * that agent is unhealthy or no longer exists, warns them right in the linking\n * flow and links to the page where they can set the right agent.\n */\nexport function ActionAgentTargetNotice({ action, className = '' }: ActionAgentTargetNoticeProps) {\n const tr = useTr();\n const navigate = useNavigate();\n\n // Only COMMAND/SCRIPT actions run on an agent — skip the agent + health-probe\n // fetches entirely for webhook/workflow actions where the result is unused.\n const needsAgent = action.actionType === 'COMMAND' || action.actionType === 'SCRIPT';\n const { data: agentsData } = useListAgentsQuery({\n variables: { pagination: { limit: 200 } },\n fetchPolicy: 'cache-and-network',\n skip: !needsAgent,\n });\n const probeQuery = useVibecontrolsAgentHealthProbesQuery({\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n pollInterval: 60_000,\n skip: !needsAgent,\n });\n const probesLoading = probeQuery.data === undefined;\n\n const agents = useMemo<AgentTargetAgentLike[]>(() => {\n const raw = agentsData?.vibecontrolsAgents ?? [];\n return raw.map((a: NonNullable<typeof raw>[number]) => ({\n id: a.id,\n name: a.name,\n isActive: a.isActive,\n platform: a.platform ?? null,\n metadata: (a.metadata as Record<string, unknown> | null) ?? null,\n }));\n }, [agentsData]);\n\n const probesById = useMemo(() => {\n const m = new Map<string, AgentHealthProbe>();\n for (const p of probeQuery.data?.vibecontrolsAgentHealthProbes ?? []) {\n m.set(p.agentId, { agentId: p.agentId, healthy: p.healthy, errorMessage: p.errorMessage });\n }\n return m;\n }, [probeQuery.data]);\n\n const res = useMemo(\n () => resolveAgentTarget(action, agents, probesById, probesLoading),\n [action, agents, probesById, probesLoading]\n );\n\n const goAgents = () => navigate('/vibecontrols/agents');\n const goAgent = (id: string) => navigate(`/vibecontrols/agents/${encodeURIComponent(id)}`);\n const goEditAction = () =>\n navigate(`/vibecontrols/actions?editAction=${encodeURIComponent(action.id)}`);\n\n // Webhook / workflow actions don't run on an agent.\n if (res.mode === 'no-agent') {\n if (action.actionType === 'WEBHOOK') {\n return (\n <div\n className={`flex items-center gap-2 rounded-lg border border-border-default bg-bg-secondary px-3 py-2 text-xs text-text-tertiary ${className}`}\n >\n <ServerCog size={14} className=\"flex-shrink-0\" />\n <span>\n {tr(\n 'vibecontrols.actions.agentTarget.webhook',\n 'Runs as a webhook request — no agent needed.'\n )}\n </span>\n </div>\n );\n }\n return null;\n }\n\n const LinkButton = ({ label, onClick }: { label: string; onClick: () => void }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"inline-flex items-center gap-0.5 font-medium underline-offset-2 hover:underline\"\n >\n {label}\n <ArrowUpRight size={12} />\n </button>\n );\n\n let tone: Tone = 'info';\n let icon = <ServerCog size={14} className=\"mt-0.5 flex-shrink-0\" />;\n let title = '';\n let body: React.ReactNode = null;\n let links: React.ReactNode = null;\n\n if (res.mode === 'any-available') {\n if (res.noHealthyAgent) {\n tone = 'warning';\n icon = <AlertTriangle size={14} className=\"mt-0.5 flex-shrink-0\" />;\n title = tr('vibecontrols.actions.agentTarget.anyTitle', 'Runs on: any available agent');\n body = tr(\n 'vibecontrols.actions.agentTarget.anyNone',\n 'No healthy agent is available right now, so this action will fail until you add or start one.'\n );\n links = (\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.manageAgents', 'Manage agents')}\n onClick={goAgents}\n />\n );\n } else {\n tone = 'info';\n title = tr('vibecontrols.actions.agentTarget.anyTitle', 'Runs on: any available agent');\n body = probesLoading\n ? tr('vibecontrols.actions.agentTarget.anyChecking', 'Checking agent availability…')\n : tr(\n 'vibecontrols.actions.agentTarget.anyOk',\n 'A healthy agent is picked automatically when this runs.'\n ) + (res.healthyCount > 0 ? ` (${res.healthyCount} available)` : '');\n }\n } else if (res.missing) {\n tone = 'error';\n icon = <AlertTriangle size={14} className=\"mt-0.5 flex-shrink-0\" />;\n title = tr(\n 'vibecontrols.actions.agentTarget.missingTitle',\n 'The agent set for this action no longer exists'\n );\n body = tr(\n 'vibecontrols.actions.agentTarget.missingBody',\n 'Update the action to choose an available agent, otherwise it will fail when it runs.'\n );\n links = (\n <>\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.setAgent', 'Set agent')}\n onClick={goEditAction}\n />\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.manageAgents', 'Manage agents')}\n onClick={goAgents}\n />\n </>\n );\n } else if (res.agent) {\n const healthy = res.healthy;\n tone = healthy ? 'success' : 'warning';\n icon = healthy ? (\n <ServerCog size={14} className=\"mt-0.5 flex-shrink-0\" />\n ) : (\n <AlertTriangle size={14} className=\"mt-0.5 flex-shrink-0\" />\n );\n title = `${tr('vibecontrols.actions.agentTarget.runsOn', 'Runs on')}: ${res.agent.name}`;\n body = healthy\n ? null\n : tr(\n 'vibecontrols.actions.agentTarget.unhealthyBody',\n \"This agent isn't healthy, so the action may fail. Pick a different agent or fix this one before linking.\"\n );\n links = healthy ? null : (\n <>\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.setAgent', 'Set agent')}\n onClick={goEditAction}\n />\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.viewAgent', 'View agent')}\n onClick={() => res.agent && goAgent(res.agent.id)}\n />\n </>\n );\n }\n\n return (\n <div className={`rounded-lg border px-3 py-2 text-xs ${TONE_CLASS[tone]} ${className}`}>\n <div className=\"flex items-start gap-2\">\n {icon}\n <div className=\"min-w-0 flex-1 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{title}</span>\n {res.mode === 'specific' && res.agent && res.status && (\n <AgentStatusBadge status={res.status} reason={res.reason} />\n )}\n </div>\n {body && <p className=\"opacity-90\">{body}</p>}\n {links && <div className=\"flex flex-wrap items-center gap-3 pt-0.5\">{links}</div>}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ActionAgentTargetNotice.js","names":[],"sources":["../../../src/components/common/ActionAgentTargetNotice.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { AlertTriangle, ArrowUpRight, ServerCog } from 'lucide-react';\n\nimport {\n useListAgentsQuery,\n useVibecontrolsAgentHealthProbesQuery,\n} from '@/generated/wspace-operations';\nimport type { AgentHealthProbe } from '@/utils/agentStatus';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { AgentStatusBadge } from '../agents/AgentStatusBadge';\nimport {\n resolveAgentTarget,\n type AgentTargetActionLike,\n type AgentTargetAgentLike,\n} from './actionAgentTarget';\n\ninterface ActionAgentTargetNoticeProps {\n /** The action being linked. Needs id + type + agent targeting fields. */\n action: AgentTargetActionLike & { id: string };\n className?: string;\n}\n\ntype Tone = 'info' | 'success' | 'warning' | 'error';\n\nconst TONE_CLASS: Record<Tone, string> = {\n info: 'border-border-subtle bg-bg-sunken text-text-secondary',\n success: 'border-status-success-border bg-status-success-bg-subtle text-status-success-text',\n warning: 'border-status-warning-border bg-status-warning-bg-subtle text-status-warning-text',\n error: 'border-status-error-border bg-status-error-bg-subtle text-status-error-text',\n};\n\n/**\n * Shown when an action is being linked to another surface (vibe-deck button,\n * scheduler, …). It tells the user which agent the action will run on and, when\n * that agent is unhealthy or no longer exists, warns them right in the linking\n * flow and links to the page where they can set the right agent.\n */\nexport function ActionAgentTargetNotice({ action, className = '' }: ActionAgentTargetNoticeProps) {\n const tr = useTr();\n const navigate = useNavigate();\n\n // Only COMMAND/SCRIPT actions run on an agent — skip the agent + health-probe\n // fetches entirely for webhook/workflow actions where the result is unused.\n const needsAgent = action.actionType === 'COMMAND' || action.actionType === 'SCRIPT';\n const { data: agentsData } = useListAgentsQuery({\n variables: { pagination: { limit: 200 } },\n fetchPolicy: 'cache-and-network',\n skip: !needsAgent,\n });\n const probeQuery = useVibecontrolsAgentHealthProbesQuery({\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n pollInterval: 60_000,\n skip: !needsAgent,\n });\n const probesLoading = probeQuery.data === undefined;\n\n const agents = useMemo<AgentTargetAgentLike[]>(() => {\n const raw = agentsData?.vibecontrolsAgents ?? [];\n return raw.map((a: NonNullable<typeof raw>[number]) => ({\n id: a.id,\n name: a.name,\n isActive: a.isActive,\n platform: a.platform ?? null,\n metadata: (a.metadata as Record<string, unknown> | null) ?? null,\n }));\n }, [agentsData]);\n\n const probesById = useMemo(() => {\n const m = new Map<string, AgentHealthProbe>();\n for (const p of probeQuery.data?.vibecontrolsAgentHealthProbes ?? []) {\n m.set(p.agentId, { agentId: p.agentId, healthy: p.healthy, errorMessage: p.errorMessage });\n }\n return m;\n }, [probeQuery.data]);\n\n const res = useMemo(\n () => resolveAgentTarget(action, agents, probesById, probesLoading),\n [action, agents, probesById, probesLoading]\n );\n\n const goAgents = () => navigate('/vibecontrols/agents');\n const goAgent = (id: string) => navigate(`/vibecontrols/agents/${encodeURIComponent(id)}`);\n const goEditAction = () =>\n navigate(`/vibecontrols/actions?editAction=${encodeURIComponent(action.id)}`);\n\n // Webhook / workflow actions don't run on an agent.\n if (res.mode === 'no-agent') {\n if (action.actionType === 'WEBHOOK') {\n return (\n <div\n className={`flex items-center gap-2 rounded-card border border-border-subtle bg-bg-sunken px-3 py-2 text-xs text-text-secondary ${className}`}\n >\n <ServerCog size={14} className=\"flex-shrink-0\" />\n <span>\n {tr(\n 'vibecontrols.actions.agentTarget.webhook',\n 'Runs as a webhook request — no agent needed.'\n )}\n </span>\n </div>\n );\n }\n return null;\n }\n\n const LinkButton = ({ label, onClick }: { label: string; onClick: () => void }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"inline-flex items-center gap-0.5 font-medium underline-offset-2 hover:underline\"\n >\n {label}\n <ArrowUpRight size={12} />\n </button>\n );\n\n let tone: Tone = 'info';\n let icon = <ServerCog size={14} className=\"mt-0.5 flex-shrink-0\" />;\n let title = '';\n let body: React.ReactNode = null;\n let links: React.ReactNode = null;\n\n if (res.mode === 'any-available') {\n if (res.noHealthyAgent) {\n tone = 'warning';\n icon = <AlertTriangle size={14} className=\"mt-0.5 flex-shrink-0\" />;\n title = tr('vibecontrols.actions.agentTarget.anyTitle', 'Runs on: any available agent');\n body = tr(\n 'vibecontrols.actions.agentTarget.anyNone',\n 'No healthy agent is available right now, so this action will fail until you add or start one.'\n );\n links = (\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.manageAgents', 'Manage agents')}\n onClick={goAgents}\n />\n );\n } else {\n tone = 'info';\n title = tr('vibecontrols.actions.agentTarget.anyTitle', 'Runs on: any available agent');\n body = probesLoading\n ? tr('vibecontrols.actions.agentTarget.anyChecking', 'Checking agent availability…')\n : tr(\n 'vibecontrols.actions.agentTarget.anyOk',\n 'A healthy agent is picked automatically when this runs.'\n ) + (res.healthyCount > 0 ? ` (${res.healthyCount} available)` : '');\n }\n } else if (res.missing) {\n tone = 'error';\n icon = <AlertTriangle size={14} className=\"mt-0.5 flex-shrink-0\" />;\n title = tr(\n 'vibecontrols.actions.agentTarget.missingTitle',\n 'The agent set for this action no longer exists'\n );\n body = tr(\n 'vibecontrols.actions.agentTarget.missingBody',\n 'Update the action to choose an available agent, otherwise it will fail when it runs.'\n );\n links = (\n <>\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.setAgent', 'Set agent')}\n onClick={goEditAction}\n />\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.manageAgents', 'Manage agents')}\n onClick={goAgents}\n />\n </>\n );\n } else if (res.agent) {\n const healthy = res.healthy;\n tone = healthy ? 'success' : 'warning';\n icon = healthy ? (\n <ServerCog size={14} className=\"mt-0.5 flex-shrink-0\" />\n ) : (\n <AlertTriangle size={14} className=\"mt-0.5 flex-shrink-0\" />\n );\n title = `${tr('vibecontrols.actions.agentTarget.runsOn', 'Runs on')}: ${res.agent.name}`;\n body = healthy\n ? null\n : tr(\n 'vibecontrols.actions.agentTarget.unhealthyBody',\n \"This agent isn't healthy, so the action may fail. Pick a different agent or fix this one before linking.\"\n );\n links = healthy ? null : (\n <>\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.setAgent', 'Set agent')}\n onClick={goEditAction}\n />\n <LinkButton\n label={tr('vibecontrols.actions.agentTarget.viewAgent', 'View agent')}\n onClick={() => res.agent && goAgent(res.agent.id)}\n />\n </>\n );\n }\n\n return (\n <div className={`rounded-card border px-3 py-2.5 text-xs ${TONE_CLASS[tone]} ${className}`}>\n <div className=\"flex items-start gap-2\">\n {icon}\n <div className=\"min-w-0 flex-1 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{title}</span>\n {res.mode === 'specific' && res.agent && res.status && (\n <AgentStatusBadge status={res.status} reason={res.reason} />\n )}\n </div>\n {body && <p className=\"opacity-90\">{body}</p>}\n {links && <div className=\"flex flex-wrap items-center gap-3 pt-0.5\">{links}</div>}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ var s = t(function({ value: t, defaultValue: s, onChange: c, language: l = "shel
|
|
|
15
15
|
scrollbarGutter: "stable"
|
|
16
16
|
};
|
|
17
17
|
return /* @__PURE__ */ o("div", {
|
|
18
|
-
className: `relative overflow-hidden rounded-
|
|
18
|
+
className: `relative overflow-hidden rounded-input border border-border-subtle bg-bg-sunken transition-all duration-200 focus-within:border-border-strong focus-within:ring-1 focus-within:ring-[var(--color-focus-ring)] ${u}`,
|
|
19
19
|
children: [/* @__PURE__ */ a("pre", {
|
|
20
20
|
ref: b,
|
|
21
21
|
"aria-hidden": "true",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandEditor.js","names":[],"sources":["../../../src/components/common/CommandEditor.tsx"],"sourcesContent":["import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type CSSProperties,\n type MutableRefObject,\n type TextareaHTMLAttributes,\n type UIEvent,\n} from 'react';\n\nimport { tokenize, type CommandLanguage } from './commandHighlight';\n\ntype NativeTextareaProps = Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'onChange' | 'value' | 'defaultValue' | 'style'\n>;\n\nexport interface CommandEditorProps extends NativeTextareaProps {\n /** Controlled value. Omit (with `defaultValue`) for uncontrolled usage. */\n value?: string;\n defaultValue?: string;\n onChange?: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /** Highlight language. Defaults to shell. */\n language?: CommandLanguage;\n /** Extra classes for the bordered wrapper (e.g. a different background). */\n className?: string;\n rows?: number;\n /** Inline styles forwarded to the textarea (e.g. minHeight). */\n style?: CSSProperties;\n}\n\n/**\n * A drop-in replacement for a command/script `<textarea>` that renders live\n * syntax highlighting. It overlays a transparent textarea (the real input,\n * which keeps native editing, selection, IME and a11y) on top of a `<pre>` that\n * paints the highlighted tokens. The two layers share an identical box model so\n * the colored text sits exactly under the caret.\n *\n * Works controlled (`value` + `onChange`) or uncontrolled (`defaultValue` + a\n * forwarded `ref`, so callers that read `ref.current.value` keep working).\n */\nexport const CommandEditor = forwardRef<HTMLTextAreaElement, CommandEditorProps>(\n function CommandEditor(\n {\n value,\n defaultValue,\n onChange,\n language = 'shell',\n className = '',\n rows = 3,\n style,\n spellCheck = false,\n ...rest\n },\n forwardedRef\n ) {\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<string>(defaultValue ?? '');\n const text = isControlled ? (value ?? '') : internal;\n\n const preRef = useRef<HTMLPreElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n const setRefs = (node: HTMLTextAreaElement | null) => {\n textareaRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n (forwardedRef as MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }\n };\n\n const tokens = useMemo(() => tokenize(text, language), [text, language]);\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setInternal(event.target.value);\n onChange?.(event);\n };\n\n const syncScroll = (event: UIEvent<HTMLTextAreaElement>) => {\n const pre = preRef.current;\n if (!pre) return;\n pre.scrollTop = event.currentTarget.scrollTop;\n pre.scrollLeft = event.currentTarget.scrollLeft;\n };\n\n // Both layers MUST carry identical typography + box metrics so the painted\n // tokens line up under the caret. `scrollbarGutter: stable` is critical: the\n // textarea is overflow-auto and grows a (gutter-consuming) scrollbar once\n // content overflows the fixed rows, which would otherwise shrink ITS wrap\n // width relative to the overflow-hidden <pre> and drift every wrapped line.\n // Reserving the gutter on both keeps their content-box widths identical in\n // every state, so wrapping — and therefore the highlight overlay — stays aligned.\n const layerClass =\n 'm-0 w-full px-3 py-2 font-mono text-sm leading-relaxed whitespace-pre-wrap break-words';\n const layerStyle: CSSProperties = { tabSize: 2, scrollbarGutter: 'stable' };\n\n return (\n <div\n className={`relative overflow-hidden rounded-
|
|
1
|
+
{"version":3,"file":"CommandEditor.js","names":[],"sources":["../../../src/components/common/CommandEditor.tsx"],"sourcesContent":["import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type CSSProperties,\n type MutableRefObject,\n type TextareaHTMLAttributes,\n type UIEvent,\n} from 'react';\n\nimport { tokenize, type CommandLanguage } from './commandHighlight';\n\ntype NativeTextareaProps = Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'onChange' | 'value' | 'defaultValue' | 'style'\n>;\n\nexport interface CommandEditorProps extends NativeTextareaProps {\n /** Controlled value. Omit (with `defaultValue`) for uncontrolled usage. */\n value?: string;\n defaultValue?: string;\n onChange?: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /** Highlight language. Defaults to shell. */\n language?: CommandLanguage;\n /** Extra classes for the bordered wrapper (e.g. a different background). */\n className?: string;\n rows?: number;\n /** Inline styles forwarded to the textarea (e.g. minHeight). */\n style?: CSSProperties;\n}\n\n/**\n * A drop-in replacement for a command/script `<textarea>` that renders live\n * syntax highlighting. It overlays a transparent textarea (the real input,\n * which keeps native editing, selection, IME and a11y) on top of a `<pre>` that\n * paints the highlighted tokens. The two layers share an identical box model so\n * the colored text sits exactly under the caret.\n *\n * Works controlled (`value` + `onChange`) or uncontrolled (`defaultValue` + a\n * forwarded `ref`, so callers that read `ref.current.value` keep working).\n */\nexport const CommandEditor = forwardRef<HTMLTextAreaElement, CommandEditorProps>(\n function CommandEditor(\n {\n value,\n defaultValue,\n onChange,\n language = 'shell',\n className = '',\n rows = 3,\n style,\n spellCheck = false,\n ...rest\n },\n forwardedRef\n ) {\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<string>(defaultValue ?? '');\n const text = isControlled ? (value ?? '') : internal;\n\n const preRef = useRef<HTMLPreElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n const setRefs = (node: HTMLTextAreaElement | null) => {\n textareaRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n (forwardedRef as MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }\n };\n\n const tokens = useMemo(() => tokenize(text, language), [text, language]);\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setInternal(event.target.value);\n onChange?.(event);\n };\n\n const syncScroll = (event: UIEvent<HTMLTextAreaElement>) => {\n const pre = preRef.current;\n if (!pre) return;\n pre.scrollTop = event.currentTarget.scrollTop;\n pre.scrollLeft = event.currentTarget.scrollLeft;\n };\n\n // Both layers MUST carry identical typography + box metrics so the painted\n // tokens line up under the caret. `scrollbarGutter: stable` is critical: the\n // textarea is overflow-auto and grows a (gutter-consuming) scrollbar once\n // content overflows the fixed rows, which would otherwise shrink ITS wrap\n // width relative to the overflow-hidden <pre> and drift every wrapped line.\n // Reserving the gutter on both keeps their content-box widths identical in\n // every state, so wrapping — and therefore the highlight overlay — stays aligned.\n const layerClass =\n 'm-0 w-full px-3 py-2 font-mono text-sm leading-relaxed whitespace-pre-wrap break-words';\n const layerStyle: CSSProperties = { tabSize: 2, scrollbarGutter: 'stable' };\n\n return (\n <div\n className={`relative overflow-hidden rounded-input border border-border-subtle bg-bg-sunken transition-all duration-200 focus-within:border-border-strong focus-within:ring-1 focus-within:ring-[var(--color-focus-ring)] ${className}`}\n >\n <pre\n ref={preRef}\n aria-hidden=\"true\"\n className={`${layerClass} pointer-events-none absolute inset-0 overflow-hidden text-text-primary`}\n style={layerStyle}\n >\n <code>\n {tokens.map((token, index) =>\n token.className ? (\n <span key={index} className={token.className}>\n {token.value}\n </span>\n ) : (\n <span key={index}>{token.value}</span>\n )\n )}\n </code>\n </pre>\n <textarea\n {...rest}\n ref={setRefs}\n rows={rows}\n spellCheck={spellCheck}\n value={isControlled ? text : undefined}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n onScroll={syncScroll}\n className={`${layerClass} relative block resize-none overflow-auto bg-transparent text-transparent placeholder:text-text-placeholder focus:outline-none`}\n style={{ ...layerStyle, caretColor: 'var(--color-text-primary)', ...style }}\n />\n </div>\n );\n }\n);\n"],"mappings":";;;;AA2CA,IAAa,IAAgB,EAC3B,SACE,EACE,UACA,iBACA,aACA,cAAW,SACX,eAAY,IACZ,UAAO,GACP,UACA,gBAAa,IACb,GAAG,KAEL,GACA;CACA,IAAM,IAAe,MAAU,KAAA,GACzB,CAAC,GAAU,KAAe,EAAiB,KAAgB,GAAG,EAC9D,IAAO,IAAgB,KAAS,KAAM,GAEtC,IAAS,EAAuB,KAAK,EACrC,IAAc,EAAmC,KAAK,EAEtD,KAAW,MAAqC;AAEpD,EADA,EAAY,UAAU,GAClB,OAAO,KAAiB,aAC1B,EAAa,EAAK,GACT,MACR,EAA8D,UAAU;IAIvE,IAAS,QAAc,EAAS,GAAM,EAAS,EAAE,CAAC,GAAM,EAAS,CAAC,EAElE,KAAgB,MAA4C;AAEhE,EADK,KAAc,EAAY,EAAM,OAAO,MAAM,EAClD,IAAW,EAAM;IAGb,KAAc,MAAwC;EAC1D,IAAM,IAAM,EAAO;AACd,QACL,EAAI,YAAY,EAAM,cAAc,WACpC,EAAI,aAAa,EAAM,cAAc;IAUjC,IACJ,0FACI,IAA4B;EAAE,SAAS;EAAG,iBAAiB;EAAU;AAE3E,QACE,kBAAC,OAAD;EACE,WAAW,iNAAiN;YAD9N,CAGE,kBAAC,OAAD;GACE,KAAK;GACL,eAAY;GACZ,WAAW,GAAG,EAAW;GACzB,OAAO;aAEP,kBAAC,QAAD,EAAA,UACG,EAAO,KAAK,GAAO,MAClB,EAAM,YACJ,kBAAC,QAAD;IAAkB,WAAW,EAAM;cAChC,EAAM;IACF,EAFI,EAEJ,GAEP,kBAAC,QAAD,EAAA,UAAmB,EAAM,OAAa,EAA3B,EAA2B,CAEzC,EACI,CAAA;GACH,CAAA,EACN,kBAAC,YAAD;GACE,GAAI;GACJ,KAAK;GACC;GACM;GACZ,OAAO,IAAe,IAAO,KAAA;GAC7B,cAAc,IAAe,KAAA,IAAY;GACzC,UAAU;GACV,UAAU;GACV,WAAW,GAAG,EAAW;GACzB,OAAO;IAAE,GAAG;IAAY,YAAY;IAA6B,GAAG;IAAO;GAC3E,CAAA,CACE;;EAGX"}
|
|
@@ -23,7 +23,7 @@ function f({ node: e, depth: t, selectedPageId: o, onSelectPage: s, onDeletePage
|
|
|
23
23
|
onKeyDown: (t) => {
|
|
24
24
|
(t.key === "Enter" || t.key === " ") && (t.preventDefault(), s(e.page.id));
|
|
25
25
|
},
|
|
26
|
-
className: `flex items-center gap-1 px-2 py-1.5 cursor-pointer rounded text-sm transition-colors group ${h ? "bg-
|
|
26
|
+
className: `flex items-center gap-1 px-2 py-1.5 cursor-pointer rounded text-sm transition-colors group ${h ? "bg-[var(--color-accent-soft)] text-text-primary" : "text-text-secondary hover:bg-bg-sunken hover:text-text-primary"}`,
|
|
27
27
|
style: { paddingLeft: `${8 + t * 16}px` },
|
|
28
28
|
onClick: () => s(e.page.id),
|
|
29
29
|
children: [
|