diff --git a/integreat_cms/cms/models/contact/contact.py b/integreat_cms/cms/models/contact/contact.py
index 0e3217c271..d465ae455a 100644
--- a/integreat_cms/cms/models/contact/contact.py
+++ b/integreat_cms/cms/models/contact/contact.py
@@ -235,6 +235,34 @@ def referring_objects(self) -> Generator[AbstractContentTranslation]:
link.content_object for link in Link.objects.filter(url__url=self.full_url)
)
+ @cached_property
+ def available_details(self) -> dict:
+ """
+ Returns the available details and their human-readable representation
+
+ :return: key-value pairs of available detail and human-readable representation
+ """
+ details = {
+ "address": _("show address"),
+ }
+
+ if self.point_of_contact_for:
+ details["point_of_contact_for"] = _("show point of contact")
+
+ if self.name:
+ details["name"] = _("show name")
+
+ if self.email:
+ details["email"] = _("show email")
+
+ if self.phone_number:
+ details["phone_number"] = _("show phone number")
+
+ if self.website:
+ details["website"] = _("show website")
+
+ return details
+
def archive(self) -> None:
"""
Archives the contact
diff --git a/integreat_cms/cms/templates/contacts/contact_card.html b/integreat_cms/cms/templates/contacts/contact_card.html
index 630ddb576e..4c8843ad82 100644
--- a/integreat_cms/cms/templates/contacts/contact_card.html
+++ b/integreat_cms/cms/templates/contacts/contact_card.html
@@ -3,54 +3,56 @@
{% spaceless %}
{% endspaceless %}
diff --git a/integreat_cms/cms/utils/content_utils.py b/integreat_cms/cms/utils/content_utils.py
index 167b481b3d..1906a889ae 100644
--- a/integreat_cms/cms/utils/content_utils.py
+++ b/integreat_cms/cms/utils/content_utils.py
@@ -142,16 +142,18 @@ def update_internal_links(link: HtmlElement, language_slug: str) -> None:
link.append(new_html)
-def render_contact_card(contact_id: int) -> HtmlElement:
+def render_contact_card(contact_id: int, wanted_details: list[str]) -> HtmlElement:
"""
Produces a rendered html element for the contact.
:param contact_id: The id of the contact to render the card for
+ :param wanted_details: list of details to be shown in the rendered card
"""
template = loader.get_template("contacts/contact_card.html")
try:
context = {
"contact": Contact.objects.get(pk=contact_id),
+ "wanted": wanted_details,
}
raw_element = template.render(context)
return fromstring(raw_element)
@@ -175,9 +177,17 @@ def update_contacts(content: HtmlElement) -> None:
"""
contact_cards = content.xpath("//div[@data-contact-id]")
contact_ids = [int(card.get("data-contact-id")) for card in contact_cards]
+ contact_urls = [card.get("data-contact-url") for card in contact_cards]
- for contact_id, contact_card in zip(contact_ids, contact_cards):
- contact_card_new = render_contact_card(contact_id)
+ for contact_id, contact_url, contact_card in zip(
+ contact_ids, contact_urls, contact_cards
+ ):
+ try:
+ wanted_details = contact_url.split("details=", 1)[1].split(",")
+ except IndexError:
+ wanted_details = []
+
+ contact_card_new = render_contact_card(contact_id, wanted_details)
contact_card.getparent().replace(contact_card, contact_card_new)
diff --git a/integreat_cms/cms/views/utils/contact_utils.py b/integreat_cms/cms/views/utils/contact_utils.py
index 847e742fc5..8c409fc917 100644
--- a/integreat_cms/cms/views/utils/contact_utils.py
+++ b/integreat_cms/cms/views/utils/contact_utils.py
@@ -5,7 +5,7 @@
from typing import TYPE_CHECKING
from django.core.exceptions import PermissionDenied
-from django.http import HttpResponse, JsonResponse
+from django.http import JsonResponse
from django.shortcuts import get_object_or_404, render
from django.views.decorators.http import require_POST
@@ -56,6 +56,7 @@ def search_contact_ajax(
{
"url": result.full_url,
"name": result.get_repr_short,
+ "details": result.available_details,
}
for result in results
]
@@ -77,7 +78,11 @@ def get_contact(
"""
# pylint: disable=unused-argument
contact = get_object_or_404(Contact, pk=contact_id)
- return render(request, "contacts/contact_card.html", {"contact": contact})
+
+ wanted = request.GET.get("details", "").split(",")
+ return render(
+ request, "contacts/contact_card.html", {"contact": contact, "wanted": wanted}
+ )
@permission_required("cms.view_contact")
@@ -95,4 +100,12 @@ def get_contact_raw(
"""
# pylint: disable=unused-argument
contact = get_object_or_404(Contact, pk=contact_id)
- return HttpResponse(contact.get_repr_short)
+ return JsonResponse(
+ {
+ "data": {
+ "url": contact.full_url,
+ "name": contact.get_repr_short,
+ "details": contact.available_details,
+ }
+ }
+ )
diff --git a/integreat_cms/locale/de/LC_MESSAGES/django.po b/integreat_cms/locale/de/LC_MESSAGES/django.po
index 13c9b63108..eb4d6d3786 100644
--- a/integreat_cms/locale/de/LC_MESSAGES/django.po
+++ b/integreat_cms/locale/de/LC_MESSAGES/django.po
@@ -2817,6 +2817,30 @@ msgstr "mit Website: {}"
msgid "General contact information"
msgstr "Allgemeine Kontaktinformationen"
+#: cms/models/contact/contact.py
+msgid "show address"
+msgstr "Adresse anzeigen"
+
+#: cms/models/contact/contact.py
+msgid "show point of contact"
+msgstr "Ansprechperson anzeigen"
+
+#: cms/models/contact/contact.py
+msgid "show name"
+msgstr "Name anzeigen"
+
+#: cms/models/contact/contact.py
+msgid "show email"
+msgstr "Email anzeigen"
+
+#: cms/models/contact/contact.py
+msgid "show phone number"
+msgstr "Telefonnummer anzeigen"
+
+#: cms/models/contact/contact.py
+msgid "show website"
+msgstr "Webseite anzeigen"
+
#: cms/models/contact/contact.py
msgid "(Copy)"
msgstr "(Kopie)"
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 26afbbe077..18682bd9f0 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
@@ -39,7 +39,21 @@ import { getCsrfToken } from "../../utils/csrf-token";
return data;
};
- const getContactRaw = async (url) => getContactHtml(`${url}raw/`);
+ const getContactRaw = async (url) => {
+ const response = await fetch(`${url.split("?")[0]}raw/`, {
+ method: "GET",
+ headers: {
+ "X-CSRFToken": getCsrfToken(),
+ },
+ });
+
+ if (response.status !== HTTP_STATUS_OK) {
+ return {};
+ }
+
+ const data = await response.json();
+ return data.data;
+ };
tinymce.PluginManager.add("custom_contact_input", (editor, _url) => {
const isContact = (node) => "contactId" in node.dataset;
@@ -58,7 +72,7 @@ import { getCsrfToken } from "../../utils/csrf-token";
let tomSelectInstance;
- const openDialog = (_button, initialSelection) => {
+ const openDialog = (_button, initialSelection, selectedDetails) => {
const contact = getContact();
const dialogConfig = {
@@ -72,6 +86,7 @@ import { getCsrfToken } from "../../utils/csrf-token";
// so we have to do with an htmlpanel and initializing TomSelect separately
html: ``,
},
+ { type: "htmlpanel", html: `
` },
],
},
buttons: [
@@ -99,8 +114,13 @@ import { getCsrfToken } from "../../utils/csrf-token";
if (!url) {
return;
}
+ const details = Array.from(
+ document.getElementById("details-area").querySelectorAll('input[type="checkbox"]:checked')
+ )
+ .map((cb) => cb.value)
+ .join(",");
api.close();
- getContactHtml(url).then((html) => {
+ getContactHtml(`${url}?details=${details}`).then((html) => {
if (!contact) {
editor.insertContent(html);
} else {
@@ -112,6 +132,7 @@ import { getCsrfToken } from "../../utils/csrf-token";
setTimeout(() => {
const selectElement = document.getElementById("completions");
+ const detailsArea = document.getElementById("details-area");
const submitElement = document.querySelector(
".tox-dialog:has(#completions) .tox-dialog__footer .tox-button:not(.tox-button--secondary)"
);
@@ -125,9 +146,47 @@ import { getCsrfToken } from "../../utils/csrf-token";
submitElement.focus();
}
};
+ const updateDetailSelection = (value) => {
+ detailsArea.innerHTML = "";
+
+ // removing the currently selected option calls this function with empty string
+ if (value === "") {
+ return;
+ }
+
+ const availableDetails = tomSelectInstance.options[value].details;
+
+ for (const [key, value] of Object.entries(availableDetails)) {
+ const wrapper = document.createElement("div");
+
+ const checkbox = document.createElement("input");
+ checkbox.type = "checkbox";
+ checkbox.checked = selectedDetails?.includes(key) || !selectedDetails;
+ checkbox.value = key;
+ checkbox.id = key;
+ checkbox.style.border = "1px solid";
+ checkbox.style.width = "1em";
+ checkbox.style.height = "1em";
+ checkbox.style.margin = "0 5px 0 5px";
+ checkbox.style.verticalAlign = "middle";
+
+ const label = document.createElement("label");
+ label.htmlFor = key;
+ label.textContent = value;
+ label.style.verticalAlign = "middle";
+
+ wrapper.append(checkbox);
+ wrapper.append(label);
+ detailsArea.append(wrapper);
+ }
+ };
if (initialSelection) {
- selectElement.add(initialSelection);
+ const updatedContactOption = document.createElement("option");
+ updatedContactOption.value = initialSelection.url;
+ updatedContactOption.text = initialSelection.name;
+
+ selectElement.add(updatedContactOption);
}
tomSelectInstance = new TomSelect(selectElement, {
@@ -142,11 +201,19 @@ import { getCsrfToken } from "../../utils/csrf-token";
});
},
onDropdownClose: setSubmitDisableStatus,
+ onChange: updateDetailSelection,
});
selectElement.classList.add("hidden");
tomSelectInstance.control_input.parentElement.classList.add("tox-textfield");
- tomSelectInstance.control_input.focus();
+ if (initialSelection) {
+ tomSelectInstance.options[initialSelection.url] = initialSelection;
+ tomSelectInstance.setValue(initialSelection.url);
+ } else {
+ // when initial selection is given, do not focus the input,
+ // in order to avoid an additional click to see the full details selection
+ tomSelectInstance.control_input.focus();
+ }
setSubmitDisableStatus(tomSelectInstance.getValue());
}, 0);
@@ -168,12 +235,9 @@ import { getCsrfToken } from "../../utils/csrf-token";
onAction: async () => {
const contactUrl = getContact().dataset.contactUrl;
const updatedContact = await getContactRaw(contactUrl);
+ const selectedDetails = contactUrl.split("?details=")[1]?.split(",");
- const updatedContactOption = document.createElement("option");
- updatedContactOption.value = `${contactUrl}`;
- updatedContactOption.text = updatedContact;
-
- openDialog(null, updatedContactOption);
+ openDialog(null, updatedContact, selectedDetails);
closeContextToolbar();
},
});