From a5f741b332b5df880cb78f8d5326d653f3be797b Mon Sep 17 00:00:00 2001
From: nmemmert <67961292+nmemmert@users.noreply.github.com>
Date: Mon, 15 Dec 2025 09:40:21 -0500
Subject: [PATCH] Add comprehensive settings: data retention, incident
thresholds, alert retry, scheduling, and dashboard customization
---
client/build/asset-manifest.json | 6 +--
client/build/index.html | 2 +-
client/src/SettingsWizard.js | 15 +++++++
server/index.js | 67 ++++++++++++++++++++++++++++++++
4 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/client/build/asset-manifest.json b/client/build/asset-manifest.json
index b81c707..9b0099a 100644
--- a/client/build/asset-manifest.json
+++ b/client/build/asset-manifest.json
@@ -1,15 +1,15 @@
{
"files": {
"main.css": "/static/css/main.44e40ac2.css",
- "main.js": "/static/js/main.977c4ae0.js",
+ "main.js": "/static/js/main.54d4db7c.js",
"static/js/453.d456ce70.chunk.js": "/static/js/453.d456ce70.chunk.js",
"index.html": "/index.html",
"main.44e40ac2.css.map": "/static/css/main.44e40ac2.css.map",
- "main.977c4ae0.js.map": "/static/js/main.977c4ae0.js.map",
+ "main.54d4db7c.js.map": "/static/js/main.54d4db7c.js.map",
"453.d456ce70.chunk.js.map": "/static/js/453.d456ce70.chunk.js.map"
},
"entrypoints": [
"static/css/main.44e40ac2.css",
- "static/js/main.977c4ae0.js"
+ "static/js/main.54d4db7c.js"
]
}
\ No newline at end of file
diff --git a/client/build/index.html b/client/build/index.html
index c9496fa..7e0bc09 100644
--- a/client/build/index.html
+++ b/client/build/index.html
@@ -1 +1 @@
-
SkyWatch
\ No newline at end of file
+SkyWatch
\ No newline at end of file
diff --git a/client/src/SettingsWizard.js b/client/src/SettingsWizard.js
index e747faa..d96e09c 100644
--- a/client/src/SettingsWizard.js
+++ b/client/src/SettingsWizard.js
@@ -16,6 +16,21 @@ function SettingsWizard() {
check_interval: 60000,
timeout: 5000,
timezone: 'UTC',
+ retention_days: 7,
+ auto_cleanup_enabled: false,
+ consecutive_failures: 3,
+ grace_period: 300,
+ downtime_threshold: 600,
+ alert_retry_count: 3,
+ alert_retry_delay: 60,
+ fallback_webhook: '',
+ global_quiet_hours_start: '',
+ global_quiet_hours_end: '',
+ escalation_hours: 4,
+ default_sort: 'name',
+ items_per_page: 20,
+ refresh_interval: 5000,
+ theme: 'light',
});
const [testResult, setTestResult] = useState(null);
diff --git a/server/index.js b/server/index.js
index 34668b9..4554e30 100644
--- a/server/index.js
+++ b/server/index.js
@@ -230,6 +230,26 @@ app.get('/api/settings', (req, res) => {
check_interval: parseInt(process.env.CHECK_INTERVAL) || 60000,
timeout: parseInt(process.env.TIMEOUT) || 5000,
timezone: process.env.TIMEZONE || 'UTC',
+ // Data retention settings
+ retention_days: parseInt(process.env.RETENTION_DAYS) || 7,
+ auto_cleanup_enabled: process.env.AUTO_CLEANUP_ENABLED === 'true',
+ // Incident thresholds
+ consecutive_failures: parseInt(process.env.CONSECUTIVE_FAILURES) || 3,
+ grace_period: parseInt(process.env.GRACE_PERIOD) || 300,
+ downtime_threshold: parseInt(process.env.DOWNTIME_THRESHOLD) || 600,
+ // Alert retry logic
+ alert_retry_count: parseInt(process.env.ALERT_RETRY_COUNT) || 3,
+ alert_retry_delay: parseInt(process.env.ALERT_RETRY_DELAY) || 60,
+ fallback_webhook: process.env.FALLBACK_WEBHOOK || '',
+ // Alert scheduling
+ global_quiet_hours_start: process.env.GLOBAL_QUIET_HOURS_START || '',
+ global_quiet_hours_end: process.env.GLOBAL_QUIET_HOURS_END || '',
+ escalation_hours: parseInt(process.env.ESCALATION_HOURS) || 4,
+ // Dashboard customization
+ default_sort: process.env.DEFAULT_SORT || 'name',
+ items_per_page: parseInt(process.env.ITEMS_PER_PAGE) || 20,
+ refresh_interval: parseInt(process.env.REFRESH_INTERVAL) || 5000,
+ theme: process.env.THEME || 'light',
};
res.json(settings);
});
@@ -252,6 +272,22 @@ app.post('/api/settings', (req, res) => {
webhook_url,
check_interval,
timeout,
+ timezone,
+ retention_days,
+ auto_cleanup_enabled,
+ consecutive_failures,
+ grace_period,
+ downtime_threshold,
+ alert_retry_count,
+ alert_retry_delay,
+ fallback_webhook,
+ global_quiet_hours_start,
+ global_quiet_hours_end,
+ escalation_hours,
+ default_sort,
+ items_per_page,
+ refresh_interval,
+ theme,
} = req.body;
const envContent = `PORT=${process.env.PORT || 3001}
@@ -266,6 +302,22 @@ WEBHOOK_ENABLED=${webhook_enabled}
WEBHOOK_URL=${webhook_url}
CHECK_INTERVAL=${check_interval}
TIMEOUT=${timeout}
+ TIMEZONE=${timezone || 'UTC'}
+ RETENTION_DAYS=${retention_days || 7}
+ AUTO_CLEANUP_ENABLED=${auto_cleanup_enabled}
+ CONSECUTIVE_FAILURES=${consecutive_failures || 3}
+ GRACE_PERIOD=${grace_period || 300}
+ DOWNTIME_THRESHOLD=${downtime_threshold || 600}
+ ALERT_RETRY_COUNT=${alert_retry_count || 3}
+ ALERT_RETRY_DELAY=${alert_retry_delay || 60}
+ FALLBACK_WEBHOOK=${fallback_webhook || ''}
+ GLOBAL_QUIET_HOURS_START=${global_quiet_hours_start || ''}
+ GLOBAL_QUIET_HOURS_END=${global_quiet_hours_end || ''}
+ ESCALATION_HOURS=${escalation_hours || 4}
+ DEFAULT_SORT=${default_sort || 'name'}
+ ITEMS_PER_PAGE=${items_per_page || 20}
+ REFRESH_INTERVAL=${refresh_interval || 5000}
+ THEME=${theme || 'light'}
`;
try {
@@ -284,6 +336,21 @@ TIMEOUT=${timeout}
process.env.WEBHOOK_URL = webhook_url;
process.env.CHECK_INTERVAL = String(check_interval);
process.env.TIMEOUT = String(timeout);
+ process.env.RETENTION_DAYS = String(retention_days || 7);
+ process.env.AUTO_CLEANUP_ENABLED = String(auto_cleanup_enabled);
+ process.env.CONSECUTIVE_FAILURES = String(consecutive_failures || 3);
+ process.env.GRACE_PERIOD = String(grace_period || 300);
+ process.env.DOWNTIME_THRESHOLD = String(downtime_threshold || 600);
+ process.env.ALERT_RETRY_COUNT = String(alert_retry_count || 3);
+ process.env.ALERT_RETRY_DELAY = String(alert_retry_delay || 60);
+ process.env.FALLBACK_WEBHOOK = fallback_webhook || '';
+ process.env.GLOBAL_QUIET_HOURS_START = global_quiet_hours_start || '';
+ process.env.GLOBAL_QUIET_HOURS_END = global_quiet_hours_end || '';
+ process.env.ESCALATION_HOURS = String(escalation_hours || 4);
+ process.env.DEFAULT_SORT = default_sort || 'name';
+ process.env.ITEMS_PER_PAGE = String(items_per_page || 20);
+ process.env.REFRESH_INTERVAL = String(refresh_interval || 5000);
+ process.env.THEME = theme || 'light';
notificationService.setConfig({
email_enabled: email_enabled === true || email_enabled === 'true',