diff --git a/documentation/changelog.rst b/documentation/changelog.rst index 52f458f078..4468260115 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -43,6 +43,7 @@ Infrastructure / Support * The UI can work without internet access: the Docker image serves the UI's JavaScript and CSS libraries itself, and a pip-installed FlexMeasures can fetch them once (see :ref:`install-ui-libraries`), while otherwise browsers keep loading them from CDNs; the ``FLEXMEASURES_JS_VERSIONS`` setting now only lists the versions a host wants to differ, optionally with the hashes of their files, so plugins reading it should read the ``js_versions`` template variable instead [see `PR #2711 `_] * ``add_beliefs_to_db_and_enqueue_forecasting_jobs`` now raises ``BeliefReplacementNotAllowed`` rather than an ``IntegrityError`` when saving would change existing values, so plugins catching ``IntegrityError`` around it should catch the new exception instead [see `PR #2722 `_] * ``[GET] /sensors/(id)`` now answers a sensor which does not exist with a 404, as the asset endpoints do, rather than with a 422, so that a client can tell a sensor which is gone apart from a request it got wrong [see `PR #2650 `_] +* Upgrade DataTables, which draws the UI's lists, from 1.10.22 to 1.13.11, its latest 1.x release [see `PR #2744 `_] * Speed up preparing a storage schedule by validating each device's constraints with vectorised comparisons instead of one ``DataFrame.eval`` per check (from ~25 ms to ~3 ms per device); the helpers ``validate_constraint`` and ``sanitize_expression`` in ``flexmeasures.data.models.planning.storage``, which nothing in FlexMeasures called any more, are removed, with ``validate_constraints`` replacing them [see `PR #2641 `_] * Rate-limit simplification: Triggers for schedules and forecasts are now always counted per organisation, against one budget that all of its users and assets share, so plans no longer choose what triggers are counted against, and the ``FLEXMEASURES_API_RATE_LIMIT_KEY`` setting is deprecated and ignored. Hosts who set it (or a plan's rate-limit key) to ``account+asset`` or ``user`` may want to raise the trigger rate limit of the affected plans, or ``FLEXMEASURES_API_TRIGGER_RATE_LIMIT``, before upgrading [see `PR #2679 `_] * Rate-limit simplification: The API's default rate limit is now counted per organisation rather than per user, so that all users and API clients of an organisation share the one budget its plan sets; it stays at 500 requests per minute, which hosts whose organisations run several integrations may want to raise on those organisations' plans (``default_rate_limit``) or server-wide (``FLEXMEASURES_API_DEFAULT_RATE_LIMIT``) before upgrading [see `PR #2677 `_] diff --git a/flexmeasures/ui/static/css/flexmeasures.css b/flexmeasures/ui/static/css/flexmeasures.css index 41b3d86404..901f7edda7 100644 --- a/flexmeasures/ui/static/css/flexmeasures.css +++ b/flexmeasures/ui/static/css/flexmeasures.css @@ -828,11 +828,35 @@ div.dataTables_paginate { vertical-align: middle; } +/* DataTables draws its sorting arrows as faint glyphs on the right of the header. + Draw them as we did with its earlier icons: light grey, with only the active arrow coloured, + and on the left, in the header's padding, when the header is not right-aligned. + The :not(.sorting_disabled) makes these rules more specific than DataTables' own, whose stylesheet loads after this one. */ + +table.dataTable thead > tr > th.sorting:not(.sorting_disabled):before, +table.dataTable thead > tr > th.sorting:not(.sorting_disabled):after { + color: #dcdcdc; + opacity: 1; +} +table.dataTable thead > tr > th.sorting_asc:not(.sorting_disabled):before, +table.dataTable thead > tr > th.sorting_desc:not(.sorting_disabled):after { + color: #7a80dd; +} +table.dataTable thead > tr > th.sorting_asc:not(.sorting_disabled):after, +table.dataTable thead > tr > th.sorting_desc:not(.sorting_disabled):before { + opacity: 0; +} +table.dataTable thead > tr > th:not(.text-right).sorting:before, +table.dataTable thead > tr > th:not(.text-right).sorting:after { + left: 3px; + right: auto; +} table.dataTable thead tr th.no-sort { padding: 9px; } +/* !important, as DataTables' own border rule is as specific as this one, and its stylesheet loads after this one */ table.dataTable thead tr th { - border-bottom: inherit; + border-bottom: inherit !important; } table.dataTable.no-footer { border-bottom: inherit !important; diff --git a/flexmeasures/ui/templates/includes/vendor.html b/flexmeasures/ui/templates/includes/vendor.html index 1db92cd673..14e2565fef 100644 --- a/flexmeasures/ui/templates/includes/vendor.html +++ b/flexmeasures/ui/templates/includes/vendor.html @@ -13,7 +13,7 @@ - {#- These rules refer to vendored fonts and images, so they live here rather than in flexmeasures.css, which cannot tell whether those were fetched. -#} + {#- These rules refer to vendored fonts, so they live here rather than in flexmeasures.css, which cannot tell whether those were fetched. -#} {% endmacro %} diff --git a/flexmeasures/ui/utils/vendor_assets.py b/flexmeasures/ui/utils/vendor_assets.py index 096ab0d4f7..fbe6398307 100644 --- a/flexmeasures/ui/utils/vendor_assets.py +++ b/flexmeasures/ui/utils/vendor_assets.py @@ -222,28 +222,23 @@ def license_path(self) -> str: ), "datatables": VendorLibrary( name="DataTables", - version="1.10.22", + version="1.13.11", base_url="https://cdn.datatables.net/{version}/", files={ - "js/jquery.dataTables.min.js": "c91c904fbfbe1fcb61c4e4cb955b35e8eb303f29d97a9f757c744fc6603a978a", - "css/jquery.dataTables.min.css": "ca31d3aa2364f2a372c1d9ed477be2b71852e7d3a98bb92476c19efe67024a48", - "images/sort_asc.png": "595704c3f3cf4cb65c7d9c8508a99e7480e150095473faed31a07c21b13389b8", - "images/sort_asc_disabled.png": "a65b8f4f84d6427a81c360282fc5394d51bf99dada5f159e6aa0fce3c396825c", - "images/sort_both.png": "3e016c23ae51417382b640ae2d19eb48047532c37ad53894bd185586559ccffb", - "images/sort_desc.png": "d08ed0e21f187dd309030d465224da8085119a15a17d616ba0e477bb50c6f10d", - "images/sort_desc_disabled.png": "6c0f0c1b21ef6807057afc8ddc1a925d1dbd21cb11e9270ec84ff4ac40d9a3fa", + "js/jquery.dataTables.min.js": "a33146fad8c7228dc4dc90043e3e50d51cead8b2267aeac32b0a8f3be8a52b86", + "css/jquery.dataTables.min.css": "b113506cbced802d49dd3f2fdec2d9de60c9cbfe53ab13b87337e34ef10200eb", }, - license="https://cdn.jsdelivr.net/npm/datatables.net@1.10.22/License.txt", - license_sha256="4f6610cece9940c3bf3de202a920e7b69491e7947d968330f03db592caa456dd", + license="https://cdn.jsdelivr.net/npm/datatables.net@1.13.11/License.txt", + license_sha256="62b5fdd54371b4f6bd07a60dbc78b38814f49a8028213f540dc2733cad605382", ), "datatablesconditionalpaging": VendorLibrary( name="DataTables conditionalPaging plug-in", - version="1.10.22", + version="1.13.6", base_url="https://cdn.datatables.net/plug-ins/{version}/features/conditionalPaging/", files={ - "dataTables.conditionalPaging.js": "336e6dd30fe2ba132c2980f057c359453c5e85ca046842717457505acdabc39c", + "dataTables.conditionalPaging.js": "b2474d8a4335060d3498248a0980471a2e772eb3655dae4d59e60dc26d12ff72", }, - license="https://cdn.jsdelivr.net/npm/datatables.net-plugins@1.10.22/License.txt", + license="https://cdn.jsdelivr.net/npm/datatables.net-plugins@1.13.6/License.txt", license_sha256="46daf76193ec5496a09285dfc4c58127f68d895c4de20ded97aff6d58b452a35", ), "d3": VendorLibrary(