diff --git a/integreat_cms/cms/fixtures/test_data.json b/integreat_cms/cms/fixtures/test_data.json
index 748b2b0992..b3234b458f 100644
--- a/integreat_cms/cms/fixtures/test_data.json
+++ b/integreat_cms/cms/fixtures/test_data.json
@@ -958,7 +958,7 @@
"fields": {
"title": "Integrationsbeauftragte",
"name": "Martina Musterfrau",
- "poi": 6,
+ "location": 6,
"email": "martina-musterfrau@example.com",
"phone_number": "0123456789",
"website": "",
@@ -973,7 +973,7 @@
"fields": {
"title": "Integrationsberaterin",
"name": "Melanie Musterfrau",
- "poi": 6,
+ "location": 6,
"email": "melanie-musterfrau@example.com",
"phone_number": "0987654321",
"website": "www.random-page.com",
@@ -988,7 +988,7 @@
"fields": {
"title": "Integrationsbeauftragte",
"name": "Mariana Musterfrau",
- "poi": 6,
+ "location": 6,
"email": "mariana-musterfrau@example.com",
"phone_number": "0123456789",
"website": "https://integreat-app.de/",
diff --git a/integreat_cms/cms/forms/__init__.py b/integreat_cms/cms/forms/__init__.py
index 8334077334..918ca0575a 100644
--- a/integreat_cms/cms/forms/__init__.py
+++ b/integreat_cms/cms/forms/__init__.py
@@ -6,6 +6,7 @@
from __future__ import annotations
from .chat.chat_message_form import ChatMessageForm
+from .contacts.contact_form import ContactForm
from .events.event_filter_form import EventFilterForm
from .events.event_form import EventForm
from .events.event_translation_form import EventTranslationForm
diff --git a/integreat_cms/cms/forms/contacts/__init__.py b/integreat_cms/cms/forms/contacts/__init__.py
new file mode 100644
index 0000000000..303c896a53
--- /dev/null
+++ b/integreat_cms/cms/forms/contacts/__init__.py
@@ -0,0 +1,3 @@
+"""
+Forms for creating and modifying contact objects
+"""
diff --git a/integreat_cms/cms/forms/contacts/contact_form.py b/integreat_cms/cms/forms/contacts/contact_form.py
new file mode 100644
index 0000000000..14b44fccc8
--- /dev/null
+++ b/integreat_cms/cms/forms/contacts/contact_form.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+
+import logging
+from typing import TYPE_CHECKING
+
+from django.utils.translation import gettext_lazy as _
+
+from ...models import Contact
+from ..custom_model_form import CustomModelForm
+
+if TYPE_CHECKING:
+ from typing import Any
+
+logger = logging.getLogger(__name__)
+
+
+class ContactForm(CustomModelForm):
+ """
+ Form for creating and modifying contact objects
+ """
+
+ class Meta:
+ """
+ This class contains additional meta configuration of the form class, see the :class:`django.forms.ModelForm`
+ for more information.
+ """
+
+ #: The model of this :class:`django.forms.ModelForm`
+ model = Contact
+ #: The fields of the model which should be handled by this form
+ fields = [
+ "title",
+ "name",
+ "location",
+ "email",
+ "phone_number",
+ "website",
+ ]
+
+ error_messages = {
+ "location": {"invalid_choice": _("Location cannot be empty.")}
+ }
diff --git a/integreat_cms/cms/migrations/0106_update_contact.py b/integreat_cms/cms/migrations/0106_update_contact.py
new file mode 100644
index 0000000000..41794eedcf
--- /dev/null
+++ b/integreat_cms/cms/migrations/0106_update_contact.py
@@ -0,0 +1,67 @@
+# Generated by Django 4.2.13 on 2024-08-20 16:10
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ """
+ Make the fields "title" and "name" not mandatory.
+ Rename the field from "poi" to "location".
+ """
+
+ dependencies = [
+ ("cms", "0105_languagetreenode_languagetreenode_unique_lft_tree_and_more"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="contact",
+ name="title",
+ field=models.CharField(blank=True, max_length=200, verbose_name="title"),
+ ),
+ migrations.AlterField(
+ model_name="contact",
+ name="name",
+ field=models.CharField(blank=True, max_length=200, verbose_name="name"),
+ ),
+ migrations.RenameField(
+ model_name="contact",
+ old_name="poi",
+ new_name="location",
+ ),
+ migrations.AlterField(
+ model_name="contact",
+ name="location",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="contacts",
+ to="cms.poi",
+ verbose_name="location",
+ ),
+ ),
+ migrations.AddConstraint(
+ model_name="contact",
+ constraint=models.UniqueConstraint(
+ models.F("location"),
+ condition=models.Q(("title", "")),
+ name="contact_singular_empty_title_per_location",
+ violation_error_message="Only one contact per location can have an empty title.",
+ ),
+ ),
+ migrations.AddConstraint(
+ model_name="contact",
+ constraint=models.CheckConstraint(
+ check=models.Q(
+ models.Q(("title", ""), _negated=True),
+ models.Q(("name", ""), _negated=True),
+ models.Q(("email", ""), _negated=True),
+ models.Q(("phone_number", ""), _negated=True),
+ models.Q(("website", ""), _negated=True),
+ _connector="OR",
+ ),
+ name="contact_non_empty",
+ violation_error_message="One of the following fields must be filled: title, name, e-mail, phone number, website.",
+ ),
+ ),
+ ]
diff --git a/integreat_cms/cms/models/contact/contact.py b/integreat_cms/cms/models/contact/contact.py
index ce343c1cae..680155840a 100644
--- a/integreat_cms/cms/models/contact/contact.py
+++ b/integreat_cms/cms/models/contact/contact.py
@@ -1,4 +1,5 @@
from django.db import models
+from django.db.models import Q
from django.utils import timezone
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
@@ -13,17 +14,22 @@ class Contact(AbstractBaseModel):
Data model representing a contact
"""
- title = models.CharField(max_length=200, verbose_name=_("title"))
- name = models.CharField(max_length=200, verbose_name=_("name"))
- poi = models.ForeignKey(
- POI, on_delete=models.PROTECT, verbose_name=_("POI"), related_name="contacts"
+ title = models.CharField(max_length=200, blank=True, verbose_name=_("title"))
+ name = models.CharField(max_length=200, blank=True, verbose_name=_("name"))
+ location = models.ForeignKey(
+ POI,
+ on_delete=models.PROTECT,
+ verbose_name=_("location"),
+ related_name="contacts",
)
email = models.EmailField(
blank=True,
verbose_name=_("email address"),
)
phone_number = models.CharField(
- max_length=250, blank=True, verbose_name=_("phone number")
+ max_length=250,
+ blank=True,
+ verbose_name=_("phone number"),
)
website = models.URLField(blank=True, max_length=250, verbose_name=_("website"))
archived = models.BooleanField(
@@ -46,7 +52,7 @@ def region(self) -> Region:
:return: Region this contact belongs to
"""
- return self.poi.region
+ return self.location.region
def __str__(self) -> str:
"""
@@ -95,3 +101,25 @@ class Meta:
verbose_name_plural = _("contacts")
default_permissions = ("change", "delete", "view")
ordering = ["name"]
+
+ constraints = [
+ models.UniqueConstraint(
+ "location",
+ condition=Q(title=""),
+ name="contact_singular_empty_title_per_location",
+ violation_error_message=_(
+ "Only one contact per location can have an empty title."
+ ),
+ ),
+ models.CheckConstraint(
+ check=~Q(title="")
+ | ~Q(name="")
+ | ~Q(email="")
+ | ~Q(phone_number="")
+ | ~Q(website=""),
+ name="contact_non_empty",
+ violation_error_message=_(
+ "One of the following fields must be filled: title, name, e-mail, phone number, website."
+ ),
+ ),
+ ]
diff --git a/integreat_cms/cms/templates/ajax_poi_form/poi_box.html b/integreat_cms/cms/templates/ajax_poi_form/poi_box.html
index 1d5dd3e949..c172044bf3 100644
--- a/integreat_cms/cms/templates/ajax_poi_form/poi_box.html
+++ b/integreat_cms/cms/templates/ajax_poi_form/poi_box.html
@@ -11,17 +11,24 @@
{{ title }}
{% endblock collapsible_box_title %}
{% block collapsible_box_content %}
- {% render_field form.has_not_location class+='inline-block' %}
-
+ {% if current_menu_item == "events_form" %}
+ {% render_field form.has_not_location class+='inline-block' %}
+
+ {% endif %}
+ {% if current_menu_item == "contacts" %}
+
+ {{ help_text }}
+
+ {% endif %}
- {% translate "Name of event location" as poi_title_placeholder %}
+ {% translate "Name of location" as poi_title_placeholder %}
- {% translate "Create an event location or start typing the name of an existing location. Only published locations can be set as event venues" %}.
+ {% if current_menu_item == "events_form" %}
+ {{ help_text }}
+ {% endif %}
{% for contact in poi_form.instance.contacts.all %}
-
+
{{ contact.title }} {{ contact.name }}
{% endfor %}
diff --git a/integreat_cms/cms/urls/protected.py b/integreat_cms/cms/urls/protected.py
index a56b4a1f7c..12f6376f8c 100644
--- a/integreat_cms/cms/urls/protected.py
+++ b/integreat_cms/cms/urls/protected.py
@@ -1404,10 +1404,20 @@
contacts.ContactListView.as_view(archived=True),
name="archived_contacts",
),
+ path(
+ "new/",
+ contacts.ContactFormView.as_view(),
+ name="new_contact",
+ ),
path(
"/",
include(
[
+ path(
+ "edit/",
+ contacts.ContactFormView.as_view(),
+ name="edit_contact",
+ ),
path(
"copy/",
contacts.copy_contact,
diff --git a/integreat_cms/cms/views/contacts/__init__.py b/integreat_cms/cms/views/contacts/__init__.py
index 232875651a..e3aef5a205 100644
--- a/integreat_cms/cms/views/contacts/__init__.py
+++ b/integreat_cms/cms/views/contacts/__init__.py
@@ -4,4 +4,5 @@
delete_contact,
restore_contact,
)
+from .contact_form_view import ContactFormView
from .contact_list_view import ContactListView
diff --git a/integreat_cms/cms/views/contacts/contact_actions.py b/integreat_cms/cms/views/contacts/contact_actions.py
index 52df42b8b6..65f63cd4c1 100644
--- a/integreat_cms/cms/views/contacts/contact_actions.py
+++ b/integreat_cms/cms/views/contacts/contact_actions.py
@@ -26,7 +26,7 @@ def archive_contact(
:return: A redirection to the :class:`~integreat_cms.cms.views.contacts.contact_list_view.ContactListView`
"""
to_be_archived_contact = get_object_or_404(
- Contact, id=contact_id, poi__region=request.region
+ Contact, id=contact_id, location__region=request.region
)
to_be_archived_contact.archive()
@@ -55,7 +55,7 @@ def delete_contact(
:return: A redirection to the :class:`~integreat_cms.cms.views.contacts.contact_list_view.ContactListView`
"""
to_be_deleted_contact = get_object_or_404(
- Contact, id=contact_id, poi__region=request.region
+ Contact, id=contact_id, location__region=request.region
)
to_be_deleted_contact.delete()
messages.success(
@@ -82,7 +82,7 @@ def restore_contact(
:return: A redirection to the :class:`~integreat_cms.cms.views.contacts.contact_list_view.ContactListView`
"""
to_be_restored_contact = get_object_or_404(
- Contact, id=contact_id, poi__region=request.region
+ Contact, id=contact_id, location__region=request.region
)
to_be_restored_contact.restore()
@@ -112,7 +112,7 @@ def copy_contact(
:return: A redirection to the :class:`~integreat_cms.cms.views.contacts.contact_list_view.ContactListView`
"""
to_be_copied_contact = get_object_or_404(
- Contact, id=contact_id, poi__region=request.region
+ Contact, id=contact_id, location__region=request.region
)
to_be_copied_contact.copy()
diff --git a/integreat_cms/cms/views/contacts/contact_context_mixin.py b/integreat_cms/cms/views/contacts/contact_context_mixin.py
index a3c88fa88c..acf8123426 100644
--- a/integreat_cms/cms/views/contacts/contact_context_mixin.py
+++ b/integreat_cms/cms/views/contacts/contact_context_mixin.py
@@ -27,6 +27,7 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
context.update(
{
+ "current_menu_item": "contacts",
"archive_dialog_title": _(
"Please confirm that you really want to archive this contact"
),
diff --git a/integreat_cms/cms/views/contacts/contact_form_view.py b/integreat_cms/cms/views/contacts/contact_form_view.py
new file mode 100644
index 0000000000..c86eba05e2
--- /dev/null
+++ b/integreat_cms/cms/views/contacts/contact_form_view.py
@@ -0,0 +1,148 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from django.contrib import messages
+from django.shortcuts import redirect, render
+from django.utils.decorators import method_decorator
+from django.utils.translation import gettext_lazy as _
+from django.views.generic import TemplateView
+
+from ...decorators import permission_required
+from ...forms import ContactForm
+from ...models import Contact
+from ...utils.translation_utils import gettext_many_lazy as __
+from .contact_context_mixin import ContactContextMixin
+
+if TYPE_CHECKING:
+ from typing import Any
+
+ from django.http import HttpRequest, HttpResponse
+
+
+@method_decorator(permission_required("cms.view_contact"), name="dispatch")
+@method_decorator(permission_required("cms.change_contact"), name="post")
+class ContactFormView(TemplateView, ContactContextMixin):
+ """
+ Class for rendering the contact form
+ """
+
+ #: The template to render (see :class:`~django.views.generic.base.TemplateResponseMixin`)
+ template_name = "contacts/contact_form.html"
+
+ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
+ r"""
+ Render contact form for HTTP GET requests
+
+ :param request: Object representing the user call
+ :param \*args: The supplied arguments
+ :param \**kwargs: The supplied keyword arguments
+ :return: The rendered template response
+ """
+ region = request.region
+ contact_instance = Contact.objects.filter(
+ id=kwargs.get("contact_id"), location__region=region
+ ).first()
+
+ if contact_instance and contact_instance.archived:
+ disabled = True
+ messages.warning(
+ request, _("You cannot edit this contact because it is archived.")
+ )
+ elif not request.user.has_perm("cms.change_contact"):
+ disabled = True
+ messages.warning(
+ request, _("You don't have the permission to edit contacts.")
+ )
+ else:
+ disabled = False
+
+ contact_form = ContactForm(
+ instance=contact_instance,
+ disabled=disabled,
+ additional_instance_attributes={"region": region},
+ )
+
+ help_text = (
+ _("This location is used for the contact.")
+ if contact_instance
+ else _(
+ "Select a location to use for your contact or create a new location. Only published locations can be set."
+ )
+ )
+
+ return render(
+ request,
+ self.template_name,
+ {
+ **self.get_context_data(**kwargs),
+ "contact_form": contact_form,
+ "poi": contact_instance.location if contact_instance else None,
+ "referring_pages": None, # to implement later, how do we collect such pages?
+ "referring_locations": None, # to implement later, how do we collect such POIs?
+ "referring_events": None, # to implement later, how do we collect such Events?
+ "help_text": help_text,
+ },
+ )
+
+ def post(self, request: HttpRequest, **kwargs: Any) -> HttpResponse:
+ r"""
+ Save contact and ender contact form for HTTP POST requests
+
+ :param request: Object representing the user call
+ :param \**kwargs: The supplied keyword arguments
+ :raises ~django.core.exceptions.PermissionDenied: If user does not have the permission to change contact
+
+ :return: The rendered template response
+ """
+ region = request.region
+
+ contact_instance = Contact.objects.filter(
+ id=kwargs.get("contact_id"), location__region=region
+ ).first()
+ contact_form = ContactForm(
+ data=request.POST,
+ instance=contact_instance,
+ additional_instance_attributes={"region": region},
+ )
+
+ if not contact_form.is_valid():
+ contact_form.add_error_messages(request)
+ else:
+ contact_form.save()
+ if not contact_instance:
+ messages.success(
+ request,
+ _('Contact "{}" was successfully created').format(
+ contact_form.instance
+ ),
+ )
+ elif not contact_form.has_changed():
+ messages.info(request, _("No changes detected"))
+ else:
+ messages.success(
+ request,
+ _('Contact "{}" was successfully saved').format(
+ contact_form.instance
+ ),
+ )
+ return redirect(
+ "edit_contact",
+ **{
+ "contact_id": contact_form.instance.id,
+ "region_slug": region.slug,
+ },
+ )
+
+ return render(
+ request,
+ self.template_name,
+ {
+ **self.get_context_data(**kwargs),
+ "contact_form": contact_form,
+ "poi": contact_instance.location if contact_instance else None,
+ "referring_pages": None,
+ "referring_locations": None,
+ "referring_events": None,
+ },
+ )
diff --git a/integreat_cms/cms/views/contacts/contact_list_view.py b/integreat_cms/cms/views/contacts/contact_list_view.py
index 07e1c51a4c..72cd84313d 100644
--- a/integreat_cms/cms/views/contacts/contact_list_view.py
+++ b/integreat_cms/cms/views/contacts/contact_list_view.py
@@ -40,11 +40,11 @@ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
region = request.region
contacts = Contact.objects.filter(
- poi__region=region, archived=self.archived
- ).select_related("poi")
+ location__region=region, archived=self.archived
+ ).select_related("location")
archived_count = Contact.objects.filter(
- poi__region=region, archived=True
+ location__region=region, archived=True
).count()
chunk_size = int(request.GET.get("size", settings.PER_PAGE))
diff --git a/integreat_cms/cms/views/events/event_context_mixin.py b/integreat_cms/cms/views/events/event_context_mixin.py
index a8837180ea..3a4b375238 100644
--- a/integreat_cms/cms/views/events/event_context_mixin.py
+++ b/integreat_cms/cms/views/events/event_context_mixin.py
@@ -48,6 +48,9 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"delete_dialog_text": _(
"All translations of this event will also be deleted."
),
+ "help_text": _(
+ "Create an event location or start typing the name of an existing location. Only published locations can be set as event venues."
+ ),
}
)
return context
diff --git a/integreat_cms/cms/views/regions/region_actions.py b/integreat_cms/cms/views/regions/region_actions.py
index e98ca0da59..dde1908597 100644
--- a/integreat_cms/cms/views/regions/region_actions.py
+++ b/integreat_cms/cms/views/regions/region_actions.py
@@ -97,7 +97,7 @@ def delete_region(
# Prevent ProtectedError when media files get deleted before their usages as organization logo
region.organizations.all().delete()
# Prevent ProtectedError when location gets deleted before their contacts
- Contact.objects.filter(poi__region=region).delete()
+ Contact.objects.filter(location__region=region).delete()
# Prevent IntegrityError when multiple feedback objects exist
region.feedback.all().delete()
# Disable linkchecking while deleting this region
diff --git a/integreat_cms/locale/de/LC_MESSAGES/django.po b/integreat_cms/locale/de/LC_MESSAGES/django.po
index 4677719fb7..16f9f2eb5a 100644
--- a/integreat_cms/locale/de/LC_MESSAGES/django.po
+++ b/integreat_cms/locale/de/LC_MESSAGES/django.po
@@ -1806,6 +1806,10 @@ msgstr "Vierte Woche"
msgid "Last week"
msgstr "Letzte Woche"
+#: cms/forms/contacts/contact_form.py
+msgid "Location cannot be empty."
+msgstr "Ort darf nicht leer sein."
+
#: cms/forms/custom_content_model_form.py
msgid ""
"Could not update because this content because it is already being edited by "
@@ -2708,8 +2712,9 @@ msgstr "Nutzer-Chats"
msgid "name"
msgstr "Name"
-#: cms/models/contact/contact.py
-msgid "POI"
+#: cms/models/contact/contact.py cms/models/events/event.py
+#: cms/models/pois/poi.py cms/models/pois/poi_translation.py
+msgid "location"
msgstr "Ort"
#: cms/models/contact/contact.py cms/models/pois/poi.py
@@ -2747,10 +2752,17 @@ msgstr "Kontakt"
msgid "contacts"
msgstr "Kontakte"
-#: cms/models/events/event.py cms/models/pois/poi.py
-#: cms/models/pois/poi_translation.py
-msgid "location"
-msgstr "Ort"
+#: cms/models/contact/contact.py
+msgid "Only one contact per location can have an empty title."
+msgstr "Nur ein Kontakt per Ort darf leeren Titel haben."
+
+#: cms/models/contact/contact.py
+msgid ""
+"One of the following fields must be filled: title, name, e-mail, phone "
+"number, website."
+msgstr ""
+"Eines der folgenden Felder muss ausgefüllt werden: Title, Name, E-mail, "
+"Telefonnummer, Website."
#: cms/models/events/event.py
msgid "start"
@@ -2973,7 +2985,8 @@ msgid "imprint feedback"
msgstr "Impressums-Feedback"
#: cms/models/feedback/map_feedback.py cms/models/regions/region.py
-#: cms/templates/_base.html cms/templates/organizations/organization_form.html
+#: cms/templates/_base.html cms/templates/contacts/contact_form.html
+#: cms/templates/organizations/organization_form.html
#: cms/templates/pois/poi_list.html
msgid "Locations"
msgstr "Orte"
@@ -4113,11 +4126,13 @@ msgid "used budget"
msgstr "verbrauchtes Budget"
#: cms/models/regions/region.py cms/templates/_base.html
+#: cms/templates/contacts/contact_form.html
#: cms/templates/organizations/organization_form.html
msgid "Pages"
msgstr "Seiten"
#: cms/models/regions/region.py cms/templates/_base.html
+#: cms/templates/contacts/contact_form.html
#: cms/templates/events/event_list.html
msgid "Events"
msgstr "Veranstaltungen"
@@ -4723,8 +4738,9 @@ msgstr "Kontaktperson"
msgid "Spoken Languages"
msgstr "Gesprochene Sprachen"
-#: cms/templates/_tinymce_config.html cms/templates/events/event_form.html
-#: cms/templates/hix_widget.html cms/templates/imprint/imprint_form.html
+#: cms/templates/_tinymce_config.html cms/templates/contacts/contact_form.html
+#: cms/templates/events/event_form.html cms/templates/hix_widget.html
+#: cms/templates/imprint/imprint_form.html
#: cms/templates/imprint/imprint_sbs.html
#: cms/templates/languagetreenodes/languagetreenode_form.html
#: cms/templates/pages/page_form.html cms/templates/pages/page_sbs.html
@@ -4781,21 +4797,12 @@ msgid "Publish"
msgstr "Veröffentlichen"
#: cms/templates/ajax_poi_form/poi_box.html
-msgid "Name of event location"
-msgstr "Name des Veranstaltungsortes"
-
-#: cms/templates/ajax_poi_form/poi_box.html
-msgid "Remove location from event"
-msgstr "Veranstaltungsort von Veranstaltung entfernen"
+msgid "Name of location"
+msgstr "Name des Ortes"
#: cms/templates/ajax_poi_form/poi_box.html
-msgid ""
-"Create an event location or start typing the name of an existing location. "
-"Only published locations can be set as event venues"
-msgstr ""
-"Erstellen Sie einen Veranstaltungsort oder beginnen Sie den Namen eines "
-"bestehenden Veranstaltungsortes einzutippen. Nur öffentliche Orte können als "
-"Veranstaltungsorte verwendet werden"
+msgid "Remove location"
+msgstr "Ort entfernen"
#: cms/templates/ajax_poi_form/poi_box.html
#: cms/templates/pois/poi_form_sidebar/position_box.html
@@ -5163,6 +5170,80 @@ msgstr "Chat"
msgid "Send message"
msgstr "Nachricht abschicken"
+#: cms/templates/contacts/contact_form.html
+msgid "Edit contact"
+msgstr "Kontakt bearbeiten"
+
+#: cms/templates/contacts/contact_form.html
+msgid "Create new contact"
+msgstr "Kontakt erstellen"
+
+#: cms/templates/contacts/contact_form.html
+#: cms/templates/languagetreenodes/languagetreenode_form.html
+#: cms/templates/offertemplates/offertemplate_form.html
+#: cms/views/media/media_context_mixin.py
+msgid "Create"
+msgstr "Erstellen"
+
+#: cms/templates/contacts/contact_form.html
+msgid "Connect a location"
+msgstr "Ort verknüpfen"
+
+#: cms/templates/contacts/contact_form.html
+msgid "Manage contact data"
+msgstr "Kontaktdaten verwalten"
+
+#: cms/templates/contacts/contact_form.html
+msgid ""
+"Add missing data or change existing data. Select the data you want to import."
+msgstr ""
+"Ergänzen Sie fehlende Daten oder ändern bestehende Daten. Wählen Sie die "
+"Daten aus, die übernommen werden sollen."
+
+#: cms/templates/contacts/contact_form.html
+msgid "Contact information"
+msgstr "Kontaktinformationen"
+
+#: cms/templates/contacts/contact_form.html
+msgid "This contact is referred to in those contents."
+msgstr "Dieser Kontakt wird in folgenden Inhalten verwendet."
+
+#: cms/templates/contacts/contact_form.html
+msgid "This contact is not currently referred to on any page."
+msgstr "Zur Zeit wird dieser Kontakt in keiner Seite verwendet."
+
+#: cms/templates/contacts/contact_form.html
+msgid "This contact is not currently referred to in any location."
+msgstr "Zur Zeit wird dieser Kontakt in keinem Ort verwendet."
+
+#: cms/templates/contacts/contact_form.html
+msgid "This contact is not currently referred to in any event."
+msgstr "Zur Zeit wird dieser Kontakt in keiner Veranstaltung verwendet."
+
+#: cms/templates/contacts/contact_form.html
+#: cms/templates/contacts/contact_list_row.html
+msgid "Archive contact"
+msgstr "Kontakte archivieren"
+
+#: cms/templates/contacts/contact_form.html
+msgid "Archive this contact"
+msgstr "Kontakt archivieren"
+
+#: cms/templates/contacts/contact_form.html
+#: cms/templates/pages/page_form_sidebar/actions_box.html
+#: cms/templates/pages/page_tree_archived_node.html
+msgid "Restore page"
+msgstr "Seite wiederherstellen"
+
+#: cms/templates/contacts/contact_form.html
+msgid "Restore this contact"
+msgstr "Kontakt wiederherstellen"
+
+#: cms/templates/contacts/contact_form.html
+#: cms/templates/contacts/contact_list_row.html
+msgid "Delete contact"
+msgstr "Kontakt löschen"
+
#: cms/templates/contacts/contact_list.html
msgid "Archived Contacts"
msgstr "Archivierte Kontakte"
@@ -5175,6 +5256,10 @@ msgstr "Zurück zu Kontakte"
msgid "Archived contacts"
msgstr "Archivierte Kontakte"
+#: cms/templates/contacts/contact_list.html
+msgid "Create contact"
+msgstr "Kontakt erstellen"
+
#: cms/templates/contacts/contact_list.html
#: cms/templates/pages/_page_xliff_import_diff.html
#: cms/templates/push_notifications/push_notification_list.html
@@ -5275,14 +5360,6 @@ msgstr "Kontakt wiederherstellen"
msgid "Copy contact"
msgstr "Kontakt kopieren"
-#: cms/templates/contacts/contact_list_row.html
-msgid "Archive contact"
-msgstr "Kontakte archivieren"
-
-#: cms/templates/contacts/contact_list_row.html
-msgid "Delete contact"
-msgstr "Kontakt löschen"
-
#: cms/templates/content_versions.html
#, python-format
msgid "\"Versions of %(content_title)s\""
@@ -6502,12 +6579,6 @@ msgstr "Sprach-Knoten \"%(translated_language_name)s\" bearbeiten"
msgid "Add language to this region"
msgstr "Sprache zu dieser Region hinzufügen"
-#: cms/templates/languagetreenodes/languagetreenode_form.html
-#: cms/templates/offertemplates/offertemplate_form.html
-#: cms/views/media/media_context_mixin.py
-msgid "Create"
-msgstr "Erstellen"
-
#: cms/templates/languagetreenodes/languagetreenode_form.html
msgid "Create and add more"
msgstr "Erstellen und weitere hinzufügen"
@@ -6964,11 +7035,6 @@ msgstr "Archiviert, weil eine übergeordnete Seite archiviert ist"
msgid "Mark this page as up-to-date"
msgstr "Seite als aktuell markieren"
-#: cms/templates/pages/page_form_sidebar/actions_box.html
-#: cms/templates/pages/page_tree_archived_node.html
-msgid "Restore page"
-msgstr "Seite wiederherstellen"
-
#: cms/templates/pages/page_form_sidebar/actions_box.html
msgid "Restore this page"
msgstr "Diese Seite wiederherstellen"
@@ -8916,6 +8982,39 @@ msgstr ""
msgid "Please confirm that you really want to delete this contact"
msgstr "Bitte bestätigen Sie, dass dieser Kontakt gelöscht werden soll"
+#: cms/views/contacts/contact_form_view.py
+msgid "You cannot edit this contact because it is archived."
+msgstr "Sie können diesen Kontakt nicht bearbeiten, weil er archiviert ist."
+
+#: cms/views/contacts/contact_form_view.py
+msgid "You don't have the permission to edit contacts."
+msgstr "Sie haben nicht die nötige Berechtigung, um Kontakte zu bearbeiten."
+
+#: cms/views/contacts/contact_form_view.py
+msgid "This location is used for the contact."
+msgstr "Dieser Ort wird für den Kontakt verwendet."
+
+#: cms/views/contacts/contact_form_view.py
+msgid ""
+"Select a location to use for your contact or create a new location. Only "
+"published locations can be set."
+msgstr ""
+"Wählen Sie einen Ort aus, der für ihren Kontakt verwendet werden soll oder "
+"erstellen Sie einen neuen Ort. Nur veröffentlichte Orte können verwendet "
+"werden."
+
+#: cms/views/contacts/contact_form_view.py
+msgid "Contact \"{}\" was successfully created"
+msgstr "Kontakt \"{}\" wurde erfolgreich erstellt"
+
+#: cms/views/contacts/contact_form_view.py cms/views/media/media_actions.py
+msgid "No changes detected"
+msgstr "Keine Änderungen vorgenommen"
+
+#: cms/views/contacts/contact_form_view.py
+msgid "Contact \"{}\" was successfully saved"
+msgstr "Kontakt \"{}\" wurde erfolgreich gespeichert"
+
#: cms/views/content_version_view.py
msgid "Back to the form"
msgstr "Zurück zum Formular"
@@ -9042,6 +9141,15 @@ msgstr "Bitte bestätigen Sie, dass diese Veranstaltung gelöscht werden soll"
msgid "All translations of this event will also be deleted."
msgstr "Alle Übersetzungen dieser Veranstaltung werden gelöscht."
+#: cms/views/events/event_context_mixin.py
+msgid ""
+"Create an event location or start typing the name of an existing location. "
+"Only published locations can be set as event venues."
+msgstr ""
+"Erstellen Sie einen Ort oder beginnen Sie den Namen eines bestehenden "
+"Veranstaltungsortes einzutippen. Nur veröffentlichte Orte können als "
+"Veranstaltungsorte verwendet werden."
+
#: cms/views/events/event_form_view.py
msgid "You cannot edit this event because it is archived."
msgstr ""
@@ -9308,10 +9416,6 @@ msgstr "Links wurden erfolgreich geprüft"
msgid "File \"{}\" was uploaded successfully"
msgstr "Datei \"{}\"wurde erfolgreich hochgeladen"
-#: cms/views/media/media_actions.py
-msgid "No changes detected"
-msgstr "Keine Änderungen vorgenommen"
-
#: cms/views/media/media_actions.py
msgid "File \"{}\" was saved successfully"
msgstr "Datei \"{}\" wurde erfolgreich gespeichert"
@@ -10769,6 +10873,51 @@ msgstr ""
"Diese Seite konnte nicht importiert werden, da sie zu einer anderen Region "
"gehört ({})."
+#~ msgid "E-mail from location"
+#~ msgstr "E-mail des Ortes"
+
+#~ msgid "Will be taken over from the location."
+#~ msgstr "Wird vom Ort übernommen."
+
+#~ msgid "phone number from location"
+#~ msgstr "Telefonnummer des Ortes"
+
+#~ msgid "website from location"
+#~ msgstr "Website des Ortes"
+
+#~ msgid ""
+#~ "E-mail address does not match with that of the selected location. Please "
+#~ "check again."
+#~ msgstr ""
+#~ "Die E-mail Adresse stimmt nicht mit der vom ausgewählten Ort überein. "
+#~ "Bitte überprüfen Sie sie erneut."
+
+#~ msgid ""
+#~ "Phone number does not match with that of the selected location. Please "
+#~ "check again."
+#~ msgstr ""
+#~ "Die Telefonnummer stimmt nicht mit der vom ausgewählten Ort überein. "
+#~ "Bitte überprüfen Sie sie erneut."
+
+#~ msgid ""
+#~ "Website URL does not match with that of the selected location. Please "
+#~ "check again."
+#~ msgstr ""
+#~ "Die Website URL stimmt nicht mit der vom ausgewählten Ort überein. Bitte "
+#~ "überprüfen Sie sie erneut."
+
+#~ msgid "Delete this contact"
+#~ msgstr "Diesen Kontakt löschen"
+
+#~ msgid "Name of related POI"
+#~ msgstr "Name des verlinkten Ortes"
+
+#~ msgid "Only published locations can be set as event venues"
+#~ msgstr "Nur veröffentlichte Orte können verwendet werden"
+
+#~ msgid "Remove location from event"
+#~ msgstr "Ort entfernen"
+
#~ msgid "Opening hours"
#~ msgstr "Öffnungszeiten"
@@ -10781,9 +10930,6 @@ msgstr ""
#~ msgid "Back to the location form"
#~ msgstr "Zurück zum Orts-Formular"
-#~ msgid "Name of related POI"
-#~ msgstr "Name des verlinkten Ortes"
-
#~ msgid "You cannot archive a location which is used by an event."
#~ msgstr ""
#~ "Der Ort kann nicht archiviert werden, da er von einer Veranstaltung "
@@ -10797,6 +10943,12 @@ msgstr ""
#~ msgid "Manage Contacts"
#~ msgstr "Kontakte verwalten"
+#~ msgid "Whether or not the website must be taken from the location."
+#~ msgstr "Ob Statistiken für die Region aktiviert sind oder nicht"
+
+#~ msgid "POI"
+#~ msgstr "Ort"
+
#~ msgid "Contents"
#~ msgstr "Inhalte"
@@ -11799,9 +11951,6 @@ msgstr ""
#~ msgid "POI is not public."
#~ msgstr "POI ist nicht veröffentlicht."
-#~ msgid "Translation cannot be imported"
-#~ msgstr "Übersetzung kann nicht importiert werden"
-
#~ msgid "The page or target language does not exist."
#~ msgstr "Die Seite oder Zielsprache existiert nicht."
diff --git a/integreat_cms/static/src/index.ts b/integreat_cms/static/src/index.ts
index 4216dce99f..b81aae6203 100644
--- a/integreat_cms/static/src/index.ts
+++ b/integreat_cms/static/src/index.ts
@@ -49,7 +49,7 @@ import "./js/grids/toggle-grid-checkbox";
import "./js/chat/send-chat-message";
import "./js/chat/delete-chat-message";
-import "./js/events/event-query-pois";
+import "./js/poi_box";
import "./js/events/conditional-fields";
import "./js/events/auto-complete";
diff --git a/integreat_cms/static/src/js/events/event-query-pois.ts b/integreat_cms/static/src/js/poi_box.ts
similarity index 95%
rename from integreat_cms/static/src/js/events/event-query-pois.ts
rename to integreat_cms/static/src/js/poi_box.ts
index 6e6193d27b..2f321ccf81 100644
--- a/integreat_cms/static/src/js/events/event-query-pois.ts
+++ b/integreat_cms/static/src/js/poi_box.ts
@@ -1,5 +1,5 @@
-import { createIconsAt } from "../utils/create-icons";
-import { getCsrfToken } from "../utils/csrf-token";
+import { createIconsAt } from "./utils/create-icons";
+import { getCsrfToken } from "./utils/csrf-token";
const toggleContactInfo = (infoType: string, info: string) => {
document.getElementById(infoType).textContent = `${info}`;
@@ -11,6 +11,13 @@ const toggleContactInfo = (infoType: string, info: string) => {
}
};
+const toggleContactFieldBox = (show: boolean) => {
+ const contactFieldsBox = document.getElementById("contact_fields");
+ contactFieldsBox?.classList.toggle("hidden", !show);
+ const contactUsageBox = document.getElementById("contact_usage");
+ contactUsageBox?.classList.toggle("hidden", !show);
+};
+
const renderPoiData = (
queryPlaceholder: string,
id: string,
@@ -42,6 +49,7 @@ const renderPoiData = (
);
document.getElementById("poi-query-result").classList.add("hidden");
(document.getElementById("poi-query-input") as HTMLInputElement).value = "";
+ toggleContactFieldBox(true);
};
const hidePoiFormWidget = () => {
@@ -203,6 +211,7 @@ const removePoi = () => {
document.getElementById("poi-address-container")?.classList.add("hidden");
// Clear the poi form
hidePoiFormWidget();
+ toggleContactFieldBox(false);
console.debug("Removed POI data");
};