diff --git a/plugins/notifications/frontend/views/NotificationForm.vue b/plugins/notifications/frontend/views/NotificationForm.vue index fa5cbf65..528df1c5 100644 --- a/plugins/notifications/frontend/views/NotificationForm.vue +++ b/plugins/notifications/frontend/views/NotificationForm.vue @@ -231,6 +231,34 @@ +
+
+ + + Optional: Filter alerts by asset type, location, or business unit (JSON format) +
+ +
+ + + Minutes until auto-dismiss (0 = manual acknowledgment only) +
+
+
{{ error }}
@@ -304,6 +332,32 @@ const form = ref({ // site's wall clock, not the viewer's browser zone. Loaded in onMounted. const siteTimezone = ref(DEFAULT_TZ) +// Alert scope as text for editing (converts to/from JSON) +const alertScopeText = ref('') + +watch(() => form.value.alertscope, (newVal) => { + if (newVal && typeof newVal === 'object') { + alertScopeText.value = JSON.stringify(newVal, null, 2) + } else if (newVal && typeof newVal === 'string') { + alertScopeText.value = newVal + } else { + alertScopeText.value = '' + } +}, { immediate: true }) + +watch(alertScopeText, (newVal) => { + if (!newVal.trim()) { + form.value.alertscope = null + return + } + try { + form.value.alertscope = JSON.parse(newVal) + } catch (e) { + // Keep the text as-is until it's valid JSON + form.value.alertscope = newVal + } +}) + function selectedTypeName() { const selectedType = types.value.find(t => t.notificationtypeid === parseInt(form.value.notificationtypeid)) return selectedType?.typename?.toLowerCase() || '' diff --git a/plugins/notifications/migrations/versions/0006_add_fleet_alerts.py b/plugins/notifications/migrations/versions/0006_add_fleet_alerts.py index 05d142fd..cec8b136 100644 --- a/plugins/notifications/migrations/versions/0006_add_fleet_alerts.py +++ b/plugins/notifications/migrations/versions/0006_add_fleet_alerts.py @@ -5,7 +5,7 @@ to support fleet-wide alert broadcasting. Creates notificationacknowledgements table to track which assets have acknowledged fleet alerts. Fleet alerts can be scoped to specific asset types, locations, or business units -via the alertscope JSONB field. alerttimeout=0 means no auto-dismiss (manual only). +via the alertscope TEXT field (JSON string). alerttimeout=0 means no auto-dismiss (manual only). Idempotent: column and table creation are skipped when they already exist. @@ -14,7 +14,6 @@ Revises: notifications0005boardorder """ from alembic import op import sqlalchemy as sa -from sqlalchemy.dialects.postgresql import JSONB revision = 'notifications0006fleetalerts' @@ -43,7 +42,7 @@ def upgrade(): if 'alertscope' not in cols: op.add_column('notifications', - sa.Column('alertscope', JSONB, nullable=True)) + sa.Column('alertscope', sa.Text, nullable=True)) if 'alerttimeout' not in cols: op.add_column('notifications',