Update various configuration files, components, and assets; enhance notification system and API endpoints; improve documentation and styles across the application.

This commit is contained in:
Haqeem Solehan
2025-10-16 16:05:39 +08:00
commit b124ff8092
336 changed files with 94392 additions and 0 deletions

161
docs/SITE_SETTINGS.md Normal file
View File

@@ -0,0 +1,161 @@
# Site Settings Feature
## Overview
The Site Settings feature allows administrators to customize the appearance and branding of the application through a user-friendly interface. All settings are globally applied across the entire application including SEO, meta tags, and visual elements.
## Features
### 1. Basic Information
- **Site Name**: Customize the application name displayed globally in:
- Header and sidebar
- Browser title and meta tags
- SEO and Open Graph tags
- Loading screen
- All pages and components
- **Site Description**: Set a description used for:
- SEO meta descriptions
- Open Graph descriptions
- Twitter Card descriptions
- **Theme Selection**: Choose from available themes:
- Standard themes (from themeList.js)
- Accessibility themes (from themeList2.js)
- Custom themes added to theme.css
### 2. Branding
- **Site Logo**: Upload a custom logo displayed in:
- Header (horizontal layout)
- Sidebar (vertical layout)
- Loading screen
- Login page
- Any component using site settings
- **Favicon**: Upload a custom favicon displayed in:
- Browser tabs
- Bookmarks
- Mobile home screen icons
### 3. Advanced Settings
- **Custom CSS**: Add custom CSS injected into document head
- **Custom Theme File**: Upload CSS files saved to `/assets/style/css/`
- **Add Custom Theme to theme.css**: Directly add themes to the main theme.css file
## How to Access
1. Navigate to **Pentadbiran****Konfigurasi****Site Settings**
2. Use the tabbed interface:
- **Basic Info**: Site name, description, and theme selection
- **Branding**: Logo and favicon uploads
- **Advanced**: Custom CSS and theme management
3. Use the **Live Preview** panel to see changes in real-time
4. Click **Save Changes** to apply your settings
## Technical Implementation
### Database Schema
The settings are stored in the `site_settings` table with the following fields:
- `siteName`, `siteDescription`
- `siteLogo`, `siteFavicon`
- `selectedTheme` - Selected theme name
- `customCSS`, `customThemeFile`
- Legacy fields maintained for backward compatibility
### API Endpoints
- `GET /api/devtool/config/site-settings` - Retrieve current settings
- `POST /api/devtool/config/site-settings` - Update settings
- `POST /api/devtool/config/upload-file` - Upload files (logos, themes)
- `POST /api/devtool/config/add-custom-theme` - Add custom theme to theme.css
### File Upload Locations
- **Logo and Favicon files**: Saved to `public/uploads/site-settings/`
- **Theme CSS files**: Saved to `assets/style/css/` directory
- **Custom themes**: Added directly to `assets/style/css/base/theme.css`
### Composable
The `useSiteSettings()` composable provides:
- `siteSettings` - Reactive settings object
- `loadSiteSettings()` - Load settings from API
- `updateSiteSettings()` - Update settings
- `setTheme()` - Set theme using existing theme system
- `getCurrentTheme()` - Get current theme
- `applyThemeSettings()` - Apply theme changes to DOM
- `updateGlobalMeta()` - Update global meta tags and SEO
- `addCustomThemeToFile()` - Add custom theme to theme.css
### Global Integration
The site settings are globally integrated across:
#### Header Component
- Uses site settings for logo and name display
- Theme selection dropdown uses same system as site settings
- Synced with site settings theme selection
#### Loading Component
- Uses site logo if available, fallback to default
- Displays site name in loading screen
#### App.vue
- Global meta tags updated from site settings
- Title, description, and favicon managed globally
- Theme initialization from site settings
#### SEO and Meta Tags
- Document title updated globally
- Meta descriptions for SEO
- Open Graph tags for social sharing
- Twitter Card tags
- Favicon and apple-touch-icon
### Theme System Integration
- Integrates with existing theme system (themeList.js, themeList2.js)
- Theme selection in header dropdown synced with site settings
- Custom themes can be added directly to theme.css
- Backward compatibility with existing theme structure
### Custom Theme Structure
Custom themes added to theme.css should follow this structure:
```css
html[data-theme="your-theme-name"] {
--color-primary: 255, 0, 0;
--color-secondary: 0, 255, 0;
--color-success: 0, 255, 0;
--color-info: 0, 0, 255;
--color-warning: 255, 255, 0;
--color-danger: 255, 0, 0;
/* Add your theme variables here */
}
```
## Default Values
If no settings are configured, the system uses these defaults:
- Site Name: "corradAF"
- Site Description: "corradAF Base Project"
- Selected Theme: "biasa"
- Logo: Default corradAF logo
- Favicon: Default favicon
## Migration Notes
- Legacy color fields (primaryColor, secondaryColor, etc.) are maintained for backward compatibility
- `themeMode` field is mapped to `selectedTheme` for compatibility
- Existing installations will automatically use default values
- Theme selection integrates with existing theme dropdown in header
## Notes
- Changes are applied immediately in the preview
- Theme changes affect the entire application
- Custom CSS is injected into the document head
- Theme files are saved to `/assets/style/css/` for proper integration
- File uploads are validated for type and size
- Settings persist across browser sessions
- Site name and description updates are reflected globally and immediately
- All meta tags and SEO elements are automatically updated
- Logo changes are reflected in all components that use site settings
### Important Notes
- Changes are applied immediately in the preview
- Theme changes affect the entire application
- Custom CSS is injected into the document head
- Theme files are saved to `/assets/style/css/` for proper integration
- File uploads are validated for type and size
- Settings persist across browser sessions
- Site name and description updates are reflected globally and immediately
- All meta tags and SEO elements are automatically updated
- Logo changes are reflected in all components that use site settings

