mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-22 14:13:21 +00:00
Merge branch 'nabos' into 'master'
Communication screens See merge request ae/Sith!116
This commit is contained in:
commit
10dfb2c122
@ -11,6 +11,7 @@
|
|||||||
<li> <a href="{{ url('trombi:detail', trombi_id=object.trombi.id) }}">{% trans %}Edit Trombi{% endtrans %}</a></li>
|
<li> <a href="{{ url('trombi:detail', trombi_id=object.trombi.id) }}">{% trans %}Edit Trombi{% endtrans %}</a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li> <a href="{{ url('trombi:create', club_id=object.id) }}">{% trans %}New Trombi{% endtrans %}</a></li>
|
<li> <a href="{{ url('trombi:create', club_id=object.id) }}">{% trans %}New Trombi{% endtrans %}</a></li>
|
||||||
|
<li> <a href="{{ url('club:poster_list', club_id=object.id) }}">{% trans %}Posters{% endtrans %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
<h4>{% trans %}Counters:{% endtrans %}</h4>
|
<h4>{% trans %}Counters:{% endtrans %}</h4>
|
||||||
|
@ -50,4 +50,8 @@ urlpatterns = [
|
|||||||
url(r'^(?P<mailing_id>[0-9]+)/mailing/delete$', MailingDeleteView.as_view(), name='mailing_delete'),
|
url(r'^(?P<mailing_id>[0-9]+)/mailing/delete$', MailingDeleteView.as_view(), name='mailing_delete'),
|
||||||
url(r'^(?P<mailing_subscription_id>[0-9]+)/mailing/delete/subscription$', MailingSubscriptionDeleteView.as_view(), name='mailing_subscription_delete'),
|
url(r'^(?P<mailing_subscription_id>[0-9]+)/mailing/delete/subscription$', MailingSubscriptionDeleteView.as_view(), name='mailing_subscription_delete'),
|
||||||
url(r'^membership/(?P<membership_id>[0-9]+)/set_old$', MembershipSetOldView.as_view(), name='membership_set_old'),
|
url(r'^membership/(?P<membership_id>[0-9]+)/set_old$', MembershipSetOldView.as_view(), name='membership_set_old'),
|
||||||
|
url(r'^(?P<club_id>[0-9]+)/poster$', PosterListView.as_view(), name='poster_list'),
|
||||||
|
url(r'^(?P<club_id>[0-9]+)/poster/create$', PosterCreateView.as_view(), name='poster_create'),
|
||||||
|
url(r'^(?P<club_id>[0-9]+)/poster/(?P<poster_id>[0-9]+)/edit$', PosterEditView.as_view(), name='poster_edit'),
|
||||||
|
url(r'^(?P<club_id>[0-9]+)/poster/(?P<poster_id>[0-9]+)/delete$', PosterDeleteView.as_view(), name='poster_delete'),
|
||||||
]
|
]
|
||||||
|
@ -37,12 +37,14 @@ from ajax_select.fields import AutoCompleteSelectField
|
|||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
|
|
||||||
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, PageEditViewBase
|
from core.views import CanCreateMixin, CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, PageEditViewBase
|
||||||
from core.views.forms import SelectDate, SelectDateTime
|
from core.views.forms import SelectDate, SelectDateTime
|
||||||
from club.models import Club, Membership, Mailing, MailingSubscription
|
from club.models import Club, Membership, Mailing, MailingSubscription
|
||||||
from sith.settings import SITH_MAXIMUM_FREE_ROLE
|
from sith.settings import SITH_MAXIMUM_FREE_ROLE
|
||||||
from counter.models import Selling, Counter
|
from counter.models import Selling, Counter
|
||||||
from core.models import User, PageRev
|
from core.models import User, PageRev
|
||||||
|
from com.views import PosterListBaseView, PosterCreateBaseView, PosterEditBaseView, PosterDeleteBaseView
|
||||||
|
from com.models import Poster
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
@ -86,8 +88,9 @@ class MailingSubscriptionForm(forms.ModelForm):
|
|||||||
|
|
||||||
class ClubTabsMixin(TabedViewMixin):
|
class ClubTabsMixin(TabedViewMixin):
|
||||||
def get_tabs_title(self):
|
def get_tabs_title(self):
|
||||||
if isinstance(self.object, PageRev):
|
obj = self.get_object()
|
||||||
self.object = self.object.page.club
|
if isinstance(obj, PageRev):
|
||||||
|
self.object = obj.page.club
|
||||||
return self.object.get_display_name()
|
return self.object.get_display_name()
|
||||||
|
|
||||||
def get_list_of_tabs(self):
|
def get_list_of_tabs(self):
|
||||||
@ -141,6 +144,11 @@ class ClubTabsMixin(TabedViewMixin):
|
|||||||
'slug': 'mailing',
|
'slug': 'mailing',
|
||||||
'name': _("Mailing list"),
|
'name': _("Mailing list"),
|
||||||
})
|
})
|
||||||
|
tab_list.append({
|
||||||
|
'url': reverse('club:poster_list', kwargs={'club_id': self.object.id}),
|
||||||
|
'slug': 'posters',
|
||||||
|
'name': _("Posters list"),
|
||||||
|
})
|
||||||
if self.request.user.is_owner(self.object):
|
if self.request.user.is_owner(self.object):
|
||||||
tab_list.append({
|
tab_list.append({
|
||||||
'url': reverse('club:club_prop', kwargs={'club_id': self.object.id}),
|
'url': reverse('club:club_prop', kwargs={'club_id': self.object.id}),
|
||||||
@ -592,3 +600,51 @@ class MailingAutoCleanView(View):
|
|||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.mailing.subscriptions.all().delete()
|
self.mailing.subscriptions.all().delete()
|
||||||
return redirect('club:mailing', club_id=self.mailing.club.id)
|
return redirect('club:mailing', club_id=self.mailing.club.id)
|
||||||
|
|
||||||
|
|
||||||
|
class PosterListView(ClubTabsMixin, PosterListBaseView, CanViewMixin):
|
||||||
|
"""List communication posters"""
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
return self.club
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterListView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['app'] = "club"
|
||||||
|
kwargs['club'] = self.club
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PosterCreateView(PosterCreateBaseView, CanCreateMixin):
|
||||||
|
"""Create communication poster"""
|
||||||
|
|
||||||
|
pk_url_kwarg = "club_id"
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
obj = super(PosterCreateView, self).get_object()
|
||||||
|
if not obj:
|
||||||
|
return self.club
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def get_success_url(self, **kwargs):
|
||||||
|
return reverse_lazy('club:poster_list', kwargs={'club_id': self.club.id})
|
||||||
|
|
||||||
|
|
||||||
|
class PosterEditView(ClubTabsMixin, PosterEditBaseView, CanEditMixin):
|
||||||
|
"""Edit communication poster"""
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse_lazy('club:poster_list', kwargs={'club_id': self.club.id})
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterEditView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['app'] = "club"
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PosterDeleteView(PosterDeleteBaseView, ClubTabsMixin, CanEditMixin):
|
||||||
|
"""Delete communication poster"""
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse_lazy('club:poster_list', kwargs={'club_id': self.club.id})
|
||||||
|
|
||||||
|
@ -39,4 +39,6 @@ class WeekmailAdmin(SearchModelAdmin):
|
|||||||
admin.site.register(Sith)
|
admin.site.register(Sith)
|
||||||
admin.site.register(News, NewsAdmin)
|
admin.site.register(News, NewsAdmin)
|
||||||
admin.site.register(Weekmail, WeekmailAdmin)
|
admin.site.register(Weekmail, WeekmailAdmin)
|
||||||
|
admin.site.register(Screen)
|
||||||
|
admin.site.register(Poster)
|
||||||
|
|
||||||
|
44
com/migrations/0004_auto_20171221_1614.py
Normal file
44
com/migrations/0004_auto_20171221_1614.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('club', '0010_auto_20170912_2028'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('com', '0003_auto_20170115_2300'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Poster',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
|
||||||
|
('name', models.CharField(verbose_name='name', max_length=128, default='')),
|
||||||
|
('file', models.ImageField(verbose_name='file', upload_to='com/posters')),
|
||||||
|
('date_begin', models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
|
('date_end', models.DateTimeField(blank=True, null=True)),
|
||||||
|
('display_time', models.IntegerField(verbose_name='display time', default=30)),
|
||||||
|
('is_moderated', models.BooleanField(verbose_name='is moderated', default=False)),
|
||||||
|
('club', models.ForeignKey(verbose_name='club', related_name='posters', to='club.Club')),
|
||||||
|
('moderator', models.ForeignKey(verbose_name='moderator', blank=True, null=True, related_name='moderated_posters', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Screen',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
|
||||||
|
('name', models.CharField(verbose_name='name', max_length=128)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='poster',
|
||||||
|
name='screens',
|
||||||
|
field=models.ManyToManyField(related_name='posters', to='com.Screen'),
|
||||||
|
),
|
||||||
|
]
|
@ -2,6 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright 2016,2017
|
# Copyright 2016,2017
|
||||||
# - Skia <skia@libskia.so>
|
# - Skia <skia@libskia.so>
|
||||||
|
# - Sli <antoine@bartuccio.fr>
|
||||||
#
|
#
|
||||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||||
# http://ae.utbm.fr.
|
# http://ae.utbm.fr.
|
||||||
@ -31,11 +32,16 @@ from django.core.urlresolvers import reverse
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.staticfiles.templatetags.staticfiles import static
|
from django.contrib.staticfiles.templatetags.staticfiles import static
|
||||||
from django.core.mail import EmailMultiAlternatives
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from core.models import User, Preferences, RealGroup, Notification
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from core.models import User, Preferences, RealGroup, Notification, SithFile
|
||||||
from club.models import Club
|
from club.models import Club
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Sith(models.Model):
|
class Sith(models.Model):
|
||||||
"""A one instance class storing all the modifiable infos"""
|
"""A one instance class storing all the modifiable infos"""
|
||||||
alert_msg = models.TextField(_("alert message"), default="", blank=True)
|
alert_msg = models.TextField(_("alert message"), default="", blank=True)
|
||||||
@ -183,3 +189,54 @@ class WeekmailArticle(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s - %s (%s)" % (self.title, self.author, self.club)
|
return "%s - %s (%s)" % (self.title, self.author, self.club)
|
||||||
|
|
||||||
|
|
||||||
|
class Screen(models.Model):
|
||||||
|
name = models.CharField(_("name"), max_length=128)
|
||||||
|
|
||||||
|
def active_posters(self):
|
||||||
|
now = timezone.now()
|
||||||
|
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(Q(date_end__isnull=True) | Q(date_end__gte=now))
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s" % (self.name)
|
||||||
|
|
||||||
|
|
||||||
|
class Poster(models.Model):
|
||||||
|
name = models.CharField(_("name"), blank=False, null=False, max_length=128, default="")
|
||||||
|
file = models.ImageField(_("file"), null=False, upload_to="com/posters")
|
||||||
|
club = models.ForeignKey(Club, related_name="posters", verbose_name=_("club"), null=False)
|
||||||
|
screens = models.ManyToManyField(Screen, related_name="posters")
|
||||||
|
date_begin = models.DateTimeField(blank=False, null=False, default=timezone.now)
|
||||||
|
date_end = models.DateTimeField(blank=True, null=True)
|
||||||
|
display_time = models.IntegerField(_("display time"), blank=False, null=False, default=30)
|
||||||
|
is_moderated = models.BooleanField(_("is moderated"), default=False)
|
||||||
|
moderator = models.ForeignKey(User, related_name="moderated_posters", verbose_name=_("moderator"), null=True, blank=True)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.date_end and self.date_begin > self.date_end:
|
||||||
|
raise ValidationError(_("Begin date should be before end date"))
|
||||||
|
if not self.is_moderated:
|
||||||
|
for u in RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID).first().users.all():
|
||||||
|
Notification(user=u, url=reverse("com:poster_moderate_list"),
|
||||||
|
type="POSTER_MODERATION").save()
|
||||||
|
return super(Poster, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
def is_owned_by(self, user):
|
||||||
|
return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or Club.objects.filter(id__in=user.clubs_with_rights)
|
||||||
|
|
||||||
|
def can_be_moderated_by(self, user):
|
||||||
|
return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
|
||||||
|
|
||||||
|
def get_display_name(self):
|
||||||
|
return self.club.get_display_name()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def page(self):
|
||||||
|
return self.club.page
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
43
com/templates/com/poster_edit.jinja
Normal file
43
com/templates/com/poster_edit.jinja
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% trans %}Poster{% endtrans %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="poster_edit">
|
||||||
|
|
||||||
|
<div id="title">
|
||||||
|
<div id="links" class="left">
|
||||||
|
{% if app == "com" %}
|
||||||
|
<a id="list" class="link" href="{{ url(app + ":poster_list") }}">{% trans %}List{% endtrans %}</a>
|
||||||
|
{% elif app == "club" %}
|
||||||
|
<a id="list" class="link" href="{{ url(app + ":poster_list", club.id) }}">{% trans %}List{% endtrans %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<h3>{% trans %}Posters - edit{% endtrans %}</h3>
|
||||||
|
<div id="links" class="right">
|
||||||
|
{% if app == "com" %}
|
||||||
|
<a class="link delete" href="{{ url(app + ":poster_delete", poster.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||||
|
{% elif app == "club" %}
|
||||||
|
<a class="link delete" href="{{ url(app + ":poster_delete", club.id, poster.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="poster">
|
||||||
|
|
||||||
|
<form action="" method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p() }}
|
||||||
|
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
67
com/templates/com/poster_list.jinja
Normal file
67
com/templates/com/poster_list.jinja
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{ static('com/js/poster_list.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% trans %}Poster{% endtrans %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="poster_list">
|
||||||
|
|
||||||
|
<div id="title">
|
||||||
|
<h3>{% trans %}Posters{% endtrans %}</h3>
|
||||||
|
<div id="links" class="right">
|
||||||
|
{% if app == "com" %}
|
||||||
|
<a id="create" class="link" href="{{ url(app + ":poster_create") }}">{% trans %}Create{% endtrans %}</a>
|
||||||
|
<a id="moderation" class="link" href="{{ url("com:poster_moderate_list") }}">{% trans %}Moderation{% endtrans %}</a>
|
||||||
|
{% elif app == "club" %}
|
||||||
|
<a id="create" class="link" href="{{ url(app + ":poster_create", club.id) }}">{% trans %}Create{% endtrans %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="posters">
|
||||||
|
|
||||||
|
{% if poster_list.count() == 0 %}
|
||||||
|
<div id="no-posters">{% trans %}No posters{% endtrans %}</div>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% for poster in poster_list %}
|
||||||
|
<div class="poster{% if not poster.is_moderated %} not_moderated{% endif %}">
|
||||||
|
<div class="name">{{ poster.name }}</div>
|
||||||
|
<div class="image"><img src="{{ poster.file.url }}"></img></div>
|
||||||
|
<div class="dates">
|
||||||
|
<div class="begin">{{ poster.date_begin | date("d/M/Y H:m") }}</div>
|
||||||
|
<div class="end">{{ poster.date_end | date("d/M/Y H:m") }}</div>
|
||||||
|
</div>
|
||||||
|
{% if app == "com" %}
|
||||||
|
<a class="edit" href="{{ url(app + ":poster_edit", poster.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
|
{% elif app == "club" %}
|
||||||
|
<a class="edit" href="{{ url(app + ":poster_edit", club.id, poster.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
|
{% endif %}
|
||||||
|
<div class="tooltip">
|
||||||
|
<ul>
|
||||||
|
{% for screen in poster.screens.all() %}
|
||||||
|
<li>{{ screen }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="view"><div id="placeholder"></div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
39
com/templates/com/poster_moderate.jinja
Normal file
39
com/templates/com/poster_moderate.jinja
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{ static('com/js/poster_list.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="poster_list">
|
||||||
|
|
||||||
|
<div id="title">
|
||||||
|
<div id="links" class="left">
|
||||||
|
<a id="list" class="link" href="{{ url("com:poster_list") }}">{% trans %}List{% endtrans %}</a>
|
||||||
|
</div>
|
||||||
|
<h3>{% trans %}Posters - moderation{% endtrans %}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="posters">
|
||||||
|
|
||||||
|
{% if object_list.count == 0 %}
|
||||||
|
<div id="no-posters">{% trans %}No objects{% endtrans %}</div>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% for poster in object_list %}
|
||||||
|
<div class="poster{% if not poster.is_moderated %} not_moderated{% endif %}">
|
||||||
|
<div class="name"> {{ poster.name }} </div>
|
||||||
|
<div class="image"> <img src="{{ poster.file.url }}"></img> </div>
|
||||||
|
<a class="moderate" href="{{ url("com:poster_moderate", object_id=poster.id) }}">Moderate</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="view"><div id="placeholder"></div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
34
com/templates/com/screen_edit.jinja
Normal file
34
com/templates/com/screen_edit.jinja
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% trans %}Screen{% endtrans %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="screen_edit">
|
||||||
|
|
||||||
|
<div id="title">
|
||||||
|
<div id="links" class="left">
|
||||||
|
<a id="list" class="link" href="{{ url("com:screen_list") }}">{% trans %}List{% endtrans %}</a>
|
||||||
|
</div>
|
||||||
|
<h3>{% trans %}Screen - edit{% endtrans %}</h3>
|
||||||
|
<div id="links" class="right">
|
||||||
|
<a class="link delete" href="{{ url("com:screen_delete", screen.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="screen">
|
||||||
|
|
||||||
|
<form action="" method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p() }}
|
||||||
|
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
39
com/templates/com/screen_list.jinja
Normal file
39
com/templates/com/screen_list.jinja
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% trans %}Screens{% endtrans %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="screen_list">
|
||||||
|
|
||||||
|
<div id="title">
|
||||||
|
<h3>{% trans %}Screens{% endtrans %}</h3>
|
||||||
|
<div id="links" class="right">
|
||||||
|
<a id="create" class="link" href="{{ url("com:screen_create") }}">{% trans %}Create{% endtrans %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="screens">
|
||||||
|
|
||||||
|
{% if screen_list.count() == 0 %}
|
||||||
|
<div id="no-screens">{% trans %}No screens{% endtrans %}</div>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% for screen in screen_list %}
|
||||||
|
<div class="screen">
|
||||||
|
<div class="name">{{ screen.name }}</div>
|
||||||
|
<a class="edit" href="{{ url("com:screen_edit", screen.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
|
<a class="slideshow" href="{{ url("com:screen_slideshow", screen.id) }}" target="_blank">{% trans %}Slideshow{% endtrans %}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
30
com/templates/com/screen_slideshow.jinja
Normal file
30
com/templates/com/screen_slideshow.jinja
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<title>{% trans %}Slideshow{% endtrans %}</title>
|
||||||
|
<link href="{{ scss('com/slideshow.scss') }}" rel="stylesheet" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="slideshow">
|
||||||
|
|
||||||
|
<div id="slides">
|
||||||
|
{% for poster in posters %}
|
||||||
|
<div class="slide {% if loop.first %}center{% else %}right{% endif %}" display_time="{{ poster.display_time }}">
|
||||||
|
<img src="{{ poster.file.url }}"></img>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="progress_bullets">
|
||||||
|
{% for poster in posters %}
|
||||||
|
<div class="bullet {% if loop.first %}active{% endif %}"></div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="progress_bar"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script>
|
||||||
|
<script src="{{ static('com/js/slideshow.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
com/urls.py
11
com/urls.py
@ -47,5 +47,16 @@ urlpatterns = [
|
|||||||
url(r'^mailings$', MailingListAdminView.as_view(), name='mailing_admin'),
|
url(r'^mailings$', MailingListAdminView.as_view(), name='mailing_admin'),
|
||||||
url(r'^mailings/(?P<mailing_id>[0-9]+)/moderate$', MailingModerateView.as_view(), name='mailing_moderate'),
|
url(r'^mailings/(?P<mailing_id>[0-9]+)/moderate$', MailingModerateView.as_view(), name='mailing_moderate'),
|
||||||
url(r'^mailings/(?P<mailing_id>[0-9]+)/delete$', MailingDeleteView.as_view(redirect_page='com:mailing_admin'), name='mailing_delete'),
|
url(r'^mailings/(?P<mailing_id>[0-9]+)/delete$', MailingDeleteView.as_view(redirect_page='com:mailing_admin'), name='mailing_delete'),
|
||||||
|
url(r'^poster$', PosterListView.as_view(), name='poster_list'),
|
||||||
|
url(r'^poster/create$', PosterCreateView.as_view(), name='poster_create'),
|
||||||
|
url(r'^poster/(?P<poster_id>[0-9]+)/edit$', PosterEditView.as_view(), name='poster_edit'),
|
||||||
|
url(r'^poster/(?P<poster_id>[0-9]+)/delete$', PosterDeleteView.as_view(), name='poster_delete'),
|
||||||
|
url(r'^poster/moderate$', PosterModerateListView.as_view(), name='poster_moderate_list'),
|
||||||
|
url(r'^poster/(?P<object_id>[0-9]+)/moderate$', PosterModerateView.as_view(), name='poster_moderate'),
|
||||||
|
url(r'^screen$', ScreenListView.as_view(), name='screen_list'),
|
||||||
|
url(r'^screen/create$', ScreenCreateView.as_view(), name='screen_create'),
|
||||||
|
url(r'^screen/(?P<screen_id>[0-9]+)/slideshow$', ScreenSlideshowView.as_view(), name='screen_slideshow'),
|
||||||
|
url(r'^screen/(?P<screen_id>[0-9]+)/edit$', ScreenEditView.as_view(), name='screen_edit'),
|
||||||
|
url(r'^screen/(?P<screen_id>[0-9]+)/delete$', ScreenDeleteView.as_view(), name='screen_delete'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
256
com/views.py
256
com/views.py
@ -40,7 +40,7 @@ from django import forms
|
|||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from com.models import Sith, News, NewsDate, Weekmail, WeekmailArticle
|
from com.models import Sith, News, NewsDate, Weekmail, WeekmailArticle, Screen, Poster
|
||||||
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin, QuickNotifMixin
|
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin, QuickNotifMixin
|
||||||
from core.views.forms import SelectDateTime
|
from core.views.forms import SelectDateTime
|
||||||
from core.models import Notification, RealGroup, User
|
from core.models import Notification, RealGroup, User
|
||||||
@ -52,6 +52,23 @@ from club.models import Club, Mailing
|
|||||||
sith = Sith.objects.first
|
sith = Sith.objects.first
|
||||||
|
|
||||||
|
|
||||||
|
class PosterForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Poster
|
||||||
|
fields = ['name', 'file', 'club', 'screens', 'date_begin', 'date_end', 'display_time']
|
||||||
|
widgets = {
|
||||||
|
'screens': forms.CheckboxSelectMultiple,
|
||||||
|
'is_moderated': forms.HiddenInput()
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.user = kwargs.pop('user', None)
|
||||||
|
super(PosterForm, self).__init__(*args, **kwargs)
|
||||||
|
if self.user:
|
||||||
|
if not self.user.is_com_admin:
|
||||||
|
self.fields['club'].queryset = Club.objects.filter(id__in=self.user.clubs_with_rights)
|
||||||
|
|
||||||
|
|
||||||
class ComTabsMixin(TabedViewMixin):
|
class ComTabsMixin(TabedViewMixin):
|
||||||
def get_tabs_title(self):
|
def get_tabs_title(self):
|
||||||
return _("Communication administration")
|
return _("Communication administration")
|
||||||
@ -88,9 +105,27 @@ class ComTabsMixin(TabedViewMixin):
|
|||||||
'slug': 'mailings',
|
'slug': 'mailings',
|
||||||
'name': _("Mailing lists administration"),
|
'name': _("Mailing lists administration"),
|
||||||
})
|
})
|
||||||
|
tab_list.append({
|
||||||
|
'url': reverse('com:poster_list'),
|
||||||
|
'slug': 'posters',
|
||||||
|
'name': _("Posters list"),
|
||||||
|
})
|
||||||
|
tab_list.append({
|
||||||
|
'url': reverse('com:screen_list'),
|
||||||
|
'slug': 'screens',
|
||||||
|
'name': _("Screens list"),
|
||||||
|
})
|
||||||
return tab_list
|
return tab_list
|
||||||
|
|
||||||
|
|
||||||
|
class IsComAdminMixin(View):
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)):
|
||||||
|
raise PermissionDenied
|
||||||
|
return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
|
class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
|
||||||
model = Sith
|
model = Sith
|
||||||
template_name = 'core/edit.jinja'
|
template_name = 'core/edit.jinja'
|
||||||
@ -465,3 +500,222 @@ class MailingModerateView(View):
|
|||||||
return redirect('com:mailing_admin')
|
return redirect('com:mailing_admin')
|
||||||
|
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
|
|
||||||
|
class PosterListBaseView(ListView):
|
||||||
|
"""List communication posters"""
|
||||||
|
current_tab = "posters"
|
||||||
|
model = Poster
|
||||||
|
template_name = 'com/poster_list.jinja'
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
club_id = kwargs.pop('club_id', None)
|
||||||
|
self.club = None
|
||||||
|
if club_id:
|
||||||
|
self.club = get_object_or_404(Club, pk=club_id)
|
||||||
|
return super(PosterListBaseView, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if self.request.user.is_com_admin:
|
||||||
|
return Poster.objects.all().order_by('-date_begin')
|
||||||
|
else:
|
||||||
|
return Poster.objects.filter(club=self.club.id)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterListBaseView, self).get_context_data(**kwargs)
|
||||||
|
if not self.request.user.is_com_admin:
|
||||||
|
kwargs['club'] = self.club
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PosterCreateBaseView(CreateView):
|
||||||
|
"""Create communication poster"""
|
||||||
|
current_tab = "posters"
|
||||||
|
form_class = PosterForm
|
||||||
|
template_name = 'core/create.jinja'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return Poster.objects.all()
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
if 'club_id' in kwargs:
|
||||||
|
self.club = get_object_or_404(Club, pk=kwargs['club_id'])
|
||||||
|
return super(PosterCreateBaseView, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
kwargs = super(PosterCreateBaseView, self).get_form_kwargs()
|
||||||
|
kwargs.update({'user': self.request.user})
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterCreateBaseView, self).get_context_data(**kwargs)
|
||||||
|
if not self.request.user.is_com_admin:
|
||||||
|
kwargs['club'] = self.club
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
if self.request.user.is_com_admin:
|
||||||
|
form.instance.is_moderated = True
|
||||||
|
return super(PosterCreateBaseView, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class PosterEditBaseView(UpdateView):
|
||||||
|
"""Edit communication poster"""
|
||||||
|
pk_url_kwarg = "poster_id"
|
||||||
|
current_tab = "posters"
|
||||||
|
form_class = PosterForm
|
||||||
|
template_name = 'com/poster_edit.jinja'
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
if 'club_id' in kwargs and kwargs['club_id']:
|
||||||
|
try:
|
||||||
|
self.club = Club.objects.get(pk=kwargs['club_id'])
|
||||||
|
except Club.DoesNotExist:
|
||||||
|
raise PermissionDenied
|
||||||
|
return super(PosterEditBaseView, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return Poster.objects.all()
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
kwargs = super(PosterEditBaseView, self).get_form_kwargs()
|
||||||
|
kwargs.update({'user': self.request.user})
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterEditBaseView, self).get_context_data(**kwargs)
|
||||||
|
if not self.request.user.is_com_admin:
|
||||||
|
kwargs['club'] = self.club
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
if self.request.user.is_com_admin:
|
||||||
|
form.instance.is_moderated = False
|
||||||
|
return super(PosterEditBaseView, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class PosterDeleteBaseView(DeleteView):
|
||||||
|
"""Edit communication poster"""
|
||||||
|
pk_url_kwarg = "poster_id"
|
||||||
|
current_tab = "posters"
|
||||||
|
model = Poster
|
||||||
|
template_name = 'core/delete_confirm.jinja'
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
if 'club_id' in kwargs and kwargs['club_id']:
|
||||||
|
try:
|
||||||
|
self.club = Club.objects.get(pk=kwargs['club_id'])
|
||||||
|
except Club.DoesNotExist:
|
||||||
|
raise PermissionDenied
|
||||||
|
return super(PosterDeleteBaseView, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class PosterListView(IsComAdminMixin, ComTabsMixin, PosterListBaseView):
|
||||||
|
"""List communication posters"""
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterListView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['app'] = "com"
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PosterCreateView(IsComAdminMixin, ComTabsMixin, PosterCreateBaseView):
|
||||||
|
"""Create communication poster"""
|
||||||
|
success_url = reverse_lazy('com:poster_list')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterCreateView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['app'] = "com"
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PosterEditView(IsComAdminMixin, ComTabsMixin, PosterEditBaseView):
|
||||||
|
"""Edit communication poster"""
|
||||||
|
success_url = reverse_lazy('com:poster_list')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterEditView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['app'] = "com"
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PosterDeleteView(IsComAdminMixin, ComTabsMixin, PosterDeleteBaseView):
|
||||||
|
"""Delete communication poster"""
|
||||||
|
success_url = reverse_lazy('com:poster_list')
|
||||||
|
|
||||||
|
|
||||||
|
class PosterModerateListView(IsComAdminMixin, ComTabsMixin, ListView):
|
||||||
|
"""Moderate list communication poster"""
|
||||||
|
current_tab = "posters"
|
||||||
|
model = Poster
|
||||||
|
template_name = 'com/poster_moderate.jinja'
|
||||||
|
queryset = Poster.objects.filter(is_moderated=False).all()
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterModerateListView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['app'] = "com"
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class PosterModerateView(IsComAdminMixin, ComTabsMixin, View):
|
||||||
|
"""Moderate communication poster"""
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
obj = get_object_or_404(Poster, pk=kwargs['object_id'])
|
||||||
|
if obj.can_be_moderated_by(request.user):
|
||||||
|
obj.is_moderated = True
|
||||||
|
obj.moderator = request.user
|
||||||
|
obj.save()
|
||||||
|
return redirect('com:poster_moderate_list')
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(PosterModerateListView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['app'] = "com"
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenListView(IsComAdminMixin, ComTabsMixin, ListView):
|
||||||
|
"""List communication screens"""
|
||||||
|
current_tab = "screens"
|
||||||
|
model = Screen
|
||||||
|
template_name = 'com/screen_list.jinja'
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenSlideshowView(DetailView):
|
||||||
|
"""Slideshow of actives posters"""
|
||||||
|
pk_url_kwarg = "screen_id"
|
||||||
|
model = Screen
|
||||||
|
template_name = 'com/screen_slideshow.jinja'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs = super(ScreenSlideshowView, self).get_context_data(**kwargs)
|
||||||
|
kwargs['posters'] = self.object.active_posters()
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenCreateView(IsComAdminMixin, ComTabsMixin, CreateView):
|
||||||
|
"""Create communication screen"""
|
||||||
|
current_tab = "screens"
|
||||||
|
model = Screen
|
||||||
|
fields = ['name', ]
|
||||||
|
template_name = 'core/create.jinja'
|
||||||
|
success_url = reverse_lazy('com:screen_list')
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenEditView(IsComAdminMixin, ComTabsMixin, UpdateView):
|
||||||
|
"""Edit communication screen"""
|
||||||
|
pk_url_kwarg = "screen_id"
|
||||||
|
current_tab = "screens"
|
||||||
|
model = Screen
|
||||||
|
fields = ['name', ]
|
||||||
|
template_name = 'com/screen_edit.jinja'
|
||||||
|
success_url = reverse_lazy('com:screen_list')
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenDeleteView(IsComAdminMixin, ComTabsMixin, DeleteView):
|
||||||
|
"""Delete communication screen"""
|
||||||
|
pk_url_kwarg = "screen_id"
|
||||||
|
current_tab = "screens"
|
||||||
|
model = Screen
|
||||||
|
template_name = 'core/delete_confirm.jinja'
|
||||||
|
success_url = reverse_lazy('com:screen_list')
|
||||||
|
19
core/migrations/0028_auto_20171216_2044.py
Normal file
19
core/migrations/0028_auto_20171216_2044.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0027_gift'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='notification',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(default='GENERIC', verbose_name='type', max_length=32, choices=[('POSTER_MODERATION', 'A new poster needs to be moderated'), ('MAILING_MODERATION', 'A new mailing list needs to be moderated'), ('NEWS_MODERATION', 'There are %s fresh news to be moderated'), ('FILE_MODERATION', 'New files to be moderated'), ('SAS_MODERATION', 'There are %s pictures to be moderated in the SAS'), ('NEW_PICTURES', "You've been identified on some pictures"), ('REFILLING', 'You just refilled of %s €'), ('SELLING', 'You just bought %s'), ('GENERIC', 'You have a notification')]),
|
||||||
|
),
|
||||||
|
]
|
@ -518,6 +518,14 @@ class User(AbstractBaseUser):
|
|||||||
infos.save()
|
infos.save()
|
||||||
return infos
|
return infos
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def clubs_with_rights(self):
|
||||||
|
return [m.club.id for m in self.memberships.filter(models.Q(end_date__isnull=True) | models.Q(end_date__gte=timezone.now())).all() if m.club.has_rights_in_club(self)]
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def is_com_admin(self):
|
||||||
|
return self.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
|
||||||
|
|
||||||
|
|
||||||
class AnonymousUser(AuthAnonymousUser):
|
class AnonymousUser(AuthAnonymousUser):
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
|
24
core/static/com/js/poster_list.js
Normal file
24
core/static/com/js/poster_list.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
$("#poster_list #view").click(function(e){
|
||||||
|
$("#view").removeClass("active");
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#poster_list .poster .image").click(function(e){
|
||||||
|
|
||||||
|
el = $(e.target);
|
||||||
|
if(el.hasClass("image"))
|
||||||
|
el = el.find("img")
|
||||||
|
$("#poster_list #view #placeholder").html(el.clone());
|
||||||
|
|
||||||
|
$("#view").addClass("active");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).keyup(function(e) {
|
||||||
|
if (e.keyCode == 27) { // escape key maps to keycode `27`
|
||||||
|
e.preventDefault();
|
||||||
|
$("#view").removeClass("active");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
118
core/static/com/js/slideshow.js
Normal file
118
core/static/com/js/slideshow.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
transition_time = 1000;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
max = $("#slideshow .slide").length;
|
||||||
|
|
||||||
|
next_trigger = 0
|
||||||
|
|
||||||
|
function enterFullscreen() {
|
||||||
|
element = document.getElementById("slideshow");
|
||||||
|
$(element).addClass("fullscreen");
|
||||||
|
if(element.requestFullscreen) {
|
||||||
|
element.requestFullscreen();
|
||||||
|
} else if(element.mozRequestFullScreen) {
|
||||||
|
element.mozRequestFullScreen();
|
||||||
|
} else if(element.webkitRequestFullscreen) {
|
||||||
|
element.webkitRequestFullscreen();
|
||||||
|
} else if(element.msRequestFullscreen) {
|
||||||
|
element.msRequestFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitFullscreen() {
|
||||||
|
element = document.getElementById("slideshow");
|
||||||
|
$(element).removeClass("fullscreen");
|
||||||
|
if (document.exitFullscreen) {
|
||||||
|
document.exitFullscreen();
|
||||||
|
} else if (document.webkitExitFullscreen) {
|
||||||
|
document.webkitExitFullscreen();
|
||||||
|
} else if (document.mozCancelFullScreen) {
|
||||||
|
document.mozCancelFullScreen();
|
||||||
|
} else if (document.msExitFullscreen) {
|
||||||
|
document.msExitFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_progress_bar()
|
||||||
|
{
|
||||||
|
|
||||||
|
$("#slideshow #progress_bar").css("transition", "none");
|
||||||
|
$("#slideshow #progress_bar").removeClass("progress");
|
||||||
|
$("#slideshow #progress_bar").addClass("init");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_progress_bar(display_time)
|
||||||
|
{
|
||||||
|
|
||||||
|
$("#slideshow #progress_bar").removeClass("init");
|
||||||
|
$("#slideshow #progress_bar").addClass("progress");
|
||||||
|
$("#slideshow #progress_bar").css("transition", "width " + display_time + "s linear")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function next()
|
||||||
|
{
|
||||||
|
|
||||||
|
init_progress_bar();
|
||||||
|
slide = $($("#slideshow .slide").get(i % max));
|
||||||
|
slide.removeClass("center");
|
||||||
|
slide.addClass("left");
|
||||||
|
|
||||||
|
next_slide = $($("#slideshow .slide").get((i + 1) % max));
|
||||||
|
next_slide.removeClass("right");
|
||||||
|
next_slide.addClass("center");
|
||||||
|
display_time = next_slide.attr("display_time") || 2;
|
||||||
|
|
||||||
|
$("#slideshow .bullet").removeClass("active");
|
||||||
|
bullet = $("#slideshow .bullet")[(i + 1) % max];
|
||||||
|
$(bullet).addClass("active");
|
||||||
|
|
||||||
|
i = (i + 1) % max;
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
|
||||||
|
others_left = $("#slideshow .slide.left");
|
||||||
|
others_left.removeClass("left");
|
||||||
|
others_left.addClass("right");
|
||||||
|
|
||||||
|
start_progress_bar(display_time);
|
||||||
|
next_trigger = setTimeout(next, display_time * 1000);
|
||||||
|
|
||||||
|
}, transition_time);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
display_time = $("#slideshow .center").attr("display_time");
|
||||||
|
init_progress_bar();
|
||||||
|
setTimeout(function(){
|
||||||
|
if(max > 1){
|
||||||
|
start_progress_bar(display_time);
|
||||||
|
setTimeout(next, display_time * 1000);
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
|
||||||
|
$("#slideshow").click(function(e){
|
||||||
|
if(!$("#slideshow").hasClass("fullscreen"))
|
||||||
|
{
|
||||||
|
console.log("Entering fullscreen ...");
|
||||||
|
enterFullscreen();
|
||||||
|
}else{
|
||||||
|
console.log("Exiting fullscreen ...");
|
||||||
|
exitFullscreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).keyup(function(e) {
|
||||||
|
if (e.keyCode == 27) { // escape key maps to keycode `27`
|
||||||
|
e.preventDefault();
|
||||||
|
console.log("Exiting fullscreen ...");
|
||||||
|
exitFullscreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
148
core/static/com/slideshow.scss
Normal file
148
core/static/com/slideshow.scss
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
body{
|
||||||
|
position: absolute;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#slideshow{
|
||||||
|
position: relative;
|
||||||
|
background-color: lightgrey;
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
*{
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
|
||||||
|
&::before{
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
content: "Click to expand";
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
background-color: rgba(black, 0.5);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fullscreen{
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
&:before{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#slides{
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#slides{
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.slide{
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
top: 0px;
|
||||||
|
|
||||||
|
background-color: grey;
|
||||||
|
transition: left 1s ease-out;
|
||||||
|
|
||||||
|
img{
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide.left{
|
||||||
|
left: -100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide.center{
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide.right{
|
||||||
|
left: 100%;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#progress_bullets{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.bullet{
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
background-color: grey;
|
||||||
|
|
||||||
|
&.active{
|
||||||
|
background-color: #c99836;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress_bar{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: #304c83;
|
||||||
|
|
||||||
|
&.init{
|
||||||
|
width: 0px;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.progress{
|
||||||
|
width: 100%;
|
||||||
|
transition: width 10s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -642,6 +642,200 @@ header {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*---------------------------POSTERS----------------------------*/
|
||||||
|
|
||||||
|
#poster_list, #screen_list, #poster_edit, #screen_edit{
|
||||||
|
position: relative;
|
||||||
|
#title{
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
border-bottom: 2px solid black;
|
||||||
|
h3{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
#links{
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
bottom: 5px;
|
||||||
|
&.left{
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
&.right{
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.link{
|
||||||
|
padding: 5px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
margin-left: 5px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: #ffaa00;
|
||||||
|
color: black;
|
||||||
|
&:hover{
|
||||||
|
color: black;
|
||||||
|
background-color: #c99836;
|
||||||
|
}
|
||||||
|
&.delete{
|
||||||
|
background-color: #cb0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#posters, #screens{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
#no-posters, #no-screens{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.poster, .screen{
|
||||||
|
min-width: 10%;
|
||||||
|
max-width: 20%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 10px;
|
||||||
|
border: 2px solid darkgrey;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: lightgrey;
|
||||||
|
*{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.name{
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border-bottom: 1px solid whitesmoke;
|
||||||
|
}
|
||||||
|
.image{
|
||||||
|
flex-grow: 1;
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border-bottom: 1px solid whitesmoke;
|
||||||
|
img{
|
||||||
|
max-height: 20vw;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
&::before{
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 10;
|
||||||
|
content: "Click to expand";
|
||||||
|
color: white;
|
||||||
|
background-color: rgba(black, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.dates{
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border-bottom: 1px solid whitesmoke;
|
||||||
|
*{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.begin, .end{
|
||||||
|
width: 48%;
|
||||||
|
}
|
||||||
|
.begin{
|
||||||
|
border-right: 1px solid whitesmoke;
|
||||||
|
padding-right: 2%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.edit, .moderate, .slideshow{
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: #ffaa00;
|
||||||
|
color: black;
|
||||||
|
&:hover{
|
||||||
|
color: black;
|
||||||
|
background-color: #c99836;
|
||||||
|
}
|
||||||
|
&:nth-child(2n){
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tooltip{
|
||||||
|
visibility: hidden;
|
||||||
|
width: 120px;
|
||||||
|
background-color: #f9fafb;
|
||||||
|
color: #000;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
ul{
|
||||||
|
margin-left: 0;
|
||||||
|
display: inline-block;
|
||||||
|
li{
|
||||||
|
display: list-item;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.not_moderated
|
||||||
|
{
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
&:hover .tooltip{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#view{
|
||||||
|
position: fixed;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 10;
|
||||||
|
visibility: hidden;
|
||||||
|
background-color: rgba(10, 10, 10, 0.9);
|
||||||
|
overflow: hidden;
|
||||||
|
&.active{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
#placeholder{
|
||||||
|
width: 80vw;
|
||||||
|
height: 80vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
img{
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------ACCOUNTING----------------------------*/
|
/*---------------------------ACCOUNTING----------------------------*/
|
||||||
#accounting {
|
#accounting {
|
||||||
.journal-table {
|
.journal-table {
|
||||||
|
54
core/templates/core/poster_list.jinja
Normal file
54
core/templates/core/poster_list.jinja
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{ static('com/js/poster_list.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% trans %}Poster{% endtrans %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="poster_list">
|
||||||
|
|
||||||
|
<div id="title">
|
||||||
|
<h3>{% trans %}Posters{% endtrans %}</h3>
|
||||||
|
<div id="links" class="right">
|
||||||
|
<a id="create" class="link" href="{{ url(app + ":poster_list") }}">{% trans %}Create{% endtrans %}</a>
|
||||||
|
{% if app == "com" %}
|
||||||
|
<a id="moderation" class="link" href="{{ url("com:poster_moderate_list") }}">{% trans %}Moderation{% endtrans %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="posters">
|
||||||
|
|
||||||
|
{% if poster_list.count() == 0 %}
|
||||||
|
<div id="no-posters">{% trans %}No posters{% endtrans %}</div>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% for poster in poster_list %}
|
||||||
|
<div class="poster">
|
||||||
|
<div class="name">{{ poster.name }}</div>
|
||||||
|
<div class="image"><img src="{{ poster.file.url }}"></img></div>
|
||||||
|
<div class="dates">
|
||||||
|
<div class="begin">{{ poster.date_begin | date("d/M/Y H:m") }}</div>
|
||||||
|
<div class="end">{{ poster.date_end | date("d/M/Y H:m") }}</div>
|
||||||
|
</div>
|
||||||
|
<a class="edit" href="{{ url(poster_edit_url_name, poster.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="view"><div id="placeholder"></div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
30
core/templates/core/screen_slideshow.jinja
Normal file
30
core/templates/core/screen_slideshow.jinja
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<title>{% trans %}Slideshow{% endtrans %}</title>
|
||||||
|
<link href="{{ scss('com/slideshow.scss') }}" rel="stylesheet" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="slideshow">
|
||||||
|
|
||||||
|
<div id="slides">
|
||||||
|
{% for poster in posters %}
|
||||||
|
<div class="slide {% if loop.first %}center{% else %}right{% endif %}" display_time="{{ poster.display_time }}">
|
||||||
|
<img src="{{ poster.file.url }}"></img>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="progress_bullets">
|
||||||
|
{% for poster in posters %}
|
||||||
|
<div class="bullet {% if loop.first %}active{% endif %}"></div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="progress_bar"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script>
|
||||||
|
<script src="{{ static('com/js/slideshow.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -87,6 +87,8 @@
|
|||||||
<li><a href="{{ url('com:info_edit') }}">{% trans %}Edit information message{% endtrans %}</a></li>
|
<li><a href="{{ url('com:info_edit') }}">{% trans %}Edit information message{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('core:file_moderation') }}">{% trans %}Moderate files{% endtrans %}</a></li>
|
<li><a href="{{ url('core:file_moderation') }}">{% trans %}Moderate files{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('com:mailing_admin') }}">{% trans %}Mailing lists administration{% endtrans %}</a></li>
|
<li><a href="{{ url('com:mailing_admin') }}">{% trans %}Mailing lists administration{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:poster_list') }}">{% trans %}Posters{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:screen_list') }}">{% trans %}Screens{% endtrans %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.is_in_group(settings.SITH_GROUP_SAS_ADMIN_ID) %}
|
{% if user.is_in_group(settings.SITH_GROUP_SAS_ADMIN_ID) %}
|
||||||
<li><a href="{{ url('sas:moderation') }}">{% trans %}Moderate pictures{% endtrans %}</a></li>
|
<li><a href="{{ url('sas:moderation') }}">{% trans %}Moderate pictures{% endtrans %}</a></li>
|
||||||
|
@ -562,6 +562,7 @@ SITH_LAUNDERETTE_PRICES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SITH_NOTIFICATIONS = [
|
SITH_NOTIFICATIONS = [
|
||||||
|
('POSTER_MODERATION', _("A new poster needs to be moderated")),
|
||||||
('MAILING_MODERATION', _("A new mailing list needs to be moderated")),
|
('MAILING_MODERATION', _("A new mailing list needs to be moderated")),
|
||||||
('NEWS_MODERATION', _("There are %s fresh news to be moderated")),
|
('NEWS_MODERATION', _("There are %s fresh news to be moderated")),
|
||||||
('FILE_MODERATION', _("New files to be moderated")),
|
('FILE_MODERATION', _("New files to be moderated")),
|
||||||
|
Loading…
Reference in New Issue
Block a user