Milestone 08-14

* Mahjong Ranking wurde stark vereinfacht um Fehler besser vorzubeugen.
* Online WYSIWYG Editor auf CKEditor umgeändert, damit online bearbeiten für unbedarfte besser funktioniert.
* Viele kleine Optimierungen am CSS für bessere Performance.
* CSS wird jetzt aus LESS Code generiert
* Für dise Arbeit wird jetzt grunt und node package management lokal verwendet.
This commit is contained in:
Christian Berg
2015-08-23 16:37:39 +02:00
parent 8981d4b261
commit a7bfd2157d
279 changed files with 14708 additions and 2429 deletions

View File

@@ -1,22 +1,19 @@
# -*- encoding: utf-8 -*-
from datetime import date
import urllib
from django.contrib import auth, messages
from django.contrib import auth
from django.core.urlresolvers import reverse
import django.forms
import django.http
from django.contrib.messages.views import SuccessMessageMixin
from django.utils.translation import gettext as _
from django.views import generic
import xlwt
from events.models import Event
from events.views import EventDetailMixin
from . import forms, models
from membership.models import Membership
from utils.mixins import LoginRequiredMixin, PermissionRequiredMixin
kyu_dan_order = {
'+full_name': ('user__last_name', 'user__first_name'),
'-full_name': ('-user__last_name', '-user__first_name'),
@@ -46,49 +43,32 @@ class DeleteHanchan(EventDetailMixin, PermissionRequiredMixin, generic.DeleteVie
kwargs={'event': self.object.event.pk})
class HanchanForm(EventDetailMixin, PermissionRequiredMixin, generic.UpdateView):
class HanchanForm(SuccessMessageMixin, EventDetailMixin, PermissionRequiredMixin, generic.UpdateView):
"""
Ein Formular um eine neue Hanchan anzulegen, bzw. eine bestehende zu
Ein Formular um neue Hanchans anzulegen, bzw. eine bestehende zu
bearbeitsen
"""
form_class = forms.HanchanForm
model = models.Hanchan
permission_required = 'mahjong_ranking.add_hanchan'
def form_valid(self, form, formset):
if not self.object.pk:
self.object = form.save()
formset.save()
self.object.save()
else:
formset.save()
self.object = form.save()
return django.http.HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, formset):
return self.render_to_response(self.get_context_data(
form=form,
formset=formset,
object=self.object,
))
def get_context_data(self, **kwargs):
context = generic.UpdateView.get_context_data(self, **kwargs)
context['event'] = self.event
return context
def get_form_class(self):
"""
Returns the form class to use in this view
Users with edit Persmission will see the AdminForm to confirm
unconfirmed Hanchans.
"""
if self.request.user.has_perm('mahjong_ranking.delete_hanchan'):
if self.request.user.has_perm('mahjong_ranking.change_hanchan'):
return forms.HanchanAdminForm
else:
return forms.HanchanForm
def get_formset(self):
return forms.PlayerFormSet(
data=self.request.POST or None,
instance=self.object
)
def get_object(self, queryset=None):
if self.kwargs.get('hanchan'):
if self.kwargs.get('hanchan') and self.request.user.has_perm('mahjong_ranking.change_hanchan'):
hanchan = models.Hanchan.objects.get(id=self.kwargs['hanchan'])
self.event = hanchan.event
elif self.kwargs.get('event'):
@@ -97,38 +77,23 @@ class HanchanForm(EventDetailMixin, PermissionRequiredMixin, generic.UpdateView)
event=self.event,
start=self.event.start
)
else:
hanchan = self.model()
if hanchan.id and not hanchan.valid:
messages.warning(self.request, hanchan.check_validity())
return hanchan
def get_context_data(self, **kwargs):
context = generic.UpdateView.get_context_data(self, **kwargs)
context['event'] = self.event
return context
def get(self, request, *args, **kwargs):
def get_success_url(self):
"""
:param request:
Adding a new Hanchan redirect to create_hanchan form.
Editing an exiting one: redierect to the Hanchanevent.
"""
self.object = self.get_object()
form = self.get_form(self.get_form_class())
formset = self.get_formset()
return self.render_to_response(
self.get_context_data(form=form, formset=formset)
)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
formset = self.get_formset()
if form.is_valid() and formset.is_valid():
return self.form_valid(form, formset)
if self.kwargs.get('hanchan'):
return self.object.get_absolute_url()
else:
return self.form_invalid(form, formset)
return reverse('add-hanchan-form', kwargs={'event': self.event.pk})
def get_success_message(self, cleaned_data):
if self.kwargs.get('hanchan'):
return _('%s has been updated successfully.') % self.object
else:
return _('%s has been added successfully. You can now add a new one.') % self.object
class EventHanchanList(EventDetailMixin, generic.ListView):
@@ -142,7 +107,6 @@ class EventHanchanList(EventDetailMixin, generic.ListView):
try:
self.event = models.Event.objects.get(pk=self.kwargs['event'])
queryset = models.Hanchan.objects.filter(event=self.event)
queryset = queryset.prefetch_related('player_set__user')
queryset = queryset.order_by('start')
return queryset
except models.Event.DoesNotExist:
@@ -160,8 +124,7 @@ class EventRankingList(EventDetailMixin, generic.ListView):
try:
self.event = models.Event.objects.get(pk=self.kwargs['event'])
queryset = models.EventRanking.objects.filter(event=self.event)
queryset = queryset.prefetch_related()
return queryset
return queryset.prefetch_related()
except models.Event.DoesNotExist:
raise django.http.Http404(_('Event does not exist'))
@@ -176,130 +139,47 @@ class KyuDanRankingList(generic.ListView):
def dispatch(self, request, *args, **kwargs):
self.order_by = kyu_dan_order[
kwargs.get('order_by', self.default_order)] # @IgnorePep8
kwargs.get('order_by', self.default_order)
]
return generic.ListView.dispatch(self, request, *args, **kwargs)
def get_queryset(self):
queryset = models.KyuDanRanking.objects.all()
queryset = queryset.select_related('user__membership')
queryset = queryset.order_by(*self.order_by)
return queryset
queryset = models.KyuDanRanking.objects.all().order_by(*self.order_by)
return queryset.select_related('user__membership')
class LadderRankingList(generic.ListView):
model = models.LadderRanking
class SeasonRankingList(generic.ListView):
model = models.SeasonRanking
paginate_by = 25
season = None
is_archive = False
def get_queryset(self):
try:
if self.kwargs.get('season'):
self.season = models.LadderSeason.objects.get(
pk=self.kwargs['season'])
self.is_archive = True
elif self.kwargs.get('is_archive'):
self.season = models.LadderSeason.objects.order_by('-pk')[1]
self.is_archive = True
else:
self.season = models.LadderSeason.objects.current()
except models.LadderSeason.DoesNotExist:
raise django.http.Http404(_('Season does not exist'))
queryset = models.LadderRanking.objects.filter(season=self.season,
placement__isnull=False).select_related()
return queryset
self.season = int(self.kwargs.get('season', date.today().year))
queryset = self.model.objects.filter(season=self.season,
placement__isnull=False)
return queryset.select_related()
def get_context_data(self, **kwargs):
context = generic.ListView.get_context_data(self, **kwargs)
context['is_archive'] = self.is_archive
context = super(SeasonRankingList, self).get_context_data(**kwargs)
context['season'] = self.season
context['season_list'] = models.LadderSeason.objects.all()
context['latest_hanchan_list'] = models.Hanchan.objects.filter(
valid=True)[:3]
context['season_start'] = date(year=self.season, month=1, day=1)
context['season_end'] = date(year=self.season, month=12, day=31)
context['season_list'] = models.SeasonRanking.objects.season_list
context['latest_hanchan_list'] = models.Hanchan.objects.confirmed_hanchans()[:3]
context['latest_event_list'] = Event.objects.archive()[:3]
return context
class LadderRankingExcel(generic.View):
center = xlwt.easyxf('align: horiz centre')
# Format für Datumswerte
date = xlwt.easyxf('align: horiz right', num_format_str='d.MM.YYYY')
# Format für Überschriften
header = xlwt.easyxf('font: bold on; align: wrap on, vert centre, \
horiz center; pattern: back_color grey25;')
filename = u"ladderranking.xls"
def get(self, request, **kwargs):
self.queryset = self.team.members.all()
response = django.http.HttpResponse(mimetype=u'application/msexcel')
filename = urllib.quote(self.filename.encode('utf-8'))
response[
'Content-Disposition'] = "attachment; filename*=UTF-8''%s" % filename
field_names = [u"Login", u"Name", u"E-Mail", u"Telefon", u"Handy",
u"Geburtstag",
u"T-Shirt", u"Teams", u"Gr.", u"Kg", u"Notfall Adresse",
u"Notfall Nummer", u"Notizen", ]
# Erstelle ein Workbook (Das ist eine Excel Datei)
workbook = xlwt.Workbook(encoding='utf-8')
# Das Sheet ist eine Tabelle in der Excel Datei.
# Dort wird die erste Spalte fixiert und mit den Zeilenüberschriften befüllt.
sheet = workbook.add_sheet('Mitglieder', cell_overwrite_ok=False)
sheet.set_panes_frozen(True)
sheet.set_horz_split_pos(1) # in general, freeze after last heading row
sheet.set_remove_splits(
True) # if user does unfreeze, don't leave a split there
for column in range(0, len(field_names)):
sheet.write(0, column, field_names[column], style=header)
# Dann fangen wir an ab der 2. Zeile die einzelnen Datensätze einzuspielen.
current_row = 2
for user in self.queryset:
self.set_col(sheet, current_row, 0, user.username)
self.set_col(sheet, current_row, 1, user.get_full_name())
self.set_col(sheet, current_row, 2, user.email)
try:
profile = user.get_profile()
self.set_col(sheet, current_row, 3, profile.telephone or None)
self.set_col(sheet, current_row, 4, profile.mobilephone or None)
self.set_col(sheet, current_row, 5, profile.birthday or None,
style=self.date)
self.set_col(sheet, current_row, 6, profile.shirt_size or None,
style=self.center)
self.set_col(sheet, current_row, 7, self.get_other_teams(user))
self.set_col(sheet, current_row, 8, profile.height or None)
self.set_col(sheet, current_row, 9, profile.weight or None)
self.set_col(sheet, current_row, 10,
profile.emergency_contact or None)
self.set_col(sheet, current_row, 11,
profile.emergency_phone or None)
except Membership.DoesNotExist:
pass
current_row += 1
for column in range(0, 13):
sheet.col(column).width = (self.max_colwidth[column] + 1) * 256
workbook.save(response)
return response
class PlayerScore(LoginRequiredMixin, generic.ListView):
paginate_by = 25
def get(self, request, *args, **kwargs):
user_model = auth.get_user_model()
try:
user_model = auth.get_user_model()
self.user = user_model.objects.get(username=self.kwargs.get('username'))
except user_model.DoesNotExist:
raise django.http.Http404(
_("No user found matching the name %s") % self.kwargs.get(
'username'))
return generic.ListView.get(self, request, *args, **kwargs)
raise django.http.Http404(_("No user found matching the name {}").format(self.kwargs.get('username')))
return super(PlayerScore, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = generic.ListView.get_context_data(self, **kwargs)
@@ -310,11 +190,11 @@ class PlayerScore(LoginRequiredMixin, generic.ListView):
except models.KyuDanRanking.DoesNotExist:
context['ranking'] = None
try:
context['ladder_ranking'] = models.LadderRanking.objects.get(
context['ladder_ranking'] = models.SeasonRanking.objects.get(
user=self.user,
season=models.LadderSeason.objects.current())
except models.LadderRanking.DoesNotExist:
context['ladder_ranking'] = models.LadderRanking(user=self.user)
season=date.today().year)
except models.SeasonRanking.DoesNotExist:
context['ladder_ranking'] = models.SeasonRanking(user=self.user)
return context
@@ -322,42 +202,39 @@ class PlayerDanScore(PlayerScore):
template_name = 'mahjong_ranking/player_dan_score.html'
def get_queryset(self):
return models.Player.objects.dan_hanchans(self.user)
return models.Hanchan.objects.dan_hanchans(user=self.user)
class PlayerInvalidScore(PlayerScore):
template_name = 'mahjong_ranking/player_invalid_score.html'
def get_queryset(self):
return models.Player.objects.non_counting_hanchans(self.user)
return models.Hanchan.objects.unconfirmed_hanchans(user=self.user)
class PlayerKyuScore(PlayerScore):
template_name = 'mahjong_ranking/player_kyu_score.html'
def get_queryset(self):
return models.Player.objects.kyu_hanchans(self.user)
return models.Hanchan.objects.kyu_hanchans(self.user)
class PlayerLadderScore(PlayerScore):
template_name = 'mahjong_ranking/player_ladder_score.html'
def get_context_data(self, **kwargs):
context = PlayerScore.get_context_data(self, **kwargs)
season_list = models.LadderRanking.objects.filter(
user=self.user).select_related('user')
season_list = season_list.values_list('id', 'season__name')
context = super(PlayerLadderScore, self).get_context_data(**kwargs)
context['season'] = self.season
context['seasons_select_form'] = forms.SeasonSelectForm(user=self.user)
context['seasons_select_field'] = django.forms.ChoiceField(
choices=season_list)
context['season_start'] = date(year=self.season, month=1, day=1)
context['season_end'] = date(year=self.season, month=12, day=31)
context['season_list'] = models.SeasonRanking.objects.season_list
return context
def get_queryset(self, **kwargs):
if self.request.GET.get('season'):
self.season = models.LadderSeason.objects.get(
pk=self.request.GET['season'])
else:
self.season = models.LadderSeason.objects.current()
return models.Player.objects.ladder_hanchans(user=self.user,
season=self.season)
try:
self.season = int(self.request.GET.get('season'))
except:
self.season = date.today().year
hanchan_list = models.Hanchan.objects.season_hanchans(user=self.user, season=self.season)
print hanchan_list
return hanchan_list