monitoring-dashboard / index.html
vrvrv's picture
Add 2 files
f63d432 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced Monitoring Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.risk-level-1 {
background-color: #10B981;
}
.risk-level-2 {
background-color: #F59E0B;
}
.risk-level-3 {
background-color: #EF4444;
}
.slide-down {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.slide-down.active {
max-height: 500px;
transition: max-height 0.5s ease-in;
}
.spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.square-details {
background-color: #f9fafb;
border-left: 4px solid #3b82f6;
}
</style>
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<div class="flex justify-between items-center mb-6">
<h1 class="text-3xl font-bold text-gray-800">Advanced Monitoring Dashboard</h1>
<div class="flex space-x-3">
<button id="expandAllBtn" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-expand mr-2"></i> Expand All
</button>
<button id="exportBtn" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-file-export mr-2"></i> Export
</button>
<button id="rerunBtn" class="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-sync-alt mr-2"></i> Rerun
</button>
<button id="addBtn" class="bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded-lg flex items-center">
<i class="fas fa-plus mr-2"></i> Add
</button>
</div>
</div>
<div class="bg-white rounded-xl shadow-md overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
<input type="checkbox" id="selectAll" class="rounded text-blue-500">
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
SQR MID
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Risk Level
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Recent Message
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Report
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Last Updated
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200" id="monitoringTableBody">
<!-- Rows will be populated by JavaScript -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Monitoring Modal -->
<div id="addModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
<div class="bg-white rounded-xl p-6 w-full max-w-md">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-gray-800">Add New Monitoring</h2>
<button id="closeAddModal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mb-4">
<label for="sqrMidInput" class="block text-sm font-medium text-gray-700 mb-1">SQR MID</label>
<input type="text" id="sqrMidInput" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500">
</div>
<div id="previewSection" class="hidden mb-4 p-4 bg-gray-50 rounded-lg">
<div class="flex items-center mb-3">
<div class="w-16 h-16 bg-gray-200 rounded-lg mr-3 overflow-hidden">
<img id="previewImage" src="" alt="Preview" class="w-full h-full object-cover">
</div>
<div>
<h3 id="previewName" class="font-medium text-gray-800"></h3>
<p id="previewDesc" class="text-sm text-gray-600"></p>
</div>
</div>
<div class="text-sm">
<p class="font-medium text-gray-700 mb-1">Recent Message:</p>
<p id="previewMessage" class="text-gray-600"></p>
</div>
</div>
<div class="flex justify-end space-x-3">
<button id="cancelAddBtn" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50">
Close
</button>
<button id="confirmAddBtn" class="px-4 py-2 bg-indigo-500 text-white rounded-md hover:bg-indigo-600">
Add & Monitor
</button>
</div>
</div>
</div>
<!-- Config Modal -->
<div id="configModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
<div class="bg-white rounded-xl p-6 w-full max-w-md">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-gray-800">Edit Monitoring Config</h2>
<button id="closeConfigModal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Monitoring Frequency</label>
<select id="monitoringInterval" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="1">1 hour</option>
<option value="2">2 hours</option>
<option value="3">3 hours</option>
<option value="4">4 hours</option>
<option value="6">6 hours</option>
<option value="8">8 hours</option>
<option value="12">12 hours</option>
<option value="24">24 hours</option>
</select>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Recent Messages Count</label>
<select id="messageCount" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="10">10 messages</option>
<option value="20">20 messages</option>
<option value="30">30 messages</option>
<option value="40">40 messages</option>
<option value="50">50 messages</option>
</select>
</div>
<div class="flex justify-end space-x-3">
<button id="cancelConfigBtn" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50">
Cancel
</button>
<button id="saveConfigBtn" class="px-4 py-2 bg-indigo-500 text-white rounded-md hover:bg-indigo-600">
Save Changes
</button>
</div>
</div>
</div>
<script>
// Enhanced sample data with square details
const monitoringData = [
{
sqr_mid: "MID-1001",
name: "Payment Gateway",
description: "Main payment processing service",
image: "https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
risk_level: 1,
recent_messages: [
"Transaction processed successfully",
"No errors detected in last scan",
"System performance optimal"
],
report: "All systems operational. No issues detected in the last 24 hours.",
last_updated: "2023-05-15 09:23:45",
status: "ready",
config: {
interval: 1,
message_count: 10
}
},
{
sqr_mid: "MID-1002",
name: "Inventory Service",
description: "Product inventory management",
image: "https://images.unsplash.com/photo-1556740738-b6a63e27c4df?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
risk_level: 2,
recent_messages: [
"Warning: Low stock detected for SKU-4567",
"Synchronization with warehouse delayed by 15 minutes",
"Database backup completed"
],
report: "Minor issues detected. Low stock warnings for 3 products. Synchronization delays.",
last_updated: "2023-05-15 08:45:12",
status: "ready",
config: {
interval: 2,
message_count: 20
}
},
{
sqr_mid: "MID-1003",
name: "Customer API",
description: "Customer data access endpoint",
image: "https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
risk_level: 3,
recent_messages: [
"ERROR: Authentication failure rate at 12%",
"Response times exceeding SLA by 300ms",
"Emergency maintenance scheduled"
],
report: "Critical issues detected. High failure rate on authentication. Performance degraded.",
last_updated: "2023-05-15 07:30:18",
status: "ready",
config: {
interval: 4,
message_count: 30
}
},
{
sqr_mid: "MID-1004",
name: "Order Processing",
description: "Order fulfillment pipeline",
image: "https://images.unsplash.com/photo-1556742044-3c52d6e88c62?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
risk_level: 2,
recent_messages: [
"Warning: Processing queue backlog of 125 orders",
"Shipping API connectivity issues resolved",
"Daily report generated"
],
report: "Moderate issues. Order backlog detected. Shipping API had temporary outage.",
last_updated: "2023-05-15 10:15:33",
status: "ready",
config: {
interval: 8,
message_count: 10
}
}
];
// DOM elements
const tableBody = document.getElementById('monitoringTableBody');
const addModal = document.getElementById('addModal');
const configModal = document.getElementById('configModal');
const expandAllBtn = document.getElementById('expandAllBtn');
const exportBtn = document.getElementById('exportBtn');
const rerunBtn = document.getElementById('rerunBtn');
const addBtn = document.getElementById('addBtn');
const selectAll = document.getElementById('selectAll');
const sqrMidInput = document.getElementById('sqrMidInput');
const previewSection = document.getElementById('previewSection');
const confirmAddBtn = document.getElementById('confirmAddBtn');
const cancelAddBtn = document.getElementById('cancelAddBtn');
const closeAddModal = document.getElementById('closeAddModal');
const closeConfigModal = document.getElementById('closeConfigModal');
const cancelConfigBtn = document.getElementById('cancelConfigBtn');
const saveConfigBtn = document.getElementById('saveConfigBtn');
// Current config being edited
let currentConfigItem = null;
// Initialize the table with enhanced square details
function renderTable() {
tableBody.innerHTML = '';
monitoringData.forEach(item => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50';
row.dataset.sqrMid = item.sqr_mid;
// Checkbox
const checkboxCell = document.createElement('td');
checkboxCell.className = 'px-6 py-4 whitespace-nowrap';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'row-checkbox rounded text-blue-500';
checkboxCell.appendChild(checkbox);
row.appendChild(checkboxCell);
// SQR MID
const sqrMidCell = document.createElement('td');
sqrMidCell.className = 'px-6 py-4 whitespace-nowrap';
sqrMidCell.innerHTML = `<div class="text-sm font-medium text-gray-900">${item.sqr_mid}</div>`;
row.appendChild(sqrMidCell);
// Risk Level
const riskCell = document.createElement('td');
riskCell.className = 'px-6 py-4 whitespace-nowrap';
riskCell.innerHTML = `
<div class="flex items-center">
<div class="h-4 w-4 rounded-full risk-level-${item.risk_level} mr-2"></div>
<span class="text-sm font-medium">Level ${item.risk_level}</span>
</div>
`;
row.appendChild(riskCell);
// Recent Messages
const messagesCell = document.createElement('td');
messagesCell.className = 'px-6 py-4 whitespace-nowrap';
messagesCell.innerHTML = `
<div class="flex items-center">
<div class="text-sm text-gray-500 max-w-xs truncate">${item.recent_messages[0]}</div>
<button class="ml-2 text-gray-400 hover:text-gray-600 message-toggle">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="slide-down mt-2">
<ul class="text-sm text-gray-500 list-disc pl-5">
${item.recent_messages.map(msg => `<li class="mb-1">${msg}</li>`).join('')}
</ul>
</div>
`;
row.appendChild(messagesCell);
// Report
const reportCell = document.createElement('td');
reportCell.className = 'px-6 py-4 whitespace-nowrap';
reportCell.innerHTML = `
<div class="flex items-center">
<div class="text-sm text-gray-500 max-w-xs truncate">${item.report.substring(0, 50)}...</div>
<button class="ml-2 text-gray-400 hover:text-gray-600 report-toggle">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="slide-down mt-2">
<div class="text-sm text-gray-500">${item.report}</div>
</div>
`;
row.appendChild(reportCell);
// Last Updated
const updatedCell = document.createElement('td');
updatedCell.className = 'px-6 py-4 whitespace-nowrap';
updatedCell.innerHTML = `<div class="text-sm text-gray-500">${item.last_updated}</div>`;
row.appendChild(updatedCell);
// Actions
const actionsCell = document.createElement('td');
actionsCell.className = 'px-6 py-4 whitespace-nowrap text-sm font-medium';
actionsCell.innerHTML = `
<div class="flex items-center space-x-2">
<span class="status-badge inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
item.status === 'ready' ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
}">
${item.status === 'rerun' ? '<i class="fas fa-sync-alt spinner mr-1"></i>' : ''}
${item.status}
</span>
<button class="text-indigo-600 hover:text-indigo-900 config-btn">
<i class="fas fa-cog"></i>
</button>
<button class="text-red-600 hover:text-red-900 delete-btn">
<i class="fas fa-trash"></i>
</button>
</div>
`;
row.appendChild(actionsCell);
// Square Details Row (initially hidden)
const detailsRow = document.createElement('tr');
detailsRow.className = 'square-details hidden';
detailsRow.dataset.sqrMid = item.sqr_mid;
detailsRow.innerHTML = `
<td colspan="8" class="px-6 py-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="col-span-1">
<h3 class="font-medium text-gray-800 mb-1">Square Details</h3>
<p class="text-sm text-gray-600 mb-2">${item.description}</p>
<img src="${item.image}" alt="${item.name}" class="w-full h-32 object-cover rounded-lg">
</div>
<div class="col-span-2">
<h3 class="font-medium text-gray-800 mb-1">Recent Messages</h3>
<ul class="text-sm text-gray-500 list-disc pl-5">
${item.recent_messages.map(msg => `<li class="mb-1">${msg}</li>`).join('')}
</ul>
<h3 class="font-medium text-gray-800 mt-3 mb-1">Full Report</h3>
<p class="text-sm text-gray-500">${item.report}</p>
</div>
</div>
</td>
`;
// Add click handler to show square details when clicking the SQR MID
sqrMidCell.addEventListener('click', function(e) {
if (e.target.tagName !== 'INPUT') { // Don't trigger when clicking checkbox
detailsRow.classList.toggle('hidden');
}
});
tableBody.appendChild(row);
tableBody.appendChild(detailsRow);
});
// Add event listeners to all toggle buttons
document.querySelectorAll('.message-toggle').forEach(btn => {
btn.addEventListener('click', function() {
const slideDown = this.closest('td').querySelector('.slide-down');
slideDown.classList.toggle('active');
const icon = this.querySelector('i');
if (slideDown.classList.contains('active')) {
icon.classList.replace('fa-chevron-down', 'fa-chevron-up');
} else {
icon.classList.replace('fa-chevron-up', 'fa-chevron-down');
}
});
});
document.querySelectorAll('.report-toggle').forEach(btn => {
btn.addEventListener('click', function() {
const slideDown = this.closest('td').querySelector('.slide-down');
slideDown.classList.toggle('active');
const icon = this.querySelector('i');
if (slideDown.classList.contains('active')) {
icon.classList.replace('fa-chevron-down', 'fa-chevron-up');
} else {
icon.classList.replace('fa-chevron-up', 'fa-chevron-down');
}
});
});
// Add event listeners to config buttons
document.querySelectorAll('.config-btn').forEach(btn => {
btn.addEventListener('click', function() {
const row = this.closest('tr');
const sqrMid = row.dataset.sqrMid;
const item = monitoringData.find(item => item.sqr_mid === sqrMid);
currentConfigItem = item;
// Set current values in modal
document.getElementById('monitoringInterval').value = item.config.interval;
document.getElementById('messageCount').value = item.config.message_count;
configModal.classList.remove('hidden');
});
});
// Add event listeners to delete buttons
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', function() {
const row = this.closest('tr');
const sqrMid = row.dataset.sqrMid;
if (confirm(`Are you sure you want to delete monitoring for ${sqrMid}?`)) {
const index = monitoringData.findIndex(item => item.sqr_mid === sqrMid);
if (index !== -1) {
monitoringData.splice(index, 1);
renderTable();
}
}
});
});
}
// Event listeners
addBtn.addEventListener('click', () => {
addModal.classList.remove('hidden');
sqrMidInput.focus();
});
closeAddModal.addEventListener('click', () => {
addModal.classList.add('hidden');
previewSection.classList.add('hidden');
sqrMidInput.value = '';
});
cancelAddBtn.addEventListener('click', () => {
addModal.classList.add('hidden');
previewSection.classList.add('hidden');
sqrMidInput.value = '';
});
closeConfigModal.addEventListener('click', () => {
configModal.classList.add('hidden');
});
cancelConfigBtn.addEventListener('click', () => {
configModal.classList.add('hidden');
});
saveConfigBtn.addEventListener('click', () => {
if (currentConfigItem) {
currentConfigItem.config.interval = parseInt(document.getElementById('monitoringInterval').value);
currentConfigItem.config.message_count = parseInt(document.getElementById('messageCount').value);
renderTable();
configModal.classList.add('hidden');
alert('Configuration saved successfully!');
}
});
expandAllBtn.addEventListener('click', () => {
const allSlideDowns = document.querySelectorAll('.slide-down');
const allMessageToggles = document.querySelectorAll('.message-toggle i');
const allReportToggles = document.querySelectorAll('.report-toggle i');
const anyExpanded = Array.from(allSlideDowns).some(el => el.classList.contains('active'));
allSlideDowns.forEach(el => {
if (anyExpanded) {
el.classList.remove('active');
} else {
el.classList.add('active');
}
});
allMessageToggles.forEach(icon => {
if (anyExpanded) {
icon.classList.replace('fa-chevron-up', 'fa-chevron-down');
} else {
icon.classList.replace('fa-chevron-down', 'fa-chevron-up');
}
});
allReportToggles.forEach(icon => {
if (anyExpanded) {
icon.classList.replace('fa-chevron-up', 'fa-chevron-down');
} else {
icon.classList.replace('fa-chevron-down', 'fa-chevron-up');
}
});
});
exportBtn.addEventListener('click', () => {
const selectedRows = Array.from(document.querySelectorAll('.row-checkbox:checked')).map(checkbox => {
return checkbox.closest('tr').dataset.sqrMid;
});
if (selectedRows.length === 0) {
alert('Please select at least one row to export.');
return;
}
const dataToExport = monitoringData.filter(item => selectedRows.includes(item.sqr_mid));
// In a real app, this would generate an actual Excel file
console.log('Exporting data:', dataToExport);
alert(`Preparing export for ${selectedRows.length} selected items.`);
});
rerunBtn.addEventListener('click', () => {
const selectedRows = Array.from(document.querySelectorAll('.row-checkbox:checked')).map(checkbox => {
return checkbox.closest('tr').dataset.sqrMid;
});
if (selectedRows.length === 0) {
alert('Please select at least one row to rerun.');
return;
}
// Update status to rerun and show loading spinner
monitoringData.forEach(item => {
if (selectedRows.includes(item.sqr_mid)) {
item.status = 'rerun';
}
});
renderTable();
// Simulate server response after 3 seconds
setTimeout(() => {
monitoringData.forEach(item => {
if (selectedRows.includes(item.sqr_mid)) {
item.status = 'ready';
// Simulate updated data
item.last_updated = new Date().toISOString().replace('T', ' ').substring(0, 19);
// Randomly change risk level for demo purposes
if (Math.random() > 0.7) {
item.risk_level = Math.floor(Math.random() * 3) + 1;
}
// Add a new recent message
const messages = [
"Rerun completed successfully",
"New data processed",
"System check completed",
"Updated metrics available"
];
item.recent_messages.unshift(messages[Math.floor(Math.random() * messages.length)]);
// Update report
item.report = `Rerun completed at ${new Date().toISOString().substring(11, 19)}. ` +
(item.risk_level === 1 ? "No issues detected." :
item.risk_level === 2 ? "Some warnings detected." : "Critical issues found.");
}
});
renderTable();
alert('Rerun completed for selected items!');
}, 3000);
});
selectAll.addEventListener('change', function() {
const checkboxes = document.querySelectorAll('.row-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
});
sqrMidInput.addEventListener('input', function() {
// In a real app, this would call an API to validate the SQR MID
// For demo purposes, we'll just show a preview after 3 characters
if (this.value.length >= 3) {
// Simulate API response
const mockResponses = {
"MID": {
name: "Payment Gateway",
description: "Main payment processing service",
image: "https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
recent_message: "Transaction processed successfully"
},
"INV": {
name: "Inventory Service",
description: "Product inventory management",
image: "https://images.unsplash.com/photo-1556740738-b6a63e27c4df?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
recent_message: "Warning: Low stock detected for SKU-4567"
},
"CUS": {
name: "Customer API",
description: "Customer data access endpoint",
image: "https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
recent_message: "ERROR: Authentication failure rate at 12%"
},
"ORD": {
name: "Order Processing",
description: "Order fulfillment pipeline",
image: "https://images.unsplash.com/photo-1556742044-3c52d6e88c62?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
recent_message: "Warning: Processing queue backlog of 125 orders"
}
};
const prefix = this.value.substring(0, 3).toUpperCase();
const mockData = mockResponses[prefix] || {
name: `Service ${this.value}`,
description: `Description for service ${this.value}`,
image: "https://via.placeholder.com/150/008000/FFFFFF",
recent_message: `Initializing monitoring for ${this.value}`
};
document.getElementById('previewImage').src = mockData.image;
document.getElementById('previewName').textContent = mockData.name;
document.getElementById('previewDesc').textContent = mockData.description;
document.getElementById('previewMessage').textContent = mockData.recent_message;
previewSection.classList.remove('hidden');
} else {
previewSection.classList.add('hidden');
}
});
confirmAddBtn.addEventListener('click', function() {
const sqrMid = sqrMidInput.value.trim();
if (!sqrMid) {
alert('Please enter a valid SQR MID');
return;
}
// Check if already exists
if (monitoringData.some(item => item.sqr_mid === sqrMid)) {
alert('This SQR MID is already being monitored');
return;
}
// Add new monitoring item
const newItem = {
sqr_mid: sqrMid,
name: document.getElementById('previewName').textContent || `Service ${sqrMid}`,
description: document.getElementById('previewDesc').textContent || `Monitoring for ${sqrMid}`,
image: document.getElementById('previewImage').src || "https://via.placeholder.com/150/008000/FFFFFF",
risk_level: 1,
recent_messages: [
document.getElementById('previewMessage').textContent || `Monitoring started for ${sqrMid}`
],
report: `Initial monitoring report for ${sqrMid}. No issues detected.`,
last_updated: new Date().toISOString().replace('T', ' ').substring(0, 19),
status: "ready",
config: {
interval: 1,
message_count: 10
}
};
monitoringData.push(newItem);
renderTable();
// Reset and close modal
sqrMidInput.value = '';
previewSection.classList.add('hidden');
addModal.classList.add('hidden');
alert(`Successfully added monitoring for ${sqrMid}`);
});
// Initial render
renderTable();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=vrvrv/monitoring-dashboard" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>