From 9f18f50d9b10a1e2d55c925bb2038e61e658cdc6 Mon Sep 17 00:00:00 2001 From: luminaryFlowers <71102109+luminaryFlowers@users.noreply.github.com> Date: Mon, 29 Jul 2024 09:49:12 -0700 Subject: [PATCH] our partners, partner with us pages done, added event filters --- .../0007_partnertype_partner_partner_type.py | 29 ++++ app/core/models.py | 26 ++- ...05_eventcategory_eventhosttype_and_more.py | 44 +++++ ...06_alter_eventcategory_options_and_more.py | 27 ++++ ...nerpage_event_categories_title_and_more.py | 23 +++ ...08_alter_eventhosttype_options_and_more.py | 32 ++++ ...eventownerpage_category_select_and_more.py | 28 ++++ app/events/models.py | 88 ++++++++++ .../templates/events/event_owner_page.html | 57 +++++++ .../events/individual_event_page.html | 35 +++- app/partners/__init__.py | 0 app/partners/admin.py | 3 + app/partners/apps.py | 6 + app/partners/migrations/0001_initial.py | 44 +++++ ...er_partnerwithuspage_black_box_link_url.py | 18 +++ ..._partnerwithuspage_black_box_link_email.py | 18 +++ .../migrations/0004_ourpartnerspage.py | 38 +++++ ...rtnerspage_black_box_link_text_and_more.py | 33 ++++ ...0006_ourpartnerspage_filter_button_text.py | 18 +++ app/partners/migrations/__init__.py | 0 app/partners/models.py | 151 ++++++++++++++++++ .../templates/partners/our_partners_page.html | 78 +++++++++ .../partners/partner_with_us_page.html | 53 ++++++ app/partners/tests.py | 3 + app/partners/views.py | 3 + .../ui/components/FlexTitleWithLink.html | 11 +- .../ui/components/PageHeaderWithBlur.html | 10 +- home/templatetags/homepage_tags.py | 2 - hot_osm/settings/base.py | 1 + 29 files changed, 866 insertions(+), 13 deletions(-) create mode 100644 app/core/migrations/0007_partnertype_partner_partner_type.py create mode 100644 app/events/migrations/0005_eventcategory_eventhosttype_and_more.py create mode 100644 app/events/migrations/0006_alter_eventcategory_options_and_more.py create mode 100644 app/events/migrations/0007_eventownerpage_event_categories_title_and_more.py create mode 100644 app/events/migrations/0008_alter_eventhosttype_options_and_more.py create mode 100644 app/events/migrations/0009_alter_eventownerpage_category_select_and_more.py create mode 100644 app/partners/__init__.py create mode 100644 app/partners/admin.py create mode 100644 app/partners/apps.py create mode 100644 app/partners/migrations/0001_initial.py create mode 100644 app/partners/migrations/0002_alter_partnerwithuspage_black_box_link_url.py create mode 100644 app/partners/migrations/0003_rename_black_box_link_url_partnerwithuspage_black_box_link_email.py create mode 100644 app/partners/migrations/0004_ourpartnerspage.py create mode 100644 app/partners/migrations/0005_alter_ourpartnerspage_black_box_link_text_and_more.py create mode 100644 app/partners/migrations/0006_ourpartnerspage_filter_button_text.py create mode 100644 app/partners/migrations/__init__.py create mode 100644 app/partners/models.py create mode 100644 app/partners/templates/partners/our_partners_page.html create mode 100644 app/partners/templates/partners/partner_with_us_page.html create mode 100644 app/partners/tests.py create mode 100644 app/partners/views.py diff --git a/app/core/migrations/0007_partnertype_partner_partner_type.py b/app/core/migrations/0007_partnertype_partner_partner_type.py new file mode 100644 index 0000000..3e6defc --- /dev/null +++ b/app/core/migrations/0007_partnertype_partner_partner_type.py @@ -0,0 +1,29 @@ +# Generated by Django 4.2.7 on 2024-07-25 23:16 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0006_delete_hotsearchablepage'), + ] + + operations = [ + migrations.CreateModel( + name='PartnerType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type_name', models.CharField()), + ], + options={ + 'verbose_name_plural': 'Partner Types', + }, + ), + migrations.AddField( + model_name='partner', + name='partner_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.partnertype'), + ), + ] diff --git a/app/core/models.py b/app/core/models.py index 9e66f7b..49732e3 100644 --- a/app/core/models.py +++ b/app/core/models.py @@ -1,12 +1,28 @@ +from django import forms from django.db import models + from wagtail.models import Page from wagtail.fields import StreamField from wagtail.blocks import CharBlock, StreamBlock, StructBlock, URLBlock, RichTextBlock, PageChooserBlock - from wagtail.snippets.models import register_snippet from wagtail.admin.panels import FieldPanel, MultiFieldPanel, InlinePanel +@register_snippet +class PartnerType(models.Model): + type_name = models.CharField() + + panels = [ + FieldPanel("type_name") + ] + + def __str__(self): + return self.type_name + + class Meta: + verbose_name_plural = "Partner Types" + + @register_snippet class Partner(models.Model): partner_name = models.CharField() @@ -18,11 +34,19 @@ class Partner(models.Model): help_text="Partner logo" ) partner_url = models.URLField(blank=True) + partner_type = models.ForeignKey( + 'core.PartnerType', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) panels = [ FieldPanel("partner_name"), FieldPanel("partner_logo"), FieldPanel("partner_url"), + FieldPanel("partner_type", widget=forms.RadioSelect), ] def __str__(self): diff --git a/app/events/migrations/0005_eventcategory_eventhosttype_and_more.py b/app/events/migrations/0005_eventcategory_eventhosttype_and_more.py new file mode 100644 index 0000000..781f5ec --- /dev/null +++ b/app/events/migrations/0005_eventcategory_eventhosttype_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 4.2.7 on 2024-07-26 18:42 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapping_hubs', '0013_alter_mappinghubprojectspage_black_box_link_text_and_more'), + ('events', '0004_eventownerpage_keyword_search_hint_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='EventCategory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('category_name', models.CharField()), + ], + ), + migrations.CreateModel( + name='EventHostType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type_name', models.CharField()), + ], + ), + migrations.AddField( + model_name='individualeventpage', + name='event_region_hub', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='mapping_hubs.individualmappinghubpage'), + ), + migrations.AddField( + model_name='individualeventpage', + name='event_category', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='events.eventcategory'), + ), + migrations.AddField( + model_name='individualeventpage', + name='event_host_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='events.eventhosttype'), + ), + ] diff --git a/app/events/migrations/0006_alter_eventcategory_options_and_more.py b/app/events/migrations/0006_alter_eventcategory_options_and_more.py new file mode 100644 index 0000000..bcbffd0 --- /dev/null +++ b/app/events/migrations/0006_alter_eventcategory_options_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.7 on 2024-07-26 18:56 + +from django.db import migrations +import modelcluster.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0005_eventcategory_eventhosttype_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='eventcategory', + options={'verbose_name_plural': 'Event Categories'}, + ), + migrations.RemoveField( + model_name='individualeventpage', + name='event_category', + ), + migrations.AddField( + model_name='individualeventpage', + name='event_categories', + field=modelcluster.fields.ParentalManyToManyField(blank=True, to='events.eventcategory'), + ), + ] diff --git a/app/events/migrations/0007_eventownerpage_event_categories_title_and_more.py b/app/events/migrations/0007_eventownerpage_event_categories_title_and_more.py new file mode 100644 index 0000000..3081615 --- /dev/null +++ b/app/events/migrations/0007_eventownerpage_event_categories_title_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.7 on 2024-07-26 19:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0006_alter_eventcategory_options_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='eventownerpage', + name='event_categories_title', + field=models.CharField(default='Categories'), + ), + migrations.AddField( + model_name='eventownerpage', + name='event_region_hub_title', + field=models.CharField(default='Region Hub'), + ), + ] diff --git a/app/events/migrations/0008_alter_eventhosttype_options_and_more.py b/app/events/migrations/0008_alter_eventhosttype_options_and_more.py new file mode 100644 index 0000000..6afdc0f --- /dev/null +++ b/app/events/migrations/0008_alter_eventhosttype_options_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.7 on 2024-07-26 21:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0007_eventownerpage_event_categories_title_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='eventhosttype', + options={'verbose_name_plural': 'Event Host Types'}, + ), + migrations.AddField( + model_name='eventownerpage', + name='category_select', + field=models.CharField(default='Filter by category'), + ), + migrations.AddField( + model_name='eventownerpage', + name='filter_by_country', + field=models.CharField(default='Filter by country'), + ), + migrations.AddField( + model_name='eventownerpage', + name='host_type_select', + field=models.CharField(default='Filter by host type'), + ), + ] diff --git a/app/events/migrations/0009_alter_eventownerpage_category_select_and_more.py b/app/events/migrations/0009_alter_eventownerpage_category_select_and_more.py new file mode 100644 index 0000000..b2bfab5 --- /dev/null +++ b/app/events/migrations/0009_alter_eventownerpage_category_select_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.7 on 2024-07-26 21:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0008_alter_eventhosttype_options_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='eventownerpage', + name='category_select', + field=models.CharField(default='Filter by Category'), + ), + migrations.AlterField( + model_name='eventownerpage', + name='filter_by_country', + field=models.CharField(default='Filter by Country'), + ), + migrations.AlterField( + model_name='eventownerpage', + name='host_type_select', + field=models.CharField(default='Filter by Host Type'), + ), + ] diff --git a/app/events/models.py b/app/events/models.py index 7acc034..1d48f22 100644 --- a/app/events/models.py +++ b/app/events/models.py @@ -1,4 +1,6 @@ +from django import forms from django.db import models +from django.db.models import Q from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from wagtail.models import Page @@ -7,6 +9,9 @@ from wagtail.blocks import CharBlock, StreamBlock, StructBlock, URLBlock, RichTextBlock, PageChooserBlock from modelcluster.fields import ParentalKey, ParentalManyToManyField from wagtail.search import index +from wagtail.snippets.models import register_snippet + +from app.members.models import IndividualMappingHubPage class EventOwnerPage(Page): @@ -19,6 +24,28 @@ def get_context(self, request, *args, **kwargs): if keyword: events_list = events_list.search(keyword).get_queryset() + categories = EventCategory.objects.all() + query = Q() + for category in categories: + if request.GET.get(str(category), ''): + query = query | Q(event_categories=category) + events_list = events_list.filter(query) + + # these queries and filters are done in seperate parts so that filtering is done as ANDs instead of ORs + event_host_types = EventHostType.objects.all() + query = Q() + for host_type in event_host_types: + if request.GET.get(str(host_type), ''): + query = query | Q(event_host_type=host_type) + events_list = events_list.filter(query) + + hubs = IndividualMappingHubPage.objects.live().filter(locale=context['page'].locale) + query = Q() + for hub in hubs: + if request.GET.get(str(hub), ''): + query = query | Q(event_region_hub=hub) + events_list = events_list.filter(query).distinct() + match request.GET.get('sort', ''): case 'sort.new': events_list = events_list.order_by('-start_date_time') @@ -43,6 +70,9 @@ def get_context(self, request, *args, **kwargs): context['events'] = events context['events_paginator'] = paginator context['current_page'] = int(page) + context['categories'] = categories + context['hubs'] = hubs + context['event_host_types'] = event_host_types return context max_count = 1 @@ -52,6 +82,8 @@ def get_context(self, request, *args, **kwargs): ] event_location_title = models.CharField(default="Event Location") + event_region_hub_title = models.CharField(default="Region Hub") + event_categories_title = models.CharField(default="Categories") join_event_title = models.CharField(default="Join This Event") rsvp_button_text = models.CharField(default="RSVP") more_events_title = models.CharField(default="More Events") @@ -60,6 +92,9 @@ def get_context(self, request, *args, **kwargs): event_read_more_text = models.CharField(default="Read more") keyword_search_hint = models.CharField(default="Search by keyword") + filter_by_country = models.CharField(default="Filter by Country") + host_type_select = models.CharField(default="Filter by Host Type") + category_select = models.CharField(default="Filter by Category") sort_by_new = models.CharField(default="Sort by New") sort_by_old = models.CharField(default="Sort by Old") sort_by_titlea = models.CharField(default="Sort by Title Alphabetical") @@ -70,6 +105,9 @@ def get_context(self, request, *args, **kwargs): content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('keyword_search_hint'), + FieldPanel('filter_by_country'), + FieldPanel('host_type_select'), + FieldPanel('category_select'), FieldPanel('sort_by_new'), FieldPanel('sort_by_old'), FieldPanel('sort_by_titlea'), @@ -79,6 +117,8 @@ def get_context(self, request, *args, **kwargs): ], heading="Event Search Page"), MultiFieldPanel([ FieldPanel('event_location_title'), + FieldPanel('event_region_hub_title'), + FieldPanel('event_categories_title'), FieldPanel('join_event_title'), FieldPanel('rsvp_button_text'), FieldPanel('more_events_title'), @@ -89,6 +129,36 @@ def get_context(self, request, *args, **kwargs): ] +@register_snippet +class EventHostType(models.Model): + type_name = models.CharField() + + panels = [ + FieldPanel("type_name") + ] + + def __str__(self): + return self.type_name + + class Meta: + verbose_name_plural = "Event Host Types" + + +@register_snippet +class EventCategory(models.Model): + category_name = models.CharField() + + panels = [ + FieldPanel("category_name") + ] + + def __str__(self): + return self.category_name + + class Meta: + verbose_name_plural = "Event Categories" + + class IndividualEventPage(Page): parent_page_types = [ 'events.EventOwnerPage' @@ -112,7 +182,22 @@ class IndividualEventPage(Page): ])) ], use_json_field=True, null=True) + event_host_type = models.ForeignKey( + 'events.EventHostType', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) event_location = models.CharField(blank=True) + event_region_hub = models.ForeignKey( + 'mapping_hubs.IndividualMappingHubPage', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + event_categories = ParentalManyToManyField('events.EventCategory', blank=True) rsvp_description = RichTextField(blank=True, help_text="If this field is empty, the RSVP description will not appear.") rsvp_link = models.URLField(blank=True, help_text="If this field is empty, the RSVP button will not appear. If both RSVP Description and Link are empty, the RSVP section will be hidden.") @@ -137,7 +222,10 @@ class IndividualEventPage(Page): FieldPanel('extended_description'), ], heading="Body"), MultiFieldPanel([ + FieldPanel('event_host_type', widget=forms.RadioSelect), FieldPanel('event_location'), + PageChooserPanel('event_region_hub'), + FieldPanel('event_categories', widget=forms.CheckboxSelectMultiple), FieldPanel('rsvp_description'), FieldPanel('rsvp_link'), FieldPanel('more_events'), diff --git a/app/events/templates/events/event_owner_page.html b/app/events/templates/events/event_owner_page.html index 1d067b5..3ffad23 100644 --- a/app/events/templates/events/event_owner_page.html +++ b/app/events/templates/events/event_owner_page.html @@ -21,6 +21,63 @@

