diff --git a/district/models.py b/district/models.py index 21c9d7fd68423de12a6e2dc949e41ed98420b412..fc0bd5d1f73730d53f49463bc555b2ebbb3b9c93 100644 --- a/district/models.py +++ b/district/models.py @@ -52,6 +52,7 @@ from shared.models import ( ExtendedMetadataPageMixin, FooterMixin, MenuMixin, + NewsletterFormMixin, SubpageMixin, ) from shared.utils import make_promote_panels, strip_all_html_tags, trim_to_length @@ -73,6 +74,7 @@ class DistrictHomePage( MetadataPageMixin, CalendarMixin, FooterMixin, + NewsletterFormMixin, Page, ): ### FIELDS @@ -254,6 +256,7 @@ class DistrictHomePage( ], gettext_lazy("Kontakty"), ), + *NewsletterFormMixin.settings_panels, MultiFieldPanel( [ FieldPanel("footer_person_list"), diff --git a/shared/blocks.py b/shared/blocks.py index 0e5b066608cdcab065fdce02cb63917a0fab408d..d4d366443637f9661095177da7f0704f4ceaa812 100644 --- a/shared/blocks.py +++ b/shared/blocks.py @@ -1074,9 +1074,6 @@ class FooterLinksBlock(blocks.StructBlock): class NewsletterSubscriptionBlock(blocks.StructBlock): - subscription_id = blocks.CharBlock(label="ID newsletteru") - access_token = blocks.CharBlock(label="Access token") - design = blocks.StructBlock( local_blocks=[ ("icon", ImageChooserBlock(label="Vyberte si ikonku k formuláři")), @@ -1142,11 +1139,6 @@ class NewsletterSubscriptionBlock(blocks.StructBlock): config = blocks.StructBlock( local_blocks=[ ( - "require_confirmation", - blocks.BooleanBlock( - label="Požadovat zaslání ověřovacího e-mailu?", required=False - ), - )( "show_name_input", blocks.BooleanBlock( label="Umožnit uživateli přidat jméno a příjmení?", required=False @@ -1168,7 +1160,6 @@ class NewsletterSubscriptionBlock(blocks.StructBlock): ), ], default=[ - ("require_confirmation", True), ("show_name_input", False), ("force_subscribe", True), ("send_timezone", False), diff --git a/shared/models.py b/shared/models.py index f9e8b0bbbe313d4a6aec45497170a091a85541b2..0dc2ab9eb46fe2a7948416b8d159c93d9a911ad0 100644 --- a/shared/models.py +++ b/shared/models.py @@ -1,13 +1,12 @@ -import json import logging -from datetime import date, timedelta -import requests -from django.core.cache import cache +from django.core.serializers.json import DjangoJSONEncoder from django.db import models +from django.http import JsonResponse from django.utils import timezone -from icalevents import icalevents +from requests import request from wagtail.admin.panels import FieldPanel, MultiFieldPanel, PublishingPanel +from wagtail.contrib.routable_page.models import RoutablePageMixin, route from wagtail.fields import StreamField from wagtail.models import Page @@ -21,6 +20,58 @@ from shared.blocks import ( logger = logging.getLogger(__name__) +class NewsletterFormMixin(RoutablePageMixin, models.Model): + subscription_id = models.CharField(label="ID newsletteru") + access_token = models.CharField(label="Access token") + require_confirmation = models.BooleanField( + label="Požadovat zaslání ověřovacího e-mailu?", default=True + ) + + settings_panels = [ + MultiFieldPanel( + [ + FieldPanel("subscription_id"), + FieldPanel("access_token"), + ], + heading="Nastavení API newsletteru", + ), + ] + + @route(r"^newsletter/$", name="newsletter") + def newsletter_post(self, posted): + if posted.method == "POST": + mailtrain_request = {"EMAIL": posted.POST["email"]} + if "first_name" in posted.POST and "last_name" in posted.POST: + mailtrain_request.update( + { + "MERGE_FIRST_NAME": posted.POST["first_name"], + "MERGE_LAST_NAME": posted.POST["last_name"], + } + ) + if "force_subscribe" in posted.GET: + mailtrain_request.update( + { + "FORCE_SUBSCRIBE": "yes", + } + ) + if "timezone" in posted.POST: + mailtrain_request.update({"TIMEZONE": posted.POST["timezone"]}) + if self.require_confirmation: + mailtrain_request.update({"REQUIRE_CONFIRMATION": "yes"}) + return JsonResponse( + request( + "POST", + f"https://mailtrain.pirati.cz/api/subscribe/{self.subscription_id}?access_token={self.access_token}", + mailtrain_request, + ).json(), + encoder=DjangoJSONEncoder, + ) + raise ValueError("Request has to be post!") + + class Meta: + abstract = True + + class SubpageMixin: """Must be used in class definition before MetadataPageMixin!""" diff --git a/shared/static/shared/js/vue-formulate-helper.js b/shared/static/shared/js/vue-formulate-helper.js index edc7cfdde91bad424a7a84dd7710933ba8b43b9a..e7fc14fd45be20112447aa85e4dd59991567a43a 100644 --- a/shared/static/shared/js/vue-formulate-helper.js +++ b/shared/static/shared/js/vue-formulate-helper.js @@ -2,3 +2,18 @@ Vue.use(VueFormulate, { plugins: [VueFormulateI18n.cs], locale: "cs", }); + +Vue.use(Vue.component("MailtrainFormContainer", { + props: { + url: String, + }, + methods: { + onSubmit(...data) { + // Intl.DateTimeFormat().resolvedOptions().timeZone) + console.log(this, ...data); + }, + }, + render(createElement) { + return createElement("div", {}, this.$slots.default); + } +})) diff --git a/shared/templates/shared/blocks/newsletter_subscription_block.html b/shared/templates/shared/blocks/newsletter_subscription_block.html index 043f39103c52bb8b6c80be6bba9dc7ae23321405..41793f6ba3832794f146231e505b39a99c2c637b 100644 --- a/shared/templates/shared/blocks/newsletter_subscription_block.html +++ b/shared/templates/shared/blocks/newsletter_subscription_block.html @@ -24,31 +24,40 @@ {{ self.design.subtitle }} </span> <div class="flex flex-col items-start"> - <FormulateForm method="POST" action="{% fullpageurl page.root_page %}/newsletter" #default="{ isLoading, hasErrors }"> - {% csrf_token %} - {% if self.config.show_name_input %} - <FormulateInput type="text" name="first_name" :element-class="() => ['text-input', 'bg-white', 'form-field__control', 'mb-3', 'w-full']" label="{{ self.design.labels.first_name }}" - placeholder="{{ self.design.labels.first_name }}" validation="required" error-behavior="value" + <MailtrainFormContainer url="{% if self.config.force_subscribe %}{% routablepageurl page.root_page 'newsletter' force_subscribe=True %}{% else %}{% routablepageurl page.root_page 'newsletter' %}{% endif %}"> + <FormulateForm @submit="onSubmit" #default="{ isLoading, hasErrors }"> + {% csrf_token %} + {% if self.config.send_timezone %} + <FormulateInput + type="hidden" + name="send_timezone" + value="True" + /> + {% endif %} + {% if self.config.show_name_input %} + <FormulateInput type="text" name="first_name" :element-class="() => ['text-input', 'bg-white', 'form-field__control', 'mb-3', 'w-full']" label="{{ self.design.labels.first_name }}" + placeholder="{{ self.design.labels.first_name }}" validation="required" error-behavior="value" + label-class="sr-only" /> + <FormulateInput type="text" name="last_name" :element-class="() => ['text-input', 'bg-white', 'form-field__control', 'mb-3', 'w-full']" label="{{ self.design.labels.last_name }}" + placeholder="{{ self.design.labels.last_name }}" validation="required" error-behavior="value" + label-class="sr-only" /> + {% endif %} + <FormulateInput type="email" name="email" :element-class="() => ['text-input', 'bg-white', 'form-field__control', 'mb-3', 'w-full']" label="{{ self.design.labels.email }}" + placeholder="{{ self.design.labels.email }}" validation="required|email" error-behavior="value" label-class="sr-only" /> - <FormulateInput type="text" name="last_name" :element-class="() => ['text-input', 'bg-white', 'form-field__control', 'mb-3', 'w-full']" label="{{ self.design.labels.last_name }}" - placeholder="{{ self.design.labels.last_name }}" validation="required" error-behavior="value" - label-class="sr-only" /> - {% endif %} - <FormulateInput type="email" name="email" :element-class="() => ['text-input', 'bg-white', 'form-field__control', 'mb-3', 'w-full']" label="{{ self.design.labels.email }}" - placeholder="{{ self.design.labels.email }}" validation="required|email" error-behavior="value" - label-class="sr-only" /> - <div class="checkbox form-field__control flex items-center mb-3"> - <FormulateInput type="checkbox" label="{% include_block self.design.consent %}" label-class="text-xs font-alt font-light" validation="required" error-behavior="value" /> - </div> - <FormulateErrors /> - <button type="submit" :disabled="isLoading || hasErrors" class="btn btn--black btn--to-yellow-500 btn--hoveractive uppercase"> - <span class="btn__body-wrap"> - <span v-html="isLoading ? 'Odesílám...' : '{{ self.design.button }}'" class="btn__body text-lg lg:text-base"> - Odebírat + <div class="checkbox form-field__control flex items-center mb-3"> + <FormulateInput type="checkbox" label="{% include_block self.design.consent %}" label-class="text-xs font-alt font-light" validation="required" error-behavior="value" /> + </div> + <FormulateErrors /> + <button type="submit" :disabled="isLoading || hasErrors" class="btn btn--black btn--to-yellow-500 btn--hoveractive uppercase"> + <span class="btn__body-wrap"> + <span v-html="isLoading ? 'Odesílám...' : '{{ self.design.button }}'" class="btn__body text-lg lg:text-base"> + Odebírat + </span> </span> - </span> - </button> - </FormulateForm> + </button> + </FormulateForm> + </MailtrainFormContainer> </div> </div> </div> diff --git a/uniweb/models.py b/uniweb/models.py index 423ad0481b51c2436c7197d100ae02d1333cfd08..d0093886ac7a46d811b777401092273f0125e4cc 100644 --- a/uniweb/models.py +++ b/uniweb/models.py @@ -32,6 +32,7 @@ from shared.models import ( ExtendedMetadataHomePageMixin, ExtendedMetadataPageMixin, FooterMixin, + NewsletterFormMixin, SubpageMixin, ) from shared.utils import make_promote_panels, strip_all_html_tags, trim_to_length @@ -301,7 +302,12 @@ class UniwebArticleTag(TaggedItemBase): class UniwebHomePage( - Page, ExtendedMetadataHomePageMixin, MetadataPageMixin, CalendarMixin, FooterMixin + Page, + ExtendedMetadataHomePageMixin, + MetadataPageMixin, + CalendarMixin, + NewsletterFormMixin, + FooterMixin, ): ### FIELDS @@ -364,6 +370,7 @@ class UniwebHomePage( ], "nastavení webu", ), + *NewsletterFormMixin.settings_panels, FieldPanel("calendar_url"), MultiFieldPanel( [