@ -1,10 +1,12 @@
 | 
				
			|||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
from django.forms import ModelForm, ImageField
 | 
					from django.forms import ModelForm, ImageField, FileField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ckeditor.fields import RichTextField
 | 
					from ckeditor.fields import RichTextField
 | 
				
			||||||
from filer.models.imagemodels import Image
 | 
					from filer.models.imagemodels import Image
 | 
				
			||||||
 | 
					from filer.models.filemodels import File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from aircox.models import Comment, Program
 | 
					from aircox.models import Comment, Episode, Program
 | 
				
			||||||
 | 
					from aircox.controllers.sound_file import SoundFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CommentForm(ModelForm):
 | 
					class CommentForm(ModelForm):
 | 
				
			||||||
@ -35,3 +37,21 @@ class ProgramForm(ModelForm):
 | 
				
			|||||||
            obj, _ = Image.objects.get_or_create(original_filename=file_obj.name, file=file_obj)
 | 
					            obj, _ = Image.objects.get_or_create(original_filename=file_obj.name, file=file_obj)
 | 
				
			||||||
            self.instance.cover = obj
 | 
					            self.instance.cover = obj
 | 
				
			||||||
        super().save(commit=commit)
 | 
					        super().save(commit=commit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					{% load static i18n thumbnail aircox %}<!doctype html>
 | 
				
			||||||
{% comment %}
 | 
					{% comment %}
 | 
				
			||||||
Base website template. It displays various elements depending on context
 | 
					Base website template. It displays various elements depending on context
 | 
				
			||||||
variables.
 | 
					variables.
 | 
				
			||||||
@ -10,8 +11,6 @@ Usefull context:
 | 
				
			|||||||
- sidebar_url_name: url name sidebar item complete list
 | 
					- sidebar_url_name: url name sidebar item complete list
 | 
				
			||||||
- sidebar_url_parent: parent page for sidebar items complete list
 | 
					- sidebar_url_parent: parent page for sidebar items complete list
 | 
				
			||||||
{% endcomment %}
 | 
					{% endcomment %}
 | 
				
			||||||
{% load static i18n thumbnail aircox %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<html>
 | 
					<html>
 | 
				
			||||||
    <head>
 | 
					    <head>
 | 
				
			||||||
        <meta charset="utf-8" />
 | 
					        <meta charset="utf-8" />
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,18 @@
 | 
				
			|||||||
{% load i18n aircox %}
 | 
					{% load i18n aircox %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block top-nav-tools %}
 | 
				
			||||||
 | 
					{% has_perm page page.program.change_permission_codename simple=True as can_edit %}
 | 
				
			||||||
 | 
					{% if can_edit %}
 | 
				
			||||||
 | 
					<a class="navbar-item" href="{% url 'episode-edit' page.pk %}" target="_self">
 | 
				
			||||||
 | 
					    <span class="icon is-small">
 | 
				
			||||||
 | 
					        <i class="fa fa-pen"></i>
 | 
				
			||||||
 | 
					    </span> 
 | 
				
			||||||
 | 
					    <span>{% translate "Edit" %}</span>
 | 
				
			||||||
 | 
					</a>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block content-container %}
 | 
					{% block content-container %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a-episode :page="{title: "{{ page.title }}", podcasts: {{ object.podcasts|json }}}">
 | 
					<a-episode :page="{title: "{{ page.title }}", podcasts: {{ object.podcasts|json }}}">
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										30
									
								
								aircox/templates/aircox/episode_form.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								aircox/templates/aircox/episode_form.html
									
									
									
									
									
										Normal file
									
								
							@ -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 %}
 | 
				
			||||||
 | 
					<a class="navbar-item" href="{% url 'episode-detail' object.slug %}" target="_self">
 | 
				
			||||||
 | 
					    <span class="icon is-small">
 | 
				
			||||||
 | 
					        <i class="fa fa-eye"></i>
 | 
				
			||||||
 | 
					    </span> 
 | 
				
			||||||
 | 
					    <span>{% translate "View" %}</span>
 | 
				
			||||||
 | 
					</a>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block main %}
 | 
				
			||||||
 | 
					<form method="post" enctype="multipart/form-data">{% csrf_token %}
 | 
				
			||||||
 | 
					    <table>
 | 
				
			||||||
 | 
					        {{ form.as_table }}
 | 
				
			||||||
 | 
					        {% render_honeypot_field "website" %}
 | 
				
			||||||
 | 
					    </table>
 | 
				
			||||||
 | 
					    <br/>
 | 
				
			||||||
 | 
					    <input type="submit" value="Update" class="button is-success">
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@ -25,12 +25,31 @@
 | 
				
			|||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block content %}
 | 
					{% block actions %}
 | 
				
			||||||
{% if not object.content %}
 | 
					{% if object.sound_set.public.count %}
 | 
				
			||||||
    {% with object.parent.content as content %}
 | 
					<button class="button" @click="player.playButtonClick($event)"
 | 
				
			||||||
    {{ block.super }}
 | 
					        data-sounds="{{ object.podcasts|json }}">
 | 
				
			||||||
    {% endwith %}
 | 
					    <span class="icon is-small">
 | 
				
			||||||
{% else %}
 | 
					        <span class="fas fa-play"></span>
 | 
				
			||||||
    {{ block.super }}
 | 
					    </span>
 | 
				
			||||||
 | 
					</button>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block actions %}
 | 
				
			||||||
 | 
					{% has_perm page object.program.change_permission_codename simple=True as can_edit %}
 | 
				
			||||||
 | 
					{% if can_edit %}
 | 
				
			||||||
 | 
					  <a class="button" href="{% url 'episode-edit' object.pk %}" target="_self">
 | 
				
			||||||
 | 
					    <span class="icon is-small"><i class="fas fa-pen" alt="{% trans 'edit' %}"></i></span>
 | 
				
			||||||
 | 
					  </a>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if object.sound_set.public.count %}
 | 
				
			||||||
 | 
					<button class="button" @click="player.playButtonClick($event)"
 | 
				
			||||||
 | 
					        data-sounds="{{ object.podcasts|json }}">
 | 
				
			||||||
 | 
					    <span class="icon is-small">
 | 
				
			||||||
 | 
					        <span class="fas fa-play"></span>
 | 
				
			||||||
 | 
					    </span>
 | 
				
			||||||
 | 
					</button>
 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
 | 
				
			|||||||
@ -114,6 +114,11 @@ urls = [
 | 
				
			|||||||
        views.EpisodeDetailView.as_view(),
 | 
					        views.EpisodeDetailView.as_view(),
 | 
				
			||||||
        name="episode-detail",
 | 
					        name="episode-detail",
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
 | 
					    path(
 | 
				
			||||||
 | 
					        _("programs/episodes/<pk>/edit/"),
 | 
				
			||||||
 | 
					        views.EpisodeUpdateView.as_view(),
 | 
				
			||||||
 | 
					        name="episode-edit",
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
    path(_("podcasts/"), views.PodcastListView.as_view(), name="podcast-list"),
 | 
					    path(_("podcasts/"), views.PodcastListView.as_view(), name="podcast-list"),
 | 
				
			||||||
    path(_("podcasts/c/<slug:category_slug>/"), views.PodcastListView.as_view(), name="podcast-list"),
 | 
					    path(_("podcasts/c/<slug:category_slug>/"), views.PodcastListView.as_view(), name="podcast-list"),
 | 
				
			||||||
    # ---- others
 | 
					    # ---- others
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@ from . import admin, errors
 | 
				
			|||||||
from .article import ArticleDetailView, ArticleListView
 | 
					from .article import ArticleDetailView, ArticleListView
 | 
				
			||||||
from .base import BaseAPIView, BaseView
 | 
					from .base import BaseAPIView, BaseView
 | 
				
			||||||
from .diffusion import DiffusionListView, TimeTableView
 | 
					from .diffusion import DiffusionListView, TimeTableView
 | 
				
			||||||
from .episode import EpisodeDetailView, EpisodeListView, PodcastListView
 | 
					from .episode import EpisodeDetailView, EpisodeListView, PodcastListView, EpisodeUpdateView
 | 
				
			||||||
from .home import HomeView
 | 
					from .home import HomeView
 | 
				
			||||||
from .log import LogListAPIView, LogListView
 | 
					from .log import LogListAPIView, LogListView
 | 
				
			||||||
from .page import (
 | 
					from .page import (
 | 
				
			||||||
@ -32,6 +32,7 @@ __all__ = (
 | 
				
			|||||||
    "EpisodeDetailView",
 | 
					    "EpisodeDetailView",
 | 
				
			||||||
    "EpisodeListView",
 | 
					    "EpisodeListView",
 | 
				
			||||||
    "PodcastListView",
 | 
					    "PodcastListView",
 | 
				
			||||||
 | 
					    "EpisodeUpdateView",
 | 
				
			||||||
    "HomeView",
 | 
					    "HomeView",
 | 
				
			||||||
    "LogListAPIView",
 | 
					    "LogListAPIView",
 | 
				
			||||||
    "LogListView",
 | 
					    "LogListView",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,20 @@
 | 
				
			|||||||
from django.shortcuts import reverse
 | 
					from django.contrib.auth.mixins import UserPassesTestMixin
 | 
				
			||||||
 | 
					from django.urls import reverse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aircox.forms import EpisodeForm
 | 
				
			||||||
from ..filters import EpisodeFilters
 | 
					from ..filters import EpisodeFilters
 | 
				
			||||||
from ..models import Episode, Program, StaticPage
 | 
					from ..models import Episode, Program, StaticPage
 | 
				
			||||||
from .page import PageListView
 | 
					from .page import PageListView
 | 
				
			||||||
from .program import ProgramPageDetailView
 | 
					from .program import ProgramPageDetailView, BaseProgramMixin
 | 
				
			||||||
 | 
					from .page import PageUpdateView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__all__ = (
 | 
					__all__ = (
 | 
				
			||||||
    "EpisodeDetailView",
 | 
					    "EpisodeDetailView",
 | 
				
			||||||
    "EpisodeListView",
 | 
					    "EpisodeListView",
 | 
				
			||||||
    "PodcastListView",
 | 
					    "PodcastListView",
 | 
				
			||||||
 | 
					    "EpisodeUpdateView",
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,3 +45,18 @@ class EpisodeListView(PageListView):
 | 
				
			|||||||
class PodcastListView(EpisodeListView):
 | 
					class PodcastListView(EpisodeListView):
 | 
				
			||||||
    attach_to_value = StaticPage.Target.PODCASTS
 | 
					    attach_to_value = StaticPage.Target.PODCASTS
 | 
				
			||||||
    queryset = Episode.objects.published().with_podcasts().order_by("-pub_date")
 | 
					    queryset = Episode.objects.published().with_podcasts().order_by("-pub_date")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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})
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user