@mindmakr/gs-websdk
Version:
Web SDK for Guru SaaS System - Complete JavaScript/TypeScript SDK for building applications with dynamic schema management
707 lines (588 loc) • 16.1 kB
Markdown
# Field Properties & UI Enhancement Guide
This guide provides comprehensive information about the field properties and UI enhancements available in the Guru SaaS dynamic schema system. These properties allow you to create rich, interactive forms with backend-driven UI configuration.
## Table of Contents
- [Overview](#overview)
- [Field Enhancement Properties](#field-enhancement-properties)
- [Layout Properties](#layout-properties)
- [Styling Properties](#styling-properties)
- [Validation Properties](#validation-properties)
- [Conditional Properties](#conditional-properties)
- [Widget-Specific Properties](#widget-specific-properties)
- [Theme Integration](#theme-integration)
- [Real Backend Examples](#real-backend-examples)
## Overview
The Guru SaaS field properties system allows you to define rich UI configurations directly in your schema templates. These properties are stored in the `enhanced_properties` field of schema templates and can be applied using the fluent API builder or directly through the schema management APIs.
### Field Enhancement Structure
```typescript
interface FieldEnhancement {
// Visual properties
icon?: string;
image?: string;
// Style properties
style?: {
variant?: 'default' | 'outline' | 'ghost' | 'destructive' | 'secondary';
size?: 'sm' | 'md' | 'lg' | 'xl';
className?: string;
};
// Layout properties
layout?: {
width?: 'quarter' | 'half' | 'three-quarter' | 'full';
height?: 'small' | 'medium' | 'large';
group?: string;
order?: number;
conditional?: ConditionalConfig;
};
// Validation rules
validation?: ValidationRule[];
// UI behavior
placeholder?: Record<string, string>;
helpText?: Record<string, string>;
options?: Record<string, any>;
}
```
## Field Enhancement Properties
### Icon Properties
Add visual icons to fields for better UX:
```typescript
// Using the fluent API
.text('email', 'Email Address')
.icon('mail')
// Direct API call
await client.schema.updateFieldEnhancement(templateId, 'email', {
icon: 'mail'
});
// Backend API endpoint
PUT /api/schema-templates/{id}/field-enhancement
{
"field_key": "email",
"enhancement": {
"icon": "mail"
}
}
```
**Available Icons:**
- `user`, `mail`, `phone`, `lock`, `calendar`, `clock`, `upload`, `image`, `video`, `audio`
- `star`, `heart`, `check`, `x`, `plus`, `minus`, `edit`, `delete`, `save`
- `home`, `building`, `map-pin`, `credit-card`, `shield`, `settings`
### Image Properties
Add images or visual indicators:
```typescript
.text('company', 'Company Name')
.image('https://example.com/company-icon.png')
// Or using enhancement API
{
"image": "https://example.com/company-icon.png"
}
```
### Multi-language Support
Support multiple languages for labels and help text:
```typescript
.text('name', 'Name')
.placeholder({
en: 'Enter your full name',
es: 'Ingrese su nombre completo',
fr: 'Entrez votre nom complet'
})
.help({
en: 'Your legal name as it appears on documents',
es: 'Su nombre legal tal como aparece en los documentos',
fr: 'Votre nom légal tel qu\'il apparaît sur les documents'
})
```
## Layout Properties
### Width Configuration
Control field width using CSS Grid system:
```typescript
// Using fluent API
.text('firstName', 'First Name')
.layout({ width: 'half' })
.text('lastName', 'Last Name')
.layout({ width: 'half' })
.textarea('bio', 'Biography')
.layout({ width: 'full' })
// Available widths
- 'quarter' (25% width)
- 'half' (50% width)
- 'three-quarter' (75% width)
- 'full' (100% width)
```
### Height Configuration
Control field height for textareas and complex widgets:
```typescript
.textarea('description', 'Description')
.layout({
width: 'full',
height: 'large' // 'small', 'medium', 'large'
})
```
### Field Grouping
Group related fields together:
```typescript
.section('Contact Information')
.text('email', 'Email')
.layout({ width: 'half', group: 'contact' })
.phone('phone', 'Phone')
.layout({ width: 'half', group: 'contact' })
.text('address', 'Address')
.layout({ width: 'full', group: 'contact' })
```
### Field Ordering
Control the display order of fields:
```typescript
.text('priority', 'Priority')
.layout({ order: 1 })
.text('title', 'Title')
.layout({ order: 0 }) // Will appear first
```
## Styling Properties
### Variants
Control the visual style of form fields:
```typescript
.text('username', 'Username')
.style({
variant: 'outline', // 'default', 'outline', 'ghost', 'destructive', 'secondary'
size: 'lg' // 'sm', 'md', 'lg', 'xl'
})
.text('error_field', 'Error Field')
.style({ variant: 'destructive' }) // Red styling for errors
```
### Custom CSS Classes
Add custom CSS classes for advanced styling:
```typescript
.text('featured', 'Featured Item')
.style({
className: 'featured-field highlight-border'
})
```
### Real Backend Implementation
The backend stores these in the `enhanced_properties` field:
```sql
-- Schema template table structure
CREATE TABLE schema_templates (
id SERIAL PRIMARY KEY,
enhanced_properties JSONB,
-- other fields...
);
-- Example stored data
{
"username": {
"style": {
"variant": "outline",
"size": "lg"
},
"icon": "user"
}
}
```
## Validation Properties
### Custom Validation Rules
Add complex validation beyond JSON Schema:
```typescript
.text('password', 'Password')
.validation([
{
type: 'min_length',
value: 8,
message: {
en: 'Password must be at least 8 characters',
es: 'La contraseña debe tener al menos 8 caracteres'
}
},
{
type: 'regex',
value: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])',
message: {
en: 'Password must contain uppercase, lowercase, number, and special character',
es: 'La contraseña debe contener mayúsculas, minúsculas, números y caracteres especiales'
}
}
])
```
### Field Dependencies
Validate based on other field values:
```typescript
.text('confirmPassword', 'Confirm Password')
.validation([
{
type: 'field_equals',
value: 'password',
message: {
en: 'Passwords must match',
es: 'Las contraseñas deben coincidir'
}
}
])
```
### Available Validation Types
```typescript
type ValidationType =
| 'required'
| 'min_length' | 'max_length'
| 'min' | 'max'
| 'regex' | 'pattern'
| 'equals' | 'not_equals'
| 'field_equals' | 'field_not_equals'
| 'contains' | 'not_contains'
| 'in_array' | 'not_in_array'
| 'email' | 'url' | 'phone'
| 'date' | 'datetime' | 'time'
| 'numeric' | 'alpha' | 'alphanumeric';
```
## Conditional Properties
### Conditional Display
Show/hide fields based on other field values:
```typescript
.boolean('hasPhone', 'I have a phone number')
.phone('phoneNumber', 'Phone Number')
.conditional({
field: 'hasPhone',
operator: 'equals',
value: true
})
// This field will only show when hasPhone is true
```
### Advanced Conditional Logic
```typescript
.select('userType', 'User Type')
.options(['individual', 'business'], ['Individual', 'Business'])
.text('companyName', 'Company Name')
.conditional({
field: 'userType',
operator: 'equals',
value: 'business'
})
.text('taxId', 'Tax ID')
.conditional({
field: 'userType',
operator: 'equals',
value: 'business'
})
```
### Multiple Conditions
```typescript
.text('managerName', 'Manager Name')
.conditional([
{
field: 'userType',
operator: 'equals',
value: 'business'
},
{
field: 'hasManager',
operator: 'equals',
value: true
}
])
```
## Widget-Specific Properties
### Text Input Widgets
```typescript
.text('search', 'Search')
.options({
autocomplete: 'off',
spellcheck: false,
maxLength: 100
})
```
### File Upload Widgets
```typescript
.image('profilePicture', 'Profile Picture')
.options({
accept: 'image/*',
maxSize: 5242880, // 5MB in bytes
preview: true,
cropRatio: '1:1'
})
.file('document', 'Upload Document')
.options({
accept: '.pdf,.doc,.docx',
maxSize: 10485760, // 10MB
multiple: false
})
```
### Select Widgets
```typescript
.select('country', 'Country')
.options(['US', 'CA', 'UK'], ['United States', 'Canada', 'United Kingdom'])
.uiOptions({
searchable: true,
placeholder: 'Select a country',
clearable: true
})
```
### Rich Text Widgets
```typescript
.richText('content', 'Content')
.options({
toolbar: ['bold', 'italic', 'underline', 'link', 'image'],
maxLength: 5000,
placeholder: 'Enter your content here...'
})
```
### Reference Field Widgets
```typescript
.reference('relatedProduct', 'Related Product')
.options({
entityType: 'product',
displayField: 'name',
searchFields: ['name', 'sku'],
allowEmpty: true,
filterBy: { category: 'electronics' },
limit: 10
})
```
## Theme Integration
### Automatic Theme Application
The SDK automatically applies theme variables to all fields:
```typescript
// Theme is automatically applied from backend configuration
const layoutConfig = generateLayoutFromSchema(template, currentTheme);
// Fields receive theme props automatically
<TextInput
theme={{
colors: theme.colors,
typography: theme.typography,
spacing: theme.spacing,
borderRadius: theme.borderRadius
}}
/>
```
### Custom Theme Overrides
Override theme for specific fields:
```typescript
.text('highlightedField', 'Important Field')
.style({
className: 'custom-theme-override',
variant: 'outline'
})
.options({
customTheme: {
primaryColor: '#ff6b35',
borderRadius: '12px'
}
})
```
## Real Backend Examples
### Creating Enhanced Template via API
```javascript
// POST /api/schema-templates
const templateData = {
name: 'Enhanced Customer Form',
code: 'enhanced_customer',
category: 'customer_management',
schema_definition: {
type: 'object',
title: 'Customer Information',
properties: {
firstName: {
type: 'string',
title: 'First Name',
minLength: 1,
maxLength: 50
},
email: {
type: 'string',
format: 'email',
title: 'Email Address'
},
phone: {
type: 'string',
format: 'phone',
title: 'Phone Number'
},
priority: {
type: 'string',
title: 'Priority Level',
enum: ['low', 'medium', 'high'],
enumNames: ['Low', 'Medium', 'High']
}
},
required: ['firstName', 'email']
},
enhanced_properties: {
firstName: {
icon: 'user',
style: {
variant: 'outline',
size: 'lg'
},
layout: {
width: 'half'
},
validation: [
{
type: 'min_length',
value: 2,
message: {
en: 'Name must be at least 2 characters',
es: 'El nombre debe tener al menos 2 caracteres'
}
}
]
},
email: {
icon: 'mail',
style: {
variant: 'outline',
size: 'lg'
},
layout: {
width: 'half'
},
placeholder: {
en: 'Enter your email address',
es: 'Ingrese su dirección de correo'
}
},
phone: {
icon: 'phone',
layout: {
width: 'half'
},
options: {
format: '(###) ###-####',
mask: true
}
},
priority: {
style: {
variant: 'outline'
},
layout: {
width: 'half'
},
helpText: {
en: 'Select the priority level for this customer',
es: 'Seleccione el nivel de prioridad para este cliente'
}
}
}
};
const template = await fetch('/api/schema-templates', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(templateData)
});
```
### Updating Field Enhancement via API
```javascript
// PUT /api/schema-templates/{id}/field-enhancement
await fetch(`/api/schema-templates/${templateId}/field-enhancement`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({
field_key: 'email',
enhancement: {
icon: 'mail-check',
style: {
variant: 'outline',
size: 'xl'
},
validation: [
{
type: 'email',
message: {
en: 'Please enter a valid email address',
es: 'Por favor ingrese una dirección de correo válida'
}
}
]
}
})
});
```
### Getting Field Rendering Configuration
```javascript
// GET /api/schema-templates/{id}/field-rendering/{fieldKey}
const fieldConfig = await fetch(
`/api/schema-templates/${templateId}/field-rendering/email`,
{
headers: {
'Authorization': `Bearer ${token}`
}
}
);
// Response includes complete rendering configuration
{
"field_key": "email",
"component": "EmailInput",
"props": {
"label": "Email Address",
"placeholder": "Enter your email address",
"required": true,
"icon": "mail",
"variant": "outline",
"size": "lg",
"validation": [...],
"theme": {...}
},
"layout": {
"width": "half",
"order": 1
}
}
```
### Using with SDK
```typescript
import { GuruSaaS, TemplateBuilder } from '@mindmakr/gs-websdk';
const client = new GuruSaaS({
baseUrl: 'http://localhost',
authUrl: 'http://localhost:4000',
globalDataUrl: 'http://localhost:5010',
debug: true
});
// Using fluent API
const template = new TemplateBuilder('customer_profile', 'Customer Profile')
.category('customer_management')
.section('Personal Information')
.text('firstName', 'First Name')
.required()
.icon('user')
.style({ variant: 'outline', size: 'lg' })
.layout({ width: 'half' })
.validation([
{
type: 'min_length',
value: 2,
message: { en: 'Name too short', es: 'Nombre muy corto' }
}
])
.email('email', 'Email Address')
.required()
.icon('mail')
.style({ variant: 'outline', size: 'lg' })
.layout({ width: 'half' })
.placeholder({
en: 'your@email.com',
es: 'su@email.com'
})
.section('Contact Details')
.phone('phone', 'Phone Number')
.icon('phone')
.layout({ width: 'half' })
.options({
format: '(###) ###-####',
mask: true
})
.select('priority', 'Priority Level')
.options(['low', 'medium', 'high'], ['Low', 'Medium', 'High'])
.layout({ width: 'half' })
.help({
en: 'Customer priority level',
es: 'Nivel de prioridad del cliente'
})
.build();
// Create the enhanced template
const createdTemplate = await client.schema.createSchemaTemplate(template);
// Get enhanced field properties
const enhancements = await client.schema.getEnhancedFieldProperties(createdTemplate.id);
// Generate layout configuration
const layoutConfig = generateLayoutFromSchema(createdTemplate, currentTheme);
```
This comprehensive field properties system allows you to create rich, interactive forms that are completely driven by backend configuration, making your applications highly flexible and customizable without requiring frontend code changes.