class EventView(BrowserView): """ Event View """ implements(IEventView) def __init__(self, context, request): self.context = context self.request = request self.database = IEventDatabaseProvider(context) self.portal_state = getMultiAdapter( (self.context, self.request), name=u'plone_portal_state' ) self.navigation_root = self.portal_state.navigation_root() self.db_org_id = getattr(aq_base(self.navigation_root), 'dbOrgId', 0) self.params = param_utils.getQueryParams(request) self.eid = self.params['eid'] def getEvent(self): """ find an event by eid """ return self.database.getEvent(self.eid) def getEventDates(self): """ Return a display list of dates. """ return getEventDateRep(self.database.getEventDates(self.eid)) def displayTime(self, event): """ start/end time for display; None if all-day """ begins = event['begins'] ends = event['ends'] if begins == ends: if begins == '12:00 AM': return None return begins if ends == '12:00 AM': return begins return u"%s–%s" % (begins, ends) def needOrg(self, oid): """ do we need to show organizational details? """ # Yes, unless oid of event matches that from nav root return self.db_org_id != oid def getOrg(self, oid): """ return a dict for the organization """ return self.database.getOrgData(oid) def getParams(self): """ get the useful params as a dict """ return self.params
def __init__(self, context, request): self.context = context self.request = request self.database = IEventDatabaseProvider(context) self.portal_state = getMultiAdapter( (self.context, self.request), name=u'plone_portal_state' ) self.navigation_root = self.portal_state.navigation_root() self.db_org_id = getattr(aq_base(self.navigation_root), 'dbOrgId', 0) self.params = param_utils.getQueryParams(request) self.eid = self.params['eid']
def __init__(self, context, request): assert(INavigationRoot.providedBy(context)) super(EventEditForm, self).__init__(context, request) self.database = IEventDatabaseProvider(context) # get eid from 'eid' or 'form.widgets.eid' self.eid = int( request.form.get('eid', request.form.get('form.widgets.eid', '0').replace(',', '') ) ) self.pdtcal = parsedatetime.Calendar() request['disable_border'] = 1 request['disable_plone.rightcolumn'] = 1
def __init__(self, context, request): self.editing = False self.context = context self.request = request self.database = IEventDatabaseProvider(context) self.portal_calendar = getToolByName(context, 'portal_calendar') self.portal_state = getMultiAdapter((self.context, self.request), name=u'plone_portal_state') self.navigation_root = self.portal_state.navigation_root() # get db_org_id from the nav root or set to 0 self.db_org_id = getattr(aq_base(self.navigation_root), 'dbOrgId', 0) # get dbOrgList from anywhere in aq chain self.db_org_list = param_utils.strToIntList( aq_get(self.navigation_root, 'dbOrgList', '') ) if not self.db_org_list and self.db_org_id: self.db_org_list = [self.db_org_id] self.context_state = getMultiAdapter((self.context, self.request), name=u'plone_context_state') self.today = date.today() # get params from request vals = param_utils.getQueryParams(request) # get params from nav root svals = param_utils.getSiteParams(self.navigation_root) self.site_params = svals # consolidate with site params winning collisions param_utils.consolidateParams(vals, svals) param_orgs = vals.get('org') if param_orgs and not self.db_org_list: self.db_org_list = param_orgs vals['public'] = 'y' self.site_params['public'] = 'y' # If no org set, always show public, community if not self.db_org_list: vals['public'] = 'y' vals['common'] = 'y' # so they don't show up on URLs: self.site_params['public'] = 'y' self.site_params['common'] = 'y' self.params = vals
class EventQueryView(BrowserView): """ EventQuery browser view """ implements(IEventQueryView) def __init__(self, context, request): self.editing = False self.context = context self.request = request self.database = IEventDatabaseProvider(context) self.portal_calendar = getToolByName(context, 'portal_calendar') self.portal_state = getMultiAdapter((self.context, self.request), name=u'plone_portal_state') self.navigation_root = self.portal_state.navigation_root() # get db_org_id from the nav root or set to 0 self.db_org_id = getattr(aq_base(self.navigation_root), 'dbOrgId', 0) # get dbOrgList from anywhere in aq chain self.db_org_list = param_utils.strToIntList( aq_get(self.navigation_root, 'dbOrgList', '') ) if not self.db_org_list and self.db_org_id: self.db_org_list = [self.db_org_id] self.context_state = getMultiAdapter((self.context, self.request), name=u'plone_context_state') self.today = date.today() # get params from request vals = param_utils.getQueryParams(request) # get params from nav root svals = param_utils.getSiteParams(self.navigation_root) self.site_params = svals # consolidate with site params winning collisions param_utils.consolidateParams(vals, svals) param_orgs = vals.get('org') if param_orgs and not self.db_org_list: self.db_org_list = param_orgs vals['public'] = 'y' self.site_params['public'] = 'y' # If no org set, always show public, community if not self.db_org_list: vals['public'] = 'y' vals['common'] = 'y' # so they don't show up on URLs: self.site_params['public'] = 'y' self.site_params['common'] = 'y' self.params = vals @memoize def getOrgData(self): """ Returns organization's data as a dict """ return self.database.getOrgData(self.db_org_id) def eventsByDateRange(self, start, end): """ Returns a sequence of Events with dates between start and end. Also, optionally, selects by several criteria """ return self.database.eventsByDateRange( start, end, self.db_org_list, **self.params ) def eventsByDay(self, start, end): """ Returns a day-keyed dictionary of days between start and end with events. Each day in the sequence is returned as a event list sorted by startTime. Also, optionally, selects by several criteria """ days = {} query = self.eventsByDateRange(start, end) # get the dates, taking recurrence into account for result in query: recurs = result.get('recurs', 'daily') estart = result['start'] ldate = min(end, result['end']) if recurs == 'weekly': dates = caldate.weekly(start, ldate, estart) elif recurs == 'biweekly': dates = caldate.biweekly(start, ldate, estart) elif recurs == 'monthly': dates = caldate.monthly(start, ldate, estart) else: # daily dates = caldate.daily(start, ldate, estart) for d in dates: days.setdefault(d, []).append(result) return days def getEventsForMonthDates(self, month_dates): """ Take a structured month list of week lists of days and fill it in with each day being a dict with keys: day - timedate date events - a sequence of events in startTime order today - True if day is today Each event is a dictionary of event attributes """ today = self.today start = month_dates[0][0] end = month_dates[-1][-1] events = self.eventsByDay(start, end) emonth = [] my_month = month_dates[1][1].month for week in month_dates: thisweek = [] for day in week: thisweek.append({ 'day': day.day, 'events': events.get(day, []), 'today': day == today, 'klass': (day.month != my_month) and 'omonth' or '', }) emonth.append(thisweek) return emonth def getEventMonth(self, target): """ returns a sequence of weeks, each week being a sequence of days; return is in getEventsForMonthDates format """ cal = calendar.Calendar() cal.firstweekday = self.portal_calendar.getFirstWeekDay() month_dates = cal.monthdatescalendar(target.year, target.month) return self.getEventsForMonthDates(month_dates) def getEventWeek(self, target): """ returns a sequence of weeks, each week being a sequence of days; return is in getEventsForMonthDates format """ month_dates = [caldate.weekDatesCalendar(target)] return self.getEventsForMonthDates(month_dates) def getEventDay(self, target): """ returns a sequence of weeks, each week being a sequence of days; return is in getEventsForMonthDates format """ month_dates = [[target]] return self.getEventsForMonthDates(month_dates) @memoize def getWeekdays(self): """Returns a list of Messages for the weekday names.""" weekdays = list(calendar.day_name) weekdays.insert(0, weekdays.pop()) return weekdays def getParams(self): """ get params """ return self.params @memoize def eventMonth(self): """ get events in a month data structure, based on params """ target = self.params.get('date', self.today) mode = self.params.get('mode', 'month') if mode == 'day': return self.getEventDay(target) elif mode == 'week': return self.getEventWeek(target) else: return self.getEventMonth(target) @memoize def eventList(self): """ get events in a simple list, based on params. list format [(date, eventdict),...] """ target = self.params.get('date', self.today) mode = self.params.get('mode', 'month') if mode == 'day': edict = self.eventsByDay(target, target) elif mode == 'week': edict = self.eventsByDay(caldate.startOfWeek(target), caldate.endOfWeek(target)) elif mode == 'upcoming': end = self.today + timedelta(self.params.get('days', 30)) edict = self.eventsByDay(self.today, end) else: edict = self.eventsByDay(caldate.startOfMonth(target), caldate.endOfMonth(target)) keys = edict.keys() keys.sort() elist = [] for key in keys: elist.append([key, edict[key]]) return elist def eventDayList(self, max=0): """ return upcoming events as list of day lists. Format is [[date, [eventdict,...]]...] """ def mediumFormatDate(d): return d.strftime("%A, %x") self.params['mode'] = 'upcoming' events = self.eventList() day = [] rez = [] last_date = date(1900, 1, 1) found = 0 for e in events: sdate = e[0] if sdate != last_date: if day: rez.append([mediumFormatDate(last_date), day]) day = [] last_date = sdate day += e[1] found += len(day) if found >= max: break if day: rez.append([mediumFormatDate(last_date), day]) return rez def myUrl(self, **overrides): """ Assemble a URL that will reproduce the current calendar with optional overrides. override with a None value to remove an item. """ params = self.params.copy() # consolidate overrides for s in overrides: oval = overrides[s] if oval is None: # delete it from params try: del params[s] except KeyError: pass else: params[s] = overrides[s] # remove keys present in site params for s in params.keys(): if s in self.site_params: del params[s] # generate query params when the setting isn't the default val = params.get('date') if val and val != self.today: s = "date=%s;" % val.isoformat() else: s = '' val = params.get('mode', 'month') if val != 'month': s = "%smode=%s;" % (s, val) val = params.get('gcid') if val: s = "%sgcid=%s;" % (s, val) val = params.get('public', 'b') if val != 'b': s = "%spublic=%s;" % (s, val) val = params.get('common', 'b') if val != 'b': s = "%scommon=%s;" % (s, val) val = params.get('udf1', 'n') if val != 'n': s = "%sudf1=%s;" % (s, val) val = params.get('udf2', 'n') if val != 'n': s = "%sudf2=%s;" % (s, val) val = params.get('org', self.db_org_id) if val != self.db_org_id: s = "%sorg=%s;" % (s, ','.join([str(int(i)) for i in val])) if s: s = "?%s" % s return "%s%s" % (self.context_state.current_base_url(), s) def monthUrl(self): """ url for month-mode calendar """ return self.myUrl(mode='month') def weekUrl(self): """ url for week-mode calendar """ return self.myUrl(mode='week') def dayUrl(self): """ url for day-mode calendar """ return self.myUrl(mode='day') def nextUrl(self): """ url for next calendar """ mode = self.params.get('mode', 'month') cdate = self.params.get('date', date.today()) if mode == 'day': cdate += timedelta(1) elif mode == 'week': cdate += timedelta(7) elif mode == 'month': cdate = caldate.startOfNextMonth(cdate) return self.myUrl(date=cdate) def todayUrl(self): """ url to get today's calendar """ return self.myUrl(date=self.today) def prevUrl(self): """ url for previous calendar """ mode = self.params.get('mode', 'month') cdate = self.params.get('date', self.today) if mode == 'day': cdate -= timedelta(1) elif mode == 'week': cdate -= timedelta(7) elif mode == 'month': cdate = caldate.startOfMonth(cdate) - timedelta(1) return self.myUrl(date=cdate) def getMode(self): """ return the current display mode: month, week, day """ return self.params.get('mode', 'month') def getMonthYear(self): """ return the displayed month and year, suitable for presentation """ return self.params.get('date', self.today).strftime("%B, %Y") def getFullDate(self): """ return the full date of the current display, suitable for presentation """ return self.params.get('date', self.today).strftime("%B %d, %Y").replace(' 0', ' ') def getCats(self, oid=0, include_all=True): """ return a list of categories in alpha order unless suppressed """ current_gcid = self.params.get('gcid', -1) if include_all: res = [{ 'title': u'All', 'url': self.allCatsUrl(), 'current': current_gcid == -1 }] else: res = [] for item in self.database.getCats(oid=oid): res.append({ 'title': decodeString(item.title), 'gcid': item.gcid, 'url': self.myUrl(gcid=item.gcid), 'current': item.gcid == current_gcid, }) return res @memoize def getDisplayCats(self): """ return an appropriate list of cats for display """ if self.params.get('nocat-display'): return [] db_org_id = self.db_org_id if db_org_id == 0: return self.getCats(oid=0) cat_options = getattr(self.navigation_root, 'catOptions', []) if 'useOrgCats' in cat_options: return self.getCats(oid=db_org_id) if 'useMajorCats' in cat_options: return self.getCats(oid=0) return [] def allCatsUrl(self): """ url with no gcid """ return self.myUrl(gcid=None) def allCatsCurrent(self): """ returns true if there's no gcid in the params """ return self.params.get('gcid', None) is None @memoize def showEventUrl(self): """ base url to display individual events """ return "%s/showEvent?eid=" % self.portal_state.navigation_root_url() @memoize def useAcronyms(self): """ should we display acronyms? """ return not (self.db_org_id or self.db_org_list) and self.getMode() != 'day' def setParam(self, **kwa): """ set params directly, typically from a template """ for key, value in kwa.items(): val = param_utils.sanitizeParam(key, value) if val is not None: self.params[key] = val # also set site_params so that the flag # won't show in the query params returned # by myURL(). This is based on the assumption # that this method is called from a template. self.site_params[key] = val def editMode(self): """ are we in edit mode? """ return self.editing @ram.cache(lambda *args: time() // 300) def orgList(self): """ return a list of current organizations """ print "Generating orgList" base_url = self.context_state.current_base_url() org_list = self.database.currentOrgs() ol_len_third = len(org_list) / 3 + 1 rez = [[], [], []] count = 0 for o in org_list: if o.alt_cal_url: url = o.alt_cal_url else: url = "%s?org=%d" % (base_url, o.oid) rez[count / ol_len_third].append({ 'url': url, 'orgname': o.orgname, 'acronym': o.acronym, }) count += 1 return rez @memoize def showOrgList(self): """ returns True if we should display org list """ # print self.db_org_id, self.db_org_list return not (self.db_org_id or self.db_org_list) @memoize def orgForDisplay(self): """ returns current org -- if there is one, and if we need a special display. """ if len(self.db_org_list) == 1: return self.database.getOrg(self.db_org_list[0]) return None
def __init__(self, context, request): assert(INavigationRoot.providedBy(context)) super(EventOrgEditForm, self).__init__(context, request) self.database = IEventDatabaseProvider(context) request['disable_border'] = 1 request['disable_plone.rightcolumn'] = 1
class EventOrgEditForm(form.SchemaForm): """ Define Form handling """ schema = IEventOrgSchema ignoreContext = False label = u"Calendar settings" description = u"Community Calendar settings for this organization." # form_name = u"Calendar settings" # attributes we'll be setting and getting from the # context. The rest will come from the database. context_attributes = ( 'catOptions', 'defaultMajorCats', 'udf1_name', 'udf2_name', ) # attributes we'll get from the database view database_attributes = ( 'name', 'description', 'acronym', 'url', 'alt_cal_url', 'contact', 'email', 'phone', 'ccal_link', ) def __init__(self, context, request): assert(INavigationRoot.providedBy(context)) super(EventOrgEditForm, self).__init__(context, request) self.database = IEventDatabaseProvider(context) request['disable_border'] = 1 request['disable_plone.rightcolumn'] = 1 # self.evq_view = getMultiAdapter((self.context, self.request), name=u'eventquery_view') def getContent(self): """ fill and return a content object """ obj = OrgContext() # orgCatSource will need to be able to get at the database obj._database = self.database for key in EventOrgEditForm.context_attributes: value = getattr(self.context, key, '') setattr(obj, key, value) if self.database.db_org_id: org_data = self.database.getOrgData() for key in EventOrgEditForm.database_attributes: value = org_data.get(key) setattr(obj, key, value) obj.org_categories = [c.title for c in self.database.getOrgCats()] else: obj.name = getattr(self.context, 'title', u"Organization Name") obj.description = getattr(self.context, 'description', u"Organization Description") return obj @button.buttonAndHandler(u'Save') def handleApply(self, action): data, errors = self.extractData() # get write access to the database portal_state = getMultiAdapter( (self.context, self.request), name=u'plone_portal_state' ) navigation_root = portal_state.navigation_root() writer = IEventDatabaseWriteProvider(navigation_root) if errors: self.status = self.formErrorsMessage return for key in EventOrgEditForm.context_attributes: value = data.get(key) setattr(self.context, key, value) org_data = {} for key in EventOrgEditForm.database_attributes: org_data[key] = data.get(key) if writer.db_org_id == 0: db_org_id = writer.insertOrg(**org_data) setattr(navigation_root, 'dbOrgId', db_org_id) else: writer.updateOrgData(**org_data) writer.updateOrgCats(data.get('org_categories', [])) messages = IStatusMessage(self.request) messages.add(u"Organization event settings updated", type=u"info") self.request.response.redirect("caledit") @button.buttonAndHandler(u"Cancel") def handleCancel(self, action): """User cancelled. Redirect back to the front page. """ self.request.response.redirect("caledit")
class EventEditForm(form.SchemaForm): """ Define Form handling """ schema = IEventEditForm ignoreContext = False # attributes we'll get from the database view database_attributes = ( 'eid', 'title', 'description', 'location', 'eventUrl', 'eventContact', 'eventEmail', 'eventPhone', 'begins', 'ends', ) def __init__(self, context, request): assert(INavigationRoot.providedBy(context)) super(EventEditForm, self).__init__(context, request) self.database = IEventDatabaseProvider(context) # get eid from 'eid' or 'form.widgets.eid' self.eid = int( request.form.get('eid', request.form.get('form.widgets.eid', '0').replace(',', '') ) ) self.pdtcal = parsedatetime.Calendar() request['disable_border'] = 1 request['disable_plone.rightcolumn'] = 1 def updateWidgets(self): super(EventEditForm, self).updateWidgets() self.widgets['eid'].mode = z3c.form.interfaces.HIDDEN_MODE def updateActions(self): super(EventEditForm, self).updateActions() delete_action = self.actions.get('handleDelete') if delete_action: delete_action.onclick = u"return confirm('Delete this event?')" def getContent(self): """ fill and return a content object """ def strToDate(s): yr, mo, day = s.split('-') return date(int(yr), int(mo), int(day)) def findRecurs(dates): last_delta = None starts = [d.start for d in dates] prev = strToDate(starts[0]) for start in starts[1:]: dt = strToDate(start) delta = dt - prev if last_delta and delta != last_delta: return None prev = dt last_delta = delta if delta.days == 1: recurs = "daily" elif delta.days == 7: recurs = "weekly" elif delta.days == 7: recurs = "biweekly" else: return None # we need to return an object with start, end, recurs # attributes obj = Recurrence() obj.start = starts[0] obj.end = starts[-1] obj.recurs = recurs return obj obj = EventContext() obj._database = self.database eid = self.eid if eid: event_data = self.database.getEvent(eid) for key in EventEditForm.database_attributes: value = event_data.get(key) setattr(obj, key, value) for key in ('public', 'free', 'community'): setattr(obj, key, event_data[key] == "Y") cats = [c.gcid for c in self.database.getEventCats(eid)] my_cats = [c.gcid for c in self.database.getOrgCats()] org_cats = [] major_cats = [] for gcid in cats: if gcid in my_cats: org_cats.append(gcid) else: major_cats.append(gcid) obj.majorCats = major_cats obj.orgCats = org_cats dates = self.database.getEventDates(eid) # check to see if this is an old-style date list # that happens to recur regularly if len(dates) > 1: recurs = findRecurs(dates) if recurs: # we can normalize it to start, end, recurs dates = [recurs] if len(dates) == 1: # simple scheduling obj.start = strToDate(dates[0].start) obj.end = strToDate(dates[0].end) obj.recurs = dates[0].recurs else: # we are irregularly scheduled obj.start = date.today() obj.end = date.today() obj.recurs = 'irregular' if len(dates): wkdates = [] for d in dates: yr, mo, dy = d.start.split('-') wkdates.append("/".join((mo, dy, yr[2:]))) obj.dates = ", ".join(wkdates) else: obj.start = date.today() obj.end = date.today() portal_state = getMultiAdapter( (self.context, self.request), name=u'plone_portal_state') navigation_root = portal_state.navigation_root() obj.majorCats = getattr(navigation_root, 'defaultMajorCats', []) return obj def _getWriter(self): """ return a database writer """ portal_state = getMultiAdapter( (self.context, self.request), name=u'plone_portal_state' ) navigation_root = portal_state.navigation_root() return IEventDatabaseWriteProvider(navigation_root) @button.buttonAndHandler(u'Save Event') def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return # get write access to the database writer = self._getWriter() form = self.request.form portal_state = getMultiAdapter( (self.context, self.request), name=u'plone_portal_state' ) member = portal_state.member() eid = data['eid'] event_data = {} for key in EventEditForm.database_attributes: if key != 'eid': if key == 'begins': # ##:## time from struct_time event_data['startTime'] = struct_time2str(form['begins_time']) elif key == 'ends': event_data['endTime'] = struct_time2str(form['ends_time']) else: event_data[key] = data.get(key) for key in ('public', 'free', 'community'): event_data[key] = data.get(key) and "Y" or "N" if eid: writer.updateEvent(eid, member, **event_data) writer.deleteEventCats(eid) writer.deleteEventDates(eid) else: eid = writer.eventInsert(member, **event_data) writer.evCatsInsert(eid, list(data['orgCats'].union(data['majorCats']))) if data['recurs'] == 'irregular': # irregular scheduling; save a list of dates writer.evDatesInsert( eid, [(dt, dt, u"daily") for dt in form['date_list']] ) else: # regular scheduling writer.evDatesInsert(eid, ((data['start'], data['end'], data['recurs']), )) messages = IStatusMessage(self.request) messages.add(u"Event saved", type=u"info") self.request.response.redirect("@@caledit") @button.buttonAndHandler(u"Delete Event", name="handleDelete", condition=lambda form: form.eid != 0) def handleDelete(self, action): """ Delete this event. """ eid = self.eid assert(eid != 0) writer = self._getWriter() writer.deleteEventCats(eid) writer.deleteEventDates(eid) writer.deleteEvent(eid) messages = IStatusMessage(self.request) messages.add(u"Event deleted", type=u"info") self.request.response.redirect("caledit") @button.buttonAndHandler(u"Cancel Edits") def handleCancel(self, action): """User cancelled. Redirect back to the front page. """ self.request.response.redirect("caledit")