From 05feccb1e22ad1ec04252c89961b904a2ab1baca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Bedna=C5=99=C3=ADk?= <jan.bednarik@gmail.com>
Date: Mon, 31 May 2021 13:43:17 +0200
Subject: [PATCH] elections2021: Export program

---
 .isort.cfg                                    |  2 +-
 elections2021/constants.py                    | 17 ++++
 .../management/commands/export_program.py     | 77 +++++++++++++++++++
 elections2021/models.py                       |  7 +-
 .../elections2021/export_program_point.html   | 56 ++++++++++++++
 requirements/base.in                          |  1 +
 requirements/base.txt                         | 34 +++++++-
 7 files changed, 185 insertions(+), 9 deletions(-)
 create mode 100644 elections2021/management/commands/export_program.py
 create mode 100644 elections2021/templates/elections2021/export_program_point.html

diff --git a/.isort.cfg b/.isort.cfg
index 98158d88..fa7bf911 100644
--- a/.isort.cfg
+++ b/.isort.cfg
@@ -4,4 +4,4 @@ line_length = 88
 multi_line_output = 3
 default_section = "THIRDPARTY"
 include_trailing_comma = true
-known_third_party = arrow,bleach,bs4,captcha,django,environ,faker,ics,markdown,modelcluster,pirates,pytest,pytz,requests,sentry_sdk,snapshottest,taggit,wagtail,wagtailmetadata
+known_third_party = arrow,bleach,bs4,captcha,django,environ,faker,ics,markdown,modelcluster,pirates,pytest,pytz,requests,sentry_sdk,snapshottest,taggit,wagtail,wagtailmetadata,weasyprint
diff --git a/elections2021/constants.py b/elections2021/constants.py
index e05e449f..46602324 100644
--- a/elections2021/constants.py
+++ b/elections2021/constants.py
@@ -244,6 +244,23 @@ MINISTRY_ARCHETYPES = {
     MINISTRY_ENVIRONMENT: "prostredi",
 }
 
