Filled with Data / Addressbook corrections
Before Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 42 KiB |
|
@ -1,8 +1,9 @@
|
|||
from django.db import models
|
||||
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 location_field.models import PlainLocationField
|
||||
|
@ -78,6 +79,9 @@ class EventParticipation( models.Model ):
|
|||
|
||||
@staticmethod
|
||||
def hasUserSetParticipationForAllEvents( user ):
|
||||
if not EventParticipation.isMember(user):
|
||||
return True
|
||||
|
||||
futurePart = EventParticipation.objects.filter( event__date__gte = datetime.now() )
|
||||
|
||||
maybeObjects = futurePart.filter( user = user ).filter( status = '?' )
|
||||
|
@ -86,6 +90,18 @@ class EventParticipation( models.Model ):
|
|||
else:
|
||||
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
|
||||
def get_or_create( user , event ):
|
||||
|
@ -99,8 +115,9 @@ class EventParticipation( models.Model ):
|
|||
class Meta:
|
||||
unique_together = ("event", "user")
|
||||
permissions = (
|
||||
("change_others_participation", _("Can modify participation status of other users") ),
|
||||
("admin", _("Admin") ),
|
||||
("member", _("Member") ),
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
@ -7,10 +7,12 @@ from models import EventParticipation
|
|||
class ParticipationSerializer(serializers.ModelSerializer):
|
||||
event = serializers.PrimaryKeyRelatedField( many=False, read_only = False )
|
||||
user = serializers.Field( source='get_username' )
|
||||
status = serializers.CharField( source='status', required=False )
|
||||
|
||||
def get_identity(self, data):
|
||||
""" This hook is required for bulk update. """
|
||||
""" This hook is required for bulk update. """
|
||||
try:
|
||||
print "get_identity event:" + str( data.get('event', None) ) + " user " + str( data.get('user') )
|
||||
return ( data.get('event', None), data.get('user') )
|
||||
except AttributeError:
|
||||
return None
|
||||
|
|
|
@ -41,38 +41,36 @@
|
|||
}
|
||||
}
|
||||
|
||||
function putStatus( button, status ) {
|
||||
function putStatus( button, status )
|
||||
{
|
||||
$("#saving").html("Speichere..");
|
||||
|
||||
p = button.parent();
|
||||
putObject = [ { "event": p.data("event-id"),
|
||||
"user": p.data("username"),
|
||||
"status": status } ];
|
||||
|
||||
|
||||
request = $.ajax( {
|
||||
type: "PUT",
|
||||
url: "{% url 'event_api' %}",
|
||||
contentType: "application/json",
|
||||
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 );
|
||||
//request.done(function(jqXHR, textStatus) {
|
||||
// setEventButtonStatus( button, status )
|
||||
//});
|
||||
}
|
||||
|
||||
$(function(){
|
||||
|
||||
$(".event-comment").bindWithDelay("keypress", function() {
|
||||
|
||||
$("#saving").html("Speichere..");
|
||||
|
||||
putObject = [ { "event": $(this).data("event-id"),
|
||||
"user": $(this).data("username"),
|
||||
"comment": $(this).val() } ];
|
||||
|
||||
|
||||
$.ajax( {
|
||||
type: "PUT",
|
||||
url: "{% url 'event_api' %}",
|
||||
|
@ -103,13 +101,17 @@
|
|||
|
||||
|
||||
<div class="container">
|
||||
<form>
|
||||
<p>
|
||||
<div class="row">
|
||||
<div class="row-fluid eventTable">
|
||||
<div class="span12">
|
||||
|
||||
<h2>Termine</h2>
|
||||
|
||||
|
||||
|
||||
<p class="pull-right" ><a href="grid">zur Übersicht</a></p>
|
||||
|
||||
|
||||
<div class="box-content">
|
||||
<table class="table table-striped">
|
||||
|
||||
|
@ -140,7 +142,7 @@
|
|||
<td class="center"> {{ event.location }} </td>
|
||||
|
||||
<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 %}">
|
||||
<i class="icon-ok-sign icon-white"></i>
|
||||
</button>
|
||||
|
@ -172,8 +174,9 @@
|
|||
<div class="span12">
|
||||
<em>Änderungen werden automatisch gespeichert: </em> <em id="saving">Ok</em>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -16,9 +16,14 @@
|
|||
{% block content %}
|
||||
{% addtoblock "css" %}
|
||||
<style>
|
||||
.eventButton {
|
||||
button.eventButton {
|
||||
width: 55px;
|
||||
}
|
||||
span.eventButton {
|
||||
height: 16px;
|
||||
width: 45px;
|
||||
text-align: center;
|
||||
}
|
||||
.eventButton i {
|
||||
margin-right:2px;
|
||||
}
|
||||
|
@ -30,14 +35,14 @@
|
|||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
{% if not perms.eventplanner.change_others_participation %}
|
||||
{% if not perms.eventplanner.admin %}
|
||||
$(".eventButton").attr('disabled', 'disabled');
|
||||
$(".deleteButton").hide();
|
||||
{% endif %}
|
||||
|
||||
$('.eventButton').tooltip()
|
||||
|
||||
$(".eventButton").click( function (e) {
|
||||
$("button.eventButton").click( function (e) {
|
||||
e.preventDefault();
|
||||
$(this).removeClass("btn-danger")
|
||||
.removeClass("btn-warning")
|
||||
|
@ -135,6 +140,9 @@
|
|||
|
||||
|
||||
{% for p in event.participation %}
|
||||
|
||||
{% if perms.eventplanner.admin %}
|
||||
|
||||
<td class="center userEventTableData" data-username="{{p.user.username}}" data-event="{{event.pk}}">
|
||||
{% if p.status == "Yes" %}
|
||||
<button class="btn btn-mini btn-success eventButton" title="{{p.comment}}" data-status="{{p.status}}">
|
||||
|
@ -152,7 +160,29 @@
|
|||
<span class="text">?</span>
|
||||
</button>
|
||||
{% 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>
|
||||
<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>
|
||||
{% endfor %}
|
||||
|
||||
{% if perms.eventplanner.admin %}
|
||||
<tr>
|
||||
<td class="center"> <a href="add">Termin hinzufügen...</a> </td>
|
||||
<tr>
|
||||
{% endif %}</form>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -173,7 +205,7 @@
|
|||
</div><!--/row-->
|
||||
|
||||
|
||||
{% if perms.eventplanner.change_others_participation %}
|
||||
{% if perms.eventplanner.admin %}
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<button id="saveButton" class="btn btn-primary" disabled="true">Speichern</button>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
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('',
|
||||
url(r'^$', main_view ),
|
||||
url(r'^$', eventplanning ),
|
||||
url(r'^grid$', events_grid ),
|
||||
url(r'^planning$', eventplanning ),
|
||||
url(r'^(?P<pk>\d+)$', permission_required('eventmanager.events.edit')( EventUpdate.as_view() ) ),
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
|
||||
from django.shortcuts import render, redirect
|
||||
from django.http import HttpResponse
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.forms.models import ModelForm
|
||||
from django.forms import TextInput
|
||||
|
||||
from models import Event, EventParticipation
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
from serializers import ParticipationSerializer
|
||||
|
@ -32,42 +30,46 @@ def event_api( request, username = None, eventId = None ):
|
|||
if username:
|
||||
participationQs = EventParticipation.objects.filter( user__username = username )
|
||||
if eventId:
|
||||
participationQs = participationQs.filter( event__pk = eventId )
|
||||
|
||||
participationQs = participationQs.filter( event__pk = eventId )
|
||||
except EventParticipation.DoesNotExist:
|
||||
return HttpResponse( status=404 )
|
||||
|
||||
|
||||
|
||||
if request.method == 'GET':
|
||||
serializer = ParticipationSerializer( participationQs )
|
||||
return Response( serializer.data )
|
||||
|
||||
elif request.method == 'PUT':
|
||||
print "Request data" + str ( request.DATA )
|
||||
serializer = ParticipationSerializer ( participationQs, data = request.DATA, many=True )
|
||||
if serializer.is_valid():
|
||||
for serializedObject in serializer.object:
|
||||
if not EventParticipation.isMember( request.user ):
|
||||
return Response( status = status.HTTP_403_FORBIDDEN )
|
||||
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 )
|
||||
|
||||
print serializer.data
|
||||
serializer.save()
|
||||
return Response( serializer.data )
|
||||
else:
|
||||
print "In Bad request" + str(serializer.errors)
|
||||
return Response( status = status.HTTP_400_BAD_REQUEST )
|
||||
|
||||
|
||||
|
||||
# ------------------------------------ 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 ):
|
||||
"""
|
||||
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_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ) )
|
||||
|
||||
|
@ -80,13 +82,12 @@ def eventplanning( request ):
|
|||
|
||||
|
||||
def events_grid( request ):
|
||||
|
||||
usernames = [ u.username for u in User.objects.all() ]
|
||||
usernames = [ u.username for u in EventParticipation.members() ]
|
||||
|
||||
all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ) )
|
||||
|
||||
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,
|
||||
'usernames' : usernames }
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
.addressbook_entry {
|
||||
box-shadow: 0px 0px 7px -1px rgb(214, 214, 214);
|
||||
border: 2px solid rgb(217, 217, 217);
|
||||
width: 350px !important;
|
||||
width: 360px !important;
|
||||
float: left;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
|
@ -48,6 +48,10 @@
|
|||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.addressbook_entry td.labelCell {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
</style>
|
||||
{% endaddtoblock %}
|
||||
|
||||
|
@ -101,7 +105,7 @@
|
|||
<li class="separator">/</li>
|
||||
<li><a href="#" data-filter=".unterstimme">Unterstimmen</a></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><a href="#" data-filter=".rest">Rest</a></li>
|
||||
</ul>
|
||||
|
@ -124,12 +128,12 @@
|
|||
</div>
|
||||
|
||||
<table>
|
||||
{% if m.street %} <tr><td> Adresse </td><td>{{m.street}} </td>
|
||||
<tr><td> </td><td>{{m.zip_code}} {{m.city}}</td>{% endif %}
|
||||
{% if m.birthday %} <tr><td> 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_mobile %}<tr><td> 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.street %} <tr><td class="labelCell"> Adresse </td><td>{{m.street}} </td>
|
||||
<tr><td class="labelCell"> </td><td>{{m.zip_code}} {{m.city}}</td>{% endif %}
|
||||
{% if m.birthday %} <tr><td class="labelCell"> Geburtstag: </td><td>{{m.birthday }} </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 class="labelCell"> Telefon (Mobil): </td><td>{{m.phone_mobile }} </td>{% endif %}
|
||||
{% if m.phone_work %} <tr><td class="labelCell"> Telefon (Arbeit): </td><td>{{m.phone_work }} </td>{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
|
|
@ -30,43 +30,6 @@
|
|||
font-size: 17px;
|
||||
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{
|
||||
margin: 0 auto 50px;
|
||||
float: none;
|
||||
|
|
|
@ -43,13 +43,15 @@
|
|||
in <em>{{countdown.event.location}} </em>
|
||||
|
||||
<br/>
|
||||
{% if countdown.participation == "?" %}
|
||||
Du hast dich noch nicht für diesen Termin eingetragen!
|
||||
{% elif countdown.participation == "Yes" %}
|
||||
Du hast für diesen Termin zugesagt.
|
||||
{% elif countdown.participation == "No" %}
|
||||
Du hast für diesen Termin abgesagt.
|
||||
{%endif %}
|
||||
{% if 'participation' in countdown %}
|
||||
{% if countdown.participation == "?" %}
|
||||
Du hast dich noch nicht für diesen Termin eingetragen!
|
||||
{% elif countdown.participation == "Yes" %}
|
||||
Du hast für diesen Termin zugesagt.
|
||||
{% elif countdown.participation == "No" %}
|
||||
Du hast für diesen Termin abgesagt.
|
||||
{%endif %}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="span6 count" id="clock">
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
<article class="slide" id="adressbook"
|
||||
style="background: url('{{STATIC_URL}}/img/slides/spielen2.jpg') repeat-x top center;">
|
||||
<div class="info">
|
||||
<a href="/addressbook">Adressbuch</a>
|
||||
<a href="/musicians">Adressbuch</a>
|
||||
<div class="subtitle subtitlebg">Geburtstage, Telefonnummern, ...</div>
|
||||
</div>
|
||||
</article>
|
||||
|
|
|
@ -21,24 +21,25 @@ from django.contrib.auth.models import User
|
|||
def home_view(request):
|
||||
context = dict()
|
||||
|
||||
|
||||
# Event participation for slider text
|
||||
context['hasParticipationSetForAllEvents'] = EventParticipation.hasUserSetParticipationForAllEvents( request.user)
|
||||
|
||||
if EventParticipation.isMember( request.user ):
|
||||
context['hasParticipationSetForAllEvents'] = EventParticipation.hasUserSetParticipationForAllEvents( request.user)
|
||||
|
||||
# Countdown
|
||||
countdown = dict()
|
||||
events = Event.objects.filter( date__gte = datetime.now() ).order_by('date')[:1]
|
||||
if ( len(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,
|
||||
events[0].displaytime.hour, events[0].displaytime.minute )
|
||||
|
||||
countdown['event'] = events[0]
|
||||
countdown['epoch'] = int( (eventTime - datetime.now() ).total_seconds() * 1000 )
|
||||
countdown['participation'] = part[0].status
|
||||
|
||||
context['countdown'] = countdown
|
||||
|
||||
|
@ -128,5 +129,5 @@ from django.core.urlresolvers import reverse
|
|||
|
||||
def change_password( request ):
|
||||
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= "/" )
|
||||
|
||||
|
|