Skip to content

Commit

Permalink
Prevent orphaned contact cards
Browse files Browse the repository at this point in the history
  • Loading branch information
charludo committed Jan 8, 2025
1 parent 7d703ab commit a295ac3
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 69 deletions.
45 changes: 44 additions & 1 deletion integreat_cms/cms/fixtures/test_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,21 @@
"created_date": "2024-08-06T13:23:45.256Z"
}
},
{
"model": "cms.contact",
"pk": 5,
"fields": {
"point_of_contact_for": "Testkontakt",
"name": "refered to in a page",
"location": 4,
"email": "",
"phone_number": "",
"website": "",
"archived": false,
"last_updated": "2025-01-08T13:53:31.813Z",
"created_date": "2025-01-08T13:53:31.806Z"
}
},
{
"model": "cms.recurrencerule",
"pk": 1,
Expand Down Expand Up @@ -2304,6 +2319,22 @@
"redirect_to": ""
}
},
{
"model": "linkcheck.url",
"pk": 21,
"fields": {
"url": "http://localhost:8000/augsburg/contact/5/",
"last_checked": "2025-01-08T13:54:42.851Z",
"anchor_status": null,
"ssl_status": null,
"status": true,
"status_code": 200,
"redirect_status_code": null,
"message": "",
"error_message": "",
"redirect_to": ""
}
},
{
"model": "linkcheck.link",
"pk": 1,
Expand Down Expand Up @@ -2760,6 +2791,18 @@
"ignore": false
}
},
{
"model": "linkcheck.link",
"pk": 40,
"fields": {
"content_type": ["cms", "pagetranslation"],
"object_id": 39,
"field": "content",
"url": 21,
"text": "Contact",
"ignore": false
}
},
{
"model": "cms.page",
"pk": 1,
Expand Down Expand Up @@ -4262,7 +4305,7 @@
"title": "Gesundheitsamt",
"slug": "gesundheitsamt",
"status": "PUBLIC",
"content": "<div><p><strong>Leistungen des Gesundheitsamtes:</strong></p>\r\n<ul>\r\n<li>Beratung zur Gesundheitsfragen</li>\r\n<li>Beratung für Menschen, die an einer psychischen Krankheit leiden</li>\r\n<li>Kontaktstelle für Selbsthilfegruppen Infos auch unter:<br><a href=\"https://www.augsburg.de/umwelt-soziales/gesundheit/selbsthilfegruppen\">www.augsburg.de/selbsthilfe-schwaben</a></li>\r\n<li>Beratung für Schwangere</li>\r\n<li>Impfberatung</li>\r\n<li>Belehrung nach Infektionsschutzgesetz § 43 (Lebensmittelbelehrung, Gesundheitszeugnis)</li>\r\n<li>Untersuchung für Kinder, bevor sie in die Schule gehen können (Schuleingangsuntersuchung)</li>\r\n<li>Erstuntersuchung von unbegleiteten minderjährigen Ausländerinnen und Ausländern auf Veranlassung des AKJF</li>\r\n<li>Erstuntersuchung nach amtlicher Vorladung im Bereich Migration und Asyl</li>\r\n<li>Meldepflichtige Krankheiten (Tuberkulose, Gelbsucht etc.)</li>\r\n<li>Tuberkulosefürsorge</li>\r\n<li>Gesundheitsberatung und Untersuchung für Prostituierte</li>\r\n<li>anonyme AIDS-Beratung / HIV-Test</li>\r\n</ul>\r\n</div>",
"content": "<div>\r\n<p><strong>Leistungen des Gesundheitsamtes:</strong></p>\r\n<ul>\r\n<li>Beratung zur Gesundheitsfragen</li>\r\n<li>Beratung für Menschen, die an einer psychischen Krankheit leiden</li>\r\n<li>Kontaktstelle für Selbsthilfegruppen Infos auch unter:<br><a class=\"link-external\" href=\"https://www.augsburg.de/umwelt-soziales/gesundheit/selbsthilfegruppen\">www.augsburg.de/selbsthilfe-schwaben</a></li>\r\n<li>Beratung für Schwangere</li>\r\n<li>Impfberatung</li>\r\n<li>Belehrung nach Infektionsschutzgesetz § 43 (Lebensmittelbelehrung, Gesundheitszeugnis)</li>\r\n<li>Untersuchung für Kinder, bevor sie in die Schule gehen können (Schuleingangsuntersuchung)</li>\r\n<li>Erstuntersuchung von unbegleiteten minderjährigen Ausländerinnen und Ausländern auf Veranlassung des AKJF</li>\r\n<li>Erstuntersuchung nach amtlicher Vorladung im Bereich Migration und Asyl</li>\r\n<li>Meldepflichtige Krankheiten (Tuberkulose, Gelbsucht etc.)</li>\r\n<li>Tuberkulosefürsorge</li>\r\n<li>Gesundheitsberatung und Untersuchung für Prostituierte</li>\r\n<li>anonyme AIDS-Beratung / HIV-Test</li>\r\n</ul>\r\n<div contenteditable=\"false\" data-contact-id=\"5\" data-contact-url=\"http://localhost:8000/augsburg/contact/5/\" class=\"contact-card notranslate\" dir=\"ltr\" translate=\"no\"><a href=\"http://localhost:8000/augsburg/contact/5/\" style=\"display: none\">Contact</a><h4>\n \n refered to in a page\n \n \n |\n \n \n Testkontakt\n \n </h4><p><img src=\"http://localhost:8000/static/svg/pin.svg\" alt=\"Address: \" width=\"15\" height=\"15\">\n   <a href=\"https://integreat.app/augsburg/de/locations/test-ort/\">Wolfgangstraße 2, 86153 Augsburg</a></p></div>\n</div>",
"language": 1,
"currently_in_translation": false,
"machine_translated": false,
Expand Down
8 changes: 4 additions & 4 deletions integreat_cms/cms/models/contact/contact.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Generator, TYPE_CHECKING
from typing import List, TYPE_CHECKING

from django.conf import settings
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
Expand Down Expand Up @@ -225,15 +225,15 @@ def referring_event_translations(self) -> QuerySet[EventTranslation]:
)

@cached_property
def referring_objects(self) -> Generator[AbstractContentTranslation]:
def referring_objects(self) -> List[AbstractContentTranslation]:
"""
Returns a list of all objects linking to this contact.
:return: all objects referring to this contact
"""
return (
return [
link.content_object for link in Link.objects.filter(url__url=self.full_url)
)
]

def archive(self) -> None:
"""
Expand Down
6 changes: 4 additions & 2 deletions integreat_cms/cms/templates/contacts/contact_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ <h3 class="heading font-bold text-black">
data-confirmation-title="{{ archive_dialog_title }}"
data-confirmation-text="{{ archive_dialog_text }}"
data-confirmation-subject="{{ contact_form.instance.name }}"
data-action="{% url 'archive_contact' contact_id=contact_form.instance.id region_slug=request.region.slug %}">
data-action="{% url 'archive_contact' contact_id=contact_form.instance.id region_slug=request.region.slug %}"
{% if contact_form.instance.referring_objects %}disabled{% endif %}>
<i icon-name="archive" class="mr-2"></i>
{% translate "Archive this contact" %}
</button>
Expand All @@ -115,7 +116,8 @@ <h3 class="heading font-bold text-black">
data-confirmation-title="{{ delete_dialog_title }}"
data-confirmation-text="{{ delete_dialog_text }}"
data-confirmation-subject="{{ contact_form.instance.name }}"
data-action="{% url 'delete_contact' contact_id=contact_form.instance.id region_slug=request.region.slug %}">
data-action="{% url 'delete_contact' contact_id=contact_form.instance.id region_slug=request.region.slug %}"
{% if contact_form.instance.referring_objects %}disabled{% endif %}>
<i icon-name="trash-2" class="mr-2"></i>
{% translate "Delete contact" %}
</button>
Expand Down
54 changes: 35 additions & 19 deletions integreat_cms/cms/views/contacts/contact_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,25 @@ def archive_contact(
to_be_archived_contact = get_object_or_404(
Contact, id=contact_id, location__region=request.region
)
to_be_archived_contact.archive()

messages.success(
if not to_be_archived_contact.referring_objects:
to_be_archived_contact.archive()
messages.success(
request,
_("Contact {0} was successfully archived").format(to_be_archived_contact),
)
return redirect(
"contacts",
**{
"region_slug": region_slug,
},
)
messages.error(
request,
_("Contact {0} was successfully archived").format(to_be_archived_contact),
)
return redirect(
"contacts",
**{
"region_slug": region_slug,
},
_('Cannot archive contact "{0}" while content objects refer to it.').format(
to_be_archived_contact,
),
)
return redirect("edit_contact", region_slug=region_slug, contact_id=contact_id)


@permission_required("cms.delete_contact")
Expand All @@ -57,16 +64,25 @@ def delete_contact(
to_be_deleted_contact = get_object_or_404(
Contact, id=contact_id, location__region=request.region
)
to_be_deleted_contact.delete()
messages.success(
request, _("Contact {0} was successfully deleted").format(to_be_deleted_contact)
)
return redirect(
"contacts",
**{
"region_slug": region_slug,
},
if not to_be_deleted_contact.referring_objects:
to_be_deleted_contact.delete()
messages.success(
request,
_("Contact {0} was successfully deleted").format(to_be_deleted_contact),
)
return redirect(
"contacts",
**{
"region_slug": region_slug,
},
)
messages.error(
request,
_('Cannot delete contact "{0}" while content objects refer to it.').format(
to_be_deleted_contact,
),
)
return redirect("edit_contact", region_slug=region_slug, contact_id=contact_id)


@permission_required("cms.change_contact")
Expand Down
47 changes: 42 additions & 5 deletions integreat_cms/cms/views/contacts/contact_bulk_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from django.contrib import messages
from django.db.models import Q
from django.utils.translation import ngettext_lazy
from django.utils.translation import gettext_lazy, ngettext_lazy

from ...models import Contact
from ...utils.stringify_list import iter_to_string
Expand Down Expand Up @@ -50,10 +50,14 @@ def post(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
"""

