diff --git a/elections2021/constants.py b/elections2021/constants.py index 9f424d7683b4deedf6fe06f825902cac99dbd954..c7ef4f5f95ded94032fa25f9b9cb112dc85d35dc 100644 --- a/elections2021/constants.py +++ b/elections2021/constants.py @@ -34,6 +34,22 @@ ARTICLE_RICH_TEXT_FEATURES = [ "document-link", ] +STRATEGIC_RICH_TEXT_FEATURES = [ + "h3", + "h4", + "bold", + "italic", + "superscript", + "subscript", + "strikethrough", + "ul-elections2021", + "ol-elections2021", + "blockquote-elections2021", + "link", + "image", + "document-link", +] + CANDIDATE_RICH_TEXT_FEATURES = [ "h3", "bold", @@ -54,6 +70,7 @@ EXTRA_FEATURES = ["h4", "ul-program-elections2021", "superscript", "link", "ital ARTICLES_PER_PAGE = 9 TOP_CANDIDATES_NUM = 12 PROGRAM_POINTS_PER_PAGE = 12 +STRATEGIC_PER_PAGE = 9 REGION_PHA = "PHA" REGION_JHC = "JHC" diff --git a/elections2021/migrations/0016_elections2021textpage.py b/elections2021/migrations/0016_elections2021textpage.py new file mode 100644 index 0000000000000000000000000000000000000000..a7b51c0546d1e7d9949d59685620583f600ce1c4 --- /dev/null +++ b/elections2021/migrations/0016_elections2021textpage.py @@ -0,0 +1,72 @@ +# Generated by Django 3.2.2 on 2021-05-16 21:42 + +import django.db.models.deletion +import wagtail.core.fields +import wagtailmetadata.models +from django.db import migrations, models + +import shared.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("wagtailcore", "0062_comment_models_and_pagesubscription"), + ("wagtailimages", "0023_add_choose_permissions"), + ("elections2021", "0015_auto_20210516_0127"), + ] + + operations = [ + migrations.CreateModel( + name="Elections2021TextPage", + 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", + ), + ), + ( + "body", + wagtail.core.fields.RichTextField( + blank=True, null=True, verbose_name="obsah stránky" + ), + ), + ( + "photo", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="wagtailimages.image", + verbose_name="hlavní fotka", + ), + ), + ( + "search_image", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailimages.image", + verbose_name="Search image", + ), + ), + ], + options={ + "verbose_name": "Textová stránka", + }, + bases=( + shared.models.SubpageMixin, + wagtailmetadata.models.WagtailImageMetadataMixin, + "wagtailcore.page", + models.Model, + ), + ), + ] diff --git a/elections2021/migrations/0017_auto_20210517_0059.py b/elections2021/migrations/0017_auto_20210517_0059.py new file mode 100644 index 0000000000000000000000000000000000000000..9a68b8ebdd05123a6770d397cd8a898de25fb9f2 --- /dev/null +++ b/elections2021/migrations/0017_auto_20210517_0059.py @@ -0,0 +1,151 @@ +# Generated by Django 3.2.2 on 2021-05-16 22:59 + +import django.db.models.deletion +import wagtail.core.blocks +import wagtail.core.fields +import wagtailmetadata.models +from django.db import migrations, models + +import shared.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("wagtailcore", "0062_comment_models_and_pagesubscription"), + ("wagtailimages", "0023_add_choose_permissions"), + ("elections2021", "0016_elections2021textpage"), + ] + + operations = [ + migrations.RemoveField( + model_name="elections2021textpage", + name="photo", + ), + migrations.CreateModel( + name="Elections2021StrategicPage", + 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", + ), + ), + ( + "card_style", + models.CharField( + choices=[ + ("white", "bílé pozadí"), + ("black", "černé pozadí"), + ("yellow", "žluté pozadí"), + ("green", "zelené pozadí"), + ], + default="white", + max_length=10, + verbose_name="styl karty v přehledu", + ), + ), + ("perex", models.TextField(verbose_name="perex")), + ( + "content", + wagtail.core.fields.StreamField( + [ + ( + "title", + wagtail.core.blocks.CharBlock( + icon="title", + label="nadpis", + template="elections2021/_strategic_title_block.html", + ), + ), + ( + "text", + wagtail.core.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "bold", + "italic", + "superscript", + "subscript", + "strikethrough", + "ul-elections2021", + "ol-elections2021", + "blockquote-elections2021", + "link", + "image", + "document-link", + ], + label="text", + template="uniweb/blocks/_strategic_text_block.html", + ), + ), + ], + blank=True, + verbose_name="obsah stránky", + ), + ), + ( + "search_image", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailimages.image", + verbose_name="Search image", + ), + ), + ], + options={ + "verbose_name": "Strategický dokument", + }, + bases=( + shared.models.SubpageMixin, + wagtailmetadata.models.WagtailImageMetadataMixin, + "wagtailcore.page", + models.Model, + ), + ), + migrations.CreateModel( + name="Elections2021StrategicListPage", + 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", + ), + ), + ( + "search_image", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailimages.image", + verbose_name="Search image", + ), + ), + ], + options={ + "verbose_name": "Přehled strategických dokumentů", + }, + bases=( + shared.models.SubpageMixin, + wagtailmetadata.models.WagtailImageMetadataMixin, + "wagtailcore.page", + models.Model, + ), + ), + ] diff --git a/elections2021/models.py b/elections2021/models.py index 3d59a76faadaf3d2833d514b3f4fc18537362652..456cdbcb3166199d25f9e0e7189d460f60433cb8 100644 --- a/elections2021/models.py +++ b/elections2021/models.py @@ -7,6 +7,7 @@ from django.core.paginator import Paginator from django.db import models from django.db.models.functions import Greatest from django.http import HttpResponseRedirect +from django.utils.text import slugify from django.utils.translation import gettext_lazy from modelcluster.contrib.taggit import ClusterTaggableManager from modelcluster.fields import ParentalKey @@ -90,6 +91,8 @@ from .constants import ( SENIORS, SPORT, STANDARD_FEATURES, + STRATEGIC_PER_PAGE, + STRATEGIC_RICH_TEXT_FEATURES, STUDENTS, STYLE_CHOICES, STYLE_CSS, @@ -161,6 +164,8 @@ class Elections2021HomePage(Page, MetadataPageMixin): "elections2021.Elections2021ProgramPage", "elections2021.Elections2021QuestionsPage", "elections2021.Elections2021ProgramAppPage", + "elections2021.Elections2021TextPage", + "elections2021.Elections2021StrategicListPage", ] ### OTHERS @@ -303,9 +308,10 @@ class Elections2021ArticlesPage(SubpageMixin, MetadataPageMixin, Page): ], gettext_lazy("Common page configuration"), ), + CommentPanel(), ] - settings_panels = [CommentPanel()] + settings_panels = [] ### RELATIONS @@ -360,9 +366,10 @@ class Elections2021CandidatesListPage( ], gettext_lazy("Common page configuration"), ), + CommentPanel(), ] - settings_panels = [CommentPanel()] + settings_panels = [] ### RELATIONS @@ -437,9 +444,10 @@ class Elections2021CandidatesMapPage(SubpageMixin, MetadataPageMixin, Page): ], gettext_lazy("Common page configuration"), ), + CommentPanel(), ] - settings_panels = [CommentPanel()] + settings_panels = [] ### RELATIONS @@ -522,9 +530,10 @@ class Elections2021CandidatePage(SubpageMixin, MetadataPageMixin, Page): ], gettext_lazy("Common page configuration"), ), + CommentPanel(), ] - settings_panels = [CommentPanel()] + settings_panels = [] ### RELATIONS @@ -1575,9 +1584,10 @@ class Elections2021ProgramAppPage(SubpageMixin, MetadataPageMixin, Page): ], gettext_lazy("Common page configuration"), ), + CommentPanel(), ] - settings_panels = [CommentPanel()] + settings_panels = [] ### RELATIONS @@ -1640,3 +1650,153 @@ class Elections2021ProgramAppPage(SubpageMixin, MetadataPageMixin, Page): "education": EDUCATION in selection["topics"], } return context + + +class Elections2021TextPage(SubpageMixin, MetadataPageMixin, Page): + ### FIELDS + + body = RichTextField( + "obsah stránky", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES + ) + + ### PANELS + + content_panels = Page.content_panels + [FieldPanel("body")] + + promote_panels = [ + MultiFieldPanel( + [ + FieldPanel("slug"), + FieldPanel("seo_title"), + FieldPanel("search_description"), + ImageChooserPanel("search_image"), + HelpPanel(help.build(help.NO_SEO_TITLE)), + ], + gettext_lazy("Common page configuration"), + ), + CommentPanel(), + ] + + settings_panels = [] + + ### RELATIONS + + parent_page_types = ["elections2021.Elections2021HomePage"] + subpage_types = [] + + ### OTHERS + + class Meta: + verbose_name = "Textová stránka" + + +class Elections2021StrategicListPage(SubpageMixin, MetadataPageMixin, Page): + ### FIELDS + + ### PANELS + + promote_panels = [ + MultiFieldPanel( + [ + FieldPanel("slug"), + FieldPanel("seo_title"), + FieldPanel("search_description"), + ImageChooserPanel("search_image"), + HelpPanel(help.build(help.NO_SEO_TITLE)), + ], + gettext_lazy("Common page configuration"), + ), + CommentPanel(), + ] + + settings_panels = [] + + ### RELATIONS + + parent_page_types = ["elections2021.Elections2021HomePage"] + subpage_types = ["elections2021.Elections2021StrategicPage"] + + ### OTHERS + + class Meta: + verbose_name = "Strategické dokumenty" + + def get_context(self, request): + context = super().get_context(request) + context["strategic_documents"] = Paginator( + self.get_children().live().specific(), STRATEGIC_PER_PAGE + ).get_page(request.GET.get("page")) + return context + + +class Elections2021StrategicPage(SubpageMixin, MetadataPageMixin, Page): + ### FIELDS + + card_style = models.CharField( + "styl karty v přehledu", choices=STYLE_CHOICES, default=WHITE, max_length=10 + ) + perex = models.TextField("perex") + content = StreamField( + [ + ( + "title", + blocks.CharBlock( + label="nadpis sekce (pro navigaci)", + icon="title", + template="elections2021/_strategic_title_block.html", + ), + ), + ( + "text", + blocks.RichTextBlock( + label="text", + features=STRATEGIC_RICH_TEXT_FEATURES, + template="elections2021/_strategic_text_block.html", + ), + ), + ], + verbose_name="obsah stránky", + blank=True, + ) + + ### PANELS + + content_panels = Page.content_panels + [ + FieldPanel("perex"), + StreamFieldPanel("content"), + FieldPanel("card_style"), + ] + + promote_panels = [ + MultiFieldPanel( + [ + FieldPanel("slug"), + FieldPanel("seo_title"), + FieldPanel("search_description"), + ImageChooserPanel("search_image"), + HelpPanel(help.build(help.NO_SEO_TITLE)), + ], + gettext_lazy("Common page configuration"), + ), + CommentPanel(), + ] + + settings_panels = [] + + ### RELATIONS + + parent_page_types = ["elections2021.Elections2021StrategicListPage"] + subpage_types = [] + + ### OTHERS + + class Meta: + verbose_name = "Strategický dokument" + + def get_context(self, request): + context = super().get_context(request) + context["navigation"] = [] + for block in self.content: + if block.block_type == "title": + context["navigation"].append((slugify(block.value), block.value)) + return context diff --git a/elections2021/templates/elections2021/_strategic_text_block.html b/elections2021/templates/elections2021/_strategic_text_block.html new file mode 100644 index 0000000000000000000000000000000000000000..a81a9ac469ac12202be3bf42e2aaf291d6f6b18f --- /dev/null +++ b/elections2021/templates/elections2021/_strategic_text_block.html @@ -0,0 +1,2 @@ +{% load wagtailcore_tags %} +{{ block.value|richtext }} diff --git a/elections2021/templates/elections2021/_strategic_title_block.html b/elections2021/templates/elections2021/_strategic_title_block.html new file mode 100644 index 0000000000000000000000000000000000000000..6dcd7824e04417e6c9fe668acf66f813390e76da --- /dev/null +++ b/elections2021/templates/elections2021/_strategic_title_block.html @@ -0,0 +1 @@ +<h2 id="{{ block.value|slugify }}">{{ block.value }}</h2> diff --git a/elections2021/templates/elections2021/elections2021_strategic_list_page.html b/elections2021/templates/elections2021/elections2021_strategic_list_page.html new file mode 100644 index 0000000000000000000000000000000000000000..07c010871ba4bad0b812eccedecc5dc61e07f235 --- /dev/null +++ b/elections2021/templates/elections2021/elections2021_strategic_list_page.html @@ -0,0 +1,54 @@ +{% extends "elections2021/base.html" %} +{% load wagtailcore_tags %} + +{% block content %} + +<article class="relative bg-lemon md:bg-split-color px-4 md:pl-8 md:pr-0 2xl:px-8 hero py-0 w-full "> + <div class="2xl:container w-auto bg-lemon md:pl-20 pr-0 grid lg:grid-rows-2 lg:grid-cols-7 items-center 2xl:mx-auto"> + <div class="lg:row-span-1 lg:col-span-7 order-1 pt-14 md:pr-20"> + <h1 class="head-alt-md sm:head-alt-lg">{{ page.title }}</h1> + </div> + {% comment %} + <div class="lg:row-span-1 lg:col-span-7 order-3 pb-14 md:pr-20"> + <div class="pt-8 sm:flex"> + <input name="" type="text" class="text-input form-field__control w-full max-w-xl" value="" placeholder="Placeholder"> + <button class="btn btn--icon block sm:inline-block"> + <div class="btn__body-wrap"> + <div class="btn__body py-4">Vyhledat</div> + <div class="btn__icon bg-grey-800"> + <i class="ico--chevron-right"></i> + </div> + </div> + </button> + </div> + </div> + {% endcomment %} + </div> +</article> + +<div class="container container--default pt-8 pb-16 lg:py-24"> + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> + + {% for strategic in strategic_documents %} + {% if strategic.card_style == "black" %} + <div class="card shadow-none bg-black border-b border-solid border-black card--min-square text-white card--hoveractive"> + {% elif strategic.card_style == "yellow" %} + <div class="card shadow-none bg-lemon border-b border-solid border-lemon card--min-square card--hoveractive"> + {% elif strategic.card_style == "green" %} + <div class="card shadow-none bg-acidgreen border-b border-solid border-acidgreen card--min-square text-black card--hoveractive"> + {% else %} + <div class="card shadow-none bg-white border-b border-solid border-grey-125 card--min-square card--hoveractive"> + {% endif %} + <div class="card__body"> + <h1 class="card-headline mb-8"><a href="{% pageurl strategic %}">{{ strategic.title }}</a></h1> + <p class="card-body-text">{{ strategic.perex }}</p> + </div> + </div> + {% endfor %} + + </div> +</div> + +{% include "elections2021/_pagination.html" with paginator=strategic_documents %} + +{% endblock %} diff --git a/elections2021/templates/elections2021/elections2021_strategic_page.html b/elections2021/templates/elections2021/elections2021_strategic_page.html new file mode 100644 index 0000000000000000000000000000000000000000..d67f2b11d2eea727e51d5324200f0836853dd12e --- /dev/null +++ b/elections2021/templates/elections2021/elections2021_strategic_page.html @@ -0,0 +1,101 @@ +{% extends "elections2021/base.html" %} +{% load wagtailcore_tags %} + +{% block content %} + +<div class="container container--default py-8 lg:py-24"> + <article> + <div class="pt-2 pb-1.5 md:pt-3.5 md:pb-2 mb-8"> + <h1 class="head-alt-md md:head-alt-lg head-alt-highlighted max-w-5xl mb-4">{{ page.title }}</h1> + </div> + + <div class="lg:flex mt-20 justify-start"> + <div class="lg:w-2/3 relative"> + {% if navigation %} + <div class="floating-nav-wrapper hidden lg:block" id="floatingNavBarWrapper"> + <div class="floating-nav-panel " id="floatingNavBar"> + <div class="opener py-6 pb-16 px-11 bg-acidgreen text-white font-alt"> + RYCHLÁ NAVIGACE + </div> + <div class="inner float-panel-inner elevation-2"> + <ul> + {% for slug, title in navigation %} + <li><a href="#{{ slug }}">{{ title }}</a></li> + {% endfor %} + </ul> + </div> + </div> + </div> + <script> + window.addEventListener("load", onLoadFunction); + var anchorsArray = []; + + function placeUponId(id, space) { + return document.getElementById(id).getBoundingClientRect().top + window.scrollY - space; + } + + function onLoadFunction(e) { + var anchorElemsArray; + onResizeFunction(); + for (const entry of anchorsArray) { + entry.menuitem.addEventListener("click", clickHandler); + } + + function clickHandler(e) { + e.preventDefault(); + var id = this.getAttribute("href").replace("#", ""); + //console.log(placeUponId(id, 20)); + scroll({ + top: placeUponId(id, 20), + behavior: "smooth" + }); + } + + window.addEventListener("resize", onResizeFunction); + } + + function onResizeFunction(e) { + var itemsProcessed = 0; + var anchorElemsArray = document.getElementsByClassName("float-panel-inner")[0].querySelectorAll("li a"); + anchorsArray = []; + anchorElemsArray.forEach(function(entry) { + var id = entry.getAttribute("href").replace("#", ""); + anchorsArray.push({ + id: id, + top: placeUponId(id, 200), + menuitem: entry + }); + itemsProcessed++; + if (itemsProcessed === anchorElemsArray.length) { + anchorsArray.reverse(); + } + }); + //console.log(anchorsArray); + } + window.onscroll = function() { + var top = window.pageYOffset || document.documentElement.scrollTop; + var activereached = false; + anchorsArray.forEach(function(entry) { + entry.menuitem.classList.remove("active"); + entry.menuitem.classList.remove("passed"); + if (top >= placeUponId(entry.id, 200)) { + if (activereached) entry.menuitem.classList.add("passed"); + else entry.menuitem.classList.add("active"); + activereached = true; + } + }); + }; + </script> + {% endif %} + + <div class="content-block w-full"> + {% for block in page.content %} + {% include_block block %} + {% endfor %} + </div> + </div> + </div> + </article> +</div> + +{% endblock %} diff --git a/elections2021/templates/elections2021/elections2021_text_page.html b/elections2021/templates/elections2021/elections2021_text_page.html new file mode 100644 index 0000000000000000000000000000000000000000..b513d2d59531242a262ab1cdf65a8db47f83f5df --- /dev/null +++ b/elections2021/templates/elections2021/elections2021_text_page.html @@ -0,0 +1,15 @@ +{% extends "elections2021/base.html" %} +{% load wagtailcore_tags %} + +{% block content %} + +<div class="container container--default pt-8 lg:py-24"> + <div class="pt-2 pb-1.5 md:pt-3.5 md:pb-2 mb-8"> + <h1 class="head-alt-md md:head-alt-lg head-alt-highlighted max-w-5xl mb-4">{{ page.title }}</h1> + </div> + <div class="content-block max-w-5xl"> + {{ page.body|richtext }} + </div> +</div> + +{% endblock %}