544 lines
19 KiB
Markdown
544 lines
19 KiB
Markdown
# BNKops Influence Campaign Tool
|
|
|
|
A comprehensive web application that helps Alberta residents connect with their elected representatives across all levels of government. Users can find their representatives by postal code and send direct emails to advocate for important issues.
|
|
|
|
## Features
|
|
|
|
- **Representative Lookup**: Find elected officials by Alberta postal code (T prefixed)
|
|
- **Multi-Level Government**: Displays federal MPs, provincial MLAs, and municipal representatives
|
|
- **Contact Information**: Shows photos, email addresses, phone numbers, and office locations
|
|
- **Direct Email**: Built-in email composer to contact representatives
|
|
- **Campaign Management**: Create and manage advocacy campaigns with customizable settings
|
|
- **Public Campaigns Grid**: Homepage display of all active campaigns for easy discovery and participation
|
|
- **Response Wall**: Community-driven platform for sharing and voting on representative responses
|
|
- **Email Count Display**: Optional engagement metrics showing total emails sent per campaign
|
|
- **Smart Caching**: Fast performance with NocoDB caching and graceful fallback to live API
|
|
- **Responsive Design**: Works seamlessly on desktop and mobile devices
|
|
- **Real-time Data**: Integrates with Represent OpenNorth API for up-to-date information
|
|
|
|
## Technology Stack
|
|
|
|
- **Backend**: Node.js with Express.js
|
|
- **Database**: NocoDB (REST API)
|
|
- **External API**: Represent OpenNorth Canada API
|
|
- **Frontend**: Vanilla JavaScript, HTML5, CSS3
|
|
- **Email**: SMTP integration
|
|
- **Deployment**: Docker with docker-compose
|
|
- **Rate Limiting**: Express rate limiter for API protection
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
- Docker and Docker Compose
|
|
- Access to existing NocoDB instance
|
|
- SMTP email configuration
|
|
|
|
### Installation
|
|
|
|
1. **Clone and navigate to the project**:
|
|
```bash
|
|
cd /path/to/changemaker.lite/influence
|
|
```
|
|
|
|
2. **Configure environment**:
|
|
```bash
|
|
cp .env.example .env
|
|
# Edit .env with your configuration
|
|
```
|
|
|
|
3. **Set up NocoDB tables**:
|
|
```bash
|
|
./scripts/build-nocodb.sh
|
|
```
|
|
|
|
4. **Start the application**:
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
5. **Access the application**:
|
|
- Open http://localhost:3333
|
|
- Enter an Alberta postal code (e.g., T5N4B8)
|
|
- View your representatives and send emails
|
|
|
|
## Development Mode
|
|
|
|
### Email Testing with MailHog
|
|
|
|
For development and testing, the application includes MailHog integration to safely test email functionality without sending real emails to elected officials.
|
|
|
|
#### Quick Setup for Development
|
|
|
|
1. **Use development configuration**:
|
|
```bash
|
|
# Your .env should include these settings for development:
|
|
NODE_ENV=development
|
|
EMAIL_TEST_MODE=true
|
|
SMTP_HOST=mailhog
|
|
SMTP_PORT=1025
|
|
SMTP_USER=test
|
|
SMTP_PASS=test
|
|
TEST_EMAIL_RECIPIENT=your-email@example.com
|
|
```
|
|
|
|
2. **Start with MailHog included**:
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
3. **Access development tools**:
|
|
- **Application**: http://localhost:3333
|
|
- **Email Testing Interface**: http://localhost:3333/email-test.html (admin login required)
|
|
- **MailHog Web UI**: http://localhost:8025 (view all caught emails)
|
|
|
|
#### Email Testing Features
|
|
|
|
**Test Mode Benefits:**
|
|
- ✅ All emails redirected to your test recipient
|
|
- ✅ Original recipient shown in subject line: `[TEST - Original: real@email.com] Subject`
|
|
- ✅ Safe testing without spamming elected officials
|
|
- ✅ Complete email logging with test mode indicators
|
|
|
|
**Email Testing Interface** (`/email-test.html`):
|
|
- **Quick Test**: Send test email with one click
|
|
- **Email Preview**: See exactly how emails will look before sending
|
|
- **Custom Composition**: Test with your own subject and message content
|
|
- **Email Logs**: View all sent emails with test/live filtering
|
|
- **SMTP Diagnostics**: Test connection and troubleshoot issues
|
|
|
|
**MailHog Web Interface** (`http://localhost:8025`):
|
|
- View all emails caught during development
|
|
- Inspect email content, headers, and formatting
|
|
- Search and filter caught emails
|
|
- No emails leave your local environment
|
|
|
|
#### Development Workflow
|
|
|
|
1. **Safe Development**:
|
|
```bash
|
|
# Ensure test mode is enabled
|
|
EMAIL_TEST_MODE=true
|
|
|
|
# Start development environment
|
|
docker compose up --build
|
|
```
|
|
|
|
2. **Test Email Functionality**:
|
|
- Use the main app to send emails (they'll be redirected)
|
|
- Check MailHog UI to see the actual email content
|
|
- Use `/email-test.html` for advanced testing and preview
|
|
|
|
3. **Production Deployment**:
|
|
```bash
|
|
# Switch to production SMTP settings
|
|
EMAIL_TEST_MODE=false
|
|
SMTP_HOST=smtp.your-provider.com
|
|
SMTP_USER=your-real-email@domain.com
|
|
SMTP_PASS=your-real-password
|
|
|
|
# Restart application
|
|
docker compose restart
|
|
```
|
|
|
|
#### Development Environment Variables
|
|
|
|
```bash
|
|
# Development Mode Configuration
|
|
NODE_ENV=development
|
|
EMAIL_TEST_MODE=true
|
|
|
|
# MailHog SMTP (for development)
|
|
SMTP_HOST=mailhog
|
|
SMTP_PORT=1025
|
|
SMTP_SECURE=false
|
|
SMTP_USER=test
|
|
SMTP_PASS=test
|
|
SMTP_FROM_EMAIL=dev@albertainfluence.local
|
|
SMTP_FROM_NAME="BNKops Influence Campaign (DEV)"
|
|
|
|
# Email Testing
|
|
TEST_EMAIL_RECIPIENT=developer@example.com
|
|
|
|
# Production SMTP (commented out for dev)
|
|
# SMTP_HOST=smtp.protonmail.ch
|
|
# SMTP_PORT=587
|
|
# SMTP_USER=your-production-email@domain.com
|
|
# SMTP_PASS=your-production-password
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables (.env)
|
|
|
|
```bash
|
|
# Server Configuration
|
|
NODE_ENV=production
|
|
PORT=3333
|
|
|
|
# NocoDB Configuration
|
|
NOCODB_API_URL=https://db.cmlite.org
|
|
NOCODB_API_TOKEN=your_nocodb_token
|
|
NOCODB_PROJECT_ID=your_project_id
|
|
|
|
# Email Configuration (SMTP)
|
|
SMTP_HOST=smtp.gmail.com
|
|
SMTP_PORT=587
|
|
SMTP_SECURE=false
|
|
SMTP_USER=your_email@gmail.com
|
|
SMTP_PASS=your_app_password
|
|
SMTP_FROM_NAME=BNKops Influence Campaign
|
|
SMTP_FROM_EMAIL=your_email@gmail.com
|
|
|
|
# Rate Limiting
|
|
RATE_LIMIT_WINDOW_MS=900000
|
|
RATE_LIMIT_MAX_REQUESTS=100
|
|
```
|
|
|
|
## Campaign Management Guide
|
|
|
|
### Creating a Campaign
|
|
|
|
1. **Access Admin Panel**: Navigate to `/admin.html` and log in with admin credentials
|
|
2. **Create New Campaign**: Click "Create Campaign" button
|
|
3. **Configure Basic Settings**:
|
|
- **Campaign Title**: Short, descriptive name (becomes the URL slug)
|
|
- **Description**: Brief overview shown on the campaign landing page
|
|
- **Call to Action**: Motivational message encouraging participation
|
|
|
|
4. **Set Email Template**:
|
|
- **Email Subject**: Pre-filled subject line for emails
|
|
- **Email Body**: Default message template (users may edit if allowed)
|
|
|
|
5. **Upload Cover Photo** (Optional):
|
|
- Click "Choose File" to upload a hero image
|
|
- Supported formats: JPEG, PNG, GIF, WebP
|
|
- Maximum size: 5MB
|
|
- Image displays as campaign page banner
|
|
|
|
6. **Configure Campaign Settings**:
|
|
- **📧 Allow SMTP Email**: Enable server-side email sending
|
|
- **🔗 Allow Mailto Link**: Enable browser-based mailto: links
|
|
- **👤 Collect User Info**: Request user name and email
|
|
- **📊 Show Email Count**: Display total emails sent (engagement metric)
|
|
- **✏️ Allow Email Editing**: Let users customize email template
|
|
- **🎯 Target Government Levels**: Select Federal, Provincial, Municipal, School Board
|
|
|
|
7. **Set Campaign Status**:
|
|
- **Draft**: Hidden from public, testing mode
|
|
- **Active**: Visible to public on main page
|
|
- **Paused**: Temporarily disabled
|
|
- **Archived**: Completed campaigns
|
|
|
|
8. **Save Campaign**: Click "Create Campaign" to publish
|
|
|
|
### Public Campaigns Display
|
|
|
|
The homepage automatically displays all active campaigns in a responsive grid below the representative lookup section.
|
|
|
|
**Features**:
|
|
- **Automatic Display**: Only active campaigns (status="active") are shown publicly
|
|
- **Campaign Cards**: Each campaign displays as an attractive card with:
|
|
- Cover photo (if uploaded) or gradient background
|
|
- Campaign title and truncated description
|
|
- Target government level badges (Federal, Provincial, Municipal, etc.)
|
|
- Email count badge (if enabled via campaign settings)
|
|
- "Learn More & Participate" call-to-action
|
|
- **Responsive Grid**: Automatically adjusts columns based on screen size
|
|
- Desktop: 3-4 columns
|
|
- Tablet: 2 columns
|
|
- Mobile: 1 column
|
|
- **Click Navigation**: Users can click any campaign card to visit the full campaign page
|
|
- **Smart Loading**: Shows loading state while fetching campaigns, gracefully hides section if no active campaigns exist
|
|
- **Security**: HTML content is escaped to prevent XSS attacks
|
|
- **Sorting**: Campaigns display newest first by creation date
|
|
|
|
**Public API Endpoint**: `/api/public/campaigns` (no authentication required)
|
|
- Returns only campaigns with `status='active'`
|
|
- Includes email counts when `show_email_count=true`
|
|
- Optimized for performance with minimal data transfer
|
|
|
|
### Email Count Display Feature
|
|
|
|
The **Show Email Count** setting controls whether campaign pages display total engagement metrics.
|
|
|
|
**When Enabled** (✅ checked):
|
|
- Campaign page shows: "X Albertans have sent emails through this campaign"
|
|
- Provides social proof and encourages participation
|
|
- Updates in real-time as users send emails
|
|
- Displays prominently above the call-to-action
|
|
|
|
**When Disabled** (❌ unchecked):
|
|
- Email count section is hidden
|
|
- Useful for sensitive campaigns or privacy concerns
|
|
- Engagement metrics still tracked in admin panel
|
|
|
|
**Best Practices**:
|
|
- ✅ Enable for public awareness campaigns to show momentum
|
|
- ✅ Enable for volunteer recruitment to demonstrate support
|
|
- ❌ Disable for personal advocacy or sensitive issues
|
|
- ❌ Disable for new campaigns until participation grows
|
|
|
|
**Technical Details**:
|
|
- Count includes all successfully sent emails via campaign
|
|
- Tracks both SMTP-sent and mailto-initiated emails (if logged)
|
|
- Admin panel always shows counts regardless of public display setting
|
|
- Database field: `show_email_count` (checkbox, default: true)
|
|
|
|
### Editing Campaigns
|
|
|
|
1. Navigate to Admin Panel → "Campaigns" tab
|
|
2. Find campaign card and click "Edit"
|
|
3. Modify any settings including the email count display toggle
|
|
4. Save changes - updates apply immediately to public-facing page
|
|
|
|
### Campaign Analytics
|
|
|
|
Access campaign performance metrics in the Admin Panel:
|
|
- Total emails sent per campaign
|
|
- User participation rates
|
|
- Email delivery status
|
|
- Representative contact distribution
|
|
|
|
## API Endpoints
|
|
|
|
### Representatives
|
|
- `GET /api/representatives/by-postal/:postalCode` - Get representatives by postal code
|
|
- `POST /api/representatives/refresh-postal/:postalCode` - Refresh cached data
|
|
|
|
### Email
|
|
- `POST /api/emails/send` - Send email to representative
|
|
- `GET /api/emails/logs` - Get email sending logs (with filters)
|
|
|
|
### Email Testing (Development)
|
|
- `POST /api/emails/preview` - Preview email without sending (admin only)
|
|
- `POST /api/emails/test` - Send test email to configured recipient (admin only)
|
|
- `GET /api/test-smtp` - Test SMTP connection (admin only)
|
|
|
|
### Health
|
|
- `GET /api/health` - Application health check
|
|
- `GET /api/test-represent` - Test Represent API connection
|
|
|
|
## Database Schema
|
|
|
|
### Campaigns Table
|
|
- slug, title, description
|
|
- email_subject, email_body
|
|
- call_to_action, cover_photo
|
|
- status (draft/active/paused/archived)
|
|
- allow_smtp_email, allow_mailto_link
|
|
- collect_user_info, **show_email_count**
|
|
- allow_email_editing
|
|
- target_government_levels (MultiSelect)
|
|
- created_by_user_id, created_by_user_email, created_by_user_name
|
|
|
|
### Campaign Emails Table
|
|
- campaign_id, user_name, user_email, user_postal_code
|
|
- recipient_name, recipient_email, recipient_level
|
|
- subject, message, status, sent_at
|
|
|
|
### Representatives Table
|
|
- postal_code, name, email, district_name
|
|
- elected_office, party_name, representative_set_name
|
|
- url, photo_url, cached_at
|
|
|
|
### Email Logs Table
|
|
- recipient_email, recipient_name, sender_email
|
|
- subject, message, status, sent_at
|
|
|
|
### Postal Codes Table
|
|
- postal_code, city, province
|
|
- centroid_lat, centroid_lng, last_updated
|
|
|
|
### Users Table
|
|
- email, password_hash, name
|
|
- role (admin/user), status (active/temporary)
|
|
- expires_at, last_login
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
```
|
|
influence/
|
|
├── app/
|
|
│ ├── controllers/ # Business logic
|
|
│ ├── routes/ # API routes
|
|
│ ├── services/ # External integrations
|
|
│ ├── utils/ # Helper functions
|
|
│ ├── middleware/ # Express middleware
|
|
│ ├── public/ # Frontend assets
|
|
│ └── server.js # Express app entry point
|
|
├── scripts/
|
|
│ └── build-nocodb.sh # Database setup
|
|
├── docker-compose.yml # Container orchestration
|
|
├── Dockerfile # Container definition
|
|
└── .env # Environment configuration
|
|
```
|
|
|
|
### Key Components
|
|
|
|
- **RepresentativesController**: Handles postal code lookups and caching
|
|
- **EmailController**: Manages email composition, sending, and testing
|
|
- **NocoDBService**: Database operations with error handling
|
|
- **RepresentAPI**: Integration with OpenNorth Represent API
|
|
- **EmailService**: SMTP email functionality with test mode support
|
|
- **Email Testing System**: Preview, test, and log email functionality for development
|
|
|
|
## Features in Detail
|
|
|
|
### Smart Caching System
|
|
- First request fetches from Represent API and caches in NocoDB
|
|
- Subsequent requests served from cache for fast performance
|
|
- Graceful fallback to API when NocoDB is unavailable
|
|
- Automatic error recovery and retry logic
|
|
|
|
### Representative Display
|
|
- Shows photo with fallback to initials
|
|
- Contact information including phone and address
|
|
- Party affiliation and government level
|
|
- Direct links to official profiles
|
|
|
|
### Campaign System
|
|
- **Campaign Creation**: Create advocacy campaigns with custom titles, descriptions, and email templates
|
|
- **Cover Photos**: Upload hero images for campaign landing pages (JPEG/PNG/GIF/WebP, max 5MB)
|
|
- **Flexible Email Methods**: Choose between SMTP email or mailto links for user convenience
|
|
- **User Info Collection**: Optional name/email collection for campaign tracking
|
|
- **Email Count Display**: Show total engagement metrics on campaign pages (toggle on/off)
|
|
- **Email Editing**: Allow users to customize campaign email templates (optional)
|
|
- **Target Levels**: Select which government levels to target (Federal/Provincial/Municipal/School Board)
|
|
- **Campaign Status**: Draft, Active, Paused, or Archived workflow states
|
|
|
|
### Response Wall Feature
|
|
The Response Wall creates transparency and accountability by allowing campaign participants to share responses they receive from elected representatives.
|
|
|
|
**Key Features:**
|
|
- **Public Response Sharing**: Constituents can post responses received via email, letter, phone, meetings, or social media
|
|
- **Community Voting**: Upvote system highlights helpful and representative responses
|
|
- **Verification System**: Admin-moderated verification badges for authentic responses
|
|
- **Screenshot Support**: Upload visual proof of responses (images up to 5MB)
|
|
- **Anonymous Posting**: Option to share responses without revealing identity
|
|
- **Filtering & Sorting**: Filter by government level, sort by recent/upvotes/verified
|
|
- **Engagement Statistics**: Track total responses, verified count, and community upvotes
|
|
- **Moderation Queue**: Admin panel for approving, rejecting, or verifying submitted responses
|
|
- **Campaign Integration**: Response walls linked to specific campaigns for contextualized feedback
|
|
|
|
**Access Response Wall:**
|
|
- Via campaign page: Add `?campaign=your-campaign-slug` parameter to `/response-wall.html`
|
|
- Admin moderation: Navigate to "Response Moderation" tab in admin panel
|
|
- Public viewing: All approved responses visible to encourage participation
|
|
|
|
**Moderation Workflow:**
|
|
1. Users submit responses with required details (representative name, level, type, response text)
|
|
2. Submissions enter "pending" status in moderation queue
|
|
3. Admins review and approve/reject from admin panel
|
|
4. Approved responses appear on public Response Wall
|
|
5. Admins can mark verified responses with special badge
|
|
6. Community upvotes highlight most impactful responses
|
|
|
|
### QR Code Sharing Feature
|
|
The application includes dynamic QR code generation for easy campaign and response wall sharing.
|
|
|
|
**Key Features:**
|
|
- **Campaign QR Codes**: Generate scannable QR codes for campaign pages
|
|
- **Response Wall QR Codes**: Share response walls with QR codes for mobile scanning
|
|
- **High-Quality Generation**: 400x400px PNG images with high error correction (level H)
|
|
- **Download Support**: One-click download of QR code images for printing or sharing
|
|
- **Social Integration**: QR code button alongside social share buttons (Facebook, Twitter, LinkedIn, etc.)
|
|
- **Caching**: QR codes cached for 1 hour to improve performance
|
|
|
|
**How to Use:**
|
|
1. Visit any campaign page or response wall
|
|
2. Click the QR code icon (📱) in the social share buttons section
|
|
3. A modal appears with the generated QR code
|
|
4. Scan with any smartphone camera to visit the page
|
|
5. Click "Download QR Code" to save the image for printing or sharing
|
|
|
|
**Technical Implementation:**
|
|
- Backend endpoint: `GET /api/campaigns/:slug/qrcode?type=campaign|response-wall`
|
|
- Uses `qrcode` npm package for generation
|
|
- Proper MIME type and cache headers
|
|
- Modal UI with download functionality
|
|
|
|
**Use Cases:**
|
|
- Print QR codes on flyers and posters for offline campaign promotion
|
|
- Share QR codes in presentations and meetings
|
|
- Include in email newsletters for mobile-friendly access
|
|
- Display at events for easy sign-up
|
|
|
|
### Email Integration
|
|
- Modal-based email composer
|
|
- Pre-filled recipient information
|
|
- SMTP sending with delivery confirmation
|
|
- Email history and logging
|
|
|
|
### Error Handling
|
|
- Comprehensive error logging
|
|
- User-friendly error messages
|
|
- API fallback mechanisms
|
|
- Rate limiting protection
|
|
|
|
## Production Deployment
|
|
|
|
### Docker Production
|
|
```bash
|
|
# Build and start in production mode
|
|
docker compose -f docker-compose.yml up -d --build
|
|
|
|
# View logs
|
|
docker compose logs -f app
|
|
|
|
# Scale if needed
|
|
docker compose up --scale app=2
|
|
```
|
|
|
|
### Monitoring
|
|
- Health check endpoint: `/api/health`
|
|
- Application logs via Docker
|
|
- NocoDB integration status monitoring
|
|
- Email delivery tracking
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **NocoDB Connection Errors**:
|
|
- Check API URL and token in .env
|
|
- Run `./scripts/build-nocodb.sh` to setup tables
|
|
- Application works without NocoDB (API fallback)
|
|
|
|
2. **Email Not Sending**:
|
|
- Verify SMTP credentials in .env
|
|
- Check spam/junk folders
|
|
- Review email logs via API endpoint
|
|
- In development: Check MailHog UI at http://localhost:8025
|
|
- Use email testing interface at `/email-test.html` for diagnostics
|
|
|
|
3. **No Representatives Found**:
|
|
- Ensure postal code starts with 'T' (Alberta)
|
|
- Check Represent API status
|
|
- Try different postal code format
|
|
|
|
### Log Analysis
|
|
```bash
|
|
# View application logs
|
|
docker compose logs app
|
|
|
|
# Follow logs in real-time
|
|
docker compose logs -f app
|
|
|
|
# Check specific errors
|
|
docker compose logs app | grep ERROR
|
|
```
|
|
|
|
## Contributing
|
|
|
|
This is part of the larger changemaker.lite project. Follow the established patterns for:
|
|
- Error handling and logging
|
|
- API response formats
|
|
- Database integration
|
|
- Frontend component structure
|
|
|
|
## License
|
|
|
|
Part of the changemaker.lite project ecosystem.
|
|
|