Skip to content
Snippets Groups Projects
Commit e3520e8c authored by Tomi Valentová's avatar Tomi Valentová
Browse files

wip - octopus people import

parent 6d4791cf
No related branches found
No related tags found
2 merge requests!1097Release,!1095Add basic Octopus people sync
Pipeline #19298 passed
Showing
with 220 additions and 92 deletions
......@@ -12,8 +12,8 @@ from wagtail.blocks import (
TextBlock,
URLBlock,
)
from django.template.defaultfilters import slugify
from wagtail.images.blocks import ImageChooserBlock
from shared.blocks import CandidateBlock as SharedCandidateBlockMixin
from shared.blocks import CandidateListBlock as SharedCandidateListBlockMixin
from shared.blocks import (
......@@ -127,6 +127,39 @@ class PersonCustomPositionBlock(PersonCustomPositionBlockMixin):
)
class OctopusGroupBlock(blocks.StructBlock):
title = CharBlock(label="Titulek", required=True)
slug = blocks.CharBlock(
label="Slug skupiny",
required=False,
help_text="Není třeba vyplňovat, bude automaticky vyplněno",
)
group_shortcut = CharBlock(label="Zkratka skupiny", required=True)
def get_prep_value(self, value):
value = super().get_prep_value(value)
value["slug"] = slugify(value["title"])
return value
def get_context(self, value, *args, **kwargs):
from .models import DistrictOctopusPersonPage
context = super().get_context(value, *args, **kwargs)
context["person_list"] = DistrictOctopusPersonPage.objects.filter(
originating_group=value["group_shortcut"]
).order_by("title").all()
return context
class Meta:
label = "Skupina osob z Chobotnice"
icon = "group"
template = "styleguide2/includes/organisms/cards/people_card_list.html"
class PeopleGroupBlock(PeopleGroupBlockMixin):
person_list = blocks.ListBlock(
blocks.PageChooserBlock(
......
import os
import tempfile
from shared.forms import JekyllImportForm as SharedJekyllImportForm
from shared.forms import OctopusPeopleImportForm as SharedOctopusPeopleImportForm
from .tasks import import_jekyll_articles
from .tasks import import_people_from_group
......@@ -9,7 +9,10 @@ from .tasks import import_people_from_group
class JekyllImportForm(SharedJekyllImportForm):
def handle_import(self):
lock_file_name = f"/tmp/.{self.instance.id}.articles-import-lock"
lock_file_name = os.path.join(
tempfile.gettempdir(),
f".{self.instance.id}.articles-import-lock"
)
if os.path.isfile(lock_file_name):
return
......@@ -23,20 +26,3 @@ class JekyllImportForm(SharedJekyllImportForm):
dry_run=self.cleaned_data["dry_run"],
use_git=True,
)
\ No newline at end of file
class OctopusImportForm(SharedOctopusPeopleImportForm):
def handle_import_from_group(self):
lock_file_name = f"/tmp/.{self.instance.id}.people-from-group-import-lock"
if os.path.isfile(lock_file_name):
return
open(lock_file_name, "w").close()
import_people_from_group.delay(
people_parent_page_id=self.instance.id,
collection_id=self.cleaned_data["collection"].id,
group_shortcut=self.cleaned_data["group_shortcut"],
lock_file_name=lock_file_name
)
\ No newline at end of file
......@@ -4,9 +4,7 @@ from ...jekyll_import import JekyllArticleImporter
class Command(BaseCommand):
help = """Importuje články z pirátského jekyll webu.
"""
help = """Importuje články z pirátského jekyll webu."""
def add_arguments(self, parser):
parser.add_argument("path", help="Cesta k jekyll repu")
......
from django.core.management.base import BaseCommand
from district.models import DistrictPeoplePage
from district.tasks import import_people_from_group
from wagtail.models.media import Collection
class Command(BaseCommand):
help = """Importuje Osoby z Chobotnice."""
def handle(self, *args, **options):
for people_page in DistrictPeoplePage.objects.all():
for shortcut in people_page.get_syncable_octopus_groups():
collection_id = people_page.root_page.image_collection_id
if collection_id is None:
collection_id = Collection.objects.first().id
import_people_from_group.delay(
people_page.id,
collection_id,
shortcut,
)
\ No newline at end of file
# Generated by Django 5.0.7 on 2024-07-31 09:54
import wagtail.blocks
import wagtail.fields
import wagtail.images.blocks
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('district', '0263_districtoctopuspersonpage_is_automatically_created_and_more'),
]
operations = [
migrations.AlterField(
model_name='districtpeoplepage',
name='content',
field=wagtail.fields.StreamField([('octopus_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug skupiny', required=False)), ('group_shortcut', wagtail.blocks.CharBlock(label='Zkratka skupiny', required=True))], label='Skupina z Chobotnice')), ('people_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek')), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug skupiny', required=False)), ('person_list', wagtail.blocks.ListBlock(wagtail.blocks.PageChooserBlock(label='Detail osoby', page_type=['district.DistrictPersonPage', 'district.DistrictOctopusPersonPage']), default=[], help_text='S pozicemi z jejich podstránek', label='Osoby')), ('person_list_with_custom_positions', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('page', wagtail.blocks.PageChooserBlock(label='Detail osoby', page_type=['district.DistrictOctopusPersonPage', 'district.DistrictPersonPage'])), ('position', wagtail.blocks.CharBlock(help_text='Pokud není pozice vyplněná, použije se pozice ze stránky osoby.', label='Pozice', required=False))]), default=[], help_text='S nastavitelnými pozicemi', label='Osoby'))], group='', label='Seznam osob')), ('team_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Název sekce týmů')), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug sekce', required=False)), ('team_list', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('headline', wagtail.blocks.CharBlock(label='Titulek bloku', required=False)), ('card_items', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Obrázek')), ('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('text', wagtail.blocks.RichTextBlock(label='Krátký text pod nadpisem', required=False)), ('page', wagtail.blocks.PageChooserBlock(label='Stránka', page_type=['district.DistrictArticlesPage', 'district.DistrictCenterPage', 'district.DistrictContactPage', 'district.DistrictCrossroadPage', 'district.DistrictCustomPage', 'district.DistrictPeoplePage', 'district.DistrictGeoFeatureCollectionPage', 'district.DistrictCalendarPage', 'district.DistrictPdfPage', 'district.DistrictNewProgramPage'], required=False)), ('link', wagtail.blocks.URLBlock(label='Odkaz', required=False))], template='styleguide2/includes/molecules/boxes/card_box_block.html'), label='Karty s odkazy'))], label='Karta týmu'), label='Týmy'))]))], blank=True, verbose_name='Lidé a týmy'),
),
]
# Generated by Django 5.0.7 on 2024-07-31 10:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('district', '0264_alter_districtpeoplepage_content'),
]
operations = [
migrations.AlterField(
model_name='districtoctopuspersonpage',
name='is_automatically_created',
field=models.BooleanField(verbose_name='Profil vytvořen automaticky'),
),
migrations.AlterField(
model_name='districtoctopuspersonpage',
name='originating_group',
field=models.CharField(help_text='Skupina, ze které byla tato osba importována.', max_length=128, verbose_name='Skupina'),
),
]
# Generated by Django 5.0.7 on 2024-07-31 10:43
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('district', '0265_alter_districtoctopuspersonpage_is_automatically_created_and_more'),
('wagtailcore', '0093_uploadedfile'),
]
operations = [
migrations.AddField(
model_name='districthomepage',
name='image_collection',
field=models.ForeignKey(blank=True, help_text="Do této kolekce se budou importovat např. fotky osob importovaných z Chobotnice. Pokud je tato hodnota nevyplněna, použije se běžná 'Root' kolekce.", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.collection', verbose_name='Default kolekce obrázků'),
),
]
import json
from functools import cached_property
from wagtail.models.media import Collection
from django.conf import settings
from django.contrib import messages
from django.core.cache import cache
......@@ -70,7 +71,7 @@ from shared.utils import (
)
from . import blocks
from .forms import JekyllImportForm, OctopusImportForm
from .forms import JekyllImportForm
CONTENT_BLOCKS = DEFAULT_CONTENT_BLOCKS + [
("chart", ChartBlock()),
......@@ -130,6 +131,19 @@ class DistrictHomePage(CalendarMixin, MainHomePageMixin):
max_length=250,
default="Fake news tam nenajdeš, ale dozvíš se, co chystáme doopravdy!",
)
image_collection = models.ForeignKey(
Collection,
verbose_name="Default kolekce obrázků",
help_text=(
"Do této kolekce se budou importovat např. fotky osob "
"importovaných z Chobotnice. Pokud je tato hodnota "
"nevyplněna, použije se běžná 'Root' kolekce."
),
on_delete=models.SET_NULL,
related_name="+",
blank=True,
null=True
)
calendar_button_text = models.CharField(
"Text tlačítka kalendáře", max_length=256, default="Kalendář"
......@@ -180,6 +194,7 @@ class DistrictHomePage(CalendarMixin, MainHomePageMixin):
"Formulář pro odběr newsletteru",
),
FieldPanel("matomo_id"),
FieldPanel("image_collection"),
FieldPanel("custom_css"),
FieldPanel("fallback_image"),
]
......@@ -323,25 +338,20 @@ class DistrictOctopusPersonPage(ExtendedMetadataPageMixin, SubpageMixin, Metadat
is_automatically_created = models.BooleanField(
verbose_name="Profil vytvořen automaticky",
help_text=(
"Pokud vytváříš stránku pro osobu z Chobotnice manuálně, "
"toto pole by nemělo být zaškrtlé. V ostatních případech "
"ho zaškrtlé nech."
)
)
# Shouldn't be visible in the admin interface
originating_group = models.CharField(
verbose_name="Skupina",
help_text="Skupina, ze které byla tato osba importována",
max_length=128
help_text="Skupina, ze které byla tato osba importována.",
max_length=128,
)
### PANELS
content_panels = Page.content_panels + [
FieldPanel("person"),
FieldPanel("is_automatically_created")
FieldPanel("is_automatically_created", read_only=True),
FieldPanel("originating_group", read_only=True)
]
### RELATIONS
......@@ -565,11 +575,12 @@ class DistrictPersonPage(MainPersonPageMixin):
class DistrictPeoplePage(MainPeoplePageMixin):
base_form_class = OctopusImportForm
### FIELDS
content = StreamField(
[
("people_group", blocks.PeopleGroupBlock(label="Seznam osob")),
("octopus_group", blocks.OctopusGroupBlock(label="Skupina z Chobotnice")),
("people_group", blocks.PeopleGroupBlock(label="Seznam osob", group="")),
("team_group", blocks.TeamBlock()),
],
verbose_name="Lidé a týmy",
......@@ -577,31 +588,34 @@ class DistrictPeoplePage(MainPeoplePageMixin):
use_json_field=True,
)
### RELATIONS
parent_page_types = ["district.DistrictHomePage"]
subpage_types = [
"district.DistrictPersonPage",
"district.DistrictOctopusPersonPage"
]
import_panels = [
MultiFieldPanel(
[
FieldPanel("do_import"),
FieldPanel("collection"),
FieldPanel("group_shortcut")
],
"import osob z Chobotnice",
),
]
### PANELS
edit_handler = TabbedInterface(
[
ObjectList(MainPeoplePageMixin.content_panels, heading="Obsah"),
ObjectList(MainPeoplePageMixin.promote_panels, heading="Metadata"),
ObjectList(import_panels, heading="Import"),
]
)
### OTHERS
def get_syncable_octopus_groups(self):
group_shortcuts = []
for block in self.content:
if block.block_type == "octopus_group":
group_shortcuts.append(block.value["group_shortcut"])
return group_shortcuts
class DistrictCalendarPage(SubpageMixin, MetadataPageMixin, CalendarMixin, Page):
### PANELS
......
import logging
import tempfile
import os
from celery import shared_task
......@@ -34,10 +36,19 @@ def import_people_from_group(
people_parent_page_id,
collection_id,
group_shortcut,
lock_file_name
):
from .models import DistrictPeoplePage, DistrictOctopusPersonPage
lock_file_name = os.path.join(
tempfile.gettempdir(),
f"{people_parent_page_id}-{group_shortcut}.people-from-group-import-lock"
)
if os.path.isfile(lock_file_name):
return
open(lock_file_name, "w").close()
return PeopleGroupImporter(
people_parent_page_id=people_parent_page_id,
people_parent_page_model=DistrictPeoplePage,
......
from django import template
register = template.Library()
@register.filter
def get_block_octopus_person_list(block):
from district.models import DistrictOctopusPersonPage
return DistrictOctopusPersonPage.objects.filter(
originating_group=block.value["group_shortcut"]
).order_by("title").all()
\ No newline at end of file
import os
import tempfile
from shared.forms import JekyllImportForm as SharedJekyllImportForm
......@@ -7,7 +8,10 @@ from .tasks import import_jekyll_articles
class JekyllImportForm(SharedJekyllImportForm):
def handle_import(self):
lock_file_name = f"/tmp/.{self.instance.id}.import-lock"
lock_file_name = os.path.join(
tempfile.gettempdir(),
f".{self.instance.id}.articles-import-lock"
)
if os.path.isfile(lock_file_name):
return
......
import os
import tempfile
from shared.forms import JekyllImportForm as SharedJekyllImportForm
......@@ -7,7 +8,10 @@ from .tasks import import_jekyll_articles
class JekyllImportForm(SharedJekyllImportForm):
def handle_import(self):
lock_file_name = f"/tmp/.{self.instance.id}.import-lock"
lock_file_name = os.path.join(
tempfile.gettempdir(),
f".{self.instance.id}.articles-import-lock"
)
if os.path.isfile(lock_file_name):
return
......
......@@ -9,44 +9,6 @@ class SubscribeForm(forms.Form):
return_page_id = forms.IntegerField()
class OctopusPeopleImportForm(WagtailAdminPageForm):
do_import = forms.BooleanField(
initial=False, required=False, label="Provést import osob z Chobotnice"
)
collection = forms.ModelChoiceField(
queryset=Collection.objects.all(), required=False, label="Kolekce obrázků"
)
group_shortcut = forms.CharField(
label="Zkratka skupiny osob",
required=False,
)
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("group_shortcut"):
self.add_error("group_shortcut", "Pro import je toto pole povinné")
return cleaned_data
def save(self, commit=True):
if self.cleaned_data.get("do_import"):
self.handle_import_from_group()
return super().save(commit=commit)
class JekyllImportForm(WagtailAdminPageForm):
do_import = forms.BooleanField(
initial=False, required=False, label="Provést import z Jekyllu"
......
......@@ -25,7 +25,7 @@
{% block switch %}
{% for content_item in content %}
{% if content_item.block_type == "people_group" or content_item.block_type == "team_group" %}
{% if content_item.block_type == "octopus_group" or content_item.block_type == "people_group" or content_item.block_type == "team_group" %}
<a @click="toggleView('{{ content_item.value.slug }}-{{ forloop.counter }}')" class="switch__item"
:class="{'switch__item--active': isCurrentView('{{ content_item.value.slug }}-{{ forloop.counter }}')}"
>
......
{% extends "styleguide2/base.html" %}
{% load wagtailcore_tags wagtailimages_tags shared_filters people_filters %}
{% load wagtailcore_tags wagtailimages_tags shared_filters people_filters district_people_filters %}
{% block content %}
......@@ -11,7 +11,7 @@
<ui-view-provider
:initial="{
{% for content_item in page.content %}
{% if content_item.block_type == "people_group" or content_item.block_type == "team_group" %}
{% if content_item.block_type == "octopus_group" or content_item.block_type == "people_group" or content_item.block_type == "team_group" %}
'{{ content_item.value.slug }}-{{ forloop.counter }}': {% if page.content|is_first_people_type:forloop %}false{% else %}true{% endif %},
{% endif %}
{% endfor %}
......@@ -29,6 +29,24 @@
xl:justify-start
"
>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 w-full">
{% for block in page.content %}
{% if block.block_type == "octopus_group" %}
<template v-if="isCurrentView('{{ block.value.slug }}-{{ forloop.counter }}')">
{% with block|get_block_octopus_person_list as person_list %}
{% if person_list|length %}
{% for person_page in person_list %}
{% image person_page.specific.get_profile_image fill-480x480 as profile_image %}
{% include 'styleguide2/includes/molecules/contact/contact_person_large_box.html' with image=profile_image name=person_page.title function=person_page.position telephone=person_page.phone mail=person_page.email url=person_page.url %}
{% endfor %}
{% endif %}
{% endwith %}
</template>
{% endif %}
{% endfor %}
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 w-full">
{% for block in page.content %}
{% if block.block_type == "people_group" %}
......@@ -81,7 +99,7 @@
</div>
{% for block in page.content %}
{% if block.block_type != "people_group" and block.block_type != "team_group" %}
{% if block.block_type != "octopus_group" and block.block_type != "people_group" and block.block_type != "team_group" %}
{% include_block block %}
{% endif %}
{% endfor %}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment