Add first Matmat' app

This commit is contained in:
Skia 2017-05-09 23:42:01 +02:00
parent 5060114305
commit b3bc33a319
15 changed files with 460 additions and 1 deletions

View File

@ -7,6 +7,11 @@
<ul>
<li> <a href="{{ url('com:news_new') }}?club={{ object.id }}">{% trans %}Create a news{% endtrans %}</a></li>
<li> <a href="{{ url('com:weekmail_article') }}?club={{ object.id }}">{% trans %}Post in the Weekmail{% endtrans %}</a></li>
{% if object.matmat %}
<li> <a href="{{ url('matmat:detail', matmat_id=object.matmat.id) }}">{% trans %}Edit Matmatronch{% endtrans %}</a></li>
{% else %}
<li> <a href="{{ url('matmat:create', club_id=object.id) }}">{% trans %}New Matmatronch{% endtrans %}</a></li>
{% endif %}
</ul>
<h4>{% trans %}Counters:{% endtrans %}</h4>
<ul>

View File

@ -0,0 +1,26 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Preferences{% endtrans %}
{% endblock %}
{% block content %}
<h2>{% trans %}Preferences{% endtrans %}</h2>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
{% if matmat_form %}
<form action="{{ url('matmat:user_tools') }}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ matmat_form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
{% else %}
<p><a href="{{ url('matmat:user_tools') }}">Matmatronch tools</a></p>
{% endif %}
{% endblock %}

View File

