diff --git a/l4d2web/l4d2web/app.py b/l4d2web/l4d2web/app.py index 0fce842..faad17f 100644 --- a/l4d2web/l4d2web/app.py +++ b/l4d2web/l4d2web/app.py @@ -61,6 +61,13 @@ def create_app(test_config: dict[str, object] | None = None) -> Flask: app.add_template_filter(format_time_html, "timeago") + @app.context_processor + def inject_base_layout() -> dict[str, str]: + from flask import has_request_context + + is_modal = has_request_context() and request.headers.get("HX-Modal") == "1" + return {"base_layout": "_modal_partial.html" if is_modal else "base.html"} + @app.before_request def csrf_protect() -> Response | None: if "csrf_token" not in session: diff --git a/l4d2web/l4d2web/templates/_modal_partial.html b/l4d2web/l4d2web/templates/_modal_partial.html new file mode 100644 index 0000000..cb0dbe4 --- /dev/null +++ b/l4d2web/l4d2web/templates/_modal_partial.html @@ -0,0 +1 @@ +{% block content %}{% endblock %} diff --git a/l4d2web/tests/test_url_addressable_modals.py b/l4d2web/tests/test_url_addressable_modals.py new file mode 100644 index 0000000..6fec021 --- /dev/null +++ b/l4d2web/tests/test_url_addressable_modals.py @@ -0,0 +1,29 @@ +from flask import render_template_string + +from l4d2web.app import create_app + + +def _make_app(tmp_path, monkeypatch, db_name: str): + db_url = f"sqlite:///{tmp_path/db_name}" + monkeypatch.setenv("DATABASE_URL", db_url) + return create_app({"TESTING": True, "DATABASE_URL": db_url, "SECRET_KEY": "test"}) + + +def test_base_layout_is_modal_partial_when_hx_modal_header_set(tmp_path, monkeypatch): + app = _make_app(tmp_path, monkeypatch, "layout-modal.db") + with app.test_request_context("/", headers={"HX-Modal": "1"}): + assert render_template_string("{{ base_layout }}") == "_modal_partial.html" + + +def test_base_layout_is_base_html_for_normal_request(tmp_path, monkeypatch): + app = _make_app(tmp_path, monkeypatch, "layout-default.db") + with app.test_request_context("/"): + assert render_template_string("{{ base_layout }}") == "base.html" + + +def test_base_layout_does_not_react_to_plain_hx_request_header(tmp_path, monkeypatch): + # HTMX sets HX-Request on every request including the build-status poll; + # only HX-Modal should switch the layout. + app = _make_app(tmp_path, monkeypatch, "layout-hxreq.db") + with app.test_request_context("/", headers={"HX-Request": "true"}): + assert render_template_string("{{ base_layout }}") == "base.html"