archive_successful = []
archive_failure = []

for content_object in self.get_queryset():
content_object.archive()
archive_successful.append(content_object)
if not content_object.referring_objects:
content_object.archive()
archive_successful.append(content_object)
else:
archive_failure.append(content_object)

if archive_successful:
messages.success(
Expand All @@ -69,6 +73,20 @@ def post(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
),
)

if archive_failure:
messages.error(
request,
ngettext_lazy(
"{model_name} {object_names} cannot be archived while content objects refer to it.",
"The following {model_name_plural} could be archived: {object_names}",
).format(
len(archive_failure),
model_name=self.model._meta.verbose_name.title(),
model_name_plural=self.model._meta.verbose_name_plural,
object_names=iter_to_string(archive_failure),
),
)

return super().post(request, *args, **kwargs)


Expand Down Expand Up @@ -131,9 +149,14 @@ def post(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
:return: The redirect
"""
delete_sucessful = []
delete_failure = []

for content_object in self.get_queryset():
content_object.delete()
delete_sucessful.append(content_object)
if not content_object.referring_objects:
content_object.delete()
delete_sucessful.append(content_object)
else:
delete_failure.append(content_object)

if delete_sucessful:
messages.success(
Expand All @@ -149,4 +172,18 @@ def post(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
),
)

if delete_failure:
messages.error(
request,
ngettext_lazy(
"{model_name} {object_names} cannot be deleted while content objects refer to it.",
"The following {model_name_plural} could be deleted: {object_names}",
len(delete_failure),
).format(
model_name=self.model._meta.verbose_name.title(),
model_name_plural=self.model._meta.verbose_name_plural,
object_names=iter_to_string(delete_failure),
),
)

return super().post(request, *args, **kwargs)
40 changes: 40 additions & 0 deletions integreat_cms/locale/de/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -9159,11 +9159,23 @@ msgstr[1] ""
msgid "Contact {0} was successfully archived"
msgstr "Kontakt {0} wurde erfolgreich archiviert"

#: cms/views/contacts/contact_actions.py
#, python-brace-format
msgid "Cannot archive contact \"{0}\" while content objects refer to it."
msgstr ""
"Kontakt {0} kann nicht archiviert werden solange Inhalte auf ihn verweisen."

#: cms/views/contacts/contact_actions.py
#, python-brace-format
msgid "Contact {0} was successfully deleted"
msgstr "Kontakt {0} wurde erfolgreich gelöscht."

#: cms/views/contacts/contact_actions.py
#, python-brace-format
msgid "Cannot delete contact \"{0}\" while content objects refer to it."
msgstr ""
"Kontakt {0} kann nicht gelöscht werden solange Inhalte auf ihn verweisen."

#: cms/views/contacts/contact_actions.py
#, python-brace-format
msgid "Contact {0} was successfully restored"
Expand All @@ -9174,6 +9186,20 @@ msgstr "Kontakt {0} wurde erfolgreich wiederhergestellt"
msgid "Contact {0} was successfully copied"
msgstr "Kontakt {0} wurde erfolgreich kopiert"

#: cms/views/contacts/contact_bulk_actions.py
#, python-brace-format
msgid ""
"{model_name} {object_names} cannot be archived while content objects refer "
"to it."
msgid_plural ""
"The following {model_name_plural} could be archived: {object_names}"
msgstr[0] ""
"{model_name} {object_names} kann nicht archiviert werden solange Inhalte auf "
"ihn verweisen."
msgstr[1] ""
"Die folgenden {model_name_plural} konnten nicht archiviert werden: "
"{object_names}"

#: cms/views/contacts/contact_bulk_actions.py
#: cms/views/organizations/organization_bulk_actions.py
#, python-brace-format
Expand All @@ -9184,6 +9210,20 @@ msgstr[0] "{model_name} {object_names} wurde erfolgreich gelöscht."
msgstr[1] ""
"Die folgenden {model_name_plural} wurden erfolgreich gelöscht: {object_names}"

#: cms/views/contacts/contact_bulk_actions.py
#, python-brace-format
msgid ""
"{model_name} {object_names} cannot be deleted while content objects refer to "
"it."
msgid_plural ""
"The following {model_name_plural} could be deleted: {object_names}"
msgstr[0] ""
"{model_name} {object_names} kann nicht gelöscht werden solange Inhalte auf "
"ihn verweisen."
msgstr[1] ""
"Die folgenden {model_name_plural} konnten nicht gelöscht werden: "
"{object_names}"

#: cms/views/contacts/contact_context_mixin.py
msgid "Please confirm that you really want to archive this contact"
msgstr "Bitte bestätigen Sie, dass dieser Kontakt archiviert werden soll."
Expand Down
Loading

0 comments on commit a295ac3

Please sign in to comment.