Getting instance data
This commit is contained in:
@@ -56,11 +56,20 @@
|
||||
<td>{{ instance.conversations_count }}</td>
|
||||
<td>{{ "%.1f"|format(instance.data_size) }} GB</td>
|
||||
<td>{{ instance.payment_plan }}</td>
|
||||
<td>{{ instance.main_url }}</td>
|
||||
<td>
|
||||
<a href="{{ instance.main_url }}"
|
||||
target="_blank"
|
||||
class="text-decoration-none"
|
||||
style="color: var(--primary-color);">
|
||||
{{ instance.main_url }}
|
||||
<i class="fas fa-external-link-alt ms-1"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-{{ 'success' if instance.status == 'active' else 'danger' }}"
|
||||
data-bs-toggle="tooltip"
|
||||
data-instance-id="{{ instance.id }}"
|
||||
data-token="{{ instance.connection_token }}"
|
||||
title="{{ instance.status_details }}">
|
||||
{{ instance.status|title }}
|
||||
</span>
|
||||
@@ -240,8 +249,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
|
||||
// Check statuses on page load
|
||||
checkAllInstanceStatuses();
|
||||
// Add refresh button to header
|
||||
const headerButtons = document.querySelector('.header-buttons');
|
||||
if (headerButtons) {
|
||||
const refreshButton = document.createElement('button');
|
||||
refreshButton.className = 'btn btn-outline-primary';
|
||||
refreshButton.innerHTML = '<i class="fas fa-sync-alt"></i> Refresh';
|
||||
refreshButton.onclick = function() {
|
||||
fetchCompanyNames();
|
||||
};
|
||||
headerButtons.appendChild(refreshButton);
|
||||
}
|
||||
|
||||
// Wait a short moment to ensure the table is rendered
|
||||
setTimeout(() => {
|
||||
// Check statuses on page load
|
||||
checkAllInstanceStatuses();
|
||||
|
||||
// Fetch company names for all instances
|
||||
fetchCompanyNames();
|
||||
}, 100);
|
||||
|
||||
// Set up periodic status checks (every 30 seconds)
|
||||
setInterval(checkAllInstanceStatuses, 30000);
|
||||
@@ -295,6 +322,239 @@ async function checkInstanceStatus(instanceId) {
|
||||
}
|
||||
}
|
||||
|
||||
// Function to get JWT token using API key
|
||||
async function getJWTToken(instanceUrl, apiKey) {
|
||||
try {
|
||||
const response = await fetch(`${instanceUrl}/api/admin/management-token`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'X-API-Key': apiKey
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`HTTP error ${response.status}:`, errorText);
|
||||
throw new Error(`Server returned ${response.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data.token;
|
||||
} catch (error) {
|
||||
console.error('Error getting JWT token:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to fetch instance statistics
|
||||
async function fetchInstanceStats(instanceUrl, instanceId, jwtToken) {
|
||||
try {
|
||||
const response = await fetch(`${instanceUrl}/api/admin/statistics`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Authorization': `Bearer ${jwtToken}`
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`HTTP error ${response.status}:`, errorText);
|
||||
throw new Error(`Server returned ${response.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log('Received stats data:', data);
|
||||
|
||||
const row = document.querySelector(`[data-instance-id="${instanceId}"]`).closest('tr');
|
||||
|
||||
// Update rooms count
|
||||
const roomsCell = row.querySelector('td:nth-child(3)');
|
||||
if (roomsCell) {
|
||||
roomsCell.textContent = data.rooms || '0';
|
||||
}
|
||||
|
||||
// Update conversations count
|
||||
const conversationsCell = row.querySelector('td:nth-child(4)');
|
||||
if (conversationsCell) {
|
||||
conversationsCell.textContent = data.conversations || '0';
|
||||
}
|
||||
|
||||
// Update data usage
|
||||
const dataCell = row.querySelector('td:nth-child(5)');
|
||||
if (dataCell) {
|
||||
const dataSize = data.total_storage || 0;
|
||||
const dataSizeGB = (dataSize / (1024 * 1024 * 1024)).toFixed(1);
|
||||
dataCell.textContent = `${dataSizeGB} GB`;
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching instance stats:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to fetch company name from instance settings
|
||||
async function fetchCompanyName(instanceUrl, instanceId) {
|
||||
const row = document.querySelector(`[data-instance-id="${instanceId}"]`).closest('tr');
|
||||
const companyCell = row.querySelector('td:nth-child(2)');
|
||||
|
||||
// Show loading state
|
||||
if (companyCell) {
|
||||
companyCell.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Loading...';
|
||||
}
|
||||
|
||||
try {
|
||||
const apiKey = document.querySelector(`[data-instance-id="${instanceId}"]`).dataset.token;
|
||||
if (!apiKey) {
|
||||
throw new Error('No API key available');
|
||||
}
|
||||
|
||||
console.log(`Getting JWT token for instance ${instanceId}`);
|
||||
const jwtToken = await getJWTToken(instanceUrl, apiKey);
|
||||
console.log('Got JWT token');
|
||||
|
||||
// Fetch company name
|
||||
console.log(`Fetching company name for instance ${instanceId} from ${instanceUrl}/api/admin/settings`);
|
||||
const response = await fetch(`${instanceUrl}/api/admin/settings`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Authorization': `Bearer ${jwtToken}`
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`HTTP error ${response.status}:`, errorText);
|
||||
throw new Error(`Server returned ${response.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log('Received data:', data);
|
||||
|
||||
if (companyCell) {
|
||||
companyCell.textContent = data.company_name || 'N/A';
|
||||
}
|
||||
|
||||
// Fetch statistics using the same JWT token
|
||||
await fetchInstanceStats(instanceUrl, instanceId, jwtToken);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching company name:', error);
|
||||
if (companyCell) {
|
||||
const errorMessage = error.message || 'Unknown error';
|
||||
companyCell.innerHTML = `
|
||||
<span class="text-danger"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="${errorMessage}">
|
||||
<i class="fas fa-exclamation-circle"></i> Error
|
||||
</span>`;
|
||||
|
||||
// Initialize tooltip
|
||||
new bootstrap.Tooltip(companyCell.querySelector('[data-bs-toggle="tooltip"]'));
|
||||
|
||||
// Also show error in stats cells
|
||||
const row = document.querySelector(`[data-instance-id="${instanceId}"]`).closest('tr');
|
||||
const statsCells = [
|
||||
row.querySelector('td:nth-child(3)'), // Rooms
|
||||
row.querySelector('td:nth-child(4)'), // Conversations
|
||||
row.querySelector('td:nth-child(5)') // Data
|
||||
];
|
||||
|
||||
statsCells.forEach(cell => {
|
||||
if (cell) {
|
||||
cell.innerHTML = `
|
||||
<span class="text-danger"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="${errorMessage}">
|
||||
<i class="fas fa-exclamation-circle"></i> Error
|
||||
</span>`;
|
||||
new bootstrap.Tooltip(cell.querySelector('[data-bs-toggle="tooltip"]'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to fetch company names for all instances
|
||||
async function fetchCompanyNames() {
|
||||
const instances = document.querySelectorAll('[data-instance-id]');
|
||||
const loadingPromises = [];
|
||||
|
||||
console.log('Starting to fetch company names and stats for all instances');
|
||||
|
||||
for (const instance of instances) {
|
||||
const instanceId = instance.dataset.instanceId;
|
||||
const row = instance.closest('tr');
|
||||
|
||||
// Debug: Log all cells in the row
|
||||
console.log(`Row for instance ${instanceId}:`, {
|
||||
cells: Array.from(row.querySelectorAll('td')).map(td => ({
|
||||
text: td.textContent.trim(),
|
||||
html: td.innerHTML.trim()
|
||||
}))
|
||||
});
|
||||
|
||||
// Changed from nth-child(8) to nth-child(7) since Main URL is the 7th column
|
||||
const urlCell = row.querySelector('td:nth-child(7)');
|
||||
|
||||
if (!urlCell) {
|
||||
console.error(`Could not find URL cell for instance ${instanceId}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const urlLink = urlCell.querySelector('a');
|
||||
if (!urlLink) {
|
||||
console.error(`Could not find URL link for instance ${instanceId}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const instanceUrl = urlLink.getAttribute('href');
|
||||
const token = instance.dataset.token;
|
||||
|
||||
console.log(`Instance ${instanceId}:`, {
|
||||
url: instanceUrl,
|
||||
hasToken: !!token
|
||||
});
|
||||
|
||||
if (instanceUrl && token) {
|
||||
loadingPromises.push(fetchCompanyName(instanceUrl, instanceId));
|
||||
} else {
|
||||
const cells = [
|
||||
row.querySelector('td:nth-child(2)'), // Company
|
||||
row.querySelector('td:nth-child(3)'), // Rooms
|
||||
row.querySelector('td:nth-child(4)'), // Conversations
|
||||
row.querySelector('td:nth-child(5)') // Data
|
||||
];
|
||||
|
||||
cells.forEach(cell => {
|
||||
if (cell) {
|
||||
cell.innerHTML = `
|
||||
<span class="text-warning"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="${!instanceUrl ? 'No URL available' : 'No authentication token available'}">
|
||||
<i class="fas fa-exclamation-triangle"></i> Not configured
|
||||
</span>`;
|
||||
new bootstrap.Tooltip(cell.querySelector('[data-bs-toggle="tooltip"]'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.all(loadingPromises);
|
||||
console.log('Finished fetching all company names and stats');
|
||||
} catch (error) {
|
||||
console.error('Error in fetchCompanyNames:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Show modals
|
||||
function showAddInstanceModal() {
|
||||
document.getElementById('addInstanceForm').reset();
|
||||
@@ -343,19 +603,33 @@ async function submitAddInstance() {
|
||||
|
||||
async function editInstance(id) {
|
||||
try {
|
||||
const response = await fetch(`/instances/${id}`);
|
||||
if (!response.ok) throw new Error('Failed to fetch instance');
|
||||
|
||||
const instance = await response.json();
|
||||
// Find the row by looking for the edit button with the matching onclick handler
|
||||
const editButton = document.querySelector(`button[onclick="editInstance(${id})"]`);
|
||||
if (!editButton) {
|
||||
throw new Error('Instance row not found');
|
||||
}
|
||||
const row = editButton.closest('tr');
|
||||
if (!row) {
|
||||
throw new Error('Instance row not found');
|
||||
}
|
||||
|
||||
// Get the name from the first cell
|
||||
const name = row.querySelector('td:first-child').textContent.trim();
|
||||
|
||||
// Get the main URL from the link in the URL cell (7th column)
|
||||
const urlCell = row.querySelector('td:nth-child(7)');
|
||||
const urlLink = urlCell.querySelector('a');
|
||||
const mainUrl = urlLink ? urlLink.getAttribute('href') : urlCell.textContent.trim();
|
||||
|
||||
// Populate form
|
||||
document.getElementById('edit_instance_id').value = instance.id;
|
||||
document.getElementById('edit_name').value = instance.name;
|
||||
document.getElementById('edit_main_url').value = instance.main_url;
|
||||
document.getElementById('edit_instance_id').value = id;
|
||||
document.getElementById('edit_name').value = name;
|
||||
document.getElementById('edit_main_url').value = mainUrl;
|
||||
|
||||
editInstanceModal.show();
|
||||
} catch (error) {
|
||||
alert('Error fetching instance: ' + error.message);
|
||||
console.error('Error preparing instance edit:', error);
|
||||
alert('Error: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,12 +653,16 @@ async function submitEditInstance() {
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to update instance');
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Failed to update instance: ${errorText}`);
|
||||
}
|
||||
|
||||
editInstanceModal.hide();
|
||||
location.reload(); // Refresh to show updated instance
|
||||
} catch (error) {
|
||||
alert('Error updating instance: ' + error.message);
|
||||
console.error('Error updating instance:', error);
|
||||
alert('Error: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user