Added auth functionality, initial work with views and field types
This commit is contained in:
406
FIELD_TYPES_ARCHITECTURE.md
Normal file
406
FIELD_TYPES_ARCHITECTURE.md
Normal file
@@ -0,0 +1,406 @@
|
||||
# Field Types System Architecture
|
||||
|
||||
## System Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (Vue 3 + Nuxt) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||||
│ │ View Components │ │
|
||||
│ ├───────────────────────────────────────────────────────────┤ │
|
||||
│ │ ListView.vue │ DetailView.vue │ EditView.vue │ │
|
||||
│ │ - Data Table │ - Read Display │ - Form │ │
|
||||
│ │ - Search │ - Sections │ - Validation │ │
|
||||
│ │ - Sort/Filter │ - Actions │ - Sections │ │
|
||||
│ │ - Bulk Actions │ │ │ │
|
||||
│ └────────────────────────┬──────────────────────────────────┘ │
|
||||
│ │ uses │
|
||||
│ ┌────────────────────────▼──────────────────────────────────┐ │
|
||||
│ │ FieldRenderer.vue │ │
|
||||
│ │ Universal component for rendering any field type │ │
|
||||
│ │ - Handles LIST, DETAIL, EDIT modes │ │
|
||||
│ │ - Type-aware rendering │ │
|
||||
│ │ - Validation support │ │
|
||||
│ └────────────────────────┬──────────────────────────────────┘ │
|
||||
│ │ uses │
|
||||
│ ┌────────────────────────▼──────────────────────────────────┐ │
|
||||
│ │ shadcn-vue Components │ │
|
||||
│ │ Input, Textarea, Select, Checkbox, Switch, Calendar, │ │
|
||||
│ │ Table, Badge, Dialog, Popover, etc. │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||||
│ │ Composables │ │
|
||||
│ ├───────────────────────────────────────────────────────────┤ │
|
||||
│ │ useFields() │ useViewState() │ │
|
||||
│ │ - Map backend data │ - CRUD operations │ │
|
||||
│ │ - Build configs │ - State management │ │
|
||||
│ │ - Generate sections │ - Navigation │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||||
│ │ Type Definitions │ │
|
||||
│ │ field-types.ts - TypeScript interfaces for field system │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ HTTP/REST API
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Backend (NestJS) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||||
│ │ Controllers │ │
|
||||
│ ├───────────────────────────────────────────────────────────┤ │
|
||||
│ │ SetupObjectController │ RuntimeObjectController │ │
|
||||
│ │ - GET /objects │ - GET /objects/:name │ │
|
||||
│ │ - GET /objects/:name │ - GET /objects/:name/:id │ │
|
||||
│ │ - GET /ui-config ✨ │ - POST /objects/:name │ │
|
||||
│ │ - POST /objects │ - PUT /objects/:name/:id │ │
|
||||
│ └────────────────────────┬────────────────┬─────────────────┘ │
|
||||
│ │ │ │
|
||||
│ ┌────────────────────────▼────────────────▼─────────────────┐ │
|
||||
│ │ Services │ │
|
||||
│ ├───────────────────────────────────────────────────────────┤ │
|
||||
│ │ ObjectService │ FieldMapperService ✨ │ │
|
||||
│ │ - CRUD operations │ - Map field definitions │ │
|
||||
│ │ - Query building │ - Generate UI configs │ │
|
||||
│ │ - Validation │ - Default metadata │ │
|
||||
│ └────────────────────────┬──────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────────────────────▼──────────────────────────────────┐ │
|
||||
│ │ Models │ │
|
||||
│ │ ObjectDefinition │ FieldDefinition ✨ │ │
|
||||
│ │ - Object metadata │ - Field metadata │ │
|
||||
│ │ │ - UIMetadata interface │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ Prisma/Knex
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Database (PostgreSQL) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||||
│ │ object_definitions │ │
|
||||
│ │ - id, tenant_id, api_name, label, plural_label │ │
|
||||
│ │ - description, is_system, table_name │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ │ 1:many │
|
||||
│ ▼ │
|
||||
│ ┌───────────────────────────────────────────────────────────┐ │
|
||||
│ │ field_definitions │ │
|
||||
│ │ - id, object_definition_id, api_name, label, type │ │
|
||||
│ │ - is_required, is_unique, is_system │ │
|
||||
│ │ - ui_metadata (JSONB) ✨ NEW │ │
|
||||
│ │ { │ │
|
||||
│ │ placeholder, helpText, showOnList, showOnDetail, │ │
|
||||
│ │ showOnEdit, sortable, options, rows, min, max, │ │
|
||||
│ │ validationRules, format, prefix, suffix, etc. │ │
|
||||
│ │ } │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
✨ = New/Enhanced component
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
### 1. Loading Object Definition
|
||||
|
||||
```
|
||||
┌──────────┐ GET /api/setup/objects/Contact/ui-config ┌──────────┐
|
||||
│ │ ──────────────────────────────────────────────────> │ │
|
||||
│ Frontend │ │ Backend │
|
||||
│ │ <────────────────────────────────────────────────── │ │
|
||||
└──────────┘ { objectDef with mapped fields } └──────────┘
|
||||
│
|
||||
│ useFields().buildListViewConfig(objectDef)
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ ListViewConfig │
|
||||
│ - objectApiName: "Contact" │
|
||||
│ - mode: "list" │
|
||||
│ - fields: [ │
|
||||
│ { │
|
||||
│ apiName: "firstName", │
|
||||
│ type: "text", │
|
||||
│ showOnList: true, │
|
||||
│ ... │
|
||||
│ } │
|
||||
│ ] │
|
||||
└──────────────────────────────────────┘
|
||||
│
|
||||
│ Pass to ListView component
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ ListView renders data table │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. Fetching Records
|
||||
|
||||
```
|
||||
┌──────────┐ GET /api/runtime/objects/Contact ┌──────────┐
|
||||
│ │ ──────────────────────────────────────────────────> │ │
|
||||
│ Frontend │ │ Backend │
|
||||
│ │ <────────────────────────────────────────────────── │ │
|
||||
└──────────┘ [{ id, firstName, lastName, ... }] └──────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ ListView displays records │
|
||||
│ Each field rendered by │
|
||||
│ FieldRenderer with mode="list" │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3. Field Rendering
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ FieldRenderer │
|
||||
│ Props: { field, modelValue, mode } │
|
||||
└────────────────────────┬────────────────────────────────────┘
|
||||
│
|
||||
┌────────────────┼────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
mode="list" mode="detail" mode="edit"
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
Simple text Formatted Input component
|
||||
or badge display with based on type:
|
||||
display labels - Input
|
||||
- Textarea
|
||||
- Select
|
||||
- DatePicker
|
||||
- Checkbox
|
||||
- etc.
|
||||
```
|
||||
|
||||
### 4. Saving Record
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐
|
||||
│ EditView │ ──> User fills form ──> Validation │ │
|
||||
│ │ │ │ │
|
||||
│ │ ▼ │ │
|
||||
│ │ Valid? │ │
|
||||
│ │ ✓ Yes │ │
|
||||
│ │ @save event │ │ │
|
||||
│ │ ──────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ POST/PUT /api/runtime/objects/Contact/:id │ Backend │
|
||||
│ Frontend │ ──────────────────────────────────────────────────> │ │
|
||||
│ │ │ │
|
||||
│ │ <────────────────────────────────────────────────── │ │
|
||||
│ │ { saved record } │ │
|
||||
│ │ │ │
|
||||
│ │ ──> Navigate to DetailView │ │
|
||||
└──────────┘ └──────────┘
|
||||
```
|
||||
|
||||
## Component Hierarchy
|
||||
|
||||
```
|
||||
Page/App
|
||||
└── ObjectViewContainer
|
||||
├── ListView
|
||||
│ ├── Search/Filters
|
||||
│ ├── Table
|
||||
│ │ ├── TableHeader
|
||||
│ │ │ └── Sortable columns
|
||||
│ │ └── TableBody
|
||||
│ │ └── TableRow (for each record)
|
||||
│ │ └── TableCell (for each field)
|
||||
│ │ └── FieldRenderer (mode="list")
|
||||
│ └── Actions (Create, Export, etc.)
|
||||
│
|
||||
├── DetailView
|
||||
│ ├── Header with actions
|
||||
│ └── Sections
|
||||
│ └── Card (for each section)
|
||||
│ └── FieldRenderer (mode="detail") for each field
|
||||
│
|
||||
└── EditView
|
||||
├── Header with Save/Cancel
|
||||
└── Form
|
||||
└── Sections
|
||||
└── Card (for each section)
|
||||
└── FieldRenderer (mode="edit") for each field
|
||||
└── Input component based on field type
|
||||
```
|
||||
|
||||
## Field Type Mapping
|
||||
|
||||
```
|
||||
Database Type → FieldType Enum → Component (Edit Mode)
|
||||
─────────────────────────────────────────────────────────
|
||||
string → TEXT → Input[type="text"]
|
||||
text → TEXTAREA → Textarea
|
||||
email → EMAIL → Input[type="email"]
|
||||
url → URL → Input[type="url"]
|
||||
integer → NUMBER → Input[type="number"]
|
||||
decimal → NUMBER → Input[type="number"]
|
||||
currency → CURRENCY → Input[type="number"] + prefix
|
||||
boolean → BOOLEAN → Checkbox
|
||||
date → DATE → DatePicker
|
||||
datetime → DATETIME → DatePicker (with time)
|
||||
picklist → SELECT → Select
|
||||
multipicklist → MULTI_SELECT → Select[multiple]
|
||||
lookup → BELONGS_TO → Combobox (relation picker)
|
||||
file → FILE → FileUpload
|
||||
image → IMAGE → ImageUpload
|
||||
richtext → MARKDOWN → Textarea (+ preview)
|
||||
json → JSON → Textarea (JSON editor)
|
||||
```
|
||||
|
||||
## View Mode Rendering
|
||||
|
||||
```
|
||||
Field Type: TEXT
|
||||
─────────────────────────────────────────────────────
|
||||
LIST mode │ Simple text, truncated
|
||||
│ <span>{{ value }}</span>
|
||||
─────────────────────────────────────────────────────
|
||||
DETAIL mode │ Text with label
|
||||
│ <div>
|
||||
│ <Label>Name</Label>
|
||||
│ <span>{{ value }}</span>
|
||||
│ </div>
|
||||
─────────────────────────────────────────────────────
|
||||
EDIT mode │ Input field
|
||||
│ <Input v-model="value" />
|
||||
─────────────────────────────────────────────────────
|
||||
|
||||
Field Type: BOOLEAN
|
||||
─────────────────────────────────────────────────────
|
||||
LIST mode │ Badge (Yes/No)
|
||||
│ <Badge>Yes</Badge>
|
||||
─────────────────────────────────────────────────────
|
||||
DETAIL mode │ Checkbox (disabled) + text
|
||||
│ <Checkbox :checked="value" disabled />
|
||||
│ <span>Yes</span>
|
||||
─────────────────────────────────────────────────────
|
||||
EDIT mode │ Checkbox (editable)
|
||||
│ <Checkbox v-model="value" />
|
||||
─────────────────────────────────────────────────────
|
||||
|
||||
Field Type: SELECT
|
||||
─────────────────────────────────────────────────────
|
||||
LIST mode │ Selected label
|
||||
│ <span>Active</span>
|
||||
─────────────────────────────────────────────────────
|
||||
DETAIL mode │ Selected label with styling
|
||||
│ <Badge>Active</Badge>
|
||||
─────────────────────────────────────────────────────
|
||||
EDIT mode │ Dropdown select
|
||||
│ <Select v-model="value">
|
||||
│ <SelectItem value="active">Active</SelectItem>
|
||||
│ </Select>
|
||||
─────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
```
|
||||
Setup/Configuration (Metadata)
|
||||
────────────────────────────────────────────────────
|
||||
GET /api/setup/objects
|
||||
Returns: List of all object definitions
|
||||
|
||||
GET /api/setup/objects/:objectName
|
||||
Returns: Object definition with fields
|
||||
|
||||
GET /api/setup/objects/:objectName/ui-config ✨
|
||||
Returns: Object definition with UI-ready field configs
|
||||
(fields mapped to frontend format with UIMetadata)
|
||||
|
||||
POST /api/setup/objects
|
||||
Body: { apiName, label, description, ... }
|
||||
Returns: Created object definition
|
||||
|
||||
POST /api/setup/objects/:objectName/fields
|
||||
Body: { apiName, label, type, uiMetadata, ... }
|
||||
Returns: Created field definition
|
||||
|
||||
Runtime (Data CRUD)
|
||||
────────────────────────────────────────────────────
|
||||
GET /api/runtime/objects/:objectName
|
||||
Query: { search, filters, page, pageSize }
|
||||
Returns: Array of records
|
||||
|
||||
GET /api/runtime/objects/:objectName/:recordId
|
||||
Returns: Single record
|
||||
|
||||
POST /api/runtime/objects/:objectName
|
||||
Body: { field1: value1, field2: value2, ... }
|
||||
Returns: Created record
|
||||
|
||||
PUT /api/runtime/objects/:objectName/:recordId
|
||||
Body: { field1: value1, field2: value2, ... }
|
||||
Returns: Updated record
|
||||
|
||||
DELETE /api/runtime/objects/:objectName/:recordId
|
||||
Returns: Success status
|
||||
```
|
||||
|
||||
## Key Features
|
||||
|
||||
### Frontend
|
||||
- ✅ Universal field renderer for 15+ field types
|
||||
- ✅ Three view modes (list, detail, edit)
|
||||
- ✅ Client-side validation with custom rules
|
||||
- ✅ Responsive design (mobile-friendly)
|
||||
- ✅ Accessible components (WCAG compliant)
|
||||
- ✅ Type-safe with TypeScript
|
||||
- ✅ Composables for easy integration
|
||||
- ✅ Demo page for testing
|
||||
|
||||
### Backend
|
||||
- ✅ UI metadata stored in JSONB column
|
||||
- ✅ Field mapper service for transformation
|
||||
- ✅ Default metadata generation
|
||||
- ✅ Validation rule support
|
||||
- ✅ Flexible field type system
|
||||
- ✅ Multi-tenant support
|
||||
- ✅ RESTful API
|
||||
|
||||
### Database
|
||||
- ✅ Flexible schema with JSONB metadata
|
||||
- ✅ Support for custom objects
|
||||
- ✅ Versioning and migration support
|
||||
- ✅ Indexed for performance
|
||||
|
||||
## Extension Points
|
||||
|
||||
```
|
||||
1. Custom Field Types
|
||||
└─> Add to FieldType enum
|
||||
└─> Add rendering logic to FieldRenderer.vue
|
||||
└─> Add mapping in FieldMapperService
|
||||
|
||||
2. Custom Validation Rules
|
||||
└─> Add to ValidationRule type
|
||||
└─> Add validation logic in EditView.vue
|
||||
|
||||
3. Custom Actions
|
||||
└─> Add to ViewAction interface
|
||||
└─> Handle in view components
|
||||
|
||||
4. Custom Sections
|
||||
└─> Configure in DetailViewConfig/EditViewConfig
|
||||
└─> Auto-generation in useFields()
|
||||
|
||||
5. Custom Formatting
|
||||
└─> Add to UIMetadata
|
||||
└─> Implement in FieldRenderer.vue
|
||||
```
|
||||
|
||||
This architecture provides a scalable, maintainable, and extensible system for building dynamic forms and views! 🎉
|
||||
Reference in New Issue
Block a user