From 821a85ba04fa889cfd5dfef462a8f8f81db199ca Mon Sep 17 00:00:00 2001 From: Tudor Amariei Date: Wed, 6 Nov 2024 13:00:41 +0200 Subject: [PATCH] Add an expandable section of voting domains --- .../components/expandable_voting_domains.html | 30 ++++++++++++ .../ngos_listing_by_voting_domain.html | 2 +- backend/hub/templates/hub/ngo/list.html | 46 ++++++++++++------- backend/hub/views.py | 40 +++++++++++----- backend/static_extras/css/hub.css | 46 +++++++++++++++++++ 5 files changed, 135 insertions(+), 29 deletions(-) create mode 100644 backend/hub/templates/hub/ngo/components/expandable_voting_domains.html diff --git a/backend/hub/templates/hub/ngo/components/expandable_voting_domains.html b/backend/hub/templates/hub/ngo/components/expandable_voting_domains.html new file mode 100644 index 0000000..59a50aa --- /dev/null +++ b/backend/hub/templates/hub/ngo/components/expandable_voting_domains.html @@ -0,0 +1,30 @@ +
+ +

+ {{ section_title }} ({{ counters.ngos_accepted }}) + +

+
+ +
+ + + +
+
diff --git a/backend/hub/templates/hub/ngo/components/ngos_listing_by_voting_domain.html b/backend/hub/templates/hub/ngo/components/ngos_listing_by_voting_domain.html index 8db7c91..3a8754b 100644 --- a/backend/hub/templates/hub/ngo/components/ngos_listing_by_voting_domain.html +++ b/backend/hub/templates/hub/ngo/components/ngos_listing_by_voting_domain.html @@ -3,7 +3,7 @@ {% for section_details in page_obj %} -

+

{{ section_details.domain.name }} ({{ section_details.organizations|length }})

diff --git a/backend/hub/templates/hub/ngo/list.html b/backend/hub/templates/hub/ngo/list.html index 04af387..8163073 100644 --- a/backend/hub/templates/hub/ngo/list.html +++ b/backend/hub/templates/hub/ngo/list.html @@ -17,32 +17,46 @@ value="{{ current_search }}" aria-label="{% trans 'Search...' %}" placeholder="{% trans 'Search...' %}"> - + + + +

-

- {% trans "Registered organizations" %} ({{ counters.ngos_accepted }}) -

+ + {% trans "Registered organizations" as section_title %} + + {% if page_obj and VOTING_DOMAIN_ENABLED %} + + {% include "hub/ngo/components/expandable_voting_domains.html" with section_title=section_title %} + + {% else %} + +

+ {{ section_title }} ({{ counters.ngos_accepted }}) +

+ + {% endif %} +
{% if page_obj %}
- - {% if VOTING_DOMAIN_ENABLED %} - {% include "hub/ngo/components/ngos_listing_by_voting_domain.html" %} - {% else %} - {% include "hub/ngo/components/ngos_listing.html" %} - {% endif %} - + + {% if VOTING_DOMAIN_ENABLED %} + {% include "hub/ngo/components/ngos_listing_by_voting_domain.html" %} + {% else %} + {% include "hub/ngo/components/ngos_listing.html" %} + {% endif %} +
{% include "hub/shared/pagination.html" with page_obj=page_obj domain=current_domain %} diff --git a/backend/hub/views.py b/backend/hub/views.py index 9a9f715..1cb7b83 100644 --- a/backend/hub/views.py +++ b/backend/hub/views.py @@ -1,4 +1,5 @@ import logging +import unicodedata from datetime import datetime from typing import Dict, List, Optional, Union from urllib.parse import unquote @@ -37,6 +38,7 @@ ) from hub.models import ( FLAG_CHOICES, + SETTINGS_CHOICES, BlogPost, Candidate, CandidateConfirmation, @@ -46,7 +48,6 @@ Domain, FeatureFlag, Organization, - SETTINGS_CHOICES, ) from hub.workers.update_organization import update_organization @@ -244,24 +245,39 @@ class OrganizationListView(SearchMixin): paginate_by = 9 template_name = "hub/ngo/list.html" + @staticmethod + def _filter_letter(char: str) -> bool: + if char.isalpha(): + return True + elif char == " ": + return True + + return False + def group_organizations_by_domain(self, queryset) -> List[Dict[str, Union[Domain, List[Organization]]]]: organizations_by_domain: Dict[Domain, List[Organization]] = {} for organization in queryset: - domain_name: Domain = organization.voting_domain - if domain_name not in organizations_by_domain: - organizations_by_domain[domain_name] = [] + domain: Domain = organization.voting_domain + if domain not in organizations_by_domain: + organizations_by_domain[domain] = [] - organizations_by_domain[domain_name].append(organization) + organizations_by_domain[domain].append(organization) # dictionary to list of dictionaries - organizations_by_domain_list = [ - { - "domain": domain, - "organizations": sorted(organizations, key=lambda org: org.name), - } - for domain, organizations in organizations_by_domain.items() - ] + organizations_by_domain_list = [] + for domain, organizations in organizations_by_domain.items(): + snake_case_domain_key = "".join(filter(self._filter_letter, domain.name)).lower().replace(" ", "_") + normalized_domain_key = unicodedata.normalize("NFKD", snake_case_domain_key).encode("ascii", "ignore") + + organizations_by_domain_list.append( + { + "domain": domain, + "domain_key": normalized_domain_key.decode("utf-8"), + "organizations": sorted(organizations, key=lambda org: org.name), + } + ) + organizations_by_domain_list = sorted(organizations_by_domain_list, key=lambda x: x["domain"].pk) return organizations_by_domain_list diff --git a/backend/static_extras/css/hub.css b/backend/static_extras/css/hub.css index 6967221..7ae7224 100644 --- a/backend/static_extras/css/hub.css +++ b/backend/static_extras/css/hub.css @@ -669,3 +669,49 @@ hr.tight { border-color: #ffdd57; color: #5c4a00; } + +.collapsible-title { + overflow: hidden; + cursor: pointer; +} + +.active, .collapsible-title:hover { + background-color: #ffdd57; +} + +.collapsible-content { + padding: 0 18px; + display: none; + overflow: hidden; + background-color: #f1f1f1; +} + +details { + user-select: none; +} + +details>summary span.icon { + width: 24px; + height: 24px; + transition: all 0.3s; + margin-left: auto; + font: inherit; + font-size: 1em; +} + +summary span.icon { + transform: rotate(90deg); +} + +details[open] summary span.icon { + transform: rotate(270deg); +} + +summary { + display: flex; + cursor: pointer; +} + +summary::-webkit-details-marker { + display: none; +}