Filled with Data / Addressbook corrections

This commit is contained in:
Martin Bauer 2013-10-14 19:46:53 +02:00
parent 114a2df9cf
commit 175df72a21
23 changed files with 124 additions and 99 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View File

@ -1,8 +1,9 @@
from django.db import models from django.db import models
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.contrib.auth.models import User from django.contrib.auth.models import User, Permission
from django.db.models import Q
from datetime import datetime from datetime import datetime
from location_field.models import PlainLocationField from location_field.models import PlainLocationField
@ -78,6 +79,9 @@ class EventParticipation( models.Model ):
@staticmethod @staticmethod
def hasUserSetParticipationForAllEvents( user ): def hasUserSetParticipationForAllEvents( user ):
if not EventParticipation.isMember(user):
return True
futurePart = EventParticipation.objects.filter( event__date__gte = datetime.now() ) futurePart = EventParticipation.objects.filter( event__date__gte = datetime.now() )
maybeObjects = futurePart.filter( user = user ).filter( status = '?' ) maybeObjects = futurePart.filter( user = user ).filter( status = '?' )
@ -86,6 +90,18 @@ class EventParticipation( models.Model ):
else: else:
return True return True
@staticmethod
def isMember( user ):
return user.has_perm('eventplanner.member')
@staticmethod
def isAdmin( user ):
return user.has_perm('eventplanner.admin')
@staticmethod
def members():
perm = Permission.objects.get( codename='member' )
return User.objects.filter(Q(groups__permissions=perm) | Q(user_permissions=perm) ).distinct()
@staticmethod @staticmethod
def get_or_create( user , event ): def get_or_create( user , event ):
@ -99,8 +115,9 @@ class EventParticipation( models.Model ):
class Meta: class Meta:
unique_together = ("event", "user") unique_together = ("event", "user")
permissions = ( permissions = (
("change_others_participation", _("Can modify participation status of other users") ), ("admin", _("Admin") ),
("member", _("Member") ),
) )

View File

@ -7,10 +7,12 @@ from models import EventParticipation
class ParticipationSerializer(serializers.ModelSerializer): class ParticipationSerializer(serializers.ModelSerializer):
event = serializers.PrimaryKeyRelatedField( many=False, read_only = False ) event = serializers.PrimaryKeyRelatedField( many=False, read_only = False )
user = serializers.Field( source='get_username' ) user = serializers.Field( source='get_username' )
status = serializers.CharField( source='status', required=False )
def get_identity(self, data): def get_identity(self, data):
""" This hook is required for bulk update. """ """ This hook is required for bulk update. """
try: try:
print "get_identity event:" + str( data.get('event', None) ) + " user " + str( data.get('user') )
return ( data.get('event', None), data.get('user') ) return ( data.get('event', None), data.get('user') )
except AttributeError: except AttributeError:
return None return None

View File

