From 8d1c6480327ae015a7a0408455ad78dcb7423a42 Mon Sep 17 00:00:00 2001 From: gnikwo Date: Tue, 17 Oct 2017 15:13:29 +0200 Subject: [PATCH 01/12] Communication screen - without club tool --- com/admin.py | 2 + com/models.py | 44 +++- com/templates/com/poster_edit.jinja | 35 +++ com/templates/com/poster_list.jinja | 52 +++++ com/templates/com/poster_moderate.jinja | 39 ++++ com/templates/com/screen_edit.jinja | 34 +++ com/templates/com/screen_list.jinja | 40 ++++ com/templates/com/screen_slideshow.jinja | 30 +++ com/urls.py | 11 + com/views.py | 139 ++++++++++- core/admin.py | 21 +- core/static/com/js/poster_create.js | 22 ++ core/static/com/js/poster_list.js | 24 ++ core/static/com/js/slideshow.js | 115 +++++++++ core/static/com/slideshow.scss | 209 +++++++++++++++++ core/static/core/style.scss | 283 +++++++++++++++++++++++ 16 files changed, 1091 insertions(+), 9 deletions(-) create mode 100644 com/templates/com/poster_edit.jinja create mode 100644 com/templates/com/poster_list.jinja create mode 100644 com/templates/com/poster_moderate.jinja create mode 100644 com/templates/com/screen_edit.jinja create mode 100644 com/templates/com/screen_list.jinja create mode 100644 com/templates/com/screen_slideshow.jinja create mode 100644 core/static/com/js/poster_create.js create mode 100644 core/static/com/js/poster_list.js create mode 100644 core/static/com/js/slideshow.js create mode 100644 core/static/com/slideshow.scss diff --git a/com/admin.py b/com/admin.py index db60dd05..df553be2 100644 --- a/com/admin.py +++ b/com/admin.py @@ -39,4 +39,6 @@ class WeekmailAdmin(SearchModelAdmin): admin.site.register(Sith) admin.site.register(News, NewsAdmin) admin.site.register(Weekmail, WeekmailAdmin) +admin.site.register(Screen) +admin.site.register(Poster) diff --git a/com/models.py b/com/models.py index 3d2089c5..bd1f7afe 100644 --- a/com/models.py +++ b/com/models.py @@ -32,10 +32,14 @@ from django.conf import settings from django.contrib.staticfiles.templatetags.staticfiles import static from django.core.mail import EmailMultiAlternatives -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 + + class Sith(models.Model): """A one instance class storing all the modifiable infos""" alert_msg = models.TextField(_("alert message"), default="", blank=True) @@ -183,3 +187,41 @@ class WeekmailArticle(models.Model): def __str__(self): return "%s - %s (%s)" % (self.title, self.author, self.club) + + +class Screen(models.Model): + name = models.CharField(_("name"), max_length=128) + club = models.ForeignKey(Club, related_name="screens", verbose_name=_("club"), null=False) + + 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: %s" % (self.club, 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") + 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) + 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 + return super(Poster, self).save(*args, **kwargs) + + def is_owned_by(self, user): + return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) + + def can_moderate(self, user): + return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) + + def __str__(self): + return self.name diff --git a/com/templates/com/poster_edit.jinja b/com/templates/com/poster_edit.jinja new file mode 100644 index 00000000..5b9cca1c --- /dev/null +++ b/com/templates/com/poster_edit.jinja @@ -0,0 +1,35 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Poster{% endtrans %} +{% endblock %} + +{% block content %} +
+ +
+ +

{% trans %}Posters - edit{% endtrans %}

+ +
+ +
+ +
+ {% csrf_token %} + {{ form.as_p() }} +

+
+ + +
+ +
+{% endblock %} + + + diff --git a/com/templates/com/poster_list.jinja b/com/templates/com/poster_list.jinja new file mode 100644 index 00000000..cfb8d223 --- /dev/null +++ b/com/templates/com/poster_list.jinja @@ -0,0 +1,52 @@ +{% extends "core/base.jinja" %} + +{% block script %} +{{ super() }} + +{% endblock %} + + +{% block title %} +{% trans %}Poster{% endtrans %} +{% endblock %} + +{% block content %} +
+ +
+

{% trans %}Posters{% endtrans %}

+ +
+ +
+ + {% if posters.count() == 0 %} +
{% trans %}No posters{% endtrans %}
+ {% else %} + + {% for poster in posters %} +
+
{{ poster.name }}
+
+
+
{{ poster.date_begin | date("d/M/Y H:m") }}
+
{{ poster.date_end | date("d/M/Y H:m") }}
+
+ {% trans %}Edit{% endtrans %} +
+ {% endfor %} + + {% endif %} + +
+ +
+ +
+{% endblock %} + + + diff --git a/com/templates/com/poster_moderate.jinja b/com/templates/com/poster_moderate.jinja new file mode 100644 index 00000000..b9cbf988 --- /dev/null +++ b/com/templates/com/poster_moderate.jinja @@ -0,0 +1,39 @@ +{% extends "core/base.jinja" %} + +{% block script %} +{{ super() }} + +{% endblock %} + +{% block content %} +
+ +
+ +

{% trans %}Posters - moderation{% endtrans %}

+
+ +
+ + {% if object_list.count == 0 %} +
{% trans %}No objects{% endtrans %}
+ {% else %} + + {% for poster in object_list %} +
+
{{ poster.name }}
+
+ Moderate +
+ {% endfor %} + + {% endif %} + +
+ +
+ +
+{% endblock %} diff --git a/com/templates/com/screen_edit.jinja b/com/templates/com/screen_edit.jinja new file mode 100644 index 00000000..b18c2e00 --- /dev/null +++ b/com/templates/com/screen_edit.jinja @@ -0,0 +1,34 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Screen{% endtrans %} +{% endblock %} + +{% block content %} +
+ +
+ +

{% trans %}Screen - edit{% endtrans %}

+ +
+ +
+ +
+ {% csrf_token %} + {{ form.as_p() }} +

+
+ +
+ +
+{% endblock %} + + + diff --git a/com/templates/com/screen_list.jinja b/com/templates/com/screen_list.jinja new file mode 100644 index 00000000..83f614be --- /dev/null +++ b/com/templates/com/screen_list.jinja @@ -0,0 +1,40 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Screens{% endtrans %} +{% endblock %} + +{% block content %} +
+ +
+

{% trans %}Screens{% endtrans %}

+ +
+ +
+ + {% if screen_list.count() == 0 %} +
{% trans %}No screens{% endtrans %}
+ {% else %} + + {% for screen in screen_list %} +
+
{{ screen.name }}
+
Club: {{ screen.club }}
+ {% trans %}Edit{% endtrans %} + {% trans %}Slideshow{% endtrans %} +
+ {% endfor %} + + {% endif %} + +
+ +
+{% endblock %} + + + diff --git a/com/templates/com/screen_slideshow.jinja b/com/templates/com/screen_slideshow.jinja new file mode 100644 index 00000000..76ff743c --- /dev/null +++ b/com/templates/com/screen_slideshow.jinja @@ -0,0 +1,30 @@ + + + + {% trans %}Slideshow{% endtrans %} + + + +
+ +
+ {% for poster in posters %} +
+ +
+ {% endfor %} +
+ +
+ {% for poster in posters %} +
+ {% endfor %} +
+ +
+ +
+ + + + diff --git a/com/urls.py b/com/urls.py index 3f172693..9f5b0d97 100644 --- a/com/urls.py +++ b/com/urls.py @@ -47,5 +47,16 @@ urlpatterns = [ url(r'^mailings$', MailingListAdminView.as_view(), name='mailing_admin'), url(r'^mailings/(?P[0-9]+)/moderate$', MailingModerateView.as_view(), name='mailing_moderate'), url(r'^mailings/(?P[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[0-9]+)/edit$', PosterEditView.as_view(), name='poster_edit'), + url(r'^poster/(?P[0-9]+)/delete$', PosterDeleteView.as_view(), name='poster_delete'), + url(r'^poster/moderate$', PosterModerateListView.as_view(), name='poster_moderate_list'), + url(r'^poster/(?P[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[0-9]+)/slideshow$', ScreenSlideshowView.as_view(), name='screen_slideshow'), + url(r'^screen/(?P[0-9]+)/edit$', ScreenEditView.as_view(), name='screen_edit'), + url(r'^screen/(?P[0-9]+)/delete$', ScreenDeleteView.as_view(), name='screen_delete'), ] diff --git a/com/views.py b/com/views.py index 34bd99d0..ab6dd64d 100644 --- a/com/views.py +++ b/com/views.py @@ -40,7 +40,7 @@ from django import forms 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.forms import SelectDateTime from core.models import Notification, RealGroup, User @@ -88,9 +88,27 @@ class ComTabsMixin(TabedViewMixin): 'slug': 'mailings', '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 +class IsComAdminMixin(View): + + def dispatch(self, request, *args, **kwargs): + if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or request.user.is_root): + raise PermissionDenied + return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs) + + class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView): model = Sith template_name = 'core/edit.jinja' @@ -117,6 +135,14 @@ class IndexEditView(ComEditView): success_url = reverse_lazy('com:index_edit') +class ModerateListView(ListView): + """Generic view for moderation pages""" + + +class ModerateView(View): + """Generic view for moderation pages""" + + class WeekmailDestinationEditView(ComEditView): fields = ['weekmail_destinations'] current_tab = "weekmail_destinations" @@ -465,3 +491,114 @@ class MailingModerateView(View): return redirect('com:mailing_admin') raise PermissionDenied + + +class PosterListView(IsComAdminMixin, ComTabsMixin, ListView): + """List communication posters""" + current_tab = "posters" + model = Poster + template_name = 'com/poster_list.jinja' + + def get_context_data(self, **kwargs): + kwargs = super(PosterListView, self).get_context_data(**kwargs) + kwargs['posters'] = Poster.objects.all().order_by('-date_begin') + return kwargs + + +class PosterCreateView(IsComAdminMixin, ComTabsMixin, CreateView): + """Create communication poster""" + current_tab = "posters" + model = Poster + fields = ['name', 'file', 'screens', 'date_begin', 'date_end'] + template_name = 'core/create.jinja' + success_url = reverse_lazy('com:poster_list') + + +class PosterEditView(IsComAdminMixin, ComTabsMixin, UpdateView): + """Edit communication poster""" + pk_url_kwarg = "poster_id" + current_tab = "posters" + model = Poster + fields = ['name', 'file', 'screens', 'date_begin', 'date_end'] + template_name = 'com/poster_edit.jinja' + success_url = reverse_lazy('com:poster_list') + + +class PosterDeleteView(IsComAdminMixin, ComTabsMixin, DeleteView): + """Delete communication poster""" + pk_url_kwarg = "poster_id" + current_tab = "posters" + model = Poster + template_name = 'core/delete_confirm.jinja' + 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' + def get_context_data(self, **kwargs): + kwargs = super(PosterModerateListView, self).get_context_data(**kwargs) + kwargs['moderation_url'] = 'com:poster_moderate' + kwargs['object_list'] = Poster.objects.filter(is_moderated=False).all() + return kwargs + + +class PosterModerateView(IsComAdminMixin, ComTabsMixin, ModerateView): + """Moderate communication poster""" + def get(self, request, *args, **kwargs): + obj = get_object_or_404(Poster, pk=kwargs['object_id']) + if obj.can_moderate(request.user): + obj.is_moderated = True + obj.moderator = request.user + obj.save() + return redirect('com:poster_moderate_list') + raise PermissionDenied + + +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', 'club'] + 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', 'club'] + 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') diff --git a/core/admin.py b/core/admin.py index eec0e90b..6c954aa8 100644 --- a/core/admin.py +++ b/core/admin.py @@ -2,6 +2,7 @@ # # Copyright 2016,2017 # - Skia +# - Nabos # # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # http://ae.utbm.fr. @@ -28,9 +29,12 @@ from core.models import User, Page, RealGroup, SithFile from django.contrib.auth.models import Group as AuthGroup from haystack.admin import SearchModelAdmin +@admin.register(SithFile) +class SithFileAdmin(admin.ModelAdmin): + form = make_ajax_form(SithFile, { + 'parent': 'files', # ManyToManyField + }) -admin.site.unregister(AuthGroup) -admin.site.register(RealGroup) class UserAdmin(SearchModelAdmin): list_display = ["first_name", "last_name", "username", "email", "nick_name"] @@ -45,6 +49,11 @@ class UserAdmin(SearchModelAdmin): admin.site.register(User, UserAdmin) + search_fields = ['username', 'first_name', 'last_name'] + list_display = ('username', 'first_name', 'last_name') + list_filter = ['department', 'promo', 'groups'] + list_per_page = 20 + @admin.register(Page) class PageAdmin(admin.ModelAdmin): form = make_ajax_form(Page, { @@ -54,8 +63,6 @@ class PageAdmin(admin.ModelAdmin): 'view_groups': 'groups', }) -@admin.register(SithFile) -class SithFileAdmin(admin.ModelAdmin): - form = make_ajax_form(SithFile, { - 'parent': 'files', # ManyToManyField - }) +admin.site.register(User, UserAdmin) +admin.site.unregister(AuthGroup) +admin.site.register(RealGroup) diff --git a/core/static/com/js/poster_create.js b/core/static/com/js/poster_create.js new file mode 100644 index 00000000..5438a2d4 --- /dev/null +++ b/core/static/com/js/poster_create.js @@ -0,0 +1,22 @@ +$(document).ready(function(){ + + $("#poster_list #view").click(function(e){ + $("#view").removeClass("active"); + }); + + $("#poster_list .poster").click(function(e){ + + el = $(e.target); + $("#poster_list #view #placeholder").html(el); + + $("#view").addClass("active"); + }); + + $(document).keyup(function(e) { + if (e.keyCode == 27) { // escape key maps to keycode `27` + e.preventDefault(); + $("#view").removeClass("active"); + } + }); + +}); diff --git a/core/static/com/js/poster_list.js b/core/static/com/js/poster_list.js new file mode 100644 index 00000000..9d4090e9 --- /dev/null +++ b/core/static/com/js/poster_list.js @@ -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"); + } + }); + +}); diff --git a/core/static/com/js/slideshow.js b/core/static/com/js/slideshow.js new file mode 100644 index 00000000..76882230 --- /dev/null +++ b/core/static/com/js/slideshow.js @@ -0,0 +1,115 @@ +$(document).ready(function(){ + + wait_time = 40 * 1000; + 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").removeClass("progress"); + $("#slideshow #progress_bar").addClass("init"); + + } + + function start_progress_bar() + { + + $("#slideshow #progress_bar").removeClass("init"); + $("#slideshow #progress_bar").addClass("progress"); + + } + + 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"); + + $("#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(); + next_trigger = setTimeout(next, wait_time); + + }, transition_time); + + } + + + init_progress_bar(); + setTimeout(function(){ + if(max > 1){ + start_progress_bar(); + setTimeout(next, wait_time); + } + }, 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(); + } + }); + +}); diff --git a/core/static/com/slideshow.scss b/core/static/com/slideshow.scss new file mode 100644 index 00000000..b2f851d2 --- /dev/null +++ b/core/static/com/slideshow.scss @@ -0,0 +1,209 @@ +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 40s linear; + + } + + } + +} + diff --git a/core/static/core/style.scss b/core/static/core/style.scss index c6964963..8e28ea22 100644 --- a/core/static/core/style.scss +++ b/core/static/core/style.scss @@ -642,6 +642,289 @@ header { 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; + + } + + } + + } + + } + + #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 { .journal-table { From 17d3860ec5d23676ecffe597a200cc1d6ecaaa6f Mon Sep 17 00:00:00 2001 From: gnikwo Date: Sun, 22 Oct 2017 19:12:28 +0200 Subject: [PATCH 02/12] Fix bad merge --- core/admin.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/core/admin.py b/core/admin.py index 6c954aa8..eec0e90b 100644 --- a/core/admin.py +++ b/core/admin.py @@ -2,7 +2,6 @@ # # Copyright 2016,2017 # - Skia -# - Nabos # # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # http://ae.utbm.fr. @@ -29,12 +28,9 @@ from core.models import User, Page, RealGroup, SithFile from django.contrib.auth.models import Group as AuthGroup from haystack.admin import SearchModelAdmin -@admin.register(SithFile) -class SithFileAdmin(admin.ModelAdmin): - form = make_ajax_form(SithFile, { - 'parent': 'files', # ManyToManyField - }) +admin.site.unregister(AuthGroup) +admin.site.register(RealGroup) class UserAdmin(SearchModelAdmin): list_display = ["first_name", "last_name", "username", "email", "nick_name"] @@ -49,11 +45,6 @@ class UserAdmin(SearchModelAdmin): admin.site.register(User, UserAdmin) - search_fields = ['username', 'first_name', 'last_name'] - list_display = ('username', 'first_name', 'last_name') - list_filter = ['department', 'promo', 'groups'] - list_per_page = 20 - @admin.register(Page) class PageAdmin(admin.ModelAdmin): form = make_ajax_form(Page, { @@ -63,6 +54,8 @@ class PageAdmin(admin.ModelAdmin): 'view_groups': 'groups', }) -admin.site.register(User, UserAdmin) -admin.site.unregister(AuthGroup) -admin.site.register(RealGroup) +@admin.register(SithFile) +class SithFileAdmin(admin.ModelAdmin): + form = make_ajax_form(SithFile, { + 'parent': 'files', # ManyToManyField + }) From 693c3ed27ebfe08067141a51e12dd5cb447ee051 Mon Sep 17 00:00:00 2001 From: gnikwo Date: Mon, 23 Oct 2017 09:30:26 +0200 Subject: [PATCH 03/12] Moved club field + migrations --- com/migrations/0004_auto_20171023_0929.py | 43 +++++++++++++++++++++++ com/models.py | 4 +-- com/views.py | 2 +- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 com/migrations/0004_auto_20171023_0929.py diff --git a/com/migrations/0004_auto_20171023_0929.py b/com/migrations/0004_auto_20171023_0929.py new file mode 100644 index 00000000..9bd6f55e --- /dev/null +++ b/com/migrations/0004_auto_20171023_0929.py @@ -0,0 +1,43 @@ +# -*- 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)), + ('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'), + ), + ] diff --git a/com/models.py b/com/models.py index bd1f7afe..26844330 100644 --- a/com/models.py +++ b/com/models.py @@ -191,7 +191,6 @@ class WeekmailArticle(models.Model): class Screen(models.Model): name = models.CharField(_("name"), max_length=128) - club = models.ForeignKey(Club, related_name="screens", verbose_name=_("club"), null=False) def active_posters(self): now = timezone.now() @@ -206,6 +205,7 @@ class Screen(models.Model): 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) @@ -220,7 +220,7 @@ class Poster(models.Model): def is_owned_by(self, user): return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) - def can_moderate(self, user): + def can_be_moderated_by(self, user): return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) def __str__(self): diff --git a/com/views.py b/com/views.py index ab6dd64d..d891de8d 100644 --- a/com/views.py +++ b/com/views.py @@ -549,7 +549,7 @@ class PosterModerateView(IsComAdminMixin, ComTabsMixin, ModerateView): """Moderate communication poster""" def get(self, request, *args, **kwargs): obj = get_object_or_404(Poster, pk=kwargs['object_id']) - if obj.can_moderate(request.user): + if obj.can_be_moderated_by(request.user): obj.is_moderated = True obj.moderator = request.user obj.save() From 21b24f2891d012267a8b49e004bfca603435adef Mon Sep 17 00:00:00 2001 From: gnikwo Date: Wed, 1 Nov 2017 18:12:33 +0100 Subject: [PATCH 04/12] Club views and discussions fixes --- club/templates/club/club_tools.jinja | 1 + club/urls.py | 3 + club/views.py | 82 +++++++++++++- com/models.py | 4 +- com/views.py | 100 +++++++++++++----- core/models.py | 3 + .../templates/core}/poster_edit.jinja | 2 +- .../templates/core}/poster_list.jinja | 14 +-- .../templates/core}/poster_moderate.jinja | 2 +- .../templates/core}/screen_edit.jinja | 2 +- .../templates/core}/screen_list.jinja | 5 +- .../templates/core}/screen_slideshow.jinja | 2 +- core/templates/core/user_tools.jinja | 2 + core/views/forms.py | 2 +- 14 files changed, 182 insertions(+), 42 deletions(-) rename {com/templates/com => core/templates/core}/poster_edit.jinja (87%) rename {com/templates/com => core/templates/core}/poster_list.jinja (62%) rename {com/templates/com => core/templates/core}/poster_moderate.jinja (91%) rename {com/templates/com => core/templates/core}/screen_edit.jinja (87%) rename {com/templates/com => core/templates/core}/screen_list.jinja (73%) rename {com/templates/com => core/templates/core}/screen_slideshow.jinja (92%) diff --git a/club/templates/club/club_tools.jinja b/club/templates/club/club_tools.jinja index 5207a315..e35c9bc2 100644 --- a/club/templates/club/club_tools.jinja +++ b/club/templates/club/club_tools.jinja @@ -11,6 +11,7 @@
  • {% trans %}Edit Trombi{% endtrans %}
  • {% else %}
  • {% trans %}New Trombi{% endtrans %}
  • +
  • {% trans %}Posters{% endtrans %}
  • {% endif %}

    {% trans %}Counters:{% endtrans %}

    diff --git a/club/urls.py b/club/urls.py index a4022b16..153b17a7 100644 --- a/club/urls.py +++ b/club/urls.py @@ -50,4 +50,7 @@ urlpatterns = [ url(r'^(?P[0-9]+)/mailing/delete$', MailingDeleteView.as_view(), name='mailing_delete'), url(r'^(?P[0-9]+)/mailing/delete/subscription$', MailingSubscriptionDeleteView.as_view(), name='mailing_subscription_delete'), url(r'^membership/(?P[0-9]+)/set_old$', MembershipSetOldView.as_view(), name='membership_set_old'), + url(r'^(?P[0-9]+)/poster$', PosterListView.as_view(), name='poster_list'), + url(r'^(?P[0-9]+)/poster/create$', PosterCreateView.as_view(), name='poster_create'), + url(r'^(?P[0-9]+)/poster/(?P[0-9]+)/edit$', PosterEditView.as_view(), name='poster_edit'), ] diff --git a/club/views.py b/club/views.py index 4841c56e..fa6ab2db 100644 --- a/club/views.py +++ b/club/views.py @@ -37,12 +37,13 @@ from ajax_select.fields import AutoCompleteSelectField from django.core.exceptions import PermissionDenied from django.shortcuts import get_object_or_404, redirect -from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, PageEditViewBase -from core.views.forms import SelectDate, SelectDateTime +from core.views import CanCreateMixin, CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, PageEditViewBase +from core.views.forms import SelectDate, SelectDateTime, PosterForm from club.models import Club, Membership, Mailing, MailingSubscription from sith.settings import SITH_MAXIMUM_FREE_ROLE from counter.models import Selling, Counter from core.models import User, PageRev +from com.models import Poster from django.conf import settings @@ -141,6 +142,11 @@ class ClubTabsMixin(TabedViewMixin): 'slug': 'mailing', '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): tab_list.append({ 'url': reverse('club:club_prop', kwargs={'club_id': self.object.id}), @@ -592,3 +598,75 @@ class MailingAutoCleanView(View): def get(self, request, *args, **kwargs): self.mailing.subscriptions.all().delete() return redirect('club:mailing', club_id=self.mailing.club.id) + + +class PosterListView(CanViewMixin, ListView): + """List communication posters""" + current_tab = "posters" + model = Poster + template_name = 'core/poster_list.jinja' + + def dispatch(self, request, *args, **kwargs): + self.club = get_object_or_404(Club, pk=kwargs['club_id']) + return super(PosterListView, self).dispatch(request, *args, **kwargs) + + def get_queryset(self): + return Poster.objects.filter(club=self.club.id) + + def get_context_data(self, **kwargs): + kwargs = super(PosterListView, self).get_context_data(**kwargs) + kwargs['club'] = self.club + kwargs['app'] = "club" + kwargs['poster_create_url_name'] = "club:poster_create" + kwargs['poster_edit_url_name'] = "club:poster_edit" + kwargs['poster_list_url_name'] = "club:poster_list" + return kwargs + + +class PosterCreateView(CanCreateMixin, CreateView): + """Create communication poster""" + current_tab = "posters" + form_class = PosterForm + template_name = 'core/create.jinja' + success_url = reverse_lazy('club:poster_list') + + def dispatch(self, request, *args, **kwargs): + self.club = get_object_or_404(Club, pk=kwargs['club_id']) + self.request = request + return super(PosterCreateView, self).dispatch(request, *args, **kwargs) + + def get_initial(self): + initials = super(PosterCreateView, self).get_initial() + initials['user'] = self.request.user + + def get_context_data(self, **kwargs): + kwargs = super(PosterCreateView, self).get_context_data(**kwargs) + kwargs['club'] = self.club + kwargs['app'] = "club" + kwargs['poster_create_url_name'] = "club:poster_create" + kwargs['poster_edit_url_name'] = "club:poster_edit" + kwargs['poster_list_url_name'] = "club:poster_list" + return kwargs + +class PosterEditView(CanEditMixin, UpdateView): + """Edit communication poster""" + pk_url_kwarg = "poster_id" + current_tab = "posters" + form_class = PosterForm + template_name = 'core/poster_edit.jinja' + success_url = reverse_lazy('club:poster_list') + + def dispatch(self, request, *args, **kwargs): + self.club = get_object_or_404(Club, pk=kwargs['club_id']) + self.request = request + return super(PosterCreateView, self).dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs = super(PosterEditView, self).get_context_data(**kwargs) + kwargs['club'] = self.club + kwargs['app'] = "club" + kwargs['poster_create_url_name'] = "club:poster_create" + kwargs['poster_edit_url_name'] = "club:poster_edit" + kwargs['poster_list_url_name'] = "club:poster_list" + return kwargs + diff --git a/com/models.py b/com/models.py index 26844330..e7796159 100644 --- a/com/models.py +++ b/com/models.py @@ -200,7 +200,7 @@ class Screen(models.Model): return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) def __str__(self): - return "%s: %s" % (self.club, self.name) + return "%s" % (self.name) class Poster(models.Model): name = models.CharField(_("name"), blank=False, null=False, max_length=128, default="") @@ -218,7 +218,7 @@ class Poster(models.Model): return super(Poster, self).save(*args, **kwargs) def is_owned_by(self, user): - return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) + return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or Club.objects.filter(id__in=user.get_clubs_with_rights()) def can_be_moderated_by(self, user): return user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) diff --git a/com/views.py b/com/views.py index d891de8d..723a2036 100644 --- a/com/views.py +++ b/com/views.py @@ -42,7 +42,7 @@ from datetime import timedelta from com.models import Sith, News, NewsDate, Weekmail, WeekmailArticle, Screen, Poster from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin, QuickNotifMixin -from core.views.forms import SelectDateTime +from core.views.forms import SelectDateTime, PosterForm from core.models import Notification, RealGroup, User from club.models import Club, Mailing @@ -104,7 +104,7 @@ class ComTabsMixin(TabedViewMixin): class IsComAdminMixin(View): def dispatch(self, request, *args, **kwargs): - if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or request.user.is_root): + if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)): raise PermissionDenied return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs) @@ -135,14 +135,6 @@ class IndexEditView(ComEditView): success_url = reverse_lazy('com:index_edit') -class ModerateListView(ListView): - """Generic view for moderation pages""" - - -class ModerateView(View): - """Generic view for moderation pages""" - - class WeekmailDestinationEditView(ComEditView): fields = ['weekmail_destinations'] current_tab = "weekmail_destinations" @@ -497,32 +489,52 @@ class PosterListView(IsComAdminMixin, ComTabsMixin, ListView): """List communication posters""" current_tab = "posters" model = Poster - template_name = 'com/poster_list.jinja' + template_name = 'core/poster_list.jinja' + queryset = Poster.objects.all().order_by('-date_begin') def get_context_data(self, **kwargs): kwargs = super(PosterListView, self).get_context_data(**kwargs) - kwargs['posters'] = Poster.objects.all().order_by('-date_begin') + kwargs['app'] = "com" + kwargs['poster_create_url_name'] = "com:poster_create" + kwargs['poster_edit_url_name'] = "com:poster_edit" + kwargs['poster_list_url_name'] = "com:poster_list" return kwargs class PosterCreateView(IsComAdminMixin, ComTabsMixin, CreateView): """Create communication poster""" current_tab = "posters" - model = Poster - fields = ['name', 'file', 'screens', 'date_begin', 'date_end'] + form_class = PosterForm template_name = 'core/create.jinja' success_url = reverse_lazy('com:poster_list') + def get_context_data(self, **kwargs): + kwargs = super(PosterEditView, self).get_context_data(**kwargs) + kwargs['app'] = "com" + kwargs['poster_create_url_name'] = "com:poster_create" + kwargs['poster_edit_url_name'] = "com:poster_edit" + kwargs['poster_list_url_name'] = "com:poster_list" + return kwargs + class PosterEditView(IsComAdminMixin, ComTabsMixin, UpdateView): """Edit communication poster""" pk_url_kwarg = "poster_id" current_tab = "posters" - model = Poster - fields = ['name', 'file', 'screens', 'date_begin', 'date_end'] - template_name = 'com/poster_edit.jinja' + form_class = PosterForm + template_name = 'core/poster_edit.jinja' success_url = reverse_lazy('com:poster_list') + def get_context_data(self, **kwargs): + kwargs = super(PosterEditView, self).get_context_data(**kwargs) + kwargs['app'] = "com" + kwargs['poster_create_url_name'] = "com:poster_create" + kwargs['poster_edit_url_name'] = "com:poster_edit" + kwargs['poster_list_url_name'] = "com:poster_list" + return kwargs + + def get_queryset(self): + return Poster.objects.all() class PosterDeleteView(IsComAdminMixin, ComTabsMixin, DeleteView): """Delete communication poster""" @@ -537,15 +549,20 @@ class PosterModerateListView(IsComAdminMixin, ComTabsMixin, ListView): """Moderate list communication poster""" current_tab = "posters" model = Poster - template_name = 'com/poster_moderate.jinja' + template_name = 'core/poster_moderate.jinja' + def get_context_data(self, **kwargs): kwargs = super(PosterModerateListView, self).get_context_data(**kwargs) kwargs['moderation_url'] = 'com:poster_moderate' kwargs['object_list'] = Poster.objects.filter(is_moderated=False).all() + kwargs['app'] = "com" + kwargs['poster_create_url_name'] = "com:poster_create" + kwargs['poster_edit_url_name'] = "com:poster_edit" + kwargs['poster_list_url_name'] = "com:poster_list" return kwargs -class PosterModerateView(IsComAdminMixin, ComTabsMixin, ModerateView): +class PosterModerateView(IsComAdminMixin, ComTabsMixin, View): """Moderate communication poster""" def get(self, request, *args, **kwargs): obj = get_object_or_404(Poster, pk=kwargs['object_id']) @@ -556,19 +573,36 @@ class PosterModerateView(IsComAdminMixin, ComTabsMixin, ModerateView): 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" + kwargs['poster_create_url_name'] = "com:poster_create" + kwargs['poster_edit_url_name'] = "com:poster_edit" + kwargs['poster_list_url_name'] = "com:poster_list" + return kwargs + class ScreenListView(IsComAdminMixin, ComTabsMixin, ListView): """List communication screens""" current_tab = "screens" model = Screen - template_name = 'com/screen_list.jinja' + template_name = 'core/screen_list.jinja' + + + def get_context_data(self, **kwargs): + kwargs = super(ScreenListView, self).get_context_data(**kwargs) + kwargs['app'] = "com" + kwargs['screen_create_url_name'] = "com:screen_create" + kwargs['screen_edit_url_name'] = "com:screen_edit" + kwargs['screen_list_url_name'] = "com:screen_list" + return kwargs class ScreenSlideshowView(DetailView): """Slideshow of actives posters""" pk_url_kwarg = "screen_id" model = Screen - template_name = 'com/screen_slideshow.jinja' + template_name = 'core/screen_slideshow.jinja' def get_context_data(self, **kwargs): kwargs = super(ScreenSlideshowView, self).get_context_data(**kwargs) @@ -580,21 +614,39 @@ class ScreenCreateView(IsComAdminMixin, ComTabsMixin, CreateView): """Create communication screen""" current_tab = "screens" model = Screen - fields = ['name', 'club'] + fields = ['name', ] template_name = 'core/create.jinja' success_url = reverse_lazy('com:screen_list') + def get_context_data(self, **kwargs): + kwargs = super(ScreenCreateView, self).get_context_data(**kwargs) + kwargs['app'] = "com" + kwargs['screen_create_url_name'] = "com:screen_create" + kwargs['screen_edit_url_name'] = "com:screen_edit" + kwargs['screen_list_url_name'] = "com:screen_list" + return kwargs + + class ScreenEditView(IsComAdminMixin, ComTabsMixin, UpdateView): """Edit communication screen""" pk_url_kwarg = "screen_id" current_tab = "screens" model = Screen - fields = ['name', 'club'] - template_name = 'com/screen_edit.jinja' + fields = ['name', ] + template_name = 'core/screen_edit.jinja' success_url = reverse_lazy('com:screen_list') + def get_context_data(self, **kwargs): + kwargs = super(ScreenEditView, self).get_context_data(**kwargs) + kwargs['app'] = "com" + kwargs['screen_create_url_name'] = "com:screen_create" + kwargs['screen_edit_url_name'] = "com:screen_edit" + kwargs['screen_list_url_name'] = "com:screen_list" + return kwargs + + class ScreenDeleteView(IsComAdminMixin, ComTabsMixin, DeleteView): """Delete communication screen""" pk_url_kwarg = "screen_id" diff --git a/core/models.py b/core/models.py index af5ae973..4e41c576 100644 --- a/core/models.py +++ b/core/models.py @@ -518,6 +518,9 @@ class User(AbstractBaseUser): infos.save() return infos + def get_clubs_with_rights(self): + return [m.club.id for m in self.memberships.filter(end_date__gte=timezone.now()).all() if m.club.has_rights_in_club(self)] + class AnonymousUser(AuthAnonymousUser): def __init__(self, request): diff --git a/com/templates/com/poster_edit.jinja b/core/templates/core/poster_edit.jinja similarity index 87% rename from com/templates/com/poster_edit.jinja rename to core/templates/core/poster_edit.jinja index 5b9cca1c..02f140f8 100644 --- a/com/templates/com/poster_edit.jinja +++ b/core/templates/core/poster_edit.jinja @@ -9,7 +9,7 @@

    {% trans %}Posters - edit{% endtrans %}