Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 579 lines (527 sloc) 26.303 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):
27 def post(self):
28 noop = dojo('/groups/events',force=True)
29
30
f49797a @dustball Reminders 2.0
dustball authored
31 class ReminderCron(webapp.RequestHandler):
32 def post(self):
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))
40 for event in events:
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)
f49797a @dustball Reminders 2.0
dustball 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)
78
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)
89
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' % (
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,
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' % (
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,
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()
9c331d0 @progrium refactoring the export handler a bit
progrium authored
155
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(
165 title = event.name,
166 link = url_base + event_path(event),
167 description = event.details,
168 guid = url_base + event_path(event),
169 pubDate = event.updated,
170 ) for event in events]
171 )
172 return 'application/xml', rss.to_xml()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
173
f1997e4 @christopherb Made misc style fixes
christopherb authored
174
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
175 class EditHandler(webapp.RequestHandler):
176 def get(self, id):
177 event = Event.get_by_id(int(id))
178 user = users.get_current_user()
736390e @dustball Bug fixes & UI
dustball authored
179 show_all_nav = user
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
180 access_rights = UserRights(user, event)
181 if access_rights.can_edit:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
182 logout_url = users.create_logout_url('/')
183 rooms = ROOM_OPTIONS
184 hours = [1,2,3,4,5,6,7,8,9,10,11,12]
185 self.response.out.write(template.render('templates/edit.html', locals()))
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
186 else:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
187 self.response.out.write("Access denied")
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
188
189 def post(self, id):
190 event = Event.get_by_id(int(id))
191 user = users.get_current_user()
192 access_rights = UserRights(user, event)
193 if access_rights.can_edit:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
194 try:
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
195 start_time = datetime.strptime('%s %s:%s %s' % (
196 self.request.get('date'),
197 self.request.get('start_time_hour'),
198 self.request.get('start_time_minute'),
199 self.request.get('start_time_ampm')), '%m/%d/%Y %I:%M %p')
200 end_time = datetime.strptime('%s %s:%s %s' % (
201 self.request.get('date'),
202 self.request.get('end_time_hour'),
203 self.request.get('end_time_minute'),
204 self.request.get('end_time_ampm')), '%m/%d/%Y %I:%M %p')
20c252d @dustball Fix key/index bug
dustball authored
205 conflicts = Event.check_conflict(start_time,end_time,self.request.get_all('rooms'), int(id))
c97598b @dustball Room Conflict Detection
dustball authored
206 if conflicts:
207 raise ValueError('Room conflict detected')
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
208 if not self.request.get('estimated_size').isdigit():
209 raise ValueError('Estimated number of people must be a number')
210 if not int(self.request.get('estimated_size')) > 0:
211 raise ValueError('Estimated number of people must be greater then zero')
212 if ( self.request.get( 'contact_phone' ) and not is_phone_valid( self.request.get( 'contact_phone' ) ) ):
213 raise ValueError( 'Phone number does not appear to be valid' )
214 else:
b193624 much nicer event edit logs
jonathan authored
215 log_desc = "Event edited<br />"
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
216 previous_object = Event.get_by_id(int(id))
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
217 event.name = self.request.get('name')
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
218 if (previous_object.name != event.name):
a4f9ae7 changed my mind about the italics
jonathan authored
219 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
220 event.start_time = start_time
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
221 if (previous_object.start_time != event.start_time):
a4f9ae7 changed my mind about the italics
jonathan authored
222 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
223 event.end_time = end_time
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
224 if (previous_object.end_time != event.end_time):
a4f9ae7 changed my mind about the italics
jonathan authored
225 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
226 event.estimated_size = cgi.escape(self.request.get('estimated_size'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
227 if (previous_object.estimated_size != event.estimated_size):
a4f9ae7 changed my mind about the italics
jonathan authored
228 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
229 event.contact_name = cgi.escape(self.request.get('contact_name'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
230 if (previous_object.contact_name != event.contact_name):
a4f9ae7 changed my mind about the italics
jonathan authored
231 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
232 event.contact_phone = cgi.escape(self.request.get('contact_phone'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
233 if (previous_object.contact_phone != event.contact_phone):
a4f9ae7 changed my mind about the italics
jonathan authored
234 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
235 event.details = cgi.escape(self.request.get('details'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
236 if (previous_object.details != event.details):
a4f9ae7 changed my mind about the italics
jonathan authored
237 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
238 event.url = cgi.escape(self.request.get('url'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
239 if (previous_object.url != event.url):
a4f9ae7 changed my mind about the italics
jonathan authored
240 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
241 event.fee = cgi.escape(self.request.get('fee'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
242 if (previous_object.fee != event.fee):
a4f9ae7 changed my mind about the italics
jonathan authored
243 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
244 event.notes = cgi.escape(self.request.get('notes'))
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
245 if (previous_object.notes != event.notes):
a4f9ae7 changed my mind about the italics
jonathan authored
246 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
247 event.rooms = self.request.get_all('rooms')
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
248 if (previous_object.rooms != event.rooms):
6199d1a issue 11 print this page for your record
jonathan authored
249 log_desc = log_desc + "<strong>Rooms changed</strong><br />"
f35ea58 patches requested to log
jonathan authored
250 log_desc = log_desc + "<strong>Old room:</strong> " + previous_object.roomlist() + "<br />"
251 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
252 event.put()
8aa7c21 patch edit screen.. changed datepicker formatting to be cohesive.. fi…
jonathan authored
253 log = HDLog(event=event,description=log_desc)
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
254 log.put()
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
255 self.redirect(event_path(event))
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
256 except ValueError, e:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
257 error = str(e)
258 self.response.out.write(template.render('templates/error.html', locals()))
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
259 else:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
260 self.response.out.write("Access denied")
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
261
262
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
263 class EventHandler(webapp.RequestHandler):
264 def get(self, id):
5ef05d9 @dustball RSVP system
dustball authored
265
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
266 event = Event.get_by_id(int(id))
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
267 if self.request.path.endswith('json'):
268 self.response.headers['content-type'] = 'application/json'
269 self.response.out.write(simplejson.dumps(event.to_dict()))
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
270 else:
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
271 user = users.get_current_user()
272 if user:
766e87c @christopherb Added UserRights class.
christopherb authored
273 access_rights = UserRights(user, event)
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
274 logout_url = users.create_logout_url('/')
766e87c @christopherb Added UserRights class.
christopherb authored
275
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
276 else:
277 login_url = users.create_login_url('/')
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
278 event.details = db.Text(event.details.replace('\n','<br/>'))
736390e @dustball Bug fixes & UI
dustball authored
279 show_all_nav = user
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
280 event.notes = db.Text(event.notes.replace('\n','<br/>'))
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
281 self.response.out.write(template.render('templates/event.html', locals()))
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
282
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
283 def post(self, id):
284 event = Event.get_by_id(int(id))
285 user = users.get_current_user()
766e87c @christopherb Added UserRights class.
christopherb authored
286 access_rights = UserRights(user, event)
287
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
288 state = self.request.get('state')
289 if state:
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
290 desc = ''
766e87c @christopherb Added UserRights class.
christopherb authored
291 if state.lower() == 'approve' and access_rights.can_approve:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
292 event.approve()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
293 desc = 'Approved event'
5ef05d9 @dustball RSVP system
dustball authored
294 if state.lower() == 'rsvp' and user:
295 event.rsvp()
b84b533 @dustball Fix one more staff logic bomb
dustball authored
296 if state.lower() == 'staff' and access_rights.can_staff:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
297 event.add_staff(user)
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
298 desc = 'Added self as staff'
766e87c @christopherb Added UserRights class.
christopherb authored
299 if state.lower() == 'unstaff' and access_rights.can_unstaff:
72849c2 @billsaysthis added unstaff event, including email notification if event becomes un…
billsaysthis authored
300 event.remove_staff(user)
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
301 desc = 'Removed self as staff'
f8ffd89 @billsaysthis refactor lists to use singe event partial, adds contact email link in…
billsaysthis authored
302 if state.lower() == 'onhold' and access_rights.can_cancel:
303 event.on_hold()
304 desc = 'Put event on hold'
766e87c @christopherb Added UserRights class.
christopherb authored
305 if state.lower() == 'cancel' and access_rights.can_cancel:
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
306 event.cancel()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
307 desc = 'Cancelled event'
766e87c @christopherb Added UserRights class.
christopherb authored
308 if state.lower() == 'delete' and access_rights.is_admin:
a67ac50 @mdhancher Add a simple admin-only event delete and undelete.
mdhancher authored
309 event.delete()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
310 desc = 'Deleted event'
766e87c @christopherb Added UserRights class.
christopherb authored
311 if state.lower() == 'undelete' and access_rights.is_admin:
a67ac50 @mdhancher Add a simple admin-only event delete and undelete.
mdhancher authored
312 event.undelete()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
313 desc = 'Undeleted event'
766e87c @christopherb Added UserRights class.
christopherb authored
314 if state.lower() == 'expire' and access_rights.is_admin:
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
315 event.expire()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
316 desc = 'Expired event'
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
317 if event.status == 'approved':
318 notify_owner_approved(event)
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
319 if desc != '':
320 log = HDLog(event=event,description=desc)
321 log.put()
9f06c39 @casey Added RSS for upcoming events.
casey authored
322 self.redirect(event_path(event))
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
323
f1997e4 @christopherb Made misc style fixes
christopherb authored
324
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
325 class ApprovedHandler(webapp.RequestHandler):
326 def get(self):
327 user = users.get_current_user()
328 if user:
329 logout_url = users.create_logout_url('/')
330 else:
331 login_url = users.create_login_url('/')
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
332 today = local_today()
736390e @dustball Bug fixes & UI
dustball authored
333 show_all_nav = user
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
334 events = Event.get_approved_list()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
335 tomorrow = today + timedelta(days=1)
d63161a Add widget mode
Brian Klug authored
336 whichbase = 'base.html'
337 if self.request.get('base'):
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
338 whichbase = self.request.get('base') + '.html'
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
339 self.response.out.write(template.render('templates/approved.html', locals()))
340
f1997e4 @christopherb Made misc style fixes
christopherb authored
341
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
342 class MyEventsHandler(webapp.RequestHandler):
343 @util.login_required
344 def get(self):
345 user = users.get_current_user()
346 if user:
347 logout_url = users.create_logout_url('/')
348 else:
349 login_url = users.create_login_url('/')
350 events = Event.all().filter('member = ', user).order('start_time')
736390e @dustball Bug fixes & UI
dustball authored
351 show_all_nav = user
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
352 today = local_today()
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
353 tomorrow = today + timedelta(days=1)
354 self.response.out.write(template.render('templates/myevents.html', locals()))
355
f1997e4 @christopherb Made misc style fixes
christopherb authored
356
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
357 class PastHandler(webapp.RequestHandler):
358 def get(self):
359 user = users.get_current_user()
360 if user:
361 logout_url = users.create_logout_url('/')
362 else:
363 login_url = users.create_login_url('/')
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
364 today = local_today()
736390e @dustball Bug fixes & UI
dustball authored
365 show_all_nav = user
d75579f @progrium minor updates here and there to bills contributions.
progrium authored
366 events = Event.all().filter('start_time < ', today).order('-start_time')
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
367 self.response.out.write(template.render('templates/past.html', locals()))
368
f1997e4 @christopherb Made misc style fixes
christopherb authored
369
b4ea292 Handler to bug pending events
Brian Klug authored
370 class CronBugOwnersHandler(webapp.RequestHandler):
371 def get(self):
372 events = Event.get_pending_list()
373 for e in events:
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
374 bug_owner_pending(e)
375
376
377 class AllFutureHandler(webapp.RequestHandler):
378 def get(self):
379 user = users.get_current_user()
380 if user:
381 logout_url = users.create_logout_url('/')
382 else:
383 login_url = users.create_login_url('/')
736390e @dustball Bug fixes & UI
dustball authored
384 show_all_nav = user
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
385 events = Event.get_all_future_list()
386 today = local_today()
387 tomorrow = today + timedelta(days=1)
388 self.response.out.write(template.render('templates/all_future.html', locals()))
b4ea292 Handler to bug pending events
Brian Klug authored
389
85d17af @dustball "Large Events" page and iCal feed
dustball authored
390 class LargeHandler(webapp.RequestHandler):
391 def get(self):
392 user = users.get_current_user()
393 if user:
394 logout_url = users.create_logout_url('/')
395 else:
396 login_url = users.create_login_url('/')
397 show_all_nav = user
398 events = Event.get_large_list()
399 today = local_today()
400 tomorrow = today + timedelta(days=1)
401 self.response.out.write(template.render('templates/large.html', locals()))
402
f1997e4 @christopherb Made misc style fixes
christopherb authored
403
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
404 class PendingHandler(webapp.RequestHandler):
405 def get(self):
406 user = users.get_current_user()
407 if user:
408 logout_url = users.create_logout_url('/')
409 else:
410 login_url = users.create_login_url('/')
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
411 events = Event.get_pending_list()
736390e @dustball Bug fixes & UI
dustball authored
412 show_all_nav = user
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
413 today = local_today()
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
414 tomorrow = today + timedelta(days=1)
415 self.response.out.write(template.render('templates/pending.html', locals()))
416
f1997e4 @christopherb Made misc style fixes
christopherb authored
417
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
418 class NewHandler(webapp.RequestHandler):
fcf7602 @progrium working approval process and ical view of approved events
progrium authored
419 @util.login_required
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
420 def get(self):
421 user = users.get_current_user()
4d85afa @dustball Remove staffing requirement and make members more responsible
dustball authored
422 human = human_username(user)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
423 if user:
424 logout_url = users.create_logout_url('/')
425 else:
426 login_url = users.create_login_url('/')
427 rooms = ROOM_OPTIONS
cb7a9d1 pull in the rules live and memcache them for 1 day on new and confirm…
jonathan authored
428 rules = memcache.get("rules")
429 if(rules is None):
f35065d @dustball New wiki page
dustball authored
430 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
431 memcache.add("rules", rules, 86400)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
432 self.response.out.write(template.render('templates/new.html', locals()))
e2b9558 @btubbs Fixes issue 4. Changed to jqueryUI datepicker. Replaced jquery
btubbs authored
433
f1997e4 @christopherb Made misc style fixes
christopherb authored
434
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
435 def post(self):
436 user = users.get_current_user()
7742592 @progrium start of maintaining form state on errors
progrium authored
437 try:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
438 start_time = datetime.strptime('%s %s:%s %s' % (
7742592 @progrium start of maintaining form state on errors
progrium authored
439 self.request.get('date'),
440 self.request.get('start_time_hour'),
441 self.request.get('start_time_minute'),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
442 self.request.get('start_time_ampm')), '%m/%d/%Y %I:%M %p')
443 end_time = datetime.strptime('%s %s:%s %s' % (
7742592 @progrium start of maintaining form state on errors
progrium authored
444 self.request.get('date'),
445 self.request.get('end_time_hour'),
446 self.request.get('end_time_minute'),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
447 self.request.get('end_time_ampm')), '%m/%d/%Y %I:%M %p')
c97598b @dustball Room Conflict Detection
dustball authored
448 conflicts = Event.check_conflict(start_time,end_time,self.request.get_all('rooms'))
449 if conflicts:
450 raise ValueError('Room conflict detected')
8615877 Fix validation for event size
Brian Klug authored
451 if not self.request.get('estimated_size').isdigit():
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
452 raise ValueError('Estimated number of people must be a number')
8615877 Fix validation for event size
Brian Klug authored
453 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
454 raise ValueError('Estimated number of people must be greater then zero')
7742592 @progrium start of maintaining form state on errors
progrium authored
455 if (end_time-start_time).days < 0:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
456 raise ValueError('End time must be after start time')
a244c65 @dustball Bug fixes
dustball authored
457 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
458 raise ValueError( 'Phone number does not appear to be valid' )
7742592 @progrium start of maintaining form state on errors
progrium authored
459 else:
460 event = Event(
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
461 name = cgi.escape(self.request.get('name')),
7742592 @progrium start of maintaining form state on errors
progrium authored
462 start_time = start_time,
463 end_time = end_time,
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
464 type = cgi.escape(self.request.get('type')),
465 estimated_size = cgi.escape(self.request.get('estimated_size')),
466 contact_name = cgi.escape(self.request.get('contact_name')),
467 contact_phone = cgi.escape(self.request.get('contact_phone')),
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
468 details = cgi.escape(self.request.get('details')),
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
469 url = cgi.escape(self.request.get('url')),
470 fee = cgi.escape(self.request.get('fee')),
8414350 @billsaysthis multiline for details and notes fields
billsaysthis authored
471 notes = cgi.escape(self.request.get('notes')),
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
472 rooms = self.request.get_all('rooms'),
b879063 @mdhancher Respect the local timezone (Pacific), and tidy up related imports.
mdhancher authored
473 expired = local_today() + timedelta(days=PENDING_LIFETIME), # Set expected expiration date
7742592 @progrium start of maintaining form state on errors
progrium authored
474 )
475 event.put()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
476 log = HDLog(event=event,description="Created new event")
477 log.put()
7742592 @progrium start of maintaining form state on errors
progrium authored
478 notify_owner_confirmation(event)
479 notify_new_event(event)
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
480 set_cookie(self.response.headers, 'formvalues', None)
87868cf issue 11 add a confirmation page
jonathan authored
481 #self.redirect('/event/%s-%s' % (event.key().id(), slugify(event.name)))
482 self.redirect('/confirm/%s-%s' % (event.key().id(), slugify(event.name)))
483
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
484 except Exception, e:
485 message = str(e)
486 if 'match format' in message:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
487 message = 'Date is required.'
81a81e1 @progrium adding errors for form validation, full notifications, and minor edit…
progrium authored
488 if message.startswith('Property'):
489 message = message[9:].replace('_', ' ').capitalize()
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
490 # This is NOT a reliable way to handle erorrs
491 #set_cookie(self.response.headers, 'formerror', message)
492 #set_cookie(self.response.headers, 'formvalues', dict(self.request.POST))
493 #self.redirect('/new')
494 error = message
495 self.response.out.write(template.render('templates/error.html', locals()))
87868cf issue 11 add a confirmation page
jonathan authored
496
497 class ConfirmationHandler(webapp.RequestHandler):
498 def get(self, id):
499 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
500 rules = memcache.get("rules")
501 if(rules is None):
f35065d @dustball New wiki page
dustball authored
502 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
503 memcache.add("rules", rules, 86400)
87868cf issue 11 add a confirmation page
jonathan authored
504 self.response.out.write(template.render('templates/confirmation.html', locals()))
505
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
506 class LogsHandler(webapp.RequestHandler):
507 @util.login_required
508 def get(self):
509 user = users.get_current_user()
510 logs = HDLog.get_logs_list()
511 if user:
512 logout_url = users.create_logout_url('/')
513 else:
514 login_url = users.create_login_url('/')
736390e @dustball Bug fixes & UI
dustball authored
515 show_all_nav = user
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
516 self.response.out.write(template.render('templates/logs.html', locals()))
517
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
518 class FeedbackHandler(webapp.RequestHandler):
519 @util.login_required
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
520 def get(self, id):
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
521 user = users.get_current_user()
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
522 event = Event.get_by_id(int(id))
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
523 if user:
524 logout_url = users.create_logout_url('/')
525 else:
526 login_url = users.create_login_url('/')
527 self.response.out.write(template.render('templates/feedback.html', locals()))
528
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
529 def post(self, id):
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
530 user = users.get_current_user()
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
531 event = Event.get_by_id(int(id))
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
532 try:
533 if self.request.get('rating'):
534 feedback = Feedback(
535 event = event,
536 rating = int(self.request.get('rating')),
ca3c6dd Escaped additional fields that could be used for XSS
Christopher Biettchert authored
537 comment = cgi.escape(self.request.get('comment')))
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
538 feedback.put()
0eb5a92 @billsaysthis basic logging for all user-initiated post methods in place
billsaysthis authored
539 log = HDLog(event=event,description="Posted feedback")
540 log.put()
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
541 self.redirect('/event/%s-%s' % (event.key().id(), slugify(event.name)))
542 else:
7ebb2cd @christopherb Cleaned up the style of the files some. Mostly standardizing on singl…
christopherb authored
543 raise ValueError('Please select a rating')
8c52522 @billsaysthis small tweak to how feedbacks displayed in event page
billsaysthis authored
544 except Exception:
545 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
546 self.redirect('/feedback/new/' + id)
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
547
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
548 def main():
549 application = webapp.WSGIApplication([
550 ('/', ApprovedHandler),
4c7da5d @billsaysthis added func to ensure word 'in' only shown when rooms are assigned
billsaysthis authored
551 ('/all_future', AllFutureHandler),
85d17af @dustball "Large Events" page and iCal feed
dustball authored
552 ('/large', LargeHandler),
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
553 ('/pending', PendingHandler),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
554 ('/past', PastHandler),
b4ea292 Handler to bug pending events
Brian Klug authored
555 ('/cronbugowners', CronBugOwnersHandler),
a82b43e @billsaysthis add myevents, pastevents code, refined list display on event page
billsaysthis authored
556 ('/myevents', MyEventsHandler),
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
557 ('/new', NewHandler),
87868cf issue 11 add a confirmation page
jonathan authored
558 ('/confirm/(\d+).*', ConfirmationHandler),
ca8c7f2 @dustball Let edit events and refactor error handling
dustball authored
559 ('/edit/(\d+).*', EditHandler),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
560 # single event views
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
561 ('/event/(\d+).*', EventHandler),
2e08a66 @progrium cleaning things up and adding json representations for jon
progrium authored
562 ('/event/(\d+)\.json', EventHandler),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
563 # various export methods -- events.{json,rss,ics}
564 ('/events\.(.+)', ExportHandler),
565 #
566 # CRON tasks
47a7f7a @progrium basic form validation, added end time, start of notifications, some f…
progrium authored
567 ('/expire', ExpireCron),
34d98f0 @billsaysthis moved feedback stuff to separate py file, small tweak to email notifi…
billsaysthis authored
568 ('/expiring', ExpireReminderCron),
219203b @dustball Cache better
dustball authored
569 ('/domaincache', DomainCacheCron),
f49797a @dustball Reminders 2.0
dustball authored
570 ('/reminder', ReminderCron),
841fefb added meaningful descriptions to ical events.
Stig Hackvan authored
571 #
2ad290e @billsaysthis add logging model and obscure list view
billsaysthis authored
572 ('/logs', LogsHandler),
d2c3dc7 @billsaysthis moved app-specific js to separate file
billsaysthis authored
573 ('/feedback/new/(\d+).*', FeedbackHandler) ],debug=True)
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
574 util.run_wsgi_app(application)
575
f1997e4 @christopherb Made misc style fixes
christopherb authored
576
9b632dd @progrium initial commit -- basic form, rough listing
progrium authored
577 if __name__ == '__main__':
578 main()
Something went wrong with that request. Please try again.