Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 608 lines (554 sloc) 27.862 kB
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
1 import cgi
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
2 from google.appengine.ext import webapp, db
3 from google.appengine.ext.webapp import util, template
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
4 from google.appengine.api import urlfetch, memcache, users, mail
5
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
6 from django.utils import simplejson
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
7 from django.template.defaultfilters import slugify
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
8 from icalendar import Calendar, Event as CalendarEvent
b4ea292 Handler to bug pending events
Brian Klug authored
9 import logging, urllib, os
7bdb866 Let all members staff events.
Brian Klug authored
10 from pprint import pprint
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
11 from datetime import datetime, timedelta
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
12
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
13 from models import Event, Feedback, HDLog, ROOM_OPTIONS, PENDING_LIFETIME
c97598b @dustball Room Conflict Detection
dustball authored
14 from utils import username, human_username, set_cookie, local_today, is_phone_valid, UserRights, dojo
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
15 from notices import *
7742592 @progrium start of maintaining form state on errors
progrium authored
16
9f06c39 @casey Added RSS for upcoming events.
casey authored
17 import PyRSS2Gen
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
18 import re
7787223 restored an inscrutible but necessary pytz tzinfo quirk to the start/…
Stig Hackvan authored
19 import pytz
9f06c39 @casey Added RSS for upcoming events.
casey authored
20
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
21 webapp.template.register_template_library('templatefilters')
22
9f06c39 @casey Added RSS for upcoming events.
casey authored
23 def event_path(event):
24 return '/event/%s-%s' % (event.key().id(), slugify(event.name))
25
219203b @dustball Cache better
dustball authored
26 class DomainCacheCron(webapp.RequestHandler):
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
27 def post(self):
219203b @dustball Cache better
dustball authored
28 noop = dojo('/groups/events',force=True)
29
30
f49797a @dustball Reminders 2.0
dustball authored
31 class ReminderCron(webapp.RequestHandler):
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
32 def post(self):
f49797a @dustball Reminders 2.0
dustball authored
33 self.response.out.write("REMINDERS")
34 today = local_today()
35 # remind everyone 3 days in advance they need to show up
36 events = Event.all() \
37 .filter('status IN', ['approved']) \
38 .filter('reminded =', False) \
39 .filter('start_time <', today + timedelta(days=3))
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
40 for event in events:
f49797a @dustball Reminders 2.0
dustball authored
41 self.response.out.write(event.name)
42 # only mail them if they created the event 2+ days ago
43 if event.created < today - timedelta(days=2):
44 schedule_reminder_email(event)
45 event.reminded = True
46 event.put()
47
48
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
49 class ExpireCron(webapp.RequestHandler):
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
50 def post(self):
51 # Expire events marked to expire today
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
52 today = local_today()
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
53 events = Event.all() \
54 .filter('status IN', ['pending', 'understaffed']) \
55 .filter('expired >=', today) \
56 .filter('expired <', today + timedelta(days=1))
57 for event in events:
58 event.expire()
59 notify_owner_expired(event)
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
60
f1997e4 @christopherb Made misc style fixes
christopherb authored
61
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
62 class ExpireReminderCron(webapp.RequestHandler):
63 def post(self):
64 # Find events expiring in 10 days to warn owner
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
65 ten_days = local_today() + timedelta(days=10)
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
66 events = Event.all() \
67 .filter('status IN', ['pending', 'understaffed']) \
68 .filter('expired >=', ten_days) \
69 .filter('expired <', ten_days + timedelta(days=1))
70 for event in events:
71 notify_owner_expiring(event)
72
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
73 class ExportHandler(webapp.RequestHandler):
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
74 def get(self, format):
9c331d0 @progrium refactoring the export handler a bit
progrium authored
75 content_type, body = getattr(self, 'export_%s' % format)()
76 self.response.headers['content-type'] = content_type
77 self.response.out.write(body)
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
78
9c331d0 @progrium refactoring the export handler a bit
progrium authored
79 def export_json(self):
20a578c @dustball Reasonable limits
dustball authored
80 events = Event.get_recent_past_and_future()
9c331d0 @progrium refactoring the export handler a bit
progrium authored
81 for k in self.request.GET:
82 if self.request.GET[k] and k in ['member']:
83 value = users.User(urllib.unquote(self.request.GET[k]))
84 else:
85 value = urllib.unquote(self.request.GET[k])
86 events = events.filter('%s =' % k, value)
87 events = map(lambda x: x.to_dict(summarize=True), events)
88 return 'application/json', simplejson.dumps(events)
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
89
9c331d0 @progrium refactoring the export handler a bit
progrium authored
90 def export_ics(self):
20a578c @dustball Reasonable limits
dustball authored
91 events = Event.get_recent_past_and_future()
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
92 url_base = 'http://' + self.request.headers.get('host', 'events.hackerdojo.com')
9c331d0 @progrium refactoring the export handler a bit
progrium authored
93 cal = Calendar()
94 for event in events:
95 iev = CalendarEvent()
96 iev.add('summary', event.name if event.status == 'approved' else event.name + ' (%s)' % event.status.upper())
97 # make verbose description with empty fields where information is missing
98 ev_desc = '__Status: %s\n__Member: %s\n__Type: %s\n__Estimated size: %s\n__Info URL: %s\n__Fee: %s\n__Contact: %s, %s\n__Rooms: %s\n\n__Details: %s\n\n__Notes: %s' % (
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
99 event.status,
100 event.owner(),
101 event.type,
102 event.estimated_size,
103 event.url,
104 event.fee,
105 event.contact_name,
106 event.contact_phone,
107 event.roomlist(),
108 event.details,
9c331d0 @progrium refactoring the export handler a bit
progrium authored
109 event.notes)
110 # then delete the empty fields with a regex
111 ev_desc = re.sub(re.compile(r'^__.*?:[ ,]*$\n*',re.M),'',ev_desc)
112 ev_desc = re.sub(re.compile(r'^__',re.M),'',ev_desc)
113 ev_url = url_base + event_path(event)
114 iev.add('description', ev_desc + '\n--\n' + ev_url)
115 iev.add('url', ev_url)
116 if event.start_time:
117 iev.add('dtstart', event.start_time.replace(tzinfo=pytz.timezone('US/Pacific')))
118 if event.end_time:
119 iev.add('dtend', event.end_time.replace(tzinfo=pytz.timezone('US/Pacific')))
120 cal.add_component(iev)
121 return 'text/calendar', cal.as_string()
85d17af @dustball "Large Events" page and iCal feed
dustball authored
122
123 def export_large_ics(self):
20a578c @dustball Reasonable limits
dustball authored
124 events = Event.get_recent_past_and_future()
85d17af @dustball "Large Events" page and iCal feed
dustball authored
125 url_base = 'http://' + self.request.headers.get('host', 'events.hackerdojo.com')
126 cal = Calendar()
127 for event in events:
128 iev = CalendarEvent()
129 iev.add('summary', event.name + ' (%s)' % event.estimated_size)
130 # make verbose description with empty fields where information is missing
131 ev_desc = '__Status: %s\n__Member: %s\n__Type: %s\n__Estimated size: %s\n__Info URL: %s\n__Fee: %s\n__Contact: %s, %s\n__Rooms: %s\n\n__Details: %s\n\n__Notes: %s' % (
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
132 event.status,
133 event.owner(),
134 event.type,
135 event.estimated_size,
136 event.url,
137 event.fee,
138 event.contact_name,
139 event.contact_phone,
140 event.roomlist(),
141 event.details,
85d17af @dustball "Large Events" page and iCal feed
dustball authored
142 event.notes)
143 # then delete the empty fields with a regex
144 ev_desc = re.sub(re.compile(r'^__.*?:[ ,]*$\n*',re.M),'',ev_desc)
145 ev_desc = re.sub(re.compile(r'^__',re.M),'',ev_desc)
146 ev_url = url_base + event_path(event)
147 iev.add('description', ev_desc + '\n--\n' + ev_url)
148 iev.add('url', ev_url)
149 if event.start_time:
150 iev.add('dtstart', event.start_time.replace(tzinfo=pytz.timezone('US/Pacific')))
151 if event.end_time:
152 iev.add('dtend', event.end_time.replace(tzinfo=pytz.timezone('US/Pacific')))
153 cal.add_component(iev)
154 return 'text/calendar', cal.as_string()
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
155
9c331d0 @progrium refactoring the export handler a bit
progrium authored
156 def export_rss(self):
157 url_base = 'http://' + self.request.headers.get('host', 'events.hackerdojo.com')
20a578c @dustball Reasonable limits
dustball authored
158 events = Event.get_recent_past_and_future()
9c331d0 @progrium refactoring the export handler a bit
progrium authored
159 rss = PyRSS2Gen.RSS2(
160 title = "Hacker Dojo Events Feed",
161 link = url_base,
162 description = "Upcoming events at the Hacker Dojo in Mountain View, CA",
163 lastBuildDate = datetime.now(),
164 items = [PyRSS2Gen.RSSItem(
15786c3 @mikeharris100 Include event date on RSS feed (Fixes #39)
mikeharris100 authored
165 title = "%s @ %s: %s" % (
166 event.start_time.strftime("%A, %B %d"),
167 event.start_time.strftime("%I:%M%p").lstrip("0"),
168 event.name),
9c331d0 @progrium refactoring the export handler a bit
progrium authored
169 link = url_base + event_path(event),
170 description = event.details,
171 guid = url_base + event_path(event),
172 pubDate = event.updated,
173 ) for event in events]
174 )
175 return 'application/xml', rss.to_xml()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
176
f1997e4 @christopherb Made misc style fixes
christopherb authored
177
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
178 class EditHandler(webapp.RequestHandler):
179 def get(self, id):
180 event = Event.get_by_id(int(id))
181 user = users.get_current_user()
736390e @dustball Bug fixes & UI
dustball authored
182 show_all_nav = user
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
183 access_rights = UserRights(user, event)
184 if access_rights.can_edit:
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
185 logout_url = users.create_logout_url('/')
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
186 rooms = ROOM_OPTIONS
187 hours = [1,2,3,4,5,6,7,8,9,10,11,12]
188 self.response.out.write(template.render('templates/edit.html', locals()))
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
189 else:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
190 self.response.out.write("Access denied")
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
191
192 def post(self, id):
193 event = Event.get_by_id(int(id))
194 user = users.get_current_user()
195 access_rights = UserRights(user, event)
196 if access_rights.can_edit:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
197 try:
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
198 start_time = datetime.strptime('%s %s:%s %s' % (
c6a3cce @mikeharris100 (For #12) Added basic ability to add/edit/view end *date* of an event
mikeharris100 authored
199 self.request.get('start_date'),
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
200 self.request.get('start_time_hour'),
201 self.request.get('start_time_minute'),
202 self.request.get('start_time_ampm')), '%m/%d/%Y %I:%M %p')
203 end_time = datetime.strptime('%s %s:%s %s' % (
c6a3cce @mikeharris100 (For #12) Added basic ability to add/edit/view end *date* of an event
mikeharris100 authored
204 self.request.get('end_date'),
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
205 self.request.get('end_time_hour'),
206 self.request.get('end_time_minute'),
207 self.request.get('end_time_ampm')), '%m/%d/%Y %I:%M %p')
20c252d @dustball Fix key/index bug
dustball authored
208 conflicts = Event.check_conflict(start_time,end_time,self.request.get_all('rooms'), int(id))
c97598b @dustball Room Conflict Detection
dustball authored
209 if conflicts:
81f76e6 @dustball Better error message for deck/savannah conflicts
dustball authored
210 if "Deck" in self.request.get_all('rooms') or "Savanna" in self.request.get_all('rooms'):
211 raise ValueError('Room conflict detected <small>(Note: Deck &amp; Savanna share the same area, two events cannot take place at the same time in these rooms.)</small>')
212 else:
213 raise ValueError('Room conflict detected')
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
214 if not self.request.get('estimated_size').isdigit():
215 raise ValueError('Estimated number of people must be a number')
216 if not int(self.request.get('estimated_size')) > 0:
217 raise ValueError('Estimated number of people must be greater then zero')
218 if ( self.request.get( 'contact_phone' ) and not is_phone_valid( self.request.get( 'contact_phone' ) ) ):
219 raise ValueError( 'Phone number does not appear to be valid' )
220 else:
b193624 much nicer event edit logs
jonathan authored
221 log_desc = "Event edited<br />"
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
222 previous_object = Event.get_by_id(int(id))
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
223 event.name = self.request.get('name')
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
224 if (previous_object.name != event.name):
a4f9ae7 changed my mind about the italics
jonathan authored
225 log_desc = log_desc + "<strong>Title:</strong> " + previous_object.name + " to " + event.name + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
226 event.start_time = start_time
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
227 if (previous_object.start_time != event.start_time):
a4f9ae7 changed my mind about the italics
jonathan authored
228 log_desc = log_desc + "<strong>Start time:</strong> " + str(previous_object.start_time) + " to " + str(event.start_time) + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
229 event.end_time = end_time
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
230 if (previous_object.end_time != event.end_time):
a4f9ae7 changed my mind about the italics
jonathan authored
231 log_desc = log_desc + "<strong>End time:</strong> " + str(previous_object.end_time) + " to " + str(event.end_time) + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
232 event.estimated_size = cgi.escape(self.request.get('estimated_size'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
233 if (previous_object.estimated_size != event.estimated_size):
a4f9ae7 changed my mind about the italics
jonathan authored
234 log_desc = log_desc + "<strong>Est. size:</strong> " + previous_object.estimated_size + " to " + event.estimated_size + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
235 event.contact_name = cgi.escape(self.request.get('contact_name'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
236 if (previous_object.contact_name != event.contact_name):
a4f9ae7 changed my mind about the italics
jonathan authored
237 log_desc = log_desc + "<strong>Contact:</strong> " + previous_object.contact_name + " to " + event.contact_name + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
238 event.contact_phone = cgi.escape(self.request.get('contact_phone'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
239 if (previous_object.contact_phone != event.contact_phone):
a4f9ae7 changed my mind about the italics
jonathan authored
240 log_desc = log_desc + "<strong>Contact phone:</strong> " + previous_object.contact_phone + " to " + event.contact_phone + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
241 event.details = cgi.escape(self.request.get('details'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
242 if (previous_object.details != event.details):
a4f9ae7 changed my mind about the italics
jonathan authored
243 log_desc = log_desc + "<strong>Details:</strong> " + previous_object.details + " to " + event.details + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
244 event.url = cgi.escape(self.request.get('url'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
245 if (previous_object.url != event.url):
a4f9ae7 changed my mind about the italics
jonathan authored
246 log_desc = log_desc + "<strong>Url:</strong> " + previous_object.url + " to " + event.url + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
247 event.fee = cgi.escape(self.request.get('fee'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
248 if (previous_object.fee != event.fee):
a4f9ae7 changed my mind about the italics
jonathan authored
249 log_desc = log_desc + "<strong>Fee:</strong> " + previous_object.fee + " to " + event.fee + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
250 event.notes = cgi.escape(self.request.get('notes'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
251 if (previous_object.notes != event.notes):
a4f9ae7 changed my mind about the italics
jonathan authored
252 log_desc = log_desc + "<strong>Notes:</strong> " + previous_object.notes + " to " + event.notes + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
253 event.rooms = self.request.get_all('rooms')
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
254 if (previous_object.rooms != event.rooms):
6199d1a issue 11 print this page for your record
jonathan authored
255 log_desc = log_desc + "<strong>Rooms changed</strong><br />"
f35ea58 patches requested to log
jonathan authored
256 log_desc = log_desc + "<strong>Old room:</strong> " + previous_object.roomlist() + "<br />"
257 log_desc = log_desc + "<strong>New room:</strong> " + event.roomlist() + "<br />"
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
258 event.put()
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
259 log = HDLog(event=event,description=log_desc)
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
260 log.put()
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
261 self.redirect(event_path(event))
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
262 except ValueError, e:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
263 error = str(e)
264 self.response.out.write(template.render('templates/error.html', locals()))
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
265 else:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
266 self.response.out.write("Access denied")
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
267
268
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
269 class EventHandler(webapp.RequestHandler):
270 def get(self, id):
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
271
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
272 event = Event.get_by_id(int(id))
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
273 if self.request.path.endswith('json'):
274 self.response.headers['content-type'] = 'application/json'
275 self.response.out.write(simplejson.dumps(event.to_dict()))
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
276 else:
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
277 user = users.get_current_user()
278 if user:
766e87c @christopherb Added UserRights class.
christopherb authored
279 access_rights = UserRights(user, event)
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
280 logout_url = users.create_logout_url('/')
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
281
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
282 else:
283 login_url = users.create_login_url('/')
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
284 event.details = db.Text(event.details.replace('\n','<br/>'))
736390e @dustball Bug fixes & UI
dustball authored
285 show_all_nav = user
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
286 event.notes = db.Text(event.notes.replace('\n','<br/>'))
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
287 self.response.out.write(template.render('templates/event.html', locals()))
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
288
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
289 def post(self, id):
290 event = Event.get_by_id(int(id))
291 user = users.get_current_user()
766e87c @christopherb Added UserRights class.
christopherb authored
292 access_rights = UserRights(user, event)
293
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
294 state = self.request.get('state')
295 if state:
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
296 desc = ''
766e87c @christopherb Added UserRights class.
christopherb authored
297 if state.lower() == 'approve' and access_rights.can_approve:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
298 event.approve()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
299 desc = 'Approved event'
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
300 if state.lower() == 'notapproved' and access_rights.can_not_approve:
301 event.not_approved()
302 desc = 'Event marked not approved'
5ef05d9 @dustball RSVP system
dustball authored
303 if state.lower() == 'rsvp' and user:
304 event.rsvp()
134bb40 @dustball New RSVP e-mail and fix issue #35
dustball authored
305 notify_owner_rsvp(event,user)
b84b533 @dustball Fix one more staff logic bomb
dustball authored
306 if state.lower() == 'staff' and access_rights.can_staff:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
307 event.add_staff(user)
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
308 desc = 'Added self as staff'
766e87c @christopherb Added UserRights class.
christopherb authored
309 if state.lower() == 'unstaff' and access_rights.can_unstaff:
72849c2 @billsaysthis added unstaff event, including email notification if event becomes un…
billsaysthis authored
310 event.remove_staff(user)
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
311 desc = 'Removed self as staff'
f8ffd89 @billsaysthis refactor lists to use singe event partial, adds contact email link in…
billsaysthis authored
312 if state.lower() == 'onhold' and access_rights.can_cancel:
313 event.on_hold()
314 desc = 'Put event on hold'
766e87c @christopherb Added UserRights class.
christopherb authored
315 if state.lower() == 'cancel' and access_rights.can_cancel:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
316 event.cancel()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
317 desc = 'Cancelled event'
766e87c @christopherb Added UserRights class.
christopherb authored
318 if state.lower() == 'delete' and access_rights.is_admin:
a67ac50 @mdhancher Add a simple admin-only event delete and undelete.
mdhancher authored
319 event.delete()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
320 desc = 'Deleted event'
766e87c @christopherb Added UserRights class.
christopherb authored
321 if state.lower() == 'undelete' and access_rights.is_admin:
a67ac50 @mdhancher Add a simple admin-only event delete and undelete.
mdhancher authored
322 event.undelete()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
323 desc = 'Undeleted event'
766e87c @christopherb Added UserRights class.
christopherb authored
324 if state.lower() == 'expire' and access_rights.is_admin:
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
325 event.expire()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
326 desc = 'Expired event'
134bb40 @dustball New RSVP e-mail and fix issue #35
dustball authored
327 if event.status == 'approved' and state.lower() == 'approve':
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
328 notify_owner_approved(event)
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
329 if desc != '':
330 log = HDLog(event=event,description=desc)
331 log.put()
9f06c39 @casey Added RSS for upcoming events.
casey authored
332 self.redirect(event_path(event))
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
333
f1997e4 @christopherb Made misc style fixes
christopherb authored
334
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
335 class ApprovedHandler(webapp.RequestHandler):
336 def get(self):
337 user = users.get_current_user()
338 if user:
339 logout_url = users.create_logout_url('/')
340 else:
341 login_url = users.create_login_url('/')
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
342 today = local_today()
736390e @dustball Bug fixes & UI
dustball authored
343 show_all_nav = user
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
344 events = Event.get_approved_list()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
345 tomorrow = today + timedelta(days=1)
d63161a Add widget mode
Brian Klug authored
346 whichbase = 'base.html'
347 if self.request.get('base'):
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
348 whichbase = self.request.get('base') + '.html'
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
349 self.response.out.write(template.render('templates/approved.html', locals()))
350
f1997e4 @christopherb Made misc style fixes
christopherb authored
351
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
352 class MyEventsHandler(webapp.RequestHandler):
353 @util.login_required
354 def get(self):
355 user = users.get_current_user()
356 if user:
357 logout_url = users.create_logout_url('/')
358 else:
359 login_url = users.create_login_url('/')
360 events = Event.all().filter('member = ', user).order('start_time')
736390e @dustball Bug fixes & UI
dustball authored
361 show_all_nav = user
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
362 today = local_today()
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
363 tomorrow = today + timedelta(days=1)
364 self.response.out.write(template.render('templates/myevents.html', locals()))
365
f1997e4 @christopherb Made misc style fixes
christopherb authored
366
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
367 class PastHandler(webapp.RequestHandler):
368 def get(self):
369 user = users.get_current_user()
370 if user:
371 logout_url = users.create_logout_url('/')
372 else:
373 login_url = users.create_login_url('/')
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
374 today = local_today()
736390e @dustball Bug fixes & UI
dustball authored
375 show_all_nav = user
d75579f @progrium minor updates here and there to bills contributions.
progrium authored
376 events = Event.all().filter('start_time < ', today).order('-start_time')
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
377 self.response.out.write(template.render('templates/past.html', locals()))
378
f1997e4 @christopherb Made misc style fixes
christopherb authored
379
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
380 class NotApprovedHandler(webapp.RequestHandler):
381 def get(self):
382 user = users.get_current_user()
383 if user:
384 logout_url = users.create_logout_url('/')
385 else:
386 login_url = users.create_login_url('/')
387 today = local_today()
388 show_all_nav = user
389 events = Event.get_recent_not_approved_list()
390 self.response.out.write(template.render('templates/not_approved.html', locals()))
391
392
b4ea292 Handler to bug pending events
Brian Klug authored
393 class CronBugOwnersHandler(webapp.RequestHandler):
394 def get(self):
395 events = Event.get_pending_list()
396 for e in events:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
397 bug_owner_pending(e)
398
399
400 class AllFutureHandler(webapp.RequestHandler):
401 def get(self):
402 user = users.get_current_user()
403 if user:
404 logout_url = users.create_logout_url('/')
405 else:
406 login_url = users.create_login_url('/')
736390e @dustball Bug fixes & UI
dustball authored
407 show_all_nav = user
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
408 events = Event.get_all_future_list()
409 today = local_today()
410 tomorrow = today + timedelta(days=1)
411 self.response.out.write(template.render('templates/all_future.html', locals()))
b4ea292 Handler to bug pending events
Brian Klug authored
412
85d17af @dustball "Large Events" page and iCal feed
dustball authored
413 class LargeHandler(webapp.RequestHandler):
414 def get(self):
415 user = users.get_current_user()
416 if user:
417 logout_url = users.create_logout_url('/')
418 else:
419 login_url = users.create_login_url('/')
420 show_all_nav = user
421 events = Event.get_large_list()
422 today = local_today()
423 tomorrow = today + timedelta(days=1)
424 self.response.out.write(template.render('templates/large.html', locals()))
425
f1997e4 @christopherb Made misc style fixes
christopherb authored
426
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
427 class PendingHandler(webapp.RequestHandler):
428 def get(self):
429 user = users.get_current_user()
430 if user:
431 logout_url = users.create_logout_url('/')
432 else:
433 login_url = users.create_login_url('/')
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
434 events = Event.get_pending_list()
736390e @dustball Bug fixes & UI
dustball authored
435 show_all_nav = user
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
436 today = local_today()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
437 tomorrow = today + timedelta(days=1)
438 self.response.out.write(template.render('templates/pending.html', locals()))
439
f1997e4 @christopherb Made misc style fixes
christopherb authored
440
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
441 class NewHandler(webapp.RequestHandler):
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
442 @util.login_required
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
443 def get(self):
444 user = users.get_current_user()
4d85afa @dustball Remove staffing requirement and make members more responsible
dustball authored
445 human = human_username(user)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
446 if user:
447 logout_url = users.create_logout_url('/')
448 else:
449 login_url = users.create_login_url('/')
450 rooms = ROOM_OPTIONS
cb7a9d1 pull in the rules live and memcache them for 1 day on new and confirm…
jonathan authored
451 rules = memcache.get("rules")
452 if(rules is None):
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
453 rules = urlfetch.fetch("http://wiki.hackerdojo.com/api_v2/op/GetPage/page/Event+Policies/_type/html", "GET").content
cb7a9d1 pull in the rules live and memcache them for 1 day on new and confirm…
jonathan authored
454 memcache.add("rules", rules, 86400)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
455 self.response.out.write(template.render('templates/new.html', locals()))
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
456
f1997e4 @christopherb Made misc style fixes
christopherb authored
457
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
458 def post(self):
459 user = users.get_current_user()
7742592 @progrium start of maintaining form state on errors
progrium authored
460 try:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
461 start_time = datetime.strptime('%s %s:%s %s' % (
c6a3cce @mikeharris100 (For #12) Added basic ability to add/edit/view end *date* of an event
mikeharris100 authored
462 self.request.get('start_date'),
7742592 @progrium start of maintaining form state on errors
progrium authored
463 self.request.get('start_time_hour'),
464 self.request.get('start_time_minute'),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
465 self.request.get('start_time_ampm')), '%m/%d/%Y %I:%M %p')
466 end_time = datetime.strptime('%s %s:%s %s' % (
c6a3cce @mikeharris100 (For #12) Added basic ability to add/edit/view end *date* of an event
mikeharris100 authored
467 self.request.get('end_date'),
7742592 @progrium start of maintaining form state on errors
progrium authored
468 self.request.get('end_time_hour'),
469 self.request.get('end_time_minute'),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
470 self.request.get('end_time_ampm')), '%m/%d/%Y %I:%M %p')
c97598b @dustball Room Conflict Detection
dustball authored
471 conflicts = Event.check_conflict(start_time,end_time,self.request.get_all('rooms'))
472 if conflicts:
81f76e6 @dustball Better error message for deck/savannah conflicts
dustball authored
473 if "Deck" in self.request.get_all('rooms') or "Savanna" in self.request.get_all('rooms'):
474 raise ValueError('Room conflict detected <small>(Note: Deck &amp; Savanna share the same area, two events cannot take place at the same time in these rooms.)</small>')
475 else:
476 raise ValueError('Room conflict detected')
8615877 Fix validation for event size
Brian Klug authored
477 if not self.request.get('estimated_size').isdigit():
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
478 raise ValueError('Estimated number of people must be a number')
8615877 Fix validation for event size
Brian Klug authored
479 if not int(self.request.get('estimated_size')) > 0:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
480 raise ValueError('Estimated number of people must be greater then zero')
7742592 @progrium start of maintaining form state on errors
progrium authored
481 if (end_time-start_time).days < 0:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
482 raise ValueError('End time must be after start time')
a244c65 @dustball Bug fixes
dustball authored
483 if ( self.request.get( 'contact_phone' ) and not is_phone_valid( self.request.get( 'contact_phone' ) ) ):
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
484 raise ValueError( 'Phone number does not appear to be valid' )
7742592 @progrium start of maintaining form state on errors
progrium authored
485 else:
486 event = Event(
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
487 name = cgi.escape(self.request.get('name')),
7742592 @progrium start of maintaining form state on errors
progrium authored
488 start_time = start_time,
489 end_time = end_time,
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
490 type = cgi.escape(self.request.get('type')),
491 estimated_size = cgi.escape(self.request.get('estimated_size')),
492 contact_name = cgi.escape(self.request.get('contact_name')),
493 contact_phone = cgi.escape(self.request.get('contact_phone')),
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
494 details = cgi.escape(self.request.get('details')),
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
495 url = cgi.escape(self.request.get('url')),
496 fee = cgi.escape(self.request.get('fee')),
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
497 notes = cgi.escape(self.request.get('notes')),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
498 rooms = self.request.get_all('rooms'),
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
499 expired = local_today() + timedelta(days=PENDING_LIFETIME), # Set expected expiration date
7742592 @progrium start of maintaining form state on errors
progrium authored
500 )
501 event.put()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
502 log = HDLog(event=event,description="Created new event")
503 log.put()
7742592 @progrium start of maintaining form state on errors
progrium authored
504 notify_owner_confirmation(event)
505 notify_new_event(event)
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
506 set_cookie(self.response.headers, 'formvalues', None)
87868cf issue 11 add a confirmation page
jonathan authored
507 #self.redirect('/event/%s-%s' % (event.key().id(), slugify(event.name)))
508 self.redirect('/confirm/%s-%s' % (event.key().id(), slugify(event.name)))
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
509
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
510 except Exception, e:
511 message = str(e)
512 if 'match format' in message:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
513 message = 'Date is required.'
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
514 if message.startswith('Property'):
515 message = message[9:].replace('_', ' ').capitalize()
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
516 # This is NOT a reliable way to handle erorrs
517 #set_cookie(self.response.headers, 'formerror', message)
518 #set_cookie(self.response.headers, 'formvalues', dict(self.request.POST))
519 #self.redirect('/new')
520 error = message
521 self.response.out.write(template.render('templates/error.html', locals()))
87868cf issue 11 add a confirmation page
jonathan authored
522
523 class ConfirmationHandler(webapp.RequestHandler):
524 def get(self, id):
525 event = Event.get_by_id(int(id))
cb7a9d1 pull in the rules live and memcache them for 1 day on new and confirm…
jonathan authored
526 rules = memcache.get("rules")
527 if(rules is None):
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
528 rules = urlfetch.fetch("http://wiki.hackerdojo.com/api_v2/op/GetPage/page/Event+Policies/_type/html", "GET").content
cb7a9d1 pull in the rules live and memcache them for 1 day on new and confirm…
jonathan authored
529 memcache.add("rules", rules, 86400)
b47158d Issue 36 Need to use deffered mail sends everywhere
Abraham Erki authored
530 user = users.get_current_user()
531 logout_url = users.create_logout_url('/')
87868cf issue 11 add a confirmation page
jonathan authored
532 self.response.out.write(template.render('templates/confirmation.html', locals()))
533
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
534 class LogsHandler(webapp.RequestHandler):
535 @util.login_required
536 def get(self):
537 user = users.get_current_user()
538 logs = HDLog.get_logs_list()
539 if user:
540 logout_url = users.create_logout_url('/')
541 else:
542 login_url = users.create_login_url('/')
736390e @dustball Bug fixes & UI
dustball authored
543 show_all_nav = user
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
544 self.response.out.write(template.render('templates/logs.html', locals()))
545
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
546 class FeedbackHandler(webapp.RequestHandler):
547 @util.login_required
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
548 def get(self, id):
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
549 user = users.get_current_user()
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
550 event = Event.get_by_id(int(id))
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
551 if user:
552 logout_url = users.create_logout_url('/')
553 else:
554 login_url = users.create_login_url('/')
555 self.response.out.write(template.render('templates/feedback.html', locals()))
556
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
557 def post(self, id):
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
558 user = users.get_current_user()
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
559 event = Event.get_by_id(int(id))
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
560 try:
561 if self.request.get('rating'):
562 feedback = Feedback(
563 event = event,
564 rating = int(self.request.get('rating')),
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
565 comment = cgi.escape(self.request.get('comment')))
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
566 feedback.put()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
567 log = HDLog(event=event,description="Posted feedback")
568 log.put()
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
569 self.redirect('/event/%s-%s' % (event.key().id(), slugify(event.name)))
570 else:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
571 raise ValueError('Please select a rating')
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
572 except Exception:
573 set_cookie(self.response.headers, 'formvalues', dict(self.request.POST))
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
574 self.redirect('/feedback/new/' + id)
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
575
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
576 def main():
577 application = webapp.WSGIApplication([
578 ('/', ApprovedHandler),
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
579 ('/all_future', AllFutureHandler),
85d17af @dustball "Large Events" page and iCal feed
dustball authored
580 ('/large', LargeHandler),
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
581 ('/pending', PendingHandler),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
582 ('/past', PastHandler),
b4ea292 Handler to bug pending events
Brian Klug authored
583 ('/cronbugowners', CronBugOwnersHandler),
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
584 ('/myevents', MyEventsHandler),
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
585 ('/not_approved', NotApprovedHandler),
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
586 ('/new', NewHandler),
87868cf issue 11 add a confirmation page
jonathan authored
587 ('/confirm/(\d+).*', ConfirmationHandler),
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
588 ('/edit/(\d+).*', EditHandler),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
589 # single event views
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
590 ('/event/(\d+).*', EventHandler),
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
591 ('/event/(\d+)\.json', EventHandler),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
592 # various export methods -- events.{json,rss,ics}
593 ('/events\.(.+)', ExportHandler),
594 #
595 # CRON tasks
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
596 ('/expire', ExpireCron),
34d98f0 @billsaysthis moved feedback stuff to separate py file, small tweak to email notifi…
billsaysthis authored
597 ('/expiring', ExpireReminderCron),
5459516 @billsaysthis [#40] add not approved status and list view
billsaysthis authored
598 ('/domaincache', DomainCacheCron),
f49797a @dustball Reminders 2.0
dustball authored
599 ('/reminder', ReminderCron),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
600 #
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
601 ('/logs', LogsHandler),
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
602 ('/feedback/new/(\d+).*', FeedbackHandler) ],debug=True)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
603 util.run_wsgi_app(application)
604
f1997e4 @christopherb Made misc style fixes
christopherb authored
605
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
606 if __name__ == '__main__':
607 main()
Something went wrong with that request. Please try again.