From 28f1d100d187397ba94abf24fd2dba163efb0df6 Mon Sep 17 00:00:00 2001 From: waleed Date: Thu, 16 Apr 2026 17:33:22 -0700 Subject: [PATCH 1/3] improvement(logs): fix trigger badge wrapping, time range picker, status filters, and React anti-patterns --- .../[workspaceId]/logs/__dev__/mock-logs.ts | 34 ++++ .../components/line-chart/line-chart.tsx | 2 +- .../components/logs-toolbar/logs-toolbar.tsx | 155 +++++++--------- .../app/workspace/[workspaceId]/logs/logs.tsx | 105 ++++++----- .../app/workspace/[workspaceId]/logs/utils.ts | 56 ++++-- .../workflow-block/workflow-block.tsx | 8 +- .../lib/copilot/generated/tool-schemas-v1.ts | 174 +++++++++--------- 7 files changed, 285 insertions(+), 249 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts diff --git a/apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts b/apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts new file mode 100644 index 00000000000..3fc2a5685ff --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts @@ -0,0 +1,34 @@ +import type { WorkflowLog } from '@/stores/logs/filters/types' + +const MOCK_WORKFLOW = { + id: '__mock__', + name: 'mock-workflow', + color: '#6366f1', +} + +const base = (overrides: Partial): WorkflowLog => ({ + id: `mock-${overrides.trigger}-1`, + workflowId: MOCK_WORKFLOW.id, + executionId: `mock-exec-${overrides.trigger}-1`, + level: 'info', + status: 'success', + duration: '1.2s', + trigger: null, + createdAt: new Date().toISOString(), + workflow: MOCK_WORKFLOW, + cost: { total: 0.001, input: 0.0005, output: 0.0005 }, + ...overrides, +}) + +export const DEV_MOCK_LOGS: WorkflowLog[] = [ + base({ id: 'mock-gcal-1', trigger: 'google_calendar', executionId: 'mock-exec-gcal-1' }), + base({ id: 'mock-gmail-1', trigger: 'gmail', executionId: 'mock-exec-gmail-1' }), + base({ id: 'mock-slack-1', trigger: 'slack', executionId: 'mock-exec-slack-1' }), + base({ + id: 'mock-gh-1', + trigger: 'github', + executionId: 'mock-exec-gh-1', + status: 'failed', + level: 'error', + }), +] diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx index 8534cb8cdb2..83d11ad5a5c 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx @@ -293,7 +293,7 @@ function LineChartComponent({ className='inline-block h-[6px] w-[6px] rounded-xs' style={{ backgroundColor: resolvedColors[s.id || ''] || s.color }} /> - {s.label} + {s.label} ) })} diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx index 518ad67654b..b132b2fd68d 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx @@ -249,11 +249,13 @@ export const LogsToolbar = memo(function LogsToolbar({ const statusOptions: ComboboxOption[] = useMemo( () => - (Object.keys(STATUS_CONFIG) as LogStatus[]).map((status) => ({ - value: status, - label: STATUS_CONFIG[status].label, - icon: getColorIcon(STATUS_CONFIG[status].color), - })), + (Object.keys(STATUS_CONFIG) as LogStatus[]) + .filter((status) => STATUS_CONFIG[status].filterable) + .map((status) => ({ + value: status, + label: STATUS_CONFIG[status].label, + icon: getColorIcon(STATUS_CONFIG[status].color), + })), [] ) @@ -305,34 +307,29 @@ export const LogsToolbar = memo(function LogsToolbar({ [setTriggers, workspaceId] ) - const statusDisplayLabel = useMemo(() => { - if (selectedStatuses.length === 0) return 'Status' - if (selectedStatuses.length === 1) { - const status = statusOptions.find((s) => s.value === selectedStatuses[0]) - return status?.label || '1 selected' - } - return `${selectedStatuses.length} selected` - }, [selectedStatuses, statusOptions]) + const statusDisplayLabel = + selectedStatuses.length === 0 + ? 'Status' + : selectedStatuses.length === 1 + ? (statusOptions.find((s) => s.value === selectedStatuses[0])?.label ?? '1 selected') + : `${selectedStatuses.length} selected` - const selectedStatusColor = useMemo(() => { - if (selectedStatuses.length !== 1) return null - const status = selectedStatuses[0] as LogStatus - return STATUS_CONFIG[status]?.color ?? null - }, [selectedStatuses]) + const selectedStatusColor = + selectedStatuses.length === 1 + ? (STATUS_CONFIG[selectedStatuses[0] as LogStatus]?.color ?? null) + : null const workflowOptions: ComboboxOption[] = useMemo( () => workflows.map((w) => ({ value: w.id, label: w.name, icon: getColorIcon(w.color, true) })), [workflows] ) - const workflowDisplayLabel = useMemo(() => { - if (workflowIds.length === 0) return 'Workflow' - if (workflowIds.length === 1) { - const workflow = workflows.find((w) => w.id === workflowIds[0]) - return workflow?.name || '1 selected' - } - return `${workflowIds.length} workflows` - }, [workflowIds, workflows]) + const workflowDisplayLabel = + workflowIds.length === 0 + ? 'Workflow' + : workflowIds.length === 1 + ? (workflows.find((w) => w.id === workflowIds[0])?.name ?? '1 selected') + : `${workflowIds.length} workflows` const selectedWorkflow = workflowIds.length === 1 ? workflows.find((w) => w.id === workflowIds[0]) : null @@ -342,14 +339,12 @@ export const LogsToolbar = memo(function LogsToolbar({ [folderList] ) - const folderDisplayLabel = useMemo(() => { - if (folderIds.length === 0) return 'Folder' - if (folderIds.length === 1) { - const folder = folderList.find((f) => f.id === folderIds[0]) - return folder?.name || '1 selected' - } - return `${folderIds.length} folders` - }, [folderIds, folderList]) + const folderDisplayLabel = + folderIds.length === 0 + ? 'Folder' + : folderIds.length === 1 + ? (folderList.find((f) => f.id === folderIds[0])?.name ?? '1 selected') + : `${folderIds.length} folders` const triggerOptions: ComboboxOption[] = useMemo( () => @@ -361,23 +356,21 @@ export const LogsToolbar = memo(function LogsToolbar({ [] ) - const triggerDisplayLabel = useMemo(() => { - if (triggers.length === 0) return 'Trigger' - if (triggers.length === 1) { - const trigger = triggerOptions.find((t) => t.value === triggers[0]) - return trigger?.label || '1 selected' - } - return `${triggers.length} triggers` - }, [triggers, triggerOptions]) - - const timeDisplayLabel = useMemo(() => { - if (timeRange === 'All time') return 'Time' - if (timeRange === 'Custom range' && startDate && endDate) { - return `${formatDateShort(startDate)} - ${formatDateShort(endDate)}` - } - if (timeRange === 'Custom range') return 'Custom range' - return timeRange - }, [timeRange, startDate, endDate]) + const triggerDisplayLabel = + triggers.length === 0 + ? 'Trigger' + : triggers.length === 1 + ? (triggerOptions.find((t) => t.value === triggers[0])?.label ?? '1 selected') + : `${triggers.length} triggers` + + const timeDisplayLabel = + timeRange === 'All time' + ? 'Time' + : timeRange === 'Custom range' && startDate && endDate + ? `${formatDateShort(startDate)} - ${formatDateShort(endDate)}` + : timeRange === 'Custom range' + ? 'Custom range' + : timeRange /** * Handles time range selection from combobox. @@ -792,42 +785,32 @@ export const LogsToolbar = memo(function LogsToolbar({ /> {/* Timeline Filter */} - - -
- - {timeDisplayLabel} - - } - size='sm' - align='end' - className='h-[32px] w-[120px] rounded-md' - /> -
-
- + {timeDisplayLabel} + } + size='sm' align='end' - sideOffset={4} - collisionPadding={16} - className='w-auto p-0' - > - - -
+ className='h-[32px] w-[120px] rounded-md' + /> + { + if (!isOpen) handleDatePickerCancel() + }} + startDate={startDate} + endDate={endDate} + onRangeChange={handleDateRangeApply} + onCancel={handleDatePickerCancel} + /> + diff --git a/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx index 90c24c5ee59..f7c2e9802b4 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx @@ -10,9 +10,6 @@ import { Combobox, type ComboboxOption, Download, - DropdownMenu, - DropdownMenuContent, - DropdownMenuTrigger, Library, RefreshCw, } from '@/components/emcn' @@ -47,6 +44,7 @@ import { ResourceOptionsBar, ResourceTable, } from '@/app/workspace/[workspaceId]/components' +import { DEV_MOCK_LOGS } from '@/app/workspace/[workspaceId]/logs/__dev__/mock-logs' import { useSearchState } from '@/app/workspace/[workspaceId]/logs/hooks/use-search-state' import type { Suggestion } from '@/app/workspace/[workspaceId]/logs/types' import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' @@ -361,8 +359,11 @@ export default function Logs() { }) const logs = useMemo(() => { - if (!logsQuery.data?.pages) return [] - return logsQuery.data.pages.flatMap((page) => page.logs) + const realLogs = logsQuery.data?.pages?.flatMap((page) => page.logs) ?? [] + if (process.env.NODE_ENV === 'development') { + return [...DEV_MOCK_LOGS, ...realLogs] + } + return realLogs }, [logsQuery.data?.pages]) const sortedLogs = useMemo(() => { @@ -570,18 +571,22 @@ export default function Logs() { const effectiveSidebarOpen = isSidebarOpen && selectedLogIndex !== -1 - const handleRefresh = useCallback(() => { + const triggerVisualRefresh = useCallback(() => { setIsVisuallyRefreshing(true) const timerId = window.setTimeout(() => { setIsVisuallyRefreshing(false) refreshTimersRef.current.delete(timerId) }, REFRESH_SPINNER_DURATION_MS) refreshTimersRef.current.add(timerId) + }, []) + + const handleRefresh = useCallback(() => { + triggerVisualRefresh() logsRefetchRef.current() if (selectedLogIdRef.current) { activeLogRefetchRef.current() } - }, []) + }, [triggerVisualRefresh]) const prevIsFetchingRef = useRef(logsQuery.isFetching) useEffect(() => { @@ -590,14 +595,9 @@ export default function Logs() { prevIsFetchingRef.current = isFetching if (isLive && !wasFetching && isFetching) { - setIsVisuallyRefreshing(true) - const timerId = window.setTimeout(() => { - setIsVisuallyRefreshing(false) - refreshTimersRef.current.delete(timerId) - }, REFRESH_SPINNER_DURATION_MS) - refreshTimersRef.current.add(timerId) + triggerVisualRefresh() } - }, [logsQuery.isFetching, isLive]) + }, [logsQuery.isFetching, isLive, triggerVisualRefresh]) const handleExport = useCallback(async () => { setIsExporting(true) @@ -898,6 +898,11 @@ export default function Logs() { setSearchQuery(fullQuery) }, []) + const getSuggestions = useCallback( + (input: string) => suggestionEngine.getSuggestions(input), + [suggestionEngine] + ) + const { appliedFilters, currentInput, @@ -920,7 +925,7 @@ export default function Logs() { initializeFromQuery, } = useSearchState({ onFiltersChange: handleFiltersChange, - getSuggestions: (input) => suggestionEngine.getSuggestions(input), + getSuggestions, }) const lastExternalSearchValue = useRef(searchQuery) @@ -1269,11 +1274,13 @@ function LogsFilterPanel({ searchQuery, onSearchQueryChange }: LogsFilterPanelPr const statusOptions: ComboboxOption[] = useMemo( () => - (Object.keys(STATUS_CONFIG) as LogStatus[]).map((status) => ({ - value: status, - label: STATUS_CONFIG[status].label, - icon: getColorIcon(STATUS_CONFIG[status].color), - })), + (Object.keys(STATUS_CONFIG) as LogStatus[]) + .filter((status) => STATUS_CONFIG[status].filterable) + .map((status) => ({ + value: status, + label: STATUS_CONFIG[status].label, + icon: getColorIcon(STATUS_CONFIG[status].color), + })), [] ) @@ -1482,39 +1489,31 @@ function LogsFilterPanel({ searchQuery, onSearchQueryChange }: LogsFilterPanelPr
Time Range - - -
- {timeDisplayLabel} - } - size='sm' - className='h-[32px] w-full rounded-md' - /> -
-
- - - -
+
+ {timeDisplayLabel} + } + size='sm' + className='h-[32px] w-full rounded-md' + /> + { + if (!isOpen) handleDatePickerCancel() + }} + startDate={startDate} + endDate={endDate} + onRangeChange={handleDateRangeApply} + onCancel={handleDatePickerCancel} + /> +
{filtersActive && ( diff --git a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts index 1f77a590435..27cc823a195 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts +++ b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts @@ -55,14 +55,25 @@ export function getDisplayStatus(status: string | null | undefined): LogStatus { export const STATUS_CONFIG: Record< LogStatus, - { variant: React.ComponentProps['variant']; label: string; color: string } + { + variant: React.ComponentProps['variant'] + label: string + color: string + /** Whether this status appears as a filter option. Intermediary states (e.g. cancelling) are excluded. */ + filterable: boolean + } > = { - error: { variant: 'red', label: 'Error', color: 'var(--text-error)' }, - pending: { variant: 'amber', label: 'Pending', color: '#f59e0b' }, - running: { variant: 'amber', label: 'Running', color: '#f59e0b' }, - cancelling: { variant: 'amber', label: 'Cancelling...', color: '#f59e0b' }, - cancelled: { variant: 'orange', label: 'Cancelled', color: '#f97316' }, - info: { variant: 'gray', label: 'Info', color: 'var(--terminal-status-info-color)' }, + error: { variant: 'red', label: 'Error', color: 'var(--text-error)', filterable: true }, + pending: { variant: 'amber', label: 'Pending', color: '#f59e0b', filterable: true }, + running: { variant: 'amber', label: 'Running', color: '#f59e0b', filterable: true }, + cancelling: { variant: 'amber', label: 'Cancelling...', color: '#f59e0b', filterable: false }, + cancelled: { variant: 'orange', label: 'Cancelled', color: '#f97316', filterable: true }, + info: { + variant: 'gray', + label: 'Info', + color: 'var(--terminal-status-info-color)', + filterable: true, + }, } const TRIGGER_VARIANT_MAP: Record['variant']> = { @@ -87,16 +98,14 @@ interface StatusBadgeProps { * @param props - Component props containing the status * @returns A Badge with dot indicator and status label */ -export const StatusBadge = React.memo(({ status }: StatusBadgeProps) => { +export function StatusBadge({ status }: StatusBadgeProps) { const config = STATUS_CONFIG[status] return React.createElement( Badge, { variant: config.variant, dot: true, size: 'sm' }, config.label ) -}) - -StatusBadge.displayName = 'StatusBadge' +} interface TriggerBadgeProps { trigger: string @@ -108,7 +117,7 @@ interface TriggerBadgeProps { * @param props - Component props containing the trigger type * @returns A Badge with appropriate styling for the trigger type */ -export const TriggerBadge = React.memo(({ trigger }: TriggerBadgeProps) => { +export function TriggerBadge({ trigger }: TriggerBadgeProps) { const metadata = getIntegrationMetadata(trigger) const isIntegration = !(CORE_TRIGGER_TYPES as readonly string[]).includes(trigger) const block = isIntegration ? getBlock(trigger) : null @@ -116,21 +125,32 @@ export const TriggerBadge = React.memo(({ trigger }: TriggerBadgeProps) => { const coreVariant = TRIGGER_VARIANT_MAP[trigger] if (coreVariant) { - return React.createElement(Badge, { variant: coreVariant, size: 'sm' }, metadata.label) + return React.createElement( + Badge, + { variant: coreVariant, size: 'sm', className: 'whitespace-nowrap' }, + metadata.label + ) } if (IconComponent) { return React.createElement( Badge, - { variant: 'gray-secondary', size: 'sm', icon: IconComponent }, + { + variant: 'gray-secondary', + size: 'sm', + icon: IconComponent, + className: 'whitespace-nowrap', + }, metadata.label ) } - return React.createElement(Badge, { variant: 'gray-secondary', size: 'sm' }, metadata.label) -}) - -TriggerBadge.displayName = 'TriggerBadge' + return React.createElement( + Badge, + { variant: 'gray-secondary', size: 'sm', className: 'whitespace-nowrap' }, + metadata.label + ) +} interface LogWithDuration { totalDurationMs?: number | string diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx index 43b66cde526..b9dc27ba82a 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx @@ -604,9 +604,9 @@ const SubBlockRow = memo(function SubBlockRow({ const { data: workflowMapForLookup = {} } = useWorkflowMap(workspaceId) const workflowSelectionName = useMemo(() => { - if (subBlock?.id !== 'workflowId' || typeof rawValue !== 'string') return null + if (subBlock?.type !== 'workflow-selector' || typeof rawValue !== 'string') return null return workflowMapForLookup[rawValue]?.name ?? null - }, [workflowMapForLookup, subBlock?.id, rawValue]) + }, [workflowMapForLookup, subBlock?.type, rawValue]) const { data: mcpServers = [] } = useMcpServers(workspaceId || '') const mcpServerDisplayName = useMemo(() => { @@ -632,12 +632,12 @@ const SubBlockRow = memo(function SubBlockRow({ const { data: tables = [] } = useTablesList(workspaceId || '') const tableDisplayName = useMemo(() => { - if (subBlock?.id !== 'tableId' || typeof rawValue !== 'string') { + if (subBlock?.type !== 'table-selector' || typeof rawValue !== 'string') { return null } const table = tables.find((t) => t.id === rawValue) return table?.name ?? null - }, [subBlock?.id, rawValue, tables]) + }, [subBlock?.type, rawValue, tables]) const webhookUrlDisplayValue = useMemo(() => { if (!subBlock?.id?.startsWith('webhookUrlDisplay') || !blockId) { diff --git a/apps/sim/lib/copilot/generated/tool-schemas-v1.ts b/apps/sim/lib/copilot/generated/tool-schemas-v1.ts index 95538651008..8a64b57a766 100644 --- a/apps/sim/lib/copilot/generated/tool-schemas-v1.ts +++ b/apps/sim/lib/copilot/generated/tool-schemas-v1.ts @@ -10,7 +10,7 @@ export interface ToolRuntimeSchemaEntry { } export const TOOL_RUNTIME_SCHEMAS: Record = { - ['agent']: { + agent: { parameters: { properties: { request: { @@ -23,7 +23,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['auth']: { + auth: { parameters: { properties: { request: { @@ -36,7 +36,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['check_deployment_status']: { + check_deployment_status: { parameters: { type: 'object', properties: { @@ -48,7 +48,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['complete_job']: { + complete_job: { parameters: { type: 'object', properties: { @@ -61,7 +61,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['context_write']: { + context_write: { parameters: { type: 'object', properties: { @@ -78,7 +78,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['crawl_website']: { + crawl_website: { parameters: { type: 'object', properties: { @@ -113,7 +113,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['create_file']: { + create_file: { parameters: { type: 'object', properties: { @@ -149,7 +149,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { required: ['success', 'message'], }, }, - ['create_folder']: { + create_folder: { parameters: { type: 'object', properties: { @@ -170,7 +170,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['create_job']: { + create_job: { parameters: { type: 'object', properties: { @@ -220,7 +220,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['create_workflow']: { + create_workflow: { parameters: { type: 'object', properties: { @@ -245,7 +245,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['create_workspace_mcp_server']: { + create_workspace_mcp_server: { parameters: { type: 'object', properties: { @@ -266,7 +266,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['debug']: { + debug: { parameters: { properties: { context: { @@ -285,7 +285,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['delete_file']: { + delete_file: { parameters: { type: 'object', properties: { @@ -314,7 +314,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { required: ['success', 'message'], }, }, - ['delete_folder']: { + delete_folder: { parameters: { type: 'object', properties: { @@ -330,7 +330,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['delete_workflow']: { + delete_workflow: { parameters: { type: 'object', properties: { @@ -346,7 +346,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['delete_workspace_mcp_server']: { + delete_workspace_mcp_server: { parameters: { type: 'object', properties: { @@ -359,7 +359,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['deploy']: { + deploy: { parameters: { properties: { request: { @@ -373,7 +373,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['deploy_api']: { + deploy_api: { parameters: { type: 'object', properties: { @@ -447,7 +447,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { ], }, }, - ['deploy_chat']: { + deploy_chat: { parameters: { type: 'object', properties: { @@ -595,7 +595,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { ], }, }, - ['deploy_mcp']: { + deploy_mcp: { parameters: { type: 'object', properties: { @@ -711,7 +711,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { required: ['deploymentType', 'deploymentStatus'], }, }, - ['download_to_workspace_file']: { + download_to_workspace_file: { parameters: { type: 'object', properties: { @@ -730,7 +730,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['edit_content']: { + edit_content: { parameters: { type: 'object', properties: { @@ -762,7 +762,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { required: ['success', 'message'], }, }, - ['edit_workflow']: { + edit_workflow: { parameters: { type: 'object', properties: { @@ -801,13 +801,13 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['file']: { + file: { parameters: { type: 'object', }, resultSchema: undefined, }, - ['function_execute']: { + function_execute: { parameters: { type: 'object', properties: { @@ -868,7 +868,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['generate_api_key']: { + generate_api_key: { parameters: { type: 'object', properties: { @@ -886,7 +886,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['generate_image']: { + generate_image: { parameters: { type: 'object', properties: { @@ -923,7 +923,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['generate_visualization']: { + generate_visualization: { parameters: { type: 'object', properties: { @@ -963,7 +963,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_block_outputs']: { + get_block_outputs: { parameters: { type: 'object', properties: { @@ -984,7 +984,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_block_upstream_references']: { + get_block_upstream_references: { parameters: { type: 'object', properties: { @@ -1006,7 +1006,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_deployed_workflow_state']: { + get_deployed_workflow_state: { parameters: { type: 'object', properties: { @@ -1019,7 +1019,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_deployment_version']: { + get_deployment_version: { parameters: { type: 'object', properties: { @@ -1036,7 +1036,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_execution_summary']: { + get_execution_summary: { parameters: { type: 'object', properties: { @@ -1063,7 +1063,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_job_logs']: { + get_job_logs: { parameters: { type: 'object', properties: { @@ -1088,7 +1088,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_page_contents']: { + get_page_contents: { parameters: { type: 'object', properties: { @@ -1116,14 +1116,14 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_platform_actions']: { + get_platform_actions: { parameters: { type: 'object', properties: {}, }, resultSchema: undefined, }, - ['get_workflow_data']: { + get_workflow_data: { parameters: { type: 'object', properties: { @@ -1142,7 +1142,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['get_workflow_logs']: { + get_workflow_logs: { parameters: { type: 'object', properties: { @@ -1168,7 +1168,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['glob']: { + glob: { parameters: { type: 'object', properties: { @@ -1187,7 +1187,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['grep']: { + grep: { parameters: { type: 'object', properties: { @@ -1234,7 +1234,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['job']: { + job: { parameters: { properties: { request: { @@ -1247,7 +1247,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['knowledge']: { + knowledge: { parameters: { properties: { request: { @@ -1260,7 +1260,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['knowledge_base']: { + knowledge_base: { parameters: { type: 'object', properties: { @@ -1452,7 +1452,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { required: ['success', 'message'], }, }, - ['list_folders']: { + list_folders: { parameters: { type: 'object', properties: { @@ -1464,14 +1464,14 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['list_user_workspaces']: { + list_user_workspaces: { parameters: { type: 'object', properties: {}, }, resultSchema: undefined, }, - ['list_workspace_mcp_servers']: { + list_workspace_mcp_servers: { parameters: { type: 'object', properties: { @@ -1483,7 +1483,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['manage_credential']: { + manage_credential: { parameters: { type: 'object', properties: { @@ -1512,7 +1512,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['manage_custom_tool']: { + manage_custom_tool: { parameters: { type: 'object', properties: { @@ -1591,7 +1591,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['manage_job']: { + manage_job: { parameters: { type: 'object', properties: { @@ -1661,7 +1661,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['manage_mcp_tool']: { + manage_mcp_tool: { parameters: { type: 'object', properties: { @@ -1712,7 +1712,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['manage_skill']: { + manage_skill: { parameters: { type: 'object', properties: { @@ -1744,7 +1744,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['materialize_file']: { + materialize_file: { parameters: { type: 'object', properties: { @@ -1778,7 +1778,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['move_folder']: { + move_folder: { parameters: { type: 'object', properties: { @@ -1796,7 +1796,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['move_workflow']: { + move_workflow: { parameters: { type: 'object', properties: { @@ -1816,7 +1816,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['oauth_get_auth_link']: { + oauth_get_auth_link: { parameters: { type: 'object', properties: { @@ -1830,7 +1830,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['oauth_request_access']: { + oauth_request_access: { parameters: { type: 'object', properties: { @@ -1844,7 +1844,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['open_resource']: { + open_resource: { parameters: { type: 'object', properties: { @@ -1872,7 +1872,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['read']: { + read: { parameters: { type: 'object', properties: { @@ -1899,7 +1899,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['redeploy']: { + redeploy: { parameters: { type: 'object', properties: { @@ -1967,7 +1967,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { ], }, }, - ['rename_file']: { + rename_file: { parameters: { type: 'object', properties: { @@ -2002,7 +2002,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { required: ['success', 'message'], }, }, - ['rename_workflow']: { + rename_workflow: { parameters: { type: 'object', properties: { @@ -2019,7 +2019,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['research']: { + research: { parameters: { properties: { topic: { @@ -2032,7 +2032,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['respond']: { + respond: { parameters: { additionalProperties: true, properties: { @@ -2055,7 +2055,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['restore_resource']: { + restore_resource: { parameters: { type: 'object', properties: { @@ -2073,7 +2073,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['revert_to_version']: { + revert_to_version: { parameters: { type: 'object', properties: { @@ -2090,7 +2090,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['run']: { + run: { parameters: { properties: { context: { @@ -2107,7 +2107,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['run_block']: { + run_block: { parameters: { type: 'object', properties: { @@ -2139,7 +2139,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['run_from_block']: { + run_from_block: { parameters: { type: 'object', properties: { @@ -2171,7 +2171,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['run_workflow']: { + run_workflow: { parameters: { type: 'object', properties: { @@ -2199,7 +2199,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['run_workflow_until_block']: { + run_workflow_until_block: { parameters: { type: 'object', properties: { @@ -2231,7 +2231,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['scrape_page']: { + scrape_page: { parameters: { type: 'object', properties: { @@ -2252,7 +2252,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['search_documentation']: { + search_documentation: { parameters: { type: 'object', properties: { @@ -2269,7 +2269,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['search_library_docs']: { + search_library_docs: { parameters: { type: 'object', properties: { @@ -2290,7 +2290,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['search_online']: { + search_online: { parameters: { type: 'object', properties: { @@ -2331,7 +2331,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['search_patterns']: { + search_patterns: { parameters: { type: 'object', properties: { @@ -2353,7 +2353,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['set_block_enabled']: { + set_block_enabled: { parameters: { type: 'object', properties: { @@ -2375,7 +2375,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['set_environment_variables']: { + set_environment_variables: { parameters: { type: 'object', properties: { @@ -2409,7 +2409,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['set_global_workflow_variables']: { + set_global_workflow_variables: { parameters: { type: 'object', properties: { @@ -2447,7 +2447,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['superagent']: { + superagent: { parameters: { properties: { task: { @@ -2461,7 +2461,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['table']: { + table: { parameters: { properties: { request: { @@ -2474,7 +2474,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['tool_search_tool_regex']: { + tool_search_tool_regex: { parameters: { properties: { case_insensitive: { @@ -2495,7 +2495,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['update_job_history']: { + update_job_history: { parameters: { type: 'object', properties: { @@ -2513,7 +2513,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['update_workspace_mcp_server']: { + update_workspace_mcp_server: { parameters: { type: 'object', properties: { @@ -2538,7 +2538,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['user_memory']: { + user_memory: { parameters: { type: 'object', properties: { @@ -2586,7 +2586,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, resultSchema: undefined, }, - ['user_table']: { + user_table: { parameters: { type: 'object', properties: { @@ -2777,13 +2777,13 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { required: ['success', 'message'], }, }, - ['workflow']: { + workflow: { parameters: { type: 'object', }, resultSchema: undefined, }, - ['workspace_file']: { + workspace_file: { parameters: { type: 'object', properties: { From b6cd0fe54bdfa9a3ad14ad236a89f8072743024d Mon Sep 17 00:00:00 2001 From: waleed Date: Thu, 16 Apr 2026 17:38:17 -0700 Subject: [PATCH 2/3] chore(logs): remove dev mock logs --- .../[workspaceId]/logs/__dev__/mock-logs.ts | 34 ------------------- .../app/workspace/[workspaceId]/logs/logs.tsx | 7 +--- 2 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts diff --git a/apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts b/apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts deleted file mode 100644 index 3fc2a5685ff..00000000000 --- a/apps/sim/app/workspace/[workspaceId]/logs/__dev__/mock-logs.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { WorkflowLog } from '@/stores/logs/filters/types' - -const MOCK_WORKFLOW = { - id: '__mock__', - name: 'mock-workflow', - color: '#6366f1', -} - -const base = (overrides: Partial): WorkflowLog => ({ - id: `mock-${overrides.trigger}-1`, - workflowId: MOCK_WORKFLOW.id, - executionId: `mock-exec-${overrides.trigger}-1`, - level: 'info', - status: 'success', - duration: '1.2s', - trigger: null, - createdAt: new Date().toISOString(), - workflow: MOCK_WORKFLOW, - cost: { total: 0.001, input: 0.0005, output: 0.0005 }, - ...overrides, -}) - -export const DEV_MOCK_LOGS: WorkflowLog[] = [ - base({ id: 'mock-gcal-1', trigger: 'google_calendar', executionId: 'mock-exec-gcal-1' }), - base({ id: 'mock-gmail-1', trigger: 'gmail', executionId: 'mock-exec-gmail-1' }), - base({ id: 'mock-slack-1', trigger: 'slack', executionId: 'mock-exec-slack-1' }), - base({ - id: 'mock-gh-1', - trigger: 'github', - executionId: 'mock-exec-gh-1', - status: 'failed', - level: 'error', - }), -] diff --git a/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx index f7c2e9802b4..59fb73ec6d2 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx @@ -44,7 +44,6 @@ import { ResourceOptionsBar, ResourceTable, } from '@/app/workspace/[workspaceId]/components' -import { DEV_MOCK_LOGS } from '@/app/workspace/[workspaceId]/logs/__dev__/mock-logs' import { useSearchState } from '@/app/workspace/[workspaceId]/logs/hooks/use-search-state' import type { Suggestion } from '@/app/workspace/[workspaceId]/logs/types' import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' @@ -359,11 +358,7 @@ export default function Logs() { }) const logs = useMemo(() => { - const realLogs = logsQuery.data?.pages?.flatMap((page) => page.logs) ?? [] - if (process.env.NODE_ENV === 'development') { - return [...DEV_MOCK_LOGS, ...realLogs] - } - return realLogs + return logsQuery.data?.pages?.flatMap((page) => page.logs) ?? [] }, [logsQuery.data?.pages]) const sortedLogs = useMemo(() => { From 4ec1fa3ba7d6dc3e69b0356f451a2d5b764bb9bd Mon Sep 17 00:00:00 2001 From: waleed Date: Thu, 16 Apr 2026 17:48:05 -0700 Subject: [PATCH 3/3] fix(logs): prevent DatePicker onOpenChange from reverting time range after Apply --- .../logs/components/logs-toolbar/logs-toolbar.tsx | 10 +++++++++- apps/sim/app/workspace/[workspaceId]/logs/logs.tsx | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx index b132b2fd68d..501d208fb87 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx @@ -224,6 +224,7 @@ export const LogsToolbar = memo(function LogsToolbar({ const [datePickerOpen, setDatePickerOpen] = useState(false) const [previousTimeRange, setPreviousTimeRange] = useState(timeRange) + const dateRangeAppliedRef = useRef(false) const { data: folders = {} } = useFolderMap(workspaceId) const { data: allWorkflowList = [] } = useWorkflows(workspaceId) @@ -398,6 +399,7 @@ export const LogsToolbar = memo(function LogsToolbar({ */ const handleDateRangeApply = useCallback( (start: string, end: string) => { + dateRangeAppliedRef.current = true setDateRange(start, end) setDatePickerOpen(false) captureEvent(posthogRef.current, 'logs_filter_applied', { @@ -803,7 +805,13 @@ export const LogsToolbar = memo(function LogsToolbar({ showTrigger={false} open={datePickerOpen} onOpenChange={(isOpen) => { - if (!isOpen) handleDatePickerCancel() + if (!isOpen) { + if (dateRangeAppliedRef.current) { + dateRangeAppliedRef.current = false + } else { + handleDatePickerCancel() + } + } }} startDate={startDate} endDate={endDate} diff --git a/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx index 59fb73ec6d2..fa0373e4444 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/logs.tsx @@ -1259,6 +1259,7 @@ function LogsFilterPanel({ searchQuery, onSearchQueryChange }: LogsFilterPanelPr const [datePickerOpen, setDatePickerOpen] = useState(false) const [previousTimeRange, setPreviousTimeRange] = useState(timeRange) + const dateRangeAppliedRef = useRef(false) const { data: folders = {} } = useFolderMap(workspaceId) const { data: allWorkflowList = [] } = useWorkflows(workspaceId) @@ -1357,6 +1358,7 @@ function LogsFilterPanel({ searchQuery, onSearchQueryChange }: LogsFilterPanelPr } const handleDateRangeApply = (start: string, end: string) => { + dateRangeAppliedRef.current = true setDateRange(start, end) setDatePickerOpen(false) } @@ -1501,7 +1503,13 @@ function LogsFilterPanel({ searchQuery, onSearchQueryChange }: LogsFilterPanelPr showTrigger={false} open={datePickerOpen} onOpenChange={(isOpen) => { - if (!isOpen) handleDatePickerCancel() + if (!isOpen) { + if (dateRangeAppliedRef.current) { + dateRangeAppliedRef.current = false + } else { + handleDatePickerCancel() + } + } }} startDate={startDate} endDate={endDate}