Exemple #1
0
 def _wiki_link(self, req, args, kwargs, wiki, label, a_class, check=None):
     """Build links to wiki pages."""
     check_sign = None
     url = self.env.href.wiki(wiki)
     if WikiSystem(self.env).has_page(wiki.lstrip("/")):
         a_class += " page"
         title = _("Go to page %s") % wiki
         if check and check[0] == "link":
             chrome_path = "/".join([req.base_path, "chrome"])
             ok_img = "wikicalendar/check_ok.png"
             ok = tag.image(src="/".join([chrome_path, ok_img]), alt="ok", title="ok")
             nok_img = "wikicalendar/check_nok.png"
             nok = tag.image(src="/".join([chrome_path, nok_img]), alt="X", title="X")
             unk_img = "wikicalendar/check_unknown.png"
             unk = tag.image(src="/".join([chrome_path, unk_img]), alt="?", title="?")
             result = self._do_check(check[1], wiki)
             check_sign = result and (result == 1 and ok or nok) or unk
     else:
         # The default (empty page) is used, if template name is invalid.
         url += "?action=edit"
         # Add page template to create new wiki pages, if specified.
         template = None
         if len(args) >= 6 or kwargs.has_key("base"):
             try:
                 template = kwargs["base"]
             except KeyError:
                 template = args[5]
         if template:
             url += "&template=" + template
         title = _("Create page %s") % wiki
     link = tag.a(tag(label), href=url)
     link(class_=a_class, title_=title)
     return tag(link, check_sign)
Exemple #2
0
 def _gen_wiki_links(self, wiki, label, a_class, url, wiki_page_template,
                     check=None):
     check_sign = None
     if WikiSystem(self.env).has_page(wiki.lstrip('/')):
         a_class += " page"
         title = _("Go to page %s") % wiki
         if check and check[0] == 'link':
             chrome_path = '/'.join([self.ref.req.base_path, 'chrome'])
             ok_img = 'wikicalendar/check_ok.png'
             ok = tag.image(src='/'.join([chrome_path, ok_img]),
                            alt='ok', title='ok')
             nok_img = 'wikicalendar/check_nok.png'
             nok = tag.image(src='/'.join([chrome_path, nok_img]),
                             alt='X', title='X')
             unk_img = 'wikicalendar/check_unknown.png'
             unk = tag.image(src='/'.join([chrome_path, unk_img]),
                             alt='?', title='?')
             result = self._do_check(check[1], wiki)
             check_sign = result and (result == 1 and ok or nok) or unk
     else:
         url += "?action=edit"
         # adding template name, if specified
         if wiki_page_template != "":
             url += "&template=" + wiki_page_template
         title = _("Create page %s") % wiki
     link = tag.a(tag(label), href=url)
     link(class_=a_class, title_=title)
     return tag(link, check_sign)
Exemple #3
0
 def _wiki_link(self, req, args, kwargs, wiki, label, a_class, check=None):
     """Build links to wiki pages."""
     check_sign = None
     url = self.env.href.wiki(wiki)
     if WikiSystem(self.env).has_page(wiki.lstrip('/')):
         a_class += " page"
         title = _("Go to page %s") % wiki
         if check and check[0] == 'link':
             chrome_path = '/'.join([req.base_path, 'chrome'])
             ok_img = 'wikicalendar/check_ok.png'
             ok = tag.image(src='/'.join([chrome_path, ok_img]),
                            alt='ok',
                            title='ok')
             nok_img = 'wikicalendar/check_nok.png'
             nok = tag.image(src='/'.join([chrome_path, nok_img]),
                             alt='X',
                             title='X')
             unk_img = 'wikicalendar/check_unknown.png'
             unk = tag.image(src='/'.join([chrome_path, unk_img]),
                             alt='?',
                             title='?')
             result = self._do_check(check[1], wiki)
             check_sign = result and (result == 1 and ok or nok) or unk
     else:
         # The default (empty page) is used, if template name is invalid.
         url += "?action=edit"
         # Add page template to create new wiki pages, if specified.
         template = None
         if len(args) >= 6 or kwargs.has_key('base'):
             try:
                 template = kwargs['base']
             except KeyError:
                 template = args[5]
         if template:
             url += "&template=" + template
         title = _("Create page %s") % wiki
     link = tag.a(tag(label), href=url)
     link(class_=a_class, title_=title)
     return tag(link, check_sign)
