diff --git a/apps/sim/.env.example b/apps/sim/.env.example new file mode 100644 index 00000000000..738e9760366 --- /dev/null +++ b/apps/sim/.env.example @@ -0,0 +1,19 @@ +# 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 + +# NextJS (Required) +NEXT_PUBLIC_APP_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)/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)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index 6a81c5ba228..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 '../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/(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..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/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/api/workspaces/invitations/accept/route.ts b/apps/sim/app/api/workspaces/invitations/accept/route.ts index 2b30618005a..560b36f68e7 100644 --- a/apps/sim/app/api/workspaces/invitations/accept/route.ts +++ b/apps/sim/app/api/workspaces/invitations/accept/route.ts @@ -149,7 +149,10 @@ export async function GET(req: NextRequest) { .where(eq(workspaceInvitation.id, invitation.id)) return NextResponse.redirect( - new URL(`/w/${invitation.workspaceId}`, env.NEXT_PUBLIC_APP_URL || 'https://simstudio.ai') + new URL( + `/workspace/${invitation.workspaceId}/w`, + env.NEXT_PUBLIC_APP_URL || 'https://simstudio.ai' + ) ) } @@ -194,7 +197,10 @@ export async function GET(req: NextRequest) { // Redirect to the workspace return NextResponse.redirect( - new URL(`/w/${invitation.workspaceId}`, env.NEXT_PUBLIC_APP_URL || 'https://simstudio.ai') + new URL( + `/workspace/${invitation.workspaceId}/w`, + env.NEXT_PUBLIC_APP_URL || 'https://simstudio.ai' + ) ) } catch (error) { console.error('Error accepting invitation:', error) 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/error.tsx b/apps/sim/app/w/error.tsx deleted file mode 100644 index adac0456b81..00000000000 --- a/apps/sim/app/w/error.tsx +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -import { NextError } from './[id]/components/error' - -export default NextError diff --git a/apps/sim/app/w/global-error.tsx b/apps/sim/app/w/global-error.tsx deleted file mode 100644 index 9c7bd975759..00000000000 --- a/apps/sim/app/w/global-error.tsx +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -import { NextGlobalError } from './[id]/components/error' - -export default NextGlobalError 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/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/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/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/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/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/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/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/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/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/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/w/knowledge/[id]/[documentId]/document.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx index 9758f46fa8e..fc25327f6db 100644 --- a/apps/sim/app/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/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/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/w/knowledge/[id]/[documentId]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/page.tsx diff --git a/apps/sim/app/w/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx similarity index 98% rename from apps/sim/app/w/knowledge/[id]/base.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx index 2b7ab83d394..eeffdb79e7d 100644 --- a/apps/sim/app/w/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspaceId]/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/[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' @@ -122,6 +122,8 @@ export function KnowledgeBase({ }: KnowledgeBaseProps) { const { mode, isExpanded } = useSidebarStore() const { removeKnowledgeBase } = useKnowledgeStore() + const params = useParams() + const workspaceId = params.workspaceId 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}/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}/knowledge`) } else { throw new Error(result.error || 'Failed to delete knowledge base') } @@ -741,7 +743,7 @@ export function KnowledgeBase({ { id: 'knowledge-root', label: 'Knowledge', - href: '/w/knowledge', + href: '/knowledge', }, { id: `knowledge-base-${id}`, @@ -760,7 +762,7 @@ export function KnowledgeBase({ { id: 'knowledge-root', label: 'Knowledge', - href: '/w/knowledge', + href: '/knowledge', }, { id: 'error', diff --git a/apps/sim/app/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/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/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/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/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/w/knowledge/[id]/page.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/page.tsx similarity index 100% rename from apps/sim/app/w/knowledge/[id]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/[id]/page.tsx diff --git a/apps/sim/app/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/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/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/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/w/knowledge/components/create-modal/create-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/components/create-modal/create-modal.tsx index 5fbfd6effa2..77bf98e8fb8 100644 --- a/apps/sim/app/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/w/knowledge/knowledge.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx similarity index 100% rename from apps/sim/app/w/knowledge/knowledge.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx diff --git a/apps/sim/app/w/knowledge/loading.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/loading.tsx similarity index 100% rename from apps/sim/app/w/knowledge/loading.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/loading.tsx diff --git a/apps/sim/app/w/knowledge/page.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/page.tsx similarity index 100% rename from apps/sim/app/w/knowledge/page.tsx rename to apps/sim/app/workspace/[workspaceId]/knowledge/page.tsx diff --git a/apps/sim/app/w/layout.tsx b/apps/sim/app/workspace/[workspaceId]/layout.tsx similarity index 79% rename from apps/sim/app/w/layout.tsx rename to apps/sim/app/workspace/[workspaceId]/layout.tsx index 42ac184a820..261b5d42224 100644 --- a/apps/sim/app/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/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/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/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/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/w/logs/components/filters/components/folder.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/folder.tsx similarity index 93% rename from apps/sim/app/w/logs/components/filters/components/folder.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/folder.tsx index 025e20a7193..bc7432758f7 100644 --- a/apps/sim/app/w/logs/components/filters/components/folder.tsx +++ b/apps/sim/app/workspace/[workspaceId]/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, @@ -8,9 +9,8 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' -import { useFilterStore } from '@/app/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/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.workspaceId 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/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/w/logs/components/filters/components/level.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/level.tsx index 78550907e93..c83706a5b40 100644 --- a/apps/sim/app/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/w/logs/stores/store' -import type { LogLevel } from '@/app/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/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/w/logs/components/filters/components/timeline.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/timeline.tsx index 39ae02fb0d1..0a475b6f1dc 100644 --- a/apps/sim/app/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/w/logs/stores/store' -import type { TimeRange } from '@/app/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/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/w/logs/components/filters/components/trigger.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/trigger.tsx index 760649d35be..1cabe0583c9 100644 --- a/apps/sim/app/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/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/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/w/logs/components/filters/components/workflow.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/components/workflow.tsx index d5f94b6de74..47081d31674 100644 --- a/apps/sim/app/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/w/logs/stores/store' +import { useFilterStore } from '@/app/workspace/[workspaceId]/logs/stores/store' interface WorkflowOption { id: string diff --git a/apps/sim/app/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/w/logs/components/filters/filters.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/filters/filters.tsx diff --git a/apps/sim/app/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/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/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/w/logs/components/sidebar/sidebar.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/components/sidebar/sidebar.tsx index a47131e42d5..65d070356b8 100644 --- a/apps/sim/app/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/w/logs/stores/types' -import { formatDate } from '@/app/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/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/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/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/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/w/logs/logs.tsx b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx similarity index 100% rename from apps/sim/app/w/logs/logs.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/logs.tsx diff --git a/apps/sim/app/w/logs/page.tsx b/apps/sim/app/workspace/[workspaceId]/logs/page.tsx similarity index 100% rename from apps/sim/app/w/logs/page.tsx rename to apps/sim/app/workspace/[workspaceId]/logs/page.tsx diff --git a/apps/sim/app/w/logs/stores/store.ts b/apps/sim/app/workspace/[workspaceId]/logs/stores/store.ts similarity index 100% rename from apps/sim/app/w/logs/stores/store.ts rename to apps/sim/app/workspace/[workspaceId]/logs/stores/store.ts diff --git a/apps/sim/app/w/logs/stores/types.ts b/apps/sim/app/workspace/[workspaceId]/logs/stores/types.ts similarity index 100% rename from apps/sim/app/w/logs/stores/types.ts rename to apps/sim/app/workspace/[workspaceId]/logs/stores/types.ts diff --git a/apps/sim/app/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/w/logs/utils/format-date.ts rename to apps/sim/app/workspace/[workspaceId]/logs/utils/format-date.ts diff --git a/apps/sim/app/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/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/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/w/marketplace/components/error-message.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/error-message.tsx diff --git a/apps/sim/app/w/marketplace/components/section.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/components/section.tsx similarity index 100% rename from apps/sim/app/w/marketplace/components/section.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/section.tsx diff --git a/apps/sim/app/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/w/marketplace/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/components/toolbar/toolbar.tsx diff --git a/apps/sim/app/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/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/w/marketplace/components/workflow-card.tsx b/apps/sim/app/workspace/[workspaceId]/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/[workspaceId]/marketplace/components/workflow-card.tsx index 82db83df0b7..76667b1d724 100644 --- a/apps/sim/app/w/marketplace/components/workflow-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/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/[workspaceId]/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.workspaceId 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/[workspaceId]/marketplace/constants/categories.tsx similarity index 100% rename from apps/sim/app/w/marketplace/constants/categories.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/constants/categories.tsx diff --git a/apps/sim/app/w/marketplace/marketplace.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/marketplace.tsx similarity index 100% rename from apps/sim/app/w/marketplace/marketplace.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/marketplace.tsx diff --git a/apps/sim/app/w/marketplace/page.tsx b/apps/sim/app/workspace/[workspaceId]/marketplace/page.tsx similarity index 100% rename from apps/sim/app/w/marketplace/page.tsx rename to apps/sim/app/workspace/[workspaceId]/marketplace/page.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/page.tsx b/apps/sim/app/workspace/[workspaceId]/page.tsx new file mode 100644 index 00000000000..bd93acadf88 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/page.tsx @@ -0,0 +1,10 @@ +import { redirect } from 'next/navigation' + +export default async function WorkspacePage({ + params, +}: { + params: Promise<{ workspaceId: string }> +}) { + const { workspaceId } = await params + redirect(`/workspace/${workspaceId}/w`) +} diff --git a/apps/sim/app/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/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/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/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 ef4b60ed270..f680c2ffa99 100644 --- a/apps/sim/app/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/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/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/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/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/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/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/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/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/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/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/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/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 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/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx index f8a794b7fd1..5f98febf4ce 100644 --- a/apps/sim/app/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/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/[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/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/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 af068534848..8595d333f88 100644 --- a/apps/sim/app/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/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/[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/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 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/[workspaceId]/w/[workflowId]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx index 187c4fe10e9..500eac1ff38 100644 --- a/apps/sim/app/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 @@ -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/[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/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/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/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/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/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/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/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/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/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 99% rename from apps/sim/app/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 index 3d64dcc06f2..7b7bdb59687 100644 --- a/apps/sim/app/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 @@ -35,7 +35,7 @@ import { getCategoryColor, getCategoryIcon, getCategoryLabel, -} from '@/app/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/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/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/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/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/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/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/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/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/w/[id]/components/control-bar/control-bar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/control-bar.tsx similarity index 92% rename from apps/sim/app/w/[id]/components/control-bar/control-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/control-bar.tsx index 5da2dc64df6..eb8fa54c308 100644 --- a/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/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,8 +40,9 @@ 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/[workspaceId]/w/components/providers/workspace-permissions-provider' import { useExecutionStore } from '@/stores/execution/store' +import { useFolderStore } from '@/stores/folders/store' import { useNotificationStore } from '@/stores/notifications/store' import { usePanelStore } from '@/stores/panel/store' import { useGeneralStore } from '@/stores/settings/general/store' @@ -84,6 +85,8 @@ interface ControlBarProps { export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { const router = useRouter() const { data: session } = useSession() + const params = useParams() + const workspaceId = params.workspaceId as string // Store hooks const { @@ -100,7 +103,6 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { workflows, updateWorkflow, activeWorkflowId, - activeWorkspaceId, removeWorkflow, duplicateWorkflow, setDeploymentStatus, @@ -108,6 +110,7 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { } = useWorkflowRegistry() const { isExecuting, handleRunWorkflow } = useWorkflowExecution() const { setActiveTab } = usePanelStore() + const { getFolderTree, expandedFolders } = useFolderStore() // Get current workflow and workspace ID for permissions const currentWorkflow = activeWorkflowId ? workflows[activeWorkflowId] : null @@ -399,33 +402,82 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { } } + /** + * Get workflows in the exact order they appear in the sidebar + */ + const getSidebarOrderedWorkflows = () => { + // Get and sort regular workflows by last modified (newest first) + const regularWorkflows = Object.values(workflows) + .filter((workflow) => workflow.workspaceId === workspaceId) + .filter((workflow) => workflow.marketplaceData?.status !== '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 + }) + + // Group workflows by folder + const workflowsByFolder = regularWorkflows.reduce( + (acc, workflow) => { + const folderId = workflow.folderId || 'root' + if (!acc[folderId]) acc[folderId] = [] + acc[folderId].push(workflow) + return acc + }, + {} as Record + ) + + const orderedWorkflows: typeof regularWorkflows = [] + + // Recursively collect workflows from expanded folders + const collectFromFolders = (folders: ReturnType) => { + folders.forEach((folder) => { + if (expandedFolders.has(folder.id)) { + orderedWorkflows.push(...(workflowsByFolder[folder.id] || [])) + if (folder.children.length > 0) { + collectFromFolders(folder.children) + } + } + }) + } + + // Get workflows from expanded folders first, then root workflows + if (workspaceId) collectFromFolders(getFolderTree(workspaceId)) + orderedWorkflows.push(...(workflowsByFolder.root || [])) + + return orderedWorkflows + } + /** * Handle deleting the current workflow */ const handleDeleteWorkflow = () => { if (!activeWorkflowId || !userPermissions.canEdit) return - const workflowIds = Object.keys(workflows) - const currentIndex = workflowIds.indexOf(activeWorkflowId) + const sidebarWorkflows = getSidebarOrderedWorkflows() + const currentIndex = sidebarWorkflows.findIndex((w) => w.id === 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] + // Find next workflow: try next, then previous + let nextWorkflowId: string | null = null + if (sidebarWorkflows.length > 1) { + if (currentIndex < sidebarWorkflows.length - 1) { + nextWorkflowId = sidebarWorkflows[currentIndex + 1].id } else if (currentIndex > 0) { - nextWorkflowId = workflowIds[currentIndex - 1] - } else { - nextWorkflowId = workflowIds.find((id) => id !== activeWorkflowId) || null + nextWorkflowId = sidebarWorkflows[currentIndex - 1].id } } - // Navigate to the next workflow or home + // Navigate to next workflow or workspace home if (nextWorkflowId) { - router.push(`/w/${nextWorkflowId}`) + router.push(`/workspace/${workspaceId}/w/${nextWorkflowId}`) } else { - router.push('/') + router.push(`/workspace/${workspaceId}`) } // Remove the workflow from the registry @@ -573,8 +625,17 @@ export function ControlBar({ hasValidationErrors = false }: ControlBarProps) { const handleDuplicateWorkflow = async () => { if (!activeWorkflowId || !userPermissions.canEdit) return - // Duplicate the workflow - no automatic navigation - await duplicateWorkflow(activeWorkflowId) + try { + const newWorkflow = await duplicateWorkflow(activeWorkflowId) + if (newWorkflow) { + router.push(`/workspace/${workspaceId}/w/${newWorkflow}`) + } else { + addNotification('error', 'Failed to duplicate workflow', activeWorkflowId) + } + } catch (error) { + logger.error('Error duplicating workflow:', { error }) + addNotification('error', 'Failed to duplicate workflow', activeWorkflowId) + } } /** diff --git a/apps/sim/app/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/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/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/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/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/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/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/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/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/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/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 94% rename from apps/sim/app/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 index 9625cb5f611..14f5343666f 100644 --- a/apps/sim/app/w/[id]/components/loop-node/loop-node.test.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/loop-node/loop-node.test.tsx @@ -2,7 +2,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { useWorkflowStore } from '@/stores/workflows/workflow/store' import { LoopNodeComponent } from './loop-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 }), })) @@ -60,7 +56,6 @@ vi.mock('@/lib/utils', () => ({ cn: (...classes: any[]) => classes.filter(Boolean).join(' '), })) -// Mock the LoopBadges component vi.mock('./components/loop-badges', () => ({ LoopBadges: ({ loopId }: any) => ({ loopId }), })) @@ -87,8 +82,6 @@ describe('LoopNodeComponent', () => { beforeEach(() => { vi.clearAllMocks() - // Mock useWorkflowStore - ;(useWorkflowStore as any).mockImplementation((selector: any) => { const state = { removeBlock: mockRemoveBlock, @@ -96,7 +89,6 @@ describe('LoopNodeComponent', () => { return selector(state) }) - // Mock getNodes mockGetNodes.mockReturnValue([]) }) @@ -111,14 +103,12 @@ describe('LoopNodeComponent', () => { }) it('should be a memoized component', () => { - // Since we mocked memo to return the component as-is, we can verify it exists expect(LoopNodeComponent).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: 'loopNode' as const, @@ -135,9 +125,7 @@ describe('LoopNodeComponent', () => { dragging: false, } - // This tests that TypeScript compilation succeeds with these props expect(() => { - // We're not calling the component, just verifying the types const _component: typeof LoopNodeComponent = LoopNodeComponent expect(_component).toBeDefined() }).not.toThrow() @@ -163,10 +151,8 @@ describe('LoopNodeComponent', () => { describe('Store Integration', () => { it('should integrate with workflow store', () => { - // Test that the component uses the store correctly expect(useWorkflowStore).toBeDefined() - // Verify the store selector function works const mockState = { removeBlock: mockRemoveBlock } const selector = vi.fn((state) => state.removeBlock) @@ -181,7 +167,6 @@ describe('LoopNodeComponent', () => { expect(mockRemoveBlock).toBeDefined() expect(typeof mockRemoveBlock).toBe('function') - // Test calling removeBlock mockRemoveBlock('test-id') expect(mockRemoveBlock).toHaveBeenCalledWith('test-id') }) @@ -189,7 +174,6 @@ describe('LoopNodeComponent', () => { describe('Component Logic Tests', () => { it('should handle nesting level calculation logic', () => { - // Test the nesting level calculation logic const testCases = [ { nodes: [], parentId: undefined, expectedLevel: 0 }, { nodes: [{ id: 'parent', data: {} }], parentId: 'parent', expectedLevel: 1 }, diff --git a/apps/sim/app/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/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/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/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/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/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/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/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/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/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 31b887312a2..f0b8d9498a2 100644 --- a/apps/sim/app/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/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/[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/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/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/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/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/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/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/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/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/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/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/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/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/w/[id]/components/panel/panel.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/panel/panel.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx index 7afc5e3eb1e..27494712dc0 100644 --- a/apps/sim/app/w/[id]/components/panel/panel.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/components/skeleton-loading/skeleton-loading.tsx similarity index 99% rename from apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/skeleton-loading/skeleton-loading.tsx index 141700a1ec2..de8e90cdfab 100644 --- a/apps/sim/app/w/[id]/components/skeleton-loading/skeleton-loading.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/skeleton-loading/skeleton-loading.tsx @@ -5,7 +5,6 @@ import { Button } from '@/components/ui/button' import { Skeleton } from '@/components/ui/skeleton' import { useSidebarStore } from '@/stores/sidebar/store' -// Skeleton Components const SkeletonControlBar = () => { return (
diff --git a/apps/sim/app/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/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/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/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/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/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/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/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/w/[id]/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/toolbar.tsx similarity index 95% rename from apps/sim/app/w/[id]/components/toolbar/toolbar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/toolbar.tsx index 8d86f8407f5..177413e6ed7 100644 --- a/apps/sim/app/w/[id]/components/toolbar/toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/components/providers/workspace-permissions-provider' import { getAllBlocks, getBlocksByCategory } from '@/blocks' import type { BlockCategory } from '@/blocks/types' import { useSidebarStore } from '@/stores/sidebar/store' @@ -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.workspaceId 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/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/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/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 97% rename from apps/sim/app/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 baf322f53e7..b9f17f57024 100644 --- a/apps/sim/app/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 @@ -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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/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/[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/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/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/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/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/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 d47adca2d8e..a228efb1714 100644 --- a/apps/sim/app/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 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/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/folder-selector/folder-selector.tsx index 2a0d9990eab..31abe42a2b3 100644 --- a/apps/sim/app/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 aee40413bec..84f74fc0833 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/[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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 a23eb809d83..3168af8fbfe 100644 --- a/apps/sim/app/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/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/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/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 cb584d2e751..4bb03e252f1 100644 --- a/apps/sim/app/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/w/[id]/components/workflow-block/workflow-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx index 90be7d0fa0e..0ffb7258664 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/workflow-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/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/[workspaceId]/w/components/providers/workspace-permissions-provider' import type { BlockConfig, SubBlockConfig } from '@/blocks/types' import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow' import { useExecutionStore } from '@/stores/execution/store' diff --git a/apps/sim/app/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/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/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/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/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/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/w/[id]/hooks/use-presence.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-presence.ts similarity index 97% rename from apps/sim/app/w/[id]/hooks/use-presence.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-presence.ts index 972f000faf9..2e3b1a5f8ab 100644 --- a/apps/sim/app/w/[id]/hooks/use-presence.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-presence.ts @@ -3,7 +3,7 @@ import { useMemo } from 'react' import { useSocket } from '@/contexts/socket-context' -interface PresenceUser { +type PresenceUser = { connectionId: string | number name?: string color?: string diff --git a/apps/sim/app/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/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/w/[id]/layout.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/layout.tsx similarity index 100% rename from apps/sim/app/w/[id]/layout.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/layout.tsx diff --git a/apps/sim/app/w/[id]/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/page.tsx similarity index 100% rename from apps/sim/app/w/[id]/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/page.tsx diff --git a/apps/sim/app/w/[id]/utils.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils.ts similarity index 100% rename from apps/sim/app/w/[id]/utils.ts rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils.ts diff --git a/apps/sim/app/w/[id]/workflow.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx similarity index 96% rename from apps/sim/app/w/[id]/workflow.tsx rename to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx index 68a38d78d1d..72606e7f03a 100644 --- a/apps/sim/app/w/[id]/workflow.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx @@ -11,12 +11,16 @@ import ReactFlow, { useReactFlow, } from '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 { ControlBar } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/control-bar' +import { ErrorBoundary } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/error/index' +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 { Panel } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel' +import { ParallelNodeComponent } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/parallel-node/parallel-node' +import { SkeletonLoading } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/skeleton-loading/skeleton-loading' +import { Toolbar } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/toolbar/toolbar' +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' @@ -26,14 +30,8 @@ import { useNotificationStore } from '@/stores/notifications/store' import { useVariablesStore } from '@/stores/panel/variables/store' import { useGeneralStore } from '@/stores/settings/general/store' import { useSidebarStore } from '@/stores/sidebar/store' -// Removed sync manager import - Socket.IO handles real-time sync import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' -import { ControlBar } from './components/control-bar/control-bar' -import { ErrorBoundary } from './components/error/index' -import { Panel } from './components/panel/panel' -import { SkeletonLoading } from './components/skeleton-loading/skeleton-loading' -import { Toolbar } from './components/toolbar/toolbar' import { WorkflowBlock } from './components/workflow-block/workflow-block' import { WorkflowEdge } from './components/workflow-edge/workflow-edge' import { @@ -95,7 +93,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() @@ -806,7 +804,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) { @@ -832,13 +830,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) { @@ -849,14 +847,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 } @@ -877,7 +875,7 @@ const WorkflowContent = React.memo(() => { validateAndNavigate() }, [ - params.id, + params.workflowId, workflows, isLoading, setActiveWorkflow, @@ -1033,6 +1031,11 @@ const WorkflowContent = React.memo(() => { validateNestedSubflows() }, [blocks, validateNestedSubflows]) + // Validate nested subflows whenever blocks change + useEffect(() => { + validateNestedSubflows() + }, [blocks, validateNestedSubflows]) + // Update edges const onEdgesChange = useCallback( (changes: any) => { @@ -1473,7 +1476,7 @@ const WorkflowContent = React.memo(() => {
@@ -1489,12 +1492,12 @@ const WorkflowContent = React.memo(() => { return (
-
+
0} />
diff --git a/apps/sim/app/w/components/providers/providers.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/providers/providers.tsx similarity index 100% rename from apps/sim/app/w/components/providers/providers.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/providers/providers.tsx diff --git a/apps/sim/app/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/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/w/components/providers/workspace-permissions-provider.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider.tsx similarity index 86% rename from apps/sim/app/w/components/providers/workspace-permissions-provider.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider.tsx index 77b4dfbf5d8..9ebbd4286e8 100644 --- a/apps/sim/app/w/components/providers/workspace-permissions-provider.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider.tsx @@ -1,12 +1,15 @@ 'use client' import React, { createContext, useContext, useMemo } from 'react' +import { useParams } from 'next/navigation' +import { createLogger } from '@/lib/logs/console-logger' 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' + +const logger = createLogger('WorkspacePermissionsProvider') interface WorkspacePermissionsContextType { // Raw workspace permissions data @@ -27,17 +30,20 @@ interface WorkspacePermissionsProviderProps { const WorkspacePermissionsProvider = React.memo( ({ children }) => { - const { activeWorkspaceId } = useWorkflowRegistry() + const params = useParams() + const workspaceId = params.workspaceId as string + + if (!workspaceId) { + logger.warn('Workspace ID is undefined from params:', params) + } - // Fetch workspace permissions once const { permissions: workspacePermissions, loading: permissionsLoading, error: permissionsError, updatePermissions, - } = useWorkspacePermissions(activeWorkspaceId) + } = useWorkspacePermissions(workspaceId) - // Compute user permissions based on workspace permissions const userPermissions = useUserPermissions( workspacePermissions, permissionsLoading, diff --git a/apps/sim/app/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 94% rename from apps/sim/app/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 5ff60db8657..188ee91ea8d 100644 --- a/apps/sim/app/w/components/sidebar/components/create-menu/create-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/create-menu/create-menu.tsx @@ -1,7 +1,9 @@ 'use client' import { useState } from 'react' +import { logger } from '@sentry/nextjs' import { File, Folder, Plus } 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' @@ -9,7 +11,6 @@ import { Label } from '@/components/ui/label' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { cn } from '@/lib/utils' import { useFolderStore } from '@/stores/folders/store' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' interface CreateMenuProps { onCreateWorkflow: (folderId?: string) => void @@ -22,7 +23,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.workspaceId as string const { createFolder } = useFolderStore() const handleCreateWorkflow = () => { @@ -37,18 +39,18 @@ 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) } catch (error) { - console.error('Failed to create folder:', error) + logger.error('Failed to create folder:', { error }) } finally { setIsCreating(false) } diff --git a/apps/sim/app/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 93% rename from apps/sim/app/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 fcda8a79bec..08cebccd299 100644 --- a/apps/sim/app/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 @@ -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 { @@ -13,8 +14,10 @@ import { } from '@/components/ui/dropdown-menu' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' +import { createLogger } from '@/lib/logs/console-logger' import { useFolderStore } from '@/stores/folders/store' -import { useWorkflowRegistry } from '@/stores/workflows/registry/store' + +const logger = createLogger('FolderContextMenu') interface FolderContextMenuProps { folderId: string @@ -37,8 +40,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.workspaceId as string - const { activeWorkspaceId } = useWorkflowRegistry() const { createFolder, updateFolder, deleteFolder } = useFolderStore() const handleCreateWorkflow = () => { @@ -59,25 +63,25 @@ 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('') setShowSubfolderDialog(false) } catch (error) { - console.error('Failed to create subfolder:', error) + logger.error('Failed to create subfolder:', { error }) } finally { setIsCreating(false) } diff --git a/apps/sim/app/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 94% rename from apps/sim/app/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 db9ffe073a2..5d0accc0e3d 100644 --- a/apps/sim/app/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 @@ -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, @@ -14,9 +15,12 @@ import { AlertDialogTitle, } from '@/components/ui/alert-dialog' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' +import { createLogger } from '@/lib/logs/console-logger' import { type FolderTreeNode, useFolderStore } from '@/stores/folders/store' import { FolderContextMenu } from '../../folder-context-menu/folder-context-menu' +const logger = createLogger('FolderItem') + interface FolderItemProps { folder: FolderTreeNode isCollapsed?: boolean @@ -39,7 +43,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.workspaceId as string const isExpanded = expandedFolders.has(folder.id) const updateTimeoutRef = useRef | undefined>(undefined) const pendingStateRef = useRef(null) @@ -76,7 +81,7 @@ export function FolderItem({ try { await updateFolderAPI(folderId, { name: newName }) } catch (error) { - console.error('Failed to rename folder:', error) + logger.error('Failed to rename folder:', { error }) } } @@ -87,10 +92,10 @@ 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) + logger.error('Failed to delete folder:', { error }) } finally { setIsDeleting(false) } diff --git a/apps/sim/app/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 91% rename from apps/sim/app/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 07bf393d9bb..f054a4ca7a7 100644 --- a/apps/sim/app/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 @@ -3,10 +3,14 @@ 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 { createLogger } from '@/lib/logs/console-logger' import { useFolderStore, useIsWorkflowSelected } from '@/stores/folders/store' import type { WorkflowMetadata } from '@/stores/workflows/registry/types' +const logger = createLogger('WorkflowItem') + interface WorkflowItemProps { workflow: WorkflowMetadata active: boolean @@ -26,6 +30,8 @@ export function WorkflowItem({ }: WorkflowItemProps) { const [isDragging, setIsDragging] = useState(false) const dragStartedRef = useRef(false) + const params = useParams() + const workspaceId = params.workspaceId as string const { selectedWorkflows, selectOnly, toggleWorkflowSelection } = useFolderStore() const isSelected = useIsWorkflowSelected(workflow.id) @@ -74,7 +80,7 @@ export function WorkflowItem({ { - 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( @@ -255,7 +258,7 @@ export function FolderTree({ - 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/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/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/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/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/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 98% rename from apps/sim/app/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 fd28d8d910f..ff51008450e 100644 --- a/apps/sim/app/w/components/sidebar/components/invite-modal/invite-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/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' @@ -15,10 +16,9 @@ import { cn } from '@/lib/utils' import { useUserPermissionsContext, useWorkspacePermissionsContext, -} from '@/app/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' -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.workspaceId 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/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 96% rename from apps/sim/app/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 dc04a9e719c..12ff428a0f5 100644 --- a/apps/sim/app/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 @@ -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.workspaceId 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/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/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/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/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/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/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/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 99% rename from apps/sim/app/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 index da4faef5dc4..21ad99b186b 100644 --- a/apps/sim/app/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 @@ -172,10 +172,10 @@ export function Credentials({ onOpenChange }: CredentialsProps) { } // Clear the URL parameters - router.replace('/w') + router.replace('/workspace') } else if (error) { logger.error('OAuth error:', { error }) - router.replace('/w') + router.replace('/workspace') } }, [searchParams, router, userId]) diff --git a/apps/sim/app/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 87% rename from apps/sim/app/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 bf4e067eb8f..c54e7d73e94 100644 --- a/apps/sim/app/w/components/sidebar/components/workflow-list/workflow-list.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/workflow-list.tsx @@ -3,10 +3,9 @@ import { useMemo } from 'react' import clsx from 'clsx' import Link from 'next/link' -import { usePathname } from 'next/navigation' +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 { @@ -17,9 +16,12 @@ interface WorkflowItemProps { } function WorkflowItem({ workflow, active, isMarketplace, isCollapsed }: WorkflowItemProps) { + const params = useParams() + const workspaceId = params.workspaceId as string + return ( ))} @@ -121,7 +124,7 @@ export function WorkflowList({ @@ -132,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/w/components/sidebar/components/workspace-header/workspace-header.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx similarity index 93% rename from apps/sim/app/w/components/sidebar/components/workspace-header/workspace-header.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/workspace-header.tsx index 4f9351d0154..3d67c0087d6 100644 --- a/apps/sim/app/w/components/sidebar/components/workspace-header/workspace-header.tsx +++ b/apps/sim/app/workspace/[workspaceId]/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, @@ -28,11 +28,14 @@ import { import { Input } from '@/components/ui/input' import { Skeleton } from '@/components/ui/skeleton' 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/[workspaceId]/w/components/providers/workspace-permissions-provider' import { useSidebarStore } from '@/stores/sidebar/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' +const logger = createLogger('WorkspaceHeader') + interface Workspace { id: string name: string @@ -254,7 +257,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.workspaceId as string // Get user permissions for the active workspace const userPermissions = useUserPermissionsContext() @@ -275,7 +280,7 @@ export const WorkspaceHeader = React.memo( const data = await response.json() setPlan(data.isPro ? 'Pro Plan' : 'Free Plan') } catch (err) { - console.error('Error fetching subscription status:', err) + logger.error('Error fetching subscription status:', err) } }, []) @@ -289,30 +294,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 + 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) - setActiveWorkspaceId(fallbackWorkspace.id) + // 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') } } } - // If no activeWorkspaceId, let loadWorkspaceFromWorkflowId handle workspace selection } } catch (err) { - console.error('Error fetching workspaces:', err) + logger.error('Error fetching workspaces:', err) } finally { setIsWorkspacesLoading(false) } - }, [activeWorkspaceId, setActiveWorkspaceId]) + }, [currentWorkspaceId, router]) useEffect(() => { // Fetch subscription status if user is logged in @@ -337,7 +348,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,10 +378,10 @@ 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) + logger.error('Error creating workspace:', err) } finally { setIsWorkspacesLoading(false) } @@ -396,7 +407,7 @@ export const WorkspaceHeader = React.memo( if (!response.ok) { if (response.status === 403) { - console.error( + logger.error( 'Permission denied: Only users with admin permissions can update workspaces' ) } @@ -420,7 +431,7 @@ export const WorkspaceHeader = React.memo( }) } } catch (err) { - console.error('Error updating workspace:', err) + logger.error('Error updating workspace:', err) } finally { setIsWorkspacesLoading(false) } @@ -442,7 +453,7 @@ export const WorkspaceHeader = React.memo( if (!response.ok) { if (response.status === 403) { - console.error( + logger.error( 'Permission denied: Only users with admin permissions can delete workspaces' ) } @@ -463,7 +474,7 @@ export const WorkspaceHeader = React.memo( setIsOpen(false) } catch (err) { - console.error('Error deleting workspace:', err) + logger.error('Error deleting workspace:', err) } finally { setIsDeleting(false) } @@ -486,7 +497,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/[workspaceId]/w/components/sidebar/sidebar.tsx similarity index 91% rename from apps/sim/app/w/components/sidebar/sidebar.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx index e8485572e82..f1557a64796 100644 --- a/apps/sim/app/w/components/sidebar/sidebar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/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/[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' @@ -31,16 +34,13 @@ 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 const router = useRouter() + const params = useParams() + const workspaceId = params.workspaceId as string const pathname = usePathname() const [showSettings, setShowSettings] = useState(false) @@ -66,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 { @@ -93,16 +93,16 @@ export function Sidebar() { } return { regularWorkflows: regular, tempWorkflows: temp } - }, [workflows, isLoading, activeWorkspaceId]) + }, [workflows, isLoading, workspaceId]) // Create workflow handler 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) } @@ -154,10 +154,10 @@ export function Sidebar() { {/* Workflows Section */}

{isLoading ? : 'Workflows'}

@@ -179,18 +179,18 @@ export function Sidebar() { } - href='/w/logs' + href={`/workspace/${workspaceId}/logs`} label='Logs' - active={pathname === '/w/logs'} + active={pathname === `/workspace/${workspaceId}/logs`} isCollapsed={isCollapsed} shortcutCommand={getKeyboardShortcutText('L', true, true)} shortcutCommandPosition='below' /> } - href='/w/knowledge' + href={`/workspace/${workspaceId}/knowledge`} label='Knowledge' - active={pathname === '/w/knowledge'} + active={pathname === `/workspace/${workspaceId}/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/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx similarity index 93% rename from apps/sim/app/w/components/workflow-preview/workflow-preview.tsx rename to apps/sim/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview.tsx index 79abac5ab47..ff6a7c2e97a 100644 --- a/apps/sim/app/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/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/[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/w/hooks/use-keyboard-shortcuts.ts b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts similarity index 89% rename from apps/sim/app/w/hooks/use-keyboard-shortcuts.ts rename to apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts index 9f49d8a1818..70d418eb620 100644 --- a/apps/sim/app/w/hooks/use-keyboard-shortcuts.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-keyboard-shortcuts.ts @@ -95,7 +95,16 @@ export function useGlobalShortcuts() { ((isMac && event.metaKey) || (!isMac && event.ctrlKey)) ) { event.preventDefault() - router.push('/w/logs') + + const pathParts = window.location.pathname.split('/') + const workspaceIndex = pathParts.indexOf('workspace') + + if (workspaceIndex !== -1 && pathParts[workspaceIndex + 1]) { + const workspaceId = pathParts[workspaceIndex + 1] + router.push(`/workspace/${workspaceId}/logs`) + } else { + router.push('/workspace') + } } } diff --git a/apps/sim/app/w/hooks/use-registry-loading.ts b/apps/sim/app/workspace/[workspaceId]/w/hooks/use-registry-loading.ts similarity index 69% rename from apps/sim/app/w/hooks/use-registry-loading.ts rename to apps/sim/app/workspace/[workspaceId]/w/hooks/use-registry-loading.ts index 207514e18fd..239a7148dbe 100644 --- a/apps/sim/app/w/hooks/use-registry-loading.ts +++ b/apps/sim/app/workspace/[workspaceId]/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' @@ -34,44 +34,41 @@ 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.workspaceId 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) - // 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/`) && + 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]) + }, [isLoading, workspaceId, workflows, pathname, router]) // Handle loading states useEffect(() => { diff --git a/apps/sim/app/w/page.tsx b/apps/sim/app/workspace/[workspaceId]/w/page.tsx similarity index 70% rename from apps/sim/app/w/page.tsx rename to apps/sim/app/workspace/[workspaceId]/w/page.tsx index fea6f1d2df9..998bd9a27b8 100644 --- a/apps/sim/app/w/page.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/page.tsx @@ -1,12 +1,15 @@ 'use client' import { useEffect } from 'react' -import { useRouter } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' +import { LoadingAgent } from '@/components/ui/loading-agent' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' export default function WorkflowsPage() { const router = useRouter() const { workflows, isLoading } = useWorkflowRegistry() + const params = useParams() + const workspaceId = params.workspaceId useEffect(() => { // Wait for workflows to load @@ -16,7 +19,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,14 +27,15 @@ 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 (
-
-

