404 lines
14 KiB
JavaScript
404 lines
14 KiB
JavaScript
/**
|
|
* Admin Email Broadcasting Module
|
|
* Handles email composition, broadcasting to all users, and progress tracking
|
|
*/
|
|
|
|
// Email state - use users module data instead of declaring our own
|
|
// let allUsersData = []; // Removed - use window.adminUsers.getAllUsersData() instead
|
|
|
|
// Email All Users Functions
|
|
async function showEmailUsersModal() {
|
|
// Load current users data
|
|
try {
|
|
const response = await fetch('/api/users');
|
|
const data = await response.json();
|
|
|
|
if (data.success && data.users) {
|
|
// Use the users module to store user data
|
|
if (window.adminUsers && window.adminUsers.setAllUsersData) {
|
|
window.adminUsers.setAllUsersData(data.users);
|
|
}
|
|
|
|
// Update recipients count
|
|
const recipientsCount = document.getElementById('recipients-count');
|
|
if (recipientsCount) {
|
|
recipientsCount.textContent = `${data.users.length}`;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading users for email:', error);
|
|
window.adminCore.showStatus('Failed to load user data', 'error');
|
|
return;
|
|
}
|
|
|
|
// Show modal
|
|
const modal = document.getElementById('email-users-modal');
|
|
if (modal) {
|
|
modal.style.display = 'flex';
|
|
|
|
// Clear previous content
|
|
const subjectInput = document.getElementById('email-subject');
|
|
const contentEditor = document.getElementById('email-content');
|
|
const previewCheckbox = document.getElementById('show-preview');
|
|
const previewDiv = document.getElementById('email-preview');
|
|
|
|
if (subjectInput) subjectInput.value = '';
|
|
if (contentEditor) contentEditor.innerHTML = '';
|
|
if (previewCheckbox) previewCheckbox.checked = false;
|
|
if (previewDiv) previewDiv.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function closeEmailUsersModal() {
|
|
const modal = document.getElementById('email-users-modal');
|
|
if (modal) {
|
|
modal.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function setupRichTextEditor() {
|
|
const toolbar = document.querySelector('.rich-text-toolbar');
|
|
const editor = document.getElementById('email-content');
|
|
|
|
if (!toolbar || !editor) return;
|
|
|
|
// Handle toolbar button clicks
|
|
toolbar.addEventListener('click', (e) => {
|
|
if (e.target.classList.contains('toolbar-btn')) {
|
|
e.preventDefault();
|
|
const command = e.target.getAttribute('data-command');
|
|
|
|
if (command === 'createLink') {
|
|
const url = prompt('Enter the URL:');
|
|
if (url) {
|
|
document.execCommand(command, false, url);
|
|
}
|
|
} else {
|
|
document.execCommand(command, false, null);
|
|
}
|
|
|
|
// Update preview if visible
|
|
updateEmailPreview();
|
|
}
|
|
});
|
|
|
|
// Update preview on content change
|
|
editor.addEventListener('input', updateEmailPreview);
|
|
|
|
// Handle preview toggle
|
|
const showPreviewCheckbox = document.getElementById('show-preview');
|
|
if (showPreviewCheckbox) {
|
|
showPreviewCheckbox.addEventListener('change', togglePreview);
|
|
}
|
|
|
|
// Update preview when subject changes
|
|
const subjectInput = document.getElementById('email-subject');
|
|
if (subjectInput) {
|
|
subjectInput.addEventListener('input', updateEmailPreview);
|
|
}
|
|
}
|
|
|
|
function togglePreview() {
|
|
const preview = document.getElementById('email-preview');
|
|
const checkbox = document.getElementById('show-preview');
|
|
|
|
if (preview && checkbox) {
|
|
if (checkbox.checked) {
|
|
preview.style.display = 'block';
|
|
updateEmailPreview();
|
|
} else {
|
|
preview.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateEmailPreview() {
|
|
const previewSubject = document.getElementById('preview-subject');
|
|
const previewBody = document.getElementById('preview-body');
|
|
const subjectInput = document.getElementById('email-subject');
|
|
const contentEditor = document.getElementById('email-content');
|
|
|
|
if (previewSubject && subjectInput) {
|
|
previewSubject.textContent = subjectInput.value || 'Your subject will appear here';
|
|
}
|
|
|
|
if (previewBody && contentEditor) {
|
|
const content = contentEditor.innerHTML || 'Your message will appear here';
|
|
previewBody.innerHTML = content;
|
|
}
|
|
}
|
|
|
|
async function sendEmailToAllUsers(e) {
|
|
e.preventDefault();
|
|
|
|
const subjectInput = document.getElementById('email-subject');
|
|
const contentEditor = document.getElementById('email-content');
|
|
|
|
const subject = subjectInput?.value.trim();
|
|
const content = contentEditor?.innerHTML.trim();
|
|
|
|
if (!subject) {
|
|
window.adminCore.showStatus('Please enter an email subject', 'error');
|
|
return;
|
|
}
|
|
|
|
if (!content || content === '<br>' || content === '') {
|
|
window.adminCore.showStatus('Please enter email content', 'error');
|
|
return;
|
|
}
|
|
|
|
const allUsers = (window.adminUsers && window.adminUsers.getAllUsersData) ? window.adminUsers.getAllUsersData() : [];
|
|
if (allUsers.length === 0) {
|
|
window.adminCore.showStatus('No users found to email', 'error');
|
|
return;
|
|
}
|
|
|
|
const confirmMessage = `Send this email to all ${allUsers.length} users?`;
|
|
if (!confirm(confirmMessage)) {
|
|
return;
|
|
}
|
|
|
|
// Initialize progress tracking
|
|
initializeEmailProgress(allUsers.length);
|
|
|
|
try {
|
|
const response = await fetch('/api/users/email-all', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
subject: subject,
|
|
content: content
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
// Display detailed results
|
|
updateEmailProgress(data.results);
|
|
window.adminCore.showStatus(data.message, 'success');
|
|
console.log('Email results:', data.results);
|
|
} else {
|
|
showEmailError(data.error || 'Failed to send emails');
|
|
if (data.details) {
|
|
console.error('Failed email details:', data.details);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Error sending emails to all users:', error);
|
|
showEmailError('Failed to send emails - Network error');
|
|
}
|
|
}
|
|
|
|
// Initialize email progress display
|
|
function initializeEmailProgress(totalCount) {
|
|
const progressContainer = document.getElementById('email-progress-container');
|
|
const statusList = document.getElementById('email-status-list');
|
|
const pendingCountEl = document.getElementById('pending-count');
|
|
const successCountEl = document.getElementById('success-count');
|
|
const errorCountEl = document.getElementById('error-count');
|
|
const progressBar = document.getElementById('email-progress-bar');
|
|
const progressText = document.getElementById('progress-text');
|
|
const closeBtn = document.getElementById('close-progress-btn');
|
|
|
|
if (!progressContainer) return;
|
|
|
|
// Show progress container
|
|
progressContainer.classList.add('show');
|
|
|
|
// Reset counters
|
|
if (pendingCountEl) pendingCountEl.textContent = totalCount;
|
|
if (successCountEl) successCountEl.textContent = '0';
|
|
if (errorCountEl) errorCountEl.textContent = '0';
|
|
|
|
// Reset progress bar
|
|
if (progressBar) {
|
|
progressBar.style.width = '0%';
|
|
progressBar.classList.remove('complete', 'error');
|
|
}
|
|
if (progressText) progressText.textContent = '0%';
|
|
|
|
// Clear status list
|
|
if (statusList) statusList.innerHTML = '';
|
|
|
|
// Hide close button initially
|
|
if (closeBtn) closeBtn.style.display = 'none';
|
|
|
|
// Add status items for each user
|
|
const allUsers = (window.adminUsers && window.adminUsers.getAllUsersData) ? window.adminUsers.getAllUsersData() : [];
|
|
allUsers.forEach(user => {
|
|
if (statusList) {
|
|
const statusItem = document.createElement('div');
|
|
statusItem.className = 'email-status-item';
|
|
statusItem.innerHTML = `
|
|
<div class="email-status-recipient">${user.Name || user.Email}</div>
|
|
<div class="email-status-result pending">
|
|
<div class="progress-spinner"></div>
|
|
<span>Sending...</span>
|
|
</div>
|
|
`;
|
|
statusList.appendChild(statusItem);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Update progress with results
|
|
function updateEmailProgress(results) {
|
|
const statusList = document.getElementById('email-status-list');
|
|
const pendingCountEl = document.getElementById('pending-count');
|
|
const successCountEl = document.getElementById('success-count');
|
|
const errorCountEl = document.getElementById('error-count');
|
|
const progressBar = document.getElementById('email-progress-bar');
|
|
const progressText = document.getElementById('progress-text');
|
|
const closeBtn = document.getElementById('close-progress-btn');
|
|
|
|
const successful = results.successful || [];
|
|
const failed = results.failed || [];
|
|
const total = results.total || (successful.length + failed.length);
|
|
|
|
// Update counters
|
|
if (successCountEl) successCountEl.textContent = successful.length;
|
|
if (errorCountEl) errorCountEl.textContent = failed.length;
|
|
if (pendingCountEl) pendingCountEl.textContent = '0';
|
|
|
|
// Update progress bar
|
|
const percentage = ((successful.length + failed.length) / total * 100).toFixed(1);
|
|
if (progressBar && progressText) {
|
|
progressBar.style.width = percentage + '%';
|
|
progressText.textContent = percentage + '%';
|
|
|
|
if (failed.length > 0) {
|
|
progressBar.classList.add('error');
|
|
} else {
|
|
progressBar.classList.add('complete');
|
|
}
|
|
}
|
|
|
|
// Update individual status items
|
|
if (statusList) {
|
|
const statusItems = statusList.children;
|
|
|
|
// Update successful emails
|
|
successful.forEach(result => {
|
|
const statusItem = Array.from(statusItems).find(item =>
|
|
item.querySelector('.email-status-recipient').textContent.includes(result.email) ||
|
|
item.querySelector('.email-status-recipient').textContent.includes(result.name)
|
|
);
|
|
if (statusItem) {
|
|
statusItem.querySelector('.email-status-result').innerHTML = `
|
|
<span class="email-status-result success">✓ Sent</span>
|
|
`;
|
|
}
|
|
});
|
|
|
|
// Update failed emails
|
|
failed.forEach(result => {
|
|
const statusItem = Array.from(statusItems).find(item =>
|
|
item.querySelector('.email-status-recipient').textContent.includes(result.email) ||
|
|
item.querySelector('.email-status-recipient').textContent.includes(result.name)
|
|
);
|
|
if (statusItem) {
|
|
statusItem.querySelector('.email-status-result').innerHTML = `
|
|
<span class="email-status-result error" title="${result.error || 'Unknown error'}">✗ Failed</span>
|
|
`;
|
|
}
|
|
});
|
|
}
|
|
|
|
// Show close button
|
|
if (closeBtn) {
|
|
closeBtn.style.display = 'block';
|
|
closeBtn.onclick = () => {
|
|
const progressContainer = document.getElementById('email-progress-container');
|
|
if (progressContainer) {
|
|
progressContainer.classList.remove('show');
|
|
}
|
|
closeEmailUsersModal();
|
|
};
|
|
}
|
|
}
|
|
|
|
// Show email error
|
|
function showEmailError(message) {
|
|
const progressContainer = document.getElementById('email-progress-container');
|
|
const progressBar = document.getElementById('email-progress-bar');
|
|
const progressText = document.getElementById('progress-text');
|
|
const closeBtn = document.getElementById('close-progress-btn');
|
|
|
|
// Show progress container if not visible
|
|
if (progressContainer) {
|
|
progressContainer.classList.add('show');
|
|
}
|
|
|
|
// Update progress bar to show error
|
|
if (progressBar && progressText) {
|
|
progressBar.style.width = '100%';
|
|
progressBar.classList.add('error');
|
|
progressText.textContent = 'Error';
|
|
}
|
|
|
|
// Show close button
|
|
if (closeBtn) {
|
|
closeBtn.style.display = 'block';
|
|
closeBtn.onclick = () => {
|
|
if (progressContainer) {
|
|
progressContainer.classList.remove('show');
|
|
}
|
|
};
|
|
}
|
|
|
|
window.adminCore.showStatus(message, 'error');
|
|
}
|
|
|
|
// Setup email modal event listeners
|
|
function setupEmailModalEventListeners() {
|
|
// Email all users functionality
|
|
const closeEmailModalBtn = document.getElementById('close-email-modal');
|
|
const cancelEmailBtn = document.getElementById('cancel-email-btn');
|
|
const emailUsersForm = document.getElementById('email-users-form');
|
|
const emailModal = document.getElementById('email-users-modal');
|
|
|
|
if (closeEmailModalBtn) {
|
|
closeEmailModalBtn.addEventListener('click', closeEmailUsersModal);
|
|
}
|
|
|
|
if (cancelEmailBtn) {
|
|
cancelEmailBtn.addEventListener('click', closeEmailUsersModal);
|
|
}
|
|
|
|
if (emailUsersForm) {
|
|
emailUsersForm.addEventListener('submit', sendEmailToAllUsers);
|
|
}
|
|
|
|
// Close modal when clicking outside
|
|
if (emailModal) {
|
|
emailModal.addEventListener('click', function(e) {
|
|
if (e.target === emailModal) {
|
|
closeEmailUsersModal();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Setup rich text editor functionality
|
|
setupRichTextEditor();
|
|
}
|
|
|
|
// Export email broadcasting functions
|
|
window.adminEmail = {
|
|
showEmailUsersModal,
|
|
closeEmailUsersModal,
|
|
setupRichTextEditor,
|
|
togglePreview,
|
|
updateEmailPreview,
|
|
sendEmailToAllUsers,
|
|
setupEmailModalEventListeners,
|
|
getAllUsersData: () => (window.adminUsers && window.adminUsers.getAllUsersData) ? window.adminUsers.getAllUsersData() : [],
|
|
setAllUsersData: (data) => {
|
|
if (window.adminUsers && window.adminUsers.setAllUsersData) {
|
|
window.adminUsers.setAllUsersData(data);
|
|
}
|
|
}
|
|
};
|