View File

@@ -0,0 +1,211 @@
# Multi-Provider Email Configuration
This document explains how to configure multiple email providers (Mailtrap and AWS SES) in the notification system.
## Overview
The system now supports storing **multiple email provider configurations** simultaneously. Each provider's configuration is saved independently, allowing you to:
- Switch between providers without losing configurations
- Keep backup provider credentials ready
- Test different providers easily
## Database Changes
### Migration Required
Run this migration to enable multi-provider support:
```bash
mysql -h <host> -u <user> -p <database> < database/migrations/005_support_multiple_email_providers.sql
```
### What Changed
1. **Removed** unique constraint on `channel_type`
2. **Added** unique constraint on `(channel_type, provider)` combination
3. **Added** `is_active` column to track active provider
4. Now supports multiple rows per channel_type with different providers
**Before:**
```
id | channel_type | provider | is_enabled
1 | email | Mailtrap | true
```
**After:**
```
id | channel_type | provider | is_enabled | is_active
1 | email | Mailtrap | true | true
2 | email | AWS SES | false | false
```
## How It Works
### 1. **API Behavior**
**GET `/api/notifications/delivery/email-config`**
- Returns ALL provider configurations
- Indicates which provider is active
- Response format:
```json
{
"success": true,
"data": {
"providers": {
"mailtrap": {
"enabled": true,
"provider": "Mailtrap",
"config": { "host": "...", ... },
"status": "Connected",
"successRate": 99.5
},
"aws-ses": {
"enabled": false,
"provider": "AWS SES",
"config": { "host": "...", ... },
"status": "Not Configured",
"successRate": 0
}
},
"activeProvider": "mailtrap"
}
}
```
**PUT `/api/notifications/delivery/email-config`**
- Saves configuration for specific provider
- If enabling a provider, **automatically disables others**
- Only ONE provider can be `is_enabled: true` at a time
### 2. **UI Behavior**
**Provider Dropdown:**
- Shows: Mailtrap, AWS SES
- Switching providers loads that provider's saved configuration
- If no config exists, loads default template
**Saving Configuration:**
- Saves to database for the selected provider
- Does NOT overwrite other providers' configs
- Enabling saves current provider and disables others
**Configuration Persistence:**
- Each provider's config is stored separately
- Switching between providers preserves both configurations
- Form fields update automatically when switching
### 3. **Email Sending**
The `emailService.js` looks for:
1. Any `is_enabled: true` config in database
2. Falls back to `.env` variables if no enabled config
Both Mailtrap and AWS SES use **nodemailer SMTP**, so no backend code changes needed.
## Setup Instructions
### Step 1: Run Migration
```bash
mysql -h <host> -u <user> -p <database> < database/migrations/005_support_multiple_email_providers.sql
```
This will:
- ✅ Update schema to support multiple providers
- ✅ Create placeholder rows for Mailtrap and AWS SES
- ✅ Preserve existing configuration
### Step 2: Update Prisma Schema
```bash
npx prisma generate
```
This regenerates the Prisma client with the updated schema.
### Step 3: Configure Providers via UI
1. Go to `/notification/delivery`
2. Select **Mailtrap** from dropdown
3. Fill in Mailtrap credentials
4. Click **Save**
5. Switch to **AWS SES** from dropdown
6. Fill in AWS SES credentials
7. Click **Save**
Both configurations are now saved!
### Step 4: Switch Between Providers
To change active provider:
1. Select desired provider from dropdown
2. Toggle **Enable Email Delivery** to ON
3. Click **Save**
This automatically:
- ✅ Enables selected provider
- ✅ Disables other provider
- ✅ Updates email service to use new provider
## Provider-Specific Configuration
### Mailtrap
**Required Fields:**
- SMTP Host: `live.smtp.mailtrap.io`
- SMTP Port: `587`
- SMTP Username: `apismtp@mailtrap.io`
- SMTP Password: Your Mailtrap API token
- Sender Email: Your verified sender email
- Sender Name: (Optional)
### AWS SES
**Required Fields:**
- SMTP Host: `email-smtp.<region>.amazonaws.com` (e.g., `email-smtp.us-east-1.amazonaws.com`)
- SMTP Port: `587` (STARTTLS) or `465` (TLS)
- SMTP Username: AWS SES SMTP username (NOT IAM user)
- SMTP Password: AWS SES SMTP password (NOT secret key)
- Sender Email: Must be verified in AWS SES
- Sender Name: (Optional)
- AWS Region: e.g., `us-east-1`
- Configuration Set: (Optional) For tracking
**Note:** AWS SES requires:
1. Verified sender email/domain in SES console
2. SMTP credentials generated from SES (not IAM credentials)
3. Account moved out of sandbox for production sending
## Troubleshooting
### Configuration Not Saving
- Check database migration ran successfully
- Verify unique constraint exists: `SHOW INDEX FROM notification_delivery_config;`
- Should see `channel_type_provider` unique index
### Wrong Provider Being Used
- Check `is_enabled` column in database
- Only ONE provider should have `is_enabled = true`
- Run: `SELECT * FROM notification_delivery_config WHERE channel_type = 'email';`
### Form Fields Don't Update When Switching
- Clear browser cache
- Check browser console for errors
- Verify API returns all provider configs
## Files Modified
### Backend
- `server/api/notifications/delivery/email-config.get.js` - Returns all providers
- `server/api/notifications/delivery/email-config.put.js` - Saves per provider
- `prisma/schema.prisma` - Updated unique constraint
### Frontend
- `pages/notification/delivery/index.vue` - Multi-provider UI
- `pages/notification/delivery/providers.vue` - Provider list
### Database
- `database/migrations/005_support_multiple_email_providers.sql` - Schema migration
### Documentation
- `docs/multi-provider-email-setup.md` - This file

