Skip to content
Snippets Groups Projects
Verified Commit 7b20ab35 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Add views for managing live documents

parent 1b20eb62
No related branches found
No related tags found
1 merge request!16Resolve "Provide infrastructure for live documents"
Pipeline #25283 passed with warnings
......@@ -34,7 +34,7 @@ get_menu_entries_lazy = lazy(_get_menu_entries, list)
MENUS = {
"NAV_MENU_CORE": [
{
"name": _("Poster"),
"name": _("Documents"),
"url": "#",
"icon": "open_in_browser",
"root": True,
......@@ -64,6 +64,17 @@ MENUS = {
),
],
},
{
"name": _("Live documents"),
"url": "live_documents",
"icon": "update",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"resint.view_livedocuments_rule",
),
],
},
],
}
]
......
......@@ -109,3 +109,32 @@ add_perm("resint.view_poster_pdf_menu", view_poster_pdf_menu_predicate)
# Show the poster manage menu
view_poster_menu_predicate = view_posters_predicate | view_poster_groups_predicate
add_perm("resint.view_poster_menu", view_poster_menu_predicate)
# View live document list
view_live_documents_predicate = has_person & has_global_perm("resint.view_livedocument")
add_perm("resint.view_livedocuments_rule", view_live_documents_predicate)
# View live document
view_live_document_predicate = has_person & (
has_global_perm("resint.view_livedocument") | has_object_perm("resint.view_livedocument")
)
add_perm("resint.view_livedocument_rule", view_live_document_predicate)
# Add live document
add_live_document_predicate = view_live_documents_predicate & has_global_perm(
"resint.add_livedocument"
)
add_perm("resint.add_livedocument_rule", add_live_document_predicate)
# Edit live document
edit_live_document_predicate = view_live_documents_predicate & has_global_perm(
"resint.change_livedocument"
)
add_perm("resint.edit_livedocument_rule", edit_live_document_predicate)
# Delete live document
delete_live_document_predicate = view_live_documents_predicate & has_global_perm(
"resint.delete_livedocument"
)
add_perm("resint.delete_livedocument_rule", delete_live_document_predicate)
from django.utils.translation import gettext as _
from django_tables2 import A, Column, LinkColumn, Table
class LiveDocumentTable(Table):
"""Table to list live documents."""
class Meta:
attrs = {"class": "responsive-table highlight"}
document_name = Column(accessor="pk")
name = LinkColumn("edit_live_document", args=[A("id")])
edit = LinkColumn(
"edit_live_document",
args=[A("id")],
text=_("Edit"),
attrs={"a": {"class": "btn-flat waves-effect waves-orange orange-text"}},
verbose_name=_("Actions"),
)
delete = LinkColumn(
"delete_live_document",
args=[A("id")],
text=_("Delete"),
attrs={"a": {"class": "btn-flat waves-effect waves-red red-text"}},
verbose_name=_("Actions"),
)
def render_document_name(self, value, record):
return record._meta.verbose_name
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load material_form i18n data_helpers %}
{% block browser_title %}
{% verbose_name_object model as document_title %}
{% blocktrans with document=document_title %}Create {{ document }}{% endblocktrans %}
{% endblock %}
{% block page_title %}
{% verbose_name_object model as document_title %}
{% blocktrans with document=document_title %}Create {{ document }}{% endblocktrans %}
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{% form form=form %}{% endform %}
{% include "core/partials/save_button.html" %}
</form>
{% endblock %}
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load material_form i18n data_helpers %}
{% block browser_title %}
{% verbose_name_object object as document_title %}
{% blocktrans with document=document_title %}Edit {{ document }}{% endblocktrans %}
{% endblock %}
{% block page_title %}
{% verbose_name_object object as document_title %}
{% blocktrans with document=document_title %}Edit {{ document }}{% endblocktrans %}
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{% form form=form %}{% endform %}
{% include "core/partials/save_button.html" %}
</form>
{% endblock %}
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load i18n data_helpers rules %}
{% load render_table from django_tables2 %}
{% block browser_title %}{% blocktrans %}Live documents{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Live documents{% endblocktrans %}{% endblock %}
{% block content %}
<a class="btn green waves-effect waves-light dropdown-trigger" href="#" data-target="widget-dropdown">
<i class="material-icons left">add</i>
{% trans "Create live document" %}
</a>
<ul id="widget-dropdown" class="dropdown-content">
<li>
<a href="{% url 'create_live_document' "resint" "livedocument" %}">
{% trans "Live document" %}
</a>
</li>
{% for ct, model in widget_types %}
<li>
<a href="{% url 'create_live_document' ct.app_label ct.model %}">
{% verbose_name_object model as widget_name %}
{% blocktrans with name=widget_name %}Create {{ name }}{% endblocktrans %}
</a>
</li>
{% endfor %}
</ul>
{% render_table table %}
{% endblock %}
from django.urls import path
from .views import (
LiveDocumentCreateView,
LiveDocumentDeleteView,
LiveDocumentEditView,
LiveDocumentListView,
LiveDocumentShowView,
PosterCurrentView,
PosterDeleteView,
PosterEditView,
......@@ -22,4 +27,19 @@ urlpatterns = [
path("groups/create/", PosterGroupCreateView.as_view(), name="create_poster_group"),
path("groups/<int:pk>/edit/", PosterGroupEditView.as_view(), name="edit_poster_group"),
path("groups/<int:pk>/delete/", PosterGroupDeleteView.as_view(), name="delete_poster_group"),
path("live/", LiveDocumentListView.as_view(), name="live_documents"),
path(
"live/<str:app>/<str:model>/create/",
LiveDocumentCreateView.as_view(),
name="create_live_document",
),
path("live/<int:pk>/edit/", LiveDocumentEditView.as_view(), name="edit_live_document",),
path(
"live_documents/<int:pk>/delete/",
LiveDocumentDeleteView.as_view(),
name="delete_live_document",
),
path(
"live_documents/<str:slug>.pdf", LiveDocumentShowView.as_view(), name="show_live_document",
),
]
from typing import Any, Dict
from typing import Any, Dict, Type
from django.contrib.contenttypes.models import ContentType
from django.db.models import QuerySet
from django.forms import BaseModelForm, modelform_factory
from django.http import FileResponse, HttpRequest
from django.shortcuts import get_object_or_404
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.translation import gettext as _
from django.views import View
from django.views.decorators.cache import never_cache
from django.views.generic.detail import SingleObjectMixin
from django.views.generic.list import ListView
from django_tables2 import SingleTableView
from guardian.shortcuts import get_objects_for_user
from reversion.views import RevisionMixin
from rules.contrib.views import PermissionRequiredMixin
from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView
from .forms import PosterGroupForm, PosterUploadForm
from .models import Poster, PosterGroup
from .models import LiveDocument, Poster, PosterGroup
from .tables import LiveDocumentTable
class PosterGroupListView(PermissionRequiredMixin, ListView):
......@@ -138,3 +146,87 @@ class PosterCurrentView(PermissionRequiredMixin, SingleObjectMixin, View):
current_poster = group.current_poster
file = current_poster.pdf if current_poster else group.default_pdf
return FileResponse(file, content_type="application/pdf")
class LiveDocumentListView(PermissionRequiredMixin, SingleTableView):
"""Table of all live documents."""
model = LiveDocument
table_class = LiveDocumentTable
permission_required = "resint.view_livedocuments_rule"
template_name = "resint/live_document/list.html"
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["widget_types"] = [
(ContentType.objects.get_for_model(m, False), m) for m in LiveDocument.__subclasses__()
]
return context
@method_decorator(never_cache, name="dispatch")
class LiveDocumentCreateView(PermissionRequiredMixin, AdvancedCreateView):
"""Create view for live documents."""
def get_model(self, request, *args, **kwargs):
app_label = kwargs.get("app")
model = kwargs.get("model")
ct = get_object_or_404(ContentType, app_label=app_label, model=model)
return ct.model_class()
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context["model"] = self.model
return context
def get(self, request, *args, **kwargs):
self.model = self.get_model(request, *args, **kwargs)
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.model = self.get_model(request, *args, **kwargs)
return super().post(request, *args, **kwargs)
fields = "__all__"
model = LiveDocument
permission_required = "resint.add_livedocument_rule"
template_name = "resint/live_document/create.html"
success_url = reverse_lazy("live_documents")
success_message = _("The live document has been created.")
@method_decorator(never_cache, name="dispatch")
class LiveDocumentEditView(PermissionRequiredMixin, AdvancedEditView):
"""Edit view for live documents."""
def get_form_class(self) -> Type[BaseModelForm]:
return modelform_factory(self.object.__class__, fields=self.fields)
model = LiveDocument
fields = "__all__"
permission_required = "resint.edit_livedocument_rule"
template_name = "resint/live_document/edit.html"
success_url = reverse_lazy("live_documents")
success_message = _("The live document has been saved.")
@method_decorator(never_cache, name="dispatch")
class LiveDocumentDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView):
"""Delete view for live documents."""
model = LiveDocument
permission_required = "resint.delete_livedocument_rule"
template_name = "core/pages/delete.html"
success_url = reverse_lazy("live_documents")
success_message = _("The live document has been deleted.")
class LiveDocumentShowView(PermissionRequiredMixin, SingleObjectMixin, View):
"""Show the current version of the live document."""
model = LiveDocument
permission_required = "resint.view_livedocument_rule"
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> FileResponse:
live_document = self.get_object()
return FileResponse(live_document.get_current_file(), content_type="application/pdf")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment