Spaces:
Running
Running
'use client'; | |
import { useState, useEffect } from 'react'; | |
import * as duckdb from '@duckdb/duckdb-wasm'; | |
import Table from './components/Table'; | |
import Modal from './components/Modal'; | |
type ModelData = { | |
ancestor: string; | |
direct_children: string[] | null; | |
all_children: string[]; | |
all_children_count: number; | |
direct_children_count: number | null; | |
}; | |
type OrgData = { | |
org: string; | |
family_model_count: number; | |
family_direct_children_count: number; | |
family_all_children_count: number; | |
}; | |
export default function Home() { | |
const [allModels, setAllModels] = useState<ModelData[]>([]); | |
const [orgData, setOrgData] = useState<OrgData[]>([]); | |
const [currentPage, setCurrentPage] = useState(1); | |
const [pageSize, setPageSize] = useState(100); | |
const [filterText, setFilterText] = useState(''); | |
const [isLoading, setIsLoading] = useState(true); | |
const [orderBy, setOrderBy] = useState<'all_children' | 'direct_children'>('all_children'); | |
const [activeTab, setActiveTab] = useState<'models' | 'orgs'>('models'); | |
const [orgCurrentPage, setOrgCurrentPage] = useState(1); | |
const [orgPageSize, setOrgPageSize] = useState(100); | |
const [orgOrderBy, setOrgOrderBy] = useState<keyof OrgData>('family_all_children_count'); | |
const [orgFilterText, setOrgFilterText] = useState(''); | |
const [selectedModel, setSelectedModel] = useState<ModelData | null>(null); | |
const [selectedOrg, setSelectedOrg] = useState<string | null>(null); | |
const [selectedOrgModels, setSelectedOrgModels] = useState<ModelData[]>([]); | |
const [selectedModelChildren, setSelectedModelChildren] = useState<string[]>([]); | |
const [selectedModelChildrenType, setSelectedModelChildrenType] = useState<'direct' | 'all'>('all'); | |
const [modelChildrenPage, setModelChildrenPage] = useState(1); | |
const [orgModelsPage, setOrgModelsPage] = useState(1); | |
const modalPageSize = 10; | |
useEffect(() => { | |
const urlParams = new URLSearchParams(window.location.search); | |
const tab = urlParams.get('tab'); | |
const page = urlParams.get('page'); | |
const order = urlParams.get('order'); | |
const filter = urlParams.get('filter'); | |
const orgFilter = urlParams.get('orgFilter'); | |
if (tab === 'orgs') { | |
setActiveTab('orgs'); | |
} | |
if (page) { | |
setCurrentPage(parseInt(page, 10)); | |
} | |
if (order === 'direct_children') { | |
setOrderBy('direct_children'); | |
} else { | |
setOrderBy('all_children'); | |
} | |
if (filter) { | |
setFilterText(filter); | |
} | |
if (orgFilter) { | |
setOrgFilterText(orgFilter); | |
} | |
}, []); | |
useEffect(() => { | |
const urlParams = new URLSearchParams(); | |
if (activeTab === 'orgs') { | |
urlParams.set('tab', 'orgs'); | |
} | |
if (currentPage > 1) { | |
urlParams.set('page', currentPage.toString()); | |
} | |
if (orderBy === 'direct_children') { | |
urlParams.set('order', 'direct_children'); | |
} | |
if (filterText) { | |
urlParams.set('filter', filterText); | |
} | |
if (orgFilterText) { | |
urlParams.set('orgFilter', orgFilterText); | |
} | |
const newUrl = `${window.location.pathname}?${urlParams.toString()}`; | |
window.history.replaceState(null, '', newUrl); | |
}, [activeTab, currentPage, orderBy, filterText, orgFilterText]); | |
useEffect(() => { | |
async function fetchData() { | |
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles(); | |
// Select a bundle based on browser checks | |
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES); | |
const worker_url = URL.createObjectURL( | |
new Blob([`importScripts("${bundle.mainWorker!}");`], { type: 'text/javascript' }) | |
); | |
// Instantiate the asynchronous version of DuckDB-Wasm | |
const worker = new Worker(worker_url); | |
const logger = new duckdb.ConsoleLogger(); | |
const db = new duckdb.AsyncDuckDB(logger, worker); | |
await db.instantiate(bundle.mainModule, bundle.pthreadWorker); | |
// Register the Parquet file using the URL | |
await db.registerFileURL( | |
'ancestor_children.parquet', | |
`${window.location.origin}/ancestor_children.parquet`, | |
duckdb.DuckDBDataProtocol.HTTP, | |
false | |
); | |
// Execute the SQL query using the registered Parquet file | |
const query = ` | |
SELECT | |
ancestor, | |
direct_children, | |
all_children, | |
CAST(all_children_count AS INTEGER) AS all_children_count, | |
CAST(direct_children_count AS INTEGER) AS direct_children_count | |
FROM 'ancestor_children.parquet' | |
`; | |
const conn = await db.connect(); | |
const result = await conn.query(query); | |
// Convert the result to a JavaScript array | |
const data: ModelData[] = result.toArray(); | |
// Execute the SQL query to get the grouped org data with additional counts | |
const orgQuery = ` | |
SELECT | |
SPLIT_PART(ancestor, '/', 1) AS org, | |
CAST(COUNT(DISTINCT ancestor) AS INTEGER) AS family_model_count, | |
CAST(SUM(direct_children_count) AS INTEGER) AS family_direct_children_count, | |
CAST(SUM(all_children_count) AS INTEGER) AS family_all_children_count | |
FROM 'ancestor_children.parquet' | |
GROUP BY org | |
ORDER BY family_all_children_count DESC | |
`; | |
const orgResult = await conn.query(orgQuery); | |
// Convert the org result to a JavaScript array | |
const orgData: OrgData[] = orgResult.toArray(); | |
// Close the connection and terminate the worker | |
await conn.close(); | |
await db.terminate(); | |
setAllModels(data); | |
setOrgData(orgData); | |
setIsLoading(false); | |
} | |
fetchData(); | |
}, []); | |
const filteredModels = allModels.filter((model) => | |
model.ancestor.toLowerCase().includes(filterText.toLowerCase()) | |
); | |
const sortedModels = filteredModels.sort((a, b) => { | |
if (orderBy === 'all_children') { | |
return b.all_children_count - a.all_children_count; | |
} else { | |
return (b.direct_children_count ?? 0) - (a.direct_children_count ?? 0); | |
} | |
}); | |
const handleTabChange = (tab: 'models' | 'orgs') => { | |
setActiveTab(tab); | |
setCurrentPage(1); | |
setOrderBy('all_children'); | |
setFilterText(''); | |
setOrgFilterText(''); | |
}; | |
const handlePageChange = (page: number, tab: 'models' | 'orgs') => { | |
if (tab === 'models') { | |
setCurrentPage(page); | |
} else { | |
setOrgCurrentPage(page); | |
} | |
}; | |
const handleOrderByClick = (column: 'all_children' | 'direct_children') => { | |
setOrderBy(column); | |
setCurrentPage(1); | |
}; | |
const filteredOrgData = orgData.filter((org) => | |
org.org.toLowerCase().includes(orgFilterText.toLowerCase()) | |
); | |
const sortedOrgData = filteredOrgData.sort((a, b) => { | |
if (orgOrderBy === 'org') { | |
return a.org.localeCompare(b.org); | |
} | |
return b[orgOrderBy] - a[orgOrderBy]; | |
}); | |
const paginatedOrgData = sortedOrgData.slice( | |
(orgCurrentPage - 1) * orgPageSize, | |
orgCurrentPage * orgPageSize | |
); | |
const orgTotalPages = Math.ceil(sortedOrgData.length / orgPageSize); | |
const handleModelChildrenClick = (model: ModelData, type: 'direct' | 'all') => { | |
console.log('Model data:', model); | |
console.log('Children type:', type); | |
setSelectedModel(model); | |
setSelectedModelChildrenType(type); | |
let children; | |
if (type === 'direct') { | |
children = model.direct_children || []; | |
} else { | |
children = model.all_children || []; | |
} | |
console.log('Children:', children); | |
// Handle Vector data structure | |
if (children && typeof children === 'object' && 'get' in children && 'length' in children) { | |
const vectorChildren = []; | |
for (let i = 0; i < children.length; i++) { | |
vectorChildren.push(children.get(i)); | |
} | |
setSelectedModelChildren(vectorChildren); | |
} else if (Array.isArray(children)) { | |
setSelectedModelChildren(children); | |
} else { | |
console.error('Unexpected children data structure:', children); | |
setSelectedModelChildren([]); | |
} | |
}; | |
const handleOrgModelsClick = (org: string) => { | |
setSelectedOrg(org); | |
const orgModels = allModels.filter((model) => model.ancestor.split('/')[0] === org); | |
setSelectedOrgModels(orgModels); | |
}; | |
const handleModelChildrenPageChange = (page: number) => { | |
setModelChildrenPage(page); | |
}; | |
const handleOrgModelsPageChange = (page: number) => { | |
setOrgModelsPage(page); | |
}; | |
return ( | |
<main className="container mx-auto py-8 bg-white dark:bg-gray-900 text-gray-900 dark:text-white"> | |
<h1 className="text-4xl font-bold mb-4">All Models</h1> | |
<div className="mb-4 flex space-x-4"> | |
<a | |
href={`?tab=models`} | |
onClick={(e) => { | |
e.preventDefault(); | |
handleTabChange('models'); | |
}} | |
className={`px-4 py-2 rounded-md ${ | |
activeTab === 'models' | |
? 'bg-blue-500 dark:bg-blue-600 text-white' | |
: 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200' | |
}`} | |
> | |
Models | |
</a> | |
<a | |
href={`?tab=orgs`} | |
onClick={(e) => { | |
e.preventDefault(); | |
handleTabChange('orgs'); | |
}} | |
className={`px-4 py-2 rounded-md ${ | |
activeTab === 'orgs' | |
? 'bg-blue-500 dark:bg-blue-600 text-white' | |
: 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200' | |
}`} | |
> | |
Organizations | |
</a> | |
</div> | |
{activeTab === 'models' ? ( | |
<> | |
<div className="mb-4"> | |
<input | |
type="text" | |
placeholder="Filter by model name" | |
value={filterText} | |
onChange={(e) => setFilterText(e.target.value)} | |
className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-white" | |
/> | |
</div> | |
{isLoading ? ( | |
<p>Loading data...</p> | |
) : ( | |
<Table | |
data={sortedModels} | |
columns={[ | |
{ | |
key: 'ancestor', | |
label: 'Model', | |
}, | |
{ | |
key: 'direct_children_count', | |
label: 'Direct Children', | |
render: (value, row) => ( | |
<button | |
className="text-right text-blue-500 hover:underline" | |
onClick={() => handleModelChildrenClick(row, 'direct')} | |
> | |
{value ?? 0} | |
</button> | |
), | |
}, | |
{ | |
key: 'all_children_count', | |
label: 'All Children', | |
render: (value, row) => ( | |
<button | |
className="text-right text-blue-500 hover:underline" | |
onClick={() => handleModelChildrenClick(row, 'all')} | |
> | |
{value} | |
</button> | |
), | |
}, | |
]} | |
orderBy={orderBy} | |
onOrderByChange={(key) => { | |
if (key === 'all_children' || key === 'direct_children') { | |
setOrderBy(key); | |
setCurrentPage(1); | |
} | |
}} | |
pageSize={pageSize} | |
currentPage={currentPage} | |
onPageChange={(page) => handlePageChange(page, 'models')} | |
/> | |
)} | |
</> | |
) : ( | |
<> | |
<div className="mb-4"> | |
<input | |
type="text" | |
placeholder="Filter by organization name" | |
value={orgFilterText} | |
onChange={(e) => setOrgFilterText(e.target.value)} | |
className="px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-white" | |
/> | |
</div> | |
{isLoading ? ( | |
<p>Loading data...</p> | |
) : ( | |
<Table | |
data={paginatedOrgData} | |
columns={[ | |
{ | |
key: 'org', | |
label: 'Organization', | |
}, | |
{ | |
key: 'family_model_count', | |
label: 'Model Count', | |
render: (value, row) => ( | |
<button | |
className="text-right text-blue-500 hover:underline" | |
onClick={() => handleOrgModelsClick(row.org)} | |
> | |
{value} | |
</button> | |
), | |
}, | |
{ | |
key: 'family_direct_children_count', | |
label: 'Direct Children', | |
render: (value) => <span className="text-right">{value}</span>, | |
}, | |
{ | |
key: 'family_all_children_count', | |
label: 'All Children', | |
render: (value) => <span className="text-right">{value}</span>, | |
}, | |
]} | |
orderBy={orgOrderBy} | |
onOrderByChange={(key) => setOrgOrderBy(key)} | |
pageSize={orgPageSize} | |
currentPage={orgCurrentPage} | |
onPageChange={(page) => handlePageChange(page, 'orgs')} | |
/> | |
)} | |
</> | |
)} | |
{selectedModel && ( | |
<Modal onClose={() => { | |
setSelectedModel(null); | |
setModelChildrenPage(1); | |
}}> | |
<h2 className="text-2xl font-bold mb-4"> | |
{selectedModelChildrenType === 'direct' ? 'Direct Children' : 'All Children'} of {selectedModel.ancestor} | |
</h2> | |
{selectedModelChildren.length > 0 ? ( | |
<Table | |
data={selectedModelChildren.map((child, index) => ({ id: index, model: child }))} | |
columns={[{ key: 'model', label: 'Model' }]} | |
pageSize={modalPageSize} | |
currentPage={modelChildrenPage} | |
onPageChange={handleModelChildrenPageChange} | |
/> | |
) : ( | |
<p>No children found for this model.</p> | |
)} | |
</Modal> | |
)} | |
{selectedOrg && ( | |
<Modal onClose={() => { | |
setSelectedOrg(null); | |
setOrgModelsPage(1); | |
}}> | |
<h2 className="text-2xl font-bold mb-4">Models under {selectedOrg}</h2> | |
{selectedOrgModels.length > 0 ? ( | |
<Table | |
data={selectedOrgModels} | |
columns={[ | |
{ | |
key: 'ancestor', | |
label: 'Model', | |
}, | |
{ | |
key: 'direct_children_count', | |
label: 'Direct Children', | |
render: (value) => <span className="text-right">{value ?? 0}</span>, | |
}, | |
{ | |
key: 'all_children_count', | |
label: 'All Children', | |
render: (value) => <span className="text-right">{value}</span>, | |
}, | |
]} | |
pageSize={modalPageSize} | |
currentPage={orgModelsPage} | |
onPageChange={handleOrgModelsPageChange} | |
/> | |
) : ( | |
<p>No models found for this organization.</p> | |
)} | |
</Modal> | |
)} | |
</main> | |
); | |
} | |