def _process(self): if not request.is_xhr: return WPCategoryCalendar.render_template( 'display/calendar.html', self.category, start_dt=request.args.get('start_dt')) tz = self.category.display_tzinfo start = tz.localize(dateutil.parser.parse( request.args['start'])).astimezone(utc) end = tz.localize(dateutil.parser.parse( request.args['end'])).astimezone(utc) query = (Event.query.filter(Event.starts_between(start, end), Event.is_visible_in(self.category.id), ~Event.is_deleted).options( load_only('id', 'title', 'start_dt', 'end_dt', 'category_id'))) events = self._get_event_data(query) ongoing_events = (Event.query.filter( Event.is_visible_in(self.category.id), Event.start_dt < start, Event.end_dt > end).options( load_only('id', 'title', 'start_dt', 'end_dt', 'timezone')).order_by(Event.title).all()) return jsonify_data( flash=False, events=events, ongoing_event_count=len(ongoing_events), ongoing_events_html=self._render_ongoing_events(ongoing_events))
def _process(self): query = (Event.query .filter(Event.starts_between(self.start_dt, self.end_dt), Event.is_visible_in(self.category.id), ~Event.is_deleted) .options(load_only('id', 'title', 'start_dt', 'end_dt', 'category_id'))) events = self._get_event_data(query) ongoing_events = (Event.query .filter(Event.is_visible_in(self.category.id), ~Event.is_deleted, Event.start_dt < self.start_dt, Event.end_dt > self.end_dt) .options(load_only('id', 'title', 'start_dt', 'end_dt', 'timezone')) .order_by(Event.title) .all()) return jsonify_data(flash=False, events=events, ongoing_event_count=len(ongoing_events), ongoing_events_html=self._render_ongoing_events(ongoing_events))
def _get_upcoming_event(self): query = (Event.query .filter(Event.is_visible_in(self.category.id), Event.start_dt > now_utc(), ~Event.is_deleted) .options(subqueryload('acl_entries')) .order_by(Event.start_dt, Event.id)) res = get_n_matching(query, 1, lambda event: event.can_access(session.user)) if res: return res[0]
def _get_upcoming_event(self): query = (Event.query .filter(Event.is_visible_in(self.category), Event.start_dt > now_utc(), ~Event.is_deleted) .options(subqueryload('acl_entries')) .order_by(Event.start_dt, Event.id)) res = get_n_matching(query, 1, lambda event: event.can_access(session.user)) if res: return res[0]
def _process(self): if not request.is_xhr: return WPCategory.render_template('display/calendar.html', self.category, start_dt=request.args.get('start_dt')) tz = self.category.display_tzinfo start = tz.localize(dateutil.parser.parse(request.args['start'])).astimezone(utc) end = tz.localize(dateutil.parser.parse(request.args['end'])).astimezone(utc) query = (Event.query .filter(Event.starts_between(start, end), Event.is_visible_in(self.category), ~Event.is_deleted) .options(load_only('id', 'title', 'start_dt', 'end_dt', 'category_id'))) events = self._get_event_data(query) ongoing_events = (Event.query .filter(Event.is_visible_in(self.category), Event.start_dt < start, Event.end_dt > end) .options(load_only('id', 'title', 'start_dt', 'end_dt', 'timezone')) .order_by(Event.title) .all()) return jsonify_data(flash=False, events=events, ongoing_event_count=len(ongoing_events), ongoing_events_html=self._render_ongoing_events(ongoing_events))
def get_event_query_filter(category, is_flat=False, hidden_event_ids=None): criteria = [~Event.is_deleted] if is_flat: # Hidden events (visibility == 0) are excluded here, but we can't include an OR criterion # checking for a direct category id match as this completely destroys the performance of # the query. # This should be OK though since showing hidden events in the flattened event list isn't # important - they would only be shown to category managers and when using the non-flat # view they still see them anyway. criteria.append(Event.is_visible_in(category.id)) else: criteria.append(Event.category_id == category.id) if hidden_event_ids: criteria.append(Event.id.notin_(hidden_event_ids)) return db.and_(*criteria)
def get_category_timetable(categ_ids, start_dt, end_dt, detail_level='event', tz=utc, from_categ=None, grouped=True): """Retrieve time blocks that fall within a specific time interval for a given set of categories. :param categ_ids: iterable containing list of category IDs :param start_dt: start of search interval (``datetime``, expected to be in display timezone) :param end_dt: end of search interval (``datetime`` in expected to be in display timezone) :param detail_level: the level of detail of information (``event|session|contribution``) :param tz: the ``timezone`` information should be displayed in :param from_categ: ``Category`` that will be taken into account to calculate visibility :param grouped: Whether to group results by start date :returns: a dictionary containing timetable information in a structured way. See source code for examples. """ day_start = start_dt.astimezone(utc) day_end = end_dt.astimezone(utc) dates_overlap = lambda t: (t.start_dt >= day_start) & (t.start_dt <= day_end) items = defaultdict(lambda: defaultdict(list)) # first of all, query TimetableEntries/events that fall within # specified range of dates (and category set) events = _query_events(categ_ids, day_start, day_end) if from_categ: events = events.filter(Event.is_visible_in(from_categ)) for eid, tt_start_dt in events: if tt_start_dt: items[eid][tt_start_dt.astimezone(tz).date()].append(tt_start_dt) else: items[eid] = None # then, retrieve detailed information about the events event_ids = set(items) query = (Event.find(Event.id.in_(event_ids)) .options(subqueryload(Event.person_links).joinedload(EventPersonLink.person), joinedload(Event.own_room).noload('owner'), joinedload(Event.own_venue), joinedload(Event.category).undefer('effective_icon_data'), undefer('effective_protection_mode'))) scheduled_events = defaultdict(list) ongoing_events = [] events = [] for e in query: if grouped: local_start_dt = e.start_dt.astimezone(tz).date() local_end_dt = e.end_dt.astimezone(tz).date() if items[e.id] is None: # if there is no TimetableEntry, this means the event has not timetable on that interval for day in iterdays(max(start_dt.date(), local_start_dt), min(end_dt.date(), local_end_dt)): # if the event starts on this date, we've got a time slot if day.date() == local_start_dt: scheduled_events[day.date()].append((e.start_dt, e)) else: ongoing_events.append(e) else: for start_d, start_dts in items[e.id].viewitems(): scheduled_events[start_d].append((start_dts[0], e)) else: events.append(e) # result['events'][date(...)] -> [(datetime(....), Event(...))] # result[event_id]['contribs'][date(...)] -> [(TimetableEntry(...), Contribution(...))] # result['ongoing_events'] = [Event(...)] if grouped: result = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) else: result = defaultdict(lambda: defaultdict(list)) result.update({ 'events': scheduled_events if grouped else events, 'ongoing_events': ongoing_events }) # according to detail level, ask for extra information from the DB if detail_level != 'event': query = _query_blocks(event_ids, dates_overlap, detail_level) if grouped: for b in query: start_date = b.timetable_entry.start_dt.astimezone(tz).date() result[b.session.event_id]['blocks'][start_date].append((b.timetable_entry, b)) else: for b in query: result[b.session.event_id]['blocks'].append(b) if detail_level == 'contribution': query = (Contribution.find(Contribution.event_id.in_(event_ids), dates_overlap(TimetableEntry), ~Contribution.is_deleted) .options(contains_eager(Contribution.timetable_entry), joinedload(Contribution.person_links)) .join(TimetableEntry)) if grouped: for c in query: start_date = c.timetable_entry.start_dt.astimezone(tz).date() result[c.event_id]['contribs'][start_date].append((c.timetable_entry, c)) else: for c in query: result[c.event_id]['contributions'].append(c) query = (Break.find(TimetableEntry.event_id.in_(event_ids), dates_overlap(TimetableEntry)) .options(contains_eager(Break.timetable_entry)) .join(TimetableEntry)) if grouped: for b in query: start_date = b.timetable_entry.start_dt.astimezone(tz).date() result[b.timetable_entry.event_id]['breaks'][start_date].append((b.timetable_entry, b)) else: for b in query: result[b.timetable_entry.event_id]['breaks'].append(b) return result
def get_category_timetable(categ_ids, start_dt, end_dt, detail_level='event', tz=utc, from_categ=None, grouped=True): """Retrieve time blocks that fall within a specific time interval for a given set of categories. :param categ_ids: iterable containing list of category IDs :param start_dt: start of search interval (``datetime``, expected to be in display timezone) :param end_dt: end of search interval (``datetime`` in expected to be in display timezone) :param detail_level: the level of detail of information (``event|session|contribution``) :param tz: the ``timezone`` information should be displayed in :param from_categ: ``Category`` that will be taken into account to calculate visibility :param grouped: Whether to group results by start date :returns: a dictionary containing timetable information in a structured way. See source code for examples. """ day_start = start_dt.astimezone(utc) day_end = end_dt.astimezone(utc) dates_overlap = lambda t: (t.start_dt >= day_start) & (t.start_dt <= day_end) items = defaultdict(lambda: defaultdict(list)) # first of all, query TimetableEntries/events that fall within # specified range of dates (and category set) events = _query_events(categ_ids, day_start, day_end) if from_categ: events = events.filter(Event.is_visible_in(from_categ)) for eid, tt_start_dt in events: if tt_start_dt: items[eid][tt_start_dt.astimezone(tz).date()].append(tt_start_dt) else: items[eid] = None # then, retrieve detailed information about the events event_ids = set(items) query = (Event.find(Event.id.in_(event_ids)) .options(subqueryload(Event.person_links).joinedload(EventPersonLink.person), joinedload(Event.own_room).noload('owner'), joinedload(Event.own_venue), joinedload(Event.category).undefer('effective_icon_data'), undefer('effective_protection_mode'))) scheduled_events = defaultdict(list) ongoing_events = [] events = [] for e in query: if grouped: local_start_dt = e.start_dt.astimezone(tz).date() local_end_dt = e.end_dt.astimezone(tz).date() if items[e.id] is None: # if there is no TimetableEntry, this means the event has not timetable on that interval for day in iterdays(max(start_dt.date(), local_start_dt), min(end_dt.date(), local_end_dt)): # if the event starts on this date, we've got a time slot if day.date() == local_start_dt: scheduled_events[day.date()].append((e.start_dt, e)) else: ongoing_events.append(e) else: for start_d, start_dts in items[e.id].viewitems(): scheduled_events[start_d].append((start_dts[0], e)) else: events.append(e) # result['events'][date(...)] -> [(datetime(....), Event(...))] # result[event_id]['contribs'][date(...)] -> [(TimetableEntry(...), Contribution(...))] # result['ongoing_events'] = [Event(...)] if grouped: result = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) else: result = defaultdict(lambda: defaultdict(list)) result.update({ 'events': scheduled_events if grouped else events, 'ongoing_events': ongoing_events }) # according to detail level, ask for extra information from the DB if detail_level != 'event': query = _query_blocks(event_ids, dates_overlap, detail_level) if grouped: for b in query: start_date = b.timetable_entry.start_dt.astimezone(tz).date() result[b.session.event_id]['blocks'][start_date].append((b.timetable_entry, b)) else: for b in query: result[b.session.event_id]['blocks'].append(b) if detail_level == 'contribution': query = (Contribution.find(Contribution.event_id.in_(event_ids), dates_overlap(TimetableEntry), ~Contribution.is_deleted) .options(contains_eager(Contribution.timetable_entry), joinedload(Contribution.person_links)) .join(TimetableEntry)) if grouped: for c in query: start_date = c.timetable_entry.start_dt.astimezone(tz).date() result[c.event_id]['contribs'][start_date].append((c.timetable_entry, c)) else: for c in query: result[c.event_id]['contributions'].append(c) query = (Break.find(TimetableEntry.event_id.in_(event_ids), dates_overlap(TimetableEntry)) .options(contains_eager(Break.timetable_entry)) .join(TimetableEntry)) if grouped: for b in query: start_date = b.timetable_entry.start_dt.astimezone(tz).date() result[b.timetable_entry.event_id]['breaks'][start_date].append((b.timetable_entry, b)) else: for b in query: result[b.timetable_entry.event_id]['breaks'].append(b) return result