Merge branch 'clubs' into 'master'

Club tools enhacement

See merge request ae/Sith!108
This commit is contained in:
Skia 2017-10-06 11:48:02 +02:00
commit 0bef8d33d3
29 changed files with 825 additions and 335 deletions

View File

@ -58,6 +58,6 @@ def FetchMailingLists(request):
if key != settings.SITH_MAILING_FETCH_KEY: if key != settings.SITH_MAILING_FETCH_KEY:
raise PermissionDenied raise PermissionDenied
data = '' data = ''
for mailing in Mailing.objects.filter(is_moderated=True).all(): for mailing in Mailing.objects.filter(is_moderated=True, club__is_active=True).all():
data += mailing.fetch_format() + "\n" data += mailing.fetch_format() + "\n"
return Response(data) return Response(data)

View File

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from club.models import Club
from core.operations import PsqlRunOnly
def generate_club_pages(apps, schema_editor):
def recursive_generate_club_page(club):
club.make_page()
for child in Club.objects.filter(parent=club).all():
recursive_generate_club_page(child)
for club in Club.objects.filter(parent=None).all():
recursive_generate_club_page(club)
class Migration(migrations.Migration):
dependencies = [
('core', '0024_auto_20170906_1317'),
('club', '0010_club_logo'),
]
operations = [
migrations.AddField(
model_name='club',
name='is_active',
field=models.BooleanField(default=True, verbose_name='is active'),
),
migrations.AddField(
model_name='club',
name='page',
field=models.OneToOneField(related_name='club', blank=True, null=True, to='core.Page'),
),
migrations.AddField(
model_name='club',
name='short_description',
field=models.CharField(verbose_name='short description', max_length=1000, default='', blank=True, null=True),
),
PsqlRunOnly('SET CONSTRAINTS ALL IMMEDIATE', reverse_sql=migrations.RunSQL.noop),
migrations.RunPython(generate_club_pages),
PsqlRunOnly(migrations.RunSQL.noop, reverse_sql='SET CONSTRAINTS ALL IMMEDIATE'),
]

View File

