Skip to content
Snippets Groups Projects
Commit a23fd914 authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

base elections web models

parent c7c841bd
No related branches found
No related tags found
2 merge requests!876Fix shared articles & release elections web,!863Add elections web
Showing
with 813 additions and 187 deletions
File moved
from django.apps import AppConfig
class ElectionsConfig(AppConfig):
name = "elections"
# Generated by Django 4.1.10 on 2024-01-04 15:23
from django.db import migrations, models
import django.db.models.deletion
import shared.blocks.main
import shared.models.base
import wagtail.blocks
import wagtail.contrib.routable_page.models
import wagtail.fields
import wagtailmetadata.models
class Migration(migrations.Migration):
initial = True
dependencies = [
("wagtailcore", "0083_workflowcontenttype"),
("wagtailimages", "0025_alter_image_file_alter_rendition_file"),
("main", "0066_alter_mainarticlepage_content_and_more"),
]
operations = [
migrations.CreateModel(
name="ElectionsHomePage",
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",
),
),
(
"title_suffix",
models.CharField(
blank=True,
help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
max_length=100,
null=True,
verbose_name="Přípona titulku stránky",
),
),
(
"important_item_name",
models.CharField(
blank=True,
help_text="Pokud není odkazovaná stránka na Majáku, použij možnost zadání samotné adresy níže.",
max_length=16,
null=True,
verbose_name="Jméno",
),
),
(
"important_item_url",
models.URLField(blank=True, null=True, verbose_name="Adresa"),
),
(
"menu",
wagtail.fields.StreamField(
[
(
"menu_item",
wagtail.blocks.StructBlock(
[
(
"title",
wagtail.blocks.CharBlock(
help_text="Pokud není odkazovaná stránka na Majáku, použij možnost zadání samotné adresy níže.",
label="Titulek",
required=True,
),
),
(
"page",
wagtail.blocks.PageChooserBlock(
label="Stránka", required=False
),
),
(
"link",
wagtail.blocks.URLBlock(
label="Odkaz", required=False
),
),
]
),
)
],
blank=True,
use_json_field=True,
verbose_name="Položky",
),
),
(
"menu_button_name",
models.CharField(
max_length=16, verbose_name="Text na tlačítku pro zapojení"
),
),
(
"menu_button_content",
wagtail.fields.StreamField(
[
(
"navbar_menu_item",
wagtail.blocks.StructBlock(
[
(
"button_link",
wagtail.blocks.URLBlock(
label="Odkaz tlačítka"
),
),
(
"button_text",
wagtail.blocks.CharBlock(
label="Text tlačítka"
),
),
]
),
)
],
blank=True,
use_json_field=True,
verbose_name="Obsah menu pro zapojení se",
),
),
(
"footer_other_links",
wagtail.fields.StreamField(
[
(
"other_links",
wagtail.blocks.StructBlock(
[
(
"title",
wagtail.blocks.CharBlock(label="Titulek"),
),
(
"list",
wagtail.blocks.ListBlock(
shared.blocks.main.LinkBlock,
label="Seznam odkazů s titulkem",
),
),
]
),
)
],
blank=True,
use_json_field=True,
verbose_name="Odkazy v zápatí webu",
),
),
(
"footer_person_list",
wagtail.fields.StreamField(
[
(
"person",
wagtail.blocks.StructBlock(
[
(
"position",
wagtail.blocks.CharBlock(
label="Název pozice", required=False
),
),
(
"person",
wagtail.blocks.PageChooserBlock(
label="Osoba",
page_type=["main.MainPersonPage"],
),
),
]
),
)
],
blank=True,
use_json_field=True,
verbose_name="Osoby v zápatí webu",
),
),
(
"matomo_id",
models.IntegerField(
blank=True,
null=True,
verbose_name="Matomo ID pro sledování návštěvnosti",
),
),
(
"social_links",
wagtail.fields.StreamField(
[
(
"social_links",
wagtail.blocks.StructBlock(
[
(
"text",
wagtail.blocks.CharBlock(label="Název"),
),
(
"link",
wagtail.blocks.URLBlock(label="Odkaz"),
),
(
"icon",
wagtail.blocks.CharBlock(
help_text="Seznam ikon - https://styleguide.pirati.cz/latest/?p=viewall-atoms-icons <br/>Název ikony zadejte bez tečky na začátku",
label="Ikona",
),
),
]
),
)
],
blank=True,
use_json_field=True,
verbose_name="Odkazy na sociální sítě",
),
),
(
"content",
wagtail.fields.StreamField(
[], blank=True, use_json_field=True, verbose_name="Hlavní obsah"
),
),
(
"gdpr_and_cookies_page",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="main.mainsimplepage",
verbose_name="Stránka pro GDPR",
),
),
(
"important_item_page",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="+",
to="wagtailcore.page",
verbose_name="Stránka",
),
),
(
"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": "Web pro volby",
},
bases=(
wagtail.contrib.routable_page.models.RoutablePageMixin,
wagtailmetadata.models.WagtailImageMetadataMixin,
shared.models.base.ArticlesMixin,
"wagtailcore.page",
models.Model,
),
),
]
# Generated by Django 4.1.10 on 2024-01-04 15:24
from django.db import migrations, models
import django.db.models.deletion
import modelcluster.fields
import shared.models.base
import wagtail.contrib.routable_page.models
import wagtailmetadata.models
class Migration(migrations.Migration):
dependencies = [
("wagtailcore", "0083_workflowcontenttype"),
("shared", "0003_initial"),
("wagtailimages", "0025_alter_image_file_alter_rendition_file"),
("elections", "0001_initial"),
]
operations = [
migrations.CreateModel(
name="ElectionsArticlesPage",
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",
),
),
(
"last_import_log",
models.TextField(
blank=True,
null=True,
verbose_name="Výstup z posledního importu",
),
),
("perex", models.TextField()),
(
"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",
),
),
(
"shared_tags",
modelcluster.fields.ParentalManyToManyField(
blank=True,
help_text="Pro výběr jednoho tagu klikněte na tag a uložte nebo publikujte stránku. Pro výběr více tagů využijte podržte Ctrl a vyberte příslušné tagy.",
to="shared.sharedtag",
verbose_name="Výběr tagů pro články sdílené mezi sítěmi",
),
),
],
options={
"verbose_name": "Rozcestník článků",
"abstract": False,
},
bases=(
wagtail.contrib.routable_page.models.RoutablePageMixin,
shared.models.base.SubpageMixin,
wagtailmetadata.models.WagtailImageMetadataMixin,
shared.models.base.ArticlesMixin,
"wagtailcore.page",
models.Model,
),
),
]
# Generated by Django 4.1.10 on 2024-01-04 15:26
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import modelcluster.contrib.taggit
import modelcluster.fields
import shared.models.base
import wagtail.blocks
import wagtail.documents.blocks
import wagtail.fields
import wagtailmetadata.models
class Migration(migrations.Migration):
dependencies = [
("main", "0067_alter_mainarticletag_content_object"),
("wagtailimages", "0025_alter_image_file_alter_rendition_file"),
("taggit", "0005_auto_20220424_2025"),
("wagtailcore", "0083_workflowcontenttype"),
("shared", "0003_initial"),
("elections", "0002_electionsarticlespage"),
]
operations = [
migrations.CreateModel(
name="ElectionsArticlePage",
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",
),
),
(
"date",
models.DateField(
default=django.utils.timezone.now, verbose_name="datum"
),
),
("perex", models.TextField(verbose_name="perex")),
(
"author",
models.CharField(
blank=True, max_length=250, null=True, verbose_name="autor"
),
),
("shared_type", models.TextField(blank=True, null=True)),
(
"content",
wagtail.fields.StreamField(
[
(
"text",
wagtail.blocks.RichTextBlock(
template="styleguide2/includes/atoms/text/prose_richtext.html"
),
),
(
"quote",
wagtail.blocks.StructBlock(
[
(
"quote",
wagtail.blocks.CharBlock(label="Citace"),
),
(
"autor_name",
wagtail.blocks.CharBlock(
label="Jméno autora"
),
),
]
),
),
(
"download",
wagtail.blocks.StructBlock(
[
(
"file",
wagtail.documents.blocks.DocumentChooserBlock(
label="Stáhnutelný soubor"
),
)
]
),
),
],
blank=True,
use_json_field=True,
verbose_name="Článek",
),
),
(
"author_page",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="main.mainpersonpage",
verbose_name="Stránka autora (osoby)",
),
),
(
"image",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="wagtailimages.image",
verbose_name="obrázek",
),
),
(
"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",
),
),
(
"shared_from",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="+",
to="wagtailcore.page",
),
),
(
"shared_tags",
modelcluster.contrib.taggit.ClusterTaggableManager(
blank=True,
help_text="A comma-separated list of tags.",
through="shared.SharedTaggedMainArticle",
to="shared.SharedTag",
verbose_name="Tagy pro sdílení mezi weby",
),
),
],
options={
"verbose_name": "Aktualita",
"abstract": False,
},
bases=(
shared.models.base.SubpageMixin,
wagtailmetadata.models.WagtailImageMetadataMixin,
"wagtailcore.page",
models.Model,
),
),
migrations.CreateModel(
name="ElectionsSearchPage",
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": "Vyhledávací stránka",
"abstract": False,
},
bases=(
shared.models.base.SubpageMixin,
wagtailmetadata.models.WagtailImageMetadataMixin,
"wagtailcore.page",
models.Model,
),
),
migrations.CreateModel(
name="ElectionsArticleTag",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"content_object",
modelcluster.fields.ParentalKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="elections_tagged_items",
to="elections.electionsarticlepage",
),
),
(
"tag",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="%(app_label)s_%(class)s_items",
to="taggit.tag",
),
),
],
options={
"abstract": False,
},
),
migrations.AddField(
model_name="electionsarticlepage",
name="tags",
field=modelcluster.contrib.taggit.ClusterTaggableManager(
blank=True,
help_text="A comma-separated list of tags.",
through="elections.ElectionsArticleTag",
to="taggit.Tag",
verbose_name="Tags",
),
),
]
# Generated by Django 4.1.10 on 2024-01-04 15:46
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("elections", "0003_electionsarticlepage_electionssearchpage_and_more"),
]
operations = [
migrations.AlterModelOptions(
name="electionshomepage",
options={"verbose_name": "Volební web"},
),
]
# Generated by Django 4.1.10 on 2024-01-04 16:21
from django.db import migrations
import modelcluster.contrib.taggit
class Migration(migrations.Migration):
dependencies = [
("shared", "0004_sharedtaggedelectionsarticle"),
("elections", "0004_alter_electionshomepage_options"),
]
operations = [
migrations.AlterField(
model_name="electionsarticlepage",
name="shared_tags",
field=modelcluster.contrib.taggit.ClusterTaggableManager(
blank=True,
help_text="A comma-separated list of tags.",
through="shared.SharedTaggedElectionsArticle",
to="shared.SharedTag",
verbose_name="Tagy pro sdílení mezi weby",
),
),
]
from dateutil.relativedelta import relativedelta
from django.conf import settings
from django.contrib import messages
from django.core.paginator import Paginator
from django.db import models
from django.forms.models import model_to_dict
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from django.utils import timezone
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import Tag, TaggedItemBase
from wagtail.admin.panels import (
FieldPanel,
HelpPanel,
MultiFieldPanel,
ObjectList,
PageChooserPanel,
TabbedInterface,
)
from wagtail.blocks import PageChooserBlock, RichTextBlock
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.fields import RichTextField, StreamField
from wagtail.models import Page
from wagtail.search import index
from wagtailmetadata.models import MetadataPageMixin
from calendar_utils.models import CalendarMixin
from shared import blocks as shared_blocks
from shared.forms import SubscribeForm
from shared.models import ( # MenuMixin,
ArticleMixin,
ArticlesMixin,
ArticlesPageMixin,
ExtendedMetadataHomePageMixin,
ExtendedMetadataPageMixin,
MainArticlePageMixin,
MainArticlesPageMixin,
MainContactPageMixin,
MainHomePageMixin,
MainSearchPageMixin,
MainSimplePageMixin,
PageInMenuMixin,
SharedTaggedElectionsArticle,
SubpageMixin,
)
from shared.utils import make_promote_panels, subscribe_to_newsletter
from tuning import admin_help
from . import blocks
class ElectionsHomePage(MainHomePageMixin):
# content
content = StreamField(
[],
verbose_name="Hlavní obsah",
blank=True,
use_json_field=True,
)
# settings
gdpr_and_cookies_page = models.ForeignKey(
# Keep this a reference to the main website's GDPR page. Not ideal, but works (for now).
"main.MainSimplePage",
verbose_name="Stránka pro GDPR",
on_delete=models.PROTECT,
blank=True,
null=True,
)
subpage_types = [
"elections.ElectionsArticlesPage",
"elections.ElectionsSearchPage",
]
### OTHERS
class Meta:
verbose_name = "Volební web"
@property
def article_page_model(self):
return ElectionsArticlePage
@property
def articles_page_model(self):
return ElectionsArticlesPage
@property
def search_page_model(self):
return ElectionsSearchPage
@property
def people_page(self):
return self._first_subpage_of_type(ElectionsPeoplePage)
@property
def root_page(self):
return self
def _first_subpage_of_type(self, page_type) -> Page or None:
try:
return self.get_descendants().type(page_type).live().specific()[0]
except IndexError:
return None
@route(r"^sdilene/$", name="shared")
def shared(self, request):
return self.setup_article_page_context(request)
class ElectionsArticlesPage(MainArticlesPageMixin):
parent_page_types = ["elections.ElectionsHomePage"]
subpage_types = ["elections.ElectionsArticlePage"]
class ElectionsArticleTag(TaggedItemBase):
content_object = ParentalKey(
"elections.ElectionsArticlePage",
on_delete=models.CASCADE,
related_name="elections_tagged_items",
)
class ElectionsArticlePage(MainArticlePageMixin):
author_page = models.ForeignKey(
"main.MainPersonPage",
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name="Stránka autora (osoby)",
)
tags = ClusterTaggableManager(
through=ElectionsArticleTag,
related_name="elections_tagged_articles",
blank=True,
)
shared_tags = ClusterTaggableManager(
verbose_name="Tagy pro sdílení mezi weby",
through=SharedTaggedElectionsArticle,
blank=True,
)
parent_page_types = ["elections.ElectionsArticlesPage"]
subpage_types = []
class ElectionsSearchPage(MainSearchPageMixin):
parent_page_types = ["elections.ElectionsHomePage"]
subpage_types = []
@property
def searchable_models(self) -> list:
return [
ElectionsArticlePage,
ElectionsPersonPage,
ElectionsSimplePage,
]
{% extends "styleguide2/article_page.html" %}
{% extends "styleguide2/articles_page.html" %}
{% extends "styleguide2/contact_page.html" %}
{% extends "styleguide2/home_page.html" %}
{% extends "styleguide2/search_page.html" %}
{% extends "styleguide2/simple_page.html" %}
from django.apps import AppConfig
class DistrictConfig(AppConfig):
class MainConfig(AppConfig):
name = "main"
MONTH_NAMES = [
"Leden",
"Únor",
"Březen",
"Duben",
"Květen",
"Červen",
"Červenec",
"Srpen",
"Září",
"Říjen",
"Listopad",
"Prosinec",
]
from django import forms
from wagtail.admin.forms import WagtailAdminPageForm
from wagtail.models.collections import Collection
from shared.jekyll_import import JekyllArticleImporter
class JekyllImportForm(WagtailAdminPageForm):
do_import = forms.BooleanField(
initial=False, required=False, label="Provést import z Jekyllu"
)
collection = forms.ModelChoiceField(
queryset=Collection.objects.all(), required=False, label="Kolekce obrázků"
)
dry_run = forms.BooleanField(
initial=True,
required=False,
label="Jenom na zkoušku",
help_text="Žádné články se neuloží, vypíše případné problémy či "
"již existující články - 'ostrému' importu existující "
"články nevadí, přeskočí je",
)
jekyll_repo_url = forms.URLField(
max_length=512,
required=False,
help_text="např. https://github.com/pirati-web/pirati.cz",
)
readonly_log = forms.CharField(
disabled=True,
label="Log z posledního importu",
required=False,
widget=forms.Textarea,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["readonly_log"].initial = self.instance.last_import_log
def clean(self):
cleaned_data = super().clean()
if not cleaned_data.get("do_import"):
return cleaned_data
if cleaned_data.get("do_import") and not self.instance.id:
self.add_error(
"do_import", "Import proveďte prosím až po vytvoření stránky"
)
if not cleaned_data.get("collection"):
self.add_error("collection", "Pro import je toto pole povinné")
if not cleaned_data.get("jekyll_repo_url"):
self.add_error("jekyll_repo_url", "Pro import je toto pole povinné")
if cleaned_data.get("jekyll_repo_url", "").endswith(".zip"):
self.add_error(
"jekyll_repo_url", "Vložte odkaz pouze na repozitář, ne na zip"
)
return cleaned_data
def handle_import(self):
from .models import MainArticlePage
JekyllArticleImporter(
article_parent_page=self.instance,
collection_id=self.cleaned_data["collection"].id,
url=self.cleaned_data["jekyll_repo_url"],
dry_run=self.cleaned_data["dry_run"],
use_git=True,
page_model=MainArticlePage,
).perform_import()
def save(self, commit=True):
if self.cleaned_data.get("do_import"):
self.handle_import()
return super().save(commit=commit)
from django.db import models
from wagtail import blocks
from wagtail.admin.panels import FieldPanel, MultiFieldPanel
from wagtail.fields import StreamField
from wagtail.models import Page
from shared.blocks import MenuItemBlock as MenuItemBlockBase
from shared.models import MenuMixin as MenuMixinBase
class MenuItemBlock(MenuItemBlockBase):
title = blocks.CharBlock(
label="Titulek",
help_text="Pokud není odkazovaná stránka na Majáku, použij možnost zadání samotné adresy níže.",
required=True,
)
class Meta:
label = "Položka v menu"
#
#
# class MenuParentBlock(MenuParentBlockBase):
# class Meta:
# label = "Podmenu"
# template = "styleguide/2.3.x/menu_parent.html"
class MenuMixin(MenuMixinBase):
important_item_name = models.CharField(
verbose_name="Jméno",
help_text="Pokud není odkazovaná stránka na Majáku, použij možnost zadání samotné adresy níže.",
max_length=16,
blank=True,
null=True,
)
important_item_page = models.ForeignKey(
Page,
verbose_name="Stránka",
null=True,
blank=True,
related_name="+",
on_delete=models.PROTECT,
)
important_item_url = models.URLField(
verbose_name="Adresa",
blank=True,
null=True,
)
menu = StreamField(
[("menu_item", MenuItemBlock())], # , ("menu_parent", MenuParentBlock())
verbose_name="Položky",
blank=True,
use_json_field=True,
)
menu_panels = [
MultiFieldPanel(
[
FieldPanel("important_item_name"),
FieldPanel("important_item_page"),
FieldPanel("important_item_url"),
],
heading="Důležitá položka menu",
),
MultiFieldPanel(
[
FieldPanel("menu"),
],
heading="Další obsah menu",
),
]
class Meta:
abstract = True
class PageInMenuMixin(Page):
def get_menu_title(self) -> str:
for menu_item in self.root_page.menu:
if menu_item.value["page"] is None:
continue
if menu_item.value["page"].id == self.id:
return menu_item.value["title"]
return self.title
class Meta:
abstract = True
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment