tonne of imporvements, debugs, new ui

This commit is contained in:
2025-09-20 15:58:55 -06:00
parent f49306a96f
commit b6960e45e8
13 changed files with 673 additions and 87 deletions

View File

@@ -11,7 +11,7 @@ class CampaignsController {
// Get email counts for each campaign and normalize data structure
const campaignsWithCounts = await Promise.all(campaigns.map(async (campaign) => {
const id = campaign.Id ?? campaign.id;
const id = campaign.ID || campaign.Id || campaign.id;
let emailCount = 0;
if (id != null) {
emailCount = await nocoDB.getCampaignEmailCount(id);
@@ -66,7 +66,13 @@ class CampaignsController {
});
}
const normalizedId = campaign.Id ?? campaign.id ?? id;
// Debug logging
console.log('Campaign object keys:', Object.keys(campaign));
console.log('Campaign ID field:', campaign.ID, campaign.Id, campaign.id);
const normalizedId = campaign.ID || campaign.Id || campaign.id;
console.log('Using normalized ID:', normalizedId);
const emailCount = await nocoDB.getCampaignEmailCount(normalizedId);
// Normalize campaign data structure for frontend
@@ -136,7 +142,7 @@ class CampaignsController {
res.json({
success: true,
campaign: {
id: campaign.Id || campaign.id,
id: campaign.ID || campaign.Id || campaign.id,
slug: campaign['Campaign Slug'] || campaign.slug,
title: campaign['Campaign Title'] || campaign.title,
description: campaign['Description'] || campaign.description,
@@ -219,7 +225,7 @@ class CampaignsController {
res.status(201).json({
success: true,
campaign: {
id: campaign.Id ?? campaign.id,
id: campaign.ID || campaign.Id || campaign.id,
slug: campaign['Campaign Slug'] || campaign.slug,
title: campaign['Campaign Title'] || campaign.title,
description: campaign['Description'] || campaign.description,
@@ -259,7 +265,7 @@ class CampaignsController {
// Ensure slug is unique (but allow current campaign to keep its slug)
const existingCampaign = await nocoDB.getCampaignBySlug(slug);
const existingId = existingCampaign ? (existingCampaign.Id || existingCampaign.id) : null;
const existingId = existingCampaign ? (existingCampaign.ID || existingCampaign.Id || existingCampaign.id) : null;
if (existingCampaign && String(existingId) !== String(id)) {
let counter = 1;
let originalSlug = slug;
@@ -288,7 +294,7 @@ class CampaignsController {
res.json({
success: true,
campaign: {
id: campaign.Id ?? campaign.id ?? id,
id: campaign.ID || campaign.Id || campaign.id,
slug: campaign['Campaign Slug'] || campaign.slug,
title: campaign['Campaign Title'] || campaign.title,
description: campaign['Description'] || campaign.description,
@@ -361,8 +367,10 @@ class CampaignsController {
error: 'Campaign not found'
});
}
if (campaign.status !== 'active') {
if ((campaign['Status'] || campaign.status) !== 'active') {
return res.status(403).json({
success: false,
error: 'Campaign is not currently active'
@@ -370,22 +378,22 @@ class CampaignsController {
}
// Check if the requested email method is allowed
if (emailMethod === 'smtp' && !campaign.allow_smtp_email) {
if (emailMethod === 'smtp' && !(campaign['Allow SMTP Email'] || campaign.allow_smtp_email)) {
return res.status(403).json({
success: false,
error: 'SMTP email sending is not enabled for this campaign'
});
}
if (emailMethod === 'mailto' && !campaign.allow_mailto_link) {
if (emailMethod === 'mailto' && !(campaign['Allow Mailto Link'] || campaign.allow_mailto_link)) {
return res.status(403).json({
success: false,
error: 'Mailto links are not enabled for this campaign'
});
}
const subject = campaign.email_subject;
const message = campaign.email_body;
const subject = campaign['Email Subject'] || campaign.email_subject;
const message = campaign['Email Body'] || campaign.email_body;
let emailResult = { success: true };
@@ -403,14 +411,14 @@ class CampaignsController {
html: `
<p>${message.replace(/\n/g, '<br>')}</p>
<hr>
<p><small>This message was sent via the Alberta Influence Campaign Tool by ${userName || 'A constituent'} (${userEmail}) from postal code ${postalCode} as part of the "${campaign.title}" campaign.</small></p>
<p><small>This message was sent via the BNKops Influence Campaign Tool by ${userName || 'A constituent'} (${userEmail}) from postal code ${postalCode} as part of the "${campaign['Campaign Title'] || campaign.title}" campaign.</small></p>
`
});
}
// Log the campaign email
await nocoDB.logCampaignEmail({
campaign_id: campaign.Id ?? campaign.id,
campaign_id: campaign.ID || campaign.Id || campaign.id,
campaign_slug: slug,
user_email: userEmail,
user_name: userName,
@@ -422,8 +430,7 @@ class CampaignsController {
email_method: emailMethod,
subject: subject,
message: message,
status: emailMethod === 'mailto' ? 'clicked' : (emailResult.success ? 'sent' : 'failed'),
timestamp: new Date().toISOString()
status: emailMethod === 'mailto' ? 'clicked' : (emailResult.success ? 'sent' : 'failed')
});
if (emailMethod === 'smtp') {
@@ -458,6 +465,62 @@ class CampaignsController {
}
}
// Track user info when they find representatives
async trackUserInfo(req, res, next) {
try {
const { slug } = req.params;
const { userEmail, userName, postalCode } = req.body;
// Get campaign
const campaign = await nocoDB.getCampaignBySlug(slug);
if (!campaign) {
return res.status(404).json({
success: false,
error: 'Campaign not found'
});
}
const campaignStatus = campaign['Status'] || campaign.status;
if (campaignStatus !== 'active') {
return res.status(403).json({
success: false,
error: 'Campaign is not currently active'
});
}
// Log user interaction - finding representatives
await nocoDB.logCampaignEmail({
campaign_id: campaign.ID || campaign.Id || campaign.id,
campaign_slug: slug,
user_email: userEmail || '',
user_name: userName || '',
user_postal_code: postalCode,
recipient_email: '',
recipient_name: '',
recipient_title: '',
recipient_level: 'Other',
email_method: 'smtp', // Use valid option but distinguish by status
subject: 'User Info Capture',
message: 'User searched for representatives',
status: 'user_info_captured'
});
res.json({
success: true,
message: 'User info tracked successfully'
});
} catch (error) {
console.error('Track user info error:', error);
res.status(500).json({
success: false,
error: 'Failed to track user info',
message: error.message,
details: error.response?.data || null
});
}
}
// Get representatives for postal code (for campaign use)
async getRepresentativesForCampaign(req, res, next) {
try {