@ -46,6 +46,7 @@ from core.views.forms import RegisteringForm, UserPropForm, UserProfileForm, Log
from core.models import User, SithFile, Preferences
from club.models import Club
from subscription.models import Subscription
from matmat.views import UserMatmatForm
def login(request):
"""
@ -427,7 +428,7 @@ class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView):
"""
model = User
pk_url_kwarg = "user_id"
template_name = "core/edit.jinja"
template_name = "core/user_preferences.jinja"
form_class = modelform_factory(Preferences, fields=['receive_weekmail'])
context_object_name = "profile"
current_tab = "prefs"
@ -446,6 +447,12 @@ class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView):
kwargs.update({'instance': pref})
return kwargs
def get_context_data(self, **kwargs):
kwargs = super(UserPreferencesView, self).get_context_data(**kwargs)
if not hasattr(self.object, 'matmat_user'):
kwargs['matmat_form'] = UserMatmatForm()
return kwargs
class UserUpdateGroupView(UserTabsMixin, CanEditPropMixin, UpdateView):
"""
Edit a user's groups

24
matmat/__init__.py Normal file
View File

@ -0,0 +1,24 @@
# -*- coding:utf-8 -*
#
# Copyright 2017
# - Skia <skia@libskia.so>
#
# 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.
#
#

29
matmat/admin.py Normal file
View File

@ -0,0 +1,29 @@
# -*- coding:utf-8 -*
#
# Copyright 2017
# - Skia <skia@libskia.so>
#
# 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.
#
#
from django.contrib import admin
from matmat.models import Matmat
admin.site.register(Matmat)

View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('club', '0007_auto_20170324_0917'),
]
operations = [
migrations.CreateModel(
name='Matmat',
fields=[
('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
('subscription_deadline', models.DateField(verbose_name='subscription deadline', default=django.utils.timezone.now, help_text='Before this date, users are allowed to subscribe to this Matmatronch. After this date, users subscribed will be allowed to comment on each other.')),
('comments_deadline', models.DateField(verbose_name='comments deadline', default=django.utils.timezone.now, help_text="After this date, users won't be able to make comments anymore")),
('club', models.OneToOneField(related_name='matmat', to='club.Club')),
],
),
migrations.CreateModel(
name='MatmatComment',
fields=[
('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='matmat', to=settings.AUTH_USER_MODEL, related_name='users', null=True)),
],
),
migrations.CreateModel(
name='MatmatUser',
fields=[
('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
('matmat', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='matmat', to='matmat.Matmat', related_name='users', null=True)),
('user', models.OneToOneField(related_name='matmat_user', verbose_name='matmat user', to=settings.AUTH_USER_MODEL)),
],
),
]

View File

99
matmat/models.py Normal file
View File

@ -0,0 +1,99 @@
# -*- coding:utf-8 -*
#
# Copyright 2017
# - Skia <skia@libskia.so>
#
# 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.
#
#
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.conf import settings
from django.utils import timezone
from django.core.exceptions import ValidationError
from datetime import timedelta, date
from core.models import User
from club.models import Club
class MatmatManager(models.Manager):
def get_queryset(self):
return super(MatmatManager, self).get_queryset()
class AvailableMatmatManager(models.Manager):
def get_queryset(self):
return super(AvailableMatmatManager,
self).get_queryset().filter(subscription_deadline__gte=date.today())
class Matmat(models.Model):
"""
This is the main class, the Matmat itself.
It contains the deadlines for the users, and the link to the club that makes
its Matmatronch.
"""
subscription_deadline = models.DateField(_('subscription deadline'),
default=timezone.now, help_text=_("Before this date, users are "
"allowed to subscribe to this Matmatronch. "
"After this date, users subscribed will be allowed to comment on each other."))
comments_deadline = models.DateField(_('comments deadline'),
default=timezone.now, help_text=_("After this date, users won't be "
"able to make comments anymore"))
club = models.OneToOneField(Club, related_name='matmat')
objects = MatmatManager()
availables = AvailableMatmatManager()
def __str__(self):
return str(self.club.name)
def clean(self):
if self.subscription_deadline > self.comments_deadline:
raise ValidationError(_("Closing the subscriptions after the "
"comments is definitively not a good idea."))
def get_absolute_url(self):
return reverse('matmat:detail', kwargs={'matmat_id': self.id})
def is_owned_by(self, user):
return user.is_owner(self.club)
def can_be_viewed_by(self, user):
return user.can_edit(self.club)
class MatmatUser(models.Model):
"""
This class is only here to avoid cross references between the core, club,
and matmat modules. It binds a User to a Matmat without needing to import
Matmat into the core.
"""
user = models.OneToOneField(User, verbose_name=_("matmat user"), related_name='matmat_user')
matmat = models.ForeignKey(Matmat, verbose_name=_("matmat"), related_name='users', blank=True, null=True, on_delete=models.SET_NULL)
class MatmatComment(models.Model):
"""
This represent a comment given by someone to someone else in the same Matmat
instance.
"""
author = models.ForeignKey(MatmatUser, verbose_name=_("author"), related_name='given_comments')
target = models.ForeignKey(MatmatUser, verbose_name=_("target"), related_name='received_comments')
content = models.TextField(_("content"), default="", max_length=400)
is_moderated = models.BooleanField(_("is moderated"), default=False)

View File

@ -0,0 +1,19 @@
{% extends 'core/base.jinja' %}
{% block title %}
{% trans club=object.club %}{{ club }}'s Matmatronch{% endtrans %}
{% endblock %}
{% block content %}
<h2>{% trans club=object.club %}{{ club }}'s Matmatronch{% endtrans %}</h2>
<a href="{{ url('matmat:edit', matmat_id=object.id) }}">Edit</a>
<p>Subscription deadline: {{ object.subscription_deadline|date(DATETIME_FORMAT) }}</p>
<p>Comment deadline: {{ object.comments_deadline|date(DATETIME_FORMAT) }}</p>
<a href="#">Export</a>
<p>People:</p>
<ul>
{% for u in object.users.all() %}
<li>{{ u.user.get_display_name() }} - <a href="{{ url('matmat:delete_user', matmat_id=object.id, user_id=u.id) }}">Delete</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,25 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans user_name=user.get_display_name() %}{{ user_name }}'s Matmat{% endtrans %}
{% endblock %}
{% block content %}
<h3>{% trans%}Matmatronch'{% endtrans %}</h3>
{% if subscribe_form %}
<form action="" method="post">
{% csrf_token %}
{{ subscribe_form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
{% else %}
<p>{% trans matmat = user.matmat_user.matmat %}You are subscribed to the Matmatronch {{ matmat }}{% endtrans %}</p>
{% for u in user.matmat_user.matmat.users.all() %}
<div class="ib">
<div>{{ u.user.get_display_name() }}</div>
<a>Comment</a>
</div>
{% endfor %}
{% endif %}
{% endblock %}

27
matmat/tests.py Normal file
View File

@ -0,0 +1,27 @@
# -*- coding:utf-8 -*
#
# Copyright 2017
# - Skia <skia@libskia.so>
#
# 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.
#
#
from django.test import TestCase
# Create your tests here.

36
matmat/urls.py Normal file
View File

@ -0,0 +1,36 @@
# -*- coding:utf-8 -*
#
# Copyright 2017
# - Skia <skia@libskia.so>
#
# 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.
#
#
from django.conf.urls import url, include
from matmat.views import *
urlpatterns = [
url(r'^(?P<club_id>[0-9]+)/new$', MatmatCreateView.as_view(), name='create'),
url(r'^(?P<matmat_id>[0-9]+)/edit$', MatmatEditView.as_view(), name='edit'),
url(r'^(?P<matmat_id>[0-9]+)/delete/(?P<user_id>[0-9]+)$', MatmatDeleteUserView.as_view(), name='delete_user'),
url(r'^(?P<matmat_id>[0-9]+)$', MatmatDetailView.as_view(), name='detail'),
url(r'^tools$', UserMatmatView.as_view(), name='user_tools'),
]

118
matmat/views.py Normal file
View File

@ -0,0 +1,118 @@
# -*- coding:utf-8 -*
#
# Copyright 2017
# - Skia <skia@libskia.so>
#
# 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.
#
#
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, RedirectView, TemplateView
from django.views.generic.edit import UpdateView, CreateView, DeleteView, FormView, SingleObjectMixin
from django.utils.translation import ugettext_lazy as _
from django import forms
from matmat.models import Matmat, MatmatUser
from core.views.forms import SelectFile, SelectDate
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin, QuickNotifMixin
from core.models import User
from club.models import Club
class MatmatForm(forms.ModelForm):
class Meta:
model = Matmat
fields = ['subscription_deadline', 'comments_deadline']
widgets = {
'subscription_deadline': SelectDate,
'comments_deadline': SelectDate,
}
class MatmatCreateView(CanEditPropMixin, CreateView):
"""
Create a matmat for a club
"""
model = Matmat
form_class = MatmatForm
template_name = 'core/create.jinja'
def post(self, request, *args, **kwargs):
"""
Affect club
"""
form = self.get_form()
if form.is_valid():
club = get_object_or_404(Club, id=self.kwargs['club_id'])
form.instance.club = club
ret = self.form_valid(form)
return ret
else:
return self.form_invalid(form)
class MatmatEditView(CanEditPropMixin, UpdateView):
model = Matmat
form_class = MatmatForm
template_name = 'core/edit.jinja'
pk_url_kwarg = 'matmat_id'
class MatmatDetailView(CanViewMixin, DetailView):
model = Matmat
template_name = 'matmat/detail.jinja'
pk_url_kwarg = 'matmat_id'
class MatmatDeleteUserView(CanEditPropMixin, SingleObjectMixin, RedirectView):
model = Matmat
pk_url_kwarg = 'matmat_id'
permanent = False
def get(self, request, *args, **kwargs):
self.object = self.get_object()
user = get_object_or_404(MatmatUser, id=self.kwargs['user_id'])
user.delete()
# See if we need to also delete the comments on the user, or if we keep them
return redirect(self.object.get_absolute_url())
# User side
class UserMatmatForm(forms.Form):
matmat = forms.ModelChoiceField(Matmat.availables.all(), required=False, label=_("Select matmatronch"),
help_text=_("This allows you to subscribe to a Matmatronch. "
"Be aware that you can subscribe only once, so don't play with that, "
"or you will expose yourself to the admins' wrath!"))
class UserMatmatView(QuickNotifMixin, TemplateView):
"""
Display a user's matmat tools
"""
template_name = "core/user_matmat.jinja"
def post(self, request, *args, **kwargs):
self.form = UserMatmatForm(request.POST)
if self.form.is_valid():
matmat_user = MatmatUser(user=request.user,
matmat=self.form.cleaned_data['matmat'])
matmat_user.save()
self.quick_notif_list += ['qn_success']
return super(UserMatmatView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
kwargs = super(UserMatmatView, self).get_context_data(**kwargs)
kwargs['user'] = self.request.user
if not hasattr(self.request.user, 'matmat_user'):
kwargs['subscribe_form'] = UserMatmatForm()
return kwargs

View File

@ -86,6 +86,7 @@ INSTALLED_APPS = (
'election',
'forum',
'stock',
'matmat',
)
MIDDLEWARE_CLASSES = (

View File

@ -66,6 +66,7 @@ urlpatterns = [
url(r'^api/v1/', include('api.urls', namespace="api", app_name="api")),
url(r'^election/', include('election.urls', namespace="election", app_name="election")),
url(r'^forum/', include('forum.urls', namespace="forum", app_name="forum")),
url(r'^matmat/', include('matmat.urls', namespace="matmat", app_name="matmat")),
url(r'^admin/', include(admin.site.urls)),
url(r'^ajax_select/', include(ajax_select_urls)),
url(r'^i18n/', include('django.conf.urls.i18n')),