def execute(macro, args): """ Execute the 'macro' with the given 'args': an optional list of selected category names (categories whose pages are to be shown), together with optional named arguments of the following forms: start=YYYY-MM shows event details starting from the specified month start=current-N shows event details relative to the current month end=YYYY-MM shows event details ending at the specified month end=current+N shows event details relative to the current month mode=calendar shows a calendar view of events mode=list shows a list of events by month mode=table shows a table of events names=daily shows the name of an event on every day of that event names=weekly shows the name of an event once per week calendar=NAME uses the given NAME to provide request parameters which can be used to control the calendar view template=PAGE uses the given PAGE as the default template for new events (or the default template from the configuration if not specified) parent=PAGE uses the given PAGE as the parent of any new event page """ request = macro.request fmt = macro.formatter page = fmt.page _ = request.getText # Interpret the arguments. try: parsed_args = args and wikiutil.parse_quoted_separated(args, name_value=False) or [] except AttributeError: parsed_args = args.split(",") parsed_args = [arg for arg in parsed_args if arg] # Get special arguments. category_names = [] raw_calendar_start = None raw_calendar_end = None calendar_start = None calendar_end = None mode = None name_usage = "weekly" calendar_name = None template_name = getattr(request.cfg, "event_aggregator_new_event_template", "EventTemplate") parent_name = None for arg in parsed_args: if arg.startswith("start="): raw_calendar_start = arg[6:] elif arg.startswith("end="): raw_calendar_end = arg[4:] elif arg.startswith("mode="): mode = arg[5:] elif arg.startswith("names="): name_usage = arg[6:] elif arg.startswith("calendar="): calendar_name = arg[9:] elif arg.startswith("template="): template_name = arg[9:] elif arg.startswith("parent="): parent_name = arg[7:] else: category_names.append(arg) original_calendar_start = calendar_start = EventAggregatorSupport.getParameterMonth(raw_calendar_start) original_calendar_end = calendar_end = EventAggregatorSupport.getParameterMonth(raw_calendar_end) # Find request parameters to override settings. calendar_start = EventAggregatorSupport.getFormMonth(request, calendar_name, "start") or calendar_start calendar_end = EventAggregatorSupport.getFormMonth(request, calendar_name, "end") or calendar_end mode = EventAggregatorSupport.getQualifiedParameter(request, calendar_name, "mode", mode or "calendar") # Get the events. events, shown_events, all_shown_events, earliest, latest = \ EventAggregatorSupport.getEvents(request, category_names, calendar_start, calendar_end) # Get a concrete period of time. first, last = EventAggregatorSupport.getConcretePeriod(calendar_start, calendar_end, earliest, latest) # Define a view of the calendar, retaining useful navigational information. view = View(page, calendar_name, raw_calendar_start, raw_calendar_end, original_calendar_start, original_calendar_end, calendar_start, calendar_end, first, last, category_names, template_name, parent_name, mode, name_usage) # Make a calendar. output = [] # Output download controls. output.append(fmt.div(on=1, css_class="event-controls")) output.append(view.writeDownloadControls()) output.append(fmt.div(on=0)) # Output a table. if mode == "table": # Start of table view output. output.append(fmt.table(on=1, attrs={"tableclass" : "event-table"})) output.append(fmt.table_row(on=1)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-table-heading"})) output.append(fmt.text(_("Event dates"))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-table-heading"})) output.append(fmt.text(_("Event location"))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-table-heading"})) output.append(fmt.text(_("Event details"))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # Get the events in order. ordered_events = EventAggregatorSupport.getOrderedEvents(all_shown_events) # Show the events in order. for event in ordered_events: event_page = event.getPage() event_summary = event.getSummary(parent_name) event_details = event.getDetails() # Prepare CSS classes with category-related styling. css_classes = ["event-table-details"] for topic in event_details.get("topics") or event_details.get("categories") or []: # Filter the category text to avoid illegal characters. css_classes.append("event-table-category-%s" % "".join(filter(lambda c: c.isalnum(), topic))) attrs = {"class" : " ".join(css_classes)} output.append(fmt.table_row(on=1)) # Start and end dates. output.append(fmt.table_cell(on=1, attrs=attrs)) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["start"]))) output.append(fmt.span(on=0)) if event_details["start"] != event_details["end"]: output.append(fmt.text(" - ")) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["end"]))) output.append(fmt.span(on=0)) output.append(fmt.table_cell(on=0)) # Location. output.append(fmt.table_cell(on=1, attrs=attrs)) if event_details.has_key("location"): output.append(fmt.text(event_details["location"])) output.append(fmt.table_cell(on=0)) # Link to the page using the summary. output.append(fmt.table_cell(on=1, attrs=attrs)) output.append(event_page.linkToPage(request, event_summary)) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # End of table view output. output.append(fmt.table(on=0)) # Output a list or calendar. elif mode in ("list", "calendar"): # Output top-level information. # Start of list view output. if mode == "list": output.append(fmt.bullet_list(on=1, attr={"class" : "event-listings"})) # Visit all months in the requested range, or across known events. for month in first.months_until(last): # Either output a calendar view... if mode == "calendar": # Output a month. output.append(fmt.table(on=1, attrs={"tableclass" : "event-month"})) output.append(fmt.table_row(on=1)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-month-heading", "colspan" : "21"})) # Either write a month heading or produce links for navigable # calendars. output.append(view.writeMonthHeading(month)) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # Weekday headings. output.append(fmt.table_row(on=1)) for weekday in range(0, 7): output.append(fmt.table_cell(on=1, attrs={"class" : "event-weekday-heading", "colspan" : "3"})) output.append(fmt.text(_(EventAggregatorSupport.getDayLabel(weekday)))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # Process the days of the month. start_weekday, number_of_days = month.month_properties() # The start weekday is the weekday of day number 1. # Find the first day of the week, counting from below zero, if # necessary, in order to land on the first day of the month as # day number 1. first_day = 1 - start_weekday while first_day <= number_of_days: # Find events in this week and determine how to mark them on the # calendar. week_start = month.as_date(max(first_day, 1)) week_end = month.as_date(min(first_day + 6, number_of_days)) full_coverage, week_slots = EventAggregatorSupport.getCoverage( week_start, week_end, shown_events.get(month, [])) # Output a week, starting with the day numbers. output.append(view.writeDayNumbers(first_day, number_of_days, month, full_coverage)) # Either generate empty days... if not week_slots: output.append(view.writeEmptyWeek(first_day, number_of_days)) # Or generate each set of scheduled events... else: output.append(view.writeWeekSlots(first_day, number_of_days, month, week_end, week_slots)) # Process the next week... first_day += 7 # End of month. output.append(fmt.table(on=0)) # Or output a summary view... elif mode == "list": # Output a list. output.append(fmt.listitem(on=1, attr={"class" : "event-listings-month"})) output.append(fmt.div(on=1, attr={"class" : "event-listings-month-heading"})) # Either write a month heading or produce links for navigable # calendars. output.append(view.writeMonthHeading(month)) output.append(fmt.div(on=0)) output.append(fmt.bullet_list(on=1, attr={"class" : "event-month-listings"})) # Get the events in order. ordered_events = EventAggregatorSupport.getOrderedEvents(shown_events.get(month, [])) # Show the events in order. for event in ordered_events: event_page = event.getPage() event_details = event.getDetails() event_summary = event.getSummary(parent_name) output.append(fmt.listitem(on=1, attr={"class" : "event-listing"})) # Link to the page using the summary. output.append(fmt.paragraph(on=1)) output.append(event_page.linkToPage(request, event_summary)) output.append(fmt.paragraph(on=0)) # Start and end dates. output.append(fmt.paragraph(on=1)) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["start"]))) output.append(fmt.span(on=0)) output.append(fmt.text(" - ")) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["end"]))) output.append(fmt.span(on=0)) output.append(fmt.paragraph(on=0)) # Location. if event_details.has_key("location"): output.append(fmt.paragraph(on=1)) output.append(fmt.text(event_details["location"])) output.append(fmt.paragraph(on=1)) # Topics. if event_details.has_key("topics") or event_details.has_key("categories"): output.append(fmt.bullet_list(on=1, attr={"class" : "event-topics"})) for topic in event_details.get("topics") or event_details.get("categories") or []: output.append(fmt.listitem(on=1)) output.append(fmt.text(topic)) output.append(fmt.listitem(on=0)) output.append(fmt.bullet_list(on=0)) output.append(fmt.listitem(on=0)) output.append(fmt.bullet_list(on=0)) # Output top-level information. # End of list view output. if mode == "list": output.append(fmt.bullet_list(on=0)) # Output view controls. output.append(fmt.div(on=1, css_class="event-controls")) output.append(view.writeViewControls()) output.append(fmt.div(on=0)) return ''.join(output)