From af28668fb752067dc810794046b9d5d539664593 Mon Sep 17 00:00:00 2001 From: Zayneb Date: Fri, 30 Oct 2026 16:04:45 +0000 Subject: [PATCH 1/6] Fix opening hours editing for archived places --- integreat_cms/cms/views/places/place_context_mixin.py | 2 +- integreat_cms/cms/views/places/place_form_view.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integreat_cms/cms/views/places/place_context_mixin.py b/integreat_cms/cms/views/places/place_context_mixin.py index e3783d97ad..ec0cf63df8 100644 --- a/integreat_cms/cms/views/places/place_context_mixin.py +++ b/integreat_cms/cms/views/places/place_context_mixin.py @@ -35,7 +35,7 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]: context = super().get_context_data(**kwargs) opening_hour_config_data = get_open_hour_config_data( related_class=self.related_class, - can_change_place=self.request.user.has_perm("cms.change_place"), + can_change_place=kwargs.get("can_change_place", self.request.user.has_perm("cms.change_place")), ) context.update( { diff --git a/integreat_cms/cms/views/places/place_form_view.py b/integreat_cms/cms/views/places/place_form_view.py index 129b1f6764..b4f7c0af0d 100644 --- a/integreat_cms/cms/views/places/place_form_view.py +++ b/integreat_cms/cms/views/places/place_form_view.py @@ -103,7 +103,7 @@ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: request, self.template_name, { - **self.get_context_data(**kwargs), + **self.get_context_data(**kwargs, can_change_place=not disabled), "place_form": place_form, "place_translation_form": place_translation_form, "language": language, From b02fad5825362f6c35cb692ac5cfed911cb69b12 Mon Sep 17 00:00:00 2001 From: Zayneb Date: Fri, 30 Oct 2026 17:20:54 +0000 Subject: [PATCH 2/6] Fix map and coordinate editing for archived places --- .../place_form_sidebar/position_box.html | 8 +-- .../cms/views/places/place_context_mixin.py | 4 +- .../static/src/js/places/place-map.ts | 20 +++++--- tests/cms/views/place/test_place_form.py | 49 +++++++++++++++++++ 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html b/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html index 10a47fbb13..b386fe82f9 100644 --- a/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html +++ b/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html @@ -35,7 +35,8 @@ + checked + {% if place_form.instance.archived or not perms.cms.change_place %}disabled{% endif %} /> @@ -53,12 +54,13 @@ class="aspect-video" data-url="{% url "get_address_from_coordinates" region_slug=request.region.slug %}" data-bounding-box="{{ request.region.bounding_box.api_representation }}" - data-change-permission="{{ perms.cms.change_place }}"> + data-change-permission="{% if perms.cms.change_place and not place_form.instance.archived %}True{% else %}False{% endif %}"> + diff --git a/integreat_cms/cms/views/places/place_context_mixin.py b/integreat_cms/cms/views/places/place_context_mixin.py index ec0cf63df8..44853dbed2 100644 --- a/integreat_cms/cms/views/places/place_context_mixin.py +++ b/integreat_cms/cms/views/places/place_context_mixin.py @@ -35,7 +35,9 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]: context = super().get_context_data(**kwargs) opening_hour_config_data = get_open_hour_config_data( related_class=self.related_class, - can_change_place=kwargs.get("can_change_place", self.request.user.has_perm("cms.change_place")), + can_change_place=kwargs.get( + "can_change_place", self.request.user.has_perm("cms.change_place") + ), ) context.update( { diff --git a/integreat_cms/static/src/js/places/place-map.ts b/integreat_cms/static/src/js/places/place-map.ts index 5d4e75f982..f868bab7dc 100644 --- a/integreat_cms/static/src/js/places/place-map.ts +++ b/integreat_cms/static/src/js/places/place-map.ts @@ -151,7 +151,9 @@ const renderMap = () => { // Initialize map and marker const map = new Map(options); const marker = new Marker(); - marker.setDraggable(container.dataset.changePermission === "True"); + + const canChangePlace = container.dataset.changePermission === "True"; + marker.setDraggable(canChangePlace); // If initial coordinates are given, set the marker to this position if (coordinates) { @@ -159,12 +161,16 @@ const renderMap = () => { } // Support setting the marker both via drag & drop and via clicking on the map - map.on("click", (event: MapMouseEvent) => { - marker.setLngLat(event.lngLat).addTo(map); - updateHelpText(event.lngLat); - fetchAddress(marker); - }); - marker.on("dragend", () => fetchAddress(marker)); + // Only allow changing the position when editing is permitted + if (canChangePlace) { + map.on("click", (event: MapMouseEvent) => { + marker.setLngLat(event.lngLat).addTo(map); + updateHelpText(event.lngLat); + fetchAddress(marker); + }); + + marker.on("dragend", () => fetchAddress(marker)); + } // Set the initial zoom map.on("load", map.resize); diff --git a/tests/cms/views/place/test_place_form.py b/tests/cms/views/place/test_place_form.py index 093b3e3ed7..5a46658a40 100644 --- a/tests/cms/views/place/test_place_form.py +++ b/tests/cms/views/place/test_place_form.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import re from datetime import timedelta from typing import TYPE_CHECKING @@ -742,3 +743,51 @@ def test_case_insensitive_unique_slug( assert PlaceTranslation.objects.filter(slug="slug").count() == 1 assert PlaceTranslation.objects.filter(slug="slug-2").count() == 1 + + +@pytest.mark.django_db +@pytest.mark.parametrize("archived", [True, False]) +def test_place_editing_controls_respect_archived_state( + load_test_data: None, + client: Client, + archived: bool, +) -> None: + # Log in as a user with editing permission + user = get_user_model().objects.get(username="root") + client.force_login(user) + + # Get a test place and set its archived status + place = Place.objects.get(id=4) + place.archived = archived + place.save(update_fields=["archived"]) + + # Open the place editing page + url = reverse( + "edit_place", + kwargs={ + "region_slug": "augsburg", + "language_slug": "de", + "place_id": place.id, + }, + ) + response = client.get(url) + + assert response.status_code == 200 + + # Check opening-hours editing permission + config = response.context["opening_hour_config_data"] + assert config["canChangePlace"] is not archived + + html = response.content.decode("utf-8") + + # Check map editing permission + expected_permission = "False" if archived else "True" + assert f'data-change-permission="{expected_permission}"' in html + + # Check automatic-coordinates checkbox + checkbox = re.search( + r']*\bid="auto-fill-coordinates"[^>]*>', + html, + ) + assert checkbox is not None + assert ("disabled" in checkbox.group(0)) is archived From d04c9450ec6f6c378dd9564e3c6f55546233b040 Mon Sep 17 00:00:00 2001 From: MizukiTemma <82345046+MizukiTemma@users.noreply.github.com> Date: Tue, 10 Nov 2026 18:00:46 +0100 Subject: [PATCH 3/6] Update integreat_cms/static/src/js/places/place-map.ts --- integreat_cms/static/src/js/places/place-map.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integreat_cms/static/src/js/places/place-map.ts b/integreat_cms/static/src/js/places/place-map.ts index f868bab7dc..ce64562e6e 100644 --- a/integreat_cms/static/src/js/places/place-map.ts +++ b/integreat_cms/static/src/js/places/place-map.ts @@ -152,7 +152,7 @@ const renderMap = () => { const map = new Map(options); const marker = new Marker(); - const canChangePlace = container.dataset.changePermission === "True"; + const canChangePlace = container.dataset.changePermission === "False"; marker.setDraggable(canChangePlace); // If initial coordinates are given, set the marker to this position From e0ae283e053a6af9cb8b3d6f30a2390b8859b6c3 Mon Sep 17 00:00:00 2001 From: MizukiTemma <82345046+MizukiTemma@users.noreply.github.com> Date: Tue, 10 Nov 2026 18:01:08 +0100 Subject: [PATCH 4/6] Update integreat_cms/cms/templates/places/place_form_sidebar/position_box.html --- .../cms/templates/places/place_form_sidebar/position_box.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html b/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html index b386fe82f9..6c3a934902 100644 --- a/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html +++ b/integreat_cms/cms/templates/places/place_form_sidebar/position_box.html @@ -54,7 +54,7 @@ class="aspect-video" data-url="{% url "get_address_from_coordinates" region_slug=request.region.slug %}" data-bounding-box="{{ request.region.bounding_box.api_representation }}" - data-change-permission="{% if perms.cms.change_place and not place_form.instance.archived %}True{% else %}False{% endif %}"> + data-change-permission="{{ disabled }}"> + data-change-permission="{{ disabled }}"> diff --git a/integreat_cms/cms/views/places/place_form_view.py b/integreat_cms/cms/views/places/place_form_view.py index b4f7c0af0d..b632d525de 100644 --- a/integreat_cms/cms/views/places/place_form_view.py +++ b/integreat_cms/cms/views/places/place_form_view.py @@ -117,6 +117,7 @@ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: "contact_form": contact_form, "show_contact_form_widget": False, "is_edit": is_edit, + "disabled": disabled, }, ) From 3b1bf39583ea7a2aead577eb72f4c85784795974 Mon Sep 17 00:00:00 2001 From: MizukiTemma Date: Tue, 10 Nov 2026 18:48:01 +0100 Subject: [PATCH 6/6] Adjust test --- tests/cms/views/place/test_place_form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cms/views/place/test_place_form.py b/tests/cms/views/place/test_place_form.py index 5a46658a40..07c2d01c3c 100644 --- a/tests/cms/views/place/test_place_form.py +++ b/tests/cms/views/place/test_place_form.py @@ -781,7 +781,7 @@ def test_place_editing_controls_respect_archived_state( html = response.content.decode("utf-8") # Check map editing permission - expected_permission = "False" if archived else "True" + expected_permission = "True" if archived else "False" assert f'data-change-permission="{expected_permission}"' in html # Check automatic-coordinates checkbox