From 3e4ebb72bded8f48b888b5952a5661662b59bbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 30 Jan 2021 14:53:07 +0100 Subject: [PATCH 01/10] Add and adapt django-tex dependency Load dependency Use custom escaping environment Adapt installation guidelines --- AKModel/environment.py | 26 ++++++++++++++++++++++++++ AKPlanning/settings.py | 11 +++++++++++ INSTALL.md | 1 + requirements.txt | 1 + 4 files changed, 39 insertions(+) create mode 100644 AKModel/environment.py diff --git a/AKModel/environment.py b/AKModel/environment.py new file mode 100644 index 00000000..5883361b --- /dev/null +++ b/AKModel/environment.py @@ -0,0 +1,26 @@ +# environment.py +import re + +from django_tex.environment import environment + +# Used to filter all very special UTF-8 chars that are probably not contained in the LaTeX fonts +# and would hence cause compilation errors +utf8_replace_pattern = re.compile(u'[^\u0000-\u206F]', re.UNICODE) + +def latex_escape_utf8(value): + """ + Escape latex special chars and remove invalid utf-8 values + + :param value: string to escape + :type value: str + :return: escaped string + :rtype: str + """ + return utf8_replace_pattern.sub('', value).replace('&', '\&').replace('_', '\_').replace('#', '\#').replace('$', '\$').replace('%', '\%').replace('{', '\{').replace('}', '\}') + +def improved_tex_environment(**options): + env = environment(**options) + env.filters.update({ + 'latex_escape_utf8': latex_escape_utf8, + }) + return env diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index b6745ea1..f01056ac 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -52,6 +52,7 @@ INSTALLED_APPS = [ 'simple_history', 'registration', 'bootstrap_datepicker_plus', + 'django_tex', ] MIDDLEWARE = [ @@ -85,6 +86,14 @@ TEMPLATES = [ ], }, }, + { + 'NAME': 'tex', + 'BACKEND': 'django_tex.engine.TeXEngine', + 'APP_DIRS': True, + 'OPTIONS': { + 'environment': 'AKModel.environment.improved_tex_environment', + } + }, ] WSGI_APPLICATION = 'AKPlanning.wsgi.application' @@ -137,6 +146,8 @@ LANGUAGES = [ INTERNAL_IPS = ['127.0.0.1', '::1'] +LATEX_INTERPRETER = 'pdflatex' + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.2/howto/static-files/ diff --git a/INSTALL.md b/INSTALL.md index 040a5aa8..54a002e3 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -12,6 +12,7 @@ AKPlanning has two types of requirements: System requirements are dependent on o * Python 3.7 incl. development tools * Virtualenv +* pdflatex & beamer class (`texlive-latex-base texlive-latex-recommended texlive-latex-extra texlive-fonts-extra`) * for production using uwsgi: * C compiler e.g. gcc * uwsgi diff --git a/requirements.txt b/requirements.txt index 176ecddc..c4d0c932 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,5 +8,6 @@ django-simple-history==3.0.0 django-registration-redux==2.9 django-debug-toolbar==3.2.1 django-bootstrap-datepicker-plus==3.0.5 +django-tex==1.1.8.post1 mysqlclient==2.0.3 # for production deployment pytz==2021.1 -- GitLab From ea3e709e7a24ce441cb29ca85184c2822df2f431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 30 Jan 2021 14:56:09 +0100 Subject: [PATCH 02/10] Fix formation issue in simplified duration representation of AKSlot Also use this representation in durations list of AK --- AKModel/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AKModel/models.py b/AKModel/models.py index b3719536..dcb1d457 100644 --- a/AKModel/models.py +++ b/AKModel/models.py @@ -264,7 +264,7 @@ class AK(models.Model): @property def durations_list(self): - return ", ".join(str(slot.duration) for slot in self.akslot_set.all()) + return ", ".join(str(slot.duration_simplified) for slot in self.akslot_set.all()) @property def tags_list(self): -- GitLab From 57f7794e79a7423663f34d738dbdf9d492fa31e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 30 Jan 2021 15:01:48 +0100 Subject: [PATCH 03/10] Implement simple AK to slide export Create template for slides Add view Link view from status page Update translations --- AKModel/admin.py | 7 +- AKModel/locale/de_DE/LC_MESSAGES/django.po | 10 ++- AKModel/templates/AKModel/export/slides.tex | 72 +++++++++++++++++++++ AKModel/templates/admin/AKModel/status.html | 2 + AKModel/views.py | 22 ++++++- 5 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 AKModel/templates/AKModel/export/slides.tex diff --git a/AKModel/admin.py b/AKModel/admin.py index 9427710f..16fe017f 100644 --- a/AKModel/admin.py +++ b/AKModel/admin.py @@ -1,8 +1,8 @@ +from django import forms from django.apps import apps from django.contrib import admin from django.contrib.admin import SimpleListFilter from django.db.models import Count, F -from django import forms from django.shortcuts import render, redirect from django.urls import path, reverse_lazy from django.utils import timezone @@ -16,9 +16,11 @@ from AKModel.availability.forms import AvailabilitiesFormMixin from AKModel.availability.models import Availability from AKModel.models import Event, AKOwner, AKCategory, AKTrack, AKTag, AKRequirement, AK, AKSlot, Room, AKOrgaMessage, \ ConstraintViolation -from AKModel.views import EventStatusView, AKCSVExportView, AKWikiExportView, AKMessageDeleteView, AKRequirementOverview, \ +from AKModel.views import EventStatusView, AKCSVExportView, AKWikiExportView, AKMessageDeleteView, \ + AKRequirementOverview, \ NewEventWizardStartView, NewEventWizardSettingsView, NewEventWizardPrepareImportView, NewEventWizardFinishView, \ NewEventWizardImportView, NewEventWizardActivateView +from AKModel.views import export_slides @admin.register(Event) @@ -56,6 +58,7 @@ class EventAdmin(admin.ModelAdmin): path('<slug:event_slug>/requirements/', self.admin_site.admin_view(AKRequirementOverview.as_view()), name="event_requirement_overview"), path('<slug:event_slug>/ak-csv-export/', self.admin_site.admin_view(AKCSVExportView.as_view()), name="ak_csv_export"), path('<slug:event_slug>/ak-wiki-export/', self.admin_site.admin_view(AKWikiExportView.as_view()), name="ak_wiki_export"), + path('<slug:event_slug>/ak-slide-export/', export_slides, name="ak_slide_export"), path('<slug:slug>/delete-orga-messages/', self.admin_site.admin_view(AKMessageDeleteView.as_view()), name="ak_delete_orga_messages"), ] diff --git a/AKModel/locale/de_DE/LC_MESSAGES/django.po b/AKModel/locale/de_DE/LC_MESSAGES/django.po index 0f5209a9..ae977083 100644 --- a/AKModel/locale/de_DE/LC_MESSAGES/django.po +++ b/AKModel/locale/de_DE/LC_MESSAGES/django.po @@ -485,7 +485,7 @@ msgstr "Anzahl Personen, die online Interesse bekundet haben" #: AKModel/models.py:240 AKModel/models.py:440 #: AKModel/templates/admin/AKModel/status.html:49 -#: AKModel/templates/admin/AKModel/status.html:56 +#: AKModel/templates/admin/AKModel/status.html:56 AKModel/views.py:194 msgid "AKs" msgstr "AKs" @@ -898,6 +898,10 @@ msgstr "AKs als CSV exportieren" msgid "Export AKs for Wiki" msgstr "AKs im Wiki-Format exportieren" +#: AKModel/templates/admin/AKModel/status.html:82 +msgid "Export AK Slides" +msgstr "AK-Folien exportieren" + #: AKModel/templates/admin/AKModel/status.html:87 msgid "No requirements yet" msgstr "Bisher keine Anforderungen" @@ -938,6 +942,10 @@ msgstr "AK-Wiki-Export" msgid "AK Orga Messages successfully deleted" msgstr "AK-Organachrichten erfolgreich gelöscht" +#: AKModel/views.py:195 +msgid "Wishes" +msgstr "Wünsche" + #: AKModel/views.py:207 msgid "Settings" msgstr "Einstellungen" diff --git a/AKModel/templates/AKModel/export/slides.tex b/AKModel/templates/AKModel/export/slides.tex new file mode 100644 index 00000000..31f8bdcd --- /dev/null +++ b/AKModel/templates/AKModel/export/slides.tex @@ -0,0 +1,72 @@ +\documentclass{beamer} +\usetheme{metropolis} +% \usetheme[numbering=fraction, progressbar=foot]{metropolis} TODO Activate when total number of frames bug is resolved + +\usepackage[utf8]{inputenc} +\usepackage{fontawesome5} + +\title{ {{- title -}} } +\subtitle{ {{- subtitle -}} } +\date{\today} + +\begin{document} + +\begin{frame} +\maketitle +\end{frame} + + +{%for category in categories %} + + \section{ {{- category.name | latex_escape_utf8 -}} } + + {% for ak in category.ak_set.all() %} + + {% if not ak.wish %} + + %\setbeamertemplate{frame footer}{} + + \begin{frame}[shrink=15] + \frametitle{ {{- ak.name | latex_escape_utf8 -}} } + + \vspace{1em} + + \faUser~ {{ ak.owners_list | latex_escape_utf8 }} + + \faClock~ {{ak.durations_list}} + + {% if ak.reso %} + \faScroll + {% endif %} + + {{ ak.description | latex_escape_utf8 }} + + \end{frame} + + {% endif %} + + {% endfor %} + +{% endfor %} + + +\section{ {{- wish_category_title -}} } + +{% for ak in wishes %} + + %\setbeamertemplate{frame footer}{} + + \begin{frame}[shrink=15] + \frametitle{ {{- ak.name | latex_escape_utf8 -}} } + + \vspace{1em} + + \faFilter~ {{ ak.category.name | latex_escape_utf8 }} + + {{ ak.description | latex_escape_utf8 }} + + \end{frame} + +{% endfor %} + +\end{document} diff --git a/AKModel/templates/admin/AKModel/status.html b/AKModel/templates/admin/AKModel/status.html index ee84a94a..dd269c83 100644 --- a/AKModel/templates/admin/AKModel/status.html +++ b/AKModel/templates/admin/AKModel/status.html @@ -80,6 +80,8 @@ href="{% url 'admin:ak_csv_export' event_slug=event.slug %}">{% trans "Export AKs as CSV" %}</a> <a class="btn btn-success" href="{% url 'admin:ak_wiki_export' event_slug=event.slug %}">{% trans "Export AKs for Wiki" %}</a> + <a class="btn btn-success" + href="{% url 'admin:ak_slide_export' event_slug=event.slug %}">{% trans "Export AK Slides" %}</a> {% endif %} <h3 class="block-header">{% trans "Requirements" %}</h3> diff --git a/AKModel/views.py b/AKModel/views.py index cc78a0c5..aeeb7b5c 100644 --- a/AKModel/views.py +++ b/AKModel/views.py @@ -1,10 +1,13 @@ from django.contrib import admin, messages +from django.contrib.admin.views.decorators import staff_member_required from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from django.views.generic import TemplateView, DetailView, ListView, DeleteView, CreateView, FormView, UpdateView from rest_framework import viewsets, permissions, mixins +from django_tex.shortcuts import render_to_pdf + from AKModel.forms import NewEventWizardStartForm, NewEventWizardSettingsForm, NewEventWizardPrepareImportForm, \ NewEventWizardImportForm, NewEventWizardActivateForm @@ -242,8 +245,6 @@ class NewEventWizardPrepareImportView(WizardViewMixin, EventSlugMixin, FormView) template_name = "admin/AKModel/event_wizard/created_prepare_import.html" wizard_step = 3 - - def form_valid(self, form): # Selected a valid event to import from? Use this to go to next step of wizard return redirect("admin:new_event_wizard_import", event_slug=self.event.slug, import_slug=form.cleaned_data["import_event"].slug) @@ -287,3 +288,20 @@ class NewEventWizardFinishView(WizardViewMixin, DetailView): model = Event template_name = "admin/AKModel/event_wizard/finish.html" wizard_step = 6 + + +@staff_member_required +def export_slides(request, event_slug): + template_name = 'AKModel/export/slides.tex' + + event = get_object_or_404(Event, slug=event_slug) + + context = { + 'title': event.name, + 'categories': event.akcategory_set.all(), + 'subtitle': _("AKs"), + 'wish_category_title': _("Wishes"), + "wishes": [ak for ak in event.ak_set.order_by('category') if ak.wish] + } + + return render_to_pdf(request, template_name, context, filename='slides.pdf') -- GitLab From f1e83ef38a7857a0be2d0f5d7d744fbb874c7c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 8 May 2021 19:16:26 +0200 Subject: [PATCH 04/10] Use fork of django-tex that allows multiple consecutive runs of latex compile command Additionally, this provides better escaping of user content Set setting for consecutive runs to 2 --- AKPlanning/settings.py | 3 ++- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index f01056ac..380475ae 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -92,7 +92,7 @@ TEMPLATES = [ 'APP_DIRS': True, 'OPTIONS': { 'environment': 'AKModel.environment.improved_tex_environment', - } + }, }, ] @@ -147,6 +147,7 @@ LANGUAGES = [ INTERNAL_IPS = ['127.0.0.1', '::1'] LATEX_INTERPRETER = 'pdflatex' +LATEX_RUN_COUNT = 2 # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.2/howto/static-files/ diff --git a/requirements.txt b/requirements.txt index c4d0c932..55307ddc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,6 @@ django-simple-history==3.0.0 django-registration-redux==2.9 django-debug-toolbar==3.2.1 django-bootstrap-datepicker-plus==3.0.5 -django-tex==1.1.8.post1 +django-tex @ git+https://github.com/bhaettasch/django-tex.git@91db2dc814a35c6e1d4a4b758a1a7b56822305b5 mysqlclient==2.0.3 # for production deployment pytz==2021.1 -- GitLab From c3ddea6001e7237c9ae998258f545bc5854fe787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 8 May 2021 20:02:05 +0200 Subject: [PATCH 05/10] Show number of overall slides on export slides --- AKModel/templates/AKModel/export/slides.tex | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/AKModel/templates/AKModel/export/slides.tex b/AKModel/templates/AKModel/export/slides.tex index 31f8bdcd..4e2508af 100644 --- a/AKModel/templates/AKModel/export/slides.tex +++ b/AKModel/templates/AKModel/export/slides.tex @@ -1,6 +1,5 @@ \documentclass{beamer} -\usetheme{metropolis} -% \usetheme[numbering=fraction, progressbar=foot]{metropolis} TODO Activate when total number of frames bug is resolved +\usetheme[numbering=fraction, progressbar=foot]{metropolis} \usepackage[utf8]{inputenc} \usepackage{fontawesome5} @@ -39,7 +38,7 @@ \faScroll {% endif %} - {{ ak.description | latex_escape_utf8 }} + {{ ak.description | truncatechars(500) | latex_escape_utf8 }} \end{frame} -- GitLab From ee8617e0771d04e6ffb8598e321a8e70d80ae9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sat, 8 May 2021 20:02:40 +0200 Subject: [PATCH 06/10] Truncate length of description texts for AK info slides --- AKModel/templates/AKModel/export/slides.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AKModel/templates/AKModel/export/slides.tex b/AKModel/templates/AKModel/export/slides.tex index 4e2508af..4bf131d6 100644 --- a/AKModel/templates/AKModel/export/slides.tex +++ b/AKModel/templates/AKModel/export/slides.tex @@ -62,7 +62,7 @@ \faFilter~ {{ ak.category.name | latex_escape_utf8 }} - {{ ak.description | latex_escape_utf8 }} + {{ ak.description | truncatechars(500) | latex_escape_utf8 }} \end{frame} -- GitLab From efe34bd3fe2bd1701426254d2fa802d2c4efddc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sun, 9 May 2021 00:12:47 +0200 Subject: [PATCH 07/10] Show symbol legend and placeholder symbols for wishes in slides Additionally, change slide ratio to 16:9 --- AKModel/locale/de_DE/LC_MESSAGES/django.po | 84 +++++++++++++-------- AKModel/templates/AKModel/export/slides.tex | 21 +++++- AKModel/views.py | 13 +++- 3 files changed, 82 insertions(+), 36 deletions(-) diff --git a/AKModel/locale/de_DE/LC_MESSAGES/django.po b/AKModel/locale/de_DE/LC_MESSAGES/django.po index ae977083..22e42f30 100644 --- a/AKModel/locale/de_DE/LC_MESSAGES/django.po +++ b/AKModel/locale/de_DE/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 22:48+0000\n" +"POT-Creation-Date: 2021-05-08 18:07+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: AKModel/admin.py:66 AKModel/admin.py:67 +#: AKModel/admin.py:69 AKModel/admin.py:70 #: AKModel/templates/admin/AKModel/event_wizard/activate.html:32 #: AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html:48 #: AKModel/templates/admin/AKModel/event_wizard/finish.html:21 @@ -21,23 +21,23 @@ msgstr "" msgid "Status" msgstr "Status" -#: AKModel/admin.py:153 +#: AKModel/admin.py:156 msgid "Wish" msgstr "AK-Wunsch" -#: AKModel/admin.py:159 +#: AKModel/admin.py:162 msgid "Is wish" msgstr "Ist ein Wunsch" -#: AKModel/admin.py:160 +#: AKModel/admin.py:163 msgid "Is not a wish" msgstr "Ist kein Wunsch" -#: AKModel/admin.py:187 +#: AKModel/admin.py:209 msgid "Export to wiki syntax" msgstr "In Wiki-Syntax exportieren" -#: AKModel/admin.py:283 +#: AKModel/admin.py:317 msgid "AK Details" msgstr "AK-Details" @@ -170,7 +170,7 @@ msgstr "Zeitzone" msgid "Time Zone where this event takes place in" msgstr "Zeitzone in der das Event stattfindet" -#: AKModel/models.py:25 AKModel/views.py:206 +#: AKModel/models.py:25 AKModel/views.py:209 msgid "Start" msgstr "Start" @@ -430,7 +430,7 @@ msgstr "AK präsentieren" msgid "Present results of this AK" msgstr "Die Ergebnisse dieses AKs vorstellen" -#: AKModel/models.py:218 AKModel/templates/admin/AKModel/status.html:85 +#: AKModel/models.py:218 AKModel/templates/admin/AKModel/status.html:87 msgid "Requirements" msgstr "Anforderungen" @@ -485,7 +485,7 @@ msgstr "Anzahl Personen, die online Interesse bekundet haben" #: AKModel/models.py:240 AKModel/models.py:440 #: AKModel/templates/admin/AKModel/status.html:49 -#: AKModel/templates/admin/AKModel/status.html:56 AKModel/views.py:194 +#: AKModel/templates/admin/AKModel/status.html:56 AKModel/views.py:310 msgid "AKs" msgstr "AKs" @@ -761,7 +761,7 @@ msgid "Successfully imported.<br><br>Do you want to activate your event now?" msgstr "Erfolgreich importiert.<br><br>Soll das Event jetzt aktiviert werden?" #: AKModel/templates/admin/AKModel/event_wizard/activate.html:27 -#: AKModel/views.py:211 +#: AKModel/views.py:214 msgid "Finish" msgstr "Abschluss" @@ -845,7 +845,7 @@ msgid "No AKs with this requirement" msgstr "Kein AK mit dieser Anforderung" #: AKModel/templates/admin/AKModel/requirements_overview.html:45 -#: AKModel/templates/admin/AKModel/status.html:101 +#: AKModel/templates/admin/AKModel/status.html:103 msgid "Add Requirement" msgstr "Anforderung hinzufügen" @@ -898,23 +898,23 @@ msgstr "AKs als CSV exportieren" msgid "Export AKs for Wiki" msgstr "AKs im Wiki-Format exportieren" -#: AKModel/templates/admin/AKModel/status.html:82 +#: AKModel/templates/admin/AKModel/status.html:84 msgid "Export AK Slides" msgstr "AK-Folien exportieren" -#: AKModel/templates/admin/AKModel/status.html:87 +#: AKModel/templates/admin/AKModel/status.html:89 msgid "No requirements yet" msgstr "Bisher keine Anforderungen" -#: AKModel/templates/admin/AKModel/status.html:100 +#: AKModel/templates/admin/AKModel/status.html:102 msgid "Show AKs for requirements" msgstr "Zu Anforderungen gehörige AKs anzeigen" -#: AKModel/templates/admin/AKModel/status.html:104 +#: AKModel/templates/admin/AKModel/status.html:106 msgid "Messages" msgstr "Nachrichten" -#: AKModel/templates/admin/AKModel/status.html:106 +#: AKModel/templates/admin/AKModel/status.html:108 msgid "Delete all messages" msgstr "Alle Nachrichten löschen" @@ -922,58 +922,78 @@ msgstr "Alle Nachrichten löschen" msgid "Active Events" msgstr "Aktive Events" -#: AKModel/views.py:136 +#: AKModel/views.py:139 msgid "Event Status" msgstr "Eventstatus" -#: AKModel/views.py:149 +#: AKModel/views.py:152 msgid "Requirements for Event" msgstr "Anforderungen für das Event" -#: AKModel/views.py:163 +#: AKModel/views.py:166 msgid "AK CSV Export" msgstr "AK-CSV-Export" -#: AKModel/views.py:177 +#: AKModel/views.py:180 msgid "AK Wiki Export" msgstr "AK-Wiki-Export" -#: AKModel/views.py:197 +#: AKModel/views.py:200 msgid "AK Orga Messages successfully deleted" msgstr "AK-Organachrichten erfolgreich gelöscht" -#: AKModel/views.py:195 -msgid "Wishes" -msgstr "Wünsche" - -#: AKModel/views.py:207 +#: AKModel/views.py:210 msgid "Settings" msgstr "Einstellungen" -#: AKModel/views.py:208 +#: AKModel/views.py:211 msgid "Event created, Prepare Import" msgstr "Event angelegt, Import vorbereiten" -#: AKModel/views.py:209 +#: AKModel/views.py:212 msgid "Import categories & requirements" msgstr "Kategorien & Anforderungen kopieren" -#: AKModel/views.py:210 +#: AKModel/views.py:213 #, fuzzy #| msgid "Active State" msgid "Activate?" msgstr "Aktivieren?" -#: AKModel/views.py:270 +#: AKModel/views.py:271 #, python-format msgid "Copied '%(obj)s'" msgstr "'%(obj)s' kopiert" -#: AKModel/views.py:272 +#: AKModel/views.py:273 #, python-format msgid "Could not copy '%(obj)s' (%(error)s)" msgstr "'%(obj)s' konnte nicht kopiert werden (%(error)s)" +#: AKModel/views.py:300 +msgid "Symbols" +msgstr "Symbole" + +#: AKModel/views.py:301 +msgid "Who?" +msgstr "Wer?" + +#: AKModel/views.py:302 +msgid "Duration(s)" +msgstr "Dauer(n)" + +#: AKModel/views.py:303 +msgid "Reso intention?" +msgstr "Resolutionsabsicht?" + +#: AKModel/views.py:304 +msgid "Category (for Wishes)" +msgstr "Kategorie (für Wünsche)" + +#: AKModel/views.py:311 +msgid "Wishes" +msgstr "Wünsche" + #~ msgid "Confirm" #~ msgstr "Bestätigen" diff --git a/AKModel/templates/AKModel/export/slides.tex b/AKModel/templates/AKModel/export/slides.tex index 4bf131d6..d7c9ce62 100644 --- a/AKModel/templates/AKModel/export/slides.tex +++ b/AKModel/templates/AKModel/export/slides.tex @@ -1,4 +1,4 @@ -\documentclass{beamer} +\documentclass[aspectratio=169]{beamer} \usetheme[numbering=fraction, progressbar=foot]{metropolis} \usepackage[utf8]{inputenc} @@ -14,6 +14,19 @@ \maketitle \end{frame} +\begin{frame} + \frametitle{ {{- translations.symbols -}} } + + \faUser~ {{ translations.who }} + + \faClock~ {{ translations.duration }} + + \faScroll~{{ translations.reso }} + + \faFilter~ {{ translations.category }} + +\end{frame} + {%for category in categories %} @@ -49,7 +62,7 @@ {% endfor %} -\section{ {{- wish_category_title -}} } +\section{ {{- translations.wishes -}} } {% for ak in wishes %} @@ -62,6 +75,10 @@ \faFilter~ {{ ak.category.name | latex_escape_utf8 }} + \faUser~ + + \faClock~ + {{ ak.description | truncatechars(500) | latex_escape_utf8 }} \end{frame} diff --git a/AKModel/views.py b/AKModel/views.py index aeeb7b5c..ea7e09a2 100644 --- a/AKModel/views.py +++ b/AKModel/views.py @@ -296,12 +296,21 @@ def export_slides(request, event_slug): event = get_object_or_404(Event, slug=event_slug) + translations = { + 'symbols': _("Symbols"), + 'who': _("Who?"), + 'duration': _("Duration(s)"), + 'reso': _("Reso intention?"), + 'category': _("Category (for Wishes)"), + 'wishes': _("Wishes"), + } + context = { 'title': event.name, 'categories': event.akcategory_set.all(), 'subtitle': _("AKs"), - 'wish_category_title': _("Wishes"), - "wishes": [ak for ak in event.ak_set.order_by('category') if ak.wish] + "wishes": [ak for ak in event.ak_set.order_by('category') if ak.wish], + "translations": translations, } return render_to_pdf(request, template_name, context, filename='slides.pdf') -- GitLab From 8fa36c56d58c51247b1eef3bf9e1390f6d24e45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sun, 9 May 2021 00:24:09 +0200 Subject: [PATCH 08/10] Move slides template to semantically correct place --- AKModel/templates/{ => admin}/AKModel/export/slides.tex | 0 AKModel/views.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename AKModel/templates/{ => admin}/AKModel/export/slides.tex (100%) diff --git a/AKModel/templates/AKModel/export/slides.tex b/AKModel/templates/admin/AKModel/export/slides.tex similarity index 100% rename from AKModel/templates/AKModel/export/slides.tex rename to AKModel/templates/admin/AKModel/export/slides.tex diff --git a/AKModel/views.py b/AKModel/views.py index ea7e09a2..b620f1e7 100644 --- a/AKModel/views.py +++ b/AKModel/views.py @@ -292,7 +292,7 @@ class NewEventWizardFinishView(WizardViewMixin, DetailView): @staff_member_required def export_slides(request, event_slug): - template_name = 'AKModel/export/slides.tex' + template_name = 'admin/AKModel/export/slides.tex' event = get_object_or_404(Event, slug=event_slug) -- GitLab From 58301524ca3454f360063e33394319a169fc9b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sun, 9 May 2021 01:34:41 +0200 Subject: [PATCH 09/10] Display list of next AKs on slides --- .../templates/admin/AKModel/export/slides.tex | 26 +++++++++++++++---- AKModel/views.py | 24 +++++++++++++++-- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/AKModel/templates/admin/AKModel/export/slides.tex b/AKModel/templates/admin/AKModel/export/slides.tex index d7c9ce62..814c57ed 100644 --- a/AKModel/templates/admin/AKModel/export/slides.tex +++ b/AKModel/templates/admin/AKModel/export/slides.tex @@ -28,11 +28,11 @@ \end{frame} -{%for category in categories %} +{%for category, ak_list in categories_with_aks %} \section{ {{- category.name | latex_escape_utf8 -}} } - {% for ak in category.ak_set.all() %} + {% for ak, next_aks in ak_list %} {% if not ak.wish %} @@ -51,7 +51,15 @@ \faScroll {% endif %} - {{ ak.description | truncatechars(500) | latex_escape_utf8 }} + {{ ak.description | truncatechars(400) | latex_escape_utf8 }} + + \vspace{2em} + + \begin{scriptsize} + {% for n_ak in next_aks %} + {% if n_ak %}\hfill \faAngleDoubleRight~ {{- n_ak.name | latex_escape_utf8 -}}{% endif %} + {% endfor %} + \end{scriptsize} \end{frame} @@ -64,7 +72,7 @@ \section{ {{- translations.wishes -}} } -{% for ak in wishes %} +{% for ak, next_aks in wishes %} %\setbeamertemplate{frame footer}{} @@ -79,7 +87,15 @@ \faClock~ - {{ ak.description | truncatechars(500) | latex_escape_utf8 }} + {{ ak.description | truncatechars(400) | latex_escape_utf8 }} + + \vspace{2em} + + \begin{scriptsize} + {% for n_ak in next_aks %} + {% if n_ak %}\hfill \faAngleDoubleRight~ {{- n_ak.name | latex_escape_utf8 -}}{% endif %} + {% endfor %} + \end{scriptsize} \end{frame} diff --git a/AKModel/views.py b/AKModel/views.py index b620f1e7..06bd3211 100644 --- a/AKModel/views.py +++ b/AKModel/views.py @@ -1,3 +1,5 @@ +from itertools import zip_longest + from django.contrib import admin, messages from django.contrib.admin.views.decorators import staff_member_required from django.http import HttpResponseRedirect @@ -296,6 +298,8 @@ def export_slides(request, event_slug): event = get_object_or_404(Event, slug=event_slug) + NEXT_AK_LIST_LENGTH = 4 + translations = { 'symbols': _("Symbols"), 'who': _("Who?"), @@ -305,11 +309,27 @@ def export_slides(request, event_slug): 'wishes': _("Wishes"), } + def build_ak_list_with_next_aks(ak_list): + next_aks_list = zip_longest(*[ak_list[i + 1:] for i in range(NEXT_AK_LIST_LENGTH)], fillvalue=None) + return [(ak, next_aks) for ak, next_aks in zip_longest(ak_list, next_aks_list, fillvalue=list())] + + categories = event.akcategory_set.all() + categories_with_aks = [] + ak_wishes = [] + for category in categories: + ak_list = [] + for ak in category.ak_set.all(): # order_by("owners").distinct(): + if ak.wish: + ak_wishes.append(ak) + else: + ak_list.append(ak) + categories_with_aks.append((category, build_ak_list_with_next_aks(ak_list))) + context = { 'title': event.name, - 'categories': event.akcategory_set.all(), + 'categories_with_aks': categories_with_aks, 'subtitle': _("AKs"), - "wishes": [ak for ak in event.ak_set.order_by('category') if ak.wish], + "wishes": build_ak_list_with_next_aks(ak_wishes), "translations": translations, } -- GitLab From f469c2b28c4aedbf5d0e2278231cec4da119bea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?= <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de> Date: Sun, 9 May 2021 01:46:01 +0200 Subject: [PATCH 10/10] Introduce result presentation mode for slides and allow to specify mode and num of next AKs via GET params The export now allows to optional params, ?presentation_mode (without args) and ?num_next=<int> (default 3) --- .../templates/admin/AKModel/export/slides.tex | 39 ++++++++++--------- AKModel/views.py | 7 +++- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/AKModel/templates/admin/AKModel/export/slides.tex b/AKModel/templates/admin/AKModel/export/slides.tex index 814c57ed..d30f70e5 100644 --- a/AKModel/templates/admin/AKModel/export/slides.tex +++ b/AKModel/templates/admin/AKModel/export/slides.tex @@ -69,36 +69,37 @@ {% endfor %} +{% if not result_presentation_mode %} -\section{ {{- translations.wishes -}} } + \section{ {{- translations.wishes -}} } -{% for ak, next_aks in wishes %} + {% for ak, next_aks in wishes %} - %\setbeamertemplate{frame footer}{} + %\setbeamertemplate{frame footer}{} - \begin{frame}[shrink=15] - \frametitle{ {{- ak.name | latex_escape_utf8 -}} } + \begin{frame}[shrink=15] + \frametitle{ {{- ak.name | latex_escape_utf8 -}} } - \vspace{1em} + \vspace{1em} - \faFilter~ {{ ak.category.name | latex_escape_utf8 }} + \faFilter~ {{ ak.category.name | latex_escape_utf8 }} - \faUser~ + \faUser~ - \faClock~ + \faClock~ - {{ ak.description | truncatechars(400) | latex_escape_utf8 }} + {{ ak.description | truncatechars(400) | latex_escape_utf8 }} - \vspace{2em} + \vspace{2em} - \begin{scriptsize} - {% for n_ak in next_aks %} - {% if n_ak %}\hfill \faAngleDoubleRight~ {{- n_ak.name | latex_escape_utf8 -}}{% endif %} - {% endfor %} - \end{scriptsize} + \begin{scriptsize} + {% for n_ak in next_aks %} + {% if n_ak %}\hfill \faAngleDoubleRight~ {{- n_ak.name | latex_escape_utf8 -}}{% endif %} + {% endfor %} + \end{scriptsize} - \end{frame} - -{% endfor %} + \end{frame} + {% endfor %} +{% endif %} \end{document} diff --git a/AKModel/views.py b/AKModel/views.py index 06bd3211..c1926d7d 100644 --- a/AKModel/views.py +++ b/AKModel/views.py @@ -298,7 +298,8 @@ def export_slides(request, event_slug): event = get_object_or_404(Event, slug=event_slug) - NEXT_AK_LIST_LENGTH = 4 + NEXT_AK_LIST_LENGTH = int(request.GET["num_next"]) if "num_next" in request.GET else 3 + RESULT_PRESENTATION_MODE = True if "presentation_mode" in request.GET else False translations = { 'symbols': _("Symbols"), @@ -322,7 +323,8 @@ def export_slides(request, event_slug): if ak.wish: ak_wishes.append(ak) else: - ak_list.append(ak) + if not RESULT_PRESENTATION_MODE or ak.present: + ak_list.append(ak) categories_with_aks.append((category, build_ak_list_with_next_aks(ak_list))) context = { @@ -331,6 +333,7 @@ def export_slides(request, event_slug): 'subtitle': _("AKs"), "wishes": build_ak_list_with_next_aks(ak_wishes), "translations": translations, + "result_presentation_mode": RESULT_PRESENTATION_MODE, } return render_to_pdf(request, template_name, context, filename='slides.pdf') -- GitLab