{{page.title}}

{% include "ui/components/icon_svgs/SearchIcon.html" with class="text-hot-red mx-3" %} + {% comment %} HOST TYPE {% endcomment %} +
+
+

+ {{page.host_type_select}} +

+ {% include "ui/components/icon_svgs/LinkCaret.html" with class="rotate-90 text-hot-red" %} +
+
+
+ {% for event_host_type in event_host_types %} +
+ + +
+ {% endfor %} +
+
+ + {% comment %} CATEGORY {% endcomment %} +
+
+

+ {{page.category_select}} +

+ {% include "ui/components/icon_svgs/LinkCaret.html" with class="rotate-90 text-hot-red" %} +
+
+
+ {% for category in categories %} +
+ + +
+ {% endfor %} +
+
+ + {% comment %} HUB {% endcomment %} +
+
+

+ {{page.filter_by_country}} +

+ {% include "ui/components/icon_svgs/LinkCaret.html" with class="rotate-90 text-hot-red" %} +
+
+
+ {% for hub in hubs %} +
+ + +
+ {% endfor %} +
+
+ {% comment %} SORT {% endcomment %}
diff --git a/app/events/templates/events/individual_event_page.html b/app/events/templates/events/individual_event_page.html index de51588..0598ed3 100644 --- a/app/events/templates/events/individual_event_page.html +++ b/app/events/templates/events/individual_event_page.html @@ -36,11 +36,40 @@

{{ page.title }}

{{page.get_parent.specific.event_location_title}}

-

- {{page.event_location}} -

+ {% if page.event_host_type %} +

+ {{page.event_host_type}} +

+ {% endif %} + {% if page.event_location %} +

+ {{page.event_location}} +

+ {% endif %}
+ {% if page.event_region_hub %} +

+ {{page.get_parent.specific.event_region_hub_title}} +

+

+ {{page.event_region_hub.title}} +

+
+ {% endif %} + + {% if page.event_categories %} +

+ {{page.get_parent.specific.event_categories_title}} +

+

+ {% for category in page.event_categories.all %} + {{category}}{% if not forloop.last %}, {% endif %} + {% endfor %} +

+
+ {% endif %} + {% if page.rsvp_description or page.rsvp_link %}

diff --git a/app/partners/__init__.py b/app/partners/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/partners/admin.py b/app/partners/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/app/partners/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/app/partners/apps.py b/app/partners/apps.py new file mode 100644 index 0000000..6eb8a4b --- /dev/null +++ b/app/partners/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PartnersConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'app.partners' diff --git a/app/partners/migrations/0001_initial.py b/app/partners/migrations/0001_initial.py new file mode 100644 index 0000000..b7f4b2c --- /dev/null +++ b/app/partners/migrations/0001_initial.py @@ -0,0 +1,44 @@ +# Generated by Django 4.2.7 on 2024-07-25 18:00 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailimages', '0025_alter_image_file_alter_rendition_file'), + ('wagtailcore', '0089_log_entry_data_json_null_to_object'), + ] + + operations = [ + migrations.CreateModel( + name='PartnerWithUsPage', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('header_description', wagtail.fields.RichTextField(blank=True)), + ('intro', wagtail.fields.RichTextField(blank=True)), + ('partnership_types_title', models.CharField(default='Types of Partnerships')), + ('partnership_types', wagtail.fields.StreamField([('blocks', wagtail.blocks.StructBlock([('icon', wagtail.images.blocks.ImageChooserBlock()), ('title', wagtail.blocks.CharBlock()), ('description', wagtail.blocks.RichTextBlock())]))], blank=True, help_text='Blocks to be shown under the Types of Partnerships section.', null=True, use_json_field=True)), + ('meet_our_partners_title', models.CharField(default='Meet Our Partners')), + ('view_all_partners_text', models.CharField(default='View All Partners')), + ('view_all_partners_link', wagtail.fields.StreamField([('page', wagtail.blocks.PageChooserBlock()), ('url', wagtail.blocks.URLBlock())], blank=True, use_json_field=True)), + ('red_box_title', models.CharField(default='Still have questions?')), + ('red_box_link_text', models.CharField(default='Contact our team')), + ('red_box_link_url', wagtail.fields.StreamField([('page', wagtail.blocks.PageChooserBlock()), ('url', wagtail.blocks.URLBlock())], blank=True, use_json_field=True)), + ('black_box_title', models.CharField(default='Become a Partner')), + ('black_box_link_text', models.CharField(default='Email to partnerships@hotosm.org')), + ('black_box_link_url', wagtail.fields.StreamField([('page', wagtail.blocks.PageChooserBlock()), ('url', wagtail.blocks.URLBlock())], blank=True, use_json_field=True)), + ('header_image', models.ForeignKey(blank=True, help_text='Header image', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image')), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + ] diff --git a/app/partners/migrations/0002_alter_partnerwithuspage_black_box_link_url.py b/app/partners/migrations/0002_alter_partnerwithuspage_black_box_link_url.py new file mode 100644 index 0000000..f1df0d9 --- /dev/null +++ b/app/partners/migrations/0002_alter_partnerwithuspage_black_box_link_url.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2024-07-25 19:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('partners', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='partnerwithuspage', + name='black_box_link_url', + field=models.EmailField(default='partnerships@hotosm.org', max_length=254), + ), + ] diff --git a/app/partners/migrations/0003_rename_black_box_link_url_partnerwithuspage_black_box_link_email.py b/app/partners/migrations/0003_rename_black_box_link_url_partnerwithuspage_black_box_link_email.py new file mode 100644 index 0000000..9ec3527 --- /dev/null +++ b/app/partners/migrations/0003_rename_black_box_link_url_partnerwithuspage_black_box_link_email.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2024-07-25 19:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('partners', '0002_alter_partnerwithuspage_black_box_link_url'), + ] + + operations = [ + migrations.RenameField( + model_name='partnerwithuspage', + old_name='black_box_link_url', + new_name='black_box_link_email', + ), + ] diff --git a/app/partners/migrations/0004_ourpartnerspage.py b/app/partners/migrations/0004_ourpartnerspage.py new file mode 100644 index 0000000..fb72bed --- /dev/null +++ b/app/partners/migrations/0004_ourpartnerspage.py @@ -0,0 +1,38 @@ +# Generated by Django 4.2.7 on 2024-07-25 21:43 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.blocks +import wagtail.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0089_log_entry_data_json_null_to_object'), + ('wagtailimages', '0025_alter_image_file_alter_rendition_file'), + ('partners', '0003_rename_black_box_link_url_partnerwithuspage_black_box_link_email'), + ] + + operations = [ + migrations.CreateModel( + name='OurPartnersPage', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('intro', wagtail.fields.RichTextField(blank=True, help_text='This is shown in the header.')), + ('filter_by_type_text', models.CharField(default='Filter by Type')), + ('load_more_partners_text', models.CharField(default='Load More Partners')), + ('red_box_title', models.CharField(default='Join a working group')), + ('red_box_link_text', models.CharField(default='Working Groups')), + ('red_box_link_url', wagtail.fields.StreamField([('page', wagtail.blocks.PageChooserBlock()), ('url', wagtail.blocks.URLBlock())], blank=True, use_json_field=True)), + ('black_box_title', models.CharField(default='Contact a mapping community')), + ('black_box_link_text', models.CharField(default='Community Contact')), + ('black_box_link_url', wagtail.fields.StreamField([('page', wagtail.blocks.PageChooserBlock()), ('url', wagtail.blocks.URLBlock())], blank=True, use_json_field=True)), + ('header_image', models.ForeignKey(blank=True, help_text='Header image', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image')), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + ] diff --git a/app/partners/migrations/0005_alter_ourpartnerspage_black_box_link_text_and_more.py b/app/partners/migrations/0005_alter_ourpartnerspage_black_box_link_text_and_more.py new file mode 100644 index 0000000..d301782 --- /dev/null +++ b/app/partners/migrations/0005_alter_ourpartnerspage_black_box_link_text_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.7 on 2024-07-25 23:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('partners', '0004_ourpartnerspage'), + ] + + operations = [ + migrations.AlterField( + model_name='ourpartnerspage', + name='black_box_link_text', + field=models.CharField(default='Become a funder'), + ), + migrations.AlterField( + model_name='ourpartnerspage', + name='black_box_title', + field=models.CharField(default='Become a funding partner'), + ), + migrations.AlterField( + model_name='ourpartnerspage', + name='red_box_link_text', + field=models.CharField(default='Partner with us'), + ), + migrations.AlterField( + model_name='ourpartnerspage', + name='red_box_title', + field=models.CharField(default='Learn ways to partner with HOT'), + ), + ] diff --git a/app/partners/migrations/0006_ourpartnerspage_filter_button_text.py b/app/partners/migrations/0006_ourpartnerspage_filter_button_text.py new file mode 100644 index 0000000..47d6b22 --- /dev/null +++ b/app/partners/migrations/0006_ourpartnerspage_filter_button_text.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2024-07-26 16:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('partners', '0005_alter_ourpartnerspage_black_box_link_text_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='ourpartnerspage', + name='filter_button_text', + field=models.CharField(default='Submit'), + ), + ] diff --git a/app/partners/migrations/__init__.py b/app/partners/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/partners/models.py b/app/partners/models.py new file mode 100644 index 0000000..9377506 --- /dev/null +++ b/app/partners/models.py @@ -0,0 +1,151 @@ +from django.db import models +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from django.db.models import Q + +from wagtail.admin.panels import FieldPanel, MultiFieldPanel +from wagtail.fields import RichTextField, StreamField +from wagtail.blocks import CharBlock, StreamBlock, StructBlock, URLBlock, RichTextBlock, PageChooserBlock +from wagtail.images.blocks import ImageChooserBlock +from wagtail.models import Page +from app.core.models import LinkOrPageBlock, Partner, PartnerType + + +# The "partners" snippet is in the core app's models. + +class PartnerWithUsPage(Page): + def get_context(self, request, *args, **kwargs): + context = super().get_context(request, *args, **kwargs) + + partners = Partner.objects.all() + + context['partners'] = partners + return context + + max_count = 1 + + header_image = models.ForeignKey( + "wagtailimages.Image", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="+", + help_text="Header image" + ) + header_description = RichTextField(blank=True) + + intro = RichTextField(blank=True) + + partnership_types_title = models.CharField(default="Types of Partnerships") + partnership_types = StreamField([ + ('blocks', StructBlock([ + ('icon', ImageChooserBlock()), + ('title', CharBlock()), + ('description', RichTextBlock()) + ])) + ], use_json_field=True, null=True, blank=True, help_text="Blocks to be shown under the Types of Partnerships section.") + + meet_our_partners_title = models.CharField(default="Meet Our Partners") + view_all_partners_text = models.CharField(default="View All Partners") + view_all_partners_link = StreamField(LinkOrPageBlock(), use_json_field=True, blank=True) + + red_box_title = models.CharField(default="Still have questions?") + red_box_link_text = models.CharField(default="Contact our team") + red_box_link_url = StreamField(LinkOrPageBlock(), use_json_field=True, blank=True) + black_box_title = models.CharField(default="Become a Partner") + black_box_link_text = models.CharField(default="Email to partnerships@hotosm.org") + black_box_link_email = models.EmailField(default="partnerships@hotosm.org", max_length=254) + + content_panels = Page.content_panels + [ + MultiFieldPanel([ + FieldPanel('header_image'), + FieldPanel('header_description'), + ], heading="Header"), + FieldPanel('intro'), + MultiFieldPanel([ + FieldPanel('partnership_types_title'), + FieldPanel('partnership_types'), + ], heading="Types of Partnerships"), + MultiFieldPanel([ + FieldPanel('meet_our_partners_title'), + FieldPanel('view_all_partners_text'), + FieldPanel('view_all_partners_link'), + ], heading="Meet Our Partners"), + MultiFieldPanel([ + FieldPanel('red_box_title'), + FieldPanel('red_box_link_text'), + FieldPanel('red_box_link_url'), + FieldPanel('black_box_title'), + FieldPanel('black_box_link_text'), + FieldPanel('black_box_link_email'), + ], heading="Dogear Boxes"), + ] + + +class OurPartnersPage(Page): + def get_context(self, request, *args, **kwargs): + context = super().get_context(request, *args, **kwargs) + + partners = Partner.objects.all() + + p_types = PartnerType.objects.all() + query = Q() + for p_type in p_types: + if request.GET.get(str(p_type), ''): + query = query | Q(partner_type__type_name=p_type) + partners = partners.filter(query).distinct() + + page = request.GET.get('page', 1) + paginator = Paginator(partners, 12) # if you want more/less items per page (i.e., per load), change the number here to something else + try: + partners = paginator.page(page) + except PageNotAnInteger: + partners = paginator.page(1) + except EmptyPage: + partners = paginator.page(paginator.num_pages) + + context['partners'] = partners + context['partner_types'] = p_types + return context + + max_count = 1 + + header_image = models.ForeignKey( + "wagtailimages.Image", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="+", + help_text="Header image" + ) + intro = RichTextField(blank=True, help_text="This is shown in the header.") + + filter_by_type_text = models.CharField(default="Filter by Type") + + filter_button_text = models.CharField(default="Submit") + + load_more_partners_text = models.CharField(default="Load More Partners") + + red_box_title = models.CharField(default="Learn ways to partner with HOT") + red_box_link_text = models.CharField(default="Partner with us") + red_box_link_url = StreamField(LinkOrPageBlock(), use_json_field=True, blank=True) + black_box_title = models.CharField(default="Become a funding partner") + black_box_link_text = models.CharField(default="Become a funder") + black_box_link_url = StreamField(LinkOrPageBlock(), use_json_field=True, blank=True) + + content_panels = Page.content_panels + [ + MultiFieldPanel([ + FieldPanel('header_image'), + FieldPanel('intro'), + ], heading="Header"), + FieldPanel('filter_by_type_text'), + FieldPanel('filter_button_text'), + FieldPanel('load_more_partners_text'), + MultiFieldPanel([ + FieldPanel('red_box_title'), + FieldPanel('red_box_link_text'), + FieldPanel('red_box_link_url'), + FieldPanel('black_box_title'), + FieldPanel('black_box_link_text'), + FieldPanel('black_box_link_url'), + ], heading="Dogear Boxes"), + ] diff --git a/app/partners/templates/partners/our_partners_page.html b/app/partners/templates/partners/our_partners_page.html new file mode 100644 index 0000000..2af7fa2 --- /dev/null +++ b/app/partners/templates/partners/our_partners_page.html @@ -0,0 +1,78 @@ +{% extends "base.html" %} +{% load static %} +{% load wagtailcore_tags %} +{% load wagtailimages_tags %} +{% load compress %} +{% block body_class %}template-ourpartnerspage{% endblock %} +{% block extra_css %} + {% compress css %} + {% endcompress css %} +{% endblock extra_css %} + +{% block content %} + {% include "ui/components/PageHeaderWithBlur.html" with title=page.title subtitle=page.intro image=page.header_image full_length=True %} + +
+
+
+
+ {% comment %} TYPES {% endcomment %} +
+
+

+ {{page.filter_by_type_text}} +

+ {% include "ui/components/icon_svgs/LinkCaret.html" with class="rotate-90 text-hot-red" %} +
+
+
+ {% for p_type in partner_types %} +
+ + +
+ {% endfor %} +
+
+ +
+ +
+
+
+ +
+ {% for partner in partners %} +
+ {% image partner.partner_logo original class="max-h-24 max-w-36 h-auto w-auto" %} +
+ {% endfor %} +
+

+ {% if partners.has_next %} + {% comment %} {% endcomment %} + + {% endif %} +

+ +
+
+ {% include "ui/components/dogear_boxes/DogearRed.html" with title=page.red_box_title linktext=page.red_box_link_text linkurl=page.red_box_link_url %} +
+
+ {% include "ui/components/dogear_boxes/DogearBlack.html" with title=page.black_box_title linktext=page.black_box_link_text linkurl=page.black_box_link_url %} +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/app/partners/templates/partners/partner_with_us_page.html b/app/partners/templates/partners/partner_with_us_page.html new file mode 100644 index 0000000..491f0d3 --- /dev/null +++ b/app/partners/templates/partners/partner_with_us_page.html @@ -0,0 +1,53 @@ +{% extends "base.html" %} +{% load static %} +{% load wagtailcore_tags %} +{% load wagtailimages_tags %} +{% load compress %} +{% block body_class %}template-partnerwithuspage{% endblock %} +{% block extra_css %} + {% compress css %} + {% endcompress css %} +{% endblock extra_css %} + +{% block content %} + {% include "ui/components/PageHeaderWithBlur.html" with title=page.title subtitle=page.header_description image=page.header_image full_length=True %} + +
+
+
+
+ {{page.intro|safe}} +
+
+ + {% include "ui/components/SectionHeadingWithUnderline.html" with title=page.partnership_types_title %} +
+ {% for block in page.partnership_types %} +
+ {% image block.value.icon original class="h-8 w-8 mt-2" %} +

