From b03d1f5d58cb9bb2573abf523f321fb0a8d13ef3 Mon Sep 17 00:00:00 2001 From: waleed Date: Wed, 21 Jan 2026 20:14:30 -0800 Subject: [PATCH] styling --- .../document-tags-modal.tsx | 2 +- .../edit-chunk-modal/edit-chunk-modal.tsx | 2 +- .../rename-document-modal.tsx | 9 +- .../components/base-card/base-card.tsx | 43 ++- .../edit-knowledge-base-modal.tsx | 10 +- .../[workspaceId]/knowledge/knowledge.tsx | 11 +- .../[tableId]/components/action-bar.tsx | 31 --- .../[tableId]/components/body-states.tsx | 2 +- .../[tableId]/components/editable-cell.tsx | 207 +++++++++++++++ .../[tableId]/components/editable-row.tsx | 41 +++ .../[tableId]/components/filter-panel.tsx | 169 ++++++++++++ .../[tableId]/components/header-bar.tsx | 63 ----- .../tables/[tableId]/components/index.ts | 8 +- .../[tableId]/components/pagination.tsx | 40 --- .../components/query-builder/filter-row.tsx | 89 ------- .../components/query-builder/index.tsx | 137 ---------- .../components/query-builder/sort-row.tsx | 65 ----- .../tables/[tableId]/components/row-modal.tsx | 170 ++++++------ .../[tableId]/components/schema-modal.tsx | 38 ++- .../[tableId]/components/table-toolbar.tsx | 194 ++++++++++++++ .../[tableId]/components/table-viewer.tsx | 219 +++++++++------- .../[workspaceId]/tables/[tableId]/error.tsx | 71 ----- .../tables/[tableId]/hooks/index.ts | 1 + .../[tableId]/hooks/use-inline-editing.ts | 192 ++++++++++++++ .../tables/components/constants.ts | 14 + .../tables/components/create-modal.tsx | 245 ++++++++++-------- .../tables/components/empty-state.tsx | 2 +- .../tables/components/error-state.tsx | 11 +- .../[workspaceId]/tables/components/index.ts | 2 + .../components/table-card-context-menu.tsx | 152 +++++++++++ .../tables/components/table-card.tsx | 237 ++++++++--------- .../components/table-list-context-menu.tsx | 76 ++++++ .../tables/components/tables-view.tsx | 134 ++++++++-- .../workspace/[workspaceId]/tables/error.tsx | 41 --- .../[workspaceId]/tables/lib/utils.ts | 51 ++++ .../[workspaceId]/templates/templates.tsx | 6 +- .../table-selector/table-selector.tsx | 63 ++--- .../editor/components/sub-block/sub-block.tsx | 57 +++- 38 files changed, 1819 insertions(+), 1086 deletions(-) delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/action-bar.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/editable-cell.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/editable-row.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/filter-panel.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/header-bar.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/pagination.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/filter-row.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/index.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/sort-row.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-toolbar.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/error.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/hooks/use-inline-editing.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/components/constants.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/components/table-card-context-menu.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/components/table-list-context-menu.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/error.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx index 13c01e223..0556cbf46 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx @@ -555,7 +555,7 @@ export function DocumentTagsModal({ Cancel - diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx index b07e66dd1..a30f3eee2 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx @@ -1,8 +1,8 @@ 'use client' -import { useCallback, useState } from 'react' +import { useCallback, useRef, useState } from 'react' import { useParams, useRouter } from 'next/navigation' -import { Badge, DocumentAttachment, Tooltip } from '@/components/emcn' +import { Badge, Button, DocumentAttachment, Tooltip } from '@/components/emcn' import { BaseTagsModal } from '@/app/workspace/[workspaceId]/knowledge/[id]/components' import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' import { useContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/hooks' @@ -143,6 +143,7 @@ export function BaseCard({ const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false) const [isTagsModalOpen, setIsTagsModalOpen] = useState(false) const [isDeleting, setIsDeleting] = useState(false) + const menuButtonRef = useRef(null) const searchParams = new URLSearchParams({ kbName: title, @@ -151,6 +152,23 @@ export function BaseCard({ const shortId = id ? `kb-${id.slice(0, 8)}` : '' + const handleMenuButtonClick = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + if (menuButtonRef.current) { + const rect = menuButtonRef.current.getBoundingClientRect() + const syntheticEvent = { + preventDefault: () => {}, + stopPropagation: () => {}, + clientX: rect.right, + clientY: rect.bottom, + } as React.MouseEvent + handleContextMenu(syntheticEvent) + } + }, + [handleContextMenu] + ) + const handleClick = useCallback( (e: React.MouseEvent) => { if (isContextMenuOpen) { @@ -223,9 +241,24 @@ export function BaseCard({

{title}

- {shortId && ( - {shortId} - )} +
+ {shortId && ( + {shortId} + )} + +
diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/components/edit-knowledge-base-modal/edit-knowledge-base-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/edit-knowledge-base-modal/edit-knowledge-base-modal.tsx index 9732b662d..3eb0d5f4d 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/components/edit-knowledge-base-modal/edit-knowledge-base-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/components/edit-knowledge-base-modal/edit-knowledge-base-modal.tsx @@ -70,6 +70,12 @@ export function EditKnowledgeBaseModal({ }) const nameValue = watch('name') + const descriptionValue = watch('description') + + // Check if form values have changed from initial values + const hasChanges = + nameValue?.trim() !== initialName.trim() || + (descriptionValue?.trim() || '') !== (initialDescription?.trim() || '') useEffect(() => { if (open) { @@ -159,9 +165,9 @@ export function EditKnowledgeBaseModal({ Cancel diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx index 0be7e8f61..dfbd612d4 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx @@ -265,12 +265,11 @@ export function Knowledge() {
) : error ? ( -
-
-

- Error loading knowledge bases -

-

{error}

+
+
+ + Error: {typeof error === 'string' ? error : 'Failed to load knowledge bases'} +
) : ( diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/action-bar.tsx deleted file mode 100644 index c5472658a..000000000 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/action-bar.tsx +++ /dev/null @@ -1,31 +0,0 @@ -'use client' - -import { Trash2, X } from 'lucide-react' -import { Button } from '@/components/emcn' - -interface ActionBarProps { - selectedCount: number - onDelete: () => void - onClearSelection: () => void -} - -export function ActionBar({ selectedCount, onDelete, onClearSelection }: ActionBarProps) { - return ( -
-
- - {selectedCount} {selectedCount === 1 ? 'row' : 'rows'} selected - - -
- - -
- ) -} diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/body-states.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/body-states.tsx index 3f391ac1e..1303c6a37 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/body-states.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/body-states.tsx @@ -53,7 +53,7 @@ export function EmptyRows({ columnCount, hasFilter, onAddRow }: EmptyRowsProps) return ( -
+
{hasFilter ? 'No rows match your filter' : 'No data'} diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/editable-cell.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/editable-cell.tsx new file mode 100644 index 000000000..ae39f4373 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/editable-cell.tsx @@ -0,0 +1,207 @@ +'use client' + +import { useCallback, useEffect, useRef, useState } from 'react' +import { ChevronRight } from 'lucide-react' +import { Checkbox, Input, Textarea } from '@/components/emcn' +import { cn } from '@/lib/core/utils/cn' +import type { ColumnDefinition } from '@/lib/table' + +interface EditableCellProps { + value: unknown + column: ColumnDefinition + onChange: (value: unknown) => void + isEditing?: boolean + isNew?: boolean +} + +function formatValueForDisplay(value: unknown, type: string): string { + if (value === null || value === undefined) return 'NULL' + if (type === 'json') { + return typeof value === 'string' ? value : JSON.stringify(value) + } + if (type === 'boolean') { + return value ? 'TRUE' : 'FALSE' + } + if (type === 'date' && value) { + try { + const date = new Date(String(value)) + return date.toLocaleDateString('en-US', { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }) + } catch { + return String(value) + } + } + return String(value) +} + +function formatValueForInput(value: unknown, type: string): string { + if (value === null || value === undefined) return '' + if (type === 'json') { + return typeof value === 'string' ? value : JSON.stringify(value, null, 2) + } + if (type === 'date' && value) { + try { + const date = new Date(String(value)) + return date.toISOString().split('T')[0] + } catch { + return String(value) + } + } + return String(value) +} + +export function EditableCell({ + value, + column, + onChange, + isEditing = false, + isNew = false, +}: EditableCellProps) { + const [localValue, setLocalValue] = useState(value) + const [isActive, setIsActive] = useState(false) + const inputRef = useRef(null) + + useEffect(() => { + setLocalValue(value) + }, [value]) + + useEffect(() => { + if (isActive && inputRef.current) { + inputRef.current.focus() + } + }, [isActive]) + + const handleFocus = useCallback(() => { + setIsActive(true) + }, []) + + const handleBlur = useCallback(() => { + setIsActive(false) + if (localValue !== value) { + onChange(localValue) + } + }, [localValue, value, onChange]) + + const handleChange = useCallback((newValue: unknown) => { + setLocalValue(newValue) + }, []) + + const handleKeyDown = useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey && column.type !== 'json') { + e.preventDefault() + ;(e.target as HTMLElement).blur() + } + if (e.key === 'Escape') { + setLocalValue(value) + ;(e.target as HTMLElement).blur() + } + }, + [value, column.type] + ) + + const isNull = value === null || value === undefined + + // Boolean type - always show checkbox + if (column.type === 'boolean') { + return ( +
+ { + const newValue = checked === true + setLocalValue(newValue) + onChange(newValue) + }} + /> + + {localValue ? 'TRUE' : 'FALSE'} + +
+ ) + } + + // JSON type - use textarea + if (column.type === 'json') { + if (isActive || isNew) { + return ( +