Skip to content

Add Enabled flag to AlarmGroups; filter disabled groups from AlarmOperation#593

Draft
Copilot wants to merge 3 commits intomasterfrom
copilot/add-enabled-flag-to-alarmgroups
Draft

Add Enabled flag to AlarmGroups; filter disabled groups from AlarmOperation#593
Copilot wants to merge 3 commits intomasterfrom
copilot/add-enabled-flag-to-alarmgroups

Conversation

Copy link
Copy Markdown

Copilot AI commented Mar 11, 2026

AlarmGroups had no enable/disable mechanism, so AlarmOperation always evaluated all alarms regardless of intent. This adds an Enabled flag with default true (preserving existing behavior) and filters disabled groups out of alarm evaluation at the SQL level.

Data Model

  • Added Enabled BIT NOT NULL DEFAULT(1) to AlarmGroup table
  • AlarmGroup and AlarmGroupView C# models updated with [DefaultValue(true)] public bool Enabled { get; set; }

SQL Views

  • ActiveAlarmView: both UNION branches now exclude disabled groups — AlarmFactor branch uses INNER JOIN AlarmGroup AG ON ... AND AG.Enabled = 1; synthetic-factor branch uses WHERE AlarmGroup.Enabled = 1. This is where HIDSAlarmOperation queries, so no C# changes are needed.
  • AlarmGroupView: exposes Enabled column for UI consumption
(
    SELECT AF.ID, AF.Factor, AF.AlarmGroupID, AF.SeverityID
    FROM AlarmFactor AF
    INNER JOIN AlarmGroup AG ON AF.AlarmGroupID = AG.ID AND AG.Enabled = 1
    UNION
    SELECT NULL, 1.0, AlarmGroup.ID, AlarmGroup.SeverityID
    FROM AlarmGroup
    WHERE AlarmGroup.Enabled = 1
) AlarmFactor LEFT JOIN ...

Migration

The migration SQL for existing databases is provided as a PR comment. It performs an idempotent ALTER TABLE (column add guarded by IF NOT EXISTS), followed by drop/recreate of both views — safe to run against existing databases.

API / TypeScript

  • IAlarmGroup and IAlarmGroupView interfaces gain Enabled: boolean
  • New groups initialized with Enabled: true in Redux reset action

UI (SPCTools)

  • GeneralSettings.tsx: CheckBox for Enabled in the wizard's general settings step
  • AlarmGroup.tsx: Status column (Enabled/Disabled badge) in the list view; Enabled added as a searchable field
  • WizardHome.tsx: "Save" button (btn-success) added to the left of the "Continue" button when editing an existing alarm group (steps 1–3 only); allows saving changes directly without completing the remaining wizard steps. The button is disabled with a validation tooltip when the current step has unmet required fields.
Original prompt

