Skip to content

Commit

Permalink
Add form for contact information
Browse files Browse the repository at this point in the history
Co-authored-by: David Venhoff <[email protected]>
Co-authored-by: Peter Nerlich <[email protected]>
  • Loading branch information
3 people authored and MizukiTemma committed Oct 4, 2024
1 parent 85d4c0d commit e01c256
Show file tree
Hide file tree
Showing 22 changed files with 722 additions and 104 deletions.
6 changes: 3 additions & 3 deletions integreat_cms/cms/fixtures/test_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,7 @@
"fields": {
"title": "Integrationsbeauftragte",
"name": "Martina Musterfrau",
"poi": 6,
"location": 6,
"email": "[email protected]",
"phone_number": "0123456789",
"website": "",
Expand All @@ -973,7 +973,7 @@
"fields": {
"title": "Integrationsberaterin",
"name": "Melanie Musterfrau",
"poi": 6,
"location": 6,
"email": "[email protected]",
"phone_number": "0987654321",
"website": "www.random-page.com",
Expand All @@ -988,7 +988,7 @@
"fields": {
"title": "Integrationsbeauftragte",
"name": "Mariana Musterfrau",
"poi": 6,
"location": 6,
"email": "[email protected]",
"phone_number": "0123456789",
"website": "https://integreat-app.de/",
Expand Down
1 change: 1 addition & 0 deletions integreat_cms/cms/forms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions integreat_cms/cms/forms/contacts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
Forms for creating and modifying contact objects
"""
42 changes: 42 additions & 0 deletions integreat_cms/cms/forms/contacts/contact_form.py
Original file line number Diff line number Diff line change
@@ -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.")}
}
67 changes: 67 additions & 0 deletions integreat_cms/cms/migrations/0106_update_contact.py
Original file line number Diff line number Diff line change
@@ -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.",
),
),
]
40 changes: 34 additions & 6 deletions integreat_cms/cms/models/contact/contact.py
Original file line number Diff line number Diff line change
@@ -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 _
Expand All @@ -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(
Expand All @@ -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:
"""
Expand Down Expand Up @@ -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."
),
),
]
25 changes: 17 additions & 8 deletions integreat_cms/cms/templates/ajax_poi_form/poi_box.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,24 @@
{{ title }}
{% endblock collapsible_box_title %}
{% block collapsible_box_content %}
{% render_field form.has_not_location class+='inline-block' %}
<label class="secondary !inline"
for="{{ form.has_not_location.id_for_label }}">
{{ form.has_not_location.label }}
</label>
{% if current_menu_item == "events_form" %}
{% render_field form.has_not_location class+='inline-block' %}
<label class="secondary !inline"
for="{{ form.has_not_location.id_for_label }}">
{{ form.has_not_location.label }}
</label>
{% endif %}
{% if current_menu_item == "contacts" %}
<div class="help-text mt-4 font-bold">
{{ help_text }}
</div>
{% endif %}
<div id="location-block"
class="{% if form.has_not_location.value %}hidden{% endif %}">
<label for="{{ form.location.id_for_label }}">
{{ form.location.label }}
</label>
{% translate "Name of event location" as poi_title_placeholder %}
{% translate "Name of location" as poi_title_placeholder %}
<div class="relative my-2">
<input id="poi-query-input"
type="search"
Expand All @@ -34,14 +41,16 @@
data-default-placeholder="{{ poi_title_placeholder }}" />
<div class="absolute inset-y-0 right-0 flex items-center px-2 text-gray-800">
<button id="poi-remove"
title="{% translate "Remove location from event" %}"
title="{% translate "Remove location" %}"
{% if form.disabled %}disabled{% endif %}>
<i icon-name="trash-2" class="h-5 w-5"></i>
</button>
</div>
</div>
<p class="text-sm italic block mt-2 mb-2">
{% 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 %}
</p>
<div class="relative" id="poi-query-result">
{% include "_poi_query_result.html" %}
Expand Down
Loading

0 comments on commit e01c256

Please sign in to comment.