Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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