mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
Phase 1: Bootstrap database and fix DBAL for public pages
- Generated Prisma schema from YAML - Created database file at dbal/shared/prisma/dev.db - Fixed seedDatabase() path resolution for Next.js context - Fixed DBAL tenant filter to allow public pages (tenantId: null) - Added 'use client' directive to all fakemui components using React hooks - Added DATABASE_URL environment variable configuration The bootstrap endpoint successfully seeds the database with installed packages. Front page now can query for public PageConfig entries without tenant requirement. Remaining: - Fix layout package path resolution - Test front page rendering with database-driven components - Create comprehensive E2E tests with Playwright Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -74,7 +74,13 @@
|
||||
"Bash(do)",
|
||||
"Bash(if [ -f \"/Users/rmac/Documents/metabuilder/packages/$pkg/seed/metadata.json\" ])",
|
||||
"Bash(then)",
|
||||
"Bash(else)"
|
||||
"Bash(else)",
|
||||
"Bash(curl:*)",
|
||||
"Bash(for file in /Users/rmac/Documents/metabuilder/fakemui/fakemui/feedback/Snackbar.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/inputs/Autocomplete.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/inputs/ColorPicker.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/inputs/DatePicker.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/inputs/FileUpload.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/inputs/FormControl.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/inputs/Rating.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/inputs/Slider.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/lab/TreeView.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/navigation/SpeedDial.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/utils/GlobalStyles.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/utils/NoSsr.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/utils/Popper.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/utils/TextareaAutosize.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/utils/ToastContext.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/x/DataGrid.tsx /Users/rmac/Documents/metabuilder/fakemui/fakemui/x/DatePicker.tsx)",
|
||||
"Bash(if [ -f \"$file\" ])",
|
||||
"Bash(if ! head -1 \"$file\")",
|
||||
"Bash(for file in fakemui/fakemui/utils/useMediaQuery.js)",
|
||||
"Bash(perl -pi -e:*)"
|
||||
]
|
||||
},
|
||||
"spinnerTipsEnabled": false
|
||||
|
||||
@@ -172,7 +172,12 @@ export const createPageConfigOperations = (adapter: DBALAdapter, tenantId?: stri
|
||||
return result
|
||||
},
|
||||
list: options => {
|
||||
// For public pages, allow listing pages with tenantId: null
|
||||
const tenantFilter = resolveTenantFilter(tenantId, options?.filter)
|
||||
if (!tenantFilter && !tenantId) {
|
||||
// No configured tenant and no filter provided - allow listing public pages (tenantId: null)
|
||||
return adapter.list('PageConfig', { ...options, filter: { ...(options?.filter ?? {}), tenantId: null } }) as Promise<ListResult<PageConfig>>
|
||||
}
|
||||
if (!tenantFilter) {
|
||||
throw DBALError.validationError('Tenant ID is required', [{ field: 'tenantId', error: 'tenantId is required' }])
|
||||
}
|
||||
|
||||
@@ -39,7 +39,19 @@ export function createPrismaClient(config?: PrismaClientConfig): PrismaClient {
|
||||
}
|
||||
|
||||
// Production/Development mode: Use SQLite adapter with file or URL
|
||||
const databaseUrl = dbUrl || 'file:./prisma/dev.db'
|
||||
let databaseUrl = dbUrl
|
||||
|
||||
// If no DATABASE_URL is set, use a default that works from any directory
|
||||
if (!databaseUrl) {
|
||||
// Detect if we're running from Next.js (frontends/nextjs)
|
||||
const cwd = process.cwd()
|
||||
let projectRoot = cwd
|
||||
if (cwd.endsWith('frontends/nextjs') || cwd.endsWith('frontends\\nextjs')) {
|
||||
projectRoot = require('path').resolve(cwd, '../..')
|
||||
}
|
||||
databaseUrl = `file:${require('path').resolve(projectRoot, 'dbal/shared/prisma/dev.db')}`
|
||||
}
|
||||
|
||||
const adapter = new PrismaBetterSqlite3({
|
||||
url: databaseUrl,
|
||||
})
|
||||
|
||||
@@ -28,10 +28,16 @@ import { getPrismaClient } from '../runtime/prisma-client'
|
||||
* @param dbal DBALClient instance for database access
|
||||
*/
|
||||
export async function seedDatabase(dbal: DBALClient): Promise<void> {
|
||||
// __dirname resolves to dist directory, so we need to go up 3 levels
|
||||
// dist -> src -> development -> . -> dbal -> shared/seeds/database
|
||||
const seedDir = path.resolve(__dirname, '../../../shared/seeds/database')
|
||||
const packagesDir = path.resolve(__dirname, '../../../../packages')
|
||||
// Determine project root: Next.js runs from nextjs directory, so check parent if needed
|
||||
let cwd = process.cwd()
|
||||
|
||||
// If we're in frontends/nextjs, go up two levels to project root
|
||||
if (cwd.endsWith('frontends/nextjs') || cwd.endsWith('frontends\\nextjs')) {
|
||||
cwd = path.resolve(cwd, '../..')
|
||||
}
|
||||
|
||||
const seedDir = path.resolve(cwd, 'dbal/shared/seeds/database')
|
||||
const packagesDir = path.resolve(cwd, 'packages')
|
||||
|
||||
// 1. Load installed_packages.yaml
|
||||
const packagesPath = path.join(seedDir, 'installed_packages.yaml')
|
||||
|
||||
106
docs/FRONTPAGE_RENDERING_PLAN.md
Normal file
106
docs/FRONTPAGE_RENDERING_PLAN.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Front Page Rendering Plan
|
||||
|
||||
Render the MetaBuilder front page (`/`) using real package components with Playwright E2E tests, while replicating the look and feel of the old system.
|
||||
|
||||
## Objectives
|
||||
|
||||
### Objective 1: Render Front Page Using Real Package Components ✅
|
||||
- Front page loads components from `ui_home` package
|
||||
- Uses JSON-based component definitions
|
||||
- Displays properly with fakemui Material Design components
|
||||
- Works with database-driven PageConfig and InstalledPackage records
|
||||
|
||||
### Objective 2: Replicate Old System Look & Feel
|
||||
- Analyze old system UI/UX (`/old/src/`)
|
||||
- Extract visual design, layout, and interaction patterns
|
||||
- Implement similar aesthetics using fakemui components
|
||||
- Maintain consistency with existing MetaBuilder design system
|
||||
|
||||
### Objective 3: Playwright E2E Testing
|
||||
- Create tests that verify front page rendering
|
||||
- Test component loading from packages
|
||||
- Verify user access and permissions
|
||||
- Test fallback behavior when components not available
|
||||
|
||||
## Current State Analysis
|
||||
|
||||
### Front Page (`page.tsx`)
|
||||
```
|
||||
✅ Already configured for dynamic rendering
|
||||
✅ DBAL client integration working
|
||||
✅ PageConfig and InstalledPackage lookup implemented
|
||||
✅ JSON component rendering available
|
||||
✅ Package component loading ready
|
||||
```
|
||||
|
||||
**What's missing:**
|
||||
- Database not yet initialized (no tables)
|
||||
- No seed data loaded (no PageConfig or InstalledPackage records)
|
||||
- No bootstrap API endpoint called
|
||||
- Example components need to be expanded with design
|
||||
|
||||
### Old System (`/old/src/`)
|
||||
**Key patterns to replicate:**
|
||||
- Hero section with gradient background
|
||||
- Call-to-action buttons
|
||||
- Multi-level interface system
|
||||
- Clean, modern design with Material Design patterns
|
||||
- Responsive layout
|
||||
|
||||
## Execution Plan
|
||||
|
||||
### Phase 1: Database Bootstrap (3 steps, ~5 min)
|
||||
|
||||
Step 1: Generate Prisma schema from YAML
|
||||
```bash
|
||||
npm --prefix dbal/development run codegen:prisma
|
||||
```
|
||||
|
||||
Step 2: Push schema to SQLite database
|
||||
```bash
|
||||
npm --prefix dbal/development run db:push
|
||||
```
|
||||
|
||||
Step 3: Bootstrap system with seed data
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/bootstrap
|
||||
```
|
||||
|
||||
### Phase 2: Update UI Home Components (1 step, ~20 min)
|
||||
|
||||
Step 4: Update `/packages/ui_home/component/ui-components.json` to replicate old system design
|
||||
|
||||
Key components to enhance:
|
||||
- Hero section with gradient, heading, subheading, CTA buttons
|
||||
- Feature grid showing system capabilities
|
||||
- Get started section
|
||||
- Footer with navigation
|
||||
|
||||
### Phase 3: Playwright E2E Tests (2 steps, ~15 min)
|
||||
|
||||
Step 5: Create test suite `/e2e/frontpage.spec.ts`
|
||||
|
||||
Step 6: Run tests
|
||||
```bash
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
### Phase 4: Refinement (~15 min)
|
||||
|
||||
Step 7: Visual verification and adjustments
|
||||
Step 8: Performance optimization
|
||||
Step 9: Final testing
|
||||
|
||||
## What Needs to Happen Now
|
||||
|
||||
1. **Bootstrap Database**: Generate schema, push to DB, call bootstrap
|
||||
2. **Check Components**: Verify ui_home seed data loads correctly
|
||||
3. **Update Design**: Enhance components to match old system aesthetic
|
||||
4. **Create Tests**: Write Playwright tests for front page
|
||||
5. **Verify**: Test that everything renders correctly
|
||||
|
||||
---
|
||||
|
||||
**Status**: Ready to execute
|
||||
**Next Step**: Phase 1 - Bootstrap database
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useCallback, useMemo } from 'react'
|
||||
import clsx from 'clsx'
|
||||
import styles from '../../styles/TreeView.module.scss'
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useEffect, useCallback, useState } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useRef, useEffect } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { forwardRef, useState, useCallback } from 'react'
|
||||
import { FormLabel } from './FormLabel'
|
||||
import { FormHelperText } from './FormHelperText'
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { forwardRef, useState, useRef, useEffect } from 'react'
|
||||
import { FormLabel } from './FormLabel'
|
||||
import { FormHelperText } from './FormHelperText'
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { forwardRef, useCallback, useRef, useState } from 'react'
|
||||
import { FormLabel } from './FormLabel'
|
||||
import { FormHelperText } from './FormHelperText'
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { forwardRef, createContext, useContext, useMemo, useId } from 'react'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { forwardRef, useState, useCallback, useMemo } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, createContext, useContext, forwardRef } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useEffect, useId } from 'react'
|
||||
|
||||
type CSSProperties = React.CSSProperties
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
export interface NoSsrProps {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { classNames } from './classNames'
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { forwardRef, useRef, useEffect, useCallback } from 'react'
|
||||
import { classNames } from './classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { createContext, useContext, useState, useCallback, useRef, useEffect } from 'react'
|
||||
import { Snackbar, SnackbarContent } from '../feedback/Snackbar'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useMemo, useCallback } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useRef, useEffect } from 'react'
|
||||
import { classNames } from '../utils/classNames'
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* Renders JSON component definitions to React elements
|
||||
*/
|
||||
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import type { JSONComponent } from './types'
|
||||
import type { JsonValue } from '@/types/utility-types'
|
||||
|
||||
Reference in New Issue
Block a user