From 32e54f0381986137121f56fb727a02de6a7563f8 Mon Sep 17 00:00:00 2001 From: Deeman Date: Sat, 21 Feb 2026 22:40:59 +0100 Subject: [PATCH] =?UTF-8?q?countries:=20HATEOAS=20+=20HTMX=20=E2=80=94=20c?= =?UTF-8?q?lick=20origin=20to=20update=20chart=20instantly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace Apply button flow with immediate HTMX partial fetches: - toggleCountry() does an optimistic UI update (row + badge) then calls htmx.ajax() targeting #cc-canvas with swap=innerHTML - URL is pushed to history on every selection change (bookmarkable) - HX-Request now returns countries_canvas.html fragment (chips + chart/empty + inline IIFE that re-syncs globals + re-inits Chart.js) - Panel (dark) is never swapped; canvas fades during in-flight request - PALETTE, buildRankings(), initChart() defined once on page load, called by both initial render and partial IIFE after each swap - Apply button removed; Clear triggers fetchCanvas() with empty codes Co-Authored-By: Claude Sonnet 4.6 --- web/src/beanflows/dashboard/routes.py | 10 +- .../dashboard/templates/countries.html | 526 +++++++----------- .../dashboard/templates/countries_canvas.html | 104 ++++ 3 files changed, 313 insertions(+), 327 deletions(-) create mode 100644 web/src/beanflows/dashboard/templates/countries_canvas.html diff --git a/web/src/beanflows/dashboard/routes.py b/web/src/beanflows/dashboard/routes.py index ca8009d..a281e3b 100644 --- a/web/src/beanflows/dashboard/routes.py +++ b/web/src/beanflows/dashboard/routes.py @@ -195,9 +195,15 @@ async def countries(): analytics.COFFEE_COMMODITY_CODE, selected_codes, metric ) - # HTMX partial: return just the chart data as JSON + # HTMX partial: return just the canvas fragment (chips + chart) if request.headers.get("HX-Request"): - return jsonify({"data": comparison_data, "metric": metric}) + return await render_template( + "countries_canvas.html", + all_countries=all_countries, + selected_codes=selected_codes, + metric=metric, + comparison_data=comparison_data, + ) return await render_template( "countries.html", diff --git a/web/src/beanflows/dashboard/templates/countries.html b/web/src/beanflows/dashboard/templates/countries.html index 379da27..d946780 100644 --- a/web/src/beanflows/dashboard/templates/countries.html +++ b/web/src/beanflows/dashboard/templates/countries.html @@ -7,7 +7,6 @@ {% endblock %} {% block content %} - - -
-
+

Origin Intelligence

Compare coffee metrics across {{ all_countries|length }} producing & consuming nations

@@ -510,7 +404,8 @@
{% if selected_codes %} - Showing {{ selected_codes|length }} {{ "country" if selected_codes|length == 1 else "countries" }} + Showing {{ selected_codes|length }} + {{ "country" if selected_codes|length == 1 else "countries" }} {% else %} Select countries to compare {% endif %} @@ -520,14 +415,14 @@
- +
Origins {{ selected_codes|length }}/10
-
@@ -541,43 +436,39 @@ {{ "{:,.0f}".format(c.production) if c.production else "" }}
- +
{% endfor %}
- - +
- -
- + +
- {% if selected_codes %} - {% for code in selected_codes %} - {% set country = all_countries | selectattr("country_code", "equalto", code) | first %} - {% if country %} - - {{ country.country_name }} - × - - {% endif %} - {% endfor %} - {% else %} - No countries selected + {% for code in selected_codes %} + {% set c = all_countries | selectattr("country_code", "equalto", code) | first %} + {% if c %} + + {{ c.country_name }} + × + + {% endif %} + {% endfor %} + {% if not selected_codes %} + No countries selected {% endif %}
- + {% if comparison_data %} - -
+
{{ metric.replace("_"," ").title() }} Over Time
@@ -589,12 +480,9 @@
- -
- +
{% else %} - -
+
@@ -607,193 +495,165 @@
Select Origins to Compare

Choose up to 10 coffee-producing countries from the panel on the left to visualize production, trade flows, and inventory trends.

- {% endif %}
-
+
{% endblock %} {% block scripts %} {% endblock %} diff --git a/web/src/beanflows/dashboard/templates/countries_canvas.html b/web/src/beanflows/dashboard/templates/countries_canvas.html new file mode 100644 index 0000000..2b78cd2 --- /dev/null +++ b/web/src/beanflows/dashboard/templates/countries_canvas.html @@ -0,0 +1,104 @@ +{# + countries_canvas.html — HTMX partial for the canvas area. + Returned on every HX-Request to /dashboard/countries. + Renders chips + chart (or empty state), then runs an IIFE that: + 1. Syncs globals (orderedSel, selectedSet, currentMetric) from server state + 2. Syncs panel row visual state + 3. Applies palette to chips + 4. Initialises Chart.js + rankings table +#} + + +
+ {% for code in selected_codes %} + {% set c = all_countries | selectattr("country_code", "equalto", code) | first %} + {% if c %} + + {{ c.country_name }} + × + + {% endif %} + {% endfor %} + {% if not selected_codes %} + No countries selected + {% endif %} +
+ + +{% if comparison_data %} + +
+
+
+
{{ metric.replace("_"," ").title() }} Over Time
+
USDA WASDE · 1000 60-kg bags · click legend to toggle
+
+ 1k bags +
+
+ +
+
+ +
+ +{% else %} + +
+
+ + + + + + +
+
Select Origins to Compare
+

Choose up to 10 coffee-producing countries from the panel on the left to visualize production, trade flows, and inventory trends.

+
+ +{% endif %} + + +