244 lines
9.0 KiB
Markdown
244 lines
9.0 KiB
Markdown
# Custom Recipients Implementation
|
|
|
|
## Overview
|
|
This feature allows campaigns to target any email address (custom recipients) instead of or in addition to elected representatives from the Represent API.
|
|
|
|
## Implementation Summary
|
|
|
|
### ✅ Backend (Complete)
|
|
|
|
#### 1. Database Schema (`scripts/build-nocodb.sh`)
|
|
- **custom_recipients table** with fields:
|
|
- `id` - Primary key
|
|
- `campaign_id` - Links to campaigns table
|
|
- `campaign_slug` - Campaign identifier
|
|
- `recipient_name` - Full name of recipient
|
|
- `recipient_email` - Email address
|
|
- `recipient_title` - Job title/position (optional)
|
|
- `recipient_organization` - Organization name (optional)
|
|
- `notes` - Internal notes (optional)
|
|
- `is_active` - Boolean flag
|
|
|
|
- **campaigns table** updated:
|
|
- Added `allow_custom_recipients` boolean field (default: false)
|
|
|
|
#### 2. Backend Controller (`app/controllers/customRecipients.js`)
|
|
Full CRUD operations:
|
|
- `getRecipientsByCampaign(req, res)` - Fetch all recipients for a campaign
|
|
- `createRecipient(req, res)` - Add single recipient with validation
|
|
- `bulkCreateRecipients(req, res)` - Import multiple recipients from CSV
|
|
- `updateRecipient(req, res)` - Update recipient details
|
|
- `deleteRecipient(req, res)` - Delete single recipient
|
|
- `deleteAllRecipients(req, res)` - Clear all recipients for a campaign
|
|
|
|
#### 3. NocoDB Service (`app/services/nocodb.js`)
|
|
- `getCustomRecipients(campaignId)` - Query by campaign ID
|
|
- `getCustomRecipientsBySlug(campaignSlug)` - Query by slug
|
|
- `createCustomRecipient(recipientData)` - Create with field mapping
|
|
- `updateCustomRecipient(recipientId, updateData)` - Partial updates
|
|
- `deleteCustomRecipient(recipientId)` - Single deletion
|
|
- `deleteCustomRecipientsByCampaign(campaignId)` - Bulk deletion
|
|
|
|
#### 4. API Routes (`app/routes/api.js`)
|
|
All routes protected with `requireNonTemp` authentication:
|
|
- `GET /api/campaigns/:slug/custom-recipients` - List all recipients
|
|
- `POST /api/campaigns/:slug/custom-recipients` - Create single recipient
|
|
- `POST /api/campaigns/:slug/custom-recipients/bulk` - Bulk import
|
|
- `PUT /api/campaigns/:slug/custom-recipients/:id` - Update recipient
|
|
- `DELETE /api/campaigns/:slug/custom-recipients/:id` - Delete recipient
|
|
- `DELETE /api/campaigns/:slug/custom-recipients` - Delete all recipients
|
|
|
|
#### 5. Campaign Controller Updates (`app/controllers/campaigns.js`)
|
|
- Added `allow_custom_recipients` field to all campaign CRUD operations
|
|
- Field normalization in 5+ locations for consistent API responses
|
|
|
|
### ✅ Frontend (Complete)
|
|
|
|
#### 1. JavaScript Module (`app/public/js/custom-recipients.js`)
|
|
Comprehensive module with:
|
|
- **CRUD Operations**: Add, edit, delete recipients
|
|
- **Bulk Import**: CSV file upload or paste with parsing
|
|
- **Validation**: Email format validation
|
|
- **UI Management**: Dynamic recipient list display with cards
|
|
- **Error Handling**: User-friendly error messages
|
|
- **XSS Protection**: HTML escaping for security
|
|
|
|
Key methods:
|
|
```javascript
|
|
CustomRecipients.init(campaignSlug) // Initialize module
|
|
CustomRecipients.loadRecipients(slug) // Load from API
|
|
CustomRecipients.displayRecipients() // Render list
|
|
// Plus handleAddRecipient, handleEditRecipient, handleDeleteRecipient, etc.
|
|
```
|
|
|
|
#### 2. Admin Panel Integration (`app/public/admin.html` + `app/public/js/admin.js`)
|
|
- **Create Form**: Checkbox to enable custom recipients
|
|
- **Edit Form**:
|
|
- Checkbox with show/hide toggle
|
|
- Add recipient form (5 fields: name, email, title, organization, notes)
|
|
- Bulk CSV import button with modal
|
|
- Recipients list with edit/delete actions
|
|
- Clear all button
|
|
- **JavaScript Integration**:
|
|
- `toggleCustomRecipientsSection()` - Show/hide based on checkbox
|
|
- `setupCustomRecipientsHandlers()` - Event listeners for checkbox
|
|
- Auto-load recipients when editing campaign with feature enabled
|
|
- Form data includes `allow_custom_recipients` in create/update
|
|
|
|
#### 3. Bulk Import Modal (`app/public/admin.html`)
|
|
Complete modal with:
|
|
- CSV format instructions
|
|
- File upload input
|
|
- Paste textarea for direct CSV input
|
|
- Import results display with success/failure details
|
|
- CSV format: `recipient_name,recipient_email,recipient_title,recipient_organization,notes`
|
|
|
|
#### 4. CSS Styling (`app/public/admin.html`)
|
|
- `.recipient-card` - Card layout with hover effects
|
|
- `.recipient-info` - Name, email, metadata display
|
|
- `.recipient-actions` - Edit/delete icon buttons with hover colors
|
|
- `.bulk-import-help` - Modal styling
|
|
- Responsive grid layout
|
|
|
|
## Usage
|
|
|
|
### For Administrators:
|
|
|
|
1. **Create Campaign**:
|
|
- Check "Allow Custom Recipients" during creation
|
|
- An info section will appear explaining that recipients can be added after campaign is created
|
|
- Complete the campaign creation
|
|
|
|
2. **Edit Campaign**:
|
|
- Navigate to the Edit tab and select your campaign
|
|
- Check "Allow Custom Recipients" to enable the feature
|
|
- The custom recipients management section will appear below the checkbox
|
|
|
|
3. **Add Single Recipient**:
|
|
- Fill in name (required) and email (required)
|
|
- Optionally add title, organization, notes
|
|
- Click "Add Recipient"
|
|
|
|
4. **Bulk Import**:
|
|
- Click "Bulk Import (CSV)" button
|
|
- Upload CSV file or paste CSV data
|
|
- CSV format: `recipient_name,recipient_email,recipient_title,recipient_organization,notes`
|
|
- First row can be header (will be skipped if contains "recipient_name")
|
|
- Results show success/failure for each row
|
|
|
|
5. **Edit Recipient**:
|
|
- Click edit icon on recipient card
|
|
- Form populates with current data
|
|
- Make changes and click "Update Recipient"
|
|
- Or click "Cancel" to revert
|
|
|
|
6. **Delete Recipients**:
|
|
- Single: Click delete icon on card
|
|
- All: Click "Clear All" button
|
|
|
|
### API Examples:
|
|
|
|
```bash
|
|
# Create recipient
|
|
curl -X POST /api/campaigns/my-campaign/custom-recipients \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"recipient_name": "Jane Doe",
|
|
"recipient_email": "jane@example.com",
|
|
"recipient_title": "CEO",
|
|
"recipient_organization": "Tech Corp"
|
|
}'
|
|
|
|
# Bulk import
|
|
curl -X POST /api/campaigns/my-campaign/custom-recipients/bulk \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"recipients": [
|
|
{"recipient_name": "John Smith", "recipient_email": "john@example.com"},
|
|
{"recipient_name": "Jane Doe", "recipient_email": "jane@example.com"}
|
|
]
|
|
}'
|
|
|
|
# Get all recipients
|
|
curl /api/campaigns/my-campaign/custom-recipients
|
|
|
|
# Update recipient
|
|
curl -X PUT /api/campaigns/my-campaign/custom-recipients/123 \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"recipient_title": "CTO"}'
|
|
|
|
# Delete recipient
|
|
curl -X DELETE /api/campaigns/my-campaign/custom-recipients/123
|
|
|
|
# Delete all recipients
|
|
curl -X DELETE /api/campaigns/my-campaign/custom-recipients
|
|
```
|
|
|
|
## Security Features
|
|
|
|
- **Authentication**: All API routes require non-temporary user session
|
|
- **Validation**: Email format validation on client and server
|
|
- **XSS Protection**: HTML escaping in display
|
|
- **Campaign Check**: Verifies campaign exists and feature is enabled
|
|
- **Input Sanitization**: express-validator on API endpoints
|
|
|
|
## Next Steps (TODO)
|
|
|
|
1. **Dashboard Integration**: Add same UI to `dashboard.html` for regular users
|
|
2. **Campaign Display**: Update `campaign.js` to show custom recipients alongside elected officials
|
|
3. **Email Composer**: Ensure custom recipients work in email sending flow
|
|
4. **Testing**: Comprehensive end-to-end testing
|
|
5. **Documentation**: Update main README and files-explainer
|
|
|
|
## Files Modified/Created
|
|
|
|
### Backend:
|
|
- ✅ `scripts/build-nocodb.sh` - Database schema
|
|
- ✅ `app/controllers/customRecipients.js` - NEW FILE (282 lines)
|
|
- ✅ `app/services/nocodb.js` - Service methods
|
|
- ✅ `app/routes/api.js` - API endpoints
|
|
- ✅ `app/controllers/campaigns.js` - Field updates
|
|
|
|
### Frontend:
|
|
- ✅ `app/public/js/custom-recipients.js` - NEW FILE (538 lines)
|
|
- ✅ `app/public/js/admin.js` - Integration code
|
|
- ✅ `app/public/admin.html` - UI components and forms
|
|
|
|
### Documentation:
|
|
- ✅ `CUSTOM_RECIPIENTS_IMPLEMENTATION.md` - This file
|
|
|
|
## Testing Checklist
|
|
|
|
- [ ] Database table creation (run build-nocodb.sh)
|
|
- [ ] Create campaign with custom recipients enabled
|
|
- [ ] Add single recipient via form
|
|
- [ ] Edit recipient information
|
|
- [ ] Delete single recipient
|
|
- [ ] Bulk import via CSV file
|
|
- [ ] Bulk import via paste
|
|
- [ ] Clear all recipients
|
|
- [ ] Toggle checkbox on/off
|
|
- [ ] Verify API authentication
|
|
- [ ] Test with campaign where feature is disabled
|
|
- [ ] Check recipient display on campaign page
|
|
- [ ] Test email sending to custom recipients
|
|
|
|
## Known Limitations
|
|
|
|
1. Custom recipients can only be added AFTER campaign is created (not during creation)
|
|
2. Dashboard UI not yet implemented (admin panel only)
|
|
3. Campaign display page doesn't show custom recipients yet
|
|
4. CSV import uses simple comma splitting (doesn't handle quoted commas)
|
|
5. No duplicate email detection
|
|
|
|
## Future Enhancements
|
|
|
|
- [ ] Duplicate email detection/prevention
|
|
- [ ] Import validation preview before saving
|
|
- [ ] Export recipients to CSV
|
|
- [ ] Recipient groups/categories
|
|
- [ ] Import from external sources (Google Contacts, etc.)
|
|
- [ ] Recipient engagement tracking
|
|
- [ ] Custom fields for recipients
|
|
- [ ] Merge tags in email templates using recipient data
|