Skip to content

Commit 9a50591

Browse files
committed
refactor, improvement
1 parent e6ca3b3 commit 9a50591

File tree

79 files changed

+1051
-389
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1051
-389
lines changed

apps/sim/app/_styles/globals.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@
105105
--text-tertiary: #5c5c5c;
106106
--text-muted: #707070;
107107
--text-subtle: #8c8c8c;
108+
--text-body: #3b3b3b;
109+
--text-icon: #5e5e5e;
110+
111+
--sidebar-font-weight: 420;
108112
--text-inverse: #ffffff;
109113
--text-muted-inverse: #a0a0a0;
110114
--text-error: #ef4444;
@@ -223,6 +227,10 @@
223227
--text-tertiary: #b3b3b3;
224228
--text-muted: #787878;
225229
--text-subtle: #7d7d7d;
230+
--text-body: #cdcdcd;
231+
--text-icon: #939393;
232+
233+
--sidebar-font-weight: 420;
226234
--text-inverse: #1b1b1b;
227235
--text-muted-inverse: #b3b3b3;
228236
--text-error: #ef4444;

apps/sim/app/api/logs/route.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,22 @@ import {
88
workflowExecutionLogs,
99
} from '@sim/db/schema'
1010
import { createLogger } from '@sim/logger'
11-
import { and, desc, eq, gte, gt, lt, lte, ne, inArray, isNotNull, isNull, or, type SQL, sql } from 'drizzle-orm'
11+
import {
12+
and,
13+
desc,
14+
eq,
15+
gt,
16+
gte,
17+
inArray,
18+
isNotNull,
19+
isNull,
20+
lt,
21+
lte,
22+
ne,
23+
or,
24+
type SQL,
25+
sql,
26+
} from 'drizzle-orm'
1227
import { type NextRequest, NextResponse } from 'next/server'
1328
import { z } from 'zod'
1429
import { getSession } from '@/lib/auth'
@@ -179,10 +194,18 @@ export async function GET(request: NextRequest) {
179194
}
180195

181196
// Workflow-specific filters exclude job logs entirely
182-
const hasWorkflowSpecificFilters = !!(params.workflowIds || params.folderIds || params.workflowName || params.folderName)
197+
const hasWorkflowSpecificFilters = !!(
198+
params.workflowIds ||
199+
params.folderIds ||
200+
params.workflowName ||
201+
params.folderName
202+
)
183203
// If triggers filter is set and doesn't include 'mothership', skip job logs
184204
const triggersList = params.triggers?.split(',').filter(Boolean) || []
185-
const triggersExcludeJobs = triggersList.length > 0 && !triggersList.includes('all') && !triggersList.includes('mothership')
205+
const triggersExcludeJobs =
206+
triggersList.length > 0 &&
207+
!triggersList.includes('all') &&
208+
!triggersList.includes('mothership')
186209
const includeJobLogs = !hasWorkflowSpecificFilters && !triggersExcludeJobs
187210

