diff --git a/donate/forms.py b/donate/forms.py index 05fe9cceab424c3c361c4f1dc9c5d86cd5f9f58f..de9f6f1688dba03ac30ff0e17d44a7c1279b4153 100644 --- a/donate/forms.py +++ b/donate/forms.py @@ -8,11 +8,13 @@ class DonateForm(forms.Form): CUSTOM_AMOUNT = -1 DEFAULT_CUSTOM_AMOUNT = 1000 ALLOWED_PERIODICITY = [730, 99999] + PORTAL_ID_IN_SELECT = -1 amount = forms.IntegerField() custom_amount = forms.IntegerField(required=False) periodicity = forms.IntegerField() portal_project_id = forms.IntegerField() + select_portal_project_id = forms.IntegerField(required=False) def clean_periodicity(self): value = self.cleaned_data["periodicity"] @@ -32,6 +34,8 @@ class DonateForm(forms.Form): amount = self.get_amount() periodicity = self.cleaned_data["periodicity"] portal_project_id = self.cleaned_data["portal_project_id"] + if portal_project_id == self.PORTAL_ID_IN_SELECT: + portal_project_id = self.cleaned_data["select_portal_project_id"] query = urllib.parse.urlencode( { "amount": amount, diff --git a/donate/migrations/0012_auto_20200915_0114.py b/donate/migrations/0012_auto_20200915_0114.py new file mode 100644 index 0000000000000000000000000000000000000000..081f64e18bce135811a5a9d7efdd3e77536b01db --- /dev/null +++ b/donate/migrations/0012_auto_20200915_0114.py @@ -0,0 +1,68 @@ +# Generated by Django 3.1.1 on 2020-09-14 23:14 + +import django.db.models.deletion +import modelcluster.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("donate", "0011_donateprojectpage_form_preselected"), + ] + + operations = [ + migrations.RemoveField( + model_name="donatetargeteddonationspage", name="targeted_donations", + ), + migrations.CreateModel( + name="TargetedDonation", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ( + "is_main", + models.BooleanField( + default=False, + help_text="zobrazené samostatně nahoře", + verbose_name="hlavní dar", + ), + ), + ("title", models.CharField(max_length=255, verbose_name="název")), + ( + "description", + models.CharField( + blank=True, + help_text="zobrazí se jen u hlavních darů", + max_length=255, + null=True, + verbose_name="popis", + ), + ), + ( + "portal_project_id", + models.IntegerField(verbose_name="ID projektu v darovacím portálu"), + ), + ( + "page", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="targeted_donations", + to="donate.donatetargeteddonationspage", + ), + ), + ], + options={"ordering": ["sort_order"], "abstract": False,}, + ), + ] diff --git a/donate/models.py b/donate/models.py index b588a5f8f3d451da818ee31939bbd3bc00fd17e0..0540fb968ff058a132ffd36eaf1136173ff526e8 100644 --- a/donate/models.py +++ b/donate/models.py @@ -4,16 +4,18 @@ from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.db import models from django.shortcuts import redirect from django.utils.translation import gettext_lazy +from modelcluster.fields import ParentalKey from wagtail.admin.edit_handlers import ( FieldPanel, HelpPanel, + InlinePanel, MultiFieldPanel, PublishingPanel, StreamFieldPanel, ) from wagtail.core import blocks from wagtail.core.fields import RichTextField, StreamField -from wagtail.core.models import Page +from wagtail.core.models import Orderable, Page from wagtail.images.blocks import ImageChooserBlock from wagtail.images.edit_handlers import ImageChooserPanel from wagtailmetadata.models import MetadataPageMixin @@ -574,17 +576,31 @@ class DonateInfoPage(DonateFormMixin, Page, SubpageMixin, MetadataPageMixin): return self.get_parent().specific.portal_project_id -class TargetedDonationBlock(blocks.StructBlock): - title = blocks.CharBlock(label="název") - description = blocks.CharBlock(label="popis", required=False) - portal_project_id = blocks.IntegerBlock( - label="ID projektu v darovacím portálu", - required=False, - help_text="Pokud není zadáno ID projektu, tak se adresný dar nezobrazí.", +class TargetedDonation(Orderable): + page = ParentalKey( + "donate.DonateTargetedDonationsPage", + on_delete=models.CASCADE, + related_name="targeted_donations", ) + is_main = models.BooleanField( + "hlavní dar", default=False, help_text="zobrazené samostatně nahoře" + ) + title = models.CharField("název", max_length=255) + description = models.CharField( + "popis", + null=True, + blank=True, + max_length=255, + help_text="zobrazí se jen u hlavních darů", + ) + portal_project_id = models.IntegerField("ID projektu v darovacím portálu") - class Meta: - label = "adresný dar" + panels = [ + FieldPanel("portal_project_id"), + FieldPanel("title"), + FieldPanel("description"), + FieldPanel("is_main"), + ] class DonateTargetedDonationsPage( @@ -592,17 +608,13 @@ class DonateTargetedDonationsPage( ): ### FIELDS - targeted_donations = StreamField( - [("item", TargetedDonationBlock())], verbose_name="adresné dary", blank=True - ) - # page does not have specific portal_project_id portal_project_id = None ### PANELS content_panels = Page.content_panels + [ - StreamFieldPanel("targeted_donations"), + MultiFieldPanel([InlinePanel("targeted_donations")], "adresné dary"), ] promote_panels = [ @@ -630,6 +642,33 @@ class DonateTargetedDonationsPage( class Meta: verbose_name = "Adresné dary" - @property - def show_donate_form(self): - return bool(self.targeted_donations) + def get_context(self, request): + context = super().get_context(request) + + try: + selected_project_id = int(request.GET.get("p", 0)) + selected_target = self.targeted_donations.get( + portal_project_id=selected_project_id + ) + except (ValueError, TargetedDonation.DoesNotExist): + selected_target = None + + if selected_target: + context["main_targets"] = [selected_target] + context["other_targets"] = [] + context["is_preselected"] = True + else: + context["main_targets"] = self.targeted_donations.filter(is_main=True) + context["other_targets"] = self.targeted_donations.filter(is_main=False) + context["is_preselected"] = False + + if context["main_targets"]: + context["initial_project_id"] = context["main_targets"][0].portal_project_id + elif context["other_targets"]: + context["initial_project_id"] = context["other_targets"][ + 0 + ].portal_project_id + else: + context["initial_project_id"] = 0 + + return context diff --git a/donate/static/donate/assets/css/style.css b/donate/static/donate/assets/css/style.css index 36b6430e26f2887a7154f68bc916493c1d4e7523..ec01c9eb26347b2f0b7cc41a9d9c3f625144808e 100644 --- a/donate/static/donate/assets/css/style.css +++ b/donate/static/donate/assets/css/style.css @@ -752,6 +752,15 @@ footer h1, footer h2, footer h3, footer h4, footer h5, footer h6 { height: 2rem; } +.custom-control-label-for-select { + line-height: 1; + padding-top: 0.4rem; +} + +.custom-control-select { + padding: 0.3rem; +} + .custom-control-input { width: 2rem; height: 2.5rem; diff --git a/donate/static/donate/assets/js/scripts.js b/donate/static/donate/assets/js/scripts.js index fd9bf077fe197f99488970567a6f771f7aa6a717..9554c300a0df8a6029980eb10e433bbc165074c9 100644 --- a/donate/static/donate/assets/js/scripts.js +++ b/donate/static/donate/assets/js/scripts.js @@ -50,26 +50,51 @@ /* DONATE FORM */ -// On amount radio change -$("input[name='amount']").change(function() { + // On amount radio change + $("input[name='amount']").change(function() { - // If custom amount is selected - if($(this).attr('id') == 'amount4') { + // If custom amount is selected + if($(this).attr('id') == 'amount4') { - // Show custom amount input and set it required - $("#js-custom-amount-input").show(50); - $('#customamount').attr('required', true); + // Show custom amount input and set it required + $("#js-custom-amount-input").show(50); + $('#customamount').attr('required', true); - } else { + } else { - // Hide custom amount and remove required field - $("#js-custom-amount-input").hide(50); - $('#customamount').attr('required', false); + // Hide custom amount and remove required field + $("#js-custom-amount-input").hide(50); + $('#customamount').attr('required', false); + } + }); + + // Trigger correct state onload + $("input[name='amount']:checked").change(); + + // Update sharing link on form change for target donations + + function updateLink(projectId) { + var url = new URL(location.href); + url.searchParams.set("p", projectId); + console.log(url.href); + $("#target_sharing_link").attr("href", url.href); } -}); -// Trigger correct state onload -$("input[name='amount']:checked").change(); + $("input:radio.target-radio").change(function () { + if ($(this).is(":checked")) { + if ($(this).val() == -1) { + updateLink($("#other_target_select").val()); + } else { + updateLink($(this).val()); + } + } + }); + + $("#other_target_select").change(function () { + if ($("#other_target").is(":checked")) { + updateLink($("#other_target_select").val()); + } + }); })(jQuery); diff --git a/donate/templates/donate/donate_targeted_donations_page.html b/donate/templates/donate/donate_targeted_donations_page.html index 5529abaa19c8aa17c6f7e77ae365270184675374..3d49c8564d4607be7b8459ed89900dc57dae7790 100644 --- a/donate/templates/donate/donate_targeted_donations_page.html +++ b/donate/templates/donate/donate_targeted_donations_page.html @@ -15,20 +15,35 @@ <section class="section--primary section--form"> <div class="container"> - {% if page.show_donate_form %} - <form id="js-donate-form" method="post"> + {% if main_targets or other_targets %} + <form id="js-donate-form" class="sharing-link" method="post"> {% csrf_token %} <div class="form-group row mb-4 align-items-center"> <div class="col-12"> - {% for target in page.targeted_donations %} - {% if target.value.portal_project_id %} + + {% for target in main_targets %} + {% if target.portal_project_id %} <div class="custom-control custom-radio my-3"> - <input type="radio" id="target{{ forloop.counter }}" name="portal_project_id" value="{{ target.value.portal_project_id }}" class="custom-control-input"{% if forloop.first %} checked required{% endif %}> - <label class="custom-control-label col-form-label-lg" for="target{{ forloop.counter }}">{{ target.value.title }}<br> <span class="small">{{ target.value.description }}</span></label> + <input type="radio" id="main_target{{ forloop.counter }}" name="portal_project_id" value="{{ target.portal_project_id }}" class="custom-control-input target-radio"{% if forloop.first %} checked required{% endif %}> + <label class="custom-control-label col-form-label-lg" for="main_target{{ forloop.counter }}">{{ target.title }}<br> <span class="small">{{ target.description|default:"" }}</span></label> </div> {% endif %} {% endfor %} + + {% if other_targets %} + <div class="custom-control custom-radio my-3"> + <input type="radio" id="other_target" name="portal_project_id" value="-1" class="custom-control-input target-radio"{% if not main_targets %} checked required{% endif %}> + <label class="custom-control-label col-form-label-lg custom-control-label-for-select" for="other_target"> + <select id="other_target_select" name="select_portal_project_id" class="custom-control-select"> + {% for target in other_targets %} + <option value="{{ target.portal_project_id }}">{{ target.title }}</option> + {% endfor %} + </select> + </label> + </div> + {% endif %} + </div> </div> @@ -54,7 +69,7 @@ </div> </div> <div class="form-group row mb-4 align-items-center" id="js-custom-amount-input" style="display: none;"> - <div class="offset-md-3 col-md-9"> + <div class="offset-md-3 col-md-3"> <div class="input-group input-group-lg mb-3 custom-amount"> <input type="number" class="form-control" id="customamount" name="custom_amount" aria-describedby="customamount-currency"> <div class="input-group-append"> @@ -82,6 +97,15 @@ </div> </div> </form> + + <div class="mt-5"> + {% if is_preselected %} + <a href="{% pageurl page %}">ukaž všechny adresné dary pro kraj</a> + {% else %} + <a id="target_sharing_link" href="{% pageurl page %}?p={{ initial_project_id }}">odkaz pro sdílení</a> + {% endif %} + </div> + {% else %} <div class="row mb-4"> <p>Krajské sdružení momentálně nepřijímá adresné dary. Místo toho <a href="{% pageurl page.get_parent %}">podpořte celý kraj!</a></p>