From 1a27ae2a76a4e981d44cccf90e43f655341dbc91 Mon Sep 17 00:00:00 2001 From: Christophe Siraut Date: Fri, 1 Dec 2023 16:13:47 +0100 Subject: [PATCH] misc: add in-site episode management for animators --- aircox/templates/aircox/episode_detail.html | 12 +++++ aircox/templates/aircox/episode_form.html | 30 ++++++++++++ .../aircox/widgets/episode_item.html | 33 ++++++++++--- aircox/urls.py | 5 ++ aircox/views/__init__.py | 3 +- aircox/views/episode.py | 47 ++++++++++++++++++- 6 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 aircox/templates/aircox/episode_form.html diff --git a/aircox/templates/aircox/episode_detail.html b/aircox/templates/aircox/episode_detail.html index 8ad5be2..abc06a9 100644 --- a/aircox/templates/aircox/episode_detail.html +++ b/aircox/templates/aircox/episode_detail.html @@ -3,6 +3,18 @@ {% load i18n aircox %} +{% block top-nav-tools %} +{% has_perm page page.program.change_permission_codename simple=True as can_edit %} +{% if can_edit %} + + + +   + {% translate "Edit" %} + +{% endif %} +{% endblock %} + {% block content-container %} diff --git a/aircox/templates/aircox/episode_form.html b/aircox/templates/aircox/episode_form.html new file mode 100644 index 0000000..e86f672 --- /dev/null +++ b/aircox/templates/aircox/episode_form.html @@ -0,0 +1,30 @@ +{% extends "aircox/basepage_detail.html" %} +{% load static i18n humanize honeypot aircox %} + + +{% block head_extra %} + {{ form.media }} +{% endblock %} + +{% block init-scripts %} +{% endblock %} + +{% block top-nav-tools %} + + + +   + {% translate "View" %} + +{% endblock %} + +{% block main %} +
{% csrf_token %} + + {{ form.as_table }} + {% render_honeypot_field "website" %} +
+
+ +
+{% endblock %} diff --git a/aircox/templates/aircox/widgets/episode_item.html b/aircox/templates/aircox/widgets/episode_item.html index 57648b4..02f23a1 100644 --- a/aircox/templates/aircox/widgets/episode_item.html +++ b/aircox/templates/aircox/widgets/episode_item.html @@ -25,12 +25,31 @@ {% endblock %} -{% block content %} -{% if not object.content %} - {% with object.parent.content as content %} - {{ block.super }} - {% endwith %} -{% else %} - {{ block.super }} +{% block actions %} +{% if object.sound_set.public.count %} + +{% endif %} +{% endblock %} + +{% block actions %} +{% has_perm page object.program.change_permission_codename simple=True as can_edit %} +{% if can_edit %} + + + +{% endif %} + +{% if object.sound_set.public.count %} + {% endif %} {% endblock %} diff --git a/aircox/urls.py b/aircox/urls.py index c7085b1..7f2b79b 100755 --- a/aircox/urls.py +++ b/aircox/urls.py @@ -114,6 +114,11 @@ urls = [ views.EpisodeDetailView.as_view(), name="episode-detail", ), + path( + _("programs/episodes//edit/"), + views.EpisodeUpdateView.as_view(), + name="episode-edit", + ), path(_("podcasts/"), views.PodcastListView.as_view(), name="podcast-list"), path(_("podcasts/c//"), views.PodcastListView.as_view(), name="podcast-list"), # ---- others diff --git a/aircox/views/__init__.py b/aircox/views/__init__.py index d9c2010..9029130 100644 --- a/aircox/views/__init__.py +++ b/aircox/views/__init__.py @@ -2,7 +2,7 @@ from . import admin, errors from .article import ArticleDetailView, ArticleListView from .base import BaseAPIView, BaseView from .diffusion import DiffusionListView, TimeTableView -from .episode import EpisodeDetailView, EpisodeListView, PodcastListView +from .episode import EpisodeDetailView, EpisodeListView, PodcastListView, EpisodeUpdateView from .home import HomeView from .log import LogListAPIView, LogListView from .page import ( @@ -32,6 +32,7 @@ __all__ = ( "EpisodeDetailView", "EpisodeListView", "PodcastListView", + "EpisodeUpdateView", "HomeView", "LogListAPIView", "LogListView", diff --git a/aircox/views/episode.py b/aircox/views/episode.py index 7d0c4a9..dd166b2 100644 --- a/aircox/views/episode.py +++ b/aircox/views/episode.py @@ -1,14 +1,24 @@ -from django.shortcuts import reverse +from django.contrib.auth.mixins import UserPassesTestMixin +from django.forms import ModelForm, FileField +from django.urls import reverse + +from ckeditor.fields import RichTextField +from filer.models.filemodels import File + +from aircox.controllers.sound_file import SoundFile from ..filters import EpisodeFilters from ..models import Episode, Program, StaticPage from .page import PageListView -from .program import ProgramPageDetailView +from .program import ProgramPageDetailView, BaseProgramMixin +from .page import PageUpdateView + __all__ = ( "EpisodeDetailView", "EpisodeListView", "PodcastListView", + "EpisodeUpdateView", ) @@ -39,3 +49,36 @@ class EpisodeListView(PageListView): class PodcastListView(EpisodeListView): attach_to_value = StaticPage.Target.PODCASTS queryset = Episode.objects.published().with_podcasts().order_by("-pub_date") + + +class EpisodeForm(ModelForm): + content = RichTextField() + new_podcast = FileField(required=False) + + class Meta: + model = Episode + fields = ["content"] + + def save(self, commit=True): + file_obj = self.cleaned_data["new_podcast"] + if file_obj: + obj, _ = File.objects.get_or_create(original_filename=file_obj.name, file=file_obj) + sound_file = SoundFile(obj.path) + sound_file.sync( + program=self.instance.program, episode=self.instance, type=0, is_public=True, is_downloadable=True + ) + + +class EpisodeUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView): + model = Episode + form_class = EpisodeForm + + def get_sidebar_queryset(self): + return super().get_sidebar_queryset().filter(parent=self.program) + + def test_func(self): + program = self.get_object().program + return self.request.user.has_perm("aircox.%s" % program.change_permission_codename) + + def get_success_url(self): + return reverse("episode-detail", kwargs={"slug": self.get_object().slug})