+ {{block.value.title}} +

+
+ {{block.value.description}} +
+
+ {% endfor %} +
+ + {% include "ui/components/FlexTitleWithLink.html" with title=page.meet_our_partners_title linktext=page.view_all_partners_text linkurl=page.view_all_partners_link underline=True %} +
+ {% include "ui/components/partners/PartnerViewBlock.html" %} +
+ +
+
+ {% include "ui/components/dogear_boxes/DogearRed.html" with title=page.red_box_title linktext=page.red_box_link_text linkurl=page.red_box_link_url %} +
+
+ {% include "ui/components/dogear_boxes/DogearBlack.html" with title=page.black_box_title linktext=page.black_box_link_text linkurl="mailto:"|add:page.black_box_link_email %} +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/app/partners/tests.py b/app/partners/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/partners/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/partners/views.py b/app/partners/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/app/partners/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/app/ui/templates/ui/components/FlexTitleWithLink.html b/app/ui/templates/ui/components/FlexTitleWithLink.html index ecf2dc6..8141c90 100644 --- a/app/ui/templates/ui/components/FlexTitleWithLink.html +++ b/app/ui/templates/ui/components/FlexTitleWithLink.html @@ -7,9 +7,14 @@ - linkurl: string; the url for the link {% endcomment %}
-

