diff --git a/district/migrations/0040_districthomepage_menu.py b/district/migrations/0040_districthomepage_menu.py new file mode 100644 index 0000000000000000000000000000000000000000..69a02b6e1308d561632a3c217308b937c935e099 --- /dev/null +++ b/district/migrations/0040_districthomepage_menu.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.11 on 2022-03-09 08:35 + +import wagtail.core.blocks +import wagtail.core.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("district", "0039_alter_districtcustompage_content"), + ] + + operations = [ + migrations.AddField( + model_name="districthomepage", + name="menu", + field=wagtail.core.fields.StreamField( + [ + ( + "menu_item", + wagtail.core.blocks.StructBlock( + [ + ( + "title", + wagtail.core.blocks.CharBlock( + label="Titulek", required=True + ), + ), + ( + "page", + wagtail.core.blocks.PageChooserBlock( + label="Stránka", required=False + ), + ), + ( + "link", + wagtail.core.blocks.URLBlock( + label="Odkaz", required=False + ), + ), + ] + ), + ), + ( + "menu_parent", + wagtail.core.blocks.StructBlock( + [ + ( + "title", + wagtail.core.blocks.CharBlock( + label="Titulek", required=True + ), + ), + ( + "menu_items", + wagtail.core.blocks.ListBlock( + wagtail.core.blocks.StructBlock( + [ + ( + "title", + wagtail.core.blocks.CharBlock( + label="Titulek", required=True + ), + ), + ( + "page", + wagtail.core.blocks.PageChooserBlock( + label="Stránka", required=False + ), + ), + ( + "link", + wagtail.core.blocks.URLBlock( + label="Odkaz", required=False + ), + ), + ] + ) + ), + ), + ] + ), + ), + ], + blank=True, + verbose_name="Menu", + ), + ), + ] diff --git a/district/models.py b/district/models.py index 2adb5672456723651f9cf3a39182efd2c4a4bd10..539bc68a47c17421494f5ebd76a29236f2f6eebc 100644 --- a/district/models.py +++ b/district/models.py @@ -11,8 +11,10 @@ from wagtail.admin.edit_handlers import ( CommentPanel, FieldPanel, MultiFieldPanel, + ObjectList, PageChooserPanel, StreamFieldPanel, + TabbedInterface, ) from wagtail.contrib.table_block.blocks import TableBlock from wagtail.core.blocks import RichTextBlock @@ -22,13 +24,13 @@ from wagtail.images.edit_handlers import ImageChooserPanel from wagtailmetadata.models import MetadataPageMixin from calendar_utils.models import CalendarMixin -from shared.models import ArticleMixin, SubpageMixin +from shared.models import ArticleMixin, MenuMixin, SubpageMixin from uniweb.constants import RICH_TEXT_FEATURES from . import blocks -class DistrictHomePage(MetadataPageMixin, CalendarMixin, Page): +class DistrictHomePage(MenuMixin, MetadataPageMixin, CalendarMixin, Page): ### FIELDS subheader = StreamField( @@ -161,6 +163,16 @@ class DistrictHomePage(MetadataPageMixin, CalendarMixin, Page): CommentPanel(), ] + ### EDIT HANDLERS + edit_handler = TabbedInterface( + [ + ObjectList(content_panels, heading="Obsah"), + ObjectList(promote_panels, heading="Propagovat"), + ObjectList(settings_panels, heading="Nastavení"), + ObjectList(MenuMixin.menu_panels, heading="Menu"), + ] + ) + ### RELATIONS subpage_types = [ diff --git a/district/templates/district/base.html b/district/templates/district/base.html index 65e5ae0040b4a87d01de29e75de20a77455ad3c4..9e827574dccf7a9344ca18e28e03873703ecfea8 100644 --- a/district/templates/district/base.html +++ b/district/templates/district/base.html @@ -79,64 +79,9 @@ <div v-if="show || isLgScreenSize" class="navbar__main navbar__section navbar__section--expandable container-padding--zero lg:container-padding--auto"> <ul class="navbar-menu text-white"> - {% if page.root_page.articles_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.articles_page %}" class="navbar-menu__link"> - Aktuality - </a> - </li> - {% endif %} - {% if page.root_page.people_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.people_page %}" class="navbar-menu__link"> - Lidé - </a> - </li> - {% endif %} - {% if page.root_page.election_page and page.root_page.program_page %} - <li class="navbar-menu__item"> - <ui-navbar-subitem label="Volby"> - <ul class="navbar-menu__submenu"> - <li> - <a href="{{ page.root_page.election_page.url }}" class="navbar-menu__link"> - {{ page.root_page.election_page }} - </a> - </li> - <li> - <a href="{{ page.root_page.program_page.url }}" class="navbar-menu__link"> - {{ page.root_page.program_page }} - </a> - </li> - </ul> - </ui-navbar-subitem> - </li> - {% elif page.root_page.program_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.program_page %}" class="navbar-menu__link"> - Program - </a> - </li> - {% elif page.root_page.election_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.election_page %}" class="navbar-menu__link"> - Volby - </a> - </li> - {% endif %} - {% if page.root_page.center_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.center_page %}" class="navbar-menu__link"> - Pirátské centrum - </a> - </li> - {% endif %} - {% if page.root_page.contact_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.contact_page %}" class="navbar-menu__link"> - Kontakt - </a> - </li> - {% endif %} + {% for block in page.root_page.menu %} + {% include_block block %} + {% endfor %} </ul> </div> diff --git a/district/wagtail_hooks.py b/district/wagtail_hooks.py index 07ae0e6bb082420737315f50b17f2ba9533a51b8..ea3324d401ca66f0a0c822b8b60ade28a8417ab8 100644 --- a/district/wagtail_hooks.py +++ b/district/wagtail_hooks.py @@ -1,46 +1,46 @@ -import re - -from wagtail.core import hooks - -# FIXME hooks are loaded globally so it doesn't make sense to have it in this module - - -@hooks.register("construct_page_chooser_queryset") -def this_web_only(pages, request): - add_result = re.search( - "page/(.*)/", request.META.get("HTTP_REFERER") - ) # FIXME better regex - edit_result = re.search("pages/(.*)/edit", request.META.get("HTTP_REFERER")) - - if add_result: - return handle_add_page_selection(pages=pages, add_result=add_result) - - if edit_result: - return handle_edit_page_selection(pages=pages, edit_result=edit_result) - - return pages - - -def handle_add_page_selection(pages, add_result): - parent_page_id = add_result.group(1) - if parent_page_id == 1: # pro novou homepage žádné podstránky nejsou - return pages.none() - - parent_page = pages.model.objects.get(id=parent_page_id) - root_page = getattr(parent_page.specific, "root_page", None) - return get_only_root_page_descendants(pages=pages, root_page=root_page) - - -def handle_edit_page_selection(pages, edit_result): - current_page_id = edit_result.group(1) - current_page = pages.model.objects.get(id=current_page_id) - root_page = getattr(current_page.specific, "root_page", None) - return get_only_root_page_descendants(pages=pages, root_page=root_page) - - -def get_only_root_page_descendants(pages, root_page): - if not root_page: - return pages - - web_pages_id_list = root_page.get_descendants().live().values_list("id", flat=True) - return pages.filter(id__in=web_pages_id_list) +# import re +# +# from wagtail.core import hooks +# +# # FIXME hooks are loaded globally so it doesn't make sense to have it in this module +# +# +# @hooks.register("construct_page_chooser_queryset") +# def this_web_only(pages, request): +# add_result = re.search( +# "page/(.*)/", request.META.get("HTTP_REFERER") +# ) # FIXME better regex +# edit_result = re.search("pages/(.*)/edit", request.META.get("HTTP_REFERER")) +# +# if add_result: +# return handle_add_page_selection(pages=pages, add_result=add_result) +# +# if edit_result: +# return handle_edit_page_selection(pages=pages, edit_result=edit_result) +# +# return pages +# +# +# def handle_add_page_selection(pages, add_result): +# parent_page_id = add_result.group(1) +# if parent_page_id == 1: # pro novou homepage žádné podstránky nejsou +# return pages.none() +# +# parent_page = pages.model.objects.get(id=parent_page_id) +# root_page = getattr(parent_page.specific, "root_page", None) +# return get_only_root_page_descendants(pages=pages, root_page=root_page) +# +# +# def handle_edit_page_selection(pages, edit_result): +# current_page_id = edit_result.group(1) +# current_page = pages.model.objects.get(id=current_page_id) +# root_page = getattr(current_page.specific, "root_page", None) +# return get_only_root_page_descendants(pages=pages, root_page=root_page) +# +# +# def get_only_root_page_descendants(pages, root_page): +# if not root_page: +# return pages +# +# web_pages_id_list = root_page.get_descendants().live().values_list("id", flat=True) +# return pages.filter(id__in=web_pages_id_list) diff --git a/region/migrations/0015_regionhomepage_menu.py b/region/migrations/0015_regionhomepage_menu.py new file mode 100644 index 0000000000000000000000000000000000000000..85a6406d856266eb5ac6cc03630a540ad23b2c81 --- /dev/null +++ b/region/migrations/0015_regionhomepage_menu.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.11 on 2022-03-09 08:24 + +import wagtail.core.blocks +import wagtail.core.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("region", "0014_regioncrossroadpage_regioncustompage"), + ] + + operations = [ + migrations.AddField( + model_name="regionhomepage", + name="menu", + field=wagtail.core.fields.StreamField( + [ + ( + "menu_item", + wagtail.core.blocks.StructBlock( + [ + ( + "title", + wagtail.core.blocks.CharBlock( + label="Titulek", required=True + ), + ), + ( + "page", + wagtail.core.blocks.PageChooserBlock( + label="Stránka", required=False + ), + ), + ( + "link", + wagtail.core.blocks.URLBlock( + label="Odkaz", required=False + ), + ), + ] + ), + ), + ( + "menu_parent", + wagtail.core.blocks.StructBlock( + [ + ( + "title", + wagtail.core.blocks.CharBlock( + label="Titulek", required=True + ), + ), + ( + "menu_items", + wagtail.core.blocks.ListBlock( + wagtail.core.blocks.StructBlock( + [ + ( + "title", + wagtail.core.blocks.CharBlock( + label="Titulek", required=True + ), + ), + ( + "page", + wagtail.core.blocks.PageChooserBlock( + label="Stránka", required=False + ), + ), + ( + "link", + wagtail.core.blocks.URLBlock( + label="Odkaz", required=False + ), + ), + ] + ) + ), + ), + ] + ), + ), + ], + blank=True, + verbose_name="Menu", + ), + ), + ] diff --git a/region/models.py b/region/models.py index decef6fb873c368c083bd7d8bf1e4cc33e4ee23e..b3d86dccb892f0368d109c8ba4e196c803ab0179 100644 --- a/region/models.py +++ b/region/models.py @@ -11,8 +11,10 @@ from wagtail.admin.edit_handlers import ( CommentPanel, FieldPanel, MultiFieldPanel, + ObjectList, PageChooserPanel, StreamFieldPanel, + TabbedInterface, ) from wagtail.contrib.table_block.blocks import TableBlock from wagtail.core.blocks import RichTextBlock @@ -22,13 +24,13 @@ from wagtail.images.edit_handlers import ImageChooserPanel from wagtailmetadata.models import MetadataPageMixin from calendar_utils.models import CalendarMixin -from shared.models import ArticleMixin, SubpageMixin +from shared.models import ArticleMixin, MenuMixin, SubpageMixin from uniweb.constants import RICH_TEXT_FEATURES from . import blocks -class RegionHomePage(MetadataPageMixin, CalendarMixin, Page): +class RegionHomePage(MenuMixin, MetadataPageMixin, CalendarMixin, Page): ### FIELDS subheader = StreamField( @@ -161,6 +163,16 @@ class RegionHomePage(MetadataPageMixin, CalendarMixin, Page): CommentPanel(), ] + ### EDIT HANDLERS + edit_handler = TabbedInterface( + [ + ObjectList(content_panels, heading="Obsah"), + ObjectList(promote_panels, heading="Propagovat"), + ObjectList(settings_panels, heading="Nastavení"), + ObjectList(MenuMixin.menu_panels, heading="Menu"), + ] + ) + ### RELATIONS subpage_types = [ diff --git a/region/templates/region/base.html b/region/templates/region/base.html index 65e5ae0040b4a87d01de29e75de20a77455ad3c4..9e827574dccf7a9344ca18e28e03873703ecfea8 100644 --- a/region/templates/region/base.html +++ b/region/templates/region/base.html @@ -79,64 +79,9 @@ <div v-if="show || isLgScreenSize" class="navbar__main navbar__section navbar__section--expandable container-padding--zero lg:container-padding--auto"> <ul class="navbar-menu text-white"> - {% if page.root_page.articles_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.articles_page %}" class="navbar-menu__link"> - Aktuality - </a> - </li> - {% endif %} - {% if page.root_page.people_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.people_page %}" class="navbar-menu__link"> - Lidé - </a> - </li> - {% endif %} - {% if page.root_page.election_page and page.root_page.program_page %} - <li class="navbar-menu__item"> - <ui-navbar-subitem label="Volby"> - <ul class="navbar-menu__submenu"> - <li> - <a href="{{ page.root_page.election_page.url }}" class="navbar-menu__link"> - {{ page.root_page.election_page }} - </a> - </li> - <li> - <a href="{{ page.root_page.program_page.url }}" class="navbar-menu__link"> - {{ page.root_page.program_page }} - </a> - </li> - </ul> - </ui-navbar-subitem> - </li> - {% elif page.root_page.program_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.program_page %}" class="navbar-menu__link"> - Program - </a> - </li> - {% elif page.root_page.election_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.election_page %}" class="navbar-menu__link"> - Volby - </a> - </li> - {% endif %} - {% if page.root_page.center_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.center_page %}" class="navbar-menu__link"> - Pirátské centrum - </a> - </li> - {% endif %} - {% if page.root_page.contact_page %} - <li class="navbar-menu__item"> - <a href="{% pageurl page.root_page.contact_page %}" class="navbar-menu__link"> - Kontakt - </a> - </li> - {% endif %} + {% for block in page.root_page.menu %} + {% include_block block %} + {% endfor %} </ul> </div> diff --git a/shared/blocks.py b/shared/blocks.py new file mode 100644 index 0000000000000000000000000000000000000000..b0d28484ffa65460d0761e21033b258f0c0d814d --- /dev/null +++ b/shared/blocks.py @@ -0,0 +1,38 @@ +from django.forms.utils import ErrorList +from wagtail.core import blocks +from wagtail.core.blocks.struct_block import StructBlockValidationError + + +class MenuItemBlock(blocks.StructBlock): + title = blocks.CharBlock(label="Titulek", required=True) + page = blocks.PageChooserBlock(label="Stránka", required=False) + link = blocks.URLBlock(label="Odkaz", required=False) + + class Meta: + label = "Položka v menu" + template = "styleguide/2.3.x/menu_item.html" + + def clean(self, value): + errors = {} + + if value["page"] and value["link"]: + errors["page"] = ErrorList( + ["Stránka nemůže být vybrána současně s odkazem."] + ) + errors["link"] = ErrorList( + ["Odkaz nemůže být vybrán současně se stránkou."] + ) + if errors: + raise StructBlockValidationError(errors) + return super().clean(value) + + +class MenuParentBlock(blocks.StructBlock): + title = blocks.CharBlock(label="Titulek", required=True) + menu_items = blocks.ListBlock( + MenuItemBlock(), + ) + + class Meta: + label = "Podmenu" + template = "styleguide/2.3.x/menu_parent.html" diff --git a/shared/models.py b/shared/models.py index 7fec651d1969c2955066403ac7f82eb5011a976f..e399811a875c7bdcc94c0e602a70c0230f8baa5a 100644 --- a/shared/models.py +++ b/shared/models.py @@ -1,13 +1,12 @@ -import requests -from django.core.cache import cache -from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.utils import timezone -from wagtail.admin.edit_handlers import FieldPanel -from wagtail.core.fields import RichTextField +from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel, StreamFieldPanel +from wagtail.core.fields import RichTextField, StreamField from wagtail.core.models import Page from wagtail.images.edit_handlers import ImageChooserPanel +from shared.blocks import MenuItemBlock, MenuParentBlock + class SubpageMixin: """Must be used in class definition before MetadataPageMixin!""" @@ -82,3 +81,23 @@ class ArticleMixin(models.Model): def tag_filter_page(self): """Page used for filtering by tags in url like `?tag=foo`.""" return self.get_parent() + + +class MenuMixin(Page): + menu = StreamField( + [("menu_item", MenuItemBlock()), ("menu_parent", MenuParentBlock())], + verbose_name="Menu", + blank=True, + ) + + menu_panels = [ + MultiFieldPanel( + [ + StreamFieldPanel("menu"), + ], + heading="Menu Options", + ), + ] + + class Meta: + abstract = True diff --git a/shared/templates/styleguide/2.3.x/menu_item.html b/shared/templates/styleguide/2.3.x/menu_item.html new file mode 100644 index 0000000000000000000000000000000000000000..9c0b7fda56a961a62fc39197c37a158ee90bf239 --- /dev/null +++ b/shared/templates/styleguide/2.3.x/menu_item.html @@ -0,0 +1,6 @@ +<li class="navbar-menu__item"> + {% firstof self.page.url self.link as target %} + <a href="{{ target }}" class="navbar-menu__link"> + {{ self.title }} + </a> +</li> diff --git a/shared/templates/styleguide/2.3.x/menu_parent.html b/shared/templates/styleguide/2.3.x/menu_parent.html new file mode 100644 index 0000000000000000000000000000000000000000..26d600ff2cb28cf9ad121d6329bc13e29de815f9 --- /dev/null +++ b/shared/templates/styleguide/2.3.x/menu_parent.html @@ -0,0 +1,14 @@ +<li class="navbar-menu__item"> + <ui-navbar-subitem label="{{ self.title }}"> + <ul class="navbar-menu__submenu"> + {% for nested_item in self.menu_items %} + <li> + {% firstof nested_item.page.url nested_item.link as target %} + <a href="{{ target }}" class="navbar-menu__link"> + {{ nested_item.title }} + </a> + </li> + {% endfor %} + </ul> + </ui-navbar-subitem> +</li>