diff --git a/aleksis/apps/resint/frontend/index.js b/aleksis/apps/resint/frontend/index.js new file mode 100644 index 0000000000000000000000000000000000000000..ff8b4c56321a3362fc00224b01800f62466f9a1f --- /dev/null +++ b/aleksis/apps/resint/frontend/index.js @@ -0,0 +1 @@ +export default {}; diff --git a/aleksis/apps/resint/frontend/messages/en.json b/aleksis/apps/resint/frontend/messages/en.json new file mode 100644 index 0000000000000000000000000000000000000000..0db3279e44b0dc4fb7e694b6cb10210a96ba6ba5 --- /dev/null +++ b/aleksis/apps/resint/frontend/messages/en.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/aleksis/apps/resint/migrations/0008_postergroup_slug_unique.py b/aleksis/apps/resint/migrations/0008_postergroup_slug_unique.py new file mode 100644 index 0000000000000000000000000000000000000000..e95a4887d8e71fdfef6379c535ce50ea664df651 --- /dev/null +++ b/aleksis/apps/resint/migrations/0008_postergroup_slug_unique.py @@ -0,0 +1,24 @@ +# Generated by Django 4.1.5 on 2023-02-03 16:42 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("contenttypes", "0002_remove_content_type_name"), + ("resint", "0007_current_file_not_null"), + ] + + operations = [ + migrations.AlterField( + model_name="postergroup", + name="slug", + field=models.SlugField( + help_text="If you use 'example', the filename will be 'example.pdf'.", + unique=True, + verbose_name="Slug used in URL name", + ), + ), + ] diff --git a/aleksis/apps/resint/models.py b/aleksis/apps/resint/models.py index eab9cc406f0dbb80a7b8accf9e7dbd595bc3eef7..e453376d7763c4ccc7970d55c77060195033f52e 100644 --- a/aleksis/apps/resint/models.py +++ b/aleksis/apps/resint/models.py @@ -4,6 +4,7 @@ from typing import Any, Optional from django.core.files import File from django.core.validators import FileExtensionValidator, MaxValueValidator, MinValueValidator from django.db import models +from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -15,17 +16,56 @@ from celery.states import SUCCESS from reversion.models import Revision, Version from aleksis.core.mixins import ExtensibleModel, ExtensiblePolymorphicModel +from aleksis.core.models import DynamicRoute from aleksis.core.util.pdf import generate_pdf_from_template +class PosterGroupDynamicRoute(DynamicRoute): + @classmethod + def get_dynamic_routes(cls): + poster_groups = PosterGroup.objects.all() + + dynamic_routes = [] + + for poster_group in poster_groups: + dynamic_routes.append(cls.get_route_data(poster_group)) + + return dynamic_routes + + @classmethod + def get_route_data(cls, instance): + dynamic_route = {} + + dynamic_route["parent_route_name"] = "" + + dynamic_route["route_path"] = reverse("poster_show_current", args=[instance.slug]) + dynamic_route["route_name"] = f"resint.posterGroup.{instance.slug}" + + dynamic_route["display_account_menu"] = False + dynamic_route["display_sidenav_menu"] = instance.show_in_menu + dynamic_route["sidenav_menu_root"] = True + dynamic_route["menu_new_tab"] = True + + dynamic_route["menu_title"] = instance.name + dynamic_route["menu_icon"] = "mdi-file-pdf-box" + + dynamic_route["menu_permission"] = "resint.view_poster_pdf_menu" + dynamic_route["route_permission"] = "resint.view_poster_pdf_menu" + + # TODO Handle case of posters that are supposed to be displayed even when user is not logged in + + return dynamic_route + + class PosterGroup(ExtensibleModel): """Group for time-based documents, called posters.""" slug = models.SlugField( verbose_name=_("Slug used in URL name"), help_text=_("If you use 'example', the filename will be 'example.pdf'."), + unique=True ) - name = models.CharField(max_length=255, verbose_name=_("Name")) + name = models.CharField(max_length=255, verbose_name=_("Name"), unique=True) publishing_day = models.PositiveSmallIntegerField( verbose_name=_("Publishing weekday"), choices=i18n_day_name_choices_lazy() ) @@ -44,8 +84,8 @@ class PosterGroup(ExtensibleModel): verbose_name = _("Poster group") verbose_name_plural = _("Poster groups") constraints = [ - models.UniqueConstraint(fields=["site_id", "name"], name="unique_site_name"), - models.UniqueConstraint(fields=["site_id", "slug"], name="unique_site_slug"), + models.UniqueConstraint(fields=["site_id", "name"], name="unique_site_name"), + models.UniqueConstraint(fields=["site_id", "slug"], name="unique_site_slug"), ] permissions = [ ("view_poster_of_group", _("Can view all posters of this group")), @@ -57,6 +97,7 @@ class PosterGroup(ExtensibleModel): def __str__(self) -> str: return f"{self.name} ({self.publishing_day_name}, {self.publishing_time})" + @property def publishing_day_name(self) -> str: """Return the full name of the publishing day (e. g. Monday).""" diff --git a/aleksis/apps/resint/rules.py b/aleksis/apps/resint/rules.py index f1d9f72db0f2e38dfc1b9f20f4c74876a2e10432..1db1cfb625c8a2035a6d1d11063f78522d057685 100644 --- a/aleksis/apps/resint/rules.py +++ b/aleksis/apps/resint/rules.py @@ -103,7 +103,10 @@ view_poster_pdf_predicate = is_public_poster_group | ( add_perm("resint.view_poster_pdf", view_poster_pdf_predicate) # View menu entry for single posters -view_poster_pdf_menu_predicate = show_poster_group_in_menu & view_poster_pdf_predicate +view_poster_pdf_menu_predicate = has_person & ( + has_global_perm("resint.view_postergroup") + | has_global_perm("resint.view_poster") +) add_perm("resint.view_poster_pdf_menu", view_poster_pdf_menu_predicate) # Show the poster manage menu