Exemple #4
0
 def _gen_wiki_links(self,
                     wiki,
                     label,
                     a_class,
                     url,
                     wiki_page_template,
                     check=None):
     check_sign = None
     if WikiSystem(self.env).has_page(wiki.lstrip('/')):
         a_class += " page"
         title = _("Go to page %s") % wiki
         if check and check[0] == 'link':
             chrome_path = '/'.join([self.ref.req.base_path, 'chrome'])
             ok_img = 'wikicalendar/check_ok.png'
             ok = tag.image(src='/'.join([chrome_path, ok_img]),
                            alt='ok',
                            title='ok')
             nok_img = 'wikicalendar/check_nok.png'
             nok = tag.image(src='/'.join([chrome_path, nok_img]),
                             alt='X',
                             title='X')
             unk_img = 'wikicalendar/check_unknown.png'
             unk = tag.image(src='/'.join([chrome_path, unk_img]),
                             alt='?',
                             title='?')
             result = self._do_check(check[1], wiki)
             check_sign = result and (result == 1 and ok or nok) or unk
     else:
         url += "?action=edit"
         # adding template name, if specified
         if wiki_page_template != "":
             url += "&template=" + wiki_page_template
         title = _("Create page %s") % wiki
     link = tag.a(tag(label), href=url)
     link(class_=a_class, title_=title)
     return tag(link, check_sign)
