-
Notifications
You must be signed in to change notification settings - Fork 10
fix(web): correct the reported settings, plan, and update screens #1370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "ftw": patch | ||
| --- | ||
|
|
||
| Settings no longer shows a second Easee password, and a newly added device is scrolled into view. Charging without a schedule no longer says the ready time has passed. A site with no devices does not show a legacy plan. The update dialog shows measured bytes, including when the total is unknown, and says when that measurement has stopped. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import assert from "node:assert/strict"; | ||
| import { readFileSync } from "node:fs"; | ||
| import test from "node:test"; | ||
|
|
||
| const source = readFileSync(new URL("./plan.js", import.meta.url), "utf8"); | ||
|
|
||
| test("a site with no devices does not show a legacy plan", () => { | ||
| assert.match(source, /function configuredDeviceCount\(status\)/); | ||
| assert.match(source, /if \(configuredDeviceCount\(state\.status\) === 0\)/); | ||
| assert.match(source, /No devices yet — add a device in Settings, and the plan starts once FTW can see your site\./); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -321,6 +321,14 @@ import { | |
| : 'Mathematical optimizer unavailable. This plan uses the built-in Go fallback.' + reason; | ||
| } | ||
|
|
||
| function configuredDeviceCount(status) { | ||
| const drivers = status && status.drivers; | ||
| if (!drivers) return 0; | ||
| if (Array.isArray(drivers)) return drivers.length; | ||
| if (typeof drivers === 'object') return Object.keys(drivers).length; | ||
| return 0; | ||
|
Comment on lines
+324
to
+329
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On an OCPP-only installation, OCPP telemetry is stored without a AGENTS.md reference: AGENTS.md:L24-L25 Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| function render() { | ||
| const canvas = document.getElementById('plan-chart'); | ||
| if (!canvas) return; | ||
|
|
@@ -345,6 +353,14 @@ import { | |
| const { tMin, tMax } = horizonBounds(state.horizon); | ||
| const xScale = t => pad.l + (t - tMin) / (tMax - tMin) * plotW; | ||
| const plan = state.plan; | ||
| if (configuredDeviceCount(state.status) === 0) { | ||
| ctx.fillStyle = C.dim; | ||
| ctx.font = '14px sans-serif'; | ||
| ctx.fillText('No devices yet. Add one in Settings.', pad.l, pad.t + 28); | ||
| const summary = document.getElementById('plan-summary'); | ||
| if (summary) summary.textContent = 'No devices yet — add a device in Settings, and the plan starts once FTW can see your site.'; | ||
| return; | ||
|
Comment on lines
+356
to
+362
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a hot config reload removes the last driver, this branch updates only the canvas and summary before returning. It skips AGENTS.md reference: AGENTS.md:L22-L23 Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| // Layout: price bars (top) | mode band (thin strip) | power bars (middle) | SoC (bottom) | ||
| const modeBandH = 10; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import assert from "node:assert/strict"; | ||
| import { readFileSync } from "node:fs"; | ||
| import test from "node:test"; | ||
|
|
||
| const source = readFileSync(new URL("./tabs/devices.js", import.meta.url), "utf8"); | ||
|
|
||
| test("a cloud password is not rendered again in Secrets", () => { | ||
| assert.match(source, /querySelector\('\[data-path="drivers\.' \+ dIdx \+ '\.config\.password"\]'\)/); | ||
| assert.match(source, /secrets = secrets\.filter\(function \(k\) \{ return k !== 'password'; \}\)/); | ||
| }); | ||
|
|
||
| test("every add path scrolls the new device into view and focuses a connection field", () => { | ||
| assert.match(source, /data-device-idx="' \+ idx \+ '"/); | ||
| assert.match(source, /function revealAddedDevice\(idx\)/); | ||
| assert.match(source, /card\.scrollIntoView\(\{ block: "center" \}\)/); | ||
| const calls = source.match(/revealAddedDevice\(/g) || []; | ||
| assert.ok(calls.length >= 4, "catalog, mqtt and modbus adds must reveal the new card"); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A supported
POST /api/loadpoints/{id}/targetcan settarget_socandtarget_timewithout creatinglp.schedule. For such an externally supplied one-shot goal,hasScheduleis false, so this new branch preempts the deadline-aware branch and incorrectly says no schedule exists even while Core is planning toward that target. Treat a valid target/deadline as an active goal here, reserving this copy for loadpoints with neither a schedule nor a one-shot target.AGENTS.md reference: AGENTS.md:L28-L30
Useful? React with 👍 / 👎.