diff --git a/api/views/club.py b/api/views/club.py
index ca2a8c1b..e4d4b30a 100644
--- a/api/views/club.py
+++ b/api/views/club.py
@@ -58,6 +58,6 @@ def FetchMailingLists(request):
if key != settings.SITH_MAILING_FETCH_KEY:
raise PermissionDenied
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"
return Response(data)
diff --git a/club/migrations/0010_auto_20170912_2028.py b/club/migrations/0010_auto_20170912_2028.py
new file mode 100644
index 00000000..af3e2bdf
--- /dev/null
+++ b/club/migrations/0010_auto_20170912_2028.py
@@ -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'),
+ ]
diff --git a/club/models.py b/club/models.py
index d2901505..81c92ef2 100644
--- a/club/models.py
+++ b/club/models.py
@@ -32,12 +32,13 @@ from django.db import transaction
from django.core.urlresolvers import reverse
from django.utils import timezone
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.
+
class Club(models.Model):
"""
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)
+ 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)
# email = models.EmailField(_('email address'), unique=True) # This should, and will be generated automatically
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)
home = models.OneToOneField(SithFile, related_name='home_of_club', verbose_name=_("home"), null=True, blank=True,
on_delete=models.SET_NULL)
+ page = models.OneToOneField(Page, related_name="club", blank=True, null=True)
class Meta:
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):
"""Raise a validation error when a loop is found within the parent list"""
objs = []
@@ -102,6 +110,31 @@ class Club(models.Model):
self.home = home
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):
with transaction.atomic():
creation = False
@@ -122,6 +155,7 @@ class Club(models.Model):
self.home.edit_groups = [board]
self.home.view_groups = [member, subscribers]
self.home.save()
+ self.make_page()
def __str__(self):
return self.name
@@ -313,8 +347,14 @@ class MailingSubscription(models.Model):
def can_be_edited_by(self, user):
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):
- return self.email + ' '
+ return self.get_email + ' '
def __str__(self):
if self.user:
diff --git a/club/templates/club/club_detail.jinja b/club/templates/club/club_detail.jinja
index daedbfcb..6dbb62b2 100644
--- a/club/templates/club/club_detail.jinja
+++ b/club/templates/club/club_detail.jinja
@@ -2,7 +2,16 @@
{% from 'core/macros.jinja' import user_profile_link %}
{% block content %}
-
{% trans %}Club{% endtrans %}
+
+ {% if club.logo %}
+
+ {% endif %}
+ {% if page_revision %}
+ {{ page_revision|markdown }}
+ {% else %}
+
{% trans %}Club{% endtrans %}
+ {% endif %}
+
{% endblock %}
diff --git a/club/templates/club/club_list.jinja b/club/templates/club/club_list.jinja
index 059ad85a..ba875c89 100644
--- a/club/templates/club/club_list.jinja
+++ b/club/templates/club/club_list.jinja
@@ -5,7 +5,20 @@
{% endblock %}
{% macro display_club(club) -%}
- {{ club.name }}
+
+ {% if club.is_active or user.is_root %}
+
+ {{ club.name }}
+
+ {% if not club.is_active %}
+ ({% trans %}inactive{% endtrans %})
+ {% endif %}
+
+ {% if club.president %} - {{ club.president.user }} {% endif %}
+ {% if club.short_description %}{{ club.short_description|markdown }}
{% endif %}
+
+ {% endif %}
+
{%- if club.children.all()|length != 0 %}
{%- for c in club.children.order_by('name') %}
@@ -23,7 +36,7 @@
{% if club_list %}
{% trans %}Club list{% endtrans %}
- {%- 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) }}
{%- endfor %}
diff --git a/club/templates/club/mailing.jinja b/club/templates/club/mailing.jinja
index 5ee67422..9c2af2b8 100644
--- a/club/templates/club/mailing.jinja
+++ b/club/templates/club/mailing.jinja
@@ -16,6 +16,12 @@
- {% trans %}Delete{% endtrans %}
{%- endif -%}
+
+
@@ -29,7 +35,7 @@
{% else %}
{% trans %}Unregistered user{% endtrans %}
{% endif %}
- {{ subscriber.email }}
+ {{ subscriber.get_email }}
{% trans %}Delete{% endtrans %}
{% endfor %}
diff --git a/club/templates/club/page_history.jinja b/club/templates/club/page_history.jinja
new file mode 100644
index 00000000..766ef8a1
--- /dev/null
+++ b/club/templates/club/page_history.jinja
@@ -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 %}
+
+
+
diff --git a/club/templates/club/pagerev_edit.jinja b/club/templates/club/pagerev_edit.jinja
new file mode 100644
index 00000000..232fe559
--- /dev/null
+++ b/club/templates/club/pagerev_edit.jinja
@@ -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 %}
+
+
+
diff --git a/club/urls.py b/club/urls.py
index 96195b11..a4022b16 100644
--- a/club/urls.py
+++ b/club/urls.py
@@ -32,7 +32,10 @@ urlpatterns = [
url(r'^new$', ClubCreateView.as_view(), name='club_new'),
url(r'^stats$', ClubStatView.as_view(), name='club_stats'),
url(r'^(?P[0-9]+)/$', ClubView.as_view(), name='club_view'),
+ url(r'^(?P[0-9]+)/rev/(?P[0-9]+)/$', ClubRevView.as_view(), name='club_view_rev'),
+ url(r'^(?P[0-9]+)/hist$', ClubPageHistView.as_view(), name='club_hist'),
url(r'^(?P[0-9]+)/edit$', ClubEditView.as_view(), name='club_edit'),
+ url(r'^(?P[0-9]+)/edit/page$', ClubPageEditView.as_view(), name='club_edit_page'),
url(r'^(?P[0-9]+)/members$', ClubMembersView.as_view(), name='club_members'),
url(r'^(?P[0-9]+)/elderlies$', ClubOldMembersView.as_view(), name='club_old_members'),
url(r'^(?P[0-9]+)/sellings$', ClubSellingView.as_view(), name='club_sellings'),
@@ -42,6 +45,8 @@ urlpatterns = [
url(r'^(?P[0-9]+)/mailing$', ClubMailingView.as_view(action="display"), name='mailing'),
url(r'^(?P[0-9]+)/mailing/new/mailing$', ClubMailingView.as_view(action="add_mailing"), name='mailing_create'),
url(r'^(?P[0-9]+)/mailing/new/subscription$', ClubMailingView.as_view(action="add_member"), name='mailing_subscription_create'),
+ url(r'^(?P[0-9]+)/mailing/generate$', MailingAutoGenerationView.as_view(), name='mailing_generate'),
+ url(r'^(?P[0-9]+)/mailing/clean$', MailingAutoCleanView.as_view(), name='mailing_clean'),
url(r'^(?P[0-9]+)/mailing/delete$', MailingDeleteView.as_view(), name='mailing_delete'),
url(r'^(?P[0-9]+)/mailing/delete/subscription$', MailingSubscriptionDeleteView.as_view(), name='mailing_subscription_delete'),
url(r'^membership/(?P[0-9]+)/set_old$', MembershipSetOldView.as_view(), name='membership_set_old'),
diff --git a/club/views.py b/club/views.py
index a8206fe6..4841c56e 100644
--- a/club/views.py
+++ b/club/views.py
@@ -24,25 +24,25 @@
#
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.detail import SingleObjectMixin
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.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext as _t
from ajax_select.fields import AutoCompleteSelectField
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 club.models import Club, Membership, Mailing, MailingSubscription
from sith.settings import SITH_MAXIMUM_FREE_ROLE
from counter.models import Selling, Counter
-from core.models import User
+from core.models import User, PageRev
from django.conf import settings
@@ -86,6 +86,8 @@ class MailingSubscriptionForm(forms.ModelForm):
class ClubTabsMixin(TabedViewMixin):
def get_tabs_title(self):
+ if isinstance(self.object, PageRev):
+ self.object = self.object.page.club
return self.object.get_display_name()
def get_list_of_tabs(self):
@@ -106,6 +108,12 @@ class ClubTabsMixin(TabedViewMixin):
'slug': 'elderlies',
'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):
tab_list.append({
'url': reverse('club:tools', kwargs={'club_id': self.object.id}),
@@ -117,6 +125,12 @@ class ClubTabsMixin(TabedViewMixin):
'slug': '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({
'url': reverse('club:club_sellings', kwargs={'club_id': self.object.id}),
'slug': 'sellings',
@@ -153,6 +167,55 @@ class ClubView(ClubTabsMixin, DetailView):
template_name = 'club/club_detail.jinja'
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):
"""
@@ -209,29 +272,31 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, UpdateView):
form.instance = Membership(club=self.object, user=self.request.user)
if not self.request.user.is_root:
form.fields.pop('start_date', None)
- # form.initial = {'user': self.request.user}
- # form._user = self.request.user
return form
- def post(self, request, *args, **kwargs):
+ def form_valid(self, form):
"""
Check user rights
"""
- self.object = self.get_object()
- form = self.get_form()
- if form.is_valid():
- ms = self.object.get_membership_for(request.user)
- if (form.cleaned_data['role'] <= SITH_MAXIMUM_FREE_ROLE or
- (ms is not None and ms.role >= form.cleaned_data['role']) or
- request.user.is_board_member or
- request.user.is_root):
- return self.form_valid(form)
- else:
- form.add_error(None, _("You do not have the permission to do that"))
- return self.form_invalid(form)
+ user = self.request.user
+ ms = self.object.get_membership_for(user)
+ if (form.cleaned_data['role'] <= SITH_MAXIMUM_FREE_ROLE or
+ (ms is not None and ms.role >= form.cleaned_data['role']) or
+ user.is_board_member or user.is_root):
+ form.save()
+ form = self.form_class()
+ return super(ModelFormMixin, self).form_valid(form)
else:
+ form.add_error(None, _("You do not have the permission to do that"))
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):
"""
@@ -337,7 +402,7 @@ class ClubEditView(ClubTabsMixin, CanEditMixin, UpdateView):
"""
model = Club
pk_url_kwarg = "club_id"
- fields = ['address', 'logo']
+ fields = ['address', 'logo', 'short_description']
template_name = 'core/edit.jinja'
current_tab = "edit"
@@ -348,7 +413,7 @@ class ClubEditPropView(ClubTabsMixin, CanEditPropMixin, UpdateView):
"""
model = Club
pk_url_kwarg = "club_id"
- fields = ['name', 'unix_name', 'parent']
+ fields = ['name', 'unix_name', 'parent', 'is_active']
template_name = 'core/edit.jinja'
current_tab = "props"
@@ -497,3 +562,33 @@ class MailingSubscriptionDeleteView(CanEditMixin, DeleteView):
def get_success_url(self, **kwargs):
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)
diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py
index 108a1fb5..12d69e9f 100644
--- a/core/management/commands/populate.py
+++ b/core/management/commands/populate.py
@@ -85,6 +85,12 @@ class Command(BaseCommand):
profiles_root.save()
home_root = SithFile(parent=None, name="users", is_folder=True, owner=root)
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.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'],
unix_name=settings.SITH_LAUNDERETTE_MANAGER['unix_name'],
address=settings.SITH_LAUNDERETTE_MANAGER['address'])
+
launderette_club.save()
self.reset_index("club")
for b in settings.SITH_COUNTER_BARS:
diff --git a/core/migrations/0025_auto_20170919_1521.py b/core/migrations/0025_auto_20170919_1521.py
new file mode 100644
index 00000000..039f9dd2
--- /dev/null
+++ b/core/migrations/0025_auto_20170919_1521.py
@@ -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.')]),
+ ),
+ ]
diff --git a/core/migrations/0026_auto_20170926_1512.py b/core/migrations/0026_auto_20170926_1512.py
new file mode 100644
index 00000000..03e90c4b
--- /dev/null
+++ b/core/migrations/0026_auto_20170926_1512.py
@@ -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'),
+ ),
+ ]
diff --git a/core/models.py b/core/models.py
index 8573fd4a..6c4997b0 100644
--- a/core/models.py
+++ b/core/models.py
@@ -841,7 +841,7 @@ class Page(models.Model):
name = models.CharField(_('page unix name'), max_length=30,
validators=[
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 '
'unaccented letters, numbers ' 'and ./+/-/_ characters.')
), ],
@@ -892,6 +892,19 @@ class Page(models.Model):
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):
l = []
p = self.parent
@@ -999,6 +1012,15 @@ class Page(models.Model):
except:
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):
self.unset_lock_recursive()
self.set_lock_recursive(User.objects.get(id=0))
@@ -1048,6 +1070,9 @@ class PageRev(models.Model):
else:
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):
if self.revision is None:
self.revision = self.page.revisions.all().count() + 1
diff --git a/core/operations.py b/core/operations.py
new file mode 100644
index 00000000..ea847fd9
--- /dev/null
+++ b/core/operations.py
@@ -0,0 +1,50 @@
+# -*- coding:utf-8 -*
+#
+# Copyright 2016,2017
+# - Sli
+#
+# 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)
diff --git a/core/static/core/style.scss b/core/static/core/style.scss
index e18025f8..7032d14a 100644
--- a/core/static/core/style.scss
+++ b/core/static/core/style.scss
@@ -1224,3 +1224,15 @@ label {
.ui-corner-left {
border-radius: 0px;
}
+
+#club_detail {
+ .club_logo {
+ float: right;
+ img {
+ display: block;
+ max-height: 10em;
+ max-width: 10em;
+ }
+ }
+
+}
diff --git a/core/templates/core/base.jinja b/core/templates/core/base.jinja
index b3d733ee..a7951efe 100644
--- a/core/templates/core/base.jinja
+++ b/core/templates/core/base.jinja
@@ -150,6 +150,7 @@
{% if not popup %}
{% trans %}Main{% endtrans %}
+ {% trans %}Clubs{% endtrans %}
{% trans %}Matmatronch{% endtrans %}
{% trans %}Wiki{% endtrans %}
{% trans %}SAS{% endtrans %}
diff --git a/core/templates/core/macros.jinja b/core/templates/core/macros.jinja
index 8a9bfcbe..61f8928f 100644
--- a/core/templates/core/macros.jinja
+++ b/core/templates/core/macros.jinja
@@ -125,4 +125,4 @@
{% else %}
{% trans %}Next{% endtrans %}
{% endif %}
-{% endmacro %}
\ No newline at end of file
+{% endmacro %}
diff --git a/core/templates/core/macros_pages.jinja b/core/templates/core/macros_pages.jinja
new file mode 100644
index 00000000..5e4396cb
--- /dev/null
+++ b/core/templates/core/macros_pages.jinja
@@ -0,0 +1,50 @@
+{% from "core/macros.jinja" import user_profile_link %}
+
+{% macro page_history(page) %}
+{% trans page_name=page.name %}You're seeing the history of page "{{ page_name }}"{% endtrans %}
+
+ {% for r in (page.revisions.all()|sort(attribute='date', reverse=True)) %}
+ {% if loop.index < 2 %}
+ {% trans %}last{% endtrans %} -
+ {{ user_profile_link(page.revisions.last().author) }} -
+ {{ page.revisions.last().date|localtime|date(DATETIME_FORMAT) }} {{ page.revisions.last().date|localtime|time(DATETIME_FORMAT) }}
+ {% else %}
+ {{ r.revision }} -
+ {{ user_profile_link(r.author) }} -
+ {{ r.date|localtime|date(DATETIME_FORMAT) }} {{ r.date|localtime|time(DATETIME_FORMAT) }}
+ {% endif %}
+ {% endfor %}
+
+{% endmacro %}
+
+{% macro page_edit_form(page, form, url, token) %}
+{% trans %}Edit page{% endtrans %}
+
+
+
+{% endmacro %}
+
+{% macro markdown_preview_script(token) %}
+
+{% endmacro %}
+
+{% macro markdown_preview_button() %}
+
+{% endmacro %}
\ No newline at end of file
diff --git a/core/templates/core/page.jinja b/core/templates/core/page.jinja
index 1e3d2368..73a58676 100644
--- a/core/templates/core/page.jinja
+++ b/core/templates/core/page.jinja
@@ -25,12 +25,16 @@