diff --git a/integreat_cms/cms/templates/pois/poi_list.html b/integreat_cms/cms/templates/pois/poi_list.html
index f6fe9a88cc..98a7cbae5f 100644
--- a/integreat_cms/cms/templates/pois/poi_list.html
+++ b/integreat_cms/cms/templates/pois/poi_list.html
@@ -2,6 +2,7 @@
{% load i18n %}
{% load rules %}
{% load static %}
+{% load sort_tags %}
{% load content_filters %}
{% block content %}
{% get_current_language as LANGUAGE_CODE %}
@@ -62,14 +63,19 @@
+ {% translate "Street" as street_label %}
+ {% translate "Postal Code" as postcode_label %}
+ {% translate "City" as city_label %}
+ {% translate "Country" as country_label %}
+ {% translate "Category" as category_label %}
|
{% if perms.cms.change_poi %}
{% endif %}
|
-
- {% translate "Title in" %} {{ language.translated_name }}
+ |
+ {% sort_link title_label "translations__title" %}
|
{% if backend_language and backend_language != language %}
@@ -93,20 +99,20 @@
|
{% translate "Publication status" %}
|
-
- {% translate "Street" %}
+ |
+ {% sort_link street_label "address" %}
|
-
- {% translate "Postal Code" %}
+ |
+ {% sort_link postcode_label "postcode" %}
|
-
- {% translate "City" %}
+ |
+ {% sort_link city_label "city" %}
|
-
- {% translate "Country" %}
+ |
+ {% sort_link country_label "country" %}
|
-
- {% translate "Category" %}
+ |
+ {% sort_link category_label "category" %}
|
{% translate "Options" %}
diff --git a/integreat_cms/cms/templatetags/sort_tags.py b/integreat_cms/cms/templatetags/sort_tags.py
index f10b6211e8..2abffbffcf 100644
--- a/integreat_cms/cms/templatetags/sort_tags.py
+++ b/integreat_cms/cms/templatetags/sort_tags.py
@@ -1,5 +1,6 @@
from django import template
from django.template.context import RequestContext
+from django.utils.html import escape
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
@@ -31,7 +32,9 @@ def sort_link(context: RequestContext, label: str, field: str) -> str:
url = f"?{urlencode(params, doseq=True)}"
- return mark_safe(f'{label}{arrow}')
+ return mark_safe(
+ f'{escape(label)}{arrow}'
+ )
@register.inclusion_tag("_sortable_table_header.html", takes_context=True)
diff --git a/integreat_cms/cms/views/mixins.py b/integreat_cms/cms/views/mixins.py
index 4895ac8531..d14b319a0f 100644
--- a/integreat_cms/cms/views/mixins.py
+++ b/integreat_cms/cms/views/mixins.py
@@ -9,6 +9,7 @@
from django.conf import settings
from django.contrib.auth.mixins import UserPassesTestMixin
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
+from django.db.models import Min
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.generic.base import ContextMixin, TemplateResponseMixin
@@ -237,5 +238,22 @@ def get_filtered_sorted_queryset(self, queryset: QuerySet) -> QuerySet:
if order_by:
# queryset.order_by([]) would override default ordering and result in an unordered queryset
# so we only use order_by if "sort" is not empty
- return queryset.order_by(*order_by)
+ annotations = {}
+ final_order = []
+ for f in order_by:
+ bare = f.lstrip("-")
+ descending = f.startswith("-")
+ if "__" in bare:
+ # Sorting by a relational field via JOIN produces duplicate rows.
+ # Use Min annotation instead, which collapses via GROUP BY.
+ annotation_name = f"_sort_{bare.replace('__', '_')}"
+ annotations[annotation_name] = Min(bare)
+ final_order.append(
+ f"-{annotation_name}" if descending else annotation_name
+ )
+ else:
+ final_order.append(f)
+ if annotations:
+ queryset = queryset.annotate(**annotations)
+ queryset = queryset.order_by(*final_order)
return queryset
diff --git a/integreat_cms/cms/views/pois/poi_list_view.py b/integreat_cms/cms/views/pois/poi_list_view.py
index bdd5648621..98874cc9a8 100644
--- a/integreat_cms/cms/views/pois/poi_list_view.py
+++ b/integreat_cms/cms/views/pois/poi_list_view.py
@@ -41,6 +41,15 @@ class POIListView(
#: The translation model of this list view (used to determine whether machine translations are permitted)
translation_model = POITranslation
model = POI
+ table_fields = [
+ ("translations__title", _("Title")),
+ (None, _("Publication status")),
+ ("address", _("Street")),
+ ("postcode", _("Postal Code")),
+ ("city", _("City")),
+ ("country", _("Country")),
+ ("category", _("Category")),
+ ]
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
r"""
@@ -105,5 +114,6 @@ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
"source_language": region.get_source_language(language.slug),
"content_type": "locations",
"is_archive": self.archived,
+ "title_label": "{} {}".format(_("Title in"), language.translated_name),
},
)
diff --git a/integreat_cms/locale/de/LC_MESSAGES/django.po b/integreat_cms/locale/de/LC_MESSAGES/django.po
index b1209572c8..a9b702ebbd 100644
--- a/integreat_cms/locale/de/LC_MESSAGES/django.po
+++ b/integreat_cms/locale/de/LC_MESSAGES/django.po
@@ -27,6 +27,7 @@ msgid "CMS"
msgstr "CMS"
#: cms/constants/administrative_division.py cms/templates/pois/poi_list.html
+#: cms/views/pois/poi_list_view.py
msgid "City"
msgstr "Stadt"
@@ -1941,7 +1942,7 @@ msgstr "{} hier eingeben"
#: cms/templates/content_versions.html cms/templates/events/event_form.html
#: cms/templates/events/event_list.html cms/templates/pages/page_form.html
#: cms/templates/pages/pages_page_tree.html cms/templates/pois/poi_form.html
-#: cms/templates/pois/poi_list.html
+#: cms/templates/pois/poi_list.html cms/views/pois/poi_list_view.py
msgid "Publication status"
msgstr "Veröffentlichungsstatus"
@@ -2071,6 +2072,7 @@ msgstr "Alle Kategorien"
#: cms/templates/feedback/admin_feedback_list.html
#: cms/templates/feedback/region_feedback_list.html
#: cms/templates/pois/poi_list.html cms/views/feedback/feedback_resource.py
+#: cms/views/pois/poi_list_view.py
msgid "Category"
msgstr "Kategorie"
@@ -3664,7 +3666,7 @@ msgstr "Ob die Seite explizit archiviert ist oder nicht"
#: cms/templates/events/event_form.html cms/templates/events/event_list.html
#: cms/templates/pages/_generic_page_tree_header.html
#: cms/templates/pages/page_form.html cms/templates/pois/poi_form.html
-#: cms/templates/pois/poi_list.html
+#: cms/templates/pois/poi_list.html cms/views/pois/poi_list_view.py
msgid "Title in"
msgstr "Titel auf"
@@ -7649,6 +7651,7 @@ msgstr "Keine Änderungen vorgenommen."
#: cms/templates/pages/_page_xliff_import_diff.html
#: cms/templates/push_notifications/push_notification_list.html
+#: cms/views/pois/poi_list_view.py
msgid "Title"
msgstr "Titel"
@@ -8280,15 +8283,15 @@ msgid ""
msgstr ""
"Sie können Orte nur in der Standard-Sprache (%(default_language)s) anlegen."
-#: cms/templates/pois/poi_list.html
+#: cms/templates/pois/poi_list.html cms/views/pois/poi_list_view.py
msgid "Street"
msgstr "Straße"
-#: cms/templates/pois/poi_list.html
+#: cms/templates/pois/poi_list.html cms/views/pois/poi_list_view.py
msgid "Postal Code"
msgstr "Postleitzahl"
-#: cms/templates/pois/poi_list.html
+#: cms/templates/pois/poi_list.html cms/views/pois/poi_list_view.py
msgid "Country"
msgstr "Land"
| |