@nestledjs/data-browser
Version:
Universal admin data browser for Nestled framework projects with full CRUD operations
319 lines (222 loc) • 7.9 kB
Markdown
# @nestledjs/data-browser
Universal admin data browser for Nestled framework projects with full CRUD operations, advanced filtering, and customizable views.
## Features
- 🔍 **Auto-generated CRUD Interface** - Automatically generates admin UI for all Prisma models
- 📊 **Advanced Data Table** - Sorting, filtering, pagination, column selection
- 🔎 **Smart Search** - Multi-field text search with debouncing
- 📝 **Dynamic Forms** - Auto-generated create/edit forms from model schema
- 🎨 **Dark Mode Support** - Full dark mode theming
- 💾 **Persistent Preferences** - Saves column visibility, sort order, and search preferences per model
- 🔐 **Type-Safe** - Full TypeScript support with GraphQL code generation
- 📱 **Responsive** - Mobile-friendly with fullscreen mode
## Installation
```bash
npm install @nestledjs/data-browser
# or
pnpm add @nestledjs/data-browser
# or
yarn add @nestledjs/data-browser
```
## Prerequisites
This package requires a Nestled framework project with:
- **Apollo Client v4+** for GraphQL operations
- **React Router v7+** for routing
- **@nestledjs/forms** for form generation
- **Prisma** for database models
- **Generated GraphQL SDK** with admin CRUD operations
### Peer Dependencies
```json
{
"@apollo/client": "^4.0.0",
"@nestledjs/forms": "^0.5.0",
"react": "^19.0.0",
"react-router": "^7.0.0"
}
```
### Required Project Components
Your Nestled project must also export:
1. **Web UI Components** from `@your-project/web-ui`:
- `WebUiDataTable`
- `WebUiErrorBoundary`
2. **Form Theme** from `@your-project/shared/styles`:
- `formTheme`
3. **GraphQL SDK** from `@your-project/shared/sdk`:
- `DATABASE_MODELS` (auto-generated model metadata)
- GraphQL documents with `__Admin*Document` naming
## Quick Start
### Step 1: Install
```bash
pnpm add @nestledjs/data-browser
```
### Step 2: Update Import Paths
Since this package imports from your project's namespaced packages, find and replace in the source:
```
@nestled-template → @your-project-name
```
This affects 3 files in `libs/admin-data/src/lib/pages/`.
### Step 3: Create Route Wrapper
Create `apps/web/app/routes/admin/data/_layout.tsx`:
```typescript
import * as Sdk from '@your-project/shared/sdk'
import { DATABASE_MODELS } from '@your-project/shared/sdk'
import { AdminDataProvider, AdminDataLayout } from '@nestledjs/data-browser'
export default function DataLayoutRoute() {
return (
<AdminDataProvider
sdk={Sdk}
databaseModels={DATABASE_MODELS}
basePath="/admin/data"
>
<AdminDataLayout />
</AdminDataProvider>
)
}
```
### Step 4: Create Page Routes
Create these minimal route files:
**`apps/web/app/routes/admin/data/index.tsx`**:
```typescript
import { AdminDataIndexPage } from '@nestledjs/data-browser'
export default AdminDataIndexPage
```
**`apps/web/app/routes/admin/data/$dataTypePlural.tsx`**:
```typescript
import { AdminDataListPage, AdminDataErrorBoundary } from '@nestledjs/data-browser'
export default function DataListRoute() {
return <AdminDataListPage />
}
export function ErrorBoundary({ error }: Readonly<{ error: Error }>) {
return <AdminDataErrorBoundary error={error} />
}
```
**`apps/web/app/routes/admin/data/$dataType.create.tsx`**:
```typescript
import { AdminDataCreatePage, AdminDataCreateErrorBoundary } from '@nestledjs/data-browser'
export default function CreateDataRoute() {
return <AdminDataCreatePage />
}
export function ErrorBoundary({ error }: Readonly<{ error: Error }>) {
return <AdminDataCreateErrorBoundary error={error} />
}
```
**`apps/web/app/routes/admin/data/$dataType.$id.tsx`**:
```typescript
import { AdminDataEditPage, AdminDataEditErrorBoundary } from '@nestledjs/data-browser'
export default function EditDataRoute() {
return <AdminDataEditPage />
}
export function ErrorBoundary({ error }: Readonly<{ error: Error }>) {
return <AdminDataEditErrorBoundary error={error} />
}
```
### Step 5: Register Routes
In `apps/web/app/routes.tsx`:
```typescript
import { index, route, type RouteConfig } from '@react-router/dev/routes'
export default [
route('admin', './routes/admin/_layout.tsx', [
route('data', './routes/admin/data/_layout.tsx', [
index('./routes/admin/data/index.tsx'),
route(':dataTypePlural', './routes/admin/data/$dataTypePlural.tsx'),
route(':dataType/create', './routes/admin/data/$dataType.create.tsx'),
route(':dataType/:id', './routes/admin/data/$dataType.$id.tsx'),
]),
]),
] satisfies RouteConfig
```
### Step 6: Access the Data Browser
Navigate to `/admin/data` in your application!
## Usage
### Landing Page (`/admin/data`)
Shows all available database models with a searchable list.
### List View (`/admin/data/users`)
- **Search**: Multi-field text search across string fields
- **Filter**: Advanced filters for dates, numbers, enums, and relations
- **Sort**: Click column headers to sort
- **Columns**: Show/hide columns via column selector
- **Pagination**: Navigate through large datasets
### Create (`/admin/data/user/create`)
Auto-generated form based on your Prisma model schema with:
- Type-aware inputs (text, number, date, enum, relation dropdowns)
- Validation based on model requirements
- Real-time error handling
### Edit (`/admin/data/user/123`)
Pre-filled form with current values, plus delete functionality.
## API
### AdminDataProvider
The context provider that makes SDK and models available to all components.
```typescript
<AdminDataProvider
sdk={Sdk} // Your GraphQL SDK namespace
databaseModels={DATABASE_MODELS} // Array of model metadata
basePath="/admin/data" // Optional: Custom route prefix
>
{children}
</AdminDataProvider>
```
### useAdminDataContext
Hook to access the admin data context:
```typescript
const { sdk, databaseModels, basePath } = useAdminDataContext()
```
## GraphQL Schema Requirements
The data browser expects these operations for each model:
```graphql
# Queries
query __AdminUser($input: AdminUserInput!)
query __AdminUsers($input: AdminUsersInput!)
# Mutations
mutation __AdminCreateUser($input: CreateUserInput!)
mutation __AdminUpdateUser($input: UpdateUserInput!)
mutation __AdminDeleteUser($input: DeleteUserInput!)
```
These are auto-generated by the Nestled CRUD generator when you run:
```bash
pnpm db-update
```
## Preferences Storage
User preferences are saved to `localStorage` with key `mi-admin-config`:
- Column visibility per model
- Sort preference per model
- Search fields per model
**Export/Import**: Use the header buttons to backup and restore preferences across devices.
## Customization
### Custom Base Path
```typescript
<AdminDataProvider basePath="/admin/database">
```
Changes all routes to use `/admin/database/*` instead of `/admin/data/*`.
### Custom Styling
The data browser uses Tailwind CSS classes. Customize via your project's Tailwind config and the `formTheme` export.
## Troubleshooting
### "Missing GraphQL documents for model X"
**Solution**: Run GraphQL code generation:
```bash
pnpm sdk
```
### "useAdminDataContext must be used within AdminDataProvider"
**Solution**: Ensure all data browser components are children of `<AdminDataProvider>` in `_layout.tsx`.
### Import errors for WebUiDataTable or formTheme
**Solution**: Ensure your project exports these from:
- `@your-project/web-ui`
- `@your-project/shared/styles`
### DATABASE_MODELS is undefined
**Solution**: Run the model generator:
```bash
pnpm generate:models
```
This creates the `DATABASE_MODELS` export from your Prisma schema.
## Development
### Build
```bash
nx build admin-data
```
Output: `dist/libs/admin-data/`
### Publish
```bash
nx publish admin-data
```
## License
MIT
## Support
For issues and questions, please visit the [Nestled framework repository](https://github.com/nestledjs/nestled).