Commit f3227c9f authored by Thom Wiggers's avatar Thom Wiggers 📐
Browse files

Merge branch 'fix/69-fix-boardpages' into 'master'

Change board/committee pages

Closes #69 

- Remove JavaScript usage for the board pages and use indexed urls
- Rename the urls of the committee pages
- Add the board url to the menu
- Replace default committtee placeholder image
- Preserve the i18n fields from a base class in the translations util
- Fix adding a CommitteeMembership for a board (they were not shown in the list due to the manager being overridden)
- Fix problems when adding/updating a CommitteeMembership of a user that is marked as chair.
- Translatable committee names
- Translatable roles in committeememberships

See merge request !65
parents 83a42bf7 364ae1c3
from django.contrib import admin
from utils.translation import TranslatedModelAdmin
from . import models
@admin.register(models.Committee)
class CommitteeAdmin(admin.ModelAdmin):
class CommitteeAdmin(TranslatedModelAdmin):
list_filter = ('until',)
fields = ('name', 'description', 'photo', 'permissions',
'since', 'until',)
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.exclude(board__is_board=True)
@admin.register(models.Board)
class BoardAdmin(admin.ModelAdmin):
class BoardAdmin(TranslatedModelAdmin):
exclude = ('is_board',)
fields = ('name', 'description', 'photo', 'permissions',
'since', 'until',)
@admin.register(models.CommitteeMembership)
class CommitteeMembershipAdmin(admin.ModelAdmin):
class CommitteeMembershipAdmin(TranslatedModelAdmin):
pass
......
......@@ -3,8 +3,10 @@
"model": "activemembers.committee",
"pk": 1,
"fields": {
"name": "testcie1",
"description": "Test",
"name_nl": "testcie1",
"name_en": "testcie1",
"description_nl": "Test",
"description_en": "Test",
"photo": "Thom_Wiggers.jpg",
"permissions": [
25,
......@@ -17,8 +19,10 @@
"model": "activemembers.committee",
"pk": 2,
"fields": {
"name": "testcie2",
"description": "testdesc2",
"name_nl": "testcie2",
"name_en": "testcie2",
"description_nl": "testdesc2",
"description_en": "testdesc2",
"photo": "Thom_Wiggers_4YRoxV3.jpg",
"permissions": []
}
......
......@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-05 10:26+0200\n"
"PO-Revision-Date: 2016-09-05 10:26+0100\n"
"POT-Creation-Date: 2016-09-11 14:27+0200\n"
"PO-Revision-Date: 2016-09-11 14:29+0200\n"
"Last-Translator: Joost Rijneveld <joost@joostrijneveld.nl>\n"
"Language-Team: \n"
"Language: nl\n"
......@@ -16,177 +16,199 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.10\n"
"X-Generator: Poedit 1.8.8\n"
#: models.py:40
#: models.py:41
msgid "Committee name"
msgstr ""
msgstr "Commissienaam"
#: models.py:45
#: models.py:46
msgid "Description"
msgstr ""
msgstr "Beschrijving"
#: models.py:49
#: models.py:50
msgid "Image"
msgstr ""
msgstr "Afbeelding"
#: models.py:62
#: models.py:63
msgid "permissions"
msgstr ""
msgstr "permissies"
#: models.py:67
#: models.py:68
msgid "founded in"
msgstr ""
msgstr "opgericht in"
#: models.py:73
#: models.py:74
msgid "existed until"
msgstr ""
msgstr "bestond tot"
#: models.py:78
#: models.py:79
msgid "contact email address"
msgstr ""
msgstr "contact e-mailadres"
#: models.py:87
#: models.py:88
msgid "committee"
msgstr ""
msgstr "commissie"
#: models.py:88
#: models.py:89 templates/activemembers/committee_index.html:6
msgid "committees"
msgstr ""
msgstr "commissies"
#: models.py:100
#: models.py:101
msgid "Is this a board"
msgstr ""
msgstr "Is dit een bestuur"
#: models.py:122
#: models.py:123
msgid "Member"
msgstr ""
msgstr "Lid"
#: models.py:128
#: models.py:129
msgid "Committee"
msgstr ""
msgstr "Commissie"
#: models.py:132
#: models.py:133
msgid "Committee member since"
msgstr ""
msgstr "Commissielid sinds"
#: models.py:133
#: models.py:134
msgid "The date this member joined the committee in this role"
msgstr ""
msgstr "De datum waarop deze persoon lid werd deze commissie in deze rol"
#: models.py:138
#: models.py:139
msgid "Committee member until"
msgstr ""
msgstr "Commissielid tot"
#: models.py:139
#: models.py:140
msgid "A member of this committee until this time (can't be in the future)."
msgstr ""
"De datum waarop deze persoon de commissie verliet (kan niet in de toekomst "
"liggen)"
#: models.py:146
#: models.py:147
msgid "Chair of the committee"
msgstr ""
msgstr "Voorzitter van de commissie"
#: models.py:147
#: models.py:148
msgid "There can only be one chair at a time!"
msgstr ""
msgstr "Er kan maar één voorzitter tegelijkertijd zijn!"
#: models.py:152
#: models.py:153
msgid "role"
msgstr ""
msgstr "rol"
#: models.py:153
#: models.py:154
msgid "The role of this member"
msgstr ""
msgstr "De rol van dit lid binnen de commissie"
#: models.py:176
#: models.py:177
msgid "Membership expiration date can't be in the future: '{}'"
msgstr ""
msgstr "Een lidmaatschap kan niet verlopen in de toekomst: ‘{]’"
#: models.py:182
#: models.py:183
msgid "End date can't be before start date"
msgstr ""
msgstr "De einddatum kan niet voor de startdatum liggen"
#: models.py:196
#: models.py:197
msgid "This committee already has a chair"
msgstr ""
msgstr "Deze commissie heeft al een voorzitter"
#: models.py:213
#: models.py:214
msgid "This member is already in the committee"
msgstr ""
msgstr "Deze persoon is al lid van deze commissie"
#: models.py:216
#: models.py:217
msgid "This member is already in the committee for this period"
msgstr ""
msgstr "Deze persoon is al lid van deze commissie in de aangegeven periode"
#: models.py:247
#: models.py:251
msgid "committee membership"
msgstr ""
msgstr "commissielidmaatschap"
#: models.py:248
#: models.py:252
msgid "committee memberships"
msgstr ""
msgstr "commissielidmaatschappen"
#: models.py:256
#: models.py:260
#, python-brace-format
msgid "Mentor introduction {year}"
msgstr "Mentor introductie {year}"
#: templates/committees/boards.html:4 templates/committees/boards.html:8
#: templates/activemembers/board_detail.html:4
#: templates/activemembers/board_index.html:3
#: templates/activemembers/board_index.html:6
msgid "Boards"
msgstr ""
msgstr "Besturen"
#: templates/committees/boards.html:14
#: templates/activemembers/board_detail.html:8
#: templates/activemembers/board_index.html:33
#: templates/activemembers/board_index.html:38
msgid "Board"
msgstr "Besturen"
#: templates/activemembers/board_detail.html:26
msgid "Board members"
msgstr "Bestuursleden"
#: templates/activemembers/board_detail.html:42
#: templates/activemembers/committee_detail.html:44
msgid "Chair"
msgstr "Voorzitter"
#: templates/activemembers/board_detail.html:59
msgid "This board doesn't have any members?"
msgstr "Dit bestuur heeft geen leden?"
#: templates/activemembers/board_index.html:10
#, python-format
msgid ""
"Thalia's board makes sure all operations during the academic year are taken "
"care of, in front or behind the scenes. If you have any questions then you "
"can address them during the day or, if you're not always on the campus, "
"you're always welcome to <a href=\"mailto:info@thalia.nu\">send them an "
"email</a>."
msgstr ""
"Het gehele Thaliabestuur zet zich gedurende een collegejaar in om alle "
"activiteiten van Thalia in goede banen te leiden, voor of achter de "
"schermen. Bij vragen en opmerkingen kun je ze altijd persoonlijk aanspreken "
"of <a href=\"mailto:info@thalia.nu\">mailen</a>. Besturen van langer geleden "
"(eerder dan 2001), zijn op <a href=\"/board/oud-besturen\">deze pagina</a> "
"te vinden."
msgstr ""
"of <a href=\"mailto:info@thalia.nu\">mailen</a>."
#: templates/committees/boards.html:53
msgid "Board members"
msgstr ""
#: templates/activemembers/board_index.html:25
#: templates/activemembers/committee_detail.html:18
#: templates/activemembers/committee_detail.html:20
#, python-format
msgid "Photo of %(name)s"
msgstr "Foto van %(name)s"
#: templates/committees/boards.html:73
msgid "Chair"
msgstr ""
#: templates/activemembers/board_index.html:45
msgid "There are no boards!"
msgstr "Er zijn geen besturen!"
#: templates/committees/details.html:3 templates/committees/index.html:3
#: templates/committees/index.html:6
#: templates/activemembers/committee_detail.html:3
#: templates/activemembers/committee_index.html:3
msgid "Committees"
msgstr ""
msgstr "Commissies"
#: templates/committees/details.html:22
#: templates/activemembers/committee_detail.html:24
#, python-format
msgid "About the %(name)s"
msgstr ""
msgstr "Over de %(name)s"
#: templates/committees/details.html:26
#: templates/activemembers/committee_detail.html:28
msgid "Committee members"
msgstr ""
msgstr "Commissieleden"
#: templates/committees/details.html:34
msgid "Default avatar"
msgstr ""
#: templates/committees/details.html:42
msgid "Voorzitter"
msgstr ""
#: templates/committees/details.html:49
#: templates/activemembers/committee_detail.html:51
#, python-format
msgid "Committee member since: %(since)s"
msgstr ""
msgstr "Commissielid sinds: %(since)s"
#: templates/committees/details.html:59
#: templates/activemembers/committee_detail.html:61
msgid "This committee doesn't have any members?"
msgstr ""
msgstr "Deze commissie heeft geen leden?"
#: templates/committees/index.html:39
#: templates/activemembers/committee_index.html:39
msgid "There are no committees!"
msgstr ""
msgstr "Er zijn geen commissies!"
#~ msgid "Mentors {year}-{year_to}"
#~ msgstr "Mentoren {year}-{year_to}"
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-09-06 17:31
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.manager
class Migration(migrations.Migration):
dependencies = [
('activemembers', '0008_auto_20160906_1015'),
]
def forwards_func(apps, schema_editor):
Committee = apps.get_model("activemembers", "committee")
db_alias = schema_editor.connection.alias
for committee in Committee.unfiltered_objects.using(db_alias).all():
committee.name_en = committee.name_nl
committee.description_en = committee.description_nl
committee.save()
def reverse_func(apps, schema_editor):
pass
operations = [
migrations.AlterModelManagers(
name='committee',
managers=[
('unfiltered_objects', django.db.models.manager.Manager()),
],
),
migrations.RenameField('committee', 'name', 'name_nl'),
migrations.RenameField('committee', 'description', 'description_nl'),
migrations.AddField(
model_name='committee',
name='name_en',
field=models.CharField(default='', max_length=40, unique=True,
verbose_name='Committee name (EN)'),
preserve_default=False,
),
migrations.AlterField(
model_name='committee',
name='name_nl',
field=models.CharField(max_length=40, unique=True,
verbose_name='Committee name (NL)'),
preserve_default=True,
),
migrations.AddField(
model_name='committee',
name='description_en',
field=models.TextField(default='', verbose_name='Description (EN)'),
preserve_default=False,
),
migrations.AlterField(
model_name='committee',
name='description_nl',
field=models.TextField(verbose_name='Description (NL)'),
preserve_default=True,
),
migrations.RenameField('committeemembership', 'role', 'role_nl'),
migrations.AddField(
model_name='committeemembership',
name='role_en',
field=models.CharField(blank=True, help_text='The role of this member', max_length=255, null=True, verbose_name='role (EN)'),
),
migrations.AlterField(
model_name='committeemembership',
name='role_nl',
field=models.CharField(blank=True, help_text='The role of this member', max_length=255, null=True, verbose_name='role (NL)'),
),
migrations.RunPython(forwards_func, reverse_func),
]
\ No newline at end of file
import datetime
import logging
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
from django.contrib.auth.models import Permission
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from members.models import Member
from utils.translation import MultilingualField, ModelTranslateMeta
logger = logging.getLogger(__name__)
......@@ -29,19 +28,22 @@ class ActiveCommitteeManager(models.Manager):
.exclude(until__lt=timezone.now().date()))
class Committee(models.Model):
class Committee(models.Model, metaclass=ModelTranslateMeta):
"""A committee"""
active_committees = ActiveCommitteeManager()
unfiltered_objects = models.Manager()
objects = CommitteeManager()
active_committees = ActiveCommitteeManager()
name = models.CharField(
name = MultilingualField(
models.CharField,
max_length=40,
verbose_name=_('Committee name'),
unique=True,
)
description = models.TextField(
description = MultilingualField(
models.TextField,
verbose_name=_('Description'),
)
......@@ -81,7 +83,7 @@ class Committee(models.Model):
return self.name
def get_absolute_url(self):
return reverse('activemembers:details', args=[str(self.pk)])
return reverse('activemembers:committee', args=[str(self.pk)])
class Meta:
verbose_name = _('committee')
......@@ -102,7 +104,7 @@ class Board(Committee):
)
def get_absolute_url(self):
return '/committee/boards/{}'.format(self.name.lower())
return reverse('committees:board', args=[str(self.pk)])
class ActiveMembershipManager(models.Manager):
......@@ -112,7 +114,7 @@ class ActiveMembershipManager(models.Manager):
return super().get_queryset().exclude(until__lt=timezone.now().date())
class CommitteeMembership(models.Model):
class CommitteeMembership(models.Model, metaclass=ModelTranslateMeta):
objects = models.Manager()
active_memberships = ActiveMembershipManager()
......@@ -148,7 +150,8 @@ class CommitteeMembership(models.Model):
default=False,
)
role = models.CharField(
role = MultilingualField(
models.CharField,
_('role'),
help_text=_('The role of this member'),
max_length=255,
......@@ -159,7 +162,7 @@ class CommitteeMembership(models.Model):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.pk is None:
if self.pk is not None:
self._was_chair = bool(self.chair)
else:
self._was_chair = False
......@@ -221,13 +224,16 @@ class CommitteeMembership(models.Model):
# If the chair changed and we're still active, we create a new instance
# Inactive instances should be handled manually
if (self.pk is not None and self._was_chair != self.chair and
not self.until):
not self.until and self.since != timezone.now().date()):
logger.info("Creating new membership instance")
self.until = timezone.now().date()
self.until = timezone.now().date() - datetime.timedelta(days=1)
super().save(*args, **kwargs)
self.pk = None # forces INSERT
self.since = self.until # Set since date to older expiration
# Set since date to older expiration:
self.since = timezone.now().date()
self.until = None
self._was_chair = self.chair
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
......
......@@ -9,7 +9,7 @@ class StaticViewSitemap(sitemaps.Sitemap):
changefreq = 'daily'
def items(self):
return ['activemembers:index']
return ['activemembers:committees', 'committees:boards']
def location(self, item):
return reverse(item)
......
var blocked= false;
$(document).ready(function(){
$("#collection-div").hide();
$(".post-slider .slides").trigger("slideTo", boardPositions.indexOf(boardNr));
$(".bestuur-list").hide();
$("#board" + boardNr).show();
$("#title").html(boardTitles[boardNr]);
window.history.pushState(boardNr, 'Title', '/association/activemembers/boards/' + boardNr);
});
$("#carousel-prev").click(function(){
if(blocked) {
return;
}
blocked = true;
var number = boardPositions.indexOf(boardNr) - 1;
if (number < 0){
number = parseInt(boardMax) - 1;
}
boardNr = boardPositions[number];
$(".bestuur-list").hide();
$("#board" + boardNr).show();
$("#title").html(boardTitles[boardNr]);
window.history.pushState(boardNr, 'Title', '/association/activemembers/boards/' + boardNr);
setTimeout(function(){blocked=false}, 500);
});
$("#carousel-next").click(function(){
if(blocked) {
return;
}
blocked = true;
var number = boardPositions.indexOf(boardNr) + 1;
var maximum = parseInt(boardMax);
if (number >= maximum){
number = 0;
}
boardNr = boardPositions[number];
$(".bestuur-list").hide();
$("#board" + boardNr).show();
$("#title").html(boardTitles[boardNr]);
window.history.pushState(boardNr, 'Title', '/association/activemembers/boards/' + boardNr);
setTimeout(function(){blocked=false}, 500);