blob: dec8b003ef60028adfb0a6eea9cdf2a58805b13b [file] [log] [blame]
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Sheriff schedule pages."""
import datetime
import json
from google.appengine.ext import db
from base_page import BasePage
import utils
FETCH_LIMIT = 50
class Sheriffs(db.Model):
"""Contains the list of Sheriffs"""
username = db.StringProperty(required=True)
@classmethod
def get_all_sheriffs(cls):
return cls.all().fetch(limit=FETCH_LIMIT)
class SheriffSchedules(db.Model):
"""Sheriffs and their schedules."""
schedule_start = db.DateTimeProperty(required=True)
schedule_end = db.DateTimeProperty(required=True)
username = db.StringProperty(required=True)
@classmethod
def get_upcoming_schedules(cls):
return (cls.all()
.filter('schedule_end >', datetime.datetime.now())
.order('schedule_end')
.fetch(limit=FETCH_LIMIT))
@classmethod
def get_current_sheriff(cls):
current_schedule = cls.all().filter(
'schedule_end >', datetime.datetime.now()).get()
if current_schedule:
return current_schedule.username
else:
return 'None'
@classmethod
def delete_schedules_after(cls, datetime_obj):
schedules = cls.all().filter(
'schedule_end >', datetime_obj).fetch(limit=FETCH_LIMIT)
for schedule in schedules:
schedule.delete()
def AsDict(self):
data = super(SheriffSchedules, self).AsDict()
data['username'] = self.username
data['schedule_start'] = self.schedule_start.strftime('%m/%d')
data['schedule_end'] = self.schedule_end.strftime('%m/%d')
return data
class CurrentSheriffPage(BasePage):
"""Displays the current sheriff and schedule in JSON."""
def get(self):
self.response.headers['Content-Type'] = 'application/json'
self.response.headers['Access-Control-Allow-Origin'] = '*'
upcoming_schedules = SheriffSchedules.get_upcoming_schedules()
if upcoming_schedules:
data = json.dumps(upcoming_schedules[0].AsDict())
else:
data = json.dumps({})
callback = self.request.get('callback')
if callback:
data = callback + '(' + data + ')'
self.response.headers['Content-Type'] = 'application/json'
self.response.out.write(data)
class SheriffPage(BasePage):
"""Displays the list and rotation schedule of all sheriffs."""
@utils.require_user
def get(self):
return self._handle()
def _handle(self, error_message='', last_message=''):
"""Sets the information to be displayed on the main page."""
template_values = self.InitializeTemplate(
self.APP_NAME + ' Sheriff Rotation Schedule')
upcoming_schedules = []
for upcoming_schedule in SheriffSchedules.get_upcoming_schedules():
schedule_start = upcoming_schedule.schedule_start
schedule_end = upcoming_schedule.schedule_end
upcoming_schedule.readable_range = '%s - %s' % (
schedule_start.strftime('%d %B'), schedule_end.strftime('%d %B'))
upcoming_schedules.append(upcoming_schedule)
if upcoming_schedules:
# The first in the list is the current week.
upcoming_schedules[0].current_week = True
# Set the schedules to the template
template_values['schedules'] = upcoming_schedules
self.DisplayTemplate('sheriffs.html', template_values)
class update_sheriffs_schedule(BasePage):
"""update_sheriffs_schedule - Sets the sheriff schedule.
Usage:
update_sheriffs_schedules?schedule_start=3/11/2013&weeks=10
The above will populate the schedule for 10 weeks starting on March 11th using
all the sheriffs in a round robin manner from the Sheriffs table.
"""
@utils.admin_only
@utils.require_user
def get(self):
return self._handle()
def _handle(self, error_message='', last_message=''):
"""Sets the information to be displayed on the main page."""
# Read the schedule_start and weeks URL get parameters.
schedule_start_tokens = self.request.get('schedule_start').split('/')
schedule_start = datetime.datetime(int(schedule_start_tokens[2]),
int(schedule_start_tokens[0]),
int(schedule_start_tokens[1]))
weeks = int(self.request.get('weeks'))
# Get the list of sheriffs from the Sheriffs table.
sheriffs = []
for sheriff in Sheriffs.get_all_sheriffs():
sheriffs.append(sheriff.username)
# Delete all entries greater than the specified start time.
SheriffSchedules.delete_schedules_after(schedule_start)
# Populate the specified weeks with the sheriffs.
sheriffs_index = 0
while weeks > 0:
curr_schedule_end = schedule_start + datetime.timedelta(days=6)
SheriffSchedules(
schedule_start=schedule_start,
schedule_end=curr_schedule_end,
username=sheriffs[sheriffs_index]).put()
# Treat sheriffs like a circular array.
sheriffs_index = (sheriffs_index + 1) % len(sheriffs)
# Get the new schedule_start datetime.
schedule_start = schedule_start + datetime.timedelta(days=7)
# Decrement the number of weeks left to be filled.
weeks -= 1
def bootstrap():
# Guarantee that at least one instance exists.
if db.GqlQuery('SELECT __key__ FROM Sheriffs').get() is None:
Sheriffs(username='None').put()
if db.GqlQuery('SELECT __key__ FROM SheriffSchedules').get() is None:
SheriffSchedules(
schedule_start=datetime.datetime(1970, 1, 1),
schedule_end=datetime.datetime(1970, 1, 7),
username='None').put()