Loading workflows...

+
+ +
) diff --git a/apps/sim/app/workspace/page.tsx b/apps/sim/app/workspace/page.tsx new file mode 100644 index 00000000000..d6d6b54e62b --- /dev/null +++ b/apps/sim/app/workspace/page.tsx @@ -0,0 +1,134 @@ +'use client' + +import { useEffect } from 'react' +import { useRouter } from 'next/navigation' +import { LoadingAgent } from '@/components/ui/loading-agent' +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, creating default workspace') + + try { + const createResponse = await fetch('/api/workspaces', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name: 'My Workspace' }), + }) + + if (createResponse.ok) { + const createData = await createResponse.json() + const newWorkspace = createData.workspace + + if (newWorkspace?.id) { + logger.info(`Created default workspace: ${newWorkspace.id}`) + router.replace(`/workspace/${newWorkspace.id}/w`) + return + } + } + + logger.error('Failed to create default workspace') + } catch (createError) { + logger.error('Error creating default workspace:', createError) + } + + // If we can't create a workspace, redirect to login to reset state + router.replace('/login') + 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 ( +
+
+ +
+
+ ) + } + + // If user is not authenticated, show nothing (redirect will happen) + if (!session?.user) { + return null + } + + return null +} diff --git a/apps/sim/components/ui/loading-agent.tsx b/apps/sim/components/ui/loading-agent.tsx index 582d2ae609f..5f87b57f17d 100644 --- a/apps/sim/components/ui/loading-agent.tsx +++ b/apps/sim/components/ui/loading-agent.tsx @@ -11,7 +11,6 @@ export interface LoadingAgentProps { export function LoadingAgent({ size = 'md' }: LoadingAgentProps) { const pathLength = 120 - // Size mappings for width and height const sizes = { sm: { width: 16, height: 18 }, md: { width: 21, height: 24 }, diff --git a/apps/sim/components/ui/tag-dropdown.tsx b/apps/sim/components/ui/tag-dropdown.tsx index 78c9bf0a146..cb3c15b9f00 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/[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' diff --git a/apps/sim/hooks/use-workspace-permissions.ts b/apps/sim/hooks/use-workspace-permissions.ts index fb5ec21ba67..c4b4941ea60 100644 --- a/apps/sim/hooks/use-workspace-permissions.ts +++ b/apps/sim/hooks/use-workspace-permissions.ts @@ -5,7 +5,6 @@ import { API_ENDPOINTS } from '@/stores/constants' const logger = createLogger('useWorkspacePermissions') -// Use the enum from the database schema for type safety export type PermissionType = (typeof permissionTypeEnum.enumValues)[number] export interface WorkspaceUser { diff --git a/apps/sim/lib/logs/trace-spans.ts b/apps/sim/lib/logs/trace-spans.ts index eed9418a59f..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/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 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 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/index.ts b/apps/sim/stores/index.ts index 347685dce12..8c265e03452 100644 --- a/apps/sim/stores/index.ts +++ b/apps/sim/stores/index.ts @@ -9,7 +9,6 @@ import { useNotificationStore } from './notifications/store' import { useConsoleStore } from './panel/console/store' import { useVariablesStore } from './panel/variables/store' import { useEnvironmentStore } from './settings/environment/store' -// Removed sync system imports - Socket.IO handles real-time sync import { useWorkflowRegistry } from './workflows/registry/store' import { useSubBlockStore } from './workflows/subblock/store' import { useWorkflowStore } from './workflows/workflow/store' @@ -41,12 +40,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() diff --git a/apps/sim/stores/workflows/index.ts b/apps/sim/stores/workflows/index.ts index 161957de7c7..5fe909c51f6 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() @@ -157,17 +149,10 @@ export function getAllWorkflowsWithValues() { return result } -// Removed syncWorkflows - Socket.IO handles real-time sync automatically - -// Workflows store exports - localStorage persistence removed - export { useWorkflowRegistry } from './registry/store' export type { WorkflowMetadata } from './registry/types' export { useSubBlockStore } from './subblock/store' export type { SubBlockStore } from './subblock/types' -// Re-export utilities export { mergeSubblockState } from './utils' -// Re-export store hooks export { useWorkflowStore } from './workflow/store' -// Re-export types export type { WorkflowState } from './workflow/types' diff --git a/apps/sim/stores/workflows/registry/store.ts b/apps/sim/stores/workflows/registry/store.ts index 0ce08f959d5..4968c2dac29 100644 --- a/apps/sim/stores/workflows/registry/store.ts +++ b/apps/sim/stores/workflows/registry/store.ts @@ -4,7 +4,6 @@ import { createLogger } from '@/lib/logs/console-logger' import { clearWorkflowVariablesTracking } from '@/stores/panel/variables/store' import { API_ENDPOINTS } from '../../constants' import { useSubBlockStore } from '../subblock/store' -// Removed fetchWorkflowsFromDB import - moved to local function import { useWorkflowStore } from '../workflow/store' import type { BlockState } from '../workflow/types' import type { DeploymentStatus, WorkflowMetadata, WorkflowRegistry } from './types' @@ -12,11 +11,10 @@ import { generateUniqueName, getNextWorkflowColor } from './utils' const logger = createLogger('WorkflowRegistry') -// Simplified function to fetch workflows from DB (moved from sync.ts) 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 +29,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 +96,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 +250,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 +263,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 +282,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 +312,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 +330,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 +344,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 +586,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 +1009,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 +1017,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 +1450,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 diff --git a/apps/sim/stores/workflows/workflow/types.ts b/apps/sim/stores/workflows/workflow/types.ts index 3ad2725f0cd..65ef3624515 100644 --- a/apps/sim/stores/workflows/workflow/types.ts +++ b/apps/sim/stores/workflows/workflow/types.ts @@ -2,24 +2,17 @@ import type { Edge } from 'reactflow' import type { BlockOutput, SubBlockType } from '@/blocks/types' import type { DeploymentStatus } from '../registry/types' -// Centralized subflow type system - easy to extend without database changes export const SUBFLOW_TYPES = { LOOP: 'loop', PARALLEL: 'parallel', - // Future types can be added here: - // CONDITIONAL: 'conditional', - // RETRY: 'retry', - // BATCH: 'batch', } as const export type SubflowType = (typeof SUBFLOW_TYPES)[keyof typeof SUBFLOW_TYPES] -// Type guard for runtime validation export function isValidSubflowType(type: string): type is SubflowType { return Object.values(SUBFLOW_TYPES).includes(type as SubflowType) } -// Subflow configuration interfaces export interface LoopConfig { nodes: string[] iterations: number