From 013f0da15f48ad047df66e4e698738421461b7b2 Mon Sep 17 00:00:00 2001
From: OndraRehounek <ondra.rehounek@seznam.cz>
Date: Wed, 24 Aug 2022 16:11:27 +0200
Subject: [PATCH] main: prepare articles page for import

---
 main/forms.py                                 | 79 +++++++++++++++++++
 .../0015_mainarticlespage_last_import_log.py  | 20 +++++
 main/models.py                                | 50 +++++++++++-
 main/tasks.py                                 | 27 +++++++
 4 files changed, 173 insertions(+), 3 deletions(-)
 create mode 100644 main/forms.py
 create mode 100644 main/migrations/0015_mainarticlespage_last_import_log.py
 create mode 100644 main/tasks.py

diff --git a/main/forms.py b/main/forms.py
new file mode 100644
index 00000000..b5386a49
--- /dev/null
+++ b/main/forms.py
@@ -0,0 +1,79 @@
+from django import forms
+from wagtail.admin.forms import WagtailAdminPageForm
+from wagtail.core.models.collections import Collection
+
+from .tasks import import_jekyll_articles
+
+
+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="V GitHubu tlačítko Code -> a odkaz z Download zip"
+        "např. 'https://github.com/pirati-web/cb.pirati.cz/archive/refs/heads/gh-pages.zip',"
+        "pokud máte nainstalovaný Git, zvolte Použít Git a vložte"
+        "jednoduše URL repozitáře "
+        "např. 'https://github.com/pirati-web/cb.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):
+        import_jekyll_articles.delay(
+            article_parent_page_id=self.instance.id,
+            collection_id=self.cleaned_data["collection"].id,
+            url=self.cleaned_data["jekyll_repo_url"],
+            dry_run=self.cleaned_data["dry_run"],
+            use_git=True,
+        )
+
+    def save(self, commit=True):
+        if self.cleaned_data.get("do_import"):
+            self.handle_import()
+
+        return super().save(commit=commit)
diff --git a/main/migrations/0015_mainarticlespage_last_import_log.py b/main/migrations/0015_mainarticlespage_last_import_log.py
new file mode 100644
index 00000000..d4542a92
--- /dev/null
+++ b/main/migrations/0015_mainarticlespage_last_import_log.py
@@ -0,0 +1,20 @@
+# Generated by Django 4.0.7 on 2022-08-24 14:10
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("main", "0014_alter_mainarticlespage_options_and_more"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="mainarticlespage",
+            name="last_import_log",
+            field=models.TextField(
+                blank=True, null=True, verbose_name="Výstup z posledního importu"
+            ),
+        ),
+    ]
diff --git a/main/models.py b/main/models.py
index 64750535..32491cba 100644
--- a/main/models.py
+++ b/main/models.py
@@ -9,8 +9,14 @@ from django.utils import timezone
 from modelcluster.contrib.taggit import ClusterTaggableManager
 from modelcluster.fields import ParentalKey
 from taggit.models import TaggedItemBase
-from wagtail.admin.edit_handlers import FieldPanel, ObjectList, TabbedInterface
-from wagtail.contrib.routable_page.models import RoutablePageMixin, route
+from wagtail.admin.edit_handlers import (
+    FieldPanel,
+    HelpPanel,
+    MultiFieldPanel,
+    ObjectList,
+    TabbedInterface,
+)
+from wagtail.contrib.routable_page.models import route
 from wagtail.core.blocks import CharBlock, PageChooserBlock, RichTextBlock
 from wagtail.core.fields import RichTextField, StreamField
 from wagtail.core.models import Page
@@ -30,6 +36,7 @@ from tuning import admin_help
 from twitter_utils.models import Tweet
 
 from . import blocks
+from .forms import JekyllImportForm
 from .menu import MenuMixin
 
 
@@ -200,17 +207,54 @@ class MainArticlesPage(
         verbose_name="Timeline",
         blank=True,
     )
+    last_import_log = models.TextField(
+        "Výstup z posledního importu", null=True, blank=True
+    )
+
+    import_panels = [
+        MultiFieldPanel(
+            [
+                FieldPanel("do_import"),
+                FieldPanel("collection"),
+                FieldPanel("dry_run"),
+                FieldPanel("jekyll_repo_url"),
+                FieldPanel("readonly_log"),
+                HelpPanel(
+                    "Import provádějte vždy až po vytvoření stránky aktualit. "
+                    'Pro uložení logu je nutné volit možnost "Publikovat", nikoliv'
+                    'pouze "Uložit koncept". '
+                    "Import proběhne na pozadí a může trvat až několik minut. "
+                    "Dejte si po spuštění importu kávu a potom obnovte stránku pro "
+                    "zobrazení výsledku importu."
+                ),
+            ],
+            "import z Jekyll repozitáře",
+        ),
+    ]
 
     ### RELATIONS
 
     parent_page_types = ["main.MainHomePage"]
-    subpage_types = []
+    subpage_types = ["main.MainArticlePage"]
 
     ### PANELS
     content_panels = Page.content_panels + [FieldPanel("perex"), FieldPanel("timeline")]
+    promote_panels = make_promote_panels()
+
+    ### EDIT HANDLERS
+
+    edit_handler = TabbedInterface(
+        [
+            ObjectList(content_panels, heading="Obsah"),
+            ObjectList(promote_panels, heading="Propagovat"),
+            ObjectList(import_panels, heading="Import"),
+        ]
+    )
 
     ### OTHERS
 
+    base_form_class = JekyllImportForm
+
     class Meta:
         verbose_name = "Rozcestník článků"
 
diff --git a/main/tasks.py b/main/tasks.py
new file mode 100644
index 00000000..03f20935
--- /dev/null
+++ b/main/tasks.py
@@ -0,0 +1,27 @@
+import logging
+
+from majak.celery import app
+from shared.jekyll_import import JekyllArticleImporter
+
+logger = logging.getLogger(__name__)
+
+
+@app.task
+def import_jekyll_articles(
+    article_parent_page_id: int,
+    collection_id: int,
+    url: str,
+    dry_run: bool,
+    use_git: bool,
+):
+    from .models import MainArticlePage, MainArticlesPage
+
+    return JekyllArticleImporter(
+        article_parent_page_id=article_parent_page_id,
+        collection_id=collection_id,
+        url=url,
+        dry_run=dry_run,
+        use_git=use_git,
+        parent_page_model=MainArticlesPage,
+        page_model=MainArticlePage,
+    ).perform_import()
-- 
GitLab