mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 06:14:59 +00:00
275 lines
9.7 KiB
Markdown
275 lines
9.7 KiB
Markdown
# UI Refactoring Summary: Component Trees in features.json
|
|
|
|
## Overview
|
|
|
|
This refactoring successfully moved UI boilerplate code from React components into the `features.json` configuration file, creating a more declarative and maintainable architecture.
|
|
|
|
## What Was Changed
|
|
|
|
### 1. New ComponentTreeRenderer Utility
|
|
|
|
Created `/src/utils/ComponentTreeRenderer.tsx` - a powerful utility that renders React component trees from JSON configuration:
|
|
|
|
**Features:**
|
|
- ✅ Renders nested component hierarchies from JSON
|
|
- ✅ Supports template interpolation (`{{variable}}`)
|
|
- ✅ Conditional rendering with `condition` property
|
|
- ✅ Loops/iterations with `forEach` property
|
|
- ✅ Event handler binding
|
|
- ✅ Icon component mapping
|
|
- ✅ Material-UI component integration
|
|
|
|
### 2. Expanded features.json Schema
|
|
|
|
Added new component trees to `/src/config/features.json`:
|
|
|
|
#### Component Trees Added:
|
|
1. **TableManagerTab** - UI for creating and managing database tables
|
|
2. **ColumnManagerTab** - UI for adding, modifying, and dropping columns
|
|
3. **ConstraintManagerTab** - UI for managing table constraints
|
|
4. **IndexManagerTab** - UI for creating and managing indexes
|
|
5. **QueryBuilderTab** - Visual query builder interface
|
|
|
|
Each component tree defines the complete UI structure declaratively in JSON format.
|
|
|
|
### 3. Refactored Components
|
|
|
|
#### Before: Boilerplate JSX Code
|
|
```tsx
|
|
// Old TableManagerTab.tsx - 116 lines with hardcoded JSX
|
|
return (
|
|
<>
|
|
<Typography variant="h5" gutterBottom>
|
|
{feature?.name || 'Table Manager'}
|
|
</Typography>
|
|
<Box sx={{ mt: 2, mb: 2 }}>
|
|
{canCreate && (
|
|
<Button variant="contained" startIcon={<AddIcon />} ...>
|
|
Create Table
|
|
</Button>
|
|
)}
|
|
// ... more boilerplate
|
|
</Box>
|
|
// ... more JSX
|
|
</>
|
|
);
|
|
```
|
|
|
|
#### After: Configuration-Driven
|
|
```tsx
|
|
// New TableManagerTab.tsx - 67 lines (42% reduction)
|
|
const tree = getComponentTree('TableManagerTab');
|
|
const data = { feature, tables, canCreate, canDelete };
|
|
const handlers = { openCreateDialog, openDropDialog };
|
|
|
|
return (
|
|
<ComponentTreeRenderer tree={tree} data={data} handlers={handlers} />
|
|
);
|
|
```
|
|
|
|
## Benefits of This Refactoring
|
|
|
|
### 1. **Reduced Code Duplication**
|
|
- UI structure defined once in JSON
|
|
- Components become thin wrappers with business logic only
|
|
- TableManagerTab: 116 → 67 lines (42% reduction)
|
|
- ColumnManagerTab: 215 → 133 lines (38% reduction)
|
|
|
|
### 2. **Declarative UI Definition**
|
|
- UI structure is now data, not code
|
|
- Easier to modify without touching TypeScript/React
|
|
- Non-developers can understand and modify UI structure
|
|
|
|
### 3. **Consistent Component Usage**
|
|
- All UIs use the same Material-UI components
|
|
- Enforces consistency across the application
|
|
- Easier to apply global UI changes
|
|
|
|
### 4. **Better Separation of Concerns**
|
|
- UI structure (features.json) separated from business logic (component files)
|
|
- Event handlers and state management remain in components
|
|
- Data fetching and API calls stay in components
|
|
|
|
### 5. **Easier Testing**
|
|
- Component logic can be tested independently of UI structure
|
|
- UI structure can be validated as JSON schema
|
|
- Atomic components (DataGrid, ConfirmDialog) remain fully testable
|
|
|
|
### 6. **Configuration-Driven Development**
|
|
- Features can be defined entirely in JSON
|
|
- Reduces need for React/TypeScript knowledge
|
|
- Enables rapid prototyping and iteration
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ features.json │
|
|
│ ┌──────────────────────────────────────┐ │
|
|
│ │ Component Trees │ │
|
|
│ │ - TableManagerTab │ │
|
|
│ │ - ColumnManagerTab │ │
|
|
│ │ - IndexManagerTab │ │
|
|
│ │ - ConstraintManagerTab │ │
|
|
│ │ - QueryBuilderTab │ │
|
|
│ └──────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ ComponentTreeRenderer │
|
|
│ - Parses JSON component tree │
|
|
│ - Interpolates data and expressions │
|
|
│ - Evaluates conditions │
|
|
│ - Handles loops (forEach) │
|
|
│ - Binds event handlers │
|
|
│ - Renders React components │
|
|
└─────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ Refactored Components │
|
|
│ - Define state and business logic │
|
|
│ - Handle events and data fetching │
|
|
│ - Pass data and handlers to renderer │
|
|
│ - Keep atomic dialogs (CreateTableDialog, etc.) │
|
|
└─────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Atomic Components Retained
|
|
|
|
These components remain as-is (atomic, reusable building blocks):
|
|
|
|
- ✅ **DataGrid** - Table display with edit/delete actions
|
|
- ✅ **ConfirmDialog** - Confirmation dialog for destructive actions
|
|
- ✅ **FormDialog** - Generic form dialog
|
|
- ✅ **CreateTableDialog** - Specialized table creation dialog
|
|
- ✅ **DropTableDialog** - Table deletion dialog
|
|
- ✅ **ColumnDialog** - Column add/modify/drop dialog
|
|
- ✅ **ConstraintDialog** - Constraint management dialog
|
|
|
|
## Component Tree Schema
|
|
|
|
```typescript
|
|
type ComponentNode = {
|
|
component: string; // Component name (e.g., "Box", "Button")
|
|
props?: Record<string, any>; // Component props
|
|
children?: ComponentNode[]; // Nested children
|
|
condition?: string; // Render condition (e.g., "canCreate")
|
|
forEach?: string; // Loop over array (e.g., "tables")
|
|
dataSource?: string; // Data binding
|
|
comment?: string; // Documentation
|
|
};
|
|
```
|
|
|
|
## Example Component Tree
|
|
|
|
```json
|
|
{
|
|
"TableManagerTab": {
|
|
"component": "Box",
|
|
"children": [
|
|
{
|
|
"component": "Typography",
|
|
"props": {
|
|
"variant": "h5",
|
|
"gutterBottom": true,
|
|
"text": "{{feature.name}}"
|
|
}
|
|
},
|
|
{
|
|
"component": "Button",
|
|
"condition": "canCreate",
|
|
"props": {
|
|
"variant": "contained",
|
|
"startIcon": "Add",
|
|
"onClick": "openCreateDialog",
|
|
"text": "Create Table"
|
|
}
|
|
},
|
|
{
|
|
"component": "List",
|
|
"children": [
|
|
{
|
|
"component": "ListItem",
|
|
"forEach": "tables",
|
|
"children": [...]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Future Enhancements
|
|
|
|
### Potential Improvements:
|
|
1. **More Component Trees** - Add component trees for remaining large components
|
|
2. **Component Library** - Expand component map with more Material-UI components
|
|
3. **Tree Validation** - Add JSON schema validation for component trees
|
|
4. **Visual Editor** - Create a visual editor for component trees
|
|
5. **Hot Reloading** - Enable live updates when features.json changes
|
|
6. **A/B Testing** - Switch between different component tree versions
|
|
7. **Multi-Platform** - Use same trees for web and mobile
|
|
|
|
### Components to Refactor Next:
|
|
- QueryBuilderTab (413 lines → can be reduced significantly)
|
|
- IndexManagerTab (434 lines → can be reduced significantly)
|
|
- ConstraintManagerTab (203 lines → can be reduced significantly)
|
|
|
|
## Migration Guide
|
|
|
|
To refactor a component to use ComponentTreeRenderer:
|
|
|
|
### Step 1: Define Component Tree in features.json
|
|
```json
|
|
{
|
|
"componentTrees": {
|
|
"YourComponentName": {
|
|
"component": "Box",
|
|
"children": [
|
|
// Define your UI structure here
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Step 2: Refactor Component
|
|
```tsx
|
|
import { getComponentTree } from '@/utils/featureConfig';
|
|
import ComponentTreeRenderer from '@/utils/ComponentTreeRenderer';
|
|
|
|
export default function YourComponent(props) {
|
|
const [state, setState] = useState(/* ... */);
|
|
|
|
const tree = getComponentTree('YourComponentName');
|
|
const data = { /* your data */ };
|
|
const handlers = { /* your event handlers */ };
|
|
|
|
return (
|
|
<>
|
|
<ComponentTreeRenderer tree={tree} data={data} handlers={handlers} />
|
|
{/* Keep atomic components like dialogs here */}
|
|
</>
|
|
);
|
|
}
|
|
```
|
|
|
|
### Step 3: Test
|
|
- Verify UI renders correctly
|
|
- Check conditional rendering
|
|
- Test event handlers
|
|
- Validate loops/iterations
|
|
|
|
## Conclusion
|
|
|
|
This refactoring successfully demonstrates the power of configuration-driven UI development. By moving UI boilerplate to JSON, we've:
|
|
|
|
- ✅ Reduced code by 38-42% in refactored components
|
|
- ✅ Improved maintainability and consistency
|
|
- ✅ Enabled non-developers to modify UI structure
|
|
- ✅ Created a foundation for rapid feature development
|
|
- ✅ Maintained atomic component library for complex interactions
|
|
|
|
The architecture is scalable and can be extended to cover more components in the future.
|