From 37786d371e17d35e0764e1b5cd519d873d90d97b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Jun 2025 11:49:05 -0700 Subject: [PATCH 01/20] added qa to list of reserved subdomains --- apps/sim/app/api/chat/subdomains/validate/route.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sim/app/api/chat/subdomains/validate/route.ts b/apps/sim/app/api/chat/subdomains/validate/route.ts index 77467042626..1b01b44024d 100644 --- a/apps/sim/app/api/chat/subdomains/validate/route.ts +++ b/apps/sim/app/api/chat/subdomains/validate/route.ts @@ -44,6 +44,7 @@ export async function GET(request: Request) { 'help', 'support', 'admin', + 'qa', ] if (reservedSubdomains.includes(subdomain)) { return NextResponse.json( From 09dc3848b8f6ceac8f1b49834ac3f5ab020120a7 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Tue, 24 Jun 2025 15:39:38 +0000 Subject: [PATCH 02/20] refactor: get started with workspace id in url --- .../components/social-login-buttons.tsx | 2 +- apps/sim/app/(auth)/login/login-form.test.tsx | 2 +- apps/sim/app/(auth)/login/login-form.tsx | 6 +- apps/sim/app/(auth)/signup/signup-form.tsx | 2 +- .../sim/app/(auth)/verify/use-verification.ts | 4 +- .../(landing)/components/sections/footer.tsx | 2 +- .../(landing)/components/sections/hero.tsx | 2 +- .../app/api/marketplace/workflows/route.ts | 2 +- apps/sim/app/invite/[id]/invite.tsx | 4 +- .../app/invite/invite-error/invite-error.tsx | 2 +- .../code-prompt-bar/code-prompt-bar.tsx | 0 .../components/chat-deploy/chat-deploy.tsx | 2 +- .../components/deploy-form/deploy-form.tsx | 0 .../components/api-endpoint/api-endpoint.tsx | 0 .../components/api-key/api-key.tsx | 0 .../deploy-status/deploy-status.tsx | 0 .../example-command/example-command.tsx | 0 .../deployment-info/deployment-info.tsx | 8 +- .../components/deploy-modal/deploy-modal.tsx | 6 +- .../components/deployed-workflow-card.tsx | 2 +- .../components/deployed-workflow-modal.tsx | 0 .../deployment-controls.test.ts | 0 .../deployment-controls.tsx | 0 .../history-dropdown-item.tsx | 0 .../marketplace-modal/marketplace-modal.tsx | 2 +- .../notification-dropdown-item.tsx | 0 .../components/user-avatar/user-avatar.tsx | 0 .../user-avatar-stack/user-avatar-stack.tsx | 0 .../control-bar/control-bar.test.ts | 0 .../components/control-bar/control-bar.tsx | 8 +- .../w/[id]/components/copilot/copilot.tsx | 0 .../w/[id]/components/error/index.tsx | 0 .../loop-node/components/loop-badges.test.tsx | 0 .../loop-node/components/loop-badges.tsx | 0 .../[id]/components/loop-node/loop-config.ts | 0 .../components/loop-node/loop-node.test.tsx | 0 .../w/[id]/components/loop-node/loop-node.tsx | 0 .../notifications/notifications.tsx | 0 .../components/panel/components/chat/chat.tsx | 0 .../components/chat-message/chat-message.tsx | 0 .../chat/components/chat-modal/chat-modal.tsx | 4 +- .../output-select/output-select.tsx | 0 .../components/audio-player/audio-player.tsx | 0 .../console-entry/console-entry.tsx | 0 .../components/json-view/json-view.tsx | 0 .../panel/components/console/console.tsx | 0 .../panel/components/variables/variables.tsx | 0 .../w/[id]/components/panel/panel.tsx | 2 +- .../components/parallel-badges.tsx | 0 .../parallel-node/parallel-config.ts | 0 .../parallel-node/parallel-node.test.tsx | 0 .../parallel-node/parallel-node.tsx | 0 .../skeleton-loading/skeleton-loading.tsx | 0 .../toolbar-block/toolbar-block.tsx | 0 .../toolbar-loop-block/toolbar-loop-block.tsx | 0 .../toolbar-parallel-block.tsx | 0 .../components/toolbar-tabs/toolbar-tabs.tsx | 0 .../w/[id]/components/toolbar/toolbar.tsx | 2 +- .../components/action-bar/action-bar.tsx | 0 .../connection-blocks/connection-blocks.tsx | 5 +- .../channel-selector-input.tsx | 0 .../components/slack-channel-selector.tsx | 0 .../sub-block/components/checkbox-list.tsx | 0 .../components/sub-block/components/code.tsx | 2 +- .../sub-block/components/condition-input.tsx | 0 .../components/oauth-required-modal.tsx | 0 .../credential-selector.tsx | 0 .../sub-block/components/date-input.tsx | 0 .../document-selector/document-selector.tsx | 0 .../sub-block/components/dropdown.tsx | 0 .../sub-block/components/eval-input.tsx | 0 .../components/confluence-file-selector.tsx | 0 .../components/discord-channel-selector.tsx | 0 .../components/google-calendar-selector.tsx | 0 .../components/google-drive-picker.tsx | 0 .../components/jira-issue-selector.tsx | 0 .../components/microsoft-file-selector.tsx | 0 .../components/teams-message-selector.tsx | 0 .../file-selector/file-selector-input.tsx | 0 .../sub-block/components/file-upload.tsx | 0 .../components/folder-selector-input.tsx | 0 .../folder-selector/folder-selector.tsx | 2 +- .../knowledge-base-selector.tsx | 0 .../sub-block/components/long-input.tsx | 0 .../components/discord-server-selector.tsx | 0 .../components/jira-project-selector.tsx | 0 .../components/linear-project-selector.tsx | 0 .../components/linear-team-selector.tsx | 0 .../project-selector-input.tsx | 0 .../response/components/property-renderer.tsx | 0 .../response/components/value-input.tsx | 0 .../components/response/response-format.tsx | 0 .../schedule/components/schedule-modal.tsx | 0 .../components/schedule/schedule-config.tsx | 0 .../sub-block/components/short-input.tsx | 0 .../sub-block/components/slider-input.tsx | 0 .../components/starter/input-format.tsx | 0 .../sub-block/components/switch.tsx | 0 .../components/sub-block/components/table.tsx | 0 .../sub-block/components/time-input.tsx | 0 .../components/code-editor/code-editor.tsx | 0 .../custom-tool-modal/custom-tool-modal.tsx | 2 +- .../components/tool-command/tool-command.tsx | 0 .../components/tool-input/tool-input.tsx | 0 .../webhook/components/providers/airtable.tsx | 0 .../webhook/components/providers/discord.tsx | 0 .../webhook/components/providers/generic.tsx | 0 .../webhook/components/providers/github.tsx | 0 .../webhook/components/providers/gmail.tsx | 2 +- .../webhook/components/providers/slack.tsx | 2 +- .../webhook/components/providers/stripe.tsx | 0 .../webhook/components/providers/telegram.tsx | 0 .../webhook/components/providers/whatsapp.tsx | 0 .../webhook/components/ui/config-field.tsx | 0 .../webhook/components/ui/config-section.tsx | 0 .../webhook/components/ui/confirmation.tsx | 0 .../webhook/components/ui/copyable.tsx | 0 .../components/ui/instructions-section.tsx | 0 .../webhook/components/ui/test-result.tsx | 0 .../components/ui/webhook-config-field.tsx | 0 .../webhook/components/ui/webhook-footer.tsx | 0 .../webhook/components/ui/webhook-url.tsx | 0 .../webhook/components/webhook-modal.tsx | 0 .../sub-block/components/webhook/webhook.tsx | 0 .../sub-block/hooks/use-sub-block-value.ts | 0 .../components/sub-block/sub-block.tsx | 0 .../workflow-block/workflow-block.tsx | 2 +- .../workflow-edge/workflow-edge.tsx | 0 .../w/[id]/hooks/use-block-connections.ts | 0 .../w/[id]/hooks/use-code-generation.ts | 0 .../[workspace]}/w/[id]/hooks/use-presence.ts | 0 .../w/[id]/hooks/use-workflow-execution.ts | 0 .../[workspace]}/w/[id]/layout.tsx | 0 .../[workspace]}/w/[id]/page.tsx | 0 .../[workspace]}/w/[id]/utils.ts | 0 .../[workspace]}/w/[id]/workflow.tsx | 12 +- .../w/components/providers/providers.tsx | 0 .../w/components/providers/theme-provider.tsx | 0 .../workspace-permissions-provider.tsx | 0 .../components/create-menu/create-menu.tsx | 0 .../folder-context-menu.tsx | 0 .../folder-tree/components/folder-item.tsx | 0 .../folder-tree/components/workflow-item.tsx | 7 +- .../components/folder-tree/folder-tree.tsx | 12 +- .../components/help-form/help-form.tsx | 0 .../components/help-modal/help-modal.tsx | 0 .../components/invite-modal/invite-modal.tsx | 2 +- .../invites-sent/invites-sent.tsx | 0 .../components/nav-section/nav-section.tsx | 0 .../components/account/account.tsx | 0 .../components/api-keys/api-keys.tsx | 0 .../components/credentials/credentials.tsx | 4 +- .../components/environment/environment.tsx | 0 .../components/general/general.tsx | 0 .../components/privacy/privacy.tsx | 0 .../settings-navigation.tsx | 0 .../components/team-seats-dialog.tsx | 0 .../components/subscription/subscription.tsx | 0 .../team-management/team-management.tsx | 0 .../settings-modal/settings-modal.tsx | 0 .../sidebar-control/sidebar-control.tsx | 0 .../workflow-list/workflow-list.tsx | 13 ++- .../workspace-header/workspace-header.tsx | 8 +- .../w/components/sidebar/sidebar.tsx | 21 ++-- .../workflow-preview/workflow-preview.tsx | 8 +- .../{ => workspace/[workspace]}/w/error.tsx | 0 .../[workspace]}/w/global-error.tsx | 0 .../w/hooks/use-keyboard-shortcuts.ts | 0 .../w/hooks/use-registry-loading.ts | 14 ++- .../create-chunk-modal/create-chunk-modal.tsx | 0 .../delete-chunk-modal/delete-chunk-modal.tsx | 0 .../components/document-loading.tsx | 0 .../edit-chunk-modal/edit-chunk-modal.tsx | 0 .../knowledge/[id]/[documentId]/document.tsx | 2 +- .../w/knowledge/[id]/[documentId]/page.tsx | 0 .../[workspace]}/w/knowledge/[id]/base.tsx | 18 +-- .../[id]/components/action-bar/action-bar.tsx | 0 .../knowledge-base-loading.tsx | 0 .../[workspace]}/w/knowledge/[id]/page.tsx | 0 .../base-overview/base-overview.tsx | 0 .../components/create-modal/create-modal.tsx | 2 +- .../empty-state-card/empty-state-card.tsx | 0 .../components/icons/document-icons.tsx | 0 .../knowledge-header/knowledge-header.tsx | 0 .../primary-button/primary-button.tsx | 0 .../components/search-input/search-input.tsx | 0 .../knowledge-base-card-skeleton.tsx | 0 .../components/skeletons/table-skeleton.tsx | 0 .../[workspace]}/w/knowledge/knowledge.tsx | 0 .../[workspace]}/w/knowledge/loading.tsx | 0 .../[workspace]}/w/knowledge/page.tsx | 0 .../{ => workspace/[workspace]}/w/layout.tsx | 0 .../components/control-bar/control-bar.tsx | 0 .../filters/components/filter-section.tsx | 0 .../components/filters/components/folder.tsx | 2 +- .../components/filters/components/level.tsx | 4 +- .../filters/components/timeline.tsx | 4 +- .../components/filters/components/trigger.tsx | 2 +- .../filters/components/workflow.tsx | 2 +- .../w/logs/components/filters/filters.tsx | 0 .../sidebar/components/markdown-renderer.tsx | 0 .../w/logs/components/sidebar/sidebar.tsx | 4 +- .../tool-calls/tool-calls-display.tsx | 0 .../trace-spans/trace-spans-display.tsx | 0 .../[workspace]}/w/logs/logs.tsx | 0 .../[workspace]}/w/logs/page.tsx | 0 .../[workspace]}/w/logs/stores/store.ts | 0 .../[workspace]}/w/logs/stores/types.ts | 0 .../[workspace]}/w/logs/utils/format-date.ts | 0 .../components/control-bar/control-bar.tsx | 0 .../marketplace/components/error-message.tsx | 0 .../w/marketplace/components/section.tsx | 0 .../components/toolbar/toolbar.tsx | 0 .../components/workflow-card-skeleton.tsx | 0 .../marketplace/components/workflow-card.tsx | 8 +- .../w/marketplace/constants/categories.tsx | 0 .../w/marketplace/marketplace.tsx | 0 .../[workspace]}/w/marketplace/page.tsx | 0 .../{ => workspace/[workspace]}/w/page.tsx | 7 +- apps/sim/app/workspace/page.tsx | 108 ++++++++++++++++++ apps/sim/components/ui/tag-dropdown.tsx | 5 +- apps/sim/lib/logs/trace-spans.ts | 2 +- apps/sim/middleware.ts | 24 +++- 223 files changed, 265 insertions(+), 111 deletions(-) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx (88%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx (96%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/control-bar.test.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/control-bar/control-bar.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/copilot/copilot.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/error/index.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/loop-node/components/loop-badges.test.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/loop-node/components/loop-badges.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/loop-node/loop-config.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/loop-node/loop-node.test.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/loop-node/loop-node.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/notifications/notifications.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/chat/chat.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx (97%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/console/components/json-view/json-view.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/console/console.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/components/variables/variables.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/panel/panel.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/parallel-node/components/parallel-badges.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/parallel-node/parallel-config.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/parallel-node/parallel-node.test.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/parallel-node/parallel-node.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/skeleton-loading/skeleton-loading.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/toolbar/toolbar.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/code.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/table.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx (97%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-block/workflow-block.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/components/workflow-edge/workflow-edge.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/hooks/use-block-connections.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/hooks/use-code-generation.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/hooks/use-presence.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/hooks/use-workflow-execution.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/layout.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/page.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/utils.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/[id]/workflow.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/providers/providers.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/providers/theme-provider.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/providers/workspace-permissions-provider.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/create-menu/create-menu.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/folder-tree/components/folder-item.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/folder-tree/components/workflow-item.tsx (94%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/folder-tree/folder-tree.tsx (94%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/help-modal/components/help-form/help-form.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/help-modal/help-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/invite-modal/invite-modal.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/nav-section/nav-section.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/account/account.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/credentials/credentials.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/environment/environment.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/general/general.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/privacy/privacy.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/settings-navigation/settings-navigation.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/settings-modal/settings-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/sidebar-control/sidebar-control.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/workflow-list/workflow-list.tsx (90%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/components/workspace-header/workspace-header.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/sidebar/sidebar.tsx (94%) rename apps/sim/app/{ => workspace/[workspace]}/w/components/workflow-preview/workflow-preview.tsx (94%) rename apps/sim/app/{ => workspace/[workspace]}/w/error.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/global-error.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/hooks/use-keyboard-shortcuts.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/hooks/use-registry-loading.ts (86%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/[documentId]/components/document-loading.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/[documentId]/document.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/[documentId]/page.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/base.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/components/action-bar/action-bar.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/[id]/page.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/base-overview/base-overview.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/create-modal/create-modal.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/empty-state-card/empty-state-card.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/icons/document-icons.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/knowledge-header/knowledge-header.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/primary-button/primary-button.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/search-input/search-input.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/components/skeletons/table-skeleton.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/knowledge.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/loading.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/knowledge/page.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/layout.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/control-bar/control-bar.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/filters/components/filter-section.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/filters/components/folder.tsx (98%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/filters/components/level.tsx (91%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/filters/components/timeline.tsx (88%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/filters/components/trigger.tsx (97%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/filters/components/workflow.tsx (97%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/filters/filters.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/sidebar/components/markdown-renderer.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/sidebar/sidebar.tsx (99%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/tool-calls/tool-calls-display.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/components/trace-spans/trace-spans-display.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/logs.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/page.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/stores/store.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/stores/types.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/logs/utils/format-date.ts (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/components/control-bar/control-bar.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/components/error-message.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/components/section.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/components/toolbar/toolbar.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/components/workflow-card-skeleton.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/components/workflow-card.tsx (94%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/constants/categories.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/marketplace.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/marketplace/page.tsx (100%) rename apps/sim/app/{ => workspace/[workspace]}/w/page.tsx (81%) create mode 100644 apps/sim/app/workspace/page.tsx diff --git a/apps/sim/app/(auth)/components/social-login-buttons.tsx b/apps/sim/app/(auth)/components/social-login-buttons.tsx index 29fb289076f..09157d7de1e 100644 --- a/apps/sim/app/(auth)/components/social-login-buttons.tsx +++ b/apps/sim/app/(auth)/components/social-login-buttons.tsx @@ -17,7 +17,7 @@ interface SocialLoginButtonsProps { export function SocialLoginButtons({ githubAvailable, googleAvailable, - callbackURL = '/w', + callbackURL = '/workspace', isProduction, }: SocialLoginButtonsProps) { const [isGithubLoading, setIsGithubLoading] = useState(false) diff --git a/apps/sim/app/(auth)/login/login-form.test.tsx b/apps/sim/app/(auth)/login/login-form.test.tsx index 00bf49df227..a40edfd88fc 100644 --- a/apps/sim/app/(auth)/login/login-form.test.tsx +++ b/apps/sim/app/(auth)/login/login-form.test.tsx @@ -149,7 +149,7 @@ describe('LoginPage', () => { { email: 'test@example.com', password: 'password123', - callbackURL: '/w', + callbackURL: '/workspace', }, expect.objectContaining({ onError: expect.any(Function), diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index 566aa18cd01..88b9e5af624 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -125,7 +125,7 @@ export default function LoginPage({ const [showValidationError, setShowValidationError] = useState(false) // Initialize state for URL parameters - const [callbackUrl, setCallbackUrl] = useState('/w') + const [callbackUrl, setCallbackUrl] = useState('/workspace') const [isInviteFlow, setIsInviteFlow] = useState(false) // Forgot password states @@ -155,7 +155,7 @@ export default function LoginPage({ setCallbackUrl(callback) } else { logger.warn('Invalid callback URL detected and blocked:', { url: callback }) - // Keep the default safe value ('/w') + // Keep the default safe value ('/workspace') } } @@ -222,7 +222,7 @@ export default function LoginPage({ try { // Final validation before submission - const safeCallbackUrl = validateCallbackUrl(callbackUrl) ? callbackUrl : '/w' + const safeCallbackUrl = validateCallbackUrl(callbackUrl) ? callbackUrl : '/workspace' const result = await client.signIn.email( { diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index c061c6ba030..8b5e88dc813 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -410,7 +410,7 @@ function SignupFormContent({ diff --git a/apps/sim/app/(auth)/verify/use-verification.ts b/apps/sim/app/(auth)/verify/use-verification.ts index 933352d4907..b800cbd5782 100644 --- a/apps/sim/app/(auth)/verify/use-verification.ts +++ b/apps/sim/app/(auth)/verify/use-verification.ts @@ -148,7 +148,7 @@ export function useVerification({ router.push(redirectUrl) } else { // Default redirect to dashboard - router.push('/w') + router.push('/workspace') } }, 2000) } else { @@ -233,7 +233,7 @@ export function useVerification({ if (isDevOrDocker || !hasResendKey) { setIsVerified(true) const timeoutId = setTimeout(() => { - router.push('/w') + router.push('/workspace') }, 1000) return () => clearTimeout(timeoutId) diff --git a/apps/sim/app/(landing)/components/sections/footer.tsx b/apps/sim/app/(landing)/components/sections/footer.tsx index d0fdbf8c1b4..0a957c6011f 100644 --- a/apps/sim/app/(landing)/components/sections/footer.tsx +++ b/apps/sim/app/(landing)/components/sections/footer.tsx @@ -21,7 +21,7 @@ function Footer() { if (typeof window !== 'undefined') { // Check if user has an active session if (isAuthenticated) { - router.push('/w') + router.push('/workspace') } else { // Check if user has logged in before const hasLoggedInBefore = diff --git a/apps/sim/app/(landing)/components/sections/hero.tsx b/apps/sim/app/(landing)/components/sections/hero.tsx index a3823a7cc0c..e822888b7c2 100644 --- a/apps/sim/app/(landing)/components/sections/hero.tsx +++ b/apps/sim/app/(landing)/components/sections/hero.tsx @@ -18,7 +18,7 @@ function Hero() { if (typeof window !== 'undefined') { // Check if user has an active session if (isAuthenticated) { - router.push('/w') + router.push('/workspace') } else { // Check if user has logged in before const hasLoggedInBefore = diff --git a/apps/sim/app/api/marketplace/workflows/route.ts b/apps/sim/app/api/marketplace/workflows/route.ts index 40bc4fe1975..27ed728f803 100644 --- a/apps/sim/app/api/marketplace/workflows/route.ts +++ b/apps/sim/app/api/marketplace/workflows/route.ts @@ -2,7 +2,7 @@ import { desc, eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { createLogger } from '@/lib/logs/console-logger' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' -import { CATEGORIES } from '@/app/w/marketplace/constants/categories' +import { CATEGORIES } from '@/app/workspace/[workspace]/w/marketplace/constants/categories' import { db } from '@/db' import * as schema from '@/db/schema' diff --git a/apps/sim/app/invite/[id]/invite.tsx b/apps/sim/app/invite/[id]/invite.tsx index 3cac00e554f..86b748b6866 100644 --- a/apps/sim/app/invite/[id]/invite.tsx +++ b/apps/sim/app/invite/[id]/invite.tsx @@ -131,7 +131,7 @@ export default function Invite() { // Redirect to workspace after a brief delay setTimeout(() => { - router.push('/w') + router.push('/workspace') }, 2000) } else { // For organization invites, use the client API @@ -153,7 +153,7 @@ export default function Invite() { // Redirect to workspace after a brief delay setTimeout(() => { - router.push('/w') + router.push('/workspace') }, 2000) } } catch (err: any) { diff --git a/apps/sim/app/invite/invite-error/invite-error.tsx b/apps/sim/app/invite/invite-error/invite-error.tsx index 480a59d2ae8..064a70b9332 100644 --- a/apps/sim/app/invite/invite-error/invite-error.tsx +++ b/apps/sim/app/invite/invite-error/invite-error.tsx @@ -54,7 +54,7 @@ export default function InviteError() {

{displayMessage}

- + diff --git a/apps/sim/app/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx index ef4b60ed270..bcad2555072 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx @@ -33,7 +33,7 @@ import { Textarea } from '@/components/ui/textarea' import { createLogger } from '@/lib/logs/console-logger' import { getBaseDomain } from '@/lib/urls/utils' import { cn } from '@/lib/utils' -import { OutputSelect } from '@/app/w/[id]/components/panel/components/chat/components/output-select/output-select' +import { OutputSelect } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/output-select/output-select' import { useNotificationStore } from '@/stores/notifications/store' import type { OutputConfig } from '@/stores/panel/chat/types' diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx similarity index 88% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx index f8a794b7fd1..7cedaa2e676 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx @@ -15,10 +15,10 @@ import { } from '@/components/ui/alert-dialog' import { Button } from '@/components/ui/button' import { Skeleton } from '@/components/ui/skeleton' -import { ApiEndpoint } from '@/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint' -import { ApiKey } from '@/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key' -import { DeployStatus } from '@/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status' -import { ExampleCommand } from '@/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command' +import { ApiEndpoint } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint' +import { ApiKey } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key' +import { DeployStatus } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status' +import { ExampleCommand } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command' import { useNotificationStore } from '@/stores/notifications/store' import type { WorkflowState } from '@/stores/workflows/workflow/types' import { DeployedWorkflowModal } from '../../../deployment-controls/components/deployed-workflow-modal' diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx similarity index 98% rename from apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx index af068534848..e2f642fc1db 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx @@ -20,9 +20,9 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/u import { env } from '@/lib/env' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { ChatDeploy } from '@/app/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy' -import { DeployForm } from '@/app/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form' -import { DeploymentInfo } from '@/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info' +import { ChatDeploy } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy' +import { DeployForm } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form' +import { DeploymentInfo } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info' import { useNotificationStore } from '@/stores/notifications/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx similarity index 96% rename from apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx index 187c4fe10e9..29e894b9d9a 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx @@ -6,7 +6,7 @@ import { Label } from '@/components/ui/label' import { Switch } from '@/components/ui/switch' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { WorkflowPreview } from '@/app/w/components/workflow-preview/workflow-preview' +import { WorkflowPreview } from '@/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { WorkflowState } from '@/stores/workflows/workflow/types' diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx index 3d64dcc06f2..b9bcc397224 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx @@ -35,7 +35,7 @@ import { getCategoryColor, getCategoryIcon, getCategoryLabel, -} from '@/app/w/marketplace/constants/categories' +} from '@/app/workspace/[workspace]/w/marketplace/constants/categories' import { useNotificationStore } from '@/stores/notifications/store' import { getWorkflowWithValues } from '@/stores/workflows' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' diff --git a/apps/sim/app/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx diff --git a/apps/sim/app/w/[id]/components/control-bar/control-bar.test.ts b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.test.ts similarity index 100% rename from apps/sim/app/w/[id]/components/control-bar/control-bar.test.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.test.ts diff --git a/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx index 5da2dc64df6..ea9b709720c 100644 --- a/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx @@ -16,7 +16,7 @@ import { Trash2, X, } from 'lucide-react' -import { useRouter } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { AlertDialog, AlertDialogAction, @@ -40,7 +40,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip import { useSession } from '@/lib/auth-client' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useUserPermissionsContext } from '@/app/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' import { useExecutionStore } from '@/stores/execution/store' import { useNotificationStore } from '@/stores/notifications/store' import { usePanelStore } from '@/stores/panel/store' @@ -84,6 +84,8 @@ interface ControlBarProps { export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { const router = useRouter() const { data: session } = useSession() + const params = useParams() + const workspaceId = params.workspace as string // Store hooks const { @@ -423,7 +425,7 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { // Navigate to the next workflow or home if (nextWorkflowId) { - router.push(`/w/${nextWorkflowId}`) + router.push(`/workspace/${workspaceId}/w/${nextWorkflowId}`) } else { router.push('/') } diff --git a/apps/sim/app/w/[id]/components/copilot/copilot.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/copilot/copilot.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/copilot/copilot.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/copilot/copilot.tsx diff --git a/apps/sim/app/w/[id]/components/error/index.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/error/index.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/error/index.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/error/index.tsx diff --git a/apps/sim/app/w/[id]/components/loop-node/components/loop-badges.test.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.test.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/loop-node/components/loop-badges.test.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.test.tsx diff --git a/apps/sim/app/w/[id]/components/loop-node/components/loop-badges.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/loop-node/components/loop-badges.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.tsx diff --git a/apps/sim/app/w/[id]/components/loop-node/loop-config.ts b/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-config.ts similarity index 100% rename from apps/sim/app/w/[id]/components/loop-node/loop-config.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-config.ts diff --git a/apps/sim/app/w/[id]/components/loop-node/loop-node.test.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.test.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/loop-node/loop-node.test.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.test.tsx diff --git a/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/loop-node/loop-node.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.tsx diff --git a/apps/sim/app/w/[id]/components/notifications/notifications.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/notifications/notifications.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/notifications/notifications.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/notifications/notifications.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/chat/chat.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/chat.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/chat/chat.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/chat.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx similarity index 97% rename from apps/sim/app/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx index 31b887312a2..5cb609367fc 100644 --- a/apps/sim/app/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx @@ -4,8 +4,8 @@ import { type KeyboardEvent, useEffect, useMemo, useRef } from 'react' import { ArrowUp, X } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' -import { JSONView } from '@/app/w/[id]/components/panel/components/console/components/json-view/json-view' -import { useWorkflowExecution } from '@/app/w/[id]/hooks/use-workflow-execution' +import { JSONView } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view' +import { useWorkflowExecution } from '@/app/workspace/[workspace]/w/[id]/hooks/use-workflow-execution' import { useExecutionStore } from '@/stores/execution/store' import { useChatStore } from '@/stores/panel/chat/store' import type { ChatMessage as ChatMessageType } from '@/stores/panel/chat/types' diff --git a/apps/sim/app/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/console/components/json-view/json-view.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/console/components/json-view/json-view.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/console/console.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/console.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/console/console.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/console.tsx diff --git a/apps/sim/app/w/[id]/components/panel/components/variables/variables.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/variables/variables.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/panel/components/variables/variables.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/variables/variables.tsx diff --git a/apps/sim/app/w/[id]/components/panel/panel.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/panel.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/panel/panel.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/panel/panel.tsx index 7afc5e3eb1e..27494712dc0 100644 --- a/apps/sim/app/w/[id]/components/panel/panel.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/panel.tsx @@ -5,8 +5,8 @@ import { Expand, PanelRight } from 'lucide-react' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { useChatStore } from '@/stores/panel/chat/store' import { useConsoleStore } from '@/stores/panel/console/store' +import { usePanelStore } from '@/stores/panel/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' -import { usePanelStore } from '../../../../../stores/panel/store' import { Chat } from './components/chat/chat' import { ChatModal } from './components/chat/components/chat-modal/chat-modal' import { Console } from './components/console/console' diff --git a/apps/sim/app/w/[id]/components/parallel-node/components/parallel-badges.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/components/parallel-badges.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/parallel-node/components/parallel-badges.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/components/parallel-badges.tsx diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts b/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-config.ts similarity index 100% rename from apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-config.ts diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.test.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.test.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/parallel-node/parallel-node.test.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.test.tsx diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.tsx diff --git a/apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/skeleton-loading/skeleton-loading.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/skeleton-loading/skeleton-loading.tsx diff --git a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx diff --git a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx diff --git a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx diff --git a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx diff --git a/apps/sim/app/w/[id]/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx similarity index 98% rename from apps/sim/app/w/[id]/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx index 8d86f8407f5..c46772d3b5a 100644 --- a/apps/sim/app/w/[id]/components/toolbar/toolbar.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx @@ -6,7 +6,7 @@ import { useParams } from 'next/navigation' import { Input } from '@/components/ui/input' import { ScrollArea } from '@/components/ui/scroll-area' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' -import { useUserPermissionsContext } from '@/app/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' import { getAllBlocks, getBlocksByCategory } from '@/blocks' import type { BlockCategory } from '@/blocks/types' import { useSidebarStore } from '@/stores/sidebar/store' diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx similarity index 98% rename from apps/sim/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx index baf322f53e7..119e238f166 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx @@ -1,6 +1,9 @@ import { Card } from '@/components/ui/card' import { cn } from '@/lib/utils' -import { type ConnectedBlock, useBlockConnections } from '@/app/w/[id]/hooks/use-block-connections' +import { + type ConnectedBlock, + useBlockConnections, +} from '@/app/workspace/[workspace]/w/[id]/hooks/use-block-connections' import { useSubBlockStore } from '@/stores/workflows/subblock/store' interface ConnectionBlocksProps { diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx index d47adca2d8e..7f50bc0f32e 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx @@ -11,7 +11,7 @@ import { checkEnvVarTrigger, EnvVarDropdown } from '@/components/ui/env-var-drop import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useCodeGeneration } from '@/app/w/[id]/hooks/use-code-generation' +import { useCodeGeneration } from '@/app/workspace/[workspace]/w/[id]/hooks/use-code-generation' import { useSubBlockStore } from '@/stores/workflows/subblock/store' import { CodePromptBar } from '../../../../code-prompt-bar/code-prompt-bar' import { useSubBlockValue } from '../hooks/use-sub-block-value' diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx similarity index 98% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx index 2a0d9990eab..d28d88d0c6f 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx @@ -15,7 +15,7 @@ import { import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { createLogger } from '@/lib/logs/console-logger' import { type Credential, getProviderIdFromServiceId, getServiceIdFromScopes } from '@/lib/oauth' -import { OAuthRequiredModal } from '@/app/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal' +import { OAuthRequiredModal } from '@/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal' import { saveToStorage } from '@/stores/workflows/persistence' const logger = createLogger('FolderSelector') diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/table.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/table.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx index aee40413bec..8ff8e31db1d 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx @@ -24,7 +24,7 @@ import { Label } from '@/components/ui/label' import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useCodeGeneration } from '@/app/w/[id]/hooks/use-code-generation' +import { useCodeGeneration } from '@/app/workspace/[workspace]/w/[id]/hooks/use-code-generation' import { useCustomToolsStore } from '@/stores/custom-tools/store' import { CodePromptBar } from '../../../../../../../code-prompt-bar/code-prompt-bar' import { CodeEditor } from '../code-editor/code-editor' diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx similarity index 98% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx index a23eb809d83..c8e61e8b757 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx @@ -16,7 +16,7 @@ import { import { Skeleton } from '@/components/ui/skeleton' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { Logger } from '@/lib/logs/console-logger' -import { JSONView } from '@/app/w/[id]/components/panel/components/console/components/json-view/json-view' +import { JSONView } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view' import { ConfigSection } from '../ui/config-section' const logger = new Logger('GmailConfig') diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx similarity index 97% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx index cb584d2e751..d257662f3f5 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx @@ -1,6 +1,6 @@ import { SlackIcon } from '@/components/icons' import { Notice } from '@/components/ui/notice' -import { JSONView } from '@/app/w/[id]/components/panel/components/console/components/json-view/json-view' +import { JSONView } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view' import { ConfigSection } from '../ui/config-section' import { InstructionsSection } from '../ui/instructions-section' import { TestResultDisplay } from '../ui/test-result' diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx diff --git a/apps/sim/app/w/[id]/components/workflow-block/workflow-block.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/workflow-block/workflow-block.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block.tsx index 82cf37cfa1d..7ea97c01218 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/workflow-block.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block.tsx @@ -7,7 +7,7 @@ import { Card } from '@/components/ui/card' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { parseCronToHumanReadable } from '@/lib/schedules/utils' import { cn, formatDateTime, validateName } from '@/lib/utils' -import { useUserPermissionsContext } from '@/app/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' import type { BlockConfig, SubBlockConfig } from '@/blocks/types' import { useExecutionStore } from '@/stores/execution/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' diff --git a/apps/sim/app/w/[id]/components/workflow-edge/workflow-edge.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-edge/workflow-edge.tsx similarity index 100% rename from apps/sim/app/w/[id]/components/workflow-edge/workflow-edge.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-edge/workflow-edge.tsx diff --git a/apps/sim/app/w/[id]/hooks/use-block-connections.ts b/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-block-connections.ts similarity index 100% rename from apps/sim/app/w/[id]/hooks/use-block-connections.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-block-connections.ts diff --git a/apps/sim/app/w/[id]/hooks/use-code-generation.ts b/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-code-generation.ts similarity index 100% rename from apps/sim/app/w/[id]/hooks/use-code-generation.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-code-generation.ts diff --git a/apps/sim/app/w/[id]/hooks/use-presence.ts b/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-presence.ts similarity index 100% rename from apps/sim/app/w/[id]/hooks/use-presence.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-presence.ts diff --git a/apps/sim/app/w/[id]/hooks/use-workflow-execution.ts b/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-workflow-execution.ts similarity index 100% rename from apps/sim/app/w/[id]/hooks/use-workflow-execution.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-workflow-execution.ts diff --git a/apps/sim/app/w/[id]/layout.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/layout.tsx similarity index 100% rename from apps/sim/app/w/[id]/layout.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/layout.tsx diff --git a/apps/sim/app/w/[id]/page.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/page.tsx similarity index 100% rename from apps/sim/app/w/[id]/page.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/page.tsx diff --git a/apps/sim/app/w/[id]/utils.ts b/apps/sim/app/workspace/[workspace]/w/[id]/utils.ts similarity index 100% rename from apps/sim/app/w/[id]/utils.ts rename to apps/sim/app/workspace/[workspace]/w/[id]/utils.ts diff --git a/apps/sim/app/w/[id]/workflow.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/workflow.tsx similarity index 98% rename from apps/sim/app/w/[id]/workflow.tsx rename to apps/sim/app/workspace/[workspace]/w/[id]/workflow.tsx index e656b3fb1eb..6441010eb9f 100644 --- a/apps/sim/app/w/[id]/workflow.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/workflow.tsx @@ -13,10 +13,10 @@ import ReactFlow, { import 'reactflow/dist/style.css' import { createLogger } from '@/lib/logs/console-logger' -import { LoopNodeComponent } from '@/app/w/[id]/components/loop-node/loop-node' -import { NotificationList } from '@/app/w/[id]/components/notifications/notifications' -import { ParallelNodeComponent } from '@/app/w/[id]/components/parallel-node/parallel-node' -import { useUserPermissionsContext } from '@/app/w/components/providers/workspace-permissions-provider' +import { LoopNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node' +import { NotificationList } from '@/app/workspace/[workspace]/w/[id]/components/notifications/notifications' +import { ParallelNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node' +import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' import { getBlock } from '@/blocks' import { useSocket } from '@/contexts/socket-context' import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' @@ -830,14 +830,14 @@ const WorkflowContent = React.memo(() => { // If no workflows exist, redirect to workspace root to let server handle workflow creation if (workflowIds.length === 0 && !isLoading) { logger.info('No workflows found, redirecting to workspace root') - router.replace('/w') + router.replace(`/workspace/${workspaceId}/w`) return } // Navigate to existing workflow or first available if (!workflows[currentId]) { logger.info(`Workflow ${currentId} not found, redirecting to first available workflow`) - router.replace(`/w/${workflowIds[0]}`) + router.replace(`/workspace/${workspaceId}/w/${workflowIds[0]}`) return } diff --git a/apps/sim/app/w/components/providers/providers.tsx b/apps/sim/app/workspace/[workspace]/w/components/providers/providers.tsx similarity index 100% rename from apps/sim/app/w/components/providers/providers.tsx rename to apps/sim/app/workspace/[workspace]/w/components/providers/providers.tsx diff --git a/apps/sim/app/w/components/providers/theme-provider.tsx b/apps/sim/app/workspace/[workspace]/w/components/providers/theme-provider.tsx similarity index 100% rename from apps/sim/app/w/components/providers/theme-provider.tsx rename to apps/sim/app/workspace/[workspace]/w/components/providers/theme-provider.tsx diff --git a/apps/sim/app/w/components/providers/workspace-permissions-provider.tsx b/apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx similarity index 100% rename from apps/sim/app/w/components/providers/workspace-permissions-provider.tsx rename to apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx diff --git a/apps/sim/app/w/components/sidebar/components/create-menu/create-menu.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/create-menu/create-menu.tsx similarity index 100% rename from apps/sim/app/w/components/sidebar/components/create-menu/create-menu.tsx rename to apps/sim/app/workspace/[workspace]/w/components/sidebar/components/create-menu/create-menu.tsx diff --git a/apps/sim/app/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx similarity index 100% rename from apps/sim/app/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx rename to apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx diff --git a/apps/sim/app/w/components/sidebar/components/folder-tree/components/folder-item.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx similarity index 100% rename from apps/sim/app/w/components/sidebar/components/folder-tree/components/folder-item.tsx rename to apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx diff --git a/apps/sim/app/w/components/sidebar/components/folder-tree/components/workflow-item.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx similarity index 94% rename from apps/sim/app/w/components/sidebar/components/folder-tree/components/workflow-item.tsx rename to apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx index 07bf393d9bb..8badbfd2715 100644 --- a/apps/sim/app/w/components/sidebar/components/folder-tree/components/workflow-item.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx @@ -3,6 +3,7 @@ import { useRef, useState } from 'react' import clsx from 'clsx' import Link from 'next/link' +import { useParams } from 'next/navigation' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { useFolderStore, useIsWorkflowSelected } from '@/stores/folders/store' import type { WorkflowMetadata } from '@/stores/workflows/registry/types' @@ -26,6 +27,8 @@ export function WorkflowItem({ }: WorkflowItemProps) { const [isDragging, setIsDragging] = useState(false) const dragStartedRef = useRef(false) + const params = useParams() + const workspaceId = params.workspace as string const { selectedWorkflows, selectOnly, toggleWorkflowSelection } = useFolderStore() const isSelected = useIsWorkflowSelected(workflow.id) @@ -74,7 +77,7 @@ export function WorkflowItem({ ))} @@ -121,7 +126,7 @@ export function WorkflowList({ diff --git a/apps/sim/app/w/components/sidebar/components/workspace-header/workspace-header.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx similarity index 98% rename from apps/sim/app/w/components/sidebar/components/workspace-header/workspace-header.tsx rename to apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx index 4f9351d0154..d540c17e4ec 100644 --- a/apps/sim/app/w/components/sidebar/components/workspace-header/workspace-header.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx @@ -29,7 +29,7 @@ import { Input } from '@/components/ui/input' import { Skeleton } from '@/components/ui/skeleton' import { useSession } from '@/lib/auth-client' import { cn } from '@/lib/utils' -import { useUserPermissionsContext } from '@/app/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' import { useSidebarStore } from '@/stores/sidebar/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' @@ -337,7 +337,7 @@ export const WorkspaceHeader = React.memo( switchToWorkspace(workspace.id) // Update URL to include workspace ID - router.push(`/w/${workspace.id}`) + router.push(`/workspace/${workspace.id}/w`) }, [activeWorkspace?.id, switchToWorkspace, router] ) @@ -367,7 +367,7 @@ export const WorkspaceHeader = React.memo( switchToWorkspace(newWorkspace.id) // Update URL to include new workspace ID - router.push(`/w/${newWorkspace.id}`) + router.push(`/workspace/${newWorkspace.id}/w`) } } catch (err) { console.error('Error creating workspace:', err) @@ -486,7 +486,7 @@ export const WorkspaceHeader = React.memo( // Determine URL for workspace links const workspaceUrl = useMemo( - () => (activeWorkspace ? `/w/${activeWorkspace.id}` : '/w'), + () => (activeWorkspace ? `/workspace/${activeWorkspace.id}/w` : '/workspace'), [activeWorkspace] ) diff --git a/apps/sim/app/w/components/sidebar/sidebar.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx similarity index 94% rename from apps/sim/app/w/components/sidebar/sidebar.tsx rename to apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx index e8485572e82..667c4bdca97 100644 --- a/apps/sim/app/w/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx @@ -3,12 +3,15 @@ import { useEffect, useMemo, useState } from 'react' import clsx from 'clsx' import { HelpCircle, LibraryBig, ScrollText, Send, Settings } from 'lucide-react' -import { usePathname, useRouter } from 'next/navigation' +import { useParams, usePathname, useRouter } from 'next/navigation' import { Skeleton } from '@/components/ui/skeleton' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { useSession } from '@/lib/auth-client' import { createLogger } from '@/lib/logs/console-logger' -import { getKeyboardShortcutText, useGlobalShortcuts } from '@/app/w/hooks/use-keyboard-shortcuts' +import { + getKeyboardShortcutText, + useGlobalShortcuts, +} from '@/app/workspace/[workspace]/w/hooks/use-keyboard-shortcuts' import { useSidebarStore } from '@/stores/sidebar/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { WorkflowMetadata } from '@/stores/workflows/registry/types' @@ -41,6 +44,8 @@ export function Sidebar() { const userPermissions = useUserPermissionsContext() const isLoading = workflowsLoading || sessionLoading const router = useRouter() + const params = useParams() + const workspaceId = params.workspace as string const pathname = usePathname() const [showSettings, setShowSettings] = useState(false) @@ -99,10 +104,10 @@ export function Sidebar() { const handleCreateWorkflow = async (folderId?: string) => { try { const id = await createWorkflow({ - workspaceId: activeWorkspaceId || undefined, + workspaceId: workspaceId || undefined, folderId: folderId || undefined, }) - router.push(`/w/${id}`) + router.push(`/workspace/${workspaceId}/w/${id}`) } catch (error) { logger.error('Error creating workflow:', error) } @@ -179,18 +184,18 @@ export function Sidebar() { } - href='/w/logs' + href={`/workspace/${workspaceId}/w/logs`} label='Logs' - active={pathname === '/w/logs'} + active={pathname === `/workspace/${workspaceId}/w/logs`} isCollapsed={isCollapsed} shortcutCommand={getKeyboardShortcutText('L', true, true)} shortcutCommandPosition='below' /> } - href='/w/knowledge' + href={`/workspace/${workspaceId}/w/knowledge`} label='Knowledge' - active={pathname === '/w/knowledge'} + active={pathname === `/workspace/${workspaceId}/w/knowledge`} isCollapsed={isCollapsed} shortcutCommand={getKeyboardShortcutText('K', true, true)} shortcutCommandPosition='below' diff --git a/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx b/apps/sim/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview.tsx similarity index 94% rename from apps/sim/app/w/components/workflow-preview/workflow-preview.tsx rename to apps/sim/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview.tsx index 79abac5ab47..93ab119ed66 100644 --- a/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview.tsx @@ -15,10 +15,10 @@ import 'reactflow/dist/style.css' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { LoopNodeComponent } from '@/app/w/[id]/components/loop-node/loop-node' -import { ParallelNodeComponent } from '@/app/w/[id]/components/parallel-node/parallel-node' -import { WorkflowBlock } from '@/app/w/[id]/components/workflow-block/workflow-block' -import { WorkflowEdge } from '@/app/w/[id]/components/workflow-edge/workflow-edge' +import { LoopNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node' +import { ParallelNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node' +import { WorkflowBlock } from '@/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block' +import { WorkflowEdge } from '@/app/workspace/[workspace]/w/[id]/components/workflow-edge/workflow-edge' import { getBlock } from '@/blocks' import type { WorkflowState } from '@/stores/workflows/workflow/types' diff --git a/apps/sim/app/w/error.tsx b/apps/sim/app/workspace/[workspace]/w/error.tsx similarity index 100% rename from apps/sim/app/w/error.tsx rename to apps/sim/app/workspace/[workspace]/w/error.tsx diff --git a/apps/sim/app/w/global-error.tsx b/apps/sim/app/workspace/[workspace]/w/global-error.tsx similarity index 100% rename from apps/sim/app/w/global-error.tsx rename to apps/sim/app/workspace/[workspace]/w/global-error.tsx diff --git a/apps/sim/app/w/hooks/use-keyboard-shortcuts.ts b/apps/sim/app/workspace/[workspace]/w/hooks/use-keyboard-shortcuts.ts similarity index 100% rename from apps/sim/app/w/hooks/use-keyboard-shortcuts.ts rename to apps/sim/app/workspace/[workspace]/w/hooks/use-keyboard-shortcuts.ts diff --git a/apps/sim/app/w/hooks/use-registry-loading.ts b/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts similarity index 86% rename from apps/sim/app/w/hooks/use-registry-loading.ts rename to apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts index 207514e18fd..168323ddde6 100644 --- a/apps/sim/app/w/hooks/use-registry-loading.ts +++ b/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts @@ -1,7 +1,7 @@ 'use client' import { useEffect } from 'react' -import { usePathname, useRouter } from 'next/navigation' +import { useParams, usePathname, useRouter } from 'next/navigation' import { createLogger } from '@/lib/logs/console-logger' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' @@ -42,6 +42,8 @@ export function useRegistryLoading() { useWorkflowRegistry() const pathname = usePathname() const router = useRouter() + const params = useParams() + const workspaceId = params.workspace as string // Handle workspace selection from URL useEffect(() => { @@ -61,14 +63,16 @@ export function useRegistryLoading() { const workflowCount = Object.keys(workflows).length const currentWorkflowId = extractWorkflowIdFromPathname(pathname) - // If we're at a generic workspace URL (/w, /w/, or /w/workspaceId) without a specific workflow + // Check if we're on the workspace root and need to redirect to first workflow if ( - !currentWorkflowId && - (pathname === '/w' || pathname === '/w/' || pathname === `/w/${activeWorkspaceId}`) + (pathname === `/workspace/${workspaceId}/w` || + pathname === `/workspace/${workspaceId}/w/` || + pathname === `/workspace/${workspaceId}/w/${activeWorkspaceId}`) && + Object.keys(workflows).length > 0 ) { const firstWorkflowId = Object.keys(workflows)[0] logger.info('First-time navigation: redirecting to first workflow:', firstWorkflowId) - router.replace(`/w/${firstWorkflowId}`) + router.replace(`/workspace/${workspaceId}/w/${firstWorkflowId}`) } } }, [isLoading, activeWorkspaceId, workflows, pathname, router]) diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/components/document-loading.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/document-loading.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/[documentId]/components/document-loading.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/document-loading.tsx diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/document.tsx similarity index 99% rename from apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/document.tsx index 9758f46fa8e..3d54d03b17f 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/document.tsx @@ -16,7 +16,7 @@ import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { createLogger } from '@/lib/logs/console-logger' -import { ActionBar } from '@/app/w/knowledge/[id]/components/action-bar/action-bar' +import { ActionBar } from '@/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar' import { useDocumentChunks } from '@/hooks/use-knowledge' import { type ChunkData, type DocumentData, useKnowledgeStore } from '@/stores/knowledge/store' import { useSidebarStore } from '@/stores/sidebar/store' diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/page.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/page.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/[documentId]/page.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/page.tsx diff --git a/apps/sim/app/w/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/base.tsx similarity index 98% rename from apps/sim/app/w/knowledge/[id]/base.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/base.tsx index 2b7ab83d394..9383c60c038 100644 --- a/apps/sim/app/w/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/base.tsx @@ -13,7 +13,7 @@ import { Trash2, X, } from 'lucide-react' -import { useRouter } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { AlertDialog, AlertDialogAction, @@ -28,10 +28,10 @@ import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { createLogger } from '@/lib/logs/console-logger' -import { ActionBar } from '@/app/w/knowledge/[id]/components/action-bar/action-bar' -import { getDocumentIcon } from '@/app/w/knowledge/components/icons/document-icons' -import { PrimaryButton } from '@/app/w/knowledge/components/primary-button/primary-button' -import { SearchInput } from '@/app/w/knowledge/components/search-input/search-input' +import { ActionBar } from '@/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar' +import { getDocumentIcon } from '@/app/workspace/[workspace]/w/knowledge/components/icons/document-icons' +import { PrimaryButton } from '@/app/workspace/[workspace]/w/knowledge/components/primary-button/primary-button' +import { SearchInput } from '@/app/workspace/[workspace]/w/knowledge/components/search-input/search-input' import { useKnowledgeBase, useKnowledgeBaseDocuments } from '@/hooks/use-knowledge' import { type DocumentData, useKnowledgeStore } from '@/stores/knowledge/store' import { useSidebarStore } from '@/stores/sidebar/store' @@ -122,6 +122,8 @@ export function KnowledgeBase({ }: KnowledgeBaseProps) { const { mode, isExpanded } = useSidebarStore() const { removeKnowledgeBase } = useKnowledgeStore() + const params = useParams() + const workspaceId = params.workspace as string const { knowledgeBase, isLoading: isLoadingKnowledgeBase, @@ -402,11 +404,11 @@ export function KnowledgeBase({ const handleDocumentClick = (docId: string) => { // Find the document to get its filename const document = documents.find((doc) => doc.id === docId) - const params = new URLSearchParams({ + const urlParams = new URLSearchParams({ kbName: knowledgeBaseName, // Use the instantly available name docName: document?.filename || 'Document', }) - router.push(`/w/knowledge/${id}/${docId}?${params.toString()}`) + router.push(`/workspace/${workspaceId}/w/knowledge/${id}/${docId}?${urlParams.toString()}`) } const handleDeleteKnowledgeBase = async () => { @@ -428,7 +430,7 @@ export function KnowledgeBase({ if (result.success) { // Remove from store and redirect to knowledge bases list removeKnowledgeBase(id) - router.push('/w/knowledge') + router.push(`/workspace/${workspaceId}/w/knowledge`) } else { throw new Error(result.error || 'Failed to delete knowledge base') } diff --git a/apps/sim/app/w/knowledge/[id]/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/components/action-bar/action-bar.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar.tsx diff --git a/apps/sim/app/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx diff --git a/apps/sim/app/w/knowledge/[id]/page.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/page.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/page.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/[id]/page.tsx diff --git a/apps/sim/app/w/knowledge/components/base-overview/base-overview.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/base-overview/base-overview.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/base-overview/base-overview.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/base-overview/base-overview.tsx diff --git a/apps/sim/app/w/knowledge/components/create-modal/create-modal.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/create-modal/create-modal.tsx similarity index 99% rename from apps/sim/app/w/knowledge/components/create-modal/create-modal.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/create-modal/create-modal.tsx index 5fbfd6effa2..63ce953ab0e 100644 --- a/apps/sim/app/w/knowledge/components/create-modal/create-modal.tsx +++ b/apps/sim/app/workspace/[workspace]/w/knowledge/components/create-modal/create-modal.tsx @@ -12,7 +12,7 @@ import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { createLogger } from '@/lib/logs/console-logger' -import { getDocumentIcon } from '@/app/w/knowledge/components/icons/document-icons' +import { getDocumentIcon } from '@/app/workspace/[workspace]/w/knowledge/components/icons/document-icons' import type { DocumentData, KnowledgeBaseData } from '@/stores/knowledge/store' import { useKnowledgeStore } from '@/stores/knowledge/store' diff --git a/apps/sim/app/w/knowledge/components/empty-state-card/empty-state-card.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/empty-state-card/empty-state-card.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/empty-state-card/empty-state-card.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/empty-state-card/empty-state-card.tsx diff --git a/apps/sim/app/w/knowledge/components/icons/document-icons.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/icons/document-icons.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/icons/document-icons.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/icons/document-icons.tsx diff --git a/apps/sim/app/w/knowledge/components/knowledge-header/knowledge-header.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/knowledge-header/knowledge-header.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/knowledge-header/knowledge-header.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/knowledge-header/knowledge-header.tsx diff --git a/apps/sim/app/w/knowledge/components/primary-button/primary-button.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/primary-button/primary-button.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/primary-button/primary-button.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/primary-button/primary-button.tsx diff --git a/apps/sim/app/w/knowledge/components/search-input/search-input.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/search-input/search-input.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/search-input/search-input.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/search-input/search-input.tsx diff --git a/apps/sim/app/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx diff --git a/apps/sim/app/w/knowledge/components/skeletons/table-skeleton.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/table-skeleton.tsx similarity index 100% rename from apps/sim/app/w/knowledge/components/skeletons/table-skeleton.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/table-skeleton.tsx diff --git a/apps/sim/app/w/knowledge/knowledge.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/knowledge.tsx similarity index 100% rename from apps/sim/app/w/knowledge/knowledge.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/knowledge.tsx diff --git a/apps/sim/app/w/knowledge/loading.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/loading.tsx similarity index 100% rename from apps/sim/app/w/knowledge/loading.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/loading.tsx diff --git a/apps/sim/app/w/knowledge/page.tsx b/apps/sim/app/workspace/[workspace]/w/knowledge/page.tsx similarity index 100% rename from apps/sim/app/w/knowledge/page.tsx rename to apps/sim/app/workspace/[workspace]/w/knowledge/page.tsx diff --git a/apps/sim/app/w/layout.tsx b/apps/sim/app/workspace/[workspace]/w/layout.tsx similarity index 100% rename from apps/sim/app/w/layout.tsx rename to apps/sim/app/workspace/[workspace]/w/layout.tsx diff --git a/apps/sim/app/w/logs/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/control-bar/control-bar.tsx similarity index 100% rename from apps/sim/app/w/logs/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/control-bar/control-bar.tsx diff --git a/apps/sim/app/w/logs/components/filters/components/filter-section.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/filter-section.tsx similarity index 100% rename from apps/sim/app/w/logs/components/filters/components/filter-section.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/filter-section.tsx diff --git a/apps/sim/app/w/logs/components/filters/components/folder.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx similarity index 98% rename from apps/sim/app/w/logs/components/filters/components/folder.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx index 025e20a7193..1e4d59b5e38 100644 --- a/apps/sim/app/w/logs/components/filters/components/folder.tsx +++ b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx @@ -8,7 +8,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' import { useFolderStore } from '@/stores/folders/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' diff --git a/apps/sim/app/w/logs/components/filters/components/level.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/level.tsx similarity index 91% rename from apps/sim/app/w/logs/components/filters/components/level.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/level.tsx index 78550907e93..37b42523b78 100644 --- a/apps/sim/app/w/logs/components/filters/components/level.tsx +++ b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/level.tsx @@ -6,8 +6,8 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/w/logs/stores/store' -import type { LogLevel } from '@/app/w/logs/stores/types' +import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' +import type { LogLevel } from '@/app/workspace/[workspace]/w/logs/stores/types' export default function Level() { const { level, setLevel } = useFilterStore() diff --git a/apps/sim/app/w/logs/components/filters/components/timeline.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/timeline.tsx similarity index 88% rename from apps/sim/app/w/logs/components/filters/components/timeline.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/timeline.tsx index 39ae02fb0d1..ccd414c8c89 100644 --- a/apps/sim/app/w/logs/components/filters/components/timeline.tsx +++ b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/timeline.tsx @@ -6,8 +6,8 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/w/logs/stores/store' -import type { TimeRange } from '@/app/w/logs/stores/types' +import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' +import type { TimeRange } from '@/app/workspace/[workspace]/w/logs/stores/types' export default function Timeline() { const { timeRange, setTimeRange } = useFilterStore() diff --git a/apps/sim/app/w/logs/components/filters/components/trigger.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/trigger.tsx similarity index 97% rename from apps/sim/app/w/logs/components/filters/components/trigger.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/trigger.tsx index 760649d35be..2f431d0e215 100644 --- a/apps/sim/app/w/logs/components/filters/components/trigger.tsx +++ b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/trigger.tsx @@ -7,7 +7,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' import type { TriggerType } from '../../../stores/types' export default function Trigger() { diff --git a/apps/sim/app/w/logs/components/filters/components/workflow.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/workflow.tsx similarity index 97% rename from apps/sim/app/w/logs/components/filters/components/workflow.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/workflow.tsx index d5f94b6de74..aefaacc4a8a 100644 --- a/apps/sim/app/w/logs/components/filters/components/workflow.tsx +++ b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/workflow.tsx @@ -8,7 +8,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' interface WorkflowOption { id: string diff --git a/apps/sim/app/w/logs/components/filters/filters.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/filters.tsx similarity index 100% rename from apps/sim/app/w/logs/components/filters/filters.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/filters/filters.tsx diff --git a/apps/sim/app/w/logs/components/sidebar/components/markdown-renderer.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/components/markdown-renderer.tsx similarity index 100% rename from apps/sim/app/w/logs/components/sidebar/components/markdown-renderer.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/components/markdown-renderer.tsx diff --git a/apps/sim/app/w/logs/components/sidebar/sidebar.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/sidebar.tsx similarity index 99% rename from apps/sim/app/w/logs/components/sidebar/sidebar.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/sidebar.tsx index a47131e42d5..eb4f9124c5a 100644 --- a/apps/sim/app/w/logs/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/sidebar.tsx @@ -7,8 +7,8 @@ import { CopyButton } from '@/components/ui/copy-button' import { ScrollArea } from '@/components/ui/scroll-area' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import { redactApiKeys } from '@/lib/utils' -import type { WorkflowLog } from '@/app/w/logs/stores/types' -import { formatDate } from '@/app/w/logs/utils/format-date' +import type { WorkflowLog } from '@/app/workspace/[workspace]/w/logs/stores/types' +import { formatDate } from '@/app/workspace/[workspace]/w/logs/utils/format-date' import { formatCost } from '@/providers/utils' import { ToolCallsDisplay } from '../tool-calls/tool-calls-display' import { TraceSpansDisplay } from '../trace-spans/trace-spans-display' diff --git a/apps/sim/app/w/logs/components/tool-calls/tool-calls-display.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/tool-calls/tool-calls-display.tsx similarity index 100% rename from apps/sim/app/w/logs/components/tool-calls/tool-calls-display.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/tool-calls/tool-calls-display.tsx diff --git a/apps/sim/app/w/logs/components/trace-spans/trace-spans-display.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/trace-spans/trace-spans-display.tsx similarity index 100% rename from apps/sim/app/w/logs/components/trace-spans/trace-spans-display.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/components/trace-spans/trace-spans-display.tsx diff --git a/apps/sim/app/w/logs/logs.tsx b/apps/sim/app/workspace/[workspace]/w/logs/logs.tsx similarity index 100% rename from apps/sim/app/w/logs/logs.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/logs.tsx diff --git a/apps/sim/app/w/logs/page.tsx b/apps/sim/app/workspace/[workspace]/w/logs/page.tsx similarity index 100% rename from apps/sim/app/w/logs/page.tsx rename to apps/sim/app/workspace/[workspace]/w/logs/page.tsx diff --git a/apps/sim/app/w/logs/stores/store.ts b/apps/sim/app/workspace/[workspace]/w/logs/stores/store.ts similarity index 100% rename from apps/sim/app/w/logs/stores/store.ts rename to apps/sim/app/workspace/[workspace]/w/logs/stores/store.ts diff --git a/apps/sim/app/w/logs/stores/types.ts b/apps/sim/app/workspace/[workspace]/w/logs/stores/types.ts similarity index 100% rename from apps/sim/app/w/logs/stores/types.ts rename to apps/sim/app/workspace/[workspace]/w/logs/stores/types.ts diff --git a/apps/sim/app/w/logs/utils/format-date.ts b/apps/sim/app/workspace/[workspace]/w/logs/utils/format-date.ts similarity index 100% rename from apps/sim/app/w/logs/utils/format-date.ts rename to apps/sim/app/workspace/[workspace]/w/logs/utils/format-date.ts diff --git a/apps/sim/app/w/marketplace/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/components/control-bar/control-bar.tsx similarity index 100% rename from apps/sim/app/w/marketplace/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/components/control-bar/control-bar.tsx diff --git a/apps/sim/app/w/marketplace/components/error-message.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/components/error-message.tsx similarity index 100% rename from apps/sim/app/w/marketplace/components/error-message.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/components/error-message.tsx diff --git a/apps/sim/app/w/marketplace/components/section.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/components/section.tsx similarity index 100% rename from apps/sim/app/w/marketplace/components/section.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/components/section.tsx diff --git a/apps/sim/app/w/marketplace/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/components/toolbar/toolbar.tsx similarity index 100% rename from apps/sim/app/w/marketplace/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/components/toolbar/toolbar.tsx diff --git a/apps/sim/app/w/marketplace/components/workflow-card-skeleton.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card-skeleton.tsx similarity index 100% rename from apps/sim/app/w/marketplace/components/workflow-card-skeleton.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card-skeleton.tsx diff --git a/apps/sim/app/w/marketplace/components/workflow-card.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card.tsx similarity index 94% rename from apps/sim/app/w/marketplace/components/workflow-card.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card.tsx index 82db83df0b7..16e42371a0b 100644 --- a/apps/sim/app/w/marketplace/components/workflow-card.tsx +++ b/apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card.tsx @@ -2,9 +2,9 @@ import { useEffect, useState } from 'react' import { Eye } from 'lucide-react' -import { useRouter } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card' -import { WorkflowPreview } from '@/app/w/components/workflow-preview/workflow-preview' +import { WorkflowPreview } from '@/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { Workflow } from '../marketplace' @@ -28,6 +28,8 @@ interface WorkflowCardProps { export function WorkflowCard({ workflow, onHover }: WorkflowCardProps) { const [isPreviewReady, setIsPreviewReady] = useState(!!workflow.workflowState) const router = useRouter() + const params = useParams() + const workspaceId = params.workspace as string const { createWorkflow } = useWorkflowRegistry() // When workflow state becomes available, update preview ready state @@ -71,7 +73,7 @@ export function WorkflowCard({ workflow, onHover }: WorkflowCardProps) { }) // Navigate to the new workflow - router.push(`/w/${newWorkflowId}`) + router.push(`/workspace/${workspaceId}/w/${newWorkflowId}`) } else { console.error('Cannot import workflow: state is not available') } diff --git a/apps/sim/app/w/marketplace/constants/categories.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/constants/categories.tsx similarity index 100% rename from apps/sim/app/w/marketplace/constants/categories.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/constants/categories.tsx diff --git a/apps/sim/app/w/marketplace/marketplace.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/marketplace.tsx similarity index 100% rename from apps/sim/app/w/marketplace/marketplace.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/marketplace.tsx diff --git a/apps/sim/app/w/marketplace/page.tsx b/apps/sim/app/workspace/[workspace]/w/marketplace/page.tsx similarity index 100% rename from apps/sim/app/w/marketplace/page.tsx rename to apps/sim/app/workspace/[workspace]/w/marketplace/page.tsx diff --git a/apps/sim/app/w/page.tsx b/apps/sim/app/workspace/[workspace]/w/page.tsx similarity index 81% rename from apps/sim/app/w/page.tsx rename to apps/sim/app/workspace/[workspace]/w/page.tsx index fea6f1d2df9..f23d73471ce 100644 --- a/apps/sim/app/w/page.tsx +++ b/apps/sim/app/workspace/[workspace]/w/page.tsx @@ -4,9 +4,10 @@ import { useEffect } from 'react' import { useRouter } from 'next/navigation' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' -export default function WorkflowsPage() { +export default function WorkflowsPage({ params }: { params: { workspace: string } }) { const router = useRouter() const { workflows, isLoading } = useWorkflowRegistry() + const workspaceId = params.workspace useEffect(() => { // Wait for workflows to load @@ -16,7 +17,7 @@ export default function WorkflowsPage() { // If we have workflows, redirect to the first one if (workflowIds.length > 0) { - router.replace(`/w/${workflowIds[0]}`) + router.replace(`/workspace/${workspaceId}/w/${workflowIds[0]}`) return } @@ -24,7 +25,7 @@ export default function WorkflowsPage() { // or the user doesn't have any workspaces. Redirect to home to let the system // handle workspace/workflow creation properly. router.replace('/') - }, [workflows, isLoading, router]) + }, [workflows, isLoading, router, workspaceId]) // Show loading state while determining where to redirect return ( diff --git a/apps/sim/app/workspace/page.tsx b/apps/sim/app/workspace/page.tsx new file mode 100644 index 00000000000..97e98d50041 --- /dev/null +++ b/apps/sim/app/workspace/page.tsx @@ -0,0 +1,108 @@ +'use client' + +import { useEffect } from 'react' +import { useRouter } from 'next/navigation' +import { useSession } from '@/lib/auth-client' +import { createLogger } from '@/lib/logs/console-logger' + +const logger = createLogger('WorkspacePage') + +export default function WorkspacePage() { + const router = useRouter() + const { data: session, isPending } = useSession() + + useEffect(() => { + const redirectToFirstWorkspace = async () => { + // Wait for session to load + if (isPending) { + return + } + + // If user is not authenticated, redirect to login + if (!session?.user) { + logger.info('User not authenticated, redirecting to login') + router.replace('/login') + return + } + + try { + // Check if we need to redirect a specific workflow from old URL format + const urlParams = new URLSearchParams(window.location.search) + const redirectWorkflowId = urlParams.get('redirect_workflow') + + if (redirectWorkflowId) { + // Try to get the workspace for this workflow + try { + const workflowResponse = await fetch(`/api/workflows/${redirectWorkflowId}`) + if (workflowResponse.ok) { + const workflowData = await workflowResponse.json() + const workspaceId = workflowData.data?.workspaceId + + if (workspaceId) { + logger.info( + `Redirecting workflow ${redirectWorkflowId} to workspace ${workspaceId}` + ) + router.replace(`/workspace/${workspaceId}/w/${redirectWorkflowId}`) + return + } + } + } catch (error) { + logger.error('Error fetching workflow for redirect:', error) + } + } + + // Fetch user's workspaces + const response = await fetch('/api/workspaces') + + if (!response.ok) { + throw new Error('Failed to fetch workspaces') + } + + const data = await response.json() + const workspaces = data.workspaces || [] + + if (workspaces.length === 0) { + logger.warn('No workspaces found for user') + // Could potentially create a default workspace here or redirect to a create workspace page + // For now, we'll just log the issue + return + } + + // Get the first workspace (they should be ordered by most recent) + const firstWorkspace = workspaces[0] + logger.info(`Redirecting to first workspace: ${firstWorkspace.id}`) + + // Redirect to the first workspace + router.replace(`/workspace/${firstWorkspace.id}/w`) + } catch (error) { + logger.error('Error fetching workspaces for redirect:', error) + // Don't redirect if there's an error - let the user stay on the page + } + } + + // Only run this logic when we're at the root /workspace path + // If we're already in a specific workspace, the children components will handle it + if (typeof window !== 'undefined' && window.location.pathname === '/workspace') { + redirectToFirstWorkspace() + } + }, [session, isPending, router]) + + // Show loading state while we determine where to redirect + if (isPending) { + return ( +
+
+
+

Loading workspace...

+
+
+ ) + } + + // If user is not authenticated, show nothing (redirect will happen) + if (!session?.user) { + return null + } + + return null +} diff --git a/apps/sim/components/ui/tag-dropdown.tsx b/apps/sim/components/ui/tag-dropdown.tsx index 78c9bf0a146..12fe17a4efd 100644 --- a/apps/sim/components/ui/tag-dropdown.tsx +++ b/apps/sim/components/ui/tag-dropdown.tsx @@ -2,7 +2,10 @@ import type React from 'react' import { useCallback, useEffect, useMemo, useState } from 'react' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { type ConnectedBlock, useBlockConnections } from '@/app/w/[id]/hooks/use-block-connections' +import { + type ConnectedBlock, + useBlockConnections, +} from '@/app/workspace/[workspace]/w/[id]/hooks/use-block-connections' import { getBlock } from '@/blocks' import { useVariablesStore } from '@/stores/panel/variables/store' import type { Variable } from '@/stores/panel/variables/types' diff --git a/apps/sim/lib/logs/trace-spans.ts b/apps/sim/lib/logs/trace-spans.ts index eed9418a59f..5279536dda5 100644 --- a/apps/sim/lib/logs/trace-spans.ts +++ b/apps/sim/lib/logs/trace-spans.ts @@ -1,4 +1,4 @@ -import type { TraceSpan } from '@/app/w/logs/stores/types' +import type { TraceSpan } from '@/app/workspace/[workspace]/w/logs/stores/types' import type { ExecutionResult } from '@/executor/types' // Helper function to build a tree of trace spans from execution logs diff --git a/apps/sim/middleware.ts b/apps/sim/middleware.ts index 6e958c91d16..286620c31b1 100644 --- a/apps/sim/middleware.ts +++ b/apps/sim/middleware.ts @@ -44,13 +44,24 @@ export async function middleware(request: NextRequest) { return NextResponse.rewrite(new URL(`/chat/${subdomain}${url.pathname}`, request.url)) } - // Check if the path is exactly /w - if (url.pathname === '/w') { - return NextResponse.redirect(new URL('/w/1', request.url)) + // Legacy redirect: /w -> /workspace (will be handled by workspace layout) + if (url.pathname === '/w' || url.pathname.startsWith('/w/')) { + // Extract workflow ID if present + const pathParts = url.pathname.split('/') + if (pathParts.length >= 3 && pathParts[1] === 'w') { + const workflowId = pathParts[2] + // Redirect old workflow URLs to new format + // We'll need to resolve the workspace ID for this workflow + return NextResponse.redirect( + new URL(`/workspace?redirect_workflow=${workflowId}`, request.url) + ) + } + // Simple /w redirect to workspace root + return NextResponse.redirect(new URL('/workspace', request.url)) } // Handle protected routes that require authentication - if (url.pathname.startsWith('/w/') || url.pathname === '/w') { + if (url.pathname.startsWith('/workspace')) { if (!hasActiveSession) { return NextResponse.redirect(new URL('/login', request.url)) } @@ -137,8 +148,9 @@ export async function middleware(request: NextRequest) { // Update matcher to include invitation routes export const config = { matcher: [ - '/w', // Match exactly /w - '/w/:path*', // Match protected routes + '/w', // Legacy /w redirect + '/w/:path*', // Legacy /w/* redirects + '/workspace/:path*', // New workspace routes '/login', '/signup', '/invite/:path*', // Match invitation routes From 82905dbcca7aa4cbaec428785b5a92731af40938 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Tue, 24 Jun 2025 17:25:34 +0000 Subject: [PATCH 03/20] refactor: get rid of the old local way of storing active workspace and depend on params --- apps/sim/app/workspace/[workspace]/page.tsx | 11 + .../components/control-bar/control-bar.tsx | 4 +- .../w/[id]/components/toolbar/toolbar.tsx | 7 +- .../workspace-permissions-provider.tsx | 7 +- .../components/create-menu/create-menu.tsx | 9 +- .../folder-context-menu.tsx | 11 +- .../folder-tree/components/folder-item.tsx | 6 +- .../components/folder-tree/folder-tree.tsx | 15 +- .../components/invite-modal/invite-modal.tsx | 28 +-- .../invites-sent/invites-sent.tsx | 11 +- .../workflow-list/workflow-list.tsx | 6 +- .../workspace-header/workspace-header.tsx | 30 ++- .../w/components/sidebar/sidebar.tsx | 11 +- .../w/hooks/use-registry-loading.ts | 29 +-- .../components/filters/components/folder.tsx | 13 +- apps/sim/app/workspace/[workspace]/w/page.tsx | 5 +- apps/sim/stores/folders/store.ts | 8 +- apps/sim/stores/workflows/index.ts | 10 +- apps/sim/stores/workflows/registry/store.ts | 191 +++--------------- apps/sim/stores/workflows/registry/types.ts | 6 +- 20 files changed, 138 insertions(+), 280 deletions(-) create mode 100644 apps/sim/app/workspace/[workspace]/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/page.tsx b/apps/sim/app/workspace/[workspace]/page.tsx new file mode 100644 index 00000000000..f1b7ace0d6b --- /dev/null +++ b/apps/sim/app/workspace/[workspace]/page.tsx @@ -0,0 +1,11 @@ +import { redirect } from 'next/navigation' + +interface WorkspacePageProps { + params: { + workspace: string + } +} + +export default function WorkspacePage({ params }: WorkspacePageProps) { + redirect(`/workspace/${params.workspace}/w`) +} diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx index ea9b709720c..80c97986dfc 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx @@ -102,7 +102,7 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { workflows, updateWorkflow, activeWorkflowId, - activeWorkspaceId, + removeWorkflow, duplicateWorkflow, setDeploymentStatus, @@ -114,7 +114,7 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { // Get current workflow and workspace ID for permissions const currentWorkflow = activeWorkflowId ? workflows[activeWorkflowId] : null - // User permissions - use stable activeWorkspaceId from registry instead of deriving from currentWorkflow + // User permissions const userPermissions = useUserPermissionsContext() // Debug mode state diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx index c46772d3b5a..8265c59c9d3 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx +++ b/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx @@ -43,16 +43,15 @@ export const Toolbar = React.memo(() => { const params = useParams() const workflowId = params?.id as string - // Get the workspace ID from the workflow registry - const { activeWorkspaceId, workflows } = useWorkflowRegistry() + // Get the workspace ID from URL params + const { workflows } = useWorkflowRegistry() + const workspaceId = params.workspace as string const currentWorkflow = useMemo( () => (workflowId ? workflows[workflowId] : null), [workflowId, workflows] ) - const workspaceId = currentWorkflow?.workspaceId || activeWorkspaceId - const userPermissions = useUserPermissionsContext() const [activeTab, setActiveTab] = useState('blocks') diff --git a/apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx b/apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx index 77b4dfbf5d8..27196faa830 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx @@ -1,12 +1,12 @@ 'use client' import React, { createContext, useContext, useMemo } from 'react' +import { useParams } from 'next/navigation' import { useUserPermissions, type WorkspaceUserPermissions } from '@/hooks/use-user-permissions' import { useWorkspacePermissions, type WorkspacePermissions, } from '@/hooks/use-workspace-permissions' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' interface WorkspacePermissionsContextType { // Raw workspace permissions data @@ -27,7 +27,8 @@ interface WorkspacePermissionsProviderProps { const WorkspacePermissionsProvider = React.memo( ({ children }) => { - const { activeWorkspaceId } = useWorkflowRegistry() + const params = useParams() + const workspaceId = params.workspace as string // Fetch workspace permissions once const { @@ -35,7 +36,7 @@ const WorkspacePermissionsProvider = React.memo void @@ -22,7 +22,8 @@ export function CreateMenu({ onCreateWorkflow, isCollapsed }: CreateMenuProps) { const [isCreating, setIsCreating] = useState(false) const [isHoverOpen, setIsHoverOpen] = useState(false) - const { activeWorkspaceId } = useWorkflowRegistry() + const params = useParams() + const workspaceId = params.workspace as string const { createFolder } = useFolderStore() const handleCreateWorkflow = () => { @@ -37,13 +38,13 @@ export function CreateMenu({ onCreateWorkflow, isCollapsed }: CreateMenuProps) { const handleFolderSubmit = async (e: React.FormEvent) => { e.preventDefault() - if (!folderName.trim() || !activeWorkspaceId) return + if (!folderName.trim() || !workspaceId) return setIsCreating(true) try { await createFolder({ name: folderName.trim(), - workspaceId: activeWorkspaceId, + workspaceId: workspaceId, }) setFolderName('') setShowFolderDialog(false) diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx index fcda8a79bec..bf18707b248 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx @@ -2,6 +2,7 @@ import { useState } from 'react' import { File, Folder, MoreHorizontal, Pencil, Trash2 } from 'lucide-react' +import { useParams } from 'next/navigation' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { @@ -14,7 +15,6 @@ import { import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { useFolderStore } from '@/stores/folders/store' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' interface FolderContextMenuProps { folderId: string @@ -37,8 +37,9 @@ export function FolderContextMenu({ const [renameName, setRenameName] = useState(folderName) const [isCreating, setIsCreating] = useState(false) const [isRenaming, setIsRenaming] = useState(false) + const params = useParams() + const workspaceId = params.workspace as string - const { activeWorkspaceId } = useWorkflowRegistry() const { createFolder, updateFolder, deleteFolder } = useFolderStore() const handleCreateWorkflow = () => { @@ -59,19 +60,19 @@ export function FolderContextMenu({ onDelete(folderId) } else { // Default delete behavior - deleteFolder(folderId) + deleteFolder(folderId, workspaceId) } } const handleSubfolderSubmit = async (e: React.FormEvent) => { e.preventDefault() - if (!subfolderName.trim() || !activeWorkspaceId) return + if (!subfolderName.trim() || !workspaceId) return setIsCreating(true) try { await createFolder({ name: subfolderName.trim(), - workspaceId: activeWorkspaceId, + workspaceId: workspaceId, parentId: folderId, }) setSubfolderName('') diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx index db9ffe073a2..f6e355a8c9c 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx @@ -3,6 +3,7 @@ import { useCallback, useEffect, useRef, useState } from 'react' import clsx from 'clsx' import { ChevronDown, ChevronRight, Folder, FolderOpen } from 'lucide-react' +import { useParams } from 'next/navigation' import { AlertDialog, AlertDialogAction, @@ -39,7 +40,8 @@ export function FolderItem({ const { expandedFolders, toggleExpanded, updateFolderAPI, deleteFolder } = useFolderStore() const [showDeleteDialog, setShowDeleteDialog] = useState(false) const [isDeleting, setIsDeleting] = useState(false) - + const params = useParams() + const workspaceId = params.workspace as string const isExpanded = expandedFolders.has(folder.id) const updateTimeoutRef = useRef | undefined>(undefined) const pendingStateRef = useRef(null) @@ -87,7 +89,7 @@ export function FolderItem({ const confirmDelete = async () => { setIsDeleting(true) try { - await deleteFolder(folder.id) + await deleteFolder(folder.id, workspaceId) setShowDeleteDialog(false) } catch (error) { console.error('Failed to delete folder:', error) diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/folder-tree.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/folder-tree.tsx index 0c48f832131..b8342bc21f4 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/folder-tree.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/folder-tree.tsx @@ -164,7 +164,6 @@ export function FolderTree({ const pathname = usePathname() const params = useParams() const workspaceId = params.workspace as string - const { activeWorkspaceId } = useWorkflowRegistry() const { getFolderTree, expandedFolders, @@ -176,16 +175,16 @@ export function FolderTree({ // Fetch folders when workspace changes useEffect(() => { - if (activeWorkspaceId) { - fetchFolders(activeWorkspaceId) + if (workspaceId) { + fetchFolders(workspaceId) } - }, [activeWorkspaceId, fetchFolders]) + }, [workspaceId, fetchFolders]) useEffect(() => { clearSelection() - }, [activeWorkspaceId, clearSelection]) + }, [workspaceId, clearSelection]) - const folderTree = activeWorkspaceId ? getFolderTree(activeWorkspaceId) : [] + const folderTree = workspaceId ? getFolderTree(workspaceId) : [] // Group workflows by folder const workflowsByFolder = regularWorkflows.reduce( @@ -298,8 +297,8 @@ export function FolderTree({ folderTree.length === 0 && !isCollapsed && (
- No workflows or folders in {activeWorkspaceId ? 'this workspace' : 'your account'}. - Create one to get started. + No workflows or folders in {workspaceId ? 'this workspace' : 'your account'}. Create one + to get started.
)}
diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invite-modal.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invite-modal.tsx index 43cc6fac2be..bffada6c10a 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invite-modal.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invite-modal.tsx @@ -2,6 +2,7 @@ import React, { type KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react' import { HelpCircle, Loader2, X } from 'lucide-react' +import { useParams } from 'next/navigation' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Input } from '@/components/ui/input' @@ -18,7 +19,6 @@ import { } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' import type { WorkspacePermissions } from '@/hooks/use-workspace-permissions' import { API_ENDPOINTS } from '@/stores/constants' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' const logger = createLogger('InviteModal') @@ -397,7 +397,9 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { const [showSent, setShowSent] = useState(false) const [errorMessage, setErrorMessage] = useState(null) const [successMessage, setSuccessMessage] = useState(null) - const { activeWorkspaceId } = useWorkflowRegistry() + const params = useParams() + const workspaceId = params.workspace as string + const { data: session } = useSession() const { workspacePermissions, @@ -410,7 +412,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { const hasNewInvites = emails.length > 0 || inputValue.trim() const fetchPendingInvitations = useCallback(async () => { - if (!activeWorkspaceId) return + if (!workspaceId) return setIsPendingInvitationsLoading(true) try { @@ -421,7 +423,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { data.invitations ?.filter( (inv: PendingInvitation) => - inv.status === 'pending' && inv.workspaceId === activeWorkspaceId + inv.status === 'pending' && inv.workspaceId === workspaceId ) .map((inv: PendingInvitation) => ({ email: inv.email, @@ -436,10 +438,10 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { } finally { setIsPendingInvitationsLoading(false) } - }, [activeWorkspaceId]) + }, [workspaceId]) useEffect(() => { - if (open && activeWorkspaceId) { + if (open && workspaceId) { fetchPendingInvitations() } }, [open, fetchPendingInvitations]) @@ -535,7 +537,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { ) const handleSaveChanges = useCallback(async () => { - if (!userPerms.canAdmin || !hasPendingChanges || !activeWorkspaceId) return + if (!userPerms.canAdmin || !hasPendingChanges || !workspaceId) return setIsSaving(true) setErrorMessage(null) @@ -546,7 +548,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { permissions: changes.permissionType || 'read', })) - const response = await fetch(API_ENDPOINTS.WORKSPACE_PERMISSIONS(activeWorkspaceId), { + const response = await fetch(API_ENDPOINTS.WORKSPACE_PERMISSIONS(workspaceId), { method: 'PATCH', headers: { 'Content-Type': 'application/json', @@ -583,7 +585,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { }, [ userPerms.canAdmin, hasPendingChanges, - activeWorkspaceId, + workspaceId, existingUserPermissionChanges, updatePermissions, ]) @@ -646,7 +648,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { setErrorMessage(null) setSuccessMessage(null) - if (emails.length === 0 || !activeWorkspaceId) { + if (emails.length === 0 || !workspaceId) { return } @@ -667,7 +669,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { 'Content-Type': 'application/json', }, body: JSON.stringify({ - workspaceId: activeWorkspaceId, + workspaceId, email: email, role: 'member', permission: permissionType, @@ -739,7 +741,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { inputValue, addEmail, emails, - activeWorkspaceId, + workspaceId, userPermissions, invalidEmails, fetchPendingInvitations, @@ -922,7 +924,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { !hasNewInvites || isSubmitting || isSaving || - !activeWorkspaceId + !workspaceId } className={cn( 'ml-auto gap-2 font-medium', diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx index dc04a9e719c..ab8711d7820 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx @@ -1,6 +1,7 @@ 'use client' import { useEffect, useState } from 'react' +import { useParams } from 'next/navigation' import { Skeleton } from '@/components/ui/skeleton' import { Table, @@ -11,7 +12,6 @@ import { TableRow, } from '@/components/ui/table' import { createLogger } from '@/lib/logs/console-logger' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' const logger = createLogger('InvitesSent') @@ -47,11 +47,12 @@ export function InvitesSent() { const [invitations, setInvitations] = useState([]) const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState(null) - const { activeWorkspaceId } = useWorkflowRegistry() + const params = useParams() + const workspaceId = params.workspace as string useEffect(() => { async function fetchInvitations() { - if (!activeWorkspaceId) { + if (!workspaceId) { setIsLoading(false) return } @@ -82,7 +83,7 @@ export function InvitesSent() { } fetchInvitations() - }, [activeWorkspaceId]) + }, [workspaceId]) const TableSkeleton = () => (
@@ -106,7 +107,7 @@ export function InvitesSent() { ) } - if (!activeWorkspaceId) { + if (!workspaceId) { return null } diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workflow-list/workflow-list.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workflow-list/workflow-list.tsx index 41e8f445126..1c95c66ee56 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workflow-list/workflow-list.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workflow-list/workflow-list.tsx @@ -6,7 +6,6 @@ import Link from 'next/link' import { useParams, usePathname } from 'next/navigation' import { Skeleton } from '@/components/ui/skeleton' import { useSession } from '@/lib/auth-client' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { WorkflowMetadata } from '@/stores/workflows/registry/types' interface WorkflowItemProps { @@ -62,7 +61,6 @@ export function WorkflowList({ const pathname = usePathname() const params = useParams() const workspaceId = params.workspace as string - const { activeWorkspaceId } = useWorkflowRegistry() const { data: session } = useSession() // Generate skeleton items for loading state @@ -137,8 +135,8 @@ export function WorkflowList({ {/* Empty state */} {showEmptyState && !isCollapsed && (
- No workflows in {activeWorkspaceId ? 'this workspace' : 'your account'}. Create one to - get started. + No workflows in {workspaceId ? 'this workspace' : 'your account'}. Create one to get + started.
)} diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx index d540c17e4ec..7d5044c246a 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx @@ -3,7 +3,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react' import { ChevronDown, Pencil, Trash2, X } from 'lucide-react' import Link from 'next/link' -import { useRouter } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { AgentIcon } from '@/components/icons' import { AlertDialog, @@ -254,7 +254,9 @@ export const WorkspaceHeader = React.memo( const router = useRouter() // Get workflowRegistry state and actions - const { activeWorkspaceId, switchToWorkspace, setActiveWorkspaceId } = useWorkflowRegistry() + const { switchToWorkspace } = useWorkflowRegistry() + const params = useParams() + const currentWorkspaceId = params.workspace as string // Get user permissions for the active workspace const userPermissions = useUserPermissionsContext() @@ -289,30 +291,36 @@ export const WorkspaceHeader = React.memo( const fetchedWorkspaces = data.workspaces as Workspace[] setWorkspaces(fetchedWorkspaces) - // Only update workspace if we have a valid activeWorkspaceId from registry - if (activeWorkspaceId) { + // Only update workspace if we have a valid currentWorkspaceId from URL + if (currentWorkspaceId) { const matchingWorkspace = fetchedWorkspaces.find( - (workspace) => workspace.id === activeWorkspaceId + (workspace) => workspace.id === currentWorkspaceId ) if (matchingWorkspace) { setActiveWorkspace(matchingWorkspace) } else { - // Active workspace not found, fallback to first workspace - const fallbackWorkspace = fetchedWorkspaces[0] - if (fallbackWorkspace) { + // Log the mismatch for debugging + console.warn(`Workspace ${currentWorkspaceId} not found in user's workspaces`) + + // Current workspace not found, fallback to first workspace + if (fetchedWorkspaces.length > 0) { + const fallbackWorkspace = fetchedWorkspaces[0] setActiveWorkspace(fallbackWorkspace) - setActiveWorkspaceId(fallbackWorkspace.id) + // Navigate to the fallback workspace + router.push(`/workspace/${fallbackWorkspace.id}/w`) + } else { + // No workspaces available - handle this edge case + console.error('No workspaces available for user') } } } - // If no activeWorkspaceId, let loadWorkspaceFromWorkflowId handle workspace selection } } catch (err) { console.error('Error fetching workspaces:', err) } finally { setIsWorkspacesLoading(false) } - }, [activeWorkspaceId, setActiveWorkspaceId]) + }, [currentWorkspaceId, router]) useEffect(() => { // Fetch subscription status if user is logged in diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx index 667c4bdca97..b367943bc4e 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx @@ -34,12 +34,7 @@ export function Sidebar() { useRegistryLoading() useGlobalShortcuts() - const { - workflows, - activeWorkspaceId, - createWorkflow, - isLoading: workflowsLoading, - } = useWorkflowRegistry() + const { workflows, createWorkflow, isLoading: workflowsLoading } = useWorkflowRegistry() const { isPending: sessionLoading } = useSession() const userPermissions = useUserPermissionsContext() const isLoading = workflowsLoading || sessionLoading @@ -71,7 +66,7 @@ export function Sidebar() { if (!isLoading) { Object.values(workflows).forEach((workflow) => { - if (workflow.workspaceId === activeWorkspaceId || !workflow.workspaceId) { + if (workflow.workspaceId === workspaceId || !workflow.workspaceId) { if (workflow.marketplaceData?.status === 'temp') { temp.push(workflow) } else { @@ -98,7 +93,7 @@ export function Sidebar() { } return { regularWorkflows: regular, tempWorkflows: temp } - }, [workflows, isLoading, activeWorkspaceId]) + }, [workflows, isLoading, workspaceId]) // Create workflow handler const handleCreateWorkflow = async (folderId?: string) => { diff --git a/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts b/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts index 168323ddde6..3211b62cb79 100644 --- a/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts +++ b/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts @@ -34,40 +34,33 @@ function extractWorkflowIdFromPathname(pathname: string): string | null { * Custom hook to manage workflow registry loading state and handle first-time navigation * * This hook initializes the loading state and automatically clears it - * when workflows are loaded. It also handles smart workspace selection - * and navigation for first-time users. + * when workflows are loaded. It also handles navigation for first-time users. */ export function useRegistryLoading() { - const { workflows, setLoading, isLoading, activeWorkspaceId, loadWorkspaceFromWorkflowId } = - useWorkflowRegistry() + const { workflows, setLoading, isLoading, loadWorkflows } = useWorkflowRegistry() const pathname = usePathname() const router = useRouter() const params = useParams() const workspaceId = params.workspace as string - // Handle workspace selection from URL + // Load workflows for current workspace useEffect(() => { - if (!activeWorkspaceId) { - const workflowIdFromUrl = extractWorkflowIdFromPathname(pathname) - if (workflowIdFromUrl) { - loadWorkspaceFromWorkflowId(workflowIdFromUrl).catch((error) => { - logger.warn('Failed to load workspace from workflow ID:', error) - }) - } + if (workspaceId) { + loadWorkflows(workspaceId).catch((error) => { + logger.warn('Failed to load workflows for workspace:', error) + }) } - }, [activeWorkspaceId, pathname, loadWorkspaceFromWorkflowId]) + }, [workspaceId, loadWorkflows]) // Handle first-time navigation: if we're at /w and have workflows, navigate to first one useEffect(() => { - if (!isLoading && activeWorkspaceId && Object.keys(workflows).length > 0) { - const workflowCount = Object.keys(workflows).length + if (!isLoading && workspaceId && Object.keys(workflows).length > 0) { const currentWorkflowId = extractWorkflowIdFromPathname(pathname) // Check if we're on the workspace root and need to redirect to first workflow if ( (pathname === `/workspace/${workspaceId}/w` || - pathname === `/workspace/${workspaceId}/w/` || - pathname === `/workspace/${workspaceId}/w/${activeWorkspaceId}`) && + pathname === `/workspace/${workspaceId}/w/`) && Object.keys(workflows).length > 0 ) { const firstWorkflowId = Object.keys(workflows)[0] @@ -75,7 +68,7 @@ export function useRegistryLoading() { router.replace(`/workspace/${workspaceId}/w/${firstWorkflowId}`) } } - }, [isLoading, activeWorkspaceId, workflows, pathname, router]) + }, [isLoading, workspaceId, workflows, pathname, router]) // Handle loading states useEffect(() => { diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx index 1e4d59b5e38..68e412f2bdc 100644 --- a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx +++ b/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react' import { Check, ChevronDown, Folder } from 'lucide-react' +import { useParams } from 'next/navigation' import { Button } from '@/components/ui/button' import { DropdownMenu, @@ -10,7 +11,6 @@ import { } from '@/components/ui/dropdown-menu' import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' import { useFolderStore } from '@/stores/folders/store' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' interface FolderOption { id: string @@ -22,7 +22,8 @@ interface FolderOption { export default function FolderFilter() { const { folderIds, toggleFolderId, setFolderIds } = useFilterStore() const { getFolderTree, getFolderPath, fetchFolders } = useFolderStore() - const { activeWorkspaceId } = useWorkflowRegistry() + const params = useParams() + const workspaceId = params.workspace as string const [folders, setFolders] = useState([]) const [loading, setLoading] = useState(true) @@ -31,9 +32,9 @@ export default function FolderFilter() { const fetchFoldersData = async () => { try { setLoading(true) - if (activeWorkspaceId) { - await fetchFolders(activeWorkspaceId) - const folderTree = getFolderTree(activeWorkspaceId) + if (workspaceId) { + await fetchFolders(workspaceId) + const folderTree = getFolderTree(workspaceId) // Flatten the folder tree and create options with full paths const flattenFolders = (nodes: any[], parentPath = ''): FolderOption[] => { @@ -68,7 +69,7 @@ export default function FolderFilter() { } fetchFoldersData() - }, [activeWorkspaceId, fetchFolders, getFolderTree]) + }, [workspaceId, fetchFolders, getFolderTree]) // Get display text for the dropdown button const getSelectedFoldersText = () => { diff --git a/apps/sim/app/workspace/[workspace]/w/page.tsx b/apps/sim/app/workspace/[workspace]/w/page.tsx index f23d73471ce..bcdd47eb14d 100644 --- a/apps/sim/app/workspace/[workspace]/w/page.tsx +++ b/apps/sim/app/workspace/[workspace]/w/page.tsx @@ -1,12 +1,13 @@ 'use client' import { useEffect } from 'react' -import { useRouter } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' -export default function WorkflowsPage({ params }: { params: { workspace: string } }) { +export default function WorkflowsPage() { const router = useRouter() const { workflows, isLoading } = useWorkflowRegistry() + const params = useParams() const workspaceId = params.workspace useEffect(() => { diff --git a/apps/sim/stores/folders/store.ts b/apps/sim/stores/folders/store.ts index efa25f2ef79..57ad937eb4f 100644 --- a/apps/sim/stores/folders/store.ts +++ b/apps/sim/stores/folders/store.ts @@ -71,7 +71,7 @@ interface FolderState { color?: string }) => Promise updateFolderAPI: (id: string, updates: Partial) => Promise - deleteFolder: (id: string) => Promise + deleteFolder: (id: string, workspaceId: string) => Promise // Helper functions isWorkflowInDeletedSubfolder: (workflow: Workflow, deletedFolderId: string) => boolean @@ -304,7 +304,7 @@ export const useFolderStore = create()( return processedFolder }, - deleteFolder: async (id: string) => { + deleteFolder: async (id: string, workspaceId: string) => { const response = await fetch(`/api/folders/${id}`, { method: 'DELETE' }) if (!response.ok) { @@ -346,9 +346,9 @@ export const useFolderStore = create()( } } - if (workflowRegistry.activeWorkspaceId) { + if (workspaceId) { // Trigger workflow refresh through registry store - await workflowRegistry.switchToWorkspace(workflowRegistry.activeWorkspaceId) + await workflowRegistry.switchToWorkspace(workspaceId) } }, diff --git a/apps/sim/stores/workflows/index.ts b/apps/sim/stores/workflows/index.ts index 161957de7c7..03338206c95 100644 --- a/apps/sim/stores/workflows/index.ts +++ b/apps/sim/stores/workflows/index.ts @@ -88,7 +88,7 @@ export function getBlockWithValues(blockId: string): BlockState | null { * @returns An object containing workflows, with state only for the active workflow */ export function getAllWorkflowsWithValues() { - const { workflows, activeWorkspaceId } = useWorkflowRegistry.getState() + const { workflows } = useWorkflowRegistry.getState() const result: Record = {} const activeWorkflowId = useWorkflowRegistry.getState().activeWorkflowId const currentState = useWorkflowStore.getState() @@ -97,14 +97,6 @@ export function getAllWorkflowsWithValues() { if (activeWorkflowId && workflows[activeWorkflowId]) { const metadata = workflows[activeWorkflowId] - // Skip if workflow doesn't belong to the active workspace - if (activeWorkspaceId && metadata.workspaceId !== activeWorkspaceId) { - logger.debug( - `Skipping active workflow ${activeWorkflowId} - belongs to workspace ${metadata.workspaceId}, not active workspace ${activeWorkspaceId}` - ) - return result - } - // Get deployment status from registry const deploymentStatus = useWorkflowRegistry .getState() diff --git a/apps/sim/stores/workflows/registry/store.ts b/apps/sim/stores/workflows/registry/store.ts index 0ce08f959d5..0614e031580 100644 --- a/apps/sim/stores/workflows/registry/store.ts +++ b/apps/sim/stores/workflows/registry/store.ts @@ -16,7 +16,7 @@ const logger = createLogger('WorkflowRegistry') let isFetching = false let lastFetchTimestamp = 0 -async function fetchWorkflowsFromDB(): Promise { +async function fetchWorkflowsFromDB(workspaceId?: string): Promise { if (typeof window === 'undefined') return // Prevent concurrent fetch operations @@ -31,11 +31,10 @@ async function fetchWorkflowsFromDB(): Promise { try { useWorkflowRegistry.getState().setLoading(true) - const activeWorkspaceId = useWorkflowRegistry.getState().activeWorkspaceId const url = new URL(API_ENDPOINTS.SYNC, window.location.origin) - if (activeWorkspaceId) { - url.searchParams.append('workspaceId', activeWorkspaceId) + if (workspaceId) { + url.searchParams.append('workspaceId', workspaceId) } const response = await fetch(url.toString(), { method: 'GET' }) @@ -99,10 +98,7 @@ async function fetchWorkflowsFromDB(): Promise { apiKey, } = workflow - // Skip if workflow doesn't belong to active workspace - if (activeWorkspaceId && workspaceId !== activeWorkspaceId) { - return - } + // No need to filter by workspace since we're already fetching for specific workspace // Add to registry registryWorkflows[id] = { @@ -256,7 +252,6 @@ export const useWorkflowRegistry = create()( // Store state workflows: {}, activeWorkflowId: null, - activeWorkspaceId: null, // No longer persisted in localStorage isLoading: true, error: null, // Initialize deployment statuses @@ -270,24 +265,17 @@ export const useWorkflowRegistry = create()( }, // Simple method to load workflows (replaces sync system) - loadWorkflows: async () => { - await fetchWorkflowsFromDB() + loadWorkflows: async (workspaceId?: string) => { + await fetchWorkflowsFromDB(workspaceId) }, // Handle cleanup on workspace deletion handleWorkspaceDeletion: async (newWorkspaceId: string) => { - const currentWorkspaceId = get().activeWorkspaceId - - if (!newWorkspaceId || newWorkspaceId === currentWorkspaceId) { - logger.error('Cannot switch to invalid workspace after deletion') - return - } - // Set transition state setWorkspaceTransitioning(true) try { - logger.info(`Switching from deleted workspace ${currentWorkspaceId} to ${newWorkspaceId}`) + logger.info(`Switching to new workspace after deletion: ${newWorkspaceId}`) // Reset all workflow state resetWorkflowStores() @@ -296,12 +284,11 @@ export const useWorkflowRegistry = create()( set({ isLoading: true, workflows: {}, - activeWorkspaceId: newWorkspaceId, activeWorkflowId: null, }) // Properly await workflow fetching to prevent race conditions - await fetchWorkflowsFromDB() + await fetchWorkflowsFromDB(newWorkspaceId) set({ isLoading: false }) logger.info(`Successfully switched to workspace after deletion: ${newWorkspaceId}`) @@ -327,29 +314,17 @@ export const useWorkflowRegistry = create()( return } - const { activeWorkspaceId: currentWorkspaceId } = get() - - // Early return if switching to the same workspace (before setting flag) - if (currentWorkspaceId === workspaceId) { - logger.info(`Already in workspace ${workspaceId}`) - return - } - - // Only set transition flag AFTER validating the switch is needed + // Set transition flag setWorkspaceTransitioning(true) try { - logger.info(`Switching workspace from ${currentWorkspaceId || 'none'} to ${workspaceId}`) - - // Save to localStorage first before any async operations - get().setActiveWorkspaceId(workspaceId) + logger.info(`Switching to workspace: ${workspaceId}`) // Clear current workspace state resetWorkflowStores() - // Update workspace in state + // Update state set({ - activeWorkspaceId: workspaceId, activeWorkflowId: null, workflows: {}, isLoading: true, @@ -357,7 +332,7 @@ export const useWorkflowRegistry = create()( }) // Fetch workflows for the new workspace - await fetchWorkflowsFromDB() + await fetchWorkflowsFromDB(workspaceId) logger.info(`Successfully switched to workspace: ${workspaceId}`) } catch (error) { @@ -371,128 +346,6 @@ export const useWorkflowRegistry = create()( } }, - // Load user's last active workspace from localStorage - loadLastActiveWorkspace: async () => { - try { - const savedWorkspaceId = localStorage.getItem('lastActiveWorkspaceId') - if (!savedWorkspaceId || savedWorkspaceId === get().activeWorkspaceId) { - return // No saved workspace or already active - } - - logger.info(`Attempting to restore last active workspace: ${savedWorkspaceId}`) - - // Validate that the workspace exists by making a simple API call - try { - const response = await fetch('/api/workspaces') - if (response.ok) { - const data = await response.json() - const workspaces = data.workspaces || [] - const workspaceExists = workspaces.some((ws: any) => ws.id === savedWorkspaceId) - - if (workspaceExists) { - // Set the validated workspace ID - set({ activeWorkspaceId: savedWorkspaceId }) - logger.info(`Restored last active workspace from localStorage: ${savedWorkspaceId}`) - } else { - logger.warn( - `Saved workspace ${savedWorkspaceId} no longer exists, clearing from localStorage` - ) - localStorage.removeItem('lastActiveWorkspaceId') - } - } - } catch (apiError) { - logger.warn('Failed to validate saved workspace, will use default:', apiError) - // Don't remove from localStorage in case it's a temporary network issue - } - } catch (error) { - logger.warn('Failed to load last active workspace from localStorage:', error) - // This is non-critical, so we continue with default behavior - } - }, - - // Load workspace based on workflow ID from URL, with fallback to last active workspace - loadWorkspaceFromWorkflowId: async (workflowId: string | null) => { - try { - logger.info(`Loading workspace for workflow ID: ${workflowId}`) - - // If workflow ID provided, try to get its workspace - if (workflowId) { - try { - const response = await fetch(`/api/workflows/${workflowId}`) - if (response.ok) { - const data = await response.json() - const workflow = data.data - - if (workflow?.workspaceId) { - // Validate workspace access - const workspacesResponse = await fetch('/api/workspaces') - if (workspacesResponse.ok) { - const workspacesData = await workspacesResponse.json() - const workspaces = workspacesData.workspaces || [] - const workspaceExists = workspaces.some( - (ws: any) => ws.id === workflow.workspaceId - ) - - if (workspaceExists) { - set({ activeWorkspaceId: workflow.workspaceId }) - localStorage.setItem('lastActiveWorkspaceId', workflow.workspaceId) - logger.info(`Set active workspace from workflow: ${workflow.workspaceId}`) - return - } - } - } - } - } catch (error) { - logger.warn('Error fetching workflow:', error) - } - } - - // Fallback: use last active workspace or first available - const savedWorkspaceId = localStorage.getItem('lastActiveWorkspaceId') - const response = await fetch('/api/workspaces') - - if (response.ok) { - const data = await response.json() - const workspaces = data.workspaces || [] - - if (workspaces.length === 0) { - logger.warn('No workspaces found') - return - } - - // Try saved workspace first - let targetWorkspace = savedWorkspaceId - ? workspaces.find((ws: any) => ws.id === savedWorkspaceId) - : null - - // Fall back to first workspace - if (!targetWorkspace) { - targetWorkspace = workspaces[0] - if (savedWorkspaceId) { - localStorage.removeItem('lastActiveWorkspaceId') - } - } - - set({ activeWorkspaceId: targetWorkspace.id }) - localStorage.setItem('lastActiveWorkspaceId', targetWorkspace.id) - logger.info(`Set active workspace: ${targetWorkspace.id}`) - } - } catch (error) { - logger.error('Error in loadWorkspaceFromWorkflowId:', error) - } - }, - - // Simple method to set active workspace ID without triggering full switch - setActiveWorkspaceId: (id: string) => { - set({ activeWorkspaceId: id }) - // Save to localStorage as well - try { - localStorage.setItem('lastActiveWorkspaceId', id) - } catch (error) { - logger.warn('Failed to save workspace to localStorage:', error) - } - }, - // Method to get deployment status for a specific workflow getWorkflowDeploymentStatus: (workflowId: string | null): DeploymentStatus | null => { if (!workflowId) { @@ -735,14 +588,19 @@ export const useWorkflowRegistry = create()( * @returns The ID of the newly created workflow */ createWorkflow: async (options = {}) => { - const { workflows, activeWorkspaceId } = get() + const { workflows } = get() const id = crypto.randomUUID() - // Use provided workspace ID or fall back to active workspace ID - const workspaceId = options.workspaceId || activeWorkspaceId || undefined + // Use provided workspace ID (must be provided since we no longer track active workspace) + const workspaceId = options.workspaceId - logger.info(`Creating new workflow in workspace: ${workspaceId || 'none'}`) + if (!workspaceId) { + logger.error('Cannot create workflow without workspaceId') + set({ error: 'Workspace ID is required to create a workflow' }) + throw new Error('Workspace ID is required to create a workflow') + } + logger.info(`Creating new workflow in workspace: ${workspaceId || 'none'}`) // Generate workflow metadata with appropriate name and color const newWorkflow: WorkflowMetadata = { id, @@ -1153,7 +1011,7 @@ export const useWorkflowRegistry = create()( * Duplicates an existing workflow */ duplicateWorkflow: async (sourceId: string) => { - const { workflows, activeWorkspaceId } = get() + const { workflows } = get() const sourceWorkflow = workflows[sourceId] if (!sourceWorkflow) { @@ -1161,8 +1019,8 @@ export const useWorkflowRegistry = create()( return null } - // Get the workspace ID from the source workflow or fall back to active workspace - const workspaceId = sourceWorkflow.workspaceId || activeWorkspaceId || undefined + // Get the workspace ID from the source workflow (required) + const workspaceId = sourceWorkflow.workspaceId // Call the server to duplicate the workflow - server generates all IDs let duplicatedWorkflow @@ -1594,7 +1452,6 @@ export const useWorkflowRegistry = create()( set({ workflows: {}, activeWorkflowId: null, - activeWorkspaceId: null, isLoading: true, error: null, }) diff --git a/apps/sim/stores/workflows/registry/types.ts b/apps/sim/stores/workflows/registry/types.ts index efc854b835b..5e9234b28bb 100644 --- a/apps/sim/stores/workflows/registry/types.ts +++ b/apps/sim/stores/workflows/registry/types.ts @@ -24,7 +24,6 @@ export interface WorkflowMetadata { export interface WorkflowRegistryState { workflows: Record activeWorkflowId: string | null - activeWorkspaceId: string | null isLoading: boolean error: string | null deploymentStatuses: Record @@ -34,10 +33,7 @@ export interface WorkflowRegistryActions { setLoading: (loading: boolean) => void setActiveWorkflow: (id: string) => Promise switchToWorkspace: (id: string) => void - setActiveWorkspaceId: (id: string) => void - loadLastActiveWorkspace: () => Promise - loadWorkspaceFromWorkflowId: (workflowId: string | null) => Promise - loadWorkflows: () => Promise + loadWorkflows: (workspaceId?: string) => Promise handleWorkspaceDeletion: (newWorkspaceId: string) => void removeWorkflow: (id: string) => Promise updateWorkflow: (id: string, metadata: Partial) => Promise From f7486302a34661e2e2c0bfe2bc239dc2afcd5b15 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Tue, 24 Jun 2025 17:31:56 +0000 Subject: [PATCH 04/20] fix: import path --- apps/sim/app/(auth)/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sim/app/(auth)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index 6a81c5ba228..5c2fda1b750 100644 --- a/apps/sim/app/(auth)/layout.tsx +++ b/apps/sim/app/(auth)/layout.tsx @@ -3,7 +3,7 @@ import Image from 'next/image' import Link from 'next/link' import { GridPattern } from '../(landing)/components/grid-pattern' -import { NotificationList } from '../w/[id]/components/notifications/notifications' +import { NotificationList } from '../workspace/[workspace]/w/[id]/components/notifications/notifications' export default function AuthLayout({ children }: { children: React.ReactNode }) { return ( From f144059cdf6c9f12339d30811488ab4635020653 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Tue, 24 Jun 2025 18:43:19 +0000 Subject: [PATCH 05/20] fix: missing function and type issue --- apps/sim/app/workspace/[workspace]/page.tsx | 15 +++++----- apps/sim/stores/index.ts | 31 --------------------- 2 files changed, 7 insertions(+), 39 deletions(-) diff --git a/apps/sim/app/workspace/[workspace]/page.tsx b/apps/sim/app/workspace/[workspace]/page.tsx index f1b7ace0d6b..594ac7e8f02 100644 --- a/apps/sim/app/workspace/[workspace]/page.tsx +++ b/apps/sim/app/workspace/[workspace]/page.tsx @@ -1,11 +1,10 @@ import { redirect } from 'next/navigation' -interface WorkspacePageProps { - params: { - workspace: string - } -} - -export default function WorkspacePage({ params }: WorkspacePageProps) { - redirect(`/workspace/${params.workspace}/w`) +export default async function WorkspacePage({ + params, +}: { + params: Promise<{ workspace: string }> +}) { + const workspace = (await params).workspace + redirect(`/workspace/${workspace}/w`) } diff --git a/apps/sim/stores/index.ts b/apps/sim/stores/index.ts index 347685dce12..5c6daa3fb03 100644 --- a/apps/sim/stores/index.ts +++ b/apps/sim/stores/index.ts @@ -41,12 +41,6 @@ async function initializeApplication(): Promise { // Load custom tools from server await useCustomToolsStore.getState().loadCustomTools() - // Extract workflow ID from URL for smart workspace selection - const workflowIdFromUrl = extractWorkflowIdFromUrl() - - // Load workspace based on workflow ID in URL, with fallback to last active workspace - await useWorkflowRegistry.getState().loadWorkspaceFromWorkflowId(workflowIdFromUrl) - // Load workflows from database (replaced sync system) await useWorkflowRegistry.getState().loadWorkflows() @@ -73,31 +67,6 @@ async function initializeApplication(): Promise { } } -/** - * Extract workflow ID from current URL - * @returns workflow ID if found in URL, null otherwise - */ -function extractWorkflowIdFromUrl(): string | null { - if (typeof window === 'undefined') return null - - try { - const pathSegments = window.location.pathname.split('/') - // Check if URL matches pattern /w/{workflowId} - if (pathSegments.length >= 3 && pathSegments[1] === 'w') { - const workflowId = pathSegments[2] - // Basic UUID validation (36 characters, contains hyphens) - if (workflowId && workflowId.length === 36 && workflowId.includes('-')) { - logger.info(`Extracted workflow ID from URL: ${workflowId}`) - return workflowId - } - } - return null - } catch (error) { - logger.warn('Failed to extract workflow ID from URL:', error) - return null - } -} - /** * Checks if application is fully initialized */ From a856539ab0bca3ace95584bf07a31e9d0be767c6 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Tue, 24 Jun 2025 19:06:44 +0000 Subject: [PATCH 06/20] chore: requested changes --- apps/sim/app/(auth)/layout.tsx | 2 +- .../app/api/marketplace/workflows/route.ts | 2 +- .../{[workspace] => [workspaceId]}/page.tsx | 0 .../code-prompt-bar/code-prompt-bar.tsx | 0 .../components/chat-deploy/chat-deploy.tsx | 2 +- .../components/deploy-form/deploy-form.tsx | 0 .../components/api-endpoint/api-endpoint.tsx | 0 .../components/api-key/api-key.tsx | 0 .../deploy-status/deploy-status.tsx | 0 .../example-command/example-command.tsx | 0 .../deployment-info/deployment-info.tsx | 8 +- .../components/deploy-modal/deploy-modal.tsx | 6 +- .../components/deployed-workflow-card.tsx | 2 +- .../components/deployed-workflow-modal.tsx | 0 .../deployment-controls.test.ts | 0 .../deployment-controls.tsx | 0 .../history-dropdown-item.tsx | 0 .../marketplace-modal/marketplace-modal.tsx | 2 +- .../notification-dropdown-item.tsx | 0 .../components/user-avatar/user-avatar.tsx | 0 .../user-avatar-stack/user-avatar-stack.tsx | 0 .../control-bar/control-bar.test.ts | 0 .../components/control-bar/control-bar.tsx | 4 +- .../w/[id]/components/copilot/copilot.tsx | 0 .../w/[id]/components/error/index.tsx | 0 .../loop-node/components/loop-badges.test.tsx | 0 .../loop-node/components/loop-badges.tsx | 0 .../[id]/components/loop-node/loop-config.ts | 0 .../components/loop-node/loop-node.test.tsx | 0 .../w/[id]/components/loop-node/loop-node.tsx | 0 .../notifications/notifications.tsx | 0 .../components/panel/components/chat/chat.tsx | 0 .../components/chat-message/chat-message.tsx | 0 .../chat/components/chat-modal/chat-modal.tsx | 4 +- .../output-select/output-select.tsx | 0 .../components/audio-player/audio-player.tsx | 0 .../console-entry/console-entry.tsx | 0 .../components/json-view/json-view.tsx | 0 .../panel/components/console/console.tsx | 0 .../panel/components/variables/variables.tsx | 0 .../w/[id]/components/panel/panel.tsx | 0 .../components/parallel-badges.tsx | 0 .../parallel-node/parallel-config.ts | 0 .../parallel-node/parallel-node.test.tsx | 0 .../parallel-node/parallel-node.tsx | 0 .../skeleton-loading/skeleton-loading.tsx | 0 .../toolbar-block/toolbar-block.tsx | 0 .../toolbar-loop-block/toolbar-loop-block.tsx | 0 .../toolbar-parallel-block.tsx | 0 .../components/toolbar-tabs/toolbar-tabs.tsx | 0 .../w/[id]/components/toolbar/toolbar.tsx | 4 +- .../components/action-bar/action-bar.tsx | 0 .../connection-blocks/connection-blocks.tsx | 2 +- .../channel-selector-input.tsx | 0 .../components/slack-channel-selector.tsx | 0 .../sub-block/components/checkbox-list.tsx | 0 .../components/sub-block/components/code.tsx | 2 +- .../sub-block/components/condition-input.tsx | 0 .../components/oauth-required-modal.tsx | 0 .../credential-selector.tsx | 0 .../sub-block/components/date-input.tsx | 0 .../document-selector/document-selector.tsx | 0 .../sub-block/components/dropdown.tsx | 0 .../sub-block/components/eval-input.tsx | 0 .../components/confluence-file-selector.tsx | 0 .../components/discord-channel-selector.tsx | 0 .../components/google-calendar-selector.tsx | 0 .../components/google-drive-picker.tsx | 0 .../components/jira-issue-selector.tsx | 0 .../components/microsoft-file-selector.tsx | 0 .../components/teams-message-selector.tsx | 0 .../file-selector/file-selector-input.tsx | 0 .../sub-block/components/file-upload.tsx | 0 .../components/folder-selector-input.tsx | 0 .../folder-selector/folder-selector.tsx | 2 +- .../knowledge-base-selector.tsx | 0 .../sub-block/components/long-input.tsx | 0 .../components/discord-server-selector.tsx | 0 .../components/jira-project-selector.tsx | 0 .../components/linear-project-selector.tsx | 0 .../components/linear-team-selector.tsx | 0 .../project-selector-input.tsx | 0 .../response/components/property-renderer.tsx | 0 .../response/components/value-input.tsx | 0 .../components/response/response-format.tsx | 0 .../schedule/components/schedule-modal.tsx | 0 .../components/schedule/schedule-config.tsx | 0 .../sub-block/components/short-input.tsx | 0 .../sub-block/components/slider-input.tsx | 0 .../components/starter/input-format.tsx | 0 .../sub-block/components/switch.tsx | 0 .../components/sub-block/components/table.tsx | 0 .../sub-block/components/time-input.tsx | 0 .../components/code-editor/code-editor.tsx | 0 .../custom-tool-modal/custom-tool-modal.tsx | 2 +- .../components/tool-command/tool-command.tsx | 0 .../components/tool-input/tool-input.tsx | 0 .../webhook/components/providers/airtable.tsx | 0 .../webhook/components/providers/discord.tsx | 0 .../webhook/components/providers/generic.tsx | 0 .../webhook/components/providers/github.tsx | 0 .../webhook/components/providers/gmail.tsx | 2 +- .../webhook/components/providers/slack.tsx | 2 +- .../webhook/components/providers/stripe.tsx | 0 .../webhook/components/providers/telegram.tsx | 0 .../webhook/components/providers/whatsapp.tsx | 0 .../webhook/components/ui/config-field.tsx | 0 .../webhook/components/ui/config-section.tsx | 0 .../webhook/components/ui/confirmation.tsx | 0 .../webhook/components/ui/copyable.tsx | 0 .../components/ui/instructions-section.tsx | 0 .../webhook/components/ui/test-result.tsx | 0 .../components/ui/webhook-config-field.tsx | 0 .../webhook/components/ui/webhook-footer.tsx | 0 .../webhook/components/ui/webhook-url.tsx | 0 .../webhook/components/webhook-modal.tsx | 0 .../sub-block/components/webhook/webhook.tsx | 0 .../sub-block/hooks/use-sub-block-value.ts | 0 .../components/sub-block/sub-block.tsx | 0 .../workflow-block/workflow-block.tsx | 2 +- .../workflow-edge/workflow-edge.tsx | 0 .../w/[id]/hooks/use-block-connections.ts | 0 .../w/[id]/hooks/use-code-generation.ts | 0 .../w/[id]/hooks/use-presence.ts | 0 .../w/[id]/hooks/use-workflow-execution.ts | 0 .../w/[id]/layout.tsx | 0 .../w/[id]/page.tsx | 0 .../w/[id]/utils.ts | 0 .../w/[id]/workflow.tsx | 8 +- .../w/components/providers/providers.tsx | 0 .../w/components/providers/theme-provider.tsx | 0 .../workspace-permissions-provider.tsx | 2 +- .../components/create-menu/create-menu.tsx | 2 +- .../folder-context-menu.tsx | 2 +- .../folder-tree/components/folder-item.tsx | 2 +- .../folder-tree/components/workflow-item.tsx | 2 +- .../components/folder-tree/folder-tree.tsx | 4 +- .../components/help-form/help-form.tsx | 0 .../components/help-modal/help-modal.tsx | 0 .../components/invite-modal/invite-modal.tsx | 4 +- .../invites-sent/invites-sent.tsx | 2 +- .../components/nav-section/nav-section.tsx | 0 .../components/account/account.tsx | 0 .../components/api-keys/api-keys.tsx | 0 .../components/credentials/credentials.tsx | 0 .../components/environment/environment.tsx | 0 .../components/general/general.tsx | 0 .../components/privacy/privacy.tsx | 0 .../settings-navigation.tsx | 0 .../components/team-seats-dialog.tsx | 0 .../components/subscription/subscription.tsx | 0 .../team-management/team-management.tsx | 0 .../settings-modal/settings-modal.tsx | 0 .../sidebar-control/sidebar-control.tsx | 0 .../workflow-list/workflow-list.tsx | 4 +- .../workspace-header/workspace-header.tsx | 739 ++++++++++++++++++ .../w/components/sidebar/sidebar.tsx | 4 +- .../workflow-preview/workflow-preview.tsx | 8 +- .../w/error.tsx | 0 .../w/global-error.tsx | 0 .../w/hooks/use-keyboard-shortcuts.ts | 0 .../w/hooks/use-registry-loading.ts | 2 +- .../create-chunk-modal/create-chunk-modal.tsx | 0 .../delete-chunk-modal/delete-chunk-modal.tsx | 0 .../components/document-loading.tsx | 0 .../edit-chunk-modal/edit-chunk-modal.tsx | 0 .../knowledge/[id]/[documentId]/document.tsx | 2 +- .../w/knowledge/[id]/[documentId]/page.tsx | 0 .../w/knowledge/[id]/base.tsx | 10 +- .../[id]/components/action-bar/action-bar.tsx | 0 .../knowledge-base-loading.tsx | 0 .../w/knowledge/[id]/page.tsx | 0 .../base-overview/base-overview.tsx | 0 .../components/create-modal/create-modal.tsx | 2 +- .../empty-state-card/empty-state-card.tsx | 0 .../components/icons/document-icons.tsx | 0 .../knowledge-header/knowledge-header.tsx | 0 .../primary-button/primary-button.tsx | 0 .../components/search-input/search-input.tsx | 0 .../knowledge-base-card-skeleton.tsx | 0 .../components/skeletons/table-skeleton.tsx | 0 .../w/knowledge/knowledge.tsx | 0 .../w/knowledge/loading.tsx | 0 .../w/knowledge/page.tsx | 0 .../w/layout.tsx | 0 .../components/control-bar/control-bar.tsx | 0 .../filters/components/filter-section.tsx | 0 .../components/filters/components/folder.tsx | 4 +- .../components/filters/components/level.tsx | 4 +- .../filters/components/timeline.tsx | 4 +- .../components/filters/components/trigger.tsx | 2 +- .../filters/components/workflow.tsx | 2 +- .../w/logs/components/filters/filters.tsx | 0 .../sidebar/components/markdown-renderer.tsx | 0 .../w/logs/components/sidebar/sidebar.tsx | 4 +- .../tool-calls/tool-calls-display.tsx | 0 .../trace-spans/trace-spans-display.tsx | 0 .../w/logs/logs.tsx | 0 .../w/logs/page.tsx | 0 .../w/logs/stores/store.ts | 0 .../w/logs/stores/types.ts | 0 .../w/logs/utils/format-date.ts | 0 .../components/control-bar/control-bar.tsx | 0 .../marketplace/components/error-message.tsx | 0 .../w/marketplace/components/section.tsx | 0 .../components/toolbar/toolbar.tsx | 0 .../components/workflow-card-skeleton.tsx | 0 .../marketplace/components/workflow-card.tsx | 4 +- .../w/marketplace/constants/categories.tsx | 0 .../w/marketplace/marketplace.tsx | 0 .../w/marketplace/page.tsx | 0 .../{[workspace] => [workspaceId]}/w/page.tsx | 2 +- .../workspace-header/workspace-header.tsx | 4 +- apps/sim/components/ui/tag-dropdown.tsx | 2 +- apps/sim/lib/logs/trace-spans.ts | 2 +- 215 files changed, 811 insertions(+), 72 deletions(-) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/page.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx (89%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx (96%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/control-bar.test.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/control-bar/control-bar.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/copilot/copilot.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/error/index.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/loop-node/components/loop-badges.test.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/loop-node/components/loop-badges.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/loop-node/loop-config.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/loop-node/loop-node.test.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/loop-node/loop-node.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/notifications/notifications.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/chat/chat.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/console/components/json-view/json-view.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/console/console.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/components/variables/variables.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/panel/panel.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/parallel-node/components/parallel-badges.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/parallel-node/parallel-config.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/parallel-node/parallel-node.test.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/parallel-node/parallel-node.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/skeleton-loading/skeleton-loading.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/toolbar/toolbar.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/code.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/table.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx (97%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-block/workflow-block.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/components/workflow-edge/workflow-edge.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/hooks/use-block-connections.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/hooks/use-code-generation.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/hooks/use-presence.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/hooks/use-workflow-execution.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/layout.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/page.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/utils.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/[id]/workflow.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/providers/providers.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/providers/theme-provider.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/providers/workspace-permissions-provider.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/create-menu/create-menu.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/folder-tree/components/folder-item.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/folder-tree/components/workflow-item.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/folder-tree/folder-tree.tsx (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/help-modal/components/help-form/help-form.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/help-modal/help-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/invite-modal/invite-modal.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/nav-section/nav-section.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/account/account.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/credentials/credentials.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/environment/environment.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/general/general.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/privacy/privacy.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/settings-navigation/settings-navigation.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/settings-modal/settings-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/sidebar-control/sidebar-control.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/components/workflow-list/workflow-list.tsx (97%) create mode 100644 apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/sidebar/sidebar.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/components/workflow-preview/workflow-preview.tsx (95%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/error.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/global-error.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/hooks/use-keyboard-shortcuts.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/hooks/use-registry-loading.ts (98%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/[documentId]/components/document-loading.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/[documentId]/document.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/[documentId]/page.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/base.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/components/action-bar/action-bar.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/[id]/page.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/base-overview/base-overview.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/create-modal/create-modal.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/empty-state-card/empty-state-card.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/icons/document-icons.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/knowledge-header/knowledge-header.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/primary-button/primary-button.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/search-input/search-input.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/components/skeletons/table-skeleton.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/knowledge.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/loading.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/knowledge/page.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/layout.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/control-bar/control-bar.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/filters/components/filter-section.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/filters/components/folder.tsx (97%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/filters/components/level.tsx (91%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/filters/components/timeline.tsx (88%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/filters/components/trigger.tsx (97%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/filters/components/workflow.tsx (97%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/filters/filters.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/sidebar/components/markdown-renderer.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/sidebar/sidebar.tsx (99%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/tool-calls/tool-calls-display.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/components/trace-spans/trace-spans-display.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/logs.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/page.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/stores/store.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/stores/types.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/logs/utils/format-date.ts (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/components/control-bar/control-bar.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/components/error-message.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/components/section.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/components/toolbar/toolbar.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/components/workflow-card-skeleton.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/components/workflow-card.tsx (97%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/constants/categories.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/marketplace.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/marketplace/page.tsx (100%) rename apps/sim/app/workspace/{[workspace] => [workspaceId]}/w/page.tsx (96%) diff --git a/apps/sim/app/(auth)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index 5c2fda1b750..be1494667e2 100644 --- a/apps/sim/app/(auth)/layout.tsx +++ b/apps/sim/app/(auth)/layout.tsx @@ -3,7 +3,7 @@ import Image from 'next/image' import Link from 'next/link' import { GridPattern } from '../(landing)/components/grid-pattern' -import { NotificationList } from '../workspace/[workspace]/w/[id]/components/notifications/notifications' +import { NotificationList } from '../workspace/[workspaceId]/w/[id]/components/notifications/notifications' export default function AuthLayout({ children }: { children: React.ReactNode }) { return ( diff --git a/apps/sim/app/api/marketplace/workflows/route.ts b/apps/sim/app/api/marketplace/workflows/route.ts index 27ed728f803..fda813b4928 100644 --- a/apps/sim/app/api/marketplace/workflows/route.ts +++ b/apps/sim/app/api/marketplace/workflows/route.ts @@ -2,7 +2,7 @@ import { desc, eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { createLogger } from '@/lib/logs/console-logger' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' -import { CATEGORIES } from '@/app/workspace/[workspace]/w/marketplace/constants/categories' +import { CATEGORIES } from '@/app/workspace/[workspaceId]/w/marketplace/constants/categories' import { db } from '@/db' import * as schema from '@/db/schema' diff --git a/apps/sim/app/workspace/[workspace]/page.tsx b/apps/sim/app/workspace/[workspaceId]/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx index bcad2555072..ff8fb3f4317 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx @@ -33,7 +33,7 @@ import { Textarea } from '@/components/ui/textarea' import { createLogger } from '@/lib/logs/console-logger' import { getBaseDomain } from '@/lib/urls/utils' import { cn } from '@/lib/utils' -import { OutputSelect } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/output-select/output-select' +import { OutputSelect } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/output-select/output-select' import { useNotificationStore } from '@/stores/notifications/store' import type { OutputConfig } from '@/stores/panel/chat/types' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx similarity index 89% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx index 7cedaa2e676..592417ce9bf 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx @@ -15,10 +15,10 @@ import { } from '@/components/ui/alert-dialog' import { Button } from '@/components/ui/button' import { Skeleton } from '@/components/ui/skeleton' -import { ApiEndpoint } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint' -import { ApiKey } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key' -import { DeployStatus } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status' -import { ExampleCommand } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command' +import { ApiEndpoint } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint' +import { ApiKey } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key' +import { DeployStatus } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status' +import { ExampleCommand } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command' import { useNotificationStore } from '@/stores/notifications/store' import type { WorkflowState } from '@/stores/workflows/workflow/types' import { DeployedWorkflowModal } from '../../../deployment-controls/components/deployed-workflow-modal' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx index e2f642fc1db..de598cd1b73 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx @@ -20,9 +20,9 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/u import { env } from '@/lib/env' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { ChatDeploy } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy' -import { DeployForm } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form' -import { DeploymentInfo } from '@/app/workspace/[workspace]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info' +import { ChatDeploy } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy' +import { DeployForm } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form' +import { DeploymentInfo } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info' import { useNotificationStore } from '@/stores/notifications/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx similarity index 96% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx index 29e894b9d9a..500eac1ff38 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx @@ -6,7 +6,7 @@ import { Label } from '@/components/ui/label' import { Switch } from '@/components/ui/switch' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { WorkflowPreview } from '@/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview' +import { WorkflowPreview } from '@/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { WorkflowState } from '@/stores/workflows/workflow/types' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx index b9bcc397224..0763713db56 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx @@ -35,7 +35,7 @@ import { getCategoryColor, getCategoryIcon, getCategoryLabel, -} from '@/app/workspace/[workspace]/w/marketplace/constants/categories' +} from '@/app/workspace/[workspaceId]/w/marketplace/constants/categories' import { useNotificationStore } from '@/stores/notifications/store' import { getWorkflowWithValues } from '@/stores/workflows' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.test.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.test.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.test.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.test.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.tsx index 80c97986dfc..1de699db6b5 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/control-bar/control-bar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.tsx @@ -40,7 +40,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip import { useSession } from '@/lib/auth-client' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider' import { useExecutionStore } from '@/stores/execution/store' import { useNotificationStore } from '@/stores/notifications/store' import { usePanelStore } from '@/stores/panel/store' @@ -85,7 +85,7 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { const router = useRouter() const { data: session } = useSession() const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string // Store hooks const { diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/copilot/copilot.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/copilot/copilot.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/copilot/copilot.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/copilot/copilot.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/error/index.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/error/index.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/error/index.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/error/index.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.test.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.test.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.test.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.test.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/components/loop-badges.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-config.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-config.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-config.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-config.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.test.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.test.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.test.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.test.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/notifications/notifications.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/notifications/notifications.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/notifications/notifications.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/notifications/notifications.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/chat.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/chat.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/chat.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/chat.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx index 5cb609367fc..f90f0e226ce 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx @@ -4,8 +4,8 @@ import { type KeyboardEvent, useEffect, useMemo, useRef } from 'react' import { ArrowUp, X } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' -import { JSONView } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view' -import { useWorkflowExecution } from '@/app/workspace/[workspace]/w/[id]/hooks/use-workflow-execution' +import { JSONView } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view' +import { useWorkflowExecution } from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-workflow-execution' import { useExecutionStore } from '@/stores/execution/store' import { useChatStore } from '@/stores/panel/chat/store' import type { ChatMessage as ChatMessageType } from '@/stores/panel/chat/types' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/console.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/console.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/console/console.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/console.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/variables/variables.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/variables/variables.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/components/variables/variables.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/variables/variables.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/panel/panel.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/panel.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/panel/panel.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/panel.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/components/parallel-badges.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/components/parallel-badges.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/components/parallel-badges.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/components/parallel-badges.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-config.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-config.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-config.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-config.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.test.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.test.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.test.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.test.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/skeleton-loading/skeleton-loading.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/skeleton-loading/skeleton-loading.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/skeleton-loading/skeleton-loading.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/skeleton-loading/skeleton-loading.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/toolbar.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/toolbar.tsx index 8265c59c9d3..177413e6ed7 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/toolbar/toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/toolbar.tsx @@ -6,7 +6,7 @@ import { useParams } from 'next/navigation' import { Input } from '@/components/ui/input' import { ScrollArea } from '@/components/ui/scroll-area' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' -import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider' import { getAllBlocks, getBlocksByCategory } from '@/blocks' import type { BlockCategory } from '@/blocks/types' import { useSidebarStore } from '@/stores/sidebar/store' @@ -45,7 +45,7 @@ export const Toolbar = React.memo(() => { // Get the workspace ID from URL params const { workflows } = useWorkflowRegistry() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const currentWorkflow = useMemo( () => (workflowId ? workflows[workflowId] : null), diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx index 119e238f166..dc66efa238f 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx @@ -3,7 +3,7 @@ import { cn } from '@/lib/utils' import { type ConnectedBlock, useBlockConnections, -} from '@/app/workspace/[workspace]/w/[id]/hooks/use-block-connections' +} from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections' import { useSubBlockStore } from '@/stores/workflows/subblock/store' interface ConnectionBlocksProps { diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx index 7f50bc0f32e..1b19a028a63 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx @@ -11,7 +11,7 @@ import { checkEnvVarTrigger, EnvVarDropdown } from '@/components/ui/env-var-drop import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useCodeGeneration } from '@/app/workspace/[workspace]/w/[id]/hooks/use-code-generation' +import { useCodeGeneration } from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation' import { useSubBlockStore } from '@/stores/workflows/subblock/store' import { CodePromptBar } from '../../../../code-prompt-bar/code-prompt-bar' import { useSubBlockValue } from '../hooks/use-sub-block-value' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx index d28d88d0c6f..a7013929fab 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx @@ -15,7 +15,7 @@ import { import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { createLogger } from '@/lib/logs/console-logger' import { type Credential, getProviderIdFromServiceId, getServiceIdFromScopes } from '@/lib/oauth' -import { OAuthRequiredModal } from '@/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal' +import { OAuthRequiredModal } from '@/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal' import { saveToStorage } from '@/stores/workflows/persistence' const logger = createLogger('FolderSelector') diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx index 8ff8e31db1d..c8a9a4694ca 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx @@ -24,7 +24,7 @@ import { Label } from '@/components/ui/label' import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useCodeGeneration } from '@/app/workspace/[workspace]/w/[id]/hooks/use-code-generation' +import { useCodeGeneration } from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation' import { useCustomToolsStore } from '@/stores/custom-tools/store' import { CodePromptBar } from '../../../../../../../code-prompt-bar/code-prompt-bar' import { CodeEditor } from '../code-editor/code-editor' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx index c8e61e8b757..f54e4e7760a 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx @@ -16,7 +16,7 @@ import { import { Skeleton } from '@/components/ui/skeleton' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { Logger } from '@/lib/logs/console-logger' -import { JSONView } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view' +import { JSONView } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view' import { ConfigSection } from '../ui/config-section' const logger = new Logger('GmailConfig') diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx similarity index 97% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx index d257662f3f5..3cc52f4bb90 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx @@ -1,6 +1,6 @@ import { SlackIcon } from '@/components/icons' import { Notice } from '@/components/ui/notice' -import { JSONView } from '@/app/workspace/[workspace]/w/[id]/components/panel/components/console/components/json-view/json-view' +import { JSONView } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view' import { ConfigSection } from '../ui/config-section' import { InstructionsSection } from '../ui/instructions-section' import { TestResultDisplay } from '../ui/test-result' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/workflow-block.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/workflow-block.tsx index 7ea97c01218..f6f07acd2f9 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/workflow-block.tsx @@ -7,7 +7,7 @@ import { Card } from '@/components/ui/card' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { parseCronToHumanReadable } from '@/lib/schedules/utils' import { cn, formatDateTime, validateName } from '@/lib/utils' -import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider' import type { BlockConfig, SubBlockConfig } from '@/blocks/types' import { useExecutionStore } from '@/stores/execution/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-edge/workflow-edge.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-edge/workflow-edge.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/components/workflow-edge/workflow-edge.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-edge/workflow-edge.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-block-connections.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-block-connections.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-code-generation.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-code-generation.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-presence.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-presence.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-presence.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-presence.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-workflow-execution.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-workflow-execution.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/hooks/use-workflow-execution.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-workflow-execution.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/layout.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/layout.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/layout.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/layout.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/utils.ts b/apps/sim/app/workspace/[workspaceId]/w/[id]/utils.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/[id]/utils.ts rename to apps/sim/app/workspace/[workspaceId]/w/[id]/utils.ts diff --git a/apps/sim/app/workspace/[workspace]/w/[id]/workflow.tsx b/apps/sim/app/workspace/[workspaceId]/w/[id]/workflow.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/[id]/workflow.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[id]/workflow.tsx index 6441010eb9f..70d8a76c26b 100644 --- a/apps/sim/app/workspace/[workspace]/w/[id]/workflow.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[id]/workflow.tsx @@ -13,10 +13,10 @@ import ReactFlow, { import 'reactflow/dist/style.css' import { createLogger } from '@/lib/logs/console-logger' -import { LoopNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node' -import { NotificationList } from '@/app/workspace/[workspace]/w/[id]/components/notifications/notifications' -import { ParallelNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node' -import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' +import { LoopNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node' +import { NotificationList } from '@/app/workspace/[workspaceId]/w/[id]/components/notifications/notifications' +import { ParallelNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node' +import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider' import { getBlock } from '@/blocks' import { useSocket } from '@/contexts/socket-context' import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' diff --git a/apps/sim/app/workspace/[workspace]/w/components/providers/providers.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/providers/providers.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/providers/providers.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/providers/providers.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/providers/theme-provider.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/providers/theme-provider.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/providers/theme-provider.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/providers/theme-provider.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider.tsx index 27196faa830..efd23d0948d 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider.tsx @@ -28,7 +28,7 @@ interface WorkspacePermissionsProviderProps { const WorkspacePermissionsProvider = React.memo( ({ children }) => { const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string // Fetch workspace permissions once const { diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/create-menu/create-menu.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/create-menu/create-menu.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/create-menu/create-menu.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/create-menu/create-menu.tsx index b3700245fa2..bba7dd59459 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/create-menu/create-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/create-menu/create-menu.tsx @@ -23,7 +23,7 @@ export function CreateMenu({ onCreateWorkflow, isCollapsed }: CreateMenuProps) { const [isHoverOpen, setIsHoverOpen] = useState(false) const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { createFolder } = useFolderStore() const handleCreateWorkflow = () => { diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx index bf18707b248..d22315b7691 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx @@ -38,7 +38,7 @@ export function FolderContextMenu({ const [isCreating, setIsCreating] = useState(false) const [isRenaming, setIsRenaming] = useState(false) const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { createFolder, updateFolder, deleteFolder } = useFolderStore() diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/components/folder-item.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/components/folder-item.tsx index f6e355a8c9c..ab218a91e18 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/folder-item.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/components/folder-item.tsx @@ -41,7 +41,7 @@ export function FolderItem({ const [showDeleteDialog, setShowDeleteDialog] = useState(false) const [isDeleting, setIsDeleting] = useState(false) const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const isExpanded = expandedFolders.has(folder.id) const updateTimeoutRef = useRef | undefined>(undefined) const pendingStateRef = useRef(null) diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx index 8badbfd2715..27e60fe707d 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/components/workflow-item.tsx @@ -28,7 +28,7 @@ export function WorkflowItem({ const [isDragging, setIsDragging] = useState(false) const dragStartedRef = useRef(false) const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { selectedWorkflows, selectOnly, toggleWorkflowSelection } = useFolderStore() const isSelected = useIsWorkflowSelected(workflow.id) diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/folder-tree.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/folder-tree.tsx similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/folder-tree.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/folder-tree.tsx index b8342bc21f4..22710c6157b 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/folder-tree/folder-tree.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/folder-tree.tsx @@ -39,7 +39,7 @@ function FolderSection({ parentDragOver = false, }: FolderSectionProps) { const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { isDragOver, handleDragOver, handleDragLeave, handleDrop } = useDragHandlers( updateWorkflow, folder.id, @@ -163,7 +163,7 @@ export function FolderTree({ }: FolderTreeProps) { const pathname = usePathname() const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { getFolderTree, expandedFolders, diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/help-modal/components/help-form/help-form.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/help-modal/components/help-form/help-form.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/help-modal/components/help-form/help-form.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/help-modal/components/help-form/help-form.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/help-modal/help-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/help-modal/help-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/help-modal/help-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/help-modal/help-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invite-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/invite-modal/invite-modal.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invite-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/invite-modal/invite-modal.tsx index bffada6c10a..ff51008450e 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invite-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/invite-modal/invite-modal.tsx @@ -16,7 +16,7 @@ import { cn } from '@/lib/utils' import { useUserPermissionsContext, useWorkspacePermissionsContext, -} from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' +} from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider' import type { WorkspacePermissions } from '@/hooks/use-workspace-permissions' import { API_ENDPOINTS } from '@/stores/constants' @@ -398,7 +398,7 @@ export function InviteModal({ open, onOpenChange }: InviteModalProps) { const [errorMessage, setErrorMessage] = useState(null) const [successMessage, setSuccessMessage] = useState(null) const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { data: session } = useSession() const { diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx index ab8711d7820..12ff428a0f5 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/invite-modal/invites-sent/invites-sent.tsx @@ -48,7 +48,7 @@ export function InvitesSent() { const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState(null) const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string useEffect(() => { async function fetchInvitations() { diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/nav-section/nav-section.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/nav-section/nav-section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/nav-section/nav-section.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/nav-section/nav-section.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/account/account.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/account/account.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/account/account.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/account/account.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/api-keys/api-keys.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/credentials/credentials.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/credentials/credentials.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/credentials/credentials.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/credentials/credentials.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/environment/environment.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/environment/environment.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/environment/environment.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/environment/environment.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/general/general.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/general/general.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/general/general.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/general/general.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/privacy/privacy.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/privacy/privacy.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/privacy/privacy.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/privacy/privacy.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/settings-navigation/settings-navigation.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/settings-navigation/settings-navigation.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/settings-navigation/settings-navigation.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/settings-navigation/settings-navigation.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/settings-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/settings-modal/settings-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/settings-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/sidebar-control/sidebar-control.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/sidebar-control/sidebar-control.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/sidebar-control/sidebar-control.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/sidebar-control/sidebar-control.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workflow-list/workflow-list.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/workflow-list.tsx similarity index 97% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workflow-list/workflow-list.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/workflow-list.tsx index 1c95c66ee56..c54e7d73e94 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workflow-list/workflow-list.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/workflow-list.tsx @@ -17,7 +17,7 @@ interface WorkflowItemProps { function WorkflowItem({ workflow, active, isMarketplace, isCollapsed }: WorkflowItemProps) { const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string return ( void + isCollapsed?: boolean + onDropdownOpenChange?: (isOpen: boolean) => void +} + +// New WorkspaceModal component +interface WorkspaceModalProps { + open: boolean + onOpenChange: (open: boolean) => void + onCreateWorkspace: (name: string) => void +} + +const WorkspaceModal = React.memo( + ({ open, onOpenChange, onCreateWorkspace }) => { + const [workspaceName, setWorkspaceName] = useState('') + + const handleSubmit = useCallback( + (e: React.FormEvent) => { + e.preventDefault() + if (workspaceName.trim()) { + onCreateWorkspace(workspaceName.trim()) + setWorkspaceName('') + onOpenChange(false) + } + }, + [workspaceName, onCreateWorkspace, onOpenChange] + ) + + const handleNameChange = useCallback((e: React.ChangeEvent) => { + setWorkspaceName(e.target.value) + }, []) + + const handleClose = useCallback(() => { + onOpenChange(false) + }, [onOpenChange]) + + return ( + + + +
+ Create New Workspace + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+
+
+ ) + } +) + +WorkspaceModal.displayName = 'WorkspaceModal' + +// New WorkspaceEditModal component +interface WorkspaceEditModalProps { + open: boolean + onOpenChange: (open: boolean) => void + onUpdateWorkspace: (id: string, name: string) => void + workspace: Workspace | null +} + +const WorkspaceEditModal = React.memo( + ({ open, onOpenChange, onUpdateWorkspace, workspace }) => { + const [workspaceName, setWorkspaceName] = useState('') + + useEffect(() => { + if (workspace && open) { + setWorkspaceName(workspace.name) + } + }, [workspace, open]) + + const handleSubmit = useCallback( + (e: React.FormEvent) => { + e.preventDefault() + if (workspace && workspaceName.trim()) { + onUpdateWorkspace(workspace.id, workspaceName.trim()) + setWorkspaceName('') + onOpenChange(false) + } + }, + [workspace, workspaceName, onUpdateWorkspace, onOpenChange] + ) + + const handleNameChange = useCallback((e: React.ChangeEvent) => { + setWorkspaceName(e.target.value) + }, []) + + const handleClose = useCallback(() => { + onOpenChange(false) + }, [onOpenChange]) + + return ( + + + +
+ Edit Workspace + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+
+
+ ) + } +) + +WorkspaceEditModal.displayName = 'WorkspaceEditModal' + +export const WorkspaceHeader = React.memo( + ({ onCreateWorkflow, isCollapsed, onDropdownOpenChange }) => { + // Get sidebar store state to check current mode + const { mode, workspaceDropdownOpen, setAnyModalOpen } = useSidebarStore() + + // Keep local isOpen state in sync with the store (for internal component use) + const [isOpen, setIsOpen] = useState(workspaceDropdownOpen) + const { data: sessionData, isPending } = useSession() + const [plan, setPlan] = useState('Free Plan') + // Use client-side loading instead of isPending to avoid hydration mismatch + const [isClientLoading, setIsClientLoading] = useState(true) + const [workspaces, setWorkspaces] = useState([]) + const [activeWorkspace, setActiveWorkspace] = useState(null) + const [isWorkspacesLoading, setIsWorkspacesLoading] = useState(true) + const [isWorkspaceModalOpen, setIsWorkspaceModalOpen] = useState(false) + const [editingWorkspace, setEditingWorkspace] = useState(null) + const [isEditModalOpen, setIsEditModalOpen] = useState(false) + const [isDeleting, setIsDeleting] = useState(false) + const router = useRouter() + + // Get workflowRegistry state and actions + const { switchToWorkspace } = useWorkflowRegistry() + const params = useParams() + const currentWorkspaceId = params.workspaceId as string + + // Get user permissions for the active workspace + const userPermissions = useUserPermissionsContext() + + const userName = useMemo( + () => sessionData?.user?.name || sessionData?.user?.email || 'User', + [sessionData?.user?.name, sessionData?.user?.email] + ) + + // Set isClientLoading to false after hydration + useEffect(() => { + setIsClientLoading(false) + }, []) + + const fetchSubscriptionStatus = useCallback(async (userId: string) => { + try { + const response = await fetch('/api/user/subscription') + const data = await response.json() + setPlan(data.isPro ? 'Pro Plan' : 'Free Plan') + } catch (err) { + logger.error('Error fetching subscription status:', err) + } + }, []) + + const fetchWorkspaces = useCallback(async () => { + setIsWorkspacesLoading(true) + try { + const response = await fetch('/api/workspaces') + const data = await response.json() + + if (data.workspaces && Array.isArray(data.workspaces)) { + const fetchedWorkspaces = data.workspaces as Workspace[] + setWorkspaces(fetchedWorkspaces) + + // Only update workspace if we have a valid currentWorkspaceId from URL + if (currentWorkspaceId) { + const matchingWorkspace = fetchedWorkspaces.find( + (workspace) => workspace.id === currentWorkspaceId + ) + if (matchingWorkspace) { + setActiveWorkspace(matchingWorkspace) + } else { + // Log the mismatch for debugging + logger.warn(`Workspace ${currentWorkspaceId} not found in user's workspaces`) + + // Current workspace not found, fallback to first workspace + if (fetchedWorkspaces.length > 0) { + const fallbackWorkspace = fetchedWorkspaces[0] + setActiveWorkspace(fallbackWorkspace) + // Navigate to the fallback workspace + router.push(`/workspace/${fallbackWorkspace.id}/w`) + } else { + // No workspaces available - handle this edge case + logger.error('No workspaces available for user') + } + } + } + } + } catch (err) { + logger.error('Error fetching workspaces:', err) + } finally { + setIsWorkspacesLoading(false) + } + }, [currentWorkspaceId, router]) + + useEffect(() => { + // Fetch subscription status if user is logged in + if (sessionData?.user?.id) { + fetchSubscriptionStatus(sessionData.user.id) + fetchWorkspaces() + } + }, [sessionData?.user?.id, fetchSubscriptionStatus, fetchWorkspaces]) + + const switchWorkspace = useCallback( + (workspace: Workspace) => { + // If already on this workspace, do nothing + if (activeWorkspace?.id === workspace.id) { + setIsOpen(false) + return + } + + setActiveWorkspace(workspace) + setIsOpen(false) + + // Use full workspace switch which now handles localStorage automatically + switchToWorkspace(workspace.id) + + // Update URL to include workspace ID + router.push(`/workspace/${workspace.id}/w`) + }, + [activeWorkspace?.id, switchToWorkspace, router] + ) + + const handleCreateWorkspace = useCallback( + async (name: string) => { + setIsWorkspacesLoading(true) + + try { + const response = await fetch('/api/workspaces', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name }), + }) + + const data = await response.json() + + if (data.workspace) { + const newWorkspace = data.workspace as Workspace + setWorkspaces((prev) => [...prev, newWorkspace]) + setActiveWorkspace(newWorkspace) + + // Use switchToWorkspace to properly load workflows for the new workspace + // This will clear existing workflows, set loading state, and fetch workflows from DB + switchToWorkspace(newWorkspace.id) + + // Update URL to include new workspace ID + router.push(`/workspace/${newWorkspace.id}/w`) + } + } catch (err) { + logger.error('Error creating workspace:', err) + } finally { + setIsWorkspacesLoading(false) + } + }, + [switchToWorkspace, router] + ) + + const handleUpdateWorkspace = useCallback( + async (id: string, name: string) => { + // For update operations, we need to check permissions for the specific workspace + // Since we can only use hooks at the component level, we'll make the API call + // and let the backend handle the permission check + setIsWorkspacesLoading(true) + + try { + const response = await fetch(`/api/workspaces/${id}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name }), + }) + + if (!response.ok) { + if (response.status === 403) { + logger.error( + 'Permission denied: Only users with admin permissions can update workspaces' + ) + } + throw new Error('Failed to update workspace') + } + + const { workspace: updatedWorkspace } = await response.json() + + // Update workspaces list + setWorkspaces((prevWorkspaces) => + prevWorkspaces.map((w) => + w.id === updatedWorkspace.id ? { ...w, name: updatedWorkspace.name } : w + ) + ) + + // If active workspace was updated, update it too + if (activeWorkspace && activeWorkspace.id === updatedWorkspace.id) { + setActiveWorkspace({ + ...activeWorkspace, + name: updatedWorkspace.name, + }) + } + } catch (err) { + logger.error('Error updating workspace:', err) + } finally { + setIsWorkspacesLoading(false) + } + }, + [activeWorkspace] + ) + + const handleDeleteWorkspace = useCallback( + async (id: string) => { + // For delete operations, we need to check permissions for the specific workspace + // Since we can only use hooks at the component level, we'll make the API call + // and let the backend handle the permission check + setIsDeleting(true) + + try { + const response = await fetch(`/api/workspaces/${id}`, { + method: 'DELETE', + }) + + if (!response.ok) { + if (response.status === 403) { + logger.error( + 'Permission denied: Only users with admin permissions can delete workspaces' + ) + } + throw new Error('Failed to delete workspace') + } + + // Remove from workspace list + const updatedWorkspaces = workspaces.filter((w) => w.id !== id) + setWorkspaces(updatedWorkspaces) + + // If deleted workspace was active, switch to another workspace + if (activeWorkspace?.id === id && updatedWorkspaces.length > 0) { + // Use the specialized method for handling workspace deletion + const newWorkspaceId = updatedWorkspaces[0].id + useWorkflowRegistry.getState().handleWorkspaceDeletion(newWorkspaceId) + setActiveWorkspace(updatedWorkspaces[0]) + } + + setIsOpen(false) + } catch (err) { + logger.error('Error deleting workspace:', err) + } finally { + setIsDeleting(false) + } + }, + [workspaces, activeWorkspace?.id] + ) + + const openEditModal = useCallback( + (workspace: Workspace, e: React.MouseEvent) => { + e.stopPropagation() + // Only show edit/delete options for the active workspace if user has admin permissions + if (activeWorkspace?.id !== workspace.id || !userPermissions.canAdmin) { + return + } + setEditingWorkspace(workspace) + setIsEditModalOpen(true) + }, + [activeWorkspace?.id, userPermissions.canAdmin] + ) + + // Determine URL for workspace links + const workspaceUrl = useMemo( + () => (activeWorkspace ? `/workspace/${activeWorkspace.id}/w` : '/workspace'), + [activeWorkspace] + ) + + // Notify parent component when dropdown opens/closes + const handleDropdownOpenChange = useCallback( + (open: boolean) => { + setIsOpen(open) + // Inform the parent component about the dropdown state change + if (onDropdownOpenChange) { + onDropdownOpenChange(open) + } + }, + [onDropdownOpenChange] + ) + + // Special handling for click interactions in hover mode + const handleTriggerClick = useCallback( + (e: React.MouseEvent) => { + // When in hover mode, explicitly prevent bubbling for the trigger + if (mode === 'hover') { + e.stopPropagation() + e.preventDefault() + // Toggle dropdown state + handleDropdownOpenChange(!isOpen) + } + }, + [mode, isOpen, handleDropdownOpenChange] + ) + + const handleContainerClick = useCallback( + (e: React.MouseEvent) => { + // In hover mode, prevent clicks on the container from collapsing the sidebar + if (mode === 'hover') { + e.stopPropagation() + } + }, + [mode] + ) + + const handleWorkspaceModalOpenChange = useCallback((open: boolean) => { + setIsWorkspaceModalOpen(open) + }, []) + + const handleEditModalOpenChange = useCallback((open: boolean) => { + setIsEditModalOpen(open) + }, []) + + // Handle modal open/close state + useEffect(() => { + // Update the modal state in the store + setAnyModalOpen(isWorkspaceModalOpen || isEditModalOpen || isDeleting) + }, [isWorkspaceModalOpen, isEditModalOpen, isDeleting, setAnyModalOpen]) + + return ( +
+ {/* Workspace Modal */} + + + {/* Edit Workspace Modal */} + + + +
+ {/* Hover background with consistent padding - only when not collapsed */} + {!isCollapsed && ( +
+ )} + + {/* Content with consistent padding */} + {isCollapsed ? ( +
+ + + +
+ ) : ( +
+ +
+
+ { + if (isOpen) e.preventDefault() + }} + > + + + {isClientLoading || isWorkspacesLoading ? ( + + ) : ( +
+ + {activeWorkspace?.name || `${userName}'s Workspace`} + + +
+ )} +
+
+
+
+ )} +
+ +
+
+
+
+ +
+
+ {isClientLoading || isWorkspacesLoading ? ( + <> + + + + ) : ( + <> + + {activeWorkspace?.name || `${userName}'s Workspace`} + + {plan} + + )} +
+
+
+
+ + + + {/* Workspaces list */} +
+
Workspaces
+ {isWorkspacesLoading ? ( +
+ +
+ ) : ( +
+ {workspaces.map((workspace) => ( + switchWorkspace(workspace)} + > + {workspace.name} + {userPermissions.canAdmin && activeWorkspace?.id === workspace.id && ( +
+ + + + + + + + + Delete Workspace + + Are you sure you want to delete "{workspace.name}"? This action + cannot be undone. + + + + e.stopPropagation()}> + Cancel + + { + e.stopPropagation() + handleDeleteWorkspace(workspace.id) + }} + className='bg-destructive text-destructive-foreground hover:bg-destructive/90' + > + Delete + + + + +
+ )} +
+ ))} +
+ )} + + {/* Create new workspace button */} + setIsWorkspaceModalOpen(true)} + > + + New workspace + +
+
+ +
+ ) + } +) + +WorkspaceHeader.displayName = 'WorkspaceHeader' diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx index b367943bc4e..ca7bca924ee 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx @@ -11,7 +11,7 @@ import { createLogger } from '@/lib/logs/console-logger' import { getKeyboardShortcutText, useGlobalShortcuts, -} from '@/app/workspace/[workspace]/w/hooks/use-keyboard-shortcuts' +} from '@/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts' import { useSidebarStore } from '@/stores/sidebar/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { WorkflowMetadata } from '@/stores/workflows/registry/types' @@ -40,7 +40,7 @@ export function Sidebar() { const isLoading = workflowsLoading || sessionLoading const router = useRouter() const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const pathname = usePathname() const [showSettings, setShowSettings] = useState(false) diff --git a/apps/sim/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx similarity index 95% rename from apps/sim/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx index 93ab119ed66..3f3dc056e5a 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx @@ -15,10 +15,10 @@ import 'reactflow/dist/style.css' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { LoopNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/loop-node/loop-node' -import { ParallelNodeComponent } from '@/app/workspace/[workspace]/w/[id]/components/parallel-node/parallel-node' -import { WorkflowBlock } from '@/app/workspace/[workspace]/w/[id]/components/workflow-block/workflow-block' -import { WorkflowEdge } from '@/app/workspace/[workspace]/w/[id]/components/workflow-edge/workflow-edge' +import { LoopNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node' +import { ParallelNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node' +import { WorkflowBlock } from '@/app/workspace/[workspaceId]/w/[id]/components/workflow-block/workflow-block' +import { WorkflowEdge } from '@/app/workspace/[workspaceId]/w/[id]/components/workflow-edge/workflow-edge' import { getBlock } from '@/blocks' import type { WorkflowState } from '@/stores/workflows/workflow/types' diff --git a/apps/sim/app/workspace/[workspace]/w/error.tsx b/apps/sim/app/workspace/[workspaceId]/w/error.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/error.tsx rename to apps/sim/app/workspace/[workspaceId]/w/error.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/global-error.tsx b/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/global-error.tsx rename to apps/sim/app/workspace/[workspaceId]/w/global-error.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/hooks/use-keyboard-shortcuts.ts b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/hooks/use-keyboard-shortcuts.ts rename to apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts diff --git a/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-registry-loading.ts similarity index 98% rename from apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts rename to apps/sim/app/workspace/[workspaceId]/w/hooks/use-registry-loading.ts index 3211b62cb79..239a7148dbe 100644 --- a/apps/sim/app/workspace/[workspace]/w/hooks/use-registry-loading.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-registry-loading.ts @@ -41,7 +41,7 @@ export function useRegistryLoading() { const pathname = usePathname() const router = useRouter() const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string // Load workflows for current workspace useEffect(() => { diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/document-loading.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/document-loading.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/document-loading.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/document-loading.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/document.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/document.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/document.tsx index 3d54d03b17f..f6e7a1117a7 100644 --- a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/document.tsx @@ -16,7 +16,7 @@ import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { createLogger } from '@/lib/logs/console-logger' -import { ActionBar } from '@/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar' +import { ActionBar } from '@/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar' import { useDocumentChunks } from '@/hooks/use-knowledge' import { type ChunkData, type DocumentData, useKnowledgeStore } from '@/stores/knowledge/store' import { useSidebarStore } from '@/stores/sidebar/store' diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/[documentId]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/base.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/base.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/base.tsx index 9383c60c038..b1d72aefcff 100644 --- a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/base.tsx @@ -28,10 +28,10 @@ import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { createLogger } from '@/lib/logs/console-logger' -import { ActionBar } from '@/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar' -import { getDocumentIcon } from '@/app/workspace/[workspace]/w/knowledge/components/icons/document-icons' -import { PrimaryButton } from '@/app/workspace/[workspace]/w/knowledge/components/primary-button/primary-button' -import { SearchInput } from '@/app/workspace/[workspace]/w/knowledge/components/search-input/search-input' +import { ActionBar } from '@/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar' +import { getDocumentIcon } from '@/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons' +import { PrimaryButton } from '@/app/workspace/[workspaceId]/w/knowledge/components/primary-button/primary-button' +import { SearchInput } from '@/app/workspace/[workspaceId]/w/knowledge/components/search-input/search-input' import { useKnowledgeBase, useKnowledgeBaseDocuments } from '@/hooks/use-knowledge' import { type DocumentData, useKnowledgeStore } from '@/stores/knowledge/store' import { useSidebarStore } from '@/stores/sidebar/store' @@ -123,7 +123,7 @@ export function KnowledgeBase({ const { mode, isExpanded } = useSidebarStore() const { removeKnowledgeBase } = useKnowledgeStore() const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { knowledgeBase, isLoading: isLoadingKnowledgeBase, diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/action-bar/action-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/[id]/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/[id]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/base-overview/base-overview.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/base-overview/base-overview.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/base-overview/base-overview.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/base-overview/base-overview.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/create-modal/create-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/create-modal/create-modal.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/create-modal/create-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/create-modal/create-modal.tsx index 63ce953ab0e..93a2ae21d17 100644 --- a/apps/sim/app/workspace/[workspace]/w/knowledge/components/create-modal/create-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/create-modal/create-modal.tsx @@ -12,7 +12,7 @@ import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { createLogger } from '@/lib/logs/console-logger' -import { getDocumentIcon } from '@/app/workspace/[workspace]/w/knowledge/components/icons/document-icons' +import { getDocumentIcon } from '@/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons' import type { DocumentData, KnowledgeBaseData } from '@/stores/knowledge/store' import { useKnowledgeStore } from '@/stores/knowledge/store' diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/empty-state-card/empty-state-card.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/empty-state-card/empty-state-card.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/empty-state-card/empty-state-card.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/empty-state-card/empty-state-card.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/icons/document-icons.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/icons/document-icons.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/knowledge-header/knowledge-header.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/knowledge-header/knowledge-header.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/knowledge-header/knowledge-header.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/knowledge-header/knowledge-header.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/primary-button/primary-button.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/primary-button/primary-button.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/primary-button/primary-button.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/primary-button/primary-button.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/search-input/search-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/search-input/search-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/search-input/search-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/search-input/search-input.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/table-skeleton.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/table-skeleton.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/components/skeletons/table-skeleton.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/table-skeleton.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/knowledge.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/knowledge.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/knowledge.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/knowledge.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/loading.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/loading.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/loading.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/loading.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/knowledge/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/knowledge/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/knowledge/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/knowledge/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/layout.tsx b/apps/sim/app/workspace/[workspaceId]/w/layout.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/layout.tsx rename to apps/sim/app/workspace/[workspaceId]/w/layout.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/control-bar/control-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/control-bar/control-bar.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/filter-section.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/filter-section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/filter-section.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/filter-section.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/folder.tsx similarity index 97% rename from apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/folder.tsx index 68e412f2bdc..4a31a73e689 100644 --- a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/folder.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/folder.tsx @@ -9,7 +9,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' import { useFolderStore } from '@/stores/folders/store' interface FolderOption { @@ -23,7 +23,7 @@ export default function FolderFilter() { const { folderIds, toggleFolderId, setFolderIds } = useFilterStore() const { getFolderTree, getFolderPath, fetchFolders } = useFolderStore() const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const [folders, setFolders] = useState([]) const [loading, setLoading] = useState(true) diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/level.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/level.tsx similarity index 91% rename from apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/level.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/level.tsx index 37b42523b78..2be2ae3faca 100644 --- a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/level.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/level.tsx @@ -6,8 +6,8 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' -import type { LogLevel } from '@/app/workspace/[workspace]/w/logs/stores/types' +import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' +import type { LogLevel } from '@/app/workspace/[workspaceId]/w/logs/stores/types' export default function Level() { const { level, setLevel } = useFilterStore() diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/timeline.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/timeline.tsx similarity index 88% rename from apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/timeline.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/timeline.tsx index ccd414c8c89..9eefe99c8f8 100644 --- a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/timeline.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/timeline.tsx @@ -6,8 +6,8 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' -import type { TimeRange } from '@/app/workspace/[workspace]/w/logs/stores/types' +import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' +import type { TimeRange } from '@/app/workspace/[workspaceId]/w/logs/stores/types' export default function Timeline() { const { timeRange, setTimeRange } = useFilterStore() diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/trigger.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/trigger.tsx similarity index 97% rename from apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/trigger.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/trigger.tsx index 2f431d0e215..7375a38a42f 100644 --- a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/trigger.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/trigger.tsx @@ -7,7 +7,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' import type { TriggerType } from '../../../stores/types' export default function Trigger() { diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/workflow.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/workflow.tsx similarity index 97% rename from apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/workflow.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/workflow.tsx index aefaacc4a8a..c2664f9ca06 100644 --- a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/components/workflow.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/workflow.tsx @@ -8,7 +8,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspace]/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' interface WorkflowOption { id: string diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/filters/filters.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/filters.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/components/filters/filters.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/filters.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/components/markdown-renderer.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/components/markdown-renderer.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/components/markdown-renderer.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/components/markdown-renderer.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/sidebar.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/sidebar.tsx similarity index 99% rename from apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/sidebar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/sidebar.tsx index eb4f9124c5a..6f63da69497 100644 --- a/apps/sim/app/workspace/[workspace]/w/logs/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/sidebar.tsx @@ -7,8 +7,8 @@ import { CopyButton } from '@/components/ui/copy-button' import { ScrollArea } from '@/components/ui/scroll-area' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import { redactApiKeys } from '@/lib/utils' -import type { WorkflowLog } from '@/app/workspace/[workspace]/w/logs/stores/types' -import { formatDate } from '@/app/workspace/[workspace]/w/logs/utils/format-date' +import type { WorkflowLog } from '@/app/workspace/[workspaceId]/w/logs/stores/types' +import { formatDate } from '@/app/workspace/[workspaceId]/w/logs/utils/format-date' import { formatCost } from '@/providers/utils' import { ToolCallsDisplay } from '../tool-calls/tool-calls-display' import { TraceSpansDisplay } from '../trace-spans/trace-spans-display' diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/tool-calls/tool-calls-display.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/tool-calls/tool-calls-display.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/components/tool-calls/tool-calls-display.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/tool-calls/tool-calls-display.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/components/trace-spans/trace-spans-display.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/components/trace-spans/trace-spans-display.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/components/trace-spans/trace-spans-display.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/components/trace-spans/trace-spans-display.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/logs.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/logs.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/logs.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/logs.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/logs/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/logs/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/logs/stores/store.ts b/apps/sim/app/workspace/[workspaceId]/w/logs/stores/store.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/stores/store.ts rename to apps/sim/app/workspace/[workspaceId]/w/logs/stores/store.ts diff --git a/apps/sim/app/workspace/[workspace]/w/logs/stores/types.ts b/apps/sim/app/workspace/[workspaceId]/w/logs/stores/types.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/stores/types.ts rename to apps/sim/app/workspace/[workspaceId]/w/logs/stores/types.ts diff --git a/apps/sim/app/workspace/[workspace]/w/logs/utils/format-date.ts b/apps/sim/app/workspace/[workspaceId]/w/logs/utils/format-date.ts similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/logs/utils/format-date.ts rename to apps/sim/app/workspace/[workspaceId]/w/logs/utils/format-date.ts diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/control-bar/control-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/components/control-bar/control-bar.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/components/error-message.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/error-message.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/components/error-message.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/components/error-message.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/components/section.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/components/section.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/components/section.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/toolbar/toolbar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/components/toolbar/toolbar.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card-skeleton.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card-skeleton.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card-skeleton.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card-skeleton.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card.tsx similarity index 97% rename from apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card.tsx index 16e42371a0b..76667b1d724 100644 --- a/apps/sim/app/workspace/[workspace]/w/marketplace/components/workflow-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react' import { Eye } from 'lucide-react' import { useParams, useRouter } from 'next/navigation' import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card' -import { WorkflowPreview } from '@/app/workspace/[workspace]/w/components/workflow-preview/workflow-preview' +import { WorkflowPreview } from '@/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { Workflow } from '../marketplace' @@ -29,7 +29,7 @@ export function WorkflowCard({ workflow, onHover }: WorkflowCardProps) { const [isPreviewReady, setIsPreviewReady] = useState(!!workflow.workflowState) const router = useRouter() const params = useParams() - const workspaceId = params.workspace as string + const workspaceId = params.workspaceId as string const { createWorkflow } = useWorkflowRegistry() // When workflow state becomes available, update preview ready state diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/constants/categories.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/constants/categories.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/constants/categories.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/constants/categories.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/marketplace.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/marketplace.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/marketplace.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/marketplace.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/marketplace/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/marketplace/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspace]/w/marketplace/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/marketplace/page.tsx diff --git a/apps/sim/app/workspace/[workspace]/w/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/page.tsx similarity index 96% rename from apps/sim/app/workspace/[workspace]/w/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/page.tsx index bcdd47eb14d..a55f118d9c4 100644 --- a/apps/sim/app/workspace/[workspace]/w/page.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/page.tsx @@ -8,7 +8,7 @@ export default function WorkflowsPage() { const router = useRouter() const { workflows, isLoading } = useWorkflowRegistry() const params = useParams() - const workspaceId = params.workspace + const workspaceId = params.workspaceId useEffect(() => { // Wait for workflows to load diff --git a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx index 7d5044c246a..60256830db7 100644 --- a/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx +++ b/apps/sim/app/workspace/[workspace]/w/components/sidebar/components/workspace-header/workspace-header.tsx @@ -29,7 +29,7 @@ import { Input } from '@/components/ui/input' import { Skeleton } from '@/components/ui/skeleton' import { useSession } from '@/lib/auth-client' import { cn } from '@/lib/utils' -import { useUserPermissionsContext } from '@/app/workspace/[workspace]/w/components/providers/workspace-permissions-provider' +import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider' import { useSidebarStore } from '@/stores/sidebar/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' @@ -256,7 +256,7 @@ export const WorkspaceHeader = React.memo( // Get workflowRegistry state and actions const { switchToWorkspace } = useWorkflowRegistry() const params = useParams() - const currentWorkspaceId = params.workspace as string + const currentWorkspaceId = params.workspaceId as string // Get user permissions for the active workspace const userPermissions = useUserPermissionsContext() diff --git a/apps/sim/components/ui/tag-dropdown.tsx b/apps/sim/components/ui/tag-dropdown.tsx index 12fe17a4efd..e14dd4beea9 100644 --- a/apps/sim/components/ui/tag-dropdown.tsx +++ b/apps/sim/components/ui/tag-dropdown.tsx @@ -5,7 +5,7 @@ import { cn } from '@/lib/utils' import { type ConnectedBlock, useBlockConnections, -} from '@/app/workspace/[workspace]/w/[id]/hooks/use-block-connections' +} from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections' import { getBlock } from '@/blocks' import { useVariablesStore } from '@/stores/panel/variables/store' import type { Variable } from '@/stores/panel/variables/types' diff --git a/apps/sim/lib/logs/trace-spans.ts b/apps/sim/lib/logs/trace-spans.ts index 5279536dda5..ff012d948e0 100644 --- a/apps/sim/lib/logs/trace-spans.ts +++ b/apps/sim/lib/logs/trace-spans.ts @@ -1,4 +1,4 @@ -import type { TraceSpan } from '@/app/workspace/[workspace]/w/logs/stores/types' +import type { TraceSpan } from '@/app/workspace/[workspaceId]/w/logs/stores/types' import type { ExecutionResult } from '@/executor/types' // Helper function to build a tree of trace spans from execution logs From 8194e8735a72d3e7fcf00ace609eef48582c744c Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Tue, 24 Jun 2025 19:13:40 +0000 Subject: [PATCH 07/20] chore: refactor /w/[id] to /w/[workflowId] --- apps/sim/app/(auth)/layout.tsx | 2 +- .../code-prompt-bar/code-prompt-bar.tsx | 0 .../components/chat-deploy/chat-deploy.tsx | 2 +- .../components/deploy-form/deploy-form.tsx | 0 .../components/api-endpoint/api-endpoint.tsx | 0 .../components/api-key/api-key.tsx | 0 .../components/deploy-status/deploy-status.tsx | 0 .../example-command/example-command.tsx | 0 .../deployment-info/deployment-info.tsx | 8 ++++---- .../components/deploy-modal/deploy-modal.tsx | 6 +++--- .../components/deployed-workflow-card.tsx | 0 .../components/deployed-workflow-modal.tsx | 0 .../deployment-controls.test.ts | 0 .../deployment-controls/deployment-controls.tsx | 0 .../history-dropdown-item.tsx | 0 .../marketplace-modal/marketplace-modal.tsx | 0 .../notification-dropdown-item.tsx | 0 .../components/user-avatar/user-avatar.tsx | 0 .../user-avatar-stack/user-avatar-stack.tsx | 0 .../components/control-bar/control-bar.test.ts | 0 .../components/control-bar/control-bar.tsx | 0 .../components/copilot/copilot.tsx | 0 .../components/error/index.tsx | 0 .../loop-node/components/loop-badges.test.tsx | 0 .../loop-node/components/loop-badges.tsx | 0 .../components/loop-node/loop-config.ts | 0 .../components/loop-node/loop-node.test.tsx | 0 .../components/loop-node/loop-node.tsx | 0 .../components/notifications/notifications.tsx | 0 .../components/panel/components/chat/chat.tsx | 0 .../components/chat-message/chat-message.tsx | 0 .../chat/components/chat-modal/chat-modal.tsx | 4 ++-- .../components/output-select/output-select.tsx | 0 .../components/audio-player/audio-player.tsx | 0 .../components/console-entry/console-entry.tsx | 0 .../console/components/json-view/json-view.tsx | 0 .../panel/components/console/console.tsx | 0 .../panel/components/variables/variables.tsx | 0 .../components/panel/panel.tsx | 0 .../parallel-node/components/parallel-badges.tsx | 0 .../components/parallel-node/parallel-config.ts | 0 .../parallel-node/parallel-node.test.tsx | 0 .../components/parallel-node/parallel-node.tsx | 0 .../skeleton-loading/skeleton-loading.tsx | 0 .../components/toolbar-block/toolbar-block.tsx | 0 .../toolbar-loop-block/toolbar-loop-block.tsx | 0 .../toolbar-parallel-block.tsx | 0 .../components/toolbar-tabs/toolbar-tabs.tsx | 0 .../components/toolbar/toolbar.tsx | 0 .../components/action-bar/action-bar.tsx | 0 .../connection-blocks/connection-blocks.tsx | 2 +- .../channel-selector/channel-selector-input.tsx | 0 .../components/slack-channel-selector.tsx | 0 .../sub-block/components/checkbox-list.tsx | 0 .../components/sub-block/components/code.tsx | 2 +- .../sub-block/components/condition-input.tsx | 0 .../components/oauth-required-modal.tsx | 0 .../credential-selector/credential-selector.tsx | 0 .../sub-block/components/date-input.tsx | 0 .../document-selector/document-selector.tsx | 0 .../components/sub-block/components/dropdown.tsx | 0 .../sub-block/components/eval-input.tsx | 0 .../components/confluence-file-selector.tsx | 0 .../components/discord-channel-selector.tsx | 0 .../components/google-calendar-selector.tsx | 0 .../components/google-drive-picker.tsx | 0 .../components/jira-issue-selector.tsx | 0 .../components/microsoft-file-selector.tsx | 0 .../components/teams-message-selector.tsx | 0 .../file-selector/file-selector-input.tsx | 0 .../sub-block/components/file-upload.tsx | 0 .../components/folder-selector-input.tsx | 0 .../folder-selector/folder-selector.tsx | 2 +- .../knowledge-base-selector.tsx | 0 .../sub-block/components/long-input.tsx | 0 .../components/discord-server-selector.tsx | 0 .../components/jira-project-selector.tsx | 0 .../components/linear-project-selector.tsx | 0 .../components/linear-team-selector.tsx | 0 .../project-selector/project-selector-input.tsx | 0 .../response/components/property-renderer.tsx | 0 .../response/components/value-input.tsx | 0 .../components/response/response-format.tsx | 0 .../schedule/components/schedule-modal.tsx | 0 .../components/schedule/schedule-config.tsx | 2 +- .../sub-block/components/short-input.tsx | 0 .../sub-block/components/slider-input.tsx | 0 .../components/starter/input-format.tsx | 0 .../components/sub-block/components/switch.tsx | 0 .../components/sub-block/components/table.tsx | 0 .../sub-block/components/time-input.tsx | 0 .../components/code-editor/code-editor.tsx | 0 .../custom-tool-modal/custom-tool-modal.tsx | 2 +- .../components/tool-command/tool-command.tsx | 0 .../components/tool-input/tool-input.tsx | 0 .../webhook/components/providers/airtable.tsx | 0 .../webhook/components/providers/discord.tsx | 0 .../webhook/components/providers/generic.tsx | 0 .../webhook/components/providers/github.tsx | 0 .../webhook/components/providers/gmail.tsx | 2 +- .../webhook/components/providers/slack.tsx | 2 +- .../webhook/components/providers/stripe.tsx | 0 .../webhook/components/providers/telegram.tsx | 0 .../webhook/components/providers/whatsapp.tsx | 0 .../webhook/components/ui/config-field.tsx | 0 .../webhook/components/ui/config-section.tsx | 0 .../webhook/components/ui/confirmation.tsx | 0 .../webhook/components/ui/copyable.tsx | 0 .../components/ui/instructions-section.tsx | 0 .../webhook/components/ui/test-result.tsx | 0 .../components/ui/webhook-config-field.tsx | 0 .../webhook/components/ui/webhook-footer.tsx | 0 .../webhook/components/ui/webhook-url.tsx | 0 .../webhook/components/webhook-modal.tsx | 0 .../sub-block/components/webhook/webhook.tsx | 2 +- .../sub-block/hooks/use-sub-block-value.ts | 0 .../components/sub-block/sub-block.tsx | 0 .../components/workflow-block/workflow-block.tsx | 0 .../components/workflow-edge/workflow-edge.tsx | 0 .../hooks/use-block-connections.ts | 0 .../hooks/use-code-generation.ts | 0 .../{[id] => [workflowId]}/hooks/use-presence.ts | 0 .../hooks/use-workflow-execution.ts | 0 .../w/{[id] => [workflowId]}/layout.tsx | 0 .../w/{[id] => [workflowId]}/page.tsx | 0 .../w/{[id] => [workflowId]}/utils.ts | 0 .../w/{[id] => [workflowId]}/workflow.tsx | 16 ++++++++-------- .../workflow-preview/workflow-preview.tsx | 8 ++++---- apps/sim/app/workspace/[workspaceId]/w/error.tsx | 2 +- .../workspace/[workspaceId]/w/global-error.tsx | 2 +- apps/sim/components/ui/tag-dropdown.tsx | 2 +- 131 files changed, 34 insertions(+), 34 deletions(-) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/code-prompt-bar/code-prompt-bar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx (89%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deploy-modal/deploy-modal.tsx (98%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deployment-controls/deployment-controls.test.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/deployment-controls/deployment-controls.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/marketplace-modal/marketplace-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/control-bar.test.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/control-bar/control-bar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/copilot/copilot.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/error/index.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/loop-node/components/loop-badges.test.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/loop-node/components/loop-badges.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/loop-node/loop-config.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/loop-node/loop-node.test.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/loop-node/loop-node.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/notifications/notifications.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/chat/chat.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/chat/components/chat-message/chat-message.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/chat/components/chat-modal/chat-modal.tsx (97%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/chat/components/output-select/output-select.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/console/components/audio-player/audio-player.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/console/components/console-entry/console-entry.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/console/components/json-view/json-view.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/console/console.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/components/variables/variables.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/panel/panel.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/parallel-node/components/parallel-badges.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/parallel-node/parallel-config.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/parallel-node/parallel-node.test.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/parallel-node/parallel-node.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/skeleton-loading/skeleton-loading.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/toolbar/components/toolbar-block/toolbar-block.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/toolbar/toolbar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/action-bar/action-bar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/connection-blocks/connection-blocks.tsx (98%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/checkbox-list.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/code.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/condition-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/date-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/dropdown.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/eval-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/file-upload.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/long-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/response/components/value-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/response/response-format.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/short-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/slider-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/starter/input-format.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/switch.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/table.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/time-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx (98%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx (97%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/components/webhook/webhook.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/components/sub-block/sub-block.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-block/workflow-block.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/components/workflow-edge/workflow-edge.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/hooks/use-block-connections.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/hooks/use-code-generation.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/hooks/use-presence.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/hooks/use-workflow-execution.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/layout.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/page.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/utils.ts (100%) rename apps/sim/app/workspace/[workspaceId]/w/{[id] => [workflowId]}/workflow.tsx (99%) diff --git a/apps/sim/app/(auth)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index be1494667e2..d448a4eae24 100644 --- a/apps/sim/app/(auth)/layout.tsx +++ b/apps/sim/app/(auth)/layout.tsx @@ -3,7 +3,7 @@ import Image from 'next/image' import Link from 'next/link' import { GridPattern } from '../(landing)/components/grid-pattern' -import { NotificationList } from '../workspace/[workspaceId]/w/[id]/components/notifications/notifications' +import { NotificationList } from '../workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications' export default function AuthLayout({ children }: { children: React.ReactNode }) { return ( diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/code-prompt-bar/code-prompt-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/code-prompt-bar/code-prompt-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/code-prompt-bar/code-prompt-bar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx index ff8fb3f4317..f680c2ffa99 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy.tsx @@ -33,7 +33,7 @@ import { Textarea } from '@/components/ui/textarea' import { createLogger } from '@/lib/logs/console-logger' import { getBaseDomain } from '@/lib/urls/utils' import { cn } from '@/lib/utils' -import { OutputSelect } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/output-select/output-select' +import { OutputSelect } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select' import { useNotificationStore } from '@/stores/notifications/store' import type { OutputConfig } from '@/stores/panel/chat/types' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx similarity index 89% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx index 592417ce9bf..5f98febf4ce 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx @@ -15,10 +15,10 @@ import { } from '@/components/ui/alert-dialog' import { Button } from '@/components/ui/button' import { Skeleton } from '@/components/ui/skeleton' -import { ApiEndpoint } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint' -import { ApiKey } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key' -import { DeployStatus } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status' -import { ExampleCommand } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command' +import { ApiEndpoint } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint' +import { ApiKey } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-key/api-key' +import { DeployStatus } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/deploy-status/deploy-status' +import { ExampleCommand } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/components/example-command/example-command' import { useNotificationStore } from '@/stores/notifications/store' import type { WorkflowState } from '@/stores/workflows/workflow/types' import { DeployedWorkflowModal } from '../../../deployment-controls/components/deployed-workflow-modal' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/deploy-modal.tsx similarity index 98% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/deploy-modal.tsx index de598cd1b73..8595d333f88 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/deploy-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/deploy-modal.tsx @@ -20,9 +20,9 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/u import { env } from '@/lib/env' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { ChatDeploy } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy' -import { DeployForm } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form' -import { DeploymentInfo } from '@/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info' +import { ChatDeploy } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy' +import { DeployForm } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deploy-form/deploy-form' +import { DeploymentInfo } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info' import { useNotificationStore } from '@/stores/notifications/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/deployment-controls.test.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.test.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/deployment-controls.test.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/deployment-controls.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/deployment-controls.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/history-dropdown-item/history-dropdown-item.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/notification-dropdown-item/notification-dropdown-item.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.test.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/control-bar.test.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.test.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/control-bar.test.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/control-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/control-bar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/copilot/copilot.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/copilot/copilot.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/copilot/copilot.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/copilot/copilot.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/error/index.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/error/index.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/error/index.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/error/index.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.test.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/components/loop-badges.test.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.test.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/components/loop-badges.test.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/components/loop-badges.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/components/loop-badges.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/components/loop-badges.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-config.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-config.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-config.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-config.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.test.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-node.test.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.test.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-node.test.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-node.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-node.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/notifications/notifications.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/notifications/notifications.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/chat.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/chat.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/chat.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/chat.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/chat-message/chat-message.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-message/chat-message.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/chat-message/chat-message.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/chat-modal/chat-modal.tsx similarity index 97% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/chat-modal/chat-modal.tsx index f90f0e226ce..f0b8d9498a2 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/chat-modal/chat-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/chat-modal/chat-modal.tsx @@ -4,8 +4,8 @@ import { type KeyboardEvent, useEffect, useMemo, useRef } from 'react' import { ArrowUp, X } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' -import { JSONView } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view' -import { useWorkflowExecution } from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-workflow-execution' +import { JSONView } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/json-view/json-view' +import { useWorkflowExecution } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution' import { useExecutionStore } from '@/stores/execution/store' import { useChatStore } from '@/stores/panel/chat/store' import type { ChatMessage as ChatMessageType } from '@/stores/panel/chat/types' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/chat/components/output-select/output-select.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/output-select/output-select.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/audio-player/audio-player.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/audio-player/audio-player.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/audio-player/audio-player.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/console-entry/console-entry.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/console-entry/console-entry.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/json-view/json-view.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/json-view/json-view.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/console.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/console.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/console.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/console.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/variables/variables.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/variables/variables.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/components/variables/variables.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/variables/variables.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/panel.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/panel/panel.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/components/parallel-badges.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/components/parallel-badges.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/components/parallel-badges.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/components/parallel-badges.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-config.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-config.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-config.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-config.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.test.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-node.test.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.test.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-node.test.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-node.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-node.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/skeleton-loading/skeleton-loading.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/skeleton-loading/skeleton-loading.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/skeleton-loading/skeleton-loading.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/skeleton-loading/skeleton-loading.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-block/toolbar-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-block/toolbar-block.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/components/toolbar-tabs/toolbar-tabs.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/toolbar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/toolbar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/action-bar/action-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/action-bar/action-bar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/connection-blocks/connection-blocks.tsx similarity index 98% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/connection-blocks/connection-blocks.tsx index dc66efa238f..b9f17f57024 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/connection-blocks/connection-blocks.tsx @@ -3,7 +3,7 @@ import { cn } from '@/lib/utils' import { type ConnectedBlock, useBlockConnections, -} from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections' +} from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-connections' import { useSubBlockStore } from '@/stores/workflows/subblock/store' interface ConnectionBlocksProps { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/channel-selector/channel-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/checkbox-list.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/checkbox-list.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/code.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/code.tsx index 1b19a028a63..a228efb1714 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/code.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/code.tsx @@ -11,7 +11,7 @@ import { checkEnvVarTrigger, EnvVarDropdown } from '@/components/ui/env-var-drop import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useCodeGeneration } from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation' +import { useCodeGeneration } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-code-generation' import { useSubBlockStore } from '@/stores/workflows/subblock/store' import { CodePromptBar } from '../../../../code-prompt-bar/code-prompt-bar' import { useSubBlockValue } from '../hooks/use-sub-block-value' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/condition-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/condition-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/condition-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/credential-selector/credential-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/date-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/date-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/date-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/dropdown.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/dropdown.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/eval-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/eval-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/eval-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/confluence-file-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/discord-channel-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/google-calendar-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/microsoft-file-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-upload.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/file-upload.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-upload.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/folder-selector/components/folder-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx index a7013929fab..31abe42a2b3 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx @@ -15,7 +15,7 @@ import { import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { createLogger } from '@/lib/logs/console-logger' import { type Credential, getProviderIdFromServiceId, getServiceIdFromScopes } from '@/lib/oauth' -import { OAuthRequiredModal } from '@/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal' +import { OAuthRequiredModal } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/credential-selector/components/oauth-required-modal' import { saveToStorage } from '@/stores/workflows/persistence' const logger = createLogger('FolderSelector') diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/knowledge-base-selector/knowledge-base-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/long-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/long-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/long-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/discord-server-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/jira-project-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/linear-project-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/components/linear-team-selector.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/project-selector/project-selector-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/response/response-format.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/response/response-format.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx index 182b8ae6922..9b9c58f6d1c 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx @@ -46,7 +46,7 @@ export function ScheduleConfig({ const [refreshCounter, setRefreshCounter] = useState(0) const params = useParams() - const workflowId = params.id as string + const workflowId = params.workflowId as string // Get workflow state from store const setScheduleStatus = useWorkflowStore((state) => state.setScheduleStatus) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/short-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/short-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/slider-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/slider-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/slider-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/starter/input-format.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/starter/input-format.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/switch.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/switch.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/table.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/table.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/table.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/time-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/time-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/time-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/components/code-editor/code-editor.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx index c8a9a4694ca..84f74fc0833 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal.tsx @@ -24,7 +24,7 @@ import { Label } from '@/components/ui/label' import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { useCodeGeneration } from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation' +import { useCodeGeneration } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-code-generation' import { useCustomToolsStore } from '@/stores/custom-tools/store' import { CodePromptBar } from '../../../../../../../code-prompt-bar/code-prompt-bar' import { CodeEditor } from '../code-editor/code-editor' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/components/tool-command/tool-command.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/tool-input/tool-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/airtable.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/discord.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/generic.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/github.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx similarity index 98% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx index f54e4e7760a..3168af8fbfe 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/gmail.tsx @@ -16,7 +16,7 @@ import { import { Skeleton } from '@/components/ui/skeleton' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { Logger } from '@/lib/logs/console-logger' -import { JSONView } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view' +import { JSONView } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/json-view/json-view' import { ConfigSection } from '../ui/config-section' const logger = new Logger('GmailConfig') diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx similarity index 97% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx index 3cc52f4bb90..4bb03e252f1 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/slack.tsx @@ -1,6 +1,6 @@ import { SlackIcon } from '@/components/icons' import { Notice } from '@/components/ui/notice' -import { JSONView } from '@/app/workspace/[workspaceId]/w/[id]/components/panel/components/console/components/json-view/json-view' +import { JSONView } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/json-view/json-view' import { ConfigSection } from '../ui/config-section' import { InstructionsSection } from '../ui/instructions-section' import { TestResultDisplay } from '../ui/test-result' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/stripe.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/telegram.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/whatsapp.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-field.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/confirmation.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/copyable.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/test-result.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-config-field.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-footer.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/ui/webhook-url.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/webhook-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx index a7a82be82ab..041ddd7aa41 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/webhook.tsx @@ -310,7 +310,7 @@ export function WebhookConfig({ const [error, setError] = useState(null) const [webhookId, setWebhookId] = useState(null) const params = useParams() - const workflowId = params.id as string + const workflowId = params.workflowId as string const [isLoading, setIsLoading] = useState(false) const [gmailCredentialId, setGmailCredentialId] = useState('') diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/sub-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/sub-block.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/workflow-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-block/workflow-block.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-edge/workflow-edge.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-edge/workflow-edge.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/components/workflow-edge/workflow-edge.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-edge/workflow-edge.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-connections.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-connections.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-code-generation.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-code-generation.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-code-generation.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-presence.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-presence.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-presence.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-presence.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-workflow-execution.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/hooks/use-workflow-execution.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/layout.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/layout.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/layout.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/layout.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/page.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/utils.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/utils.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[id]/workflow.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/[id]/workflow.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx index 70d8a76c26b..fada16ee09e 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[id]/workflow.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx @@ -13,9 +13,9 @@ import ReactFlow, { import 'reactflow/dist/style.css' import { createLogger } from '@/lib/logs/console-logger' -import { LoopNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node' -import { NotificationList } from '@/app/workspace/[workspaceId]/w/[id]/components/notifications/notifications' -import { ParallelNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node' +import { LoopNodeComponent } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-node' +import { NotificationList } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/notifications/notifications' +import { ParallelNodeComponent } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-node' import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider' import { getBlock } from '@/blocks' import { useSocket } from '@/contexts/socket-context' @@ -95,7 +95,7 @@ const WorkflowContent = React.memo(() => { const { project, getNodes, fitView } = useReactFlow() // Get workspace ID from current workflow - const workflowId = params.id as string + const workflowId = params.workflowId as string const { workflows, activeWorkflowId, isLoading, setActiveWorkflow, createWorkflow } = useWorkflowRegistry() @@ -787,7 +787,7 @@ const WorkflowContent = React.memo(() => { // Track when workflow is fully ready for rendering useEffect(() => { - const currentId = params.id as string + const currentId = params.workflowId as string // Reset workflow ready state when workflow changes if (activeWorkflowId !== currentId) { @@ -813,13 +813,13 @@ const WorkflowContent = React.memo(() => { return () => clearTimeout(timeoutId) } setIsWorkflowReady(false) - }, [activeWorkflowId, params.id, workflows, isLoading]) + }, [activeWorkflowId, params.workflowId, workflows, isLoading]) // Init workflow useEffect(() => { const validateAndNavigate = async () => { const workflowIds = Object.keys(workflows) - const currentId = params.id as string + const currentId = params.workflowId as string // Wait for both initialization and workflow loading to complete if (isLoading) { @@ -859,7 +859,7 @@ const WorkflowContent = React.memo(() => { validateAndNavigate() }, [ - params.id, + params.workflowId, workflows, isLoading, setActiveWorkflow, diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx index 3f3dc056e5a..ff6a7c2e97a 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx @@ -15,10 +15,10 @@ import 'reactflow/dist/style.css' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' -import { LoopNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/loop-node/loop-node' -import { ParallelNodeComponent } from '@/app/workspace/[workspaceId]/w/[id]/components/parallel-node/parallel-node' -import { WorkflowBlock } from '@/app/workspace/[workspaceId]/w/[id]/components/workflow-block/workflow-block' -import { WorkflowEdge } from '@/app/workspace/[workspaceId]/w/[id]/components/workflow-edge/workflow-edge' +import { LoopNodeComponent } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-node' +import { ParallelNodeComponent } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-node' +import { WorkflowBlock } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block' +import { WorkflowEdge } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-edge/workflow-edge' import { getBlock } from '@/blocks' import type { WorkflowState } from '@/stores/workflows/workflow/types' diff --git a/apps/sim/app/workspace/[workspaceId]/w/error.tsx b/apps/sim/app/workspace/[workspaceId]/w/error.tsx index adac0456b81..3ee88c1074d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/error.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/error.tsx @@ -1,5 +1,5 @@ 'use client' -import { NextError } from './[id]/components/error' +import { NextError } from './[workflowId]/components/error' export default NextError diff --git a/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx b/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx index 9c7bd975759..b6a91d63362 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx @@ -1,5 +1,5 @@ 'use client' -import { NextGlobalError } from './[id]/components/error' +import { NextGlobalError } from './[workflowId]/components/error' export default NextGlobalError diff --git a/apps/sim/components/ui/tag-dropdown.tsx b/apps/sim/components/ui/tag-dropdown.tsx index e14dd4beea9..cb3c15b9f00 100644 --- a/apps/sim/components/ui/tag-dropdown.tsx +++ b/apps/sim/components/ui/tag-dropdown.tsx @@ -5,7 +5,7 @@ import { cn } from '@/lib/utils' import { type ConnectedBlock, useBlockConnections, -} from '@/app/workspace/[workspaceId]/w/[id]/hooks/use-block-connections' +} from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-connections' import { getBlock } from '@/blocks' import { useVariablesStore } from '@/stores/panel/variables/store' import type { Variable } from '@/stores/panel/variables/types' From c1a7ca60712b37117d638f9c765c269178c243c7 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Tue, 24 Jun 2025 19:32:26 +0000 Subject: [PATCH 08/20] refactor: move knowledge base, logs, marketplace to workspace --- apps/sim/app/api/marketplace/workflows/route.ts | 2 +- apps/sim/app/workspace/[workspaceId]/error.tsx | 5 +++++ .../app/workspace/[workspaceId]/global-error.tsx | 5 +++++ .../create-chunk-modal/create-chunk-modal.tsx | 0 .../delete-chunk-modal/delete-chunk-modal.tsx | 0 .../[documentId]/components/document-loading.tsx | 4 ++-- .../edit-chunk-modal/edit-chunk-modal.tsx | 0 .../knowledge/[id]/[documentId]/document.tsx | 10 +++++----- .../{w => }/knowledge/[id]/[documentId]/page.tsx | 0 .../{w => }/knowledge/[id]/base.tsx | 16 ++++++++-------- .../[id]/components/action-bar/action-bar.tsx | 0 .../knowledge-base-loading.tsx | 2 +- .../{w => }/knowledge/[id]/page.tsx | 0 .../components/base-overview/base-overview.tsx | 2 +- .../components/create-modal/create-modal.tsx | 2 +- .../empty-state-card/empty-state-card.tsx | 0 .../components/icons/document-icons.tsx | 0 .../knowledge-header/knowledge-header.tsx | 0 .../components/primary-button/primary-button.tsx | 0 .../components/search-input/search-input.tsx | 0 .../skeletons/knowledge-base-card-skeleton.tsx | 0 .../components/skeletons/table-skeleton.tsx | 0 .../{w => }/knowledge/knowledge.tsx | 0 .../[workspaceId]/{w => }/knowledge/loading.tsx | 0 .../[workspaceId]/{w => }/knowledge/page.tsx | 0 .../workspace/[workspaceId]/{w => }/layout.tsx | 4 ++-- .../logs/components/control-bar/control-bar.tsx | 0 .../filters/components/filter-section.tsx | 0 .../components/filters/components/folder.tsx | 2 +- .../logs/components/filters/components/level.tsx | 4 ++-- .../components/filters/components/timeline.tsx | 4 ++-- .../components/filters/components/trigger.tsx | 2 +- .../components/filters/components/workflow.tsx | 2 +- .../{w => }/logs/components/filters/filters.tsx | 0 .../sidebar/components/markdown-renderer.tsx | 0 .../{w => }/logs/components/sidebar/sidebar.tsx | 4 ++-- .../components/tool-calls/tool-calls-display.tsx | 0 .../trace-spans/trace-spans-display.tsx | 0 .../[workspaceId]/{w => }/logs/logs.tsx | 0 .../[workspaceId]/{w => }/logs/page.tsx | 0 .../[workspaceId]/{w => }/logs/stores/store.ts | 0 .../[workspaceId]/{w => }/logs/stores/types.ts | 0 .../{w => }/logs/utils/format-date.ts | 0 .../components/control-bar/control-bar.tsx | 0 .../marketplace/components/error-message.tsx | 0 .../{w => }/marketplace/components/section.tsx | 0 .../marketplace/components/toolbar/toolbar.tsx | 0 .../components/workflow-card-skeleton.tsx | 0 .../marketplace/components/workflow-card.tsx | 0 .../{w => }/marketplace/constants/categories.tsx | 0 .../{w => }/marketplace/marketplace.tsx | 0 .../[workspaceId]/{w => }/marketplace/page.tsx | 0 .../marketplace-modal/marketplace-modal.tsx | 2 +- .../w/components/sidebar/sidebar.tsx | 8 ++++---- apps/sim/app/workspace/[workspaceId]/w/error.tsx | 5 ----- .../workspace/[workspaceId]/w/global-error.tsx | 5 ----- .../w/hooks/use-keyboard-shortcuts.ts | 2 +- apps/sim/lib/logs/trace-spans.ts | 2 +- 58 files changed, 47 insertions(+), 47 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/error.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/global-error.tsx rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/[documentId]/components/document-loading.tsx (97%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/[documentId]/document.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/[documentId]/page.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/base.tsx (98%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/components/action-bar/action-bar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/[id]/page.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/base-overview/base-overview.tsx (95%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/create-modal/create-modal.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/empty-state-card/empty-state-card.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/icons/document-icons.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/knowledge-header/knowledge-header.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/primary-button/primary-button.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/search-input/search-input.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/components/skeletons/table-skeleton.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/knowledge.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/loading.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/knowledge/page.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/layout.tsx (79%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/control-bar/control-bar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/filters/components/filter-section.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/filters/components/folder.tsx (98%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/filters/components/level.tsx (91%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/filters/components/timeline.tsx (88%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/filters/components/trigger.tsx (97%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/filters/components/workflow.tsx (97%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/filters/filters.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/sidebar/components/markdown-renderer.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/sidebar/sidebar.tsx (99%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/tool-calls/tool-calls-display.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/components/trace-spans/trace-spans-display.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/logs.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/page.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/stores/store.ts (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/stores/types.ts (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/logs/utils/format-date.ts (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/components/control-bar/control-bar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/components/error-message.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/components/section.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/components/toolbar/toolbar.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/components/workflow-card-skeleton.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/components/workflow-card.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/constants/categories.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/marketplace.tsx (100%) rename apps/sim/app/workspace/[workspaceId]/{w => }/marketplace/page.tsx (100%) delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/error.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/global-error.tsx diff --git a/apps/sim/app/api/marketplace/workflows/route.ts b/apps/sim/app/api/marketplace/workflows/route.ts index fda813b4928..fdf7a3cdb81 100644 --- a/apps/sim/app/api/marketplace/workflows/route.ts +++ b/apps/sim/app/api/marketplace/workflows/route.ts @@ -2,7 +2,7 @@ import { desc, eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { createLogger } from '@/lib/logs/console-logger' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' -import { CATEGORIES } from '@/app/workspace/[workspaceId]/w/marketplace/constants/categories' +import { CATEGORIES } from '@/app/workspace/[workspaceId]/marketplace/constants/categories' import { db } from '@/db' import * as schema from '@/db/schema' diff --git a/apps/sim/app/workspace/[workspaceId]/error.tsx b/apps/sim/app/workspace/[workspaceId]/error.tsx new file mode 100644 index 00000000000..c5e6e668b88 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/error.tsx @@ -0,0 +1,5 @@ +'use client' + +import { NextError } from './w/[workflowId]/components/error' + +export default NextError diff --git a/apps/sim/app/workspace/[workspaceId]/global-error.tsx b/apps/sim/app/workspace/[workspaceId]/global-error.tsx new file mode 100644 index 00000000000..d92a73ce254 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/global-error.tsx @@ -0,0 +1,5 @@ +'use client' + +import { NextGlobalError } from './w/[workflowId]/components/error' + +export default NextGlobalError diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/document-loading.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-loading.tsx similarity index 97% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/document-loading.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-loading.tsx index 2b9d811d733..aad70d0ed4f 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/document-loading.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-loading.tsx @@ -25,12 +25,12 @@ export function DocumentLoading({ { id: 'knowledge-root', label: 'Knowledge', - href: '/w/knowledge', + href: '/knowledge', }, { id: `knowledge-base-${knowledgeBaseId}`, label: knowledgeBaseName, - href: `/w/knowledge/${knowledgeBaseId}`, + href: `/knowledge/${knowledgeBaseId}`, }, { id: `document-${knowledgeBaseId}-${documentName}`, diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/document.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx index f6e7a1117a7..fc25327f6db 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx @@ -16,7 +16,7 @@ import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { createLogger } from '@/lib/logs/console-logger' -import { ActionBar } from '@/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar' +import { ActionBar } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/action-bar/action-bar' import { useDocumentChunks } from '@/hooks/use-knowledge' import { type ChunkData, type DocumentData, useKnowledgeStore } from '@/stores/knowledge/store' import { useSidebarStore } from '@/stores/sidebar/store' @@ -170,10 +170,10 @@ export function Document({ const effectiveDocumentName = document?.filename || documentName || 'Document' const breadcrumbs = [ - { label: 'Knowledge', href: '/w/knowledge' }, + { label: 'Knowledge', href: '/knowledge' }, { label: effectiveKnowledgeBaseName, - href: `/w/knowledge/${knowledgeBaseId}`, + href: `/knowledge/${knowledgeBaseId}`, }, { label: effectiveDocumentName }, ] @@ -360,10 +360,10 @@ export function Document({ if (combinedError && !isLoadingChunks) { const errorBreadcrumbs = [ - { label: 'Knowledge', href: '/w/knowledge' }, + { label: 'Knowledge', href: '/knowledge' }, { label: effectiveKnowledgeBaseName, - href: `/w/knowledge/${knowledgeBaseId}`, + href: `/knowledge/${knowledgeBaseId}`, }, { label: 'Error' }, ] diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/page.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/[documentId]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/page.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx similarity index 98% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/base.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx index b1d72aefcff..eeffdb79e7d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx @@ -28,10 +28,10 @@ import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { createLogger } from '@/lib/logs/console-logger' -import { ActionBar } from '@/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar' -import { getDocumentIcon } from '@/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons' -import { PrimaryButton } from '@/app/workspace/[workspaceId]/w/knowledge/components/primary-button/primary-button' -import { SearchInput } from '@/app/workspace/[workspaceId]/w/knowledge/components/search-input/search-input' +import { ActionBar } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/action-bar/action-bar' +import { getDocumentIcon } from '@/app/workspace/[workspaceId]/knowledge/components/icons/document-icons' +import { PrimaryButton } from '@/app/workspace/[workspaceId]/knowledge/components/primary-button/primary-button' +import { SearchInput } from '@/app/workspace/[workspaceId]/knowledge/components/search-input/search-input' import { useKnowledgeBase, useKnowledgeBaseDocuments } from '@/hooks/use-knowledge' import { type DocumentData, useKnowledgeStore } from '@/stores/knowledge/store' import { useSidebarStore } from '@/stores/sidebar/store' @@ -408,7 +408,7 @@ export function KnowledgeBase({ kbName: knowledgeBaseName, // Use the instantly available name docName: document?.filename || 'Document', }) - router.push(`/workspace/${workspaceId}/w/knowledge/${id}/${docId}?${urlParams.toString()}`) + router.push(`/workspace/${workspaceId}/knowledge/${id}/${docId}?${urlParams.toString()}`) } const handleDeleteKnowledgeBase = async () => { @@ -430,7 +430,7 @@ export function KnowledgeBase({ if (result.success) { // Remove from store and redirect to knowledge bases list removeKnowledgeBase(id) - router.push(`/workspace/${workspaceId}/w/knowledge`) + router.push(`/workspace/${workspaceId}/knowledge`) } else { throw new Error(result.error || 'Failed to delete knowledge base') } @@ -743,7 +743,7 @@ export function KnowledgeBase({ { id: 'knowledge-root', label: 'Knowledge', - href: '/w/knowledge', + href: '/knowledge', }, { id: `knowledge-base-${id}`, @@ -762,7 +762,7 @@ export function KnowledgeBase({ { id: 'knowledge-root', label: 'Knowledge', - href: '/w/knowledge', + href: '/knowledge', }, { id: 'error', diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/action-bar/action-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/action-bar/action-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/action-bar/action-bar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx index f969e7ae7f2..150979ddb66 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/knowledge-base-loading/knowledge-base-loading.tsx @@ -19,7 +19,7 @@ export function KnowledgeBaseLoading({ knowledgeBaseName }: KnowledgeBaseLoading { id: 'knowledge-root', label: 'Knowledge', - href: '/w/knowledge', + href: '/knowledge', }, { id: 'knowledge-base-loading', diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/page.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/[id]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/page.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/base-overview/base-overview.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-overview/base-overview.tsx similarity index 95% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/base-overview/base-overview.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/base-overview/base-overview.tsx index 4da5fdd9ab7..223c9e9c90f 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/base-overview/base-overview.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-overview/base-overview.tsx @@ -18,7 +18,7 @@ export function BaseOverview({ id, title, docCount, description }: BaseOverviewP const params = new URLSearchParams({ kbName: title, }) - const href = `/w/knowledge/${id || title.toLowerCase().replace(/\s+/g, '-')}?${params.toString()}` + const href = `/knowledge/${id || title.toLowerCase().replace(/\s+/g, '-')}?${params.toString()}` const handleCopy = async (e: React.MouseEvent) => { e.preventDefault() diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/create-modal/create-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/create-modal/create-modal.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/create-modal/create-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/create-modal/create-modal.tsx index 93a2ae21d17..77bf98e8fb8 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/create-modal/create-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/components/create-modal/create-modal.tsx @@ -12,7 +12,7 @@ import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { createLogger } from '@/lib/logs/console-logger' -import { getDocumentIcon } from '@/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons' +import { getDocumentIcon } from '@/app/workspace/[workspaceId]/knowledge/components/icons/document-icons' import type { DocumentData, KnowledgeBaseData } from '@/stores/knowledge/store' import { useKnowledgeStore } from '@/stores/knowledge/store' diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/empty-state-card/empty-state-card.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/empty-state-card/empty-state-card.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/empty-state-card/empty-state-card.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/empty-state-card/empty-state-card.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/icons/document-icons.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/icons/document-icons.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/icons/document-icons.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/knowledge-header/knowledge-header.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/knowledge-header/knowledge-header.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/knowledge-header/knowledge-header.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/knowledge-header/knowledge-header.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/primary-button/primary-button.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/primary-button/primary-button.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/primary-button/primary-button.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/primary-button/primary-button.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/search-input/search-input.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/search-input/search-input.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/search-input/search-input.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/search-input/search-input.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/skeletons/knowledge-base-card-skeleton.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/table-skeleton.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/skeletons/table-skeleton.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/components/skeletons/table-skeleton.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/skeletons/table-skeleton.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/knowledge.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/knowledge.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/loading.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/loading.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/loading.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/loading.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/knowledge/page.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/knowledge/page.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/page.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/layout.tsx b/apps/sim/app/workspace/[workspaceId]/layout.tsx similarity index 79% rename from apps/sim/app/workspace/[workspaceId]/w/layout.tsx rename to apps/sim/app/workspace/[workspaceId]/layout.tsx index 42ac184a820..261b5d42224 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/layout.tsx +++ b/apps/sim/app/workspace/[workspaceId]/layout.tsx @@ -1,6 +1,6 @@ import { WorkspaceProvider } from '@/providers/workspace-provider' -import Providers from './components/providers/providers' -import { Sidebar } from './components/sidebar/sidebar' +import Providers from './w/components/providers/providers' +import { Sidebar } from './w/components/sidebar/sidebar' export default function WorkspaceLayout({ children }: { children: React.ReactNode }) { return ( diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/control-bar/control-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/control-bar/control-bar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/filter-section.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/filter-section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/filter-section.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/filter-section.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/folder.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/folder.tsx similarity index 98% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/folder.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/folder.tsx index 4a31a73e689..bc7432758f7 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/folder.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/folder.tsx @@ -9,7 +9,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/logs/stores/store' import { useFolderStore } from '@/stores/folders/store' interface FolderOption { diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/level.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/level.tsx similarity index 91% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/level.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/level.tsx index 2be2ae3faca..c83706a5b40 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/level.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/level.tsx @@ -6,8 +6,8 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' -import type { LogLevel } from '@/app/workspace/[workspaceId]/w/logs/stores/types' +import { useFilterStore } from '@/app/workspace/[workspaceId]/logs/stores/store' +import type { LogLevel } from '@/app/workspace/[workspaceId]/logs/stores/types' export default function Level() { const { level, setLevel } = useFilterStore() diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/timeline.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/timeline.tsx similarity index 88% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/timeline.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/timeline.tsx index 9eefe99c8f8..0a475b6f1dc 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/timeline.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/timeline.tsx @@ -6,8 +6,8 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' -import type { TimeRange } from '@/app/workspace/[workspaceId]/w/logs/stores/types' +import { useFilterStore } from '@/app/workspace/[workspaceId]/logs/stores/store' +import type { TimeRange } from '@/app/workspace/[workspaceId]/logs/stores/types' export default function Timeline() { const { timeRange, setTimeRange } = useFilterStore() diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/trigger.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/trigger.tsx similarity index 97% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/trigger.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/trigger.tsx index 7375a38a42f..1cabe0583c9 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/trigger.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/trigger.tsx @@ -7,7 +7,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/logs/stores/store' import type { TriggerType } from '../../../stores/types' export default function Trigger() { diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/workflow.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/workflow.tsx similarity index 97% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/workflow.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/workflow.tsx index c2664f9ca06..47081d31674 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/components/workflow.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/workflow.tsx @@ -8,7 +8,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/workspace/[workspaceId]/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/logs/stores/store' interface WorkflowOption { id: string diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/filters.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/filters.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/filters/filters.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/filters.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/components/markdown-renderer.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/sidebar/components/markdown-renderer.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/components/markdown-renderer.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/sidebar/components/markdown-renderer.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/sidebar.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/sidebar/sidebar.tsx similarity index 99% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/sidebar.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/sidebar/sidebar.tsx index 6f63da69497..65d070356b8 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/logs/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/sidebar/sidebar.tsx @@ -7,8 +7,8 @@ import { CopyButton } from '@/components/ui/copy-button' import { ScrollArea } from '@/components/ui/scroll-area' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import { redactApiKeys } from '@/lib/utils' -import type { WorkflowLog } from '@/app/workspace/[workspaceId]/w/logs/stores/types' -import { formatDate } from '@/app/workspace/[workspaceId]/w/logs/utils/format-date' +import type { WorkflowLog } from '@/app/workspace/[workspaceId]/logs/stores/types' +import { formatDate } from '@/app/workspace/[workspaceId]/logs/utils/format-date' import { formatCost } from '@/providers/utils' import { ToolCallsDisplay } from '../tool-calls/tool-calls-display' import { TraceSpansDisplay } from '../trace-spans/trace-spans-display' diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/tool-calls/tool-calls-display.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/tool-calls/tool-calls-display.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/tool-calls/tool-calls-display.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/tool-calls/tool-calls-display.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/components/trace-spans/trace-spans-display.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/trace-spans/trace-spans-display.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/components/trace-spans/trace-spans-display.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/trace-spans/trace-spans-display.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/logs.tsx b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/logs.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/logs.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/page.tsx b/apps/sim/app/workspace/[workspaceId]/logs/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/page.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/page.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/stores/store.ts b/apps/sim/app/workspace/[workspaceId]/logs/stores/store.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/stores/store.ts rename to apps/sim/app/workspace/[workspaceId]/logs/stores/store.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/stores/types.ts b/apps/sim/app/workspace/[workspaceId]/logs/stores/types.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/stores/types.ts rename to apps/sim/app/workspace/[workspaceId]/logs/stores/types.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/logs/utils/format-date.ts b/apps/sim/app/workspace/[workspaceId]/logs/utils/format-date.ts similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/logs/utils/format-date.ts rename to apps/sim/app/workspace/[workspaceId]/logs/utils/format-date.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/components/control-bar/control-bar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/control-bar/control-bar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/error-message.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/components/error-message.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/components/error-message.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/error-message.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/section.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/components/section.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/components/section.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/section.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/components/toolbar/toolbar.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/toolbar/toolbar.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card-skeleton.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/components/workflow-card-skeleton.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card-skeleton.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/workflow-card-skeleton.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/components/workflow-card.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/components/workflow-card.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/workflow-card.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/constants/categories.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/constants/categories.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/constants/categories.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/constants/categories.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/marketplace.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/marketplace.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/marketplace.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/marketplace.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/marketplace/page.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/page.tsx similarity index 100% rename from apps/sim/app/workspace/[workspaceId]/w/marketplace/page.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/page.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx index 0763713db56..7b7bdb59687 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/marketplace-modal/marketplace-modal.tsx @@ -35,7 +35,7 @@ import { getCategoryColor, getCategoryIcon, getCategoryLabel, -} from '@/app/workspace/[workspaceId]/w/marketplace/constants/categories' +} from '@/app/workspace/[workspaceId]/marketplace/constants/categories' import { useNotificationStore } from '@/stores/notifications/store' import { getWorkflowWithValues } from '@/stores/workflows' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx index ca7bca924ee..4230524e901 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx @@ -179,18 +179,18 @@ export function Sidebar() { } - href={`/workspace/${workspaceId}/w/logs`} + href={`/workspace/${workspaceId}/logs`} label='Logs' - active={pathname === `/workspace/${workspaceId}/w/logs`} + active={pathname === `/workspace/${workspaceId}/logs`} isCollapsed={isCollapsed} shortcutCommand={getKeyboardShortcutText('L', true, true)} shortcutCommandPosition='below' /> } - href={`/workspace/${workspaceId}/w/knowledge`} + href={`/workspace/${workspaceId}/knowledge`} label='Knowledge' - active={pathname === `/workspace/${workspaceId}/w/knowledge`} + active={pathname === `/workspace/${workspaceId}/knowledge`} isCollapsed={isCollapsed} shortcutCommand={getKeyboardShortcutText('K', true, true)} shortcutCommandPosition='below' diff --git a/apps/sim/app/workspace/[workspaceId]/w/error.tsx b/apps/sim/app/workspace/[workspaceId]/w/error.tsx deleted file mode 100644 index 3ee88c1074d..00000000000 --- a/apps/sim/app/workspace/[workspaceId]/w/error.tsx +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -import { NextError } from './[workflowId]/components/error' - -export default NextError diff --git a/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx b/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx deleted file mode 100644 index b6a91d63362..00000000000 --- a/apps/sim/app/workspace/[workspaceId]/w/global-error.tsx +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -import { NextGlobalError } from './[workflowId]/components/error' - -export default NextGlobalError diff --git a/apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts index 9f49d8a1818..d6e875c2e70 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts @@ -95,7 +95,7 @@ export function useGlobalShortcuts() { ((isMac && event.metaKey) || (!isMac && event.ctrlKey)) ) { event.preventDefault() - router.push('/w/logs') + router.push('/logs') } } diff --git a/apps/sim/lib/logs/trace-spans.ts b/apps/sim/lib/logs/trace-spans.ts index ff012d948e0..02ef418f954 100644 --- a/apps/sim/lib/logs/trace-spans.ts +++ b/apps/sim/lib/logs/trace-spans.ts @@ -1,4 +1,4 @@ -import type { TraceSpan } from '@/app/workspace/[workspaceId]/w/logs/stores/types' +import type { TraceSpan } from '@/app/workspace/[workspaceId]/logs/stores/types' import type { ExecutionResult } from '@/executor/types' // Helper function to build a tree of trace spans from execution logs From 76df2b9cd9cdeb40ad2442c6af671be496156a81 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 24 Jun 2025 17:44:30 -0700 Subject: [PATCH 09/20] fix(sockets): added throttling, refactor entire socket server, added tests (#534) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(kb): use chonkie locally (#475) * feat(parsers): text and markdown parsers (#473) * feat: text and markdown parsers * fix: don't readfile on buffer, convert buffer to string instead * fix(knowledge-wh): fixed authentication error on webhook trigger fix(knowledge-wh): fixed authentication error on webhook trigger * feat(tools): add huggingface tools/blcok (#472) * add hugging face tool * docs: add Hugging Face tool documentation * fix: format and lint Hugging Face integration files * docs: add manual intro section to Hugging Face documentation * feat: replace Record with proper HuggingFaceRequestBody interface * accidental local files added * restore some docs * make layout full for model field * change huggingface logo * add manual content * fix lint --------- Co-authored-by: Vikhyath Mondreti * fix(knowledge-ux): fixed ux for knowledge base (#478) fix(knowledge-ux): fixed ux for knowledge base (#478) * fix(billing): bump better-auth version & fix existing subscription issue when adding seats (#484) * bump better-auth version & fix existing subscription issue Bwhen adding seats * ack PR comments * fix(env): added NEXT_PUBLIC_APP_URL to .env.example (#485) * feat(subworkflows): workflows as a block within workflows (#480) * feat(subworkflows) workflows in workflows * revert sync changes * working output vars * fix greptile comments * add cycle detection * add tests * working tests * works * fix formatting * fix input var handling * add images --------- Co-authored-by: Vikhyath Mondreti Co-authored-by: Vikhyath Mondreti * fix(kb): fixed kb race condition resulting in no chunks found (#487) * fix: added all blocks activeExecutionPath (#486) * refactor(chunker): replace chonkie with custom TextChunker (#479) * refactor(chunker): replace chonkie with custom TextChunker implementation and update document processing logic * chore: cleanup unimplemented types * fix: KB tests updated * fix(tab-sync): sync between tabs on change (#489) * fix(tab-sync): sync between tabs on change * refactor: optimize JSON.stringify operations that are redundant * fix(file-upload): upload presigned url to kb for file upload instead of the whole file, circumvents 4.5MB serverless func limit (#491) * feat(folders): folders to manage workflows (#490) * feat(subworkflows) workflows in workflows * revert sync changes * working output vars * fix greptile comments * add cycle detection * add tests * working tests * works * fix formatting * fix input var handling * fix(tab-sync): sync between tabs on change * feat(folders): folders to organize workflows * address comments * change schema types * fix lint error * fix typing error * fix race cond * delete unused files * improved UI * updated naming conventions * revert unrelated changes to db schema * fixed collapsed sidebar subfolders * add logs filters for folders --------- Co-authored-by: Vikhyath Mondreti Co-authored-by: Vikhyath Mondreti Co-authored-by: Waleed Latif * revert tab sync * improvement(folders): added multi-select for moving folders (#493) * added multi-select for folders * allow drag into root * remove extraneous comments * instantly create worfklow on plus * styling improvements, fixed flicker * small improvement to dragover container * ack PR comments * fix(deployed-chat): made the chat mobile friendly (#494) * improvement(ui/ux): chat deploy (#496) * improvement(ui/ux): chat deploy experience * improvement(ui/ux): chat fontweight * feat(gmail): added option to access raw gmail from gmail polling service (#495) * added option to grab raw gmail from gmail polling service * safe json parse for function block execution to prevent vars in raw email from being resolved as sim studio vars * added tests * remove extraneous comments * fix(ui): fix the UI for folder deletion, huggingface icon, workflow block icon, standardized alert dialog (#498) * fixed folder delete UI * fixed UI for workflow block, huggingface, & added alert dialog for deleting folders * consistently style all alert dialogs * fix(reset-data): remove reset all data button from settings modal along with logic (#499) * fix(airtable): fixed airtable oauth token refresh, added tests (#502) * fixed airtable token refresh, added tests * added helpers for refreshOAuthToken function * feat(registration): disable registration + handle env booleans (#501) * feat: disable registration + handle env booleans * chore: removing pre-process because we need to use util * chore: format * feat(providers): added azure openai (#503) * added azure openai * fix request params being passed through agent block for azure * remove o1 from azure-openai models list * fix: add vscode settings to gitignore * feat(file-upload): generalized storage to support azure blob, enhanced error logging in kb, added xlsx parser (#506) * added blob storage option for azure, refactored storage client to be provider agnostic, tested kb & file upload and s3 is undisrupted, still have to test blob * updated CORS policy for blob, added azure blob-specific headers * remove extraneous comments * add file size limit and timeout * added some extra error handling in kb add documents * grouped envvars * ack PR comments * added sheetjs and xlsx parser * fix(folders): modified folder deletion to delete subfolders & workflows in it instead of moving to root (#508) * modified folder deletion to delete subfolders & workflows in it instead of moving to root * added additional testing utils * ack PR comments * feat: api response block and implementation * improvement(local-storage): remove use of local storage except for oauth and last active workspace id (#497) * remove local storage usage * remove migration for last active workspace id * Update apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/jira-issue-selector.tsx Add fallback for required scopes Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * add url builder util * fi * fix lint * lint * modify pre commit hook * fix oauth * get last active workspace working again * new workspace logic works * fetch locks * works now * remove empty useEffect * fix loading issue * skip empty workflow syncs * use isWorkspace in transition flag * add logging * add data initialized flag * fix lint * fix: build error by create a server-side utils * remove migration snapshots * reverse search for workspace based on workflow id * fix lint * improvement: loading check and animation * remove unused utils * remove console logs --------- Co-authored-by: Vikhyath Mondreti Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: Emir Karabeg Co-authored-by: Vikhyath Mondreti * feat(multi-select): simplified chat to always return readable stream, can select multiple outputs and get response streamed back in chat panel & deployed chat (#507) * improvement: all workflow executions return ReadableStream & use sse to support multiple streamed outputs in chats * fixed build * remove extraneous comments * general improvemetns * ack PR comments * fixed built * improvement(workflow-state): split workflow state into separate tables (#511) * new tables to track workflow state * fix lint * refactor into separate tables * fix typing * fix lint * add tests * fix lint * add correct foreign key constraint * add self ref * remove unused checks * fix types * fix type --------- Co-authored-by: Vikhyath Mondreti * feat(models): added new openai models, updated model pricing, added new groq model (#513) * fix(autocomplete): fixed extra closing tag on tag dropdown autocomplete (#514) * chore: enable input format again * fix: process the input made on api calls with proper extraction * feat: add json-object for ai generation for response block and others * chore: add documentation for response block * chore: rollback temp fix and uncomment original input handler * chore: add missing mock for response handler * chore: add missing mock * chore: greptile recommendations * added cost tracking for router & evaluator blocks, consolidated model information into a single file, hosted keys for evaluator & router, parallelized unit tests (#516) * fix(deployState): deploy not persisting bug (#518) * fix(undeploy-bug): fix deployment persistence failing bug * fix lint --------- Co-authored-by: Vikhyath Mondreti * fix decimal entry issues * remove unused files * fix(db): decimal position entry issues (#520) * fix decimal entry issues * remove unused files --------- Co-authored-by: Vikhyath Mondreti * fix lint * fix test * improvement(kb): added configurability for chunks, query across multiple knowledge bases (#512) * refactor: consolidate create modal file * fix: identify dead processes * fix: mark failed in DB after processing timeout * improvement: added overlap chunks and fixed modal UI * feat: multiselect logic * fix: biome changes for css ordering warn instead of error * improvement: create chunk ui * fix: removed unused schema columns * fix: removed references to deleted columns * improvement: sped up vector search time * feat: multi-kb search * add bulk endpoint to disable/delete multiple chunks * add bulk endpoint to disable/delete multiple chunks * fix: removed unused schema columns * fix: removed references to deleted columns * made endpoints for knowledge more RESTful, added tests * added batch operations for delete/enable/disable docs, alr have this for chunks * added migrations * added migrations --------- Co-authored-by: Waleed Latif * fix(models): remove temp from models that don't support it * feat(sdk): added ts and python SDKs + docs (#524) * added ts & python sdk, renamed cli from simstudio to cli * added docs * ack PR comments * improvements * fixed issue where it goes to random workspace when you click reload fixed lint issue * feat: better response builder + doc update * fix(auth): added preview URLs to list of trusted origins (#525) * trusted origins * lint error * removed localhost * ran lint --------- Co-authored-by: Waleed Latif * fix(sdk): remove dev script from SDK * PR: changes for migration * add changes on top of db migration changes * fix: allow removing single input field * improvement(permissions): workspace permissions improvements, added provider and reduced API calls by 85% (#530) * improved permissions UI & access patterns, show outstanding invites * added logger * added provider for workspace permissions, 85% reduction in API calls to get user permissions and improved performance for invitations * ack PR comments * cleanup * fix disabled tooltips * improvement(tests): parallelized tests and build fixes (#531) * added provider for workspace permissions, 85% reduction in API calls to get user permissions and improved performance for invitations * parallelized more tests, fixed test warnings * removed waitlist verification route, use more utils in tests * fixed build * ack PR comments * fix * fix(kb): reduced params in kb block, added advanced mode to starter block, updated docs * feat(realtime): sockets + normalized tables + deprecate sync (#523) * feat: implement real-time collaborative workflow editing with Socket.IO - Add Socket.IO server with room-based architecture for workflow collaboration - Implement socket context for client-side real-time communication - Add collaborative workflow hook for synchronized state management - Update CSP to allow socket connections to localhost:3002 - Add fallback authentication for testing collaborative features - Enable real-time broadcasting of workflow operations between tabs - Support multi-user editing of blocks, edges, and workflow state Key components: - socket-server/: Complete Socket.IO server with authentication and room management - contexts/socket-context.tsx: Client-side socket connection and state management - hooks/use-collaborative-workflow.ts: Hook for collaborative workflow operations - Workflow store integration for real-time state synchronization Status: Basic collaborative features working, authentication bypass enabled for testing * feat: complete collaborative subblock editing implementation ✅ All collaborative features now working perfectly: - Real-time block movement and positioning - Real-time subblock value editing (text fields, inputs) - Real-time edge operations and parent updates - Multi-user workflow rooms with proper broadcasting - Socket.IO server with room-based architecture - Permission bypass system for testing 🔧 Technical improvements: - Modified useSubBlockValue hook to use collaborative event system - All subblock setValue calls now dispatch 'update-subblock-value' events - Collaborative workflow hook handles all real-time operations - Socket server processes and persists all operations to database - Clean separation between local and collaborative state management 🧪 Tested and verified: - Multiple browser tabs with different fallback users - Block dragging and positioning updates in real-time - Subblock text editing reflects immediately across tabs - Workflow room management and user presence - Database persistence of all collaborative operations Status: Full collaborative workflow editing working with fallback authentication * feat: implement proper authentication for collaborative Socket.IO server ✅ **Authentication System Complete**: - Removed all fallback authentication code and bypasses - Socket server now requires valid Better Auth session cookies - Proper session validation using auth.api.getSession() - Authentication errors properly handled and logged - User info extracted from session: userId, userName, email, organizationId 🔧 **Technical Implementation**: - Updated CSP to allow WebSocket connections (ws://localhost:3002) - Socket authentication middleware validates session tokens - Proper error handling for missing/invalid sessions - Permission system enforces workflow access controls - Clean separation between authenticated and unauthenticated states 🧪 **Testing Status**: - Socket server properly rejects unauthenticated connections - Authentication errors logged with clear messages - CSP updated to allow both HTTP and WebSocket protocols - Ready for testing with authenticated users Status: Production-ready collaborative authentication system * feat: complete authentication integration for collaborative Socket.IO system 🎉 **PRODUCTION-READY COLLABORATIVE SYSTEM** ✅ **Authentication Integration Complete**: - Fixed Socket.IO client to send credentials (withCredentials: true) - Updated server CORS to accept credentials with specific origin - Removed all fallback authentication bypasses - Proper Better Auth session validation working 🔧 **Technical Fixes**: - Socket client: Enable withCredentials for cookie transmission - Socket server: Accept credentials with origin 'http://localhost:3000' - Better Auth cookie utility integration for session parsing - Comprehensive authentication middleware with proper error handling 🧪 **Verified Working Features**: - ✅ Real user authentication (Vikhyath Mondreti authenticated) - ✅ Multi-user workflow rooms (2+ users in same workflow) - ✅ Permission system enforcing workflow access controls - ✅ Real-time subblock editing across browser tabs - ✅ Block movement and positioning updates - ✅ Automatic room cleanup and management - ✅ Database persistence of all collaborative operations 🚀 **Status**: Complete enterprise-grade collaborative workflow editing system - No more fallback users - production authentication - Multi-tab collaboration working perfectly - Secure access control with Better Auth integration - Real-time updates for all workflow operations * remove sync system and move to server side * fix lint * delete unused file * added socketio dep * fix subblock persistence bug * working deletion of workflows * fix lint * added railway * add debug logging for railway deployment * improve typing * fix lint * working subflow persistence * fix lint * working cascade deletion * fix lint * working subflow inside subflow * works * fix lint * prevent subflow in subflow * fix lint * add additional logs, add localhost as allowedOrigin * add additional logs, add localhost as allowedOrigin * fix type error * remove unused code * fix lint * fix tests * fix lint * fix build error * workign folder updates * fix typing issue * fix lint * fix typing issues * lib/ * fix tests * added old presence component back, updated to use one-time-token better auth plugin for socket server auth, tested * fix errors * fix bugs * add migration scripts to run * fix lint * fix deploy tests * fix lint * fix minor issues * fix lint * fix migration script * allow comma separateds id file input to migration script * fix lint * fixed * fix lint * fix fallback case * fix type errors * address greptile comments * fix lint * fix script to generate new block ids * fix lint --------- Co-authored-by: Vikhyath Mondreti Co-authored-by: Vikhyath Mondreti Co-authored-by: Waleed Latif Co-authored-by: Vikhyath Mondreti * fix(sockets): updated CSP * remove unecessary logs * fix lint * added throttling, refactor entire socket server, added tests * improvements * remove self monitoring func, add block name event * working isWide, isAdvanced toggles with sockets * fix lint * fix duplicate key issue for user avatar * fix lint * fix user presence * working parallel badges / loop badges updates * working connection output persistence * fix lint * fix build errors * fix lint * logs removed * fix cascade var name update bug * works * fix lint * fix parallel blocks * fix placeholder * fix test * fixed tests --------- Co-authored-by: Aditya Tripathi Co-authored-by: Adam Gough <77861281+aadamgough@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti Co-authored-by: Vikhyath Mondreti Co-authored-by: Vikhyath Mondreti Co-authored-by: Emir Karabeg Co-authored-by: Emir Karabeg <78010029+emir-karabeg@users.noreply.github.com> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti Co-authored-by: Ajit Kadaveru --- .github/workflows/publish-cli.yml | 10 +- .github/workflows/publish-python-sdk.yml | 89 + .github/workflows/publish-ts-sdk.yml | 85 + .gitignore | 6 +- .husky/pre-commit | 2 +- apps/docs/components/icons.tsx | 7 + apps/docs/components/ui/block-types.tsx | 17 +- apps/docs/content/docs/blocks/meta.json | 2 +- apps/docs/content/docs/blocks/response.mdx | 188 + apps/docs/content/docs/blocks/workflow.mdx | 231 ++ apps/docs/content/docs/meta.json | 5 +- apps/docs/content/docs/sdks/python.mdx | 409 ++ apps/docs/content/docs/sdks/typescript.mdx | 598 +++ .../content/docs/tools/google_calendar.mdx | 34 +- apps/docs/content/docs/tools/huggingface.mdx | 127 + apps/docs/content/docs/tools/knowledge.mdx | 41 +- apps/docs/content/docs/tools/meta.json | 1 + .../docs/public/static/dark/response-dark.png | Bin 0 -> 25825 bytes .../docs/public/static/dark/workflow-dark.png | Bin 0 -> 38963 bytes .../public/static/light/response-light.png | Bin 0 -> 25568 bytes .../public/static/light/workflow-light.png | Bin 0 -> 27023 bytes apps/sim/.env.example | 16 - apps/sim/app/(auth)/login/login-form.test.tsx | 21 +- apps/sim/app/(auth)/login/login-form.tsx | 14 +- apps/sim/app/(auth)/signup/page.tsx | 5 + .../app/(auth)/signup/signup-form.test.tsx | 51 +- apps/sim/app/(auth)/signup/signup-form.tsx | 51 - .../sim/app/(auth)/verify/use-verification.ts | 17 +- .../(landing)/components/hero-workflow.tsx | 3 +- .../app/(landing)/components/nav-client.tsx | 25 +- apps/sim/app/api/__test-utils__/utils.ts | 946 ++++- .../api/auth/forget-password/route.test.ts | 80 +- .../app/api/auth/oauth/credentials/route.ts | 4 +- apps/sim/app/api/auth/oauth/utils.test.ts | 6 +- apps/sim/app/api/auth/oauth/utils.ts | 2 +- .../app/api/auth/reset-password/route.test.ts | 188 + apps/sim/app/api/auth/socket-token/route.ts | 20 + .../api/auth/verify-waitlist-token/route.ts | 75 - .../app/api/chat/[subdomain]/route.test.ts | 222 +- apps/sim/app/api/chat/[subdomain]/route.ts | 108 +- apps/sim/app/api/chat/utils.test.ts | 20 +- apps/sim/app/api/chat/utils.ts | 457 +- apps/sim/app/api/codegen/route.ts | 19 + apps/sim/app/api/files/delete/route.test.ts | 157 +- apps/sim/app/api/files/delete/route.ts | 77 +- apps/sim/app/api/files/parse/route.test.ts | 137 +- apps/sim/app/api/files/parse/route.ts | 721 ++-- .../sim/app/api/files/presigned/route.test.ts | 311 ++ apps/sim/app/api/files/presigned/route.ts | 134 +- .../api/files/serve/[...path]/route.test.ts | 307 +- .../app/api/files/serve/[...path]/route.ts | 128 +- apps/sim/app/api/files/upload/route.test.ts | 171 +- apps/sim/app/api/files/upload/route.ts | 28 +- apps/sim/app/api/files/utils.ts | 37 +- apps/sim/app/api/folders/[id]/route.test.ts | 414 ++ apps/sim/app/api/folders/[id]/route.ts | 184 + apps/sim/app/api/folders/route.test.ts | 426 ++ apps/sim/app/api/folders/route.ts | 101 + .../app/api/function/execute/route.test.ts | 544 +++ apps/sim/app/api/function/execute/route.ts | 73 +- .../[documentId]/chunks/[chunkId]/route.ts | 25 +- .../documents/[documentId]/chunks/route.ts | 184 +- .../documents/[documentId]/retry/route.ts | 101 - .../[id]/documents/[documentId]/route.test.ts | 550 +++ .../[id]/documents/[documentId]/route.ts | 121 +- .../knowledge/[id]/documents/route.test.ts | 424 ++ .../app/api/knowledge/[id]/documents/route.ts | 432 +- .../knowledge/[id]/process-documents/route.ts | 276 -- apps/sim/app/api/knowledge/[id]/route.test.ts | 332 ++ apps/sim/app/api/knowledge/[id]/route.ts | 1 - apps/sim/app/api/knowledge/route.test.ts | 220 + apps/sim/app/api/knowledge/route.ts | 21 +- .../app/api/knowledge/search/route.test.ts | 399 ++ apps/sim/app/api/knowledge/search/route.ts | 214 +- apps/sim/app/api/knowledge/utils.test.ts | 252 ++ apps/sim/app/api/knowledge/utils.ts | 254 +- apps/sim/app/api/logs/cleanup/route.ts | 2 +- apps/sim/app/api/logs/route.test.ts | 201 +- apps/sim/app/api/logs/route.ts | 51 +- apps/sim/app/api/providers/route.ts | 6 + apps/sim/app/api/schedules/execute/route.ts | 2 +- .../api/workflows/[id]/deploy/route.test.ts | 111 +- .../app/api/workflows/[id]/deploy/route.ts | 98 +- .../app/api/workflows/[id]/duplicate/route.ts | 369 ++ .../api/workflows/[id]/execute/route.test.ts | 1 + .../app/api/workflows/[id]/execute/route.ts | 22 +- apps/sim/app/api/workflows/[id]/route.ts | 363 ++ .../app/api/workflows/[id]/status/route.ts | 71 +- .../app/api/workflows/[id]/variables/route.ts | 1 - apps/sim/app/api/workflows/route.ts | 290 ++ apps/sim/app/api/workflows/sync/route.ts | 280 +- .../api/workspaces/[id]/permissions/route.ts | 153 + apps/sim/app/api/workspaces/[id]/route.ts | 99 +- .../workspaces/invitations/accept/route.ts | 54 +- .../app/api/workspaces/invitations/route.ts | 55 +- .../app/api/workspaces/members/[id]/route.ts | 74 - apps/sim/app/api/workspaces/members/route.ts | 81 +- apps/sim/app/api/workspaces/route.ts | 196 +- apps/sim/app/chat/[subdomain]/chat-client.tsx | 255 +- .../[subdomain]/components/header/header.tsx | 15 +- .../[subdomain]/components/input/input.tsx | 206 +- .../components/input/voice-input.tsx | 29 +- .../voice-interface/components/particles.tsx | 48 +- .../deployment-controls.tsx | 50 +- .../components/user-avatar/user-avatar.tsx | 106 + .../user-avatar-stack/user-avatar-stack.tsx | 99 + .../components/control-bar/control-bar.tsx | 745 ++-- .../loop-node/components/loop-badges.tsx | 111 +- .../w/[id]/components/loop-node/loop-node.tsx | 11 +- .../notifications/notifications.tsx | 5 +- .../components/panel/components/chat/chat.tsx | 321 +- .../console-entry/console-entry.tsx | 17 +- .../components/parallel-badges.tsx | 132 +- .../parallel-node/parallel-config.ts | 2 +- .../parallel-node/parallel-node.test.tsx | 108 +- .../parallel-node/parallel-node.tsx | 10 +- .../skeleton-loading/skeleton-loading.tsx | 205 + .../toolbar-block/toolbar-block.tsx | 41 +- .../toolbar-loop-block/toolbar-loop-block.tsx | 68 +- .../toolbar-parallel-block.tsx | 70 +- .../app/w/[id]/components/toolbar/toolbar.tsx | 124 +- .../components/action-bar/action-bar.tsx | 60 +- .../connection-blocks/connection-blocks.tsx | 22 +- .../sub-block/components/checkbox-list.tsx | 8 +- .../components/sub-block/components/code.tsx | 29 +- .../sub-block/components/condition-input.tsx | 24 +- .../sub-block/components/date-input.tsx | 6 +- .../document-selector/document-selector.tsx | 1 - .../sub-block/components/dropdown.tsx | 8 +- .../sub-block/components/eval-input.tsx | 22 +- .../sub-block/components/file-upload.tsx | 21 +- .../knowledge-base-selector.tsx | 184 +- .../sub-block/components/long-input.tsx | 7 +- .../response/components/property-renderer.tsx | 236 ++ .../response/components/value-input.tsx | 300 ++ .../components/response/response-format.tsx | 326 ++ .../schedule/components/schedule-modal.tsx | 5 +- .../components/schedule/schedule-config.tsx | 12 +- .../sub-block/components/short-input.tsx | 10 +- .../sub-block/components/slider-input.tsx | 8 +- .../components/starter/input-format.tsx | 206 +- .../sub-block/components/switch.tsx | 8 +- .../components/sub-block/components/table.tsx | 35 +- .../sub-block/components/time-input.tsx | 6 +- .../components/tool-input/tool-input.tsx | 24 +- .../webhook/components/providers/gmail.tsx | 126 +- .../webhook/components/ui/confirmation.tsx | 10 +- .../webhook/components/webhook-modal.tsx | 18 +- .../sub-block/components/webhook/webhook.tsx | 25 +- .../sub-block/hooks/use-sub-block-value.ts | 37 +- .../components/sub-block/sub-block.tsx | 52 +- .../workflow-block/workflow-block.tsx | 71 +- .../app/w/[id]/hooks/use-code-generation.ts | 1 + apps/sim/app/w/[id]/hooks/use-presence.ts | 42 + .../w/[id]/hooks/use-workflow-execution.ts | 575 +-- apps/sim/app/w/[id]/workflow.tsx | 433 +- .../app/w/components/providers/providers.tsx | 16 +- .../workspace-permissions-provider.tsx | 99 + .../components/create-menu/create-menu.tsx | 149 + .../folder-context-menu.tsx | 209 + .../folder-tree/components/folder-item.tsx | 219 + .../folder-tree/components/workflow-item.tsx | 137 + .../components/folder-tree/folder-tree.tsx | 303 ++ .../components/invite-modal/invite-modal.tsx | 942 ++++- .../invites-sent/invites-sent.tsx | 147 +- .../components/credentials/credentials.tsx | 78 +- .../components/general/general.tsx | 70 - .../components/team-seats-dialog.tsx | 134 + .../components/subscription/subscription.tsx | 85 +- .../team-management/team-management.tsx | 122 +- .../workspace-header/workspace-header.tsx | 1195 +++--- apps/sim/app/w/components/sidebar/sidebar.tsx | 226 +- .../workflow-preview/workflow-preview.tsx | 4 +- apps/sim/app/w/hooks/use-registry-loading.ts | 83 +- .../create-chunk-modal/create-chunk-modal.tsx | 64 +- .../edit-chunk-modal/edit-chunk-modal.tsx | 90 +- .../knowledge/[id]/[documentId]/document.tsx | 203 +- apps/sim/app/w/knowledge/[id]/base.tsx | 477 ++- .../[id]/components/action-bar/action-bar.tsx | 105 + .../knowledge-base-loading.tsx | 4 +- .../components/create-form/create-form.tsx | 570 --- .../components/create-modal/create-modal.tsx | 716 +++- .../primary-button/primary-button.tsx | 38 + .../components/search-input/search-input.tsx | 43 + apps/sim/app/w/knowledge/knowledge.tsx | 38 +- apps/sim/app/w/layout.tsx | 17 +- .../components/filters/components/folder.tsx | 168 + .../app/w/logs/components/filters/filters.tsx | 4 + .../sidebar/components/markdown-renderer.tsx | 207 +- .../app/w/logs/components/sidebar/sidebar.tsx | 3 +- apps/sim/app/w/logs/logs.tsx | 2 + apps/sim/app/w/logs/stores/store.ts | 27 +- apps/sim/app/w/logs/stores/types.ts | 3 + .../marketplace/components/workflow-card.tsx | 2 +- apps/sim/app/w/page.tsx | 38 + apps/sim/blocks/blocks/agent.ts | 57 +- apps/sim/blocks/blocks/browser_use.ts | 1 - apps/sim/blocks/blocks/evaluator.ts | 17 +- apps/sim/blocks/blocks/huggingface.ts | 125 + apps/sim/blocks/blocks/knowledge.ts | 21 +- apps/sim/blocks/blocks/response.ts | 103 + apps/sim/blocks/blocks/router.ts | 17 +- apps/sim/blocks/blocks/starter.ts | 17 +- apps/sim/blocks/blocks/workflow.ts | 86 + apps/sim/blocks/registry.ts | 6 + apps/sim/blocks/types.ts | 5 +- apps/sim/components/icons.tsx | 126 + apps/sim/components/ui/tag-dropdown.test.tsx | 114 + apps/sim/components/ui/tag-dropdown.tsx | 18 +- apps/sim/contexts/socket-context.tsx | 495 +++ .../db/migrations/0042_breezy_miracleman.sql | 21 + .../migrations/0043_silent_the_anarchist.sql | 58 + .../migrations/0044_uneven_killer_shrike.sql | 4 + .../sim/db/migrations/0045_sour_chameleon.sql | 10 + .../sim/db/migrations/0046_loose_blizzard.sql | 19 + apps/sim/db/migrations/0047_new_triathlon.sql | 1 + .../sim/db/migrations/meta/0042_snapshot.json | 3082 ++++++++++++++ .../sim/db/migrations/meta/0043_snapshot.json | 3572 ++++++++++++++++ .../sim/db/migrations/meta/0044_snapshot.json | 3560 ++++++++++++++++ .../sim/db/migrations/meta/0045_snapshot.json | 3449 ++++++++++++++++ .../sim/db/migrations/meta/0046_snapshot.json | 3670 ++++++++++++++++ .../sim/db/migrations/meta/0047_snapshot.json | 3677 +++++++++++++++++ apps/sim/db/migrations/meta/_journal.json | 42 + apps/sim/db/migrations/relations.ts | 21 - apps/sim/db/migrations/schema.ts | 76 - apps/sim/db/schema.ts | 232 +- .../executor/__test-utils__/executor-mocks.ts | 44 + .../handlers/agent/agent-handler.test.ts | 28 + .../executor/handlers/agent/agent-handler.ts | 22 +- apps/sim/executor/handlers/agent/types.ts | 2 + .../condition/condition-handler.test.ts | 1 + .../evaluator/evaluator-handler.test.ts | 5 + .../handlers/evaluator/evaluator-handler.ts | 15 +- apps/sim/executor/handlers/index.ts | 4 + .../handlers/loop/loop-handler.test.ts | 6 +- .../executor/handlers/loop/loop-handler.ts | 5 + .../parallel/parallel-handler.test.ts | 6 +- .../handlers/parallel/parallel-handler.ts | 44 +- .../handlers/response/response-handler.ts | 245 ++ .../handlers/router/router-handler.test.ts | 5 + .../handlers/router/router-handler.ts | 15 +- .../workflow/workflow-handler.test.ts | 273 ++ .../handlers/workflow/workflow-handler.ts | 214 + apps/sim/executor/index.test.ts | 828 +--- apps/sim/executor/index.ts | 418 +- apps/sim/executor/path.test.ts | 8 + apps/sim/executor/path.ts | 8 +- apps/sim/executor/resolver.ts | 4 +- apps/sim/executor/types.ts | 9 +- apps/sim/hooks/use-collaborative-workflow.ts | 763 ++++ apps/sim/hooks/use-knowledge.ts | 120 +- apps/sim/hooks/use-user-permissions.ts | 90 + apps/sim/hooks/use-workspace-permissions.ts | 100 + apps/sim/lib/auth.ts | 47 +- apps/sim/lib/documents/chunker.ts | 260 ++ apps/sim/lib/documents/document-processor.ts | 592 ++- apps/sim/lib/email/mailer.test.ts | 8 +- apps/sim/lib/email/unsubscribe.test.ts | 33 +- apps/sim/lib/email/utils.test.ts | 113 + apps/sim/lib/email/utils.ts | 10 + apps/sim/lib/env.ts | 46 +- apps/sim/lib/environment.ts | 2 +- apps/sim/lib/file-parsers/index.test.ts | 69 +- apps/sim/lib/file-parsers/index.ts | 22 + apps/sim/lib/file-parsers/md-parser.ts | 45 + apps/sim/lib/file-parsers/txt-parser.ts | 45 + apps/sim/lib/file-parsers/types.ts | 2 +- apps/sim/lib/file-parsers/xlsx-parser.ts | 104 + apps/sim/lib/logs/execution-logger.ts | 16 +- apps/sim/lib/oauth/index.ts | 1 + apps/sim/lib/oauth/oauth.test.ts | 368 ++ apps/sim/lib/{ => oauth}/oauth.ts | 370 +- apps/sim/lib/permissions/utils.test.ts | 473 +++ apps/sim/lib/permissions/utils.ts | 98 + apps/sim/lib/schedules/utils.test.ts | 66 +- apps/sim/lib/subscription.ts | 2 +- apps/sim/lib/subscription/utils.test.ts | 22 +- apps/sim/lib/uploads/blob/blob-client.test.ts | 214 + apps/sim/lib/uploads/blob/blob-client.ts | 305 ++ apps/sim/lib/uploads/blob/index.ts | 11 + apps/sim/lib/uploads/index.ts | 28 + apps/sim/lib/uploads/s3/index.ts | 11 + .../lib/uploads/{ => s3}/s3-client.test.ts | 219 +- apps/sim/lib/uploads/{ => s3}/s3-client.ts | 17 +- apps/sim/lib/uploads/setup.server.ts | 61 +- apps/sim/lib/uploads/setup.ts | 54 +- apps/sim/lib/uploads/storage-client.ts | 200 + apps/sim/lib/usage-monitor.ts | 2 +- apps/sim/lib/utils.test.ts | 100 +- .../lib/variables/variable-manager.test.ts | 66 +- apps/sim/lib/variables/variable-manager.ts | 1 - .../sim/lib/webhooks/gmail-polling-service.ts | 16 +- apps/sim/lib/webhooks/utils.ts | 34 +- apps/sim/lib/workflows/db-helpers.test.ts | 784 ++++ apps/sim/lib/workflows/db-helpers.ts | 295 ++ apps/sim/lib/workflows/utils.ts | 35 + apps/sim/next.config.ts | 29 +- apps/sim/package.json | 12 +- apps/sim/providers/anthropic/index.ts | 10 +- apps/sim/providers/azure-openai/index.ts | 633 +++ apps/sim/providers/cerebras/index.ts | 6 +- apps/sim/providers/deepseek/index.ts | 5 +- apps/sim/providers/google/index.ts | 9 +- apps/sim/providers/groq/index.ts | 9 +- apps/sim/providers/index.ts | 12 +- apps/sim/providers/model-capabilities.test.ts | 80 - apps/sim/providers/model-capabilities.ts | 75 - apps/sim/providers/models.ts | 623 +++ apps/sim/providers/openai/index.ts | 5 +- apps/sim/providers/pricing.ts | 167 - apps/sim/providers/types.ts | 4 + apps/sim/providers/utils.test.ts | 660 ++- apps/sim/providers/utils.ts | 133 +- apps/sim/providers/workspace-provider.tsx | 23 + apps/sim/providers/xai/index.ts | 5 +- apps/sim/scripts/insert-test-workflow.ts | 168 + apps/sim/scripts/migrate-workflow-states.ts | 304 ++ apps/sim/serializer/types.ts | 2 + apps/sim/socket-server/config/socket.ts | 64 + apps/sim/socket-server/database/operations.ts | 641 +++ apps/sim/socket-server/handlers/connection.ts | 42 + apps/sim/socket-server/handlers/index.ts | 30 + apps/sim/socket-server/handlers/operations.ts | 169 + apps/sim/socket-server/handlers/presence.ts | 60 + apps/sim/socket-server/handlers/subblocks.ts | 134 + apps/sim/socket-server/handlers/workflow.ts | 149 + apps/sim/socket-server/index.test.ts | 316 ++ apps/sim/socket-server/index.ts | 111 + apps/sim/socket-server/middleware/auth.ts | 76 + .../socket-server/middleware/permissions.ts | 150 + apps/sim/socket-server/rooms/manager.ts | 183 + apps/sim/socket-server/routes/http.ts | 56 + apps/sim/socket-server/validation/schemas.ts | 70 + apps/sim/stores/constants.ts | 11 +- apps/sim/stores/folders/store.ts | 389 ++ apps/sim/stores/index.ts | 389 +- apps/sim/stores/knowledge/store.ts | 37 +- apps/sim/stores/panel/chat/types.ts | 2 +- apps/sim/stores/panel/console/store.test.ts | 297 ++ apps/sim/stores/panel/console/store.ts | 162 +- apps/sim/stores/panel/console/types.ts | 36 +- apps/sim/stores/panel/variables/store.ts | 2 +- apps/sim/stores/sync-core.ts | 189 - apps/sim/stores/sync-registry.ts | 99 - apps/sim/stores/sync.ts | 206 - apps/sim/stores/workflows/index.ts | 146 +- apps/sim/stores/workflows/middleware.ts | 49 - apps/sim/stores/workflows/persistence.ts | 215 +- apps/sim/stores/workflows/registry/store.ts | 1442 ++++--- apps/sim/stores/workflows/registry/types.ts | 21 +- apps/sim/stores/workflows/server-utils.ts | 116 + apps/sim/stores/workflows/subblock/store.ts | 477 +-- apps/sim/stores/workflows/sync.ts | 515 --- .../stores/workflows/workflow/store.test.ts | 37 +- apps/sim/stores/workflows/workflow/store.ts | 195 +- apps/sim/stores/workflows/workflow/types.ts | 68 +- apps/sim/stores/workflows/workflow/utils.ts | 7 +- apps/sim/test-socket-integration.html | 275 ++ apps/sim/tests/socket-server.test.ts | 227 + apps/sim/tools/huggingface/chat.ts | 193 + apps/sim/tools/huggingface/index.ts | 3 + apps/sim/tools/huggingface/types.ts | 39 + apps/sim/tools/knowledge/search.ts | 45 +- apps/sim/tools/knowledge/types.ts | 7 +- apps/sim/tools/knowledge/upload_chunk.ts | 15 +- apps/sim/tools/mistral/parser.ts | 4 - apps/sim/tools/registry.ts | 4 + apps/sim/tools/response/types.ts | 10 + apps/sim/tools/types.ts | 2 +- apps/sim/tools/utils.test.ts | 50 +- apps/sim/tools/workflow/executor.ts | 71 + apps/sim/tools/workflow/index.ts | 1 + apps/sim/vitest.setup.ts | 31 +- biome.json | 6 +- bun.lock | 676 +-- package.json | 3 +- packages/README.md | 249 ++ packages/{simstudio => cli}/README.md | 0 packages/{simstudio => cli}/package.json | 0 packages/{simstudio => cli}/src/index.ts | 0 packages/{simstudio => cli}/tsconfig.json | 0 packages/python-sdk/.gitignore | 84 + packages/python-sdk/README.md | 375 ++ packages/python-sdk/examples/basic_usage.py | 230 ++ packages/python-sdk/pyproject.toml | 84 + packages/python-sdk/setup.py | 51 + packages/python-sdk/simstudio/__init__.py | 239 ++ packages/python-sdk/tests/__init__.py | 0 packages/python-sdk/tests/test_client.py | 97 + packages/ts-sdk/.gitignore | 43 + packages/ts-sdk/README.md | 318 ++ packages/ts-sdk/examples/basic-usage.ts | 130 + packages/ts-sdk/package.json | 61 + packages/ts-sdk/src/index.test.ts | 117 + packages/ts-sdk/src/index.ts | 180 + packages/ts-sdk/tsconfig.json | 20 + packages/ts-sdk/vitest.config.ts | 11 + railway.json | 21 + turbo.json | 2 +- 399 files changed, 60719 insertions(+), 12149 deletions(-) create mode 100644 .github/workflows/publish-python-sdk.yml create mode 100644 .github/workflows/publish-ts-sdk.yml create mode 100644 apps/docs/content/docs/blocks/response.mdx create mode 100644 apps/docs/content/docs/blocks/workflow.mdx create mode 100644 apps/docs/content/docs/sdks/python.mdx create mode 100644 apps/docs/content/docs/sdks/typescript.mdx create mode 100644 apps/docs/content/docs/tools/huggingface.mdx create mode 100644 apps/docs/public/static/dark/response-dark.png create mode 100644 apps/docs/public/static/dark/workflow-dark.png create mode 100644 apps/docs/public/static/light/response-light.png create mode 100644 apps/docs/public/static/light/workflow-light.png delete mode 100644 apps/sim/.env.example create mode 100644 apps/sim/app/api/auth/reset-password/route.test.ts create mode 100644 apps/sim/app/api/auth/socket-token/route.ts delete mode 100644 apps/sim/app/api/auth/verify-waitlist-token/route.ts create mode 100644 apps/sim/app/api/files/presigned/route.test.ts create mode 100644 apps/sim/app/api/folders/[id]/route.test.ts create mode 100644 apps/sim/app/api/folders/[id]/route.ts create mode 100644 apps/sim/app/api/folders/route.test.ts create mode 100644 apps/sim/app/api/folders/route.ts create mode 100644 apps/sim/app/api/function/execute/route.test.ts delete mode 100644 apps/sim/app/api/knowledge/[id]/documents/[documentId]/retry/route.ts create mode 100644 apps/sim/app/api/knowledge/[id]/documents/[documentId]/route.test.ts create mode 100644 apps/sim/app/api/knowledge/[id]/documents/route.test.ts delete mode 100644 apps/sim/app/api/knowledge/[id]/process-documents/route.ts create mode 100644 apps/sim/app/api/knowledge/[id]/route.test.ts create mode 100644 apps/sim/app/api/knowledge/route.test.ts create mode 100644 apps/sim/app/api/knowledge/search/route.test.ts create mode 100644 apps/sim/app/api/knowledge/utils.test.ts create mode 100644 apps/sim/app/api/workflows/[id]/duplicate/route.ts create mode 100644 apps/sim/app/api/workflows/[id]/route.ts create mode 100644 apps/sim/app/api/workflows/route.ts create mode 100644 apps/sim/app/api/workspaces/[id]/permissions/route.ts create mode 100644 apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/components/user-avatar/user-avatar.tsx create mode 100644 apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx create mode 100644 apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx create mode 100644 apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/property-renderer.tsx create mode 100644 apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx create mode 100644 apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx create mode 100644 apps/sim/app/w/[id]/hooks/use-presence.ts create mode 100644 apps/sim/app/w/components/providers/workspace-permissions-provider.tsx create mode 100644 apps/sim/app/w/components/sidebar/components/create-menu/create-menu.tsx create mode 100644 apps/sim/app/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx create mode 100644 apps/sim/app/w/components/sidebar/components/folder-tree/components/folder-item.tsx create mode 100644 apps/sim/app/w/components/sidebar/components/folder-tree/components/workflow-item.tsx create mode 100644 apps/sim/app/w/components/sidebar/components/folder-tree/folder-tree.tsx create mode 100644 apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx create mode 100644 apps/sim/app/w/knowledge/[id]/components/action-bar/action-bar.tsx rename apps/sim/app/w/knowledge/[id]/components/{ => knowledge-base-loading}/knowledge-base-loading.tsx (94%) delete mode 100644 apps/sim/app/w/knowledge/components/create-modal/components/create-form/create-form.tsx create mode 100644 apps/sim/app/w/knowledge/components/primary-button/primary-button.tsx create mode 100644 apps/sim/app/w/knowledge/components/search-input/search-input.tsx create mode 100644 apps/sim/app/w/logs/components/filters/components/folder.tsx create mode 100644 apps/sim/app/w/page.tsx create mode 100644 apps/sim/blocks/blocks/huggingface.ts create mode 100644 apps/sim/blocks/blocks/response.ts create mode 100644 apps/sim/blocks/blocks/workflow.ts create mode 100644 apps/sim/contexts/socket-context.tsx create mode 100644 apps/sim/db/migrations/0042_breezy_miracleman.sql create mode 100644 apps/sim/db/migrations/0043_silent_the_anarchist.sql create mode 100644 apps/sim/db/migrations/0044_uneven_killer_shrike.sql create mode 100644 apps/sim/db/migrations/0045_sour_chameleon.sql create mode 100644 apps/sim/db/migrations/0046_loose_blizzard.sql create mode 100644 apps/sim/db/migrations/0047_new_triathlon.sql create mode 100644 apps/sim/db/migrations/meta/0042_snapshot.json create mode 100644 apps/sim/db/migrations/meta/0043_snapshot.json create mode 100644 apps/sim/db/migrations/meta/0044_snapshot.json create mode 100644 apps/sim/db/migrations/meta/0045_snapshot.json create mode 100644 apps/sim/db/migrations/meta/0046_snapshot.json create mode 100644 apps/sim/db/migrations/meta/0047_snapshot.json delete mode 100644 apps/sim/db/migrations/relations.ts delete mode 100644 apps/sim/db/migrations/schema.ts create mode 100644 apps/sim/executor/handlers/response/response-handler.ts create mode 100644 apps/sim/executor/handlers/workflow/workflow-handler.test.ts create mode 100644 apps/sim/executor/handlers/workflow/workflow-handler.ts create mode 100644 apps/sim/hooks/use-collaborative-workflow.ts create mode 100644 apps/sim/hooks/use-user-permissions.ts create mode 100644 apps/sim/hooks/use-workspace-permissions.ts create mode 100644 apps/sim/lib/documents/chunker.ts create mode 100644 apps/sim/lib/email/utils.test.ts create mode 100644 apps/sim/lib/email/utils.ts create mode 100644 apps/sim/lib/file-parsers/md-parser.ts create mode 100644 apps/sim/lib/file-parsers/txt-parser.ts create mode 100644 apps/sim/lib/file-parsers/xlsx-parser.ts create mode 100644 apps/sim/lib/oauth/index.ts create mode 100644 apps/sim/lib/oauth/oauth.test.ts rename apps/sim/lib/{ => oauth}/oauth.ts (73%) create mode 100644 apps/sim/lib/permissions/utils.test.ts create mode 100644 apps/sim/lib/permissions/utils.ts create mode 100644 apps/sim/lib/uploads/blob/blob-client.test.ts create mode 100644 apps/sim/lib/uploads/blob/blob-client.ts create mode 100644 apps/sim/lib/uploads/blob/index.ts create mode 100644 apps/sim/lib/uploads/index.ts create mode 100644 apps/sim/lib/uploads/s3/index.ts rename apps/sim/lib/uploads/{ => s3}/s3-client.test.ts (52%) rename apps/sim/lib/uploads/{ => s3}/s3-client.ts (92%) create mode 100644 apps/sim/lib/uploads/storage-client.ts create mode 100644 apps/sim/lib/workflows/db-helpers.test.ts create mode 100644 apps/sim/lib/workflows/db-helpers.ts create mode 100644 apps/sim/providers/azure-openai/index.ts delete mode 100644 apps/sim/providers/model-capabilities.test.ts delete mode 100644 apps/sim/providers/model-capabilities.ts create mode 100644 apps/sim/providers/models.ts delete mode 100644 apps/sim/providers/pricing.ts create mode 100644 apps/sim/providers/workspace-provider.tsx create mode 100755 apps/sim/scripts/insert-test-workflow.ts create mode 100755 apps/sim/scripts/migrate-workflow-states.ts create mode 100644 apps/sim/socket-server/config/socket.ts create mode 100644 apps/sim/socket-server/database/operations.ts create mode 100644 apps/sim/socket-server/handlers/connection.ts create mode 100644 apps/sim/socket-server/handlers/index.ts create mode 100644 apps/sim/socket-server/handlers/operations.ts create mode 100644 apps/sim/socket-server/handlers/presence.ts create mode 100644 apps/sim/socket-server/handlers/subblocks.ts create mode 100644 apps/sim/socket-server/handlers/workflow.ts create mode 100644 apps/sim/socket-server/index.test.ts create mode 100644 apps/sim/socket-server/index.ts create mode 100644 apps/sim/socket-server/middleware/auth.ts create mode 100644 apps/sim/socket-server/middleware/permissions.ts create mode 100644 apps/sim/socket-server/rooms/manager.ts create mode 100644 apps/sim/socket-server/routes/http.ts create mode 100644 apps/sim/socket-server/validation/schemas.ts create mode 100644 apps/sim/stores/folders/store.ts create mode 100644 apps/sim/stores/panel/console/store.test.ts delete mode 100644 apps/sim/stores/sync-core.ts delete mode 100644 apps/sim/stores/sync-registry.ts delete mode 100644 apps/sim/stores/sync.ts create mode 100644 apps/sim/stores/workflows/server-utils.ts delete mode 100644 apps/sim/stores/workflows/sync.ts create mode 100644 apps/sim/test-socket-integration.html create mode 100644 apps/sim/tests/socket-server.test.ts create mode 100644 apps/sim/tools/huggingface/chat.ts create mode 100644 apps/sim/tools/huggingface/index.ts create mode 100644 apps/sim/tools/huggingface/types.ts create mode 100644 apps/sim/tools/response/types.ts create mode 100644 apps/sim/tools/workflow/executor.ts create mode 100644 apps/sim/tools/workflow/index.ts create mode 100644 packages/README.md rename packages/{simstudio => cli}/README.md (100%) rename packages/{simstudio => cli}/package.json (100%) rename packages/{simstudio => cli}/src/index.ts (100%) rename packages/{simstudio => cli}/tsconfig.json (100%) create mode 100644 packages/python-sdk/.gitignore create mode 100644 packages/python-sdk/README.md create mode 100644 packages/python-sdk/examples/basic_usage.py create mode 100644 packages/python-sdk/pyproject.toml create mode 100644 packages/python-sdk/setup.py create mode 100644 packages/python-sdk/simstudio/__init__.py create mode 100644 packages/python-sdk/tests/__init__.py create mode 100644 packages/python-sdk/tests/test_client.py create mode 100644 packages/ts-sdk/.gitignore create mode 100644 packages/ts-sdk/README.md create mode 100644 packages/ts-sdk/examples/basic-usage.ts create mode 100644 packages/ts-sdk/package.json create mode 100644 packages/ts-sdk/src/index.test.ts create mode 100644 packages/ts-sdk/src/index.ts create mode 100644 packages/ts-sdk/tsconfig.json create mode 100644 packages/ts-sdk/vitest.config.ts create mode 100644 railway.json diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml index 81b1b6893df..41bce6a7b68 100644 --- a/.github/workflows/publish-cli.yml +++ b/.github/workflows/publish-cli.yml @@ -4,7 +4,7 @@ on: push: branches: [main] paths: - - 'packages/simstudio/**' + - 'packages/cli/**' jobs: publish-npm: @@ -25,16 +25,16 @@ jobs: registry-url: 'https://registry.npmjs.org/' - name: Install dependencies - working-directory: packages/simstudio + working-directory: packages/cli run: bun install - name: Build package - working-directory: packages/simstudio + working-directory: packages/cli run: bun run build - name: Get package version id: package_version - working-directory: packages/simstudio + working-directory: packages/cli run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT - name: Check if version already exists @@ -48,7 +48,7 @@ jobs: - name: Publish to npm if: steps.version_check.outputs.exists == 'false' - working-directory: packages/simstudio + working-directory: packages/cli run: npm publish --access=public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish-python-sdk.yml b/.github/workflows/publish-python-sdk.yml new file mode 100644 index 00000000000..6892405de1f --- /dev/null +++ b/.github/workflows/publish-python-sdk.yml @@ -0,0 +1,89 @@ +name: Publish Python SDK + +on: + push: + branches: [main] + paths: + - 'packages/python-sdk/**' + +jobs: + publish-pypi: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: 'pip' + + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + pip install build twine pytest requests tomli + + - name: Run tests + working-directory: packages/python-sdk + run: | + PYTHONPATH=. pytest tests/ -v + + - name: Get package version + id: package_version + working-directory: packages/python-sdk + run: echo "version=$(python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])")" >> $GITHUB_OUTPUT + + - name: Check if version already exists + id: version_check + run: | + if pip index versions simstudio-sdk | grep -q "${{ steps.package_version.outputs.version }}"; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Build package + if: steps.version_check.outputs.exists == 'false' + working-directory: packages/python-sdk + run: python -m build + + - name: Check package + if: steps.version_check.outputs.exists == 'false' + working-directory: packages/python-sdk + run: twine check dist/* + + - name: Publish to PyPI + if: steps.version_check.outputs.exists == 'false' + working-directory: packages/python-sdk + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: twine upload dist/* + + - name: Log skipped publish + if: steps.version_check.outputs.exists == 'true' + run: echo "Skipped publishing because version ${{ steps.package_version.outputs.version }} already exists on PyPI" + + - name: Create GitHub Release + if: steps.version_check.outputs.exists == 'false' + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: python-sdk-v${{ steps.package_version.outputs.version }} + name: Python SDK v${{ steps.package_version.outputs.version }} + body: | + ## Python SDK v${{ steps.package_version.outputs.version }} + + Published simstudio-sdk==${{ steps.package_version.outputs.version }} to PyPI. + + ### Installation + ```bash + pip install simstudio-sdk==${{ steps.package_version.outputs.version }} + ``` + + ### Documentation + See the [README](https://github.com/simstudio/sim/tree/main/packages/python-sdk) for usage instructions. + draft: false + prerelease: false \ No newline at end of file diff --git a/.github/workflows/publish-ts-sdk.yml b/.github/workflows/publish-ts-sdk.yml new file mode 100644 index 00000000000..360f5aa20a6 --- /dev/null +++ b/.github/workflows/publish-ts-sdk.yml @@ -0,0 +1,85 @@ +name: Publish TypeScript SDK + +on: + push: + branches: [main] + paths: + - 'packages/ts-sdk/**' + +jobs: + publish-npm: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Setup Node.js for npm publishing + uses: actions/setup-node@v4 + with: + node-version: '18' + registry-url: 'https://registry.npmjs.org/' + + - name: Install dependencies + working-directory: packages/ts-sdk + run: bun install + + - name: Run tests + working-directory: packages/ts-sdk + run: bun run test + + - name: Build package + working-directory: packages/ts-sdk + run: bun run build + + - name: Get package version + id: package_version + working-directory: packages/ts-sdk + run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT + + - name: Check if version already exists + id: version_check + run: | + if npm view simstudio-ts-sdk@${{ steps.package_version.outputs.version }} version &> /dev/null; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Publish to npm + if: steps.version_check.outputs.exists == 'false' + working-directory: packages/ts-sdk + run: npm publish --access=public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Log skipped publish + if: steps.version_check.outputs.exists == 'true' + run: echo "Skipped publishing because version ${{ steps.package_version.outputs.version }} already exists on npm" + + - name: Create GitHub Release + if: steps.version_check.outputs.exists == 'false' + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: typescript-sdk-v${{ steps.package_version.outputs.version }} + name: TypeScript SDK v${{ steps.package_version.outputs.version }} + body: | + ## TypeScript SDK v${{ steps.package_version.outputs.version }} + + Published simstudio-ts-sdk@${{ steps.package_version.outputs.version }} to npm. + + ### Installation + ```bash + npm install simstudio-ts-sdk@${{ steps.package_version.outputs.version }} + ``` + + ### Documentation + See the [README](https://github.com/simstudio/sim/tree/main/packages/ts-sdk) for usage instructions. + draft: false + prerelease: false \ No newline at end of file diff --git a/.gitignore b/.gitignore index 33e7b36c952..08dedb8678c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,6 @@ sim-standalone.tar.gz # misc .DS_Store *.pem -uploads/ # env files .env @@ -63,4 +62,7 @@ docker-compose.collector.yml start-collector.sh # Turborepo -.turbo \ No newline at end of file +.turbo + +# VSCode +.vscode \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index f54fc9cd5cf..36946c38ebf 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -bunx lint-staged \ No newline at end of file +bun lint \ No newline at end of file diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index feac645b6ed..876fb6ad018 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -263,3 +263,10 @@ export const SlackIcon = (props: SVGProps) => ( ) + +export const ResponseIcon = (props: SVGProps) => ( + + + + +) diff --git a/apps/docs/components/ui/block-types.tsx b/apps/docs/components/ui/block-types.tsx index 1b2394666e7..96937dc728a 100644 --- a/apps/docs/components/ui/block-types.tsx +++ b/apps/docs/components/ui/block-types.tsx @@ -1,5 +1,13 @@ import { cn } from '@/lib/utils' -import { AgentIcon, ApiIcon, ChartBarIcon, CodeIcon, ConditionalIcon, ConnectIcon } from '../icons' +import { + AgentIcon, + ApiIcon, + ChartBarIcon, + CodeIcon, + ConditionalIcon, + ConnectIcon, + ResponseIcon, +} from '../icons' // Custom Feature component specifically for BlockTypes to handle the 6-item layout const BlockFeature = ({ @@ -127,6 +135,13 @@ export function BlockTypes() { icon: , href: '/blocks/evaluator', }, + { + title: 'Response', + description: + 'Send a response back to the caller with customizable data, status, and headers.', + icon: , + href: '/blocks/response', + }, ] const totalItems = features.length diff --git a/apps/docs/content/docs/blocks/meta.json b/apps/docs/content/docs/blocks/meta.json index 770522e1dd7..98a69a80e8a 100644 --- a/apps/docs/content/docs/blocks/meta.json +++ b/apps/docs/content/docs/blocks/meta.json @@ -1,4 +1,4 @@ { "title": "Blocks", - "pages": ["agent", "api", "condition", "function", "evaluator", "router"] + "pages": ["agent", "api", "condition", "function", "evaluator", "router", "response", "workflow"] } diff --git a/apps/docs/content/docs/blocks/response.mdx b/apps/docs/content/docs/blocks/response.mdx new file mode 100644 index 00000000000..2570acd872b --- /dev/null +++ b/apps/docs/content/docs/blocks/response.mdx @@ -0,0 +1,188 @@ +--- +title: Response +description: Send a structured response back to API calls +--- + +import { Callout } from 'fumadocs-ui/components/callout' +import { Step, Steps } from 'fumadocs-ui/components/steps' +import { Tab, Tabs } from 'fumadocs-ui/components/tabs' +import { ThemeImage } from '@/components/ui/theme-image' + +The Response block is the final component in API-enabled workflows that transforms your workflow's variables into a structured HTTP response. This block serves as the endpoint that returns data, status codes, and headers back to API callers. + + + + + Response blocks are terminal blocks - they mark the end of a workflow execution and cannot have further connections. + + +## Overview + +The Response block serves as the final output mechanism for API workflows, enabling you to: + + + + Return structured data: Transform workflow variables into JSON responses + + + Set HTTP status codes: Control the response status (200, 400, 500, etc.) + + + Configure headers: Add custom HTTP headers to the response + + + Reference variables: Use workflow variables dynamically in the response + + + +## Configuration Options + +### Response Data + +The response data is the main content that will be sent back to the API caller. This should be formatted as JSON and can include: + +- Static values +- Dynamic references to workflow variables using the `` syntax +- Nested objects and arrays +- Any valid JSON structure + +### Status Code + +Set the HTTP status code for the response. Common status codes include: + + + +
    +
  • 200: OK - Standard success response
  • +
  • 201: Created - Resource successfully created
  • +
  • 204: No Content - Success with no response body
  • +
+
+ +
    +
  • 400: Bad Request - Invalid request parameters
  • +
  • 401: Unauthorized - Authentication required
  • +
  • 404: Not Found - Resource doesn't exist
  • +
  • 422: Unprocessable Entity - Validation errors
  • +
+
+ +
    +
  • 500: Internal Server Error - Server-side error
  • +
  • 502: Bad Gateway - External service error
  • +
  • 503: Service Unavailable - Service temporarily down
  • +
+
+
+ +

+ Default status code is 200 if not specified. +

+ +### Response Headers + +Configure additional HTTP headers to include in the response. + +Headers are configured as key-value pairs: + +| Key | Value | +|-----|-------| +| Content-Type | application/json | +| Cache-Control | no-cache | +| X-API-Version | 1.0 | + +## Inputs and Outputs + + + +
    +
  • + data (JSON, optional): The JSON data to send in the response body +
  • +
  • + status (number, optional): HTTP status code (default: 200) +
  • +
  • + headers (JSON, optional): Additional response headers +
  • +
+
+ +
    +
  • + response: Complete response object containing: +
      +
    • data: The response body data
    • +
    • status: HTTP status code
    • +
    • headers: Response headers
    • +
    +
  • +
+
+
+ +## Variable References + +Use the `` syntax to dynamically insert workflow variables into your response: + +```json +{ + "user": { + "id": "", + "name": "", + "email": "" + }, + "query": "", + "results": "", + "totalFound": "", + "processingTime": "ms" +} +``` + + + Variable names are case-sensitive and must match exactly with the variables available in your workflow. + + +## Example Usage + +Here's an example of how a Response block might be configured for a user search API: + +```yaml +data: | + { + "success": true, + "data": { + "users": "", + "pagination": { + "page": "", + "limit": "", + "total": "" + } + }, + "query": { + "searchTerm": "", + "filters": "" + }, + "timestamp": "" + } +status: 200 +headers: + - key: X-Total-Count + value: + - key: Cache-Control + value: public, max-age=300 +``` + +## Best Practices + +- **Use meaningful status codes**: Choose appropriate HTTP status codes that accurately reflect the outcome of the workflow +- **Structure your responses consistently**: Maintain a consistent JSON structure across all your API endpoints for better developer experience +- **Include relevant metadata**: Add timestamps and version information to help with debugging and monitoring +- **Handle errors gracefully**: Use conditional logic in your workflow to set appropriate error responses with descriptive messages +- **Validate variable references**: Ensure all referenced variables exist and contain the expected data types before the Response block executes \ No newline at end of file diff --git a/apps/docs/content/docs/blocks/workflow.mdx b/apps/docs/content/docs/blocks/workflow.mdx new file mode 100644 index 00000000000..f45e0ce4173 --- /dev/null +++ b/apps/docs/content/docs/blocks/workflow.mdx @@ -0,0 +1,231 @@ +--- +title: Workflow +description: Execute other workflows as reusable components within your current workflow +--- + +import { Callout } from 'fumadocs-ui/components/callout' +import { Step, Steps } from 'fumadocs-ui/components/steps' +import { Tab, Tabs } from 'fumadocs-ui/components/tabs' +import { ThemeImage } from '@/components/ui/theme-image' + +The Workflow block allows you to execute other workflows as reusable components within your current workflow. This powerful feature enables modular design, code reuse, and the creation of complex nested workflows that can be composed from smaller, focused workflows. + + + + + Workflow blocks enable modular design by allowing you to compose complex workflows from smaller, reusable components. + + +## Overview + +The Workflow block serves as a bridge between workflows, enabling you to: + + + + Reuse existing workflows: Execute previously created workflows as components within new workflows + + + Create modular designs: Break down complex processes into smaller, manageable workflows + + + Maintain separation of concerns: Keep different business logic isolated in separate workflows + + + Enable team collaboration: Share and reuse workflows across different projects and team members + + + +## How It Works + +The Workflow block: + +1. Takes a reference to another workflow in your workspace +2. Passes input data from the current workflow to the child workflow +3. Executes the child workflow in an isolated context +4. Returns the results back to the parent workflow for further processing + +## Configuration Options + +### Workflow Selection + +Choose which workflow to execute from a dropdown list of available workflows in your workspace. The list includes: + +- All workflows you have access to in the current workspace +- Workflows shared with you by other team members +- Both enabled and disabled workflows (though only enabled workflows can be executed) + +### Input Data + +Define the data to pass to the child workflow: + +- **Single Variable Input**: Select a variable or block output to pass to the child workflow +- **Variable References**: Use `` to reference workflow variables +- **Block References**: Use `` to reference outputs from previous blocks +- **Automatic Mapping**: The selected data is automatically available as `start.response.input` in the child workflow +- **Optional**: The input field is optional - child workflows can run without input data +- **Type Preservation**: Variable types (strings, numbers, objects, etc.) are preserved when passed to the child workflow + +### Examples of Input References + +- `` - Pass a workflow variable +- `` - Pass the result from a previous block +- `` - Pass the original workflow input +- `` - Pass a specific field from an API response + +### Execution Context + +The child workflow executes with: + +- Its own isolated execution context +- Access to the same workspace resources (API keys, environment variables) +- Proper workspace membership and permission checks +- Independent logging and monitoring + +## Safety and Limitations + +To prevent infinite recursion and ensure system stability, the Workflow block includes several safety mechanisms: + + + **Cycle Detection**: The system automatically detects and prevents circular dependencies between workflows to avoid infinite loops. + + +- **Maximum Depth Limit**: Nested workflows are limited to a maximum depth of 10 levels +- **Cycle Detection**: Automatic detection and prevention of circular workflow dependencies +- **Timeout Protection**: Child workflows inherit timeout settings to prevent indefinite execution +- **Resource Limits**: Memory and execution time limits apply to prevent resource exhaustion + +## Inputs and Outputs + + + +
    +
  • + Workflow ID: The identifier of the workflow to execute +
  • +
  • + Input Variable: Variable or block reference to pass to the child workflow (e.g., `` or ``) +
  • +
+
+ +
    +
  • + Response: The complete output from the child workflow execution +
  • +
  • + Child Workflow Name: The name of the executed child workflow +
  • +
  • + Success Status: Boolean indicating whether the child workflow completed successfully +
  • +
  • + Error Information: Details about any errors that occurred during execution +
  • +
  • + Execution Metadata: Information about execution time, resource usage, and performance +
  • +
+
+
+ +## Example Usage + +Here's an example of how a Workflow block might be used to create a modular customer onboarding process: + +### Parent Workflow: Customer Onboarding +```yaml +# Main customer onboarding workflow +blocks: + - type: workflow + name: "Validate Customer Data" + workflowId: "customer-validation-workflow" + input: "" + + - type: workflow + name: "Setup Customer Account" + workflowId: "account-setup-workflow" + input: "" + + - type: workflow + name: "Send Welcome Email" + workflowId: "welcome-email-workflow" + input: "" +``` + +### Child Workflow: Customer Validation +```yaml +# Reusable customer validation workflow +# Access the input data using: start.response.input +blocks: + - type: function + name: "Validate Email" + code: | + const customerData = start.response.input; + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(customerData.email); + + - type: api + name: "Check Credit Score" + url: "https://api.creditcheck.com/score" + method: "POST" + body: "" +``` + +### Variable Reference Examples + +```yaml +# Using workflow variables +input: "" + +# Using block outputs +input: "" + +# Using nested object properties +input: "" + +# Using array elements (if supported by the resolver) +input: "" +``` + +## Access Control and Permissions + +The Workflow block respects workspace permissions and access controls: + +- **Workspace Membership**: Only workflows within the same workspace can be executed +- **Permission Inheritance**: Child workflows inherit the execution permissions of the parent workflow +- **API Key Access**: Child workflows have access to the same API keys and environment variables as the parent +- **User Context**: The execution maintains the original user context for audit and logging purposes + +## Best Practices + +- **Keep workflows focused**: Design child workflows to handle specific, well-defined tasks +- **Minimize nesting depth**: Avoid deeply nested workflow hierarchies for better maintainability +- **Handle errors gracefully**: Implement proper error handling for child workflow failures +- **Document dependencies**: Clearly document which workflows depend on others +- **Version control**: Consider versioning strategies for workflows that are used as components +- **Test independently**: Ensure child workflows can be tested and validated independently +- **Monitor performance**: Be aware that nested workflows can impact overall execution time + +## Common Patterns + +### Microservice Architecture +Break down complex business processes into smaller, focused workflows that can be developed and maintained independently. + +### Reusable Components +Create library workflows for common operations like data validation, email sending, or API integrations that can be reused across multiple projects. + +### Conditional Execution +Use workflow blocks within conditional logic to execute different business processes based on runtime conditions. + +### Parallel Processing +Combine workflow blocks with parallel execution to run multiple child workflows simultaneously for improved performance. + + + When designing modular workflows, think of each workflow as a function with clear inputs, outputs, and a single responsibility. + \ No newline at end of file diff --git a/apps/docs/content/docs/meta.json b/apps/docs/content/docs/meta.json index 953c887daab..6b37a43525f 100644 --- a/apps/docs/content/docs/meta.json +++ b/apps/docs/content/docs/meta.json @@ -12,7 +12,10 @@ "---Execution---", "execution", "---Advanced---", - "./variables/index" + "./variables/index", + "---SDKs---", + "./sdks/python", + "./sdks/typescript" ], "defaultOpen": true } diff --git a/apps/docs/content/docs/sdks/python.mdx b/apps/docs/content/docs/sdks/python.mdx new file mode 100644 index 00000000000..277080da7b2 --- /dev/null +++ b/apps/docs/content/docs/sdks/python.mdx @@ -0,0 +1,409 @@ +--- +title: Python SDK +description: The official Python SDK for Sim Studio +--- + +import { Callout } from 'fumadocs-ui/components/callout' +import { Card, Cards } from 'fumadocs-ui/components/card' +import { Step, Steps } from 'fumadocs-ui/components/steps' +import { Tab, Tabs } from 'fumadocs-ui/components/tabs' + +The official Python SDK for Sim Studio allows you to execute workflows programmatically from your Python applications. + + + The Python SDK supports Python 3.8+ and provides synchronous workflow execution. All workflow executions are currently synchronous. + + +## Installation + +Install the SDK using pip: + +```bash +pip install simstudio-sdk +``` + +## Quick Start + +Here's a simple example to get you started: + +```python +from simstudio import SimStudioClient + +# Initialize the client +client = SimStudioClient( + api_key="your-api-key-here", + base_url="https://simstudio.ai" # optional, defaults to https://simstudio.ai +) + +# Execute a workflow +try: + result = client.execute_workflow("workflow-id") + print("Workflow executed successfully:", result) +except Exception as error: + print("Workflow execution failed:", error) +``` + +## API Reference + +### SimStudioClient + +#### Constructor + +```python +SimStudioClient(api_key: str, base_url: str = "https://simstudio.ai") +``` + +**Parameters:** +- `api_key` (str): Your Sim Studio API key +- `base_url` (str, optional): Base URL for the Sim Studio API + +#### Methods + +##### execute_workflow() + +Execute a workflow with optional input data. + +```python +result = client.execute_workflow( + "workflow-id", + input_data={"message": "Hello, world!"}, + timeout=30.0 # 30 seconds +) +``` + +**Parameters:** +- `workflow_id` (str): The ID of the workflow to execute +- `input_data` (dict, optional): Input data to pass to the workflow +- `timeout` (float, optional): Timeout in seconds (default: 30.0) + +**Returns:** `WorkflowExecutionResult` + +##### get_workflow_status() + +Get the status of a workflow (deployment status, etc.). + +```python +status = client.get_workflow_status("workflow-id") +print("Is deployed:", status.is_deployed) +``` + +**Parameters:** +- `workflow_id` (str): The ID of the workflow + +**Returns:** `WorkflowStatus` + +##### validate_workflow() + +Validate that a workflow is ready for execution. + +```python +is_ready = client.validate_workflow("workflow-id") +if is_ready: + # Workflow is deployed and ready + pass +``` + +**Parameters:** +- `workflow_id` (str): The ID of the workflow + +**Returns:** `bool` + +##### execute_workflow_sync() + + + Currently, this method is identical to `execute_workflow()` since all executions are synchronous. This method is provided for future compatibility when asynchronous execution is added. + + +Execute a workflow (currently synchronous, same as `execute_workflow()`). + +```python +result = client.execute_workflow_sync( + "workflow-id", + input_data={"data": "some input"}, + timeout=60.0 +) +``` + +**Parameters:** +- `workflow_id` (str): The ID of the workflow to execute +- `input_data` (dict, optional): Input data to pass to the workflow +- `timeout` (float): Timeout for the initial request in seconds + +**Returns:** `WorkflowExecutionResult` + +##### set_api_key() + +Update the API key. + +```python +client.set_api_key("new-api-key") +``` + +##### set_base_url() + +Update the base URL. + +```python +client.set_base_url("https://my-custom-domain.com") +``` + +##### close() + +Close the underlying HTTP session. + +```python +client.close() +``` + +## Data Classes + +### WorkflowExecutionResult + +```python +@dataclass +class WorkflowExecutionResult: + success: bool + output: Optional[Any] = None + error: Optional[str] = None + logs: Optional[List[Any]] = None + metadata: Optional[Dict[str, Any]] = None + trace_spans: Optional[List[Any]] = None + total_duration: Optional[float] = None +``` + +### WorkflowStatus + +```python +@dataclass +class WorkflowStatus: + is_deployed: bool + deployed_at: Optional[str] = None + is_published: bool = False + needs_redeployment: bool = False +``` + +### SimStudioError + +```python +class SimStudioError(Exception): + def __init__(self, message: str, code: Optional[str] = None, status: Optional[int] = None): + super().__init__(message) + self.code = code + self.status = status +``` + +## Examples + +### Basic Workflow Execution + + + + Set up the SimStudioClient with your API key. + + + Check if the workflow is deployed and ready for execution. + + + Run the workflow with your input data. + + + Process the execution result and handle any errors. + + + +```python +import os +from simstudio import SimStudioClient + +client = SimStudioClient(api_key=os.getenv("SIMSTUDIO_API_KEY")) + +def run_workflow(): + try: + # Check if workflow is ready + is_ready = client.validate_workflow("my-workflow-id") + if not is_ready: + raise Exception("Workflow is not deployed or ready") + + # Execute the workflow + result = client.execute_workflow( + "my-workflow-id", + input_data={ + "message": "Process this data", + "user_id": "12345" + } + ) + + if result.success: + print("Output:", result.output) + print("Duration:", result.metadata.get("duration") if result.metadata else None) + else: + print("Workflow failed:", result.error) + + except Exception as error: + print("Error:", error) + +run_workflow() +``` + +### Error Handling + +Handle different types of errors that may occur during workflow execution: + +```python +from simstudio import SimStudioClient, SimStudioError +import os + +client = SimStudioClient(api_key=os.getenv("SIMSTUDIO_API_KEY")) + +def execute_with_error_handling(): + try: + result = client.execute_workflow("workflow-id") + return result + except SimStudioError as error: + if error.code == "UNAUTHORIZED": + print("Invalid API key") + elif error.code == "TIMEOUT": + print("Workflow execution timed out") + elif error.code == "USAGE_LIMIT_EXCEEDED": + print("Usage limit exceeded") + elif error.code == "INVALID_JSON": + print("Invalid JSON in request body") + else: + print(f"Workflow error: {error}") + raise + except Exception as error: + print(f"Unexpected error: {error}") + raise +``` + +### Context Manager Usage + +Use the client as a context manager to automatically handle resource cleanup: + +```python +from simstudio import SimStudioClient +import os + +# Using context manager to automatically close the session +with SimStudioClient(api_key=os.getenv("SIMSTUDIO_API_KEY")) as client: + result = client.execute_workflow("workflow-id") + print("Result:", result) +# Session is automatically closed here +``` + +### Batch Workflow Execution + +Execute multiple workflows efficiently: + +```python +from simstudio import SimStudioClient +import os + +client = SimStudioClient(api_key=os.getenv("SIMSTUDIO_API_KEY")) + +def execute_workflows_batch(workflow_data_pairs): + """Execute multiple workflows with different input data.""" + results = [] + + for workflow_id, input_data in workflow_data_pairs: + try: + # Validate workflow before execution + if not client.validate_workflow(workflow_id): + print(f"Skipping {workflow_id}: not deployed") + continue + + result = client.execute_workflow(workflow_id, input_data) + results.append({ + "workflow_id": workflow_id, + "success": result.success, + "output": result.output, + "error": result.error + }) + + except Exception as error: + results.append({ + "workflow_id": workflow_id, + "success": False, + "error": str(error) + }) + + return results + +# Example usage +workflows = [ + ("workflow-1", {"type": "analysis", "data": "sample1"}), + ("workflow-2", {"type": "processing", "data": "sample2"}), +] + +results = execute_workflows_batch(workflows) +for result in results: + print(f"Workflow {result['workflow_id']}: {'Success' if result['success'] else 'Failed'}") +``` + +### Environment Configuration + +Configure the client using environment variables: + + + + ```python + import os + from simstudio import SimStudioClient + + # Development configuration + client = SimStudioClient( + api_key=os.getenv("SIMSTUDIO_API_KEY"), + base_url=os.getenv("SIMSTUDIO_BASE_URL", "https://simstudio.ai") + ) + ``` + + + ```python + import os + from simstudio import SimStudioClient + + # Production configuration with error handling + api_key = os.getenv("SIMSTUDIO_API_KEY") + if not api_key: + raise ValueError("SIMSTUDIO_API_KEY environment variable is required") + + client = SimStudioClient( + api_key=api_key, + base_url=os.getenv("SIMSTUDIO_BASE_URL", "https://simstudio.ai") + ) + ``` + + + +## Getting Your API Key + + + + Navigate to [Sim Studio](https://simstudio.ai) and log in to your account. + + + Navigate to the workflow you want to execute programmatically. + + + Click on "Deploy" to deploy your workflow if it hasn't been deployed yet. + + + During the deployment process, select or create an API key. + + + Copy the API key to use in your Python application. + + + + + Keep your API key secure and never commit it to version control. Use environment variables or secure configuration management. + + +## Requirements + +- Python 3.8+ +- requests >= 2.25.0 + +## License + +Apache-2.0 \ No newline at end of file diff --git a/apps/docs/content/docs/sdks/typescript.mdx b/apps/docs/content/docs/sdks/typescript.mdx new file mode 100644 index 00000000000..6fb4bf4f7c8 --- /dev/null +++ b/apps/docs/content/docs/sdks/typescript.mdx @@ -0,0 +1,598 @@ +--- +title: TypeScript/JavaScript SDK +description: The official TypeScript/JavaScript SDK for Sim Studio +--- + +import { Callout } from 'fumadocs-ui/components/callout' +import { Card, Cards } from 'fumadocs-ui/components/card' +import { Step, Steps } from 'fumadocs-ui/components/steps' +import { Tab, Tabs } from 'fumadocs-ui/components/tabs' + +The official TypeScript/JavaScript SDK for Sim Studio allows you to execute workflows programmatically from your Node.js applications, web applications, and other JavaScript environments. + + + The TypeScript SDK provides full type safety and supports both Node.js and browser environments. All workflow executions are currently synchronous. + + +## Installation + +Install the SDK using your preferred package manager: + + + + ```bash + npm install simstudio-ts-sdk + ``` + + + ```bash + yarn add simstudio-ts-sdk + ``` + + + ```bash + bun add simstudio-ts-sdk + ``` + + + +## Quick Start + +Here's a simple example to get you started: + +```typescript +import { SimStudioClient } from 'simstudio-ts-sdk'; + +// Initialize the client +const client = new SimStudioClient({ + apiKey: 'your-api-key-here', + baseUrl: 'https://simstudio.ai' // optional, defaults to https://simstudio.ai +}); + +// Execute a workflow +try { + const result = await client.executeWorkflow('workflow-id'); + console.log('Workflow executed successfully:', result); +} catch (error) { + console.error('Workflow execution failed:', error); +} +``` + +## API Reference + +### SimStudioClient + +#### Constructor + +```typescript +new SimStudioClient(config: SimStudioConfig) +``` + +**Configuration:** +- `config.apiKey` (string): Your Sim Studio API key +- `config.baseUrl` (string, optional): Base URL for the Sim Studio API (defaults to `https://simstudio.ai`) + +#### Methods + +##### executeWorkflow() + +Execute a workflow with optional input data. + +```typescript +const result = await client.executeWorkflow('workflow-id', { + input: { message: 'Hello, world!' }, + timeout: 30000 // 30 seconds +}); +``` + +**Parameters:** +- `workflowId` (string): The ID of the workflow to execute +- `options` (ExecutionOptions, optional): + - `input` (any): Input data to pass to the workflow + - `timeout` (number): Timeout in milliseconds (default: 30000) + +**Returns:** `Promise` + +##### getWorkflowStatus() + +Get the status of a workflow (deployment status, etc.). + +```typescript +const status = await client.getWorkflowStatus('workflow-id'); +console.log('Is deployed:', status.isDeployed); +``` + +**Parameters:** +- `workflowId` (string): The ID of the workflow + +**Returns:** `Promise` + +##### validateWorkflow() + +Validate that a workflow is ready for execution. + +```typescript +const isReady = await client.validateWorkflow('workflow-id'); +if (isReady) { + // Workflow is deployed and ready +} +``` + +**Parameters:** +- `workflowId` (string): The ID of the workflow + +**Returns:** `Promise` + +##### executeWorkflowSync() + + + Currently, this method is identical to `executeWorkflow()` since all executions are synchronous. This method is provided for future compatibility when asynchronous execution is added. + + +Execute a workflow (currently synchronous, same as `executeWorkflow()`). + +```typescript +const result = await client.executeWorkflowSync('workflow-id', { + input: { data: 'some input' }, + timeout: 60000 +}); +``` + +**Parameters:** +- `workflowId` (string): The ID of the workflow to execute +- `options` (ExecutionOptions, optional): + - `input` (any): Input data to pass to the workflow + - `timeout` (number): Timeout for the initial request in milliseconds + +**Returns:** `Promise` + +##### setApiKey() + +Update the API key. + +```typescript +client.setApiKey('new-api-key'); +``` + +##### setBaseUrl() + +Update the base URL. + +```typescript +client.setBaseUrl('https://my-custom-domain.com'); +``` + +## Types + +### WorkflowExecutionResult + +```typescript +interface WorkflowExecutionResult { + success: boolean; + output?: any; + error?: string; + logs?: any[]; + metadata?: { + duration?: number; + executionId?: string; + [key: string]: any; + }; + traceSpans?: any[]; + totalDuration?: number; +} +``` + +### WorkflowStatus + +```typescript +interface WorkflowStatus { + isDeployed: boolean; + deployedAt?: string; + isPublished: boolean; + needsRedeployment: boolean; +} +``` + +### SimStudioError + +```typescript +class SimStudioError extends Error { + code?: string; + status?: number; +} +``` + +## Examples + +### Basic Workflow Execution + + + + Set up the SimStudioClient with your API key. + + + Check if the workflow is deployed and ready for execution. + + + Run the workflow with your input data. + + + Process the execution result and handle any errors. + + + +```typescript +import { SimStudioClient } from 'simstudio-ts-sdk'; + +const client = new SimStudioClient({ + apiKey: process.env.SIMSTUDIO_API_KEY! +}); + +async function runWorkflow() { + try { + // Check if workflow is ready + const isReady = await client.validateWorkflow('my-workflow-id'); + if (!isReady) { + throw new Error('Workflow is not deployed or ready'); + } + + // Execute the workflow + const result = await client.executeWorkflow('my-workflow-id', { + input: { + message: 'Process this data', + userId: '12345' + } + }); + + if (result.success) { + console.log('Output:', result.output); + console.log('Duration:', result.metadata?.duration); + } else { + console.error('Workflow failed:', result.error); + } + } catch (error) { + console.error('Error:', error); + } +} + +runWorkflow(); +``` + +### Error Handling + +Handle different types of errors that may occur during workflow execution: + +```typescript +import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk'; + +const client = new SimStudioClient({ + apiKey: process.env.SIMSTUDIO_API_KEY! +}); + +async function executeWithErrorHandling() { + try { + const result = await client.executeWorkflow('workflow-id'); + return result; + } catch (error) { + if (error instanceof SimStudioError) { + switch (error.code) { + case 'UNAUTHORIZED': + console.error('Invalid API key'); + break; + case 'TIMEOUT': + console.error('Workflow execution timed out'); + break; + case 'USAGE_LIMIT_EXCEEDED': + console.error('Usage limit exceeded'); + break; + case 'INVALID_JSON': + console.error('Invalid JSON in request body'); + break; + default: + console.error('Workflow error:', error.message); + } + } else { + console.error('Unexpected error:', error); + } + throw error; + } +} +``` + +### Environment Configuration + +Configure the client using environment variables: + + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + + // Development configuration + const apiKey = process.env.SIMSTUDIO_API_KEY; + if (!apiKey) { + throw new Error('SIMSTUDIO_API_KEY environment variable is required'); + } + + const client = new SimStudioClient({ + apiKey, + baseUrl: process.env.SIMSTUDIO_BASE_URL // optional + }); + ``` + + + ```typescript + import { SimStudioClient } from 'simstudio-ts-sdk'; + + // Production configuration with validation + const apiKey = process.env.SIMSTUDIO_API_KEY; + if (!apiKey) { + throw new Error('SIMSTUDIO_API_KEY environment variable is required'); + } + + const client = new SimStudioClient({ + apiKey, + baseUrl: process.env.SIMSTUDIO_BASE_URL || 'https://simstudio.ai' + }); + ``` + + + +### Node.js Express Integration + +Integrate with an Express.js server: + +```typescript +import express from 'express'; +import { SimStudioClient } from 'simstudio-ts-sdk'; + +const app = express(); +const client = new SimStudioClient({ + apiKey: process.env.SIMSTUDIO_API_KEY! +}); + +app.use(express.json()); + +app.post('/execute-workflow', async (req, res) => { + try { + const { workflowId, input } = req.body; + + const result = await client.executeWorkflow(workflowId, { + input, + timeout: 60000 + }); + + res.json({ + success: true, + data: result + }); + } catch (error) { + console.error('Workflow execution error:', error); + res.status(500).json({ + success: false, + error: error instanceof Error ? error.message : 'Unknown error' + }); + } +}); + +app.listen(3000, () => { + console.log('Server running on port 3000'); +}); +``` + +### Next.js API Route + +Use with Next.js API routes: + +```typescript +// pages/api/workflow.ts or app/api/workflow/route.ts +import { NextApiRequest, NextApiResponse } from 'next'; +import { SimStudioClient } from 'simstudio-ts-sdk'; + +const client = new SimStudioClient({ + apiKey: process.env.SIMSTUDIO_API_KEY! +}); + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method !== 'POST') { + return res.status(405).json({ error: 'Method not allowed' }); + } + + try { + const { workflowId, input } = req.body; + + const result = await client.executeWorkflow(workflowId, { + input, + timeout: 30000 + }); + + res.status(200).json(result); + } catch (error) { + console.error('Error executing workflow:', error); + res.status(500).json({ + error: 'Failed to execute workflow' + }); + } +} +``` + +### Browser Usage + +Use in the browser (with proper CORS configuration): + +```typescript +import { SimStudioClient } from 'simstudio-ts-sdk'; + +// Note: In production, use a proxy server to avoid exposing API keys +const client = new SimStudioClient({ + apiKey: 'your-public-api-key', // Use with caution in browser + baseUrl: 'https://simstudio.ai' +}); + +async function executeClientSideWorkflow() { + try { + const result = await client.executeWorkflow('workflow-id', { + input: { + userInput: 'Hello from browser' + } + }); + + console.log('Workflow result:', result); + + // Update UI with result + document.getElementById('result')!.textContent = + JSON.stringify(result.output, null, 2); + } catch (error) { + console.error('Error:', error); + } +} + +// Attach to button click +document.getElementById('executeBtn')?.addEventListener('click', executeClientSideWorkflow); +``` + + + When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions. + + +### React Hook Example + +Create a custom React hook for workflow execution: + +```typescript +import { useState, useCallback } from 'react'; +import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk'; + +const client = new SimStudioClient({ + apiKey: process.env.NEXT_PUBLIC_SIMSTUDIO_API_KEY! +}); + +interface UseWorkflowResult { + result: WorkflowExecutionResult | null; + loading: boolean; + error: Error | null; + executeWorkflow: (workflowId: string, input?: any) => Promise; +} + +export function useWorkflow(): UseWorkflowResult { + const [result, setResult] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const executeWorkflow = useCallback(async (workflowId: string, input?: any) => { + setLoading(true); + setError(null); + setResult(null); + + try { + const workflowResult = await client.executeWorkflow(workflowId, { + input, + timeout: 30000 + }); + setResult(workflowResult); + } catch (err) { + setError(err instanceof Error ? err : new Error('Unknown error')); + } finally { + setLoading(false); + } + }, []); + + return { + result, + loading, + error, + executeWorkflow + }; +} + +// Usage in component +function WorkflowComponent() { + const { result, loading, error, executeWorkflow } = useWorkflow(); + + const handleExecute = () => { + executeWorkflow('my-workflow-id', { + message: 'Hello from React!' + }); + }; + + return ( +
+ + + {error &&
Error: {error.message}
} + {result && ( +
+

Result:

+
{JSON.stringify(result, null, 2)}
+
+ )} +
+ ); +} +``` + +## Getting Your API Key + + + + Navigate to [Sim Studio](https://simstudio.ai) and log in to your account. + + + Navigate to the workflow you want to execute programmatically. + + + Click on "Deploy" to deploy your workflow if it hasn't been deployed yet. + + + During the deployment process, select or create an API key. + + + Copy the API key to use in your TypeScript/JavaScript application. + + + + + Keep your API key secure and never commit it to version control. Use environment variables or secure configuration management. + + +## Requirements + +- Node.js 16+ +- TypeScript 5.0+ (for TypeScript projects) + +## TypeScript Support + +The SDK is written in TypeScript and provides full type safety: + +```typescript +import { + SimStudioClient, + WorkflowExecutionResult, + WorkflowStatus, + SimStudioError +} from 'simstudio-ts-sdk'; + +// Type-safe client initialization +const client: SimStudioClient = new SimStudioClient({ + apiKey: process.env.SIMSTUDIO_API_KEY! +}); + +// Type-safe workflow execution +const result: WorkflowExecutionResult = await client.executeWorkflow('workflow-id', { + input: { + message: 'Hello, TypeScript!' + } +}); + +// Type-safe status checking +const status: WorkflowStatus = await client.getWorkflowStatus('workflow-id'); +``` + +## License + +Apache-2.0 \ No newline at end of file diff --git a/apps/docs/content/docs/tools/google_calendar.mdx b/apps/docs/content/docs/tools/google_calendar.mdx index e539292d929..1bac14004d0 100644 --- a/apps/docs/content/docs/tools/google_calendar.mdx +++ b/apps/docs/content/docs/tools/google_calendar.mdx @@ -90,7 +90,7 @@ In Sim Studio, the Google Calendar integration enables your agents to programmat ## Usage Instructions -Integrate Google Calendar functionality to create, read, update, and list calendar events within your workflow. Automate scheduling, check availability, and manage events using OAuth authentication. +Integrate Google Calendar functionality to create, read, update, and list calendar events within your workflow. Automate scheduling, check availability, and manage events using OAuth authentication. Email invitations are sent asynchronously and delivery depends on recipients @@ -180,6 +180,38 @@ Create events from natural language text | --------- | ---- | | `content` | string | +### `google_calendar_invite` + +Invite attendees to an existing Google Calendar event + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `accessToken` | string | Yes | Access token for Google Calendar API | +| `calendarId` | string | No | Calendar ID \(defaults to primary\) | +| `eventId` | string | Yes | Event ID to invite attendees to | +| `attendees` | array | Yes | Array of attendee email addresses to invite | +| `sendUpdates` | string | No | How to send updates to attendees: all, externalOnly, or none | +| `replaceExisting` | boolean | No | Whether to replace existing attendees or add to them \(defaults to false\) | + +#### Output + +| Parameter | Type | +| --------- | ---- | +| `metadata` | string | +| `htmlLink` | string | +| `status` | string | +| `summary` | string | +| `description` | string | +| `location` | string | +| `start` | string | +| `end` | string | +| `attendees` | string | +| `creator` | string | +| `organizer` | string | +| `content` | string | + ## Block Configuration diff --git a/apps/docs/content/docs/tools/huggingface.mdx b/apps/docs/content/docs/tools/huggingface.mdx new file mode 100644 index 00000000000..837884ed42c --- /dev/null +++ b/apps/docs/content/docs/tools/huggingface.mdx @@ -0,0 +1,127 @@ +--- +title: Hugging Face +description: Use Hugging Face Inference API +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + + + + + + + `} +/> + +{/* MANUAL-CONTENT-START:intro */} +[HuggingFace](https://huggingface.co/) is a leading AI platform that provides access to thousands of pre-trained machine learning models and powerful inference capabilities. With its extensive model hub and robust API, HuggingFace offers comprehensive tools for both research and production AI applications. +With HuggingFace, you can: + +Access pre-trained models: Utilize models for text generation, translation, image processing, and more +Generate AI completions: Create content using state-of-the-art language models through the Inference API +Natural language processing: Process and analyze text with specialized NLP models +Deploy at scale: Host and serve models for production applications +Customize models: Fine-tune existing models for specific use cases + +In Sim Studio, the HuggingFace integration enables your agents to programmatically generate completions using the HuggingFace Inference API. This allows for powerful automation scenarios such as content generation, text analysis, code completion, and creative writing. Your agents can generate completions with natural language prompts, access specialized models for different tasks, and integrate AI-generated content into workflows. This integration bridges the gap between your AI workflows and machine learning capabilities, enabling seamless AI-powered automation with one of the world's most comprehensive ML platforms. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Generate completions using Hugging Face Inference API with access to various open-source models. Leverage cutting-edge AI models for chat completions, content generation, and AI-powered conversations with customizable parameters. + + + +## Tools + +### `huggingface_chat` + +Generate completions using Hugging Face Inference API + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Hugging Face API token | +| `provider` | string | Yes | The provider to use for the API request \(e.g., novita, cerebras, etc.\) | +| `model` | string | Yes | Model to use for chat completions \(e.g., deepseek/deepseek-v3-0324\) | +| `content` | string | Yes | The user message content to send to the model | +| `systemPrompt` | string | No | System prompt to guide the model behavior | +| `maxTokens` | number | No | Maximum number of tokens to generate | +| `temperature` | number | No | Sampling temperature \(0-2\). Higher values make output more random | +| `stream` | boolean | No | Whether to stream the response | + +#### Output + +| Parameter | Type | +| --------- | ---- | +| `content` | string | +| `model` | string | +| `usage` | string | +| `completion_tokens` | string | +| `total_tokens` | string | + + + +## Block Configuration + +### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `systemPrompt` | string | No | System Prompt - Enter system prompt to guide the model behavior... | + + + +### Outputs + +| Output | Type | Description | +| ------ | ---- | ----------- | +| `response` | object | Output from response | +| ↳ `content` | string | content of the response | +| ↳ `model` | string | model of the response | +| ↳ `usage` | json | usage of the response | + + +## Notes + +- Category: `tools` +- Type: `huggingface` diff --git a/apps/docs/content/docs/tools/knowledge.mdx b/apps/docs/content/docs/tools/knowledge.mdx index 5da46bc00b6..3424c624213 100644 --- a/apps/docs/content/docs/tools/knowledge.mdx +++ b/apps/docs/content/docs/tools/knowledge.mdx @@ -1,6 +1,6 @@ --- title: Knowledge -description: Search knowledge +description: Use vector search --- import { BlockInfoCard } from "@/components/ui/block-info-card" @@ -49,7 +49,7 @@ In Sim Studio, the Knowledge Base block enables your agents to perform intellige ## Usage Instructions -Perform semantic vector search across your knowledge base to find the most relevant content. Uses advanced AI embeddings to understand meaning and context, returning the most similar documents to your search query. +Perform semantic vector search across one or more knowledge bases or upload new chunks to documents. Uses advanced AI embeddings to understand meaning and context for search operations. @@ -57,13 +57,13 @@ Perform semantic vector search across your knowledge base to find the most relev ### `knowledge_search` -Search for similar content in a knowledge base using vector similarity +Search for similar content in one or more knowledge bases using vector similarity #### Input | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `knowledgeBaseId` | string | Yes | ID of the knowledge base to search in | +| `knowledgeBaseIds` | string | Yes | ID of the knowledge base to search in, or comma-separated IDs for multiple knowledge bases | | `query` | string | Yes | Search query text | | `topK` | number | No | Number of most similar results to return \(1-100\) | @@ -73,10 +73,32 @@ Search for similar content in a knowledge base using vector similarity | --------- | ---- | | `results` | string | | `query` | string | -| `knowledgeBaseId` | string | -| `topK` | string | | `totalResults` | string | -| `message` | string | + +### `knowledge_upload_chunk` + +Upload a new chunk to a document in a knowledge base + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `knowledgeBaseId` | string | Yes | ID of the knowledge base containing the document | +| `documentId` | string | Yes | ID of the document to upload the chunk to | +| `content` | string | Yes | Content of the chunk to upload | + +#### Output + +| Parameter | Type | +| --------- | ---- | +| `data` | string | +| `chunkIndex` | string | +| `content` | string | +| `contentLength` | string | +| `tokenCount` | string | +| `enabled` | string | +| `createdAt` | string | +| `updatedAt` | string | @@ -86,7 +108,7 @@ Search for similar content in a knowledge base using vector similarity | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `knowledgeBaseId` | string | Yes | Knowledge Base - Select knowledge base | +| `operation` | string | Yes | Operation | @@ -97,10 +119,7 @@ Search for similar content in a knowledge base using vector similarity | `response` | object | Output from response | | ↳ `results` | json | results of the response | | ↳ `query` | string | query of the response | -| ↳ `knowledgeBaseId` | string | knowledgeBaseId of the response | -| ↳ `topK` | number | topK of the response | | ↳ `totalResults` | number | totalResults of the response | -| ↳ `message` | string | message of the response | ## Notes diff --git a/apps/docs/content/docs/tools/meta.json b/apps/docs/content/docs/tools/meta.json index 380fb990b8d..80332879640 100644 --- a/apps/docs/content/docs/tools/meta.json +++ b/apps/docs/content/docs/tools/meta.json @@ -19,6 +19,7 @@ "google_search", "google_sheets", "guesty", + "huggingface", "image_generator", "jina", "jira", diff --git a/apps/docs/public/static/dark/response-dark.png b/apps/docs/public/static/dark/response-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e52919887defb6a2359fd61aab60d728b9f8e02b GIT binary patch literal 25825 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 We%^PcNfRtf0=c52e*t^mI^=Hw&#Slq literal 0 HcmV?d00001 diff --git a/apps/docs/public/static/dark/workflow-dark.png b/apps/docs/public/static/dark/workflow-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6a03a49990a6be13c19a5c79dcab2ae4a0cc5a6a GIT binary patch literal 38963 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

%=zY3a5?^=^3-ZEX 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 literal 0 HcmV?d00001 diff --git a/apps/docs/public/static/light/response-light.png b/apps/docs/public/static/light/response-light.png new file mode 100644 index 0000000000000000000000000000000000000000..4503b967f1889919b54000837fb3128fd7cbd3d1 GIT binary patch literal 25568 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 literal 0 HcmV?d00001 diff --git a/apps/sim/.env.example b/apps/sim/.env.example deleted file mode 100644 index fc42b3b54bc..00000000000 --- a/apps/sim/.env.example +++ /dev/null @@ -1,16 +0,0 @@ -# Database (Required) -DATABASE_URL="postgresql://postgres:password@localhost:5432/postgres" - -# Authentication (Required) -BETTER_AUTH_SECRET=your_secret_key # Use `openssl rand -hex 32` to generate, or visit https://www.better-auth.com/docs/installation -BETTER_AUTH_URL=http://localhost:3000 - -## Security (Required) -ENCRYPTION_KEY=your_encryption_key # Use `openssl rand -hex 32` to generate - -# Email Provider (Optional) -# RESEND_API_KEY= # Uncomment and add your key from https://resend.com to send actual emails - # If left commented out, emails will be logged to console instead - -# Freestyle API Key (Required for sandboxed code execution for functions/custom-tools) -# FREESTYLE_API_KEY= # Uncomment and add your key from https://docs.freestyle.sh/Getting-Started/run diff --git a/apps/sim/app/(auth)/login/login-form.test.tsx b/apps/sim/app/(auth)/login/login-form.test.tsx index 481d546333b..00bf49df227 100644 --- a/apps/sim/app/(auth)/login/login-form.test.tsx +++ b/apps/sim/app/(auth)/login/login-form.test.tsx @@ -2,7 +2,7 @@ * @vitest-environment jsdom */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react' +import { act, fireEvent, render, screen, waitFor } from '@testing-library/react' import { useRouter, useSearchParams } from 'next/navigation' import { beforeEach, describe, expect, it, vi } from 'vitest' import { client } from '@/lib/auth-client' @@ -104,7 +104,10 @@ describe('LoginPage', () => { it('should show loading state during form submission', async () => { const mockSignIn = vi.mocked(client.signIn.email) mockSignIn.mockImplementation( - () => new Promise((resolve) => resolve({ data: { user: { id: '1' } }, error: null })) + () => + new Promise((resolve) => + setTimeout(() => resolve({ data: { user: { id: '1' } }, error: null }), 100) + ) ) render() @@ -113,12 +116,16 @@ describe('LoginPage', () => { const passwordInput = screen.getByPlaceholderText(/enter your password/i) const submitButton = screen.getByRole('button', { name: /sign in/i }) - fireEvent.change(emailInput, { target: { value: 'test@example.com' } }) - fireEvent.change(passwordInput, { target: { value: 'password123' } }) - fireEvent.click(submitButton) + await act(async () => { + fireEvent.change(emailInput, { target: { value: 'test@example.com' } }) + fireEvent.change(passwordInput, { target: { value: 'password123' } }) + fireEvent.click(submitButton) + }) - expect(screen.getByText('Signing in...')).toBeInTheDocument() - expect(submitButton).toBeDisabled() + await waitFor(() => { + expect(screen.getByText('Signing in...')).toBeInTheDocument() + expect(submitButton).toBeDisabled() + }) }) }) diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index 548d20b0508..566aa18cd01 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -5,7 +5,13 @@ import { Eye, EyeOff } from 'lucide-react' import Link from 'next/link' import { useRouter, useSearchParams } from 'next/navigation' import { Button } from '@/components/ui/button' -import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { client } from '@/lib/auth-client' @@ -494,11 +500,11 @@ export default function LoginPage({ Reset Password + + Enter your email address and we'll send you a link to reset your password. +

-
- Enter your email address and we'll send you a link to reset your password. -
+ > + {isStreaming ? ( + <> + + + + ) : ( + <> + + + )} -
+
- - -
- + +
) diff --git a/apps/sim/app/chat/[subdomain]/components/input/voice-input.tsx b/apps/sim/app/chat/[subdomain]/components/input/voice-input.tsx index 2eda962ca90..3092457ec07 100644 --- a/apps/sim/app/chat/[subdomain]/components/input/voice-input.tsx +++ b/apps/sim/app/chat/[subdomain]/components/input/voice-input.tsx @@ -43,6 +43,7 @@ interface VoiceInputProps { isListening?: boolean disabled?: boolean large?: boolean + minimal?: boolean } export function VoiceInput({ @@ -50,6 +51,7 @@ export function VoiceInput({ isListening = false, disabled = false, large = false, + minimal = false, }: VoiceInputProps) { const [isSupported, setIsSupported] = useState(false) @@ -68,6 +70,24 @@ export function VoiceInput({ return null } + if (minimal) { + return ( + + + + ) + } + if (large) { return (
@@ -93,21 +113,22 @@ export function VoiceInput({ return (
- {/* Voice Button */} + {/* Voice Button - Now matches send button styling */} - + +
) diff --git a/apps/sim/app/chat/[subdomain]/components/voice-interface/components/particles.tsx b/apps/sim/app/chat/[subdomain]/components/voice-interface/components/particles.tsx index 806f8be3efb..ab698f9be27 100644 --- a/apps/sim/app/chat/[subdomain]/components/voice-interface/components/particles.tsx +++ b/apps/sim/app/chat/[subdomain]/components/voice-interface/components/particles.tsx @@ -402,37 +402,37 @@ export function ParticlesVisualization({ avgLevel: number ) => { if (isMuted) { - // Muted: dim gray-blue - uniforms.u_red.value = 0.4 - uniforms.u_green.value = 0.4 - uniforms.u_blue.value = 0.6 + // Muted: dim purple-gray + uniforms.u_red.value = 0.25 + uniforms.u_green.value = 0.1 + uniforms.u_blue.value = 0.5 } else if (isProcessingInterruption) { - // Interruption: bright orange/yellow - uniforms.u_red.value = 1.0 - uniforms.u_green.value = 0.7 - uniforms.u_blue.value = 0.2 - } else if (isPlayingAudio) { - // AI speaking: bright blue-purple + // Interruption: bright purple uniforms.u_red.value = 0.6 - uniforms.u_green.value = 0.4 - uniforms.u_blue.value = 1.0 + uniforms.u_green.value = 0.2 + uniforms.u_blue.value = 0.9 + } else if (isPlayingAudio) { + // AI speaking: brand purple (#701FFC) + uniforms.u_red.value = 0.44 + uniforms.u_green.value = 0.12 + uniforms.u_blue.value = 0.99 } else if (isListening && avgLevel > 10) { - // User speaking: bright green-blue with intensity-based variation + // User speaking: lighter purple with intensity-based variation const intensity = Math.min(avgLevel / 50, 1) - uniforms.u_red.value = 0.2 + intensity * 0.3 - uniforms.u_green.value = 0.8 + intensity * 0.2 - uniforms.u_blue.value = 0.6 + intensity * 0.4 + uniforms.u_red.value = 0.35 + intensity * 0.15 + uniforms.u_green.value = 0.1 + intensity * 0.1 + uniforms.u_blue.value = 0.8 + intensity * 0.2 } else if (isStreaming) { - // AI thinking: pulsing purple + // AI thinking: pulsing brand purple const pulse = (Math.sin(elapsedTime * 2) + 1) / 2 - uniforms.u_red.value = 0.7 + pulse * 0.3 - uniforms.u_green.value = 0.3 - uniforms.u_blue.value = 0.9 + pulse * 0.1 + uniforms.u_red.value = 0.35 + pulse * 0.15 + uniforms.u_green.value = 0.08 + pulse * 0.08 + uniforms.u_blue.value = 0.95 + pulse * 0.05 } else { - // Default idle: soft blue-purple - uniforms.u_red.value = 0.8 - uniforms.u_green.value = 0.6 - uniforms.u_blue.value = 1.0 + // Default idle: soft brand purple + uniforms.u_red.value = 0.4 + uniforms.u_green.value = 0.15 + uniforms.u_blue.value = 0.9 } } diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx b/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx index 1dc67e4df0b..588cc5ec158 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx +++ b/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/deployment-controls.tsx @@ -1,10 +1,11 @@ 'use client' -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { Loader2, Rocket } from 'lucide-react' import { Button } from '@/components/ui/button' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { cn } from '@/lib/utils' +import type { WorkspaceUserPermissions } from '@/hooks/use-user-permissions' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { WorkflowState } from '@/stores/workflows/workflow/types' import { DeployModal } from '../deploy-modal/deploy-modal' @@ -16,6 +17,7 @@ interface DeploymentControlsProps { deployedState: WorkflowState | null isLoadingDeployedState: boolean refetchDeployedState: () => Promise + userPermissions: WorkspaceUserPermissions } export function DeploymentControls({ @@ -25,6 +27,7 @@ export function DeploymentControls({ deployedState, isLoadingDeployedState, refetchDeployedState, + userPermissions, }: DeploymentControlsProps) { const deploymentStatus = useWorkflowRegistry((state) => state.getWorkflowDeploymentStatus(activeWorkflowId) @@ -52,6 +55,31 @@ export function DeploymentControls({ } catch (error) {} } + const canDeploy = userPermissions.canAdmin + const isDisabled = isDeploying || !canDeploy + + const handleDeployClick = useCallback(() => { + if (canDeploy) { + setIsModalOpen(true) + } + }, [canDeploy, setIsModalOpen]) + + const getTooltipText = () => { + if (!canDeploy) { + return 'Admin permissions required to deploy workflows' + } + if (isDeploying) { + return 'Deploying...' + } + if (isDeployed && workflowNeedsRedeployment) { + return 'Workflow changes detected' + } + if (isDeployed) { + return 'Deployment Settings' + } + return 'Deploy as API' + } + return ( <> @@ -60,9 +88,13 @@ export function DeploymentControls({
- - {isDeploying - ? 'Deploying...' - : isDeployed && workflowNeedsRedeployment - ? 'Workflow changes detected' - : isDeployed - ? 'Deployment Settings' - : 'Deploy as API'} - + {getTooltipText()} a + b.charCodeAt(0), 0)) + : connectionId + + // Use the numeric ID to select a color pair from our palette + const colorPair = APP_COLORS[numericId % APP_COLORS.length] + + // Add a slight rotation to the gradient based on connection ID for variety + const rotation = (numericId * 25) % 360 + + return `linear-gradient(${rotation}deg, ${colorPair.from}, ${colorPair.to})` +} + +export function UserAvatar({ + connectionId, + name, + color, + tooltipContent, + size = 'md', + index = 0, +}: AvatarProps) { + // Generate a deterministic gradient for this user based on connection ID + // Or use the provided color if available + const backgroundStyle = useMemo(() => { + if (color) { + // If a color is provided, create a gradient with it + const baseColor = color + const lighterShade = color.startsWith('#') + ? `${color}dd` // Add transparency for a lighter shade effect + : color + const darkerShade = color.startsWith('#') ? color : color + + return `linear-gradient(135deg, ${lighterShade}, ${darkerShade})` + } + // Otherwise, generate a gradient based on connectionId + return generateGradient(connectionId) + }, [connectionId, color]) + + // Determine avatar size + const sizeClass = { + sm: 'h-5 w-5 text-[10px]', + md: 'h-7 w-7 text-xs', + lg: 'h-9 w-9 text-sm', + }[size] + + const initials = name ? name.charAt(0).toUpperCase() : '?' + + const avatarElement = ( +
+ {initials} +
+ ) + + // If tooltip content is provided, wrap in tooltip + if (tooltipContent) { + return ( + + {avatarElement} + + {tooltipContent} + + + ) + } + + return avatarElement +} diff --git a/apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx b/apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx new file mode 100644 index 00000000000..2489fda0622 --- /dev/null +++ b/apps/sim/app/w/[id]/components/control-bar/components/user-avatar-stack/user-avatar-stack.tsx @@ -0,0 +1,99 @@ +'use client' + +import { useMemo } from 'react' +import { usePresence } from '../../../../hooks/use-presence' +import { UserAvatar } from './components/user-avatar/user-avatar' + +interface User { + connectionId: string | number + name?: string + color?: string + info?: string +} + +interface UserAvatarStackProps { + users?: User[] + maxVisible?: number + size?: 'sm' | 'md' | 'lg' + className?: string +} + +export function UserAvatarStack({ + users: propUsers, + maxVisible = 3, + size = 'md', + className = '', +}: UserAvatarStackProps) { + // Use presence data if no users are provided via props + const { users: presenceUsers } = usePresence() + const users = propUsers || presenceUsers + + // Memoize the processed users to avoid unnecessary re-renders + const { visibleUsers, overflowCount } = useMemo(() => { + if (users.length === 0) { + return { visibleUsers: [], overflowCount: 0 } + } + + const visible = users.slice(0, maxVisible) + const overflow = Math.max(0, users.length - maxVisible) + + return { + visibleUsers: visible, + overflowCount: overflow, + } + }, [users, maxVisible]) + + // Don't render anything if there are no users + if (users.length === 0) { + return null + } + + // Determine spacing based on size + const spacingClass = { + sm: '-space-x-1', + md: '-space-x-1.5', + lg: '-space-x-2', + }[size] + + return ( +
+ {/* Render visible user avatars */} + {visibleUsers.map((user, index) => ( + +
{user.name}
+ {user.info &&
{user.info}
} +
+ ) : null + } + /> + ))} + + {/* Render overflow indicator if there are more users */} + {overflowCount > 0 && ( + +
+ {overflowCount} more user{overflowCount > 1 ? 's' : ''} +
+
{users.length} total online
+ + } + /> + )} + + ) +} diff --git a/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx b/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx index 9dbcd5aeac5..5da2dc64df6 100644 --- a/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx +++ b/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx @@ -40,13 +40,13 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip import { useSession } from '@/lib/auth-client' import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' +import { useUserPermissionsContext } from '@/app/w/components/providers/workspace-permissions-provider' import { useExecutionStore } from '@/stores/execution/store' import { useNotificationStore } from '@/stores/notifications/store' import { usePanelStore } from '@/stores/panel/store' import { useGeneralStore } from '@/stores/settings/general/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' -import { mergeSubblockState } from '@/stores/workflows/utils' import { useWorkflowStore } from '@/stores/workflows/workflow/store' import type { WorkflowState } from '@/stores/workflows/workflow/types' import { @@ -58,6 +58,7 @@ import { DeploymentControls } from './components/deployment-controls/deployment- import { HistoryDropdownItem } from './components/history-dropdown-item/history-dropdown-item' import { MarketplaceModal } from './components/marketplace-modal/marketplace-modal' import { NotificationDropdownItem } from './components/notification-dropdown-item/notification-dropdown-item' +import { UserAvatarStack } from './components/user-avatar-stack/user-avatar-stack' const logger = createLogger('ControlBar') @@ -72,11 +73,15 @@ let usageDataCache = { // Predefined run count options const RUN_COUNT_OPTIONS = [1, 5, 10, 25, 50, 100] +interface ControlBarProps { + hasValidationErrors?: boolean +} + /** * Control bar for managing workflows - handles editing, deletion, deployment, * history, notifications and execution. */ -export function ControlBar() { +export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { const router = useRouter() const { data: session } = useSession() @@ -95,6 +100,7 @@ export function ControlBar() { workflows, updateWorkflow, activeWorkflowId, + activeWorkspaceId, removeWorkflow, duplicateWorkflow, setDeploymentStatus, @@ -103,6 +109,12 @@ export function ControlBar() { const { isExecuting, handleRunWorkflow } = useWorkflowExecution() const { setActiveTab } = usePanelStore() + // Get current workflow and workspace ID for permissions + const currentWorkflow = activeWorkflowId ? workflows[activeWorkflowId] : null + + // User permissions - use stable activeWorkspaceId from registry instead of deriving from currentWorkflow + const userPermissions = useUserPermissionsContext() + // Debug mode state const { isDebugModeEnabled, toggleDebugMode } = useGeneralStore() const { isDebugging, pendingBlocks, handleStepDebug, handleCancelDebug, handleResumeDebug } = @@ -148,19 +160,19 @@ export function ControlBar() { limit: number } | null>(null) + // Shared condition for keyboard shortcut and button disabled state + const isWorkflowBlocked = isExecuting || isMultiRunning || isCancelling || hasValidationErrors + // Register keyboard shortcut for running workflow - useKeyboardShortcuts( - () => { - if (!isExecuting && !isMultiRunning && !isCancelling) { - if (isDebugModeEnabled) { - handleRunWorkflow() - } else { - handleMultipleRuns() - } + useKeyboardShortcuts(() => { + if (!isWorkflowBlocked) { + if (isDebugModeEnabled) { + handleRunWorkflow() + } else { + handleMultipleRuns() } - }, - isExecuting || isMultiRunning || isCancelling - ) + } + }, isWorkflowBlocked) // Get the marketplace data from the workflow registry if available const getMarketplaceData = () => { @@ -279,28 +291,6 @@ export function ControlBar() { activeWorkflowId ? state.workflowValues[activeWorkflowId] : null ) - /** - * Normalize blocks for semantic comparison - only compare what matters functionally - * Ignores: IDs, positions, dimensions, metadata that don't affect workflow logic - * Compares: type, name, subBlock values - */ - const normalizeBlocksForComparison = (blocks: Record) => { - if (!blocks) return [] - - return Object.values(blocks) - .map((block: any) => ({ - type: block.type, - name: block.name, - subBlocks: block.subBlocks || {}, - })) - .sort((a, b) => { - const typeA = a.type || '' - const typeB = b.type || '' - if (typeA !== typeB) return typeA.localeCompare(typeB) - return (a.name || '').localeCompare(b.name || '') - }) - } - useEffect(() => { if (!activeWorkflowId || !deployedState) { setChangeDetected(false) @@ -311,20 +301,25 @@ export function ControlBar() { return } - const currentMergedState = mergeSubblockState(currentBlocks, activeWorkflowId) - - const deployedBlocks = deployedState?.blocks - if (!deployedBlocks) { - setChangeDetected(false) - return + // Use the workflow status API to get accurate change detection + // This uses the same logic as the deployment API (reading from normalized tables) + const checkForChanges = async () => { + try { + const response = await fetch(`/api/workflows/${activeWorkflowId}/status`) + if (response.ok) { + const data = await response.json() + setChangeDetected(data.needsRedeployment || false) + } else { + logger.error('Failed to fetch workflow status:', response.status, response.statusText) + setChangeDetected(false) + } + } catch (error) { + logger.error('Error fetching workflow status:', error) + setChangeDetected(false) + } } - const normalizedCurrentBlocks = normalizeBlocksForComparison(currentMergedState) - const normalizedDeployedBlocks = normalizeBlocksForComparison(deployedBlocks) - - const hasChanges = - JSON.stringify(normalizedCurrentBlocks) !== JSON.stringify(normalizedDeployedBlocks) - setChangeDetected(hasChanges) + checkForChanges() }, [activeWorkflowId, deployedState, currentBlocks, subBlockValues, isLoadingDeployedState]) useEffect(() => { @@ -382,20 +377,18 @@ export function ControlBar() { * Workflow name handlers */ const handleNameClick = () => { - if (activeWorkflowId) { - setEditedName(workflows[activeWorkflowId].name) - setIsEditing(true) - } + if (!userPermissions.canEdit) return + setIsEditing(true) + setEditedName(activeWorkflowId ? workflows[activeWorkflowId]?.name || '' : '') } const handleNameSubmit = () => { - if (activeWorkflowId) { - const trimmedName = editedName.trim() - if (trimmedName && trimmedName !== workflows[activeWorkflowId].name) { - updateWorkflow(activeWorkflowId, { name: trimmedName }) - } - setIsEditing(false) + if (!userPermissions.canEdit) return + + if (editedName.trim() && activeWorkflowId) { + updateWorkflow(activeWorkflowId, { name: editedName.trim() }) } + setIsEditing(false) } const handleNameKeyDown = (e: React.KeyboardEvent) => { @@ -407,23 +400,36 @@ export function ControlBar() { } /** - * Workflow deletion handler + * Handle deleting the current workflow */ const handleDeleteWorkflow = () => { - if (!activeWorkflowId) return - - // Get remaining workflow IDs - const remainingIds = Object.keys(workflows).filter((id) => id !== activeWorkflowId) + if (!activeWorkflowId || !userPermissions.canEdit) return + + const workflowIds = Object.keys(workflows) + const currentIndex = workflowIds.indexOf(activeWorkflowId) + + // Find the next workflow to navigate to + let nextWorkflowId = null + if (workflowIds.length > 1) { + // Try next workflow, then previous, then any other + if (currentIndex < workflowIds.length - 1) { + nextWorkflowId = workflowIds[currentIndex + 1] + } else if (currentIndex > 0) { + nextWorkflowId = workflowIds[currentIndex - 1] + } else { + nextWorkflowId = workflowIds.find((id) => id !== activeWorkflowId) || null + } + } - // Navigate before removing the workflow to avoid any state inconsistencies - if (remainingIds.length > 0) { - router.push(`/w/${remainingIds[0]}`) + // Navigate to the next workflow or home + if (nextWorkflowId) { + router.push(`/w/${nextWorkflowId}`) } else { router.push('/') } // Remove the workflow from the registry - removeWorkflow(activeWorkflowId) + useWorkflowRegistry.getState().removeWorkflow(activeWorkflowId) } // /** @@ -443,8 +449,19 @@ export function ControlBar() { // setIsMarketplaceModalOpen(true) // } + // Helper function to open subscription settings + const openSubscriptionSettings = () => { + if (typeof window !== 'undefined') { + window.dispatchEvent( + new CustomEvent('open-settings', { + detail: { tab: 'subscription' }, + }) + ) + } + } + /** - * Handle multiple workflow runs + * Handle running workflow multiple times */ const handleMultipleRuns = async () => { if (isExecuting || isMultiRunning || runCount <= 0) return @@ -553,92 +570,124 @@ export function ControlBar() { /** * Handle duplicating the current workflow */ - const handleDuplicateWorkflow = () => { - if (!activeWorkflowId) return - - // Duplicate the workflow and get the new ID - const newWorkflowId = duplicateWorkflow(activeWorkflowId) + const handleDuplicateWorkflow = async () => { + if (!activeWorkflowId || !userPermissions.canEdit) return - if (newWorkflowId) { - // Navigate to the new workflow - router.push(`/w/${newWorkflowId}`) - } + // Duplicate the workflow - no automatic navigation + await duplicateWorkflow(activeWorkflowId) } /** * Render workflow name section (editable/non-editable) */ - const renderWorkflowName = () => ( -
- {isEditing ? ( - setEditedName(e.target.value)} - onBlur={handleNameSubmit} - onKeyDown={handleNameKeyDown} - className='w-[200px] border-none bg-transparent p-0 font-medium text-sm outline-none' - /> - ) : ( -

- {activeWorkflowId ? workflows[activeWorkflowId]?.name : 'Workflow'} -

- )} - {mounted && ( -

- Saved{' '} - {formatDistanceToNow(lastSaved || Date.now(), { - addSuffix: true, - })} -

- )} -
- ) + const renderWorkflowName = () => { + const canEdit = userPermissions.canEdit + + return ( +
+
+ {isEditing ? ( + setEditedName(e.target.value)} + onBlur={handleNameSubmit} + onKeyDown={handleNameKeyDown} + className='w-[200px] border-none bg-transparent p-0 font-medium text-sm outline-none' + /> + ) : ( + + +

+ {activeWorkflowId ? workflows[activeWorkflowId]?.name : 'Workflow'} +

+
+ {!canEdit && ( + Edit permissions required to rename workflows + )} +
+ )} + {mounted && ( +

+ Saved{' '} + {formatDistanceToNow(lastSaved || Date.now(), { + addSuffix: true, + })} +

+ )} +
+ +
+ ) + } /** * Render delete workflow button with confirmation dialog */ - const renderDeleteButton = () => ( - - - - - - - - Delete Workflow - + + + {getTooltipText()} + + ) + } - - - Delete Workflow - - Are you sure you want to delete this workflow? This action cannot be undone. - - - - Cancel - - Delete - - - - - ) + return ( + + + + + + + + {getTooltipText()} + + + + + Delete Workflow + + Are you sure you want to delete this workflow? This action cannot be undone. + + + + Cancel + + Delete + + + + + ) + } /** * Render deploy button with tooltip @@ -651,6 +700,7 @@ export function ControlBar() { deployedState={deployedState} isLoadingDeployedState={isLoadingDeployedState} refetchDeployedState={fetchDeployedState} + userPermissions={userPermissions} /> ) @@ -801,50 +851,73 @@ export function ControlBar() { /** * Render workflow duplicate button */ - const renderDuplicateButton = () => ( - - - - - Duplicate Workflow - - ) + const renderDuplicateButton = () => { + const canEdit = userPermissions.canEdit + + return ( + + + {canEdit ? ( + + ) : ( +
+ +
+ )} +
+ + {canEdit ? 'Duplicate Workflow' : 'Admin permission required to duplicate workflows'} + +
+ ) + } /** * Render auto-layout button */ const renderAutoLayoutButton = () => { const handleAutoLayoutClick = () => { - if (isExecuting || isMultiRunning || isDebugging) { + if (isExecuting || isMultiRunning || isDebugging || !userPermissions.canEdit) { return } window.dispatchEvent(new CustomEvent('trigger-auto-layout')) } + const isDisabled = isExecuting || isMultiRunning || isDebugging || !userPermissions.canEdit + return ( - + {isDisabled ? ( +
+ +
+ ) : ( + + )}
- Auto Layout + + {!userPermissions.canEdit + ? 'Admin permission required to use auto-layout' + : 'Auto Layout'} +
) } @@ -914,7 +987,12 @@ export function ControlBar() { * Render debug mode toggle button */ const renderDebugModeToggle = () => { + const canDebug = userPermissions.canRead // Debug mode now requires only read permissions + const isDisabled = isExecuting || isMultiRunning || !canDebug + const handleToggleDebugMode = () => { + if (!canDebug) return + if (isDebugModeEnabled) { if (!isExecuting) { useExecutionStore.getState().setIsDebugging(false) @@ -927,137 +1005,73 @@ export function ControlBar() { return ( - + {isDisabled ? ( +
+ +
+ ) : ( + + )}
- {isDebugModeEnabled ? 'Disable Debug Mode' : 'Enable Debug Mode'} + {!canDebug + ? 'Read permission required to use debug mode' + : isDebugModeEnabled + ? 'Disable Debug Mode' + : 'Enable Debug Mode'}
) } - // Helper function to open subscription settings - const openSubscriptionSettings = () => { - if (typeof window !== 'undefined') { - window.dispatchEvent( - new CustomEvent('open-settings', { - detail: { tab: 'subscription' }, - }) - ) - } - } - /** * Render run workflow button with multi-run dropdown and cancel button */ - const renderRunButton = () => ( -
- {showRunProgress && isMultiRunning && ( -
- -

- {completedRuns}/{runCount} runs -

-
- )} + const renderRunButton = () => { + const canRun = userPermissions.canRead // Running only requires read permissions + const isLoadingPermissions = userPermissions.isLoading + const isButtonDisabled = isWorkflowBlocked || (!canRun && !isLoadingPermissions) - {/* Show how many blocks have been executed in debug mode if debugging */} - {isDebugging && ( -
-
- Debugging Mode + return ( +
+ {showRunProgress && isMultiRunning && ( +
+ +

+ {completedRuns}/{runCount} runs +

-
- )} - - {renderDebugControls()} + )} -
- {/* Main Run/Debug Button */} - - - - - - {usageExceeded ? ( -
-

Usage Limit Exceeded

-

- You've used {usageData?.currentUsage.toFixed(2)}$ of {usageData?.limit}$. Upgrade - your plan to continue. -

-
- ) : ( - <> - {isDebugModeEnabled - ? 'Debug Workflow' - : runCount === 1 - ? 'Run Workflow' - : `Run Workflow ${runCount} times`} - - )} -
-
+ {/* Show how many blocks have been executed in debug mode if debugging */} + {isDebugging && ( +
+
+ Debugging Mode +
+
+ )} - {/* Dropdown Trigger - Only show when not in debug mode and not multi-running */} - {!isDebugModeEnabled && !isMultiRunning && ( - - +
+ {/* Main Run/Debug Button */} + + - - - {RUN_COUNT_OPTIONS.map((count) => ( - setRunCount(count)} - className={cn('justify-center', runCount === count && 'bg-muted')} - > - {count} - - ))} - - - )} - - {/* Cancel Button - Only show when multi-running */} - {isMultiRunning && ( - - - - {runCount > 1 ? 'Cancel Runs' : 'Cancel Run'} + + {hasValidationErrors ? ( +
+

Workflow Has Errors

+

+ Nested subflows are not supported. Remove subflow blocks from inside other + subflow blocks. +

+
+ ) : !canRun && !isLoadingPermissions ? ( + 'Read permission required to run workflows' + ) : usageExceeded ? ( +
+

Usage Limit Exceeded

+

+ You've used {usageData?.currentUsage.toFixed(2)}$ of {usageData?.limit}$. + Upgrade your plan to continue. +

+
+ ) : !canRun && !isLoadingPermissions ? ( + 'Read permissions required to run workflows' + ) : ( + <> + {isDebugModeEnabled + ? 'Debug Workflow' + : runCount === 1 + ? 'Run Workflow' + : `Run Workflow ${runCount} times`} + + )} +
- )} + {renderDebugControls()} + + {/* Dropdown Trigger - Only show when not in debug mode and not multi-running */} + {!isDebugModeEnabled && !isMultiRunning && ( + + + + + + {RUN_COUNT_OPTIONS.map((count) => ( + setRunCount(count)} + className={cn('justify-center', runCount === count && 'bg-muted')} + > + {count} + + ))} + + + )} + + {/* Cancel Button - Only show when multi-running */} + {isMultiRunning && ( + + + + + Cancel Runs + + )} +
-
- ) + ) + } return (
diff --git a/apps/sim/app/w/[id]/components/loop-node/components/loop-badges.tsx b/apps/sim/app/w/[id]/components/loop-node/components/loop-badges.tsx index 123a70a14c9..a73f9cc397d 100644 --- a/apps/sim/app/w/[id]/components/loop-node/components/loop-badges.tsx +++ b/apps/sim/app/w/[id]/components/loop-node/components/loop-badges.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useRef, useState } from 'react' import { ChevronDown } from 'lucide-react' import { highlight, languages } from 'prismjs' import Editor from 'react-simple-code-editor' @@ -7,6 +7,7 @@ import { Input } from '@/components/ui/input' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { cn } from '@/lib/utils' +import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' import { useWorkflowStore } from '@/stores/workflows/workflow/store' import 'prismjs/components/prism-javascript' import 'prismjs/themes/prism.css' @@ -39,11 +40,25 @@ export function LoopBadges({ nodeId, data }: LoopBadgesProps) { // Check if this is preview mode const isPreview = data?.isPreview || false - // State - const [loopType, setLoopType] = useState(data?.loopType || 'for') - const [iterations, setIterations] = useState(data?.count || 5) - const [inputValue, setInputValue] = useState((data?.count || 5).toString()) - const [editorValue, setEditorValue] = useState('') + // Get loop configuration from the workflow store (single source of truth) + const { loops } = useWorkflowStore() + const loopConfig = loops[nodeId] + + // Use loop config as primary source, fallback to data for backward compatibility + const configIterations = loopConfig?.iterations ?? data?.count ?? 5 + const configLoopType = loopConfig?.loopType ?? data?.loopType ?? 'for' + const configCollection = loopConfig?.forEachItems ?? data?.collection ?? '' + + // Derive values directly from props - no useState needed for synchronized data + const loopType = configLoopType + const iterations = configIterations + const collectionString = + typeof configCollection === 'string' ? configCollection : JSON.stringify(configCollection) || '' + + // Use actual values directly for display, temporary state only for active editing + const [tempInputValue, setTempInputValue] = useState(null) + const inputValue = tempInputValue ?? iterations.toString() + const editorValue = collectionString const [typePopoverOpen, setTypePopoverOpen] = useState(false) const [configPopoverOpen, setConfigPopoverOpen] = useState(false) const [showTagDropdown, setShowTagDropdown] = useState(false) @@ -51,62 +66,23 @@ export function LoopBadges({ nodeId, data }: LoopBadgesProps) { const textareaRef = useRef(null) const editorContainerRef = useRef(null) - // Get store methods - const updateNodeData = useCallback( - (updates: Partial) => { - if (isPreview) return // Don't update in preview mode - - useWorkflowStore.setState((state) => ({ - blocks: { - ...state.blocks, - [nodeId]: { - ...state.blocks[nodeId], - data: { - ...state.blocks[nodeId].data, - ...updates, - }, - }, - }, - })) - }, - [nodeId, isPreview] - ) - - const updateLoopType = useWorkflowStore((state) => state.updateLoopType) - const updateLoopCount = useWorkflowStore((state) => state.updateLoopCount) - const updateLoopCollection = useWorkflowStore((state) => state.updateLoopCollection) - - // Initialize editor value from data when it changes - useEffect(() => { - if (data?.loopType && data.loopType !== loopType) { - setLoopType(data.loopType) - } - if (data?.count && data.count !== iterations) { - setIterations(data.count) - setInputValue(data.count.toString()) - } - - if (loopType === 'forEach' && data?.collection) { - if (typeof data.collection === 'string') { - setEditorValue(data.collection) - } else if (Array.isArray(data.collection) || typeof data.collection === 'object') { - setEditorValue(JSON.stringify(data.collection)) - } - } else if (loopType === 'for') { - setEditorValue('') - } - }, [data?.loopType, data?.count, data?.collection, loopType, iterations]) + // Get collaborative functions + const { + collaborativeUpdateLoopType, + collaborativeUpdateLoopCount, + collaborativeUpdateLoopCollection, + } = useCollaborativeWorkflow() // Handle loop type change const handleLoopTypeChange = useCallback( (newType: 'for' | 'forEach') => { if (isPreview) return // Don't allow changes in preview mode - setLoopType(newType) - updateLoopType(nodeId, newType) + // Update the collaborative state - this will cause the component to re-render with new derived values + collaborativeUpdateLoopType(nodeId, newType) setTypePopoverOpen(false) }, - [nodeId, updateLoopType, isPreview] + [nodeId, collaborativeUpdateLoopType, isPreview] ) // Handle iterations input change @@ -118,9 +94,9 @@ export function LoopBadges({ nodeId, data }: LoopBadgesProps) { const numValue = Number.parseInt(sanitizedValue) if (!Number.isNaN(numValue)) { - setInputValue(Math.min(100, numValue).toString()) + setTempInputValue(Math.min(100, numValue).toString()) } else { - setInputValue(sanitizedValue) + setTempInputValue(sanitizedValue) } }, [isPreview] @@ -134,22 +110,21 @@ export function LoopBadges({ nodeId, data }: LoopBadgesProps) { if (!Number.isNaN(value)) { const newValue = Math.min(100, Math.max(1, value)) - setIterations(newValue) - updateLoopCount(nodeId, newValue) - setInputValue(newValue.toString()) - } else { - setInputValue(iterations.toString()) + // Update the collaborative state - this will cause iterations to be derived from props + collaborativeUpdateLoopCount(nodeId, newValue) } + // Clear temporary input state to show the actual value + setTempInputValue(null) setConfigPopoverOpen(false) - }, [inputValue, iterations, nodeId, updateLoopCount, isPreview]) + }, [inputValue, nodeId, collaborativeUpdateLoopCount, isPreview]) // Handle editor change with tag dropdown support const handleEditorChange = useCallback( (value: string) => { if (isPreview) return // Don't allow changes in preview mode - setEditorValue(value) - updateLoopCollection(nodeId, value) + // Update collaborative state directly - no local state needed + collaborativeUpdateLoopCollection(nodeId, value) // Get the textarea element from the editor const textarea = editorContainerRef.current?.querySelector('textarea') @@ -163,7 +138,7 @@ export function LoopBadges({ nodeId, data }: LoopBadgesProps) { setShowTagDropdown(triggerCheck.show) } }, - [nodeId, updateLoopCollection, isPreview] + [nodeId, collaborativeUpdateLoopCollection, isPreview] ) // Handle tag selection @@ -171,8 +146,8 @@ export function LoopBadges({ nodeId, data }: LoopBadgesProps) { (newValue: string) => { if (isPreview) return // Don't allow changes in preview mode - setEditorValue(newValue) - updateLoopCollection(nodeId, newValue) + // Update collaborative state directly - no local state needed + collaborativeUpdateLoopCollection(nodeId, newValue) setShowTagDropdown(false) // Focus back on the editor after a short delay @@ -183,7 +158,7 @@ export function LoopBadges({ nodeId, data }: LoopBadgesProps) { } }, 0) }, - [nodeId, updateLoopCollection, isPreview] + [nodeId, collaborativeUpdateLoopCollection, isPreview] ) return ( diff --git a/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx b/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx index ae0bb86741b..0131e04b792 100644 --- a/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx +++ b/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx @@ -6,7 +6,7 @@ import { StartIcon } from '@/components/icons' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' import { cn } from '@/lib/utils' -import { useWorkflowStore } from '@/stores/workflows/workflow/store' +import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' import { LoopBadges } from './components/loop-badges' // Add these styles to your existing global CSS file or create a separate CSS module @@ -69,7 +69,7 @@ const LoopNodeStyles: React.FC = () => { export const LoopNodeComponent = memo(({ data, selected, id }: NodeProps) => { const { getNodes } = useReactFlow() - const removeBlock = useWorkflowStore((state) => state.removeBlock) + const { collaborativeRemoveBlock } = useCollaborativeWorkflow() const blockRef = useRef(null) // Check if this is preview mode @@ -94,7 +94,7 @@ export const LoopNodeComponent = memo(({ data, selected, id }: NodeProps) => { const getNestedStyles = () => { // Base styles const styles: Record = { - backgroundColor: 'transparent', + backgroundColor: 'rgba(0, 0, 0, 0.02)', } // Apply nested styles @@ -123,7 +123,8 @@ export const LoopNodeComponent = memo(({ data, selected, id }: NodeProps) => { 'z-[20]', data?.state === 'valid', nestingLevel > 0 && - `border border-[0.5px] ${nestingLevel % 2 === 0 ? 'border-slate-300/60' : 'border-slate-400/60'}` + `border border-[0.5px] ${nestingLevel % 2 === 0 ? 'border-slate-300/60' : 'border-slate-400/60'}`, + data?.hasNestedError && 'border-2 border-red-500 bg-red-50/50' )} style={{ width: data.width || 500, @@ -170,7 +171,7 @@ export const LoopNodeComponent = memo(({ data, selected, id }: NodeProps) => { size='sm' onClick={(e) => { e.stopPropagation() - removeBlock(id) + collaborativeRemoveBlock(id) }} className='absolute top-2 right-2 z-20 text-gray-500 opacity-0 transition-opacity duration-200 hover:text-red-600 group-hover:opacity-100' style={{ pointerEvents: 'auto' }} diff --git a/apps/sim/app/w/[id]/components/notifications/notifications.tsx b/apps/sim/app/w/[id]/components/notifications/notifications.tsx index d572da25cb9..fd8e18cb0fd 100644 --- a/apps/sim/app/w/[id]/components/notifications/notifications.tsx +++ b/apps/sim/app/w/[id]/components/notifications/notifications.tsx @@ -134,7 +134,10 @@ function DeleteApiConfirmation({ Cancel - + Delete diff --git a/apps/sim/app/w/[id]/components/panel/components/chat/chat.tsx b/apps/sim/app/w/[id]/components/panel/components/chat/chat.tsx index 5c719500c60..9bb91ad2a4c 100644 --- a/apps/sim/app/w/[id]/components/panel/components/chat/chat.tsx +++ b/apps/sim/app/w/[id]/components/panel/components/chat/chat.tsx @@ -5,9 +5,7 @@ import { ArrowUp } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { ScrollArea } from '@/components/ui/scroll-area' -import { buildTraceSpans } from '@/lib/logs/trace-spans' -import type { BlockLog } from '@/executor/types' -import { calculateCost } from '@/providers/utils' +import type { BlockLog, ExecutionResult } from '@/executor/types' import { useExecutionStore } from '@/stores/execution/store' import { useChatStore } from '@/stores/panel/chat/store' import { useConsoleStore } from '@/stores/panel/console/store' @@ -113,189 +111,182 @@ export function Chat({ panelWidth, chatMessage, setChatMessage }: ChatProps) { // Check if we got a streaming response if (result && 'stream' in result && result.stream instanceof ReadableStream) { - // Generate a unique ID for the message - const messageId = crypto.randomUUID() + const messageIdMap = new Map() - // Create a content buffer to collect initial content - let initialContent = '' - let fullContent = '' // Store the complete content for updating logs later - let hasAddedMessage = false - const executionResult = (result as any).execution // Store the execution result with type assertion + const reader = result.stream.getReader() + const decoder = new TextDecoder() - try { - // Process the stream - const reader = result.stream.getReader() - const decoder = new TextDecoder() + const processStream = async () => { + while (true) { + const { done, value } = await reader.read() + if (done) { + // Finalize all streaming messages + messageIdMap.forEach((id) => finalizeMessageStream(id)) + break + } - console.log('Starting to read from stream') + const chunk = decoder.decode(value) + const lines = chunk.split('\n\n') - while (true) { - try { - const { done, value } = await reader.read() - if (done) { - console.log('Stream complete') - break - } + for (const line of lines) { + if (line.startsWith('data: ')) { + try { + const json = JSON.parse(line.substring(6)) + const { blockId, chunk: contentChunk, event, data } = json + + if (event === 'final' && data) { + const result = data as ExecutionResult + const nonStreamingLogs = + result.logs?.filter((log) => !messageIdMap.has(log.blockId)) || [] + + if (nonStreamingLogs.length > 0) { + const outputsToRender = selectedOutputs.filter((outputId) => + nonStreamingLogs.some((log) => log.blockId === outputId.split('.')[0]) + ) - // Decode and append chunk - const chunk = decoder.decode(value, { stream: true }) // Use stream option - - if (chunk) { - initialContent += chunk - fullContent += chunk - - // Only add the message to UI once we have some actual content to show - if (!hasAddedMessage && initialContent.trim().length > 0) { - // Add message with initial content - cast to any to bypass type checking for id - addMessage({ - content: initialContent, - workflowId: activeWorkflowId, - type: 'workflow', - isStreaming: true, - id: messageId, - } as any) - hasAddedMessage = true - } else if (hasAddedMessage) { - // Append to existing message - appendMessageContent(messageId, chunk) + for (const outputId of outputsToRender) { + const blockIdForOutput = outputId.split('.')[0] + const path = outputId.substring(blockIdForOutput.length + 1) + const log = nonStreamingLogs.find((l) => l.blockId === blockIdForOutput) + + if (log) { + let outputValue: any = log.output + if (path) { + const pathParts = path.split('.') + for (const part of pathParts) { + if ( + outputValue && + typeof outputValue === 'object' && + part in outputValue + ) { + outputValue = outputValue[part] + } else { + outputValue = undefined + break + } + } + } + if (outputValue !== undefined) { + addMessage({ + content: + typeof outputValue === 'string' + ? outputValue + : `\`\`\`json\n${JSON.stringify(outputValue, null, 2)}\n\`\`\``, + workflowId: activeWorkflowId, + type: 'workflow', + }) + } + } + } + } + } else if (blockId && contentChunk) { + if (!messageIdMap.has(blockId)) { + const newMessageId = crypto.randomUUID() + messageIdMap.set(blockId, newMessageId) + addMessage({ + id: newMessageId, + content: contentChunk, + workflowId: activeWorkflowId, + type: 'workflow', + isStreaming: true, + }) + } else { + const existingMessageId = messageIdMap.get(blockId) + if (existingMessageId) { + appendMessageContent(existingMessageId, contentChunk) + } + } + } else if (blockId && event === 'end') { + const existingMessageId = messageIdMap.get(blockId) + if (existingMessageId) { + finalizeMessageStream(existingMessageId) + } + } + } catch (e) { + console.error('Error parsing stream data:', e) } } - } catch (streamError) { - console.error('Error reading from stream:', streamError) - // Break the loop on error - break } } + } - // If we never added a message (no content received), add it now - if (!hasAddedMessage && initialContent.trim().length > 0) { - addMessage({ - content: initialContent, - workflowId: activeWorkflowId, - type: 'workflow', - id: messageId, - } as any) - } - - // Update logs with the full streaming content if available - if (executionResult && fullContent.trim().length > 0) { - try { - // Format the final content properly to match what's shown for manual executions - // Include all the markdown and formatting from the streamed response - const formattedContent = fullContent - - // Calculate cost based on token usage if available - let costData: any - - if (executionResult.output?.response?.tokens) { - const tokens = executionResult.output.response.tokens - const model = executionResult.output?.response?.model || 'gpt-4o' - const cost = calculateCost( - model, - tokens.prompt || 0, - tokens.completion || 0, - false // Don't use cached input for chat responses - ) - costData = { ...cost, model } as any + processStream().catch((e) => console.error('Error processing stream:', e)) + } else if (result && 'success' in result && result.success && 'logs' in result) { + const finalOutputs: any[] = [] + + if (selectedOutputs && selectedOutputs.length > 0) { + for (const outputId of selectedOutputs) { + // Find the log that corresponds to the start of the outputId + const log = result.logs?.find( + (l: BlockLog) => l.blockId === outputId || outputId.startsWith(`${l.blockId}_`) + ) + + if (log) { + let output = log.output + // Check if there is a path to traverse + if (outputId.length > log.blockId.length) { + const path = outputId.substring(log.blockId.length + 1) + if (path) { + const pathParts = path.split('.') + let current = output + for (const part of pathParts) { + if (current && typeof current === 'object' && part in current) { + current = current[part] + } else { + current = undefined + break + } + } + output = current + } } + if (output !== undefined) { + finalOutputs.push(output) + } + } + } + } - // Build trace spans and total duration before persisting - const { traceSpans, totalDuration } = buildTraceSpans(executionResult as any) - - // Create a completed execution ID - const completedExecutionId = - executionResult.metadata?.executionId || crypto.randomUUID() - - // Import the workflow execution hook for direct access to the workflow service - const workflowExecutionApi = await fetch(`/api/workflows/${activeWorkflowId}/log`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - executionId: completedExecutionId, - result: { - ...executionResult, - output: { - ...executionResult.output, - response: { - ...executionResult.output?.response, - content: formattedContent, - model: executionResult.output?.response?.model, - tokens: executionResult.output?.response?.tokens, - toolCalls: executionResult.output?.response?.toolCalls, - providerTiming: executionResult.output?.response?.providerTiming, - cost: costData || executionResult.output?.response?.cost, - }, - }, - cost: costData, - // Update the message to include the formatted content - logs: (executionResult.logs || []).map((log: BlockLog) => { - // Check if this is the streaming block by comparing with the selected output IDs - // Selected output IDs typically include the block ID we are streaming from - const isStreamingBlock = selectedOutputs.some( - (outputId) => - outputId === log.blockId || outputId.startsWith(`${log.blockId}_`) - ) + // If no specific outputs could be resolved, fall back to the final workflow output + if (finalOutputs.length === 0 && result.output) { + finalOutputs.push(result.output) + } - if (isStreamingBlock && log.blockType === 'agent' && log.output?.response) { - return { - ...log, - output: { - ...log.output, - response: { - ...log.output.response, - content: formattedContent, - providerTiming: log.output.response.providerTiming, - cost: costData || log.output.response.cost, - }, - }, - } - } - return log - }), - metadata: { - ...executionResult.metadata, - source: 'chat', - completedAt: new Date().toISOString(), - isStreamingComplete: true, - cost: costData || executionResult.metadata?.cost, - providerTiming: executionResult.output?.response?.providerTiming, - }, - traceSpans: traceSpans, - totalDuration: totalDuration, - }, - }), - }) - - if (!workflowExecutionApi.ok) { - console.error('Failed to log complete streaming execution') + // Add a new message for each resolved output + finalOutputs.forEach((output) => { + let content = '' + if (typeof output === 'string') { + content = output + } else if (output && typeof output === 'object') { + // Handle cases where output is { response: ... } + const outputObj = output as Record + const response = outputObj.response + if (response) { + if (typeof response.content === 'string') { + content = response.content + } else { + // Pretty print for better readability + content = `\`\`\`json\n${JSON.stringify(response, null, 2)}\n\`\`\`` } - } catch (logError) { - console.error('Error logging complete streaming execution:', logError) + } else { + content = `\`\`\`json\n${JSON.stringify(output, null, 2)}\n\`\`\`` } } - } catch (error) { - console.error('Error processing stream:', error) - // If there's an error and we haven't added a message yet, add an error message - if (!hasAddedMessage) { + if (content) { addMessage({ - content: 'Error: Failed to process the streaming response.', + content, workflowId: activeWorkflowId, type: 'workflow', - id: messageId, - } as any) - } else { - // Otherwise append the error to the existing message - appendMessageContent(messageId, '\n\nError: Failed to process the streaming response.') - } - } finally { - console.log('Finalizing stream') - if (hasAddedMessage) { - finalizeMessageStream(messageId) + }) } - } + }) + } else if (result && 'success' in result && !result.success) { + addMessage({ + content: `Error: ${'error' in result ? result.error : 'Workflow execution failed.'}`, + workflowId: activeWorkflowId, + type: 'workflow', + }) } } diff --git a/apps/sim/app/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx b/apps/sim/app/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx index de1364368e4..99adc458ee4 100644 --- a/apps/sim/app/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx +++ b/apps/sim/app/w/[id]/components/panel/components/console/components/console-entry/console-entry.tsx @@ -4,7 +4,6 @@ import { AlertCircle, AlertTriangle, Calendar, - CheckCircle2, ChevronDown, ChevronUp, Clock, @@ -66,14 +65,6 @@ export function ConsoleEntry({ entry, consoleWidth }: ConsoleEntryProps) { const BlockIcon = blockConfig?.icon - const _statusIcon = entry.error ? ( - - ) : entry.warning ? ( - - ) : ( - - ) - // Helper function to check if data has nested objects or arrays const hasNestedStructure = (data: any): boolean => { if (data === null || typeof data !== 'object') return false @@ -93,9 +84,9 @@ export function ConsoleEntry({ entry, consoleWidth }: ConsoleEntryProps) { return (
!entry.error && !entry.warning && setIsExpanded(!isExpanded)} + onClick={() => !entry.error && !entry.warning && entry.success && setIsExpanded(!isExpanded)} >
- {format(new Date(entry.startedAt), 'HH:mm:ss')} + {entry.startedAt ? format(new Date(entry.startedAt), 'HH:mm:ss') : 'N/A'}
- Duration: {entry.durationMs}ms + Duration: {entry.durationMs ?? 0}ms
diff --git a/apps/sim/app/w/[id]/components/parallel-node/components/parallel-badges.tsx b/apps/sim/app/w/[id]/components/parallel-node/components/parallel-badges.tsx index 9b95a077196..de57ce42071 100644 --- a/apps/sim/app/w/[id]/components/parallel-node/components/parallel-badges.tsx +++ b/apps/sim/app/w/[id]/components/parallel-node/components/parallel-badges.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useRef, useState } from 'react' import { ChevronDown } from 'lucide-react' import { highlight, languages } from 'prismjs' import Editor from 'react-simple-code-editor' @@ -7,6 +7,7 @@ import { Input } from '@/components/ui/input' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' import { cn } from '@/lib/utils' +import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' import { useWorkflowStore } from '@/stores/workflows/workflow/store' import 'prismjs/components/prism-javascript' import 'prismjs/themes/prism.css' @@ -39,13 +40,29 @@ export function ParallelBadges({ nodeId, data }: ParallelBadgesProps) { // Check if this is preview mode const isPreview = data?.isPreview || false - // State - const [parallelType, setParallelType] = useState<'count' | 'collection'>( - data?.parallelType || 'collection' - ) - const [iterations, setIterations] = useState(data?.count || 5) - const [inputValue, setInputValue] = useState((data?.count || 5).toString()) - const [editorValue, setEditorValue] = useState('') + // Get parallel configuration from the workflow store (single source of truth) + const { parallels } = useWorkflowStore() + const parallelConfig = parallels[nodeId] + + // Use parallel config as primary source, fallback to data for backward compatibility + const configCount = parallelConfig?.count ?? data?.count ?? 5 + const configDistribution = parallelConfig?.distribution ?? data?.collection ?? '' + // For parallel type, use the block's parallelType data property as the source of truth + // Don't infer it from whether distribution exists, as that causes unwanted switching + const configParallelType = data?.parallelType || 'collection' + + // Derive values directly from props - no useState needed for synchronized data + const parallelType = configParallelType + const iterations = configCount + const distributionString = + typeof configDistribution === 'string' + ? configDistribution + : JSON.stringify(configDistribution) || '' + + // Use actual values directly for display, temporary state only for active editing + const [tempInputValue, setTempInputValue] = useState(null) + const inputValue = tempInputValue ?? iterations.toString() + const editorValue = distributionString const [typePopoverOpen, setTypePopoverOpen] = useState(false) const [configPopoverOpen, setConfigPopoverOpen] = useState(false) const [showTagDropdown, setShowTagDropdown] = useState(false) @@ -53,78 +70,24 @@ export function ParallelBadges({ nodeId, data }: ParallelBadgesProps) { const editorContainerRef = useRef(null) const textareaRef = useRef(null) - // Get store methods - const updateParallelCount = useWorkflowStore((state) => state.updateParallelCount) - const updateParallelCollection = useWorkflowStore((state) => state.updateParallelCollection) - - // Update node data to include parallel type - const updateNodeData = useCallback( - (updates: Partial) => { - if (isPreview) return // Don't update in preview mode - - useWorkflowStore.setState((state) => ({ - blocks: { - ...state.blocks, - [nodeId]: { - ...state.blocks[nodeId], - data: { - ...state.blocks[nodeId].data, - ...updates, - }, - }, - }, - })) - }, - [nodeId, isPreview] - ) - - // Initialize state from data when it changes - useEffect(() => { - if (data?.parallelType && data.parallelType !== parallelType) { - setParallelType(data.parallelType) - } - if (data?.count && data.count !== iterations) { - setIterations(data.count) - setInputValue(data.count.toString()) - } - - if (data?.collection) { - if (typeof data.collection === 'string') { - setEditorValue(data.collection) - } else if (Array.isArray(data.collection) || typeof data.collection === 'object') { - setEditorValue(JSON.stringify(data.collection)) - } - } - }, [data?.parallelType, data?.count, data?.collection, parallelType, iterations]) + // Get collaborative functions + const { + collaborativeUpdateParallelCount, + collaborativeUpdateParallelCollection, + collaborativeUpdateParallelType, + } = useCollaborativeWorkflow() // Handle parallel type change const handleParallelTypeChange = useCallback( (newType: 'count' | 'collection') => { if (isPreview) return // Don't allow changes in preview mode - setParallelType(newType) - updateNodeData({ parallelType: newType }) - - // Reset values based on type - if (newType === 'count') { - updateParallelCollection(nodeId, '') - updateParallelCount(nodeId, iterations) - } else { - updateParallelCount(nodeId, 1) - updateParallelCollection(nodeId, editorValue || '[]') - } + // Use single collaborative function that handles all the state changes atomically + collaborativeUpdateParallelType(nodeId, newType) setTypePopoverOpen(false) }, - [ - nodeId, - iterations, - editorValue, - updateNodeData, - updateParallelCount, - updateParallelCollection, - isPreview, - ] + [nodeId, collaborativeUpdateParallelType, isPreview] ) // Handle iterations input change @@ -136,9 +99,9 @@ export function ParallelBadges({ nodeId, data }: ParallelBadgesProps) { const numValue = Number.parseInt(sanitizedValue) if (!Number.isNaN(numValue)) { - setInputValue(Math.min(20, numValue).toString()) + setTempInputValue(Math.min(20, numValue).toString()) } else { - setInputValue(sanitizedValue) + setTempInputValue(sanitizedValue) } }, [isPreview] @@ -152,22 +115,21 @@ export function ParallelBadges({ nodeId, data }: ParallelBadgesProps) { if (!Number.isNaN(value)) { const newValue = Math.min(20, Math.max(1, value)) - setIterations(newValue) - updateParallelCount(nodeId, newValue) - setInputValue(newValue.toString()) - } else { - setInputValue(iterations.toString()) + // Update the collaborative state - this will cause iterations to be derived from props + collaborativeUpdateParallelCount(nodeId, newValue) } + // Clear temporary input state to show the actual value + setTempInputValue(null) setConfigPopoverOpen(false) - }, [inputValue, iterations, nodeId, updateParallelCount, isPreview]) + }, [inputValue, nodeId, collaborativeUpdateParallelCount, isPreview]) // Handle editor change and check for tag trigger const handleEditorChange = useCallback( (value: string) => { if (isPreview) return // Don't allow changes in preview mode - setEditorValue(value) - updateParallelCollection(nodeId, value) + // Update collaborative state directly - no local state needed + collaborativeUpdateParallelCollection(nodeId, value) // Get the textarea element and cursor position const textarea = editorContainerRef.current?.querySelector('textarea') @@ -181,7 +143,7 @@ export function ParallelBadges({ nodeId, data }: ParallelBadgesProps) { setShowTagDropdown(tagTrigger.show) } }, - [nodeId, updateParallelCollection, isPreview] + [nodeId, collaborativeUpdateParallelCollection, isPreview] ) // Handle tag selection @@ -189,8 +151,8 @@ export function ParallelBadges({ nodeId, data }: ParallelBadgesProps) { (newValue: string) => { if (isPreview) return // Don't allow changes in preview mode - setEditorValue(newValue) - updateParallelCollection(nodeId, newValue) + // Update collaborative state directly - no local state needed + collaborativeUpdateParallelCollection(nodeId, newValue) setShowTagDropdown(false) // Focus back on the editor after selection @@ -201,7 +163,7 @@ export function ParallelBadges({ nodeId, data }: ParallelBadgesProps) { } }, 0) }, - [nodeId, updateParallelCollection, isPreview] + [nodeId, collaborativeUpdateParallelCollection, isPreview] ) // Handle key events diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts b/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts index a1a79eb29bd..fe00c935bec 100644 --- a/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts +++ b/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts @@ -6,7 +6,7 @@ export const ParallelTool = { name: 'Parallel', description: 'Parallel Execution', icon: SplitIcon, - bgColor: '#8BC34A', + bgColor: '#FEE12B', data: { label: 'Parallel', parallelType: 'collection' as 'collection' | 'count', diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.test.tsx b/apps/sim/app/w/[id]/components/parallel-node/parallel-node.test.tsx index 260a691795d..a6bf26b5f57 100644 --- a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.test.tsx +++ b/apps/sim/app/w/[id]/components/parallel-node/parallel-node.test.tsx @@ -2,7 +2,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { useWorkflowStore } from '@/stores/workflows/workflow/store' import { ParallelNodeComponent } from './parallel-node' -// Mock dependencies that don't need DOM vi.mock('@/stores/workflows/workflow/store', () => ({ useWorkflowStore: vi.fn(), })) @@ -16,7 +15,6 @@ vi.mock('@/lib/logs/console-logger', () => ({ })), })) -// Mock ReactFlow components and hooks vi.mock('reactflow', () => ({ Handle: ({ id, type, position }: any) => ({ id, type, position }), Position: { @@ -32,7 +30,6 @@ vi.mock('reactflow', () => ({ memo: (component: any) => component, })) -// Mock React hooks vi.mock('react', async () => { const actual = await vi.importActual('react') return { @@ -43,7 +40,6 @@ vi.mock('react', async () => { } }) -// Mock UI components vi.mock('@/components/ui/button', () => ({ Button: ({ children, onClick, ...props }: any) => ({ children, onClick, ...props }), })) @@ -52,15 +48,21 @@ vi.mock('@/components/ui/card', () => ({ Card: ({ children, ...props }: any) => ({ children, ...props }), })) -vi.mock('@/components/icons', () => ({ - StartIcon: ({ className }: any) => ({ className }), +vi.mock('@/blocks/registry', () => ({ + getBlock: vi.fn(() => ({ + name: 'Mock Block', + description: 'Mock block description', + icon: () => null, + subBlocks: [], + outputs: {}, + })), + getAllBlocks: vi.fn(() => ({})), })) vi.mock('@/lib/utils', () => ({ cn: (...classes: any[]) => classes.filter(Boolean).join(' '), })) -// Mock the ParallelBadges component vi.mock('./components/parallel-badges', () => ({ ParallelBadges: ({ parallelId }: any) => ({ parallelId }), })) @@ -87,8 +89,6 @@ describe('ParallelNodeComponent', () => { beforeEach(() => { vi.clearAllMocks() - // Mock useWorkflowStore - ;(useWorkflowStore as any).mockImplementation((selector: any) => { const state = { removeBlock: mockRemoveBlock, @@ -96,54 +96,33 @@ describe('ParallelNodeComponent', () => { return selector(state) }) - // Mock getNodes mockGetNodes.mockReturnValue([]) }) describe('Component Definition and Structure', () => { - it('should be defined as a function component', () => { + it.concurrent('should be defined as a function component', () => { expect(ParallelNodeComponent).toBeDefined() expect(typeof ParallelNodeComponent).toBe('function') }) - it('should have correct display name', () => { + it.concurrent('should have correct display name', () => { expect(ParallelNodeComponent.displayName).toBe('ParallelNodeComponent') }) - it('should be a memoized component', () => { - // Since we mocked memo to return the component as-is, we can verify it exists + it.concurrent('should be a memoized component', () => { expect(ParallelNodeComponent).toBeDefined() }) }) describe('Props Validation and Type Safety', () => { - it('should accept NodeProps interface', () => { - // Test that the component accepts the correct prop types - const validProps = { - id: 'test-id', - type: 'parallelNode' as const, - data: { - width: 400, - height: 300, - state: 'valid' as const, - }, - selected: false, - zIndex: 1, - isConnectable: true, - xPos: 0, - yPos: 0, - dragging: false, - } - - // This tests that TypeScript compilation succeeds with these props + it.concurrent('should accept NodeProps interface', () => { expect(() => { - // We're not calling the component, just verifying the types const _component: typeof ParallelNodeComponent = ParallelNodeComponent expect(_component).toBeDefined() }).not.toThrow() }) - it('should handle different data configurations', () => { + it.concurrent('should handle different data configurations', () => { const configurations = [ { width: 500, height: 300, state: 'valid' }, { width: 800, height: 600, state: 'invalid' }, @@ -162,11 +141,9 @@ describe('ParallelNodeComponent', () => { }) describe('Store Integration', () => { - it('should integrate with workflow store', () => { - // Test that the component uses the store correctly + it.concurrent('should integrate with workflow store', () => { expect(useWorkflowStore).toBeDefined() - // Verify the store selector function works const mockState = { removeBlock: mockRemoveBlock } const selector = vi.fn((state) => state.removeBlock) @@ -177,19 +154,17 @@ describe('ParallelNodeComponent', () => { expect(selector(mockState)).toBe(mockRemoveBlock) }) - it('should handle removeBlock function', () => { + it.concurrent('should handle removeBlock function', () => { expect(mockRemoveBlock).toBeDefined() expect(typeof mockRemoveBlock).toBe('function') - // Test calling removeBlock mockRemoveBlock('test-id') expect(mockRemoveBlock).toHaveBeenCalledWith('test-id') }) }) describe('Component Logic Tests', () => { - it('should handle nesting level calculation logic', () => { - // Test the nesting level calculation logic (same as loop node) + it.concurrent('should handle nesting level calculation logic', () => { const testCases = [ { nodes: [], parentId: undefined, expectedLevel: 0 }, { nodes: [{ id: 'parent', data: {} }], parentId: 'parent', expectedLevel: 1 }, @@ -206,7 +181,6 @@ describe('ParallelNodeComponent', () => { testCases.forEach(({ nodes, parentId, expectedLevel }) => { mockGetNodes.mockReturnValue(nodes) - // Simulate the nesting level calculation logic let level = 0 let currentParentId = parentId @@ -221,8 +195,7 @@ describe('ParallelNodeComponent', () => { }) }) - it('should handle nested styles generation for parallel nodes', () => { - // Test the nested styles logic with parallel-specific colors + it.concurrent('should handle nested styles generation for parallel nodes', () => { const testCases = [ { nestingLevel: 0, state: 'valid', expectedBg: 'rgba(254,225,43,0.05)' }, { nestingLevel: 0, state: 'invalid', expectedBg: 'transparent' }, @@ -231,7 +204,6 @@ describe('ParallelNodeComponent', () => { ] testCases.forEach(({ nestingLevel, state, expectedBg }) => { - // Simulate the getNestedStyles logic for parallel nodes const styles: Record = { backgroundColor: state === 'valid' ? 'rgba(254,225,43,0.05)' : 'transparent', } @@ -248,14 +220,13 @@ describe('ParallelNodeComponent', () => { }) describe('Parallel-Specific Features', () => { - it('should handle parallel execution states', () => { + it.concurrent('should handle parallel execution states', () => { const parallelStates = ['valid', 'invalid', 'executing', 'completed', 'pending'] parallelStates.forEach((state) => { const data = { width: 500, height: 300, state } expect(data.state).toBe(state) - // Test parallel-specific state handling const isExecuting = state === 'executing' const isCompleted = state === 'completed' @@ -264,8 +235,7 @@ describe('ParallelNodeComponent', () => { }) }) - it('should handle parallel node color scheme', () => { - // Test that parallel nodes use yellow color scheme + it.concurrent('should handle parallel node color scheme', () => { const parallelColors = { background: 'rgba(254,225,43,0.05)', ring: '#FEE12B', @@ -277,8 +247,7 @@ describe('ParallelNodeComponent', () => { expect(parallelColors.startIcon).toBe('#FEE12B') }) - it('should differentiate from loop node styling', () => { - // Ensure parallel nodes have different styling than loop nodes + it.concurrent('should differentiate from loop node styling', () => { const loopColors = { background: 'rgba(34,197,94,0.05)', ring: '#2FB3FF', @@ -298,7 +267,7 @@ describe('ParallelNodeComponent', () => { }) describe('Component Configuration', () => { - it('should handle different dimensions', () => { + it.concurrent('should handle different dimensions', () => { const dimensionTests = [ { width: 500, height: 300 }, { width: 800, height: 600 }, @@ -313,7 +282,7 @@ describe('ParallelNodeComponent', () => { }) }) - it('should handle different states', () => { + it.concurrent('should handle different states', () => { const stateTests = ['valid', 'invalid', 'pending', 'executing', 'completed'] stateTests.forEach((state) => { @@ -324,12 +293,11 @@ describe('ParallelNodeComponent', () => { }) describe('Event Handling Logic', () => { - it('should handle delete button click logic', () => { + it.concurrent('should handle delete button click logic', () => { const mockEvent = { stopPropagation: vi.fn(), } - // Simulate the delete button click handler const handleDelete = (e: any, nodeId: string) => { e.stopPropagation() mockRemoveBlock(nodeId) @@ -341,19 +309,18 @@ describe('ParallelNodeComponent', () => { expect(mockRemoveBlock).toHaveBeenCalledWith('test-id') }) - it('should handle event propagation prevention', () => { + it.concurrent('should handle event propagation prevention', () => { const mockEvent = { stopPropagation: vi.fn(), } - // Test that stopPropagation is called mockEvent.stopPropagation() expect(mockEvent.stopPropagation).toHaveBeenCalled() }) }) describe('Component Data Handling', () => { - it('should handle missing data properties gracefully', () => { + it.concurrent('should handle missing data properties gracefully', () => { const testCases = [ undefined, {}, @@ -375,7 +342,7 @@ describe('ParallelNodeComponent', () => { }) }) - it('should handle parent ID relationships', () => { + it.concurrent('should handle parent ID relationships', () => { const testCases = [ { parentId: undefined, hasParent: false }, { parentId: 'parent-1', hasParent: true }, @@ -390,7 +357,7 @@ describe('ParallelNodeComponent', () => { }) describe('Handle Configuration', () => { - it('should have correct handle IDs for parallel nodes', () => { + it.concurrent('should have correct handle IDs for parallel nodes', () => { const handleIds = { startSource: 'parallel-start-source', endSource: 'parallel-end-source', @@ -402,7 +369,7 @@ describe('ParallelNodeComponent', () => { expect(handleIds.endSource).not.toContain('loop') }) - it('should handle different handle positions', () => { + it.concurrent('should handle different handle positions', () => { const positions = { left: 'left', right: 'right', @@ -418,7 +385,7 @@ describe('ParallelNodeComponent', () => { }) describe('Edge Cases and Error Handling', () => { - it('should handle circular parent references', () => { + it.concurrent('should handle circular parent references', () => { // Test circular reference prevention const nodes = [ { id: 'node1', data: { parentId: 'node2' } }, @@ -456,7 +423,7 @@ describe('ParallelNodeComponent', () => { expect(visited.has('node2')).toBe(true) }) - it('should handle complex circular reference chains', () => { + it.concurrent('should handle complex circular reference chains', () => { // Test more complex circular reference scenarios const nodes = [ { id: 'node1', data: { parentId: 'node2' } }, @@ -489,7 +456,7 @@ describe('ParallelNodeComponent', () => { expect(visited.size).toBe(3) }) - it('should handle self-referencing nodes', () => { + it.concurrent('should handle self-referencing nodes', () => { // Test node that references itself const nodes = [ { id: 'node1', data: { parentId: 'node1' } }, // Self-reference @@ -520,7 +487,7 @@ describe('ParallelNodeComponent', () => { expect(visited.has('node1')).toBe(true) }) - it('should handle extreme values', () => { + it.concurrent('should handle extreme values', () => { const extremeValues = [ { width: Number.MAX_SAFE_INTEGER, height: Number.MAX_SAFE_INTEGER }, { width: -1, height: -1 }, @@ -538,7 +505,7 @@ describe('ParallelNodeComponent', () => { }) }) - it('should handle negative position values', () => { + it.concurrent('should handle negative position values', () => { const positions = [ { xPos: -100, yPos: -200 }, { xPos: 0, yPos: 0 }, @@ -556,7 +523,7 @@ describe('ParallelNodeComponent', () => { }) describe('Component Comparison with Loop Node', () => { - it('should have similar structure to loop node but different type', () => { + it.concurrent('should have similar structure to loop node but different type', () => { expect(defaultProps.type).toBe('parallelNode') expect(defaultProps.id).toContain('parallel') @@ -565,7 +532,7 @@ describe('ParallelNodeComponent', () => { expect(defaultProps.id).not.toContain('loop') }) - it('should handle the same prop structure as loop node', () => { + it.concurrent('should handle the same prop structure as loop node', () => { // Test that parallel node accepts the same prop structure as loop node const sharedPropStructure = { id: 'test-parallel', @@ -594,8 +561,7 @@ describe('ParallelNodeComponent', () => { expect(sharedPropStructure.data.height).toBe(300) }) - it('should maintain consistency with loop node interface', () => { - // Both components should accept the same base props + it.concurrent('should maintain consistency with loop node interface', () => { const baseProps = [ 'id', 'type', diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx b/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx index d5b1cbd4e90..688296190d2 100644 --- a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx +++ b/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx @@ -6,7 +6,7 @@ import { StartIcon } from '@/components/icons' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' import { cn } from '@/lib/utils' -import { useWorkflowStore } from '@/stores/workflows/workflow/store' +import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' import { ParallelBadges } from './components/parallel-badges' const ParallelNodeStyles: React.FC = () => { @@ -86,6 +86,7 @@ const ParallelNodeStyles: React.FC = () => { export const ParallelNodeComponent = memo(({ data, selected, id }: NodeProps) => { const { getNodes } = useReactFlow() + const { collaborativeRemoveBlock } = useCollaborativeWorkflow() const blockRef = useRef(null) // Check if this is preview mode @@ -111,7 +112,7 @@ export const ParallelNodeComponent = memo(({ data, selected, id }: NodeProps) => const getNestedStyles = () => { // Base styles const styles: Record = { - backgroundColor: 'transparent', + backgroundColor: 'rgba(0, 0, 0, 0.02)', } // Apply nested styles @@ -140,7 +141,8 @@ export const ParallelNodeComponent = memo(({ data, selected, id }: NodeProps) => 'z-[20]', data?.state === 'valid', nestingLevel > 0 && - `border border-[0.5px] ${nestingLevel % 2 === 0 ? 'border-slate-300/60' : 'border-slate-400/60'}` + `border border-[0.5px] ${nestingLevel % 2 === 0 ? 'border-slate-300/60' : 'border-slate-400/60'}`, + data?.hasNestedError && 'border-2 border-red-500 bg-red-50/50' )} style={{ width: data.width || 500, @@ -187,7 +189,7 @@ export const ParallelNodeComponent = memo(({ data, selected, id }: NodeProps) => size='sm' onClick={(e) => { e.stopPropagation() - useWorkflowStore.getState().removeBlock(id) + collaborativeRemoveBlock(id) }} className='absolute top-2 right-2 z-20 text-gray-500 opacity-0 transition-opacity duration-200 hover:text-red-600 group-hover:opacity-100' style={{ pointerEvents: 'auto' }} diff --git a/apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx b/apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx new file mode 100644 index 00000000000..141700a1ec2 --- /dev/null +++ b/apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx @@ -0,0 +1,205 @@ +'use client' + +import { Bell, Bug, ChevronDown, Copy, History, Layers, Play, Rocket, Trash2 } from 'lucide-react' +import { Button } from '@/components/ui/button' +import { Skeleton } from '@/components/ui/skeleton' +import { useSidebarStore } from '@/stores/sidebar/store' + +// Skeleton Components +const SkeletonControlBar = () => { + return ( +
+ {/* Left Section - Workflow Name Skeleton */} +
+ {/* Workflow name skeleton */} + + {/* "Saved X time ago" skeleton */} + +
+ + {/* Middle Section */} +
+ + {/* Right Section - Action Buttons with Real Icons */} +
+ {/* Delete Button */} + + + {/* History Button */} + + + {/* Notifications Button */} + + + {/* Duplicate Button */} + + + {/* Auto Layout Button */} + + + {/* Debug Mode Button */} + + + {/* Deploy Button */} + + + {/* Run Button with Dropdown */} +
+ {/* Main Run Button */} + + + {/* Dropdown Trigger */} + +
+
+
+ ) +} + +const SkeletonPanelComponent = () => { + return ( +
+ {/* Panel skeleton */} +
+ {/* Tab headers skeleton */} +
+ {Array.from({ length: 3 }).map((_, i) => ( + + ))} +
+ + {/* Content skeleton */} +
+ {Array.from({ length: 6 }).map((_, i) => ( + + ))} +
+
+
+ ) +} + +const SkeletonNodes = () => { + return [ + // Starter node skeleton + { + id: 'skeleton-starter', + type: 'workflowBlock', + position: { x: 100, y: 100 }, + data: { + type: 'skeleton', + config: { name: '', description: '', bgColor: '#9CA3AF' }, + name: '', + isActive: false, + isPending: false, + isSkeleton: true, + }, + dragHandle: '.workflow-drag-handle', + }, + // Additional skeleton nodes + { + id: 'skeleton-node-1', + type: 'workflowBlock', + position: { x: 500, y: 100 }, + data: { + type: 'skeleton', + config: { name: '', description: '', bgColor: '#9CA3AF' }, + name: '', + isActive: false, + isPending: false, + isSkeleton: true, + }, + dragHandle: '.workflow-drag-handle', + }, + { + id: 'skeleton-node-2', + type: 'workflowBlock', + position: { x: 300, y: 300 }, + data: { + type: 'skeleton', + config: { name: '', description: '', bgColor: '#9CA3AF' }, + name: '', + isActive: false, + isPending: false, + isSkeleton: true, + }, + dragHandle: '.workflow-drag-handle', + }, + ] +} + +interface SkeletonLoadingProps { + showSkeleton: boolean + isSidebarCollapsed: boolean + children: React.ReactNode +} + +export function SkeletonLoading({ + showSkeleton, + isSidebarCollapsed, + children, +}: SkeletonLoadingProps) { + const { mode, isExpanded } = useSidebarStore() + + return ( +
+
+ {/* Skeleton Control Bar */} +
+ +
+ + {/* Real Control Bar */} +
+ {children} +
+
+ + {/* Real content will be rendered by children - sidebar will show its own loading state */} +
+ ) +} + +export function SkeletonPanelWrapper({ showSkeleton }: { showSkeleton: boolean }) { + return ( +
+ +
+ ) +} + +export { SkeletonNodes, SkeletonPanelComponent } diff --git a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx b/apps/sim/app/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx index 2220ea7c966..b625fa40403 100644 --- a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx +++ b/apps/sim/app/w/[id]/components/toolbar/components/toolbar-block/toolbar-block.tsx @@ -1,19 +1,26 @@ import { useCallback } from 'react' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { cn } from '@/lib/utils' import type { BlockConfig } from '@/blocks/types' export type ToolbarBlockProps = { config: BlockConfig + disabled?: boolean } -export function ToolbarBlock({ config }: ToolbarBlockProps) { +export function ToolbarBlock({ config, disabled = false }: ToolbarBlockProps) { const handleDragStart = (e: React.DragEvent) => { + if (disabled) { + e.preventDefault() + return + } e.dataTransfer.setData('application/json', JSON.stringify({ type: config.type })) e.dataTransfer.effectAllowed = 'move' } // Handle click to add block const handleClick = useCallback(() => { - if (config.type === 'connectionBlock') return + if (config.type === 'connectionBlock' || disabled) return // Dispatch a custom event to be caught by the workflow component const event = new CustomEvent('add-block-from-toolbar', { @@ -22,23 +29,30 @@ export function ToolbarBlock({ config }: ToolbarBlockProps) { }, }) window.dispatchEvent(event) - }, [config.type]) + }, [config.type, disabled]) - return ( + const blockContent = (
@@ -47,4 +61,15 @@ export function ToolbarBlock({ config }: ToolbarBlockProps) {
) + + if (disabled) { + return ( + + {blockContent} + Edit permissions required to add blocks + + ) + } + + return blockContent } diff --git a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx b/apps/sim/app/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx index d07ca5e5713..6097e644273 100644 --- a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx +++ b/apps/sim/app/w/[id]/components/toolbar/components/toolbar-loop-block/toolbar-loop-block.tsx @@ -1,9 +1,19 @@ import { useCallback } from 'react' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { cn } from '@/lib/utils' import { LoopTool } from '../../../loop-node/loop-config' +type LoopToolbarItemProps = { + disabled?: boolean +} + // Custom component for the Loop Tool -export default function LoopToolbarItem() { +export default function LoopToolbarItem({ disabled = false }: LoopToolbarItemProps) { const handleDragStart = (e: React.DragEvent) => { + if (disabled) { + e.preventDefault() + return + } // Only send the essential data for the loop node const simplifiedData = { type: 'loop', @@ -13,30 +23,45 @@ export default function LoopToolbarItem() { } // Handle click to add loop block - const handleClick = useCallback((e: React.MouseEvent) => { - // Dispatch a custom event to be caught by the workflow component - const event = new CustomEvent('add-block-from-toolbar', { - detail: { - type: 'loop', - clientX: e.clientX, - clientY: e.clientY, - }, - }) - window.dispatchEvent(event) - }, []) + const handleClick = useCallback( + (e: React.MouseEvent) => { + if (disabled) return + + // Dispatch a custom event to be caught by the workflow component + const event = new CustomEvent('add-block-from-toolbar', { + detail: { + type: 'loop', + clientX: e.clientX, + clientY: e.clientY, + }, + }) + window.dispatchEvent(event) + }, + [disabled] + ) - return ( + const blockContent = (
- +

{LoopTool.name}

@@ -44,4 +69,15 @@ export default function LoopToolbarItem() {
) + + if (disabled) { + return ( + + {blockContent} + Edit permissions required to add blocks + + ) + } + + return blockContent } diff --git a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx b/apps/sim/app/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx index 9f277ba67ba..08c732dacbb 100644 --- a/apps/sim/app/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx +++ b/apps/sim/app/w/[id]/components/toolbar/components/toolbar-parallel-block/toolbar-parallel-block.tsx @@ -1,9 +1,19 @@ import { useCallback } from 'react' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { cn } from '@/lib/utils' import { ParallelTool } from '../../../parallel-node/parallel-config' +type ParallelToolbarItemProps = { + disabled?: boolean +} + // Custom component for the Parallel Tool -export default function ParallelToolbarItem() { +export default function ParallelToolbarItem({ disabled = false }: ParallelToolbarItemProps) { const handleDragStart = (e: React.DragEvent) => { + if (disabled) { + e.preventDefault() + return + } // Only send the essential data for the parallel node const simplifiedData = { type: 'parallel', @@ -13,31 +23,46 @@ export default function ParallelToolbarItem() { } // Handle click to add parallel block - const handleClick = useCallback((e: React.MouseEvent) => { - // Dispatch a custom event to be caught by the workflow component - const event = new CustomEvent('add-block-from-toolbar', { - detail: { - type: 'parallel', - clientX: e.clientX, - clientY: e.clientY, - }, - bubbles: true, - }) - window.dispatchEvent(event) - }, []) + const handleClick = useCallback( + (e: React.MouseEvent) => { + if (disabled) return + + // Dispatch a custom event to be caught by the workflow component + const event = new CustomEvent('add-block-from-toolbar', { + detail: { + type: 'parallel', + clientX: e.clientX, + clientY: e.clientY, + }, + bubbles: true, + }) + window.dispatchEvent(event) + }, + [disabled] + ) - return ( + const blockContent = (
- +

{ParallelTool.name}

@@ -45,4 +70,15 @@ export default function ParallelToolbarItem() {
) + + if (disabled) { + return ( + + {blockContent} + Edit permissions required to add blocks + + ) + } + + return blockContent } diff --git a/apps/sim/app/w/[id]/components/toolbar/toolbar.tsx b/apps/sim/app/w/[id]/components/toolbar/toolbar.tsx index a5b6d6a1746..8d86f8407f5 100644 --- a/apps/sim/app/w/[id]/components/toolbar/toolbar.tsx +++ b/apps/sim/app/w/[id]/components/toolbar/toolbar.tsx @@ -1,25 +1,69 @@ 'use client' -import { useMemo, useState } from 'react' +import React, { useCallback, useMemo, useState } from 'react' import { PanelLeftClose, PanelRight, Search } from 'lucide-react' +import { useParams } from 'next/navigation' import { Input } from '@/components/ui/input' import { ScrollArea } from '@/components/ui/scroll-area' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { useUserPermissionsContext } from '@/app/w/components/providers/workspace-permissions-provider' import { getAllBlocks, getBlocksByCategory } from '@/blocks' import type { BlockCategory } from '@/blocks/types' import { useSidebarStore } from '@/stores/sidebar/store' +import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { ToolbarBlock } from './components/toolbar-block/toolbar-block' import LoopToolbarItem from './components/toolbar-loop-block/toolbar-loop-block' import ParallelToolbarItem from './components/toolbar-parallel-block/toolbar-parallel-block' import { ToolbarTabs } from './components/toolbar-tabs/toolbar-tabs' -export function Toolbar() { +interface ToolbarButtonProps { + onClick: () => void + className: string + children: React.ReactNode + tooltipContent: string + tooltipSide?: 'left' | 'right' | 'top' | 'bottom' +} + +const ToolbarButton = React.memo( + ({ onClick, className, children, tooltipContent, tooltipSide = 'right' }) => ( + + + + + {tooltipContent} + + ) +) + +ToolbarButton.displayName = 'ToolbarButton' + +export const Toolbar = React.memo(() => { + const params = useParams() + const workflowId = params?.id as string + + // Get the workspace ID from the workflow registry + const { activeWorkspaceId, workflows } = useWorkflowRegistry() + + const currentWorkflow = useMemo( + () => (workflowId ? workflows[workflowId] : null), + [workflowId, workflows] + ) + + const workspaceId = currentWorkflow?.workspaceId || activeWorkspaceId + + const userPermissions = useUserPermissionsContext() + const [activeTab, setActiveTab] = useState('blocks') const [searchQuery, setSearchQuery] = useState('') const { mode, isExpanded } = useSidebarStore() + // In hover mode, act as if sidebar is always collapsed for layout purposes - const isSidebarCollapsed = - mode === 'expanded' ? !isExpanded : mode === 'collapsed' || mode === 'hover' + const isSidebarCollapsed = useMemo( + () => (mode === 'expanded' ? !isExpanded : mode === 'collapsed' || mode === 'hover'), + [mode, isExpanded] + ) // State to track if toolbar is open - independent of sidebar state const [isToolbarOpen, setIsToolbarOpen] = useState(true) @@ -38,21 +82,34 @@ export function Toolbar() { }) }, [searchQuery, activeTab]) + const handleOpenToolbar = useCallback(() => { + setIsToolbarOpen(true) + }, []) + + const handleCloseToolbar = useCallback(() => { + setIsToolbarOpen(false) + }, []) + + const handleSearchChange = useCallback((e: React.ChangeEvent) => { + setSearchQuery(e.target.value) + }, []) + + const handleTabChange = useCallback((tab: BlockCategory) => { + setActiveTab(tab) + }, []) + // Show toolbar button when it's closed, regardless of sidebar state if (!isToolbarOpen) { return ( - - - - - Open Toolbar - + + + Open Toolbar + ) } @@ -68,7 +125,7 @@ export function Toolbar() { placeholder='Search...' className='rounded-md pl-9' value={searchQuery} - onChange={(e) => setSearchQuery(e.target.value)} + onChange={handleSearchChange} autoComplete='off' autoCorrect='off' autoCapitalize='off' @@ -79,7 +136,7 @@ export function Toolbar() { {!searchQuery && (
- +
)} @@ -87,12 +144,12 @@ export function Toolbar() {
{blocks.map((block) => ( - + ))} {activeTab === 'blocks' && !searchQuery && ( <> - - + + )}
@@ -100,20 +157,19 @@ export function Toolbar() {
- - - - - Close Toolbar - + + + Close Toolbar +
) -} +}) + +Toolbar.displayName = 'Toolbar' diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx index 7a626eab205..1e7c5e7e967 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/action-bar/action-bar.tsx @@ -2,16 +2,17 @@ import { ArrowLeftRight, ArrowUpDown, Circle, CircleOff, Copy, Trash2 } from 'lu import { Button } from '@/components/ui/button' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { cn } from '@/lib/utils' +import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' import { useWorkflowStore } from '@/stores/workflows/workflow/store' interface ActionBarProps { blockId: string blockType: string + disabled?: boolean } -export function ActionBar({ blockId, blockType }: ActionBarProps) { - const removeBlock = useWorkflowStore((state) => state.removeBlock) - const toggleBlockEnabled = useWorkflowStore((state) => state.toggleBlockEnabled) +export function ActionBar({ blockId, blockType, disabled = false }: ActionBarProps) { + const { collaborativeRemoveBlock, collaborativeToggleBlockEnabled } = useCollaborativeWorkflow() const toggleBlockHandles = useWorkflowStore((state) => state.toggleBlockHandles) const duplicateBlock = useWorkflowStore((state) => state.duplicateBlock) const isEnabled = useWorkflowStore((state) => state.blocks[blockId]?.enabled ?? true) @@ -52,13 +53,20 @@ export function ActionBar({ blockId, blockType }: ActionBarProps) { - {isEnabled ? 'Disable Block' : 'Enable Block'} + + {disabled ? 'Read-only mode' : isEnabled ? 'Disable Block' : 'Enable Block'} + {!isStarterBlock && ( @@ -67,13 +75,20 @@ export function ActionBar({ blockId, blockType }: ActionBarProps) { - Duplicate Block + + {disabled ? 'Read-only mode' : 'Duplicate Block'} + )} @@ -82,8 +97,13 @@ export function ActionBar({ blockId, blockType }: ActionBarProps) { - {horizontalHandles ? 'Vertical Ports' : 'Horizontal Ports'} + {disabled ? 'Read-only mode' : horizontalHandles ? 'Vertical Ports' : 'Horizontal Ports'} @@ -103,13 +123,23 @@ export function ActionBar({ blockId, blockType }: ActionBarProps) { - Delete Block + + {disabled ? 'Read-only mode' : 'Delete Block'} + )}
diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx index 10accd8d66d..baf322f53e7 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/connection-blocks/connection-blocks.tsx @@ -1,10 +1,12 @@ import { Card } from '@/components/ui/card' +import { cn } from '@/lib/utils' import { type ConnectedBlock, useBlockConnections } from '@/app/w/[id]/hooks/use-block-connections' import { useSubBlockStore } from '@/stores/workflows/subblock/store' interface ConnectionBlocksProps { blockId: string setIsConnecting: (isConnecting: boolean) => void + isDisabled?: boolean } interface ResponseField { @@ -13,7 +15,11 @@ interface ResponseField { description?: string } -export function ConnectionBlocks({ blockId, setIsConnecting }: ConnectionBlocksProps) { +export function ConnectionBlocks({ + blockId, + setIsConnecting, + isDisabled = false, +}: ConnectionBlocksProps) { const { incomingConnections, hasIncomingConnections } = useBlockConnections(blockId) if (!hasIncomingConnections) return null @@ -23,6 +29,11 @@ export function ConnectionBlocks({ blockId, setIsConnecting }: ConnectionBlocksP connection: ConnectedBlock, field?: ResponseField ) => { + if (isDisabled) { + e.preventDefault() + return + } + e.stopPropagation() // Prevent parent drag handlers from firing setIsConnecting(true) e.dataTransfer.setData( @@ -127,10 +138,15 @@ export function ConnectionBlocks({ blockId, setIsConnecting }: ConnectionBlocksP return ( handleDragStart(e, connection, field)} onDragEnd={handleDragEnd} - className='group flex w-max cursor-grab items-center rounded-lg border bg-card p-2 shadow-sm transition-colors hover:bg-accent/50 active:cursor-grabbing' + className={cn( + 'group flex w-max items-center rounded-lg border bg-card p-2 shadow-sm transition-colors', + !isDisabled + ? 'cursor-grab hover:bg-accent/50 active:cursor-grabbing' + : 'cursor-not-allowed opacity-60' + )} >
{displayName} diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx index 842462abfb5..72f0deb46b7 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx @@ -11,6 +11,7 @@ interface CheckboxListProps { layout?: 'full' | 'half' isPreview?: boolean subBlockValues?: Record + disabled?: boolean } export function CheckboxList({ @@ -21,6 +22,7 @@ export function CheckboxList({ layout, isPreview = false, subBlockValues, + disabled = false, }: CheckboxListProps) { return (
@@ -35,8 +37,8 @@ export function CheckboxList({ const value = isPreview ? previewValue : storeValue const handleChange = (checked: boolean) => { - // Only update store when not in preview mode - if (!isPreview) { + // Only update store when not in preview mode or disabled + if (!isPreview && !disabled) { setStoreValue(checked) } } @@ -47,7 +49,7 @@ export function CheckboxList({ id={`${blockId}-${option.id}`} checked={Boolean(value)} onCheckedChange={handleChange} - disabled={isPreview} + disabled={isPreview || disabled} />
+ + {/* Show value input for non-container types OR container types using variables */} + {(!isContainer || isObjectVariable) && ( +
+ +
+ )} + + {/* Show object variable input for object types */} + {isContainer && !isObjectVariable && ( +
+ ) => + onUpdateProperty(property.id, updates) + } + onAddArrayItem={onAddArrayItem} + onRemoveArrayItem={onRemoveArrayItem} + onUpdateArrayItem={onUpdateArrayItem} + placeholder='Use or define properties below' + onObjectVariableChange={(newValue: string) => { + if (newValue.startsWith('<')) { + onUpdateProperty(property.id, { value: newValue }) + } else if (newValue === '') { + onUpdateProperty(property.id, { value: [] }) + } + }} + /> +
+ )} +
+ + {isContainer && !property.collapsed && !isObjectVariable && ( +
+ {Array.isArray(property.value) && property.value.length > 0 ? ( + property.value.map((childProp: JSONProperty) => ( + + )) + ) : ( +
+

No properties

+ +
+ )} +
+ )} +
+ ) +} diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx new file mode 100644 index 00000000000..6109affb3aa --- /dev/null +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/components/value-input.tsx @@ -0,0 +1,300 @@ +import { useRef, useState } from 'react' +import { Plus, Trash } from 'lucide-react' +import { Button } from '@/components/ui/button' +import { checkEnvVarTrigger, EnvVarDropdown } from '@/components/ui/env-var-dropdown' +import { Input } from '@/components/ui/input' +import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown' +import { createLogger } from '@/lib/logs/console-logger' +import type { JSONProperty } from '../response-format' + +const logger = createLogger('ValueInput') + +interface ValueInputProps { + property: JSONProperty + blockId: string + isPreview: boolean + onUpdateProperty: (id: string, updates: Partial) => void + onAddArrayItem: (arrayPropId: string) => void + onRemoveArrayItem: (arrayPropId: string, index: number) => void + onUpdateArrayItem: (arrayPropId: string, index: number, newValue: any) => void + placeholder?: string + onObjectVariableChange?: (newValue: string) => void +} + +export function ValueInput({ + property, + blockId, + isPreview, + onUpdateProperty, + onAddArrayItem, + onRemoveArrayItem, + onUpdateArrayItem, + placeholder, + onObjectVariableChange, +}: ValueInputProps) { + const [showEnvVars, setShowEnvVars] = useState(false) + const [showTags, setShowTags] = useState(false) + const [searchTerm, setSearchTerm] = useState('') + const [cursorPosition, setCursorPosition] = useState(0) + const [activeSourceBlockId, setActiveSourceBlockId] = useState(null) + + const inputRefs = useRef<{ [key: string]: HTMLInputElement | null }>({}) + + const findPropertyById = (props: JSONProperty[], id: string): JSONProperty | null => { + for (const prop of props) { + if (prop.id === id) return prop + if (prop.type === 'object' && Array.isArray(prop.value)) { + const found = findPropertyById(prop.value, id) + if (found) return found + } + } + return null + } + + const handleDragOver = (e: React.DragEvent) => { + e.preventDefault() + } + + const handleDrop = (e: React.DragEvent, propId: string) => { + if (isPreview) return + e.preventDefault() + + try { + const data = JSON.parse(e.dataTransfer.getData('application/json')) + if (data.type !== 'connectionBlock') return + + const input = inputRefs.current[propId] + const dropPosition = input?.selectionStart ?? 0 + + const currentValue = property.value?.toString() ?? '' + const newValue = `${currentValue.slice(0, dropPosition)}<${currentValue.slice(dropPosition)}` + + input?.focus() + + Promise.resolve().then(() => { + onUpdateProperty(property.id, { value: newValue }) + setCursorPosition(dropPosition + 1) + setShowTags(true) + + if (data.connectionData?.sourceBlockId) { + setActiveSourceBlockId(data.connectionData.sourceBlockId) + } + + setTimeout(() => { + if (input) { + input.selectionStart = dropPosition + 1 + input.selectionEnd = dropPosition + 1 + } + }, 0) + }) + } catch (error) { + logger.error('Failed to parse drop data:', { error }) + } + } + + const getPlaceholder = () => { + if (placeholder) return placeholder + + switch (property.type) { + case 'number': + return '42 or ' + case 'boolean': + return 'true/false or ' + case 'array': + return '["item1", "item2"] or ' + case 'object': + return '{...} or ' + default: + return 'Enter text or ' + } + } + + const handleInputChange = (e: React.ChangeEvent) => { + const newValue = e.target.value + const cursorPos = e.target.selectionStart || 0 + + if (onObjectVariableChange) { + onObjectVariableChange(newValue.trim()) + } else { + onUpdateProperty(property.id, { value: newValue }) + } + + if (!isPreview) { + const tagTrigger = checkTagTrigger(newValue, cursorPos) + const envVarTrigger = checkEnvVarTrigger(newValue, cursorPos) + + setShowTags(tagTrigger.show) + setShowEnvVars(envVarTrigger.show) + setSearchTerm(envVarTrigger.searchTerm || '') + setCursorPosition(cursorPos) + } + } + + const handleTagSelect = (newValue: string) => { + if (onObjectVariableChange) { + onObjectVariableChange(newValue) + } else { + onUpdateProperty(property.id, { value: newValue }) + } + setShowTags(false) + } + + const handleEnvVarSelect = (newValue: string) => { + if (onObjectVariableChange) { + onObjectVariableChange(newValue) + } else { + onUpdateProperty(property.id, { value: newValue }) + } + setShowEnvVars(false) + } + + const isArrayVariable = + property.type === 'array' && + typeof property.value === 'string' && + property.value.trim().startsWith('<') && + property.value.trim().includes('>') + + // Handle array type with individual items + if (property.type === 'array' && !isArrayVariable && Array.isArray(property.value)) { + return ( +
+
+ { + inputRefs.current[`${property.id}-array-variable`] = el + }} + value={typeof property.value === 'string' ? property.value : ''} + onChange={(e) => { + const newValue = e.target.value.trim() + if (newValue.startsWith('<') || newValue.startsWith('[')) { + onUpdateProperty(property.id, { value: newValue }) + } else if (newValue === '') { + onUpdateProperty(property.id, { value: [] }) + } + + const cursorPos = e.target.selectionStart || 0 + if (!isPreview) { + const tagTrigger = checkTagTrigger(newValue, cursorPos) + const envVarTrigger = checkEnvVarTrigger(newValue, cursorPos) + + setShowTags(tagTrigger.show) + setShowEnvVars(envVarTrigger.show) + setSearchTerm(envVarTrigger.searchTerm || '') + setCursorPosition(cursorPos) + } + }} + onDragOver={handleDragOver} + onDrop={(e) => handleDrop(e, `${property.id}-array-variable`)} + placeholder='Use or define items below' + disabled={isPreview} + className='h-7 text-xs' + /> + {!isPreview && showTags && ( + setShowTags(false)} + /> + )} + {!isPreview && showEnvVars && ( + setShowEnvVars(false)} + /> + )} +
+ + {property.value.length > 0 && ( + <> +
Array Items:
+ {property.value.map((item: any, index: number) => ( +
+
+ { + inputRefs.current[`${property.id}-array-${index}`] = el + }} + value={item || ''} + onChange={(e) => onUpdateArrayItem(property.id, index, e.target.value)} + onDragOver={handleDragOver} + onDrop={(e) => handleDrop(e, `${property.id}-array-${index}`)} + placeholder={`Item ${index + 1}`} + disabled={isPreview} + className='h-7 text-xs' + /> +
+ +
+ ))} + + )} + + +
+ ) + } + + // Handle regular input for all other types + return ( +
+ { + inputRefs.current[property.id] = el + }} + value={property.value || ''} + onChange={handleInputChange} + onDragOver={handleDragOver} + onDrop={(e) => handleDrop(e, property.id)} + placeholder={getPlaceholder()} + disabled={isPreview} + className='h-7 text-xs' + /> + {!isPreview && showTags && ( + setShowTags(false)} + /> + )} + {!isPreview && showEnvVars && ( + setShowEnvVars(false)} + /> + )} +
+ ) +} diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx new file mode 100644 index 00000000000..edef012ccc8 --- /dev/null +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/response/response-format.tsx @@ -0,0 +1,326 @@ +import { useState } from 'react' +import { Code, Eye, Plus } from 'lucide-react' +import { Button } from '@/components/ui/button' +import { Label } from '@/components/ui/label' +import { useSubBlockValue } from '../../hooks/use-sub-block-value' +import { PropertyRenderer } from './components/property-renderer' + +export interface JSONProperty { + id: string + key: string + type: 'string' | 'number' | 'boolean' | 'object' | 'array' + value: any + collapsed?: boolean +} + +interface ResponseFormatProps { + blockId: string + subBlockId: string + isPreview?: boolean + previewValue?: JSONProperty[] | null +} + +const TYPE_ICONS = { + string: 'Aa', + number: '123', + boolean: 'T/F', + object: '{}', + array: '[]', +} + +const TYPE_COLORS = { + string: 'text-green-600 dark:text-green-400', + number: 'text-blue-600 dark:text-blue-400', + boolean: 'text-purple-600 dark:text-purple-400', + object: 'text-orange-600 dark:text-orange-400', + array: 'text-pink-600 dark:text-pink-400', +} + +const DEFAULT_PROPERTY: JSONProperty = { + id: crypto.randomUUID(), + key: 'message', + type: 'string', + value: '', + collapsed: false, +} + +export function ResponseFormat({ + blockId, + subBlockId, + isPreview = false, + previewValue, +}: ResponseFormatProps) { + const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId) + const [showPreview, setShowPreview] = useState(false) + + const value = isPreview ? previewValue : storeValue + const properties: JSONProperty[] = value || [DEFAULT_PROPERTY] + + const isVariableReference = (value: any): boolean => { + return typeof value === 'string' && value.trim().startsWith('<') && value.trim().includes('>') + } + + const findPropertyById = (props: JSONProperty[], id: string): JSONProperty | null => { + for (const prop of props) { + if (prop.id === id) return prop + if (prop.type === 'object' && Array.isArray(prop.value)) { + const found = findPropertyById(prop.value, id) + if (found) return found + } + } + return null + } + + const generateJSON = (props: JSONProperty[]): any => { + const result: any = {} + + for (const prop of props) { + if (!prop.key.trim()) return + + let value = prop.value + + if (prop.type === 'object') { + if (Array.isArray(prop.value)) { + value = generateJSON(prop.value) + } else if (typeof prop.value === 'string' && isVariableReference(prop.value)) { + value = prop.value + } else { + value = {} // Default empty object for non-array, non-variable values + } + } else if (prop.type === 'array' && Array.isArray(prop.value)) { + value = prop.value.map((item: any) => { + if (typeof item === 'object' && item.type) { + if (item.type === 'object' && Array.isArray(item.value)) { + return generateJSON(item.value) + } + if (item.type === 'array' && Array.isArray(item.value)) { + return item.value.map((subItem: any) => + typeof subItem === 'object' && subItem.type ? subItem.value : subItem + ) + } + return item.value + } + return item + }) + } else if (prop.type === 'number' && !isVariableReference(value)) { + value = Number.isNaN(Number(value)) ? value : Number(value) + } else if (prop.type === 'boolean' && !isVariableReference(value)) { + const strValue = String(value).toLowerCase().trim() + value = strValue === 'true' || strValue === '1' || strValue === 'yes' || strValue === 'on' + } + + result[prop.key] = value + } + + return result + } + + const updateProperties = (newProperties: JSONProperty[]) => { + if (isPreview) return + setStoreValue(newProperties) + } + + const updateProperty = (id: string, updates: Partial) => { + const updateRecursive = (props: JSONProperty[]): JSONProperty[] => { + return props.map((prop) => { + if (prop.id === id) { + const updated = { ...prop, ...updates } + + if (updates.type && updates.type !== prop.type) { + if (updates.type === 'object') { + updated.value = [] + } else if (updates.type === 'array') { + updated.value = [] + } else if (updates.type === 'boolean') { + updated.value = 'false' + } else if (updates.type === 'number') { + updated.value = '0' + } else { + updated.value = '' + } + } + + return updated + } + + if (prop.type === 'object' && Array.isArray(prop.value)) { + return { ...prop, value: updateRecursive(prop.value) } + } + + return prop + }) + } + + updateProperties(updateRecursive(properties)) + } + + const addProperty = (parentId?: string) => { + const newProp: JSONProperty = { + id: crypto.randomUUID(), + key: '', + type: 'string', + value: '', + collapsed: false, + } + + if (parentId) { + const addToParent = (props: JSONProperty[]): JSONProperty[] => { + return props.map((prop) => { + if (prop.id === parentId && prop.type === 'object') { + return { ...prop, value: [...(prop.value || []), newProp] } + } + if (prop.type === 'object' && Array.isArray(prop.value)) { + return { ...prop, value: addToParent(prop.value) } + } + return prop + }) + } + updateProperties(addToParent(properties)) + } else { + updateProperties([...properties, newProp]) + } + } + + const removeProperty = (id: string) => { + const removeRecursive = (props: JSONProperty[]): JSONProperty[] => { + return props + .filter((prop) => prop.id !== id) + .map((prop) => { + if (prop.type === 'object' && Array.isArray(prop.value)) { + return { ...prop, value: removeRecursive(prop.value) } + } + return prop + }) + } + + const newProperties = removeRecursive(properties) + updateProperties( + newProperties.length > 0 + ? newProperties + : [ + { + id: crypto.randomUUID(), + key: '', + type: 'string', + value: '', + collapsed: false, + }, + ] + ) + } + + const addArrayItem = (arrayPropId: string) => { + const addItem = (props: JSONProperty[]): JSONProperty[] => { + return props.map((prop) => { + if (prop.id === arrayPropId && prop.type === 'array') { + return { ...prop, value: [...(prop.value || []), ''] } + } + if (prop.type === 'object' && Array.isArray(prop.value)) { + return { ...prop, value: addItem(prop.value) } + } + return prop + }) + } + updateProperties(addItem(properties)) + } + + const removeArrayItem = (arrayPropId: string, index: number) => { + const removeItem = (props: JSONProperty[]): JSONProperty[] => { + return props.map((prop) => { + if (prop.id === arrayPropId && prop.type === 'array') { + const newValue = [...(prop.value || [])] + newValue.splice(index, 1) + return { ...prop, value: newValue } + } + if (prop.type === 'object' && Array.isArray(prop.value)) { + return { ...prop, value: removeItem(prop.value) } + } + return prop + }) + } + updateProperties(removeItem(properties)) + } + + const updateArrayItem = (arrayPropId: string, index: number, newValue: any) => { + const updateItem = (props: JSONProperty[]): JSONProperty[] => { + return props.map((prop) => { + if (prop.id === arrayPropId && prop.type === 'array') { + const updatedValue = [...(prop.value || [])] + updatedValue[index] = newValue + return { ...prop, value: updatedValue } + } + if (prop.type === 'object' && Array.isArray(prop.value)) { + return { ...prop, value: updateItem(prop.value) } + } + return prop + }) + } + updateProperties(updateItem(properties)) + } + + const hasConfiguredProperties = properties.some((prop) => prop.key.trim()) + + return ( +
+
+ +
+ + +
+
+ + {showPreview && ( +
+
+            {JSON.stringify(generateJSON(properties), null, 2)}
+          
+
+ )} + +
+ {properties.map((prop) => ( + + ))} +
+ + {!hasConfiguredProperties && ( +
+

Build your JSON response format

+

+ Use <variable.name> in values or drag variables from above +

+
+ )} +
+ ) +} diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx index 6c3d0d927cc..f71b26046c3 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/components/schedule-modal.tsx @@ -648,7 +648,10 @@ export function ScheduleModal({ setShowDeleteConfirm(false)}> Cancel - + {isDeleting ? 'Deleting...' : 'Delete Schedule'} diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx index a088192b723..182b8ae6922 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/schedule/schedule-config.tsx @@ -21,6 +21,7 @@ interface ScheduleConfigProps { isConnecting: boolean isPreview?: boolean previewValue?: any | null + disabled?: boolean } export function ScheduleConfig({ @@ -29,6 +30,7 @@ export function ScheduleConfig({ isConnecting, isPreview = false, previewValue, + disabled = false, }: ScheduleConfigProps) { const [error, setError] = useState(null) const [scheduleId, setScheduleId] = useState(null) @@ -137,7 +139,7 @@ export function ScheduleConfig({ } const handleOpenModal = () => { - if (isPreview) return + if (isPreview || disabled) return setIsModalOpen(true) } @@ -151,7 +153,7 @@ export function ScheduleConfig({ } const handleSaveSchedule = async (): Promise => { - if (isPreview) return false + if (isPreview || disabled) return false setIsSaving(true) setError(null) @@ -255,7 +257,7 @@ export function ScheduleConfig({ } const handleDeleteSchedule = async (): Promise => { - if (isPreview || !scheduleId) return false + if (isPreview || !scheduleId || disabled) return false setIsDeleting(true) try { @@ -328,7 +330,7 @@ export function ScheduleConfig({ size='icon' className='h-8 w-8 shrink-0' onClick={handleOpenModal} - disabled={isPreview || isDeleting || isConnecting} + disabled={isPreview || isDeleting || isConnecting || disabled} > {isDeleting ? (
@@ -344,7 +346,7 @@ export function ScheduleConfig({ size='sm' className='flex h-10 w-full items-center bg-background font-normal text-sm' onClick={handleOpenModal} - disabled={isPreview || isConnecting || isSaving || isDeleting} + disabled={isPreview || isConnecting || isSaving || isDeleting || disabled} > {isLoading ? (
diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx index 4aed0f8571d..76bf854a796 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx @@ -22,6 +22,7 @@ interface ShortInputProps { onChange?: (value: string) => void isPreview?: boolean previewValue?: string | null + disabled?: boolean } export function ShortInput({ @@ -35,6 +36,7 @@ export function ShortInput({ value: propValue, isPreview = false, previewValue, + disabled = false, }: ShortInputProps) { const [isFocused, setIsFocused] = useState(false) const [showEnvVars, setShowEnvVars] = useState(false) @@ -92,6 +94,12 @@ export function ShortInput({ // Handle input changes const handleChange = (e: React.ChangeEvent) => { + // Don't allow changes if disabled + if (disabled) { + e.preventDefault() + return + } + const newValue = e.target.value const newCursorPosition = e.target.selectionStart ?? 0 @@ -328,7 +336,7 @@ export function ShortInput({ onKeyDown={handleKeyDown} autoComplete='off' style={{ overflowX: 'auto' }} - disabled={isPreview} + disabled={disabled} />
(blockId, subBlockId) @@ -44,7 +46,7 @@ export function SliderInput({ }, [normalizedValue, value, setStoreValue, isPreview]) const handleValueChange = (newValue: number[]) => { - if (!isPreview) { + if (!isPreview && !disabled) { const processedValue = integer ? Math.round(newValue[0]) : newValue[0] setStoreValue(processedValue) } @@ -57,8 +59,8 @@ export function SliderInput({ min={min} max={max} step={integer ? 1 : step} - onValueChange={(value) => setStoreValue(integer ? Math.round(value[0]) : value[0])} - disabled={isPreview} + onValueChange={handleValueChange} + disabled={isPreview || disabled} className='[&_[class*=SliderTrack]]:h-1 [&_[role=slider]]:h-4 [&_[role=slider]]:w-4' />
(blockId, subBlockId) // Use preview value when in preview mode, otherwise use store value const value = isPreview ? previewValue : storeValue - const fields: InputField[] = value || [DEFAULT_FIELD] + const fields: InputField[] = value || [] // Field operations const addField = () => { - if (isPreview) return + if (isPreview || disabled) return const newField: InputField = { ...DEFAULT_FIELD, @@ -58,18 +60,18 @@ export function InputFormat({ } const removeField = (id: string) => { - if (isPreview || fields.length === 1) return + if (isPreview || disabled) return setStoreValue(fields.filter((field: InputField) => field.id !== id)) } // Update handlers const updateField = (id: string, field: keyof InputField, value: any) => { - if (isPreview) return + if (isPreview || disabled) return setStoreValue(fields.map((f: InputField) => (f.id === id ? { ...f, [field]: value } : f))) } const toggleCollapse = (id: string) => { - if (isPreview) return + if (isPreview || disabled) return setStoreValue( fields.map((f: InputField) => (f.id === id ? { ...f, collapsed: !f.collapsed } : f)) ) @@ -104,7 +106,7 @@ export function InputFormat({ variant='ghost' size='icon' onClick={addField} - disabled={isPreview} + disabled={isPreview || disabled} className='h-6 w-6 rounded-full' > @@ -115,7 +117,7 @@ export function InputFormat({ variant='ghost' size='icon' onClick={() => removeField(field.id)} - disabled={isPreview || fields.length === 1} + disabled={isPreview || disabled} className='h-6 w-6 rounded-full text-destructive hover:text-destructive' > @@ -132,96 +134,112 @@ export function InputFormat({ // Main render return (
- {fields.map((field, index) => { - const isUnconfigured = !field.name || field.name.trim() === '' - - return ( -
+

No input fields defined

+ - - - updateField(field.id, 'type', 'string')} - className='cursor-pointer' - > - Aa - String - - updateField(field.id, 'type', 'number')} - className='cursor-pointer' - > - 123 - Number - - updateField(field.id, 'type', 'boolean')} - className='cursor-pointer' - > - 0/1 - Boolean - - updateField(field.id, 'type', 'object')} - className='cursor-pointer' - > - {'{}'} - Object - - updateField(field.id, 'type', 'array')} - className='cursor-pointer' - > - [] - Array - - - + + Add Field + +
+ ) : ( + fields.map((field, index) => { + const isUnconfigured = !field.name || field.name.trim() === '' + + return ( +
+ {renderFieldHeader(field, index)} + + {!field.collapsed && ( +
+
+ + updateField(field.id, 'name', e.target.value)} + placeholder='firstName' + disabled={isPreview || disabled} + className='h-9 placeholder:text-muted-foreground/50' + /> +
+ +
+ + + + + + + updateField(field.id, 'type', 'string')} + className='cursor-pointer' + > + Aa + String + + updateField(field.id, 'type', 'number')} + className='cursor-pointer' + > + 123 + Number + + updateField(field.id, 'type', 'boolean')} + className='cursor-pointer' + > + 0/1 + Boolean + + updateField(field.id, 'type', 'object')} + className='cursor-pointer' + > + {'{}'} + Object + + updateField(field.id, 'type', 'array')} + className='cursor-pointer' + > + [] + Array + + + +
-
- )} -
- ) - })} + )} +
+ ) + }) + )} - {!hasConfiguredFields && ( + {fields.length > 0 && !hasConfiguredFields && (
Define fields above to enable structured API input
diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx index b3bc57f6f65..4812957ebe9 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx @@ -9,6 +9,7 @@ interface SwitchProps { value?: boolean isPreview?: boolean previewValue?: boolean | null + disabled?: boolean } export function Switch({ @@ -18,6 +19,7 @@ export function Switch({ value: propValue, isPreview = false, previewValue, + disabled = false, }: SwitchProps) { const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId) @@ -25,8 +27,8 @@ export function Switch({ const value = isPreview ? previewValue : propValue !== undefined ? propValue : storeValue const handleChange = (checked: boolean) => { - // Only update store when not in preview mode - if (!isPreview) { + // Only update store when not in preview mode and not disabled + if (!isPreview && !disabled) { setStoreValue(checked) } } @@ -37,7 +39,7 @@ export function Switch({ id={`${blockId}-${subBlockId}`} checked={Boolean(value)} onCheckedChange={handleChange} - disabled={isPreview} + disabled={isPreview || disabled} />
- - {/* Danger Zone Section */} -
-
-
- - - - - - -

{TOOLTIPS.resetData}

-
-
-
- - - - - - - Are you absolutely sure? - - This action cannot be undone. This will permanently delete all your workflows, - settings, and stored data. - - - - Cancel - - Reset Data - - - - -
-
) } diff --git a/apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx b/apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx new file mode 100644 index 00000000000..4cd3ab874e9 --- /dev/null +++ b/apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/components/team-seats-dialog.tsx @@ -0,0 +1,134 @@ +import { useEffect, useState } from 'react' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' +import { Label } from '@/components/ui/label' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { env } from '@/lib/env' + +interface TeamSeatsDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + title: string + description: string + currentSeats?: number + initialSeats?: number + isLoading: boolean + onConfirm: (seats: number) => Promise + confirmButtonText: string + showCostBreakdown?: boolean +} + +export function TeamSeatsDialog({ + open, + onOpenChange, + title, + description, + currentSeats, + initialSeats = 1, + isLoading, + onConfirm, + confirmButtonText, + showCostBreakdown = false, +}: TeamSeatsDialogProps) { + const [selectedSeats, setSelectedSeats] = useState(initialSeats) + + useEffect(() => { + if (open) { + setSelectedSeats(initialSeats) + } + }, [open, initialSeats]) + + const costPerSeat = env.TEAM_TIER_COST_LIMIT ?? 40 + const totalMonthlyCost = selectedSeats * costPerSeat + const costChange = currentSeats ? (selectedSeats - currentSeats) * costPerSeat : 0 + + const handleConfirm = async () => { + await onConfirm(selectedSeats) + } + + return ( + + + + {title} + {description} + + +
+ + + +

+ Your team will have {selectedSeats} {selectedSeats === 1 ? 'seat' : 'seats'} with a + total of ${totalMonthlyCost} inference credits per month. +

+ + {showCostBreakdown && currentSeats !== undefined && ( +
+
+ Current seats: + {currentSeats} +
+
+ New seats: + {selectedSeats} +
+
+ Monthly cost change: + + {costChange > 0 ? '+' : ''}${costChange} + +
+
+ )} +
+ + + + + +
+
+ ) +} diff --git a/apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx b/apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx index c0a2450d3a9..406f0db287b 100644 --- a/apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx +++ b/apps/sim/app/w/components/sidebar/components/settings-modal/components/subscription/subscription.tsx @@ -2,26 +2,12 @@ import { useEffect, useState } from 'react' import { AlertCircle } from 'lucide-react' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { Button } from '@/components/ui/button' -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog' -import { Label } from '@/components/ui/label' import { Progress } from '@/components/ui/progress' -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select' import { Skeleton } from '@/components/ui/skeleton' import { useActiveOrganization, useSession, useSubscription } from '@/lib/auth-client' +import { env } from '@/lib/env' import { createLogger } from '@/lib/logs/console-logger' +import { TeamSeatsDialog } from './components/team-seats-dialog' const logger = createLogger('Subscription') @@ -332,7 +318,7 @@ export function Subscription({ setIsTeamDialogOpen(true) } - const confirmTeamUpgrade = async () => { + const confirmTeamUpgrade = async (selectedSeats?: number) => { if (!session?.user) { setError('You need to be logged in to upgrade your team subscription') return @@ -341,10 +327,12 @@ export function Subscription({ setIsUpgradingTeam(true) setError(null) + const seatsToUse = selectedSeats || seats + try { const result = await subscription.upgrade({ plan: 'team', - seats, + seats: seatsToUse, successUrl: window.location.href, cancelUrl: window.location.href, }) @@ -816,54 +804,19 @@ export function Subscription({
)} - - - - Team Subscription - - Set up a team workspace with collaborative features. Each seat costs $40/month and - gets $40 of inference credits. - - - -
- - - -

- Your team will have {seats} {seats === 1 ? 'seat' : 'seats'} with a total of $ - {seats * 40} inference credits per month. -

-
- - - - - -
-
+ { + setSeats(selectedSeats) + await confirmTeamUpgrade(selectedSeats) + }} + confirmButtonText='Upgrade to Team Plan' + /> )}
diff --git a/apps/sim/app/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx b/apps/sim/app/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx index e9fe686013a..ea6a05d4e3c 100644 --- a/apps/sim/app/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx +++ b/apps/sim/app/w/components/sidebar/components/settings-modal/components/team-management/team-management.tsx @@ -15,8 +15,10 @@ import { Progress } from '@/components/ui/progress' import { Skeleton } from '@/components/ui/skeleton' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { client, useSession } from '@/lib/auth-client' +import { env } from '@/lib/env' import { createLogger } from '@/lib/logs/console-logger' import { checkEnterprisePlan } from '@/lib/subscription/utils' +import { TeamSeatsDialog } from '../subscription/components/team-seats-dialog' const logger = createLogger('TeamManagement') @@ -115,6 +117,10 @@ export function TeamManagement() { [activeOrganization] ) + const [isAddSeatDialogOpen, setIsAddSeatDialogOpen] = useState(false) + const [newSeatCount, setNewSeatCount] = useState(1) + const [isUpdatingSeats, setIsUpdatingSeats] = useState(false) + const loadData = useCallback(async () => { if (!session?.user) return @@ -281,7 +287,7 @@ export function TeamManagement() { } try { - await updateSeats(currentSeats - 1) + await reduceSeats(currentSeats - 1) await refreshOrganization() } catch (err: any) { setError(err.message || 'Failed to reduce seats') @@ -581,7 +587,7 @@ export function TeamManagement() { if (shouldReduceSeats && subscriptionData) { const currentSeats = subscriptionData.seats || 0 if (currentSeats > 1) { - await updateSeats(currentSeats - 1) + await reduceSeats(currentSeats - 1) } } @@ -637,34 +643,68 @@ export function TeamManagement() { ) } - const updateSeats = useCallback( - async (newSeatCount: number) => { - if (!subscriptionData || !activeOrganization) return + // Handle opening the add seat dialog + const handleAddSeatDialog = () => { + if (subscriptionData) { + setNewSeatCount((subscriptionData.seats || 1) + 1) // Default to current seats + 1 + setIsAddSeatDialogOpen(true) + } + } - // Don't allow enterprise users to modify seats - if (checkEnterprisePlan(subscriptionData)) { - setError('Enterprise plan seats can only be modified by contacting support') - return - } + // Handle reducing seats + const reduceSeats = async (newSeatCount: number) => { + if (!subscriptionData || !activeOrganization) return - try { - setIsLoading(true) - setError(null) + try { + setIsLoading(true) + setError(null) - const { error } = await client.subscription.upgrade({ - plan: 'team', - referenceId: activeOrganization.id, - successUrl: window.location.href, - cancelUrl: window.location.href, - seats: newSeatCount, - }) - if (error) throw new Error(error.message || 'Failed to update seats') - } finally { - setIsLoading(false) + const { error } = await client.subscription.upgrade({ + plan: 'team', + referenceId: activeOrganization.id, + subscriptionId: subscriptionData.id, + seats: newSeatCount, + successUrl: window.location.href, + cancelUrl: window.location.href, + }) + if (error) throw new Error(error.message || 'Failed to reduce seats') + } finally { + setIsLoading(false) + } + } + + // Confirm seat addition + const confirmAddSeats = async (selectedSeats?: number) => { + if (!subscriptionData || !activeOrganization) return + + const seatsToUse = selectedSeats || newSeatCount + + try { + setIsUpdatingSeats(true) + setError(null) + + const { error } = await client.subscription.upgrade({ + plan: 'team', + referenceId: activeOrganization.id, + subscriptionId: subscriptionData.id, + seats: seatsToUse, + successUrl: window.location.href, + cancelUrl: window.location.href, + }) + + if (error) { + setError(error.message || 'Failed to update seats') + } else { + // Close the dialog after successful upgrade + setIsAddSeatDialogOpen(false) + await refreshOrganization() } - }, - [subscriptionData, activeOrganization] - ) + } catch (err: any) { + setError(err.message || 'Failed to update seats') + } finally { + setIsUpdatingSeats(false) + } + } if (isLoading && !activeOrganization && !(hasTeamPlan || hasEnterprisePlan)) { return @@ -935,18 +975,7 @@ export function TeamManagement() { - - - -
- -
-
- - setWorkspaceName(e.target.value)} - placeholder='Enter workspace name' - className='w-full' - autoFocus - /> -
-
- -
+ return ( + + + +
+ Create New Workspace +
- -
- - - ) -} + + +
+
+
+
+ + +
+
+ +
+
+
+
+ + + ) + } +) + +WorkspaceModal.displayName = 'WorkspaceModal' // New WorkspaceEditModal component interface WorkspaceEditModalProps { @@ -134,548 +144,585 @@ interface WorkspaceEditModalProps { workspace: Workspace | null } -function WorkspaceEditModal({ - open, - onOpenChange, - onUpdateWorkspace, - workspace, -}: WorkspaceEditModalProps) { - const [workspaceName, setWorkspaceName] = useState('') - - useEffect(() => { - if (workspace && open) { - setWorkspaceName(workspace.name) - } - }, [workspace, open]) - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() - if (workspace && workspaceName.trim()) { - onUpdateWorkspace(workspace.id, workspaceName.trim()) - setWorkspaceName('') +const WorkspaceEditModal = React.memo( + ({ open, onOpenChange, onUpdateWorkspace, workspace }) => { + const [workspaceName, setWorkspaceName] = useState('') + + useEffect(() => { + if (workspace && open) { + setWorkspaceName(workspace.name) + } + }, [workspace, open]) + + const handleSubmit = useCallback( + (e: React.FormEvent) => { + e.preventDefault() + if (workspace && workspaceName.trim()) { + onUpdateWorkspace(workspace.id, workspaceName.trim()) + setWorkspaceName('') + onOpenChange(false) + } + }, + [workspace, workspaceName, onUpdateWorkspace, onOpenChange] + ) + + const handleNameChange = useCallback((e: React.ChangeEvent) => { + setWorkspaceName(e.target.value) + }, []) + + const handleClose = useCallback(() => { onOpenChange(false) - } - } + }, [onOpenChange]) - return ( - - - -
- Edit Workspace - -
-
- -
-
-
-
- - setWorkspaceName(e.target.value)} - placeholder='Enter workspace name' - className='w-full' - autoFocus - /> -
-
- -
+ return ( + + + +
+ Edit Workspace +
- -
- -
- ) -} + + +
+
+
+
+ + +
+
+ +
+
+
+
+ + + ) + } +) + +WorkspaceEditModal.displayName = 'WorkspaceEditModal' + +export const WorkspaceHeader = React.memo( + ({ onCreateWorkflow, isCollapsed, onDropdownOpenChange }) => { + // Get sidebar store state to check current mode + const { mode, workspaceDropdownOpen, setAnyModalOpen } = useSidebarStore() + + // Keep local isOpen state in sync with the store (for internal component use) + const [isOpen, setIsOpen] = useState(workspaceDropdownOpen) + const { data: sessionData, isPending } = useSession() + const [plan, setPlan] = useState('Free Plan') + // Use client-side loading instead of isPending to avoid hydration mismatch + const [isClientLoading, setIsClientLoading] = useState(true) + const [workspaces, setWorkspaces] = useState([]) + const [activeWorkspace, setActiveWorkspace] = useState(null) + const [isWorkspacesLoading, setIsWorkspacesLoading] = useState(true) + const [isWorkspaceModalOpen, setIsWorkspaceModalOpen] = useState(false) + const [editingWorkspace, setEditingWorkspace] = useState(null) + const [isEditModalOpen, setIsEditModalOpen] = useState(false) + const [isDeleting, setIsDeleting] = useState(false) + const router = useRouter() + + // Get workflowRegistry state and actions + const { activeWorkspaceId, switchToWorkspace, setActiveWorkspaceId } = useWorkflowRegistry() + + // Get user permissions for the active workspace + const userPermissions = useUserPermissionsContext() + + const userName = useMemo( + () => sessionData?.user?.name || sessionData?.user?.email || 'User', + [sessionData?.user?.name, sessionData?.user?.email] + ) + + // Set isClientLoading to false after hydration + useEffect(() => { + setIsClientLoading(false) + }, []) + + const fetchSubscriptionStatus = useCallback(async (userId: string) => { + try { + const response = await fetch('/api/user/subscription') + const data = await response.json() + setPlan(data.isPro ? 'Pro Plan' : 'Free Plan') + } catch (err) { + console.error('Error fetching subscription status:', err) + } + }, []) -export function WorkspaceHeader({ - onCreateWorkflow, - isCollapsed, - onDropdownOpenChange, -}: WorkspaceHeaderProps) { - // Get sidebar store state to check current mode - const { mode, workspaceDropdownOpen, setAnyModalOpen } = useSidebarStore() - - // Keep local isOpen state in sync with the store (for internal component use) - const [isOpen, setIsOpen] = useState(workspaceDropdownOpen) - const { data: sessionData, isPending } = useSession() - const [plan, setPlan] = useState('Free Plan') - // Use client-side loading instead of isPending to avoid hydration mismatch - const [isClientLoading, setIsClientLoading] = useState(true) - const [workspaces, setWorkspaces] = useState([]) - const [activeWorkspace, setActiveWorkspace] = useState(null) - const [isWorkspacesLoading, setIsWorkspacesLoading] = useState(true) - const [isWorkspaceModalOpen, setIsWorkspaceModalOpen] = useState(false) - const [editingWorkspace, setEditingWorkspace] = useState(null) - const [isEditModalOpen, setIsEditModalOpen] = useState(false) - const [isDeleting, setIsDeleting] = useState(false) - const router = useRouter() - - // Get workflowRegistry state and actions - const { activeWorkspaceId, setActiveWorkspace: setActiveWorkspaceId } = useWorkflowRegistry() - - const userName = sessionData?.user?.name || sessionData?.user?.email || 'User' - - // Set isClientLoading to false after hydration - useEffect(() => { - setIsClientLoading(false) - }, []) - - useEffect(() => { - // Fetch subscription status if user is logged in - if (sessionData?.user?.id) { - fetch('/api/user/subscription') - .then((res) => res.json()) - .then((data) => { - setPlan(data.isPro ? 'Pro Plan' : 'Free Plan') - }) - .catch((err) => { - console.error('Error fetching subscription status:', err) - }) - - // Fetch user's workspaces + const fetchWorkspaces = useCallback(async () => { setIsWorkspacesLoading(true) - fetch('/api/workspaces') - .then((res) => res.json()) - .then((data) => { - if (data.workspaces && Array.isArray(data.workspaces)) { - const fetchedWorkspaces = data.workspaces as Workspace[] - setWorkspaces(fetchedWorkspaces) - - // Find workspace that matches the active ID from registry or use first workspace + try { + const response = await fetch('/api/workspaces') + const data = await response.json() + + if (data.workspaces && Array.isArray(data.workspaces)) { + const fetchedWorkspaces = data.workspaces as Workspace[] + setWorkspaces(fetchedWorkspaces) + + // Only update workspace if we have a valid activeWorkspaceId from registry + if (activeWorkspaceId) { const matchingWorkspace = fetchedWorkspaces.find( (workspace) => workspace.id === activeWorkspaceId ) - const workspaceToActivate = matchingWorkspace || fetchedWorkspaces[0] - - // If we found a workspace, set it as active and update registry if needed - if (workspaceToActivate) { - setActiveWorkspace(workspaceToActivate) - - // If active workspace in UI doesn't match registry, update registry - if (workspaceToActivate.id !== activeWorkspaceId) { - setActiveWorkspaceId(workspaceToActivate.id) + if (matchingWorkspace) { + setActiveWorkspace(matchingWorkspace) + } else { + // Active workspace not found, fallback to first workspace + const fallbackWorkspace = fetchedWorkspaces[0] + if (fallbackWorkspace) { + setActiveWorkspace(fallbackWorkspace) + setActiveWorkspaceId(fallbackWorkspace.id) } } } - setIsWorkspacesLoading(false) - }) - .catch((err) => { - console.error('Error fetching workspaces:', err) - setIsWorkspacesLoading(false) - }) - } - }, [sessionData?.user?.id, activeWorkspaceId, setActiveWorkspaceId]) - - const switchWorkspace = (workspace: Workspace) => { - // If already on this workspace, do nothing - if (activeWorkspace?.id === workspace.id) { - setIsOpen(false) - return - } - - setActiveWorkspace(workspace) - setIsOpen(false) - - // Update the workflow registry store with the new active workspace - setActiveWorkspaceId(workspace.id) - - // Update URL to include workspace ID - router.push(`/w/${workspace.id}`) - } - - const handleCreateWorkspace = (name: string) => { - setIsWorkspacesLoading(true) - - fetch('/api/workspaces', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name }), - }) - .then((res) => res.json()) - .then((data) => { - if (data.workspace) { - const newWorkspace = data.workspace as Workspace - setWorkspaces((prev) => [...prev, newWorkspace]) - setActiveWorkspace(newWorkspace) - - // Update the workflow registry store with the new active workspace - setActiveWorkspaceId(newWorkspace.id) - - // Update URL to include new workspace ID - router.push(`/w/${newWorkspace.id}`) + // If no activeWorkspaceId, let loadWorkspaceFromWorkflowId handle workspace selection } + } catch (err) { + console.error('Error fetching workspaces:', err) + } finally { setIsWorkspacesLoading(false) - }) - .catch((err) => { - console.error('Error creating workspace:', err) - setIsWorkspacesLoading(false) - }) - } - - const handleUpdateWorkspace = async (id: string, name: string) => { - // Check if user has permission to update the workspace - const workspace = workspaces.find((w) => w.id === id) - if (!workspace || workspace.role !== 'owner') { - console.error('Permission denied: Only workspace owners can update workspaces') - return - } - - setIsWorkspacesLoading(true) - - try { - const response = await fetch(`/api/workspaces/${id}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ name }), - }) - - if (!response.ok) { - throw new Error('Failed to update workspace') } + }, [activeWorkspaceId, setActiveWorkspaceId]) - const { workspace } = await response.json() - - // Update workspaces list - setWorkspaces((prevWorkspaces) => - prevWorkspaces.map((w) => (w.id === workspace.id ? { ...w, name: workspace.name } : w)) - ) - - // If active workspace was updated, update it too - if (activeWorkspace?.id === workspace.id) { - setActiveWorkspace({ ...activeWorkspace, name: workspace.name } as Workspace) + useEffect(() => { + // Fetch subscription status if user is logged in + if (sessionData?.user?.id) { + fetchSubscriptionStatus(sessionData.user.id) + fetchWorkspaces() } - } catch (err) { - console.error('Error updating workspace:', err) - } finally { - setIsWorkspacesLoading(false) - } - } - - const handleDeleteWorkspace = async (id: string) => { - // Check if user has permission to delete the workspace - const workspace = workspaces.find((w) => w.id === id) - if (!workspace || workspace.role !== 'owner') { - console.error('Permission denied: Only workspace owners can delete workspaces') - return - } - - setIsDeleting(true) - - try { - const response = await fetch(`/api/workspaces/${id}`, { - method: 'DELETE', - }) + }, [sessionData?.user?.id, fetchSubscriptionStatus, fetchWorkspaces]) + + const switchWorkspace = useCallback( + (workspace: Workspace) => { + // If already on this workspace, do nothing + if (activeWorkspace?.id === workspace.id) { + setIsOpen(false) + return + } - if (!response.ok) { - throw new Error('Failed to delete workspace') - } + setActiveWorkspace(workspace) + setIsOpen(false) - // Remove from workspace list - const updatedWorkspaces = workspaces.filter((w) => w.id !== id) - setWorkspaces(updatedWorkspaces) + // Use full workspace switch which now handles localStorage automatically + switchToWorkspace(workspace.id) - // If deleted workspace was active, switch to another workspace - if (activeWorkspace?.id === id && updatedWorkspaces.length > 0) { - // Use the specialized method for handling workspace deletion - const newWorkspaceId = updatedWorkspaces[0].id - useWorkflowRegistry.getState().handleWorkspaceDeletion(newWorkspaceId) - setActiveWorkspace(updatedWorkspaces[0]) - } + // Update URL to include workspace ID + router.push(`/w/${workspace.id}`) + }, + [activeWorkspace?.id, switchToWorkspace, router] + ) + + const handleCreateWorkspace = useCallback( + async (name: string) => { + setIsWorkspacesLoading(true) + + try { + const response = await fetch('/api/workspaces', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name }), + }) + + const data = await response.json() + + if (data.workspace) { + const newWorkspace = data.workspace as Workspace + setWorkspaces((prev) => [...prev, newWorkspace]) + setActiveWorkspace(newWorkspace) + + // Use switchToWorkspace to properly load workflows for the new workspace + // This will clear existing workflows, set loading state, and fetch workflows from DB + switchToWorkspace(newWorkspace.id) + + // Update URL to include new workspace ID + router.push(`/w/${newWorkspace.id}`) + } + } catch (err) { + console.error('Error creating workspace:', err) + } finally { + setIsWorkspacesLoading(false) + } + }, + [switchToWorkspace, router] + ) + + const handleUpdateWorkspace = useCallback( + async (id: string, name: string) => { + // For update operations, we need to check permissions for the specific workspace + // Since we can only use hooks at the component level, we'll make the API call + // and let the backend handle the permission check + setIsWorkspacesLoading(true) + + try { + const response = await fetch(`/api/workspaces/${id}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name }), + }) + + if (!response.ok) { + if (response.status === 403) { + console.error( + 'Permission denied: Only users with admin permissions can update workspaces' + ) + } + throw new Error('Failed to update workspace') + } - setIsOpen(false) - } catch (err) { - console.error('Error deleting workspace:', err) - } finally { - setIsDeleting(false) - } - } + const { workspace: updatedWorkspace } = await response.json() - const openEditModal = (workspace: Workspace, e: React.MouseEvent) => { - e.stopPropagation() - // Check if user has permission to edit the workspace - if (workspace.role !== 'owner') { - console.error('Permission denied: Only workspace owners can edit workspaces') - return - } - setEditingWorkspace(workspace) - setIsEditModalOpen(true) - } + // Update workspaces list + setWorkspaces((prevWorkspaces) => + prevWorkspaces.map((w) => + w.id === updatedWorkspace.id ? { ...w, name: updatedWorkspace.name } : w + ) + ) + + // If active workspace was updated, update it too + if (activeWorkspace && activeWorkspace.id === updatedWorkspace.id) { + setActiveWorkspace({ + ...activeWorkspace, + name: updatedWorkspace.name, + }) + } + } catch (err) { + console.error('Error updating workspace:', err) + } finally { + setIsWorkspacesLoading(false) + } + }, + [activeWorkspace] + ) + + const handleDeleteWorkspace = useCallback( + async (id: string) => { + // For delete operations, we need to check permissions for the specific workspace + // Since we can only use hooks at the component level, we'll make the API call + // and let the backend handle the permission check + setIsDeleting(true) + + try { + const response = await fetch(`/api/workspaces/${id}`, { + method: 'DELETE', + }) + + if (!response.ok) { + if (response.status === 403) { + console.error( + 'Permission denied: Only users with admin permissions can delete workspaces' + ) + } + throw new Error('Failed to delete workspace') + } - // Determine URL for workspace links - const workspaceUrl = activeWorkspace ? `/w/${activeWorkspace.id}` : '/w' + // Remove from workspace list + const updatedWorkspaces = workspaces.filter((w) => w.id !== id) + setWorkspaces(updatedWorkspaces) - // Notify parent component when dropdown opens/closes - const handleDropdownOpenChange = (open: boolean) => { - setIsOpen(open) - // Inform the parent component about the dropdown state change - if (onDropdownOpenChange) { - onDropdownOpenChange(open) - } - } + // If deleted workspace was active, switch to another workspace + if (activeWorkspace?.id === id && updatedWorkspaces.length > 0) { + // Use the specialized method for handling workspace deletion + const newWorkspaceId = updatedWorkspaces[0].id + useWorkflowRegistry.getState().handleWorkspaceDeletion(newWorkspaceId) + setActiveWorkspace(updatedWorkspaces[0]) + } - // Special handling for click interactions in hover mode - const handleTriggerClick = (e: React.MouseEvent) => { - // When in hover mode, explicitly prevent bubbling for the trigger - if (mode === 'hover') { - e.stopPropagation() - e.preventDefault() - // Toggle dropdown state - handleDropdownOpenChange(!isOpen) - } - } + setIsOpen(false) + } catch (err) { + console.error('Error deleting workspace:', err) + } finally { + setIsDeleting(false) + } + }, + [workspaces, activeWorkspace?.id] + ) + + const openEditModal = useCallback( + (workspace: Workspace, e: React.MouseEvent) => { + e.stopPropagation() + // Only show edit/delete options for the active workspace if user has admin permissions + if (activeWorkspace?.id !== workspace.id || !userPermissions.canAdmin) { + return + } + setEditingWorkspace(workspace) + setIsEditModalOpen(true) + }, + [activeWorkspace?.id, userPermissions.canAdmin] + ) + + // Determine URL for workspace links + const workspaceUrl = useMemo( + () => (activeWorkspace ? `/w/${activeWorkspace.id}` : '/w'), + [activeWorkspace] + ) + + // Notify parent component when dropdown opens/closes + const handleDropdownOpenChange = useCallback( + (open: boolean) => { + setIsOpen(open) + // Inform the parent component about the dropdown state change + if (onDropdownOpenChange) { + onDropdownOpenChange(open) + } + }, + [onDropdownOpenChange] + ) + + // Special handling for click interactions in hover mode + const handleTriggerClick = useCallback( + (e: React.MouseEvent) => { + // When in hover mode, explicitly prevent bubbling for the trigger + if (mode === 'hover') { + e.stopPropagation() + e.preventDefault() + // Toggle dropdown state + handleDropdownOpenChange(!isOpen) + } + }, + [mode, isOpen, handleDropdownOpenChange] + ) + + const handleContainerClick = useCallback( + (e: React.MouseEvent) => { + // In hover mode, prevent clicks on the container from collapsing the sidebar + if (mode === 'hover') { + e.stopPropagation() + } + }, + [mode] + ) + + const handleWorkspaceModalOpenChange = useCallback((open: boolean) => { + setIsWorkspaceModalOpen(open) + }, []) + + const handleEditModalOpenChange = useCallback((open: boolean) => { + setIsEditModalOpen(open) + }, []) + + // Handle modal open/close state + useEffect(() => { + // Update the modal state in the store + setAnyModalOpen(isWorkspaceModalOpen || isEditModalOpen || isDeleting) + }, [isWorkspaceModalOpen, isEditModalOpen, isDeleting, setAnyModalOpen]) + + return ( +
+ {/* Workspace Modal */} + + + {/* Edit Workspace Modal */} + + + +
+ {/* Hover background with consistent padding - only when not collapsed */} + {!isCollapsed && ( +
+ )} - // Handle modal open/close state - useEffect(() => { - // Update the modal state in the store - setAnyModalOpen(isWorkspaceModalOpen || isEditModalOpen || isDeleting) - }, [isWorkspaceModalOpen, isEditModalOpen, isDeleting, setAnyModalOpen]) - - return ( -
- {/* Workspace Modal */} - - - {/* Edit Workspace Modal */} - - - -
{ - // In hover mode, prevent clicks on the container from collapsing the sidebar - if (mode === 'hover') { - e.stopPropagation() - } - }} - > - {/* Hover background with consistent padding - only when not collapsed */} - {!isCollapsed &&
} - - {/* Content with consistent padding */} - {isCollapsed ? ( -
- - - -
- ) : ( -
- -
+ -
- { - if (isOpen) e.preventDefault() - }} - > - - + + +
+ ) : ( +
+ +
+
+ { + if (isOpen) e.preventDefault() + }} + > + + + {isClientLoading || isWorkspacesLoading ? ( + + ) : ( +
+ + {activeWorkspace?.name || `${userName}'s Workspace`} + + +
+ )} +
+
+
+
+ )} +
+ +
+
+
+
+ +
+
{isClientLoading || isWorkspacesLoading ? ( - + <> + + + ) : ( -
- + <> + {activeWorkspace?.name || `${userName}'s Workspace`} - -
+ {plan} + )}
- - - {/* Plus button positioned absolutely */} - {!isCollapsed && ( -
- - -
- {isClientLoading ? ( - - ) : ( +
+
+ + + + {/* Workspaces list */} +
+
Workspaces
+ {isWorkspacesLoading ? ( +
+ +
+ ) : ( +
+ {workspaces.map((workspace) => ( + switchWorkspace(workspace)} + > + {workspace.name} + {userPermissions.canAdmin && activeWorkspace?.id === workspace.id && ( +
- )} -
- - New Workflow - + + + + + + + + Delete Workspace + + Are you sure you want to delete "{workspace.name}"? This action + cannot be undone. + + + + e.stopPropagation()}> + Cancel + + { + e.stopPropagation() + handleDeleteWorkspace(workspace.id) + }} + className='bg-destructive text-destructive-foreground hover:bg-destructive/90' + > + Delete + + + + +
+ )} + + ))}
)} -
- )} -
- -
-
-
-
- -
-
- {isClientLoading || isWorkspacesLoading ? ( - <> - - - - ) : ( - <> - - {activeWorkspace?.name || `${userName}'s Workspace`} - - {plan} - - )} -
-
-
-
- - - {/* Workspaces list */} -
-
Workspaces
- {isWorkspacesLoading ? ( -
- -
- ) : ( -
- {workspaces.map((workspace) => ( - switchWorkspace(workspace)} - > - {workspace.name} - {workspace.role === 'owner' && ( -
- - - - - - - - - Delete Workspace - - Are you sure you want to delete "{workspace.name}"? This action - cannot be undone. - - - - e.stopPropagation()}> - Cancel - - { - e.stopPropagation() - handleDeleteWorkspace(workspace.id) - }} - className='bg-destructive text-destructive-foreground hover:bg-destructive/90' - > - Delete - - - - -
- )} -
- ))} -
- )} + {/* Create new workspace button */} + setIsWorkspaceModalOpen(true)} + > + + New workspace + +
+
+ +
+ ) + } +) - {/* Create new workspace button */} - setIsWorkspaceModalOpen(true)} - > - + New workspace - -
- - -
- ) -} +WorkspaceHeader.displayName = 'WorkspaceHeader' diff --git a/apps/sim/app/w/components/sidebar/sidebar.tsx b/apps/sim/app/w/components/sidebar/sidebar.tsx index 7f755b764b3..e8485572e82 100644 --- a/apps/sim/app/w/components/sidebar/sidebar.tsx +++ b/apps/sim/app/w/components/sidebar/sidebar.tsx @@ -7,19 +7,26 @@ import { usePathname, useRouter } from 'next/navigation' import { Skeleton } from '@/components/ui/skeleton' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { useSession } from '@/lib/auth-client' +import { createLogger } from '@/lib/logs/console-logger' import { getKeyboardShortcutText, useGlobalShortcuts } from '@/app/w/hooks/use-keyboard-shortcuts' import { useSidebarStore } from '@/stores/sidebar/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import type { WorkflowMetadata } from '@/stores/workflows/registry/types' import { useRegistryLoading } from '../../hooks/use-registry-loading' +import { useUserPermissionsContext } from '../providers/workspace-permissions-provider' +import { CreateMenu } from './components/create-menu/create-menu' +import { FolderTree } from './components/folder-tree/folder-tree' import { HelpModal } from './components/help-modal/help-modal' import { InviteModal } from './components/invite-modal/invite-modal' import { NavSection } from './components/nav-section/nav-section' import { SettingsModal } from './components/settings-modal/settings-modal' import { SidebarControl } from './components/sidebar-control/sidebar-control' -import { WorkflowList } from './components/workflow-list/workflow-list' import { WorkspaceHeader } from './components/workspace-header/workspace-header' +const logger = createLogger('Sidebar') + +const IS_DEV = process.env.NODE_ENV === 'development' + export function Sidebar() { useRegistryLoading() useGlobalShortcuts() @@ -31,61 +38,34 @@ export function Sidebar() { isLoading: workflowsLoading, } = useWorkflowRegistry() const { isPending: sessionLoading } = useSession() + const userPermissions = useUserPermissionsContext() const isLoading = workflowsLoading || sessionLoading const router = useRouter() const pathname = usePathname() + const [showSettings, setShowSettings] = useState(false) const [showHelp, setShowHelp] = useState(false) const [showInviteMembers, setShowInviteMembers] = useState(false) - const [isDevEnvironment, setIsDevEnvironment] = useState(false) - const { - mode, - isExpanded, - toggleExpanded, - setMode, - workspaceDropdownOpen, - setWorkspaceDropdownOpen, - isAnyModalOpen, - setAnyModalOpen, - } = useSidebarStore() + const { mode, workspaceDropdownOpen, setWorkspaceDropdownOpen, isAnyModalOpen, setAnyModalOpen } = + useSidebarStore() const [isHovered, setIsHovered] = useState(false) const [explicitMouseEnter, setExplicitMouseEnter] = useState(false) useEffect(() => { - setIsDevEnvironment(process.env.NODE_ENV === 'development') - }, []) - - // Track when active workspace changes to ensure we refresh the UI - useEffect(() => { - if (activeWorkspaceId) { - // We don't need to do anything here, just force a re-render - // when activeWorkspaceId changes to ensure fresh data - } - }, [activeWorkspaceId]) - - // Update modal state in the store when settings or help modals open/close - useEffect(() => { - setAnyModalOpen(showSettings || showHelp || showInviteMembers) - }, [showSettings, showHelp, showInviteMembers, setAnyModalOpen]) - - // Reset explicit mouse enter state when modal state changes - useEffect(() => { - if (isAnyModalOpen) { + const anyModalIsOpen = showSettings || showHelp || showInviteMembers + setAnyModalOpen(anyModalIsOpen) + if (anyModalIsOpen) { setExplicitMouseEnter(false) } - }, [isAnyModalOpen]) + }, [showSettings, showHelp, showInviteMembers, setAnyModalOpen]) // Separate regular workflows from temporary marketplace workflows const { regularWorkflows, tempWorkflows } = useMemo(() => { const regular: WorkflowMetadata[] = [] const temp: WorkflowMetadata[] = [] - // Only process workflows when not in loading state if (!isLoading) { Object.values(workflows).forEach((workflow) => { - // Include workflows that either: - // 1. Belong to the active workspace, OR - // 2. Don't have a workspace ID (legacy workflows) if (workflow.workspaceId === activeWorkspaceId || !workflow.workspaceId) { if (workflow.marketplaceData?.status === 'temp') { temp.push(workflow) @@ -95,8 +75,8 @@ export function Sidebar() { } }) - // Sort regular workflows by last modified date (newest first) - regular.sort((a, b) => { + // Sort by last modified date (newest first) + const sortByLastModified = (a: WorkflowMetadata, b: WorkflowMetadata) => { const dateA = a.lastModified instanceof Date ? a.lastModified.getTime() @@ -106,45 +86,25 @@ export function Sidebar() { ? b.lastModified.getTime() : new Date(b.lastModified).getTime() return dateB - dateA - }) + } - // Sort temp workflows by last modified date (newest first) - temp.sort((a, b) => { - const dateA = - a.lastModified instanceof Date - ? a.lastModified.getTime() - : new Date(a.lastModified).getTime() - const dateB = - b.lastModified instanceof Date - ? b.lastModified.getTime() - : new Date(b.lastModified).getTime() - return dateB - dateA - }) + regular.sort(sortByLastModified) + temp.sort(sortByLastModified) } return { regularWorkflows: regular, tempWorkflows: temp } }, [workflows, isLoading, activeWorkspaceId]) - // Create workflow - const handleCreateWorkflow = async () => { + // Create workflow handler + const handleCreateWorkflow = async (folderId?: string) => { try { - // Import the isActivelyLoadingFromDB function to check sync status - const { isActivelyLoadingFromDB } = await import('@/stores/workflows/sync') - - // Prevent creating workflows during active DB operations - if (isActivelyLoadingFromDB()) { - console.log('Please wait, syncing in progress...') - return - } - - // Create the workflow and ensure it's associated with the active workspace - const id = createWorkflow({ + const id = await createWorkflow({ workspaceId: activeWorkspaceId || undefined, + folderId: folderId || undefined, }) - router.push(`/w/${id}`) } catch (error) { - console.error('Error creating workflow:', error) + logger.error('Error creating workflow:', error) } } @@ -155,7 +115,7 @@ export function Sidebar() { mode === 'collapsed' || (mode === 'hover' && ((!isHovered && !workspaceDropdownOpen) || isAnyModalOpen || !explicitMouseEnter)) - // Only show overlay effect when in hover mode and actually being hovered or dropdown is open + const showOverlay = mode === 'hover' && ((isHovered && !isAnyModalOpen && explicitMouseEnter) || workspaceDropdownOpen) @@ -165,8 +125,8 @@ export function Sidebar() { className={clsx( 'fixed inset-y-0 left-0 z-10 flex flex-col border-r bg-background transition-all duration-200 sm:flex', isCollapsed ? 'w-14' : 'w-60', - showOverlay ? 'shadow-lg' : '', - mode === 'hover' ? 'main-content-overlay' : '' + showOverlay && 'shadow-lg', + mode === 'hover' && 'main-content-overlay' )} onMouseEnter={() => { if (mode === 'hover' && !isAnyModalOpen) { @@ -179,12 +139,8 @@ export function Sidebar() { setIsHovered(false) } }} - style={{ - // When in hover mode and expanded, position above content without pushing it - position: showOverlay ? 'fixed' : 'fixed', - }} > - {/* Workspace Header - Fixed at top */} + {/* Workspace Header */}
- {/* Main navigation - Fixed at top below header */} - {/*
- - } - href="/w/1" - label="Home" - active={pathname === '/w/1'} - isCollapsed={isCollapsed} - /> - } - href="/w/templates" - label="Templates" - active={pathname === '/w/templates'} - isCollapsed={isCollapsed} - /> - } - href="/w/marketplace" - label="Marketplace" - active={pathname === '/w/marketplace'} - isCollapsed={isCollapsed} - /> - -
*/} - - {/* Scrollable Content Area - Contains Workflows and Logs/Settings */} + {/* Scrollable Content Area */}
{/* Workflows Section */}
-

- {isLoading ? ( - isCollapsed ? ( - '' - ) : ( - - ) - ) : isCollapsed ? ( - '' - ) : ( - 'Workflows' +

+ {isLoading ? : 'Workflows'} +

+ {!isCollapsed && !isLoading && ( + )} -

- +
- {/* Logs and Settings Navigation - Follows workflows */} + {/* Navigation Section */}
- {/* Push the bottom controls down when content is short */}
+ {/* Bottom Controls */} {isCollapsed ? (
- {/* Invite members button */} - {!isDevEnvironment && ( + {!IS_DEV && (
setShowInviteMembers(true)} - className='mx-auto flex h-8 w-8 cursor-pointer items-center justify-center rounded-md font-medium text-muted-foreground text-sm hover:bg-accent/50' + onClick={ + userPermissions.canAdmin ? () => setShowInviteMembers(true) : undefined + } + className={clsx( + 'mx-auto flex h-8 w-8 items-center justify-center rounded-md font-medium text-sm', + userPermissions.canAdmin + ? 'cursor-pointer text-muted-foreground hover:bg-accent/50' + : 'cursor-not-allowed text-muted-foreground/50' + )} >
- Invite Members + + {userPermissions.canAdmin + ? 'Invite Members' + : 'Admin permission required to invite members'} +
)} - {/* Help button */}
Help - {/* Sidebar control */} @@ -323,23 +258,36 @@ export function Sidebar() {
) : ( <> - {/* Invite members bar */} - {!isDevEnvironment && ( + {!IS_DEV && (
-
setShowInviteMembers(true)} - className='flex cursor-pointer items-center rounded-md px-2 py-1.5 font-medium text-muted-foreground text-sm hover:bg-accent/50' - > - - Invite members -
+ + +
setShowInviteMembers(true) : undefined + } + className={clsx( + 'flex items-center rounded-md px-2 py-1.5 font-medium text-sm', + userPermissions.canAdmin + ? 'cursor-pointer text-muted-foreground hover:bg-accent/50' + : 'cursor-not-allowed text-muted-foreground/50' + )} + > + + Invite members +
+
+ + {userPermissions.canAdmin + ? 'Invite new members to this workspace' + : 'Admin permission required to invite members'} + +
)} - {/* Bottom buttons container */}
- {/* Sidebar control on left with tooltip */} @@ -347,7 +295,6 @@ export function Sidebar() { Toggle sidebar - {/* Help button on right with tooltip */}
)} + {/* Modals */} - {!isDevEnvironment && ( - - )} + {!IS_DEV && } ) } diff --git a/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx b/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx index c81e847c374..79abac5ab47 100644 --- a/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx +++ b/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx @@ -177,7 +177,7 @@ export function WorkflowPreview({ config: blockConfig, name: block.name, blockState: block, - isReadOnly: true, + canEdit: false, isPreview: true, subBlockValues: subBlocksClone, }, @@ -207,7 +207,7 @@ export function WorkflowPreview({ showSubBlocks, isChild: true, parentId: blockId, - isReadOnly: true, + canEdit: false, isPreview: true, }, draggable: false, diff --git a/apps/sim/app/w/hooks/use-registry-loading.ts b/apps/sim/app/w/hooks/use-registry-loading.ts index 0ca7ba5134a..207514e18fd 100644 --- a/apps/sim/app/w/hooks/use-registry-loading.ts +++ b/apps/sim/app/w/hooks/use-registry-loading.ts @@ -1,27 +1,94 @@ 'use client' import { useEffect } from 'react' +import { usePathname, useRouter } from 'next/navigation' +import { createLogger } from '@/lib/logs/console-logger' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' +const logger = createLogger('UseRegistryLoading') + /** - * Custom hook to manage workflow registry loading state + * Extract workflow ID from pathname + * @param pathname - Current pathname + * @returns workflow ID if found, null otherwise + */ +function extractWorkflowIdFromPathname(pathname: string): string | null { + try { + const pathSegments = pathname.split('/') + // Check if URL matches pattern /w/{workflowId} + if (pathSegments.length >= 3 && pathSegments[1] === 'w') { + const workflowId = pathSegments[2] + // Basic UUID validation (36 characters, contains hyphens) + if (workflowId && workflowId.length === 36 && workflowId.includes('-')) { + return workflowId + } + } + return null + } catch (error) { + logger.warn('Failed to extract workflow ID from pathname:', error) + return null + } +} + +/** + * Custom hook to manage workflow registry loading state and handle first-time navigation * * This hook initializes the loading state and automatically clears it - * when workflows are loaded or after a timeout + * when workflows are loaded. It also handles smart workspace selection + * and navigation for first-time users. */ export function useRegistryLoading() { - const { workflows, setLoading } = useWorkflowRegistry() + const { workflows, setLoading, isLoading, activeWorkspaceId, loadWorkspaceFromWorkflowId } = + useWorkflowRegistry() + const pathname = usePathname() + const router = useRouter() + + // Handle workspace selection from URL + useEffect(() => { + if (!activeWorkspaceId) { + const workflowIdFromUrl = extractWorkflowIdFromPathname(pathname) + if (workflowIdFromUrl) { + loadWorkspaceFromWorkflowId(workflowIdFromUrl).catch((error) => { + logger.warn('Failed to load workspace from workflow ID:', error) + }) + } + } + }, [activeWorkspaceId, pathname, loadWorkspaceFromWorkflowId]) + // Handle first-time navigation: if we're at /w and have workflows, navigate to first one useEffect(() => { - // Set loading state initially - setLoading(true) + if (!isLoading && activeWorkspaceId && Object.keys(workflows).length > 0) { + const workflowCount = Object.keys(workflows).length + const currentWorkflowId = extractWorkflowIdFromPathname(pathname) + + // If we're at a generic workspace URL (/w, /w/, or /w/workspaceId) without a specific workflow + if ( + !currentWorkflowId && + (pathname === '/w' || pathname === '/w/' || pathname === `/w/${activeWorkspaceId}`) + ) { + const firstWorkflowId = Object.keys(workflows)[0] + logger.info('First-time navigation: redirecting to first workflow:', firstWorkflowId) + router.replace(`/w/${firstWorkflowId}`) + } + } + }, [isLoading, activeWorkspaceId, workflows, pathname, router]) + + // Handle loading states + useEffect(() => { + // Only set loading if we don't have workflows and aren't already loading + if (Object.keys(workflows).length === 0 && !isLoading) { + setLoading(true) + } // If workflows are already loaded, clear loading state - if (Object.keys(workflows).length > 0) { - setTimeout(() => setLoading(false), 300) + if (Object.keys(workflows).length > 0 && isLoading) { + setTimeout(() => setLoading(false), 100) return } + // Only create timeout if we're actually loading + if (!isLoading) return + // Create a timeout to clear loading state after max time const timeout = setTimeout(() => { setLoading(false) @@ -40,5 +107,5 @@ export function useRegistryLoading() { clearTimeout(timeout) clearInterval(checkInterval) } - }, [setLoading, workflows]) + }, [setLoading, workflows, isLoading]) } diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx b/apps/sim/app/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx index a231ff90f32..fcb04c42b83 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx +++ b/apps/sim/app/w/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx @@ -1,7 +1,7 @@ 'use client' import { useRef, useState } from 'react' -import { AlertCircle, FileText, Loader2, X } from 'lucide-react' +import { AlertCircle, Loader2, X } from 'lucide-react' import { AlertDialog, AlertDialogAction, @@ -13,7 +13,6 @@ import { AlertDialogTitle, } from '@/components/ui/alert-dialog' import { Button } from '@/components/ui/button' -import { Checkbox } from '@/components/ui/checkbox' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' @@ -38,7 +37,6 @@ export function CreateChunkModal({ onChunkCreated, }: CreateChunkModalProps) { const [content, setContent] = useState('') - const [enabled, setEnabled] = useState(true) const [isCreating, setIsCreating] = useState(false) const [error, setError] = useState(null) const [showUnsavedChangesAlert, setShowUnsavedChangesAlert] = useState(false) @@ -68,7 +66,7 @@ export function CreateChunkModal({ }, body: JSON.stringify({ content: content.trim(), - enabled, + enabled: true, }), } ) @@ -104,7 +102,6 @@ export function CreateChunkModal({ onOpenChange(false) // Reset form state when modal closes setContent('') - setEnabled(true) setError(null) setShowUnsavedChangesAlert(false) } @@ -148,11 +145,10 @@ export function CreateChunkModal({
-
-
- {/* Document Info */} +
+ {/* Document Info Section - Fixed at top */} +
-

{document?.filename || 'Unknown Document'} @@ -161,41 +157,6 @@ export function CreateChunkModal({

- {/* Content Input */} -
- -