source: weekplanplugin/trunk/weekplan/macro.py

Last change on this file was 17664, checked in by lucid, 4 years ago

WeekPlanPlugin: Python3 compatibility.
(fix #13736)

File size: 5.5 KB
Line 
1# -*- coding: utf-8 -*-
2
3from __future__ import division
4
5import datetime
6import math
7from functools import reduce
8
9from trac.core import *
10from trac.util.datefmt import parse_date, utc
11from trac.util.html import tag
12from trac.web.chrome import (Chrome, add_script, add_script_data,
13                             add_stylesheet, ITemplateProvider)
14from trac.wiki.api import parse_args
15from trac.wiki.macros import WikiMacroBase
16
17from weekplan.core import WeekPlanModule
18
19
20class WeekPlanMacro(WikiMacroBase):
21    """Show a week-by-week calendar and allow planning events.
22   
23    The arguments are:
24    * `plan`: Id of the shown collection of events. (required)
25      * Can be a `|`-separated list of multiple plans.
26    * `start`: A date  in the first week shown. (Defaults to today.)
27    * `weeks`: Number of weeks shown. (Defaults to one.)
28    * `weeksperrow`: Number of weeks per row. (Defaults to one.)
29    * `width`: Width of the calendar. (Defaults to 400.)
30    * `rowheight`: Height of one row of the calendar. (Defaults to 100.)
31    * `showweekends`: Show Saturdays and Sundays (Defaults to hidden.)
32    * `color`: Color of the events. (Defaults to `#3A87AD|#39AC60|#D7A388|#88BDD7|#9939AC|#AC9939`.)
33      * Can be a `|`-separated list of multiple colors. Each plan uses a different colors if multiple plans are specified.
34    * `label`: Labels shown instead of the plan ids. (Defaults to the plan ids.)
35      * Can be a `|`-separated list of multiple labels. Each plan uses a different label if multiple plans are specified.
36    * `hidelegend`: Show a legend below the calendar. (Defaults to shown.)
37    Example:
38    {{{
39        [[WeekPlan(plan=example, start=1.1.2014,weeks=10)]]
40    }}}
41    """
42
43    def expand_macro(self, formatter, name, content):
44        args, kw = parse_args(content)
45        args = [arg.strip() for arg in args]
46
47        plan_ids = kw.get('plan', '').split('|')
48        if not plan_ids:
49            raise TracError('Missing plan id')
50
51        colors = kw.get('color', '#38A|#4B6|#DA8|#9CD|#CAD|#CC7').split('|')
52        colors = dict(zip(plan_ids, colors*((len(plan_ids)-1)//len(colors)+1)))
53
54        labels = [label for label in kw.get('label', '').split('|') if label]
55        labels = dict(zip(plan_ids, labels + plan_ids[len(labels):]))
56
57        start = kw.get('start')
58        if start is None:
59            start = datetime.date.today()
60        else:
61            start = parse_date(start, utc).date()
62        weeks = int(kw.get('weeks', 1))
63        weeksperrow = int(kw.get('weeksperrow', 1))
64
65        width = int(kw.get('width', 400))
66        rowheight = int(kw.get('rowheight', 100))
67
68        req = formatter.req
69        context = formatter.context
70        core = WeekPlanModule(self.env)
71
72        plan_data = {
73            'form_token': req.form_token,
74            'api_url': formatter.href('weekplan'),
75            'plans': plan_ids,
76            'plans_with_add_event': [plan_id for plan_id in plan_ids if core.can_plan_add_event(plan_id)],
77            'plans_with_update_event': [plan_id for plan_id in plan_ids if core.can_plan_update_event(plan_id)],
78            'plans_with_delete_event': [plan_id for plan_id in plan_ids if core.can_plan_delete_event(plan_id)],
79            'colors': colors,
80            'labels': labels,
81            'calendar_data': {
82                'firstDay': 1, # Start weeks on Monday
83                'weekends': 'showweekends' in args, # Hide Saturdays and Sundays by default
84                'columnFormat': 'ddd', # Show column headers "Mon Tue Wed Thu Fri"
85                'defaultView': 'multiWeek', # Custom extension of "basicWeek" view!
86                'defaultDate': start.isoformat(),
87                'weeks': weeks, # New option for custom "multiWeek" view
88                'weeksperrow': weeksperrow, # New option for custom "multiWeek" view
89                'contentHeight': math.ceil(weeks / weeksperrow) * rowheight,
90                'header': { # Title and navigation buttons
91                    'left': '',
92                    'center': 'title',
93                    'right': 'prev,next'
94                },
95                'eventSources': [
96                    {
97                        'url': formatter.href('weekplan'),
98                        'data': {
99                            'format': 'json',
100                            'plan': '|'.join(plan_ids),
101                        },
102                    },
103                ],
104            },
105        }
106        plan_data_id = '%012x' % id(plan_data)
107       
108        add_stylesheet(req, 'weekplan/css/fullcalendar.css')
109        add_script(req, 'weekplan/js/moment.min.js')
110        add_script(req, 'weekplan/js/fullcalendar.js')
111        add_script(req, 'weekplan/js/weekplan.js')
112        add_script_data(req, {'weekplan_%s' % plan_data_id: plan_data})
113        Chrome(self.env).add_jquery_ui(req)
114       
115        calendar_element = tag.div("Enable JavaScript to display the week plan.",
116            class_='trac-weekplan system-message',
117            id='trac-weekplan-%s' % plan_data_id,
118            style='width:%spx' % width)
119        if 'hidelegend' in args:
120            return calendar_element
121        else:
122            return tag.div(
123                calendar_element,
124                self._render_legend(plan_ids, labels, colors))
125
126    def _render_legend(self, names, labels, colors):
127        def merge(a, b):
128            return a + u' | ' + b
129        items = [tag.span(u'■', style='color:%s' % colors[name]) + ' ' + labels[name] for name in names]
130        return tag.p(
131            reduce(merge, items),
132            class_='trac-weekplan-legend')
Note: See TracBrowser for help on using the repository browser.