diff --git a/index.html b/index.html new file mode 100644 index 0000000..718de5f --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + +
+ + +${item.error_details}
+ `; + document.body.appendChild(detailModal); + + const closeModal = detailModal.querySelector('.modal-close'); + closeModal.addEventListener('click', () => { + document.body.removeChild(detailModal); + }); + }); + + const productSection = container.lastElementChild; + productSection.appendChild(jobItem); + }); + }) + .catch((error) => { + console.error('Error fetching data:', error); + container.innerHTML = 'Error loading backup data. Check backend logs.
'; + }); \ No newline at end of file diff --git a/server.js b/server.js new file mode 100644 index 0000000..6980bbc --- /dev/null +++ b/server.js @@ -0,0 +1,37 @@ +const express = require('express'); +const { Pool } = require('pg'); +const app = express(); +const port = 3000; + +const pool = new Pool({ + user: 'your_user', + host: 'localhost', + database: 'backup_dashboard', + password: 'your_password', + port: 5432, +}); + +app.get('/api/backups', async (req, res) => { + try { + const result = await pool.query(` + SELECT + company_name, + backup_product, + job_name, + last_backup_time, + status, + error_details, + next_backup_time + FROM backup_jobs + ORDER BY company_name, backup_product; + `); + res.json(result.rows); + } catch (err) { + console.error(err); + res.status(500).send('Server error'); + } +}); + +app.listen(port, () => { + console.log(`Backend running on http://localhost:${port}`); +}); \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..6a49322 --- /dev/null +++ b/styles.css @@ -0,0 +1,95 @@ +body { + font-family: Arial, sans-serif; + margin: 20px; + background: #f4f6f8; +} + +.dashboard { + max-width: 1200px; + margin: auto; +} + +.company-section { + margin-bottom: 40px; + padding: 20px; + background: #fff; + border-radius: 8px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.company-header { + font-size: 24px; + margin-bottom: 15px; +} + +.backup-product { + margin-bottom: 20px; + padding: 10px; + background: #e8f0fe; + border-radius: 5px; +} + +.job-list { + margin-left: 20px; +} + +.job-item { + display: flex; + justify-content: space-between; + padding: 8px; + margin-bottom: 5px; + background: #fff; + border-radius: 5px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.job-name { + font-weight: bold; +} + +.status-pill { + padding: 4px 8px; + border-radius: 20px; + font-size: 12px; + cursor: pointer; +} + +.status-success { + background: #d4edda; + color: #155724; +} + +.status-warning { + background: #fff3cd; + color: #856404; +} + +.status-error { + background: #f8d7da; + color: #721c24; +} + +.detail-modal { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: #fff; + padding: 20px; + border-radius: 8px; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); + z-index: 1000; + display: none; +} + +.detail-modal.show { + display: block; +} + +.modal-close { + position: absolute; + top: 10px; + right: 15px; + font-size: 20px; + cursor: pointer; +} \ No newline at end of file