diff --git a/integreat_cms/cms/models/contact/contact.py b/integreat_cms/cms/models/contact/contact.py index 4cfe5f8c98..0e3217c271 100644 --- a/integreat_cms/cms/models/contact/contact.py +++ b/integreat_cms/cms/models/contact/contact.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import Generator, TYPE_CHECKING from django.conf import settings from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector @@ -23,6 +23,8 @@ if TYPE_CHECKING: from django.db.models.query import QuerySet + from ..abstract_content_translation import AbstractContentTranslation + class Contact(AbstractBaseModel): """ @@ -182,7 +184,7 @@ def referring_page_translations(self) -> QuerySet[PageTranslation]: Link.objects.filter( url__url=self.full_url, content_type=PageTranslationLinklist.content_type(), - ).values_list("object_id", flat=True) + ).values("object_id") ), ) @@ -200,7 +202,7 @@ def referring_poi_translations(self) -> QuerySet[POITranslation]: Link.objects.filter( url__url=self.full_url, content_type=POITranslationLinklist.content_type(), - ).values_list("object_id", flat=True) + ).values("object_id") ), ) @@ -218,10 +220,21 @@ def referring_event_translations(self) -> QuerySet[EventTranslation]: Link.objects.filter( url__url=self.full_url, content_type=EventTranslationLinklist.content_type(), - ).values_list("object_id", flat=True) + ).values("object_id") ), ) + @cached_property + def referring_objects(self) -> Generator[AbstractContentTranslation]: + """ + Returns a list of all objects linking to this contact. + + :return: all objects referring to this contact + """ + return ( + link.content_object for link in Link.objects.filter(url__url=self.full_url) + ) + def archive(self) -> None: """ Archives the contact @@ -244,68 +257,6 @@ def copy(self) -> None: self.point_of_contact_for = self.point_of_contact_for + " " + _("(Copy)") self.save() - @cached_property - def url_prefix(self) -> str: - """ - Generates the prefix of the url of the contact - - For information about the components of such an url, - see :meth:`~integreat_cms.cms.models.contact.contact.Contact.get_absolute_url` - - :return: The prefix to the url - """ - return "/" + "/".join( - filter( - None, - [ - self.location.region.slug, - self.url_infix, - ], - ) - ) - - @cached_property - def url_infix(self) -> str: - """ - Generates the infix of the url of the contact - - For information about the components of such an url, - see :meth:`~integreat_cms.cms.models.contact.contact.Contact.get_absolute_url` - """ - return "contact/" - - @cached_property - def base_link(self) -> str: - """ - Generates the base link which is the whole url without id - - For information about the components of such an url, - see :meth:`~integreat_cms.cms.models.contact.contact.Contact.get_absolute_url` - - :return: the base link of the content - """ - if not self.id: - return settings.BASE_URL + "/" - return settings.BASE_URL + self.url_prefix - - def get_absolute_url(self) -> str: - """ - Generates the absolute url of the contact - - Here is an example for demonstrating the components:: - - https://integreat.app/augsburg/contact/42/ - |----------------------------------------| full_url - |-------------------| get_absolute_url() - |-------------------------------------| base_link - |----------------| url_prefix - |-------| url_infix - |--| id - - :return: The absolute url - """ - return self.url_prefix + str(self.id) + "/" - @cached_property def full_url(self) -> str: """ @@ -313,7 +264,7 @@ def full_url(self) -> str: :return: The full url """ - return settings.BASE_URL + self.get_absolute_url() + return f"{settings.BASE_URL}/{self.location.region.slug}/contact/{self.id}/" class Meta: verbose_name = _("contact") diff --git a/integreat_cms/cms/templates/contacts/contact_card.html b/integreat_cms/cms/templates/contacts/contact_card.html index caf37a6d5e..2c80071947 100644 --- a/integreat_cms/cms/templates/contacts/contact_card.html +++ b/integreat_cms/cms/templates/contacts/contact_card.html @@ -1,89 +1,58 @@ -{% load settings_tags %} +{% load svg_tags %} {% load static %} {% spaceless %}
- - - - - {{ contact.location.short_address }} - - + + {{ contact.location.short_address }}
{% endif %} - {% if contact.email and contact.email.strip %} + {% if contact.email %}- + - + - {{ contact.email.strip }} + {{ contact.email }}
{% endif %} - {% if contact.phone_number and contact.phone_number.strip %} + {% if contact.phone_number %}- - - - - {{ contact.phone_number.strip }} - - + + {{ contact.phone_number }}
{% endif %} - {% if contact.website and contact.website.strip %} + {% if contact.website %}- + - + - {{ contact.website.strip }} + {{ contact.website }}
diff --git a/integreat_cms/cms/templatetags/svg_tags.py b/integreat_cms/cms/templatetags/svg_tags.py new file mode 100644 index 0000000000..0f325f8bf0 --- /dev/null +++ b/integreat_cms/cms/templatetags/svg_tags.py @@ -0,0 +1,23 @@ +""" +Contains a collection of tags for working with svg icons. +""" + +from __future__ import annotations + +from django import template + +from ..utils.tinymce_icon_utils import get_icon_url + +register = template.Library() + + +@register.simple_tag +def get_svg_icon(svg: str) -> str: + """ + This tags inserts the link to an svg icon + + :param svg: The svg icon to insert + + :return: The full url of the svg + """ + return get_icon_url(svg) diff --git a/integreat_cms/cms/utils/content_utils.py b/integreat_cms/cms/utils/content_utils.py index d0475d2848..167b481b3d 100644 --- a/integreat_cms/cms/utils/content_utils.py +++ b/integreat_cms/cms/utils/content_utils.py @@ -157,7 +157,7 @@ def render_contact_card(contact_id: int) -> HtmlElement: return fromstring(raw_element) except Contact.DoesNotExist: logger.warning("Contact with id=%i does not exist!", contact_id) - return Element("p", contact_id) + return Element("p") except LxmlError as e: logger.debug( "Failed to parse rendered HTML for contact card: %r\n→ %s\nEOF", diff --git a/integreat_cms/cms/views/utils/contact_utils.py b/integreat_cms/cms/views/utils/contact_utils.py index 939aa49ce4..847e742fc5 100644 --- a/integreat_cms/cms/views/utils/contact_utils.py +++ b/integreat_cms/cms/views/utils/contact_utils.py @@ -9,9 +9,8 @@ from django.shortcuts import get_object_or_404, render from django.views.decorators.http import require_POST -from ...models import ( - Contact, -) +from ...decorators import permission_required +from ...models import Contact if TYPE_CHECKING: from typing import Any, Literal @@ -64,6 +63,7 @@ def search_contact_ajax( ) +@permission_required("cms.view_contact") def get_contact( request: HttpRequest, contact_id: int, region_slug: str | None = None ) -> str: @@ -80,6 +80,7 @@ def get_contact( return render(request, "contacts/contact_card.html", {"contact": contact}) +@permission_required("cms.view_contact") def get_contact_raw( request: HttpRequest, contact_id: int, region_slug: str | None = None ) -> str: diff --git a/integreat_cms/core/signals/contact_signals.py b/integreat_cms/core/signals/contact_signals.py index af575e96e6..c329dce266 100644 --- a/integreat_cms/core/signals/contact_signals.py +++ b/integreat_cms/core/signals/contact_signals.py @@ -29,12 +29,7 @@ def contact_save_handler(instance: Contact, **kwargs: Any) -> None: :param instance: The page translation that gets saved :param \**kwargs: The supplied keyword arguments """ - referring_objects = ( - list(instance.referring_page_translations) - + list(instance.referring_poi_translations) - + list(instance.referring_event_translations) - ) - for referrer in referring_objects: + for referrer in instance.referring_objects: if getattr(referrer.foreign_object, "archived", False): continue logger.debug("Updating %r, since it references %r.", referrer, instance) diff --git a/integreat_cms/static/src/js/tinymce-plugins/custom_contact_input/plugin.js b/integreat_cms/static/src/js/tinymce-plugins/custom_contact_input/plugin.js index 21f2ce6f11..26afbbe077 100644 --- a/integreat_cms/static/src/js/tinymce-plugins/custom_contact_input/plugin.js +++ b/integreat_cms/static/src/js/tinymce-plugins/custom_contact_input/plugin.js @@ -153,11 +153,12 @@ import { getCsrfToken } from "../../utils/csrf-token"; return editor.windowManager.open(dialogConfig); }; - editor.addShortcut("Meta+P", tinymceConfig.getAttribute("data-contact-menu-text"), openDialog); + editor.addShortcut("Meta+L", tinymceConfig.getAttribute("data-contact-menu-text"), openDialog); editor.ui.registry.addMenuItem("add_contact", { text: tinymceConfig.getAttribute("data-contact-menu-text"), icon: "contact", + shortcut: "Meta+L", onAction: openDialog, });