fix(dashboard): move basin gauges to trend pages next to basin chart
Some checks failed
CI / lint-and-test (push) Has been cancelled
Some checks failed
CI / lint-and-test (push) Has been cancelled
The tank gauge (basin level) and 270° arc gauge (fill %) now live on the trend pages alongside the basin metrics chart — not on the control page. Each trend page (10 min / 1 hour) gets its own pair of gauges. Layout per trend page Basin group: - Chart (width 8): Basin fill % + Level + Net flow series - Tank gauge (width 2): 0–3 m with color zones at stop/start levels - Arc gauge (width 2): 0–100% fill with red/orange/green zones Deployed via partial (nodes-only) deploy so the basin wasn't reset. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -905,53 +905,15 @@ def build_ui_tab():
|
|||||||
["ui_ps_netflow"],
|
["ui_ps_netflow"],
|
||||||
["ui_ps_timeleft"],
|
["ui_ps_timeleft"],
|
||||||
["ui_ps_qin"],
|
["ui_ps_qin"],
|
||||||
# Trend + gauge outputs
|
# Trend + gauge outputs (short + long page gauges)
|
||||||
["trend_short_basin", "trend_long_basin", "gauge_ps_fill"], # fill % → charts + gauge
|
["trend_short_basin", "trend_long_basin", "gauge_ps_fill", "gauge_ps_fill_long"], # fill %
|
||||||
["trend_short_basin", "trend_long_basin", "gauge_ps_level"], # level → charts + tank gauge
|
["trend_short_basin", "trend_long_basin", "gauge_ps_level", "gauge_ps_level_long"], # level
|
||||||
["trend_short_basin", "trend_long_basin"], # net flow → charts only
|
["trend_short_basin", "trend_long_basin"], # net flow
|
||||||
],
|
],
|
||||||
))
|
))
|
||||||
|
|
||||||
# PS gauges — tank for level, 270° arc for fill %
|
# (Basin gauges live on the trend pages, not the control page —
|
||||||
# Tank gauge: basin level 0 – 3 m with color zones matching
|
# see the trend section below for gauge_ps_level / gauge_ps_fill.)
|
||||||
# startLevel (1.2 m) and stopLevel (0.6 m).
|
|
||||||
nodes.append({
|
|
||||||
"id": "gauge_ps_level", "type": "ui-gauge", "z": TAB_UI,
|
|
||||||
"group": g_ps, "name": "Basin level gauge",
|
|
||||||
"gtype": "gauge-tank", "gstyle": "Rounded",
|
|
||||||
"title": "Basin Level", "units": "m",
|
|
||||||
"prefix": "", "suffix": " m",
|
|
||||||
"min": 0, "max": 3,
|
|
||||||
"segments": [
|
|
||||||
{"color": "#f44336", "from": 0}, # red: below stopLevel
|
|
||||||
{"color": "#ff9800", "from": 0.6}, # orange: between stop and start
|
|
||||||
{"color": "#2196f3", "from": 1.2}, # blue: normal operating range
|
|
||||||
{"color": "#ff9800", "from": 2.5}, # orange: approaching overflow
|
|
||||||
{"color": "#f44336", "from": 2.8}, # red: overflow zone
|
|
||||||
],
|
|
||||||
"width": 3, "height": 5, "order": 1,
|
|
||||||
"icon": "", "sizeGauge": 20, "sizeGap": 2, "sizeSegments": 10,
|
|
||||||
"x": LANE_X[3], "y": y + 160, "wires": [],
|
|
||||||
})
|
|
||||||
# 270° arc: fill percentage 0–100%
|
|
||||||
nodes.append({
|
|
||||||
"id": "gauge_ps_fill", "type": "ui-gauge", "z": TAB_UI,
|
|
||||||
"group": g_ps, "name": "Basin fill gauge",
|
|
||||||
"gtype": "gauge-34", "gstyle": "Rounded",
|
|
||||||
"title": "Fill", "units": "%",
|
|
||||||
"prefix": "", "suffix": "%",
|
|
||||||
"min": 0, "max": 100,
|
|
||||||
"segments": [
|
|
||||||
{"color": "#f44336", "from": 0}, # red: dangerously low
|
|
||||||
{"color": "#ff9800", "from": 10}, # orange: low
|
|
||||||
{"color": "#4caf50", "from": 30}, # green: normal
|
|
||||||
{"color": "#ff9800", "from": 80}, # orange: getting full
|
|
||||||
{"color": "#f44336", "from": 95}, # red: near overflow
|
|
||||||
],
|
|
||||||
"width": 3, "height": 4, "order": 2,
|
|
||||||
"icon": "water_drop", "sizeGauge": 20, "sizeGap": 2, "sizeSegments": 10,
|
|
||||||
"x": LANE_X[4], "y": y + 160, "wires": [],
|
|
||||||
})
|
|
||||||
|
|
||||||
# PS text widgets
|
# PS text widgets
|
||||||
nodes.append(ui_text("ui_ps_direction", TAB_UI, LANE_X[2], y + 160, g_ps,
|
nodes.append(ui_text("ui_ps_direction", TAB_UI, LANE_X[2], y + 160, g_ps,
|
||||||
@@ -1127,25 +1089,66 @@ def build_ui_tab():
|
|||||||
order=1,
|
order=1,
|
||||||
))
|
))
|
||||||
|
|
||||||
# ===== Basin charts (fill %, level, net flow) =====
|
# ===== Basin charts + gauges (fill %, level, net flow) =====
|
||||||
# Short-term
|
# Gauge segment definitions (reused for both pages)
|
||||||
nodes.append(ui_chart(
|
TANK_SEGMENTS = [
|
||||||
"trend_short_basin", TAB_UI, LANE_X[3], y_charts + 360,
|
{"color": "#f44336", "from": 0}, # red: below stopLevel
|
||||||
"ui_grp_trend_short_basin",
|
{"color": "#ff9800", "from": 0.6}, # orange: between stop and start
|
||||||
"Basin — 10 min", "Basin metrics",
|
{"color": "#2196f3", "from": 1.2}, # blue: normal operating
|
||||||
width=12, height=8,
|
{"color": "#ff9800", "from": 2.5}, # orange: approaching overflow
|
||||||
remove_older="10", remove_older_unit="60", remove_older_points="300",
|
{"color": "#f44336", "from": 2.8}, # red: overflow zone
|
||||||
y_axis_label="", order=1,
|
]
|
||||||
))
|
FILL_SEGMENTS = [
|
||||||
# Long-term
|
{"color": "#f44336", "from": 0},
|
||||||
nodes.append(ui_chart(
|
{"color": "#ff9800", "from": 10},
|
||||||
"trend_long_basin", TAB_UI, LANE_X[3], y_charts + 440,
|
{"color": "#4caf50", "from": 30},
|
||||||
"ui_grp_trend_long_basin",
|
{"color": "#ff9800", "from": 80},
|
||||||
"Basin — 1 hour", "Basin metrics",
|
{"color": "#f44336", "from": 95},
|
||||||
width=12, height=8,
|
]
|
||||||
remove_older="60", remove_older_unit="60", remove_older_points="1800",
|
|
||||||
y_axis_label="", order=1,
|
for suffix, grp, remove_older, remove_points, y_off in [
|
||||||
))
|
("short", "ui_grp_trend_short_basin", "10", "300", 360),
|
||||||
|
("long", "ui_grp_trend_long_basin", "60", "1800", 540),
|
||||||
|
]:
|
||||||
|
# Basin trend chart (width 8 to leave room for gauges)
|
||||||
|
nodes.append(ui_chart(
|
||||||
|
f"trend_{suffix}_basin", TAB_UI, LANE_X[3], y_charts + y_off,
|
||||||
|
grp,
|
||||||
|
f"Basin — {'10 min' if suffix == 'short' else '1 hour'}", "Basin metrics",
|
||||||
|
width=8, height=8,
|
||||||
|
remove_older=remove_older, remove_older_unit="60",
|
||||||
|
remove_older_points=remove_points,
|
||||||
|
y_axis_label="", order=1,
|
||||||
|
))
|
||||||
|
# Tank gauge: basin level 0–3 m
|
||||||
|
gauge_id_suffix = "" if suffix == "short" else "_long"
|
||||||
|
nodes.append({
|
||||||
|
"id": f"gauge_ps_level{gauge_id_suffix}", "type": "ui-gauge",
|
||||||
|
"z": TAB_UI, "group": grp,
|
||||||
|
"name": f"Basin level gauge ({suffix})",
|
||||||
|
"gtype": "gauge-tank", "gstyle": "Rounded",
|
||||||
|
"title": "Level", "units": "m",
|
||||||
|
"prefix": "", "suffix": " m",
|
||||||
|
"min": 0, "max": 3,
|
||||||
|
"segments": TANK_SEGMENTS,
|
||||||
|
"width": 2, "height": 5, "order": 2,
|
||||||
|
"icon": "", "sizeGauge": 20, "sizeGap": 2, "sizeSegments": 10,
|
||||||
|
"x": LANE_X[4], "y": y_charts + y_off, "wires": [],
|
||||||
|
})
|
||||||
|
# 270° arc: fill %
|
||||||
|
nodes.append({
|
||||||
|
"id": f"gauge_ps_fill{gauge_id_suffix}", "type": "ui-gauge",
|
||||||
|
"z": TAB_UI, "group": grp,
|
||||||
|
"name": f"Basin fill gauge ({suffix})",
|
||||||
|
"gtype": "gauge-34", "gstyle": "Rounded",
|
||||||
|
"title": "Fill", "units": "%",
|
||||||
|
"prefix": "", "suffix": "%",
|
||||||
|
"min": 0, "max": 100,
|
||||||
|
"segments": FILL_SEGMENTS,
|
||||||
|
"width": 2, "height": 4, "order": 3,
|
||||||
|
"icon": "water_drop", "sizeGauge": 20, "sizeGap": 2, "sizeSegments": 10,
|
||||||
|
"x": LANE_X[5], "y": y_charts + y_off, "wires": [],
|
||||||
|
})
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
|
|||||||
@@ -1890,12 +1890,14 @@
|
|||||||
[
|
[
|
||||||
"trend_short_basin",
|
"trend_short_basin",
|
||||||
"trend_long_basin",
|
"trend_long_basin",
|
||||||
"gauge_ps_fill"
|
"gauge_ps_fill",
|
||||||
|
"gauge_ps_fill_long"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"trend_short_basin",
|
"trend_short_basin",
|
||||||
"trend_long_basin",
|
"trend_long_basin",
|
||||||
"gauge_ps_level"
|
"gauge_ps_level",
|
||||||
|
"gauge_ps_level_long"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"trend_short_basin",
|
"trend_short_basin",
|
||||||
@@ -1903,100 +1905,6 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "gauge_ps_level",
|
|
||||||
"type": "ui-gauge",
|
|
||||||
"z": "tab_ui",
|
|
||||||
"group": "ui_grp_ps",
|
|
||||||
"name": "Basin level gauge",
|
|
||||||
"gtype": "gauge-tank",
|
|
||||||
"gstyle": "Rounded",
|
|
||||||
"title": "Basin Level",
|
|
||||||
"units": "m",
|
|
||||||
"prefix": "",
|
|
||||||
"suffix": " m",
|
|
||||||
"min": 0,
|
|
||||||
"max": 3,
|
|
||||||
"segments": [
|
|
||||||
{
|
|
||||||
"color": "#f44336",
|
|
||||||
"from": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#ff9800",
|
|
||||||
"from": 0.6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#2196f3",
|
|
||||||
"from": 1.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#ff9800",
|
|
||||||
"from": 2.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#f44336",
|
|
||||||
"from": 2.8
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"width": 3,
|
|
||||||
"height": 5,
|
|
||||||
"order": 1,
|
|
||||||
"icon": "",
|
|
||||||
"sizeGauge": 20,
|
|
||||||
"sizeGap": 2,
|
|
||||||
"sizeSegments": 10,
|
|
||||||
"x": 900,
|
|
||||||
"y": 760,
|
|
||||||
"wires": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "gauge_ps_fill",
|
|
||||||
"type": "ui-gauge",
|
|
||||||
"z": "tab_ui",
|
|
||||||
"group": "ui_grp_ps",
|
|
||||||
"name": "Basin fill gauge",
|
|
||||||
"gtype": "gauge-34",
|
|
||||||
"gstyle": "Rounded",
|
|
||||||
"title": "Fill",
|
|
||||||
"units": "%",
|
|
||||||
"prefix": "",
|
|
||||||
"suffix": "%",
|
|
||||||
"min": 0,
|
|
||||||
"max": 100,
|
|
||||||
"segments": [
|
|
||||||
{
|
|
||||||
"color": "#f44336",
|
|
||||||
"from": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#ff9800",
|
|
||||||
"from": 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#4caf50",
|
|
||||||
"from": 30
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#ff9800",
|
|
||||||
"from": 80
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "#f44336",
|
|
||||||
"from": 95
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"width": 3,
|
|
||||||
"height": 4,
|
|
||||||
"order": 2,
|
|
||||||
"icon": "water_drop",
|
|
||||||
"sizeGauge": 20,
|
|
||||||
"sizeGap": 2,
|
|
||||||
"sizeSegments": 10,
|
|
||||||
"x": 1160,
|
|
||||||
"y": 760,
|
|
||||||
"wires": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "ui_ps_direction",
|
"id": "ui_ps_direction",
|
||||||
"type": "ui-text",
|
"type": "ui-text",
|
||||||
@@ -3546,7 +3454,7 @@
|
|||||||
"#e5e5e5"
|
"#e5e5e5"
|
||||||
],
|
],
|
||||||
"gridColorDefault": true,
|
"gridColorDefault": true,
|
||||||
"width": 12,
|
"width": 8,
|
||||||
"height": 8,
|
"height": 8,
|
||||||
"className": "",
|
"className": "",
|
||||||
"x": 900,
|
"x": 900,
|
||||||
@@ -3555,6 +3463,100 @@
|
|||||||
[]
|
[]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "gauge_ps_level",
|
||||||
|
"type": "ui-gauge",
|
||||||
|
"z": "tab_ui",
|
||||||
|
"group": "ui_grp_trend_short_basin",
|
||||||
|
"name": "Basin level gauge (short)",
|
||||||
|
"gtype": "gauge-tank",
|
||||||
|
"gstyle": "Rounded",
|
||||||
|
"title": "Level",
|
||||||
|
"units": "m",
|
||||||
|
"prefix": "",
|
||||||
|
"suffix": " m",
|
||||||
|
"min": 0,
|
||||||
|
"max": 3,
|
||||||
|
"segments": [
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 0.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#2196f3",
|
||||||
|
"from": 1.2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 2.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 2.8
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"width": 2,
|
||||||
|
"height": 5,
|
||||||
|
"order": 2,
|
||||||
|
"icon": "",
|
||||||
|
"sizeGauge": 20,
|
||||||
|
"sizeGap": 2,
|
||||||
|
"sizeSegments": 10,
|
||||||
|
"x": 1160,
|
||||||
|
"y": 2640,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gauge_ps_fill",
|
||||||
|
"type": "ui-gauge",
|
||||||
|
"z": "tab_ui",
|
||||||
|
"group": "ui_grp_trend_short_basin",
|
||||||
|
"name": "Basin fill gauge (short)",
|
||||||
|
"gtype": "gauge-34",
|
||||||
|
"gstyle": "Rounded",
|
||||||
|
"title": "Fill",
|
||||||
|
"units": "%",
|
||||||
|
"prefix": "",
|
||||||
|
"suffix": "%",
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"segments": [
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#4caf50",
|
||||||
|
"from": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 95
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"width": 2,
|
||||||
|
"height": 4,
|
||||||
|
"order": 3,
|
||||||
|
"icon": "water_drop",
|
||||||
|
"sizeGauge": 20,
|
||||||
|
"sizeGap": 2,
|
||||||
|
"sizeSegments": 10,
|
||||||
|
"x": 1420,
|
||||||
|
"y": 2640,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "trend_long_basin",
|
"id": "trend_long_basin",
|
||||||
"type": "ui-chart",
|
"type": "ui-chart",
|
||||||
@@ -3608,15 +3610,109 @@
|
|||||||
"#e5e5e5"
|
"#e5e5e5"
|
||||||
],
|
],
|
||||||
"gridColorDefault": true,
|
"gridColorDefault": true,
|
||||||
"width": 12,
|
"width": 8,
|
||||||
"height": 8,
|
"height": 8,
|
||||||
"className": "",
|
"className": "",
|
||||||
"x": 900,
|
"x": 900,
|
||||||
"y": 2720,
|
"y": 2820,
|
||||||
"wires": [
|
"wires": [
|
||||||
[]
|
[]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "gauge_ps_level_long",
|
||||||
|
"type": "ui-gauge",
|
||||||
|
"z": "tab_ui",
|
||||||
|
"group": "ui_grp_trend_long_basin",
|
||||||
|
"name": "Basin level gauge (long)",
|
||||||
|
"gtype": "gauge-tank",
|
||||||
|
"gstyle": "Rounded",
|
||||||
|
"title": "Level",
|
||||||
|
"units": "m",
|
||||||
|
"prefix": "",
|
||||||
|
"suffix": " m",
|
||||||
|
"min": 0,
|
||||||
|
"max": 3,
|
||||||
|
"segments": [
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 0.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#2196f3",
|
||||||
|
"from": 1.2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 2.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 2.8
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"width": 2,
|
||||||
|
"height": 5,
|
||||||
|
"order": 2,
|
||||||
|
"icon": "",
|
||||||
|
"sizeGauge": 20,
|
||||||
|
"sizeGap": 2,
|
||||||
|
"sizeSegments": 10,
|
||||||
|
"x": 1160,
|
||||||
|
"y": 2820,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gauge_ps_fill_long",
|
||||||
|
"type": "ui-gauge",
|
||||||
|
"z": "tab_ui",
|
||||||
|
"group": "ui_grp_trend_long_basin",
|
||||||
|
"name": "Basin fill gauge (long)",
|
||||||
|
"gtype": "gauge-34",
|
||||||
|
"gstyle": "Rounded",
|
||||||
|
"title": "Fill",
|
||||||
|
"units": "%",
|
||||||
|
"prefix": "",
|
||||||
|
"suffix": "%",
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"segments": [
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#4caf50",
|
||||||
|
"from": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#ff9800",
|
||||||
|
"from": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#f44336",
|
||||||
|
"from": 95
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"width": 2,
|
||||||
|
"height": 4,
|
||||||
|
"order": 3,
|
||||||
|
"icon": "water_drop",
|
||||||
|
"sizeGauge": 20,
|
||||||
|
"sizeGap": 2,
|
||||||
|
"sizeSegments": 10,
|
||||||
|
"x": 1420,
|
||||||
|
"y": 2820,
|
||||||
|
"wires": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "tab_drivers",
|
"id": "tab_drivers",
|
||||||
"type": "tab",
|
"type": "tab",
|
||||||
|
|||||||
Reference in New Issue
Block a user