<table class="main">
<thead>
<tr>
+ <th>{% trans "Channel" %}</th>
<th>{% trans "Title" %}</th>
<th>{% trans "Date" %}</th>
+ <th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
- {% for channel in object_list %}
+ {% for sound in object_list %}
<tr>
- <td><a href="{{ channel.channel_url }}">{{ channel.title }}</a></td>
- <td>{{ channel.creation_timestamp }}</td>
+ <td><a href="{{ sound.channel.channel_url }}">{{ sound.channel.title }}</a></td>
+ <td>{{ sound.title }}</td>
+ <td>{{ sound.creation_timestamp }}</td>
+ <td><a href="{% url 'earwig-sound-publish' pk=sound.pk %}">{% trans "Publish" %}</a> /
+ <a href="{% url 'earwig-sound-reject' pk=sound.pk %}">{% trans "Reject" %}</a></td>
+ </tr>
+ {% empty %}
+ <tr>
+ <td colspan="4">{% trans "Nothing to moderate" %}</td>
</tr>
{% endfor %}
</tbody>
urlpatterns = [
url(r'^$', views.homepage, name='earwig-manager-homepage'),
url(r'^channel/add/$', views.channel_add, name='earwig-channel-add'),
+ url(r'^sound/(?P<pk>\d+)/publish/$', views.sound_publish, name='earwig-sound-publish'),
+ url(r'^sound/(?P<pk>\d+)/reject/$', views.sound_reject, name='earwig-sound-reject'),
]
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.core.urlresolvers import reverse_lazy
-from django.views.generic import ListView, CreateView
+from django.contrib import messages
+from django.shortcuts import redirect
+from django.utils.translation import ugettext_lazy as _
+from django.views.generic import ListView, CreateView, DetailView
-from ..sounds.models import Channel
+from ..sounds.models import Channel, Sound
class Homepage(ListView):
- model = Channel
+ model = Sound
paginate_by = 10
template_name = 'earwig/manager_home.html'
+ def get_queryset(self, **kwargs):
+ return self.model.objects.filter(status='').select_related()
+
homepage = Homepage.as_view()
class ChannelAdd(CreateView):
model = Channel
- fields = ('title', 'channel_url', 'feed_url')
+ fields = ('title', 'channel_url', 'feed_url', 'policy')
template_name = 'earwig/manager_channel_add.html'
success_url = reverse_lazy('earwig-manager-homepage')
channel_add = ChannelAdd.as_view()
+
+
+class SoundPublishView(DetailView):
+ model = Sound
+
+ def get(self, *args, **kwargs):
+ self.get_object().publish()
+ messages.success(self.request, _('%s has been published.') % self.get_object())
+ return redirect('earwig-manager-homepage')
+
+sound_publish = SoundPublishView.as_view()
+
+
+class SoundRejectView(DetailView):
+ model = Sound
+
+ def get(self, *args, **kwargs):
+ self.get_object().reject()
+ messages.warning(self.request, _('%s has been rejected.') % self.get_object())
+ return redirect('earwig-manager-homepage')
+
+sound_reject = SoundRejectView.as_view()
--- /dev/null
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.11 on 2018-09-01 13:21
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('sounds', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='channel',
+ options={'ordering': ('title',)},
+ ),
+ migrations.AlterModelOptions(
+ name='sound',
+ options={'ordering': ('channel', 'original_publication_date', 'title')},
+ ),
+ migrations.AddField(
+ model_name='channel',
+ name='policy',
+ field=models.CharField(blank=True, choices=[('', 'Default (moderate)'), ('publish', 'Autopublish')], default='', max_length=20, verbose_name='Policy'),
+ ),
+ migrations.AddField(
+ model_name='sound',
+ name='status',
+ field=models.CharField(blank=True, choices=[('', 'Waiting for moderation'), ('published', 'Published'), ('unpublished', 'Unpublished'), ('rejected', 'Rejected')], default='', max_length=20, verbose_name='Publication Status'),
+ ),
+ migrations.AddIndex(
+ model_name='sound',
+ index=models.Index(fields=['status'], name='sounds_soun_status_7a871a_idx'),
+ ),
+ ]
from django.db import models
from django.utils.translation import ugettext_lazy as _
+POLICIES = [
+ ('', _('Default (moderate)')),
+ ('publish', _('Autopublish')),
+]
+
+STATUSES = [
+ ('', _('Waiting for moderation')),
+ ('published', _('Published')),
+ ('unpublished', _('Unpublished')),
+ ('rejected', _('Rejected')),
+]
+
class Channel(models.Model):
channel_url = models.URLField(_('Channel URL'))
title = models.CharField(_('Title'), max_length=200)
feed_url = models.URLField(_('Feed URL'), blank=True)
+ policy = models.CharField(_('Policy'), max_length=20,
+ default='', blank=True, choices=POLICIES)
creation_timestamp = models.DateTimeField(auto_now_add=True)
last_update_timestamp = models.DateTimeField(auto_now=True)
+ class Meta:
+ ordering = ('title',)
+
def __str__(self):
return self.title
file_size = models.IntegerField(_('File Size'), blank=True, null=True)
duration = models.IntegerField(_('Duration'), blank=True, null=True) # in seconds
+ status = models.CharField(_('Publication Status'), max_length=20,
+ default='', blank=True, choices=STATUSES)
creation_timestamp = models.DateTimeField(auto_now_add=True)
last_update_timestamp = models.DateTimeField(auto_now=True)
+ class Meta:
+ ordering = ('channel', 'original_publication_date', 'title')
+ indexes = [models.Index(fields=['status'])]
+
+ def publish(self):
+ self.status = 'published'
+ self.save()
+
+ def unpublish(self):
+ self.status = 'unpublished'
+ self.save()
+
+ def reject(self):
+ self.status = 'rejected'
+ self.save()
+
def __str__(self):
return self.title
if sound_url != sound.sound_url:
sound.sound_url = sound_url
sound.duration = None # reset
+ if created and self.channel.policy == 'publish':
+ sound.status = 'published'
sound.save()