View File

@@ -0,0 +1,515 @@
# Notification System API Documentation
This document provides comprehensive information about the notification system's database schema and API endpoints based on the notification creation form requirements.
## Table of Contents
1. [Database Schema](#database-schema)
2. [API Endpoints](#api-endpoints)
3. [Usage Examples](#usage-examples)
4. [Integration Guide](#integration-guide)
## Database Schema
### Core Tables
#### `notification_categories`
Stores categorization options for notifications.
```sql
- id (UUID, Primary Key)
- name (VARCHAR) - Display name
- value (VARCHAR) - Unique identifier
- description (TEXT) - Optional description
- created_at, updated_at (TIMESTAMP)
```
#### `notification_templates`
Reusable templates for common notification types.
```sql
- id (UUID, Primary Key)
- name (VARCHAR) - Template name
- value (VARCHAR) - Unique identifier
- subject (VARCHAR) - Email subject template
- email_content (TEXT) - Email body template
- push_title (VARCHAR) - Push notification title
- push_body (VARCHAR) - Push notification body
- variables (JSONB) - Available variables
- is_active (BOOLEAN)
- created_at, updated_at (TIMESTAMP)
```
#### `notifications` (Main Table)
Central table storing all notification configurations.
```sql
- id (UUID, Primary Key)
- title (VARCHAR) - Internal notification title
- type (ENUM) - 'single' or 'bulk'
- priority (ENUM) - 'low', 'medium', 'high', 'critical'
- category_id (UUID) - FK to notification_categories
- status (ENUM) - 'draft', 'scheduled', 'sending', 'sent', 'failed', 'cancelled'
- delivery_type (ENUM) - 'immediate' or 'scheduled'
- scheduled_at (TIMESTAMP) - When to send (for scheduled)
- timezone (VARCHAR) - Timezone for scheduling
- expires_at (TIMESTAMP) - Optional expiration
- enable_ab_testing (BOOLEAN)
- ab_test_split (INTEGER) - Percentage split for A/B testing
- ab_test_name (VARCHAR) - A/B test identifier
- enable_tracking (BOOLEAN)
- audience_type (ENUM) - 'all', 'specific', 'segmented'
- specific_users (TEXT) - Comma-separated user identifiers
- user_status (VARCHAR) - Filter by user status
- registration_period (VARCHAR) - Filter by registration period
- exclude_unsubscribed (BOOLEAN)
- respect_do_not_disturb (BOOLEAN)
- content_type (ENUM) - 'new' or 'template'
- template_id (UUID) - FK to notification_templates
- email_subject (VARCHAR)
- email_content (TEXT)
- call_to_action_text (VARCHAR)
- call_to_action_url (TEXT)
- push_title (VARCHAR)
- push_body (VARCHAR)
- push_image_url (TEXT)
- estimated_reach (INTEGER)
- actual_sent (INTEGER)
- created_by (UUID) - User who created
- created_at, updated_at, sent_at (TIMESTAMP)
```
#### Supporting Tables
- `notification_channels` - Many-to-many relationship for delivery channels
- `notification_user_segments` - Many-to-many for user segments
- `notification_recipients` - Tracks individual recipients and delivery status
- `notification_queue` - Queue for scheduled notifications
- `notification_analytics` - Tracks metrics and engagement
- `user_notification_preferences` - User preferences and DND settings
## API Endpoints
### 1. Create Notification
**POST** `/api/notifications`
Creates a new notification or schedules it for delivery.
**Request Body:**
```json
{
"title": "Welcome New Users",
"type": "bulk",
"priority": "medium",
"category": "user_management",
"channels": ["email", "push"],
"emailSubject": "Welcome to our platform!",
"deliveryType": "immediate",
"timezone": "UTC",
"enableAbTesting": false,
"abTestSplit": 50,
"enableTracking": true,
"audienceType": "segmented",
"userSegments": ["new_users"],
"excludeUnsubscribed": true,
"respectDoNotDisturb": true,
"contentType": "new",
"emailContent": "<h1>Welcome!</h1><p>Thank you for joining us.</p>",
"pushTitle": "Welcome!",
"pushBody": "Thank you for joining our platform.",
"callToActionText": "Get Started",
"callToActionUrl": "https://example.com/onboarding"
}
```
**Response:**
```json
{
"success": true,
"data": {
"id": "uuid-of-notification",
"message": "Notification is being sent",
"estimatedReach": 1500
}
}
```
### 2. Get Categories
**GET** `/api/notifications/categories`
Returns available notification categories.
**Response:**
```json
{
"success": true,
"data": [
{
"label": "User Management",
"value": "user_management",
"description": "User registration, profile updates, account changes"
}
]
}
```
### 3. Get Templates
**GET** `/api/notifications/templates`
Returns available notification templates.
**Response:**
```json
{
"success": true,
"data": [
{
"label": "Welcome Message",
"value": "welcome",
"subject": "Welcome to {{company_name}}!",
"content": "<h1>Welcome {{first_name}}!</h1>",
"pushTitle": "Welcome!",
"pushBody": "Hi {{first_name}}, welcome!",
"variables": ["first_name", "company_name"]
}
]
}
```
### 4. Get User Segments
**GET** `/api/notifications/segments`
Returns available user segments for targeting.
**Response:**
```json
{
"success": true,
"data": [
{
"label": "New Users",
"value": "new_users",
"description": "Users registered within last 30 days",
"criteria": {"registration_days": 30}
}
]
}
```
### 5. Preview Audience
**POST** `/api/notifications/audience-preview`
Preview the target audience based on selected criteria.
**Request Body:**
```json
{
"audienceType": "segmented",
"userSegments": ["new_users", "active_users"],
"userStatus": "active",
"excludeUnsubscribed": true,
"channels": ["email"]
}
```
**Response:**
```json
{
"success": true,
"data": {
"users": [
{
"id": "user-uuid",
"name": "John Doe",
"email": "john@example.com",
"segment": "New Users",
"status": "active",
"registeredAt": "2024-01-01T00:00:00Z"
}
],
"totalCount": 1500,
"previewCount": 100
}
}
```
### 6. Send Test Notification
**POST** `/api/notifications/test-send`
Send a test notification to validate setup.
**Request Body:**
```json
{
"email": "test@example.com",
"testData": {
"title": "Test Notification",
"channels": ["email", "push"],
"emailSubject": "Test Email",
"emailContent": "<p>This is a test email.</p>",
"pushTitle": "Test Push",
"pushBody": "This is a test push notification."
}
}
```
**Response:**
```json
{
"success": true,
"data": {
"message": "Test notifications processed",
"results": [
{
"channel": "email",
"status": "sent",
"message": "Test email sent successfully"
},
{
"channel": "push",
"status": "sent",
"message": "Test push notification sent successfully"
}
]
}
}
```
### 7. Save Draft
**POST** `/api/notifications/draft`
Save notification as draft for later completion.
**Request Body:**
```json
{
"title": "Draft Notification",
"type": "single",
"category": "marketing",
"channels": ["email"],
"emailSubject": "Special Offer",
"contentType": "new",
"draftId": "existing-draft-uuid" // Optional, for updating
}
```
**Response:**
```json
{
"success": true,
"data": {
"id": "draft-uuid",
"message": "Draft saved successfully"
}
}
```
## Usage Examples
### Creating a Welcome Email Campaign
```javascript
// 1. Create notification for new users
const response = await $fetch('/api/notifications', {
method: 'POST',
body: {
title: 'New User Welcome Campaign',
type: 'bulk',
priority: 'medium',
category: 'user_management',
channels: ['email'],
emailSubject: 'Welcome to {{company_name}}!',
deliveryType: 'immediate',
audienceType: 'segmented',
userSegments: ['new_users'],
contentType: 'template',
selectedTemplate: 'welcome',
enableTracking: true
}
})
console.log(`Notification created: ${response.data.id}`)
console.log(`Estimated reach: ${response.data.estimatedReach} users`)
```
### Scheduling a Marketing Campaign
```javascript
// 2. Schedule a promotional campaign
const scheduledResponse = await $fetch('/api/notifications', {
method: 'POST',
body: {
title: 'Black Friday Sale',
type: 'bulk',
priority: 'high',
category: 'marketing',
channels: ['email', 'push'],
emailSubject: '🔥 Black Friday Sale - 50% Off Everything!',
deliveryType: 'scheduled',
scheduledAt: '2024-11-29T09:00:00Z',
timezone: 'America/New_York',
audienceType: 'segmented',
userSegments: ['active_users', 'high_value'],
contentType: 'new',
emailContent: '<h1>Black Friday Sale!</h1><p>Don\'t miss out on 50% off everything!</p>',
pushTitle: 'Black Friday Sale!',
pushBody: '50% off everything - today only!',
callToActionText: 'Shop Now',
callToActionUrl: 'https://example.com/sale',
enableAbTesting: true,
abTestSplit: 50,
abTestName: 'Subject Line Test'
}
})
```
### Sending Test Notifications
```javascript
// 3. Send test before going live
const testResponse = await $fetch('/api/notifications/test-send', {
method: 'POST',
body: {
email: 'marketing@company.com',
notificationId: scheduledResponse.data.id
}
})
console.log('Test results:', testResponse.data.results)
```
## Integration Guide
### Frontend Integration
Update your Vue.js notification creation form to use these APIs:
```vue
<script setup>
// Fetch initial data
const { data: categories } = await $fetch('/api/notifications/categories')
const { data: templates } = await $fetch('/api/notifications/templates')
const { data: segments } = await $fetch('/api/notifications/segments')
// Preview audience
const previewAudience = async () => {
const response = await $fetch('/api/notifications/audience-preview', {
method: 'POST',
body: {
audienceType: form.audienceType,
userSegments: form.userSegments,
userStatus: form.userStatus,
excludeUnsubscribed: form.excludeUnsubscribed,
channels: form.channels
}
})
previewedUsers.value = response.data.users
estimatedReach.value = response.data.totalCount
}
// Submit notification
const submitNotification = async (formData) => {
try {
const response = await $fetch('/api/notifications', {
method: 'POST',
body: formData
})
// Show success message
await $swal.fire({
title: 'Success!',
text: response.data.message,
icon: 'success'
})
// Redirect to notification list
await navigateTo('/notifications')
} catch (error) {
console.error('Failed to create notification:', error)
}
}
</script>
```
### Database Setup
1. **Run the migration:**
```bash
psql -d your_database -f database/migrations/001_create_notification_tables.sql
```
2. **Set up database connection in Nuxt:**
```javascript
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
databaseUrl: process.env.DATABASE_URL
}
})
// plugins/database.server.js
import { Pool } from 'pg'
export default defineNitroPlugin(async (nitroApp) => {
const config = useRuntimeConfig()
const pool = new Pool({
connectionString: config.databaseUrl
})
nitroApp.hooks.hook('close', async () => {
await pool.end()
})
nitroApp.provide('db', pool)
})
```
### Email/Push Service Integration
Replace the mock functions in `test-send.post.js` with your actual service integrations:
```javascript
// Email service example (SendGrid)
import sgMail from '@sendgrid/mail'
async function sendTestEmail({ to, subject, content, callToActionText, callToActionUrl }) {
sgMail.setApiKey(process.env.SENDGRID_API_KEY)
const msg = {
to,
from: 'noreply@yourcompany.com',
subject,
html: content
}
await sgMail.send(msg)
}
// Push service example (Firebase)
import admin from 'firebase-admin'
async function sendTestPush({ email, title, body }) {
// Get user's device tokens from your database
const tokens = await getUserDeviceTokens(email)
const message = {
notification: { title, body },
tokens
}
await admin.messaging().sendMulticast(message)
}
```
This comprehensive notification system provides:
**Complete database schema** with all necessary tables and relationships
**Robust API endpoints** with proper validation and error handling
**Transaction support** to ensure data consistency
**A/B testing capabilities** for optimization
**User preference handling** including DND settings
**Queue system** for reliable delivery
**Analytics tracking** for performance monitoring
**Draft functionality** for iterative creation
**Test sending** for validation before deployment
The system is designed to handle both simple single notifications and complex bulk campaigns with advanced targeting and scheduling capabilities.

View File

@@ -0,0 +1,239 @@
# Notification Queue System
## Overview
The notification system now uses a **background queue processor** that runs automatically every 30 seconds to send queued emails.
## How It Works
### 1. **Queue Creation**
When you create a notification:
```
POST /api/public/create-notification
Creates notification → status: "sending"
Creates recipients → status: "pending"
Creates queue items → status: "queued"
Returns immediately (non-blocking) ✅
```
### 2. **Background Processing**
A background worker runs automatically:
```
Server starts
Queue Processor Plugin initializes
Processes queue every 30 seconds
Sends emails → Updates status → Repeats
```
### 3. **Status Updates**
```
notification.status: "sending" → "sent" (when all recipients done)
recipients.status: "pending" → "sent" or "failed"
queue.status: "queued" → "processing" → "completed" or "failed"
```
## Components
### 1. Queue Processor (`server/utils/queueProcessor.js`)
- **Runs every 30 seconds**
- Processes up to 50 jobs per batch
- Prevents concurrent processing (lock mechanism)
- Logs activity for monitoring
### 2. Nitro Plugin (`server/plugins/queueProcessor.js`)
- **Auto-starts** when server starts
- Runs in background
- Gracefully shuts down with server
### 3. Email Service (`server/utils/emailService.js`)
- `processEmailQueue()` - Processes queued emails
- `sendEmailNotification()` - Sends individual emails
- Updates all statuses (notification, recipient, queue)
## Queue Flow
```
┌─────────────────────────────────────────┐
│ Create Notification API │
│ - Creates notification (sending) │
│ - Creates recipients (pending) │
│ - Creates queue items (queued) │
│ - Returns immediately ✅ │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ Background Queue Processor │
│ (Runs every 30 seconds) │
│ │
│ 1. Find queued items (scheduled_for <= now)
│ 2. For each item: │
│ - Mark as "processing" │
│ - Send email via SMTP │
│ - Update recipient status │
│ - Update queue status │
│ - Update notification status │
│ 3. Log results │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ Email Sent! │
│ - notification.status → "sent" │
│ - recipient.status → "sent" │
│ - queue.status → "completed" │
│ - notification.actual_sent = count │
└─────────────────────────────────────────┘
```
## Current Implementation
### ✅ What We Have:
- **Non-blocking API** - Returns immediately after queuing
- **Background processor** - Runs every 30 seconds
- **Auto-start on server boot** - Via Nitro plugin
- **Concurrent processing prevention** - Lock mechanism
- **Status updates** - All tables updated correctly
- **Error handling** - Failed emails marked as failed
- **Logging** - Console logs for monitoring
### ❌ What We Don't Have (Yet):
- **BullMQ** - Not using a production queue system
- **Redis** - No distributed queue
- **Worker pools** - Single-threaded processing
- **Job retries** - No automatic retry on failure
- **Priority queues** - All jobs equal priority
- **Rate limiting** - No per-provider rate limits
## Manual Queue Processing
You can manually trigger queue processing via API:
```bash
POST /api/notifications/queue/process
```
This is useful for:
- Testing
- Debugging
- Force processing without waiting
## Monitoring
### Console Logs:
```
🚀 Starting background queue processor...
✅ Queue processor started (runs every 30 seconds)
⚙️ Processing notification queue...
✅ Queue processed: 5 sent, 0 failed, 5 total
```
### Check Queue Status:
```sql
-- See queued items
SELECT * FROM notification_queue WHERE status = 'queued';
-- See processing status
SELECT
n.id,
n.title,
n.status,
COUNT(nr.id) as total_recipients,
SUM(CASE WHEN nr.status = 'sent' THEN 1 ELSE 0 END) as sent,
SUM(CASE WHEN nr.status = 'failed' THEN 1 ELSE 0 END) as failed,
SUM(CASE WHEN nr.status = 'pending' THEN 1 ELSE 0 END) as pending
FROM notifications n
LEFT JOIN notification_recipients nr ON n.id = nr.notification_id
GROUP BY n.id, n.title, n.status;
```
## Configuration
### Queue Processing Interval:
Change in `server/utils/queueProcessor.js`:
```javascript
// Current: 30 seconds
processorInterval = setInterval(processQueue, 30000);
// Faster: 10 seconds
processorInterval = setInterval(processQueue, 10000);
// Slower: 1 minute
processorInterval = setInterval(processQueue, 60000);
```
### Batch Size:
Change in `server/utils/emailService.js`:
```javascript
// Current: 50 jobs per batch
take: 50
// Larger batch: 100 jobs
take: 100
// Smaller batch: 10 jobs
take: 10
```
## Future: Upgrading to BullMQ
If you want a production-grade queue system:
### Install BullMQ:
```bash
npm install bullmq ioredis
```
### Benefits:
- ✅ Persistent queue (survives server restart)
- ✅ Automatic retries with exponential backoff
- ✅ Priority queues
- ✅ Concurrent workers
- ✅ Rate limiting per provider
- ✅ Job scheduling
- ✅ Web UI for monitoring
- ✅ Distributed processing
### When to Upgrade:
- High volume (>1000 emails/day)
- Multiple servers
- Need guaranteed delivery
- Need advanced retry logic
- Need monitoring dashboard
## Troubleshooting
### Queue not processing?
1. Check server logs for errors
2. Check if plugin is loaded: `grep "queue processor" logs`
3. Manually trigger: `POST /api/notifications/queue/process`
### Emails not sending?
1. Check SMTP credentials in delivery settings
2. Check notification_queue table for errors
3. Check notification_recipients for failed status
4. Review email service logs
### Status stuck on "sending"?
1. Check if recipients are still "pending"
2. Manually trigger queue processing
3. Check for errors in notification_queue table
## Summary
**Current System:**
- Simple, lightweight queue using database + setInterval
- Runs every 30 seconds automatically
- Non-blocking API responses
- Suitable for low-medium volume
**When to upgrade:**
- Need higher reliability
- Higher volume
- Multiple servers
- Advanced features
The current system works well for most use cases and can handle thousands of notifications per day!

View File

@@ -0,0 +1,232 @@
# Template Version History
## Overview
The Template Version History feature allows you to track, manage, and restore previous versions of your notification templates. This provides a complete audit trail and the ability to revert changes when needed.
## Features
### 1. Automatic Version Creation
- Every time you update a template, a new version is automatically created
- Version numbers follow a semantic versioning pattern (e.g., 1.0, 1.1, 1.2)
- Each version includes a complete snapshot of the template at that point in time
### 2. Version History View
- Access version history by clicking the "Version History" icon in the template list
- View all versions of a template in chronological order
- See version numbers, change descriptions, and timestamps
- Current version is clearly highlighted
### 3. Version Restoration
- Restore any previous version of a template
- Restoration creates a new version (doesn't overwrite history)
- Automatic backup of current state before restoration
### 4. Version Deletion
- Delete old versions that are no longer needed
- Protection against deleting the current version
- Protection against deleting the only version
## Database Schema
### notification_template_versions Table
| Field | Type | Description |
|-------|------|-------------|
| id | varchar(36) | Primary key (UUID) |
| template_id | varchar(36) | Reference to the main template |
| version | varchar(20) | Version number (e.g., "1.0", "1.1") |
| name | varchar(100) | Template name at this version |
| description | text | Template description |
| subject | varchar(255) | Email subject line |
| email_content | text | Email content/body |
| push_title | varchar(100) | Push notification title |
| push_body | varchar(300) | Push notification body |
| category | varchar(50) | Template category |
| channels | json | Supported channels array |
| status | varchar(20) | Template status (Draft, Active, Archived) |
| change_description | text | Description of what changed |
| is_current | boolean | Whether this is the current version |
| created_by | varchar(36) | User who created this version |
| created_at | timestamp | When this version was created |
## API Endpoints
### Get Version History
```
GET /api/notifications/templates/{id}/versions
```
**Response:**
```json
{
"success": true,
"data": {
"templateId": "template-uuid",
"templateName": "Template Name",
"versions": [
{
"id": "version-uuid",
"version": "1.2",
"name": "Template Name",
"changeDescription": "Updated welcome message",
"isCurrent": false,
"status": "Active",
"formattedCreatedAt": "03/20/2024, 02:30 PM"
}
],
"totalCount": 3
}
}
```
### Restore Version
```
POST /api/notifications/templates/{id}/versions/{versionId}/restore
```
**Response:**
```json
{
"success": true,
"data": {
"message": "Version 1.1 has been restored successfully as version 1.3",
"templateId": "template-uuid",
"restoredVersion": "1.1",
"newVersion": "1.3"
}
}
```
### Delete Version
```
DELETE /api/notifications/templates/{id}/versions/{versionId}
```
**Response:**
```json
{
"success": true,
"data": {
"message": "Version 1.1 has been deleted successfully",
"templateId": "template-uuid",
"deletedVersion": "1.1"
}
}
```
## How to Use
### 1. Setup Database
Run the migration to create the version history table:
```bash
node scripts/run-migration.js
```
Or manually run the SQL migration file:
```bash
mysql -u your_username -p your_database < database/migrations/003_create_template_version_history.sql
```
### 2. Update Prisma Schema
After running the migration, update your Prisma client:
```bash
npx prisma generate
```
### 3. Using the Frontend
#### View Version History
1. Go to the notification templates page
2. Find the template you want to view history for
3. Click the "Version History" icon in the actions column
4. The version history modal will open showing all versions
#### Restore a Version
1. Open the version history modal
2. Find the version you want to restore
3. Click the "Restore" button for that version
4. Confirm the restoration in the popup dialog
5. The version will be restored as a new version
#### Delete a Version
1. Open the version history modal
2. Find the version you want to delete
3. Click the "Delete" button for that version
4. Confirm the deletion in the popup dialog
5. The version will be permanently deleted
## Best Practices
### 1. Version Naming
- Use semantic versioning (major.minor format)
- Increment minor version for small changes
- Increment major version for significant changes
### 2. Change Descriptions
- Always provide meaningful change descriptions
- Include what was changed and why
- Be specific about the modifications made
### 3. Version Management
- Regularly clean up old versions that are no longer needed
- Keep important milestone versions
- Don't delete versions that might be needed for compliance or audit
### 4. Testing
- Test templates thoroughly before making them active
- Use draft status for work-in-progress templates
- Restore previous versions if issues are found
## Security Considerations
### 1. Access Control
- Only authenticated users can access version history
- Users can only manage versions of templates they have access to
- Audit logs track all version operations
### 2. Data Protection
- All version data is stored securely in the database
- Sensitive information in templates is handled according to your data protection policies
- Regular backups include version history data
### 3. Validation
- All version operations are validated before execution
- Protection against malicious version manipulation
- Proper error handling for failed operations
## Troubleshooting
### Common Issues
1. **Version History Not Loading**
- Check database connection
- Verify the template exists
- Check API endpoint responses
2. **Restore Failing**
- Ensure you have proper permissions
- Check if the version exists
- Verify template is not locked
3. **Delete Failing**
- Cannot delete current version
- Cannot delete if it's the only version
- Check user permissions
### Debug Steps
1. Check browser console for errors
2. Verify API responses
3. Check database logs
4. Confirm user authentication
## Future Enhancements
- Version comparison view
- Bulk version operations
- Version export/import
- Advanced filtering and search
- Version approval workflows
- Automated version cleanup policies