Fix per-resource settings: tags saving, is_public bug, global setting inheritance
Bug fixes: - tags field was missing from INSERT/UPDATE SQL — tags never persisted - is_public: `0 !== false` is true in JS, so private resources (is_public=0) were silently flipped to public on every edit; fixed with explicit 0/false check Global setting inheritance: - One-time DB migration nulls out check_interval and timeout on all existing resources so they inherit from global monitoring settings going forward - Scheduler reads global check_interval and timeout from DB each cycle and uses them as the fallback when per-resource values are null - Create and edit modals: empty field = use global; placeholder shows the current global value so it's clear what will be used Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
3a3d32ecac
commit
59078362da
4 files changed
+49
-18
No files matched your search
+15
-7
@@ -22,8 +22,8 @@ function Dashboard() {
|
||||
name: '',
|
||||
url: '',
|
||||
type: 'http',
|
||||
check_interval: 60000,
|
||||
timeout: 5000,
|
||||
check_interval: null,
|
||||
timeout: null,
|
||||
group_id: null,
|
||||
http_keyword: '',
|
||||
http_headers: '',
|
||||
@@ -48,6 +48,8 @@ function Dashboard() {
|
||||
const [sortKey, setSortKey] = useState('severity');
|
||||
const [renderLimit, setRenderLimit] = useState(120);
|
||||
const [refreshInterval, setRefreshInterval] = useState(15000);
|
||||
const [globalCheckInterval, setGlobalCheckInterval] = useState(60000);
|
||||
const [globalTimeout, setGlobalTimeout] = useState(5000);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [pendingDeleteId, setPendingDeleteId] = useState(null);
|
||||
const [pendingBulkDelete, setPendingBulkDelete] = useState(false);
|
||||
@@ -144,6 +146,8 @@ function Dashboard() {
|
||||
if (s.items_per_page) setRenderLimit(parseInt(s.items_per_page));
|
||||
if (s.default_sort) setSortKey(s.default_sort);
|
||||
if (s.refresh_interval) setRefreshInterval(parseInt(s.refresh_interval));
|
||||
if (s.check_interval) setGlobalCheckInterval(parseInt(s.check_interval));
|
||||
if (s.timeout) setGlobalTimeout(parseInt(s.timeout));
|
||||
}).catch(() => {});
|
||||
}, []);
|
||||
|
||||
@@ -159,7 +163,7 @@ function Dashboard() {
|
||||
}, [connectWebSocket, loadResources, refreshInterval]);
|
||||
|
||||
const emptyForm = {
|
||||
name: '', url: '', type: 'http', check_interval: 60000, timeout: 5000,
|
||||
name: '', url: '', type: 'http', check_interval: null, timeout: null,
|
||||
group_id: null, http_keyword: '', http_headers: '', quiet_hours_start: '',
|
||||
quiet_hours_end: '', cert_expiry_days: 30, sla_target: 99.9, email_to: '',
|
||||
maintenance_mode: false, tags: '', consecutive_failures_threshold: 1,
|
||||
@@ -825,13 +829,15 @@ function Dashboard() {
|
||||
|
||||
<div className="form-group">
|
||||
<label>Check Interval (ms)</label>
|
||||
<input type="number" value={formData.check_interval} onChange={(e) => setFormData({ ...formData, check_interval: parseInt(e.target.value) })} min="10000" />
|
||||
<input type="number" value={formData.check_interval ?? ''} placeholder={`${globalCheckInterval} (global default)`} onChange={(e) => setFormData({ ...formData, check_interval: e.target.value ? parseInt(e.target.value) : null })} min="10000" />
|
||||
<small>Leave empty to use global setting ({globalCheckInterval}ms)</small>
|
||||
</div>
|
||||
|
||||
{formData.type !== 'heartbeat' && (
|
||||
<div className="form-group">
|
||||
<label>Timeout (ms)</label>
|
||||
<input type="number" value={formData.timeout} onChange={(e) => setFormData({ ...formData, timeout: parseInt(e.target.value) })} min="1000" />
|
||||
<input type="number" value={formData.timeout ?? ''} placeholder={`${globalTimeout} (global default)`} onChange={(e) => setFormData({ ...formData, timeout: e.target.value ? parseInt(e.target.value) : null })} min="1000" />
|
||||
<small>Leave empty to use global setting ({globalTimeout}ms)</small>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -965,12 +971,14 @@ function Dashboard() {
|
||||
|
||||
<div className="form-group">
|
||||
<label>Check Interval (ms)</label>
|
||||
<input type="number" value={editData.check_interval || 60000} onChange={(e) => setEditData({ ...editData, check_interval: parseInt(e.target.value) })} min="10000" />
|
||||
<input type="number" value={editData.check_interval ?? ''} placeholder={`${globalCheckInterval} (global default)`} onChange={(e) => setEditData({ ...editData, check_interval: e.target.value ? parseInt(e.target.value) : null })} min="10000" />
|
||||
<small>Leave empty to use global setting ({globalCheckInterval}ms)</small>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Timeout (ms)</label>
|
||||
<input type="number" value={editData.timeout || 5000} onChange={(e) => setEditData({ ...editData, timeout: parseInt(e.target.value) })} min="1000" />
|
||||
<input type="number" value={editData.timeout ?? ''} placeholder={`${globalTimeout} (global default)`} onChange={(e) => setEditData({ ...editData, timeout: e.target.value ? parseInt(e.target.value) : null })} min="1000" />
|
||||
<small>Leave empty to use global setting ({globalTimeout}ms)</small>
|
||||
</div>
|
||||
|
||||
{(editData.type === 'http' || editData.type === 'https' || editData.type === 'health') && (
|
||||
|
||||
Reference in new issue
Block a user