mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-22 05:18:08 -05:00
updates
This commit is contained in:
@@ -21,9 +21,9 @@ import {
|
||||
import type { ColumnDefinition } from '@/lib/table'
|
||||
import { useCreateTable } from '@/hooks/queries/use-tables'
|
||||
|
||||
const logger = createLogger('CreateTableModal')
|
||||
const logger = createLogger('CreateModal')
|
||||
|
||||
interface CreateTableModalProps {
|
||||
interface CreateModalProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
}
|
||||
@@ -44,7 +44,7 @@ function createEmptyColumn(): ColumnWithId {
|
||||
return { id: nanoid(), name: '', type: 'string', required: true, unique: false }
|
||||
}
|
||||
|
||||
export function CreateTableModal({ isOpen, onClose }: CreateTableModalProps) {
|
||||
export function CreateModal({ isOpen, onClose }: CreateModalProps) {
|
||||
const params = useParams()
|
||||
const workspaceId = params.workspaceId as string
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
interface EmptyStateProps {
|
||||
hasSearchQuery: boolean
|
||||
}
|
||||
|
||||
export function EmptyState({ hasSearchQuery }: EmptyStateProps) {
|
||||
return (
|
||||
<div className='col-span-full flex h-64 items-center justify-center rounded-[4px] bg-[var(--surface-3)] dark:bg-[var(--surface-4)]'>
|
||||
<div className='text-center'>
|
||||
<p className='font-medium text-[var(--text-secondary)] text-sm'>
|
||||
{hasSearchQuery ? 'No tables found' : 'No tables yet'}
|
||||
</p>
|
||||
<p className='mt-1 text-[var(--text-muted)] text-xs'>
|
||||
{hasSearchQuery
|
||||
? 'Try adjusting your search query'
|
||||
: 'Create your first table to store structured data for your workflows'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
interface ErrorStateProps {
|
||||
error: unknown
|
||||
}
|
||||
|
||||
export function ErrorState({ error }: ErrorStateProps) {
|
||||
return (
|
||||
<div className='col-span-full flex h-64 items-center justify-center rounded-[4px] bg-[var(--surface-3)] dark:bg-[var(--surface-4)]'>
|
||||
<div className='text-center'>
|
||||
<p className='font-medium text-[var(--text-secondary)] text-sm'>Error loading tables</p>
|
||||
<p className='mt-1 text-[var(--text-muted)] text-xs'>
|
||||
{error instanceof Error ? error.message : 'An error occurred'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,2 +1,6 @@
|
||||
export * from './create-table-modal'
|
||||
export * from './create-modal'
|
||||
export * from './empty-state'
|
||||
export * from './error-state'
|
||||
export * from './loading-state'
|
||||
export * from './table-card'
|
||||
export * from './tables-view'
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
export function LoadingState() {
|
||||
return (
|
||||
<>
|
||||
{Array.from({ length: 8 }).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className='flex h-full flex-col gap-[12px] rounded-[4px] bg-[var(--surface-3)] px-[8px] py-[6px] dark:bg-[var(--surface-4)]'
|
||||
>
|
||||
<div className='flex items-center justify-between gap-[8px]'>
|
||||
<div className='h-[17px] w-[120px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
<div className='h-[22px] w-[90px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
<div className='flex flex-1 flex-col gap-[8px]'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex items-center gap-[12px]'>
|
||||
<div className='h-[15px] w-[50px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
<div className='h-[15px] w-[50px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
<div className='h-[15px] w-[60px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
<div className='h-0 w-full border-[var(--divider)] border-t' />
|
||||
<div className='flex h-[36px] flex-col gap-[6px]'>
|
||||
<div className='h-[15px] w-full animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
<div className='h-[15px] w-[75%] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -26,8 +26,8 @@ import {
|
||||
} from '@/components/emcn'
|
||||
import type { TableDefinition } from '@/lib/table'
|
||||
import { useDeleteTable } from '@/hooks/queries/use-tables'
|
||||
import { getTypeBadgeVariant } from '../[tableId]/table-data-viewer/utils'
|
||||
import { formatAbsoluteDate, formatRelativeTime } from './utils'
|
||||
import { getTypeBadgeVariant } from '../[tableId]/lib/utils'
|
||||
import { formatAbsoluteDate, formatRelativeTime } from '../lib/utils'
|
||||
|
||||
const logger = createLogger('TableCard')
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@ import { Input } from '@/components/ui/input'
|
||||
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
|
||||
import { useTablesList } from '@/hooks/queries/use-tables'
|
||||
import { useDebounce } from '@/hooks/use-debounce'
|
||||
import { CreateTableModal } from './components/create-table-modal'
|
||||
import { TableCard } from './components/table-card'
|
||||
import { CreateModal } from './create-modal'
|
||||
import { EmptyState } from './empty-state'
|
||||
import { ErrorState } from './error-state'
|
||||
import { LoadingState } from './loading-state'
|
||||
import { TableCard } from './table-card'
|
||||
|
||||
export function Tables() {
|
||||
export function TablesView() {
|
||||
const params = useParams()
|
||||
const workspaceId = params.workspaceId as string
|
||||
const userPermissions = useUserPermissionsContext()
|
||||
@@ -84,7 +87,7 @@ export function Tables() {
|
||||
{/* Content */}
|
||||
<div className='mt-[24px] grid grid-cols-1 gap-[20px] md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'>
|
||||
{isLoading ? (
|
||||
<LoadingSkeletons />
|
||||
<LoadingState />
|
||||
) : error ? (
|
||||
<ErrorState error={error} />
|
||||
) : filteredTables.length === 0 ? (
|
||||
@@ -99,69 +102,7 @@ export function Tables() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CreateTableModal isOpen={isCreateModalOpen} onClose={() => setIsCreateModalOpen(false)} />
|
||||
<CreateModal isOpen={isCreateModalOpen} onClose={() => setIsCreateModalOpen(false)} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function LoadingSkeletons() {
|
||||
return (
|
||||
<>
|
||||
{Array.from({ length: 8 }).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className='flex h-full flex-col gap-[12px] rounded-[4px] bg-[var(--surface-3)] px-[8px] py-[6px] dark:bg-[var(--surface-4)]'
|
||||
>
|
||||
<div className='flex items-center justify-between gap-[8px]'>
|
||||
<div className='h-[17px] w-[120px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
<div className='h-[22px] w-[90px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
<div className='flex flex-1 flex-col gap-[8px]'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex items-center gap-[12px]'>
|
||||
<div className='h-[15px] w-[50px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
<div className='h-[15px] w-[50px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
<div className='h-[15px] w-[60px] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
<div className='h-0 w-full border-[var(--divider)] border-t' />
|
||||
<div className='flex h-[36px] flex-col gap-[6px]'>
|
||||
<div className='h-[15px] w-full animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
<div className='h-[15px] w-[75%] animate-pulse rounded-[4px] bg-[var(--surface-4)] dark:bg-[var(--surface-5)]' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function ErrorState({ error }: { error: unknown }) {
|
||||
return (
|
||||
<div className='col-span-full flex h-64 items-center justify-center rounded-[4px] bg-[var(--surface-3)] dark:bg-[var(--surface-4)]'>
|
||||
<div className='text-center'>
|
||||
<p className='font-medium text-[var(--text-secondary)] text-sm'>Error loading tables</p>
|
||||
<p className='mt-1 text-[var(--text-muted)] text-xs'>
|
||||
{error instanceof Error ? error.message : 'An error occurred'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function EmptyState({ hasSearchQuery }: { hasSearchQuery: boolean }) {
|
||||
return (
|
||||
<div className='col-span-full flex h-64 items-center justify-center rounded-[4px] bg-[var(--surface-3)] dark:bg-[var(--surface-4)]'>
|
||||
<div className='text-center'>
|
||||
<p className='font-medium text-[var(--text-secondary)] text-sm'>
|
||||
{hasSearchQuery ? 'No tables found' : 'No tables yet'}
|
||||
</p>
|
||||
<p className='mt-1 text-[var(--text-muted)] text-xs'>
|
||||
{hasSearchQuery
|
||||
? 'Try adjusting your search query'
|
||||
: 'Create your first table to store structured data for your workflows'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
1
apps/sim/app/workspace/[workspaceId]/tables/lib/index.ts
Normal file
1
apps/sim/app/workspace/[workspaceId]/tables/lib/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './utils'
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Formats a date as relative time (e.g., "5m ago", "2d ago")
|
||||
*/
|
||||
export function formatRelativeTime(dateValue: string | Date): string {
|
||||
const dateString = typeof dateValue === 'string' ? dateValue : dateValue.toISOString()
|
||||
const date = new Date(dateString)
|
||||
@@ -13,6 +16,9 @@ export function formatRelativeTime(dateValue: string | Date): string {
|
||||
return `${Math.floor(diffInSeconds / 31536000)}y ago`
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a date as absolute date string (e.g., "Jan 15, 2024, 10:30 AM")
|
||||
*/
|
||||
export function formatAbsoluteDate(dateValue: string | Date): string {
|
||||
const dateString = typeof dateValue === 'string' ? dateValue : dateValue.toISOString()
|
||||
const date = new Date(dateString)
|
||||
@@ -1,7 +1,7 @@
|
||||
import { redirect } from 'next/navigation'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { verifyWorkspaceMembership } from '@/app/api/workflows/utils'
|
||||
import { Tables } from './tables'
|
||||
import { TablesView } from './components'
|
||||
|
||||
interface TablesPageProps {
|
||||
params: Promise<{
|
||||
@@ -22,5 +22,5 @@ export default async function TablesPage({ params }: TablesPageProps) {
|
||||
redirect('/')
|
||||
}
|
||||
|
||||
return <Tables />
|
||||
return <TablesView />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user