Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b7e377e
v0.5.91: docs i18n, turborepo upgrade
waleedlatif1 Feb 16, 2026
da46a38
v0.5.92: shortlinks, copilot scrolling stickiness, pagination
waleedlatif1 Feb 17, 2026
fdca736
v0.5.93: NextJS config changes, MCP and Blocks whitelisting, copilot …
waleedlatif1 Feb 18, 2026
15ace5e
v0.5.94: vercel integration, folder insertion, migrated tracking redi…
waleedlatif1 Feb 19, 2026
67aa4bb
v0.5.95: gemini 3.1 pro, cloudflare, dataverse, revenuecat, redis, up…
waleedlatif1 Feb 20, 2026
34d92fa
v0.5.96: sim oauth provider, slack ephemeral message tool and blockki…
waleedlatif1 Feb 21, 2026
115f04e
v0.5.97: oidc discovery for copilot mcp
waleedlatif1 Feb 21, 2026
0d86ea0
v0.5.98: change detection improvements, rate limit and code execution…
waleedlatif1 Feb 22, 2026
af59234
v0.5.99: local dev improvements, live workflow logs in terminal
waleedlatif1 Feb 23, 2026
67f8a68
v0.5.100: multiple credentials, 40% speedup, gong, attio, audit log i…
waleedlatif1 Feb 25, 2026
4fd0989
v0.5.101: circular dependency mitigation, confluence enhancements, go…
waleedlatif1 Feb 26, 2026
0d2e6ff
v0.5.102: new integrations, new tools, ci speedups, memory leak instr…
waleedlatif1 Feb 28, 2026
e07e3c3
v0.5.103: memory util instrumentation, API docs, amplitude, google pa…
waleedlatif1 Mar 2, 2026
f1ec5fe
v0.5.104: memory improvements, nested subflows, careers page redirect…
waleedlatif1 Mar 4, 2026
70c36cb
v0.5.105: slack remove reaction, nested subflow locks fix, servicenow…
waleedlatif1 Mar 5, 2026
3ce9475
v0.5.106: condition block and legacy kbs fixes, GPT 5.4
icecrasher321 Mar 6, 2026
6586c5c
v0.5.107: new reddit, slack tools
waleedlatif1 Mar 6, 2026
8c0a2e0
v0.5.108: workflow input params in agent tools, bun upgrade, dropdown…
icecrasher321 Mar 7, 2026
ecd3536
v0.5.109: obsidian and evernote integrations, slack fixes, remove mem…
waleedlatif1 Mar 9, 2026
1c2c2c6
v0.5.110: webhook execution speedups, SSRF patches
waleedlatif1 Mar 11, 2026
36612ae
v0.5.111: non-polling webhook execs off trigger.dev, gmail subject he…
icecrasher321 Mar 12, 2026
e9bdc57
v0.5.112: trace spans improvements, fathom integration, jira fixes, c…
waleedlatif1 Mar 12, 2026
4c12914
v0.5.113: jira, ashby, google ads, grain updates
icecrasher321 Mar 13, 2026
84d6fdc
v0.6: mothership, tables, connectors
waleedlatif1 Mar 17, 2026
4f3bc37
v0.6.1: added better auth admin plugin
waleedlatif1 Mar 17, 2026
4bd0731
v0.6.2: mothership stability, chat iframe embedding, KB upserts, new …
waleedlatif1 Mar 18, 2026
30f2d1a
v0.6.3: hubspot integration, kb block improvements
waleedlatif1 Mar 18, 2026
ff7b5b5
v0.6.4: subflows, docusign, ashby new tools, box, workday, billing bu…
waleedlatif1 Mar 19, 2026
9fcd02f
v0.6.5: email validation, integrations page, mothership and custom to…
waleedlatif1 Mar 19, 2026
1731a4d
v0.6.6: landing improvements, styling consistency, mothership table r…
waleedlatif1 Mar 20, 2026
19442f1
v0.6.7: kb improvements, edge z index fix, captcha, new trust center,…
waleedlatif1 Mar 21, 2026
c78c870
v0.6.8: mothership tool loop
Sg312 Mar 24, 2026
ed9a71f
v0.6.9: general ux improvements for tables, mothership
icecrasher321 Mar 25, 2026
7b572f1
v0.6.10: tour fix, connectors reliability improvements, tooltip gif f…
waleedlatif1 Mar 25, 2026
6bebbc5
v0.6.11: billing fixes, rippling, hubspot, UI improvements, demo modal
waleedlatif1 Mar 26, 2026
ca87d7c
v0.6.12: billing, blogs UI
waleedlatif1 Mar 26, 2026
e615816
v0.6.13: emcn standardization, granola and ketch integrations, securi…
waleedlatif1 Mar 27, 2026
14089f7
v0.6.14: performance improvements, connectors UX, collapsed sidebar a…
waleedlatif1 Mar 27, 2026
560fa75
v0.6.15: workers, security hardening, sidebar improvements, chat fixe…
waleedlatif1 Mar 30, 2026
1d7ae90
v0.6.16: bullmq optionality
icecrasher321 Mar 30, 2026
73e00f5
v0.6.17: trigger.dev CI, workers FF
waleedlatif1 Mar 30, 2026
0eafb33
improvement(workflows): replace Zustand workflow sync with React Quer…
waleedlatif1 Mar 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions apps/sim/app/academy/components/sandbox-canvas-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import type {
import { validateExercise } from '@/lib/academy/validation'
import { cn } from '@/lib/core/utils/cn'
import { getEffectiveBlockOutputs } from '@/lib/workflows/blocks/block-outputs'
import { getQueryClient } from '@/app/_shell/providers/get-query-client'
import { GlobalCommandsProvider } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { SandboxWorkspacePermissionsProvider } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import Workflow from '@/app/workspace/[workspaceId]/w/[workflowId]/workflow'
import { getBlock } from '@/blocks/registry'
import { workflowKeys } from '@/hooks/queries/workflows'
import { SandboxBlockConstraintsContext } from '@/hooks/use-sandbox-block-constraints'
import { useExecutionStore } from '@/stores/execution/store'
import { useTerminalConsoleStore } from '@/stores/terminal/console/store'
Expand Down Expand Up @@ -218,8 +220,13 @@ export function SandboxCanvasProvider({

useWorkflowStore.getState().replaceWorkflowState(workflowState)
useSubBlockStore.getState().initializeFromWorkflow(workflowId, workflowState.blocks)
useWorkflowRegistry.setState((state) => ({
workflows: { ...state.workflows, [workflowId]: syntheticMetadata },

const qc = getQueryClient()
const cacheKey = workflowKeys.list(SANDBOX_WORKSPACE_ID, 'active')
const cached = qc.getQueryData<WorkflowMetadata[]>(cacheKey) ?? []
qc.setQueryData(cacheKey, [...cached.filter((w) => w.id !== workflowId), syntheticMetadata])

useWorkflowRegistry.setState({
activeWorkflowId: workflowId,
hydration: {
phase: 'ready',
Expand All @@ -228,7 +235,7 @@ export function SandboxCanvasProvider({
requestId: null,
error: null,
},
}))
})

logger.info('Sandbox stores hydrated', { workflowId })
setIsReady(true)
Expand Down Expand Up @@ -262,17 +269,21 @@ export function SandboxCanvasProvider({
unsubWorkflow()
unsubSubBlock()
unsubExecution()
useWorkflowRegistry.setState((state) => {
const { [workflowId]: _removed, ...rest } = state.workflows
return {
workflows: rest,
activeWorkflowId: state.activeWorkflowId === workflowId ? null : state.activeWorkflowId,
hydration:
state.hydration.workflowId === workflowId
? { phase: 'idle', workspaceId: null, workflowId: null, requestId: null, error: null }
: state.hydration,
}
})
const cleanupQc = getQueryClient()
const cleanupKey = workflowKeys.list(SANDBOX_WORKSPACE_ID, 'active')
const cleanupCached = cleanupQc.getQueryData<WorkflowMetadata[]>(cleanupKey) ?? []
cleanupQc.setQueryData(
cleanupKey,
cleanupCached.filter((w) => w.id !== workflowId)
)

useWorkflowRegistry.setState((state) => ({
activeWorkflowId: state.activeWorkflowId === workflowId ? null : state.activeWorkflowId,
hydration:
state.hydration.workflowId === workflowId
? { phase: 'idle', workspaceId: null, workflowId: null, requestId: null, error: null }
: state.hydration,
}))
useWorkflowStore.setState({ blocks: {}, edges: [], loops: {}, parallels: {} })
useSubBlockStore.setState((state) => {
const { [workflowId]: _removed, ...rest } = state.workflowValues
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function useAvailableResources(
workspaceId: string,
existingKeys: Set<string>
): AvailableItemsByType[] {
const { data: workflows = [] } = useWorkflows(workspaceId, { syncRegistry: false })
const { data: workflows = [] } = useWorkflows(workspaceId)
const { data: tables = [] } = useTablesList(workspaceId)
const { data: files = [] } = useWorkspaceFiles(workspaceId)
const { data: knowledgeBases } = useKnowledgeBasesQuery(workspaceId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
import { Table } from '@/app/workspace/[workspaceId]/tables/[tableId]/components'
import { useUsageLimits } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/hooks'
import { useWorkflowExecution } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution'
import { useWorkflows } from '@/hooks/queries/workflows'
import { useWorkspaceFiles } from '@/hooks/queries/workspace-files'
import { useSettingsNavigation } from '@/hooks/use-settings-navigation'
import { useExecutionStore } from '@/stores/execution/store'
Expand Down Expand Up @@ -375,10 +376,12 @@ interface EmbeddedWorkflowProps {
}

function EmbeddedWorkflow({ workspaceId, workflowId }: EmbeddedWorkflowProps) {
const workflowExists = useWorkflowRegistry((state) => Boolean(state.workflows[workflowId]))
const isMetadataLoaded = useWorkflowRegistry(
(state) => state.hydration.phase !== 'idle' && state.hydration.phase !== 'metadata-loading'
const { data: workflowList } = useWorkflows(workspaceId)
const workflowExists = useMemo(
() => (workflowList ?? []).some((w) => w.id === workflowId),
[workflowList, workflowId]
)
const isMetadataLoaded = useWorkflowRegistry((state) => state.hydration.phase !== 'idle')
const hasLoadError = useWorkflowRegistry(
(state) => state.hydration.phase === 'error' && state.hydration.workflowId === workflowId
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client'

import type { ElementType, ReactNode } from 'react'
import { type ElementType, type ReactNode, useMemo } from 'react'
import type { QueryClient } from '@tanstack/react-query'
import { useParams } from 'next/navigation'
import {
Database,
File as FileIcon,
Expand All @@ -17,9 +18,8 @@ import type {
} from '@/app/workspace/[workspaceId]/home/types'
import { knowledgeKeys } from '@/hooks/queries/kb/knowledge'
import { tableKeys } from '@/hooks/queries/tables'
import { workflowKeys } from '@/hooks/queries/workflows'
import { useWorkflows, workflowKeys } from '@/hooks/queries/workflows'
import { workspaceFilesKeys } from '@/hooks/queries/workspace-files'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'

interface DropdownItemRenderProps {
item: { id: string; name: string; [key: string]: unknown }
Expand All @@ -34,7 +34,12 @@ export interface ResourceTypeConfig {
}

function WorkflowTabSquare({ workflowId, className }: { workflowId: string; className?: string }) {
const color = useWorkflowRegistry((state) => state.workflows[workflowId]?.color ?? '#888')
const { workspaceId } = useParams<{ workspaceId: string }>()
const { data: workflowList } = useWorkflows(workspaceId)
const color = useMemo(() => {
const wf = (workflowList ?? []).find((w) => w.id === workflowId)
return wf?.color ?? '#888'
}, [workflowList, workflowId])
return (
<div
className={cn('flex-shrink-0 rounded-[3px] border-[2px]', className)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const PREVIEW_MODE_LABELS: Record<PreviewMode, string> = {
* tabs always reflect the latest name even after a rename.
*/
function useResourceNameLookup(workspaceId: string): Map<string, string> {
const { data: workflows = [] } = useWorkflows(workspaceId, { syncRegistry: false })
const { data: workflows = [] } = useWorkflows(workspaceId)
const { data: tables = [] } = useTablesList(workspaceId)
const { data: files = [] } = useWorkspaceFiles(workspaceId)
const { data: knowledgeBases } = useKnowledgeBasesQuery(workspaceId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ import {
computeMentionHighlightRanges,
extractContextTokens,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/utils'
import { getWorkflows } from '@/hooks/queries/workflows'
import type { ChatContext } from '@/stores/panel'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'

export type { FileAttachmentForApi } from '@/app/workspace/[workspaceId]/home/types'

Expand Down Expand Up @@ -639,7 +639,7 @@ export function UserInput({
case 'workflow':
case 'current_workflow': {
const wfId = (matchingCtx as { workflowId: string }).workflowId
const wfColor = useWorkflowRegistry.getState().workflows[wfId]?.color ?? '#888'
const wfColor = getWorkflows().find((w) => w.id === wfId)?.color ?? '#888'
mentionIconNode = (
<div
className='absolute inset-0 m-auto h-[12px] w-[12px] rounded-[3px] border-[2px]'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use client'

import { useMemo } from 'react'
import { useParams } from 'next/navigation'
import { Database, Table as TableIcon } from '@/components/emcn/icons'
import { getDocumentIcon } from '@/components/icons/document-icons'
import type { ChatMessageContext } from '@/app/workspace/[workspaceId]/home/types'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { useWorkflows } from '@/hooks/queries/workflows'

const USER_MESSAGE_CLASSES =
'whitespace-pre-wrap break-words [overflow-wrap:anywhere] font-[430] font-[family-name:var(--font-inter)] text-base text-[var(--text-primary)] leading-[23px] tracking-[0] antialiased'
Expand Down Expand Up @@ -44,12 +46,12 @@ function computeMentionRanges(text: string, contexts: ChatMessageContext[]): Men
}

function MentionHighlight({ context }: { context: ChatMessageContext }) {
const workflowColor = useWorkflowRegistry((state) => {
if (context.kind === 'workflow' || context.kind === 'current_workflow') {
return state.workflows[context.workflowId || '']?.color ?? null
}
return null
})
const { workspaceId } = useParams<{ workspaceId: string }>()
const { data: workflowList } = useWorkflows(workspaceId)
const workflowColor = useMemo(() => {
if (context.kind !== 'workflow' && context.kind !== 'current_workflow') return null
return (workflowList ?? []).find((w) => w.id === context.workflowId)?.color ?? null
}, [workflowList, context.kind, context.workflowId])

let icon: React.ReactNode = null
const iconClasses = 'h-[12px] w-[12px] flex-shrink-0 text-[var(--text-icon)]'
Expand Down
44 changes: 23 additions & 21 deletions apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import { VFS_DIR_TO_RESOURCE } from '@/lib/copilot/resource-types'
import { isWorkflowToolName } from '@/lib/copilot/workflow-tools'
import { getNextWorkflowColor } from '@/lib/workflows/colors'
import { getQueryClient } from '@/app/_shell/providers/get-query-client'
import { invalidateResourceQueries } from '@/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-registry'
import { deploymentKeys } from '@/hooks/queries/deployments'
import {
Expand All @@ -35,7 +36,7 @@ import {
useChatHistory,
} from '@/hooks/queries/tasks'
import { getTopInsertionSortOrder } from '@/hooks/queries/utils/top-insertion-sort-order'
import { workflowKeys } from '@/hooks/queries/workflows'
import { getWorkflows, workflowKeys } from '@/hooks/queries/workflows'
import { useExecutionStream } from '@/hooks/use-execution-stream'
import { useExecutionStore } from '@/stores/execution/store'
import { useFolderStore } from '@/stores/folders/store'
Expand Down Expand Up @@ -301,31 +302,32 @@ function getPayloadData(payload: SSEPayload): SSEPayloadData | undefined {
return typeof payload.data === 'object' ? payload.data : undefined
}

/** Adds a workflow to the registry with a top-insertion sort order if it doesn't already exist. */
/** Adds a workflow to the React Query cache with a top-insertion sort order if it doesn't already exist. */
function ensureWorkflowInRegistry(resourceId: string, title: string, workspaceId: string): boolean {
const registry = useWorkflowRegistry.getState()
if (registry.workflows[resourceId]) return false
const workflows = getWorkflows(workspaceId)
if (workflows.find((w) => w.id === resourceId)) return false
const sortOrder = getTopInsertionSortOrder(
registry.workflows,
Object.fromEntries(workflows.map((w) => [w.id, w])),
useFolderStore.getState().folders,
workspaceId,
null
)
useWorkflowRegistry.setState((state) => ({
workflows: {
...state.workflows,
[resourceId]: {
id: resourceId,
name: title,
lastModified: new Date(),
createdAt: new Date(),
color: getNextWorkflowColor(),
workspaceId,
folderId: null,
sortOrder,
},
},
}))
const newMetadata: import('@/stores/workflows/registry/types').WorkflowMetadata = {
id: resourceId,
name: title,
lastModified: new Date(),
createdAt: new Date(),
color: getNextWorkflowColor(),
workspaceId,
folderId: null,
sortOrder,
}
const queryClient = getQueryClient()
const key = workflowKeys.list(workspaceId, 'active')
const current =
queryClient.getQueryData<import('@/stores/workflows/registry/types').WorkflowMetadata[]>(key) ??
[]
queryClient.setQueryData(key, [...current, newMetadata])
return true
}

Expand Down Expand Up @@ -1253,7 +1255,7 @@ export function useChat(
? ((args as Record<string, unknown>).workflowId as string)
: useWorkflowRegistry.getState().activeWorkflowId
if (targetWorkflowId) {
const meta = useWorkflowRegistry.getState().workflows[targetWorkflowId]
const meta = getWorkflows().find((w) => w.id === targetWorkflowId)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getWorkflows() called without workspaceId in callback

Low Severity

getWorkflows() is called without a workspaceId argument, relying on URL parsing as a fallback. This occurs inside an SSE streaming callback where the URL may not reliably reflect the expected workspace (e.g. during navigation). This contrasts with ensureWorkflowInRegistry at line 307 which correctly passes workspaceId. An explicit workspaceId argument would be more robust.

Fix in Cursor Fix in Web

const wasAdded = addResource({
type: 'workflow',
id: targetWorkflowId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { memo } from 'react'
import { useParams } from 'next/navigation'
import { cn } from '@/lib/core/utils/cn'
import {
DELETED_WORKFLOW_COLOR,
DELETED_WORKFLOW_LABEL,
} from '@/app/workspace/[workspaceId]/logs/utils'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { useWorkflowMap } from '@/hooks/queries/workflows'
import { StatusBar, type StatusBarSegment } from '..'

export interface WorkflowExecutionItem {
Expand Down Expand Up @@ -36,7 +37,8 @@ function WorkflowsListInner({
searchQuery: string
segmentDurationMs: number
}) {
const workflows = useWorkflowRegistry((s) => s.workflows)
const { workspaceId } = useParams<{ workspaceId: string }>()
const { data: workflows = {} } = useWorkflowMap(workspaceId)

return (
<div className='flex h-full flex-col overflow-hidden rounded-md bg-[var(--surface-2)] dark:bg-[var(--surface-1)]'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Loader2 } from 'lucide-react'
import { useParams } from 'next/navigation'
import { useShallow } from 'zustand/react/shallow'
import { Skeleton } from '@/components/emcn'
import { formatLatency } from '@/app/workspace/[workspaceId]/logs/utils'
import type { DashboardStatsResponse, WorkflowStats } from '@/hooks/queries/logs'
import { useWorkflows } from '@/hooks/queries/workflows'
import { useFilterStore } from '@/stores/logs/filters/store'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { LineChart, WorkflowsList } from './components'

interface WorkflowExecution {
Expand Down Expand Up @@ -156,7 +157,8 @@ function DashboardInner({ stats, isLoading, error }: DashboardProps) {
}))
)

const allWorkflows = useWorkflowRegistry((state) => state.workflows)
const { workspaceId } = useParams<{ workspaceId: string }>()
const { data: allWorkflowList = [] } = useWorkflows(workspaceId)

const expandedWorkflowId = workflowIds.length === 1 ? workflowIds[0] : null

Expand Down Expand Up @@ -459,7 +461,7 @@ function DashboardInner({ stats, isLoading, error }: DashboardProps) {
)
}

if (Object.keys(allWorkflows).length === 0) {
if (allWorkflowList.length === 0) {
return (
<div className='mt-6 flex flex-1 items-center justify-center'>
<div className='text-center text-[var(--text-secondary)]'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ export function WorkflowSelector({
onChange,
error,
}: WorkflowSelectorProps) {
const { data: workflows = [], isPending: isLoading } = useWorkflows(workspaceId, {
syncRegistry: false,
})
const { data: workflows = [], isPending: isLoading } = useWorkflows(workspaceId)

const options: ComboboxOption[] = useMemo(() => {
return workflows.map((w) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
import { Search, X } from 'lucide-react'
import { useParams } from 'next/navigation'
import { Badge } from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import { getTriggerOptions } from '@/lib/logs/get-trigger-options'
Expand All @@ -14,8 +15,8 @@ import {
type WorkflowData,
} from '@/lib/logs/search-suggestions'
import { useSearchState } from '@/app/workspace/[workspaceId]/logs/hooks/use-search-state'
import { useWorkflows } from '@/hooks/queries/workflows'
import { useFolderStore } from '@/stores/folders/store'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'

function truncateFilterValue(field: string, value: string): string {
if ((field === 'executionId' || field === 'workflowId') && value.length > 12) {
Expand All @@ -42,16 +43,17 @@ export function AutocompleteSearch({
className,
onOpenChange,
}: AutocompleteSearchProps) {
const workflows = useWorkflowRegistry((state) => state.workflows)
const { workspaceId } = useParams<{ workspaceId: string }>()
const { data: workflowList = [] } = useWorkflows(workspaceId)
const folders = useFolderStore((state) => state.folders)

const workflowsData = useMemo<WorkflowData[]>(() => {
return Object.values(workflows).map((w) => ({
return workflowList.map((w) => ({
id: w.id,
name: w.name,
description: w.description,
}))
}, [workflows])
}, [workflowList])

const foldersData = useMemo<FolderData[]>(() => {
return Object.values(folders).map((f) => ({
Expand Down
Loading
Loading