diff --git a/src/central/adapters/tomtom_incidents.py b/src/central/adapters/tomtom_incidents.py
index 8b9851f..8868fa1 100644
--- a/src/central/adapters/tomtom_incidents.py
+++ b/src/central/adapters/tomtom_incidents.py
@@ -333,6 +333,8 @@ class TomTomIncidentsAdapter(SourceAdapter):
return {
"calls_per_month": calls_per_month,
"cap": cap,
+ "seconds_per_month": _SECONDS_PER_MONTH,
+ "default_cadence_s": cls.default_cadence_s,
"percent": percent,
"warn": percent >= 80.0,
"blocked": percent >= 100.0,
diff --git a/src/central/gui/templates/_partials/model_list.html b/src/central/gui/templates/_partials/model_list.html
index ac882fb..077cd04 100644
--- a/src/central/gui/templates/_partials/model_list.html
+++ b/src/central/gui/templates/_partials/model_list.html
@@ -66,10 +66,13 @@
{% if quota %}
-
-
API quota: {{ quota.detail }}
- {% if quota.blocked %}
⛔ Over free-tier cap — reduce calls before saving.
- {% elif quota.warn %}
⚠️ Approaching free-tier cap.{% endif %}
+
+ API quota: {{ quota.detail }}
+ {% if quota.blocked %}
⛔ Over free-tier cap — reduce calls before saving.{% elif quota.warn %}
⚠️ Approaching free-tier cap.{% endif %}
{% endif %}
@@ -103,3 +106,64 @@
});
})();
+
+
diff --git a/tests/test_gui_adapter_edit.py b/tests/test_gui_adapter_edit.py
index d7cb04f..f196cbf 100644
--- a/tests/test_gui_adapter_edit.py
+++ b/tests/test_gui_adapter_edit.py
@@ -56,6 +56,27 @@ class TestModelListRender:
assert "model-list" in out and 'name="bboxes-0-name"' in out
assert "free tier" in out # quota panel rendered
+ def test_quota_panel_exposes_client_recompute_constants(self):
+ # v0.9.15: data-quota-* attrs let the client JS mirror the server
+ # formula with no hardcoded magic numbers.
+ fields = describe_fields(TomTomIncidentsAdapter.settings_schema, _SETTINGS)
+ quota = TomTomIncidentsAdapter.quota_estimate(TomTomIncidentsSettings(**_SETTINGS), 1800)
+ out = _render("adapters_edit.html", _ctx(_SETTINGS, fields, quota))
+ assert 'data-quota-cap="2500"' in out
+ assert 'data-quota-spm="2592000"' in out
+ assert 'data-quota-default="1800"' in out
+
+ def test_quota_panel_wraps_detail_and_msg_for_live_update(self):
+ # v0.9.15: detail/msg split into spans so the IIFE can rewrite the text
+ # and warn/block state live. JS exec needs a browser, so this is
+ # structural only -- live behaviour (cadence edit + Add/Delete row)
+ # was eyeballed manually against /adapters/tomtom_incidents.
+ fields = describe_fields(TomTomIncidentsAdapter.settings_schema, _SETTINGS)
+ quota = TomTomIncidentsAdapter.quota_estimate(TomTomIncidentsSettings(**_SETTINGS), 1800)
+ out = _render("adapters_edit.html", _ctx(_SETTINGS, fields, quota))
+ assert '
' in out
+ assert '' in out
+
def test_nws_region_intact_no_model_list(self):
from central.adapters.nws import NWSSettings
s = {"contact_email": "a@b.com",