Exemple #5
0
    def expand_macro(self, formatter, name, args):
        """Returns an image that will be displayed in the Wiki content.

        `name` is the actual name of the macro,
        `args` is the text enclosed in parenthesis at the call of the
          macro.
        """

        params = {}
        args_list, args_dict = parse_args(args)

        img_url = args_list[0]
        params['height'] = args_dict.get('height', '')
        params['width'] = args_dict.get('width', '')
        params['align'] = args_dict.get('align', 'left')

        image = tag.image(src=img_url,
                          width=params['width'],
                          eight=params['height'],
                          align=params['align'])

        link = tag.a(image, href=img_url)
        return tag.p(link, style="text-align:%s;" % params['align'])
    def expand_macro(self, formatter, name, content):

        # prepare options
        req = formatter.req
        options, query_args = parse_options(self.env.get_db_cnx(), content,
                                            copy.copy(DEFAULT_OPTIONS))

        if not options['startdate']:
            raise TracError("No start date specified!")

        # minimum time frame is one day
        if (options['startdate'] >= options['enddate']):
            options['enddate'] = options['startdate'] + timedelta(days=1)

        # calculate data
        timetable = self._calculate_timetable(options, query_args, req)

        # remove weekends
        if not options['weekends']:
            for date in timetable.keys():
                if date.weekday() >= 5:
                    del timetable[date]

        # scale data
        xdata, ydata, maxhours = self._scale_data(timetable, options)

        # build html for google chart api
        dates = sorted(timetable.keys())
        bottomaxis = "0:|" + ("|").join([str(date.day) for date in dates]) + \
            "|1:|%s/%s|%s/%s" % (dates[0].month, dates[0].year,
                                 dates[ - 1].month, dates[ - 1].year)
        leftaxis = "2,0,%s" % maxhours

        # add line for expected progress
        if options['expected'] == '0':
            expecteddata = ""
        else:
            expecteddata = "|0,100|%s,0" % (round(
                Decimal(options['expected']) * 100 / maxhours, 2))

        # prepare gridlines
        if options['gridlines'] == '0':
            gridlinesdata = "100.0,100.0,1,0"  # create top and right bounding line by using grid
        else:
            gridlinesdata = "%s,%s" % (xdata[1], (round(
                Decimal(options['gridlines']) * 100 / maxhours, 4)))

        # mark weekends
        weekends = []
        saturday = None
        index = 0
        halfday = self._round(Decimal("0.5") / (len(dates) - 1))
        for date in dates:
            if date.weekday() == 5:
                saturday = index
            if saturday and date.weekday() == 6:
                weekends.append(
                    "R,%s,0,%s,%s" %
                    (options['wecolor'],
                     self._round((Decimal(xdata[saturday]) / 100) - halfday),
                     self._round((Decimal(xdata[index]) / 100) + halfday)))
                saturday = None
            index += 1
        # special handling if time period starts with Sundays...
        if len(dates) > 0 and dates[0].weekday() == 6:
            weekends.append("R,%s,0,0.0,%s" % (options['wecolor'], halfday))
        # or ends with Saturday
        if len(dates) > 0 and dates[-1].weekday() == 5:
            weekends.append("R,%s,0,%s,1.0" %
                            (options['wecolor'], Decimal(1) - halfday))

        # chart title
        title = options.get('title', None)
        if title is None and options.get('milestone'):
            title = options['milestone'].split('|')[0]

        chart_args = unicode_urlencode({
            'chs':
            '%sx%s' % (options['width'], options['height']),
            'chf':
            'c,s,%s|bg,s,00000000' % options['bgcolor'],
            'chd':
            't:%s|%s%s' % (",".join(xdata), ",".join(ydata), expecteddata),
            'cht':
            'lxy',
            'chxt':
            'x,x,y',
            'chxl':
            bottomaxis,
            'chxr':
            leftaxis,
            'chm':
            "|".join(weekends),
            'chg':
            gridlinesdata,
            'chco':
            '%s,%s' % (options['color'], options['colorexpected']),
            'chtt':
            title
        })
        self.log.debug("BurndownChart data: %s" % repr(chart_args))
        if self.serverside_charts:
            return tag.image(
                src="%s?data=%s" %
                (req.href.estimationtools('chart'), unicode_quote(chart_args)),
                alt="Burndown Chart (server)")
        else:
            return tag.image(src="http://chart.googleapis.com/chart?%s" %
                             chart_args,
                             alt="Burndown Chart (client)")
    def expand_macro(self, formatter, name, content):
        req = formatter.req
        db = self.env.get_db_cnx()
        # prepare options
        options, query_args = parse_options(db, content, copy.copy(DEFAULT_OPTIONS))

        query_args[self.estimation_field + "!"] = None
        tickets = execute_query(self.env, req, query_args)

        sum = 0.0
        estimations = {}
        for ticket in tickets:
            if ticket['status'] in self.closed_states:
                continue
            try:
                estimation = float(ticket[self.estimation_field])
                owner = ticket['owner']
                sum += estimation
                if estimations.has_key(owner):
                    estimations[owner] += estimation
                else:
                    estimations[owner] = estimation
            except:
                pass

        estimations_string = []
        labels = []
        for owner, estimation in estimations.iteritems():
            # Note: Unconditional obfuscation of owner in case it represents
            # an email adress, and as the chart API doesn't support SSL
            # (plain http transfer only, from either client or server).
            labels.append("%s %g%s" % (obfuscate_email_address(owner),
                            round(estimation, 2),
                            self.estimation_suffix))
            estimations_string.append(str(int(estimation)))

        # Title
        title = 'Workload'

        # calculate remaining work time
        if options.get('today') and options.get('enddate'):
            currentdate = options['today']
            day = timedelta(days=1)
            days_remaining = 0
            while currentdate <= options['enddate']:
                if currentdate.weekday() < 5:
                    days_remaining += 1
                currentdate += day
            title += ' %g%s (~%s workdays left)' % (round(sum, 2),
                                    self.estimation_suffix, days_remaining)

        chart_args = unicode_urlencode({'chs': '%sx%s' % (options['width'], options['height']),
                      'chf': 'bg,s,00000000',
                      'chd': 't:%s' % ",".join(estimations_string),
                      'cht': 'p3',
                      'chtt': title,
                      'chl': "|".join(labels),
                      'chco': options['color']})
        self.log.debug("WorkloadChart data: %s" % repr(chart_args))
        if self.serverside_charts:
            return tag.image(src="%s?data=%s" % (req.href.estimationtools('chart'),
                                    unicode_quote(chart_args)),
                             alt="Workload Chart (server)")
        else:
            return tag.image(src="http://chart.googleapis.com/chart?%s" % chart_args,
                             alt="Workload Chart (client)")
    def expand_macro(self, formatter, name, content):

        # prepare options
        req = formatter.req
        options, query_args = parse_options(self.env.get_db_cnx(), content, copy.copy(DEFAULT_OPTIONS))

        if not options['startdate']:
            raise TracError("No start date specified!")

        # minimum time frame is one day
        if (options['startdate'] >= options['enddate']):
            options['enddate'] = options['startdate'] + timedelta(days=1)

        # calculate data
        timetable = self._calculate_timetable(options, query_args, req)
        
        # remove weekends
        if not options['weekends']:
            for date in timetable.keys():
                if date.weekday() >= 5:
                    del timetable[date]

        # scale data
        xdata, ydata, maxhours = self._scale_data(timetable, options)

        # build html for google chart api
        dates = sorted(timetable.keys())
        bottomaxis = "0:|" + ("|").join([str(date.day) for date in dates]) + \
            "|1:|%s/%s|%s/%s" % (dates[0].month, dates[0].year, dates[ - 1].month, dates[ - 1].year)
        leftaxis = "2,0,%s" % maxhours
        
        # add line for expected progress
        if options['expected'] == '0':
            expecteddata = ""
        else:
            expecteddata = "|0,100|%s,0" % (round(Decimal(options['expected']) * 100 / maxhours, 2))

        # prepare gridlines
        if options['gridlines'] == '0':
            gridlinesdata = "100.0,100.0,1,0"  # create top and right bounding line by using grid
        else:
            gridlinesdata = "%s,%s" % (xdata[1], (round(Decimal(options['gridlines']) * 100 / maxhours, 4)))

        # mark weekends
        weekends = []
        saturday = None
        index = 0
        halfday = self._round(Decimal("0.5") / (len(dates) - 1))
        for date in dates:
            if date.weekday() == 5:
                saturday = index
            if saturday and date.weekday() == 6:
                weekends.append("R,%s,0,%s,%s" %
                                (options['wecolor'],
                                 self._round((Decimal(xdata[saturday]) / 100) - halfday),
                                 self._round((Decimal(xdata[index]) / 100) + halfday)))
                saturday = None
            index += 1
        # special handling if time period starts with Sundays...
        if len(dates) > 0 and dates[0].weekday() == 6:
            weekends.append("R,%s,0,0.0,%s" % (options['wecolor'], halfday))
        # or ends with Saturday
        if len(dates) > 0 and dates[ - 1].weekday() == 5:
            weekends.append("R,%s,0,%s,1.0" % (options['wecolor'], Decimal(1) - halfday))

        # chart title
        title = options.get('title', None)
        if title is None and options.get('milestone'):
            title = options['milestone'].split('|')[0]

        chart_args = unicode_urlencode(
                    {'chs': '%sx%s' % (options['width'], options['height']),
                     'chf': 'c,s,%s|bg,s,00000000' % options['bgcolor'],
                     'chd': 't:%s|%s%s' % (",".join(xdata), ",".join(ydata), expecteddata),
                     'cht': 'lxy',
                     'chxt': 'x,x,y',
                     'chxl': bottomaxis,
                     'chxr': leftaxis,
                     'chm': "|".join(weekends),
                     'chg': gridlinesdata,
                     'chco': '%s,%s' % (options['color'], options['colorexpected']),
                     'chtt': title})
        self.log.debug("BurndownChart data: %s" % repr(chart_args))
        if self.serverside_charts:
            return tag.image(src="%s?data=%s" % (req.href.estimationtools('chart'),
                                    unicode_quote(chart_args)),
                             alt="Burndown Chart (server)")
        else:
            return tag.image(src="http://chart.googleapis.com/chart?%s" % chart_args,
                             alt="Burndown Chart (client)")
    def expand_macro(self, formatter, name, content):
        req = formatter.req
        db = self.env.get_db_cnx()
        # prepare options
        options, query_args = parse_options(db, content,
                                            copy.copy(DEFAULT_OPTIONS))

        query_args[self.estimation_field + "!"] = None
        tickets = execute_query(self.env, req, query_args)

        sum = 0.0
        estimations = {}
        for ticket in tickets:
            if ticket['status'] in self.closed_states:
                continue
            try:
                estimation = float(ticket[self.estimation_field] or 0.0)

                if options.get('remainingworkload'):

                    completion_cursor = db.cursor()

                    completion_cursor.execute(
                        "SELECT t.value AS totalhours, c.value AS complete, d.value AS due_close FROM ticket tk LEFT JOIN ticket_custom t ON (tk.id = t.ticket AND t.name = 'totalhours') LEFT JOIN ticket_custom c ON (tk.id = c.ticket AND c.name = 'complete') LEFT JOIN ticket_custom d ON (tk.id = d.ticket AND d.name = 'due_close') WHERE tk.id = %s"
                        % ticket['id'])

                    for row in completion_cursor:

                        ticket['totalhours'], ticket['complete'], ticket[
                            'due_close'] = row
                        break

                    # skip ticket ticket if due date is later than 'enddate':
                    if options.get('showdueonly'):

                        if not ticket['due_close']:
                            continue  # skip tickets with empty ETA when in 'showdueonly' mode
                        due_close = parse_date(ticket['due_close'],
                                               ["%Y/%m/%d"])
                        startdate = options.get('startdate')
                        enddate = options.get('enddate')

                        if startdate and startdate > due_close:
                            continue  # skip tickets with ETA in the past

                        if enddate and enddate < due_close:
                            continue  # skip tickets with ETA in the future

                        pass

                    totalhours = float(ticket['totalhours'] or 0.0)

                    completed = (float(ticket['complete'] or 0.0) /
                                 100) * estimation
                    completed_hours = min(estimation,
                                          max(totalhours, completed))

                    estimation -= completed_hours

                    pass

                owner = ticket['owner']

                sum += estimation
                if estimations.has_key(owner):
                    estimations[owner] += estimation
                else:
                    estimations[owner] = estimation
            except:
                raise

        # Title
        title = 'Workload'

        days_remaining = None

        # calculate remaining work time
        if options.get('today') and options.get('enddate'):
            currentdate = options['today']
            day = timedelta(days=1)
            days_remaining = 0
            while currentdate <= options['enddate']:
                if currentdate.weekday() < 5:
                    days_remaining += 1
                currentdate += day
            title += ' %g%s (~%s workdays left)' % (round(
                sum, 2), self.estimation_suffix, days_remaining)

        estimations_string = []
        labels = []
        workhoursperday = max(float(options.get('workhoursperday')), 0.0)
        chts = '000000'

        for owner, estimation in estimations.iteritems():
            # Note: Unconditional obfuscation of owner in case it represents
            # an email adress, and as the chart API doesn't support SSL
            # (plain http transfer only, from either client or server).
            label = "%s %g%s" % (obfuscate_email_address(owner),
                                 round(estimation, 2), self.estimation_suffix)

            if days_remaining != None:

                user_remaining_hours = days_remaining * workhoursperday

                if not user_remaining_hours or (estimation /
                                                user_remaining_hours) > 1:
                    label = "%s (~%g hours left)!" % (
                        label, round(user_remaining_hours, 2)
                    )  # user does not have enough hours left
                    chts = 'FF0000'  # set chart title style to red
                    pass
                pass

            labels.append(label)

            estimations_string.append(str(int(estimation)))

            pass

        chart_args = unicode_urlencode({
            'chs':
            '%sx%s' % (options['width'], options['height']),
            'chf':
            'bg,s,00000000',
            'chd':
            't:%s' % ",".join(estimations_string),
            'cht':
            'p3',
            'chtt':
            title,
            'chts':
            chts,
            'chl':
            "|".join(labels),
            'chco':
            options['color']
        })

        self.log.debug("WorkloadChart data: %s" % repr(chart_args))
        if self.serverside_charts:
            return tag.image(
                src="%s?data=%s" %
                (req.href.estimationtools('chart'), unicode_quote(chart_args)),
                alt="Workload Chart (server)")
        else:
            return tag.image(src="https://chart.googleapis.com/chart?%s" %
                             chart_args,
                             alt="Workload Chart (client)")
