diff --git a/blechreiz/settings.py b/blechreiz/settings.py
index 877019c..e072f95 100644
--- a/blechreiz/settings.py
+++ b/blechreiz/settings.py
@@ -78,8 +78,8 @@ STATIC_ROOT = PROJECT_PATH + '/static_collection'
# Example: "http://example.com/static/", "http://static.example.com/"
STATIC_URL = '/static/'
-LOGIN_URL="/login"
-PUBLIC_URLS=( "^login/?$", "^login/usernames/?$")
+LOGIN_URL="/musicians/login"
+PUBLIC_URLS=( "^musicians/login/?$", "^musicians/login/usernames/?$")
# Additional locations of static files
STATICFILES_DIRS = (
diff --git a/eventplanner/models.py b/eventplanner/models.py
index 8bd01aa..fbab014 100644
--- a/eventplanner/models.py
+++ b/eventplanner/models.py
@@ -9,6 +9,11 @@ from datetime import datetime
from location_field.models import PlainLocationField
+class NoNextEventException( Exception ):
+ def __str__(self):
+ return ("No event scheduled for the future")
+
+
class Event ( models.Model ):
EVENT_TYPES = (
@@ -64,11 +69,50 @@ class Event ( models.Model ):
@property
def displaydatetime(self):
if not self.displaytime == None:
- return datetime.combine( self.date, self.displaytime() )
+ return datetime.combine( self.date, self.displaytime )
else:
- return datetime.combine( self.date, datetime.min.time())
+ return datetime.combine( self.date, datetime.min.time() )
+ @staticmethod
+ def getNextEvent( eventType = "", includePreviousFromToday = True ):
+ """Return the next event, of the given type. If type is the empty string the next event is returned
+ regardless of its type.
+ if includePreviousFromToday the nextEvent returned could also have been today with a startime < now """
+ if includePreviousFromToday:
+ if eventType == "":
+ nextEvents = Event.objects.filter( date__gte = datetime.now() ).order_by('date')[:1]
+ else:
+ nextEvents = Event.objects.filter( date__gte = datetime.now(), type = eventType ).order_by('date')[:1]
+
+ if len( nextEvents ) == 0:
+ raise NoNextEventException()
+
+ return nextEvents[0]
+ else:
+ maximalNumberOfEventsOnSameDay = 4
+ nextEvents = []
+ if eventType =="":
+ nextEvents = Event.objects.filter( date__gte = datetime.now() ).order_by('date')[:maximalNumberOfEventsOnSameDay]
+ else:
+ nextEvents = Event.objects.filter( date__gte = datetime.now(), type = eventType ).order_by('date')[:maximalNumberOfEventsOnSameDay]
+
+ if len(nextEvents) == 0:
+ raise NoNextEventException()
+
+
+ i = 0
+ nextEvent = nextEvents[0]
+ # nextEvent is not necessarily events[0] since events[0] may have been previously today
+ while nextEvent.displaydatetime < datetime.now():
+ if len(nextEvents ) <= i:
+ raise NoNextEventException()
+ else:
+ i += 1
+ nextEvent = nextEvents[i]
+
+ return nextEvent
+
class EventParticipation( models.Model ):
OPTIONS = ( ('?' , _('?' )),
diff --git a/eventplanner/snippets.py b/eventplanner/snippets.py
new file mode 100644
index 0000000..8495b9b
--- /dev/null
+++ b/eventplanner/snippets.py
@@ -0,0 +1,55 @@
+
+from datetime import datetime
+from models import Event, EventParticipation, NoNextEventException
+from musicians.models import Musician
+
+
+
+def addEventCountdownForNextEventToContext( context, username, eventType = "" ):
+ """Returns an object that has to be added to the render context on the page where the countdown
+ should be displayed . The username is required to also supply participation information."""
+
+ try:
+ nextEvent = Event.getNextEvent( eventType, False )
+ except NoNextEventException:
+ return
+
+ countdown = dict()
+
+ if EventParticipation.isMember( username ):
+ part = EventParticipation.objects.filter( user = username ).filter( event = nextEvent )
+ countdown['participation'] = part[0].status
+
+ eventTime = nextEvent.displaydatetime
+ countdown['event'] = nextEvent
+ countdown['epoch'] = int( (eventTime - datetime.now() ).total_seconds() * 1000 )
+
+ context["countdown"] = countdown
+
+
+def addEventRouteForNextEventToContext( context, username, eventType = ""):
+ """Returns an object that has to be added to the render context on the page where the route
+ should be displayed . The starting address of the route will be the home of the specified user"""
+
+ try:
+ nextEvent = Event.getNextEvent( eventType, True )
+ except NoNextEventException:
+ return
+
+ routeInfo = dict()
+
+ routeInfo['event'] = nextEvent
+
+ musician = Musician.objects.get( user = username );
+ routeInfo['origin'] = musician.street + ", " + str( musician.zip_code ) + " " + musician.city
+
+ if nextEvent.map_location:
+ # map_location has format "lat,longitute,zoomlevel"
+ routeInfo['destination'] = ",".join( nextEvent.map_location.split(",")[:2] )
+ else:
+ routeInfo['destination'] = nextEvent.location
+
+
+ context["route"] = routeInfo
+
+
diff --git a/website/templates/website/event_countdown.html b/eventplanner/templates/eventplanner/countdown.inc.html
similarity index 100%
rename from website/templates/website/event_countdown.html
rename to eventplanner/templates/eventplanner/countdown.inc.html
diff --git a/website/templates/website/concert_route.html b/eventplanner/templates/eventplanner/routeToEventMap.inc.html
similarity index 85%
rename from website/templates/website/concert_route.html
rename to eventplanner/templates/eventplanner/routeToEventMap.inc.html
index 15ddad9..63ab113 100644
--- a/website/templates/website/concert_route.html
+++ b/eventplanner/templates/eventplanner/routeToEventMap.inc.html
@@ -3,12 +3,10 @@
Context:
Coordinates or textual adresses:
- {{routeInfo.origin}}
- {{routeInfo.destination}}
-
+ {{route.origin}}
+ {{route.destination}}
Event object:
- {{nextConcert}}
-
+ {{route.event}}
{% endcomment %}
@@ -16,9 +14,8 @@
{% load sekizai_tags staticfiles %}
-{% if hasNextConcertInfo %}
-
+{% if route %}
{% addtoblock "css" strip %}{% endaddtoblock %}
{% addtoblock "js" strip %}{% endaddtoblock %}
@@ -86,10 +83,10 @@
google.maps.event.addDomListener(controlUI, 'click', function()
{
- {% if not nextConcert.map_location %}
+ {% if not route.event.map_location %}
geocoder = new google.maps.Geocoder();
geocoder.region = "de";
- geocoder.geocode( {"address": "{{ nextConcert.location }}" }, function(results, status) {
+ geocoder.geocode( {"address": "{{ route.event.location }}" }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setMapTypeId( google.maps.MapTypeId.HYBRID );
map.setZoom( 15 );
@@ -98,7 +95,7 @@
}
});
{% else %}
- var loc = new google.maps.LatLng( {{ nextConcert.map_location }} );
+ var loc = new google.maps.LatLng( {{ route.event.map_location }} );
map.setMapTypeId( google.maps.MapTypeId.HYBRID );
map.setZoom( 20 );
@@ -127,8 +124,8 @@
directionsDisplay.setMap( map );
var request = {
- origin: "{{routeInfo.origin}}",
- destination: "{{routeInfo.destination}}",
+ origin: "{{route.origin}}",
+ destination: "{{route.destination}}",
travelMode: google.maps.DirectionsTravelMode.DRIVING
}
@@ -180,8 +177,8 @@
- Ort: | {{nextConcert.location}} |
- Datum: | {{nextConcert.date | date:"D, d.m.y" }} |
- Uhrzeit: | {{nextConcert.time | time:"H:i" }} Uhr |
- {% if nextConcert.meeting_time %} Treffen um: | {{ nextConcert.meeting_time | time:"H:i" }} Uhr |
{% endif %}
+ Ort: | {{route.event.location}} |
+ Datum: | {{route.event.date | date:"D, d.m.y" }} |
+ Uhrzeit: | {{route.event.time | time:"H:i" }} Uhr |
+ {% if route.event.meeting_time %} Treffen um: | {{route.event.meeting_time | time:"H:i" }} Uhr |
{% endif %}
Fahrzeit: | |
Strecke: | |
diff --git a/website/templates/website/change_password.html b/musicians/templates/musicians/change_password.html
similarity index 100%
rename from website/templates/website/change_password.html
rename to musicians/templates/musicians/change_password.html
diff --git a/website/templates/website/login.html b/musicians/templates/musicians/login.html
similarity index 98%
rename from website/templates/website/login.html
rename to musicians/templates/musicians/login.html
index fb8d5ac..0141060 100644
--- a/website/templates/website/login.html
+++ b/musicians/templates/musicians/login.html
@@ -60,7 +60,7 @@
});
- $.get( "/login/usernames", function( data ) {
+ $.get( "/musicians/login/usernames", function( data ) {
$("#username").autocomplete( { source: data } );
});
});
diff --git a/musicians/urls.py b/musicians/urls.py
index 9d6c88c..45ca4bf 100644
--- a/musicians/urls.py
+++ b/musicians/urls.py
@@ -6,6 +6,9 @@ import musicians.views
urlpatterns = patterns('',
url(r'^$', musicians.views.addressbook ),
url(r'^profile$', musicians.views.own_profile ),
- #url(r'^(?P[\w]+)$$', musicians.views.user_edit ),
+ url(r'^changePassword/$', musicians.views.change_password ),
+ url(r'^login/$', musicians.views.login_view),
+ url(r'^login/usernames$', musicians.views.userlistForAutocompletion),
+ url(r'^logout/$', musicians.views.logout_view),
)
diff --git a/musicians/views.py b/musicians/views.py
index fccc177..f7268ec 100644
--- a/musicians/views.py
+++ b/musicians/views.py
@@ -79,9 +79,76 @@ def addressbook( request ):
return render( request, 'musicians/addressbook.html', context )
+############################################################################################################
+######################### User Management Views ############################################################
+############################################################################################################
+
+from django.contrib.auth.views import password_change
+from django.contrib.auth import authenticate, login, logout
+from django.shortcuts import redirect
+from django.http import HttpResponse
+from django.utils import simplejson
+from django.contrib.auth.models import User
+from datetime import timedelta
+
+
+def change_password( request ):
+ return password_change(request, "musicians/change_password.html", post_change_redirect= "/" )
+
+def logout_view(request):
+ logout( request )
+ return redirect( login_view )
+
+
+def userlistForAutocompletion(request):
+ result = [ u.username for u in User.objects.all() ]
+ return HttpResponse( simplejson.dumps(result), mimetype='application/json' )
+
+
+def login_view( request ):
+ if request.method == 'POST': # If the form has been submitted...
+ raiseFirstLetter = lambda s: s[:1].upper() + s[1:] if s else ''
+ username = raiseFirstLetter( request.POST['username'] )
+ password = request.POST['password']
+ user = authenticate( username=username, password=password )
+ result = dict()
+ result['err'] = ""
+ if user is not None:
+ if user.is_active:
+ if not request.POST.get('remember', None):
+ # Expire in one year
+ request.session.set_expiry( timedelta( weeks=52 ) )
+ else:
+ # Expire on browser close
+ request.session.set_expiry( 0 )
+
+ login(request, user)
+ result['redirect'] = "/"
+ print ( "Setting Redirect" )
+ if 'next' in request.POST :
+ result['redirect'] = request.POST["next"]
+ print ( "Using " + request.POST["next"] )
+ else:
+ result['err'] = "Dein Account wurde deaktiviert."
+ # Return a 'disabled account' error message
+ else:
+ result['err'] = "Falscher Benutzername oder falsches Kennwort."
+
+ return HttpResponse( simplejson.dumps(result), mimetype='application/json' )
-
+ else:
+ # Check if user already logged in
+ if request.user.is_authenticated():
+ return redirect( "/")
+
+ if 'next' in request.GET:
+ nextPage = request.GET['next']
+ else:
+ nextPage = "/"
+ return render( request, 'musicians/login.html', { 'next' : nextPage } )
+
+
diff --git a/website/templates/website/base.html b/website/templates/website/base.html
index c67759b..b4a669d 100644
--- a/website/templates/website/base.html
+++ b/website/templates/website/base.html
@@ -48,8 +48,8 @@
{% endif %}
diff --git a/website/templates/website/mainpage.html b/website/templates/website/mainpage.html
index 96196e0..185c8cb 100644
--- a/website/templates/website/mainpage.html
+++ b/website/templates/website/mainpage.html
@@ -1,14 +1,12 @@
{% extends "website/base.html" %}
-
{% load sekizai_tags staticfiles %}
-
{% block content %}
- {% include "website/event_countdown.html" %}
- {% include "website/concert_route.html" %}
+ {% include "eventplanner/countdown.inc.html" %}
+ {% include "eventplanner/routeToEventMap.inc.html" %}
{% endblock %}
diff --git a/website/urls.py b/website/urls.py
index d844ad3..93ad2a4 100644
--- a/website/urls.py
+++ b/website/urls.py
@@ -1,13 +1,9 @@
from django.conf.urls import patterns, url
-from website.views import home_view, login_view, userlistForAutocompletion,logout_view, change_password
+from website.views import home_view
urlpatterns = patterns('',
- url(r'$^', home_view ),
- url(r'^login/$', login_view),
- url(r'^login/usernames$', userlistForAutocompletion),
- url(r'^logout/$', logout_view),
- url(r'^changePassword/$', change_password),
+ url(r'$^', home_view ),
)
diff --git a/website/views.py b/website/views.py
index 4d091e7..c116325 100644
--- a/website/views.py
+++ b/website/views.py
@@ -1,20 +1,8 @@
-# Create your views here.
+from django.shortcuts import render
-from django.shortcuts import render, redirect
-from django.contrib.auth import authenticate, login, logout
-
-from django.http import HttpResponse
-
-from django.utils import simplejson
from django.contrib.auth.decorators import login_required
-
-
-from eventplanner.models import Event, EventParticipation
-from musicians.models import Musician
-
-from datetime import datetime
-from datetime import timedelta
-from django.contrib.auth.models import User
+from eventplanner.snippets import addEventCountdownForNextEventToContext, addEventRouteForNextEventToContext
+from eventplanner.models import EventParticipation
@login_required
@@ -25,117 +13,8 @@ def home_view(request):
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')[:3]
-
- if ( len(events) > 0 ):
- i = 0
- nextEvent = events[0]
-
- while nextEvent.displaydatetime < datetime.now():
- if len(events ) <= i:
- return
- else:
- i += 1
- nextEvent = events[i]
-
- if EventParticipation.isMember( request.user ):
- part = EventParticipation.objects.filter( user = request.user ).filter( event = nextEvent )
- countdown['participation'] = part[0].status
-
- eventTime = nextEvent.displaydatetime
-
- countdown['event'] = nextEvent
- countdown['epoch'] = int( (eventTime - datetime.now() ).total_seconds() * 1000 )
-
- context['countdown'] = countdown
-
-
- # Route to concert
- nextConcerts = Event.objects.filter( date__gte = datetime.now(), type = 'Conc' ).order_by('date')[:1]
- if len( nextConcerts) > 0 :
- nextConcert = nextConcerts[0]
-
- routeInfo = dict()
-
- musician = Musician.objects.get( user = request.user );
- routeInfo['origin'] = musician.street + ", " + str( musician.zip_code ) + " " + musician.city
-
- if nextConcert.map_location:
- # map_location has format "lat,longitute,zoomlevel"
- routeInfo['destination'] = ",".join( nextConcert.map_location.split(",")[:2] )
- else:
- routeInfo['destination'] = nextConcert.location
-
- context['routeInfo'] = routeInfo
- context['nextConcert'] = nextConcert
- context['hasNextConcertInfo'] = True
- else:
- context['hasNextConcertInfo'] = False
-
+ addEventCountdownForNextEventToContext( context, request.user );
+ addEventRouteForNextEventToContext(context, request.user, 'Conc' )
return render( request, 'website/mainpage.html', context )
-
-def logout_view(request):
- logout( request )
- return redirect( login_view )
-
-
-def userlistForAutocompletion(request):
- result = [ u.username for u in User.objects.all() ]
- return HttpResponse( simplejson.dumps(result), mimetype='application/json' )
-
-
-def login_view( request ):
- if request.method == 'POST': # If the form has been submitted...
- raiseFirstLetter = lambda s: s[:1].upper() + s[1:] if s else ''
- username = raiseFirstLetter( request.POST['username'] )
- password = request.POST['password']
- user = authenticate( username=username, password=password )
- result = dict()
- result['err'] = ""
- if user is not None:
- if user.is_active:
- if not request.POST.get('remember', None):
- # Expire in one year
- request.session.set_expiry( timedelta( weeks=52 ) )
- else:
- # Expire on browser close
- request.session.set_expiry( 0 )
-
- login(request, user)
- result['redirect'] = "/"
- print ( "Setting Redirect" )
- if 'next' in request.POST :
- result['redirect'] = request.POST["next"]
- print ( "Using " + request.POST["next"] )
- else:
- result['err'] = "Dein Account wurde deaktiviert."
- # Return a 'disabled account' error message
- else:
- result['err'] = "Falscher Benutzername oder falsches Kennwort."
-
- return HttpResponse( simplejson.dumps(result), mimetype='application/json' )
-
- else:
- # Check if user already logged in
- if request.user.is_authenticated():
- return redirect( "/")
-
- if 'next' in request.GET:
- nextPage = request.GET['next']
- else:
- nextPage = "/"
- return render( request, 'website/login.html', { 'next' : nextPage } )
-
-
-
-import django.contrib.auth.views
-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= "/" )
-