More cleanup

moved login, logout and password change from website app to musicians
This commit is contained in:
Martin Bauer
2014-01-11 15:01:40 +01:00
parent 1aa97e53d3
commit 010efe137e
13 changed files with 202 additions and 163 deletions

View File

@@ -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 = ( ('?' , _('?' )),

55
eventplanner/snippets.py Normal file
View File

@@ -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

View File

@@ -0,0 +1,79 @@
{% load sekizai_tags staticfiles %}
{% addtoblock "css" strip %}<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}/css/lib/animate.css" media="screen, projection">{% endaddtoblock %}
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/coming-soon.css" type="text/css" media="screen" />{% endaddtoblock %}
{% if countdown %}
{% addtoblock "js" %}
<script type="text/javascript">
$(function () {
function callback(event) {
$this = $(this);
$this.find('span#'+event.type).html(event.value);
switch(event.type) {
case "seconds":
case "minutes":
case "hours":
case "days":
case "weeks":
case "daysLeft":
case "finished":
}
}
$('div#clock').countdown(new Date().valueOf() + {{ countdown.epoch }} , callback);
});
</script>
{% endaddtoblock %}
<div id="coming_soon">
<div class="head">
<div class="container">
<div class="span6 text">
<h4>Der nächste Termin:</h4>
<p>
{{countdown.event.title}} am {{countdown.event.date | date:"D, d.m.y" }}
{% if coundown.event.displaytime %} um {{countdown.event.displaytime | time:"H:i" }} Uhr {% endif %}
{% if coundown.event.location %} in <em>{{countdown.event.location}} </em> {% endif %}
<br/>
{% 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">
<div class="box">
<div class="circle"> <span id="days"></span> </div>
<p>Tage</p>
</div>
<div class="box">
<div class="circle"> <span id="hours"></span> </div>
<p>Stunden</p>
</div>
<div class="box">
<div class="circle"> <span id="minutes"></span> </div>
<p>Minuten</p>
</div>
<div class="box last">
<div class="circle"> <span id="seconds"></span> </div>
<p>Sekunden</p>
</div>
</div>
</div>
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,208 @@
{% comment %}
Displays google map with directions to next conert
Context:
Coordinates or textual adresses:
{{route.origin}}
{{route.destination}}
Event object:
{{route.event}}
{% endcomment %}
{% load sekizai_tags staticfiles %}
{% if route %}
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/concert_route.css" type="text/css" media="screen" />{% endaddtoblock %}
{% addtoblock "js" strip %}<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false&amp;language=de"></script>{% endaddtoblock %}
{% addtoblock "js" %}
<script type="text/javascript">
function OpenWindowControl(controlDiv, map) {
// Set CSS styles for the DIV containing the control
// Setting padding to 5 px will offset the control
// from the edge of the map
controlDiv.style.paddingTop = '6px';
// Set CSS for the control border
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '1px';
controlUI.style.cursor = 'pointer';
controlUI.style.textAlign = 'center';
controlUI.title = 'Fenster mit Konzert Info anzeigen';
controlDiv.appendChild(controlUI);
// Set CSS for the control interior
var controlText = document.createElement('div');
controlText.style.fontFamily = 'Arial,sans-serif';
controlText.style.fontSize = '12px';
controlText.style.paddingLeft = '4px';
controlText.style.paddingRight = '4px';
controlText.innerHTML = 'Konzert Info anzeigen';
controlUI.appendChild(controlText);
google.maps.event.addDomListener(controlUI, 'click', function() {
$("#map_box").show();
});
}
function ShowTargetControl(controlDiv, map) {
// Set CSS styles for the DIV containing the control
// Setting padding to 5 px will offset the control
// from the edge of the map
controlDiv.style.paddingTop = '6px';
controlDiv.style.paddingRight = '6px';
// Set CSS for the control border
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '1px';
controlUI.style.cursor = 'pointer';
controlUI.style.textAlign = 'center';
controlUI.title = 'Zum Zielpunkt springen';
controlDiv.appendChild(controlUI);
// Set CSS for the control interior
var controlText = document.createElement('div');
controlText.style.fontFamily = 'Arial,sans-serif';
controlText.style.fontSize = '12px';
controlText.style.paddingLeft = '4px';
controlText.style.paddingRight = '4px';
controlText.innerHTML = 'Konzertort anzeigen';
controlUI.appendChild(controlText);
google.maps.event.addDomListener(controlUI, 'click', function()
{
{% if not route.event.map_location %}
geocoder = new google.maps.Geocoder();
geocoder.region = "de";
geocoder.geocode( {"address": "{{ route.event.location }}" }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setMapTypeId( google.maps.MapTypeId.HYBRID );
map.setZoom( 15 );
map.setCenter( results[0].geometry.location );
}
});
{% else %}
var loc = new google.maps.LatLng( {{ route.event.map_location }} );
map.setMapTypeId( google.maps.MapTypeId.HYBRID );
map.setZoom( 20 );
map.setCenter( loc );
{% endif %}
});
}
$(document).ready(function() {
var m = $("#map")[0];
var myOptions = {
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROAD,
zoomControl: false,
panControl: false,
streetViewControl: false,
scrollwheel: false
}
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
var map = new google.maps.Map(m, myOptions);
directionsDisplay.setMap( map );
var request = {
origin: "{{route.origin}}",
destination: "{{route.destination}}",
travelMode: google.maps.DirectionsTravelMode.DRIVING
}
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var leg = response.routes[0].legs[0];
$("#route_duration").html( leg.duration.text );
$("#route_distance").html( leg.distance.text ) ;
}
});
var showInfoControlDiv = document.createElement('div');
var showInfoControl = new OpenWindowControl(showInfoControlDiv, map);
showInfoControlDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_RIGHT].push( showInfoControlDiv );
var showTargetControlDiv = document.createElement('div');
var showTargetControl = new ShowTargetControl(showTargetControlDiv, map);
showTargetControlDiv.index = 2;
map.controls[ google.maps.ControlPosition.TOP_RIGHT ].push(showTargetControlDiv);
$("#map_box a").click( function() {
$("#map_box").hide();
map.setOptions( { scrollwheel: true } );
});
}
);
</script>
{% endaddtoblock %}
<div id="concert_route">
<div id="map"></div>
<div id="map_box" class="row map">
<div class="container">
<div id="route_info_box" class="span5 box_wrapp">
<div class="box_cont">
<div class="head">
<h4>Nächstes Konzert</h4>
<!--
</div>
Nächstes Konzert ist in <br> <em>{{route.event.location}}</em> <br> am {{route.event.date | date:"SHORT_DATE_FORMAT" }} um {{route.event.time | time:"H:i" }} Uhr <br/>
{% if route.event.meeting_time %} Treffpunkt ist um {{ route.event.meeting_time | time:"H:i" }} Uhr <br/> {% endif %}
<table>
<tr> <td> Fahrzeit:</td> <td> <span id="route_duration"></span> </td> </tr>
<tr> <td> Strecke: </td> <td> <span id="route_distance"></span> </td> </tr>
</table>
-->
<table class="table table-striped table-condensed">
<tr><td>Ort: </td> <td> {{route.event.location}} </td> </tr>
<tr><td>Datum: </td> <td> {{route.event.date | date:"D, d.m.y" }} </td> </tr>
<tr><td>Uhrzeit: </td> <td> {{route.event.time | time:"H:i" }} Uhr </td> </tr>
{% if route.event.meeting_time %} <tr><td>Treffen um: </td> <td> {{route.event.meeting_time | time:"H:i" }} Uhr </td> </tr> {% endif %}
<tr> <td> Fahrzeit:</td> <td> <span id="route_duration"></span> </td> </tr>
<tr> <td> Strecke: </td> <td> <span id="route_distance"></span> </td> </tr>
</table>
<a class="btn" >Schliessen</a>
</div>
</div>
</div>
</div>
</div>
{% endif %}