+MINISTRY_CODES = {
+    MINISTRY_TRANSPORT: "transport",
+    MINISTRY_FINANCES: "finances",
+    MINISTRY_CULTURE: "culture",
+    MINISTRY_DEFENSE: "defense",
+    MINISTRY_SOCIAL: "social",
+    MINISTRY_COUNTRYSIDE: "countryside",
+    MINISTRY_BUSINESS: "business",
+    MINISTRY_JUSTICE: "justice",
+    MINISTRY_SCHOOLS: "schools",
+    MINISTRY_INTERIOR: "interior",
+    MINISTRY_FOREIGN: "foreign",
+    MINISTRY_HEALTH: "health",
+    MINISTRY_AGRICULTURE: "agriculture",
+    MINISTRY_ENVIRONMENT: "environment",
+}
+
 BENEFITS = (
     # (id, název, pracovní název)
     ("1", "Pro mladé", "mladí a bezdětní včetně studentů"),
diff --git a/elections2021/management/commands/export_program.py b/elections2021/management/commands/export_program.py
new file mode 100644
index 00000000..8e8c82ac
--- /dev/null
+++ b/elections2021/management/commands/export_program.py
@@ -0,0 +1,77 @@
+import re
+
+from django.core.management.base import BaseCommand
+from django.template.loader import render_to_string
+from django.utils import timezone
+from weasyprint import CSS, HTML
+
+from ...constants import MINISTRY_CHOICES, MINISTRY_CODES
+from ...models import Elections2021ProgramPointPage
+
+
+def get_ministry_points(ministry):
+    weight = f"weight_ministry_{MINISTRY_CODES[ministry]}"
+    return Elections2021ProgramPointPage.filter_by_weights([weight])
+
+
+class Command(BaseCommand):
+    def add_arguments(self, parser):
+        parser.add_argument("output", type=str, help=".pdf nebo .html soubor")
+
+    def handle(self, *args, **options):
+        now = timezone.localtime().strftime("%d.%m.%Y %H:%M")
+
+        toc = []
+        body = []
+
+        for ministry, title in MINISTRY_CHOICES:
+            sub_toc = []
+
+            body.append(
+                f'<h2 id="{ministry}" class="ministry-title">Resort: {title}</h2>'
+            )
+            for page in get_ministry_points(ministry):
+                value = render_to_string(
+                    "elections2021/export_program_point.html", {"page": page}
+                )
+                value = re.sub(r'href="#zdroje"', f'href="#zdroje_{page.id}"', value)
+                body.append(value)
+
+                sub_toc.append(f'<li><a href="#{page.slug}">{page.title}</a></li>')
+
+            sub_toc = "".join(sub_toc)
+            toc.append(
+                f'<li><a href="#{ministry}">{title}</a><br><ul>{sub_toc}</ul></li>'
+            )
+
+        style = """
+            body { font-family: "Roboto Condensed", Helvetica, sans-serif; line-height: 1.5; }
+            .ministry-title { page-break-before: always; margin-bottom: 0; line-height: 1; }
+            .point-title { border-top: 5px double #AAAAAA; padding-top: 0.5rem; margin-top: 3rem; text-transform: uppercase; }
+            .section-title { border-top: 1px solid #AAAAAA; padding-top: 0.5rem; margin-top: 2rem; text-transform: uppercase; }
+            sup { font-size: 70%; }
+        """
+
+        toc = "".join(toc)
+        content = (
+            [
+                f'<html><head><style type="text/css">{style}</style></head><body>',
+                "<h1>Program koalice Piráti a Starostové</h1>",
+                f'<div><p>export z webu <a href="https://www.piratiastarostove.cz/">piratiastarostove.cz</a> z {now}</p></div>',
+                f"<div><p>obsah:</p><p><ul>{toc}</ul></p></div>",
+            ]
+            + body
+            + ["</body></html>"]
+        )
+
+        content = "".join(content)
+
+        if options["output"].endswith(".pdf"):
+            html = HTML(string=content)
+            css = CSS(string="@page { size: A4; margin: 1cm; }")
+            html.write_pdf(options["output"], stylesheets=[css])
+        elif options["output"].endswith(".html"):
+            with open(options["output"], "w") as file:
+                file.write(content)
+        else:
+            print("ERROR: Jako výstup zadej soubor .html nebo .pdf")
diff --git a/elections2021/models.py b/elections2021/models.py
index d680316e..1bcd1116 100644
--- a/elections2021/models.py
+++ b/elections2021/models.py
@@ -1226,12 +1226,7 @@ class Elections2021ProgramPage(
         if not ministry:
             return HttpResponseRedirect(self.url)
 
-        title = None
-        head_photo = None
-
-        if ministry:
-            title = next(title for key, title in MINISTRY_CHOICES if key == ministry)
-            head_image = self.get_archetype_image(MINISTRY_ARCHETYPES[ministry])
+        title = next(title for key, title in MINISTRY_CHOICES if key == ministry)
 
         if ministry == MINISTRY_TRANSPORT:
             weights = ["weight_ministry_transport"]
diff --git a/elections2021/templates/elections2021/export_program_point.html b/elections2021/templates/elections2021/export_program_point.html
new file mode 100644
index 00000000..df3f2c56
--- /dev/null
+++ b/elections2021/templates/elections2021/export_program_point.html
@@ -0,0 +1,56 @@
+{% load wagtailcore_tags wagtailimages_tags elections2021_extras %}
+<h2 id="{{ page.slug }}" class="point-title">{{ page.title }}</h2>
+<div>{{ page.annotation|richtext|format_sources }}</div>
+
+<h3 class="section-title">Takhle to dál nejde</h3>
+<div>{{ page.problem|richtext|format_sources }}</div>
+
+<h3 class="section-title">V čem je problém</h3>
+<div>{{ page.context|richtext|format_sources }}</div>
+
+<h3 class="section-title">Naše vize</h3>
+<div>{{ page.ideal|richtext|format_sources }}</div>
+
+<h3 class="section-title">Jak to chceme udělat?</h3>
+<div>{{ page.proposal|richtext|format_sources }}</div>
+
+<h3 class="section-title">Kolik na to chceme času?</h3>
+<div>
+  {% if page.time_horizon_number %}
+    <p>{{ page.time_horizon_number }} {{ page.time_horizon_unit }}</p>
+  {% endif %}
+  {% if page.time_horizon_text %}
+    <p>{{ page.time_horizon_text|richtext|format_sources }}</p>
+  {% endif %}
+</div>
+
+<h3 class="section-title">Pro koho to chceme hlavně</h3>
+<div>
+  {% for block in page.benefits_main %}
+    <h4>{{ block.value.title }}</h4>
+    <div>{{ block.value.text|richtext|format_sources }}</div>
+  {% endfor %}
+  {% for block in page.benefits %}
+    <h4>{{ block.value.title }}</h4>
+    <div>{{ block.value.text|richtext|format_sources }}</div>
+  {% endfor %}
+</div>
+
+{% if page.benefit_for_all %}
+  <h3 class="section-title">Benefit pro všechny</h3>
+  <div>{{ page.benefit_for_all|richtext|format_sources }}</div>
+{% endif %}
+
+<h3 class="section-title">Co pro to už děláme</h3>
+<div>{{ page.already_done|richtext|format_sources }}</div>
+
+<h3 class="section-title">Na co se nás často ptáte</h3>
+<div>
+  {% for block in page.faq %}
+    <h4>{{ block.value.question }}</h4>
+    <div>{{ block.value.answer|richtext|format_sources }}</div>
+  {% endfor %}
+</div>
+
+<h3 class="section-title" id="zdroje_{{ page.id }}">Klidně si to ověřte</h3>
+<div>{{ page.sources|richtext }}</div>
diff --git a/requirements/base.in b/requirements/base.in
index a90545dd..06c40912 100644
--- a/requirements/base.in
+++ b/requirements/base.in
@@ -18,3 +18,4 @@ Markdown
 beautifulsoup4
 bleach
 ipython
+weasyprint
diff --git a/requirements/base.txt b/requirements/base.txt
index 79713326..638e3698 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -22,12 +22,21 @@ beautifulsoup4==4.9.3
     #   wagtail
 bleach==3.3.0
     # via -r base.in
+cairocffi==1.2.0
+    # via
+    #   cairosvg
+    #   weasyprint
+cairosvg==2.5.2
+    # via weasyprint
 certifi==2020.12.5
     # via
     #   requests
     #   sentry-sdk
 cffi==1.14.5
-    # via cryptography
+    # via
+    #   cairocffi
+    #   cryptography
+    #   weasyprint
 chardet==4.0.0
     # via requests
 cryptography==3.4.7
@@ -35,8 +44,14 @@ cryptography==3.4.7
     #   josepy
     #   mozilla-django-oidc
     #   pyopenssl
+cssselect2==0.4.1
+    # via
+    #   cairosvg
+    #   weasyprint
 decorator==5.0.8
     # via ipython
+defusedxml==0.7.1
+    # via cairosvg
 django-environ==0.4.5
     # via -r base.in
 django-extensions==3.1.3
@@ -79,7 +94,9 @@ draftjs-exporter==2.1.7
 et-xmlfile==1.1.0
     # via openpyxl
 html5lib==1.1
-    # via wagtail
+    # via
+    #   wagtail
+    #   weasyprint
 ics==0.7
     # via -r base.in
 idna==2.10
@@ -116,8 +133,10 @@ pickleshare==0.7.5
     # via ipython
 pillow==8.2.0
     # via
+    #   cairosvg
     #   django-simple-captcha
     #   wagtail
+    #   weasyprint
 pirates==0.5.0
     # via -r base.in
 prompt-toolkit==3.0.18
@@ -134,6 +153,8 @@ pyopenssl==20.0.1
     # via josepy
 pyparsing==2.4.7
     # via packaging
+pyphen==0.10.0
+    # via weasyprint
 python-dateutil==2.8.1
     # via
     #   arrow
@@ -172,6 +193,11 @@ tatsu==5.6.1
     # via ics
 telepath==0.1.1
     # via wagtail
+tinycss2==1.1.0
+    # via
+    #   cairosvg
+    #   cssselect2
+    #   weasyprint
 traitlets==5.0.5
     # via
     #   ipython
@@ -188,10 +214,14 @@ wagtail==2.13
     #   wagtail-metadata
 wcwidth==0.2.5
     # via prompt-toolkit
+weasyprint==52.5
+    # via -r base.in
 webencodings==0.5.1
     # via
     #   bleach
+    #   cssselect2
     #   html5lib
+    #   tinycss2
 whitenoise==5.2.0
     # via -r base.in
 willow==1.4
-- 
GitLab