Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
refactor(files): extract shared DataTable, isolate client-safe constants
- Move SUPPORTED_CODE_EXTENSIONS to validation-constants.ts so client
  components no longer transitively import Node's `path` module
- Extract shared DataTable component used by both CsvPreview and
  XlsxPreview, eliminating duplicated table markup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • Loading branch information
waleedlatif1 and claude committed Apr 5, 2026
commit a7b732be3563bf8640e7ec80eff11f7c9143d929
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { memo } from 'react'

interface DataTableProps {
headers: string[]
rows: string[][]
}

export const DataTable = memo(function DataTable({ headers, rows }: DataTableProps) {
return (
<div className='overflow-x-auto rounded-md border border-[var(--border)]'>
<table className='w-full border-collapse text-[13px]'>
<thead className='bg-[var(--surface-2)]'>
<tr>
{headers.map((header, i) => (
<th
key={i}
className='whitespace-nowrap px-3 py-2 text-left font-semibold text-[12px] text-[var(--text-primary)]'
>
{String(header ?? '')}
</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, ri) => (
<tr key={ri} className='border-[var(--border)] border-t'>
{headers.map((_, ci) => (
<td
key={ci}
className='whitespace-nowrap px-3 py-2 text-[var(--text-secondary)]'
>
{String(row[ci] ?? '')}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { Skeleton } from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
import { getFileExtension } from '@/lib/uploads/utils/file-utils'
import { SUPPORTED_CODE_EXTENSIONS } from '@/lib/uploads/utils/validation'
import { SUPPORTED_CODE_EXTENSIONS } from '@/lib/uploads/utils/validation-constants'
import {
useUpdateWorkspaceFileContent,
useWorkspaceFileBinary,
useWorkspaceFileContent,
} from '@/hooks/queries/workspace-files'
import { useAutosave } from '@/hooks/use-autosave'
import { useStreamingText } from '@/hooks/use-streaming-text'
import { DataTable } from './data-table'
import { PreviewPanel, resolvePreviewType } from './preview-panel'

const logger = createLogger('FileViewer')
Expand Down Expand Up @@ -1058,39 +1059,11 @@ const XlsxPreview = memo(function XlsxPreview({
</div>
)}
<div className='flex-1 overflow-auto p-6'>
<div className='overflow-x-auto rounded-md border border-[var(--border)]'>
<table className='w-full border-collapse text-[13px]'>
<thead className='bg-[var(--surface-2)]'>
<tr>
{currentSheet.headers.map((header, i) => (
<th
key={i}
className='whitespace-nowrap px-3 py-2 text-left font-semibold text-[12px] text-[var(--text-primary)]'
>
{String(header ?? '')}
</th>
))}
</tr>
</thead>
<tbody>
{currentSheet.rows.map((row, ri) => (
<tr key={ri} className='border-[var(--border)] border-t'>
{currentSheet.headers.map((_, ci) => (
<td
key={ci}
className='whitespace-nowrap px-3 py-2 text-[var(--text-secondary)]'
>
{String(row[ci] ?? '')}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
<DataTable headers={currentSheet.headers} rows={currentSheet.rows} />
{currentSheet.truncated && (
<p className='mt-3 text-center text-[12px] text-[var(--text-muted)]'>
Showing first {XLSX_MAX_ROWS.toLocaleString()} rows. Download the file to view all data.
Showing first {XLSX_MAX_ROWS.toLocaleString()} rows. Download the file to view all
data.
</p>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import remarkGfm from 'remark-gfm'
import { Checkbox } from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import { getFileExtension } from '@/lib/uploads/utils/file-utils'
import { DataTable } from './data-table'
import { useAutoScroll } from '@/hooks/use-auto-scroll'
import { useStreamingReveal } from '@/hooks/use-streaming-reveal'

Expand Down Expand Up @@ -486,33 +487,7 @@ const CsvPreview = memo(function CsvPreview({ content }: { content: string }) {

return (
<div className='h-full overflow-auto p-6'>
<div className='overflow-x-auto rounded-md border border-[var(--border)]'>
<table className='w-full border-collapse text-[13px]'>
<thead className='bg-[var(--surface-2)]'>
<tr>
{headers.map((header, i) => (
<th
key={i}
className='whitespace-nowrap px-3 py-2 text-left font-semibold text-[12px] text-[var(--text-primary)]'
>
{header}
</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, ri) => (
<tr key={ri} className='border-[var(--border)] border-t'>
{headers.map((_, ci) => (
<td key={ci} className='whitespace-nowrap px-3 py-2 text-[var(--text-secondary)]'>
{row[ci] ?? ''}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
<DataTable headers={headers} rows={rows} />
</div>
)
})
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/app/workspace/[workspaceId]/files/files.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ import {
isAudioFileType,
isVideoFileType,
} from '@/lib/uploads/utils/file-utils'
import { SUPPORTED_CODE_EXTENSIONS } from '@/lib/uploads/utils/validation-constants'
import {
isSupportedExtension,
SUPPORTED_AUDIO_EXTENSIONS,
SUPPORTED_CODE_EXTENSIONS,
SUPPORTED_DOCUMENT_EXTENSIONS,
SUPPORTED_VIDEO_EXTENSIONS,
} from '@/lib/uploads/utils/validation'
Expand Down
52 changes: 52 additions & 0 deletions apps/sim/lib/uploads/utils/validation-constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Extension constants that are safe to import from client components.
* Separated from validation.ts which imports Node's `path` module.
*/

export const SUPPORTED_CODE_EXTENSIONS = [
'mdx',
'xml',
'css',
'scss',
'less',
'js',
'jsx',
'ts',
'tsx',
'py',
'rb',
'go',
'rs',
'java',
'kt',
'swift',
'c',
'cpp',
'h',
'hpp',
'cs',
'php',
'sh',
'bash',
'zsh',
'fish',
'sql',
'graphql',
'gql',
'toml',
'ini',
'conf',
'cfg',
'env',
'log',
'diff',
'patch',
'dockerfile',
'makefile',
'gitignore',
'editorconfig',
'prettierrc',
'eslintrc',
] as const

export type SupportedCodeExtension = (typeof SUPPORTED_CODE_EXTENSIONS)[number]
51 changes: 3 additions & 48 deletions apps/sim/lib/uploads/utils/validation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import path from 'path'

export { SUPPORTED_CODE_EXTENSIONS } from '@/lib/uploads/utils/validation-constants'
export type { SupportedCodeExtension } from '@/lib/uploads/utils/validation-constants'

/**
* Checks whether a string is a valid file extension (lowercase alphanumeric only).
* Rejects extensions containing spaces, punctuation, or other non-alphanumeric characters
Expand Down Expand Up @@ -29,54 +32,6 @@ export const SUPPORTED_DOCUMENT_EXTENSIONS = [
'yml',
] as const

export const SUPPORTED_CODE_EXTENSIONS = [
'mdx',
'xml',
'css',
'scss',
'less',
'js',
'jsx',
'ts',
'tsx',
'py',
'rb',
'go',
'rs',
'java',
'kt',
'swift',
'c',
'cpp',
'h',
'hpp',
'cs',
'php',
'sh',
'bash',
'zsh',
'fish',
'sql',
'graphql',
'gql',
'toml',
'ini',
'conf',
'cfg',
'env',
'log',
'diff',
'patch',
'dockerfile',
'makefile',
'gitignore',
'editorconfig',
'prettierrc',
'eslintrc',
] as const

export type SupportedCodeExtension = (typeof SUPPORTED_CODE_EXTENSIONS)[number]

export const SUPPORTED_AUDIO_EXTENSIONS = [
'mp3',
'm4a',
Expand Down
Loading