Exemple #10
0
    def expand_macro(self, formatter, name, content):
        req = formatter.req
        db = self.env.get_db_cnx()
        # prepare options
        options, query_args = parse_options(db, content,
                                            copy.copy(DEFAULT_OPTIONS))

        query_args[self.estimation_field + "!"] = None
        tickets = execute_query(self.env, req, query_args)

        sum = 0.0
        estimations = {}
        for ticket in tickets:
            if ticket['status'] in self.closed_states:
                continue
            try:
                estimation = float(ticket[self.estimation_field])
                owner = ticket['owner']
                sum += estimation
                if estimations.has_key(owner):
                    estimations[owner] += estimation
                else:
                    estimations[owner] = estimation
            except:
                pass

        estimations_string = []
        labels = []
        for owner, estimation in estimations.iteritems():
            # Note: Unconditional obfuscation of owner in case it represents
            # an email adress, and as the chart API doesn't support SSL
            # (plain http transfer only, from either client or server).
            labels.append("%s %g%s" %
                          (obfuscate_email_address(owner), round(
                              estimation, 2), self.estimation_suffix))
            estimations_string.append(str(int(estimation)))

        # Title
        title = 'Workload'

        # calculate remaining work time
        if options.get('today') and options.get('enddate'):
            currentdate = options['today']
            day = timedelta(days=1)
            days_remaining = 0
            while currentdate <= options['enddate']:
                if currentdate.weekday() < 5:
                    days_remaining += 1
                currentdate += day
            title += ' %g%s (~%s workdays left)' % (round(
                sum, 2), self.estimation_suffix, days_remaining)

        chart_args = unicode_urlencode({
            'chs':
            '%sx%s' % (options['width'], options['height']),
            'chf':
            'bg,s,00000000',
            'chd':
            't:%s' % ",".join(estimations_string),
            'cht':
            'p3',
            'chtt':
            title,
            'chl':
            "|".join(labels),
            'chco':
            options['color']
        })
        self.log.debug("WorkloadChart data: %s" % repr(chart_args))
        if self.serverside_charts:
            return tag.image(
                src="%s?data=%s" %
                (req.href.estimationtools('chart'), unicode_quote(chart_args)),
                alt="Workload Chart (server)")
        else:
            return tag.image(src="http://chart.googleapis.com/chart?%s" %
                             chart_args,
                             alt="Workload Chart (client)")