@ -41,38 +41,36 @@
} }
} }
function putStatus( button, status ) { function putStatus( button, status )
{
$("#saving").html("Speichere.."); $("#saving").html("Speichere..");
p = button.parent(); p = button.parent();
putObject = [ { "event": p.data("event-id"), putObject = [ { "event": p.data("event-id"),
"user": p.data("username"), "user": p.data("username"),
"status": status } ]; "status": status } ];
request = $.ajax( { request = $.ajax( {
type: "PUT", type: "PUT",
url: "{% url 'event_api' %}", url: "{% url 'event_api' %}",
contentType: "application/json", contentType: "application/json",
data: JSON.stringify(putObject), data: JSON.stringify(putObject),
success: function() { $("#saving").html("Ok"); } success: function() { $("#saving").html("Ok"); },
error: function(jqXHR, text, errorText) { console.log("Ajax failed " + errorText + JSON.stringify(putObject) ); }
}); });
setEventButtonStatus( button, status ); setEventButtonStatus( button, status );
//request.done(function(jqXHR, textStatus) {
// setEventButtonStatus( button, status )
//});
} }
$(function(){ $(function(){
$(".event-comment").bindWithDelay("keypress", function() { $(".event-comment").bindWithDelay("keypress", function() {
$("#saving").html("Speichere.."); $("#saving").html("Speichere..");
putObject = [ { "event": $(this).data("event-id"), putObject = [ { "event": $(this).data("event-id"),
"user": $(this).data("username"), "user": $(this).data("username"),
"comment": $(this).val() } ]; "comment": $(this).val() } ];
$.ajax( { $.ajax( {
type: "PUT", type: "PUT",
url: "{% url 'event_api' %}", url: "{% url 'event_api' %}",
@ -103,13 +101,17 @@
<div class="container"> <div class="container">
<form> <p>
<div class="row"> <div class="row">
<div class="row-fluid eventTable"> <div class="row-fluid eventTable">
<div class="span12"> <div class="span12">
<h2>Termine</h2> <h2>Termine</h2>
<p class="pull-right" ><a href="grid">zur Übersicht</a></p>
<div class="box-content"> <div class="box-content">
<table class="table table-striped"> <table class="table table-striped">
@ -140,7 +142,7 @@
<td class="center"> {{ event.location }} </td> <td class="center"> {{ event.location }} </td>
<td class="center"> <td class="center">
<div class="btn-group event-status-select" data-event-id="{{event.pk}}" data-username="{{user.username}}" > <div class="btn-group event-status-select" data-event-id="{{event.pk}}" data-username="{{user.username}}" >
<button class="btn event-status-yes {% if event.participation.status == "Yes" %} btn-success {% else %} btn-info {% endif %}"> <button class="btn event-status-yes {% if event.participation.status == "Yes" %} btn-success {% else %} btn-info {% endif %}">
<i class="icon-ok-sign icon-white"></i> <i class="icon-ok-sign icon-white"></i>
</button> </button>
@ -172,8 +174,9 @@
<div class="span12"> <div class="span12">
<em>Änderungen werden automatisch gespeichert: </em> <em id="saving">Ok</em> <em>Änderungen werden automatisch gespeichert: </em> <em id="saving">Ok</em>
</div> </div>
</div> </div>
</form>
</p>
</div> </div>

View File

@ -16,9 +16,14 @@
{% block content %} {% block content %}
{% addtoblock "css" %} {% addtoblock "css" %}
<style> <style>
.eventButton { button.eventButton {
width: 55px; width: 55px;
} }
span.eventButton {
height: 16px;
width: 45px;
text-align: center;
}
.eventButton i { .eventButton i {
margin-right:2px; margin-right:2px;
} }
@ -30,14 +35,14 @@
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
{% if not perms.eventplanner.change_others_participation %} {% if not perms.eventplanner.admin %}
$(".eventButton").attr('disabled', 'disabled'); $(".eventButton").attr('disabled', 'disabled');
$(".deleteButton").hide(); $(".deleteButton").hide();
{% endif %} {% endif %}
$('.eventButton').tooltip() $('.eventButton').tooltip()
$(".eventButton").click( function (e) { $("button.eventButton").click( function (e) {
e.preventDefault(); e.preventDefault();
$(this).removeClass("btn-danger") $(this).removeClass("btn-danger")
.removeClass("btn-warning") .removeClass("btn-warning")
@ -135,6 +140,9 @@
{% for p in event.participation %} {% for p in event.participation %}
{% if perms.eventplanner.admin %}
<td class="center userEventTableData" data-username="{{p.user.username}}" data-event="{{event.pk}}"> <td class="center userEventTableData" data-username="{{p.user.username}}" data-event="{{event.pk}}">
{% if p.status == "Yes" %} {% if p.status == "Yes" %}
<button class="btn btn-mini btn-success eventButton" title="{{p.comment}}" data-status="{{p.status}}"> <button class="btn btn-mini btn-success eventButton" title="{{p.comment}}" data-status="{{p.status}}">
@ -152,7 +160,29 @@
<span class="text">?</span> <span class="text">?</span>
</button> </button>
{% endif %} {% endif %}
</td> {% endfor %} </td>
{% else %}
<td class="center userEventTableData" data-username="{{p.user.username}}" data-event="{{event.pk}}">
{% if p.status == "Yes" %}
<span class="badge badge-success eventButton" title="{{p.comment}}" data-status="{{p.status}}">
{% if p.comment %} <i class="icon-comment icon-white"></i> {% endif %}
<span class="text">Ja</span>
</span>
{% elif p.status == "No" %}
<span class="badge badge-important eventButton" title="{{p.comment}}" data-status="{{p.status}}">
{% if p.comment%} <i class="icon-comment icon-white"></i> {% endif %}
<span class="text">Nein</span>
</span>
{% else %}
<span class="badge badge-warning eventButton" title="{{p.comment}}" data-status="{{p.status}}">
{% if p.comment %} <i class="icon-comment icon-white"></i> {% endif %}
<span class="text">?</span>
</span>
{% endif %}
</td>
{% endif %}
{% endfor %}
<td> <td>
<a class="btn btn-mini btn-inverse deleteButton" data-pk="{{event.pk}}"><i class="icon-trash icon-white"></i> Löschen </a> <a class="btn btn-mini btn-inverse deleteButton" data-pk="{{event.pk}}"><i class="icon-trash icon-white"></i> Löschen </a>
@ -160,9 +190,11 @@
</tr> </tr>
{% endfor %} {% endfor %}
{% if perms.eventplanner.admin %}
<tr> <tr>
<td class="center"> <a href="add">Termin hinzufügen...</a> </td> <td class="center"> <a href="add">Termin hinzufügen...</a> </td>
<tr> <tr>
{% endif %}</form>
</tbody> </tbody>
</table> </table>
@ -173,7 +205,7 @@
</div><!--/row--> </div><!--/row-->
{% if perms.eventplanner.change_others_participation %} {% if perms.eventplanner.admin %}
<div class="row"> <div class="row">
<div class="span12"> <div class="span12">
<button id="saveButton" class="btn btn-primary" disabled="true">Speichern</button> <button id="saveButton" class="btn btn-primary" disabled="true">Speichern</button>

View File

@ -1,11 +1,11 @@
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import permission_required
from eventplanner.views import main_view, events_grid, eventplanning,event_api,EventUpdate,EventCreate,deleteEvent from eventplanner.views import events_grid, eventplanning,event_api,EventUpdate,EventCreate,deleteEvent
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^$', main_view ), url(r'^$', eventplanning ),
url(r'^grid$', events_grid ), url(r'^grid$', events_grid ),
url(r'^planning$', eventplanning ), url(r'^planning$', eventplanning ),
url(r'^(?P<pk>\d+)$', permission_required('eventmanager.events.edit')( EventUpdate.as_view() ) ), url(r'^(?P<pk>\d+)$', permission_required('eventmanager.events.edit')( EventUpdate.as_view() ) ),

View File

@ -1,12 +1,10 @@
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.http import HttpResponse from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.forms.models import ModelForm from django.forms.models import ModelForm
from django.forms import TextInput from django.forms import TextInput
from models import Event, EventParticipation from models import Event, EventParticipation
from django.contrib.auth.models import User
from serializers import ParticipationSerializer from serializers import ParticipationSerializer
@ -32,42 +30,46 @@ def event_api( request, username = None, eventId = None ):
if username: if username:
participationQs = EventParticipation.objects.filter( user__username = username ) participationQs = EventParticipation.objects.filter( user__username = username )
if eventId: if eventId:
participationQs = participationQs.filter( event__pk = eventId ) participationQs = participationQs.filter( event__pk = eventId )
except EventParticipation.DoesNotExist: except EventParticipation.DoesNotExist:
return HttpResponse( status=404 ) return HttpResponse( status=404 )
if request.method == 'GET': if request.method == 'GET':
serializer = ParticipationSerializer( participationQs ) serializer = ParticipationSerializer( participationQs )
return Response( serializer.data ) return Response( serializer.data )
elif request.method == 'PUT': elif request.method == 'PUT':
print "Request data" + str ( request.DATA )
serializer = ParticipationSerializer ( participationQs, data = request.DATA, many=True ) serializer = ParticipationSerializer ( participationQs, data = request.DATA, many=True )
if serializer.is_valid(): if serializer.is_valid():
for serializedObject in serializer.object: for serializedObject in serializer.object:
if not EventParticipation.isMember( request.user ):
return Response( status = status.HTTP_403_FORBIDDEN )
if serializedObject.user != request.user: if serializedObject.user != request.user:
if not request.user.has_perm('change_others_participation') : if not EventParticipation.isAdmin( request.user ):
return Response( status = status.HTTP_403_FORBIDDEN ) return Response( status = status.HTTP_403_FORBIDDEN )
print serializer.data
serializer.save() serializer.save()
return Response( serializer.data ) return Response( serializer.data )
else: else:
print "In Bad request" + str(serializer.errors)
return Response( status = status.HTTP_400_BAD_REQUEST ) return Response( status = status.HTTP_400_BAD_REQUEST )
# ------------------------------------ Normal Views ---------------------------------------------------- # ------------------------------------ Normal Views ----------------------------------------------------
def main_view( request ):
if request.user.has_perm( 'eventplanner.change_others_participation'):
return events_grid( request )
else:
return eventplanning( request )
def eventplanning( request ): def eventplanning( request ):
""" """
View for a specific user, to edit his events View for a specific user, to edit his events
""" """
# non-members see the grid - but cannot edit anything
if not EventParticipation.isMember( request.user ):
print "Not a member"
return events_grid(request)
# All events in the future sorted by date # All events in the future sorted by date
all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ) ) all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ) )
@ -80,13 +82,12 @@ def eventplanning( request ):
def events_grid( request ): def events_grid( request ):
usernames = [ u.username for u in EventParticipation.members() ]
usernames = [ u.username for u in User.objects.all() ]
all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ) ) all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ) )
for e in all_future_events: for e in all_future_events:
e.participation = [ EventParticipation.get_or_create( event = e, user = u ) for u in User.objects.all() ] e.participation = [ EventParticipation.get_or_create( event = e, user = u ) for u in EventParticipation.members() ]
context = { 'events': all_future_events, context = { 'events': all_future_events,
'usernames' : usernames } 'usernames' : usernames }

View File

@ -23,7 +23,7 @@
.addressbook_entry { .addressbook_entry {
box-shadow: 0px 0px 7px -1px rgb(214, 214, 214); box-shadow: 0px 0px 7px -1px rgb(214, 214, 214);
border: 2px solid rgb(217, 217, 217); border: 2px solid rgb(217, 217, 217);
width: 350px !important; width: 360px !important;
float: left; float: left;
padding-top: 20px; padding-top: 20px;
padding-bottom: 20px; padding-bottom: 20px;
@ -48,6 +48,10 @@
margin-right: 10px; margin-right: 10px;
} }
.addressbook_entry td.labelCell {
white-space: nowrap;
}
</style> </style>
{% endaddtoblock %} {% endaddtoblock %}
@ -101,7 +105,7 @@
<li class="separator">/</li> <li class="separator">/</li>
<li><a href="#" data-filter=".unterstimme">Unterstimmen</a></li> <li><a href="#" data-filter=".unterstimme">Unterstimmen</a></li>
<li class="separator">/</li> <li class="separator">/</li>
<li><a href="#" data-filter=".oberstimmen">Oberstimmen</a></li> <li><a href="#" data-filter=".oberstimme">Oberstimmen</a></li>
<li class="separator">/</li> <li class="separator">/</li>
<li><a href="#" data-filter=".rest">Rest</a></li> <li><a href="#" data-filter=".rest">Rest</a></li>
</ul> </ul>
@ -124,12 +128,12 @@
</div> </div>
<table> <table>
{% if m.street %} <tr><td> Adresse </td><td>{{m.street}} </td> {% if m.street %} <tr><td class="labelCell"> Adresse </td><td>{{m.street}} </td>
<tr><td> </td><td>{{m.zip_code}} {{m.city}}</td>{% endif %} <tr><td class="labelCell"> </td><td>{{m.zip_code}} {{m.city}}</td>{% endif %}
{% if m.birthday %} <tr><td> Geburtstag: </td><td>{{m.birthday }} </td>{% endif %} {% if m.birthday %} <tr><td class="labelCell"> Geburtstag: </td><td>{{m.birthday }} </td>{% endif %}
{% if m.phone_home %} <tr><td> Telefon (Home): </td><td>{{m.phone_home }} </td>{% endif %} {% if m.phone_home %} <tr><td class="labelCell"> Telefon (Home): </td><td>{{m.phone_home }} </td>{% endif %}
{% if m.phone_mobile %}<tr><td> Telefon (Mobil): </td><td>{{m.phone_mobile }} </td>{% endif %} {% if m.phone_mobile %}<tr><td class="labelCell"> Telefon (Mobil): </td><td>{{m.phone_mobile }} </td>{% endif %}
{% if m.phone_work %} <tr><td> Telefon (Arbeit): </td><td>{{m.phone_work }} </td>{% endif %} {% if m.phone_work %} <tr><td class="labelCell"> Telefon (Arbeit): </td><td>{{m.phone_work }} </td>{% endif %}
</table> </table>
</div> </div>
{% endfor %} {% endfor %}

View File

@ -30,43 +30,6 @@
font-size: 17px; font-size: 17px;
margin: 0 0 40px 0; margin: 0 0 40px 0;
} }
#sign_in .header .social{
margin: 0 auto 28px;
float: none;
text-align: center;
}
#sign_in .header .social a.circle{
text-align: center;
width: 56px;
height: 56px;
border-radius: 100%;
margin-right: 25px;
display: inline-block;
-webkit-transition: border-color ease-in .1s;
-moz-transition: border-color ease-in .1s;
-o-transition: border-color ease-in .1s;
transition: border-color ease-in .1s;
}
#sign_in .header .social a.circle img{
display: inline-block;
margin-top: 15px;
}
#sign_in .header .social a.facebook{
border:2px solid #233678;
background: #233678;
}
#sign_in .header .social a.twitter{
border:2px solid #54AEE1;
background: #54AEE1;
}
#sign_in .header .social a.gplus{
border:2px solid #292929;
background: #292929;
margin: 0;
}
#sign_in .header .social a.circle:hover{
border-color: rgb(255, 255, 255);
}
#sign_in .division{ #sign_in .division{
margin: 0 auto 50px; margin: 0 auto 50px;
float: none; float: none;

