Format trombi

This commit is contained in:
Pierre Brunet 2017-06-12 10:10:52 +02:00
parent 113c9e696b
commit 69c95cfd37
3 changed files with 101 additions and 79 deletions

View File

@ -34,14 +34,17 @@ from core.models import User
from core.utils import get_start_of_semester, get_semester from core.utils import get_start_of_semester, get_semester
from club.models import Club from club.models import Club
class TrombiManager(models.Manager): class TrombiManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(TrombiManager, self).get_queryset() return super(TrombiManager, self).get_queryset()
class AvailableTrombiManager(models.Manager): class AvailableTrombiManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(AvailableTrombiManager, return super(AvailableTrombiManager,
self).get_queryset().filter(subscription_deadline__gte=date.today()) self).get_queryset().filter(subscription_deadline__gte=date.today())
class Trombi(models.Model): class Trombi(models.Model):
""" """
@ -50,14 +53,14 @@ class Trombi(models.Model):
its Trombi. its Trombi.
""" """
subscription_deadline = models.DateField(_('subscription deadline'), subscription_deadline = models.DateField(_('subscription deadline'),
default=date.today, help_text=_("Before this date, users are " default=date.today, help_text=_("Before this date, users are "
"allowed to subscribe to this Trombi. " "allowed to subscribe to this Trombi. "
"After this date, users subscribed will be allowed to comment on each other.")) "After this date, users subscribed will be allowed to comment on each other."))
comments_deadline = models.DateField(_('comments deadline'), comments_deadline = models.DateField(_('comments deadline'),
default=date.today, help_text=_("After this date, users won't be " default=date.today, help_text=_("After this date, users won't be "
"able to make comments anymore.")) "able to make comments anymore."))
max_chars = models.IntegerField(_('maximum characters'), default=400, max_chars = models.IntegerField(_('maximum characters'), default=400,
help_text=_('Maximum number of characters allowed in a comment.')) help_text=_('Maximum number of characters allowed in a comment.'))
show_profiles = models.BooleanField(_("show users profiles to each other"), default=True) show_profiles = models.BooleanField(_("show users profiles to each other"), default=True)
club = models.OneToOneField(Club, related_name='trombi') club = models.OneToOneField(Club, related_name='trombi')
@ -70,7 +73,7 @@ class Trombi(models.Model):
def clean(self): def clean(self):
if self.subscription_deadline > self.comments_deadline: if self.subscription_deadline > self.comments_deadline:
raise ValidationError(_("Closing the subscriptions after the " raise ValidationError(_("Closing the subscriptions after the "
"comments is definitively not a good idea.")) "comments is definitively not a good idea."))
def get_absolute_url(self): def get_absolute_url(self):
return reverse('trombi:detail', kwargs={'trombi_id': self.id}) return reverse('trombi:detail', kwargs={'trombi_id': self.id})
@ -81,6 +84,7 @@ class Trombi(models.Model):
def can_be_viewed_by(self, user): def can_be_viewed_by(self, user):
return user.id in [u.user.id for u in self.users.all()] return user.id in [u.user.id for u in self.users.all()]
class TrombiUser(models.Model): class TrombiUser(models.Model):
""" """
This class is only here to avoid cross references between the core, club, This class is only here to avoid cross references between the core, club,
@ -92,9 +96,9 @@ class TrombiUser(models.Model):
user = models.OneToOneField(User, verbose_name=_("trombi user"), related_name='trombi_user') user = models.OneToOneField(User, verbose_name=_("trombi user"), related_name='trombi_user')
trombi = models.ForeignKey(Trombi, verbose_name=_("trombi"), related_name='users', blank=True, null=True, on_delete=models.SET_NULL) trombi = models.ForeignKey(Trombi, verbose_name=_("trombi"), related_name='users', blank=True, null=True, on_delete=models.SET_NULL)
profile_pict = models.ImageField(upload_to='trombi', verbose_name=_("profile pict"), null=True, blank=True, profile_pict = models.ImageField(upload_to='trombi', verbose_name=_("profile pict"), null=True, blank=True,
help_text=_("The profile picture you want in the trombi (warning: this picture may be published)")) help_text=_("The profile picture you want in the trombi (warning: this picture may be published)"))
scrub_pict = models.ImageField(upload_to='trombi', verbose_name=_("scrub pict"), null=True, blank=True, scrub_pict = models.ImageField(upload_to='trombi', verbose_name=_("scrub pict"), null=True, blank=True,
help_text=_("The scrub picture you want in the trombi (warning: this picture may be published)")) help_text=_("The scrub picture you want in the trombi (warning: this picture may be published)"))
def __str__(self): def __str__(self):
return str(self.user) return str(self.user)
@ -120,6 +124,7 @@ class TrombiUser(models.Model):
end=end_date, end=end_date,
).save() ).save()
class TrombiComment(models.Model): class TrombiComment(models.Model):
""" """
This represent a comment given by someone to someone else in the same Trombi This represent a comment given by someone to someone else in the same Trombi
@ -156,4 +161,3 @@ class TrombiClubMembership(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return reverse('trombi:profile') return reverse('trombi:profile')

View File

@ -22,7 +22,7 @@
# #
# #
from django.conf.urls import url, include from django.conf.urls import url
from trombi.views import * from trombi.views import *

View File

@ -23,10 +23,10 @@
# #
from django.http import Http404 from django.http import Http404
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.core.urlresolvers import reverse_lazy, reverse from django.core.urlresolvers import reverse
from django.views.generic import ListView, DetailView, RedirectView, TemplateView from django.views.generic import DetailView, RedirectView, TemplateView
from django.views.generic.edit import UpdateView, CreateView, DeleteView, FormView, SingleObjectMixin from django.views.generic.edit import UpdateView, CreateView
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django import forms from django import forms
from django.conf import settings from django.conf import settings
@ -35,11 +35,12 @@ from django.forms.models import modelform_factory
from datetime import date from datetime import date
from trombi.models import Trombi, TrombiUser, TrombiComment, TrombiClubMembership from trombi.models import Trombi, TrombiUser, TrombiComment, TrombiClubMembership
from core.views.forms import SelectFile, SelectDate from core.views.forms import SelectDate
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin, QuickNotifMixin from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, QuickNotifMixin
from core.models import User from core.models import User
from club.models import Club from club.models import Club
class TrombiTabsMixin(TabedViewMixin): class TrombiTabsMixin(TabedViewMixin):
def get_tabs_title(self): def get_tabs_title(self):
return _("Trombi") return _("Trombi")
@ -47,39 +48,42 @@ class TrombiTabsMixin(TabedViewMixin):
def get_list_of_tabs(self): def get_list_of_tabs(self):
tab_list = [] tab_list = []
tab_list.append({ tab_list.append({
'url': reverse('trombi:user_tools'), 'url': reverse('trombi:user_tools'),
'slug': 'tools', 'slug': 'tools',
'name': _("Tools"), 'name': _("Tools"),
}) })
tab_list.append({ tab_list.append({
'url': reverse('trombi:profile'), 'url': reverse('trombi:profile'),
'slug': 'profile', 'slug': 'profile',
'name': _("My profile"), 'name': _("My profile"),
}) })
tab_list.append({ tab_list.append({
'url': reverse('trombi:pictures'), 'url': reverse('trombi:pictures'),
'slug': 'pictures', 'slug': 'pictures',
'name': _("My pictures"), 'name': _("My pictures"),
}) })
try: try:
trombi = self.request.user.trombi_user.trombi trombi = self.request.user.trombi_user.trombi
if self.request.user.is_owner(trombi): if self.request.user.is_owner(trombi):
tab_list.append({ tab_list.append({
'url': reverse('trombi:detail', kwargs={'trombi_id': trombi.id}), 'url': reverse('trombi:detail', kwargs={'trombi_id': trombi.id}),
'slug': 'admin_tools', 'slug': 'admin_tools',
'name': _("Admin tools"), 'name': _("Admin tools"),
}) })
except: pass except:
pass
return tab_list return tab_list
class TrombiForm(forms.ModelForm): class TrombiForm(forms.ModelForm):
class Meta: class Meta:
model = Trombi model = Trombi
fields = ['subscription_deadline', 'comments_deadline', 'max_chars', 'show_profiles'] fields = ['subscription_deadline', 'comments_deadline', 'max_chars', 'show_profiles']
widgets = { widgets = {
'subscription_deadline': SelectDate, 'subscription_deadline': SelectDate,
'comments_deadline': SelectDate, 'comments_deadline': SelectDate,
} }
class TrombiCreateView(CanEditPropMixin, CreateView): class TrombiCreateView(CanEditPropMixin, CreateView):
""" """
@ -102,6 +106,7 @@ class TrombiCreateView(CanEditPropMixin, CreateView):
else: else:
return self.form_invalid(form) return self.form_invalid(form)
class TrombiEditView(CanEditPropMixin, TrombiTabsMixin, UpdateView): class TrombiEditView(CanEditPropMixin, TrombiTabsMixin, UpdateView):
model = Trombi model = Trombi
form_class = TrombiForm form_class = TrombiForm
@ -110,7 +115,8 @@ class TrombiEditView(CanEditPropMixin, TrombiTabsMixin, UpdateView):
current_tab = "admin_tools" current_tab = "admin_tools"
def get_success_url(self): def get_success_url(self):
return super(TrombiEditView, self).get_success_url()+"?qn_success" return super(TrombiEditView, self).get_success_url() + "?qn_success"
class TrombiDetailView(CanEditMixin, QuickNotifMixin, TrombiTabsMixin, DetailView): class TrombiDetailView(CanEditMixin, QuickNotifMixin, TrombiTabsMixin, DetailView):
model = Trombi model = Trombi
@ -118,6 +124,7 @@ class TrombiDetailView(CanEditMixin, QuickNotifMixin, TrombiTabsMixin, DetailVie
pk_url_kwarg = 'trombi_id' pk_url_kwarg = 'trombi_id'
current_tab = "admin_tools" current_tab = "admin_tools"
class TrombiDeleteUserView(CanEditPropMixin, TrombiTabsMixin, DeleteView): class TrombiDeleteUserView(CanEditPropMixin, TrombiTabsMixin, DeleteView):
model = TrombiUser model = TrombiUser
pk_url_kwarg = 'user_id' pk_url_kwarg = 'user_id'
@ -127,6 +134,7 @@ class TrombiDeleteUserView(CanEditPropMixin, TrombiTabsMixin, DeleteView):
def get_success_url(self): def get_success_url(self):
return reverse('trombi:detail', kwargs={'trombi_id': self.object.trombi.id}) + "?qn_success" return reverse('trombi:detail', kwargs={'trombi_id': self.object.trombi.id}) + "?qn_success"
class TrombiModerateCommentsView(CanEditPropMixin, QuickNotifMixin, TrombiTabsMixin, DetailView): class TrombiModerateCommentsView(CanEditPropMixin, QuickNotifMixin, TrombiTabsMixin, DetailView):
model = Trombi model = Trombi
template_name = 'trombi/comment_moderation.jinja' template_name = 'trombi/comment_moderation.jinja'
@ -136,13 +144,15 @@ class TrombiModerateCommentsView(CanEditPropMixin, QuickNotifMixin, TrombiTabsMi
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(TrombiModerateCommentsView, self).get_context_data(**kwargs) kwargs = super(TrombiModerateCommentsView, self).get_context_data(**kwargs)
kwargs['comments'] = TrombiComment.objects.filter(is_moderated=False, kwargs['comments'] = TrombiComment.objects.filter(is_moderated=False,
author__trombi__id=self.object.id).exclude(target__user__id=self.request.user.id) author__trombi__id=self.object.id).exclude(target__user__id=self.request.user.id)
return kwargs return kwargs
class TrombiModerateForm(forms.Form): class TrombiModerateForm(forms.Form):
reason = forms.CharField(help_text=_("Explain why you rejected the comment")) reason = forms.CharField(help_text=_("Explain why you rejected the comment"))
action = forms.CharField(initial="delete", widget=forms.widgets.HiddenInput) action = forms.CharField(initial="delete", widget=forms.widgets.HiddenInput)
class TrombiModerateCommentView(DetailView): class TrombiModerateCommentView(DetailView):
model = TrombiComment model = TrombiComment
template_name = 'core/edit.jinja' template_name = 'core/edit.jinja'
@ -159,42 +169,45 @@ class TrombiModerateCommentView(DetailView):
if request.POST['action'] == "accept": if request.POST['action'] == "accept":
self.object.is_moderated = True self.object.is_moderated = True
self.object.save() self.object.save()
return redirect(reverse('trombi:moderate_comments', kwargs={'trombi_id': self.object.author.trombi.id})+"?qn_success") return redirect(reverse('trombi:moderate_comments', kwargs={'trombi_id': self.object.author.trombi.id}) + "?qn_success")
elif request.POST['action'] == "reject": elif request.POST['action'] == "reject":
return super(TrombiModerateCommentView, self).get(request, *args, **kwargs) return super(TrombiModerateCommentView, self).get(request, *args, **kwargs)
elif request.POST['action'] == "delete" and "reason" in request.POST.keys(): elif request.POST['action'] == "delete" and "reason" in request.POST.keys():
self.object.author.user.email_user( self.object.author.user.email_user(
subject="[%s] %s" % (settings.SITH_NAME, _("Rejected comment")), subject="[%s] %s" % (settings.SITH_NAME, _("Rejected comment")),
message=_("Your comment to %(target)s on the Trombi \"%(trombi)s\" was rejected for the following " message=_("Your comment to %(target)s on the Trombi \"%(trombi)s\" was rejected for the following "
"reason: %(reason)s\n\n" "reason: %(reason)s\n\n"
"Your comment was:\n\n%(content)s" "Your comment was:\n\n%(content)s"
) % { ) % {
'target': self.object.target.user.get_display_name(), 'target': self.object.target.user.get_display_name(),
'trombi': self.object.author.trombi, 'trombi': self.object.author.trombi,
'reason': request.POST["reason"], 'reason': request.POST["reason"],
'content': self.object.content, 'content': self.object.content,
}, },
) )
self.object.delete() self.object.delete()
return redirect(reverse('trombi:moderate_comments', kwargs={'trombi_id': self.object.author.trombi.id})+"?qn_success") return redirect(reverse('trombi:moderate_comments', kwargs={'trombi_id': self.object.author.trombi.id}) + "?qn_success")
raise Http404 raise Http404
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(TrombiModerateCommentView, self).get_context_data(**kwargs) kwargs = super(TrombiModerateCommentView, self).get_context_data(**kwargs)
kwargs['form'] = TrombiModerateForm() kwargs['form'] = TrombiModerateForm()
return kwargs return kwargs
# User side # User side
class TrombiModelChoiceField(forms.ModelChoiceField): class TrombiModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj): def label_from_instance(self, obj):
return _("%(name)s (deadline: %(date)s)") % {'name': str(obj), 'date': str(obj.subscription_deadline)} return _("%(name)s (deadline: %(date)s)") % {'name': str(obj), 'date': str(obj.subscription_deadline)}
class UserTrombiForm(forms.Form): class UserTrombiForm(forms.Form):
trombi = TrombiModelChoiceField(Trombi.availables.all(), required=False, label=_("Select trombi"), trombi = TrombiModelChoiceField(Trombi.availables.all(), required=False, label=_("Select trombi"),
help_text=_("This allows you to subscribe to a Trombi. " help_text=_("This allows you to subscribe to a Trombi. "
"Be aware that you can subscribe only once, so don't play with that, " "Be aware that you can subscribe only once, so don't play with that, "
"or you will expose yourself to the admins' wrath!")) "or you will expose yourself to the admins' wrath!"))
class UserTrombiToolsView(QuickNotifMixin, TrombiTabsMixin, TemplateView): class UserTrombiToolsView(QuickNotifMixin, TrombiTabsMixin, TemplateView):
""" """
@ -207,7 +220,7 @@ class UserTrombiToolsView(QuickNotifMixin, TrombiTabsMixin, TemplateView):
self.form = UserTrombiForm(request.POST) self.form = UserTrombiForm(request.POST)
if self.form.is_valid(): if self.form.is_valid():
trombi_user = TrombiUser(user=request.user, trombi_user = TrombiUser(user=request.user,
trombi=self.form.cleaned_data['trombi']) trombi=self.form.cleaned_data['trombi'])
trombi_user.save() trombi_user.save()
self.quick_notif_list += ['qn_success'] self.quick_notif_list += ['qn_success']
return super(UserTrombiToolsView, self).get(request, *args, **kwargs) return super(UserTrombiToolsView, self).get(request, *args, **kwargs)
@ -222,6 +235,7 @@ class UserTrombiToolsView(QuickNotifMixin, TrombiTabsMixin, TemplateView):
kwargs['date'] = date kwargs['date'] = date
return kwargs return kwargs
class UserTrombiEditPicturesView(TrombiTabsMixin, UpdateView): class UserTrombiEditPicturesView(TrombiTabsMixin, UpdateView):
model = TrombiUser model = TrombiUser
fields = ['profile_pict', 'scrub_pict'] fields = ['profile_pict', 'scrub_pict']
@ -232,18 +246,18 @@ class UserTrombiEditPicturesView(TrombiTabsMixin, UpdateView):
return self.request.user.trombi_user return self.request.user.trombi_user
def get_success_url(self): def get_success_url(self):
return reverse('trombi:user_tools')+"?qn_success" return reverse('trombi:user_tools') + "?qn_success"
class UserTrombiEditProfileView(QuickNotifMixin, TrombiTabsMixin, UpdateView): class UserTrombiEditProfileView(QuickNotifMixin, TrombiTabsMixin, UpdateView):
model = User model = User
form_class = modelform_factory(User, form_class = modelform_factory(User,
fields=['second_email', 'phone', 'department', 'dpt_option', fields=['second_email', 'phone', 'department', 'dpt_option',
'quote', 'parent_address'], 'quote', 'parent_address'],
labels={ labels={'second_email': _("Personal email (not UTBM)"),
'second_email': _("Personal email (not UTBM)"), 'phone': _("Phone"),
'phone': _("Phone"), 'parent_address': _("Native town"),
'parent_address': _("Native town"), })
})
template_name = "trombi/edit_profile.jinja" template_name = "trombi/edit_profile.jinja"
current_tab = "profile" current_tab = "profile"
@ -251,7 +265,8 @@ class UserTrombiEditProfileView(QuickNotifMixin, TrombiTabsMixin, UpdateView):
return self.request.user return self.request.user
def get_success_url(self): def get_success_url(self):
return reverse('trombi:user_tools')+"?qn_success" return reverse('trombi:user_tools') + "?qn_success"
class UserTrombiResetClubMembershipsView(RedirectView): class UserTrombiResetClubMembershipsView(RedirectView):
permanent = False permanent = False
@ -262,7 +277,8 @@ class UserTrombiResetClubMembershipsView(RedirectView):
return redirect(self.get_success_url()) return redirect(self.get_success_url())
def get_success_url(self): def get_success_url(self):
return reverse('trombi:profile')+"?qn_success" return reverse('trombi:profile') + "?qn_success"
class UserTrombiDeleteMembershipView(TrombiTabsMixin, CanEditMixin, DeleteView): class UserTrombiDeleteMembershipView(TrombiTabsMixin, CanEditMixin, DeleteView):
model = TrombiClubMembership model = TrombiClubMembership
@ -274,6 +290,7 @@ class UserTrombiDeleteMembershipView(TrombiTabsMixin, CanEditMixin, DeleteView):
def get_success_url(self): def get_success_url(self):
return super(UserTrombiDeleteMembershipView, self).get_success_url() + "?qn_success" return super(UserTrombiDeleteMembershipView, self).get_success_url() + "?qn_success"
class UserTrombiEditMembershipView(CanEditMixin, TrombiTabsMixin, UpdateView): class UserTrombiEditMembershipView(CanEditMixin, TrombiTabsMixin, UpdateView):
model = TrombiClubMembership model = TrombiClubMembership
pk_url_kwarg = "membership_id" pk_url_kwarg = "membership_id"
@ -300,6 +317,7 @@ class UserTrombiProfileView(TrombiTabsMixin, DetailView):
raise Http404() raise Http404()
return super(UserTrombiProfileView, self).get(request, *args, **kwargs) return super(UserTrombiProfileView, self).get(request, *args, **kwargs)
class TrombiCommentFormView(): class TrombiCommentFormView():
""" """
Create/edit a trombi comment Create/edit a trombi comment
@ -312,20 +330,20 @@ class TrombiCommentFormView():
self.trombi = self.request.user.trombi_user.trombi self.trombi = self.request.user.trombi_user.trombi
if date.today() <= self.trombi.subscription_deadline: if date.today() <= self.trombi.subscription_deadline:
raise Http404(_("You can not yet write comment, you must wait for " raise Http404(_("You can not yet write comment, you must wait for "
"the subscription deadline to be passed.")) "the subscription deadline to be passed."))
if self.trombi.comments_deadline < date.today(): if self.trombi.comments_deadline < date.today():
raise Http404(_("You can not write comment anymore, the deadline is " raise Http404(_("You can not write comment anymore, the deadline is "
"already passed.")) "already passed."))
return modelform_factory(self.model, fields=self.fields, return modelform_factory(self.model, fields=self.fields,
widgets={ widgets={
'content': forms.widgets.Textarea(attrs={'maxlength': self.trombi.max_chars}) 'content': forms.widgets.Textarea(attrs={'maxlength': self.trombi.max_chars})
}, },
help_texts={ help_texts={
'content': _("Maximum characters: %(max_length)s") % {'max_length': self.trombi.max_chars} 'content': _("Maximum characters: %(max_length)s") % {'max_length': self.trombi.max_chars}
}) })
def get_success_url(self): def get_success_url(self):
return reverse('trombi:user_tools')+"?qn_success" return reverse('trombi:user_tools') + "?qn_success"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(TrombiCommentFormView, self).get_context_data(**kwargs) kwargs = super(TrombiCommentFormView, self).get_context_data(**kwargs)
@ -335,6 +353,7 @@ class TrombiCommentFormView():
kwargs['target'] = self.object.target kwargs['target'] = self.object.target
return kwargs return kwargs
class TrombiCommentCreateView(TrombiCommentFormView, CreateView): class TrombiCommentCreateView(TrombiCommentFormView, CreateView):
def form_valid(self, form): def form_valid(self, form):
target = get_object_or_404(TrombiUser, id=self.kwargs['user_id']) target = get_object_or_404(TrombiUser, id=self.kwargs['user_id'])
@ -342,11 +361,10 @@ class TrombiCommentCreateView(TrombiCommentFormView, CreateView):
form.instance.target = target form.instance.target = target
return super(TrombiCommentCreateView, self).form_valid(form) return super(TrombiCommentCreateView, self).form_valid(form)
class TrombiCommentEditView(TrombiCommentFormView, CanViewMixin, UpdateView): class TrombiCommentEditView(TrombiCommentFormView, CanViewMixin, UpdateView):
pk_url_kwarg = "comment_id" pk_url_kwarg = "comment_id"
def form_valid(self, form): def form_valid(self, form):
form.instance.is_moderated = False form.instance.is_moderated = False
return super(TrombiCommentEditView, self).form_valid(form) return super(TrombiCommentEditView, self).form_valid(form)