feat(ui/triggers): expression trigger panel in the script & alarm editors

This commit is contained in:
Joseph Doherty
2026-05-16 05:46:27 -04:00
parent 78b10d00d8
commit 3499d76f14
3 changed files with 117 additions and 1 deletions
@@ -23,6 +23,7 @@
<option value="Interval">Interval — run on a fixed timer</option>
<option value="ValueChange">Value change — run when an attribute changes</option>
<option value="Conditional">Conditional — run when a condition is met</option>
<option value="Expression">Expression — run when a boolean expression becomes true</option>
<option value="Call">Call — run only when invoked by another script</option>
@if (_kind == ScriptTriggerKind.Unknown)
{
@@ -45,6 +46,9 @@
case ScriptTriggerKind.Conditional:
@RenderConditional();
break;
case ScriptTriggerKind.Expression:
@RenderExpression();
break;
case ScriptTriggerKind.Call:
<div class="small text-muted">
No automatic trigger — this script runs only when another script
@@ -62,7 +66,8 @@
}
@* ── Hint ──────────────────────────────────────────────────────────── *@
@if (_kind is ScriptTriggerKind.Interval or ScriptTriggerKind.ValueChange or ScriptTriggerKind.Conditional)
@if (_kind is ScriptTriggerKind.Interval or ScriptTriggerKind.ValueChange
or ScriptTriggerKind.Conditional or ScriptTriggerKind.Expression)
{
<div class="mt-3 pt-2 border-top small text-muted">@BuildHint()</div>
}
@@ -244,6 +249,30 @@
await Emit();
}
// ── Expression ─────────────────────────────────────────────────────────
private RenderFragment RenderExpression() => __builder =>
{
<label class="form-label small text-uppercase text-muted fw-semibold mb-1">Trigger expression</label>
<MonacoEditor Height="120px"
Language="csharp"
ScriptKind="ScriptAnalysis.ScriptKind.Template"
ShowToolbar="false"
Value="@(_model.Expression ?? string.Empty)"
ValueChanged="OnExpressionChanged"
SelfAttributes="@TriggerAttributeMapper.SelfAttributes(AvailableAttributes)"
Children="@TriggerAttributeMapper.Children(AvailableAttributes)" />
<div class="form-text">
A boolean C# expression — e.g. <code>Attributes["Temperature"] &gt; 80</code>.
</div>
};
private async Task OnExpressionChanged(string value)
{
_model.Expression = value;
await Emit();
}
// ── Attribute picker (ValueChange + Conditional) ───────────────────────
private RenderFragment RenderAttributePicker(string label) => __builder =>
@@ -315,6 +344,9 @@
? $"Runs when {attr} changes, if {attr} {_model.Operator} {t.ToString("0.###", CultureInfo.InvariantCulture)}."
: $"Runs when {attr} changes and meets the configured condition — set a threshold above.",
ScriptTriggerKind.Expression =>
"Runs once each time this expression becomes true.",
_ => string.Empty
};
}