From d80d233e47e6ba1b75f389be48339b9cc8a5ed0c Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 28 Feb 2021 00:29:26 +0000 Subject: [PATCH 01/36] intern implementation --- fet2020/fet2020/settings.py | 1 + fet2020/fet2020/urls.py | 1 + fet2020/intern/__init__.py | 0 fet2020/intern/admin.py | 57 ++++++++++++++++ fet2020/intern/apps.py | 5 ++ fet2020/intern/forms.py | 49 ++++++++++++++ fet2020/intern/models.py | 101 ++++++++++++++++++++++++++++ fet2020/intern/tests.py | 3 + fet2020/intern/urls.py | 10 +++ fet2020/intern/views.py | 85 +++++++++++++++++++++++ fet2020/static/intern.css | 75 +++++++++++++++++++++ fet2020/templates/intern/docu.html | 75 +++++++++++++++++++++ fet2020/templates/intern/index.html | 29 ++++++++ fet2020/templates/intern/topic.html | 49 ++++++++++++++ fet2020/templates/layout.html | 4 +- 15 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 fet2020/intern/__init__.py create mode 100644 fet2020/intern/admin.py create mode 100644 fet2020/intern/apps.py create mode 100644 fet2020/intern/forms.py create mode 100644 fet2020/intern/models.py create mode 100644 fet2020/intern/tests.py create mode 100644 fet2020/intern/urls.py create mode 100644 fet2020/intern/views.py create mode 100644 fet2020/static/intern.css create mode 100644 fet2020/templates/intern/docu.html create mode 100644 fet2020/templates/intern/index.html create mode 100644 fet2020/templates/intern/topic.html diff --git a/fet2020/fet2020/settings.py b/fet2020/fet2020/settings.py index 8eed5b81..1958da8f 100644 --- a/fet2020/fet2020/settings.py +++ b/fet2020/fet2020/settings.py @@ -81,6 +81,7 @@ INSTALLED_APPS = [ "documents.apps.DocumentsConfig", "blackboard.apps.BlackboardConfig", "tasks.apps.TasksConfig", + "intern.apps.InternConfig", ] MIDDLEWARE = [ diff --git a/fet2020/fet2020/urls.py b/fet2020/fet2020/urls.py index 8f009383..d6014ec0 100644 --- a/fet2020/fet2020/urls.py +++ b/fet2020/fet2020/urls.py @@ -38,6 +38,7 @@ urlpatterns = [ path("member/", include(member_urlpatterns), name="member"), path("blackboard/", include("blackboard.urls"), name="blackboard"), path("tasks/", include("tasks.urls"), name="tasks"), + path("intern/", include("intern.urls"), name="intern"), path( "sitemap.xml", sitemap, diff --git a/fet2020/intern/__init__.py b/fet2020/intern/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py new file mode 100644 index 00000000..fe2b8dec --- /dev/null +++ b/fet2020/intern/admin.py @@ -0,0 +1,57 @@ +from django.contrib import admin + +from .models import TopicGroup, Topic, Documentation +from .forms import TopicGroupAdminForm, TopicAdminForm + + +class DocumentationInline(admin.TabularInline): + model = Documentation + extra = 0 + verbose_name = "Dokument" + verbose_name_plural = "Dokument-Übersicht" + + +class TopicInline(admin.TabularInline): + model = Topic + extra = 0 + verbose_name = "Topic" + verbose_name_plural = "Topic-Übersicht" + + +class TopicGroupAdmin(admin.ModelAdmin): + form = TopicGroupAdminForm + model = TopicGroup + search_fields = ("title",) + inlines = (TopicInline,) + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) + + +class TopicAdmin(admin.ModelAdmin): + form = TopicAdminForm + model = Topic + search_fields = ("title",) + inlines = (DocumentationInline,) + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) + + +""" +class DocumentationAdmin(admin.ModelAdmin): + form = DocumentationAdminForm + model = Documentation + + list_display = ["title", "topic"] + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) +""" + +admin.site.register(TopicGroup, TopicGroupAdmin) +admin.site.register(Topic, TopicAdmin) +# admin.site.register(Documentation, DocumentationAdmin) diff --git a/fet2020/intern/apps.py b/fet2020/intern/apps.py new file mode 100644 index 00000000..b2d0203a --- /dev/null +++ b/fet2020/intern/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class InternConfig(AppConfig): + name = "intern" diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py new file mode 100644 index 00000000..f2863d49 --- /dev/null +++ b/fet2020/intern/forms.py @@ -0,0 +1,49 @@ +from django import forms +from django.utils.translation import gettext_lazy as _ + +from ckeditor_uploader.widgets import CKEditorUploadingWidget + +from .models import TopicGroup, Topic, Documentation, Document + + +class TopicGroupAdminForm(forms.ModelForm): + class Meta: + model = TopicGroup + fields = [ + "title", + ] + + +class TopicAdminForm(forms.ModelForm): + class Meta: + model = Topic + fields = [ + "title", + "description", + "topic_group", + ] + + widgets = {"description": CKEditorUploadingWidget(config_name="default")} + + +class DocumentationAdminForm(forms.ModelForm): + class Meta: + model = Documentation + fields = [ + "title", + "description", + "topic", + ] + + +class DocumentForm(forms.ModelForm): + class Meta: + model = Document + + fields = [ + "title", + ] + + labels = { + "title": _("Titel des Protokolls"), + } diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py new file mode 100644 index 00000000..8715e6f4 --- /dev/null +++ b/fet2020/intern/models.py @@ -0,0 +1,101 @@ +import logging +from django.db import models +from django.utils.text import slugify +from documents import createPadifNotExists +from urllib.request import URLError + +logger = logging.getLogger(__name__) + + +class TopicGroup(models.Model): + title = models.CharField(max_length=128) + + slug = models.SlugField(unique=True, blank=True) + + objects = models.Manager() + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Topic(models.Model): + title = models.CharField(max_length=128) + + slug = models.SlugField(unique=True, blank=True) + description = models.TextField(null=True, blank=True) + + topic_group = models.ForeignKey(TopicGroup, on_delete=models.CASCADE) + + objects = models.Manager() + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Documentation(models.Model): + title = models.CharField(max_length=128) + + slug = models.SlugField(unique=True, blank=True) + description = models.TextField(null=True, blank=True) + + topic = models.ForeignKey(Topic, on_delete=models.CASCADE) + + objects = models.Manager() + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Document(models.Model): + title = models.CharField(max_length=128) + + etherpad_key = models.CharField(max_length=128, null=True, blank=True) + + documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE) + + objects = models.Manager() + + def save(self, *args, **kwargs): + try: + self.etherpad_key = createPadifNotExists( + self.documentation.topic.slug + + "-" + + self.documentation.slug + + "-" + + slugify(self.title) + ) + except URLError as error: + logger.info( + "Can't create a Etherpad '%s' from the slug. Error: %s", + slugify(self.title), + error, + ) + self.etherpad_key = None + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Protocol(Document): + event_start = models.DateTimeField(null=True, blank=True) + event_end = models.DateTimeField(null=True, blank=True) diff --git a/fet2020/intern/tests.py b/fet2020/intern/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/fet2020/intern/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/fet2020/intern/urls.py b/fet2020/intern/urls.py new file mode 100644 index 00000000..453b14a6 --- /dev/null +++ b/fet2020/intern/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from . import views + + +urlpatterns = [ + path("", views.index, name="intern"), + path("", views.show_topic, name="topic"), + path("/", views.show_docu, name="docu"), +] diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py new file mode 100644 index 00000000..298d3f9e --- /dev/null +++ b/fet2020/intern/views.py @@ -0,0 +1,85 @@ +import logging + +from django.http import HttpResponseRedirect +from django.shortcuts import render +from documents.api import get_pad_link +from collections import deque + +from .forms import DocumentForm +from .models import TopicGroup, Topic, Documentation, Document + +logger = logging.getLogger(__name__) + + +def index(request): + + topic_group = deque(TopicGroup.objects.all()) + topic = Topic.objects.all() + + context = { + "topic_group": topic_group, + "topic": topic, + } + + return render(request, "intern/index.html", context) + + +def show_topic(request, slug=None): + + topic_group = deque(TopicGroup.objects.all()) + topic = deque(Topic.objects.all()) + active_topic = Topic.objects.filter(slug=slug).first() + docu = deque(Documentation.objects.filter(topic__slug=slug)) + + context = { + "topic_group": topic_group, + "topic": topic, + "active_topic": active_topic, + "docus": docu, + } + + return render(request, "intern/topic.html", context) + + +def show_docu(request, slug=None, foo=None): + + active_docu = Documentation.objects.filter(slug=foo).first() + active_topic = Topic.objects.filter(slug=slug).first() + + if request.method == "POST": + if "btn_input" in request.POST: + form = DocumentForm(request.POST) + + if form.is_valid(): + docu = form.save(commit=False) + docu.created_by = request.user + docu.documentation = active_docu + docu.save() + + return HttpResponseRedirect(request.path) + + form = DocumentForm() + docus = deque(Document.objects.filter(documentation=active_docu)) + documents = deque([]) + + for elem in docus: + try: + documents.append( + { + "title": elem.title, + "etherpad_key": get_pad_link(elem.etherpad_key), + } + ) + except Exception as e: + logger.error( + "Can't get the agenda link from '%s'. Error: %s", elem.etherpad_key, e + ) + + context = { + "formset": form, + "active_topic": active_topic, + "active_docu": active_docu, + "documents": documents, + } + + return render(request, "intern/docu.html", context) diff --git a/fet2020/static/intern.css b/fet2020/static/intern.css new file mode 100644 index 00000000..fa206b30 --- /dev/null +++ b/fet2020/static/intern.css @@ -0,0 +1,75 @@ +.intern-topic { + border-radius: 5px; + margin-top: 1rem !important; + margin-bottom: 1rem !important; + height: 100px; } + @media print, screen and (min-width: 40em) { + .intern-topic { + height: 15vh; } } + @media print, screen and (min-width: 64em) { + .intern-topic { + height: 15vh; } } + +.intern-topic, .intern-topic-large { + background-color: #444; + position: relative; + background-size: cover; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + vertical-align: middle; + text-align: left; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; } + .intern-topic .intern-topic-text, .intern-topic-large .intern-topic-text { + color: #fefefe; + text-shadow: 1px 1px 2px #0a0a0a; } + + +.internheader { + border-radius: 5px; + margin-top: 1rem !important; + margin-bottom: 1rem !important; + height: 30px; } + @media print, screen and (min-width: 40em) { + .internheader { + height: 5vh; } } + @media print, screen and (min-width: 64em) { + .internheader { + height: 5vh; } } + +.internheader, .internheader-large { + background-color: grey; + position: relative; + background-size: cover; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + vertical-align: middle; + text-align: left; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; } + .internheader, .internheader-large { + color: #fefefe; + text-shadow: 1px 1px 2px #0a0a0a; } + + +.intern-hero { + background-color: white; +} diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html new file mode 100644 index 00000000..41196da4 --- /dev/null +++ b/fet2020/templates/intern/docu.html @@ -0,0 +1,75 @@ +{% extends "layout.html" %} + +{% block content %} +
+ + + +
+ + {{ active_docu.description|safe }} + +
+ +
+ +
+

Neues Protokoll hinzufügen

+ +
+ {% csrf_token %} + +
+ + {{ formset.management_form }} + + {% for form in formset %} +
+ {{ form.label }} + {{ form }} +
+ {% endfor %} + +
+ +
+ +
+ +
+ +
+ +
+ +{% endblock %} diff --git a/fet2020/templates/intern/index.html b/fet2020/templates/intern/index.html new file mode 100644 index 00000000..66908ce2 --- /dev/null +++ b/fet2020/templates/intern/index.html @@ -0,0 +1,29 @@ +{% extends "layout.html" %} + +{% block content %} +
+ + {% regroup topic by topic_group as topic_list %} + + {% for topic in topic_list %} +
+ {{ topic.grouper.title }} +
+ +
+ {% for tp in topic.list %} + + {% endfor %} +
+ {% endfor %} + +
+{% endblock %} diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html new file mode 100644 index 00000000..31738a0d --- /dev/null +++ b/fet2020/templates/intern/topic.html @@ -0,0 +1,49 @@ +{% extends "layout.html" %} + +{% block content %} +
+ + + +
+ + {{ active_topic.description|safe }} + + +
+ {% for docu in docus %} + + {% endfor %} +
+ +
+ +
+ +{% endblock %} diff --git a/fet2020/templates/layout.html b/fet2020/templates/layout.html index 26961578..a5477cbd 100644 --- a/fet2020/templates/layout.html +++ b/fet2020/templates/layout.html @@ -9,6 +9,7 @@ FET + {% block extraheader %} {% endblock %} @@ -62,7 +63,8 @@ footer {
  • Admin
  • Tasks
  • -
  • Intern
  • +
  • Intern
  • +
  • Legacy Intern
  • {% endif %}
  • Aktuelles
  • From cacfc83ff1356b965bf7f3da2ad9cbc02857f2b5 Mon Sep 17 00:00:00 2001 From: patrick Date: Sat, 15 May 2021 19:39:05 +0000 Subject: [PATCH 02/36] fix merge --- fet2020/templates/layout.html | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/fet2020/templates/layout.html b/fet2020/templates/layout.html index 2b47507c..d62dbbaa 100644 --- a/fet2020/templates/layout.html +++ b/fet2020/templates/layout.html @@ -55,16 +55,10 @@ {% endif %} -<<<<<<< HEAD -
  • Admin
  • -
  • Tasks
  • -
  • Intern
  • -
  • Legacy Intern
  • -=======
  • Admin
  • Tasks
  • -
  • Intern
  • ->>>>>>> origin/master +
  • Intern
  • +
  • Legacy Intern
  • {% endif %}
  • News
  • From 75bd5619d9fd5535692f353fcd978767f756579b Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 23 May 2021 13:02:39 +0000 Subject: [PATCH 03/36] update template, wordings; add ep cookie --- fet2020/intern/admin.py | 39 ++++++++++---- fet2020/intern/forms.py | 30 +++++++++-- fet2020/intern/models.py | 84 ++++++++++++++++++----------- fet2020/intern/urls.py | 2 +- fet2020/intern/views.py | 63 ++++++++++++---------- fet2020/templates/intern/docu.html | 81 ++++++++++++++++------------ fet2020/templates/intern/topic.html | 38 +++++++------ 7 files changed, 210 insertions(+), 127 deletions(-) diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py index fe2b8dec..b856dea9 100644 --- a/fet2020/intern/admin.py +++ b/fet2020/intern/admin.py @@ -1,11 +1,12 @@ from django.contrib import admin -from .models import TopicGroup, Topic, Documentation -from .forms import TopicGroupAdminForm, TopicAdminForm +from .models import TopicGroup, Topic, Documentation, Document +from .forms import TopicGroupAdminForm, TopicAdminForm, DocumentationAdminForm, DocumentAdminForm class DocumentationInline(admin.TabularInline): model = Documentation + form = DocumentationAdminForm extra = 0 verbose_name = "Dokument" verbose_name_plural = "Dokument-Übersicht" @@ -13,17 +14,21 @@ class DocumentationInline(admin.TabularInline): class TopicInline(admin.TabularInline): model = Topic + form = TopicAdminForm extra = 0 - verbose_name = "Topic" - verbose_name_plural = "Topic-Übersicht" + verbose_name = "Thema" + verbose_name_plural = "Themen" + show_change_link = True class TopicGroupAdmin(admin.ModelAdmin): form = TopicGroupAdminForm model = TopicGroup - search_fields = ("title",) + search_fields = ("title", ) inlines = (TopicInline,) + list_display = ["title", "order",] + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) @@ -35,23 +40,39 @@ class TopicAdmin(admin.ModelAdmin): search_fields = ("title",) inlines = (DocumentationInline,) + list_filter = ["archive",] + list_display = ["title", "topic_group", "archive",] + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) -""" class DocumentationAdmin(admin.ModelAdmin): form = DocumentationAdminForm model = Documentation - list_display = ["title", "topic"] + list_display = ["title", "topic",] def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) -""" + + +class DocumentAdmin(admin.ModelAdmin): + form = DocumentAdminForm + model = Document + + list_filter = ["documentation",] + list_display = ["title", "date", "documentation",] + ordering = ["-date"] + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) + admin.site.register(TopicGroup, TopicGroupAdmin) admin.site.register(Topic, TopicAdmin) -# admin.site.register(Documentation, DocumentationAdmin) +#admin.site.register(Documentation, DocumentationAdmin) +admin.site.register(Document, DocumentAdmin) diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index f2863d49..e9761345 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -1,11 +1,14 @@ +from ckeditor_uploader.widgets import CKEditorUploadingWidget from django import forms from django.utils.translation import gettext_lazy as _ -from ckeditor_uploader.widgets import CKEditorUploadingWidget - from .models import TopicGroup, Topic, Documentation, Document +class DateInput(forms.DateInput): + input_type = "date" + + class TopicGroupAdminForm(forms.ModelForm): class Meta: model = TopicGroup @@ -19,6 +22,7 @@ class TopicAdminForm(forms.ModelForm): model = Topic fields = [ "title", + "archive", "description", "topic_group", ] @@ -31,10 +35,22 @@ class DocumentationAdminForm(forms.ModelForm): model = Documentation fields = [ "title", + "placeholder", "description", "topic", ] + widgets = {"description": CKEditorUploadingWidget(config_name="default")} + + +class DocumentAdminForm(forms.ModelForm): + class Meta: + model = Document + fields = [ + "title", + "documentation", + ] + class DocumentForm(forms.ModelForm): class Meta: @@ -42,8 +58,16 @@ class DocumentForm(forms.ModelForm): fields = [ "title", + "date", ] labels = { - "title": _("Titel des Protokolls"), + "title": _("Titel"), + "date": _("Datum"), + } + + widgets = { + "date": DateInput( + format=("%d-%m-%Y"), + ) } diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index 8715e6f4..2f2a8955 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -1,19 +1,30 @@ import logging + +from datetime import date +from django.core.validators import ValidationError from django.db import models +from django.db.models.constraints import UniqueConstraint +from django.utils import timezone from django.utils.text import slugify +from django.utils.translation import gettext_lazy as _ + from documents import createPadifNotExists -from urllib.request import URLError logger = logging.getLogger(__name__) class TopicGroup(models.Model): - title = models.CharField(max_length=128) - + title = models.CharField(verbose_name="Titel", max_length=128) slug = models.SlugField(unique=True, blank=True) + order = models.PositiveSmallIntegerField(verbose_name="Reihenfolge", unique=True, null=True, blank=True) + objects = models.Manager() + class Meta: + verbose_name = "Themenbereich" + verbose_name_plural = "Themenbereiche" + def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) @@ -25,15 +36,21 @@ class TopicGroup(models.Model): class Topic(models.Model): - title = models.CharField(max_length=128) - + title = models.CharField(verbose_name="Titel", max_length=128) slug = models.SlugField(unique=True, blank=True) + + archive = models.BooleanField(verbose_name="Archiv", default=False) + description = models.TextField(null=True, blank=True) - topic_group = models.ForeignKey(TopicGroup, on_delete=models.CASCADE) + topic_group = models.ForeignKey(TopicGroup, on_delete=models.CASCADE, verbose_name="Themenbereich") objects = models.Manager() + class Meta: + verbose_name = "Thema" + verbose_name_plural = "Themen" + def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) @@ -45,9 +62,10 @@ class Topic(models.Model): class Documentation(models.Model): - title = models.CharField(max_length=128) + title = models.CharField(verbose_name="Titel", max_length=128) + slug = models.SlugField(blank=True) + placeholder = models.CharField(verbose_name="Platzhalter", max_length=128, default="Titel") - slug = models.SlugField(unique=True, blank=True) description = models.TextField(null=True, blank=True) topic = models.ForeignKey(Topic, on_delete=models.CASCADE) @@ -61,41 +79,45 @@ class Documentation(models.Model): super().save(*args, **kwargs) def __str__(self): - return self.title + return self.topic.title + " / " + self.title class Document(models.Model): - title = models.CharField(max_length=128) - + title = models.CharField(verbose_name="Titel", max_length=128) etherpad_key = models.CharField(max_length=128, null=True, blank=True) + date = models.DateField(verbose_name="Datum", default=date.today) documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE) objects = models.Manager() + class Meta: + verbose_name = "Dokument" + verbose_name_plural = "Dokumente" + + constraints = [ + UniqueConstraint(fields=['title', 'date'], name='unique_title_and_date'), + ] + + ''' + pre save signal + def clean(self): + pad_name = slugify(self.date + "-" + self.documentation.topic.slug + "-" + self.documentation.slug + "-" + slugify(self.title) + + if len(pad_name) > 50: + print(pad_name) + raise ValidationError( + _('Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: %(length)s) (Name: %(pad_name)s)'), + params={'length': len(pad_name), 'pad_name': pad_name}, + ) + ''' + def save(self, *args, **kwargs): - try: - self.etherpad_key = createPadifNotExists( - self.documentation.topic.slug - + "-" - + self.documentation.slug - + "-" - + slugify(self.title) - ) - except URLError as error: - logger.info( - "Can't create a Etherpad '%s' from the slug. Error: %s", - slugify(self.title), - error, - ) - self.etherpad_key = None + self.etherpad_key = createPadifNotExists( + slugify(self.date) + "-" + self.documentation.topic.slug + "-" + self.documentation.slug + "-" + slugify(self.title) + ) super().save(*args, **kwargs) def __str__(self): return self.title - - -class Protocol(Document): - event_start = models.DateTimeField(null=True, blank=True) - event_end = models.DateTimeField(null=True, blank=True) diff --git a/fet2020/intern/urls.py b/fet2020/intern/urls.py index 453b14a6..ff7d36f0 100644 --- a/fet2020/intern/urls.py +++ b/fet2020/intern/urls.py @@ -6,5 +6,5 @@ from . import views urlpatterns = [ path("", views.index, name="intern"), path("", views.show_topic, name="topic"), - path("/", views.show_docu, name="docu"), + path("/", views.show_docu, name="docu"), ] diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index 298d3f9e..b2c69cd8 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -1,8 +1,11 @@ import logging +from django.contrib import messages +from django.db.models import F, Q from django.http import HttpResponseRedirect from django.shortcuts import render from documents.api import get_pad_link +from documents.etherpadlib import add_ep_cookie from collections import deque from .forms import DocumentForm @@ -12,12 +15,9 @@ logger = logging.getLogger(__name__) def index(request): - - topic_group = deque(TopicGroup.objects.all()) - topic = Topic.objects.all() + topic = deque(Topic.objects.filter(archive=False).order_by(F('topic_group__order').asc(nulls_last=True), 'topic_group', 'title')) context = { - "topic_group": topic_group, "topic": topic, } @@ -25,15 +25,10 @@ def index(request): def show_topic(request, slug=None): - - topic_group = deque(TopicGroup.objects.all()) - topic = deque(Topic.objects.all()) active_topic = Topic.objects.filter(slug=slug).first() - docu = deque(Documentation.objects.filter(topic__slug=slug)) + docu = deque(Documentation.objects.filter(topic__slug=slug).order_by('title')) context = { - "topic_group": topic_group, - "topic": topic, "active_topic": active_topic, "docus": docu, } @@ -41,10 +36,9 @@ def show_topic(request, slug=None): return render(request, "intern/topic.html", context) -def show_docu(request, slug=None, foo=None): - - active_docu = Documentation.objects.filter(slug=foo).first() - active_topic = Topic.objects.filter(slug=slug).first() +def show_docu(request, topic_slug=None, slug=None): + active_docu = Documentation.objects.filter(Q(topic__slug=topic_slug) & Q(slug=slug)).first() + active_topic = Topic.objects.filter(slug=topic_slug).first() if request.method == "POST": if "btn_input" in request.POST: @@ -58,22 +52,28 @@ def show_docu(request, slug=None, foo=None): return HttpResponseRedirect(request.path) - form = DocumentForm() - docus = deque(Document.objects.filter(documentation=active_docu)) + else: + for elem in list(form.errors.values()): + messages.info(request, '; '.join(elem)) + + initial = { + "title": active_docu.placeholder, + } + + form = DocumentForm(initial=initial) + + docus = deque(Document.objects.filter(documentation=active_docu).order_by('-date')) documents = deque([]) + # list of etherpad url-link of any documents for elem in docus: - try: - documents.append( - { - "title": elem.title, - "etherpad_key": get_pad_link(elem.etherpad_key), - } - ) - except Exception as e: - logger.error( - "Can't get the agenda link from '%s'. Error: %s", elem.etherpad_key, e - ) + documents.append( + { + "title": elem.title, + "date": elem.date, + "etherpad_key": get_pad_link(elem.etherpad_key), + } + ) context = { "formset": form, @@ -82,4 +82,11 @@ def show_docu(request, slug=None, foo=None): "documents": documents, } - return render(request, "intern/docu.html", context) + response = render(request, "intern/docu.html", context) + + try: + response = add_ep_cookie(request, response) + except Exception as e: + logger.info("Etherpad Server doesn't work. Error: %s", e) + + return response diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html index 41196da4..58f28ed3 100644 --- a/fet2020/templates/intern/docu.html +++ b/fet2020/templates/intern/docu.html @@ -2,9 +2,7 @@ {% block content %}
    -
    + {% if active_docu.description %} +
    + {{ active_docu.description|safe }} +
    - {{ active_docu.description|safe }} +
    + {% endif %} + +
    + {% csrf_token %} + +
    + + {{ formset.management_form }} + + {% for form in formset %} +
    + {{ form }} +
    + {% endfor %} + + {{ formset.non_field_errors }} + +
    + +
    +
    +
    + + {% for message in messages %} +

    {{message}}

    + {% endfor %} + +
    - -
    - -
    -

    Neues Protokoll hinzufügen

    - -
    - {% csrf_token %} - -
    - - {{ formset.management_form }} - - {% for form in formset %} -
    - {{ form.label }} - {{ form }} +
    + {% for document in documents %} + +
    +
    +

    {{ document.title }}

    +
    +
    +

    {{ document.date }}

    +
    +
    +
    + {% endfor %}
    - {% endfor %} - -
    - -
    -
    - - -
    -
    {% endblock %} diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html index 31738a0d..4553a16a 100644 --- a/fet2020/templates/intern/topic.html +++ b/fet2020/templates/intern/topic.html @@ -2,9 +2,7 @@ {% block content %}
    -
    - - {{ active_topic.description|safe }} - - -
    - {% for docu in docus %} -
    - -
    -
    - {{ docu.title }} -
    -
    -
    + {% if active_topic.description %} +
    + {{ active_topic.description|safe }}
    - {% endfor %} -
    +
    + {% endif %} +
    + {% for docu in docus %} + + {% endfor %} +
    -
    {% endblock %} From 414f6d1b72f5cccd8dab51d1283c70eeb23a51e4 Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 28 Feb 2021 00:29:26 +0000 Subject: [PATCH 04/36] intern implementation --- fet2020/fet2020/settings.py | 1 + fet2020/fet2020/urls.py | 1 + fet2020/intern/__init__.py | 0 fet2020/intern/admin.py | 57 ++++++++++++++++ fet2020/intern/apps.py | 5 ++ fet2020/intern/forms.py | 49 ++++++++++++++ fet2020/intern/models.py | 101 ++++++++++++++++++++++++++++ fet2020/intern/tests.py | 3 + fet2020/intern/urls.py | 10 +++ fet2020/intern/views.py | 85 +++++++++++++++++++++++ fet2020/static/intern.css | 75 +++++++++++++++++++++ fet2020/templates/intern/docu.html | 75 +++++++++++++++++++++ fet2020/templates/intern/index.html | 29 ++++++++ fet2020/templates/intern/topic.html | 49 ++++++++++++++ fet2020/templates/layout.html | 4 +- 15 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 fet2020/intern/__init__.py create mode 100644 fet2020/intern/admin.py create mode 100644 fet2020/intern/apps.py create mode 100644 fet2020/intern/forms.py create mode 100644 fet2020/intern/models.py create mode 100644 fet2020/intern/tests.py create mode 100644 fet2020/intern/urls.py create mode 100644 fet2020/intern/views.py create mode 100644 fet2020/static/intern.css create mode 100644 fet2020/templates/intern/docu.html create mode 100644 fet2020/templates/intern/index.html create mode 100644 fet2020/templates/intern/topic.html diff --git a/fet2020/fet2020/settings.py b/fet2020/fet2020/settings.py index cb6a6ca1..591e2594 100644 --- a/fet2020/fet2020/settings.py +++ b/fet2020/fet2020/settings.py @@ -86,6 +86,7 @@ INSTALLED_APPS = [ "documents.apps.DocumentsConfig", "blackboard.apps.BlackboardConfig", "tasks.apps.TasksConfig", + "intern.apps.InternConfig", ] MIDDLEWARE = [ diff --git a/fet2020/fet2020/urls.py b/fet2020/fet2020/urls.py index 6278ffad..9b118f0a 100644 --- a/fet2020/fet2020/urls.py +++ b/fet2020/fet2020/urls.py @@ -41,6 +41,7 @@ urlpatterns = [ path("member/", include(member_urlpatterns), name="member"), path("posts/", include("posts.urls")), path("tasks/", include("tasks.urls"), name="tasks"), + path("intern/", include("intern.urls"), name="intern"), path( "sitemap.xml", sitemap, diff --git a/fet2020/intern/__init__.py b/fet2020/intern/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py new file mode 100644 index 00000000..fe2b8dec --- /dev/null +++ b/fet2020/intern/admin.py @@ -0,0 +1,57 @@ +from django.contrib import admin + +from .models import TopicGroup, Topic, Documentation +from .forms import TopicGroupAdminForm, TopicAdminForm + + +class DocumentationInline(admin.TabularInline): + model = Documentation + extra = 0 + verbose_name = "Dokument" + verbose_name_plural = "Dokument-Übersicht" + + +class TopicInline(admin.TabularInline): + model = Topic + extra = 0 + verbose_name = "Topic" + verbose_name_plural = "Topic-Übersicht" + + +class TopicGroupAdmin(admin.ModelAdmin): + form = TopicGroupAdminForm + model = TopicGroup + search_fields = ("title",) + inlines = (TopicInline,) + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) + + +class TopicAdmin(admin.ModelAdmin): + form = TopicAdminForm + model = Topic + search_fields = ("title",) + inlines = (DocumentationInline,) + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) + + +""" +class DocumentationAdmin(admin.ModelAdmin): + form = DocumentationAdminForm + model = Documentation + + list_display = ["title", "topic"] + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) +""" + +admin.site.register(TopicGroup, TopicGroupAdmin) +admin.site.register(Topic, TopicAdmin) +# admin.site.register(Documentation, DocumentationAdmin) diff --git a/fet2020/intern/apps.py b/fet2020/intern/apps.py new file mode 100644 index 00000000..b2d0203a --- /dev/null +++ b/fet2020/intern/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class InternConfig(AppConfig): + name = "intern" diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py new file mode 100644 index 00000000..f2863d49 --- /dev/null +++ b/fet2020/intern/forms.py @@ -0,0 +1,49 @@ +from django import forms +from django.utils.translation import gettext_lazy as _ + +from ckeditor_uploader.widgets import CKEditorUploadingWidget + +from .models import TopicGroup, Topic, Documentation, Document + + +class TopicGroupAdminForm(forms.ModelForm): + class Meta: + model = TopicGroup + fields = [ + "title", + ] + + +class TopicAdminForm(forms.ModelForm): + class Meta: + model = Topic + fields = [ + "title", + "description", + "topic_group", + ] + + widgets = {"description": CKEditorUploadingWidget(config_name="default")} + + +class DocumentationAdminForm(forms.ModelForm): + class Meta: + model = Documentation + fields = [ + "title", + "description", + "topic", + ] + + +class DocumentForm(forms.ModelForm): + class Meta: + model = Document + + fields = [ + "title", + ] + + labels = { + "title": _("Titel des Protokolls"), + } diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py new file mode 100644 index 00000000..8715e6f4 --- /dev/null +++ b/fet2020/intern/models.py @@ -0,0 +1,101 @@ +import logging +from django.db import models +from django.utils.text import slugify +from documents import createPadifNotExists +from urllib.request import URLError + +logger = logging.getLogger(__name__) + + +class TopicGroup(models.Model): + title = models.CharField(max_length=128) + + slug = models.SlugField(unique=True, blank=True) + + objects = models.Manager() + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Topic(models.Model): + title = models.CharField(max_length=128) + + slug = models.SlugField(unique=True, blank=True) + description = models.TextField(null=True, blank=True) + + topic_group = models.ForeignKey(TopicGroup, on_delete=models.CASCADE) + + objects = models.Manager() + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Documentation(models.Model): + title = models.CharField(max_length=128) + + slug = models.SlugField(unique=True, blank=True) + description = models.TextField(null=True, blank=True) + + topic = models.ForeignKey(Topic, on_delete=models.CASCADE) + + objects = models.Manager() + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Document(models.Model): + title = models.CharField(max_length=128) + + etherpad_key = models.CharField(max_length=128, null=True, blank=True) + + documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE) + + objects = models.Manager() + + def save(self, *args, **kwargs): + try: + self.etherpad_key = createPadifNotExists( + self.documentation.topic.slug + + "-" + + self.documentation.slug + + "-" + + slugify(self.title) + ) + except URLError as error: + logger.info( + "Can't create a Etherpad '%s' from the slug. Error: %s", + slugify(self.title), + error, + ) + self.etherpad_key = None + + super().save(*args, **kwargs) + + def __str__(self): + return self.title + + +class Protocol(Document): + event_start = models.DateTimeField(null=True, blank=True) + event_end = models.DateTimeField(null=True, blank=True) diff --git a/fet2020/intern/tests.py b/fet2020/intern/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/fet2020/intern/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/fet2020/intern/urls.py b/fet2020/intern/urls.py new file mode 100644 index 00000000..453b14a6 --- /dev/null +++ b/fet2020/intern/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from . import views + + +urlpatterns = [ + path("", views.index, name="intern"), + path("", views.show_topic, name="topic"), + path("/", views.show_docu, name="docu"), +] diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py new file mode 100644 index 00000000..298d3f9e --- /dev/null +++ b/fet2020/intern/views.py @@ -0,0 +1,85 @@ +import logging + +from django.http import HttpResponseRedirect +from django.shortcuts import render +from documents.api import get_pad_link +from collections import deque + +from .forms import DocumentForm +from .models import TopicGroup, Topic, Documentation, Document + +logger = logging.getLogger(__name__) + + +def index(request): + + topic_group = deque(TopicGroup.objects.all()) + topic = Topic.objects.all() + + context = { + "topic_group": topic_group, + "topic": topic, + } + + return render(request, "intern/index.html", context) + + +def show_topic(request, slug=None): + + topic_group = deque(TopicGroup.objects.all()) + topic = deque(Topic.objects.all()) + active_topic = Topic.objects.filter(slug=slug).first() + docu = deque(Documentation.objects.filter(topic__slug=slug)) + + context = { + "topic_group": topic_group, + "topic": topic, + "active_topic": active_topic, + "docus": docu, + } + + return render(request, "intern/topic.html", context) + + +def show_docu(request, slug=None, foo=None): + + active_docu = Documentation.objects.filter(slug=foo).first() + active_topic = Topic.objects.filter(slug=slug).first() + + if request.method == "POST": + if "btn_input" in request.POST: + form = DocumentForm(request.POST) + + if form.is_valid(): + docu = form.save(commit=False) + docu.created_by = request.user + docu.documentation = active_docu + docu.save() + + return HttpResponseRedirect(request.path) + + form = DocumentForm() + docus = deque(Document.objects.filter(documentation=active_docu)) + documents = deque([]) + + for elem in docus: + try: + documents.append( + { + "title": elem.title, + "etherpad_key": get_pad_link(elem.etherpad_key), + } + ) + except Exception as e: + logger.error( + "Can't get the agenda link from '%s'. Error: %s", elem.etherpad_key, e + ) + + context = { + "formset": form, + "active_topic": active_topic, + "active_docu": active_docu, + "documents": documents, + } + + return render(request, "intern/docu.html", context) diff --git a/fet2020/static/intern.css b/fet2020/static/intern.css new file mode 100644 index 00000000..fa206b30 --- /dev/null +++ b/fet2020/static/intern.css @@ -0,0 +1,75 @@ +.intern-topic { + border-radius: 5px; + margin-top: 1rem !important; + margin-bottom: 1rem !important; + height: 100px; } + @media print, screen and (min-width: 40em) { + .intern-topic { + height: 15vh; } } + @media print, screen and (min-width: 64em) { + .intern-topic { + height: 15vh; } } + +.intern-topic, .intern-topic-large { + background-color: #444; + position: relative; + background-size: cover; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + vertical-align: middle; + text-align: left; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; } + .intern-topic .intern-topic-text, .intern-topic-large .intern-topic-text { + color: #fefefe; + text-shadow: 1px 1px 2px #0a0a0a; } + + +.internheader { + border-radius: 5px; + margin-top: 1rem !important; + margin-bottom: 1rem !important; + height: 30px; } + @media print, screen and (min-width: 40em) { + .internheader { + height: 5vh; } } + @media print, screen and (min-width: 64em) { + .internheader { + height: 5vh; } } + +.internheader, .internheader-large { + background-color: grey; + position: relative; + background-size: cover; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + vertical-align: middle; + text-align: left; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; } + .internheader, .internheader-large { + color: #fefefe; + text-shadow: 1px 1px 2px #0a0a0a; } + + +.intern-hero { + background-color: white; +} diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html new file mode 100644 index 00000000..41196da4 --- /dev/null +++ b/fet2020/templates/intern/docu.html @@ -0,0 +1,75 @@ +{% extends "layout.html" %} + +{% block content %} +
    + + + +
    + + {{ active_docu.description|safe }} + +
    + +
    + +
    +

    Neues Protokoll hinzufügen

    + +
    + {% csrf_token %} + +
    + + {{ formset.management_form }} + + {% for form in formset %} +
    + {{ form.label }} + {{ form }} +
    + {% endfor %} + +
    + +
    + +
    + +
    + +
    + +
    + +{% endblock %} diff --git a/fet2020/templates/intern/index.html b/fet2020/templates/intern/index.html new file mode 100644 index 00000000..66908ce2 --- /dev/null +++ b/fet2020/templates/intern/index.html @@ -0,0 +1,29 @@ +{% extends "layout.html" %} + +{% block content %} +
    + + {% regroup topic by topic_group as topic_list %} + + {% for topic in topic_list %} +
    + {{ topic.grouper.title }} +
    + +
    + {% for tp in topic.list %} + + {% endfor %} +
    + {% endfor %} + +
    +{% endblock %} diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html new file mode 100644 index 00000000..31738a0d --- /dev/null +++ b/fet2020/templates/intern/topic.html @@ -0,0 +1,49 @@ +{% extends "layout.html" %} + +{% block content %} +
    + + + +
    + + {{ active_topic.description|safe }} + + +
    + {% for docu in docus %} + + {% endfor %} +
    + +
    + +
    + +{% endblock %} diff --git a/fet2020/templates/layout.html b/fet2020/templates/layout.html index cd700109..a914243a 100644 --- a/fet2020/templates/layout.html +++ b/fet2020/templates/layout.html @@ -11,6 +11,7 @@ + {% block extraheader %} {% endblock %} @@ -53,7 +54,8 @@
  • Admin
  • Tasks
  • -
  • Intern
  • +
  • Intern
  • +
  • Legacy Intern
  • {% endif %}
  • News
  • From 6687210b196859668e4bf8ab3485ef998e0839d3 Mon Sep 17 00:00:00 2001 From: patrick Date: Sat, 12 Jun 2021 12:52:17 +0000 Subject: [PATCH 05/36] fix merge --- fet2020/fet2020/urls.py | 1 - 1 file changed, 1 deletion(-) diff --git a/fet2020/fet2020/urls.py b/fet2020/fet2020/urls.py index 02facb86..9b118f0a 100644 --- a/fet2020/fet2020/urls.py +++ b/fet2020/fet2020/urls.py @@ -42,7 +42,6 @@ urlpatterns = [ path("posts/", include("posts.urls")), path("tasks/", include("tasks.urls"), name="tasks"), path("intern/", include("intern.urls"), name="intern"), - path('pages/', include('django.contrib.flatpages.urls')), path( "sitemap.xml", sitemap, From d172fe76cf9ec6e3d0587a23e01edacf36475615 Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 13 Jun 2021 21:14:36 +0000 Subject: [PATCH 06/36] update url --- fet2020/intern/urls.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fet2020/intern/urls.py b/fet2020/intern/urls.py index ff7d36f0..538bdb6a 100644 --- a/fet2020/intern/urls.py +++ b/fet2020/intern/urls.py @@ -5,6 +5,6 @@ from . import views urlpatterns = [ path("", views.index, name="intern"), - path("", views.show_topic, name="topic"), - path("/", views.show_docu, name="docu"), + path("/", views.show_topic, name="topic"), + path("//", views.show_docu, name="docu"), ] From c65deb644f305070bf81abb7c0fee8485fede73e Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 13 Jun 2021 21:15:33 +0000 Subject: [PATCH 07/36] add fields --- fet2020/intern/forms.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index e9761345..bf6b34e1 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -14,6 +14,7 @@ class TopicGroupAdminForm(forms.ModelForm): model = TopicGroup fields = [ "title", + "slug", ] @@ -22,6 +23,7 @@ class TopicAdminForm(forms.ModelForm): model = Topic fields = [ "title", + "slug", "archive", "description", "topic_group", @@ -35,6 +37,7 @@ class DocumentationAdminForm(forms.ModelForm): model = Documentation fields = [ "title", + "slug", "placeholder", "description", "topic", @@ -59,6 +62,7 @@ class DocumentForm(forms.ModelForm): fields = [ "title", "date", + "documentation", ] labels = { @@ -67,7 +71,5 @@ class DocumentForm(forms.ModelForm): } widgets = { - "date": DateInput( - format=("%d-%m-%Y"), - ) + "date": DateInput(format=("%d-%m-%Y")), } From 0ba27ed6bb497ff7d369d8f9515a0101b4989bf0 Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 13 Jun 2021 21:17:16 +0000 Subject: [PATCH 08/36] add archive view, get_absolute_url method and fileupload --- fet2020/intern/admin.py | 20 +++++++--- fet2020/intern/models.py | 60 +++++++++++++++++++---------- fet2020/intern/views.py | 5 ++- fet2020/templates/intern/index.html | 22 ++++++++++- 4 files changed, 79 insertions(+), 28 deletions(-) diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py index b856dea9..41a2644e 100644 --- a/fet2020/intern/admin.py +++ b/fet2020/intern/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin +from django.db.models import F -from .models import TopicGroup, Topic, Documentation, Document +from .models import TopicGroup, Topic, Documentation, Document, FileUpload from .forms import TopicGroupAdminForm, TopicAdminForm, DocumentationAdminForm, DocumentAdminForm @@ -12,6 +13,13 @@ class DocumentationInline(admin.TabularInline): verbose_name_plural = "Dokument-Übersicht" +class FileUploadInline(admin.TabularInline): + model = FileUpload + extra = 0 + verbose_name = "Dokument" + verbose_name_plural = "Do­ku­men­ten­samm­lung" + + class TopicInline(admin.TabularInline): model = Topic form = TopicAdminForm @@ -27,7 +35,8 @@ class TopicGroupAdmin(admin.ModelAdmin): search_fields = ("title", ) inlines = (TopicInline,) - list_display = ["title", "order",] + list_display = ["title", "order"] + ordering = [F("order").asc(nulls_last=True)] def save_model(self, request, obj, form, change): obj.created_by = request.user @@ -38,10 +47,11 @@ class TopicAdmin(admin.ModelAdmin): form = TopicAdminForm model = Topic search_fields = ("title",) - inlines = (DocumentationInline,) + inlines = (DocumentationInline, ) - list_filter = ["archive",] - list_display = ["title", "topic_group", "archive",] + list_filter = ["topic_group", "archive"] + list_display = ["title", "topic_group", "archive"] + ordering = ["archive"] def save_model(self, request, obj, form, change): obj.created_by = request.user diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index 2f2a8955..cb0f2187 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -4,6 +4,7 @@ from datetime import date from django.core.validators import ValidationError from django.db import models from django.db.models.constraints import UniqueConstraint +from django.urls import reverse from django.utils import timezone from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ @@ -15,7 +16,7 @@ logger = logging.getLogger(__name__) class TopicGroup(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) - slug = models.SlugField(unique=True, blank=True) + slug = models.SlugField(max_length=10, unique=True) order = models.PositiveSmallIntegerField(verbose_name="Reihenfolge", unique=True, null=True, blank=True) @@ -25,19 +26,22 @@ class TopicGroup(models.Model): verbose_name = "Themenbereich" verbose_name_plural = "Themenbereiche" + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse("intern") + "#" + self.slug + def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) super().save(*args, **kwargs) - def __str__(self): - return self.title - class Topic(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) - slug = models.SlugField(unique=True, blank=True) + slug = models.SlugField(max_length=10, unique=True) archive = models.BooleanField(verbose_name="Archiv", default=False) @@ -51,19 +55,22 @@ class Topic(models.Model): verbose_name = "Thema" verbose_name_plural = "Themen" + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse("topic", kwargs={"slug": self.slug}) + def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) super().save(*args, **kwargs) - def __str__(self): - return self.title - class Documentation(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) - slug = models.SlugField(blank=True) + slug = models.SlugField(max_length=10) placeholder = models.CharField(verbose_name="Platzhalter", max_length=128, default="Titel") description = models.TextField(null=True, blank=True) @@ -72,19 +79,22 @@ class Documentation(models.Model): objects = models.Manager() + def __str__(self): + return self.topic.title + " / " + self.title + + def get_absolute_url(self): + return reverse("docu", kwargs={"topic_slug": self.topic.slug, "slug": self.slug}) + def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) super().save(*args, **kwargs) - def __str__(self): - return self.topic.title + " / " + self.title - class Document(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) - etherpad_key = models.CharField(max_length=128, null=True, blank=True) + etherpad_key = models.CharField(max_length=50, blank=True) date = models.DateField(verbose_name="Datum", default=date.today) documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE) @@ -96,21 +106,17 @@ class Document(models.Model): verbose_name_plural = "Dokumente" constraints = [ - UniqueConstraint(fields=['title', 'date'], name='unique_title_and_date'), + UniqueConstraint(fields=['title', 'date', 'documentation'], name='unique_document'), ] - ''' - pre save signal def clean(self): - pad_name = slugify(self.date + "-" + self.documentation.topic.slug + "-" + self.documentation.slug + "-" + slugify(self.title) + pad_name = slugify(str(self.date) + "-" + self.documentation.topic.slug + "-" + self.documentation.slug + "-" + slugify(self.title)) if len(pad_name) > 50: - print(pad_name) raise ValidationError( - _('Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: %(length)s) (Name: %(pad_name)s)'), + _('Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: %(length)s, Name: %(pad_name)s)'), params={'length': len(pad_name), 'pad_name': pad_name}, - ) - ''' + ) def save(self, *args, **kwargs): self.etherpad_key = createPadifNotExists( @@ -121,3 +127,15 @@ class Document(models.Model): def __str__(self): return self.title + + +class FileUpload(models.Model): + title = models.CharField(verbose_name="Titel", max_length=128) + file_field = models.FileField(verbose_name="Dokument", upload_to="uploads/intern/files/") + + documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE) + + objects = models.Manager() + + def __str__(self): + return self.title diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index b2c69cd8..1b43e7c4 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -16,9 +16,11 @@ logger = logging.getLogger(__name__) def index(request): topic = deque(Topic.objects.filter(archive=False).order_by(F('topic_group__order').asc(nulls_last=True), 'topic_group', 'title')) + archive_topic = deque(Topic.objects.filter(archive=True)) context = { "topic": topic, + "archive_topic": archive_topic, } return render(request, "intern/index.html", context) @@ -47,7 +49,7 @@ def show_docu(request, topic_slug=None, slug=None): if form.is_valid(): docu = form.save(commit=False) docu.created_by = request.user - docu.documentation = active_docu + # docu.documentation = active_docu docu.save() return HttpResponseRedirect(request.path) @@ -58,6 +60,7 @@ def show_docu(request, topic_slug=None, slug=None): initial = { "title": active_docu.placeholder, + "documentation": active_docu, } form = DocumentForm(initial=initial) diff --git a/fet2020/templates/intern/index.html b/fet2020/templates/intern/index.html index 66908ce2..7e77dd1e 100644 --- a/fet2020/templates/intern/index.html +++ b/fet2020/templates/intern/index.html @@ -7,7 +7,7 @@ {% for topic in topic_list %}
    - {{ topic.grouper.title }} +

    {{ topic.grouper.title }} #

    @@ -25,5 +25,25 @@
    {% endfor %} + {% if archive_topic %} +
    +

    Archiv #

    +
    + +
    + {% for tp in archive_topic %} + + {% endfor %} +
    + {% endif %} +
    {% endblock %} From dbf5d84dd6cccf0bb6f6e2225efbfd4369d1e948 Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 16 Jun 2021 09:54:52 +0000 Subject: [PATCH 09/36] add FileUpload to admin and view --- fet2020/intern/admin.py | 25 +++++++++++++++++++++++-- fet2020/intern/forms.py | 14 ++++++++++++-- fet2020/intern/models.py | 1 + fet2020/intern/views.py | 5 ++++- fet2020/templates/intern/docu.html | 20 +++++++++++++++++--- fet2020/templates/intern/topic.html | 6 ++++-- 6 files changed, 61 insertions(+), 10 deletions(-) diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py index 41a2644e..6b48da34 100644 --- a/fet2020/intern/admin.py +++ b/fet2020/intern/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.db.models import F from .models import TopicGroup, Topic, Documentation, Document, FileUpload -from .forms import TopicGroupAdminForm, TopicAdminForm, DocumentationAdminForm, DocumentAdminForm +from .forms import TopicGroupAdminForm, TopicAdminForm, DocumentationAdminForm, DocumentAdminForm, FileUploadAdminForm class DocumentationInline(admin.TabularInline): @@ -20,6 +20,13 @@ class FileUploadInline(admin.TabularInline): verbose_name_plural = "Do­ku­men­ten­samm­lung" +class DocumentInline(admin.TabularInline): + model = Document + extra = 0 + verbose_name = "Dokument" + verbose_name_plural = "Do­ku­men­ten­samm­lung" + + class TopicInline(admin.TabularInline): model = Topic form = TopicAdminForm @@ -61,6 +68,7 @@ class TopicAdmin(admin.ModelAdmin): class DocumentationAdmin(admin.ModelAdmin): form = DocumentationAdminForm model = Documentation + inlines = (DocumentInline, FileUploadInline, ) list_display = ["title", "topic",] @@ -82,7 +90,20 @@ class DocumentAdmin(admin.ModelAdmin): super().save_model(request, obj, form, change) +class FileUploadAdmin(admin.ModelAdmin): + form = FileUploadAdminForm + model = FileUpload + + list_filter = ["documentation",] + list_display = ["title", "documentation",] + + def save_model(self, request, obj, form, change): + obj.created_by = request.user + super().save_model(request, obj, form, change) + + admin.site.register(TopicGroup, TopicGroupAdmin) admin.site.register(Topic, TopicAdmin) -#admin.site.register(Documentation, DocumentationAdmin) +admin.site.register(Documentation, DocumentationAdmin) admin.site.register(Document, DocumentAdmin) +admin.site.register(FileUpload, FileUploadAdmin) diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index bf6b34e1..fc50f163 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -2,7 +2,7 @@ from ckeditor_uploader.widgets import CKEditorUploadingWidget from django import forms from django.utils.translation import gettext_lazy as _ -from .models import TopicGroup, Topic, Documentation, Document +from .models import TopicGroup, Topic, Documentation, Document, FileUpload class DateInput(forms.DateInput): @@ -38,9 +38,9 @@ class DocumentationAdminForm(forms.ModelForm): fields = [ "title", "slug", + "topic", "placeholder", "description", - "topic", ] widgets = {"description": CKEditorUploadingWidget(config_name="default")} @@ -55,6 +55,16 @@ class DocumentAdminForm(forms.ModelForm): ] +class FileUploadAdminForm(forms.ModelForm): + class Meta: + model = FileUpload + fields = [ + "title", + "file_field", + "documentation", + ] + + class DocumentForm(forms.ModelForm): class Meta: model = Document diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index cb0f2187..c4b28139 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -132,6 +132,7 @@ class Document(models.Model): class FileUpload(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) file_field = models.FileField(verbose_name="Dokument", upload_to="uploads/intern/files/") + date = models.DateField(verbose_name="Datum", default=date.today) documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE) diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index 1b43e7c4..7dcd3933 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -9,7 +9,7 @@ from documents.etherpadlib import add_ep_cookie from collections import deque from .forms import DocumentForm -from .models import TopicGroup, Topic, Documentation, Document +from .models import TopicGroup, Topic, Documentation, Document, FileUpload logger = logging.getLogger(__name__) @@ -65,6 +65,8 @@ def show_docu(request, topic_slug=None, slug=None): form = DocumentForm(initial=initial) + files = deque(FileUpload.objects.filter(documentation=active_docu)) + docus = deque(Document.objects.filter(documentation=active_docu).order_by('-date')) documents = deque([]) @@ -83,6 +85,7 @@ def show_docu(request, topic_slug=None, slug=None): "active_topic": active_topic, "active_docu": active_docu, "documents": documents, + "files": files, } response = render(request, "intern/docu.html", context) diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html index 58f28ed3..e0d2f5d3 100644 --- a/fet2020/templates/intern/docu.html +++ b/fet2020/templates/intern/docu.html @@ -2,7 +2,7 @@ {% block content %}
    -
    +
    @@ -31,10 +31,11 @@
    {% if active_docu.description %}
    + Beschreibung bearbeiten +
    {{ active_docu.description|safe }} +
    - -
    {% endif %}
    @@ -78,6 +79,19 @@
    {% endfor %} + + {% for file in files %} + +
    +
    +

    {{ file.title }}

    +
    +
    +

    {{ file.date }}

    +
    +
    +
    + {% endfor %}
    diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html index 4553a16a..7a4b4c3d 100644 --- a/fet2020/templates/intern/topic.html +++ b/fet2020/templates/intern/topic.html @@ -2,7 +2,7 @@ {% block content %}
    -
    +
    @@ -23,9 +23,11 @@
    {% if active_topic.description %}
    + Beschreibung bearbeiten +
    {{ active_topic.description|safe }} +
    -
    {% endif %}
    From 8c1fe944b6f36d84b198cdd6ced1783b8dfdb665 Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 16 Jun 2021 11:35:24 +0000 Subject: [PATCH 10/36] add breadcrumbs --- fet2020/templates/intern/docu.html | 34 ++++++++++------------------- fet2020/templates/intern/topic.html | 19 +++++----------- 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html index e0d2f5d3..31a7644a 100644 --- a/fet2020/templates/intern/docu.html +++ b/fet2020/templates/intern/docu.html @@ -3,28 +3,12 @@ {% block content %}
    - - - - - @@ -67,6 +51,8 @@
    + {% if documents %} + Etherpad Dokumente: {% for document in documents %}
    @@ -79,7 +65,10 @@
    {% endfor %} + {% endif %} + {% if files %} + Dokumente: {% for file in files %}
    @@ -92,6 +81,7 @@
    {% endfor %} + {% endif %}
    diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html index 7a4b4c3d..25d82116 100644 --- a/fet2020/templates/intern/topic.html +++ b/fet2020/templates/intern/topic.html @@ -3,20 +3,11 @@ {% block content %}
    - - - From 539021bc41ce0ee99c4c6d01630d6d008afd811c Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 16 Jun 2021 11:35:53 +0000 Subject: [PATCH 11/36] add view only for authenticated user --- fet2020/intern/views.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index 7dcd3933..813c673d 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -10,10 +10,12 @@ from collections import deque from .forms import DocumentForm from .models import TopicGroup, Topic, Documentation, Document, FileUpload +from authentications.decorators import authenticated_user logger = logging.getLogger(__name__) +@authenticated_user def index(request): topic = deque(Topic.objects.filter(archive=False).order_by(F('topic_group__order').asc(nulls_last=True), 'topic_group', 'title')) archive_topic = deque(Topic.objects.filter(archive=True)) @@ -26,6 +28,7 @@ def index(request): return render(request, "intern/index.html", context) +@authenticated_user def show_topic(request, slug=None): active_topic = Topic.objects.filter(slug=slug).first() docu = deque(Documentation.objects.filter(topic__slug=slug).order_by('title')) @@ -38,6 +41,7 @@ def show_topic(request, slug=None): return render(request, "intern/topic.html", context) +@authenticated_user def show_docu(request, topic_slug=None, slug=None): active_docu = Documentation.objects.filter(Q(topic__slug=topic_slug) & Q(slug=slug)).first() active_topic = Topic.objects.filter(slug=topic_slug).first() From 4a0c55a31cbcbb9043af38ef1102c8a6f0a93c94 Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 20 Jun 2021 21:42:42 +0000 Subject: [PATCH 12/36] rename unique constraint --- fet2020/intern/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index c4b28139..8de18a76 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -106,7 +106,7 @@ class Document(models.Model): verbose_name_plural = "Dokumente" constraints = [ - UniqueConstraint(fields=['title', 'date', 'documentation'], name='unique_document'), + UniqueConstraint(fields=['title', 'date', 'documentation'], name='unique_intern_document'), ] def clean(self): From 39fa6b996f7337c5945833c267498f48cf9a5055 Mon Sep 17 00:00:00 2001 From: patrick Date: Sun, 20 Jun 2021 21:46:24 +0000 Subject: [PATCH 13/36] remove placeholder --- fet2020/intern/forms.py | 1 - fet2020/intern/models.py | 1 - fet2020/intern/views.py | 1 - 3 files changed, 3 deletions(-) diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index fc50f163..29ec01c2 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -39,7 +39,6 @@ class DocumentationAdminForm(forms.ModelForm): "title", "slug", "topic", - "placeholder", "description", ] diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index 8de18a76..9e0fc148 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -71,7 +71,6 @@ class Topic(models.Model): class Documentation(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) slug = models.SlugField(max_length=10) - placeholder = models.CharField(verbose_name="Platzhalter", max_length=128, default="Titel") description = models.TextField(null=True, blank=True) diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index 813c673d..a0d93bf1 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -63,7 +63,6 @@ def show_docu(request, topic_slug=None, slug=None): messages.info(request, '; '.join(elem)) initial = { - "title": active_docu.placeholder, "documentation": active_docu, } From 68a51000b8073c53ee2e4dc507113f1e7769ce58 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 24 Jun 2021 12:14:18 +0000 Subject: [PATCH 14/36] add fileupload, create views, detail view of task --- fet2020/intern/admin.py | 41 ++++- fet2020/intern/forms.py | 11 ++ fet2020/intern/models.py | 48 +++++- fet2020/intern/urls.py | 11 ++ fet2020/intern/views.py | 142 +++++++++++++-- fet2020/tasks/forms.py | 22 ++- fet2020/tasks/models.py | 54 ++++++ fet2020/tasks/urls.py | 4 + fet2020/tasks/views.py | 148 ++++++++++++---- fet2020/templates/intern/docu.html | 46 ++++- fet2020/templates/intern/etherpad_create.html | 22 +++ fet2020/templates/intern/file_create.html | 22 +++ fet2020/templates/intern/index.html | 5 +- fet2020/templates/intern/topic.html | 35 +++- fet2020/templates/tasks/docu_create.html | 22 +++ fet2020/templates/tasks/index.html | 163 ++++++------------ fet2020/templates/tasks/task_create.html | 22 +++ fet2020/templates/tasks/task_detail.html | 46 +++++ 18 files changed, 664 insertions(+), 200 deletions(-) create mode 100644 fet2020/templates/intern/etherpad_create.html create mode 100644 fet2020/templates/intern/file_create.html create mode 100644 fet2020/templates/tasks/docu_create.html create mode 100644 fet2020/templates/tasks/task_create.html create mode 100644 fet2020/templates/tasks/task_detail.html diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py index 6b48da34..167a2c4e 100644 --- a/fet2020/intern/admin.py +++ b/fet2020/intern/admin.py @@ -2,7 +2,13 @@ from django.contrib import admin from django.db.models import F from .models import TopicGroup, Topic, Documentation, Document, FileUpload -from .forms import TopicGroupAdminForm, TopicAdminForm, DocumentationAdminForm, DocumentAdminForm, FileUploadAdminForm +from .forms import ( + TopicGroupAdminForm, + TopicAdminForm, + DocumentationAdminForm, + DocumentAdminForm, + FileUploadAdminForm, +) class DocumentationInline(admin.TabularInline): @@ -39,7 +45,7 @@ class TopicInline(admin.TabularInline): class TopicGroupAdmin(admin.ModelAdmin): form = TopicGroupAdminForm model = TopicGroup - search_fields = ("title", ) + search_fields = ("title",) inlines = (TopicInline,) list_display = ["title", "order"] @@ -54,7 +60,7 @@ class TopicAdmin(admin.ModelAdmin): form = TopicAdminForm model = Topic search_fields = ("title",) - inlines = (DocumentationInline, ) + inlines = (DocumentationInline,) list_filter = ["topic_group", "archive"] list_display = ["title", "topic_group", "archive"] @@ -68,9 +74,15 @@ class TopicAdmin(admin.ModelAdmin): class DocumentationAdmin(admin.ModelAdmin): form = DocumentationAdminForm model = Documentation - inlines = (DocumentInline, FileUploadInline, ) + inlines = ( + DocumentInline, + FileUploadInline, + ) - list_display = ["title", "topic",] + list_display = [ + "title", + "topic", + ] def save_model(self, request, obj, form, change): obj.created_by = request.user @@ -81,8 +93,14 @@ class DocumentAdmin(admin.ModelAdmin): form = DocumentAdminForm model = Document - list_filter = ["documentation",] - list_display = ["title", "date", "documentation",] + list_filter = [ + "documentation", + ] + list_display = [ + "title", + "date", + "documentation", + ] ordering = ["-date"] def save_model(self, request, obj, form, change): @@ -94,8 +112,13 @@ class FileUploadAdmin(admin.ModelAdmin): form = FileUploadAdminForm model = FileUpload - list_filter = ["documentation",] - list_display = ["title", "documentation",] + list_filter = [ + "documentation", + ] + list_display = [ + "title", + "documentation", + ] def save_model(self, request, obj, form, change): obj.created_by = request.user diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index 29ec01c2..ceb9b2b4 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -27,6 +27,7 @@ class TopicAdminForm(forms.ModelForm): "archive", "description", "topic_group", + "task_list", ] widgets = {"description": CKEditorUploadingWidget(config_name="default")} @@ -82,3 +83,13 @@ class DocumentForm(forms.ModelForm): widgets = { "date": DateInput(format=("%d-%m-%Y")), } + + +class FileUploadForm(forms.ModelForm): + class Meta: + model = FileUpload + fields = [ + "title", + "file_field", + "documentation", + ] diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index 9e0fc148..c79f5b5a 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -10,6 +10,7 @@ from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from documents import createPadifNotExists +from tasks.models import TaskList logger = logging.getLogger(__name__) @@ -18,7 +19,9 @@ class TopicGroup(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) slug = models.SlugField(max_length=10, unique=True) - order = models.PositiveSmallIntegerField(verbose_name="Reihenfolge", unique=True, null=True, blank=True) + order = models.PositiveSmallIntegerField( + verbose_name="Reihenfolge", unique=True, null=True, blank=True + ) objects = models.Manager() @@ -47,7 +50,12 @@ class Topic(models.Model): description = models.TextField(null=True, blank=True) - topic_group = models.ForeignKey(TopicGroup, on_delete=models.CASCADE, verbose_name="Themenbereich") + topic_group = models.ForeignKey( + TopicGroup, on_delete=models.CASCADE, verbose_name="Themenbereich" + ) + task_list = models.ForeignKey( + TaskList, on_delete=models.CASCADE, null=True, blank=True + ) objects = models.Manager() @@ -82,7 +90,9 @@ class Documentation(models.Model): return self.topic.title + " / " + self.title def get_absolute_url(self): - return reverse("docu", kwargs={"topic_slug": self.topic.slug, "slug": self.slug}) + return reverse( + "docu", kwargs={"topic_slug": self.topic.slug, "slug": self.slug} + ) def save(self, *args, **kwargs): if not self.slug: @@ -105,21 +115,39 @@ class Document(models.Model): verbose_name_plural = "Dokumente" constraints = [ - UniqueConstraint(fields=['title', 'date', 'documentation'], name='unique_intern_document'), + UniqueConstraint( + fields=["title", "date", "documentation"], name="unique_intern_document" + ), ] def clean(self): - pad_name = slugify(str(self.date) + "-" + self.documentation.topic.slug + "-" + self.documentation.slug + "-" + slugify(self.title)) + pad_name = slugify( + str(self.date) + + "-" + + self.documentation.topic.slug + + "-" + + self.documentation.slug + + "-" + + slugify(self.title) + ) if len(pad_name) > 50: raise ValidationError( - _('Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: %(length)s, Name: %(pad_name)s)'), - params={'length': len(pad_name), 'pad_name': pad_name}, + _( + "Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: %(length)s, Name: %(pad_name)s)" + ), + params={"length": len(pad_name), "pad_name": pad_name}, ) def save(self, *args, **kwargs): self.etherpad_key = createPadifNotExists( - slugify(self.date) + "-" + self.documentation.topic.slug + "-" + self.documentation.slug + "-" + slugify(self.title) + slugify(self.date) + + "-" + + self.documentation.topic.slug + + "-" + + self.documentation.slug + + "-" + + slugify(self.title) ) super().save(*args, **kwargs) @@ -130,7 +158,9 @@ class Document(models.Model): class FileUpload(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) - file_field = models.FileField(verbose_name="Dokument", upload_to="uploads/intern/files/") + file_field = models.FileField( + verbose_name="Dokument", upload_to="uploads/intern/files/" + ) date = models.DateField(verbose_name="Datum", default=date.today) documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE) diff --git a/fet2020/intern/urls.py b/fet2020/intern/urls.py index 538bdb6a..1edc2c2f 100644 --- a/fet2020/intern/urls.py +++ b/fet2020/intern/urls.py @@ -1,10 +1,21 @@ from django.urls import path from . import views +from .views import EtherpadCreateView, FileUploadCreateView urlpatterns = [ path("", views.index, name="intern"), path("/", views.show_topic, name="topic"), path("//", views.show_docu, name="docu"), + path( + "//etherpad-create/", + EtherpadCreateView.as_view(), + name="etherpad-create", + ), + path( + "//file-create/", + FileUploadCreateView.as_view(), + name="file-create", + ), ] diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index a0d93bf1..fafc78cf 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -1,23 +1,31 @@ import logging +from collections import deque from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import F, Q -from django.http import HttpResponseRedirect +from django.http import HttpResponseRedirect, Http404 from django.shortcuts import render +from django.views.generic.edit import CreateView +from django.urls import reverse + +from authentications.decorators import authenticated_user from documents.api import get_pad_link from documents.etherpadlib import add_ep_cookie -from collections import deque - -from .forms import DocumentForm +from tasks.models import Task +from .forms import DocumentForm, FileUploadForm from .models import TopicGroup, Topic, Documentation, Document, FileUpload -from authentications.decorators import authenticated_user logger = logging.getLogger(__name__) @authenticated_user def index(request): - topic = deque(Topic.objects.filter(archive=False).order_by(F('topic_group__order').asc(nulls_last=True), 'topic_group', 'title')) + topic = deque( + Topic.objects.filter(archive=False).order_by( + F("topic_group__order").asc(nulls_last=True), "topic_group", "title" + ) + ) archive_topic = deque(Topic.objects.filter(archive=True)) context = { @@ -31,11 +39,26 @@ def index(request): @authenticated_user def show_topic(request, slug=None): active_topic = Topic.objects.filter(slug=slug).first() - docu = deque(Documentation.objects.filter(topic__slug=slug).order_by('title')) + if not active_topic: + raise Http404("wrong topic") + + docu = deque(Documentation.objects.filter(topic__slug=slug).order_by("title")) + + tasks = None + if active_topic.task_list: + tasks = deque( + Task.taskmanager.get_tasks( + user=request.user.id, + completed=False, + task_list=active_topic.task_list, + all_tasks=True, + ) + ) context = { "active_topic": active_topic, "docus": docu, + "tasks": tasks, } return render(request, "intern/topic.html", context) @@ -43,34 +66,47 @@ def show_topic(request, slug=None): @authenticated_user def show_docu(request, topic_slug=None, slug=None): - active_docu = Documentation.objects.filter(Q(topic__slug=topic_slug) & Q(slug=slug)).first() + active_docu = Documentation.objects.filter( + Q(topic__slug=topic_slug) & Q(slug=slug) + ).first() + if not active_docu: + raise Http404("wrong docu") + active_topic = Topic.objects.filter(slug=topic_slug).first() if request.method == "POST": - if "btn_input" in request.POST: + if "btn_etherpad" in request.POST: form = DocumentForm(request.POST) if form.is_valid(): - docu = form.save(commit=False) - docu.created_by = request.user - # docu.documentation = active_docu - docu.save() - + form.save() return HttpResponseRedirect(request.path) else: for elem in list(form.errors.values()): - messages.info(request, '; '.join(elem)) + messages.info(request, "; ".join(elem)) + + if "btn_fileupload" in request.POST: + form = FileUploadForm(request.POST, request.FILES) + + if form.is_valid(): + form.save() + return HttpResponseRedirect(request.path) + + else: + for elem in list(form.errors.values()): + messages.info(request, "; ".join(elem)) initial = { "documentation": active_docu, } - form = DocumentForm(initial=initial) + form_add_etherpad = DocumentForm(initial=initial) + form_add_file = FileUploadForm(initial=initial) files = deque(FileUpload.objects.filter(documentation=active_docu)) - docus = deque(Document.objects.filter(documentation=active_docu).order_by('-date')) + docus = deque(Document.objects.filter(documentation=active_docu).order_by("-date")) documents = deque([]) # list of etherpad url-link of any documents @@ -84,7 +120,8 @@ def show_docu(request, topic_slug=None, slug=None): ) context = { - "formset": form, + "form_add_etherpad": form_add_etherpad, + "form_add_file": form_add_file, "active_topic": active_topic, "active_docu": active_docu, "documents": documents, @@ -99,3 +136,72 @@ def show_docu(request, topic_slug=None, slug=None): logger.info("Etherpad Server doesn't work. Error: %s", e) return response + + +class EtherpadCreateView(LoginRequiredMixin, CreateView): + model = Document + template_name = "intern/etherpad_create.html" + form_class = DocumentForm + + topic_slug = None + slug = None + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["topic_slug"] = self.topic_slug + context["slug"] = self.slug + return context + + def get_initial(self): + self.topic_slug = self.kwargs.get("topic_slug") + self.slug = self.kwargs.get("slug") + + active_docu = Documentation.objects.filter(slug=self.kwargs.get("slug")).first() + context = { + "documentation": active_docu, + } + + return context + + def get_success_url(self): + context = { + "topic_slug": self.topic_slug, + "slug": self.slug, + } + + return reverse("docu", kwargs=context) + + +class FileUploadCreateView(LoginRequiredMixin, CreateView): + model = FileUpload + template_name = "intern/file_create.html" + form_class = FileUploadForm + + topic_slug = None + slug = None + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["topic_slug"] = self.topic_slug + context["slug"] = self.slug + + return context + + def get_initial(self): + self.topic_slug = self.kwargs.get("topic_slug") + self.slug = self.kwargs.get("slug") + + active_docu = Documentation.objects.filter(slug=self.kwargs.get("slug")).first() + context = { + "documentation": active_docu, + } + + return context + + def get_success_url(self): + context = { + "topic_slug": self.topic_slug, + "slug": self.slug, + } + + return reverse("docu", kwargs=context) diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index df92cca3..266c46a6 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -3,7 +3,7 @@ from django.contrib.admin.widgets import FilteredSelectMultiple from django.contrib.auth.models import User from django.utils.translation import gettext_lazy as _ -from .models import Task, TaskList +from .models import Task, TaskList, Document class DateInput(forms.DateInput): @@ -77,3 +77,23 @@ class TaskListForm(forms.ModelForm): class Meta: model = TaskList fields = "__all__" + + +class DocumentForm(forms.ModelForm): + class Meta: + model = Document + + fields = [ + "title", + "date", + "task", + ] + + labels = { + "title": _("Titel"), + "date": _("Datum"), + } + + widgets = { + "date": DateInput(format=("%d-%m-%Y")), + } diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py index 49c31261..8a163076 100644 --- a/fet2020/tasks/models.py +++ b/fet2020/tasks/models.py @@ -1,8 +1,15 @@ +from datetime import date from django.conf import settings +from django.core.validators import ValidationError from django.contrib.auth.models import User from django.db import models from django.db.models import Q +from django.db.models.constraints import UniqueConstraint from django.utils import timezone +from django.utils.text import slugify +from django.utils.translation import gettext_lazy as _ + +from documents import createPadifNotExists class TaskQuerySet(models.QuerySet): @@ -100,3 +107,50 @@ class Task(models.Model): self.completed_date = None super().save(*args, **kwargs) + + +class Document(models.Model): + title = models.CharField(verbose_name="Titel", max_length=128) + etherpad_key = models.CharField(max_length=50, blank=True) + date = models.DateField(verbose_name="Datum", default=date.today) + + task = models.ForeignKey(Task, on_delete=models.CASCADE) + + objects = models.Manager() + + class Meta: + verbose_name = "Dokument" + verbose_name_plural = "Dokumente" + + constraints = [ + UniqueConstraint( + fields=["title", "date", "task"], name="unique_task_document" + ), + ] + + def clean(self): + pad_name = slugify( + str(self.date) + "-" + self.task.title + "-" + slugify(self.title) + ) + + print("clean") + + if len(pad_name) > 50: + raise ValidationError( + _( + "Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: %(length)s, Name: %(pad_name)s)" + ), + params={"length": len(pad_name), "pad_name": pad_name}, + ) + + def save(self, *args, **kwargs): + self.etherpad_key = createPadifNotExists( + slugify(str(self.date) + "-" + self.task.title + "-" + slugify(self.title)) + ) + + print("save") + + super().save(*args, **kwargs) + + def __str__(self): + return self.title diff --git a/fet2020/tasks/urls.py b/fet2020/tasks/urls.py index 6ea2af7d..d95b33d0 100644 --- a/fet2020/tasks/urls.py +++ b/fet2020/tasks/urls.py @@ -1,8 +1,12 @@ from django.urls import path from . import views +from .views import TaskCreate, TaskDetail, TaskUpdate, DocumentCreate urlpatterns = [ path("", views.index, name="tasks"), + path("task-create/", TaskCreate.as_view(), name="task-create"), + path("/docu-create/", DocumentCreate.as_view(), name="docu-create"), + path("/detail/", TaskDetail.as_view(), name="task-detail"), ] diff --git a/fet2020/tasks/views.py b/fet2020/tasks/views.py index 466da333..7ebc65cb 100644 --- a/fet2020/tasks/views.py +++ b/fet2020/tasks/views.py @@ -1,45 +1,33 @@ -from django.contrib import messages -from django.contrib.auth.models import User -from django.shortcuts import render -from django.utils import timezone +import logging from collections import deque +from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.models import User +from django.shortcuts import render +from django.views.generic.detail import DetailView +from django.views.generic.edit import CreateView, UpdateView +from django.urls import reverse_lazy, reverse +from django.utils import timezone -from .forms import TaskForm -from .models import Task, TaskList from authentications.decorators import authenticated_user +from documents.api import get_pad_link +from documents.etherpadlib import add_ep_cookie + +from .forms import TaskForm, DocumentForm +from .models import Task, TaskList, Document + +logger = logging.getLogger(__name__) @authenticated_user def index(request): - current_user = request.user.id current_action = False + tasklist = None show_tasklist = None show_all_tasks = True if request.method == "POST": - if "btn_input" in request.POST: - form = TaskForm(request.POST) - - if form.is_valid(): - task = form.save(commit=False) - - if task.assigned_to: - if TaskList.objects.filter(users=task.assigned_to): - task.created_by = request.user - task.save() - else: - messages.info( - request, - "User '{}' ist nicht in der Liste von Task-Gruppe '{}'.".format( - task.assigned_to, task.task_list.name - ), - ) - else: - task.created_by = request.user - task.save() - - elif "btn_checkbox" in request.POST: + if "btn_checkbox" in request.POST: for task_id in request.POST.getlist("checkbox"): task = Task.objects.get(id=task_id) @@ -48,16 +36,15 @@ def index(request): task.completed_date = timezone.now().date() task.save() - elif "btn_user" in request.POST: + if "btn_user" in request.POST: if request.POST["action"] == "show_incompleted": current_action = False else: current_action = True if request.POST["tasklist"] != "all": - show_tasklist = TaskList.objects.filter( - id=request.POST["tasklist"] - ).first() + tasklist = TaskList.objects.filter(id=request.POST["tasklist"]).first() + show_tasklist = tasklist.id if request.POST["tasks"] == "all": show_all_tasks = True @@ -67,9 +54,9 @@ def index(request): form = TaskForm() tasks = deque( Task.taskmanager.get_tasks( - user=current_user, + user=request.user.id, completed=current_action, - task_list=show_tasklist, + task_list=tasklist, all_tasks=show_all_tasks, ) ) @@ -79,8 +66,97 @@ def index(request): "formset": form, "tasks": tasks, "tasklists": tasklists, - "current_user": current_user, + "current_user": request.user.id, "current_action": current_action, + "show_tasklist": show_tasklist, + "show_all_tasks": show_all_tasks, } return render(request, "tasks/index.html", context) + + +class TaskCreate(LoginRequiredMixin, CreateView): + model = Task + success_url = reverse_lazy("tasks") + template_name = "tasks/task_create.html" + form_class = TaskForm + + def form_valid(self, form): + form.instance.created_by = self.request.user + return super().form_valid(form) + + +class TaskUpdate(LoginRequiredMixin, UpdateView): + model = Task + success_url = reverse_lazy("tasks") + template_name = "tasks/task_create.html" + form_class = TaskForm + + +class TaskDetail(LoginRequiredMixin, DetailView): + model = Task + success_url = reverse_lazy("tasks") + template_name = "tasks/task_detail.html" + + def get(self, request, *args, **kwargs): + response = super().get(request, *args, **kwargs) + + try: + response = add_ep_cookie(self.request, response) + except Exception as e: + logger.info("Etherpad Server doesn't work. Error: %s", e) + + return response + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + docus = deque( + Document.objects.filter(task__id=self.object.id).order_by("-date") + ) + documents = deque([]) + + # list of etherpad url-link of any documents + for elem in docus: + documents.append( + { + "title": elem.title, + "date": elem.date, + "etherpad_key": get_pad_link(elem.etherpad_key), + } + ) + context["documents"] = documents + + return context + + +class DocumentCreate(LoginRequiredMixin, CreateView): + model = Document + # success_url = reverse_lazy('tasks') + template_name = "tasks/docu_create.html" + form_class = DocumentForm + + task_id = None + + def get_initial(self): + self.task_id = self.kwargs.get("pk") + + task = Task.objects.get(pk=self.task_id) + context = { + "task": task, + } + + return context + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["task_id"] = self.task_id + + return context + + def get_success_url(self): + context = { + "task_id": self.task_id, + } + + return reverse("task-detail", kwargs=context) diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html index 31a7644a..3de34b35 100644 --- a/fet2020/templates/intern/docu.html +++ b/fet2020/templates/intern/docu.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} - {% block content %} +
    @@ -22,32 +22,66 @@
    {% endif %} + will man diese Buttons haben? + +
    + + oder direkt hier es erstellen? {% csrf_token %}
    - {{ formset.management_form }} + {{ form_add_etherpad.management_form }} - {% for form in formset %} + {% for form in form_add_etherpad %}
    {{ form }}
    {% endfor %} - {{ formset.non_field_errors }} + {{ form_add_etherpad.non_field_errors }}
    - +
    - + +
    + {% csrf_token %} + +
    + + {{ form_add_file.management_form }} + + {% for form in form_add_file %} +
    + {{ form }} +
    + {% endfor %} + + {{ form_add_file.non_field_errors }} + +
    + +
    +
    +
    + {% for message in messages %}

    {{message}}

    {% endfor %}
    +
    diff --git a/fet2020/templates/intern/etherpad_create.html b/fet2020/templates/intern/etherpad_create.html new file mode 100644 index 00000000..12932236 --- /dev/null +++ b/fet2020/templates/intern/etherpad_create.html @@ -0,0 +1,22 @@ +{% extends "layout.html" %} +{% block content %} + +
    +
    + Zurück +
    +
    + +

    Neues Etherpad erstellen

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    + +{% endblock %} diff --git a/fet2020/templates/intern/file_create.html b/fet2020/templates/intern/file_create.html new file mode 100644 index 00000000..aa45bcf7 --- /dev/null +++ b/fet2020/templates/intern/file_create.html @@ -0,0 +1,22 @@ +{% extends "layout.html" %} +{% block content %} + +
    +
    + Zurück +
    +
    + +

    Neue Datei hochladen

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    + +{% endblock %} diff --git a/fet2020/templates/intern/index.html b/fet2020/templates/intern/index.html index 7e77dd1e..5f2b5b28 100644 --- a/fet2020/templates/intern/index.html +++ b/fet2020/templates/intern/index.html @@ -1,10 +1,8 @@ {% extends "layout.html" %} - {% block content %} +
    - {% regroup topic by topic_group as topic_list %} - {% for topic in topic_list %}

    {{ topic.grouper.title }} #

    @@ -46,4 +44,5 @@ {% endif %}
    + {% endblock %} diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html index 25d82116..80ac64db 100644 --- a/fet2020/templates/intern/topic.html +++ b/fet2020/templates/intern/topic.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} - {% block content %} +
    @@ -12,13 +12,34 @@
    - {% if active_topic.description %} -
    - Beschreibung bearbeiten -
    - {{ active_topic.description|safe }} -
    + + + {% if active_topic.description %} +
    + {{ active_topic.description|safe }} +
    +
    + {% endif %} + + {% if tasks %} +
    +
    offene Tasks:
    + + {% for task in tasks %} + + {% endfor %} +
    +
    + {% endif %}
    diff --git a/fet2020/templates/tasks/docu_create.html b/fet2020/templates/tasks/docu_create.html new file mode 100644 index 00000000..5aa04b71 --- /dev/null +++ b/fet2020/templates/tasks/docu_create.html @@ -0,0 +1,22 @@ +{% extends 'layout.html' %} +{% block content %} + +
    +
    + Zurück +
    +
    + +

    Neues Etherpad hinzufügen

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    + +{% endblock %} diff --git a/fet2020/templates/tasks/index.html b/fet2020/templates/tasks/index.html index 4c731910..a5d0d795 100644 --- a/fet2020/templates/tasks/index.html +++ b/fet2020/templates/tasks/index.html @@ -2,63 +2,80 @@ {% block content %}
    + +
    - {% if current_user == user.id %} -

    Task-Übersicht für {{ user.username }}

    - {% endif %} +
    + {% csrf_token %} +
    +
    + + +
    - {% for message in messages %} -

    {{message}}

    - {% endfor %} +
    + + +
    + +
    + + +
    + +
    + +
    +
    +
    +
    {% if tasks %}
    {% csrf_token %}
    - {% regroup tasks by task_list as section_list %} {% for group in section_list %}
      +

      {{ group.grouper }}

      -

      {{ group.grouper }}

      - - {% for task in group.list %} - -
      - -
      - - {{ task.title }} -
      - -
      - {% if task.due_date %} - Fälligkeitsdatum: {{ task.due_date|date:"d.m.Y" }} - {% endif %} -
      - -
      - {% if task.assigned_to %} - nur dir zugewiesen! - {% endif %} -
      -
      - - {% endfor %} + {% for task in group.list %} +
      + +
      + {% if task.due_date %} + Fällig bis: {{ task.due_date|date:"d.m.Y" }} + {% endif %} +
      +
      + {% endfor %}
    - {% endfor %}
      - -
    @@ -70,82 +87,6 @@
    {% endif %} - -

    Andere Task-Übersicht anzeigen

    - - - {% csrf_token %} - -
    -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    -
    - - - - -

    Neuen Task hinzufügen

    - -
    - {% csrf_token %} - -
    - - {{ formset.management_form }} - - {% for form in formset %} -
    - {{ form.label }} - {{ form }} -
    - {% endfor %} - -
    - -
    - -
    - -
    -
    {% endblock %} diff --git a/fet2020/templates/tasks/task_create.html b/fet2020/templates/tasks/task_create.html new file mode 100644 index 00000000..f4e71e16 --- /dev/null +++ b/fet2020/templates/tasks/task_create.html @@ -0,0 +1,22 @@ +{% extends 'layout.html' %} +{% block content %} + +
    +
    + Zurück +
    +
    + +

    Neuen Task hinzufügen

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    + +{% endblock %} diff --git a/fet2020/templates/tasks/task_detail.html b/fet2020/templates/tasks/task_detail.html new file mode 100644 index 00000000..8b9a02bf --- /dev/null +++ b/fet2020/templates/tasks/task_detail.html @@ -0,0 +1,46 @@ +{% extends 'layout.html' %} +{% block content %} + +
    +
    +
    + Zurück +
    + + +
    +
    + +
    +
    +

    {{ task.title }}

    + +

    Fällig am: {{ task.due_date }}

    + + {% if task.completed %} +

    Erledigt am: {{ task.completed_date }}

    + {% endif %} + + {% if task.note %} + {{ task.note }} + {% endif %} + + {% for document in documents %} + +
    +
    +

    {{ document.title }}

    +
    +
    +

    {{ document.date }}

    +
    +
    +
    + {% endfor %} +
    +
    +
    + +{% endblock %} From a6e2fc210ffbe27b8579751cf9fb38621cda5da9 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 24 Jun 2021 12:31:57 +0000 Subject: [PATCH 15/36] rename document -> etherpad --- fet2020/intern/admin.py | 26 +++++++++++++------------- fet2020/intern/forms.py | 10 +++++----- fet2020/intern/models.py | 38 ++++++++++++++++++++------------------ fet2020/intern/views.py | 22 +++++++++++----------- 4 files changed, 49 insertions(+), 47 deletions(-) diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py index 167a2c4e..876a81f1 100644 --- a/fet2020/intern/admin.py +++ b/fet2020/intern/admin.py @@ -1,12 +1,12 @@ from django.contrib import admin from django.db.models import F -from .models import TopicGroup, Topic, Documentation, Document, FileUpload +from .models import TopicGroup, Topic, Documentation, Etherpad, FileUpload from .forms import ( TopicGroupAdminForm, TopicAdminForm, DocumentationAdminForm, - DocumentAdminForm, + EtherpadAdminForm, FileUploadAdminForm, ) @@ -22,15 +22,15 @@ class DocumentationInline(admin.TabularInline): class FileUploadInline(admin.TabularInline): model = FileUpload extra = 0 - verbose_name = "Dokument" - verbose_name_plural = "Do­ku­men­ten­samm­lung" + verbose_name = "Datei" + verbose_name_plural = "Dateien" -class DocumentInline(admin.TabularInline): - model = Document +class EtherpadInline(admin.TabularInline): + model = Etherpad extra = 0 - verbose_name = "Dokument" - verbose_name_plural = "Do­ku­men­ten­samm­lung" + verbose_name = "Etherpad" + verbose_name_plural = "Etherpads" class TopicInline(admin.TabularInline): @@ -75,7 +75,7 @@ class DocumentationAdmin(admin.ModelAdmin): form = DocumentationAdminForm model = Documentation inlines = ( - DocumentInline, + EtherpadInline, FileUploadInline, ) @@ -89,9 +89,9 @@ class DocumentationAdmin(admin.ModelAdmin): super().save_model(request, obj, form, change) -class DocumentAdmin(admin.ModelAdmin): - form = DocumentAdminForm - model = Document +class EtherpadAdmin(admin.ModelAdmin): + form = EtherpadAdminForm + model = Etherpad list_filter = [ "documentation", @@ -128,5 +128,5 @@ class FileUploadAdmin(admin.ModelAdmin): admin.site.register(TopicGroup, TopicGroupAdmin) admin.site.register(Topic, TopicAdmin) admin.site.register(Documentation, DocumentationAdmin) -admin.site.register(Document, DocumentAdmin) +admin.site.register(Etherpad, EtherpadAdmin) admin.site.register(FileUpload, FileUploadAdmin) diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index ceb9b2b4..973333cd 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -2,7 +2,7 @@ from ckeditor_uploader.widgets import CKEditorUploadingWidget from django import forms from django.utils.translation import gettext_lazy as _ -from .models import TopicGroup, Topic, Documentation, Document, FileUpload +from .models import TopicGroup, Topic, Documentation, Etherpad, FileUpload class DateInput(forms.DateInput): @@ -46,9 +46,9 @@ class DocumentationAdminForm(forms.ModelForm): widgets = {"description": CKEditorUploadingWidget(config_name="default")} -class DocumentAdminForm(forms.ModelForm): +class EtherpadAdminForm(forms.ModelForm): class Meta: - model = Document + model = Etherpad fields = [ "title", "documentation", @@ -65,9 +65,9 @@ class FileUploadAdminForm(forms.ModelForm): ] -class DocumentForm(forms.ModelForm): +class EtherpadForm(forms.ModelForm): class Meta: - model = Document + model = Etherpad fields = [ "title", diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index c79f5b5a..70295346 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -90,9 +90,12 @@ class Documentation(models.Model): return self.topic.title + " / " + self.title def get_absolute_url(self): - return reverse( - "docu", kwargs={"topic_slug": self.topic.slug, "slug": self.slug} - ) + kwargs = { + "topic_slug": self.topic.slug, + "slug": self.slug, + } + + return reverse("docu", kwargs=kwargs) def save(self, *args, **kwargs): if not self.slug: @@ -101,7 +104,7 @@ class Documentation(models.Model): super().save(*args, **kwargs) -class Document(models.Model): +class Etherpad(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) etherpad_key = models.CharField(max_length=50, blank=True) date = models.DateField(verbose_name="Datum", default=date.today) @@ -111,8 +114,8 @@ class Document(models.Model): objects = models.Manager() class Meta: - verbose_name = "Dokument" - verbose_name_plural = "Dokumente" + verbose_name = "Etherpad" + verbose_name_plural = "Etherpads" constraints = [ UniqueConstraint( @@ -120,9 +123,9 @@ class Document(models.Model): ), ] - def clean(self): - pad_name = slugify( - str(self.date) + def __get_pad_name(self): + return ( + slugify(self.date) + "-" + self.documentation.topic.slug + "-" @@ -131,6 +134,9 @@ class Document(models.Model): + slugify(self.title) ) + def clean(self): + pad_name = slugify(self.__get_pad_name()) + if len(pad_name) > 50: raise ValidationError( _( @@ -140,15 +146,7 @@ class Document(models.Model): ) def save(self, *args, **kwargs): - self.etherpad_key = createPadifNotExists( - slugify(self.date) - + "-" - + self.documentation.topic.slug - + "-" - + self.documentation.slug - + "-" - + slugify(self.title) - ) + self.etherpad_key = createPadifNotExists(self.__get_pad_name()) super().save(*args, **kwargs) @@ -167,5 +165,9 @@ class FileUpload(models.Model): objects = models.Manager() + class Meta: + verbose_name = "Datei" + verbose_name_plural = "Dateien" + def __str__(self): return self.title diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index fafc78cf..bc3cc74d 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -13,8 +13,8 @@ from authentications.decorators import authenticated_user from documents.api import get_pad_link from documents.etherpadlib import add_ep_cookie from tasks.models import Task -from .forms import DocumentForm, FileUploadForm -from .models import TopicGroup, Topic, Documentation, Document, FileUpload +from .forms import EtherpadForm, FileUploadForm +from .models import TopicGroup, Topic, Documentation, Etherpad, FileUpload logger = logging.getLogger(__name__) @@ -76,7 +76,7 @@ def show_docu(request, topic_slug=None, slug=None): if request.method == "POST": if "btn_etherpad" in request.POST: - form = DocumentForm(request.POST) + form = EtherpadForm(request.POST) if form.is_valid(): form.save() @@ -101,17 +101,17 @@ def show_docu(request, topic_slug=None, slug=None): "documentation": active_docu, } - form_add_etherpad = DocumentForm(initial=initial) + form_add_etherpad = EtherpadForm(initial=initial) form_add_file = FileUploadForm(initial=initial) files = deque(FileUpload.objects.filter(documentation=active_docu)) - docus = deque(Document.objects.filter(documentation=active_docu).order_by("-date")) - documents = deque([]) + docus = deque(Etherpad.objects.filter(documentation=active_docu).order_by("-date")) + etherpads = deque([]) - # list of etherpad url-link of any documents + # list of etherpad url-link of any etherpads for elem in docus: - documents.append( + etherpads.append( { "title": elem.title, "date": elem.date, @@ -124,7 +124,7 @@ def show_docu(request, topic_slug=None, slug=None): "form_add_file": form_add_file, "active_topic": active_topic, "active_docu": active_docu, - "documents": documents, + "documents": etherpads, "files": files, } @@ -139,9 +139,9 @@ def show_docu(request, topic_slug=None, slug=None): class EtherpadCreateView(LoginRequiredMixin, CreateView): - model = Document + model = Etherpad template_name = "intern/etherpad_create.html" - form_class = DocumentForm + form_class = EtherpadForm topic_slug = None slug = None From 51984649351f9ba96479499277849e347da63b03 Mon Sep 17 00:00:00 2001 From: patrick Date: Mon, 28 Jun 2021 19:18:04 +0000 Subject: [PATCH 16/36] fix argument --- fet2020/tasks/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fet2020/tasks/views.py b/fet2020/tasks/views.py index 7ebc65cb..daaa50e5 100644 --- a/fet2020/tasks/views.py +++ b/fet2020/tasks/views.py @@ -156,7 +156,7 @@ class DocumentCreate(LoginRequiredMixin, CreateView): def get_success_url(self): context = { - "task_id": self.task_id, + "pk": self.task_id, } return reverse("task-detail", kwargs=context) From 530764145b2e6cdf32adf20a4efb4610c1ab5353 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Mon, 3 Jan 2022 17:40:49 +0000 Subject: [PATCH 17/36] update view in admin --- fet2020/intern/admin.py | 34 ++++++++++++++++++++-------------- fet2020/intern/forms.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py index 876a81f1..ca37fbc2 100644 --- a/fet2020/intern/admin.py +++ b/fet2020/intern/admin.py @@ -8,38 +8,44 @@ from .forms import ( DocumentationAdminForm, EtherpadAdminForm, FileUploadAdminForm, + TopicInlineForm, + DocumentationInlineForm, + EtherpadInlineForm, + FileUploadInlineForm, ) +class TopicInline(admin.TabularInline): + model = Topic + form = TopicInlineForm + extra = 0 + verbose_name = "Thema" + verbose_name_plural = "Themen" + show_change_link = True + + class DocumentationInline(admin.TabularInline): model = Documentation - form = DocumentationAdminForm + form = DocumentationInlineForm extra = 0 verbose_name = "Dokument" verbose_name_plural = "Dokument-Übersicht" -class FileUploadInline(admin.TabularInline): - model = FileUpload - extra = 0 - verbose_name = "Datei" - verbose_name_plural = "Dateien" - - class EtherpadInline(admin.TabularInline): model = Etherpad + form = EtherpadInlineForm extra = 0 verbose_name = "Etherpad" verbose_name_plural = "Etherpads" -class TopicInline(admin.TabularInline): - model = Topic - form = TopicAdminForm +class FileUploadInline(admin.TabularInline): + model = FileUpload + form = FileUploadInlineForm extra = 0 - verbose_name = "Thema" - verbose_name_plural = "Themen" - show_change_link = True + verbose_name = "Datei" + verbose_name_plural = "Dateien" class TopicGroupAdmin(admin.ModelAdmin): diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index 973333cd..3f98ad9a 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -15,6 +15,7 @@ class TopicGroupAdminForm(forms.ModelForm): fields = [ "title", "slug", + "order", ] @@ -52,6 +53,7 @@ class EtherpadAdminForm(forms.ModelForm): fields = [ "title", "documentation", + "date", ] @@ -65,6 +67,43 @@ class FileUploadAdminForm(forms.ModelForm): ] +class TopicInlineForm(forms.ModelForm): + class Meta: + model = Topic + fields = [ + "title", + "slug", + ] + + +class DocumentationInlineForm(forms.ModelForm): + class Meta: + model = Documentation + fields = [ + "title", + "slug", + ] + + +class EtherpadInlineForm(forms.ModelForm): + class Meta: + model = Etherpad + fields = [ + "title", + "documentation", + "date", + ] + + +class FileUploadInlineForm(forms.ModelForm): + class Meta: + model = FileUpload + fields = [ + "title", + "file_field", + ] + + class EtherpadForm(forms.ModelForm): class Meta: model = Etherpad From a5746adbe1c2bce1972b178a6078dfb41127d0cf Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Mon, 3 Jan 2022 17:41:26 +0000 Subject: [PATCH 18/36] delete useless print functions --- fet2020/tasks/models.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py index 8a163076..f864fa6e 100644 --- a/fet2020/tasks/models.py +++ b/fet2020/tasks/models.py @@ -133,8 +133,6 @@ class Document(models.Model): str(self.date) + "-" + self.task.title + "-" + slugify(self.title) ) - print("clean") - if len(pad_name) > 50: raise ValidationError( _( @@ -148,8 +146,6 @@ class Document(models.Model): slugify(str(self.date) + "-" + self.task.title + "-" + slugify(self.title)) ) - print("save") - super().save(*args, **kwargs) def __str__(self): From b59b9b0f53ece64a9bbed39cb926bd2aeaad3985 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Mon, 3 Jan 2022 17:44:27 +0000 Subject: [PATCH 19/36] add UniqueConstraint, change verbose names --- fet2020/intern/models.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index 70295346..57538c24 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -27,7 +27,8 @@ class TopicGroup(models.Model): class Meta: verbose_name = "Themenbereich" - verbose_name_plural = "Themenbereiche" + # "1." because this point should be displayed first in admin view. + verbose_name_plural = "1. Themenbereiche" def __str__(self): return self.title @@ -61,7 +62,7 @@ class Topic(models.Model): class Meta: verbose_name = "Thema" - verbose_name_plural = "Themen" + verbose_name_plural = "2. Themen" def __str__(self): return self.title @@ -86,6 +87,17 @@ class Documentation(models.Model): objects = models.Manager() + class Meta: + verbose_name = "Dokumentation" + verbose_name_plural = "3. Dokumentationen" + + constraints = [ + UniqueConstraint(fields=["slug", "topic"], name="unique_intern_slug_topic"), + UniqueConstraint( + fields=["title", "topic"], name="unique_intern_title_topic" + ), + ] + def __str__(self): return self.topic.title + " / " + self.title @@ -119,7 +131,7 @@ class Etherpad(models.Model): constraints = [ UniqueConstraint( - fields=["title", "date", "documentation"], name="unique_intern_document" + fields=["title", "date", "documentation"], name="unique_intern_etherpad" ), ] From 6ad39ef0122fd0c4ef6d99689dd7121a3f4a4e56 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Mon, 3 Jan 2022 17:45:38 +0000 Subject: [PATCH 20/36] add buttons --- fet2020/templates/intern/docu.html | 92 +++++++----------------- fet2020/templates/intern/index.html | 17 +++++ fet2020/templates/intern/topic.html | 18 ++++- fet2020/templates/tasks/task_create.html | 7 +- fet2020/templates/tasks/task_detail.html | 10 +-- 5 files changed, 69 insertions(+), 75 deletions(-) diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html index 3de34b35..1f7d93c8 100644 --- a/fet2020/templates/intern/docu.html +++ b/fet2020/templates/intern/docu.html @@ -13,80 +13,33 @@
    + + {% if request.user.is_authenticated %} + + {% endif %} + {% if active_docu.description %}
    - Beschreibung bearbeiten -
    {{ active_docu.description|safe }}
    {% endif %} - will man diese Buttons haben? - -
    - - oder direkt hier es erstellen? -
    - {% csrf_token %} - -
    - - {{ form_add_etherpad.management_form }} - - {% for form in form_add_etherpad %} -
    - {{ form }} -
    - {% endfor %} - - {{ form_add_etherpad.non_field_errors }} - -
    - -
    -
    -
    - -
    - {% csrf_token %} - -
    - - {{ form_add_file.management_form }} - - {% for form in form_add_file %} -
    - {{ form }} -
    - {% endfor %} - - {{ form_add_file.non_field_errors }} - -
    - -
    -
    -
    - - {% for message in messages %} -

    {{message}}

    - {% endfor %} - -
    - -
    - {% if documents %} Etherpad Dokumente: + +
    +
    +

    + neues Etherpad erstellen

    +
    +
    +
    + {% for document in documents %}
    @@ -99,10 +52,16 @@
    {% endfor %} - {% endif %} - {% if files %} Dokumente: + +
    +
    +

    + neue Datei hochladen

    +
    +
    +
    + {% for file in files %}
    @@ -115,7 +74,6 @@
    {% endfor %} - {% endif %}
    diff --git a/fet2020/templates/intern/index.html b/fet2020/templates/intern/index.html index 5f2b5b28..ff3fd4c6 100644 --- a/fet2020/templates/intern/index.html +++ b/fet2020/templates/intern/index.html @@ -2,6 +2,14 @@ {% block content %}
    +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    + {% regroup topic by topic_group as topic_list %} {% for topic in topic_list %}
    @@ -20,6 +28,15 @@
    {% endfor %} +
    {% endfor %} diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html index 80ac64db..2d489faf 100644 --- a/fet2020/templates/intern/topic.html +++ b/fet2020/templates/intern/topic.html @@ -14,7 +14,7 @@
    neuen Task hinzufügen @@ -22,10 +22,10 @@
    {% if active_topic.description %} -
    +
    {{ active_topic.description|safe }} +
    -
    {% endif %} {% if tasks %} @@ -54,6 +54,18 @@
    {% endfor %} + + + +
    diff --git a/fet2020/templates/tasks/task_create.html b/fet2020/templates/tasks/task_create.html index f4e71e16..56458b7e 100644 --- a/fet2020/templates/tasks/task_create.html +++ b/fet2020/templates/tasks/task_create.html @@ -3,7 +3,12 @@

    diff --git a/fet2020/templates/tasks/task_detail.html b/fet2020/templates/tasks/task_detail.html index 8b9a02bf..3c60a5af 100644 --- a/fet2020/templates/tasks/task_detail.html +++ b/fet2020/templates/tasks/task_detail.html @@ -2,12 +2,14 @@ {% block content %}
    -
    -
    +
    + - - From 9cc1c5577ac11da24de83e1135156ce3cae39da4 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Mon, 3 Jan 2022 17:46:27 +0000 Subject: [PATCH 21/36] fix cell class --- fet2020/templates/intern/etherpad_create.html | 4 +++- fet2020/templates/intern/file_create.html | 4 +++- fet2020/templates/tasks/docu_create.html | 6 ++++-- fet2020/templates/tasks/index.html | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/fet2020/templates/intern/etherpad_create.html b/fet2020/templates/intern/etherpad_create.html index 12932236..17793c06 100644 --- a/fet2020/templates/intern/etherpad_create.html +++ b/fet2020/templates/intern/etherpad_create.html @@ -3,7 +3,9 @@
    - Zurück +
    + Zurück +

    diff --git a/fet2020/templates/intern/file_create.html b/fet2020/templates/intern/file_create.html index aa45bcf7..bded966f 100644 --- a/fet2020/templates/intern/file_create.html +++ b/fet2020/templates/intern/file_create.html @@ -3,7 +3,9 @@
    - Zurück +
    + Zurück +

    diff --git a/fet2020/templates/tasks/docu_create.html b/fet2020/templates/tasks/docu_create.html index 5aa04b71..7305afca 100644 --- a/fet2020/templates/tasks/docu_create.html +++ b/fet2020/templates/tasks/docu_create.html @@ -2,8 +2,10 @@ {% block content %}
    -
    - Zurück +
    +
    + Zurück +

    diff --git a/fet2020/templates/tasks/index.html b/fet2020/templates/tasks/index.html index a5d0d795..3b2e3173 100644 --- a/fet2020/templates/tasks/index.html +++ b/fet2020/templates/tasks/index.html @@ -3,7 +3,9 @@

    From cca8ea8ef23c8c224de3ef2fd70a2dd7c3ea0240 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 09:05:36 +0000 Subject: [PATCH 22/36] add absolute url --- fet2020/tasks/models.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py index f864fa6e..7904748a 100644 --- a/fet2020/tasks/models.py +++ b/fet2020/tasks/models.py @@ -5,6 +5,7 @@ from django.contrib.auth.models import User from django.db import models from django.db.models import Q from django.db.models.constraints import UniqueConstraint +from django.urls import reverse from django.utils import timezone from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ @@ -57,6 +58,9 @@ class TaskList(models.Model): def __str__(self): return self.name + def get_absolute_url(self): + return reverse("tasks") + class Task(models.Model): title = models.CharField(verbose_name="Titel", max_length=140) @@ -99,6 +103,9 @@ class Task(models.Model): def __str__(self): return self.title + def get_absolute_url(self): + return reverse("task-detail", kwargs={"pk": self.id}) + def save(self, *args, **kwargs): if self.completed and not self.completed_date: self.completed_date = timezone.now().date() From d3453755a2e7cd09bfe64875ff72a153365bc717 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 09:10:43 +0000 Subject: [PATCH 23/36] add comment --- fet2020/tasks/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py index 7904748a..31717c43 100644 --- a/fet2020/tasks/models.py +++ b/fet2020/tasks/models.py @@ -130,6 +130,7 @@ class Document(models.Model): verbose_name_plural = "Dokumente" constraints = [ + # TODO: include lower/upper case - when Django 4.0, then go for it. UniqueConstraint( fields=["title", "date", "task"], name="unique_task_document" ), From a9473c154f00876a7a4fef0457132eb97ba85678 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 09:33:27 +0000 Subject: [PATCH 24/36] move manager method in managers file --- fet2020/tasks/managers.py | 31 +++++++++++++++++++++++++++++++ fet2020/tasks/models.py | 32 +------------------------------- 2 files changed, 32 insertions(+), 31 deletions(-) create mode 100644 fet2020/tasks/managers.py diff --git a/fet2020/tasks/managers.py b/fet2020/tasks/managers.py new file mode 100644 index 00000000..65df48f0 --- /dev/null +++ b/fet2020/tasks/managers.py @@ -0,0 +1,31 @@ +from django.db import models +from django.db.models import Q + + +class TaskQuerySet(models.QuerySet): + def get_ordered(self): + return self.order_by("task_list") + + +class TaskManager(models.Manager): + def get_tasks(self, user, completed, task_list, all_tasks): + # None ... assigned to all users + qs_all = self.get_queryset().get_ordered() + qs = qs_all.filter(assigned_to__id=user) + + if all_tasks: + qs_tmp = qs_all.filter( + Q(assigned_to=None) & Q(task_list__users__id__exact=user) + ) + qs = (qs | qs_tmp).distinct() + + if not completed: + qs = qs.filter(completed=completed) + + if task_list: + qs = qs.filter(task_list=task_list) + + return qs + + def get_queryset(self): + return TaskQuerySet(self.model, using=self._db) diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py index 31717c43..fdb3cbe2 100644 --- a/fet2020/tasks/models.py +++ b/fet2020/tasks/models.py @@ -3,7 +3,6 @@ from django.conf import settings from django.core.validators import ValidationError from django.contrib.auth.models import User from django.db import models -from django.db.models import Q from django.db.models.constraints import UniqueConstraint from django.urls import reverse from django.utils import timezone @@ -11,36 +10,7 @@ from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from documents import createPadifNotExists - - -class TaskQuerySet(models.QuerySet): - def get_ordered(self): - return self.order_by("task_list") - - -class TaskManager(models.Manager): - def get_tasks(self, user, completed, task_list, all_tasks): - # None ... assigned to all users - qs = self.get_queryset().get_ordered().filter(assigned_to__id=user) - - if all_tasks: - qs_tmp = ( - self.get_queryset() - .get_ordered() - .filter(Q(assigned_to=None) & Q(task_list__users__id__exact=user)) - ) - qs = (qs | qs_tmp).distinct() - - if not completed: - qs = qs.filter(completed=completed) - - if task_list: - qs = qs.filter(task_list=task_list) - - return qs - - def get_queryset(self): - return TaskQuerySet(self.model, using=self._db) +from .managers import TaskManager class TaskList(models.Model): From 17d9330109fc1e1443fd7a2968c691d762c580bb Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 11:51:47 +0000 Subject: [PATCH 25/36] add admin add_view and change_view --- fet2020/tasks/admin.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/fet2020/tasks/admin.py b/fet2020/tasks/admin.py index 54e0f3dd..782e9418 100644 --- a/fet2020/tasks/admin.py +++ b/fet2020/tasks/admin.py @@ -36,6 +36,25 @@ class TaskAdmin(admin.ModelAdmin): list_filter = ("task_list",) search_fields = ("title",) + def add_view(self, request, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().add_view( + request, + form_url, + extra_context=extra_context, + ) + + def change_view(self, request, object_id, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().change_view( + request, + object_id, + form_url, + extra_context=extra_context, + ) + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) @@ -45,6 +64,25 @@ class TaskListAdmin(admin.ModelAdmin): form = TaskListForm model = TaskList + def add_view(self, request, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().add_view( + request, + form_url, + extra_context=extra_context, + ) + + def change_view(self, request, object_id, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().change_view( + request, + object_id, + form_url, + extra_context=extra_context, + ) + admin.site.register(TaskList, TaskListAdmin) admin.site.register(Task, TaskAdmin) From 8cfa3d6578a4748fb10cb3ff52d73b5c698a1ac1 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 13:37:06 +0000 Subject: [PATCH 26/36] add add_log_action --- fet2020/tasks/views.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/fet2020/tasks/views.py b/fet2020/tasks/views.py index daaa50e5..21555b71 100644 --- a/fet2020/tasks/views.py +++ b/fet2020/tasks/views.py @@ -1,8 +1,11 @@ import logging from collections import deque +from django.contrib.admin.models import ADDITION, CHANGE, LogEntry +from django.contrib.admin.utils import construct_change_message from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType from django.shortcuts import render from django.views.generic.detail import DetailView from django.views.generic.edit import CreateView, UpdateView @@ -75,6 +78,26 @@ def index(request): return render(request, "tasks/index.html", context) +def __add_log_action(request, form, add=True): + obj = form.save() + content_type = ContentType.objects.get(app_label="tasks", model="task") + change_message = construct_change_message(form, None, add) + + if add: + action_flag = ADDITION + else: + action_flag = CHANGE + + LogEntry.objects.log_action( + user_id=request.user.pk, + content_type_id=content_type.pk, + object_id=obj.pk, + object_repr=str(obj), + action_flag=action_flag, + change_message=change_message, + ) + + class TaskCreate(LoginRequiredMixin, CreateView): model = Task success_url = reverse_lazy("tasks") @@ -83,6 +106,8 @@ class TaskCreate(LoginRequiredMixin, CreateView): def form_valid(self, form): form.instance.created_by = self.request.user + __add_log_action(self.request, form, True) + return super().form_valid(form) @@ -92,6 +117,10 @@ class TaskUpdate(LoginRequiredMixin, UpdateView): template_name = "tasks/task_create.html" form_class = TaskForm + def form_valid(self, form): + __add_log_action(self.request, form, False) + return super().form_valid(form) + class TaskDetail(LoginRequiredMixin, DetailView): model = Task From 728af8eb72640bc27623089e05414199376b5fb2 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 16:51:35 +0000 Subject: [PATCH 27/36] add task-update --- fet2020/tasks/forms.py | 34 +++++++++++++++++++++++- fet2020/tasks/urls.py | 1 + fet2020/tasks/views.py | 34 +++++++++++------------- fet2020/templates/tasks/task_detail.html | 2 +- fet2020/templates/tasks/task_update.html | 27 +++++++++++++++++++ 5 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 fet2020/templates/tasks/task_update.html diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index 266c46a6..95014b86 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -1,6 +1,8 @@ from django import forms from django.contrib.admin.widgets import FilteredSelectMultiple from django.contrib.auth.models import User +from django.forms.widgets import HiddenInput +from django.utils import timezone from django.utils.translation import gettext_lazy as _ from .models import Task, TaskList, Document @@ -34,7 +36,7 @@ class TaskAdminForm(forms.ModelForm): ].queryset.order_by("username") -class TaskForm(forms.ModelForm): +class TaskCreateForm(forms.ModelForm): class Meta: model = Task @@ -66,6 +68,36 @@ class TaskForm(forms.ModelForm): ].queryset.order_by("username") +class TaskUpdateForm(forms.ModelForm): + class Meta: + model = Task + + fields = [ + "assigned_to", + "due_date", + "priority", + "note", + ] + + labels = { + "due_date": _("Fälligkeitsdatum"), + "assigned_to": _("Zuweisen an"), + } + + widgets = { + "due_date": DateInput( + format=("%d-%m-%Y"), + ) + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # to get the self.fields set + self.fields["assigned_to"].empty_label = "Alle" + self.fields["assigned_to"].queryset = self.fields[ + "assigned_to" + ].queryset.order_by("username") + + class TaskListForm(forms.ModelForm): users = forms.ModelMultipleChoiceField( label="Benutzer", diff --git a/fet2020/tasks/urls.py b/fet2020/tasks/urls.py index d95b33d0..8bed9422 100644 --- a/fet2020/tasks/urls.py +++ b/fet2020/tasks/urls.py @@ -8,5 +8,6 @@ urlpatterns = [ path("", views.index, name="tasks"), path("task-create/", TaskCreate.as_view(), name="task-create"), path("/docu-create/", DocumentCreate.as_view(), name="docu-create"), + path("/update/", TaskUpdate.as_view(), name="task-update"), path("/detail/", TaskDetail.as_view(), name="task-detail"), ] diff --git a/fet2020/tasks/views.py b/fet2020/tasks/views.py index 21555b71..fc11ab76 100644 --- a/fet2020/tasks/views.py +++ b/fet2020/tasks/views.py @@ -16,8 +16,8 @@ from authentications.decorators import authenticated_user from documents.api import get_pad_link from documents.etherpadlib import add_ep_cookie -from .forms import TaskForm, DocumentForm -from .models import Task, TaskList, Document +from .forms import DocumentForm, TaskCreateForm, TaskUpdateForm +from .models import Document, Task, TaskList logger = logging.getLogger(__name__) @@ -54,7 +54,6 @@ def index(request): else: show_all_tasks = False - form = TaskForm() tasks = deque( Task.taskmanager.get_tasks( user=request.user.id, @@ -66,7 +65,6 @@ def index(request): tasklists = deque(TaskList.objects.all()) context = { - "formset": form, "tasks": tasks, "tasklists": tasklists, "current_user": request.user.id, @@ -78,7 +76,7 @@ def index(request): return render(request, "tasks/index.html", context) -def __add_log_action(request, form, add=True): +def add_log_action(request, form, add=True): obj = form.save() content_type = ContentType.objects.get(app_label="tasks", model="task") change_message = construct_change_message(form, None, add) @@ -102,25 +100,29 @@ class TaskCreate(LoginRequiredMixin, CreateView): model = Task success_url = reverse_lazy("tasks") template_name = "tasks/task_create.html" - form_class = TaskForm + form_class = TaskCreateForm def form_valid(self, form): form.instance.created_by = self.request.user - __add_log_action(self.request, form, True) - + add_log_action(self.request, form, True) return super().form_valid(form) class TaskUpdate(LoginRequiredMixin, UpdateView): model = Task - success_url = reverse_lazy("tasks") - template_name = "tasks/task_create.html" - form_class = TaskForm + template_name = "tasks/task_update.html" + form_class = TaskUpdateForm def form_valid(self, form): - __add_log_action(self.request, form, False) + add_log_action(self.request, form, False) return super().form_valid(form) + def get_success_url(self): + kwargs = { + "pk": self.kwargs.get("pk"), + } + return reverse("task-detail", kwargs=kwargs) + class TaskDetail(LoginRequiredMixin, DetailView): model = Task @@ -161,7 +163,6 @@ class TaskDetail(LoginRequiredMixin, DetailView): class DocumentCreate(LoginRequiredMixin, CreateView): model = Document - # success_url = reverse_lazy('tasks') template_name = "tasks/docu_create.html" form_class = DocumentForm @@ -169,12 +170,10 @@ class DocumentCreate(LoginRequiredMixin, CreateView): def get_initial(self): self.task_id = self.kwargs.get("pk") - task = Task.objects.get(pk=self.task_id) context = { "task": task, } - return context def get_context_data(self, **kwargs): @@ -184,8 +183,7 @@ class DocumentCreate(LoginRequiredMixin, CreateView): return context def get_success_url(self): - context = { + kwargs = { "pk": self.task_id, } - - return reverse("task-detail", kwargs=context) + return reverse("task-detail", kwargs=kwargs) diff --git a/fet2020/templates/tasks/task_detail.html b/fet2020/templates/tasks/task_detail.html index 3c60a5af..b190cead 100644 --- a/fet2020/templates/tasks/task_detail.html +++ b/fet2020/templates/tasks/task_detail.html @@ -7,7 +7,7 @@ Zurück
    Etherpad hinzufügen diff --git a/fet2020/templates/tasks/task_update.html b/fet2020/templates/tasks/task_update.html new file mode 100644 index 00000000..6b185bc2 --- /dev/null +++ b/fet2020/templates/tasks/task_update.html @@ -0,0 +1,27 @@ +{% extends 'layout.html' %} +{% block content %} + +
    + +
    + +

    Task {{ task.title }} bearbeiten

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    + +{% endblock %} From 9645f3cd1a06be8d321190e01b87203eb9b2d3ba Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 16:52:39 +0000 Subject: [PATCH 28/36] set task field to hidden --- fet2020/tasks/forms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index 95014b86..9f2639e2 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -128,4 +128,5 @@ class DocumentForm(forms.ModelForm): widgets = { "date": DateInput(format=("%d-%m-%Y")), + "task": HiddenInput } From 3ebeee80f9c3960b3f316e5f04b4c0fc7c468258 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Wed, 19 Jan 2022 17:26:48 +0000 Subject: [PATCH 29/36] add Document Inline to Task-Admin --- fet2020/tasks/admin.py | 15 ++++++++++++--- fet2020/tasks/forms.py | 13 ++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/fet2020/tasks/admin.py b/fet2020/tasks/admin.py index 782e9418..878f9176 100644 --- a/fet2020/tasks/admin.py +++ b/fet2020/tasks/admin.py @@ -1,12 +1,21 @@ from django.contrib import admin -from .forms import TaskAdminForm, TaskListForm -from .models import Task, TaskList +from .forms import DocumentInlineForm, TaskAdminForm, TaskListAdminForm +from .models import Document, Task, TaskList + + +class DocumentInline(admin.TabularInline): + model = Document + form = DocumentInlineForm + extra = 0 + verbose_name = "Dokument" + verbose_name_plural = "Do­ku­men­ten­samm­lung" class TaskAdmin(admin.ModelAdmin): form = TaskAdminForm model = Task + inlines = (DocumentInline,) fieldsets = ( ( None, @@ -61,7 +70,7 @@ class TaskAdmin(admin.ModelAdmin): class TaskListAdmin(admin.ModelAdmin): - form = TaskListForm + form = TaskListAdminForm model = TaskList def add_view(self, request, form_url="", extra_context=None): diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index 9f2639e2..40964b71 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -12,6 +12,17 @@ class DateInput(forms.DateInput): input_type = "date" +class DocumentInlineForm(forms.ModelForm): + class Meta: + model = Document + fields = [ + "title", + "shortterm", + "slug", + "date", + ] + + class TaskAdminForm(forms.ModelForm): class Meta: model = Task @@ -98,7 +109,7 @@ class TaskUpdateForm(forms.ModelForm): ].queryset.order_by("username") -class TaskListForm(forms.ModelForm): +class TaskListAdminForm(forms.ModelForm): users = forms.ModelMultipleChoiceField( label="Benutzer", help_text="Es können nur die Benutzer ausgewählt werden, die sich auf der Homepage angemeldet haben.", From ef45ff948006dd2e15a833ad0cc0d31142003eed Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Thu, 20 Jan 2022 10:08:49 +0000 Subject: [PATCH 30/36] add assigning tasks to users who are not in the list --- fet2020/tasks/forms.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index 40964b71..a0383427 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -1,6 +1,7 @@ from django import forms from django.contrib.admin.widgets import FilteredSelectMultiple from django.contrib.auth.models import User +from django.core.validators import ValidationError from django.forms.widgets import HiddenInput from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -78,6 +79,24 @@ class TaskCreateForm(forms.ModelForm): "assigned_to" ].queryset.order_by("username") + def clean(self): + cleaned_data = super().clean() + assigned_to = cleaned_data["assigned_to"] + + if assigned_to: + task_list = TaskList.objects.get(id=cleaned_data["task_list"].id) + for elem in task_list.users.all(): + if assigned_to == elem: + break + else: + raise ValidationError( + _( + f"User '{assigned_to}' gibt es nicht in der User-Liste der Task-Gruppe '{task_list}'." + ) + ) + + return cleaned_data + class TaskUpdateForm(forms.ModelForm): class Meta: @@ -137,7 +156,4 @@ class DocumentForm(forms.ModelForm): "date": _("Datum"), } - widgets = { - "date": DateInput(format=("%d-%m-%Y")), - "task": HiddenInput - } + widgets = {"date": DateInput(format=("%d-%m-%Y")), "task": HiddenInput} From 5c992076f129c8ae62dbbdf43c9383d7e5da18a3 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Thu, 20 Jan 2022 10:21:37 +0000 Subject: [PATCH 31/36] styling --- fet2020/templates/tasks/task_update.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fet2020/templates/tasks/task_update.html b/fet2020/templates/tasks/task_update.html index 6b185bc2..be874b22 100644 --- a/fet2020/templates/tasks/task_update.html +++ b/fet2020/templates/tasks/task_update.html @@ -12,7 +12,7 @@

    -

    Task {{ task.title }} bearbeiten

    +

    Task '{{ task.title }}' bearbeiten

    From 1c7baf02364896591953c6059b7710f65d18e5a1 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Thu, 20 Jan 2022 13:26:18 +0000 Subject: [PATCH 32/36] delete unknown fields --- fet2020/tasks/forms.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index a0383427..0fa8aac4 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -18,8 +18,6 @@ class DocumentInlineForm(forms.ModelForm): model = Document fields = [ "title", - "shortterm", - "slug", "date", ] From 188e8d83bdc74e3477c8eb936c723f8517eaea53 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Thu, 20 Jan 2022 15:08:30 +0000 Subject: [PATCH 33/36] add slug --- fet2020/tasks/admin.py | 1 + fet2020/tasks/forms.py | 1 + fet2020/tasks/models.py | 26 ++++++++++++++++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/fet2020/tasks/admin.py b/fet2020/tasks/admin.py index 878f9176..e94fc261 100644 --- a/fet2020/tasks/admin.py +++ b/fet2020/tasks/admin.py @@ -22,6 +22,7 @@ class TaskAdmin(admin.ModelAdmin): { "fields": ( "title", + "slug", "task_list", "assigned_to", "due_date", diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index 0fa8aac4..79e9a307 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -18,6 +18,7 @@ class DocumentInlineForm(forms.ModelForm): model = Document fields = [ "title", + "slug", "date", ] diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py index fdb3cbe2..b9701090 100644 --- a/fet2020/tasks/models.py +++ b/fet2020/tasks/models.py @@ -14,7 +14,7 @@ from .managers import TaskManager class TaskList(models.Model): - name = models.CharField(max_length=60) + name = models.CharField(max_length=128) slug = models.SlugField(unique=True, null=True, blank=True) users = models.ManyToManyField(User, blank=True) @@ -31,9 +31,17 @@ class TaskList(models.Model): def get_absolute_url(self): return reverse("tasks") + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.name) + + super().save(*args, **kwargs) + class Task(models.Model): - title = models.CharField(verbose_name="Titel", max_length=140) + title = models.CharField(verbose_name="Titel", max_length=128) + slug = models.SlugField(unique=True, null=True, blank=True) + task_list = models.ForeignKey( TaskList, verbose_name="Aufgabenbereich", on_delete=models.CASCADE, null=True ) @@ -77,6 +85,9 @@ class Task(models.Model): return reverse("task-detail", kwargs={"pk": self.id}) def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + if self.completed and not self.completed_date: self.completed_date = timezone.now().date() @@ -88,6 +99,8 @@ class Task(models.Model): class Document(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) + slug = models.SlugField(unique=True, null=True, blank=True) + etherpad_key = models.CharField(max_length=50, blank=True) date = models.DateField(verbose_name="Datum", default=date.today) @@ -107,9 +120,10 @@ class Document(models.Model): ] def clean(self): - pad_name = slugify( - str(self.date) + "-" + self.task.title + "-" + slugify(self.title) - ) + if not self.slug: + self.slug = slugify(self.title) + + pad_name = slugify(str(self.date) + "-" + self.task.slug + "-" + self.slug) if len(pad_name) > 50: raise ValidationError( @@ -121,7 +135,7 @@ class Document(models.Model): def save(self, *args, **kwargs): self.etherpad_key = createPadifNotExists( - slugify(str(self.date) + "-" + self.task.title + "-" + slugify(self.title)) + slugify(str(self.date) + "-" + self.task.slug + "-" + self.slug) ) super().save(*args, **kwargs) From 2b57356d891bf9a9603b6fe81203b848c1711439 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Sat, 22 Jan 2022 08:55:28 +0000 Subject: [PATCH 34/36] add help_text in add and change view --- fet2020/intern/admin.py | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/fet2020/intern/admin.py b/fet2020/intern/admin.py index ca37fbc2..8ba4e2fe 100644 --- a/fet2020/intern/admin.py +++ b/fet2020/intern/admin.py @@ -57,6 +57,25 @@ class TopicGroupAdmin(admin.ModelAdmin): list_display = ["title", "order"] ordering = [F("order").asc(nulls_last=True)] + def add_view(self, request, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().add_view( + request, + form_url, + extra_context=extra_context, + ) + + def change_view(self, request, object_id, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().change_view( + request, + object_id, + form_url, + extra_context=extra_context, + ) + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) @@ -72,6 +91,25 @@ class TopicAdmin(admin.ModelAdmin): list_display = ["title", "topic_group", "archive"] ordering = ["archive"] + def add_view(self, request, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().add_view( + request, + form_url, + extra_context=extra_context, + ) + + def change_view(self, request, object_id, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().change_view( + request, + object_id, + form_url, + extra_context=extra_context, + ) + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) @@ -90,6 +128,25 @@ class DocumentationAdmin(admin.ModelAdmin): "topic", ] + def add_view(self, request, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().add_view( + request, + form_url, + extra_context=extra_context, + ) + + def change_view(self, request, object_id, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().change_view( + request, + object_id, + form_url, + extra_context=extra_context, + ) + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) @@ -109,6 +166,25 @@ class EtherpadAdmin(admin.ModelAdmin): ] ordering = ["-date"] + def add_view(self, request, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().add_view( + request, + form_url, + extra_context=extra_context, + ) + + def change_view(self, request, object_id, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().change_view( + request, + object_id, + form_url, + extra_context=extra_context, + ) + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) @@ -126,6 +202,25 @@ class FileUploadAdmin(admin.ModelAdmin): "documentation", ] + def add_view(self, request, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().add_view( + request, + form_url, + extra_context=extra_context, + ) + + def change_view(self, request, object_id, form_url="", extra_context=None): + extra_context = extra_context or {} + extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + return super().change_view( + request, + object_id, + form_url, + extra_context=extra_context, + ) + def save_model(self, request, obj, form, change): obj.created_by = request.user super().save_model(request, obj, form, change) From 0e53d93f503ab9e5ae2a90b903da28e0bf4ed4ad Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Sun, 23 Jan 2022 18:08:33 +0000 Subject: [PATCH 35/36] add Create- and UpdateView, labels, link to tasks. change date format. --- fet2020/intern/forms.py | 142 ++++++++++++- fet2020/intern/models.py | 17 +- fet2020/intern/urls.py | 36 +++- fet2020/intern/views.py | 190 ++++++++++++++++-- fet2020/tasks/forms.py | 102 +++++++--- fet2020/tasks/models.py | 15 +- fet2020/tasks/urls.py | 5 +- fet2020/tasks/views.py | 47 +++-- fet2020/templates/intern/docu.html | 13 +- .../templates/intern/docu/docu_create.html | 23 +++ .../templates/intern/docu/docu_update.html | 26 +++ fet2020/templates/intern/etherpad_create.html | 7 +- fet2020/templates/intern/file_create.html | 7 +- fet2020/templates/intern/index.html | 34 +++- fet2020/templates/intern/task_create.html | 23 +++ fet2020/templates/intern/topic.html | 24 +-- .../templates/intern/topic/topic_create.html | 23 +++ .../templates/intern/topic/topic_update.html | 26 +++ fet2020/templates/layout.html | 4 +- fet2020/templates/tasks/index.html | 7 +- fet2020/templates/tasks/task_create.html | 5 +- fet2020/templates/tasks/task_detail.html | 18 +- fet2020/templates/tasks/task_update.html | 5 +- 23 files changed, 659 insertions(+), 140 deletions(-) create mode 100644 fet2020/templates/intern/docu/docu_create.html create mode 100644 fet2020/templates/intern/docu/docu_update.html create mode 100644 fet2020/templates/intern/task_create.html create mode 100644 fet2020/templates/intern/topic/topic_create.html create mode 100644 fet2020/templates/intern/topic/topic_update.html diff --git a/fet2020/intern/forms.py b/fet2020/intern/forms.py index 3f98ad9a..f881efc0 100644 --- a/fet2020/intern/forms.py +++ b/fet2020/intern/forms.py @@ -1,7 +1,9 @@ from ckeditor_uploader.widgets import CKEditorUploadingWidget from django import forms +from django.forms.widgets import HiddenInput from django.utils.translation import gettext_lazy as _ +from tasks.models import Task, TaskList from .models import TopicGroup, Topic, Documentation, Etherpad, FileUpload @@ -16,8 +18,15 @@ class TopicGroupAdminForm(forms.ModelForm): "title", "slug", "order", + "short_description", ] + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + "short_description": _("Kurzbeschreibung"), + } + class TopicAdminForm(forms.ModelForm): class Meta: @@ -25,12 +34,19 @@ class TopicAdminForm(forms.ModelForm): fields = [ "title", "slug", - "archive", - "description", "topic_group", "task_list", + "archive", + "description", ] + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + "task_list": _("Aufgabenbereich"), + "description": _("Beschreibung"), + } + widgets = {"description": CKEditorUploadingWidget(config_name="default")} @@ -44,6 +60,12 @@ class DocumentationAdminForm(forms.ModelForm): "description", ] + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + "description": _("Beschreibung"), + } + widgets = {"description": CKEditorUploadingWidget(config_name="default")} @@ -52,8 +74,8 @@ class EtherpadAdminForm(forms.ModelForm): model = Etherpad fields = [ "title", - "documentation", "date", + "documentation", ] @@ -75,6 +97,11 @@ class TopicInlineForm(forms.ModelForm): "slug", ] + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + } + class DocumentationInlineForm(forms.ModelForm): class Meta: @@ -84,16 +111,26 @@ class DocumentationInlineForm(forms.ModelForm): "slug", ] + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + } + class EtherpadInlineForm(forms.ModelForm): class Meta: model = Etherpad fields = [ "title", - "documentation", "date", + "documentation", ] + labels = { + "title": _("Titel"), + "date": _("Datum"), + } + class FileUploadInlineForm(forms.ModelForm): class Meta: @@ -103,6 +140,96 @@ class FileUploadInlineForm(forms.ModelForm): "file_field", ] + labels = { + "title": _("Titel"), + } + + +class TopicCreateForm(forms.ModelForm): + class Meta: + model = Topic + fields = [ + "title", + "slug", + "description", + "topic_group", + ] + + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + "description": _("Beschreibung"), + } + + widgets = { + "topic_group": HiddenInput, + } + + +class TopicUpdateForm(forms.ModelForm): + class Meta: + model = Topic + fields = [ + "title", + "slug", + "description", + "topic_group", + ] + + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + "description": _("Beschreibung"), + } + + widgets = { + "topic_group": HiddenInput, + } + + +class DocumentationCreateForm(forms.ModelForm): + class Meta: + model = Documentation + + fields = [ + "title", + "slug", + "description", + "topic", + ] + + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + "description": _("Beschreibung"), + } + + widgets = { + "topic": HiddenInput, + } + + +class DocumentationUpdateForm(forms.ModelForm): + class Meta: + model = Documentation + + fields = [ + "title", + "slug", + "description", + "topic", + ] + + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + "description": _("Beschreibung"), + } + + widgets = { + "topic": HiddenInput, + } + class EtherpadForm(forms.ModelForm): class Meta: @@ -120,7 +247,8 @@ class EtherpadForm(forms.ModelForm): } widgets = { - "date": DateInput(format=("%d-%m-%Y")), + "date": DateInput(format=("%Y-%m-%d")), + "documentation": HiddenInput, } @@ -132,3 +260,7 @@ class FileUploadForm(forms.ModelForm): "file_field", "documentation", ] + + widgets = { + "documentation": HiddenInput, + } diff --git a/fet2020/intern/models.py b/fet2020/intern/models.py index 57538c24..59c5b42b 100644 --- a/fet2020/intern/models.py +++ b/fet2020/intern/models.py @@ -19,6 +19,8 @@ class TopicGroup(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) slug = models.SlugField(max_length=10, unique=True) + short_description = models.TextField(null=True, blank=True) + order = models.PositiveSmallIntegerField( verbose_name="Reihenfolge", unique=True, null=True, blank=True ) @@ -34,7 +36,7 @@ class TopicGroup(models.Model): return self.title def get_absolute_url(self): - return reverse("intern") + "#" + self.slug + return reverse("intern:index") + "#" + self.slug def save(self, *args, **kwargs): if not self.slug: @@ -68,7 +70,7 @@ class Topic(models.Model): return self.title def get_absolute_url(self): - return reverse("topic", kwargs={"slug": self.slug}) + return reverse("intern:topic", kwargs={"slug": self.slug}) def save(self, *args, **kwargs): if not self.slug: @@ -107,7 +109,7 @@ class Documentation(models.Model): "slug": self.slug, } - return reverse("docu", kwargs=kwargs) + return reverse("intern:docu", kwargs=kwargs) def save(self, *args, **kwargs): if not self.slug: @@ -118,6 +120,8 @@ class Documentation(models.Model): class Etherpad(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) + slug = models.SlugField(null=True, blank=True) + etherpad_key = models.CharField(max_length=50, blank=True) date = models.DateField(verbose_name="Datum", default=date.today) @@ -143,11 +147,14 @@ class Etherpad(models.Model): + "-" + self.documentation.slug + "-" - + slugify(self.title) + + self.slug ) def clean(self): - pad_name = slugify(self.__get_pad_name()) + if not self.slug: + self.slug = slugify(self.title) + + pad_name = self.__get_pad_name() if len(pad_name) > 50: raise ValidationError( diff --git a/fet2020/intern/urls.py b/fet2020/intern/urls.py index 1edc2c2f..11a166f1 100644 --- a/fet2020/intern/urls.py +++ b/fet2020/intern/urls.py @@ -1,13 +1,45 @@ from django.urls import path +from . import apps from . import views -from .views import EtherpadCreateView, FileUploadCreateView +from .views import ( + DocumentationCreateView, + DocumentationUpdateView, + EtherpadCreateView, + FileUploadCreateView, + TaskCreateView, + TopicCreateView, + TopicUpdateView, +) +app_name = apps.InternConfig.name + urlpatterns = [ - path("", views.index, name="intern"), + path("", views.index, name="index"), + path( + "/topic-create/", + TopicCreateView.as_view(), + name="topic-create", + ), path("/", views.show_topic, name="topic"), + path( + "/update/", + TopicUpdateView.as_view(), + name="topic-update", + ), + path( + "/docu-create/", + DocumentationCreateView.as_view(), + name="docu-create", + ), + path("/create/", TaskCreateView.as_view(), name="task-create"), path("//", views.show_docu, name="docu"), + path( + "//update/", + DocumentationUpdateView.as_view(), + name="docu-update", + ), path( "//etherpad-create/", EtherpadCreateView.as_view(), diff --git a/fet2020/intern/views.py b/fet2020/intern/views.py index bc3cc74d..6eb8ebfc 100644 --- a/fet2020/intern/views.py +++ b/fet2020/intern/views.py @@ -6,14 +6,22 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import F, Q from django.http import HttpResponseRedirect, Http404 from django.shortcuts import render -from django.views.generic.edit import CreateView -from django.urls import reverse +from django.views.generic.edit import CreateView, UpdateView +from django.urls import reverse_lazy, reverse from authentications.decorators import authenticated_user from documents.api import get_pad_link from documents.etherpadlib import add_ep_cookie +from tasks.forms import InternTaskCreateForm from tasks.models import Task -from .forms import EtherpadForm, FileUploadForm +from .forms import ( + DocumentationCreateForm, + DocumentationUpdateForm, + EtherpadForm, + FileUploadForm, + TopicCreateForm, + TopicUpdateForm, +) from .models import TopicGroup, Topic, Documentation, Etherpad, FileUpload logger = logging.getLogger(__name__) @@ -21,15 +29,15 @@ logger = logging.getLogger(__name__) @authenticated_user def index(request): - topic = deque( - Topic.objects.filter(archive=False).order_by( - F("topic_group__order").asc(nulls_last=True), "topic_group", "title" - ) + topic = Topic.objects.filter(archive=False).order_by( + F("topic_group__order").asc(nulls_last=True), "topic_group", "title" ) - archive_topic = deque(Topic.objects.filter(archive=True)) + empty_topic_groups = TopicGroup.objects.filter(topic=None) + archive_topic = Topic.objects.filter(archive=True) context = { "topic": topic, + "empty_topic_groups": empty_topic_groups, "archive_topic": archive_topic, } @@ -42,7 +50,7 @@ def show_topic(request, slug=None): if not active_topic: raise Http404("wrong topic") - docu = deque(Documentation.objects.filter(topic__slug=slug).order_by("title")) + docu = Documentation.objects.filter(topic__slug=slug).order_by("title") tasks = None if active_topic.task_list: @@ -104,9 +112,9 @@ def show_docu(request, topic_slug=None, slug=None): form_add_etherpad = EtherpadForm(initial=initial) form_add_file = FileUploadForm(initial=initial) - files = deque(FileUpload.objects.filter(documentation=active_docu)) + files = FileUpload.objects.filter(documentation=active_docu) - docus = deque(Etherpad.objects.filter(documentation=active_docu).order_by("-date")) + docus = Etherpad.objects.filter(documentation=active_docu).order_by("-date") etherpads = deque([]) # list of etherpad url-link of any etherpads @@ -138,6 +146,124 @@ def show_docu(request, topic_slug=None, slug=None): return response +class TopicCreateView(LoginRequiredMixin, CreateView): + model = Topic + success_url = reverse_lazy("intern:index") + template_name = "intern/topic/topic_create.html" + form_class = TopicCreateForm + + slug = None + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["topic_group"] = self.slug + return context + + def get_initial(self): + self.slug = self.kwargs.get("topic_group") + topic_group = TopicGroup.objects.filter(slug=self.slug).first() + + context = { + "topic_group": topic_group, + } + + return context + + +class TopicUpdateView(LoginRequiredMixin, UpdateView): + model = Topic + template_name = "intern/topic/topic_update.html" + form_class = TopicUpdateForm + + slug = None + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["slug"] = self.slug + return context + + def get_initial(self): + self.slug = self.kwargs.get("slug") + topic = Topic.objects.filter(slug=self.slug).first() + + context = { + "topic": topic, + } + + return context + + def get_success_url(self): + context = { + "slug": self.slug, + } + + return reverse("intern:topic", kwargs=context) + + +class DocumentationCreateView(LoginRequiredMixin, CreateView): + model = Documentation + template_name = "intern/docu/docu_create.html" + form_class = DocumentationCreateForm + + slug = None + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["slug"] = self.slug + return context + + def get_initial(self): + self.slug = self.kwargs.get("slug") + topic = Topic.objects.filter(slug=self.slug).first() + + context = { + "topic": topic, + } + + return context + + def get_success_url(self): + context = { + "slug": self.slug, + } + + return reverse("intern:topic", kwargs=context) + + +class DocumentationUpdateView(LoginRequiredMixin, UpdateView): + model = Documentation + template_name = "intern/docu/docu_update.html" + form_class = DocumentationUpdateForm + + topic_slug = None + slug = None + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["topic_slug"] = self.topic_slug + context["slug"] = self.slug + return context + + def get_initial(self): + self.topic_slug = self.kwargs.get("topic_slug") + self.slug = self.kwargs.get("slug") + + active_docu = Documentation.objects.filter(slug=self.slug).first() + context = { + "documentation": active_docu, + } + + return context + + def get_success_url(self): + context = { + "topic_slug": self.topic_slug, + "slug": self.slug, + } + + return reverse("intern:docu", kwargs=context) + + class EtherpadCreateView(LoginRequiredMixin, CreateView): model = Etherpad template_name = "intern/etherpad_create.html" @@ -156,7 +282,7 @@ class EtherpadCreateView(LoginRequiredMixin, CreateView): self.topic_slug = self.kwargs.get("topic_slug") self.slug = self.kwargs.get("slug") - active_docu = Documentation.objects.filter(slug=self.kwargs.get("slug")).first() + active_docu = Documentation.objects.filter(slug=self.slug).first() context = { "documentation": active_docu, } @@ -169,7 +295,7 @@ class EtherpadCreateView(LoginRequiredMixin, CreateView): "slug": self.slug, } - return reverse("docu", kwargs=context) + return reverse("intern:docu", kwargs=context) class FileUploadCreateView(LoginRequiredMixin, CreateView): @@ -204,4 +330,40 @@ class FileUploadCreateView(LoginRequiredMixin, CreateView): "slug": self.slug, } - return reverse("docu", kwargs=context) + return reverse("intern:docu", kwargs=context) + + +class TaskCreateView(LoginRequiredMixin, CreateView): + model = Task + template_name = "intern/task_create.html" + form_class = InternTaskCreateForm + + slug = None + + def form_valid(self, form): + form.instance.created_by = self.request.user + # add_log_action(self.request, form, True) + return super().form_valid(form) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["slug"] = self.slug + return context + + def get_initial(self): + self.slug = self.kwargs.get("slug") + topic = Topic.objects.filter(slug=self.slug).first() + + context = { + "topic": topic, + "task_list": topic.task_list, + } + + return context + + def get_success_url(self): + context = { + "slug": self.slug, + } + + return reverse("intern:topic", kwargs=context) diff --git a/fet2020/tasks/forms.py b/fet2020/tasks/forms.py index 79e9a307..92d7b526 100644 --- a/fet2020/tasks/forms.py +++ b/fet2020/tasks/forms.py @@ -22,6 +22,24 @@ class DocumentInlineForm(forms.ModelForm): "date", ] + labels = { + "title": _("Titel"), + "slug": _("Permalink"), + } + + +class TaskListAdminForm(forms.ModelForm): + users = forms.ModelMultipleChoiceField( + label="Benutzer", + help_text="Es können nur die Benutzer ausgewählt werden, die sich auf der Homepage angemeldet haben.", + queryset=User.objects.all().order_by("username"), + widget=FilteredSelectMultiple("User", is_stacked=False), + ) + + class Meta: + model = TaskList + fields = "__all__" + class TaskAdminForm(forms.ModelForm): class Meta: @@ -56,6 +74,7 @@ class TaskCreateForm(forms.ModelForm): "task_list", "due_date", "assigned_to", + "note", ] labels = { @@ -67,16 +86,23 @@ class TaskCreateForm(forms.ModelForm): widgets = { "due_date": DateInput( - format=("%d-%m-%Y"), + format=("%Y-%m-%d"), ) } def __init__(self, *args, **kwargs): + if "user" in kwargs: + user = kwargs.pop("user") + else: + user = None + super().__init__(*args, **kwargs) # to get the self.fields set self.fields["assigned_to"].empty_label = "Alle" - self.fields["assigned_to"].queryset = self.fields[ - "assigned_to" - ].queryset.order_by("username") + qs = self.fields["assigned_to"].queryset + self.fields["assigned_to"].queryset = qs.order_by("username") + + if user: + self.fields["task_list"].queryset = TaskList.objects.filter(users=user) def clean(self): cleaned_data = super().clean() @@ -84,10 +110,7 @@ class TaskCreateForm(forms.ModelForm): if assigned_to: task_list = TaskList.objects.get(id=cleaned_data["task_list"].id) - for elem in task_list.users.all(): - if assigned_to == elem: - break - else: + if not task_list.users.filter(username=assigned_to.username): raise ValidationError( _( f"User '{assigned_to}' gibt es nicht in der User-Liste der Task-Gruppe '{task_list}'." @@ -97,7 +120,7 @@ class TaskCreateForm(forms.ModelForm): return cleaned_data -class TaskUpdateForm(forms.ModelForm): +class TaskUpdateForm(TaskCreateForm): class Meta: model = Task @@ -106,6 +129,7 @@ class TaskUpdateForm(forms.ModelForm): "due_date", "priority", "note", + "task_list", ] labels = { @@ -115,32 +139,13 @@ class TaskUpdateForm(forms.ModelForm): widgets = { "due_date": DateInput( - format=("%d-%m-%Y"), - ) + format=("%Y-%m-%d"), + ), + "task_list": HiddenInput, } - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) # to get the self.fields set - self.fields["assigned_to"].empty_label = "Alle" - self.fields["assigned_to"].queryset = self.fields[ - "assigned_to" - ].queryset.order_by("username") - -class TaskListAdminForm(forms.ModelForm): - users = forms.ModelMultipleChoiceField( - label="Benutzer", - help_text="Es können nur die Benutzer ausgewählt werden, die sich auf der Homepage angemeldet haben.", - queryset=User.objects.all().order_by("username"), - widget=FilteredSelectMultiple("User", is_stacked=False), - ) - - class Meta: - model = TaskList - fields = "__all__" - - -class DocumentForm(forms.ModelForm): +class DocumentCreateForm(forms.ModelForm): class Meta: model = Document @@ -155,4 +160,35 @@ class DocumentForm(forms.ModelForm): "date": _("Datum"), } - widgets = {"date": DateInput(format=("%d-%m-%Y")), "task": HiddenInput} + widgets = { + "date": DateInput(format=("%d-%m-%Y")), + "task": HiddenInput, + } + + +class InternTaskCreateForm(TaskCreateForm): + # form for creating a task from intern page. + class Meta: + model = Task + + fields = [ + "title", + "task_list", + "due_date", + "assigned_to", + "note", + ] + + labels = { + "title": _("Titel des Tasks"), + "task_list": _("Task-Gruppe"), + "due_date": _("Fälligkeitsdatum"), + "assigned_to": _("Zuweisen an"), + } + + widgets = { + "due_date": DateInput( + format=("%d-%m-%Y"), + ), + "task_list": HiddenInput, + } diff --git a/fet2020/tasks/models.py b/fet2020/tasks/models.py index b9701090..5e5456b9 100644 --- a/fet2020/tasks/models.py +++ b/fet2020/tasks/models.py @@ -29,18 +29,16 @@ class TaskList(models.Model): return self.name def get_absolute_url(self): - return reverse("tasks") + return reverse("tasks:index") - def save(self, *args, **kwargs): + def clean(self): if not self.slug: self.slug = slugify(self.name) - super().save(*args, **kwargs) - class Task(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) - slug = models.SlugField(unique=True, null=True, blank=True) + slug = models.SlugField(null=True, blank=True) task_list = models.ForeignKey( TaskList, verbose_name="Aufgabenbereich", on_delete=models.CASCADE, null=True @@ -82,12 +80,13 @@ class Task(models.Model): return self.title def get_absolute_url(self): - return reverse("task-detail", kwargs={"pk": self.id}) + return reverse("tasks:task-detail", kwargs={"pk": self.id}) - def save(self, *args, **kwargs): + def clean(self): if not self.slug: self.slug = slugify(self.title) + def save(self, *args, **kwargs): if self.completed and not self.completed_date: self.completed_date = timezone.now().date() @@ -99,7 +98,7 @@ class Task(models.Model): class Document(models.Model): title = models.CharField(verbose_name="Titel", max_length=128) - slug = models.SlugField(unique=True, null=True, blank=True) + slug = models.SlugField(null=True, blank=True) etherpad_key = models.CharField(max_length=50, blank=True) date = models.DateField(verbose_name="Datum", default=date.today) diff --git a/fet2020/tasks/urls.py b/fet2020/tasks/urls.py index 8bed9422..2c910257 100644 --- a/fet2020/tasks/urls.py +++ b/fet2020/tasks/urls.py @@ -1,11 +1,14 @@ from django.urls import path +from . import apps from . import views from .views import TaskCreate, TaskDetail, TaskUpdate, DocumentCreate +app_name = apps.TasksConfig.name + urlpatterns = [ - path("", views.index, name="tasks"), + path("", views.index, name="index"), path("task-create/", TaskCreate.as_view(), name="task-create"), path("/docu-create/", DocumentCreate.as_view(), name="docu-create"), path("/update/", TaskUpdate.as_view(), name="task-update"), diff --git a/fet2020/tasks/views.py b/fet2020/tasks/views.py index fc11ab76..870b8fdd 100644 --- a/fet2020/tasks/views.py +++ b/fet2020/tasks/views.py @@ -15,8 +15,8 @@ from django.utils import timezone from authentications.decorators import authenticated_user from documents.api import get_pad_link from documents.etherpadlib import add_ep_cookie - -from .forms import DocumentForm, TaskCreateForm, TaskUpdateForm +from intern.models import Topic +from .forms import DocumentCreateForm, TaskCreateForm, TaskUpdateForm from .models import Document, Task, TaskList logger = logging.getLogger(__name__) @@ -54,15 +54,13 @@ def index(request): else: show_all_tasks = False - tasks = deque( - Task.taskmanager.get_tasks( - user=request.user.id, - completed=current_action, - task_list=tasklist, - all_tasks=show_all_tasks, - ) + tasks = Task.taskmanager.get_tasks( + user=request.user.id, + completed=current_action, + task_list=tasklist, + all_tasks=show_all_tasks, ) - tasklists = deque(TaskList.objects.all()) + tasklists = TaskList.objects.all() context = { "tasks": tasks, @@ -98,21 +96,33 @@ def add_log_action(request, form, add=True): class TaskCreate(LoginRequiredMixin, CreateView): model = Task - success_url = reverse_lazy("tasks") + success_url = reverse_lazy("tasks:index") template_name = "tasks/task_create.html" form_class = TaskCreateForm + user = None + def form_valid(self, form): form.instance.created_by = self.request.user add_log_action(self.request, form, True) return super().form_valid(form) + def get_initial(self): + self.user = self.request.user + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs["user"] = self.request.user + return kwargs + class TaskUpdate(LoginRequiredMixin, UpdateView): model = Task template_name = "tasks/task_update.html" form_class = TaskUpdateForm + pk = None + def form_valid(self, form): add_log_action(self.request, form, False) return super().form_valid(form) @@ -121,12 +131,12 @@ class TaskUpdate(LoginRequiredMixin, UpdateView): kwargs = { "pk": self.kwargs.get("pk"), } - return reverse("task-detail", kwargs=kwargs) + return reverse("tasks:task-detail", kwargs=kwargs) class TaskDetail(LoginRequiredMixin, DetailView): model = Task - success_url = reverse_lazy("tasks") + success_url = reverse_lazy("tasks:index") template_name = "tasks/task_detail.html" def get(self, request, *args, **kwargs): @@ -142,9 +152,8 @@ class TaskDetail(LoginRequiredMixin, DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - docus = deque( - Document.objects.filter(task__id=self.object.id).order_by("-date") - ) + docus = Document.objects.filter(task__id=self.object.id).order_by("-date") + documents = deque([]) # list of etherpad url-link of any documents @@ -158,13 +167,15 @@ class TaskDetail(LoginRequiredMixin, DetailView): ) context["documents"] = documents + context["topic"] = Topic.objects.filter(task_list=self.object.task_list).first() + return context class DocumentCreate(LoginRequiredMixin, CreateView): model = Document template_name = "tasks/docu_create.html" - form_class = DocumentForm + form_class = DocumentCreateForm task_id = None @@ -186,4 +197,4 @@ class DocumentCreate(LoginRequiredMixin, CreateView): kwargs = { "pk": self.task_id, } - return reverse("task-detail", kwargs=kwargs) + return reverse("tasks:task-detail", kwargs=kwargs) diff --git a/fet2020/templates/intern/docu.html b/fet2020/templates/intern/docu.html index 1f7d93c8..1ce074b6 100644 --- a/fet2020/templates/intern/docu.html +++ b/fet2020/templates/intern/docu.html @@ -1,12 +1,12 @@ {% extends "layout.html" %} -{% block content %} +{% block content %}
    @@ -17,7 +17,7 @@ {% if request.user.is_authenticated %} {% endif %} @@ -32,7 +32,7 @@
    Etherpad Dokumente: - +
    - {% endblock %} diff --git a/fet2020/templates/intern/docu/docu_create.html b/fet2020/templates/intern/docu/docu_create.html new file mode 100644 index 00000000..769ecb74 --- /dev/null +++ b/fet2020/templates/intern/docu/docu_create.html @@ -0,0 +1,23 @@ +{% extends "layout.html" %} + +{% block content %} +
    + +
    + +

    Neue Dokumentation erstellen

    +
    +
    + + {% csrf_token %} + {{ form }} + + +
    +
    +
    +{% endblock %} diff --git a/fet2020/templates/intern/docu/docu_update.html b/fet2020/templates/intern/docu/docu_update.html new file mode 100644 index 00000000..a37790a7 --- /dev/null +++ b/fet2020/templates/intern/docu/docu_update.html @@ -0,0 +1,26 @@ +{% extends "layout.html" %} + +{% block content %} +
    + +
    + +

    Dokumentation '{{ documentation.title }}' bearbeiten

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    +{% endblock %} diff --git a/fet2020/templates/intern/etherpad_create.html b/fet2020/templates/intern/etherpad_create.html index 17793c06..b9c0ae3e 100644 --- a/fet2020/templates/intern/etherpad_create.html +++ b/fet2020/templates/intern/etherpad_create.html @@ -1,10 +1,10 @@ {% extends "layout.html" %} -{% block content %} +{% block content %}
    -
    +
    @@ -20,5 +20,4 @@
    - {% endblock %} diff --git a/fet2020/templates/intern/file_create.html b/fet2020/templates/intern/file_create.html index bded966f..1439509c 100644 --- a/fet2020/templates/intern/file_create.html +++ b/fet2020/templates/intern/file_create.html @@ -1,10 +1,10 @@ {% extends "layout.html" %} -{% block content %} +{% block content %}
    -
    +
    @@ -20,5 +20,4 @@
    - {% endblock %} diff --git a/fet2020/templates/intern/index.html b/fet2020/templates/intern/index.html index ff3fd4c6..6961ce93 100644 --- a/fet2020/templates/intern/index.html +++ b/fet2020/templates/intern/index.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} -{% block content %} +{% block content %}
    {% if request.user.is_authenticated %} @@ -13,13 +13,17 @@ {% regroup topic by topic_group as topic_list %} {% for topic in topic_list %}
    -

    {{ topic.grouper.title }} #

    +

    {{ topic.grouper.title }} #

    + + {% if topic.grouper.short_description %} + {{ topic.grouper.short_description }} + {% endif %}
    {% for tp in topic.list %}
    - + + {% endfor %} + + {% for topic_group in empty_topic_groups %} +
    +

    {{ topic_group.title }} #

    +
    + +
    +
    +
    + @@ -48,7 +70,7 @@
    {% for tp in archive_topic %}
    - +
    {{ tp.title }} @@ -59,7 +81,5 @@ {% endfor %}
    {% endif %} -
    - {% endblock %} diff --git a/fet2020/templates/intern/task_create.html b/fet2020/templates/intern/task_create.html new file mode 100644 index 00000000..26db5a25 --- /dev/null +++ b/fet2020/templates/intern/task_create.html @@ -0,0 +1,23 @@ +{% extends 'layout.html' %} + +{% block content %} +
    + +
    + +

    Neuen Task hinzufügen

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    +{% endblock %} diff --git a/fet2020/templates/intern/topic.html b/fet2020/templates/intern/topic.html index 2d489faf..12cf20e9 100644 --- a/fet2020/templates/intern/topic.html +++ b/fet2020/templates/intern/topic.html @@ -1,11 +1,11 @@ {% extends "layout.html" %} -{% block content %} +{% block content %}
    @@ -14,11 +14,13 @@
    - + {% if active_topic.task_list %} + + {% endif %}
    {% if active_topic.description %} @@ -34,18 +36,17 @@ {% for task in tasks %} {% endfor %}

    - {% endif %}
    {% for docu in docus %}
    - + - {% endblock %} diff --git a/fet2020/templates/intern/topic/topic_create.html b/fet2020/templates/intern/topic/topic_create.html new file mode 100644 index 00000000..d9332ac4 --- /dev/null +++ b/fet2020/templates/intern/topic/topic_create.html @@ -0,0 +1,23 @@ +{% extends "layout.html" %} + +{% block content %} +
    +
    +
    + Zurück +
    +
    +
    + +

    Neues Thema erstellen

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    +{% endblock %} diff --git a/fet2020/templates/intern/topic/topic_update.html b/fet2020/templates/intern/topic/topic_update.html new file mode 100644 index 00000000..e314aa94 --- /dev/null +++ b/fet2020/templates/intern/topic/topic_update.html @@ -0,0 +1,26 @@ +{% extends "layout.html" %} + +{% block content %} +
    + +
    + +

    Thema '{{ topic.title }}' bearbeiten

    +
    +
    +
    + {% csrf_token %} + {{ form }} + +
    +
    +
    +
    +{% endblock %} diff --git a/fet2020/templates/layout.html b/fet2020/templates/layout.html index bdbb55fd..e916377f 100644 --- a/fet2020/templates/layout.html +++ b/fet2020/templates/layout.html @@ -53,8 +53,8 @@
  • Admin
  • -
  • Tasks
  • -
  • Intern
  • +
  • Tasks
  • +
  • Intern
  • Legacy Intern
  • {% endif %}
  • News
  • diff --git a/fet2020/templates/tasks/index.html b/fet2020/templates/tasks/index.html index 3b2e3173..d30f9a8c 100644 --- a/fet2020/templates/tasks/index.html +++ b/fet2020/templates/tasks/index.html @@ -1,10 +1,10 @@ {% extends 'layout.html' %} -{% block content %} +{% block content %}

    @@ -61,7 +61,7 @@
    @@ -90,5 +90,4 @@
    {% endif %}
    - {% endblock %} diff --git a/fet2020/templates/tasks/task_create.html b/fet2020/templates/tasks/task_create.html index 56458b7e..68ead194 100644 --- a/fet2020/templates/tasks/task_create.html +++ b/fet2020/templates/tasks/task_create.html @@ -1,10 +1,10 @@ {% extends 'layout.html' %} -{% block content %} +{% block content %}
    Task-Gruppe erstellen @@ -23,5 +23,4 @@
    - {% endblock %} diff --git a/fet2020/templates/tasks/task_detail.html b/fet2020/templates/tasks/task_detail.html index b190cead..c40b3961 100644 --- a/fet2020/templates/tasks/task_detail.html +++ b/fet2020/templates/tasks/task_detail.html @@ -1,16 +1,21 @@ {% extends 'layout.html' %} -{% block content %} +{% block content %}

    @@ -44,5 +49,4 @@
    - {% endblock %} diff --git a/fet2020/templates/tasks/task_update.html b/fet2020/templates/tasks/task_update.html index be874b22..1b1c9dbc 100644 --- a/fet2020/templates/tasks/task_update.html +++ b/fet2020/templates/tasks/task_update.html @@ -1,10 +1,10 @@ {% extends 'layout.html' %} -{% block content %} +{% block content %}
    Task im Admin bearbeiten @@ -23,5 +23,4 @@
    - {% endblock %} From a966ebda5bcb7dc9fd81738e87fae84d0757eac5 Mon Sep 17 00:00:00 2001 From: Patrick Mayr Date: Sun, 23 Jan 2022 20:53:06 +0000 Subject: [PATCH 36/36] change post action to get action --- fet2020/tasks/managers.py | 5 +---- fet2020/tasks/views.py | 33 +++++++++++++++++++----------- fet2020/templates/tasks/index.html | 31 ++++++++++++++-------------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/fet2020/tasks/managers.py b/fet2020/tasks/managers.py index 65df48f0..ea4019ab 100644 --- a/fet2020/tasks/managers.py +++ b/fet2020/tasks/managers.py @@ -19,13 +19,10 @@ class TaskManager(models.Manager): ) qs = (qs | qs_tmp).distinct() - if not completed: - qs = qs.filter(completed=completed) - if task_list: qs = qs.filter(task_list=task_list) - return qs + return qs.filter(completed=completed) def get_queryset(self): return TaskQuerySet(self.model, using=self._db) diff --git a/fet2020/tasks/views.py b/fet2020/tasks/views.py index 870b8fdd..b4ce7acf 100644 --- a/fet2020/tasks/views.py +++ b/fet2020/tasks/views.py @@ -24,7 +24,7 @@ logger = logging.getLogger(__name__) @authenticated_user def index(request): - current_action = False + completed = False tasklist = None show_tasklist = None show_all_tasks = True @@ -39,34 +39,43 @@ def index(request): task.completed_date = timezone.now().date() task.save() - if "btn_user" in request.POST: - if request.POST["action"] == "show_incompleted": - current_action = False - else: - current_action = True - - if request.POST["tasklist"] != "all": - tasklist = TaskList.objects.filter(id=request.POST["tasklist"]).first() + if request.method == "GET": + if "tasklist" in request.GET: + if request.GET["tasklist"] != "all": + tasklist = TaskList.objects.filter(id=request.GET["tasklist"]).first() show_tasklist = tasklist.id - if request.POST["tasks"] == "all": + if "tasks" in request.GET: + if request.GET["tasks"] == "all": show_all_tasks = True else: show_all_tasks = False + if "btn_state" in request.GET: + if request.GET["btn_state"] == "open": + completed = False + elif request.GET["btn_state"] == "close": + completed = True + tasks = Task.taskmanager.get_tasks( user=request.user.id, - completed=current_action, + completed=completed, task_list=tasklist, all_tasks=show_all_tasks, ) tasklists = TaskList.objects.all() + # TODO: very bad solution... try to do it better! + if completed == False: + completed = "open" + else: + completed = "close" + context = { "tasks": tasks, "tasklists": tasklists, "current_user": request.user.id, - "current_action": current_action, + "completed": completed, "show_tasklist": show_tasklist, "show_all_tasks": show_all_tasks, } diff --git a/fet2020/templates/tasks/index.html b/fet2020/templates/tasks/index.html index d30f9a8c..4a8c23c5 100644 --- a/fet2020/templates/tasks/index.html +++ b/fet2020/templates/tasks/index.html @@ -9,40 +9,39 @@

    -
    - {% csrf_token %} +
    -
    +
    -
    +
    -
    - - +
    +
    -
    - +
    + +
    +
    +
    +
    {% if tasks %}