Implementation:TobikoData Sqlmesh Models Page
| Knowledge Sources | |
|---|---|
| Domains | Web_UI, Data_Catalog, Model_Management |
| Last Updated | 2026-02-07 20:00 GMT |
Overview
Models page component displaying a navigable list of SQLMesh models organized by namespace with search and detail view capabilities.
Description
PageModels provides a comprehensive model browser interface with sidebar navigation organized by namespace/schema and a detail view area for model-specific content. The page uses TBKSourceList with collapsible sections grouped by model namespace, implements SearchList for quick model filtering, and synchronizes model selection with URL routing and project file state.
Key features include namespace-based model organization extracted from fully qualified names, TBKModelName component for displaying model names with badges showing model type (SQL, Python, Seed, External), synchronized file selection when model has associated file path, automatic navigation to lastSelectedModel on mount, NotFound page for invalid model names, and loading states during model fetching.
The page uses TBKResizeObserver to dynamically update model name display widths and supports nested routing via Outlet for model detail views.
Usage
Use this page to browse all SQLMesh models in a project, search for specific models, and navigate to detailed model views organized by namespace.
Code Reference
Source Location
- Repository: TobikoData_Sqlmesh
- File: web/client/src/library/pages/models/Models.tsx
Signature
export default function PageModels({
route = EnumRoutes.Home
}: {
route: Routes
}): JSX.Element
Import
import PageModels from '@library/pages/models/Models'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| route | Routes | No | Base route for model navigation (defaults to EnumRoutes.Home) |
| modelName | string (URL param) | No | Selected model name from route |
Outputs
| Component | Type | Description |
|---|---|---|
| JSX.Element | React Component | Page with model list sidebar and detail outlet |
Usage Examples
// Route configuration
<Route
path={EnumRoutes.DataCatalog}
element={<PageModels route={EnumRoutes.DataCatalog} />}
>
<Route path="models/:modelName" element={<ModelDetailView />} />
</Route>
// Page structure:
// ┌───────────────────────┬─────────────────────┐
// │ [Search Models...] │ │
// ├───────────────────────┤ Model Detail View │
// │ Namespace: analytics │ │
// │ ├─ customers [SQL] │ (Outlet content) │
// │ ├─ orders [SQL] │ │
// │ ├─ revenue [Python] │ │
// │ │ │
// │ Namespace: staging │ │
// │ ├─ raw_data [Seed] │ │
// │ └─ external [External]│ │
// └───────────────────────┴─────────────────────┘
// Model categorization by namespace
const categorized = ModelName.categorize(list)
// Returns:
// {
// "analytics": [model1, model2, model3],
// "staging": [model4, model5],
// "raw": [model6]
// }
// Model list item rendering
<TBKSourceListItem
key={model.name}
size="xs"
hide-icon
active={pathname === `${to}/${model.name}`}
value={`${to}/${model.name}`}
search-value={model.displayName}
compact
>
<TBKModelName
hide-schema
hide-catalog
hide-tooltip
text={model.displayName}
>
<TBKBadge size="2xs" slot="after">
{getModelNodeTypeTitle(model.type)}
</TBKBadge>
</TBKModelName>
</TBKSourceListItem>
// Navigation on model selection
useEffect(() => {
if (isNil(model)) return
// Sync file selection
const file = files.get(model.path)
if (isNotNil(file)) {
setSelectedFile(file)
}
// Update last selected model
setLastSelectedModel(model)
// Navigate to model detail
navigate(`${to}/${model.name}`, { replace: true })
}, [files, model, to])
// Search functionality
<SearchList<ModelSQLMeshModel>
list={list}
size={EnumSize.lg}
searchBy="index"
displayBy="displayName"
to={model => `${to}/${model.name}`}
direction="top"
isFullWidth
disabled={isFetchingModels}
/>
// Handle not found state
const isNotFound =
isNil(model) && isNotNil(modelName) && isFalse(isFetchingModels)
{isNotFound ? (
<NotFound
link={to}
message="Go Back"
description={`Model "${modelName}" not found.`}
/>
) : (
<Outlet />
)}
Component Features
Sidebar Organization
- TBKSourceList: Main list container with selection support
- TBKSourceListSection: Collapsible namespace sections (default open)
- TBKSourceListItem: Individual model items with badges
- TBKModelName: Model name display with namespace parsing
- TBKBadge: Model type indicator (SQL, Python, Seed, External)
Search Functionality
- SearchList component with fuzzy search
- Searches against model index property (all metadata)
- Displays results by displayName
- Navigates to model on selection
- Disabled during model fetching
State Management
- Syncs lastSelectedModel with URL
- Updates selectedFile when model has file path
- Replaces history to prevent navigation stack buildup
- Handles model refresh on hash changes
Model Type Badges
| Model Type | Badge Display |
|---|---|
| ModelType.sql | SQL |
| ModelType.python | Python |
| ModelType.seed | Seed |
| ModelType.external | External |
Loading States
- isFetchingModels: Shows LoadingSegment with "Loading Model page..."
- Search disabled during fetch
- Empty list: No sidebar shown
Responsive Design
- TBKResizeObserver: Updates model name widths dynamically
- Compact list items for space efficiency
- Full-width search bar