@invect/ui 0.0.1
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/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/Invect-CWpIwZ5F.js +92738 -0
- package/dist/Invect.d.ts +25 -0
- package/dist/InvectShell.d.ts +14 -0
- package/dist/api/agent-tools.api.d.ts +1 -0
- package/dist/api/client.d.ts +207 -0
- package/dist/api/credentials.api.d.ts +47 -0
- package/dist/api/executions.api.d.ts +43 -0
- package/dist/api/flows.api.d.ts +100 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/node-data.api.d.ts +66 -0
- package/dist/api/query-keys.d.ts +22 -0
- package/dist/api/triggers.api.d.ts +44 -0
- package/dist/api/types.d.ts +147 -0
- package/dist/api/use-flow-run-stream.d.ts +12 -0
- package/dist/assets/invect-branding.d.ts +4 -0
- package/dist/assets/provider-icons/index.d.ts +8 -0
- package/dist/babel-C9OtljFZ.js +9721 -0
- package/dist/components/PageLayout.d.ts +17 -0
- package/dist/components/chat/ChatInput.d.ts +17 -0
- package/dist/components/chat/ChatMessageList.d.ts +14 -0
- package/dist/components/chat/ChatModelSelector.d.ts +11 -0
- package/dist/components/chat/ChatPanel.d.ts +19 -0
- package/dist/components/chat/ChatPromptOverlay.d.ts +13 -0
- package/dist/components/chat/ChatProviderSelector.d.ts +9 -0
- package/dist/components/chat/ChatSettingsPanel.d.ts +11 -0
- package/dist/components/chat/InlineCredentialSetup.d.ts +9 -0
- package/dist/components/chat/MarkdownRenderer.d.ts +7 -0
- package/dist/components/chat/chat-memory.d.ts +21 -0
- package/dist/components/chat/chat.store.d.ts +416 -0
- package/dist/components/chat/index.d.ts +5 -0
- package/dist/components/chat/use-chat.d.ts +28 -0
- package/dist/components/credentials/CreateCredentialModal.d.ts +13 -0
- package/dist/components/credentials/CredentialDetailDialog.d.ts +17 -0
- package/dist/components/credentials/EditCredentialModal.d.ts +11 -0
- package/dist/components/credentials/OAuth2ConnectButton.d.ts +38 -0
- package/dist/components/credentials/OAuth2ProviderSelector.d.ts +15 -0
- package/dist/components/credentials/credential-utils.d.ts +12 -0
- package/dist/components/credentials/index.d.ts +9 -0
- package/dist/components/dashboard/FailedRunsAlert.d.ts +3 -0
- package/dist/components/dashboard/FlowCard.d.ts +7 -0
- package/dist/components/dashboard/RecentActivityTable.d.ts +9 -0
- package/dist/components/dashboard/StatCard.d.ts +10 -0
- package/dist/components/dashboard/index.d.ts +5 -0
- package/dist/components/dashboard/status-helpers.d.ts +5 -0
- package/dist/components/flow-editor/ActionsSidebar.d.ts +2 -0
- package/dist/components/flow-editor/FlowEditor.d.ts +21 -0
- package/dist/components/flow-editor/FlowHeader.d.ts +9 -0
- package/dist/components/flow-editor/FlowLayout.d.ts +24 -0
- package/dist/components/flow-editor/ModeSwitcher.d.ts +7 -0
- package/dist/components/flow-editor/NodeSidebar.d.ts +24 -0
- package/dist/components/flow-editor/RunControls.d.ts +12 -0
- package/dist/components/flow-editor/ToolConfigPanel.d.ts +16 -0
- package/dist/components/flow-editor/ValidationPanel.d.ts +5 -0
- package/dist/components/flow-editor/flow-editor.store.d.ts +1 -0
- package/dist/components/flow-editor/index.d.ts +6 -0
- package/dist/components/flow-editor/inline-edit.d.ts +10 -0
- package/dist/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.d.ts +26 -0
- package/dist/components/flow-editor/node-config-panel/CredentialCombobox.d.ts +21 -0
- package/dist/components/flow-editor/node-config-panel/CredentialsSection.d.ts +19 -0
- package/dist/components/flow-editor/node-config-panel/DroppableInput.d.ts +20 -0
- package/dist/components/flow-editor/node-config-panel/DynamicSelectField.d.ts +22 -0
- package/dist/components/flow-editor/node-config-panel/JsonPreviewPanel.d.ts +25 -0
- package/dist/components/flow-editor/node-config-panel/NodeConfigPanel.d.ts +14 -0
- package/dist/components/flow-editor/node-config-panel/NodeConfigPanelHeader.d.ts +15 -0
- package/dist/components/flow-editor/node-config-panel/ParametersSection.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/SearchableSelectField.d.ts +17 -0
- package/dist/components/flow-editor/node-config-panel/SwitchCasesField.d.ts +18 -0
- package/dist/components/flow-editor/node-config-panel/hooks/index.d.ts +2 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.d.ts +24 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-node-execution.d.ts +46 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-upstream-slots.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/panels/AgentToolsPanel.d.ts +18 -0
- package/dist/components/flow-editor/node-config-panel/panels/ConfigurationPanel.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/panels/DataMapperPane.d.ts +40 -0
- package/dist/components/flow-editor/node-config-panel/panels/InputPanel.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/panels/OutputPanel.d.ts +7 -0
- package/dist/components/flow-editor/node-config-panel/panels/index.d.ts +4 -0
- package/dist/components/flow-editor/node-config-panel/types.d.ts +19 -0
- package/dist/components/flow-editor/node-config-panel/use-node-config-panel-store.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/use-node-config-state.d.ts +26 -0
- package/dist/components/flow-editor/node-config-panel/use-run-node.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/utils.d.ts +9 -0
- package/dist/components/flow-editor/serialize-to-sdk.d.ts +20 -0
- package/dist/components/flow-editor/toolbar-context.d.ts +2 -0
- package/dist/components/flow-editor/use-copy-paste.d.ts +7 -0
- package/dist/components/flow-editor/use-copy-paste.types.d.ts +38 -0
- package/dist/components/flow-editor/use-flow-editor.d.ts +44 -0
- package/dist/components/flow-runs-table/FlowRunsTable.d.ts +6 -0
- package/dist/components/flow-runs-table/index.d.ts +1 -0
- package/dist/components/flow-viewer/FlowRunsView.d.ts +7 -0
- package/dist/components/flow-viewer/FlowStatusView.d.ts +21 -0
- package/dist/components/flow-viewer/RunSelector.d.ts +13 -0
- package/dist/components/flow-viewer/RunsSidebar.d.ts +14 -0
- package/dist/components/flow-viewer/agent-tool-executions-list.d.ts +7 -0
- package/dist/components/flow-viewer/index.d.ts +1 -0
- package/dist/components/flow-viewer/logs-panel.d.ts +18 -0
- package/dist/components/flow-viewer/use-execution-log-data.d.ts +113 -0
- package/dist/components/graph/BatchFlowEdge.d.ts +33 -0
- package/dist/components/graph/LayoutSelector.d.ts +9 -0
- package/dist/components/graph/index.d.ts +47 -0
- package/dist/components/graph/styleUtils.d.ts +124 -0
- package/dist/components/nodes/AgentConfigPanel.d.ts +24 -0
- package/dist/components/nodes/AgentNode.d.ts +8 -0
- package/dist/components/nodes/AgentToolsBox.d.ts +41 -0
- package/dist/components/nodes/NodeAppendix.d.ts +19 -0
- package/dist/components/nodes/NodeStatusIndicator.d.ts +30 -0
- package/dist/components/nodes/NodeViewContext.d.ts +18 -0
- package/dist/components/nodes/ToolParamField.d.ts +28 -0
- package/dist/components/nodes/ToolSelectorModal.d.ts +80 -0
- package/dist/components/nodes/ToolSelectorParts.d.ts +30 -0
- package/dist/components/nodes/UniversalNode.d.ts +2 -0
- package/dist/components/nodes/createContextAwareNodes.d.ts +6 -0
- package/dist/components/nodes/index.d.ts +22 -0
- package/dist/components/nodes/nodeRegistry.d.ts +13 -0
- package/dist/components/nodes/withNodeContext.d.ts +7 -0
- package/dist/components/shared/InvectLoader.d.ts +8 -0
- package/dist/components/shared/InvectLogo.d.ts +9 -0
- package/dist/components/shared/ProviderIcon.d.ts +23 -0
- package/dist/components/side-menu/side-menu.d.ts +4 -0
- package/dist/components/sidebar/BaseSidebar.d.ts +17 -0
- package/dist/components/sidebar/index.d.ts +1 -0
- package/dist/components/triggers/CronPreview.d.ts +12 -0
- package/dist/components/triggers/index.d.ts +1 -0
- package/dist/components/ui/alert-dialog.d.ts +18 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/button.d.ts +13 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/codemirror-js-editor.d.ts +25 -0
- package/dist/components/ui/codemirror-json-editor.d.ts +18 -0
- package/dist/components/ui/codemirror-nunjucks-editor.d.ts +13 -0
- package/dist/components/ui/codemirror-vscode-theme.d.ts +24 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/command.d.ts +18 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dropdown-menu.d.ts +25 -0
- package/dist/components/ui/empty-state.d.ts +21 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/popover.d.ts +10 -0
- package/dist/components/ui/resizable.d.ts +8 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/select.d.ts +18 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/switch.d.ts +3 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/tooltip.d.ts +7 -0
- package/dist/components/ui/tree-view.d.ts +107 -0
- package/dist/contexts/AgentToolCallbacksContext.d.ts +23 -0
- package/dist/contexts/ApiContext.d.ts +11 -0
- package/dist/contexts/FlowDataContext.d.ts +9 -0
- package/dist/contexts/NodeRegistryContext.d.ts +14 -0
- package/dist/contexts/PluginRegistryContext.d.ts +39 -0
- package/dist/contexts/ThemeProvider.d.ts +18 -0
- package/dist/contexts/ValidationContext.d.ts +22 -0
- package/dist/demo/DemoInvect.d.ts +11 -0
- package/dist/demo/FlowViewer.d.ts +31 -0
- package/dist/demo/demo-api-client.d.ts +33 -0
- package/dist/demo/index.d.ts +6 -0
- package/dist/demo/sample-data.d.ts +1538 -0
- package/dist/demo.d.ts +2 -0
- package/dist/demo.js +2774 -0
- package/dist/estree-ClbRfS-1.js +7076 -0
- package/dist/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/iosevka-latin-400-normal.woff2 +0 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-document-title.d.ts +1 -0
- package/dist/hooks/use-flow-data.d.ts +22 -0
- package/dist/hooks/use-invect-portal-class.d.ts +21 -0
- package/dist/hooks/useFlowEditorStore.d.ts +1 -0
- package/dist/index.css +3 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +717 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/prettier.d.ts +13 -0
- package/dist/routes/all-flow-runs.d.ts +5 -0
- package/dist/routes/credentials.d.ts +5 -0
- package/dist/routes/flow-route-layout.d.ts +19 -0
- package/dist/routes/flow-runs.d.ts +5 -0
- package/dist/routes/flow.d.ts +5 -0
- package/dist/routes/home.d.ts +5 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/standalone-C3Df7W52.js +3463 -0
- package/dist/stores/executionViewStore.d.ts +64 -0
- package/dist/stores/flow-editor.store.d.ts +137 -0
- package/dist/stores/flowEditorStore.d.ts +1 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/uiStore.d.ts +45 -0
- package/dist/types/agent-tools.types.d.ts +53 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/node-definition.types.d.ts +85 -0
- package/dist/types/plugin.types.d.ts +100 -0
- package/dist/utils/credentialBranding.d.ts +8 -0
- package/dist/utils/credentialFiltering.d.ts +20 -0
- package/dist/utils/flowTransformations.d.ts +16 -0
- package/dist/utils/layoutUtils.d.ts +23 -0
- package/dist/utils/nodeReferenceUtils.d.ts +37 -0
- package/dist/vendor.d.ts +5 -0
- package/package.json +130 -0
- package/src/.DS_Store +0 -0
- package/src/Invect.tsx +229 -0
- package/src/InvectShell.tsx +55 -0
- package/src/api/agent-tools.api.ts +23 -0
- package/src/api/client.ts +899 -0
- package/src/api/credentials.api.ts +197 -0
- package/src/api/executions.api.ts +228 -0
- package/src/api/flows.api.ts +195 -0
- package/src/api/index.ts +17 -0
- package/src/api/node-data.api.ts +167 -0
- package/src/api/query-keys.ts +44 -0
- package/src/api/triggers.api.ts +120 -0
- package/src/api/types.ts +212 -0
- package/src/api/use-flow-run-stream.ts +206 -0
- package/src/app.css +560 -0
- package/src/assets/.DS_Store +0 -0
- package/src/assets/favicon.ico +0 -0
- package/src/assets/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/src/assets/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/src/assets/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/src/assets/fonts/iosevka-latin-400-normal.woff2 +0 -0
- package/src/assets/invect-branding.ts +51 -0
- package/src/assets/provider-icons/anthropic.svg +1 -0
- package/src/assets/provider-icons/anthropic_light.svg +1 -0
- package/src/assets/provider-icons/github.svg +1 -0
- package/src/assets/provider-icons/github_light.svg +1 -0
- package/src/assets/provider-icons/gmail.svg +1 -0
- package/src/assets/provider-icons/google_calendar.svg +1 -0
- package/src/assets/provider-icons/google_docs.svg +1 -0
- package/src/assets/provider-icons/google_drive.svg +1 -0
- package/src/assets/provider-icons/google_sheets.svg +1 -0
- package/src/assets/provider-icons/index.ts +55 -0
- package/src/assets/provider-icons/linear.svg +1 -0
- package/src/assets/provider-icons/openai.svg +1 -0
- package/src/assets/provider-icons/postgres.svg +1 -0
- package/src/assets/provider-icons/slack.svg +1 -0
- package/src/assets/small-loader-dark.svg +22 -0
- package/src/assets/small-loader-light.svg +22 -0
- package/src/assets/small.svg +7 -0
- package/src/components/.DS_Store +0 -0
- package/src/components/PageLayout.tsx +55 -0
- package/src/components/chat/ChatInput.tsx +115 -0
- package/src/components/chat/ChatMessageList.tsx +788 -0
- package/src/components/chat/ChatModelSelector.tsx +208 -0
- package/src/components/chat/ChatPanel.tsx +243 -0
- package/src/components/chat/ChatPromptOverlay.tsx +150 -0
- package/src/components/chat/ChatProviderSelector.tsx +135 -0
- package/src/components/chat/ChatSettingsPanel.tsx +277 -0
- package/src/components/chat/InlineCredentialSetup.tsx +343 -0
- package/src/components/chat/MarkdownRenderer.tsx +140 -0
- package/src/components/chat/chat-memory.ts +88 -0
- package/src/components/chat/chat.store.ts +479 -0
- package/src/components/chat/index.ts +5 -0
- package/src/components/chat/use-chat.ts +473 -0
- package/src/components/credentials/CreateCredentialModal.tsx +609 -0
- package/src/components/credentials/CredentialDetailDialog.tsx +882 -0
- package/src/components/credentials/EditCredentialModal.tsx +399 -0
- package/src/components/credentials/OAuth2ConnectButton.tsx +288 -0
- package/src/components/credentials/OAuth2ProviderSelector.tsx +360 -0
- package/src/components/credentials/credential-utils.ts +99 -0
- package/src/components/credentials/index.ts +10 -0
- package/src/components/dashboard/FailedRunsAlert.tsx +67 -0
- package/src/components/dashboard/FlowCard.tsx +64 -0
- package/src/components/dashboard/RecentActivityTable.tsx +92 -0
- package/src/components/dashboard/StatCard.tsx +32 -0
- package/src/components/dashboard/index.ts +5 -0
- package/src/components/dashboard/status-helpers.tsx +102 -0
- package/src/components/flow-editor/ActionsSidebar.tsx +503 -0
- package/src/components/flow-editor/FlowEditor.tsx +1002 -0
- package/src/components/flow-editor/FlowHeader.tsx +87 -0
- package/src/components/flow-editor/FlowLayout.tsx +117 -0
- package/src/components/flow-editor/ModeSwitcher.tsx +49 -0
- package/src/components/flow-editor/NodeSidebar.tsx +343 -0
- package/src/components/flow-editor/RunControls.tsx +109 -0
- package/src/components/flow-editor/ToolConfigPanel.tsx +434 -0
- package/src/components/flow-editor/ValidationPanel.tsx +167 -0
- package/src/components/flow-editor/flow-editor.store.ts +2 -0
- package/src/components/flow-editor/index.ts +6 -0
- package/src/components/flow-editor/inline-edit.tsx +111 -0
- package/src/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.tsx +334 -0
- package/src/components/flow-editor/node-config-panel/CredentialCombobox.tsx +217 -0
- package/src/components/flow-editor/node-config-panel/CredentialsSection.tsx +154 -0
- package/src/components/flow-editor/node-config-panel/DroppableInput.tsx +45 -0
- package/src/components/flow-editor/node-config-panel/DynamicSelectField.tsx +223 -0
- package/src/components/flow-editor/node-config-panel/JsonPreviewPanel.tsx +134 -0
- package/src/components/flow-editor/node-config-panel/NodeConfigPanel.tsx +650 -0
- package/src/components/flow-editor/node-config-panel/NodeConfigPanelHeader.tsx +91 -0
- package/src/components/flow-editor/node-config-panel/ParametersSection.tsx +144 -0
- package/src/components/flow-editor/node-config-panel/SearchableSelectField.tsx +126 -0
- package/src/components/flow-editor/node-config-panel/SwitchCasesField.tsx +212 -0
- package/src/components/flow-editor/node-config-panel/hooks/index.ts +2 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.ts +284 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-node-execution.ts +287 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-upstream-slots.ts +310 -0
- package/src/components/flow-editor/node-config-panel/panels/AgentToolsPanel.tsx +837 -0
- package/src/components/flow-editor/node-config-panel/panels/ConfigurationPanel.tsx +383 -0
- package/src/components/flow-editor/node-config-panel/panels/DataMapperPane.tsx +456 -0
- package/src/components/flow-editor/node-config-panel/panels/InputPanel.tsx +338 -0
- package/src/components/flow-editor/node-config-panel/panels/OutputPanel.tsx +109 -0
- package/src/components/flow-editor/node-config-panel/panels/index.ts +4 -0
- package/src/components/flow-editor/node-config-panel/types.ts +20 -0
- package/src/components/flow-editor/node-config-panel/use-node-config-panel-store.ts +283 -0
- package/src/components/flow-editor/node-config-panel/use-node-config-state.ts +172 -0
- package/src/components/flow-editor/node-config-panel/use-run-node.ts +147 -0
- package/src/components/flow-editor/node-config-panel/utils.ts +73 -0
- package/src/components/flow-editor/serialize-to-sdk.ts +204 -0
- package/src/components/flow-editor/toolbar-context.ts +9 -0
- package/src/components/flow-editor/use-copy-paste.ts +575 -0
- package/src/components/flow-editor/use-copy-paste.types.ts +35 -0
- package/src/components/flow-editor/use-flow-editor.ts +241 -0
- package/src/components/flow-runs-table/FlowRunsTable.tsx +631 -0
- package/src/components/flow-runs-table/index.ts +1 -0
- package/src/components/flow-viewer/FlowRunsView.tsx +268 -0
- package/src/components/flow-viewer/FlowStatusView.tsx +351 -0
- package/src/components/flow-viewer/RunSelector.tsx +422 -0
- package/src/components/flow-viewer/RunsSidebar.tsx +125 -0
- package/src/components/flow-viewer/agent-tool-executions-list.tsx +298 -0
- package/src/components/flow-viewer/index.ts +1 -0
- package/src/components/flow-viewer/logs-panel.tsx +567 -0
- package/src/components/flow-viewer/use-execution-log-data.ts +374 -0
- package/src/components/graph/BatchFlowEdge.tsx +229 -0
- package/src/components/graph/LayoutSelector.tsx +42 -0
- package/src/components/graph/index.ts +61 -0
- package/src/components/graph/styleUtils.ts +375 -0
- package/src/components/nodes/.DS_Store +0 -0
- package/src/components/nodes/AgentConfigPanel.tsx +1033 -0
- package/src/components/nodes/AgentNode.tsx +298 -0
- package/src/components/nodes/AgentToolsBox.tsx +193 -0
- package/src/components/nodes/NodeAppendix.tsx +98 -0
- package/src/components/nodes/NodeStatusIndicator.tsx +74 -0
- package/src/components/nodes/NodeViewContext.tsx +45 -0
- package/src/components/nodes/ToolParamField.tsx +282 -0
- package/src/components/nodes/ToolSelectorModal.tsx +648 -0
- package/src/components/nodes/ToolSelectorParts.tsx +505 -0
- package/src/components/nodes/UniversalNode.tsx +356 -0
- package/src/components/nodes/createContextAwareNodes.ts +19 -0
- package/src/components/nodes/index.ts +45 -0
- package/src/components/nodes/nodeRegistry.ts +50 -0
- package/src/components/nodes/withNodeContext.tsx +55 -0
- package/src/components/shared/InvectLoader.tsx +59 -0
- package/src/components/shared/InvectLogo.tsx +59 -0
- package/src/components/shared/ProviderIcon.tsx +115 -0
- package/src/components/side-menu/side-menu.tsx +267 -0
- package/src/components/sidebar/BaseSidebar.tsx +148 -0
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/triggers/CronPreview.tsx +243 -0
- package/src/components/triggers/index.ts +1 -0
- package/src/components/ui/alert-dialog.tsx +152 -0
- package/src/components/ui/badge.tsx +39 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/card.tsx +75 -0
- package/src/components/ui/codemirror-js-editor.tsx +432 -0
- package/src/components/ui/codemirror-json-editor.tsx +816 -0
- package/src/components/ui/codemirror-nunjucks-editor.tsx +451 -0
- package/src/components/ui/codemirror-vscode-theme.ts +243 -0
- package/src/components/ui/collapsible.tsx +12 -0
- package/src/components/ui/command.tsx +162 -0
- package/src/components/ui/dialog.tsx +140 -0
- package/src/components/ui/dropdown-menu.tsx +232 -0
- package/src/components/ui/empty-state.tsx +93 -0
- package/src/components/ui/input.tsx +26 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/popover.tsx +53 -0
- package/src/components/ui/resizable.tsx +61 -0
- package/src/components/ui/scroll-area.tsx +56 -0
- package/src/components/ui/select.tsx +179 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/slider.tsx +58 -0
- package/src/components/ui/switch.tsx +22 -0
- package/src/components/ui/table.tsx +90 -0
- package/src/components/ui/textarea.tsx +23 -0
- package/src/components/ui/tooltip.tsx +54 -0
- package/src/components/ui/tree-view.tsx +574 -0
- package/src/contexts/AgentToolCallbacksContext.tsx +31 -0
- package/src/contexts/ApiContext.tsx +51 -0
- package/src/contexts/FlowDataContext.tsx +21 -0
- package/src/contexts/NodeRegistryContext.tsx +54 -0
- package/src/contexts/PluginRegistryContext.tsx +182 -0
- package/src/contexts/ThemeProvider.tsx +106 -0
- package/src/contexts/ValidationContext.tsx +122 -0
- package/src/demo/DemoInvect.tsx +42 -0
- package/src/demo/FlowViewer.tsx +294 -0
- package/src/demo/demo-api-client.ts +246 -0
- package/src/demo/index.ts +28 -0
- package/src/demo/sample-data.ts +1980 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-document-title.ts +8 -0
- package/src/hooks/use-flow-data.ts +144 -0
- package/src/hooks/use-invect-portal-class.ts +27 -0
- package/src/hooks/useFlowEditorStore.ts +2 -0
- package/src/index.ts +70 -0
- package/src/lib/utils.ts +6 -0
- package/src/prettier.d.ts +13 -0
- package/src/routes/all-flow-runs.tsx +27 -0
- package/src/routes/credentials.tsx +362 -0
- package/src/routes/flow-route-layout.tsx +113 -0
- package/src/routes/flow-runs.tsx +22 -0
- package/src/routes/flow.tsx +22 -0
- package/src/routes/home.tsx +282 -0
- package/src/services/index.ts +6 -0
- package/src/stores/executionViewStore.ts +211 -0
- package/src/stores/flow-editor.store.ts +738 -0
- package/src/stores/flowEditorStore.ts +2 -0
- package/src/stores/index.ts +10 -0
- package/src/stores/uiStore.ts +189 -0
- package/src/types/agent-tools.types.ts +64 -0
- package/src/types/index.ts +5 -0
- package/src/types/node-definition.types.ts +104 -0
- package/src/types/plugin.types.ts +123 -0
- package/src/utils/credentialBranding.ts +116 -0
- package/src/utils/credentialFiltering.ts +68 -0
- package/src/utils/flowTransformations.ts +137 -0
- package/src/utils/layoutUtils.ts +127 -0
- package/src/utils/nodeReferenceUtils.ts +135 -0
- package/src/vendor.d.ts +7 -0
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
import React, { useState, useMemo } from 'react';
|
|
2
|
+
import { Link, useNavigate } from 'react-router';
|
|
3
|
+
import { useFlows } from '../../api/flows.api';
|
|
4
|
+
import { useListFlowRuns } from '../../api/executions.api';
|
|
5
|
+
import { Flow, FlowRun } from '@invect/core/types';
|
|
6
|
+
import {
|
|
7
|
+
CheckCircle,
|
|
8
|
+
XCircle,
|
|
9
|
+
Loader2,
|
|
10
|
+
Clock,
|
|
11
|
+
AlertCircle,
|
|
12
|
+
Eye,
|
|
13
|
+
Pause,
|
|
14
|
+
Calendar,
|
|
15
|
+
X,
|
|
16
|
+
ChevronLeft,
|
|
17
|
+
ChevronRight,
|
|
18
|
+
ChevronsLeft,
|
|
19
|
+
ChevronsRight,
|
|
20
|
+
Copy,
|
|
21
|
+
ChevronUp,
|
|
22
|
+
ChevronDown,
|
|
23
|
+
Play,
|
|
24
|
+
Search,
|
|
25
|
+
} from 'lucide-react';
|
|
26
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/table';
|
|
27
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';
|
|
28
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip';
|
|
29
|
+
import { Badge } from '../ui/badge';
|
|
30
|
+
import { Button } from '../ui/button';
|
|
31
|
+
import { Card, CardContent } from '../ui/card';
|
|
32
|
+
import { InvectLoader } from '../shared/InvectLoader';
|
|
33
|
+
|
|
34
|
+
// Execution status constants with proper typing
|
|
35
|
+
const EXECUTION_STATUSES = [
|
|
36
|
+
'PENDING',
|
|
37
|
+
'RUNNING',
|
|
38
|
+
'SUCCESS',
|
|
39
|
+
'FAILED',
|
|
40
|
+
'PAUSED',
|
|
41
|
+
'CANCELLED',
|
|
42
|
+
'PAUSED_FOR_BATCH',
|
|
43
|
+
] as const;
|
|
44
|
+
|
|
45
|
+
type ExecutionStatus = (typeof EXECUTION_STATUSES)[number];
|
|
46
|
+
|
|
47
|
+
// Helper function to format dates as "2:36pm" and "7 Jul 25" on separate lines
|
|
48
|
+
function formatExecutionDate(dateString: string): { time: string; date: string } {
|
|
49
|
+
try {
|
|
50
|
+
const date = new Date(dateString);
|
|
51
|
+
const time = date
|
|
52
|
+
.toLocaleTimeString('en-US', {
|
|
53
|
+
hour: 'numeric',
|
|
54
|
+
minute: '2-digit',
|
|
55
|
+
hour12: true,
|
|
56
|
+
})
|
|
57
|
+
.toLowerCase();
|
|
58
|
+
|
|
59
|
+
// Format as "7 Jul 25"
|
|
60
|
+
const day = date.getDate();
|
|
61
|
+
const month = date.toLocaleDateString('en-US', { month: 'short' });
|
|
62
|
+
const year = date.getFullYear().toString().slice(-2);
|
|
63
|
+
const dateStr = `${day} ${month} ${year}`;
|
|
64
|
+
|
|
65
|
+
return { time, date: dateStr };
|
|
66
|
+
} catch {
|
|
67
|
+
return { time: 'Unknown', date: 'time' };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Helper function to format duration
|
|
72
|
+
function formatDuration(startedAt: string, endedAt?: string): string {
|
|
73
|
+
try {
|
|
74
|
+
const start = new Date(startedAt);
|
|
75
|
+
const end = endedAt ? new Date(endedAt) : new Date();
|
|
76
|
+
const diffMs = end.getTime() - start.getTime();
|
|
77
|
+
|
|
78
|
+
const minutes = Math.floor(diffMs / (1000 * 60));
|
|
79
|
+
const hours = Math.floor(minutes / 60);
|
|
80
|
+
const days = Math.floor(hours / 24);
|
|
81
|
+
|
|
82
|
+
if (days > 0) {
|
|
83
|
+
return `${days}d ${hours % 24}h`;
|
|
84
|
+
}
|
|
85
|
+
if (hours > 0) {
|
|
86
|
+
return `${hours}h ${minutes % 60}m`;
|
|
87
|
+
}
|
|
88
|
+
if (minutes > 0) {
|
|
89
|
+
return `${minutes}m`;
|
|
90
|
+
}
|
|
91
|
+
return '< 1m';
|
|
92
|
+
} catch {
|
|
93
|
+
return 'Unknown';
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Helper function to format JSON for display
|
|
98
|
+
function formatJsonPreview(inputData: unknown): string {
|
|
99
|
+
let data = inputData;
|
|
100
|
+
if (!data) {
|
|
101
|
+
return '-';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
if (typeof data === 'string') {
|
|
106
|
+
// Try to parse if it's a JSON string
|
|
107
|
+
try {
|
|
108
|
+
const parsed = JSON.parse(data);
|
|
109
|
+
data = parsed;
|
|
110
|
+
} catch {
|
|
111
|
+
// If not valid JSON, truncate the string
|
|
112
|
+
const str = data as string;
|
|
113
|
+
return str.length > 100 ? `${str.substring(0, 100)}...` : str;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (typeof data === 'object') {
|
|
118
|
+
const jsonString = JSON.stringify(data, null, 0);
|
|
119
|
+
return jsonString.length > 100 ? `${jsonString.substring(0, 100)}...` : jsonString;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return String(data);
|
|
123
|
+
} catch {
|
|
124
|
+
return 'Invalid data';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Helper function to copy text to clipboard
|
|
129
|
+
async function copyToClipboard(text: string): Promise<void> {
|
|
130
|
+
try {
|
|
131
|
+
await navigator.clipboard.writeText(text);
|
|
132
|
+
} catch (err) {
|
|
133
|
+
console.warn('Could not copy text to clipboard:', err);
|
|
134
|
+
throw new Error('Copy to clipboard failed');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Tooltip wrapper component with copy functionality
|
|
139
|
+
const CopyableTooltip: React.FC<{
|
|
140
|
+
content: string;
|
|
141
|
+
children: React.ReactNode;
|
|
142
|
+
}> = ({ content, children }) => {
|
|
143
|
+
const [copied, setCopied] = useState(false);
|
|
144
|
+
|
|
145
|
+
const handleCopy = async (e: React.MouseEvent) => {
|
|
146
|
+
e.stopPropagation();
|
|
147
|
+
await copyToClipboard(content);
|
|
148
|
+
setCopied(true);
|
|
149
|
+
setTimeout(() => setCopied(false), 400); // Reset after 800ms for quicker feedback
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
if (!content || content === '-') {
|
|
153
|
+
return <>{children}</>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<TooltipProvider>
|
|
158
|
+
<Tooltip>
|
|
159
|
+
<TooltipTrigger asChild>
|
|
160
|
+
<div className="cursor-pointer">{children}</div>
|
|
161
|
+
</TooltipTrigger>
|
|
162
|
+
<TooltipContent className="relative max-w-md overflow-auto max-h-60 min-h-[3rem] pb-12">
|
|
163
|
+
<button
|
|
164
|
+
onClick={handleCopy}
|
|
165
|
+
className={`fixed bottom-2 right-4 p-2 cursor-pointer rounded-md transition-all duration-200 z-50 shadow-lg border ${
|
|
166
|
+
copied
|
|
167
|
+
? 'bg-primary text-primary-foreground border-primary scale-110'
|
|
168
|
+
: 'bg-card text-muted-foreground border-border hover:bg-muted hover:border-muted-foreground hover:shadow-xl'
|
|
169
|
+
}`}
|
|
170
|
+
title={copied ? 'Copied!' : 'Copy to clipboard'}
|
|
171
|
+
>
|
|
172
|
+
<Copy className="w-4 h-4" />
|
|
173
|
+
</button>
|
|
174
|
+
<pre className="font-mono text-xs break-words whitespace-pre-wrap">{content}</pre>
|
|
175
|
+
</TooltipContent>
|
|
176
|
+
</Tooltip>
|
|
177
|
+
</TooltipProvider>
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Status badge component
|
|
182
|
+
const StatusBadge: React.FC<{ status: ExecutionStatus }> = ({ status }) => {
|
|
183
|
+
const getStatusConfig = () => {
|
|
184
|
+
switch (status) {
|
|
185
|
+
case 'SUCCESS':
|
|
186
|
+
return {
|
|
187
|
+
icon: <CheckCircle className="w-4 h-4" />,
|
|
188
|
+
variant: 'secondary' as const,
|
|
189
|
+
className:
|
|
190
|
+
'text-green-700 bg-green-50 border-green-200 dark:text-green-300 dark:bg-green-900/30 dark:border-green-800',
|
|
191
|
+
};
|
|
192
|
+
case 'FAILED':
|
|
193
|
+
return {
|
|
194
|
+
icon: <XCircle className="w-4 h-4" />,
|
|
195
|
+
variant: 'destructive' as const,
|
|
196
|
+
className:
|
|
197
|
+
'text-red-700 bg-red-50 border-red-200 dark:text-red-300 dark:bg-red-900/30 dark:border-red-800',
|
|
198
|
+
};
|
|
199
|
+
case 'RUNNING':
|
|
200
|
+
return {
|
|
201
|
+
icon: <Loader2 className="w-4 h-4 animate-spin" />,
|
|
202
|
+
variant: 'default' as const,
|
|
203
|
+
className:
|
|
204
|
+
'text-blue-700 bg-blue-50 border-blue-200 dark:text-blue-300 dark:bg-blue-900/30 dark:border-blue-800',
|
|
205
|
+
};
|
|
206
|
+
case 'PENDING':
|
|
207
|
+
return {
|
|
208
|
+
icon: <Clock className="w-4 h-4" />,
|
|
209
|
+
variant: 'outline' as const,
|
|
210
|
+
className: 'text-muted-foreground bg-muted border-border',
|
|
211
|
+
};
|
|
212
|
+
case 'PAUSED':
|
|
213
|
+
return {
|
|
214
|
+
icon: <Pause className="w-4 h-4" />,
|
|
215
|
+
variant: 'outline' as const,
|
|
216
|
+
className:
|
|
217
|
+
'text-yellow-700 bg-yellow-50 border-yellow-200 dark:text-yellow-300 dark:bg-yellow-900/30 dark:border-yellow-800',
|
|
218
|
+
};
|
|
219
|
+
case 'PAUSED_FOR_BATCH':
|
|
220
|
+
return {
|
|
221
|
+
icon: <Loader2 className="w-4 h-4 animate-spin" />,
|
|
222
|
+
variant: 'default' as const,
|
|
223
|
+
className:
|
|
224
|
+
'text-purple-700 bg-purple-50 border-purple-200 dark:text-purple-300 dark:bg-purple-900/30 dark:border-purple-800',
|
|
225
|
+
};
|
|
226
|
+
case 'CANCELLED':
|
|
227
|
+
return {
|
|
228
|
+
icon: <X className="w-4 h-4" />,
|
|
229
|
+
variant: 'outline' as const,
|
|
230
|
+
className: 'text-muted-foreground bg-muted border-border',
|
|
231
|
+
};
|
|
232
|
+
default:
|
|
233
|
+
return {
|
|
234
|
+
icon: <AlertCircle className="w-4 h-4" />,
|
|
235
|
+
variant: 'outline' as const,
|
|
236
|
+
className: 'text-muted-foreground bg-muted border-border',
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const config = getStatusConfig();
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<Badge variant={config.variant} className={`${config.className} flex items-center gap-1`}>
|
|
245
|
+
{config.icon}
|
|
246
|
+
<span>{status}</span>
|
|
247
|
+
</Badge>
|
|
248
|
+
);
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
interface FlowRunsTableProps {
|
|
252
|
+
basePath?: string;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export const FlowRunsTable: React.FC<FlowRunsTableProps> = ({ basePath = '' }) => {
|
|
256
|
+
const navigate = useNavigate();
|
|
257
|
+
const [flowSearch, setFlowSearch] = useState('');
|
|
258
|
+
const [statusFilter, setStatusFilter] = useState<string | undefined>(undefined);
|
|
259
|
+
const [page, setPage] = useState(1);
|
|
260
|
+
const [pageSize, setPageSize] = useState(10);
|
|
261
|
+
const [sortBy, setSortBy] = useState<string>('startedAt');
|
|
262
|
+
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
|
|
263
|
+
|
|
264
|
+
// Get flows for name lookup
|
|
265
|
+
const { data: flowsResponse, isLoading: flowsLoading } = useFlows();
|
|
266
|
+
const flows = flowsResponse?.data ?? [];
|
|
267
|
+
|
|
268
|
+
// Create flow lookup map
|
|
269
|
+
const flowMap = useMemo(() => {
|
|
270
|
+
const map = new Map<string, { name: string }>();
|
|
271
|
+
flows.forEach((flow: Flow) => {
|
|
272
|
+
map.set(flow.id, { name: flow.name });
|
|
273
|
+
});
|
|
274
|
+
return map;
|
|
275
|
+
}, [flows]);
|
|
276
|
+
|
|
277
|
+
// Resolve flowFilter: find the flow whose name matches the search
|
|
278
|
+
const flowFilter = useMemo(() => {
|
|
279
|
+
const q = flowSearch.trim().toLowerCase();
|
|
280
|
+
if (!q) {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
const match = flows.find((f: Flow) => f.name.toLowerCase().includes(q));
|
|
284
|
+
return match?.id;
|
|
285
|
+
}, [flowSearch, flows]);
|
|
286
|
+
|
|
287
|
+
// When search changes, reset page
|
|
288
|
+
const handleFlowSearchChange = (value: string) => {
|
|
289
|
+
setFlowSearch(value);
|
|
290
|
+
setPage(1);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// Get all executions with filters, pagination, and sorting applied
|
|
294
|
+
const {
|
|
295
|
+
data: executionsResponse,
|
|
296
|
+
isLoading: executionsLoading,
|
|
297
|
+
error: executionsError,
|
|
298
|
+
} = useListFlowRuns(flowFilter, statusFilter, page, pageSize, sortBy, sortOrder);
|
|
299
|
+
|
|
300
|
+
// Extract data and pagination from response
|
|
301
|
+
const executions = executionsResponse?.data ?? [];
|
|
302
|
+
const pagination = executionsResponse?.pagination;
|
|
303
|
+
const hasPreviousPage = pagination ? pagination.page > 1 : false;
|
|
304
|
+
const hasNextPage = pagination ? pagination.page < pagination.totalPages : false;
|
|
305
|
+
|
|
306
|
+
const clearFilters = () => {
|
|
307
|
+
setFlowSearch('');
|
|
308
|
+
setStatusFilter(undefined);
|
|
309
|
+
setPage(1);
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const hasActiveFilters = flowSearch.trim() || statusFilter;
|
|
313
|
+
|
|
314
|
+
const handleSort = (field: string) => {
|
|
315
|
+
// If clicking the same field, toggle order. Otherwise, default to desc for new fields.
|
|
316
|
+
if (sortBy === field) {
|
|
317
|
+
setSortOrder(sortOrder === 'desc' ? 'asc' : 'desc');
|
|
318
|
+
} else {
|
|
319
|
+
setSortBy(field);
|
|
320
|
+
setSortOrder('desc'); // Default to descending for new sort fields
|
|
321
|
+
}
|
|
322
|
+
setPage(1); // Reset to first page when sorting changes
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const getSortIcon = (field: string) => {
|
|
326
|
+
if (sortBy !== field) {
|
|
327
|
+
return (
|
|
328
|
+
<ChevronDown className="w-4 h-4 text-muted-foreground transition-opacity opacity-0 group-hover:opacity-50" />
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
return sortOrder === 'desc' ? (
|
|
332
|
+
<ChevronDown className="w-4 h-4 text-primary" />
|
|
333
|
+
) : (
|
|
334
|
+
<ChevronUp className="w-4 h-4 text-primary" />
|
|
335
|
+
);
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const SortableHeader: React.FC<{
|
|
339
|
+
field: string;
|
|
340
|
+
children: React.ReactNode;
|
|
341
|
+
className?: string;
|
|
342
|
+
}> = ({ field, children, className = '' }) => (
|
|
343
|
+
<TableHead
|
|
344
|
+
className={`cursor-pointer select-none hover:bg-muted group transition-colors ${className}`}
|
|
345
|
+
onClick={() => handleSort(field)}
|
|
346
|
+
title={`Click to sort by ${children} ${
|
|
347
|
+
sortBy === field ? (sortOrder === 'desc' ? '(ascending)' : '(descending)') : ''
|
|
348
|
+
}`}
|
|
349
|
+
>
|
|
350
|
+
<div className="flex items-center gap-1">
|
|
351
|
+
{children}
|
|
352
|
+
{getSortIcon(field)}
|
|
353
|
+
</div>
|
|
354
|
+
</TableHead>
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
if (executionsLoading || flowsLoading) {
|
|
358
|
+
return (
|
|
359
|
+
<div className="flex items-center justify-center py-12">
|
|
360
|
+
<InvectLoader iconClassName="h-14" label="Loading flow runs..." />
|
|
361
|
+
</div>
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (executionsError) {
|
|
366
|
+
return (
|
|
367
|
+
<div className="p-4 border border-red-200 dark:border-red-800 rounded-lg bg-red-50 dark:bg-red-900/30">
|
|
368
|
+
<div className="text-red-800 dark:text-red-300">
|
|
369
|
+
<strong>Error loading flow runs:</strong>{' '}
|
|
370
|
+
{executionsError instanceof Error
|
|
371
|
+
? executionsError.message
|
|
372
|
+
: 'Failed to load executions from the server'}
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return (
|
|
379
|
+
<div className="space-y-6">
|
|
380
|
+
{/* Header and Filters */}
|
|
381
|
+
<div className="flex items-center gap-2">
|
|
382
|
+
{/* Flow search */}
|
|
383
|
+
<div className="relative flex-1 max-w-sm">
|
|
384
|
+
<Search className="absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 pointer-events-none text-muted-foreground" />
|
|
385
|
+
<input
|
|
386
|
+
type="text"
|
|
387
|
+
value={flowSearch}
|
|
388
|
+
onChange={(e) => handleFlowSearchChange(e.target.value)}
|
|
389
|
+
placeholder="Search by flow name…"
|
|
390
|
+
className="w-full rounded-lg border border-border bg-transparent py-2 pl-9 pr-3 text-sm outline-none placeholder:text-muted-foreground focus:border-primary/50"
|
|
391
|
+
/>
|
|
392
|
+
</div>
|
|
393
|
+
|
|
394
|
+
{/* Status Filter */}
|
|
395
|
+
<Select
|
|
396
|
+
value={statusFilter || 'ALL'}
|
|
397
|
+
onValueChange={(value) => {
|
|
398
|
+
setStatusFilter(value === 'ALL' ? undefined : value);
|
|
399
|
+
setPage(1);
|
|
400
|
+
}}
|
|
401
|
+
>
|
|
402
|
+
<SelectTrigger className="w-40 bg-transparent">
|
|
403
|
+
<SelectValue placeholder="All statuses" />
|
|
404
|
+
</SelectTrigger>
|
|
405
|
+
<SelectContent>
|
|
406
|
+
<SelectItem value="ALL">All statuses</SelectItem>
|
|
407
|
+
{EXECUTION_STATUSES.map((status) => (
|
|
408
|
+
<SelectItem key={status} value={status}>
|
|
409
|
+
{status}
|
|
410
|
+
</SelectItem>
|
|
411
|
+
))}
|
|
412
|
+
</SelectContent>
|
|
413
|
+
</Select>
|
|
414
|
+
|
|
415
|
+
{/* Clear Filters */}
|
|
416
|
+
{hasActiveFilters && (
|
|
417
|
+
<Button variant="outline" size="sm" onClick={clearFilters}>
|
|
418
|
+
<X className="w-4 h-4 mr-2" />
|
|
419
|
+
Clear
|
|
420
|
+
</Button>
|
|
421
|
+
)}
|
|
422
|
+
</div>
|
|
423
|
+
|
|
424
|
+
{/* Flow Runs Table */}
|
|
425
|
+
{executions.length === 0 ? (
|
|
426
|
+
<Card className="border-dashed">
|
|
427
|
+
<CardContent className="flex flex-col items-center py-14 text-center">
|
|
428
|
+
<div className="flex items-center justify-center w-14 h-14 mb-4 rounded-xl bg-muted/60">
|
|
429
|
+
{hasActiveFilters ? (
|
|
430
|
+
<Calendar className="w-7 h-7 text-muted-foreground" />
|
|
431
|
+
) : (
|
|
432
|
+
<Play className="w-7 h-7 text-muted-foreground" />
|
|
433
|
+
)}
|
|
434
|
+
</div>
|
|
435
|
+
<h3 className="text-base font-semibold text-foreground mb-1">
|
|
436
|
+
{hasActiveFilters ? 'No flow runs match your filters' : 'No flow runs yet'}
|
|
437
|
+
</h3>
|
|
438
|
+
<p className="max-w-sm mx-auto text-sm text-muted-foreground mb-5">
|
|
439
|
+
{hasActiveFilters
|
|
440
|
+
? 'Try adjusting your filters to see more results.'
|
|
441
|
+
: 'Run a workflow from the editor to see execution history here.'}
|
|
442
|
+
</p>
|
|
443
|
+
<div className="flex items-center gap-2">
|
|
444
|
+
{hasActiveFilters ? (
|
|
445
|
+
<Button variant="outline" size="sm" onClick={clearFilters}>
|
|
446
|
+
<X className="h-3.5 w-3.5 mr-1.5" />
|
|
447
|
+
Clear filters
|
|
448
|
+
</Button>
|
|
449
|
+
) : (
|
|
450
|
+
<Button size="sm" onClick={() => navigate(basePath || '/')}>
|
|
451
|
+
<Play className="h-3.5 w-3.5 mr-1.5" />
|
|
452
|
+
Go to Flows
|
|
453
|
+
</Button>
|
|
454
|
+
)}
|
|
455
|
+
</div>
|
|
456
|
+
</CardContent>
|
|
457
|
+
</Card>
|
|
458
|
+
) : (
|
|
459
|
+
<div className="overflow-hidden bg-card border border-border rounded-lg">
|
|
460
|
+
<Table>
|
|
461
|
+
<TableHeader>
|
|
462
|
+
<TableRow>
|
|
463
|
+
<TableHead className="w-[200px]">Flow</TableHead>
|
|
464
|
+
<TableHead className="w-[120px]">Status</TableHead>
|
|
465
|
+
<SortableHeader field="startedAt" className="w-[120px]">
|
|
466
|
+
Last ran
|
|
467
|
+
</SortableHeader>
|
|
468
|
+
<SortableHeader field="duration" className="w-[80px]">
|
|
469
|
+
Duration
|
|
470
|
+
</SortableHeader>
|
|
471
|
+
<SortableHeader field="inputs" className="w-[200px]">
|
|
472
|
+
Input
|
|
473
|
+
</SortableHeader>
|
|
474
|
+
<SortableHeader field="outputs" className="w-[200px]">
|
|
475
|
+
Output
|
|
476
|
+
</SortableHeader>
|
|
477
|
+
<TableHead className="w-[100px]">Actions</TableHead>
|
|
478
|
+
</TableRow>
|
|
479
|
+
</TableHeader>
|
|
480
|
+
<TableBody>
|
|
481
|
+
{executions.map((execution: FlowRun) => {
|
|
482
|
+
const flow = flowMap.get(execution.flowId);
|
|
483
|
+
const flowName = flow?.name || `Flow ${execution.flowId}`;
|
|
484
|
+
|
|
485
|
+
return (
|
|
486
|
+
<TableRow key={execution.id}>
|
|
487
|
+
<TableCell className="font-medium">
|
|
488
|
+
<div className="truncate" title={flowName}>
|
|
489
|
+
{flowName}
|
|
490
|
+
</div>
|
|
491
|
+
</TableCell>
|
|
492
|
+
<TableCell>
|
|
493
|
+
<StatusBadge status={execution.status as ExecutionStatus} />
|
|
494
|
+
</TableCell>
|
|
495
|
+
<TableCell>
|
|
496
|
+
<div className="font-mono text-sm">
|
|
497
|
+
<div className="text-xs text-muted-foreground">
|
|
498
|
+
{formatExecutionDate(String(execution.startedAt)).time}
|
|
499
|
+
</div>
|
|
500
|
+
<div className="text-xs">
|
|
501
|
+
{formatExecutionDate(String(execution.startedAt)).date}
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
</TableCell>
|
|
505
|
+
<TableCell>
|
|
506
|
+
<div className="text-sm">
|
|
507
|
+
{formatDuration(
|
|
508
|
+
String(execution.startedAt),
|
|
509
|
+
execution.completedAt ? String(execution.completedAt) : undefined,
|
|
510
|
+
)}
|
|
511
|
+
</div>
|
|
512
|
+
</TableCell>
|
|
513
|
+
<TableCell>
|
|
514
|
+
<CopyableTooltip
|
|
515
|
+
content={execution.inputs ? JSON.stringify(execution.inputs, null, 2) : ''}
|
|
516
|
+
>
|
|
517
|
+
<div className="max-w-[200px] line-clamp-2 text-xs font-mono text-muted-foreground">
|
|
518
|
+
{formatJsonPreview(execution.inputs)}
|
|
519
|
+
</div>
|
|
520
|
+
</CopyableTooltip>
|
|
521
|
+
</TableCell>
|
|
522
|
+
<TableCell>
|
|
523
|
+
<CopyableTooltip
|
|
524
|
+
content={
|
|
525
|
+
execution.outputs ? JSON.stringify(execution.outputs, null, 2) : ''
|
|
526
|
+
}
|
|
527
|
+
>
|
|
528
|
+
<div className="max-w-[200px] line-clamp-2 text-xs font-mono text-muted-foreground">
|
|
529
|
+
{formatJsonPreview(execution.outputs)}
|
|
530
|
+
</div>
|
|
531
|
+
</CopyableTooltip>
|
|
532
|
+
</TableCell>
|
|
533
|
+
<TableCell>
|
|
534
|
+
<Button variant="outline" size="sm" asChild>
|
|
535
|
+
<Link to={`${basePath}/flow/${execution.flowId}/run/${execution.id}`}>
|
|
536
|
+
<Eye className="w-4 h-4 mr-1" />
|
|
537
|
+
View
|
|
538
|
+
</Link>
|
|
539
|
+
</Button>
|
|
540
|
+
</TableCell>
|
|
541
|
+
</TableRow>
|
|
542
|
+
);
|
|
543
|
+
})}
|
|
544
|
+
</TableBody>
|
|
545
|
+
</Table>
|
|
546
|
+
</div>
|
|
547
|
+
)}
|
|
548
|
+
|
|
549
|
+
{/* Pagination Controls */}
|
|
550
|
+
{pagination && (
|
|
551
|
+
<div className="flex items-center justify-between py-4">
|
|
552
|
+
<div className="text-sm text-muted-foreground">
|
|
553
|
+
Showing {(pagination.page - 1) * pagination.limit + 1} to{' '}
|
|
554
|
+
{pagination.page * pagination.limit} of {pagination.totalPages * pagination.limit}{' '}
|
|
555
|
+
results
|
|
556
|
+
</div>
|
|
557
|
+
|
|
558
|
+
<div className="flex items-center gap-2">
|
|
559
|
+
{/* Page Size Selector */}
|
|
560
|
+
<div className="flex items-center gap-2">
|
|
561
|
+
<span className="text-sm text-muted-foreground">Rows per page:</span>
|
|
562
|
+
<Select
|
|
563
|
+
value={pageSize.toString()}
|
|
564
|
+
onValueChange={(value) => {
|
|
565
|
+
setPageSize(Number(value));
|
|
566
|
+
setPage(1); // Reset to first page when changing page size
|
|
567
|
+
}}
|
|
568
|
+
>
|
|
569
|
+
<SelectTrigger className="w-20 bg-card">
|
|
570
|
+
<SelectValue />
|
|
571
|
+
</SelectTrigger>
|
|
572
|
+
<SelectContent>
|
|
573
|
+
<SelectItem value="5">5</SelectItem>
|
|
574
|
+
<SelectItem value="10">10</SelectItem>
|
|
575
|
+
<SelectItem value="20">20</SelectItem>
|
|
576
|
+
<SelectItem value="50">50</SelectItem>
|
|
577
|
+
<SelectItem value="100">100</SelectItem>
|
|
578
|
+
</SelectContent>
|
|
579
|
+
</Select>
|
|
580
|
+
</div>
|
|
581
|
+
|
|
582
|
+
{/* Page Navigation */}
|
|
583
|
+
<div className="flex items-center gap-1">
|
|
584
|
+
<Button
|
|
585
|
+
variant="outline"
|
|
586
|
+
size="sm"
|
|
587
|
+
onClick={() => setPage(1)}
|
|
588
|
+
disabled={!hasPreviousPage}
|
|
589
|
+
>
|
|
590
|
+
<ChevronsLeft className="w-4 h-4" />
|
|
591
|
+
</Button>
|
|
592
|
+
|
|
593
|
+
<Button
|
|
594
|
+
variant="outline"
|
|
595
|
+
size="sm"
|
|
596
|
+
onClick={() => setPage(pagination.page - 1)}
|
|
597
|
+
disabled={!hasPreviousPage}
|
|
598
|
+
>
|
|
599
|
+
<ChevronLeft className="w-4 h-4" />
|
|
600
|
+
</Button>
|
|
601
|
+
|
|
602
|
+
<div className="flex items-center gap-1 px-2">
|
|
603
|
+
<span className="text-sm">
|
|
604
|
+
Page {pagination.page} of {pagination.totalPages}
|
|
605
|
+
</span>
|
|
606
|
+
</div>
|
|
607
|
+
|
|
608
|
+
<Button
|
|
609
|
+
variant="outline"
|
|
610
|
+
size="sm"
|
|
611
|
+
onClick={() => setPage(pagination.page + 1)}
|
|
612
|
+
disabled={!hasNextPage}
|
|
613
|
+
>
|
|
614
|
+
<ChevronRight className="w-4 h-4" />
|
|
615
|
+
</Button>
|
|
616
|
+
|
|
617
|
+
<Button
|
|
618
|
+
variant="outline"
|
|
619
|
+
size="sm"
|
|
620
|
+
onClick={() => setPage(pagination.totalPages)}
|
|
621
|
+
disabled={!hasNextPage}
|
|
622
|
+
>
|
|
623
|
+
<ChevronsRight className="w-4 h-4" />
|
|
624
|
+
</Button>
|
|
625
|
+
</div>
|
|
626
|
+
</div>
|
|
627
|
+
</div>
|
|
628
|
+
)}
|
|
629
|
+
</div>
|
|
630
|
+
);
|
|
631
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FlowRunsTable } from './FlowRunsTable';
|