Repo: GridProtectionAlliance/openXDA (C#, TSQL, TS).

Goal
Add an enabled flag to AlarmGroups and make AlarmOperation only consider alarms that are enabled.

Background / Current behavior

  • Alarm groups currently have no enable/disable mechanism.
  • AlarmOperation currently considers all alarms in groups.

Required changes

  1. Data model / schema
  • Add a boolean Enabled flag to AlarmGroups.
  • Default should preserve existing behavior for existing rows (i.e., Enabled = true).
  • Add/update any required database migration scripts (TSQL) and ensure deployments handle existing databases.
  1. Server-side logic (C#)
  • Update AlarmGroup entity/model to include Enabled.
  • Update AlarmOperation logic so it only evaluates alarms associated with AlarmGroups where Enabled = true.
  • Ensure queries and joins filter out disabled groups efficiently (prefer SQL-side filtering).
  1. UI (TypeScript/HTML/CSS) if applicable
  • If the repo has an AlarmGroups management UI, add a toggle/checkbox for Enabled.
  • Ensure disabled groups are visually indicated and excluded from alarm operations as per server behavior.
  1. API / contracts
  • If AlarmGroups are exposed via API, include Enabled in DTOs.
  • Ensure backward compatibility (clients not sending Enabled should create groups enabled by default).
  1. Tests
  • Add/update unit/integration tests verifying:
    • Newly created AlarmGroups default to Enabled.
    • Disabled groups are not considered by AlarmOperation.
    • Re-enabling restores consideration.

Acceptance criteria

  • AlarmGroups table (or equivalent) has an Enabled column with default true.
  • AlarmOperation ignores alarms from disabled groups.
  • UI/API can set Enabled.
  • All tests pass and no regressions for existing deployments.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: Add an Enabled Flag to the AlarmGroups, such that the AlarmOperation only considers Alarms when they are enabled

Assistant: I’ve kicked off the change request and am now waiting on your accept/reject response to proceed with implementing the Enabled flag for AlarmGroups and updating AlarmOperation to ignore disabled groups.

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Add enabled flag to AlarmGroups and update AlarmOperation behavior Add Enabled flag to AlarmGroups; filter disabled groups from AlarmOperation Mar 11, 2026
@clackner-gpa
Copy link
Copy Markdown
Member

@copilot Can you remove the SQL file for migration and add the migration to the PR as a comment?

Copy link
Copy Markdown
Author

Copilot AI commented Mar 24, 2026

@copilot Can you remove the SQL file for migration and add the migration to the PR as a comment?

Done — the migration file has been removed in commit d7a6268. Here is the migration SQL to run against existing databases:

-- Migration: Add Enabled flag to AlarmGroup
-- Existing rows default to Enabled = 1 (true) to preserve existing behavior.

-- Add Enabled column to AlarmGroup if it does not already exist
IF NOT EXISTS (
    SELECT 1
    FROM sys.columns
    WHERE object_id = OBJECT_ID('AlarmGroup')
      AND name = 'Enabled'
)
BEGIN
    ALTER TABLE AlarmGroup
    ADD Enabled BIT NOT NULL DEFAULT(1)
END
GO

-- Drop and recreate ActiveAlarmView to filter disabled AlarmGroups
IF OBJECT_ID('ActiveAlarmView', 'V') IS NOT NULL
    DROP VIEW ActiveAlarmView
GO

CREATE VIEW ActiveAlarmView AS
SELECT
    Alarm.ID AS AlarmID,
    Alarm.AlarmGroupID AS AlarmGroupID,
    AlarmGroup.AlarmTypeID AS AlarmTypeID,
    AlarmFactor.ID AS AlarmFactorID,
    AlarmFactor.SeverityID,
    Alarm.SeriesID AS SeriesID,
    AlarmFactor.Factor AS Value
FROM
    (
        SELECT AF.ID, AF.Factor, AF.AlarmGroupID, AF.SeverityID
        FROM AlarmFactor AF
        INNER JOIN AlarmGroup AG ON AF.AlarmGroupID = AG.ID AND AG.Enabled = 1
        UNION
        SELECT
            NULL AS ID,
            1.0 AS Factor,
            AlarmGroup.ID AS AlarmGroupID,
            AlarmGroup.SeverityID
        FROM AlarmGroup
        WHERE AlarmGroup.Enabled = 1
    ) AlarmFactor LEFT JOIN
    Alarm ON AlarmFactor.AlarmGroupID = alarm.AlarmGroupID LEFT JOIN
    AlarmGroup ON Alarm.AlarmGroupID = AlarmGroup.ID
GO

-- Drop and recreate AlarmGroupView to include Enabled column
IF OBJECT_ID('AlarmGroupView', 'V') IS NOT NULL
    DROP VIEW AlarmGroupView
GO

CREATE VIEW AlarmGroupView AS 
SELECT 
    AlarmGroup.ID,
    AlarmGroup.Name,
    AlarmSeverity.Name AlarmSeverity,
    CountStats.ChannelCount Channels,
    CountStats.MeterCount Meters,
    LastAlarm.StartTime LastAlarmStart,
    LastAlarm.EndTime LastAlarmEnd,
    LastAlarm.ChannelName LastChannel,
    LastAlarm.MeterName LastMeter,
    AlarmType.Description AS AlarmType,
    AlarmGroup.Enabled
FROM 
    AlarmGroup LEFT JOIN
    AlarmSeverity ON AlarmGroup.SeverityID = AlarmSeverity.ID LEFT JOIN
    AlarmType ON AlarmGroup.AlarmTypeID = AlarmType.ID OUTER APPLY
    (
        SELECT
            COUNT(DISTINCT Channel.ID) ChannelCount,
            COUNT(DISTINCT Channel.MeterID) MeterCount
        FROM
            Channel JOIN
            Series ON Series.ChannelID = Channel.ID JOIN
            Alarm ON Alarm.SeriesID = Series.ID
        WHERE Alarm.AlarmGroupID = AlarmGroup.ID
    ) CountStats OUTER APPLY
    (
        SELECT TOP 1
            LatestAlarmLog.StartTime,
            LatestAlarmLog.EndTime,
            Channel.Name ChannelName,
            Meter.Name MeterName
        FROM
            Alarm JOIN
            Series ON Alarm.SeriesID = Series.ID JOIN
            Channel ON Series.ChannelID = Channel.ID JOIN
            Meter ON Channel.MeterID = Meter.ID JOIN
            LatestAlarmLog ON LatestAlarmLog.AlarmID = Alarm.ID
        WHERE Alarm.AlarmGroupID = AlarmGroup.ID
        ORDER BY
            LatestAlarmLog.StartTime DESC,
            LatestAlarmLog.AlarmLogID DESC
    ) LastAlarm
GO

@clackner-gpa
Copy link
Copy Markdown
Member

@copilot Add a button to the AlarmGroup Wizard when editing alarm Groups to allow the user to skip steps 2 onwards and save the changes directly. It should be btn-success style and located to the left of the Next button. Make sure it also has validation as appropriate

Copy link
Copy Markdown
Author

Copilot AI commented Mar 24, 2026

@copilot Add a button to the AlarmGroup Wizard when editing alarm Groups to allow the user to skip steps 2 onwards and save the changes directly. It should be btn-success style and...

Done in commit 991c219. A "Save" button (btn-success) now appears to the left of the "Continue" button on steps 1–3 of the wizard when editing an existing alarm group (not when creating a new one). It is disabled with a tooltip showing the same validation requirements as the current step when there are unmet required fields, and dispatches SaveWizard() directly when clicked (bypassing the remaining steps). The button does not appear on the "Test" step, where the existing "Save" button already handles saving.

Copilot AI and others added 3 commits March 24, 2026 19:17
Co-authored-by: clackner-gpa <52460212+clackner-gpa@users.noreply.github.com>
@clackner-gpa clackner-gpa force-pushed the copilot/add-enabled-flag-to-alarmgroups branch from 991c219 to 6f18ee8 Compare March 24, 2026 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants