views.py 28.6 KB
Newer Older
1 2 3 4
# -*- coding:utf-8 -*
#
# Copyright 2016,2017
# - Skia <skia@libskia.so>
Sli's avatar
Sli committed
5
# - Sli <antoine@bartuccio.fr>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#

Krophil's avatar
Krophil committed
26
from django.shortcuts import redirect, get_object_or_404
Skia's avatar
Skia committed
27
from django.http import HttpResponseRedirect
Sli's avatar
Sli committed
28
from django.views.generic import ListView, DetailView, View
Skia's avatar
Skia committed
29
from django.views.generic.edit import UpdateView, CreateView, DeleteView
Skia's avatar
Skia committed
30
from django.views.generic.detail import SingleObjectMixin
Skia's avatar
Skia committed
31
from django.utils.translation import ugettext_lazy as _
32
from django.core.urlresolvers import reverse, reverse_lazy
33 34
from django.core.exceptions import ValidationError
from django.utils import timezone
Skia's avatar
Skia committed
35
from django.conf import settings
Skia's avatar
Skia committed
36
from django.db.models import Max
Skia's avatar
Skia committed
37
from django.forms.models import modelform_factory
Sli's avatar
Sli committed
38
from django.core.exceptions import PermissionDenied
39
from django import forms
40

41 42
from datetime import timedelta

43
from com.models import Sith, News, NewsDate, Weekmail, WeekmailArticle, Screen, Poster
Sli's avatar
Sli committed
44 45 46 47 48 49 50 51
from core.views import (
    CanViewMixin,
    CanEditMixin,
    CanEditPropMixin,
    TabedViewMixin,
    CanCreateMixin,
    QuickNotifMixin,
)
Sli's avatar
Sli committed
52
from core.views.forms import SelectDateTime, MarkdownInput
Skia's avatar
Skia committed
53
from core.models import Notification, RealGroup, User
Sli's avatar
Sli committed
54
from club.models import Club, Mailing
55

56

57
# Sith object
58 59 60

sith = Sith.objects.first

Krophil's avatar
Krophil committed
61

Nicolas Ballet's avatar
Nicolas Ballet committed
62 63 64
class PosterForm(forms.ModelForm):
    class Meta:
        model = Poster
Sli's avatar
Sli committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
        fields = [
            "name",
            "file",
            "club",
            "screens",
            "date_begin",
            "date_end",
            "display_time",
        ]
        widgets = {"screens": forms.CheckboxSelectMultiple}

    date_begin = forms.DateTimeField(
        ["%Y-%m-%d %H:%M:%S"],
        label=_("Start date"),
        widget=SelectDateTime,
        required=True,
        initial=timezone.now().strftime("%Y-%m-%d %H:%M:%S"),
    )
    date_end = forms.DateTimeField(
        ["%Y-%m-%d %H:%M:%S"],
        label=_("End date"),
        widget=SelectDateTime,
        required=False,
    )
Sli's avatar
Sli committed
89

Nicolas Ballet's avatar
Nicolas Ballet committed
90
    def __init__(self, *args, **kwargs):
Sli's avatar
Sli committed
91
        self.user = kwargs.pop("user", None)
Nicolas Ballet's avatar
Nicolas Ballet committed
92
        super(PosterForm, self).__init__(*args, **kwargs)
Nicolas Ballet's avatar
Nicolas Ballet committed
93 94
        if self.user:
            if not self.user.is_com_admin:
Sli's avatar
Sli committed
95 96 97 98
                self.fields["club"].queryset = Club.objects.filter(
                    id__in=self.user.clubs_with_rights
                )
                self.fields.pop("display_time")
Nicolas Ballet's avatar
Nicolas Ballet committed
99 100


101 102 103 104 105 106
class ComTabsMixin(TabedViewMixin):
    def get_tabs_title(self):
        return _("Communication administration")

    def get_list_of_tabs(self):
        tab_list = []
Sli's avatar
Sli committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
        tab_list.append(
            {"url": reverse("com:weekmail"), "slug": "weekmail", "name": _("Weekmail")}
        )
        tab_list.append(
            {
                "url": reverse("com:weekmail_destinations"),
                "slug": "weekmail_destinations",
                "name": _("Weekmail destinations"),
            }
        )
        tab_list.append(
            {"url": reverse("com:index_edit"), "slug": "index", "name": _("Index page")}
        )
        tab_list.append(
            {"url": reverse("com:info_edit"), "slug": "info", "name": _("Info message")}
        )
        tab_list.append(
            {
                "url": reverse("com:alert_edit"),
                "slug": "alert",
                "name": _("Alert message"),
            }
        )
        tab_list.append(
            {
                "url": reverse("com:mailing_admin"),
                "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"),
            }
        )
151 152
        return tab_list

Krophil's avatar
Krophil committed
153

154 155
class IsComAdminMixin(View):
    def dispatch(self, request, *args, **kwargs):
156
        if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)):
157 158 159 160
            raise PermissionDenied
        return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs)


161 162
class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
    model = Sith
Sli's avatar
Sli committed
163
    template_name = "core/edit.jinja"
164 165 166 167

    def get_object(self, queryset=None):
        return Sith.objects.first()

Krophil's avatar
Krophil committed
168

169
class AlertMsgEditView(ComEditView):
Sli's avatar
Sli committed
170
    fields = ["alert_msg"]
171
    current_tab = "alert"
Sli's avatar
Sli committed
172
    success_url = reverse_lazy("com:alert_edit")
173

Krophil's avatar
Krophil committed
174

175
class InfoMsgEditView(ComEditView):
Sli's avatar
Sli committed
176
    fields = ["info_msg"]
177
    current_tab = "info"
Sli's avatar
Sli committed
178
    success_url = reverse_lazy("com:info_edit")
179

Krophil's avatar
Krophil committed
180

181
class IndexEditView(ComEditView):
Sli's avatar
Sli committed
182
    fields = ["index_page"]
183
    current_tab = "index"
Sli's avatar
Sli committed
184
    success_url = reverse_lazy("com:index_edit")
185

Krophil's avatar
Krophil committed
186

Skia's avatar
Skia committed
187
class WeekmailDestinationEditView(ComEditView):
Sli's avatar
Sli committed
188
    fields = ["weekmail_destinations"]
Skia's avatar
Skia committed
189
    current_tab = "weekmail_destinations"
Sli's avatar
Sli committed
190 191
    success_url = reverse_lazy("com:weekmail_destinations")

Skia's avatar
Skia committed
192

193 194
# News

Krophil's avatar
Krophil committed
195

196 197 198
class NewsForm(forms.ModelForm):
    class Meta:
        model = News
Sli's avatar
Sli committed
199
        fields = ["type", "title", "club", "summary", "content", "author"]
Sli's avatar
Sli committed
200 201 202 203 204 205
        widgets = {
            "author": forms.HiddenInput,
            "type": forms.RadioSelect,
            "summary": MarkdownInput,
            "content": MarkdownInput,
        }
Sli's avatar
Sli committed
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

    start_date = forms.DateTimeField(
        ["%Y-%m-%d %H:%M:%S"],
        label=_("Start date"),
        widget=SelectDateTime,
        required=False,
    )
    end_date = forms.DateTimeField(
        ["%Y-%m-%d %H:%M:%S"],
        label=_("End date"),
        widget=SelectDateTime,
        required=False,
    )
    until = forms.DateTimeField(
        ["%Y-%m-%d %H:%M:%S"], label=_("Until"), widget=SelectDateTime, required=False
    )
Skia's avatar
Skia committed
222
    automoderation = forms.BooleanField(label=_("Automoderation"), required=False)
223 224 225

    def clean(self):
        self.cleaned_data = super(NewsForm, self).clean()
Sli's avatar
Sli committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
        if self.cleaned_data["type"] != "NOTICE":
            if not self.cleaned_data["start_date"]:
                self.add_error(
                    "start_date", ValidationError(_("This field is required."))
                )
            if not self.cleaned_data["end_date"]:
                self.add_error(
                    "end_date", ValidationError(_("This field is required."))
                )
            if self.cleaned_data["start_date"] > self.cleaned_data["end_date"]:
                self.add_error(
                    "end_date",
                    ValidationError(
                        _("You crazy? You can not finish an event before starting it.")
                    ),
                )
            if self.cleaned_data["type"] == "WEEKLY" and not self.cleaned_data["until"]:
                self.add_error("until", ValidationError(_("This field is required.")))
244 245 246 247 248 249
        return self.cleaned_data

    def save(self):
        ret = super(NewsForm, self).save()
        self.instance.dates.all().delete()
        if self.instance.type == "EVENT" or self.instance.type == "CALL":
Sli's avatar
Sli committed
250 251 252 253 254
            NewsDate(
                start_date=self.cleaned_data["start_date"],
                end_date=self.cleaned_data["end_date"],
                news=self.instance,
            ).save()
255
        elif self.instance.type == "WEEKLY":
Sli's avatar
Sli committed
256 257 258 259 260 261
            start_date = self.cleaned_data["start_date"]
            end_date = self.cleaned_data["end_date"]
            while start_date <= self.cleaned_data["until"]:
                NewsDate(
                    start_date=start_date, end_date=end_date, news=self.instance
                ).save()
262 263 264 265
                start_date += timedelta(days=7)
                end_date += timedelta(days=7)
        return ret

Krophil's avatar
Krophil committed
266

Skia's avatar
Skia committed
267
class NewsEditView(CanEditMixin, UpdateView):
268 269
    model = News
    form_class = NewsForm
Sli's avatar
Sli committed
270 271
    template_name = "com/news_edit.jinja"
    pk_url_kwarg = "news_id"
272 273 274 275

    def get_initial(self):
        init = {}
        try:
Sli's avatar
Sli committed
276 277 278 279 280
            init["start_date"] = (
                self.object.dates.order_by("id")
                .first()
                .start_date.strftime("%Y-%m-%d %H:%M:%S")
            )
Krophil's avatar
Krophil committed
281 282
        except:
            pass
283
        try:
Sli's avatar
Sli committed
284 285 286 287 288
            init["end_date"] = (
                self.object.dates.order_by("id")
                .first()
                .end_date.strftime("%Y-%m-%d %H:%M:%S")
            )
Krophil's avatar
Krophil committed
289 290
        except:
            pass
291 292
        return init

Skia's avatar
Skia committed
293 294
    def post(self, request, *args, **kwargs):
        form = self.get_form()
Sli's avatar
Sli committed
295
        if form.is_valid() and "preview" not in request.POST.keys():
Skia's avatar
Skia committed
296 297 298 299
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

Skia's avatar
Skia committed
300 301
    def form_valid(self, form):
        self.object = form.save()
Sli's avatar
Sli committed
302 303 304
        if form.cleaned_data["automoderation"] and self.request.user.is_in_group(
            settings.SITH_GROUP_COM_ADMIN_ID
        ):
Skia's avatar
Skia committed
305 306 307 308 309 310
            self.object.moderator = self.request.user
            self.object.is_moderated = True
            self.object.save()
        else:
            self.object.is_moderated = False
            self.object.save()
Sli's avatar
Sli committed
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
            for u in (
                RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
                .first()
                .users.all()
            ):
                if not u.notifications.filter(
                    type="NEWS_MODERATION", viewed=False
                ).exists():
                    Notification(
                        user=u,
                        url=reverse(
                            "com:news_detail", kwargs={"news_id": self.object.id}
                        ),
                        type="NEWS_MODERATION",
                    ).save()
Skia's avatar
Skia committed
326 327
        return super(NewsEditView, self).form_valid(form)

Krophil's avatar
Krophil committed
328

Skia's avatar
Skia committed
329
class NewsCreateView(CanCreateMixin, CreateView):
330 331
    model = News
    form_class = NewsForm
Sli's avatar
Sli committed
332
    template_name = "com/news_edit.jinja"
333 334

    def get_initial(self):
Sli's avatar
Sli committed
335
        init = {"author": self.request.user}
336
        try:
Sli's avatar
Sli committed
337
            init["club"] = Club.objects.filter(id=self.request.GET["club"]).first()
Krophil's avatar
Krophil committed
338 339
        except:
            pass
340 341
        return init

Skia's avatar
Skia committed
342 343
    def post(self, request, *args, **kwargs):
        form = self.get_form()
Sli's avatar
Sli committed
344
        if form.is_valid() and "preview" not in request.POST.keys():
Skia's avatar
Skia committed
345 346 347 348 349
            return self.form_valid(form)
        else:
            self.object = form.instance
            return self.form_invalid(form)

Skia's avatar
Skia committed
350 351
    def form_valid(self, form):
        self.object = form.save()
Sli's avatar
Sli committed
352 353 354
        if form.cleaned_data["automoderation"] and self.request.user.is_in_group(
            settings.SITH_GROUP_COM_ADMIN_ID
        ):
Skia's avatar
Skia committed
355 356 357
            self.object.moderator = self.request.user
            self.object.is_moderated = True
            self.object.save()
Skia's avatar
Skia committed
358
        else:
Sli's avatar
Sli committed
359 360 361 362 363 364 365 366 367 368 369 370 371
            for u in (
                RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
                .first()
                .users.all()
            ):
                if not u.notifications.filter(
                    type="NEWS_MODERATION", viewed=False
                ).exists():
                    Notification(
                        user=u,
                        url=reverse("com:news_admin_list"),
                        type="NEWS_MODERATION",
                    ).save()
Skia's avatar
Skia committed
372 373
        return super(NewsCreateView, self).form_valid(form)

Krophil's avatar
Krophil committed
374

Skia's avatar
Skia committed
375 376
class NewsDeleteView(CanEditMixin, DeleteView):
    model = News
Sli's avatar
Sli committed
377 378 379
    pk_url_kwarg = "news_id"
    template_name = "core/delete_confirm.jinja"
    success_url = reverse_lazy("com:news_admin_list")
Krophil's avatar
Krophil committed
380

Skia's avatar
Skia committed
381

Skia's avatar
Skia committed
382 383
class NewsModerateView(CanEditMixin, SingleObjectMixin):
    model = News
Sli's avatar
Sli committed
384
    pk_url_kwarg = "news_id"
Skia's avatar
Skia committed
385 386 387

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
Sli's avatar
Sli committed
388
        if "remove" in request.GET.keys():
Skia's avatar
Skia committed
389 390 391
            self.object.is_moderated = False
        else:
            self.object.is_moderated = True
Skia's avatar
Skia committed
392 393
        self.object.moderator = request.user
        self.object.save()
Sli's avatar
Sli committed
394 395 396
        if "next" in self.request.GET.keys():
            return redirect(self.request.GET["next"])
        return redirect("com:news_admin_list")
Skia's avatar
Skia committed
397

Krophil's avatar
Krophil committed
398

Skia's avatar
Skia committed
399
class NewsAdminListView(CanEditMixin, ListView):
400
    model = News
Sli's avatar
Sli committed
401
    template_name = "com/news_admin_list.jinja"
Skia's avatar
Skia committed
402
    queryset = News.objects.all()
403

Krophil's avatar
Krophil committed
404

Skia's avatar
Skia committed
405
class NewsListView(CanViewMixin, ListView):
406
    model = News
Sli's avatar
Sli committed
407
    template_name = "com/news_list.jinja"
Skia's avatar
Skia committed
408
    queryset = News.objects.filter(is_moderated=True)
409

Skia's avatar
Skia committed
410 411
    def get_context_data(self, **kwargs):
        kwargs = super(NewsListView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
412 413 414 415 416 417 418 419 420 421
        kwargs["NewsDate"] = NewsDate
        kwargs["timedelta"] = timedelta
        kwargs["birthdays"] = (
            User.objects.filter(
                date_of_birth__month=timezone.now().month,
                date_of_birth__day=timezone.now().day,
            )
            .filter(role__in=["STUDENT", "FORMER STUDENT"])
            .order_by("-date_of_birth")
        )
Skia's avatar
Skia committed
422 423
        return kwargs

Krophil's avatar
Krophil committed
424

Skia's avatar
Skia committed
425
class NewsDetailView(CanViewMixin, DetailView):
426
    model = News
Sli's avatar
Sli committed
427 428 429
    template_name = "com/news_detail.jinja"
    pk_url_kwarg = "news_id"

Skia's avatar
Skia committed
430

Skia's avatar
Skia committed
431 432
# Weekmail

Krophil's avatar
Krophil committed
433

Skia's avatar
Skia committed
434
class WeekmailPreviewView(ComTabsMixin, CanEditPropMixin, DetailView):
Skia's avatar
Skia committed
435
    model = Weekmail
Sli's avatar
Sli committed
436 437
    template_name = "com/weekmail_preview.jinja"
    success_url = reverse_lazy("com:weekmail")
Skia's avatar
Skia committed
438 439 440 441 442
    current_tab = "weekmail"

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        try:
Sli's avatar
Sli committed
443
            if request.POST["send"] == "validate":
Skia's avatar
Skia committed
444
                self.object.send()
Sli's avatar
Sli committed
445 446 447
                return HttpResponseRedirect(
                    reverse("com:weekmail") + "?qn_weekmail_send_success"
                )
Krophil's avatar
Krophil committed
448 449
        except:
            pass
Skia's avatar
Skia committed
450
        return super(WeekmailEditView, self).get(request, *args, **kwargs)
Skia's avatar
Skia committed
451 452

    def get_object(self, queryset=None):
Sli's avatar
Sli committed
453
        return self.model.objects.filter(sent=False).order_by("-id").first()
Skia's avatar
Skia committed
454 455 456 457

    def get_context_data(self, **kwargs):
        """Add rendered weekmail"""
        kwargs = super(WeekmailPreviewView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
458
        kwargs["weekmail_rendered"] = self.object.render_html()
Skia's avatar
Skia committed
459 460
        return kwargs

Krophil's avatar
Krophil committed
461

Skia's avatar
Skia committed
462
class WeekmailEditView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, UpdateView):
Skia's avatar
Skia committed
463
    model = Weekmail
Sli's avatar
Sli committed
464 465 466 467 468
    template_name = "com/weekmail.jinja"
    form_class = modelform_factory(
        Weekmail,
        fields=["title", "intro", "joke", "protip", "conclusion"],
        help_texts={"title": _("Delete and save to regenerate")},
Sli's avatar
Sli committed
469 470 471 472 473 474
        widgets={
            "intro": MarkdownInput,
            "joke": MarkdownInput,
            "protip": MarkdownInput,
            "conclusion": MarkdownInput,
        },
Sli's avatar
Sli committed
475 476
    )
    success_url = reverse_lazy("com:weekmail")
Skia's avatar
Skia committed
477
    current_tab = "weekmail"
Skia's avatar
Skia committed
478 479

    def get_object(self, queryset=None):
Sli's avatar
Sli committed
480
        weekmail = self.model.objects.filter(sent=False).order_by("-id").first()
Skia's avatar
Skia committed
481 482
        if not weekmail.title:
            now = timezone.now()
Sli's avatar
Sli committed
483 484 485
            weekmail.title = _("Weekmail of the ") + (
                now + timedelta(days=6 - now.weekday())
            ).strftime("%d/%m/%Y")
Skia's avatar
Skia committed
486
            weekmail.save()
Skia's avatar
Skia committed
487
        return weekmail
Skia's avatar
Skia committed
488

Skia's avatar
Skia committed
489 490
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
Sli's avatar
Sli committed
491 492 493 494 495 496 497
        if "up_article" in request.GET.keys():
            art = get_object_or_404(
                WeekmailArticle, id=request.GET["up_article"], weekmail=self.object
            )
            prev_art = (
                self.object.articles.order_by("rank").filter(rank__lt=art.rank).last()
            )
Skia's avatar
Skia committed
498 499 500 501
            if prev_art:
                art.rank, prev_art.rank = prev_art.rank, art.rank
                art.save()
                prev_art.save()
Sli's avatar
Sli committed
502 503 504 505 506 507 508 509
                self.quick_notif_list += ["qn_success"]
        if "down_article" in request.GET.keys():
            art = get_object_or_404(
                WeekmailArticle, id=request.GET["down_article"], weekmail=self.object
            )
            next_art = (
                self.object.articles.order_by("rank").filter(rank__gt=art.rank).first()
            )
Skia's avatar
Skia committed
510 511 512 513
            if next_art:
                art.rank, next_art.rank = next_art.rank, art.rank
                art.save()
                next_art.save()
Sli's avatar
Sli committed
514 515 516 517 518
                self.quick_notif_list += ["qn_success"]
        if "add_article" in request.GET.keys():
            art = get_object_or_404(
                WeekmailArticle, id=request.GET["add_article"], weekmail=None
            )
Skia's avatar
Skia committed
519
            art.weekmail = self.object
Sli's avatar
Sli committed
520
            art.rank = self.object.articles.aggregate(Max("rank"))["rank__max"] or 0
Skia's avatar
Skia committed
521 522
            art.rank += 1
            art.save()
Sli's avatar
Sli committed
523 524 525 526 527
            self.quick_notif_list += ["qn_success"]
        if "del_article" in request.GET.keys():
            art = get_object_or_404(
                WeekmailArticle, id=request.GET["del_article"], weekmail=self.object
            )
Skia's avatar
Skia committed
528 529 530
            art.weekmail = None
            art.rank = -1
            art.save()
Sli's avatar
Sli committed
531
            self.quick_notif_list += ["qn_success"]
Skia's avatar
Skia committed
532 533 534 535 536
        return super(WeekmailEditView, self).get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        """Add orphan articles """
        kwargs = super(WeekmailEditView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
537
        kwargs["orphans"] = WeekmailArticle.objects.filter(weekmail=None)
Skia's avatar
Skia committed
538 539
        return kwargs

Krophil's avatar
Krophil committed
540

Sli's avatar
Sli committed
541 542 543
class WeekmailArticleEditView(
    ComTabsMixin, QuickNotifMixin, CanEditPropMixin, UpdateView
):
Skia's avatar
Skia committed
544
    """Edit an article"""
Sli's avatar
Sli committed
545

Skia's avatar
Skia committed
546
    model = WeekmailArticle
Sli's avatar
Sli committed
547 548 549 550 551
    form_class = modelform_factory(
        WeekmailArticle,
        fields=["title", "club", "content"],
        widgets={"content": MarkdownInput},
    )
Skia's avatar
Skia committed
552
    pk_url_kwarg = "article_id"
Sli's avatar
Sli committed
553 554
    template_name = "core/edit.jinja"
    success_url = reverse_lazy("com:weekmail")
Skia's avatar
Skia committed
555
    quick_notif_url_arg = "qn_weekmail_article_edit"
Skia's avatar
Skia committed
556
    current_tab = "weekmail"
Skia's avatar
Skia committed
557

Krophil's avatar
Krophil committed
558

559
class WeekmailArticleCreateView(QuickNotifMixin, CreateView):
Skia's avatar
Skia committed
560
    """Post an article"""
Sli's avatar
Sli committed
561

Skia's avatar
Skia committed
562
    model = WeekmailArticle
Sli's avatar
Sli committed
563 564 565 566 567
    form_class = modelform_factory(
        WeekmailArticle,
        fields=["title", "club", "content"],
        widgets={"content": MarkdownInput},
    )
Sli's avatar
Sli committed
568 569
    template_name = "core/create.jinja"
    success_url = reverse_lazy("core:user_tools")
Skia's avatar
Skia committed
570 571
    quick_notif_url_arg = "qn_weekmail_new_article"

572 573 574
    def get_initial(self):
        init = {}
        try:
Sli's avatar
Sli committed
575
            init["club"] = Club.objects.filter(id=self.request.GET["club"]).first()
Krophil's avatar
Krophil committed
576 577
        except:
            pass
578 579
        return init

580 581 582
    def post(self, request, *args, **kwargs):
        form = self.get_form()
        self.object = form.instance
Krophil's avatar
Krophil committed
583
        form.is_valid()  #  Valid a first time to populate club field
584 585 586 587 588
        try:
            m = form.instance.club.get_membership_for(request.user)
            if m.role <= settings.SITH_MAXIMUM_FREE_ROLE:
                raise
        except:
Sli's avatar
Sli committed
589 590 591 592 593 594 595 596 597
            form.add_error(
                "club",
                ValidationError(
                    _(
                        "You must be a board member of the selected club to post in the Weekmail."
                    )
                ),
            )
        if form.is_valid() and not "preview" in request.POST.keys():
598 599 600 601
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

Skia's avatar
Skia committed
602 603 604 605
    def form_valid(self, form):
        form.instance.author = self.request.user
        return super(WeekmailArticleCreateView, self).form_valid(form)

Krophil's avatar
Krophil committed
606

Skia's avatar
Skia committed
607
class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView):
Skia's avatar
Skia committed
608
    """Delete an article"""
Sli's avatar
Sli committed
609

Skia's avatar
Skia committed
610
    model = WeekmailArticle
Sli's avatar
Sli committed
611 612
    template_name = "core/delete_confirm.jinja"
    success_url = reverse_lazy("com:weekmail")
613
    pk_url_kwarg = "article_id"
Sli's avatar
Sli committed
614 615 616 617 618 619 620 621


class MailingListAdminView(ComTabsMixin, ListView):
    template_name = "com/mailing_admin.jinja"
    model = Mailing
    current_tab = "mailings"

    def dispatch(self, request, *args, **kwargs):
Sli's avatar
Sli committed
622 623 624 625
        if not (
            request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
            or request.user.is_root
        ):
Sli's avatar
Sli committed
626 627 628 629 630
            raise PermissionDenied
        return super(MailingListAdminView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        kwargs = super(MailingListAdminView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
631 632 633 634
        kwargs["moderated"] = self.get_queryset().filter(is_moderated=True).all()
        kwargs["unmoderated"] = self.get_queryset().filter(is_moderated=False).all()
        kwargs["has_moderated"] = len(kwargs["moderated"]) > 0
        kwargs["has_unmoderated"] = len(kwargs["unmoderated"]) > 0
Sli's avatar
Sli committed
635
        return kwargs
Sli's avatar
Sli committed
636 637 638 639


class MailingModerateView(View):
    def get(self, request, *args, **kwargs):
Sli's avatar
Sli committed
640
        mailing = get_object_or_404(Mailing, pk=kwargs["mailing_id"])
Sli's avatar
Sli committed
641 642 643 644
        if mailing.can_moderate(request.user):
            mailing.is_moderated = True
            mailing.moderator = request.user
            mailing.save()
Sli's avatar
Sli committed
645
            return redirect("com:mailing_admin")
Sli's avatar
Sli committed
646 647

        raise PermissionDenied
648 649


Nicolas Ballet's avatar
Nicolas Ballet committed
650
class PosterListBaseView(ListView):
651
    """List communication posters"""
Sli's avatar
Sli committed
652

653 654
    current_tab = "posters"
    model = Poster
Sli's avatar
Sli committed
655
    template_name = "com/poster_list.jinja"
Nicolas Ballet's avatar
Nicolas Ballet committed
656 657

    def dispatch(self, request, *args, **kwargs):
Sli's avatar
Sli committed
658
        club_id = kwargs.pop("club_id", None)
Sli's avatar
Sli committed
659
        self.club = None
Nicolas Ballet's avatar
Nicolas Ballet committed
660 661
        if club_id:
            self.club = get_object_or_404(Club, pk=club_id)
Nicolas Ballet's avatar
Nicolas Ballet committed
662 663 664
        return super(PosterListBaseView, self).dispatch(request, *args, **kwargs)

    def get_queryset(self):
Nicolas Ballet's avatar
Nicolas Ballet committed
665
        if self.request.user.is_com_admin:
Sli's avatar
Sli committed
666
            return Poster.objects.all().order_by("-date_begin")
Nicolas Ballet's avatar
Nicolas Ballet committed
667 668
        else:
            return Poster.objects.filter(club=self.club.id)
669 670

    def get_context_data(self, **kwargs):
Nicolas Ballet's avatar
Nicolas Ballet committed
671
        kwargs = super(PosterListBaseView, self).get_context_data(**kwargs)
Nicolas Ballet's avatar
Nicolas Ballet committed
672
        if not self.request.user.is_com_admin:
Sli's avatar
Sli committed
673
            kwargs["club"] = self.club
674 675 676
        return kwargs


Nicolas Ballet's avatar
Nicolas Ballet committed
677
class PosterCreateBaseView(CreateView):
678
    """Create communication poster"""
Sli's avatar
Sli committed
679

680
    current_tab = "posters"
681
    form_class = PosterForm
Sli's avatar
Sli committed
682
    template_name = "core/create.jinja"
Nicolas Ballet's avatar
Nicolas Ballet committed
683 684 685 686 687

    def get_queryset(self):
        return Poster.objects.all()

    def dispatch(self, request, *args, **kwargs):
Sli's avatar
Sli committed
688 689
        if "club_id" in kwargs:
            self.club = get_object_or_404(Club, pk=kwargs["club_id"])
Nicolas Ballet's avatar
Nicolas Ballet committed
690
        return super(PosterCreateBaseView, self).dispatch(request, *args, **kwargs)
691

Nicolas Ballet's avatar
Nicolas Ballet committed
692 693
    def get_form_kwargs(self):
        kwargs = super(PosterCreateBaseView, self).get_form_kwargs()
Sli's avatar
Sli committed
694
        kwargs.update({"user": self.request.user})
Nicolas Ballet's avatar
Nicolas Ballet committed
695 696
        return kwargs

697
    def get_context_data(self, **kwargs):
Nicolas Ballet's avatar
Nicolas Ballet committed
698
        kwargs = super(PosterCreateBaseView, self).get_context_data(**kwargs)
Nicolas Ballet's avatar
Nicolas Ballet committed
699
        if not self.request.user.is_com_admin:
Sli's avatar
Sli committed
700
            kwargs["club"] = self.club
701 702
        return kwargs

Nicolas Ballet's avatar
Nicolas Ballet committed
703
    def form_valid(self, form):
Nicolas Ballet's avatar
Nicolas Ballet committed
704
        if self.request.user.is_com_admin:
Nicolas Ballet's avatar
Nicolas Ballet committed
705 706 707
            form.instance.is_moderated = True
        return super(PosterCreateBaseView, self).form_valid(form)

708

Nicolas Ballet's avatar
Nicolas Ballet committed
709
class PosterEditBaseView(UpdateView):
710
    """Edit communication poster"""
Sli's avatar
Sli committed
711

712 713
    pk_url_kwarg = "poster_id"
    current_tab = "posters"
714
    form_class = PosterForm
Sli's avatar
Sli committed
715
    template_name = "com/poster_edit.jinja"
Nicolas Ballet's avatar
Nicolas Ballet committed
716

Sli's avatar
Sli committed
717 718 719
    def get_initial(self):
        init = {}
        try:
Sli's avatar
Sli committed
720
            init["date_begin"] = self.object.date_begin.strftime("%Y-%m-%d %H:%M:%S")
Sli's avatar
Sli committed
721 722 723
        except Exception:
            pass
        try:
Sli's avatar
Sli committed
724
            init["date_end"] = self.object.date_end.strftime("%Y-%m-%d %H:%M:%S")
Sli's avatar
Sli committed
725 726 727 728
        except Exception:
            pass
        return init

Nicolas Ballet's avatar
Nicolas Ballet committed
729
    def dispatch(self, request, *args, **kwargs):
Sli's avatar
Sli committed
730
        if "club_id" in kwargs and kwargs["club_id"]:
Nicolas Ballet's avatar
Nicolas Ballet committed
731
            try:
Sli's avatar
Sli committed
732
                self.club = Club.objects.get(pk=kwargs["club_id"])
Nicolas Ballet's avatar
Nicolas Ballet committed
733
            except Club.DoesNotExist:
Nicolas Ballet's avatar
Nicolas Ballet committed
734
                raise PermissionDenied
Nicolas Ballet's avatar
Nicolas Ballet committed
735 736 737 738 739
        return super(PosterEditBaseView, self).dispatch(request, *args, **kwargs)

    def get_queryset(self):
        return Poster.objects.all()

Nicolas Ballet's avatar
Nicolas Ballet committed
740 741
    def get_form_kwargs(self):
        kwargs = super(PosterEditBaseView, self).get_form_kwargs()
Sli's avatar
Sli committed
742
        kwargs.update({"user": self.request.user})
Nicolas Ballet's avatar
Nicolas Ballet committed
743 744
        return kwargs

Nicolas Ballet's avatar
Nicolas Ballet committed
745 746
    def get_context_data(self, **kwargs):
        kwargs = super(PosterEditBaseView, self).get_context_data(**kwargs)
Nicolas Ballet's avatar
Nicolas Ballet committed
747
        if not self.request.user.is_com_admin:
Sli's avatar
Sli committed
748
            kwargs["club"] = self.club
Nicolas Ballet's avatar
Nicolas Ballet committed
749 750 751
        return kwargs

    def form_valid(self, form):
752
        if self.request.user.is_com_admin:
Nicolas Ballet's avatar
Nicolas Ballet committed
753 754 755 756
            form.instance.is_moderated = False
        return super(PosterEditBaseView, self).form_valid(form)


Nicolas Ballet's avatar
Nicolas Ballet committed
757 758
class PosterDeleteBaseView(DeleteView):
    """Edit communication poster"""
Sli's avatar
Sli committed
759

Nicolas Ballet's avatar
Nicolas Ballet committed
760
    pk_url_kwarg = "poster_id"
Nicolas Ballet's avatar
Nicolas Ballet committed
761 762
    current_tab = "posters"
    model = Poster
Sli's avatar
Sli committed
763
    template_name = "core/delete_confirm.jinja"
Nicolas Ballet's avatar
Nicolas Ballet committed
764 765

    def dispatch(self, request, *args, **kwargs):
Sli's avatar
Sli committed
766
        if "club_id" in kwargs and kwargs["club_id"]:
Nicolas Ballet's avatar
Nicolas Ballet committed
767
            try:
Sli's avatar
Sli committed
768
                self.club = Club.objects.get(pk=kwargs["club_id"])
Nicolas Ballet's avatar
Nicolas Ballet committed
769 770 771 772 773 774 775
            except Club.DoesNotExist:
                raise PermissionDenied
        return super(PosterDeleteBaseView, self).dispatch(request, *args, **kwargs)


class PosterListView(IsComAdminMixin, ComTabsMixin, PosterListBaseView):
    """List communication posters"""
Nicolas Ballet's avatar
Nicolas Ballet committed
776 777 778

    def get_context_data(self, **kwargs):
        kwargs = super(PosterListView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
779
        kwargs["app"] = "com"
Nicolas Ballet's avatar
Nicolas Ballet committed
780 781 782 783 784
        return kwargs


class PosterCreateView(IsComAdminMixin, ComTabsMixin, PosterCreateBaseView):
    """Create communication poster"""
Sli's avatar
Sli committed
785 786

    success_url = reverse_lazy("com:poster_list")
Nicolas Ballet's avatar
Nicolas Ballet committed
787 788 789

    def get_context_data(self, **kwargs):
        kwargs = super(PosterCreateView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
790
        kwargs["app"] = "com"
Nicolas Ballet's avatar
Nicolas Ballet committed
791 792 793 794 795
        return kwargs


class PosterEditView(IsComAdminMixin, ComTabsMixin, PosterEditBaseView):
    """Edit communication poster"""
Sli's avatar
Sli committed
796 797

    success_url = reverse_lazy("com:poster_list")
798

799 800
    def get_context_data(self, **kwargs):
        kwargs = super(PosterEditView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
801
        kwargs["app"] = "com"
802 803
        return kwargs

804

Nicolas Ballet's avatar
Nicolas Ballet committed
805
class PosterDeleteView(IsComAdminMixin, ComTabsMixin, PosterDeleteBaseView):
806
    """Delete communication poster"""
Sli's avatar
Sli committed
807 808

    success_url = reverse_lazy("com:poster_list")
809 810 811 812


class PosterModerateListView(IsComAdminMixin, ComTabsMixin, ListView):
    """Moderate list communication poster"""
Sli's avatar
Sli committed
813

814 815
    current_tab = "posters"
    model = Poster
Sli's avatar
Sli committed
816
    template_name = "com/poster_moderate.jinja"
Nicolas Ballet's avatar
Nicolas Ballet committed
817
    queryset = Poster.objects.filter(is_moderated=False).all()
818

819 820
    def get_context_data(self, **kwargs):
        kwargs = super(PosterModerateListView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
821
        kwargs["app"] = "com"
822 823 824
        return kwargs


825
class PosterModerateView(IsComAdminMixin, ComTabsMixin, View):
826
    """Moderate communication poster"""
Sli's avatar
Sli committed
827

828
    def get(self, request, *args, **kwargs):
Sli's avatar
Sli committed
829
        obj = get_object_or_404(Poster, pk=kwargs["object_id"])
830
        if obj.can_be_moderated_by(request.user):
831 832 833
            obj.is_moderated = True
            obj.moderator = request.user
            obj.save()
Sli's avatar
Sli committed
834
            return redirect("com:poster_moderate_list")
835 836
        raise PermissionDenied

837 838
    def get_context_data(self, **kwargs):
        kwargs = super(PosterModerateListView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
839
        kwargs["app"] = "com"
840 841
        return kwargs

842 843 844

class ScreenListView(IsComAdminMixin, ComTabsMixin, ListView):
    """List communication screens"""
Sli's avatar
Sli committed
845

846 847
    current_tab = "screens"
    model = Screen
Sli's avatar
Sli committed
848
    template_name = "com/screen_list.jinja"
849 850 851 852


class ScreenSlideshowView(DetailView):
    """Slideshow of actives posters"""
Sli's avatar
Sli committed
853

854 855
    pk_url_kwarg = "screen_id"
    model = Screen
Sli's avatar
Sli committed
856
    template_name = "com/screen_slideshow.jinja"
857 858 859

    def get_context_data(self, **kwargs):
        kwargs = super(ScreenSlideshowView, self).get_context_data(**kwargs)
Sli's avatar
Sli committed
860
        kwargs["posters"] = self.object.active_posters()
861 862 863 864 865
        return kwargs


class ScreenCreateView(IsComAdminMixin, ComTabsMixin, CreateView):
    """Create communication screen"""
Sli's avatar
Sli committed
866

867 868
    current_tab = "screens"
    model = Screen
Sli's avatar
Sli committed
869 870 871
    fields = ["name"]
    template_name = "core/create.jinja"
    success_url = reverse_lazy("com:screen_list")
872 873 874 875


class ScreenEditView(IsComAdminMixin, ComTabsMixin, UpdateView):
    """Edit communication screen"""
Sli's avatar
Sli committed
876

877 878 879
    pk_url_kwarg = "screen_id"
    current_tab = "screens"
    model = Screen
Sli's avatar
Sli committed
880 881 882
    fields = ["name"]
    template_name = "com/screen_edit.jinja"
    success_url = reverse_lazy("com:screen_list")
883 884 885 886


class ScreenDeleteView(IsComAdminMixin, ComTabsMixin, DeleteView):
    """Delete communication screen"""
Sli's avatar
Sli committed
887

888 889 890
    pk_url_kwarg = "screen_id"
    current_tab = "screens"
    model = Screen
Sli's avatar
Sli committed
891 892
    template_name = "core/delete_confirm.jinja"
    success_url = reverse_lazy("com:screen_list")