Exemple #1
0
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)