Feat: automations page improvements - #2554
BelhsanHmida wants to merge 25 commits into
Conversation
…me on hover Context: - Review of #2294: the next run time can be displayed in more human form, like "in 6 minutes", "in 4 hours" or "tomorrow", as other pages already do. The precise date and time is still needed, but belongs on hover. Change: - Render the next run with getHumanFriendlyDeltaOrTimeStr, the helper the Created At column and the status and user pages already use. - Move the precise time to the tooltip, on the automation's own clock, next to the timezone and the cron recurrence that produced it. - Phrase future moments as "in 6 minutes" rather than "6 minutes from now", matching how the same helper already phrases "tomorrow" and "in 4 days". Every other caller renders a past moment, so only this column changes wording. - Give the helper an options.fallback, and pass the schedule-clock time: beyond a week there is no useful relative phrasing left, and the old fallback dated the run by the viewer's clock rather than by the clock the automation keeps. - Drop "(local)" from the column heading, which no longer describes what the cell shows. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The Created At cell showed a friendly delta, but hovering it produced the raw stored timestamp in UTC, which is neither precise-looking nor the clock the rest of the row keeps. Change: - Spell the creation moment out in the automation's timezone on hover, as the next run already does, so a row mixes no clocks. - Fall back to the same schedule-clock wording once the automation is older than a week, rather than dating it by the viewer's own timezone. - Keep the stored timestamp as the tooltip when the timezone cannot be resolved. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - "Details" reads like a second Actions menu next to it, while the button only ever opens a read-only panel about one automation. Change: - Label the button Info, and rename the class, modal ids, row key and loader that name it, so the code reads the same as the page. - Note that DataTables' own info option is its record count, not this column. - Say "Could not load this automation's info" when that panel fails, matching the button. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The automation endpoint named the data source but said nothing about how its data generator was set up, so the forecaster's model, training period and regressors were invisible to anyone reading an automation. Change: - Include the data generator's stored config with the source it belongs to. The config is what separates one data source from another of the same model, so it is reported alongside the source rather than as a field of its own. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The Info panel named the data source but not the settings it was created with, so a reader could not tell which model an automation forecasts with, or over what training period. Change: - Read the configuration under the data source it describes, since it is what separates this source from another one of the same model. - Say so plainly when a source records no configuration, rather than showing an empty block. - Rename the heading from "Data generator" to "Data source", the term the rest of the panel uses. - Left-align preformatted blocks, which the centred modal text left hanging in mid-air. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - Automations are usually defined on a sub-asset, so a site asset's automations endpoint reported nothing, even while plenty ran below it. - The status page already solved the same problem for jobs, in #2500. Change: - Include the automations of the asset's descendants by default, and let include_child_assets=false narrow the listing to the asset itself, as [GET] /assets/(id)/jobs does. Whoever may read an asset may read its descendants, too, as a child asset belongs to the same account. - Name the owning asset in each entry, so a listing spanning several assets stays readable. - Add an endpoint that remembers the user's choice of scope in their session, next to the one the status page uses for its own toggle. - Regenerate the OpenAPI spec. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - Automations tend to be defined on a sub-asset, so the page of a site asset looked empty even while plenty ran beneath it, and there was nowhere to see it all at once. Change: - List the automations of sub-assets by default, and name the owning asset in a column that links to its own automations page. The column appears only while the listing spans more than one asset. - Offer the scope as a switch, but only on an asset that has children, and remember the choice for the next visit. This mirrors the status page's "Include jobs of sub-assets". - Address every per-automation request at the asset that owns the automation, not at the page's asset. Info, Run now, Edit, the activation toggle and Delete all answered 404 on a sub-asset's automation otherwise, since those endpoints check that the automation belongs to the asset named. - Rebuild rather than redraw the table when the scope changes, as the columns change with it, and order by where Created At actually sits, now that a column can precede it. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - Runs happen, and jobs change state, while the page sits open. Until now the only way to see any of it was to reload by hand, and nothing on screen said how old it was. Change: - Fetch the listing again about once a minute, and put the fresh rows into the tables that already stand, so the sort the user chose and the place they scrolled to both survive. - Hold off while the tab is in the background, and catch up as soon as it comes back. - Hold off while a panel or menu is open, so a refresh never shuts something being read, and never let two refreshes overlap. - Say when the listing last came from the server, re-wording that stamp between refreshes, since "2 minutes ago" goes stale with no new data. - A refresh costs the same requests a manual reload always has, one per automation for the job counts. A bulk endpoint for those counts would be the way to cut it, if a large asset ever makes it felt. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The automations endpoint learned to report what runs below an asset, and to describe the data source's configuration, and the automations page learned to remember its scope. Change: - Check that a sub-asset's automation is listed and names its own asset, that include_child_assets=false narrows the listing back to the asset itself, and that the data source reports the configuration it was created with. - Check that posting the page's scope records it in the session, next to the same test for the status page's job scope. - Each was confirmed to fail with the behaviour it covers removed. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
… a row is Context: - The next run is now phrased as a delta with the clock time on hover, Created At is read on the automation's own clock, and a row can belong to a sub-asset. Change: - Exercise the page's row builder against the real shared time helper, loaded the way the page loads it, rather than against a stand-in that could drift from it. - Check the six-minute case the review asked for, the hover that carries the precise time, timezone and recurrence, the fallback to the schedule's clock beyond a week, and that sorting still runs on the moment rather than on the words. - Check that Created At is read on the automation's timezone, using a moment that falls on a different date there than in UTC. - Check that a row names and links the asset its automation is defined on. - Fail the script helper loudly on an unrendered Jinja value: the two added for the scope reached the browser as a syntax error, which reads as every check failing at once. - Each was confirmed to fail with the behaviour it covers removed. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The page reaches below the asset, tells the time in relative terms, keeps itself current, and reports the data source's configuration. Change: - Describe the sub-asset scope and the query parameter that narrows it. - Describe the relative next run, what hovering gives, and the clock both time columns read on. - Mention that the page refreshes itself, and when it holds off. - Rename "details" to the Info panel, and say it carries the data source's configuration. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The page follows up on #2294 with relative run times, a scope reaching below the asset, a self-refreshing listing, and a renamed Info panel that carries the data source's config. Change: - Add a bullet to the automations detail list in the main changelog, beside the #2294 entry. - Open v3.0-38 in the API change log, for the new query parameter, the config on an automation's source, and the endpoint that remembers the page's scope. - The PR number is not known yet, so the main changelog entry links to PR #XXXX. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - test_asset_page pins the page's rendered script, and still expected the "Next run (local)" column heading and the precise time in the cell. Change: - Expect the renamed column, and the delta the cell now renders. - Also pin the scope parameter, the refresh timer, the Info button and the data source's configuration, so this test keeps covering what the page grew. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
…he cursor UTC Context: - Every automation's modal is part of its row, so it sits inside the centred Info cell and inherited that centring: headings, values and JSON all sat in the middle of a wide panel. Left-aligning only the preformatted blocks had made the mismatch plainer, not better. - The panel still labelled the cursor UTC, though #2294 began rendering it in the automation's own timezone. The value on screen read "+02:00" under a heading saying UTC. Change: - Left-align the panel, and set each heading as a small caption above the value it labels. - Give preformatted blocks a quiet background and a height to scroll within, so a long forecaster config no longer pushes the sensors and parameters out of view. - Drop "(UTC)" from the cursor heading, and say on hover which clock it is read on. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The panel labelled the cursor UTC while rendering it in the automation's own timezone, and this test pinned the wrong label. Change: - Expect the heading without "(UTC)", and guard against the old label coming back. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
…created Context: - The API and `flexmeasures add automation` both accept a forecaster `config` and a `data-generator`, but the New automation form sent neither, so a forecast automation made in the UI always got the default forecaster: CustomLGBM over P30D, with no regressors. - The Info panel now shows that configuration, which made the gap plainer: you could read a training period you had no way to set. Change: - Offer a Data generator field and a Configuration (JSON) field, and send each only when filled, so leaving them empty still means the API's own defaults. - Show both only for a forecast automation: a schedule automation's generator follows from the asset and its flex config rather than being chosen. - Say in the field's help that these settings decide which data source the results record under, and that they cannot be changed afterwards. - Report malformed JSON with the field's name and the parser's message, for the configuration as well as the parameters, rather than the bare "not valid JSON" the parameters gave. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The form now offers a data generator and a forecaster configuration, for forecast automations only. Change: - Pin the fields, the payload lines that send them, and the toggle that hides them for a schedule automation. Pinning only the parsing passed with the sending removed, so the assertions name the payload. - Confirmed to fail with the configuration left out of the request. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Documentation build overview
24 files changed ·
|
Context: - Eight commits landed on main since this branch was cut, several of them on the very page and endpoints it changes. Change: - Take main's rename of the Recurrence timezone column, and this branch's renamed Next run. - Keep the extracted column list, which the scope needs, rather than main's inline one. - Keep loadAutomations over main's inline fetch, and pull the type list into AUTOMATION_TYPES, so that reporting, which #2297 added, is listed on both the success and the error path. Two separate literals is how it came to be missing from one of them. - Keep one set of the data generator and configuration fields. Main added its own while this branch added a second, and neither conflicted textually, so the merge had kept both: duplicate element ids, and duplicate keys in the create request. - Offer those fields for reporting as well as forecasting, since a report automation also runs a generator the creator configures; only a schedule automation derives its own. - Read the request's generator from the gated value, so a schedule automation no longer sends whatever a hidden field was left holding by an earlier choice of type. - Keep both sides' changelog entries, and main's console.error on a failed listing. The branch's own diff against main is unchanged but for those resolutions: the same eleven files, with asset_automations.html and test_asset_crud.py accounting for the rest. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context: - The entry was written before the pull request existed, so it linked to a placeholder, and it predated the configuration fields on the New automation form. Change: - Link to PR #2554. - Say that a new forecast or report automation can be given its generator's configuration from the form, not only through the API and the CLI. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Flix6x
left a comment
There was a problem hiding this comment.
I'll do a pass at this with Claude now.
| """""""""""""""""""""""""""" | ||
| - ``GET /api/v3_0/assets/<id>/automations`` now lists the automations of the asset's child assets as well, so that a site asset reports everything that runs below it, and each entry names the asset it is defined on in ``asset`` and ``asset-name``. Pass ``include_child_assets=false`` to list only the automations defined on the asset itself. Whoever may read an asset may read its descendants, too, as a child asset belongs to the same account as its parent. | ||
| - ``GET /api/v3_0/assets/<id>/automations/<automation_id>`` now reports the data generator's stored configuration as ``config`` on the automation's ``source``, such as the model a forecaster trains and the period it trains over. The configuration is what separates one data source from another of the same model. | ||
| - Added ``POST /api/v3_0/assets/automations_page_child_assets``, which records in the session whether the automations page should list the automations of child assets, next to the endpoint the status page uses for its own job scope. |
There was a problem hiding this comment.
I don't think these API endpoints should be part of the public v3 API. I feel it just clutters up our Swagger docs.
I suggest moving it to an API blueprint dedicated to internal FM UI support. This API changelog might need to get a dedicated section for this new blueprint (I suggest the bottom of the page) with a disclaimer that these endpoints are not part of the official API and can have (externally) breaking changes with any FM version.
Two more such endpoint are /api/v3_0/assets/keep_legends_below_graphs and /api/v3_0/assets/default_asset_view and I suggest moving those to this blueprint, too.
next to the endpoint the status page uses for its own job scope.
I didn't understand the comment.
There was a problem hiding this comment.
Moved, together with the two you named and the status page's two, since all five do the same job: storing a choice made in the UI in the user's session. They're now a SessionAPI view in the dev blueprint, under /api/dev/session/..., as in your second comment. That blueprint's endpoints were already outside the Swagger docs and outside the official API. Their paths and fields are kebab-case now, since their URLs change anyway. The API changelog has a section at the bottom listing them, with the disclaimer. 26b630c, f5cd73b
About "next to the endpoint the status page uses for its own job scope": that meant status_page_child_jobs, which stores the status page's own Include jobs of sub-assets switch. The sentence is gone.
There was a problem hiding this comment.
A clarification on "That blueprint's endpoints were already outside the Swagger docs": the generator doesn't exclude them by blueprint. It adds a path entry to openapi-specs.json for every route under /api/, /api/dev/... included. The dev endpoints' docstrings have no OpenAPI section, though, so those entries are empty ({}), and Swagger UI renders no operations for them.
So the session endpoints stay out of the rendered Swagger docs because their docstrings don't describe them in OpenAPI, not because of their /api/dev prefix. A future OpenAPI docstring would bring them back, wherever they live. In Sphinx, dev.rst documents only the modules it names, and the new session module isn't among them.
| The page shows the next scheduled run for each automation (excluding any pending catch-up run). | ||
| An automation's details show the sensors it reads from and writes to, linking to each sensor's page. | ||
| Automations are usually defined on a sub-asset, so the page lists what runs anywhere below the asset as well, naming the asset each automation belongs to. | ||
| Turn *Include automations of sub-assets* off to see only the automations defined on the asset itself; the choice is remembered for your next visit. |
There was a problem hiding this comment.
Continuing my thoughts on grouping these UI settings under a dedicated API blueprint:
- The two previously existing endpoints (
default_asset_viewandkeep_legends_below) mention they are changing a preference for the current user. So far it hasn't been stated explicitly whether that's also true for this endpoint. "the choice is remembered for your next visit" fulfills that role here. - Alternative to a new blueprint, repurpose the dev blueprint as a UI blueprint. It contains chart endpoints under the
class SensorAPI(FlaskView). There, we could add a newFlaskViewsubclass for endpoints that set session variables (note this in its docstring).
There was a problem hiding this comment.
I went with repurposing the dev blueprint: a SessionAPI(FlaskView) next to the chart endpoints. Its docstring says these endpoints store the current user's choices in their session, and that they aren't part of the official API. The blueprint's module docstring now says it covers UI support as well as endpoints under development. 26b630c
…er may read The automations listing, and the jobs listing it followed (#2500), included every asset below the requested one, on the grounds that whoever may read an asset may read what is below it, as a child asset belongs to the same account as its parent. That does not hold: a child asset can belong to another account, so one organisation could list the automations and jobs on another's assets simply by holding a parent above them. Each asset below is now checked for read access on its own (get_readable_offspring). The test calling build_asset_jobs_data directly now does so as the user who owns the assets, as an anonymous caller may read none of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129WrXeJ5gia2pctFH93BqC Signed-off-by: F.N. Claessen <claessen@seita.nl>
The endpoints that store a user's choices in the FlexMeasures UI in their session are not API a client should build on, and filled the Swagger docs. All five move to a SessionAPI view in the dev blueprint, whose endpoints are not part of the official API either: /api/v3_0/assets/default_asset_view -> /api/dev/session/default-asset-view /api/v3_0/assets/keep_legends_below_graphs -> /api/dev/session/keep-legends-below-graphs /api/v3_0/assets/status_page_tab -> /api/dev/session/status-page-tab /api/v3_0/assets/status_page_child_jobs -> /api/dev/session/status-page-child-jobs /api/v3_0/assets/automations_page_child_assets -> /api/dev/session/automations-page-child-assets As their URLs change anyway, their paths and fields are kebab-case, and so is the include-child-assets query parameter of the automations and jobs listings. include-child-assets is no longer required by the two page endpoints, and defaults to false, as listing the assets below as well asks more of the server. They store what they are sent in the session directly, rather than copying it into request.values for set_session_variables, and their 400 responses, which the schemas' 422s made unreachable, are gone with their Swagger docs. The session keys the templates read are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129WrXeJ5gia2pctFH93BqC Signed-off-by: F.N. Claessen <claessen@seita.nl>
… and trim the changelog entry The API changelog's entry for v3.0-38 names include-child-assets, covers the jobs listing too, and says only readable assets below are included, where it claimed readers of an asset may read what is below it. The page endpoint no longer appears there: a section at the bottom lists the endpoints supporting the FlexMeasures UI, with a note that they are not part of the official API and may change in any version. The automations docs say the page refreshes once a minute, which it does, and the main changelog entry keeps to what changed for users. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129WrXeJ5gia2pctFH93BqC Signed-off-by: F.N. Claessen <claessen@seita.nl>
|
What is the reason to move endpoints to the dev API? They have been in production, so at least the naming is confusing. |
…ssets below Listing the assets below as well asks more of the server, so the automations and jobs listings, and the automations and status pages, now list only what belongs to the asset itself by default. The API takes include-child-assets=true, and each page's switch stores the choice in the session as before, now starting off. build_asset_jobs_data defaults to leaving the assets below out, too. The docs, the API changelog and the changelog entries for this PR and for #2500, which introduced the status page's switch, say so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129WrXeJ5gia2pctFH93BqC Signed-off-by: F.N. Claessen <claessen@seita.nl>
See these comment threads for how I derived there:
I see your point about not moving endpoints from a production blueprint to a dev blueprint. A related discrepancy is with the existing chart-support endpoints in that dev blueprint: at some point they were published under the v3 documentation. I don't have a complete picture of the end state and transition I have in mind yet, but I suggest for now at least:
Alternatively, I can imagine we move/keep everything to/in v3 and just make the decision to exclude all session-variable-setting endpoints from Sphinx and Swagger. I'll consider these options now, and feel free to weigh in. Footnotes
|
This reverts 095f631, which had the automations and jobs listings, and the automations and status pages, leave the assets below out unless asked. #2447 asked for a site asset to show what happened anywhere below it by default, as it is often unclear at which level a schedule was triggered, so the listings and both pages include the assets below again, with include-child-assets=false or the page's switch to narrow them down. The session endpoints that store a page's switch now also treat a missing include-child-assets as true, in line with the pages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129WrXeJ5gia2pctFH93BqC Signed-off-by: F.N. Claessen <claessen@seita.nl>
|
Opinion from Claude (the coding assistant Felix works with on this PR), posted at Felix's request. On where the session-preference endpoints should live, following up on @nhoening's question and @Flix6x's options. First, three facts that shape the choice:
How I'd weigh the options:
So I'd go with option 3, with aliases for one release if we want zero risk for anyone calling the old URLs. Separately: following #2447, both listings and both pages include the assets below by default again (7a3fe4e). |
|
From Claude (the coding assistant Felix works with on this PR), posted at Felix's request, to untangle a mix-up in Felix's earlier comment and correct it where needed. There are two sets of chart routes, with the same three names:
They are separate endpoints with separate implementations. No dev endpoint shares an endpoint name with a v3 one, so the Swagger generator doesn't mix them up either. The chart endpoints Swagger shows are all the v3_0 asset routes. With identical names, and with Corrections to Felix's comment above:
Are
So they belong with the session endpoints in a UI-support blueprint. The one judgement call left is the three sensor chart routes: their asset counterparts are public v3 API, so they could instead be promoted to v3 for symmetry. Until someone asks for that, grouping them with the other UI support seems right to me. A small aside: |
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129WrXeJ5gia2pctFH93BqC Signed-off-by: F.N. Claessen <claessen@seita.nl>
…t fault Context: - PR #2563 changes which key an automation's validation errors are reported under, which an API client reads. Change: - Added an entry to the "Automations, in detail" section of the main changelog, rather than to Bugfixes, since automations have not shipped in a release yet. - Added a v3.0-39 section to the API change log, saying explicitly that this is not a breaking change, as the automation endpoints are not part of a release. - Numbered v3.0-39 against PR #2554's v3.0-38, which merges first. Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Description
in 6 minutes,in 4 hours,tomorrow), with the exact clock time, its timezone and its recurrence on hover — addressing the review comment on CRUD for automations in the API and UI #2294.in 6 minutesrather than6 minutes from now, matching how the shared helper already phrasestomorrowandin 4 days. Every other caller renders a past moment, so only this column changes wording.Created Aton the automation's own clock too, so a row mixes no timezones.include-child-assets=falseon[GET] /assets/(id)/automations, and on[GET] /assets/(id)/jobslikewise, to list only what belongs to the asset itself./api/dev/session/..., with kebab-case paths and fields. That includes the two that already existed (default_asset_view,keep_legends_below_graphs) and the status page's two.Detailsbutton toInfo, and lay its panel out left-aligned with a scrolling configuration block.configon the automation'ssource, and show it in the Info panel under the data source it describes.(UTC)from the Info panel's cursor heading, which CRUD for automations in the API and UI #2294 began rendering in the automation's own timezone.documentation/changelog.rstLook & Feel
The listing, reaching below the asset
toy-buildinghas no automations of its own; all seven belong totoy-solarbelow it. TheAssetcolumn links to each owning asset,Next runsays how far off each run is, andUpdated just nowsays how current the listing is.The same page, narrowed to the asset itself
The switch is remembered for the next visit, and the
Assetcolumn goes away with it.Hovering a
Next runorCreated Atcell gives the precise moment on the automation's own clock, together with the recurrence that produced it:The Info panel, with the data source's configuration
The configuration sits under the data source it describes, because it is what separates this source from another of the same model. This automation forecasts with a future regressor on day-ahead prices and a past regressor on the battery, so it records under a data source of its own, and
Reads fromlists both regressors.Creating a forecast automation with a configuration
The same form, for a schedule automation
A schedule automation's generator follows from the asset and its flex config, so it is not offered one.
The row's Actions menu
A read-only viewer, on an unowned asset
No Actions menu and no
New automationbutton, but the Info panel still opens.How to test
uv run pytest flexmeasures/ui/tests/ flexmeasures/api/v3_0/tests/Results:
flexmeasures/ui/tests/146 passed,flexmeasures/api/v3_0/tests/514 passed.New tests:
flexmeasures/api/v3_0/tests/test_automations_api.py— a sub-asset's automation is listed and names its asset,include_child_assets=falsenarrows the listing, and the data source reports the configuration it was created with.flexmeasures/api/v3_0/tests/test_assets_api.py— posting the page's scope records it in the session, next to the same test for the status page's job scope.flexmeasures/ui/tests/js/test_automation_actions.py— the page's row builder, run against the real shared time helper: the six-minute case, the tooltip, the fallback beyond a week, that sorting still runs on the moment rather than on the words, theCreated Atclock, and the Asset cell.flexmeasures/ui/tests/test_asset_crud.py— the rendered page's columns, scope parameter, refresh timer, Info button and configuration fields.Each new test was confirmed to fail with the behaviour it covers removed.
Manual verification used a local instance whose
toy-building→toy-solartree carries automations across Europe/Amsterdam, UTC, Asia/Seoul and Pacific/Auckland, including DST gap and fold cases:Further Improvements
parametersfrozen. A Duplicate with changes action would serve the same need without any of that.Related Items
Follows up on #2294.
Sign-off