- {{title}} -

+
+

+ {{title}} +

+ {% if underline %} +
+ {% endif %} +

{% include "ui/components/BaseLink.html" %}

diff --git a/app/ui/templates/ui/components/PageHeaderWithBlur.html b/app/ui/templates/ui/components/PageHeaderWithBlur.html index e67f2ed..6d1c3f2 100644 --- a/app/ui/templates/ui/components/PageHeaderWithBlur.html +++ b/app/ui/templates/ui/components/PageHeaderWithBlur.html @@ -14,12 +14,14 @@
-

+

{{ title }}

- {% if subtitle %} - {{ subtitle|safe }} - {% endif %} +
+ {% if subtitle %} + {{ subtitle|safe }} + {% endif %} +
diff --git a/home/templatetags/homepage_tags.py b/home/templatetags/homepage_tags.py index 16500eb..cf36d38 100644 --- a/home/templatetags/homepage_tags.py +++ b/home/templatetags/homepage_tags.py @@ -16,8 +16,6 @@ def get_home_page(context): if not home_page: home_page = HomePage.objects.live().filter(locale=context['page'].locale).first().specific - - print(home_page) return home_page diff --git a/hot_osm/settings/base.py b/hot_osm/settings/base.py index dcb9101..1adafa5 100644 --- a/hot_osm/settings/base.py +++ b/hot_osm/settings/base.py @@ -51,6 +51,7 @@ "app.volunteer_opportunities", "app.rfp", "app.misc", + "app.partners", "search", "users", "utils",