Fix notifications fleet alert migration for MySQL and add UI fields

- Change alertscope from JSONB to TEXT for MySQL compatibility
- Add Alert Fleet checkbox, scope, and timeout fields to notification form
- Fields appear conditionally when Alert Fleet is checked
This commit is contained in:
Proudlock
2026-09-08 16:57:00 -04:00
parent 381cc6c845
commit 6340648ad9
2 changed files with 56 additions and 3 deletions

View File

@@ -231,6 +231,34 @@
</div>
</div>
<div v-if="form.alertfleet" class="fleet-alert-options">
<div class="form-group">
<label for="alertscope">Alert Scope (JSON)</label>
<textarea
id="alertscope"
v-model="alertScopeText"
class="form-control"
rows="3"
:disabled="isDetail"
placeholder='{"assettype": "computer", "location": "Building A"}'
></textarea>
<small class="form-hint">Optional: Filter alerts by asset type, location, or business unit (JSON format)</small>
</div>
<div class="form-group">
<label for="alerttimeout">Auto-dismiss Timeout (minutes)</label>
<input
id="alerttimeout"
v-model.number="form.alerttimeout"
type="number"
class="form-control"
min="0"
:disabled="isDetail"
/>
<small class="form-hint">Minutes until auto-dismiss (0 = manual acknowledgment only)</small>
</div>
</div>
<div v-if="error" class="error-message">{{ error }}</div>
<div class="form-actions">
@@ -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() || ''

View File

@@ -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',