// Basic test to verify script execution console.log('Script block loaded'); // Test function to verify DOM elements exist function testElements() { console.log('Testing DOM elements...'); const elements = [ 'company-name-value', 'company-industry', 'company-description', 'company-email', 'company-phone', 'company-website', 'company-address' ]; elements.forEach(id => { const element = document.getElementById(id); console.log(`Element ${id} exists:`, !!element); }); } let statusUpdateInterval; // Function to check instance status async function checkInstanceStatus() { console.log('checkInstanceStatus called'); try { const response = await fetch(`/instances/{{ instance.id }}/status`); if (!response.ok) throw new Error('Failed to check instance status'); const data = await response.json(); console.log('Status data:', data); // Update activity status const activityIcon = document.querySelector('.card:first-child .fa-circle-notch'); const activityBadge = document.querySelector('.card:first-child .badge'); const activityDetails = document.querySelector('.card:first-child .text-muted'); if (activityIcon) { activityIcon.className = `fas fa-circle-notch fa-spin ${data.status === 'active' ? 'text-success' : 'text-danger'} fa-2x`; } if (activityBadge) { activityBadge.className = `badge bg-${data.status === 'active' ? 'success' : 'danger'}`; activityBadge.textContent = data.status.charAt(0).toUpperCase() + data.status.slice(1); } if (activityDetails) { // Only update if we have status details if (data.status_details) { activityDetails.textContent = data.status_details; activityDetails.style.display = 'block'; } else { activityDetails.style.display = 'none'; } } } catch (error) { console.error('Error checking instance status:', error); } } // Function to check authentication status async function checkAuthStatus() { console.log('checkAuthStatus called'); try { const response = await fetch(`/instances/{{ instance.id }}/auth-status`); if (!response.ok) throw new Error('Failed to check authentication status'); const data = await response.json(); console.log('Auth data:', data); // Update authentication status const authIcon = document.querySelector('.card:nth-child(2) .fa-shield-alt'); const authBadge = document.querySelector('.card:nth-child(2) .badge'); const authDetails = document.querySelector('.card:nth-child(2) .text-muted'); if (authIcon) { authIcon.className = `fas fa-shield-alt ${data.authenticated ? 'text-success' : 'text-warning'} fa-2x`; } if (authBadge) { authBadge.className = `badge bg-${data.authenticated ? 'success' : 'warning'}`; authBadge.textContent = data.authenticated ? 'Authenticated' : 'Not Authenticated'; } if (authDetails) { authDetails.textContent = data.authenticated ? '' : 'This instance needs to be authenticated'; } } catch (error) { console.error('Error checking authentication status:', error); } } // Function to fetch company information async function fetchCompanyInfo() { console.log('fetchCompanyInfo called'); try { // First get JWT token console.log('Getting management token...'); const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); console.log('Token response status:', tokenResponse.status); if (!tokenResponse.ok) { console.error('Failed to get management token:', tokenResponse.status); throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); console.log('Token data received:', tokenData); if (!tokenData.token) { console.error('No token in response'); throw new Error('No token received'); } // Then fetch settings using the JWT token console.log('Fetching settings from:', `{{ instance.main_url }}/api/admin/settings`); const response = await fetch(`{{ instance.main_url }}/api/admin/settings`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); console.log('Settings response status:', response.status); if (!response.ok) { console.error('Settings fetch failed:', response.status); throw new Error('Failed to fetch company information'); } const data = await response.json(); console.log('Settings data received:', data); // Update company name separately with debugging const companyNameElement = document.getElementById('company-name-value'); const companyNameLabel = document.getElementById('company-name-label'); // Ensure label text is set and maintained if (companyNameLabel) { companyNameLabel.textContent = 'Company Name:'; } if (companyNameElement) { companyNameElement.textContent = data.company_name || 'Not set'; } // Update other company details const updateElement = (id, value) => { const element = document.getElementById(id); if (element && element.classList.contains('company-value')) { element.textContent = value || 'Not set'; } }; // Update other company details updateElement('company-industry', data.company_industry); updateElement('company-description', data.company_description); // Update contact information const emailElement = document.getElementById('company-email'); const phoneElement = document.getElementById('company-phone'); const websiteElement = document.getElementById('company-website'); // Update email with mailto link if (emailElement && emailElement.classList.contains('company-value')) { if (data.company_email && data.company_email !== 'Not set') { emailElement.innerHTML = ` ${data.company_email} `; } else { emailElement.textContent = 'Not set'; } } // Update phone with tel link if (phoneElement && phoneElement.classList.contains('company-value')) { if (data.company_phone && data.company_phone !== 'Not set') { phoneElement.innerHTML = ` ${data.company_phone} `; } else { phoneElement.textContent = 'Not set'; } } // Update website with external link if (websiteElement && websiteElement.classList.contains('company-value')) { if (data.company_website && data.company_website !== 'Not set') { // Ensure website has http/https prefix let websiteUrl = data.company_website; if (!websiteUrl.startsWith('http://') && !websiteUrl.startsWith('https://')) { websiteUrl = 'https://' + websiteUrl; } websiteElement.innerHTML = ` ${data.company_website} `; } else { websiteElement.textContent = 'Not set'; } } // Format address const addressParts = [ data.company_address, data.company_city, data.company_state, data.company_zip, data.company_country ].filter(Boolean); updateElement('company-address', addressParts.length ? addressParts.join(', ') : 'Not set'); console.log('Company info update complete'); } catch (error) { console.error('Error in fetchCompanyInfo:', error); // Show error state in all fields const fields = ['company-name-value', 'company-industry', 'company-description', 'company-email', 'company-phone', 'company-website', 'company-address']; fields.forEach(field => { const element = document.getElementById(field); if (element && element.classList.contains('company-value')) { element.textContent = 'Error loading data'; } }); } } // Function to update all statuses async function updateAllStatuses() { console.log('Starting updateAllStatuses...'); try { await Promise.all([ checkInstanceStatus(), checkAuthStatus(), fetchCompanyInfo() ]); console.log('All statuses updated successfully'); } catch (error) { console.error('Error in updateAllStatuses:', error); } } // Initialize status updates document.addEventListener('DOMContentLoaded', function() { console.log('DOM loaded, initializing updates...'); testElements(); // Test if elements exist // Initial update updateAllStatuses(); // Set up periodic updates (every 10 minutes) statusUpdateInterval = setInterval(updateAllStatuses, 600000); console.log('Periodic updates initialized'); }); // Clean up interval when page is unloaded window.addEventListener('beforeunload', function() { if (statusUpdateInterval) { clearInterval(statusUpdateInterval); } }); // Contacts Management Functions async function fetchContacts() { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/contacts`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to fetch contacts'); } const contacts = await response.json(); const contactsList = document.getElementById('contactsTableBody'); contactsList.innerHTML = ''; contacts.forEach(contact => { const row = document.createElement('tr'); // Role badge color mapping const roleBadgeClass = { 'admin': 'bg-danger', 'manager': 'bg-warning', 'user': 'bg-info' }[contact.role] || 'bg-secondary'; // Status badge color mapping const statusBadgeClass = contact.is_active ? 'bg-success' : 'bg-secondary'; // Format phone number for tel: link (remove any non-digit characters) const phoneNumber = contact.phone ? contact.phone.replace(/\D/g, '') : ''; row.innerHTML = ` ${contact.username} ${contact.last_name} ${contact.email} ${contact.phone ? ` ${contact.phone} ` : '-'} ${contact.company || '-'} ${contact.position || '-'} ${contact.role.charAt(0).toUpperCase() + contact.role.slice(1)} ${contact.is_active ? 'Active' : 'Inactive'}
`; contactsList.appendChild(row); }); } catch (error) { console.error('Error fetching contacts:', error); showToast('Error loading contacts', 'error'); } } async function addContact(event) { event.preventDefault(); try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const formData = new FormData(event.target); const response = await fetch(`{{ instance.main_url }}/api/admin/contacts`, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': `Bearer ${tokenData.token}` }, body: JSON.stringify({ username: formData.get('name'), email: formData.get('email'), phone: formData.get('phone'), company: formData.get('company'), position: formData.get('position'), role: formData.get('role'), is_active: formData.get('status') === 'active' }) }); if (!response.ok) { throw new Error('Failed to add contact'); } // Close modal and refresh list const modal = bootstrap.Modal.getInstance(document.getElementById('addContactModal')); modal.hide(); fetchContacts(); // Show success message showToast('Contact added successfully', 'success'); } catch (error) { console.error('Error adding contact:', error); showToast('Error adding contact', 'error'); } } async function editContact(id) { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/contacts/${id}`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to fetch contact details'); } const contact = await response.json(); // Populate form document.getElementById('edit-contact-id').value = contact.id; document.getElementById('edit-name').value = contact.username; document.getElementById('edit-email').value = contact.email || ''; document.getElementById('edit-phone').value = contact.phone || ''; document.getElementById('edit-company').value = contact.company || ''; document.getElementById('edit-position').value = contact.position || ''; document.getElementById('edit-role').value = contact.role; document.getElementById('edit-status').value = contact.is_active ? 'active' : 'inactive'; // Show modal const modal = new bootstrap.Modal(document.getElementById('editContactModal')); modal.show(); } catch (error) { console.error('Error fetching contact details:', error); showToast('Error loading contact details', 'error'); } } async function updateContact(event) { event.preventDefault(); try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const formData = new FormData(event.target); const id = formData.get('id'); const response = await fetch(`{{ instance.main_url }}/api/admin/contacts/${id}`, { method: 'PUT', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': `Bearer ${tokenData.token}` }, body: JSON.stringify({ username: formData.get('name'), email: formData.get('email'), phone: formData.get('phone'), company: formData.get('company'), position: formData.get('position'), role: formData.get('role'), is_active: formData.get('status') === 'active' }) }); if (!response.ok) { throw new Error('Failed to update contact'); } // Close modal and refresh list const modal = bootstrap.Modal.getInstance(document.getElementById('editContactModal')); modal.hide(); fetchContacts(); // Show success message showToast('Contact updated successfully', 'success'); } catch (error) { console.error('Error updating contact:', error); showToast('Error updating contact', 'error'); } } async function deleteContact(id) { // Store the contact ID for the delete confirmation const deleteModal = new bootstrap.Modal(document.getElementById('deleteContactModal')); document.getElementById('confirmDelete').onclick = async () => { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/contacts/${id}`, { method: 'DELETE', headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to delete contact'); } // Close modal and refresh list deleteModal.hide(); fetchContacts(); // Show success message showToast('Contact deleted successfully', 'success'); } catch (error) { console.error('Error deleting contact:', error); showToast('Error deleting contact', 'error'); } }; // Show the delete confirmation modal deleteModal.show(); } // Helper function to show toast messages function showToast(title, message, type = 'info') { const toast = document.createElement('div'); toast.className = `toast align-items-center text-white bg-${type} border-0`; toast.setAttribute('role', 'alert'); toast.setAttribute('aria-live', 'assertive'); toast.setAttribute('aria-atomic', 'true'); toast.innerHTML = `
${title}
${message}
`; const toastContainer = document.getElementById('toastContainer') || (() => { const container = document.createElement('div'); container.id = 'toastContainer'; container.className = 'toast-container position-fixed bottom-0 end-0 p-3'; document.body.appendChild(container); return container; })(); toastContainer.appendChild(toast); const bsToast = new bootstrap.Toast(toast); bsToast.show(); toast.addEventListener('hidden.bs.toast', () => { toast.remove(); }); } // Event Listeners document.addEventListener('DOMContentLoaded', function() { // ... existing event listeners ... // Fetch contacts when contacts tab is shown document.getElementById('contacts-tab').addEventListener('shown.bs.tab', fetchContacts); // Fetch logs when logs tab is shown document.getElementById('logs-tab').addEventListener('shown.bs.tab', fetchLogs); // Fetch mails when mails tab is shown document.getElementById('mails-tab').addEventListener('shown.bs.tab', fetchMails); // Debug the company name label const label = document.getElementById('company-name-label'); if (label) { console.log('Company name label found:', label); // Create a MutationObserver to watch for changes const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log('Label changed:', mutation); console.log('Old value:', mutation.oldValue); console.log('New value:', label.textContent); }); }); // Start observing observer.observe(label, { attributes: true, childList: true, characterData: true, subtree: true }); } else { console.log('Company name label not found'); } }); // Function to fetch logs async function fetchLogs() { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/logs`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to fetch logs'); } const data = await response.json(); const logsTableBody = document.getElementById('logsTableBody'); logsTableBody.innerHTML = ''; // Fetch all users to map IDs to names const usersResponse = await fetch(`{{ instance.main_url }}/api/admin/contacts`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!usersResponse.ok) { throw new Error('Failed to fetch users'); } const usersData = await usersResponse.json(); const userMap = new Map(usersData.map(user => [user.id, `${user.username} ${user.last_name}`])); data.events.forEach(event => { const row = document.createElement('tr'); row.innerHTML = ` ${new Date(event.timestamp).toLocaleString()} ${event.event_type || '-'} ${event.user_id ? userMap.get(event.user_id) || `User ${event.user_id}` : '-'} ${event.ip_address || '-'} `; logsTableBody.appendChild(row); }); // Update pagination updateLogsPagination(data.current_page, data.pages); } catch (error) { console.error('Error fetching logs:', error); showToast('Error loading logs', 'error'); } } // Function to fetch mails async function fetchMails() { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/mail-logs`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to fetch mail logs'); } const data = await response.json(); const mailsTableBody = document.querySelector('#mails .table tbody'); mailsTableBody.innerHTML = ''; data.mails.forEach(mail => { const row = document.createElement('tr'); row.innerHTML = ` ${new Date(mail.created_at).toLocaleString()} ${mail.recipient} ${mail.subject} ${mail.sent_at ? new Date(mail.sent_at).toLocaleString() : '-'} `; mailsTableBody.appendChild(row); }); // Update pagination updateMailsPagination(data.current_page, data.pages); } catch (error) { console.error('Error fetching mail logs:', error); showToast('Error loading mail logs', 'error'); } } // Helper function to get mail status badge class function getMailStatusBadgeClass(status) { const classes = { 'pending': 'warning', 'sent': 'success', 'failed': 'danger' }; return classes[status] || 'secondary'; } // Function to update logs pagination function updateLogsPagination(currentPage, totalPages) { const pagination = document.getElementById('logsPagination'); if (!pagination) return; pagination.innerHTML = ''; // Previous button const prevLi = document.createElement('li'); prevLi.className = `page-item ${currentPage === 1 ? 'disabled' : ''}`; prevLi.innerHTML = ` `; pagination.appendChild(prevLi); // Page numbers for (let i = 1; i <= totalPages; i++) { const li = document.createElement('li'); li.className = `page-item ${i === currentPage ? 'active' : ''}`; li.innerHTML = ` `; pagination.appendChild(li); } // Next button const nextLi = document.createElement('li'); nextLi.className = `page-item ${currentPage === totalPages ? 'disabled' : ''}`; nextLi.innerHTML = ` `; pagination.appendChild(nextLi); } // Function to update mails pagination function updateMailsPagination(currentPage, totalPages) { const pagination = document.querySelector('#mails .pagination'); if (!pagination) return; pagination.innerHTML = ''; // Previous button const prevLi = document.createElement('li'); prevLi.className = `page-item ${currentPage === 1 ? 'disabled' : ''}`; prevLi.innerHTML = ` `; pagination.appendChild(prevLi); // Page numbers for (let i = 1; i <= totalPages; i++) { const li = document.createElement('li'); li.className = `page-item ${i === currentPage ? 'active' : ''}`; li.innerHTML = ` `; pagination.appendChild(li); } // Next button const nextLi = document.createElement('li'); nextLi.className = `page-item ${currentPage === totalPages ? 'disabled' : ''}`; nextLi.innerHTML = ` `; pagination.appendChild(nextLi); } // Function to change logs page async function changeLogsPage(page) { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/logs?page=${page}`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to fetch logs'); } const data = await response.json(); // Fetch all users to map IDs to names const usersResponse = await fetch(`{{ instance.main_url }}/api/admin/contacts`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!usersResponse.ok) { throw new Error('Failed to fetch users'); } const usersData = await usersResponse.json(); const userMap = new Map(usersData.map(user => [user.id, `${user.username} ${user.last_name}`])); const logsTableBody = document.getElementById('logsTableBody'); logsTableBody.innerHTML = ''; data.events.forEach(event => { const row = document.createElement('tr'); row.innerHTML = ` ${new Date(event.timestamp).toLocaleString()} ${event.event_type || '-'} ${event.user_id ? userMap.get(event.user_id) || `User ${event.user_id}` : '-'} ${event.ip_address || '-'} `; logsTableBody.appendChild(row); }); // Update pagination updateLogsPagination(data.current_page, data.pages); } catch (error) { console.error('Error changing logs page:', error); showToast('Error loading logs', 'error'); } } // Function to change mails page async function changeMailsPage(page) { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/mail-logs?page=${page}`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to fetch mail logs'); } const data = await response.json(); const mailsTableBody = document.querySelector('#mails .table tbody'); mailsTableBody.innerHTML = ''; data.mails.forEach(mail => { const row = document.createElement('tr'); row.innerHTML = ` ${new Date(mail.created_at).toLocaleString()} ${mail.recipient} ${mail.subject} ${mail.sent_at ? new Date(mail.sent_at).toLocaleString() : '-'} `; mailsTableBody.appendChild(row); }); // Update pagination updateMailsPagination(data.current_page, data.pages); } catch (error) { console.error('Error changing mail logs page:', error); showToast('Error loading mail logs', 'error'); } } // Function to view mail details async function viewMailDetails(mailId) { try { // First get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) { throw new Error('Failed to get management token'); } const tokenData = await tokenResponse.json(); if (!tokenData.token) { throw new Error('No token received'); } const response = await fetch(`{{ instance.main_url }}/api/admin/mail-logs/${mailId}`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) { throw new Error('Failed to fetch mail details'); } const mail = await response.json(); // Update modal content document.getElementById('modalRecipient').textContent = mail.recipient; document.getElementById('modalStatus').innerHTML = ` ${mail.status} `; document.getElementById('modalTemplate').textContent = mail.template_id ? mail.template_id : '-'; document.getElementById('modalCreatedAt').textContent = new Date(mail.created_at).toLocaleString(); document.getElementById('modalSentAt').textContent = mail.sent_at ? new Date(mail.sent_at).toLocaleString() : '-'; document.getElementById('modalSubject').textContent = mail.subject; document.getElementById('modalBody').innerHTML = mail.body; // Show modal const modal = new bootstrap.Modal(document.getElementById('mailDetailsModal')); modal.show(); } catch (error) { console.error('Error viewing mail details:', error); showToast('Error loading mail details', 'error'); } } // Function to view log details function viewLogDetails(event) { const modal = new bootstrap.Modal(document.getElementById('logDetailsModal')); const content = document.getElementById('logDetailsContent'); // Format the details in a readable way let details = event.details; let formattedDetails = 'No details available'; if (details) { if (typeof details === 'string') { formattedDetails = details.replace(/\n/g, '
'); } else if (typeof details === 'object') { formattedDetails = JSON.stringify(details, null, 2).replace(/\n/g, '
'); } else { formattedDetails = String(details); } } content.innerHTML = `
Timestamp: ${new Date(event.timestamp).toLocaleString()}
Event Type: ${event.event_type || '-'}
User: ${event.user_id ? userMap.get(event.user_id) || `User ${event.user_id}` : '-'}
IP Address: ${event.ip_address || '-'}
Details:
${formattedDetails}
`; modal.show(); } // Add event listener for clear filters button document.addEventListener('DOMContentLoaded', function() { // ... existing event listeners ... const clearLogFiltersBtn = document.getElementById('clearLogFiltersBtn'); if (clearLogFiltersBtn) { clearLogFiltersBtn.addEventListener('click', function() { document.getElementById('logCategory').value = ''; document.getElementById('dateRangeFilter').value = '7d'; fetchLogs(); }); } }); // Function to fetch version and payment plan info async function fetchInstanceVersionAndPlan() { const versionEl = document.getElementById('instance-version-value'); const planEl = document.getElementById('instance-payment-plan-value'); versionEl.textContent = 'Loading...'; planEl.textContent = 'Loading...'; try { // Get JWT token const tokenResponse = await fetch(`{{ instance.main_url }}/api/admin/management-token`, { method: 'POST', headers: { 'X-API-Key': '{{ instance.connection_token }}', 'Accept': 'application/json' } }); if (!tokenResponse.ok) throw new Error('Failed to get management token'); const tokenData = await tokenResponse.json(); if (!tokenData.token) throw new Error('No token received'); // Fetch version info const response = await fetch(`{{ instance.main_url }}/api/admin/version-info`, { headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${tokenData.token}` } }); if (!response.ok) throw new Error('Failed to fetch version info'); const data = await response.json(); versionEl.textContent = data.app_version || 'Unknown'; planEl.textContent = data.pricing_tier_name || 'Unknown'; } catch (error) { versionEl.textContent = 'Error'; planEl.textContent = 'Error'; console.error('Error fetching version/plan info:', error); } } document.addEventListener('DOMContentLoaded', function() { // ... existing code ... fetchInstanceVersionAndPlan(); });