View File

@ -43,13 +43,15 @@
in <em>{{countdown.event.location}} </em> in <em>{{countdown.event.location}} </em>
<br/> <br/>
{% if countdown.participation == "?" %} {% if 'participation' in countdown %}
Du hast dich noch nicht für diesen Termin eingetragen! {% if countdown.participation == "?" %}
{% elif countdown.participation == "Yes" %} Du hast dich noch nicht für diesen Termin eingetragen!
Du hast für diesen Termin zugesagt. {% elif countdown.participation == "Yes" %}
{% elif countdown.participation == "No" %} Du hast für diesen Termin zugesagt.
Du hast für diesen Termin abgesagt. {% elif countdown.participation == "No" %}
{%endif %} Du hast für diesen Termin abgesagt.
{%endif %}
{% endif %}
</p> </p>
</div> </div>
<div class="span6 count" id="clock"> <div class="span6 count" id="clock">

View File

@ -90,7 +90,7 @@
<article class="slide" id="adressbook" <article class="slide" id="adressbook"
style="background: url('{{STATIC_URL}}/img/slides/spielen2.jpg') repeat-x top center;"> style="background: url('{{STATIC_URL}}/img/slides/spielen2.jpg') repeat-x top center;">
<div class="info"> <div class="info">
<a href="/addressbook">Adressbuch</a> <a href="/musicians">Adressbuch</a>
<div class="subtitle subtitlebg">Geburtstage, Telefonnummern, ...</div> <div class="subtitle subtitlebg">Geburtstage, Telefonnummern, ...</div>
</div> </div>
</article> </article>

