Splitting css and JS files on settings pages
This commit is contained in:
@@ -68,266 +68,8 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script>
|
||||
|
||||
<script>
|
||||
// Template variables mapping
|
||||
const templateVariables = {
|
||||
'Account Created': {
|
||||
'user.username': 'The username of the created account',
|
||||
'user.email': 'The email address of the created account',
|
||||
'user.company': 'The company name of the user',
|
||||
'user.position': 'The position of the user in their company',
|
||||
'created_at': 'The date and time when the account was created',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL',
|
||||
'setup_link': 'The link to set up the user\'s password (expires in 24 hours)',
|
||||
'created_by': 'The name of the admin who created the account'
|
||||
},
|
||||
'Password Reset': {
|
||||
'user.username': 'The username of the account',
|
||||
'user.email': 'The email address of the account',
|
||||
'reset_link': 'The password reset link',
|
||||
'expiry_time': 'The time when the reset link expires',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
},
|
||||
'Account Deleted': {
|
||||
'user.username': 'The username of the deleted account',
|
||||
'user.email': 'The email address of the deleted account',
|
||||
'deleted_at': 'The date and time of deletion',
|
||||
'deleted_by': 'The username of the admin who deleted the account',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
},
|
||||
'Account Updated': {
|
||||
'user.username': 'The username of the updated account',
|
||||
'user.email': 'The email address of the account',
|
||||
'updated_fields': 'The fields that were updated',
|
||||
'updated_at': 'The date and time of the update',
|
||||
'updated_by': 'The username of who made the update',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
},
|
||||
'Room Invite': {
|
||||
'user.username': 'The username of the invited user',
|
||||
'user.email': 'The email address of the invited user',
|
||||
'room.name': 'The name of the room',
|
||||
'room.description': 'The description of the room',
|
||||
'inviter.username': 'The username of the user who sent the invite',
|
||||
'inviter.email': 'The email address of the inviter',
|
||||
'invite_link': 'The link to accept the room invite',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
},
|
||||
'Room Invite Removed': {
|
||||
'user.username': 'The username of the user',
|
||||
'user.email': 'The email address of the user',
|
||||
'room.name': 'The name of the room',
|
||||
'room.description': 'The description of the room',
|
||||
'remover.username': 'The username of the user who removed the invite',
|
||||
'remover.email': 'The email address of the remover',
|
||||
'removed_at': 'The date and time when the invite was removed',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
},
|
||||
'Conversation Invite': {
|
||||
'user.username': 'The username of the invited user',
|
||||
'user.email': 'The email address of the invited user',
|
||||
'conversation.name': 'The name of the conversation',
|
||||
'conversation.description': 'The description of the conversation',
|
||||
'inviter.username': 'The username of the user who sent the invite',
|
||||
'inviter.email': 'The email address of the inviter',
|
||||
'invite_link': 'The link to accept the conversation invite',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
},
|
||||
'Conversation Invite Removed': {
|
||||
'user.username': 'The username of the user',
|
||||
'user.email': 'The email address of the user',
|
||||
'conversation.name': 'The name of the conversation',
|
||||
'conversation.description': 'The description of the conversation',
|
||||
'remover.username': 'The username of the user who removed the invite',
|
||||
'remover.email': 'The email address of the remover',
|
||||
'removed_at': 'The date and time when the invite was removed',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
},
|
||||
'Conversation Message': {
|
||||
'user.username': 'The username of the recipient',
|
||||
'user.email': 'The email address of the recipient',
|
||||
'sender.username': 'The username of the message sender',
|
||||
'sender.email': 'The email address of the sender',
|
||||
'message.content': 'The content of the message',
|
||||
'message.created_at': 'The date and time when the message was sent',
|
||||
'conversation.name': 'The name of the conversation',
|
||||
'conversation.description': 'The description of the conversation',
|
||||
'message_link': 'The link to view the message',
|
||||
'site.company_name': 'The name of your company',
|
||||
'site.company_website': 'Your company website URL'
|
||||
}
|
||||
};
|
||||
|
||||
// Function to update available variables display
|
||||
function updateAvailableVariables(templateType) {
|
||||
const variables = templateVariables[templateType] || {};
|
||||
const variableList = document.getElementById('variableList');
|
||||
const availableVariables = document.getElementById('availableVariables');
|
||||
|
||||
if (Object.keys(variables).length === 0) {
|
||||
availableVariables.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '<div class="row">';
|
||||
for (const [variable, description] of Object.entries(variables)) {
|
||||
html += `
|
||||
<div class="col-md-6 mb-2">
|
||||
<div class="card h-100">
|
||||
<div class="card-body p-2">
|
||||
<code class="text-primary">{{ '{{ ' }}${variable}{{ ' }}' }}</code>
|
||||
<p class="text-muted small mb-0">${description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
variableList.innerHTML = html;
|
||||
availableVariables.style.display = 'block';
|
||||
}
|
||||
|
||||
// Wait for document and jQuery to be ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize Summernote
|
||||
$('#templateBody').summernote({
|
||||
height: 300,
|
||||
toolbar: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'underline', 'italic', 'clear']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['table', ['table']],
|
||||
['insert', ['link']],
|
||||
['view', ['fullscreen', 'codeview', 'help']]
|
||||
],
|
||||
styleTags: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
|
||||
placeholder: 'Enter your email template content here...',
|
||||
callbacks: {
|
||||
onImageUpload: function(files) {
|
||||
// Disable image upload for email templates
|
||||
return false;
|
||||
}
|
||||
},
|
||||
popover: {
|
||||
image: [],
|
||||
link: [],
|
||||
air: []
|
||||
}
|
||||
});
|
||||
|
||||
// Handle template selection
|
||||
$('#templateSelect').on('change', function() {
|
||||
const selectedOption = this.options[this.selectedIndex];
|
||||
const subject = selectedOption.dataset.subject || '';
|
||||
const body = selectedOption.dataset.body || '';
|
||||
const templateType = selectedOption.dataset.type || '';
|
||||
|
||||
// Show the template editor
|
||||
$('#templateEditor').show();
|
||||
|
||||
// Update the form fields
|
||||
$('#templateSubject').val(subject);
|
||||
$('#templateBody').summernote('code', body);
|
||||
updateAvailableVariables(templateType);
|
||||
});
|
||||
|
||||
// Check for initially selected template
|
||||
const templateSelect = document.getElementById('templateSelect');
|
||||
if (templateSelect.value) {
|
||||
const selectedOption = templateSelect.options[templateSelect.selectedIndex];
|
||||
const templateType = selectedOption.dataset.type || '';
|
||||
updateAvailableVariables(templateType);
|
||||
// Show the template editor if a template is initially selected
|
||||
$('#templateEditor').show();
|
||||
}
|
||||
|
||||
// Handle template save
|
||||
$('#templateForm').on('submit', function(event) {
|
||||
event.preventDefault();
|
||||
const templateId = $('#templateSelect').val();
|
||||
const subject = $('#templateSubject').val();
|
||||
const body = $('#templateBody').summernote('code');
|
||||
|
||||
if (!templateId) {
|
||||
alert('Please select a template first');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
const saveButton = this.querySelector('button[type="submit"]');
|
||||
const originalText = saveButton.innerHTML;
|
||||
saveButton.disabled = true;
|
||||
saveButton.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Saving...';
|
||||
|
||||
// Get CSRF token from meta tag
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
|
||||
|
||||
// Send AJAX request
|
||||
fetch(`/settings/email-templates/${templateId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': csrfToken,
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subject: subject,
|
||||
body: body
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
// Show success message
|
||||
const alert = document.createElement('div');
|
||||
alert.className = 'alert alert-success alert-dismissible fade show mt-3';
|
||||
alert.innerHTML = `
|
||||
<i class="fas fa-check-circle me-2"></i>Template saved successfully
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
`;
|
||||
document.querySelector('.card-body').appendChild(alert);
|
||||
|
||||
// Update the select option's data attributes
|
||||
const option = document.getElementById('templateSelect').options[document.getElementById('templateSelect').selectedIndex];
|
||||
option.dataset.subject = subject;
|
||||
option.dataset.body = body;
|
||||
})
|
||||
.catch(error => {
|
||||
// Show error message
|
||||
const alert = document.createElement('div');
|
||||
alert.className = 'alert alert-danger alert-dismissible fade show mt-3';
|
||||
alert.innerHTML = `
|
||||
<i class="fas fa-exclamation-circle me-2"></i>${error.message || 'Failed to save template'}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
`;
|
||||
document.querySelector('.card-body').appendChild(alert);
|
||||
})
|
||||
.finally(() => {
|
||||
// Restore button state
|
||||
saveButton.disabled = false;
|
||||
saveButton.innerHTML = originalText;
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Load JavaScript -->
|
||||
<script src="{{ url_for('static', filename='js/settings/email_templates.js') }}?v={{ 'js/settings/email_templates.js'|asset_version }}"></script>
|
||||
|
||||
<style>
|
||||
/* Summernote custom styles */
|
||||
|
||||
Reference in New Issue
Block a user