@ -32,12 +32,13 @@ from django.db import transaction
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils import timezone from django.utils import timezone
from django.core.validators import RegexValidator, validate_email from django.core.validators import RegexValidator, validate_email
from django.utils.functional import cached_property
from core.models import User, MetaGroup, Group, SithFile, RealGroup, Notification from core.models import User, MetaGroup, Group, SithFile, RealGroup, Notification, Page
# Create your models here. # Create your models here.
class Club(models.Model): class Club(models.Model):
""" """
The Club class, made as a tree to allow nice tidy organization The Club class, made as a tree to allow nice tidy organization
@ -58,6 +59,8 @@ class Club(models.Model):
}, },
) )
logo = models.ImageField(upload_to='club_logos', verbose_name=_('logo'), null=True, blank=True) logo = models.ImageField(upload_to='club_logos', verbose_name=_('logo'), null=True, blank=True)
is_active = models.BooleanField(_('is active'), default=True)
short_description = models.CharField(_('short description'), max_length=1000, default='', blank=True, null=True)
address = models.CharField(_('address'), max_length=254) address = models.CharField(_('address'), max_length=254)
# email = models.EmailField(_('email address'), unique=True) # This should, and will be generated automatically # email = models.EmailField(_('email address'), unique=True) # This should, and will be generated automatically
owner_group = models.ForeignKey(Group, related_name="owned_club", owner_group = models.ForeignKey(Group, related_name="owned_club",
@ -66,10 +69,15 @@ class Club(models.Model):
view_groups = models.ManyToManyField(Group, related_name="viewable_club", blank=True) view_groups = models.ManyToManyField(Group, related_name="viewable_club", blank=True)
home = models.OneToOneField(SithFile, related_name='home_of_club', verbose_name=_("home"), null=True, blank=True, home = models.OneToOneField(SithFile, related_name='home_of_club', verbose_name=_("home"), null=True, blank=True,
on_delete=models.SET_NULL) on_delete=models.SET_NULL)
page = models.OneToOneField(Page, related_name="club", blank=True, null=True)
class Meta: class Meta:
ordering = ['name', 'unix_name'] ordering = ['name', 'unix_name']
@cached_property
def president(self):
return self.members.filter(role=settings.SITH_CLUB_ROLES_ID['President'], end_date=None).first()
def check_loop(self): def check_loop(self):
"""Raise a validation error when a loop is found within the parent list""" """Raise a validation error when a loop is found within the parent list"""
objs = [] objs = []
@ -102,6 +110,31 @@ class Club(models.Model):
self.home = home self.home = home
self.save() self.save()
def make_page(self):
root = User.objects.filter(username="root").first()
if not self.page:
club_root = Page.objects.filter(name=settings.SITH_CLUB_ROOT_PAGE).first()
if root and club_root:
public = Group.objects.filter(id=settings.SITH_GROUP_PUBLIC_ID).first()
p = Page(name=self.unix_name)
p.parent = club_root
p.save(force_lock=True)
if public:
p.view_groups.add(public)
p.save(force_lock=True)
if self.parent and self.parent.page:
p.parent = self.parent.page
self.page = p
self.save()
elif self.page and self.page.name != self.unix_name:
self.page.unset_lock()
self.page.name = self.unix_name
self.page.save(force_lock=True)
elif self.page and self.parent and self.parent.page and self.page.parent != self.parent.page:
self.page.unset_lock()
self.page.parent = self.parent.page
self.page.save(force_lock=True)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
with transaction.atomic(): with transaction.atomic():
creation = False creation = False
@ -122,6 +155,7 @@ class Club(models.Model):
self.home.edit_groups = [board] self.home.edit_groups = [board]
self.home.view_groups = [member, subscribers] self.home.view_groups = [member, subscribers]
self.home.save() self.home.save()
self.make_page()
def __str__(self): def __str__(self):
return self.name return self.name
@ -313,8 +347,14 @@ class MailingSubscription(models.Model):
def can_be_edited_by(self, user): def can_be_edited_by(self, user):
return (self.user is not None and user.id == self.user.id) return (self.user is not None and user.id == self.user.id)
@property
def get_email(self):
if self.user and not self.email:
return self.user.email
return self.email
def fetch_format(self): def fetch_format(self):
return self.email + ' ' return self.get_email + ' '
def __str__(self): def __str__(self):
if self.user: if self.user:

View File

@ -2,7 +2,16 @@
{% from 'core/macros.jinja' import user_profile_link %} {% from 'core/macros.jinja' import user_profile_link %}
{% block content %} {% block content %}
<div id="club_detail">
{% if club.logo %}
<div class="club_logo"><img src="{{ club.logo.url }}" alt="{{ club.unix_name }}"></div>
{% endif %}
{% if page_revision %}
{{ page_revision|markdown }}
{% else %}
<h3>{% trans %}Club{% endtrans %}</h3> <h3>{% trans %}Club{% endtrans %}</h3>
{% endif %}
</div>
{% endblock %} {% endblock %}

View File

@ -5,7 +5,20 @@
{% endblock %} {% endblock %}
{% macro display_club(club) -%} {% macro display_club(club) -%}
{% if club.is_active or user.is_root %}
<li><a href="{{ url('club:club_view', club_id=club.id) }}">{{ club.name }}</a> <li><a href="{{ url('club:club_view', club_id=club.id) }}">{{ club.name }}</a>
{% if not club.is_active %}
({% trans %}inactive{% endtrans %})
{% endif %}
{% if club.president %} - <a href="{{ url('core:user_profile', user_id=club.president.user.id) }}">{{ club.president.user }}</a>{% endif %}
{% if club.short_description %}<p>{{ club.short_description|markdown }}</p>{% endif %}
{% endif %}
{%- if club.children.all()|length != 0 %} {%- if club.children.all()|length != 0 %}
<ul> <ul>
{%- for c in club.children.order_by('name') %} {%- for c in club.children.order_by('name') %}
@ -23,7 +36,7 @@
{% if club_list %} {% if club_list %}
<h3>{% trans %}Club list{% endtrans %}</h3> <h3>{% trans %}Club list{% endtrans %}</h3>
<ul> <ul>
{%- for c in club_list.order_by('name') if c.parent is none %} {%- for c in club_list.all().order_by('name') if c.parent is none %}
{{ display_club(c) }} {{ display_club(c) }}
{%- endfor %} {%- endfor %}
</ul> </ul>

View File

@ -16,6 +16,12 @@
<a href="{{ url('club:mailing_delete', mailing_id=mailing.id) }}"> - {% trans %}Delete{% endtrans %}</a> <a href="{{ url('club:mailing_delete', mailing_id=mailing.id) }}"> - {% trans %}Delete{% endtrans %}</a>
{%- endif -%} {%- endif -%}
</h2> </h2>
<form method="GET" action="{{ url('club:mailing_generate', mailing_id=mailing.id) }}" style="display:inline-block;">
<input type="submit" name="generateMalingList" value="{% trans %}Generate mailing list{% endtrans %}">
</form>
<form method="GET" action="{{ url('club:mailing_clean', mailing_id=mailing.id) }}" style="display:inline-block;">
<input type="submit" name="cleanMailingList" value="{% trans %}Clean mailing list{% endtrans %}">
</form>
<hr> <hr>
<table> <table>
<tr> <tr>
@ -29,7 +35,7 @@
{% else %} {% else %}
<td>{% trans %}Unregistered user{% endtrans %}</td> <td>{% trans %}Unregistered user{% endtrans %}</td>
{% endif %} {% endif %}
<td>{{ subscriber.email }}</td> <td>{{ subscriber.get_email }}</td>
<td><a href="{{ url('club:mailing_subscription_delete', mailing_subscription_id=subscriber.id) }}">{% trans %}Delete{% endtrans %}</a></td> <td><a href="{{ url('club:mailing_subscription_delete', mailing_subscription_id=subscriber.id) }}">{% trans %}Delete{% endtrans %}</a></td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -0,0 +1,13 @@
{% extends "core/base.jinja" %}
{% from 'core/macros_pages.jinja' import page_history %}
{% block content %}
{% if club.page %}
{{ page_history(club.page) }}
{% else %}
{% trans %}No page existing for this club{% endtrans %}
{% endif %}
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends "core/base.jinja" %}
{% from 'core/macros_pages.jinja' import markdown_preview_script, page_edit_form %}
{% block head %}
{{ super() }}
{{ markdown_preview_script(csrf_token) }}
{% endblock %}
{% block content %}
{{ page_edit_form(page, form, url('club:club_edit_page', club_id=page.club.id), csrf_token) }}
{% endblock %}

View File

@ -32,7 +32,10 @@ urlpatterns = [
url(r'^new$', ClubCreateView.as_view(), name='club_new'), url(r'^new$', ClubCreateView.as_view(), name='club_new'),
url(r'^stats$', ClubStatView.as_view(), name='club_stats'), url(r'^stats$', ClubStatView.as_view(), name='club_stats'),
url(r'^(?P<club_id>[0-9]+)/$', ClubView.as_view(), name='club_view'), url(r'^(?P<club_id>[0-9]+)/$', ClubView.as_view(), name='club_view'),
url(r'^(?P<club_id>[0-9]+)/rev/(?P<rev_id>[0-9]+)/$', ClubRevView.as_view(), name='club_view_rev'),
url(r'^(?P<club_id>[0-9]+)/hist$', ClubPageHistView.as_view(), name='club_hist'),
url(r'^(?P<club_id>[0-9]+)/edit$', ClubEditView.as_view(), name='club_edit'), url(r'^(?P<club_id>[0-9]+)/edit$', ClubEditView.as_view(), name='club_edit'),
url(r'^(?P<club_id>[0-9]+)/edit/page$', ClubPageEditView.as_view(), name='club_edit_page'),
url(r'^(?P<club_id>[0-9]+)/members$', ClubMembersView.as_view(), name='club_members'), url(r'^(?P<club_id>[0-9]+)/members$', ClubMembersView.as_view(), name='club_members'),
url(r'^(?P<club_id>[0-9]+)/elderlies$', ClubOldMembersView.as_view(), name='club_old_members'), url(r'^(?P<club_id>[0-9]+)/elderlies$', ClubOldMembersView.as_view(), name='club_old_members'),
url(r'^(?P<club_id>[0-9]+)/sellings$', ClubSellingView.as_view(), name='club_sellings'), url(r'^(?P<club_id>[0-9]+)/sellings$', ClubSellingView.as_view(), name='club_sellings'),
@ -42,6 +45,8 @@ urlpatterns = [
url(r'^(?P<club_id>[0-9]+)/mailing$', ClubMailingView.as_view(action="display"), name='mailing'), url(r'^(?P<club_id>[0-9]+)/mailing$', ClubMailingView.as_view(action="display"), name='mailing'),
url(r'^(?P<club_id>[0-9]+)/mailing/new/mailing$', ClubMailingView.as_view(action="add_mailing"), name='mailing_create'), url(r'^(?P<club_id>[0-9]+)/mailing/new/mailing$', ClubMailingView.as_view(action="add_mailing"), name='mailing_create'),
url(r'^(?P<club_id>[0-9]+)/mailing/new/subscription$', ClubMailingView.as_view(action="add_member"), name='mailing_subscription_create'), url(r'^(?P<club_id>[0-9]+)/mailing/new/subscription$', ClubMailingView.as_view(action="add_member"), name='mailing_subscription_create'),
url(r'^(?P<mailing_id>[0-9]+)/mailing/generate$', MailingAutoGenerationView.as_view(), name='mailing_generate'),
url(r'^(?P<mailing_id>[0-9]+)/mailing/clean$', MailingAutoCleanView.as_view(), name='mailing_clean'),
url(r'^(?P<mailing_id>[0-9]+)/mailing/delete$', MailingDeleteView.as_view(), name='mailing_delete'), url(r'^(?P<mailing_id>[0-9]+)/mailing/delete$', MailingDeleteView.as_view(), name='mailing_delete'),
url(r'^(?P<mailing_subscription_id>[0-9]+)/mailing/delete/subscription$', MailingSubscriptionDeleteView.as_view(), name='mailing_subscription_delete'), url(r'^(?P<mailing_subscription_id>[0-9]+)/mailing/delete/subscription$', MailingSubscriptionDeleteView.as_view(), name='mailing_subscription_delete'),
url(r'^membership/(?P<membership_id>[0-9]+)/set_old$', MembershipSetOldView.as_view(), name='membership_set_old'), url(r'^membership/(?P<membership_id>[0-9]+)/set_old$', MembershipSetOldView.as_view(), name='membership_set_old'),

View File

@ -24,25 +24,25 @@
# #
from django import forms from django import forms
from django.views.generic import ListView, DetailView, TemplateView from django.views.generic import ListView, DetailView, TemplateView, View
from django.views.generic.edit import DeleteView from django.views.generic.edit import DeleteView
from django.views.generic.detail import SingleObjectMixin from django.views.generic.detail import SingleObjectMixin
from django.views.generic.edit import UpdateView, CreateView from django.views.generic.edit import UpdateView, CreateView
from django.http import HttpResponseRedirect, HttpResponse from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext as _t from django.utils.translation import ugettext as _t
from ajax_select.fields import AutoCompleteSelectField from ajax_select.fields import AutoCompleteSelectField
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404, redirect
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, PageEditViewBase
from core.views.forms import SelectDate, SelectDateTime from core.views.forms import SelectDate, SelectDateTime
from club.models import Club, Membership, Mailing, MailingSubscription from club.models import Club, Membership, Mailing, MailingSubscription
from sith.settings import SITH_MAXIMUM_FREE_ROLE from sith.settings import SITH_MAXIMUM_FREE_ROLE
from counter.models import Selling, Counter from counter.models import Selling, Counter
from core.models import User from core.models import User, PageRev
from django.conf import settings from django.conf import settings
@ -86,6 +86,8 @@ class MailingSubscriptionForm(forms.ModelForm):
class ClubTabsMixin(TabedViewMixin): class ClubTabsMixin(TabedViewMixin):
def get_tabs_title(self): def get_tabs_title(self):
if isinstance(self.object, PageRev):
self.object = self.object.page.club
return self.object.get_display_name() return self.object.get_display_name()
def get_list_of_tabs(self): def get_list_of_tabs(self):
@ -106,6 +108,12 @@ class ClubTabsMixin(TabedViewMixin):
'slug': 'elderlies', 'slug': 'elderlies',
'name': _("Old members"), 'name': _("Old members"),
}) })
if self.object.page:
tab_list.append({
'url': reverse('club:club_hist', kwargs={'club_id': self.object.id}),
'slug': 'history',
'name': _("History"),
})
if self.request.user.can_edit(self.object): if self.request.user.can_edit(self.object):
tab_list.append({ tab_list.append({
'url': reverse('club:tools', kwargs={'club_id': self.object.id}), 'url': reverse('club:tools', kwargs={'club_id': self.object.id}),
@ -117,6 +125,12 @@ class ClubTabsMixin(TabedViewMixin):
'slug': 'edit', 'slug': 'edit',
'name': _("Edit"), 'name': _("Edit"),
}) })
if self.object.page and self.request.user.can_edit(self.object.page):
tab_list.append({
'url': reverse('core:page_edit', kwargs={'page_name': self.object.page.get_full_name()}),
'slug': 'page_edit',
'name': _('Edit club page')
})
tab_list.append({ tab_list.append({
'url': reverse('club:club_sellings', kwargs={'club_id': self.object.id}), 'url': reverse('club:club_sellings', kwargs={'club_id': self.object.id}),
'slug': 'sellings', 'slug': 'sellings',
@ -153,6 +167,55 @@ class ClubView(ClubTabsMixin, DetailView):
template_name = 'club/club_detail.jinja' template_name = 'club/club_detail.jinja'
current_tab = "infos" current_tab = "infos"
def get_context_data(self, **kwargs):
kwargs = super(ClubView, self).get_context_data(**kwargs)
if self.object.page and self.object.page.revisions.exists():
kwargs['page_revision'] = self.object.page.revisions.last().content
return kwargs
class ClubRevView(ClubView):
"""
Display a specific page revision
"""
def dispatch(self, request, *args, **kwargs):
obj = self.get_object()
self.revision = get_object_or_404(PageRev, pk=kwargs['rev_id'], page__club=obj)
return super(ClubRevView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
kwargs = super(ClubRevView, self).get_context_data(**kwargs)
kwargs['page_revision'] = self.revision.content
return kwargs
class ClubPageEditView(ClubTabsMixin, PageEditViewBase):
template_name = 'club/pagerev_edit.jinja'
current_tab = "page_edit"
def dispatch(self, request, *args, **kwargs):
self.club = get_object_or_404(Club, pk=kwargs['club_id'])
if not self.club.page:
raise Http404
return super(ClubPageEditView, self).dispatch(request, *args, **kwargs)
def get_object(self):
self.page = self.club.page
return self._get_revision()
def get_success_url(self, **kwargs):
return reverse_lazy('club:club_view', kwargs={'club_id': self.club.id})
class ClubPageHistView(ClubTabsMixin, CanViewMixin, DetailView):
"""
Modification hostory of the page
"""
model = Club
pk_url_kwarg = "club_id"
template_name = 'club/page_history.jinja'
current_tab = "history"
class ClubToolsView(ClubTabsMixin, CanEditMixin, DetailView): class ClubToolsView(ClubTabsMixin, CanEditMixin, DetailView):
""" """
@ -209,28 +272,30 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, UpdateView):
form.instance = Membership(club=self.object, user=self.request.user) form.instance = Membership(club=self.object, user=self.request.user)
if not self.request.user.is_root: if not self.request.user.is_root:
form.fields.pop('start_date', None) form.fields.pop('start_date', None)
# form.initial = {'user': self.request.user}
# form._user = self.request.user
return form return form
def post(self, request, *args, **kwargs): def form_valid(self, form):
""" """
Check user rights Check user rights
""" """
self.object = self.get_object() user = self.request.user
form = self.get_form() ms = self.object.get_membership_for(user)
if form.is_valid():
ms = self.object.get_membership_for(request.user)
if (form.cleaned_data['role'] <= SITH_MAXIMUM_FREE_ROLE or if (form.cleaned_data['role'] <= SITH_MAXIMUM_FREE_ROLE or
(ms is not None and ms.role >= form.cleaned_data['role']) or (ms is not None and ms.role >= form.cleaned_data['role']) or
request.user.is_board_member or user.is_board_member or user.is_root):
request.user.is_root): form.save()
return self.form_valid(form) form = self.form_class()
return super(ModelFormMixin, self).form_valid(form)
else: else:
form.add_error(None, _("You do not have the permission to do that")) form.add_error(None, _("You do not have the permission to do that"))
return self.form_invalid(form) return self.form_invalid(form)
else:
return self.form_invalid(form) def dispatch(self, request, *args, **kwargs):
self.request = request
return super(ClubMembersView, self).dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs):
return reverse_lazy('club:club_members', kwargs={'club_id': self.club.id})
class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView): class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView):
@ -337,7 +402,7 @@ class ClubEditView(ClubTabsMixin, CanEditMixin, UpdateView):
""" """
model = Club model = Club
pk_url_kwarg = "club_id" pk_url_kwarg = "club_id"
fields = ['address', 'logo'] fields = ['address', 'logo', 'short_description']
template_name = 'core/edit.jinja' template_name = 'core/edit.jinja'
current_tab = "edit" current_tab = "edit"
@ -348,7 +413,7 @@ class ClubEditPropView(ClubTabsMixin, CanEditPropMixin, UpdateView):
""" """
model = Club model = Club
pk_url_kwarg = "club_id" pk_url_kwarg = "club_id"
fields = ['name', 'unix_name', 'parent'] fields = ['name', 'unix_name', 'parent', 'is_active']
template_name = 'core/edit.jinja' template_name = 'core/edit.jinja'
current_tab = "props" current_tab = "props"
@ -497,3 +562,33 @@ class MailingSubscriptionDeleteView(CanEditMixin, DeleteView):
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
return reverse_lazy('club:mailing', kwargs={'club_id': self.club_id}) return reverse_lazy('club:mailing', kwargs={'club_id': self.club_id})
class MailingAutoGenerationView(View):
def dispatch(self, request, *args, **kwargs):
self.mailing = get_object_or_404(Mailing, pk=kwargs['mailing_id'])
if not request.user.can_edit(self.mailing):
raise PermissionDenied
return super(MailingAutoGenerationView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
club = self.mailing.club
self.mailing.subscriptions.all().delete()
members = club.members.filter(role__gte=settings.SITH_CLUB_ROLES_ID['Board member']).exclude(end_date__lte=timezone.now())
for member in members.all():
MailingSubscription(user=member.user, mailing=self.mailing).save()
return redirect('club:mailing', club_id=club.id)
class MailingAutoCleanView(View):
def dispatch(self, request, *args, **kwargs):
self.mailing = get_object_or_404(Mailing, pk=kwargs['mailing_id'])
if not request.user.can_edit(self.mailing):
raise PermissionDenied
return super(MailingAutoCleanView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
self.mailing.subscriptions.all().delete()
return redirect('club:mailing', club_id=self.mailing.club.id)

View File

@ -85,6 +85,12 @@ class Command(BaseCommand):
profiles_root.save() profiles_root.save()
home_root = SithFile(parent=None, name="users", is_folder=True, owner=root) home_root = SithFile(parent=None, name="users", is_folder=True, owner=root)
home_root.save() home_root.save()
# Page needed for club creation
p = Page(name=settings.SITH_CLUB_ROOT_PAGE)
p.set_lock(root)
p.save()
club_root = SithFile(parent=None, name="clubs", is_folder=True, owner=root) club_root = SithFile(parent=None, name="clubs", is_folder=True, owner=root)
club_root.save() club_root.save()
SithFile(parent=None, name="SAS", is_folder=True, owner=root).save() SithFile(parent=None, name="SAS", is_folder=True, owner=root).save()
@ -97,6 +103,7 @@ class Command(BaseCommand):
launderette_club = Club(id=84, name=settings.SITH_LAUNDERETTE_MANAGER['name'], launderette_club = Club(id=84, name=settings.SITH_LAUNDERETTE_MANAGER['name'],
unix_name=settings.SITH_LAUNDERETTE_MANAGER['unix_name'], unix_name=settings.SITH_LAUNDERETTE_MANAGER['unix_name'],
address=settings.SITH_LAUNDERETTE_MANAGER['address']) address=settings.SITH_LAUNDERETTE_MANAGER['address'])
launderette_club.save() launderette_club.save()
self.reset_index("club") self.reset_index("club")
for b in settings.SITH_COUNTER_BARS: for b in settings.SITH_COUNTER_BARS:

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.core.validators
class Migration(migrations.Migration):
dependencies = [
('core', '0024_auto_20170906_1317'),
]
operations = [
migrations.AlterField(
model_name='page',
name='name',
field=models.CharField(max_length=30, verbose_name='page unix name', validators=[django.core.validators.RegexValidator('^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]$', 'Enter a valid page name. This value may contain only unaccented letters, numbers and ./+/-/_ characters.')]),
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0025_auto_20170919_1521'),
]
operations = [
migrations.AlterField(
model_name='notification',
name='type',
field=models.CharField(choices=[('MAILING_MODERATION', 'A new mailing list needs to be moderated'), ('NEWS_MODERATION', 'There are %s fresh news to be moderated'), ('FILE_MODERATION', 'New files to be moderated'), ('SAS_MODERATION', 'There are %s pictures to be moderated in the SAS'), ('NEW_PICTURES', "You've been identified on some pictures"), ('REFILLING', 'You just refilled of %s'), ('SELLING', 'You just bought %s'), ('GENERIC', 'You have a notification')], verbose_name='type', max_length=32, default='GENERIC'),
),
]

View File

@ -841,7 +841,7 @@ class Page(models.Model):
name = models.CharField(_('page unix name'), max_length=30, name = models.CharField(_('page unix name'), max_length=30,
validators=[ validators=[
validators.RegexValidator( validators.RegexValidator(
r'^[A-z.+-]+$', r'^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]$',
_('Enter a valid page name. This value may contain only ' _('Enter a valid page name. This value may contain only '
'unaccented letters, numbers ' 'and ./+/-/_ characters.') 'unaccented letters, numbers ' 'and ./+/-/_ characters.')
), ], ), ],
@ -892,6 +892,19 @@ class Page(models.Model):
code='loop', code='loop',
) )
def can_be_edited_by(self, user):
if hasattr(self, 'club') and self.club.can_be_edited_by(user):
# Override normal behavior for clubs
return True
if self.name == settings.SITH_CLUB_ROOT_PAGE and user.is_board_member:
return True
return False
def can_be_viewed_by(self, user):
if self.is_club_page:
return True
return False
def get_parent_list(self): def get_parent_list(self):
l = [] l = []
p = self.parent p = self.parent
@ -999,6 +1012,15 @@ class Page(models.Model):
except: except:
return self.name return self.name
@cached_property
def is_club_page(self):
club_root_page = Page.objects.filter(name=settings.SITH_CLUB_ROOT_PAGE).first()
return club_root_page is not None and (self == club_root_page or club_root_page in self.get_parent_list())
@cached_property
def need_club_redirection(self):
return self.is_club_page and self.name != settings.SITH_CLUB_ROOT_PAGE
def delete(self): def delete(self):
self.unset_lock_recursive() self.unset_lock_recursive()
self.set_lock_recursive(User.objects.get(id=0)) self.set_lock_recursive(User.objects.get(id=0))
@ -1048,6 +1070,9 @@ class PageRev(models.Model):
else: else:
return object.__getattribute__(self, attr) return object.__getattribute__(self, attr)
def can_be_edited_by(self, user):
return self.page.can_be_edited_by(user)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.revision is None: if self.revision is None:
self.revision = self.page.revisions.all().count() + 1 self.revision = self.page.revisions.all().count() + 1

50
core/operations.py Normal file
View File

@ -0,0 +1,50 @@
# -*- coding:utf-8 -*
#
# Copyright 2016,2017
# - Sli <antoine@bartuccio.fr>
#
# 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.
#
#
"""
This page is useful for custom migration tricks.
Sometimes, when you need to have a migration hack and you think it can be
useful again, put it there, we never know if we might need the hack again.
"""
from django.db import connection, migrations
class PsqlRunOnly(migrations.RunSQL):
"""
This is an SQL runner that will launch the given command only if
the used DBMS is PostgreSQL.
It may be useful to run Postgres' specific SQL, or to take actions
that would be non-senses with backends other than Postgre, such
as disabling particular constraints that would prevent the migration
to run successfully.
See `club/migrations/0010_auto_20170912_2028.py` as an example.
Some explanations can be found here too:
https://stackoverflow.com/questions/28429933/django-migrations-using-runpython-to-commit-changes
"""
def _run_sql(self, schema_editor, sqls):
if connection.vendor == 'postgresql':
super(PsqlRunOnly, self)._run_sql(schema_editor, sqls)

View File

@ -1224,3 +1224,15 @@ label {
.ui-corner-left { .ui-corner-left {
border-radius: 0px; border-radius: 0px;
} }
#club_detail {
.club_logo {
float: right;
img {
display: block;
max-height: 10em;
max-width: 10em;
}
}
}

View File

@ -150,6 +150,7 @@
{% if not popup %} {% if not popup %}
<nav> <nav>
<a href="{{ url('core:index') }}">{% trans %}Main{% endtrans %}</a> <a href="{{ url('core:index') }}">{% trans %}Main{% endtrans %}</a>
<a href="{{ url('core:page', page_name='clubs') }}">{% trans %}Clubs{% endtrans %}</a>
<a href="{{ url('matmat:search_clear') }}">{% trans %}Matmatronch{% endtrans %}</a> <a href="{{ url('matmat:search_clear') }}">{% trans %}Matmatronch{% endtrans %}</a>
<a href="{{ url('core:page', page_name="Index") }}">{% trans %}Wiki{% endtrans %}</a> <a href="{{ url('core:page', page_name="Index") }}">{% trans %}Wiki{% endtrans %}</a>
<a href="{{ url('sas:main') }}">{% trans %}SAS{% endtrans %}</a> <a href="{{ url('sas:main') }}">{% trans %}SAS{% endtrans %}</a>

View File

@ -0,0 +1,50 @@
{% from "core/macros.jinja" import user_profile_link %}
{% macro page_history(page) %}
<p>{% trans page_name=page.name %}You're seeing the history of page "{{ page_name }}"{% endtrans %}</p>
<ul>
{% for r in (page.revisions.all()|sort(attribute='date', reverse=True)) %}
{% if loop.index < 2 %}
<li><a href="{{ url('core:page', page_name=page.get_full_name()) }}">{% trans %}last{% endtrans %}</a> -
{{ user_profile_link(page.revisions.last().author) }} -
{{ page.revisions.last().date|localtime|date(DATETIME_FORMAT) }} {{ page.revisions.last().date|localtime|time(DATETIME_FORMAT) }}</a></li>
{% else %}
<li><a href="{{ url('core:page_rev', page_name=page.get_full_name(), rev=r['id']) }}">{{ r.revision }}</a> -
{{ user_profile_link(r.author) }} -
{{ r.date|localtime|date(DATETIME_FORMAT) }} {{ r.date|localtime|time(DATETIME_FORMAT) }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endmacro %}
{% macro page_edit_form(page, form, url, token) %}
<h2>{% trans %}Edit page{% endtrans %}</h2>
<form action="{{ url }}" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ token }}">
{{ form.as_p() }}
{{ markdown_preview_button() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
<div id="preview" class="page_content">
</div>
{% endmacro %}
{% macro markdown_preview_script(token) %}
<script>
function make_preview() {
text = $("#id_content").val();
console.log("Rendering text: " + text);
$.ajax({
url: "{{ url('api:api_markdown') }}",
method: "POST",
data: { text: text, csrfmiddlewaretoken: "{{ token }}"}
}).done(function (msg) {
$("#preview").html(msg);
});
}
</script>
{% endmacro %}
{% macro markdown_preview_button() %}
<p><input type="button" value="{% trans %}Preview{% endtrans %}" onclick="javascript:make_preview();" /></p>
{% endmacro %}

View File

@ -25,12 +25,16 @@
<div class="tool_bar"> <div class="tool_bar">
<div class="tools"> <div class="tools">
{% if page %} {% if page %}
{% if page.club %}
<a href="{{ url('club:club_view', club_id=page.club.id) }}">{% trans %}Return to club management{% endtrans %}</a>
{% else %}
<a href="{{ url('core:page', page.get_full_name()) }}">{% trans %}View{% endtrans %}</a> <a href="{{ url('core:page', page.get_full_name()) }}">{% trans %}View{% endtrans %}</a>
{% endif %}
<a href="{{ url('core:page_hist', page_name=page.get_full_name()) }}">{% trans %}History{% endtrans %}</a> <a href="{{ url('core:page_hist', page_name=page.get_full_name()) }}">{% trans %}History{% endtrans %}</a>
{% if can_edit(page, user) %} {% if can_edit(page, user) %}
<a href="{{ url('core:page_edit', page_name=page.get_full_name()) }}">{% trans %}Edit{% endtrans %}</a> <a href="{{ url('core:page_edit', page_name=page.get_full_name()) }}">{% trans %}Edit{% endtrans %}</a>
{% endif %} {% endif %}
{% if can_edit_prop(page, user) %} {% if can_edit_prop(page, user) and not page.is_club_page %}
<a href="{{ url('core:page_prop', page_name=page.get_full_name()) }}">{% trans %}Prop{% endtrans %}</a> <a href="{{ url('core:page_prop', page_name=page.get_full_name()) }}">{% trans %}Prop{% endtrans %}</a>
{% endif %} {% endif %}
{% endif %} {% endif %}

View File

@ -1,23 +1,10 @@
{% extends "core/page.jinja" %} {% extends "core/page.jinja" %}
{% from "core/macros.jinja" import user_profile_link %} {% from "core/macros_pages.jinja" import page_history %}
{% block page %} {% block page %}
<h3>{% trans %}Page history{% endtrans %}</h3> <h3>{% trans %}Page history{% endtrans %}</h3>
<p>{% trans page_name=page.name %}You're seeing the history of page "{{ page_name }}"{% endtrans %}</p> {{ page_history(page) }}
<ul>
{% for r in (page.revisions.all()|sort(attribute='date', reverse=True)) %}
{% if loop.index < 2 %}
<li><a href="{{ url('core:page', page_name=page.get_full_name()) }}">{% trans %}last{% endtrans %}</a> -
{{ user_profile_link(page.revisions.last().author) }} -
{{ page.revisions.last().date|localtime|date(DATETIME_FORMAT) }} {{ page.revisions.last().date|localtime|time(DATETIME_FORMAT) }}</a></li>
{% else %}
<li><a href="{{ url('core:page_rev', page_name=page.get_full_name(), rev=r['id']) }}">{{ r.revision }}</a> -
{{ user_profile_link(r.author) }} -
{{ r.date|localtime|date(DATETIME_FORMAT) }} {{ r.date|localtime|time(DATETIME_FORMAT) }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endblock %} {% endblock %}

View File

@ -1,12 +1,18 @@
{% extends "core/page.jinja" %} {% extends "core/page.jinja" %}
{% block content %} {% block content %}
{% if page %}
{{ super() }}
{% endif %}
<h2>{% trans %}Page properties{% endtrans %}</h2> <h2>{% trans %}Page properties{% endtrans %}</h2>
<form action="" method="post"> <form action="" method="post">
{% csrf_token %} {% csrf_token %}
{{ form.as_p() }} {{ form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p> <p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form> </form>
{% if page %}
<a href="{{ url('core:page_delete', page_id=page.id)}}">{% trans %}Delete{% endtrans %}</a>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -1,33 +1,13 @@
{% extends "core/page.jinja" %} {% extends "core/page.jinja" %}
{% from 'core/macros_pages.jinja' import markdown_preview_script, page_edit_form %}
{% block head %} {% block head %}
{{ super() }} {{ super() }}
<script> {{ markdown_preview_script(csrf_token) }}
function make_preview() {
text = $("#id_content").val();
console.log("Rendering text: " + text);
$.ajax({
url: "{{ url('api:api_markdown') }}",
method: "POST",
data: { text: text, csrfmiddlewaretoken: "{{ csrf_token }}"}
}).done(function (msg) {
$("#preview").html(msg);
});
}
</script>
{% endblock %} {% endblock %}
{% block page %} {% block page %}
<h2>{% trans %}Edit page{% endtrans %}</h2> {{ page_edit_form(page, form, url('core:page_edit', page_name=page.get_full_name()), csrf_token) }}
<form action="{{ url('core:page_edit', page_name=page.get_full_name()) }}" method="post">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="button" value="{% trans %}Preview{% endtrans %}" onclick="javascript:make_preview();" /></p>
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
<a href="{{ url('core:page_delete', page_id=page.id)}}">{% trans %}Delete{% endtrans %}</a>
<div id="preview" class="page_content">
</div>
{% endblock %} {% endblock %}

View File

@ -87,9 +87,9 @@ urlpatterns = [
url(r'^page/$', PageListView.as_view(), name='page_list'), url(r'^page/$', PageListView.as_view(), name='page_list'),
url(r'^page/create$', PageCreateView.as_view(), name='page_new'), url(r'^page/create$', PageCreateView.as_view(), name='page_new'),
url(r'^page/(?P<page_id>[0-9]*)/delete$', PageDeleteView.as_view(), name='page_delete'), url(r'^page/(?P<page_id>[0-9]*)/delete$', PageDeleteView.as_view(), name='page_delete'),
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/edit$', PageEditView.as_view(), name='page_edit'), url(r'^page/(?P<page_name>([/a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9])+)/edit$', PageEditView.as_view(), name='page_edit'),
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/prop$', PagePropView.as_view(), name='page_prop'), url(r'^page/(?P<page_name>([/a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9])+)/prop$', PagePropView.as_view(), name='page_prop'),
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/hist$', PageHistView.as_view(), name='page_hist'), url(r'^page/(?P<page_name>([/a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9])+)/hist$', PageHistView.as_view(), name='page_hist'),
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/rev/(?P<rev>[0-9]+)/', PageRevView.as_view(), name='page_rev'), url(r'^page/(?P<page_name>([/a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9])+)/rev/(?P<rev>[0-9]+)/', PageRevView.as_view(), name='page_rev'),
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/$', PageView.as_view(), name='page'), url(r'^page/(?P<page_name>([/a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9])+)/$', PageView.as_view(), name='page'),
] ]

View File

@ -269,3 +269,17 @@ class PagePropForm(forms.ModelForm):
super(PagePropForm, self).__init__(*arg, **kwargs) super(PagePropForm, self).__init__(*arg, **kwargs)
self.fields['edit_groups'].required = False self.fields['edit_groups'].required = False
self.fields['view_groups'].required = False self.fields['view_groups'].required = False
class PageForm(forms.ModelForm):
class Meta:
model = Page
fields = ['parent', 'name', 'owner_group', 'edit_groups', 'view_groups']
widgets = {
'edit_groups': CheckboxSelectMultiple,
'view_groups': CheckboxSelectMultiple,
}
def __init__(self, *args, **kwargs):
super(PageForm, self).__init__(*args, **kwargs)
self.fields['parent'].queryset = self.fields['parent'].queryset.exclude(name=settings.SITH_CLUB_ROOT_PAGE).filter(club=None)

View File

@ -27,13 +27,23 @@ from django.core.urlresolvers import reverse_lazy
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, CreateView, DeleteView from django.views.generic.edit import UpdateView, CreateView, DeleteView
from django.forms.models import modelform_factory from django.forms.models import modelform_factory
from django.forms import CheckboxSelectMultiple from django.http import Http404
from django.shortcuts import redirect
from core.models import Page, PageRev, LockError from core.models import Page, PageRev, LockError
from core.views.forms import MarkdownInput from core.views.forms import MarkdownInput, PageForm, PagePropForm
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin
class CanEditPagePropMixin(CanEditPropMixin):
def dispatch(self, request, *args, **kwargs):
res = super(CanEditPagePropMixin, self).dispatch(request, *args, **kwargs)
if self.object.is_club_page:
raise Http404
return res
class PageListView(CanViewMixin, ListView): class PageListView(CanViewMixin, ListView):
model = Page model = Page
template_name = 'core/page_list.jinja' template_name = 'core/page_list.jinja'
@ -43,6 +53,12 @@ class PageView(CanViewMixin, DetailView):
model = Page model = Page
template_name = 'core/page_detail.jinja' template_name = 'core/page_detail.jinja'
def dispatch(self, request, *args, **kwargs):
res = super(PageView, self).dispatch(request, *args, **kwargs)
if self.object and self.object.need_club_redirection:
return redirect('club:club_view', club_id=self.object.club.id)
return res
def get_object(self): def get_object(self):
self.page = Page.get_page_by_full_name(self.kwargs['page_name']) self.page = Page.get_page_by_full_name(self.kwargs['page_name'])
return self.page return self.page
@ -58,6 +74,12 @@ class PageHistView(CanViewMixin, DetailView):
model = Page model = Page
template_name = 'core/page_hist.jinja' template_name = 'core/page_hist.jinja'
def dispatch(self, request, *args, **kwargs):
res = super(PageHistView, self).dispatch(request, *args, **kwargs)
if self.object.need_club_redirection:
return redirect('club:club_hist', club_id=self.object.club.id)
return res
def get_object(self): def get_object(self):
self.page = Page.get_page_by_full_name(self.kwargs['page_name']) self.page = Page.get_page_by_full_name(self.kwargs['page_name'])
return self.page return self.page
@ -67,6 +89,12 @@ class PageRevView(CanViewMixin, DetailView):
model = Page model = Page
template_name = 'core/page_detail.jinja' template_name = 'core/page_detail.jinja'
def dispatch(self, request, *args, **kwargs):
res = super(PageRevView, self).dispatch(request, *args, **kwargs)
if self.object.need_club_redirection:
return redirect('club:club_view_rev', club_id=self.object.club.id, rev_id=kwargs['rev'])
return res
def get_object(self): def get_object(self):
self.page = Page.get_page_by_full_name(self.kwargs['page_name']) self.page = Page.get_page_by_full_name(self.kwargs['page_name'])
return self.page return self.page
@ -88,12 +116,7 @@ class PageRevView(CanViewMixin, DetailView):
class PageCreateView(CanCreateMixin, CreateView): class PageCreateView(CanCreateMixin, CreateView):
model = Page model = Page
form_class = modelform_factory(Page, form_class = PageForm
fields=['parent', 'name', 'owner_group', 'edit_groups', 'view_groups', ],
widgets={
'edit_groups': CheckboxSelectMultiple,
'view_groups': CheckboxSelectMultiple,
})
template_name = 'core/page_prop.jinja' template_name = 'core/page_prop.jinja'
def get_initial(self): def get_initial(self):
@ -118,14 +141,9 @@ class PageCreateView(CanCreateMixin, CreateView):
return ret return ret
class PagePropView(CanEditPropMixin, UpdateView): class PagePropView(CanEditPagePropMixin, UpdateView):
model = Page model = Page
form_class = modelform_factory(Page, form_class = PagePropForm
fields=['parent', 'name', 'owner_group', 'edit_groups', 'view_groups', ],
widgets={
'edit_groups': CheckboxSelectMultiple,
'view_groups': CheckboxSelectMultiple,
})
template_name = 'core/page_prop.jinja' template_name = 'core/page_prop.jinja'
slug_field = '_full_name' slug_field = '_full_name'
slug_url_kwarg = 'page_name' slug_url_kwarg = 'page_name'
@ -149,17 +167,20 @@ class PagePropView(CanEditPropMixin, UpdateView):
return self.page return self.page
class PageEditView(CanEditMixin, UpdateView): class PageEditViewBase(CanEditMixin, UpdateView):
model = PageRev model = PageRev
form_class = modelform_factory(model=PageRev, fields=['title', 'content', ], widgets={'content': MarkdownInput}) form_class = modelform_factory(model=PageRev, fields=['title', 'content', ], widgets={'content': MarkdownInput})
template_name = 'core/pagerev_edit.jinja' template_name = 'core/pagerev_edit.jinja'
def get_object(self): def get_object(self):
self.page = Page.get_page_by_full_name(self.kwargs['page_name']) self.page = Page.get_page_by_full_name(self.kwargs['page_name'])
return self._get_revision()
def _get_revision(self):
if self.page is not None: if self.page is not None:
# First edit # First edit
if self.page.revisions.all() is None: if self.page.revisions.all() is None:
rev = PageRev(author=request.user) rev = PageRev(author=self.request.user)
rev.save() rev.save()
self.page.revisions.add(rev) self.page.revisions.add(rev)
try: try:
@ -170,7 +191,7 @@ class PageEditView(CanEditMixin, UpdateView):
return None return None
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(PageEditView, self).get_context_data(**kwargs) context = super(PageEditViewBase, self).get_context_data(**kwargs)
if self.page is not None: if self.page is not None:
context['page'] = self.page context['page'] = self.page
else: else:
@ -186,10 +207,19 @@ class PageEditView(CanEditMixin, UpdateView):
new_rev.author = self.request.user new_rev.author = self.request.user
new_rev.page = self.page new_rev.page = self.page
form.instance = new_rev form.instance = new_rev
return super(PageEditView, self).form_valid(form) return super(PageEditViewBase, self).form_valid(form)
class PageDeleteView(CanEditPropMixin, DeleteView): class PageEditView(PageEditViewBase):
def dispatch(self, request, *args, **kwargs):
res = super(PageEditView, self).dispatch(request, *args, **kwargs)
if self.object.page.need_club_redirection:
return redirect('club:club_edit_page', club_id=self.object.page.club.id)
return res
class PageDeleteView(CanEditPagePropMixin, DeleteView):
model = Page model = Page
template_name = 'core/delete_confirm.jinja' template_name = 'core/delete_confirm.jinja'
pk_url_kwarg = 'page_id' pk_url_kwarg = 'page_id'

File diff suppressed because it is too large Load Diff

View File

@ -1375,6 +1375,20 @@ def migrate_mailings():
MailingSubscription(mailing=mailing, email=to_unicode(mailing_sub['email'])).save() MailingSubscription(mailing=mailing, email=to_unicode(mailing_sub['email'])).save()
def migrate_club_again():
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("SELECT * FROM asso")
print("Migrating club is_active")
for club in cur:
try:
c = Club.objects.get(unix_name=club['nom_unix_asso'])
c.is_active = club['hidden'] == 0
c.save()
except: pass
def main(): def main():
print("Start at %s" % start) print("Start at %s" % start)
# Core # Core
@ -1396,7 +1410,8 @@ def main():
# reset_sas_moderators() # reset_sas_moderators()
# migrate_forum() # migrate_forum()
# reset_index('forum') # reset_index('forum')
migrate_mailings() # migrate_mailings()
migrate_club_again()
end = datetime.datetime.now() end = datetime.datetime.now()
print("End at %s" % end) print("End at %s" % end)
print("Running time: %s" % (end - start)) print("Running time: %s" % (end - start))

View File

@ -296,6 +296,9 @@ SITH_LAUNDERETTE_MANAGER = {
'address': "6 Boulevard Anatole France, 90000 Belfort" 'address': "6 Boulevard Anatole France, 90000 Belfort"
} }
# Main root for club pages
SITH_CLUB_ROOT_PAGE = "clubs"
# Define the date in the year serving as reference for the subscriptions calendar # Define the date in the year serving as reference for the subscriptions calendar
# (month, day) # (month, day)
SITH_START_DATE = (8, 15) # 15th August SITH_START_DATE = (8, 15) # 15th August