Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/agents/ui-specialist.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ When a feature is unavailable due to insufficient data (not insufficient permiss
### Jinja2 Template Safety

- [ ] Sensor/asset IDs embedded in JS use `{{ sensor.id }}` (integer, safe), not `.name` or freeform text
- [ ] User-supplied values displayed in HTML use `{{ value | e }}` or `{{ value | safe }}` (only for pre-sanitised server values like `sensor._ui_unit | safe`)
- [ ] `availableUnitsRawJSON.replace(/'/g,
'"')` pattern is used for JSON embedded via template — this is the established workaround for Flask's single-quote JSON serialisation
- [ ] User-supplied values displayed in HTML rely on Jinja's auto-escaping (`{{ value }}`), never `{{ value | safe }}`
- [ ] Data embedded in a `<script>` uses `{{ value | tojson }}`, which yields valid JavaScript and cannot close the script element;
never a Python dict or list rendered with `| safe`, nor either of those inside a JavaScript string literal
- [ ] JavaScript sets user-supplied text with `textContent`, or passes it through `escapeHtml` (from `ui-utils.js`) when building markup for `innerHTML`

## Domain Knowledge

Expand Down
6 changes: 4 additions & 2 deletions .github/instructions/ui-terminology.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ Never expose internal role names (e.g. `account-admin`, `admin`) in UI text. Use
## Jinja2 template safety

- Sensor/asset IDs embedded in JavaScript use `{{ sensor.id }}` (integer — safe), not `.name` or freeform text.
- User-supplied values displayed in HTML use `{{ value | e }}` for auto-escaping.
- Only use `{{ value | safe }}` for pre-sanitised server values (e.g. `sensor._ui_unit | safe`).
- User-supplied values displayed in HTML rely on Jinja's auto-escaping (`{{ value }}`); do not mark them `| safe`.
- Data embedded in a `<script>` uses `{{ value | tojson }}`, which yields valid JavaScript and cannot close the script element.
Never render a Python dict or list with `| safe` there, nor place either inside a JavaScript string literal.
- In JavaScript, set user-supplied text with `textContent`, or pass it through `escapeHtml` (from `ui-utils.js`) when building markup for `innerHTML`.

## Toast vs. inline alert

Expand Down
2 changes: 2 additions & 0 deletions documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Infrastructure / Support
* Speed up ``GET /api/v3_0/assets`` on large catalogs by eager-loading the ``owner``, ``generic_asset_type`` and ``child_assets`` relations alongside the already eager-loaded ``sensors``, instead of lazy-loading each of them once per asset, which made the SQL statement count grow linearly with the number of assets returned [see `PR #2515 <https://www.github.com/FlexMeasures/flexmeasures/pull/2515>`_]
* Speed up app boot by ~1s by dropping the ``inflect`` dependency in favor of the already-used, much lighter ``inflection`` package; API error messages that list several values, such as the permissions a request requires or the units a quantity accepts, no longer place a comma before the final "and" or "or" [see `PR #2514 <https://www.github.com/FlexMeasures/flexmeasures/pull/2514>`_]
* The UI's JavaScript modules can now be tested, by running them in a headless browser from pytest, without adding a Node.js toolchain [see `PR #2435 <https://www.github.com/FlexMeasures/flexmeasures/pull/2435>`_]
* Test much more of the UI's JavaScript, and move the asset tree's layout and the flex-context editor's logic out of their templates into modules, so that they can be tested too [see `PR #2574 <https://www.github.com/FlexMeasures/flexmeasures/pull/2574>`_]
* Add ``FLEXMEASURES_DEPRECATION_AND_SUNSET`` so hosts can configure deprecation and sunset dates and information links per deprecated API version [see `PR #2362 <https://github.com/FlexMeasures/flexmeasures/pull/2362>`_].
* A CLI command that is called with an invalid option value now logs one error line, so that a cron job which captures only the log file still records why the command failed, where previously Click reported it on stderr alone and nothing was written [see `PR #2544 <https://www.github.com/FlexMeasures/flexmeasures/pull/2544>`_]
* Settings that a plugin declares in its ``__settings__`` can now be set as environment variables, next to being set in the config file (which still wins), can declare a ``default`` to fall back to, and are reported as missing with a message that says whether such a default applies or the setting stays unset [see `PR #2501 <https://www.github.com/FlexMeasures/flexmeasures/pull/2501>`_]
Expand All @@ -68,6 +69,7 @@ Bugfixes
* An asset's status page showed only some of the sensors it reported on, in an order that changed between reloads, and it reported on fixed quantities from the flex-context, which have no data to be up to date with [see `PR #2489 <https://www.github.com/FlexMeasures/flexmeasures/pull/2489>`_]
* Saving an asset chart as PNG or SVG drew the legend over the graph whenever it listed more sensors than fit beside a subplot; the exported image now makes room for every entry beside its own plot, without shrinking the plot, and spells out the sensor names that the on-screen legend abbreviates [see `PR #2517 <https://www.github.com/FlexMeasures/flexmeasures/pull/2517>`_]
* Asset type groups were named by a pluralization that mangled acronyms and nouns ending in -y, so the asset pages listed ``PVS``, ``EVS``, ``CHPS`` and ``Factorys``; they now read ``PVs``, ``EVs``, ``CHPs`` and ``Factories`` [see `PR #2514 <https://www.github.com/FlexMeasures/flexmeasures/pull/2514>`_]
* A new commitment's prices now default to the currency of the price sensors in the flex-context, where they fell back to EUR unless a fixed price was set [see `PR #2574 <https://www.github.com/FlexMeasures/flexmeasures/pull/2574>`_]

Automations, in detail
-----------------------
Expand Down
7 changes: 0 additions & 7 deletions flexmeasures/data/models/time_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,13 +632,6 @@ def timerange(self) -> dict[str, datetime_type]:
start, end = get_timerange([self.id])
return dict(start=start, end=end)

@property
def _ui_unit(self) -> str:
"""Used to customize how the sensor unit is shown in the UI."""
if self.unit == "":
return '<span title="A sensor recording numbers rather than physical or economical quantities.">dimensionless</span>'
return self.unit

def __repr__(self) -> str:
return f"<Sensor {self.id}: {self.name}, unit: {self.unit if self.unit != '' else 'dimensionless'} res.: {self.event_resolution}>"

Expand Down
Loading
Loading