mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-06-11 01:14:45 +02:00
feat(v0.6-phase2): rip out quiet hours entirely -- dashboard toggle, config schema, pipeline checks. Per Matt's repeated feedback (saved as feedback-quiet-hours-trash.md): silent is better than ugly, mesh users who need a fire alert at 3 AM need it at 3 AM. No replacement.
Backend removals:
meshai/config.py
- NotificationRuleConfig.override_quiet field
- NotificationToggle.quiet_hours_override field
- NotificationsConfig.quiet_hours_enabled / quiet_hours_start /
quiet_hours_end fields
- _default_toggles() no longer sets quiet_hours_override=True
- rule migration helper no longer copies override_quiet
meshai/notifications/router.py
- self._quiet_enabled / _quiet_start / _quiet_end instance vars
- _in_quiet_hours() method (deleted entirely)
- The dispatch-time check that suppressed non-overriding rules
during quiet hours
- 'override_quiet': False dropped from subscription rule dicts
meshai/notifications/pipeline/dispatcher.py
- _toggle_to_rule() no longer passes override_quiet=... to the
NotificationRuleConfig constructor
Test changes:
tests/test_notification_toggles.py
- RecChannel.deliver() no longer records override_quiet
- test_quiet_hours_override_immediate_only deleted (only tested the
removed feature)
Frontend removals (dashboard-frontend/src/pages/Notifications.tsx):
- The 'Enable Quiet Hours' card with its time-range inputs deleted
- 'Override Quiet Hours' per-rule toggle deleted
- 'Quiet-hours override (immediate only)' per-toggle field deleted
- quiet_hours_* fields removed from TS interfaces
- quietHoursEnabled prop + state plumbing removed from the RuleEditor
- All override_quiet: false defaults dropped from rule scaffolds
- Unused Moon icon import dropped
Verification (post-strip):
grep -rn 'quiet_hours\|override_quiet' meshai/*.py meshai/**/*.py
-> 0 hits
grep -rn 'quiet_hours\|override_quiet\|quietHours' dashboard-frontend/src
-> 0 hits
Test count: 830 -> 829 (-1: test_quiet_hours_override_immediate_only
deleted; no other regressions).
No replacement. Mesh users who need a fire alert at 3 AM need it at 3 AM.
This commit is contained in:
parent
90783376e8
commit
b948ed775f
8 changed files with 88 additions and 205 deletions
|
|
@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from 'react'
|
|||
import {
|
||||
Save, RotateCcw, RefreshCw, Plus, Trash2, ChevronDown, ChevronRight,
|
||||
Check, X, Eye as EyeIcon, EyeOff, Send, Clock, Zap,
|
||||
Calendar, AlertTriangle, Copy, Moon, AlertCircle, Layers,
|
||||
Calendar, AlertTriangle, Copy, AlertCircle, Layers,
|
||||
Wifi, WifiOff, Mail, Globe, Radio, MessageSquare,
|
||||
Activity, Cloud, Flame, Car, Snowflake, Mountain, MapPin
|
||||
} from 'lucide-react'
|
||||
|
|
@ -35,7 +35,6 @@ interface NotificationRuleConfig {
|
|||
webhook_url: string
|
||||
webhook_headers: Record<string, string>
|
||||
cooldown_minutes: number
|
||||
override_quiet: boolean
|
||||
region_scope: string[]
|
||||
}
|
||||
|
||||
|
|
@ -45,7 +44,6 @@ interface NotificationToggle {
|
|||
min_severity: string
|
||||
regions: string[]
|
||||
severity_channels: Record<string, string[]>
|
||||
quiet_hours_override: boolean
|
||||
broadcast_channel: number | null
|
||||
node_ids: string[]
|
||||
smtp_host: string
|
||||
|
|
@ -61,9 +59,6 @@ interface NotificationToggle {
|
|||
|
||||
interface NotificationsConfig {
|
||||
enabled: boolean
|
||||
quiet_hours_enabled: boolean
|
||||
quiet_hours_start: string
|
||||
quiet_hours_end: string
|
||||
cold_start_grace_seconds?: number
|
||||
band_conditions_enabled?: boolean
|
||||
band_conditions_schedule?: string[]
|
||||
|
|
@ -150,7 +145,6 @@ const RULE_TEMPLATES = [
|
|||
delivery_type: "mesh_broadcast",
|
||||
broadcast_channel: 0,
|
||||
cooldown_minutes: 30,
|
||||
override_quiet: false,
|
||||
schedule_frequency: "daily" as const,
|
||||
schedule_time: "07:00",
|
||||
schedule_time_2: "",
|
||||
|
|
@ -182,7 +176,6 @@ const RULE_TEMPLATES = [
|
|||
delivery_type: "mesh_broadcast",
|
||||
broadcast_channel: 0,
|
||||
cooldown_minutes: 15,
|
||||
override_quiet: false,
|
||||
schedule_frequency: "daily" as const,
|
||||
schedule_time: "07:00",
|
||||
schedule_time_2: "",
|
||||
|
|
@ -214,7 +207,6 @@ const RULE_TEMPLATES = [
|
|||
delivery_type: "mesh_broadcast",
|
||||
broadcast_channel: 0,
|
||||
cooldown_minutes: 60,
|
||||
override_quiet: false,
|
||||
schedule_frequency: "daily" as const,
|
||||
schedule_time: "07:00",
|
||||
schedule_time_2: "",
|
||||
|
|
@ -246,7 +238,6 @@ const RULE_TEMPLATES = [
|
|||
delivery_type: "mesh_broadcast",
|
||||
broadcast_channel: 0,
|
||||
cooldown_minutes: 30,
|
||||
override_quiet: false,
|
||||
schedule_frequency: "daily" as const,
|
||||
schedule_time: "07:00",
|
||||
schedule_time_2: "",
|
||||
|
|
@ -278,7 +269,6 @@ const RULE_TEMPLATES = [
|
|||
delivery_type: "mesh_broadcast",
|
||||
broadcast_channel: 0,
|
||||
cooldown_minutes: 5,
|
||||
override_quiet: true,
|
||||
schedule_frequency: "daily" as const,
|
||||
schedule_time: "07:00",
|
||||
schedule_time_2: "",
|
||||
|
|
@ -316,7 +306,6 @@ const RULE_TEMPLATES = [
|
|||
delivery_type: "mesh_broadcast",
|
||||
broadcast_channel: 0,
|
||||
cooldown_minutes: 0,
|
||||
override_quiet: false,
|
||||
node_ids: [] as string[],
|
||||
smtp_host: "",
|
||||
smtp_port: 587,
|
||||
|
|
@ -730,7 +719,6 @@ function NotificationRuleCard({
|
|||
ruleIndex,
|
||||
categories,
|
||||
regions,
|
||||
quietHoursEnabled,
|
||||
onChange,
|
||||
onDelete,
|
||||
onDuplicate,
|
||||
|
|
@ -740,7 +728,6 @@ function NotificationRuleCard({
|
|||
ruleIndex: number
|
||||
categories: AlertCategory[]
|
||||
regions: RegionInfo[]
|
||||
quietHoursEnabled: boolean
|
||||
onChange: (r: NotificationRuleConfig) => void
|
||||
onDelete: () => void
|
||||
onDuplicate: () => void
|
||||
|
|
@ -1400,18 +1387,7 @@ function NotificationRuleCard({
|
|||
min={0}
|
||||
helper="Min time between repeat sends"
|
||||
info="Prevents alert spam. Same condition won't re-trigger this rule within this window."
|
||||
/>
|
||||
{quietHoursEnabled && (
|
||||
<div className="flex items-end pb-1">
|
||||
<Toggle
|
||||
label="Override Quiet Hours"
|
||||
checked={rule.override_quiet ?? false}
|
||||
onChange={(v) => onChange({ ...rule, override_quiet: v })}
|
||||
helper="Deliver during quiet hours"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
/> </div>
|
||||
|
||||
{/* Rule statistics */}
|
||||
{ruleStats && (
|
||||
|
|
@ -1631,9 +1607,7 @@ function MasterToggles({ toggles, onChange }: {
|
|||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<ListInput label="Regions (empty = all)" value={t.regions || []} onChange={(v) => upd(key, { regions: v })} placeholder="Add region..." />
|
||||
<Toggle label="Quiet-hours override (immediate only)" checked={!!t.quiet_hours_override} onChange={(v) => upd(key, { quiet_hours_override: v })} />
|
||||
<div className="text-xs text-slate-500 pt-1">Channel config</div>
|
||||
<ListInput label="Regions (empty = all)" value={t.regions || []} onChange={(v) => upd(key, { regions: v })} placeholder="Add region..." /> <div className="text-xs text-slate-500 pt-1">Channel config</div>
|
||||
<NumberInput label="Broadcast channel" value={t.broadcast_channel ?? 0} onChange={(v) => upd(key, { broadcast_channel: v })} />
|
||||
<ListInput label="DM node IDs" value={t.node_ids || []} onChange={(v) => upd(key, { node_ids: v })} placeholder="!nodeid" />
|
||||
<ListInput label="Email recipients" value={t.recipients || []} onChange={(v) => upd(key, { recipients: v })} placeholder="ops@example.com" />
|
||||
|
|
@ -1764,7 +1738,6 @@ export default function Notifications() {
|
|||
webhook_url: '',
|
||||
webhook_headers: {},
|
||||
cooldown_minutes: 10,
|
||||
override_quiet: false,
|
||||
region_scope: [],
|
||||
})
|
||||
|
||||
|
|
@ -2082,46 +2055,7 @@ export default function Notifications() {
|
|||
/>
|
||||
|
||||
{config.enabled && (
|
||||
<>
|
||||
{/* Quiet Hours Section */}
|
||||
<div className="space-y-3 p-4 bg-[#0a0e17] rounded-lg border border-[#1e2a3a]">
|
||||
<div className="flex items-center gap-2">
|
||||
<Moon size={14} className="text-slate-400" />
|
||||
<label className="text-xs text-slate-500 uppercase tracking-wide">Quiet Hours</label>
|
||||
</div>
|
||||
|
||||
<Toggle
|
||||
label="Enable Quiet Hours"
|
||||
checked={config.quiet_hours_enabled ?? true}
|
||||
onChange={(v) => setConfig({ ...config, quiet_hours_enabled: v })}
|
||||
helper="Suppress non-emergency alerts during sleeping hours"
|
||||
info="When enabled, ROUTINE alerts are suppressed during quiet hours. PRIORITY and IMMEDIATE always deliver."
|
||||
/>
|
||||
|
||||
{config.quiet_hours_enabled && (
|
||||
<>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<TimeInput
|
||||
label="Start Time"
|
||||
value={config.quiet_hours_start || '22:00'}
|
||||
onChange={(v) => setConfig({ ...config, quiet_hours_start: v })}
|
||||
helper="When quiet hours begin"
|
||||
/>
|
||||
<TimeInput
|
||||
label="End Time"
|
||||
value={config.quiet_hours_end || '06:00'}
|
||||
onChange={(v) => setConfig({ ...config, quiet_hours_end: v })}
|
||||
helper="When quiet hours end"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-slate-600">
|
||||
Emergency alerts and rules with "Override Quiet Hours" enabled always deliver.
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Cold-start grace -- v0.5.8b */}
|
||||
<> {/* Cold-start grace -- v0.5.8b */}
|
||||
<div className="space-y-3 p-4 bg-[#0a0e17] rounded-lg border border-[#1e2a3a]">
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="text-xs text-slate-500 uppercase tracking-wide">Cold-start grace</label>
|
||||
|
|
@ -2212,9 +2146,7 @@ export default function Notifications() {
|
|||
rule={rule}
|
||||
ruleIndex={i}
|
||||
categories={categories}
|
||||
regions={regions}
|
||||
quietHoursEnabled={config.quiet_hours_enabled ?? true}
|
||||
onChange={(r) => {
|
||||
regions={regions} onChange={(r) => {
|
||||
const newRules = [...(config.rules || [])]
|
||||
newRules[i] = r
|
||||
setConfig({ ...config, rules: newRules })
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue