From ebbc3c9e006f9b8d7208876624a19537ff899f2c Mon Sep 17 00:00:00 2001 From: KushagraJaiswar02 Date: Mon, 30 Mar 2026 01:20:27 +0530 Subject: [PATCH] fix: infer table columns from documents for schema-less collections Collections with model: [] showed blank table views even when documents existed. Column definitions are now derived from the first document keys when model is empty. View toggles visible for any collection with documents. Boolean values render as true/false instead of blank. --- .../src/components/CollectionTable.jsx | 42 +++++++++++---- apps/web-dashboard/src/pages/Database.jsx | 54 ++++++++++--------- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/apps/web-dashboard/src/components/CollectionTable.jsx b/apps/web-dashboard/src/components/CollectionTable.jsx index d90c09757..03db79fd1 100644 --- a/apps/web-dashboard/src/components/CollectionTable.jsx +++ b/apps/web-dashboard/src/components/CollectionTable.jsx @@ -77,7 +77,31 @@ const DraggableColumnHeader = ({ header, children, style: propStyle, className } export default function CollectionTable({ data, activeCollection, onDelete, onView, onEdit }) { // 1. Column Definitions const columns = useMemo(() => { - if (!activeCollection?.model) return []; + if (!activeCollection) return []; + + const SYSTEM_FIELDS = ['_id', '__v', 'createdAt', 'updatedAt']; + + const inferType = (value) => { + if (typeof value === 'boolean') return 'BOOLEAN'; + if (typeof value === 'number') return 'NUMBER'; + if (Array.isArray(value)) return 'ARRAY'; + return 'STRING'; + }; + + const baseColumns = activeCollection.model?.length > 0 + ? activeCollection.model.map(field => ({ + key: field.key, + type: field.type + })) + : data?.length > 0 + ? Object.entries(data[0]) + .filter(([key]) => !SYSTEM_FIELDS.includes(key)) + .map(([key, value]) => ({ + key, + type: inferType(value) + })) + : []; + return [ { id: "rowNumber", @@ -87,11 +111,10 @@ export default function CollectionTable({ data, activeCollection, onDelete, onVi enableResizing: false, enableHiding: false, }, - ...activeCollection.model.map((field) => ({ - id: field.key, // Explicit ID matches accessorKey usually + ...baseColumns.map((field) => ({ + id: field.key, header: () => (
- {/* Drag Handle Indicator (Visual only, whole header is draggable) */} {field.key} {field.type} @@ -103,6 +126,7 @@ export default function CollectionTable({ data, activeCollection, onDelete, onVi maxSize: 500, cell: (info) => { const value = info.getValue(); + if (value === null || value === undefined) return ; if (typeof value === "boolean") { return ( @@ -110,8 +134,7 @@ export default function CollectionTable({ data, activeCollection, onDelete, onVi ); } - // Object type — show preview - if (value !== null && typeof value === "object" && !Array.isArray(value)) { + if (typeof value === "object" && !Array.isArray(value)) { const keys = Object.keys(value).filter(k => !k.startsWith('_')); return (
); } - // Array type — show count if (Array.isArray(value)) { return (
- {String(value ?? '')} +
+ {String(value)}
); }, @@ -183,7 +205,7 @@ export default function CollectionTable({ data, activeCollection, onDelete, onVi ), }, ]; - }, [activeCollection, onDelete, onView, onEdit]); + }, [activeCollection, data, onDelete, onView, onEdit]); // 2. Load Persisted State const storageKey = `table-settings-${activeCollection?._id}`; diff --git a/apps/web-dashboard/src/pages/Database.jsx b/apps/web-dashboard/src/pages/Database.jsx index 051c5eb77..04a5cd06b 100644 --- a/apps/web-dashboard/src/pages/Database.jsx +++ b/apps/web-dashboard/src/pages/Database.jsx @@ -413,32 +413,34 @@ export default function Database() {
{data.length} Records -
- - - -
+ {(activeCollection?.model?.length > 0 || data?.length > 0) && ( +
+ + + +
+ )}