View File

@ -21,24 +21,25 @@ from django.contrib.auth.models import User
def home_view(request): def home_view(request):
context = dict() context = dict()
# Event participation for slider text # Event participation for slider text
context['hasParticipationSetForAllEvents'] = EventParticipation.hasUserSetParticipationForAllEvents( request.user) if EventParticipation.isMember( request.user ):
context['hasParticipationSetForAllEvents'] = EventParticipation.hasUserSetParticipationForAllEvents( request.user)
# Countdown # Countdown
countdown = dict() countdown = dict()
events = Event.objects.filter( date__gte = datetime.now() ).order_by('date')[:1] events = Event.objects.filter( date__gte = datetime.now() ).order_by('date')[:1]
if ( len(events) > 0 ): if ( len(events) > 0 ):
nextEvent = events[0] nextEvent = events[0]
part = EventParticipation.objects.filter( user = request.user ).filter( event = nextEvent )
if EventParticipation.isMember( request.user ):
part = EventParticipation.objects.filter( user = request.user ).filter( event = nextEvent )
countdown['participation'] = part[0].status
eventTime = datetime( events[0].date.year, events[0].date.month, events[0].date.day, eventTime = datetime( events[0].date.year, events[0].date.month, events[0].date.day,
events[0].displaytime.hour, events[0].displaytime.minute ) events[0].displaytime.hour, events[0].displaytime.minute )
countdown['event'] = events[0] countdown['event'] = events[0]
countdown['epoch'] = int( (eventTime - datetime.now() ).total_seconds() * 1000 ) countdown['epoch'] = int( (eventTime - datetime.now() ).total_seconds() * 1000 )
countdown['participation'] = part[0].status
context['countdown'] = countdown context['countdown'] = countdown
@ -128,5 +129,5 @@ from django.core.urlresolvers import reverse
def change_password( request ): def change_password( request ):
template_name = "website/change_password.html" template_name = "website/change_password.html"
return django.contrib.auth.views.password_change(request, template_name, post_change_redirect= reverse(home_view) ) return django.contrib.auth.views.password_change(request, template_name, post_change_redirect= "/" )