fix
This commit is contained in:
		@ -1,7 +1,12 @@
 | 
				
			|||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
from django.forms import ModelForm
 | 
					from django.forms import ModelForm, ImageField, FileField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import Comment
 | 
					from ckeditor.fields import RichTextField
 | 
				
			||||||
 | 
					from filer.models.imagemodels import Image
 | 
				
			||||||
 | 
					from filer.models.filemodels import File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from aircox.models import Comment, Episode, Program
 | 
				
			||||||
 | 
					from aircox.controllers.sound_file import SoundFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CommentForm(ModelForm):
 | 
					class CommentForm(ModelForm):
 | 
				
			||||||
@ -16,3 +21,38 @@ class CommentForm(ModelForm):
 | 
				
			|||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = Comment
 | 
					        model = Comment
 | 
				
			||||||
        fields = ["nickname", "email", "content"]
 | 
					        fields = ["nickname", "email", "content"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProgramForm(ModelForm):
 | 
				
			||||||
 | 
					    content = RichTextField()
 | 
				
			||||||
 | 
					    new_cover = ImageField(required=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        model = Program
 | 
				
			||||||
 | 
					        fields = ["content"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save(self, commit=True):
 | 
				
			||||||
 | 
					        file_obj = self.cleaned_data["new_cover"]
 | 
				
			||||||
 | 
					        if file_obj:
 | 
				
			||||||
 | 
					            obj, _ = Image.objects.get_or_create(original_filename=file_obj.name, file=file_obj)
 | 
				
			||||||
 | 
					            self.instance.cover = obj
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        super().save(commit=commit)
 | 
				
			||||||
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -125,6 +125,7 @@ class Program(Page):
 | 
				
			|||||||
        editors, created = Group.objects.get_or_create(name=self.editors_group_name)
 | 
					        editors, created = Group.objects.get_or_create(name=self.editors_group_name)
 | 
				
			||||||
        if created:
 | 
					        if created:
 | 
				
			||||||
            self.editors = editors
 | 
					            self.editors = editors
 | 
				
			||||||
 | 
					            super().save()
 | 
				
			||||||
        permission, _ = Permission.objects.get_or_create(
 | 
					        permission, _ = Permission.objects.get_or_create(
 | 
				
			||||||
            name=f"change program {self.title}",
 | 
					            name=f"change program {self.title}",
 | 
				
			||||||
            codename=self.change_permission_codename,
 | 
					            codename=self.change_permission_codename,
 | 
				
			||||||
@ -159,7 +160,6 @@ class Program(Page):
 | 
				
			|||||||
            Sound.objects.filter(path__startswith=path_).update(file=Concat("file", Substr(F("file"), len(path_))))
 | 
					            Sound.objects.filter(path__startswith=path_).update(file=Concat("file", Substr(F("file"), len(path_))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.set_group_ownership()
 | 
					        self.set_group_ownership()
 | 
				
			||||||
        super().save(*kargs, **kwargs)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProgramChildQuerySet(PageQuerySet):
 | 
					class ProgramChildQuerySet(PageQuerySet):
 | 
				
			||||||
 | 
				
			|||||||
@ -81,6 +81,9 @@ class Station(models.Model):
 | 
				
			|||||||
        max_length=64,
 | 
					        max_length=64,
 | 
				
			||||||
        default=_("Music stream"),
 | 
					        default=_("Music stream"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					    legal_label = models.CharField(
 | 
				
			||||||
 | 
					        _("Legal label"), max_length=64, blank=True, default="", help_text=_("Displayed at the bottom of pages.")
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    objects = StationQuerySet.as_manager()
 | 
					    objects = StationQuerySet.as_manager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -51,7 +51,7 @@ Usefull context:
 | 
				
			|||||||
            <div class="navs">
 | 
					            <div class="navs">
 | 
				
			||||||
                {% block nav %}
 | 
					                {% block nav %}
 | 
				
			||||||
                <nav class="nav primary" role="navigation" aria-label="main navigation">
 | 
					                <nav class="nav primary" role="navigation" aria-label="main navigation">
 | 
				
			||||||
                    {% block nav-primary %}
 | 
					                    {% block primary-nav %}
 | 
				
			||||||
                    <a class="nav-brand" href="{% url "home" %}">
 | 
					                    <a class="nav-brand" href="{% url "home" %}">
 | 
				
			||||||
                        <img src="{{ station.logo.url }}">
 | 
					                        <img src="{{ station.logo.url }}">
 | 
				
			||||||
                    </a>
 | 
					                    </a>
 | 
				
			||||||
@ -60,7 +60,7 @@ Usefull context:
 | 
				
			|||||||
                        aria-label="{% translate "Main menu" %}">
 | 
					                        aria-label="{% translate "Main menu" %}">
 | 
				
			||||||
                    </a-switch>
 | 
					                    </a-switch>
 | 
				
			||||||
                    <div class="nav-menu">
 | 
					                    <div class="nav-menu">
 | 
				
			||||||
                        {% block nav-primary-menu %}
 | 
					                        {% block primary-nav-menu %}
 | 
				
			||||||
                        {% nav_items "top" css_class="nav-item" active_class="active" as items %}
 | 
					                        {% nav_items "top" css_class="nav-item" active_class="active" as items %}
 | 
				
			||||||
                        {% for item, render in items %}
 | 
					                        {% for item, render in items %}
 | 
				
			||||||
                        {{ render }}
 | 
					                        {{ render }}
 | 
				
			||||||
@ -71,11 +71,9 @@ Usefull context:
 | 
				
			|||||||
                        </a>
 | 
					                        </a>
 | 
				
			||||||
                        {% endif %}
 | 
					                        {% endif %}
 | 
				
			||||||
                        {% if user.is_authenticated %}
 | 
					                        {% if user.is_authenticated %}
 | 
				
			||||||
                        <a class="nav-item" href="{% url "profile" %}" target="new">
 | 
					                        <a class="nav-item" href="{% url "logout" %}" title="{% translate "Disconnect" %}"
 | 
				
			||||||
                            {% translate "Profile" %}
 | 
					                            aria-label="{% translate "Disconnect" %}">
 | 
				
			||||||
                        </a>
 | 
					                            <i class="fa fa-power-off"></i>
 | 
				
			||||||
                        <a class="nav-item" href="{% url 'logout' %}">
 | 
					 | 
				
			||||||
                            <i title="{% translate 'disconnect' %}" class="fa fa-power-off"></i>
 | 
					 | 
				
			||||||
                        </a>
 | 
					                        </a>
 | 
				
			||||||
                        {% endif %}
 | 
					                        {% endif %}
 | 
				
			||||||
                        {% endblock %}
 | 
					                        {% endblock %}
 | 
				
			||||||
@ -98,8 +96,6 @@ Usefull context:
 | 
				
			|||||||
                {% endblock %}
 | 
					                {% endblock %}
 | 
				
			||||||
                {% endspaceless %}
 | 
					                {% endspaceless %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                {% block header-container %}
 | 
					                {% block header-container %}
 | 
				
			||||||
                {% if page or cover or title %}
 | 
					                {% if page or cover or title %}
 | 
				
			||||||
                <header class="container header preview preview-header {% if cover %}has-cover{% endif %}">
 | 
					                <header class="container header preview preview-header {% if cover %}has-cover{% endif %}">
 | 
				
			||||||
@ -146,6 +142,24 @@ Usefull context:
 | 
				
			|||||||
            {% endblock %}
 | 
					            {% endblock %}
 | 
				
			||||||
            </main>
 | 
					            </main>
 | 
				
			||||||
            {% endblock %}
 | 
					            {% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            {% block footer-container %}
 | 
				
			||||||
 | 
					            <footer class="page-footer">
 | 
				
			||||||
 | 
					                {% block footer %}
 | 
				
			||||||
 | 
					                {% if request.station and request.station.legal_label %}
 | 
				
			||||||
 | 
					                {{ request.station.legal_label }} —
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <a class="nav-item" href="{% url "profile" %}" target="new"
 | 
				
			||||||
 | 
					                        title="{% translate "Profile" %}">
 | 
				
			||||||
 | 
					                    <span class="small icon">
 | 
				
			||||||
 | 
					                        <i class="fa fa-account">
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                </a>
 | 
				
			||||||
 | 
					                {% endblock %}
 | 
				
			||||||
 | 
					            </footer>
 | 
				
			||||||
 | 
					            {% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        {% block player-container %}
 | 
					        {% block player-container %}
 | 
				
			||||||
        <div id="player">{% include "aircox/widgets/player.html" %}</div>
 | 
					        <div id="player">{% include "aircox/widgets/player.html" %}</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -4,15 +4,19 @@
 | 
				
			|||||||
{% if user.is_authenticated and can_edit %}
 | 
					{% if user.is_authenticated and can_edit %}
 | 
				
			||||||
{% with request.resolver_match.view_name as view_name %}
 | 
					{% with request.resolver_match.view_name as view_name %}
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
  {% if view_name in 'program-edit,bla' %}
 | 
					  {% if view_name in 'page-edit,program-edit,episode-edit' %}
 | 
				
			||||||
  <!--
 | 
					  <a href="{% url view_name|detail_view page.slug %}" target="_self">
 | 
				
			||||||
  <a href="{% url 'program-detail' page.slug %}" target="_self">
 | 
					      <small>
 | 
				
			||||||
      <span title="{% translate 'View' %} {{ page }}">{% translate 'View' %} 👁 </span>
 | 
					      <span title="{% translate 'View' %} {{ page }}">{% translate 'View' %} </span>
 | 
				
			||||||
 | 
					      <i class="fa-regular fa-eye"></i>
 | 
				
			||||||
 | 
					      </small>
 | 
				
			||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
  -->
 | 
					 | 
				
			||||||
  {% else %}
 | 
					  {% else %}
 | 
				
			||||||
  <a href="{% url view_name|edit_view page.pk %}" target="_self">
 | 
					  <a href="{% url view_name|edit_view page.pk %}" target="_self">
 | 
				
			||||||
      <span title="{% translate 'Edit' %} {{ page }}">{% translate 'Edit' %} 🖉  </span>
 | 
					      <small>
 | 
				
			||||||
 | 
					      <span title="{% translate 'Edit' %} {{ page }}">{% translate 'Edit' %} </span>
 | 
				
			||||||
 | 
					      <i class="fa-solid fa-pencil"></i>
 | 
				
			||||||
 | 
					      </small>
 | 
				
			||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
  {% endif %}
 | 
					  {% endif %}
 | 
				
			||||||
{% endwith %}
 | 
					{% endwith %}
 | 
				
			||||||
 | 
				
			|||||||
@ -23,10 +23,10 @@
 | 
				
			|||||||
    <table>
 | 
					    <table>
 | 
				
			||||||
        {{ form.as_table }}
 | 
					        {{ form.as_table }}
 | 
				
			||||||
        {% render_honeypot_field "website" %}
 | 
					        {% render_honeypot_field "website" %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
    </table>
 | 
					    </table>
 | 
				
			||||||
    <br/>
 | 
					    <br/>
 | 
				
			||||||
    <input type="submit" value="Update" class="button is-success">
 | 
					    <input type="submit" value="Update" class="button is-success">
 | 
				
			||||||
 | 
					    <hr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {% include "aircox/playlist_inline.html" %}
 | 
					    {% include "aircox/playlist_inline.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,12 +16,23 @@
 | 
				
			|||||||
<section class="container">
 | 
					<section class="container">
 | 
				
			||||||
<div>
 | 
					<div>
 | 
				
			||||||
<form method="post" enctype="multipart/form-data">{% csrf_token %}
 | 
					<form method="post" enctype="multipart/form-data">{% csrf_token %}
 | 
				
			||||||
    <table>
 | 
					    {% csrf_token %}
 | 
				
			||||||
        {{ form.as_table }}
 | 
					    {% for field in form %}
 | 
				
			||||||
        {% render_honeypot_field "website" %}
 | 
					    <div class="field is-horizontal">
 | 
				
			||||||
    </table>
 | 
					        <label class="label">{{ field.label }}</label>
 | 
				
			||||||
    <br/>
 | 
					        <div class="control">{{ field }}</div>
 | 
				
			||||||
    <input type="submit" value="Update" class="button is-success">
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% if field.errors %}
 | 
				
			||||||
 | 
					    <p class="help is-danger">{{ field.errors }}</p>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					    {% if field.help_text %}
 | 
				
			||||||
 | 
					    <p class="help">{{ field.help_text|safe }}</p>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="has-text-right">
 | 
				
			||||||
 | 
					        <button type="submit" class="button">{% translate "Update" %}</button>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
</form>
 | 
					</form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</section>
 | 
					</section>
 | 
				
			||||||
 | 
				
			|||||||
@ -143,3 +143,8 @@ def do_verbose_name(obj, plural=False):
 | 
				
			|||||||
@register.filter(name="edit_view")
 | 
					@register.filter(name="edit_view")
 | 
				
			||||||
def do_edit_view(obj):
 | 
					def do_edit_view(obj):
 | 
				
			||||||
    return "%s-edit" % obj.split("-")[0]
 | 
					    return "%s-edit" % obj.split("-")[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@register.filter(name="detail_view")
 | 
				
			||||||
 | 
					def do_detail_view(obj):
 | 
				
			||||||
 | 
					    return "%s-detail" % obj.split("-")[0]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
from datetime import time, timedelta
 | 
					from datetime import time, timedelta
 | 
				
			||||||
import itertools
 | 
					import itertools
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
@ -162,3 +163,10 @@ def tracks(episode, sound):
 | 
				
			|||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def user():
 | 
					def user():
 | 
				
			||||||
    return User.objects.create_user(username="user1", password="bar")
 | 
					    return User.objects.create_user(username="user1", password="bar")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def png_content():
 | 
				
			||||||
 | 
					    image_file = "{}/image.png".format(os.path.dirname(__file__))
 | 
				
			||||||
 | 
					    with open(image_file, "rb") as fh:
 | 
				
			||||||
 | 
					        return fh.read()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								aircox/tests/image.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								aircox/tests/image.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 69 B  | 
@ -7,12 +7,6 @@ from django.core.files.uploadedfile import SimpleUploadedFile
 | 
				
			|||||||
from aircox.models import Program
 | 
					from aircox.models import Program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
png_content = (
 | 
					 | 
				
			||||||
    b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde"
 | 
					 | 
				
			||||||
    + b"\x00\x00\x00\x0cIDATx\x9cc`\xf8\xcf\x00\x00\x02\x02\x01\x00{\t\x81x\x00\x00\x00\x00IEND\xaeB`\x82"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@pytest.mark.django_db()
 | 
					@pytest.mark.django_db()
 | 
				
			||||||
def test_edit_program(user, client, program):
 | 
					def test_edit_program(user, client, program):
 | 
				
			||||||
    client.force_login(user)
 | 
					    client.force_login(user)
 | 
				
			||||||
@ -29,7 +23,7 @@ def test_edit_program(user, client, program):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.django_db()
 | 
					@pytest.mark.django_db()
 | 
				
			||||||
def test_add_cover(user, client, program):
 | 
					def test_add_cover(user, client, program, png_content):
 | 
				
			||||||
    assert program.cover is None
 | 
					    assert program.cover is None
 | 
				
			||||||
    user.groups.add(program.editors)
 | 
					    user.groups.add(program.editors)
 | 
				
			||||||
    client.force_login(user)
 | 
					    client.force_login(user)
 | 
				
			||||||
@ -58,16 +52,16 @@ def test_edit_tracklist(user, client, program, episode, tracks):
 | 
				
			|||||||
    tracklist = [t.id for t in episode.track_set.all().order_by("position")]
 | 
					    tracklist = [t.id for t in episode.track_set.all().order_by("position")]
 | 
				
			||||||
    tracklist_details_reversed = [(t.id, t.artist, t.title) for t in episode.track_set.all().order_by("-position")]
 | 
					    tracklist_details_reversed = [(t.id, t.artist, t.title) for t in episode.track_set.all().order_by("-position")]
 | 
				
			||||||
    tracklist_details_reversed = list(chain(*tracklist_details_reversed))
 | 
					    tracklist_details_reversed = list(chain(*tracklist_details_reversed))
 | 
				
			||||||
    data = """{"website": [""], "content": ["foobar"], "new_podcast": [""], "form-TOTAL_FORMS": ["3"],
 | 
					    data = """{{"website": [""], "content": ["foobar"], "new_podcast": [""], "form-TOTAL_FORMS": ["3"],
 | 
				
			||||||
    "form-INITIAL_FORMS": ["3"], "form-MIN_NUM_FORMS": ["0"], "form-MAX_NUM_FORMS": ["1000"], "form-0-position": ["0"],
 | 
					    "form-INITIAL_FORMS": ["3"], "form-MIN_NUM_FORMS": ["0"], "form-MAX_NUM_FORMS": ["1000"], "form-0-position": ["0"],
 | 
				
			||||||
    "form-0-id": ["%s"], "form-0-": ["", "", "", "", "", ""], "form-0-artist": ["%s"], "form-0-title": ["%s"],
 | 
					    "form-0-id": ["{}"], "form-0-": ["", "", "", "", "", ""], "form-0-artist": ["{}"], "form-0-title": ["{}"],
 | 
				
			||||||
    "form-0-tags": [""], "form-0-album": [""], "form-0-year": [""], "form-1-position": ["1"], "form-1-id": ["%s"],
 | 
					    "form-0-tags": [""], "form-0-album": [""], "form-0-year": [""], "form-1-position": ["1"], "form-1-id": ["{}"],
 | 
				
			||||||
    "form-1-": ["", "", "", "", "", ""], "form-1-artist": ["%s"], "form-1-title": ["%s"], "form-1-tags": [""],
 | 
					    "form-1-": ["", "", "", "", "", ""], "form-1-artist": ["{}"], "form-1-title": ["{}"], "form-1-tags": [""],
 | 
				
			||||||
    "form-1-album": [""], "form-1-year": [""], "form-2-position": ["2"], "form-2-id": ["%s"], "form-2-": ["", "", "",
 | 
					    "form-1-album": [""], "form-1-year": [""], "form-2-position": ["2"], "form-2-id": ["{}"], "form-2-": ["", "", "",
 | 
				
			||||||
    "", "", ""], "form-2-artist": ["%s"], "form-2-title": ["%s"], "form-2-tags": [""], "form-2-album": [""],
 | 
					    "", "", ""], "form-2-artist": ["{}"], "form-2-title": ["{}"], "form-2-tags": [""], "form-2-album": [""],
 | 
				
			||||||
    "form-2-year": [""]}""" % tuple(
 | 
					    "form-2-year": [""]}}""".format(
 | 
				
			||||||
        tracklist_details_reversed
 | 
					        *tracklist_details_reversed
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    r = client.post(reverse("episode-edit", kwargs={"pk": episode.pk}), json.loads(data), follow=True)
 | 
					    r = client.post(reverse("episode-edit", kwargs={"pk": episode.pk}), json.loads(data), follow=True)
 | 
				
			||||||
    assert r.status_code == 200
 | 
					    assert r.status_code == 200
 | 
				
			||||||
    assert [t.id for t in episode.track_set.all().order_by("position")] == list(reversed(tracklist))
 | 
					    assert set(episode.track_set.all().values_list("id", flat=True)) == set(tracklist)
 | 
				
			||||||
 | 
				
			|||||||
@ -132,6 +132,6 @@ urls = [
 | 
				
			|||||||
        views.errors.NoStationErrorView.as_view(),
 | 
					        views.errors.NoStationErrorView.as_view(),
 | 
				
			||||||
        name="errors-no-station",
 | 
					        name="errors-no-station",
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    path("gestion/", views.profile, name="profile"),
 | 
					    path(_("manage/"), views.ProfileView.as_view(), name="profile"),
 | 
				
			||||||
    path("accounts/profile/", views.profile, name="profile"),
 | 
					    path("accounts/profile/", views.ProfileView.as_view(), name="profile"),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ from .page import (
 | 
				
			|||||||
    PageDetailView,
 | 
					    PageDetailView,
 | 
				
			||||||
    PageListView,
 | 
					    PageListView,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from .profile import profile
 | 
					from .profile import ProfileView
 | 
				
			||||||
from .program import (
 | 
					from .program import (
 | 
				
			||||||
    ProgramDetailView,
 | 
					    ProgramDetailView,
 | 
				
			||||||
    ProgramListView,
 | 
					    ProgramListView,
 | 
				
			||||||
@ -40,7 +40,7 @@ __all__ = (
 | 
				
			|||||||
    "BasePageListView",
 | 
					    "BasePageListView",
 | 
				
			||||||
    "PageDetailView",
 | 
					    "PageDetailView",
 | 
				
			||||||
    "PageListView",
 | 
					    "PageListView",
 | 
				
			||||||
    "profile",
 | 
					    "ProfileView",
 | 
				
			||||||
    "ProgramDetailView",
 | 
					    "ProgramDetailView",
 | 
				
			||||||
    "ProgramListView",
 | 
					    "ProgramListView",
 | 
				
			||||||
    "ProgramPageDetailView",
 | 
					    "ProgramPageDetailView",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,16 +1,10 @@
 | 
				
			|||||||
from django.contrib.auth.mixins import UserPassesTestMixin
 | 
					from django.contrib.auth.mixins import UserPassesTestMixin
 | 
				
			||||||
from django.forms import ModelForm, FileField
 | 
					 | 
				
			||||||
from django.forms.models import modelformset_factory
 | 
					from django.forms.models import modelformset_factory
 | 
				
			||||||
from django.urls import reverse
 | 
					from django.urls import reverse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ckeditor.fields import RichTextField
 | 
					from aircox.forms import EpisodeForm
 | 
				
			||||||
from filer.models.filemodels import File
 | 
					from aircox.models import Episode, Program, StaticPage, Track
 | 
				
			||||||
 | 
					 | 
				
			||||||
from aircox.controllers.sound_file import SoundFile
 | 
					 | 
				
			||||||
from aircox.models import Track
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from ..filters import EpisodeFilters
 | 
					from ..filters import EpisodeFilters
 | 
				
			||||||
from ..models import Episode, Program, StaticPage
 | 
					 | 
				
			||||||
from .page import PageListView
 | 
					from .page import PageListView
 | 
				
			||||||
from .program import ProgramPageDetailView, BaseProgramMixin
 | 
					from .program import ProgramPageDetailView, BaseProgramMixin
 | 
				
			||||||
from .page import PageUpdateView
 | 
					from .page import PageUpdateView
 | 
				
			||||||
@ -53,25 +47,6 @@ class PodcastListView(EpisodeListView):
 | 
				
			|||||||
    queryset = Episode.objects.published().with_podcasts().order_by("-pub_date")
 | 
					    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
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        super().save(commit=commit)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class EpisodeUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
 | 
					class EpisodeUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
 | 
				
			||||||
    model = Episode
 | 
					    model = Episode
 | 
				
			||||||
    form_class = EpisodeForm
 | 
					    form_class = EpisodeForm
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ __all__ = [
 | 
				
			|||||||
    "BasePageDetailView",
 | 
					    "BasePageDetailView",
 | 
				
			||||||
    "PageDetailView",
 | 
					    "PageDetailView",
 | 
				
			||||||
    "PageListView",
 | 
					    "PageListView",
 | 
				
			||||||
 | 
					    "PageUpdateView",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,15 +1,15 @@
 | 
				
			|||||||
from django.contrib.auth.decorators import login_required
 | 
					from django.contrib.auth.mixins import LoginRequiredMixin
 | 
				
			||||||
from django.template.response import TemplateResponse
 | 
					from django.views.generic.base import TemplateView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from aircox.models import Program
 | 
					from aircox.models import Program
 | 
				
			||||||
 | 
					from aircox.views import BaseView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@login_required
 | 
					class ProfileView(LoginRequiredMixin, BaseView, TemplateView):
 | 
				
			||||||
def profile(request):
 | 
					    template_name = "accounts/profile.html"
 | 
				
			||||||
    programs = []
 | 
					
 | 
				
			||||||
    ugroups = request.user.groups.all()
 | 
					    def get_context_data(self, **kwargs):
 | 
				
			||||||
    for p in Program.objects.all():
 | 
					        groups = self.request.user.groups.all()
 | 
				
			||||||
        if p.editors in ugroups:
 | 
					        programs = Program.objects.filter(editors__in=groups)
 | 
				
			||||||
            programs.append(p)
 | 
					        kwargs.update({"user": self.request.user, "programs": programs})
 | 
				
			||||||
    context = {"user": request.user, "programs": programs}
 | 
					        return super().get_context_data(**kwargs)
 | 
				
			||||||
    return TemplateResponse(request, "accounts/profile.html", context)
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,10 @@
 | 
				
			|||||||
import random
 | 
					import random
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.mixins import UserPassesTestMixin
 | 
					from django.contrib.auth.mixins import UserPassesTestMixin
 | 
				
			||||||
from django.forms import ModelForm, ImageField
 | 
					 | 
				
			||||||
from django.urls import reverse
 | 
					from django.urls import reverse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ckeditor.fields import RichTextField
 | 
					from aircox.forms import ProgramForm
 | 
				
			||||||
from filer.models.imagemodels import Image
 | 
					from aircox.models import Article, Episode, Page, Program, StaticPage
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from ..models import Article, Episode, Page, Program, StaticPage
 | 
					 | 
				
			||||||
from .mixins import ParentMixin
 | 
					from .mixins import ParentMixin
 | 
				
			||||||
from .page import PageDetailView, PageListView, PageUpdateView
 | 
					from .page import PageDetailView, PageListView, PageUpdateView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -56,22 +52,6 @@ class ProgramDetailView(BaseProgramMixin, PageDetailView):
 | 
				
			|||||||
        return super().get_template_names() + ["aircox/program_detail.html"]
 | 
					        return super().get_template_names() + ["aircox/program_detail.html"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProgramForm(ModelForm):
 | 
					 | 
				
			||||||
    content = RichTextField()
 | 
					 | 
				
			||||||
    new_cover = ImageField(required=False)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    class Meta:
 | 
					 | 
				
			||||||
        model = Program
 | 
					 | 
				
			||||||
        fields = ["content"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def save(self, commit=True):
 | 
					 | 
				
			||||||
        file_obj = self.cleaned_data["new_cover"]
 | 
					 | 
				
			||||||
        if file_obj:
 | 
					 | 
				
			||||||
            obj, _ = Image.objects.get_or_create(original_filename=file_obj.name, file=file_obj)
 | 
					 | 
				
			||||||
            self.instance.cover = obj
 | 
					 | 
				
			||||||
        super().save(commit=commit)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ProgramUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
 | 
					class ProgramUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
 | 
				
			||||||
    model = Program
 | 
					    model = Program
 | 
				
			||||||
    form_class = ProgramForm
 | 
					    form_class = ProgramForm
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user