188211
const fetchSize = params.limit + params.offset
@@ -269,7 +292,7 @@ export async function GET(request: NextRequest) {
269292

270293
// Search by executionId
271294
if (params.search) {
272-
jobConditions.push(sql`${jobExecutionLogs.executionId} ILIKE ${'%' + params.search + '%'}`)
295+
jobConditions.push(sql`${jobExecutionLogs.executionId} ILIKE ${`%${params.search}%`}`)
273296
}
274297
if (params.executionId) {
275298
jobConditions.push(eq(jobExecutionLogs.executionId, params.executionId))
@@ -278,21 +301,34 @@ export async function GET(request: NextRequest) {
278301
// Cost filter
279302
if (params.costOperator && params.costValue !== undefined) {
280303
const costField = sql`(${jobExecutionLogs.cost}->>'total')::numeric`
281-
const ops = { '=': sql`=`, '>': sql`>`, '<': sql`<`, '>=': sql`>=`, '<=': sql`<=`, '!=': sql`!=` } as const
304+
const ops = {
305+
'=': sql`=`,
306+
'>': sql`>`,
307+
'<': sql`<`,
308+
'>=': sql`>=`,
309+
'<=': sql`<=`,
310+
'!=': sql`!=`,
311+
} as const
282312
jobConditions.push(sql`${costField} ${ops[params.costOperator]} ${params.costValue}`)
283313
}
284314

285315
// Duration filter
286316
if (params.durationOperator && params.durationValue !== undefined) {
287-
const durationOps: Record<string, (field: typeof jobExecutionLogs.totalDurationMs, val: number) => SQL | undefined> = {
317+
const durationOps: Record<
318+
string,
319+
(field: typeof jobExecutionLogs.totalDurationMs, val: number) => SQL | undefined
320+
> = {
288321
'=': (f, v) => eq(f, v),
289322
'>': (f, v) => gt(f, v),
290323
'<': (f, v) => lt(f, v),
291324
'>=': (f, v) => gte(f, v),
292325
'<=': (f, v) => lte(f, v),
293326
'!=': (f, v) => ne(f, v),
294327
}
295-
const durationCond = durationOps[params.durationOperator]?.(jobExecutionLogs.totalDurationMs, params.durationValue)
328+
const durationCond = durationOps[params.durationOperator]?.(
329+
jobExecutionLogs.totalDurationMs,
330+
params.durationValue
331+
)
296332
if (durationCond) jobConditions.push(durationCond)
297333
}
298334

@@ -309,18 +345,16 @@ export async function GET(request: NextRequest) {
309345
startedAt: jobExecutionLogs.startedAt,
310346
endedAt: jobExecutionLogs.endedAt,
311347
totalDurationMs: jobExecutionLogs.totalDurationMs,
312-
executionData: params.details === 'full' ? jobExecutionLogs.executionData : sql<null>`NULL`,
348+
executionData:
349+
params.details === 'full' ? jobExecutionLogs.executionData : sql<null>`NULL`,
313350
cost: jobExecutionLogs.cost,
314351
createdAt: jobExecutionLogs.createdAt,
315352
})
316353
.from(jobExecutionLogs)
317354
.where(jobWhere)
318355
.orderBy(desc(jobExecutionLogs.startedAt))
319356
.limit(fetchSize),
320-
db
321-
.select({ count: sql<number>`count(*)` })
322-
.from(jobExecutionLogs)
323-
.where(jobWhere),
357+
db.select({ count: sql<number>`count(*)` }).from(jobExecutionLogs).where(jobWhere),
324358
])
325359

326360
jobLogs = jobLogResults as typeof jobLogs
@@ -530,10 +564,7 @@ export async function GET(request: NextRequest) {
530564
trigger: execData.trigger,
531565
}
532566
: undefined,
533-
cost:
534-
params.details === 'full'
535-
? costSummary
536-
: { total: costSummary?.total || 0 },
567+
cost: params.details === 'full' ? costSummary : { total: costSummary?.total || 0 },
537568
hasPendingPause: false,
538569
}
539570
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export {
2+
ResourceContent,
3+
ResourceEmptyState,
4+
ResourceHeader,
5+
ResourceIconBadge,
6+
ResourceLayout,
7+
ResourceSearch,
8+
ResourceToolbar,
9+
} from './resource-layout'
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
'use client'
2+
3+
import type { ReactNode } from 'react'
4+
import { Search } from 'lucide-react'
5+
import { Input } from '@/components/ui/input'
6+
import { cn } from '@/lib/core/utils/cn'
7+
8+
interface ResourceLayoutProps {
9+
children: ReactNode
10+
onContextMenu?: (e: React.MouseEvent) => void
11+
}
12+
13+
/**
14+
* Shared wrapper for resource list pages (tables, files, knowledge, schedules).
15+
* Provides consistent padding, background, and scroll behaviour.
16+
*/
17+
export function ResourceLayout({ children, onContextMenu }: ResourceLayoutProps) {
18+
return (
19+
<div className='flex h-full flex-1 flex-col'>
20+
<div className='flex flex-1 overflow-hidden'>
21+
<div
22+
className='flex flex-1 flex-col overflow-auto bg-white px-6 pt-7 pb-6 dark:bg-[var(--bg)]'
23+
onContextMenu={onContextMenu}
24+
>
25+
{children}
26+
</div>
27+
</div>
28+
</div>
29+
)
30+
}
31+
32+
interface ResourceIconBadgeProps {
33+
icon: React.ElementType
34+
borderClassName: string
35+
bgClassName: string
36+
iconClassName: string
37+
}
38+
39+
/**
40+
* Coloured icon badge used in the resource header (26 x 26 rounded square).
41+
*/
42+
export function ResourceIconBadge({
43+
icon: Icon,
44+
borderClassName,
45+
bgClassName,
46+
iconClassName,
47+
}: ResourceIconBadgeProps) {
48+
return (
49+
<div
50+
className={cn(
51+
'flex h-[26px] w-[26px] items-center justify-center rounded-[6px] border',
52+
borderClassName,
53+
bgClassName
54+
)}
55+
>
56+
<Icon className={cn('h-[14px] w-[14px]', iconClassName)} />
57+
</div>
58+
)
59+
}
60+
61+
interface ResourceHeaderProps {
62+
icon: ReactNode
63+
title: string
64+
action?: ReactNode
65+
}
66+
67+
/**
68+
* Row 1 of the resource page: icon + title on the left, primary action on the right.
69+
*/
70+
export function ResourceHeader({ icon, title, action }: ResourceHeaderProps) {
71+
return (
72+
<div className='flex items-center justify-between'>
73+
<div className='flex items-center gap-3'>
74+
{icon}
75+
<h1 className='font-medium text-[18px] leading-none'>{title}</h1>
76+
</div>
77+
{action && <div className='flex items-center gap-2'>{action}</div>}
78+
</div>
79+
)
80+
}
81+
82+
interface ResourceToolbarProps {
83+
children?: ReactNode
84+
actions?: ReactNode
85+
}
86+
87+
/**
88+
* Row 2 of the resource page: filter / sort controls on the left, secondary actions on the right.
89+
*/
90+
export function ResourceToolbar({ children, actions }: ResourceToolbarProps) {
91+
return (
92+
<div className='mt-3.5 flex items-center justify-between'>
93+
<div className='flex items-center gap-2'>{children}</div>
94+
{actions && <div className='flex items-center gap-2'>{actions}</div>}
95+
</div>
96+
)
97+
}
98+
99+
interface ResourceSearchProps {
100+
value: string
101+
onChange: (value: string) => void
102+
placeholder?: string
103+
disabled?: boolean
104+
className?: string
105+
}
106+
107+
/**
108+
* Inline search input used inside `ResourceToolbar`.
109+
*/
110+
export function ResourceSearch({
111+
value,
112+
onChange,
113+
placeholder = 'Search',
114+
disabled,
115+
className,
116+
}: ResourceSearchProps) {
117+
return (
118+
<div
119+
className={cn(
120+
'flex h-8 w-60 items-center gap-1.5 rounded-lg bg-[var(--surface-4)] px-2',
121+
disabled && 'opacity-50',
122+
className
123+
)}
124+
>
125+
<Search className='h-3.5 w-3.5 text-[var(--text-subtle)]' />
126+
<Input
127+
placeholder={placeholder}
128+
value={value}
129+
onChange={(e) => onChange(e.target.value)}
130+
disabled={disabled}
131+
className='flex-1 border-0 bg-transparent px-0 font-medium text-[var(--text-secondary)] text-small leading-none placeholder:text-[var(--text-subtle)] focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-100'
132+
/>
133+
</div>
134+
)
135+
}
136+
137+
interface ResourceContentProps {
138+
children: ReactNode
139+
className?: string
140+
}
141+
142+
/**
143+
* Scrollable content area below the toolbar. Holds the list/table.
144+
*/
145+
export function ResourceContent({ children, className }: ResourceContentProps) {
146+
return <div className={cn('mt-4 min-h-0 flex-1', className)}>{children}</div>
147+
}
148+
149+
interface ResourceEmptyStateProps {
150+
title: string
151+
description?: string
152+
}
153+
154+
/**
155+
* Centred empty state used when there are no items.
156+
*/
157+
export function ResourceEmptyState({ title, description }: ResourceEmptyStateProps) {
158+
return (
159+
<div className='flex h-64 items-center justify-center'>
160+
<div className='text-center'>
161+
<p className='font-medium text-[var(--text-secondary)] text-sm'>{title}</p>
162+
{description && <p className='mt-1 text-[var(--text-muted)] text-xs'>{description}</p>}
163+
</div>
164+
</div>
165+
)
166+
}

apps/sim/app/workspace/[workspaceId]/files/components/file-list.tsx renamed to apps/sim/app/workspace/[workspaceId]/files/components/file-list/file-list.tsx

File renamed without changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { FileList } from './file-list'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { FileList } from './file-list'

apps/sim/app/workspace/[workspaceId]/files/files.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { Files as FilesIcon } from 'lucide-react'
4-
import { FileList } from '@/app/workspace/[workspaceId]/files/components/file-list'
4+
import { FileList } from '@/app/workspace/[workspaceId]/files/components'
55

66
export function Files() {
77
return (

apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const TEXTAREA_CLASSES = cn(
1111
'overflow-y-auto overflow-x-hidden break-words border-0 bg-transparent',
1212
'px-[4px] py-[4px] font-body text-[15px] leading-[24px] tracking-[-0.015em]',
1313
'text-[var(--text-primary)] outline-none',
14-
'placeholder:font-[350] placeholder:text-[var(--text-subtle)]',
14+
'placeholder:font-[380] placeholder:text-[var(--text-subtle)]',
1515
'focus-visible:ring-0 focus-visible:ring-offset-0',
1616
'[-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden'
1717
)

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-connector-modal/add-connector-modal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use client'
22

33
import { useMemo, useState } from 'react'
4-
import { useParams } from 'next/navigation'
54
import { ArrowLeft, Loader2, Plus } from 'lucide-react'
5+
import { useParams } from 'next/navigation'
66
import {
77
Button,
88
ButtonGroup,

0 commit comments

Comments
 (0)