()
| 66 | ] |
| 67 | |
| 68 | export function Tables() { |
| 69 | const params = useParams() |
| 70 | const router = useRouter() |
| 71 | const workspaceId = params.workspaceId as string |
| 72 | |
| 73 | const { config: permissionConfig } = usePermissionConfig() |
| 74 | useEffect(() => { |
| 75 | if (permissionConfig.hideTablesTab) { |
| 76 | router.replace(`/workspace/${workspaceId}`) |
| 77 | } |
| 78 | }, [permissionConfig.hideTablesTab, router, workspaceId]) |
| 79 | |
| 80 | const userPermissions = useUserPermissionsContext() |
| 81 | |
| 82 | const { data: tables = [], error } = useTablesList(workspaceId) |
| 83 | const { data: members } = useWorkspaceMembersQuery(workspaceId) |
| 84 | |
| 85 | if (error) { |
| 86 | logger.error('Failed to load tables:', error) |
| 87 | } |
| 88 | const deleteTable = useDeleteTable(workspaceId) |
| 89 | const renameTable = useRenameTable(workspaceId) |
| 90 | const createTable = useCreateTable(workspaceId) |
| 91 | const uploadCsv = useUploadCsvToTable() |
| 92 | const importCsvAsync = useImportCsvAsync() |
| 93 | |
| 94 | const tableRename = useInlineRename({ |
| 95 | onSave: (tableId, name) => renameTable.mutateAsync({ tableId, name }), |
| 96 | }) |
| 97 | |
| 98 | const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false) |
| 99 | const [isImportDialogOpen, setIsImportDialogOpen] = useState(false) |
| 100 | const [activeTable, setActiveTable] = useState<TableDefinition | null>(null) |
| 101 | |
| 102 | const [ |
| 103 | { |
| 104 | search: urlSearchTerm, |
| 105 | sort: sortColumn, |
| 106 | dir: sortDirection, |
| 107 | rows: rowCountFilter, |
| 108 | owner: ownerFilter, |
| 109 | }, |
| 110 | setTableFilters, |
| 111 | ] = useQueryStates(tablesParsers, tablesUrlKeys) |
| 112 | |
| 113 | /** |
| 114 | * The input is controlled directly by the instant nuqs value; only the URL |
| 115 | * write is debounced. The in-memory filter below still reads a debounced value |
| 116 | * so it doesn't recompute on every keystroke. |
| 117 | */ |
| 118 | const setSearchTerm = useCallback( |
| 119 | (value: string) => { |
| 120 | const trimmed = value.trim() |
| 121 | const next = trimmed.length > 0 ? trimmed : null |
| 122 | setTableFilters( |
| 123 | { search: next }, |
| 124 | next === null ? undefined : { limitUrlUpdates: debounce(SEARCH_DEBOUNCE_MS) } |
| 125 | ) |
nothing calls this directly
no test coverage detected