Exemple #1
0
  def expand_macro(self, formatter, name, content, args):

    title = 'Color Scheme'
    classes = 'colormacro' 

    if args and 'title' in args:
      title = args['title']

    if args and 'class' in args:
      classes  += ' ' + args['class']


    tbody = []
    have_comment = False
    colors = self._parse_arguments(content)

    for color in colors:
      if len(color['title']) > 0:
        have_comment = True
      ## Create row
      tbody.append(
        [
          tag.td()(tag.strong(color['title'])),
          tag.td(
              style='background-color:' + color['orig']
            )(
              tag.div(style='color: black')(color['hex']),
              tag.div(style='color: white')(color['hex'])
          ),
          tag.td(
              style='background-color:' + color['orig']
            )(
              tag.div(style='color: black')(color['rgbp']),
              tag.div(style='color: white')(color['rgbp'])
          ),
        ]
      )
      ## end for loop

    if len(tbody) > 0:
      colcount = len(tbody[0])
      if not have_comment:
        colcount -= 1
      
      table = tag.table(class_=classes)
      table()(tag.thead()(tag.th(colspan='%d' % colcount)(title)))
      ## Attach row in table.
      if have_comment:
        table()(tag.tbody(class_='colorlist')([tag.tr(row) for row in tbody]))
      else:
        table()(tag.tbody(class_='colorlist')([tag.tr(row[1:]) for row in tbody]))

      return table;
    else:
      return tag.div(class_='colormacro')('Nothing to display')
Exemple #2
0
 def render(self, context, mimetype, content, filename=None, url=None):
     content = content.read()
     content = re.split('\r[\n]', content) 
     if not content:
         return None
     head = content[0]
     if not head:
         return None
     head = re.split(',', head)
     
     if not head:
         return None
     thead = tag.thead(tag.tr([tag.th(h) for h in head]))
     content = content[1:]
     if not content:
         return None
     tbody = []
     for r in content:
         if r:
             r = re.split(',', r)
             if r:
                 tbody.append(tag.tr([tag.td(c) for c in r ]))
     
     return tag.table(thead,tag.tbody(tbody), 
         class_="wiki")
Exemple #3
0
    def expand_macro(self, formatter, name, args):
        from trac.config import Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        registry = Option.get_registry(self.compmgr)
        sections = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                sections.setdefault(section, {})[key] = option

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             tag.table(class_='wiki')(
                 tag.tbody(tag.tr(tag.td(tag.tt(option.name)),
                                  tag.td(format_to_oneliner(
                                      self.env, formatter.context,
                                      to_unicode(option.__doc__))))
                           for option in sorted(sections[section].itervalues(),
                                                key=lambda o: o.name)
                           if option.name.startswith(key_filter))))
            for section in sorted(sections))
Exemple #4
0
    def expand_macro(self, formatter, name, content):
        from trac.mimeview.api import Mimeview
        mime_map = Mimeview(self.env).mime_map
        mime_type_filter = ''
        args, kw = parse_args(content)
        if args:
            mime_type_filter = args.pop(0).strip().rstrip('*')

        mime_types = {}
        for key, mime_type in mime_map.iteritems():
            if (not mime_type_filter or
                mime_type.startswith(mime_type_filter)) and key != mime_type:
                mime_types.setdefault(mime_type, []).append(key)

        return tag.div(class_='mimetypes')(
            tag.table(class_='wiki')(
                tag.thead(tag.tr(
                    tag.th(_("MIME Types")),  # always use plural
                    tag.th(tag.a("WikiProcessors",
                                 href=formatter.context.href.wiki(
                                     'WikiProcessors'))))),
                tag.tbody(
                    tag.tr(tag.th(tag.tt(mime_type),
                                  style="text-align: left"),
                           tag.td(tag.code(
                               ' '.join(sorted(mime_types[mime_type])))))
                    for mime_type in sorted(mime_types.keys()))))
    def expand_macro(self, formatter, name, content, args={}):
        self.href = formatter.req.href
        db = self.env.get_db_cnx()
        cursor = db.cursor()

        params = [x.strip() for x in content.split(',')]
        pages = [x for x in params if '=' not in x]
        kwargs = dict([x.split('=', 1) for x in params if '=' in x])
        if not pages:
            pages = ['*']

        order = kwargs.get('order') != 'reverse' and 'DESC' or ''
        self.date_format = kwargs.get('date_format', '%Y-%m-%d %H:%M:%S')
        self.pagename = kwargs.get('pagename')

        cursor.execute(
            'SELECT name, time, author, version, comment FROM wiki AS w1' +
            ' WHERE version=(SELECT MAX(version) FROM wiki AS w2 WHERE w1.name=w2.name) AND (' +
            ' OR '.join(['name LIKE "%s"' %  x.replace('*', '%') for x in pages]) + ')' +
            ' ORDER BY time ' + order)

        rows = [self._build_row(*x) for x in cursor]

        return tag.table(self.thead, tag.tbody(rows),
                         class_='wikistatuslist',
                         bgcolor=kwargs.get('bgcolor', '#F0F0F0'))
    def filter_stream(self, req, method, filename, stream, data):
        
        if req.path_info.startswith('/ticket/'):
            div = None
            if 'ticket' in data:
                # get parents data
                ticket = data['ticket']
                # title
                div = tag.div(class_='description')
                if ticket['status'] != 'closed':
                    link = tag.a(_('add'),
                        href=req.href.newticket(parents=ticket.id),
                        title=_('Create new child ticket'))
                    link = tag.span('(', link, ')', class_='addsubticket')
                else:
                    link = None
                div.append(tag.h3(_('Subtickets '), link))

            if 'subtickets' in data:
                # table
                tbody = tag.tbody()
                div.append(tag.table(tbody, class_='subtickets'))

                # tickets
                def _func(children, depth=0):
                    for id in sorted(children, key=lambda x: int(x)):
                        ticket = Ticket(self.env, id)

                        # 1st column
                        attrs = {'href': req.href.ticket(id)}
                        if ticket['status'] == 'closed':
                            attrs['class_'] = 'closed'
                        link = tag.a('#%s' % id, **attrs)
                        summary = tag.td(link, ': %s' % ticket['summary'],
                            style='padding-left: %dpx;' % (depth * 15))
                        # 2nd column
                        type = tag.td(ticket['type'])
                        # 3rd column
                        status = tag.td(ticket['status'])
                        # 4th column
                        href = req.href.query(status='!closed',
                                              owner=ticket['owner'])
                        owner = tag.td(tag.a(ticket['owner'], href=href))

                        tbody.append(tag.tr(summary, type, status, owner))
                        if depth >= 0: 
                            _func(children[id], depth + 1)

                if self.recursion:
                    _func(data['subtickets'])
                else:
                    _func(data['subtickets'],-1)

            if div:
                add_stylesheet(req, 'subtickets/css/subtickets.css')
                stream |= Transformer('.//div[@id="ticket"]').append(div)

        return stream
Exemple #7
0
    def _render_source(self, context, stream, annotations):
        from trac.web.chrome import add_warning

        annotators, labels, titles = {}, {}, {}
        for annotator in self.annotators:
            atype, alabel, atitle = annotator.get_annotation_type()
            if atype in annotations:
                labels[atype] = alabel
                titles[atype] = atitle
                annotators[atype] = annotator
        annotations = [a for a in annotations if a in annotators]

        if isinstance(stream, list):
            stream = HTMLParser(StringIO(u"\n".join(stream)))
        elif isinstance(stream, unicode):
            text = stream

            def linesplitter():
                for line in text.splitlines(True):
                    yield TEXT, line, (None, -1, -1)

            stream = linesplitter()

        annotator_datas = []
        for a in annotations:
            annotator = annotators[a]
            try:
                data = (annotator, annotator.get_annotation_data(context))
            except TracError as e:
                self.log.warning("Can't use annotator '%s': %s", a, e)
                add_warning(
                    context.req,
                    tag.strong(
                        tag_("Can't use %(annotator)s annotator: %(error)s", annotator=tag.em(a), error=tag.pre(e))
                    ),
                )
                data = None, None
            annotator_datas.append(data)

        def _head_row():
            return tag.tr(
                [tag.th(labels[a], class_=a, title=titles[a]) for a in annotations]
                + [tag.th(u"\xa0", class_="content")]
            )

        def _body_rows():
            for idx, line in enumerate(_group_lines(stream)):
                row = tag.tr()
                for annotator, data in annotator_datas:
                    if annotator:
                        annotator.annotate_row(context, row, idx + 1, line, data)
                    else:
                        row.append(tag.td())
                row.append(tag.td(line))
                yield row

        return tag.table(class_="code")(tag.thead(_head_row()), tag.tbody(_body_rows()))
    def expand_macro(self, formatter, name, args):
        if not args:
            return Markup()

        config = None
        if name == self.CONFIG_KEY:
            lines = args.splitlines()
            if not lines or not lines[0].startswith('#!'):
                return Markup()
            config = self._parse_config([i.strip() for i in lines[0][2:].split(',')])
        else:
            config = self.CONFIG[name]

        if not config:
            return Markup()

        def to_html(text):
            if not text:
                return ''
            return Markup('<br>'.join([format_to_oneliner(self.env, formatter.context, line) \
                                for line in text.splitlines()]))

        def has_keys(dict, keys):
            for key in keys:
                if dict.has_key(key):
                    return True
            return False

        rows = self.parse_doc(args)
        if not rows:
            return Markup()

        seen = []
        for desc, keys in config:
            if [row for row in rows if has_keys(row, keys)]:
                seen.append(desc)

        thead = tag.thead()
        for desc, keys in config:
            if not desc in seen:
                continue
            thead(tag.td(tag.b(desc)))

        tbody = tag.tbody()
        for row in rows:
            trow = tag.tr()
            for desc, keys in config:
                if not desc in seen:
                    continue
                tcol = tag.td()
                for key in keys:
                    if row.has_key(key):
                        tcol(to_html(row[key]))
                trow(tcol)
            tbody(trow)

        return tag.table([thead, tbody], class_='wiki')
Exemple #9
0
 def _render_mergeinfo(self, name, mode, context, props):
     rows = []
     for row in props[name].splitlines():
         try:
             (path, revs) = row.rsplit(":", 1)
             rows.append([tag.td(path), tag.td(revs.replace(",", u",\u200b"))])
         except ValueError:
             rows.append(tag.td(row, colspan=2))
     return tag.table(tag.tbody([tag.tr(row) for row in rows]), class_="props")
Exemple #10
0
def render_refs_box(self, req, ids, order = 'year', desc = 1, headhref=False,
    path=[],args=[],page=None,max=None ):
    # Check parameters
    if not ids:
        return []     
    
    columns = self.env.config.get('zotero', 'columns','firstCreator, year, publicationTitle, title' )
    columns = columns.split(',')
    columns = [c.strip() for c in columns]
   
    model = ZoteroModelProvider(self.env)
    if page:
        page = (page-1)*max
    data = model.get_item_columns_by_iids(ids,columns, order, desc = desc, offset=page,limit=max)
    
    apath = args_path(args)
    
    heads = []
    for idx, column in enumerate(columns):
        label = column
        if zotero_fields_mapping_name.has_key(column):
            label = zotero_fields_mapping_name[column]['label']
        if headhref and path:
            head = []
            th_class = ''
            th_href = req.href(path, order=column)+apath
            if order == column:
                if desc:
                    th_class = 'desc'
                else:
                    th_class = 'asc'
                    th_href = req.href(path, order=column, desc = str(1))+apath
            head = tag.th(tag.a(label, href = th_href),class_= th_class)
            heads.append(head)
        else:
            heads.append(tag.th(label))
    body = []
    for idx, item in enumerate(data):
        item_class = 'even'
        if idx % 2 == 1:
            item_class = 'odd'
        item_td = []
        for idx, col in enumerate(columns):
            col_td = []
            if not col or item[idx+1] == 'None':
                col_td = tag.td()
            elif col == 'title':
                col_td = tag.td(tag.a(item[idx+1], 
                    href = req.href.zotero('item',str(item[0]))))
            else:   
                col_td = tag.td(item[idx+1])
            item_td.append(col_td)
        item_tr = tag.tr( item_td,class_=item_class)
        body.append(item_tr)
    return tag.table( tag.thead( heads ), tag.tbody(body),
        class_="listing dirlist", id="dirlist")
Exemple #11
0
    def expand_macro(self, formatter, name, args):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        def getdoc(option_or_section):
            doc = to_unicode(option_or_section.__doc__)
            if doc:
                doc = dgettext(option_or_section.doc_domain, doc)
            return doc

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, getdoc(section))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is True:
                default = 'true'
            elif default is False:
                default = 'false'
            elif default == 0:
                default = '0.0' if isinstance(default, float) else '0'
            elif default:
                default = ', '.join(to_unicode(val) for val in default) \
                          if isinstance(default, (list, tuple)) \
                          else to_unicode(default)
            else:
                return tag.td(_("(no default)"), class_='nodefault')
            return tag.td(tag.code(default), class_='default')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.tt(option.name)),
                        tag.td(format_to_oneliner(
                            self.env, formatter.context, getdoc(option))),
                        default_cell(option))
                 for option in sorted(options.get(section, {}).itervalues(),
                                      key=lambda o: o.name)
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
Exemple #12
0
    def expand_macro(self, formatter, name, args):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict(
            (name, dgettext(section.doc_domain, to_unicode(section.__doc__)))
            for name, section in registry.iteritems()
            if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is True:
                default = 'true'
            elif default is False:
                default = 'false'
            elif default == 0:
                default = '0.0' if isinstance(default, float) else '0'
            elif default:
                default = ', '.join(to_unicode(val) for val in default) \
                          if isinstance(default, (list, tuple)) \
                          else to_unicode(default)
            else:
                return tag.td(_("(no default)"), class_='nodefault')
            return tag.td(tag.code(default), class_='default')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(
                     tag.td(tag.tt(option.name)),
                     tag.td(
                         format_to_oneliner(
                             self.env, formatter.context,
                             dgettext(option.doc_domain,
                                      to_unicode(option.__doc__)))),
                     default_cell(option))
                 for option in sorted(options.get(section, {}).itervalues(),
                                      key=lambda o: o.name)
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
Exemple #13
0
 def _render_mergeinfo(self, name, mode, context, props):
     rows = []
     for row in props[name].splitlines():
         try:
             (path, revs) = row.rsplit(':', 1)
             rows.append([tag.td(path),
                          tag.td(revs.replace(',', u',\u200b'))])
         except ValueError:
             rows.append(tag.td(row, colspan=2))
     return tag.table(tag.tbody([tag.tr(row) for row in rows]),
                      class_='props')
Exemple #14
0
    def expand_macro(self, formatter, name, content):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(content)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        def getdoc(option_or_section):
            doc = to_unicode(option_or_section.__doc__)
            if doc:
                doc = dgettext(option_or_section.doc_domain, doc)
            return doc

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, getdoc(section))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is not None and default != '':
                return tag.td(tag.code(option.dumps(default)),
                              class_='default')
            else:
                return tag.td(_("(no default)"), class_='nodefault')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.code(option.name)),
                        tag.td(
                            format_to_oneliner(self.env, formatter.context,
                                               getdoc(option))),
                        default_cell(option),
                        class_='odd' if idx % 2 else 'even')
                 for idx, option in enumerate(
                     sorted(options.get(section, {}).itervalues(),
                            key=lambda o: o.name))
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
Exemple #15
0
    def expand_macro(self, formatter, name, content):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(content)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        def getdoc(option_or_section):
            doc = to_unicode(option_or_section.__doc__)
            if doc:
                doc = dgettext(option_or_section.doc_domain, doc)
            return doc

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, getdoc(section))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is not None and default != '':
                return tag.td(tag.code(option.dumps(default)),
                              class_='default')
            else:
                return tag.td(_("(no default)"), class_='nodefault')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.tt(option.name)),
                        tag.td(format_to_oneliner(
                            self.env, formatter.context, getdoc(option))),
                        default_cell(option),
                        class_='odd' if idx % 2 else 'even')
                 for idx, option in
                    enumerate(sorted(options.get(section, {}).itervalues(),
                                     key=lambda o: o.name))
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
Exemple #16
0
 def options_table(section, options):
     if options:
         return tag.table(class_='wiki')(
             tag.tbody(
                 tag.tr(
                     tag.td(tag.a(tag.code(option.name),
                                  class_='tracini-option',
                                  href='#%s-%s-option' %
                                       (section, option.name))),
                     tag.td(format_to_html(self.env, formatter.context,
                                           option.doc)),
                     default_cell(option),
                     id='%s-%s-option' % (section, option.name),
                     class_='odd' if idx % 2 else 'even')
              for idx, option in enumerate(options)))
Exemple #17
0
  def expand_macro(self, formatter, name, content, args):
    title = 'Color Gradient'
    classes = 'colorgradient';

    if args and 'title' in args:
      title = args['title']

    if args and 'class' in args:
      classes  += ' ' + args['class']

    colors = self._parse_arguments(content)

    lastcolor = {}
    tbody = []

    for color in colors:
      if 'orig' in lastcolor:
        tbody.append(self._create_gradient(lastcolor, color))
        
      tbody.append([
        tag.td(
          style='background-color:' + color['orig']
        )(
          tag.div(style='color: black')(color['hex']),
          tag.div(style='color: white')(color['hex'])
        ),
        tag.td(
          style='background-color:' + color['orig']
        )(
          tag.div(style='color: black')(color['rgbp']),
          tag.div(style='color: white')(color['rgbp'])
        )
      ])

      lastcolor = color

    ## end for loop

    if len(tbody) > 0:
      
      table = tag.table(class_=classes)
      table()(tag.thead()(tag.th(colspan="2")(title)))
     
      table()(tag.tbody(class_='colorgradient')([tag.tr()(td) for td in tbody]))

      return table;
    else:
      return tag.div(class_='colorgradient')('Nothing to display')
Exemple #18
0
    def expand_macro(self, formatter, name, content):
        content = content.strip() if content else ''
        name_filter = content.strip('*')
        items = {}
        for subscriber in NotificationSystem(self.env).subscribers:
            name = subscriber.__class__.__name__
            if not name_filter or name.startswith(name_filter):
                items[name] = subscriber.description()

        return tag.div(class_='trac-subscriberlist')(tag.table(class_='wiki')(
            tag.thead(tag.tr(tag.th(_("Subscriber")),
                             tag.th(_("Description")))),
            tag.tbody(
                tag.tr(tag.td(tag.code(name)),
                       tag.td(items[name]),
                       class_='odd' if idx % 2 else 'even')
                for idx, name in enumerate(sorted(items.keys())))))
Exemple #19
0
    def _add_custom_field_tables(self, stream, ticket):
        ticket_body = Transformer('//div[@id="ticket"]')

        for table_info in self._get_table_fields(ticket):
            headers = table_info["headers"]
            columns = table_info["columns"]
            tickets = table_info["tickets"]

            table = tag.div(
                tag.h3(table_info["title"]),
                tag.table(
                    tag.thead(self._get_header(headers)),
                    tag.tbody(self._get_body(tickets, columns)),
                    class_="listing tickets",
                ),
            )
            stream = stream | ticket_body.after(table)

        return stream
Exemple #20
0
    def expand_macro(self, formatter, name, content):
        content = content.strip() if content else ''
        name_filter = content.strip('*')
        items = {}
        for subscriber in NotificationSystem(self.env).subscribers:
            name = subscriber.__class__.__name__
            if not name_filter or name.startswith(name_filter):
                items[name] = subscriber.description()

        return tag.div(class_='trac-subscriberlist')(
            tag.table(class_='wiki')(
                tag.thead(tag.tr(
                    tag.th(_("Subscriber")),
                    tag.th(_("Description")))),
                tag.tbody(
                    tag.tr(tag.td(tag.code(name)),
                           tag.td(items[name]),
                           class_='odd' if idx % 2 else 'even')
                    for idx, name in enumerate(sorted(items.keys())))))
    def expand_macro(self, formatter, name, content):

        if self.ACCESS_KEY is None:
            return tag.p("[EC2 access key is missing from trac.ini]")
        
        if self.SECRET_KEY is None:
            return tag.p("[EC2 secret key is missing from trac.ini]")

        ec2 = EC2Connection(self.ACCESS_KEY, self.SECRET_KEY)

        headings = ("Instance", "AMI", "Key", "IP", "State", "Monitored")
        table = tag.table(tag.thead(tag.tr([tag.th(title) for title in headings])), class_="listing")
        tbody = tag.tbody()

        try:
            instance_data = ec2.get_all_instances()
        except UnicodeDecodeError, e:
            self.log.exception("Failed to ec2.get_all_instances() for AWSInstanceTableMacro")
            return tag.div("AWSInstanceTable macro failed.")
Exemple #22
0
    def expand_macro(self, formatter, name, args):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, dgettext(section.doc_domain,
                                        to_unicode(section.__doc__)))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.tt(option.name)),
                        tag.td(format_to_oneliner(
                            self.env, formatter.context,
                            dgettext(option.doc_domain,
                                     to_unicode(option.__doc__)))),
                        tag.td(tag.code(option.default or 'false')
                                   if option.default or option.default is False
                                   else _("(no default)"),
                               class_='default' if option.default or 
                                                   option.default is False 
                                                else 'nodefault'))
                 for option in sorted(options.get(section, {}).itervalues(),
                                      key=lambda o: o.name)
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
Exemple #23
0
    def expand_macro(self, formatter, name, content):
        evs = EarnValueSystem(self.env)
        kwargs = self._parse_arg(content)
        users = evs.get_users(formatter.req, kwargs.get('users', 'authenticated'))
        format = kwargs.get('format', 'table')
        start_time = self._parse_date(kwargs.get('start'), 0)
        end_time = self._parse_date(kwargs.get('end'), None)

        if format == 'plain':
            ev = dict([(u, evs.get_user_ev(u, start_time, end_time)) for u in users])
            tags = []
            for k, v in ev.items():
                tags.append(tag.span(k + ': ' + str(v)))
                tags.append(tag.br)
            return tag.p(*tags)

        elif format == 'table':
            evc = evs.get_users_ev_detail(users, start_time, end_time)
            rows = [tag.tr(
                tag.td(ev['action_name']),
                tag.td(ev['value']),
                tag.td(ev['fullname']),
                tag.td(ev['time']),
                tag.td(ev['summary'])
            ) for evcs in evc.values() for ev in evcs ]
            return tag.div(
                tag.table(tag.thead(
                    tag.tr(
                        tag.th('Action'),
                        tag.th('Value'),
                        tag.th('User'),
                        tag.th('Date'),
                        tag.th('Summary'), class_='trac-columns')
                ),
                tag.tbody(
                    *rows
                ), class_='listing tickets')
            )

        return None
    def _contruct_tickets_table(self, req, ticket, childtickets, priorities):
        # trac.ini : Which columns to display in child ticket listing?
        columns = self.config.getlist('childtickets', 'parent.%s.table_headers' % ticket['type'], default=['summary','owner'])

        tablediv = tag.div()
        tablediv.append(tag.label(tag.input(type="checkbox", id="cb_show_closed"),
                                  "show closed tickets"))

        for tkt_types, type_tickets in groupby(childtickets, lambda t: t['type']):
            tablediv.append(tag.h2("Type: %s" % tkt_types, class_="report-result"))
            tablediv.append(
                    tag.table(
                        tag.thead(
                            tag.tr(
                                tag.th("Ticket",class_="id"),
                                [ tag.th(s.title(),class_=s) for s in columns ])
                            ),
                        tag.tbody([ self._table_row(req,tkt,columns,priorities) for tkt in type_tickets]),
                        class_="listing tickets",
                        )
                    )

        return tablediv
Exemple #25
0
    def expand_macro(self, formatter, name, args):
        from trac.config import Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        sections = set([section for section, option in Option.registry.keys()
                        if section.startswith(section_filter)])

        return tag.div(class_='tracini')(
            [(tag.h2('[%s]' % section, id='%s-section' % section),
              tag.table(class_='wiki')(
            tag.tbody([tag.tr(tag.td(tag.tt(option.name)),
                              tag.td(format_to_oneliner(
                                            self.env, formatter.context,
                                            to_unicode(option.__doc__))))
                       for option in sorted(Option.registry.values(),
                                            key=lambda o: o.name)
                       if option.section == section and
                           option.name.startswith(key_filter)])))
             for section in sorted(sections)])
Exemple #26
0
    def render(self, context, mimetype, content, filename=None, url=None):
        content = content.read()
        content = re.split('\r[\n]', content)
        if not content:
            return None
        head = content[0]
        if not head:
            return None
        head = re.split(',', head)

        if not head:
            return None
        thead = tag.thead(tag.tr([tag.th(h) for h in head]))
        content = content[1:]
        if not content:
            return None
        tbody = []
        for r in content:
            if r:
                r = re.split(',', r)
                if r:
                    tbody.append(tag.tr([tag.td(c) for c in r]))

        return tag.table(thead, tag.tbody(tbody), class_="wiki")
Exemple #27
0
    def filter_stream(self, req, method, filename, stream, data):

        # Tickets will be modified to show the child tickets as a list under the 'Description' section.
        if filename == 'ticket.html':

            # Get the ticket info.
            ticket = data.get('ticket')

            # Modify ticket.html with sub-ticket table, create button, etc...
            # As follows:
            # - If ticket has no child tickets and child tickets are NOT allowed then skip.
            # - If ticket has child tickets and child tickets are NOT allowed (ie. rules changed or ticket type changed after children were assigned),
            #   print list of tickets but do not allow any tickets to be created.
            # - If child tickets are allowed then print list of child tickets or 'No Child Tickets' if non are currently assigned.
            #
            if ticket and ticket.exists:

                filter = Transformer('//div[@class="description"]')
                snippet = tag()

                # Are there any child tickets to display?
                childtickets = [
                    Ticket(self.env, n)
                    for n in self.env.childtickets.get(ticket.id, [])
                ]

                # (tempish) fix for #8612 : force sorting by ticket id
                childtickets = sorted(childtickets, key=lambda t: t.id)

                # trac.ini : Which columns to display in child ticket listing?
                columns = self.config.getlist('childtickets',
                                              'parent.%s.table_headers' %
                                              ticket['type'],
                                              default=['summary', 'owner'])

                # trac.ini : child tickets are allowed.
                if self.config.getbool(
                        'childtickets',
                        'parent.%s.allow_child_tickets' % ticket['type']):

                    # trac.ini : Default 'type' of child tickets?
                    default_child_type = self.config.get(
                        'childtickets',
                        'parent.%s.default_child_type' % ticket['type'],
                        default=self.config.get('ticket', 'default_type'))

                    self.env.log.debug(
                        "TracchildticketsModule : default_child_type: %s" %
                        default_child_type)

                    # Can user create a new ticket? If not, just display title (ie. no 'create' button).
                    if 'TICKET_CREATE' in req.perm(ticket.resource):

                        # Always pass these fields
                        default_child_fields = (tag.input(type="hidden",
                                                          name="parent",
                                                          value='#' +
                                                          str(ticket.id)), )

                        #Pass extra fields defined in inherit parameter of parent
                        inherited_child_fields = [
                            tag.input(type="hidden",
                                      name="%s" % field,
                                      value=ticket[field])
                            for field in self.config.getlist(
                                'childtickets', 'parent.%s.inherit' %
                                ticket['type'])
                        ]

                        # If child types are restricted then create a set of buttons for the allowed types (This will override 'default_child_type).
                        restrict_child_types = self.config.getlist(
                            'childtickets',
                            'parent.%s.restrict_child_type' % ticket['type'],
                            default=[])
                        if not restrict_child_types:
                            # ... create a default submit button
                            submit_button_fields = (
                                tag.input(type="submit",
                                          name="childticket",
                                          value="New Child Ticket",
                                          title="Create a child ticket"),
                                tag.input(type="hidden",
                                          name="type",
                                          value=default_child_type),
                            )
                        else:
                            submit_button_fields = [
                                tag.input(type="submit",
                                          name="type",
                                          value="%s" % ticket_type,
                                          title="Create a %s child ticket" %
                                          ticket_type)
                                for ticket_type in restrict_child_types
                            ]

                        snippet.append(
                            tag.div(
                                tag.form(
                                    tag.div(default_child_fields,
                                            inherited_child_fields,
                                            submit_button_fields,
                                            class_="inlinebuttons"),
                                    method="get",
                                    action=req.href.newticket(),
                                ),
                                tag.h3("Child Tickets",
                                       id="comment:child_tickets"),
                            ))
                    else:
                        snippet.append(
                            tag.div(
                                tag.h3("Child Tickets",
                                       id="comment:child_tickets")))

                # trac.ini : child tickets are NOT allowed but (somehow?!) this parent ticket has children assigned.
                elif childtickets:
                    snippet.append(
                        tag.div(
                            tag.h3("Child Tickets",
                                   id="comment:child_tickets")))

                # Test if the ticket has children: If so, then list in pretty table.
                if childtickets:
                    snippet.append(
                        tag.div(
                            tag.table(
                                tag.thead(
                                    tag.tr(tag.th("Ticket", class_="id"), [
                                        tag.th(s.title(), class_=s)
                                        for s in columns
                                    ])),
                                tag.tbody([
                                    self._table_row(req, tkt, columns)
                                    for tkt in childtickets
                                ]),
                                class_="listing tickets",
                            ), ))
                elif self.config.getbool(
                        'childtickets',
                        'parent.%s.allow_child_tickets' % ticket['type']):
                    snippet.append(tag.div(tag.p("NO SUB-TICKETS.")))

                return stream | filter.append(snippet)

        return stream
Exemple #28
0
        def _body_rows():
            for idx, line in enumerate(_group_lines(stream)):
                row = tag.tr()
                if marks and idx + 1 in marks:
                    row(class_='hilite')
                for annotator, data in annotator_datas:
                    if annotator:
                        annotator.annotate_row(context, row, idx + 1, line,
                                               data)
                    else:
                        row.append(tag.td())
                row.append(tag.td(line))
                yield row

        return tag.table(class_='code')(tag.thead(_head_row()),
                                        tag.tbody(_body_rows()))

    def get_max_preview_size(self):
        """:deprecated: use `max_preview_size` attribute directly."""
        return self.max_preview_size

    def get_charset(self, content='', mimetype=None):
        """Infer the character encoding from the `content` or the `mimetype`.

        `content` is either a `str` or an `unicode` object.
        
        The charset will be determined using this order:
         * from the charset information present in the `mimetype` argument
         * auto-detection of the charset from the `content`
         * the configured `default_charset` 
        """
Exemple #29
0
    def gen_calendar(self, tickets, query, month, width=None, nav=True):
        milestones = self._get_milestones()

        req = self.req
        locale = self._get_locale()
        first_week_day = self._get_first_week_day(locale)
        start_date_format = self.mod.start_date_format
        due_date_format = self.mod.due_date_format

        if not month:
            month = datetime.now(req.tz)
            month = datetime(month.year, month.month, 1).date()

        # init data
        today = datetime.now(req.tz).date()

        # generate calendar data
        weeks = self._get_month_calendar(month.year, month.month,
                                         first_week_day, locale)
        days = sorted(sum(weeks, []))
        tickets = self._filter_tickets(days, tickets, req.tz)
        milestones = self._filter_milestones(days, milestones, req.tz)
        cal = [[{
            'date': day,
            'tickets': tickets[day],
            'milestones': milestones[day]
        } for day in week] for week in weeks]

        def genli(t):
            if isinstance(t, Milestone):
                return self._create_milestone_item(t)
            else:
                return self._create_ticket_item(t)

        def gentd(week_idx, day_info):
            day = day_info['date']
            tt = day_info['milestones'] + day_info['tickets']
            if len(tt) < 6:
                ttshow = tt
                ttall = []
            else:
                ttshow = tt[:4]
                ttall = tt

            tdclass = []
            if day == today:
                tdclass.append('today')
            if day.weekday() in (5, 6):
                tdclass.append('weekend')

            formatted_day = format_date(day, format='long', locale=locale)

            td = tag.td(class_=' '.join(tdclass),
                        data_for_start_date=day.strftime(start_date_format),
                        data_for_due_date=day.strftime(due_date_format),
                        data_fdate=formatted_day)

            label = []
            if day == today:
                label.append(tag.span(_("Today"), class_='today'))
            label.append(
                tag.span(unicode(day.day),
                         class_=('day normal', 'day')[day == today]))
            td(tag.div(label))
            if ttshow:
                td(tag.ul([genli(t) for t in ttshow]))

            if ttall:
                id = 'calendar-more-%s' % str(day)
                td(
                    tag.a(_("%d more tickets...") % (len(ttall) - 4),
                          href='#' + id,
                          class_='show-all-list'),
                    tag.div(tag.h4(formatted_day),
                            tag.ul([genli(t) for t in ttall]),
                            class_='ticketcalendar-popup-list',
                            id=id,
                            data_title=format_date(day,
                                                   locale=locale,
                                                   format='full')))

            return td

        day_names = get_day_names(locale=locale, width='abbreviated')
        day_names = [
            day_names[(idx + first_week_day) % 7] for idx in xrange(7)
        ]

        header = tag.div(class_='ticketcalendar-header')
        if nav:

            def nav_href(d):
                return self.get_box_href(query, d)

            def nav_pager(d):
                return tag.span(tag.a(u'\u25c4',
                                      href=nav_href(d - timedelta(days=1))),
                                tag.a(_("Current month"),
                                      href=nav_href(date.today())),
                                tag.a(u'\u25ba',
                                      href=nav_href(d + timedelta(days=31))),
                                class_='ticketcalendar-pager')

            def nav_macro():
                macro = (
                    '[[TicketCalendar(type=box,month=%(month)s,'
                    'query=%(query)s,order=%(order)s%(extra)s)]]' %
                    (dict(month=month.strftime('%Y-%m'),
                          query=self.build_query_string(query.constraints),
                          order=query.order,
                          extra=query.desc and ',desc=1' or '')))
                text = tag.input(type='text',
                                 readonly='readonly',
                                 size='80',
                                 value=macro,
                                 style='width:0;display:none')
                return tag.span(_("Macro"),
                                text,
                                class_='ticketcalendar-macro')

            header(
                tag.div(nav_macro(),
                        nav_pager(month),
                        class_='ticketcalendar-nav'))

        header(
            tag.h4(
                _("%(month_name)s, %(year)s",
                  month_name=_get_month_name(month, locale),
                  year=month.year)))

        calendar = tag.table(
            tag.thead(tag.tr(tag.th(name) for name in day_names)),
            tag.tbody([
                tag.tr([gentd(idx, d) for d in w]) for idx, w in enumerate(cal)
            ]),
            class_='calendar')

        can_create = 'TICKET_CREATE' in req.perm

        ticket_box = tag.div(
            tag.h4(tag.span('', class_='tc-today-date')),
            tag.ul(
                tag.li(
                    tag.a(tag_(
                        "New ticket with \"%(date)s\" as the start date",
                        date=tag.span('', data='start-date')),
                          data_href=req.href('newticket',
                                             [(self.mod.start_date_name, '')]),
                          class_='newticket-start-date')),
                tag.li(
                    tag.a(tag_("New ticket with \"%(date)s\" as the due date",
                               date=tag.span('', data='due-date')),
                          data_href=req.href('newticket',
                                             [(self.mod.due_date_name, '')]),
                          class_='newticket-due-date'))),
            title=_("Create new ticket"),
            class_='ticketcalendar-newticket-box',
            style='display:none',
            data_writable=(None, 'writable')[can_create])

        class_ = ('ticketcalendar',
                  'ticketcalendar ticketcalendar-can-create')[can_create]
        return tag.div(header,
                       calendar,
                       ticket_box,
                       class_=class_,
                       style=width and ('width: %s' % width) or None)
Exemple #30
0
    def expand_macro(self, formatter, name, arguments):

        self.ref = formatter
        self.tz_info = formatter.req.tz
        self.thistime = datetime.datetime.now(self.tz_info)

        # Parse arguments from macro invocation
        args, kwargs = parse_args(arguments, strict=False)

        # Find out whether use http param, current or macro param year/month
        http_param_year = formatter.req.args.get('year','')
        http_param_month = formatter.req.args.get('month','')

        if http_param_year == "":
            # not clicked on a prev or next button
            if len(args) >= 1 and args[0] <> "*":
                # year given in macro parameters
                year = int(args[0])
            else:
                # use current year
                year = self.thistime.year
        else:
            # year in http params (clicked by user) overrides everything
            year = int(http_param_year)

        if http_param_month == "":
            # not clicked on a prev or next button
            if len(args) >= 2 and args[1] <> "*":
                # month given in macro parameters
                month = int(args[1])
            else:
                # use current month
                month = self.thistime.month
        else:
            # month in http params (clicked by user) overrides everything
            month = int(http_param_month)

        showbuttons = True
        if len(args) >= 3 or kwargs.has_key('nav'):
            try:
                showbuttons = kwargs['nav'] in ["True", "true", "yes", "1"]
            except KeyError:
                showbuttons = args[2] in ["True", "true", "yes", "1"]

        wiki_page_format = "%Y-%m-%d"
        if len(args) >= 4 and args[3] != "*" or kwargs.has_key('wiki'):
            try:
                wiki_page_format = str(kwargs['wiki'])
            except KeyError:
                wiki_page_format = str(args[3])
        # Support relative paths in macro arguments for wiki page links.
        wiki_page_format = self._resolve_relative_name(wiki_page_format,
                                                       formatter.resource.id)

        list_condense = 0
        show_t_open_dates = True
        wiki_page_template = ""
        wiki_subpages = []

        # Read optional check plan.
        check = []
        if kwargs.has_key('check'):
            check = kwargs['check'].split('.')

        if name == 'WikiTicketCalendar':
            if len(args) >= 5 or kwargs.has_key('cdate'):
                try:
                    show_t_open_dates = kwargs['cdate'] in \
                                               ["True", "true", "yes", "1"]
                except KeyError:
                    show_t_open_dates = args[4] in \
                                               ["True", "true", "yes", "1"]

        # Optional page template to create new wiki pages.
        # The default (empty page) is used, if the template name is invalid.
        if len(args) >= 6 or kwargs.has_key('base'):
            try:
                wiki_page_template = kwargs['base']
            except KeyError:
                wiki_page_template = args[5]

        if name == 'WikiTicketCalendar':
            # TracQuery support for ticket selection
            query_args = "id!=0"
            if len(args) >= 7 or kwargs.has_key('query'):
                # prefer query arguments provided by kwargs
                try:
                    query_args = kwargs['query']
                except KeyError:
                    query_args = args[6]
            tickets = WikiCalendarTicketProvider(self.env)
            self.tickets = tickets.harvest(formatter.req, query_args)

            # compress long ticket lists
            if len(args) >= 8 or kwargs.has_key('short'):
                # prefer query arguments provided by kwargs
                try:
                    list_condense = int(kwargs['short'])
                except KeyError:
                    list_condense = int(args[7])

            # control calendar display width
            cal_width = "100%;"
            if len(args) >= 9 or kwargs.has_key('width'):
                # prefer query arguments provided by kwargs
                try:
                    cal_width = kwargs['width']
                except KeyError:
                    cal_width = args[8]

            # multiple wiki (sub)pages per day
            if kwargs.has_key('subpages'):
                wiki_subpages = kwargs['subpages'].split('|')

            # Can use this to change the day the week starts on,
            # but this is a system-wide setting.
            calendar.setfirstweekday(calendar.MONDAY)

        cal = calendar.monthcalendar(year, month)
        curr_day = None
        if year == self.thistime.year and month == self.thistime.month:
            curr_day = self.thistime.day

        # for prev/next navigation links
        prevMonth = month - 1
        nextMonth = month + 1
        nextYear = prevYear = year
        # check for year change (KISS version)
        if prevMonth == 0:
            prevMonth = 12
            prevYear -= 1
        if nextMonth == 13:
            nextMonth = 1
            nextYear += 1

        # for fast-forward/-rewind navigation links
        ffYear = frYear = year
        if month < 4:
            frMonth = month + 9
            frYear -= 1
        else:
            frMonth = month - 3
        if month > 9:
            ffMonth = month - 9
            ffYear += 1
        else:
            ffMonth = month + 3

        last_week_prevMonth = calendar.monthcalendar(prevYear, prevMonth)[-1]
        first_week_nextMonth = calendar.monthcalendar(nextYear, nextMonth)[0]

        # Switch to user's locale, if available.
        try:
            loc_req = str(formatter.req.locale)
        except AttributeError:
            # Available since in Trac 0.12 .
            loc_req = None
        if loc_req:
            loc = locale.getlocale()
            loc_prop = locale.normalize(loc_req)
            try:
                locale.setlocale(locale.LC_TIME, loc_prop)
            except locale.Error:
                try:
                    # Re-try with UTF-8 as last resort.
                    loc_prop = '.'.join([loc_prop.split('.')[0],'utf8'])
                    locale.setlocale(locale.LC_TIME, loc_prop)
                except locale.Error:
                    loc_prop = None
            self.env.log.debug('Locale setting for calendar: ' + str(loc_prop))

        # Finally building the output
        # Begin with caption and optional navigation links
        buff = tag.tr()

        if showbuttons is True:
            # calendar navigation buttons
            nx = 'next'
            pv = 'prev'
            nav_pvY = self._mknav('&lt;&lt;', pv, month, year-1)
            nav_frM = self._mknav('&nbsp;&lt;', pv, frMonth, frYear)
            nav_pvM = self._mknav('&nbsp;&laquo;', pv, prevMonth, prevYear)
            nav_nxM = self._mknav('&raquo;&nbsp;', nx, nextMonth, nextYear)
            nav_ffM = self._mknav('&gt;&nbsp;', nx, ffMonth, ffYear)
            nav_nxY = self._mknav('&gt;&gt;', nx, month, year+1)

            # add buttons for going to previous months and year
            buff(nav_pvY, nav_frM, nav_pvM)

        # The caption will always be there.
        heading = tag.td(
             to_unicode(format_date(self._mkdatetime(year, month), '%B %Y')))
        buff = buff(heading(class_='y'))

        if showbuttons is True:
            # add buttons for going to next months and year
            buff(nav_nxM, nav_ffM, nav_nxY)
        buff = tag.caption(tag.table(tag.tbody(buff)))
        buff = tag.table(buff)
        if name == 'WikiTicketCalendar':
            if cal_width.startswith('+') is True:
                width=":".join(['min-width', cal_width]) 
                buff(class_='wikitcalendar', style=width)
            else:
                buff(class_='wikitcalendar')
        if name == 'WikiCalendar':
                buff(class_='wiki-calendar')

        heading = tag.tr()
        heading(align='center')

        for day in calendar.weekheader(2).split()[:-2]:
            col = tag.th(to_unicode(day))
            col(class_='workday', scope='col')
            heading(col)
        for day in calendar.weekheader(2).split()[-2:]:
            col = tag.th(to_unicode(day))
            col(class_='weekend', scope='col')
            heading(col)

        heading = buff(tag.thead(heading))

        # Building main calendar table body
        buff = tag.tbody()
        w = -1
        for week in cal:
            w = w + 1
            line = tag.tr()
            line(align='right')
            d = -1
            for day in week:
                d = d + 1
                if day:
                    # check for wikipage with name specified in
                    # 'wiki_page_format'
                    wiki = format_date(self._mkdatetime(year, month, day),
                                                         wiki_page_format)
                    if day == curr_day:
                        a_class = 'day today'
                        td_class = 'today'
                    else:
                        a_class = 'day'
                        td_class = 'day'

                    day_dt = self._mkdatetime(year, month, day)
                    if uts:
                        day_ts = to_utimestamp(day_dt)
                        day_ts_eod = day_ts + 86399999999
                    else:
                        day_ts = to_timestamp(day_dt)
                        day_ts_eod = day_ts + 86399

                    # check for milestone(s) on that day
                    db = self.env.get_db_cnx()
                    cursor = db.cursor()
                    cursor.execute("""
                        SELECT name
                          FROM milestone
                         WHERE due >= %s and due <= %s
                    """, (day_ts, day_ts_eod))
                    milestones = tag()
                    for row in cursor:
                        if not a_class.endswith('milestone'):
                            a_class += ' milestone'
                        milestone = to_unicode(row[0])
                        url = self.env.href.milestone(milestone)
                        milestone = '* ' + milestone
                        milestones = tag(milestones,
                                         tag.div(tag.a(milestone, href=url),
                                                 class_='milestone'))
                    day = tag.span(day)
                    day(class_='day')
                    if len(wiki_subpages) > 0:
                        pages = tag(day, Markup('<br />'))
                        for page in wiki_subpages:
                            label = tag(' ', page[0])
                            page = '/'.join([wiki, page])
                            url = self.env.href.wiki(page)
                            pages(self._gen_wiki_links(page, label, 'subpage',
                                                     url, wiki_page_template,
                                                     check))
                    else:
                        url = self.env.href.wiki(wiki)
                        pages = self._gen_wiki_links(wiki, day, a_class,
                                                     url, wiki_page_template,
                                                     check)
                    cell = tag.td(pages)
                    cell(class_=td_class, valign='top')
                    if name == 'WikiCalendar':
                        line(cell)
                    else:
                        if milestones:
                            cell(milestones)
                        else:
                            cell(tag.br())

                        match = []
                        match_od = []
                        ticket_heap = tag('')
                        ticket_list = tag.div('')
                        ticket_list(align='left', class_='condense')

                        # get tickets with due date set to day
                        for t in self.tickets:
                            due = t.get(self.tkt_due_field)
                            if due is None or due in ['', '--']:
                                continue
                            else:
                                if self.tkt_due_format == 'ts':
                                    if not isinstance(due, datetime.datetime):
                                        continue
                                    if uts:
                                        due_ts = to_utimestamp(due)
                                    else:
                                        due_ts = to_timestamp(due)
                                    if due_ts < day_ts or due_ts > day_ts_eod:
                                        continue
                                else:
                                    # Beware: Format might even be unicode str
                                    duedate = format_date(day_dt,
                                                      str(self.tkt_due_format))
                                    if not due == duedate:
                                        continue

                            id = t.get('id')
                            ticket, short = self._gen_ticket_entry(t)
                            ticket_heap(ticket)
                            if not id in match:
                                if len(match) == 0:
                                    ticket_list(short)
                                else:
                                    ticket_list(', ', short)
                                match.append(id)

                        # optionally get tickets created on day
                        if show_t_open_dates is True:
                            ticket_od_list = tag.div('')
                            ticket_od_list(align='left',
                                           class_='opendate_condense')

                            for t in self.tickets:
                                if uts:
                                    ticket_ts = to_utimestamp(t.get('time'))
                                else:
                                    ticket_ts = to_timestamp(t.get('time'))
                                if ticket_ts < day_ts or \
                                        ticket_ts > day_ts_eod:
                                    continue

                                a_class = 'opendate_'
                                id = t.get('id')
                                ticket, short = self._gen_ticket_entry(t,
                                                                  a_class)
                                ticket_heap(ticket)
                                if not id in match:
                                    if len(match_od) == 0:
                                        ticket_od_list(short)
                                    else:
                                        ticket_od_list(', ', short)
                                    match_od.append(id)

                        matches = len(match) + len(match_od)
                        if list_condense > 0 and matches >= list_condense:
                            if len(match_od) > 0:
                                if len(match) > 0:
                                    ticket_list(', ')
                                ticket_list = tag(ticket_list, ticket_od_list)
                            line(cell(ticket_list))
                        else:
                            line(cell(ticket_heap))
                else:
                    if name == 'WikiCalendar':
                        if w == 0:
                            day = last_week_prevMonth[d]
                            wiki = format_date(self._mkdatetime(
                                prevYear, prevMonth, day), wiki_page_format)
                        else:
                            day = first_week_nextMonth[d]
                            wiki = format_date(self._mkdatetime(
                                nextYear, nextMonth, day), wiki_page_format)
                        url = self.env.href.wiki(wiki)
                        a_class = 'day adjacent_month'
                        pages = self._gen_wiki_links(wiki, day, a_class,
                                                 url, wiki_page_template)

                        cell = tag.td(pages)
                        cell(class_='day adjacent_month')
                        line(cell)
                    else:
                        cell = tag.td('')
                        cell(class_='day adjacent_month')
                        line(cell)
            buff(line)

        if loc_req and loc_prop:
            # We may have switched to users locale, resetting now.
            try:
                locale.setlocale(locale.LC_ALL, loc)
                self.env.log.debug('Locale setting restored: ' + str(loc))
            except locale.Error:
                pass

        buff = tag.div(heading(buff))
        if name == 'WikiTicketCalendar':
            if cal_width.startswith('+') is True:
                width=":".join(['width', cal_width]) 
                buff(class_='wikitcalendar', style=width)
            else:
                buff(class_='wikitcalendar')
        if name == 'WikiCalendar':
                buff(class_='wiki-calendar')
        # Add common CSS stylesheet
        if self.internal_css and not self.ref.req.args.get('wikicalendar'):
            # Put definitions directly into the output.
            f = open('/'.join([self.htdocs_path, 'wikicalendar.css']), 'Ur')
            css = tag.style(Markup('<!--\n'), '\n'.join(f.readlines()),
                            Markup('-->\n'))(type="text/css")
            f.close()
            # Add hint to prevent multiple inclusions.
            self.ref.req.args['wikicalendar'] = True
            return tag(css, buff)
        elif not self.ref.req.args.get('wikicalendar'):
            add_stylesheet(self.ref.req, 'wikicalendar/wikicalendar.css')
        return buff
Exemple #31
0
 def make_list(items):
     parts = [item.rsplit('.', 1) for item in items]
     return tag.table(tag.tbody(
         tag.tr(tag.td(c, class_='trac-name'),
                tag.td('(%s.*)' % m, class_='trac-name'))
         for m, c in parts), class_='trac-pluglist')
Exemple #32
0
 def make_list(items):
     parts = [item.rsplit('.', 1) for item in items]
     return tag.table(tag.tbody(
         tag.tr(tag.td(c, class_='trac-name'),
                tag.td('(%s.*)' % m, class_='trac-name'))
         for m, c in parts), class_='trac-pluglist')
Exemple #33
0
     calendar[segment]['isocalendar'] = (None, None, None)
     calendar[segment]['date'] = None
     subtitle = "--"
     mystyle = 'color:#000;'
     mytitle = 'date could not be resolved'
   tr(tag.th(tag.h4(segment, class_ = myclass ), tag.h5( subtitle, style = mystyle, title = mytitle, class_ = myclass  ))) 
   counttickets[segment] = 0
 if self.showsummarypiechart:
   tr(tag.th(tag.h4('Summary', class_ = myclass_org ), tag.h5( 'of all tickets', style = mystyle_org, title = mytitle_org, class_ = myclass_org ))) 
 table(tag.thead(tr)) # Summary
 
 self.macroenv.tracenv.log.debug('tickets in table: '+repr(orderedtickets))
 
 
 # table body
 tbody = tag.tbody()
 counter=0
 
 for o in self.rows:
   if counter % 2 == 1:
     class_ = 'odd'
   else:
     class_ = 'even'
   counter += 1
   tr = tag.tr(class_ = class_)
   
   tr( tag.td(tag.h5(tag.a( o, href=self.macroenv.tracenv.href()+('/query?%s=%s&order=status' % (self.rowtype,o,)) )))) # query owner's tickets
   countStatus = {} # summarize the status of a ticket 
   for segment in self.segments:
     class_ = ''
     if calendar[segment]['date'] == currentDate: # Today
    def render(self, ticketset):
        return_div = tag.div(class_=self.cssclass + ' projectplanrender')

        # check for missing parameters
        missingparameter = False
        if self.rows == [] or self.rows == None:
            return_div(
                tag.div(
                    'Missing parameter "rows": use a semicolon-separated list to input the "'
                    + self.rowtype + '".',
                    class_='ppwarning'))
            missingparameter = True
        if self.rowtype == None or str(self.rowtype).strip() == '':
            return_div(
                tag.div(
                    'Missing parameter "rowtype": specifies the ticket attribute that should be showed at the rows.',
                    class_='ppwarning'))
            missingparameter = True
        if self.cols == [] or self.cols == None:
            return_div(
                tag.div(
                    'Missing parameter: use a semicolon-separated list to input the "cols".',
                    class_='ppwarning'))
            missingparameter = True
        if self.coltype == None or str(self.coltype).strip() == '':
            return_div(
                tag.div(
                    'Missing parameter "coltype": specifies the ticket attribute that should be showed in the columns.',
                    class_='ppwarning'))
            missingparameter = True
        if missingparameter:
            return return_div

        #ul = tag.ul()
        #for tid in ticketset.getIDSortedList():
        #ticket = ticketset.getTicket(tid)
        #ul( tag.li(tid, " ",ticket.getfield('component') , " ", ticket.getfield('owner') ))
        #return_div(ul)
        def getstatistictitle(statusdict):
            mytitle = ''
            mysum = 0
            for status in statusdict:
                mytitle += "%s: %s\n" % (status, str(statusdict[status]))
                mysum += int(statusdict[status])
            mytitle += "%s: %s" % ('number', mysum)
            return mytitle

        def setKV(myStruct, myKey, newValue):
            '''
        shortcut to set the values correctly
        used to reduce the code needed while using a list as key of a dict
      '''
            myStruct[str(myKey)] = newValue

        def tableKeyPrettyPrint(mylist):
            '''
        transform a list of keys to a user readable string
        in: ['a','b'] --> out: 'a|b'
      '''
            return '|'.join(mylist)

        def tableKeyQueryParameter(parameter, mylist):
            '''
        transform a list of keys to a Trac query string parameter  (OR)
        in: x, ['a','b'] --> out: 'x=a&x=b'
      '''
            return '&'.join(["%s=%s" % (parameter, s) for s in mylist])

        chartheight = 80
        chartwidth = 170

        data = {}
        statistics = {}

        # init table data
        for row in self.rows:
            colstatistics = {}
            colkeys = {}
            for col in self.cols:
                # colkeys[col] = []
                setKV(colkeys, col, [])
                # colstatistics[col] = {}
                setKV(colstatistics, col, {})
            # data[row] = colkeys
            setKV(data, row, colkeys)
            # statistics[row] = colstatistics
            setKV(statistics, row, colstatistics)

        for tid in ticketset.getIDSortedList():
            ticket = ticketset.getTicket(tid)
            ticket_rowtype = ticket.getfield(self.rowtype)
            ticket_coltype = ticket.getfield(self.coltype)

            # determine the data cell where the ticket has to be added, keep in mind that rows and cols are list of lists
            for row in self.rows:
                for col in self.cols:
                    if ticket_rowtype in row and ticket_coltype in col:
                        data[str(row)][str(col)].append(
                            ticket
                        )  # save tickets at precise values of row and col
                        self.log_debug('row:%s col:%s append:%s' %
                                       (row, col, tid))

            # if ticket_rowtype in self.rows and ticket_coltype in self.cols :

        # create HTML table
        table = tag.table(class_="data pptableticketperday",
                          border="1",
                          style='width:auto;')

        # create HTML table head
        thead = tag.thead()
        tr = tag.tr()
        tr(tag.th("%s vs %s" % (self.rowtype, self.coltype)))
        for colkey in self.cols:
            tr(
                tag.th(tag.h4(
                    tag.a(tableKeyPrettyPrint(colkey),
                          href=self.macroenv.tracenv.href() +
                          ('/query?%s&order=%s' % (tableKeyQueryParameter(
                              self.coltype, colkey), self.rowtype)))),
                       title="%s is %s" %
                       (self.coltype, tableKeyPrettyPrint(colkey)))
            )  # first line with all colkeys
        if self.showsummarypiechart:
            tr(tag.th(tag.h4("Ticket Overview")))
        thead(tr)
        table(thead)

        # create HTML table body
        tbody = tag.tbody()
        counter = 0

        for rowkey in self.rows:
            # switch line color
            if counter % 2 == 1:
                class_ = 'odd'
            else:
                class_ = 'even'
            counter += 1
            tr = tag.tr(class_=class_)  # new line

            td = tag.td()  # new cell
            td(tag.h5(
                tag.a(tableKeyPrettyPrint(rowkey),
                      href=self.macroenv.tracenv.href() +
                      ('/query?%s&order=%s' % (tableKeyQueryParameter(
                          self.rowtype, rowkey), self.coltype)))),
               title="%s is %s" %
               (self.rowtype,
                tableKeyPrettyPrint(rowkey)))  # first cell contains row key
            tr(td)
            for colkey in self.cols:
                td = tag.td()
                for ticket in data[str(rowkey)][str(colkey)]:
                    td(tag.span(self.createTicketLink(ticket),
                                class_='ticket_inner'),
                       " ",
                       mytitle="%s is %s and %s is %s" %
                       (self.rowtype, rowkey, self.coltype,
                        colkey))  # mytitle might be used later by javascript
                    if not statistics[str(rowkey)][str(colkey)].has_key(
                            ticket.getstatus()):
                        statistics[str(rowkey)][str(colkey)][
                            ticket.getstatus()] = 0
                    statistics[str(rowkey)][str(colkey)][
                        ticket.getstatus()] += 1
                tr(td)

            # compute statistics
            rowstatistics = {}
            count = 0
            for colkey in statistics[str(rowkey)]:
                for status in statistics[str(rowkey)][str(colkey)]:
                    if not rowstatistics.has_key(status):
                        rowstatistics[status] = 0
                    try:
                        rowstatistics[status] += statistics[str(rowkey)][str(
                            colkey)][status]
                        count += statistics[str(rowkey)][str(colkey)][status]
                    except:
                        pass

            if self.showsummarypiechart:
                tr(
                    tag.td(tag.img(src=self.createGoogleChartFromDict(
                        'ColorForStatus',
                        rowstatistics,
                        '%s tickets' % (count, ),
                        height=chartheight)),
                           class_='ppstatistics',
                           title=getstatistictitle(rowstatistics)))  # Summary

            tbody(tr)
        table(tbody)

        # create HTML table foot
        if self.showsummarypiechart:
            fullstatistics = {}
            tfoot = tag.tfoot()
            tr = tag.tr()

            tr(tag.td(tag.h5('Ticket Overview')))

            # create statistics for col
            fullcount = 0
            for colkey in self.cols:
                colstatistics = {}
                colcount = 0
                for rowkey in self.rows:
                    for status in statistics[str(rowkey)][str(colkey)]:
                        if not fullstatistics.has_key(status):
                            fullstatistics[status] = 0
                        if not colstatistics.has_key(status):
                            colstatistics[status] = 0
                        try:
                            colstatistics[status] += statistics[str(rowkey)][
                                str(colkey)][status]
                            colcount += statistics[str(rowkey)][str(
                                colkey)][status]
                            fullstatistics[status] += statistics[str(rowkey)][
                                str(colkey)][status]
                            fullcount += statistics[str(rowkey)][str(
                                colkey)][status]
                        except:
                            pass
                tr(
                    tag.td(
                        tag.img(src=self.createGoogleChartFromDict(
                            'ColorForStatus',
                            colstatistics,
                            '%s tickets' % (colcount, ),
                            height=chartheight)),
                        title=getstatistictitle(colstatistics)))  # Col Summary
            tr(
                tag.td(
                    tag.img(src=self.createGoogleChartFromDict(
                        'ColorForStatus',
                        fullstatistics,
                        '%s tickets' % (fullcount, ),
                        height=chartheight)),
                    class_='ppstatistics',
                    title=getstatistictitle(fullstatistics)))  # Full Summary
            tfoot(tr)
            table(tfoot)

        return_div(table)

        return return_div
    def expand_macro(self, formatter, name, arguments):

        self.ref = formatter
        self.tz_info = formatter.req.tz
        self.thistime = datetime.datetime.now(self.tz_info)

        # Parse arguments from macro invocation
        args, kwargs = parse_args(arguments, strict=False)

        # Find out whether use http param, current or macro param year/month
        http_param_year = formatter.req.args.get('year', '')
        http_param_month = formatter.req.args.get('month', '')

        if http_param_year == "":
            # not clicked on a prev or next button
            if len(args) >= 1 and args[0] <> "*":
                # year given in macro parameters
                year = int(args[0])
            else:
                # use current year
                year = self.thistime.year
        else:
            # year in http params (clicked by user) overrides everything
            year = int(http_param_year)

        if http_param_month == "":
            # not clicked on a prev or next button
            if len(args) >= 2 and args[1] <> "*":
                # month given in macro parameters
                month = int(args[1])
            else:
                # use current month
                month = self.thistime.month
        else:
            # month in http params (clicked by user) overrides everything
            month = int(http_param_month)

        showbuttons = True
        if len(args) >= 3 or kwargs.has_key('nav'):
            try:
                showbuttons = kwargs['nav'] in ["True", "true", "yes", "1"]
            except KeyError:
                showbuttons = args[2] in ["True", "true", "yes", "1"]

        wiki_page_format = "%Y-%m-%d"
        if len(args) >= 4 and args[3] != "*" or kwargs.has_key('wiki'):
            try:
                wiki_page_format = str(kwargs['wiki'])
            except KeyError:
                wiki_page_format = str(args[3])

        show_t_open_dates = True
        if len(args) >= 5 or kwargs.has_key('cdate'):
            try:
                show_t_open_dates = kwargs['cdate'] in \
                                               ["True", "true", "yes", "1"]
            except KeyError:
                show_t_open_dates = args[4] in ["True", "true", "yes", "1"]

        # template name tried to create new pages
        # optional, default (empty page) is used, if name is invalid
        wiki_page_template = ""
        if len(args) >= 6 or kwargs.has_key('base'):
            try:
                wiki_page_template = kwargs['base']
            except KeyError:
                wiki_page_template = args[5]

        # TracQuery support for ticket selection
        query_args = "id!=0"
        if len(args) >= 7 or kwargs.has_key('query'):
            # prefer query arguments provided by kwargs
            try:
                query_args = kwargs['query']
            except KeyError:
                query_args = args[6]
        self.tickets = self._ticket_query(formatter, query_args)

        # compress long ticket lists
        list_condense = 0
        if len(args) >= 8 or kwargs.has_key('short'):
            # prefer query arguments provided by kwargs
            try:
                list_condense = int(kwargs['short'])
            except KeyError:
                list_condense = int(args[7])

        # control calendar display width
        cal_width = "100%;"
        if len(args) >= 9 or kwargs.has_key('width'):
            # prefer query arguments provided by kwargs
            try:
                cal_width = kwargs['width']
            except KeyError:
                cal_width = args[8]

        # Can use this to change the day the week starts on,
        # but this is a system-wide setting.
        calendar.setfirstweekday(calendar.MONDAY)
        cal = calendar.monthcalendar(year, month)

        curr_day = None
        if year == self.thistime.year and month == self.thistime.month:
            curr_day = self.thistime.day

        # Compile regex pattern before use for better performance
        pattern_del = '(?:<span .*?>)|(?:</span>)'
        pattern_del += '|(?:<p>)|(?:<p .*?>)|(?:</p>)'
        pattern_del += '|(?:</table>)|(?:<td.*?\n)|(?:<tr.*?</tr>)'
        self.end_RE = re.compile('(?:</a>)')
        self.del_RE = re.compile(pattern_del)
        self.item_RE = re.compile('(?:<img .*?>)')
        self.open_RE = re.compile('(?:<a .*?>)')
        self.tab_RE = re.compile('(?:<table .*?>)')

        # for prev/next navigation links
        prevMonth = month - 1
        nextMonth = month + 1
        nextYear = prevYear = year
        # check for year change (KISS version)
        if prevMonth == 0:
            prevMonth = 12
            prevYear -= 1
        if nextMonth == 13:
            nextMonth = 1
            nextYear += 1

        # for fast-forward/-rewind navigation links
        ffYear = frYear = year
        if month < 4:
            frMonth = month + 9
            frYear -= 1
        else:
            frMonth = month - 3
        if month > 9:
            ffMonth = month - 9
            ffYear += 1
        else:
            ffMonth = month + 3

        # Finally building the output
        # Prepending inline CSS definitions
        styles = """ \
<!--
table.wikiTicketCalendar th { font-weight: bold; }
table.wikiTicketCalendar th.workday { width: 17%; }
table.wikiTicketCalendar th.weekend { width: 7%; }
table.wikiTicketCalendar caption {
    font-size: 120%; white-space: nowrap;
    }
table.wikiTicketCalendar caption a {
    display: inline; margin: 0; border: 0; padding: 0;
    background-color: transparent; color: #b00; text-decoration: none;
    }
table.wikiTicketCalendar caption a.prev { padding-right: 5px; font: bold; }
table.wikiTicketCalendar caption a.next { padding-left: 5px; font: bold; }
table.wikiTicketCalendar caption a:hover { background-color: #eee; }
table.wikiTicketCalendar td.today {
    background: #fbfbfb; border-color: #444444; color: #444;
    border-style: solid; border-width: 1px;
    }
table.wikiTicketCalendar td.day {
    background: #e5e5e5; border-color: #444444; color: #333;
    border-style: solid; border-width: 1px;
    }
table.wikiTicketCalendar td.fill {
    background: #eee; border-color: #ccc;
    border-style: solid; border-width: 1px;
    }
table.wikiTicketCalendar div.milestone {
    font-size: 9px; background: #f7f7f0; border: 1px solid #d7d7d7;
    border-bottom-color: #999; text-align: left;
    }
table.wikiTicketCalendar a.day {
    width: 2em; height: 100%; margin: 0; border: 0px; padding: 0;
    color: #333; text-decoration: none;
    }
table.wikiTicketCalendar a.day_haspage {
    width: 2em; height: 100%; margin: 0; border: 0px; padding: 0;
    color: #b00 !important; text-decoration: none;
    }
table.wikiTicketCalendar a.day:hover {
    border-color: #eee; background-color: #eee; color: #000;
    }
table.wikiTicketCalendar div.open, span.open   {
    font-size: 9px; color: #000000;
    }
table.wikiTicketCalendar div.closed, span.closed {
    font-size: 9px; color: #777777; text-decoration: line-through;
    }
table.wikiTicketCalendar div.opendate_open, span.opendate_open {
    font-size: 9px; color: #000077;
    }
table.wikiTicketCalendar div.opendate_closed, span.opendate_closed {
    font-size: 9px; color: #000077; text-decoration: line-through;
    }
table.wikiTicketCalendar div.condense { background-color: #e5e5e5; }
table.wikiTicketCalendar div.opendate_condense { background-color: #cdcdfa; }

/* pure CSS style tooltip */
a.tip {
    position: relative; cursor: help;
    }
a.tip span { display: none; }
a.tip:hover span {
    display: block; z-index: 1;
    font-size: 0.75em; text-decoration: none;
    /* big left move because of z-index render bug in IE<8 */
    position: absolute; top: 0.8em; left: 6em;
    border: 1px solid #000; background-color: #fff; padding: 5px;
    }
-->
"""

        # create inline style definition as Genshi fragment
        styles = tag.style(Markup(styles))
        styles(type='text/css')

        # Build caption and optional navigation links
        buff = tag.caption()

        if showbuttons is True:
            # calendar navigation buttons
            nx = 'next'
            pv = 'prev'
            nav_pvY = self._mknav('&nbsp;&lt;&lt;', pv, month, year - 1)
            nav_frM = self._mknav('&nbsp;&lt;&nbsp;', pv, frMonth, frYear)
            nav_pvM = self._mknav('&nbsp;&laquo;&nbsp;', pv, prevMonth,
                                  prevYear)
            nav_nxM = self._mknav('&nbsp;&raquo;&nbsp;', nx, nextMonth,
                                  nextYear)
            nav_ffM = self._mknav('&nbsp;&gt;&nbsp;', nx, ffMonth, ffYear)
            nav_nxY = self._mknav('&nbsp;&gt;&gt;', nx, month, year + 1)

            # add buttons for going to previous months and year
            buff(nav_pvY, nav_frM, nav_pvM)

        # The caption will always be there.
        buff(
            tag.strong(
                to_unicode(format_date(self._mkdatetime(year, month),
                                       '%B %Y'))))

        if showbuttons is True:
            # add buttons for going to next months and year
            buff(nav_nxM, nav_ffM, nav_nxY)

        buff = tag.table(buff)
        width = ":".join(['min-width', cal_width])
        buff(class_='wikiTicketCalendar', style=width)

        heading = tag.tr()
        heading(align='center')

        for day in calendar.weekheader(2).split()[:-2]:
            col = tag.th(day)
            col(class_='workday', scope='col')
            heading(col)
        for day in calendar.weekheader(2).split()[-2:]:
            col = tag.th(day)
            col(class_='weekend', scope='col')
            heading(col)

        heading = buff(tag.thead(heading))

        # Building main calendar table body
        buff = tag.tbody()
        for row in cal:
            line = tag.tr()
            line(align='right')
            for day in row:
                if not day:
                    cell = tag.td('')
                    cell(class_='fill')
                    line(cell)
                else:
                    # check for wikipage with name specified in
                    # 'wiki_page_format'
                    wiki = format_date(self._mkdatetime(year, month, day),
                                       wiki_page_format)
                    url = self.env.href.wiki(wiki)
                    if WikiSystem(self.env).has_page(wiki):
                        a_class = "day_haspage"
                        title = "Go to page %s" % wiki
                    else:
                        a_class = "day"
                        url += "?action=edit"
                        # adding template name, if specified
                        if wiki_page_template != "":
                            url += "&template=" + wiki_page_template
                        title = "Create page %s" % wiki
                    if day == curr_day:
                        td_class = 'today'
                    else:
                        td_class = 'day'

                    cell = tag.a(tag.b(day), href=url)
                    cell(class_=a_class, title_=title)
                    cell = tag.td(cell)
                    cell(class_=td_class, valign='top')

                    day_dt = self._mkdatetime(year, month, day)
                    if uts:
                        day_ts = to_utimestamp(day_dt)
                        day_ts_eod = day_ts + 86399999999
                    else:
                        day_ts = to_timestamp(day_dt)
                        day_ts_eod = day_ts + 86399

                    # check for milestone(s) on that day
                    db = self.env.get_db_cnx()
                    cursor = db.cursor()
                    cursor.execute(
                        """
                        SELECT name
                          FROM milestone
                         WHERE due >= %s and due <= %s
                    """, (day_ts, day_ts_eod))
                    while (1):
                        row = cursor.fetchone()
                        if row is None:
                            cell(tag.br())
                            break
                        else:
                            name = to_unicode(row[0])
                            url = self.env.href.milestone(name)
                            milestone = '* ' + name
                            milestone = tag.div(tag.a(milestone, href=url))
                            milestone(class_='milestone')

                            cell(milestone)

                    match = []
                    match_od = []
                    ticket_heap = tag('')
                    ticket_list = tag.div('')
                    ticket_list(align='left', class_='condense')

                    # get tickets with due date set to day
                    for t in self.tickets:
                        due = t.get(self.due_field_name)
                        if due is None or due in ['', '--']:
                            continue
                        else:
                            if self.due_field_fmt == 'ts':
                                if not isinstance(due, datetime.datetime):
                                    continue
                                else:
                                    if uts:
                                        due_ts = to_utimestamp(due)
                                    else:
                                        due_ts = to_timestamp(due)
                                if due_ts < day_ts or \
                                    due_ts > day_ts_eod:
                                    continue
                            else:
                                duedate = format_date(day_dt,
                                                      self.due_field_fmt)
                                if not due == duedate:
                                    continue

                        id = t.get('id')
                        ticket, short = self._gen_ticket_entry(t)
                        ticket_heap(ticket)
                        if not id in match:
                            if len(match) == 0:
                                ticket_list(short)
                            else:
                                ticket_list(', ', short)
                            match.append(id)

                    # optionally get tickets created on day
                    if show_t_open_dates is True:
                        ticket_od_list = tag.div('')
                        ticket_od_list(align='left',
                                       class_='opendate_condense')

                        for t in self.tickets:
                            if uts:
                                ticket_ts = to_utimestamp(t.get('time'))
                            else:
                                ticket_ts = to_timestamp(t.get('time'))
                            if ticket_ts < day_ts or ticket_ts > day_ts_eod:
                                continue

                            a_class = 'opendate_'
                            id = t.get('id')
                            ticket, short = self._gen_ticket_entry(t, a_class)
                            ticket_heap(ticket)
                            if not id in match:
                                if len(match_od) == 0:
                                    ticket_od_list(short)
                                else:
                                    ticket_od_list(', ', short)
                                match_od.append(id)

                    matches = len(match) + len(match_od)
                    if list_condense > 0 and matches >= list_condense:
                        if len(match_od) > 0:
                            if len(match) > 0:
                                ticket_list(', ')
                            ticket_list = tag(ticket_list, ticket_od_list)
                        line(cell(ticket_list))
                    else:
                        line(cell(ticket_heap))

            buff(line)

        buff = tag.div(heading(buff))
        if cal_width.startswith('+') is True:
            width = ":".join(['width', cal_width])
            buff(class_='wikiTicketCalendar', style=width)
        else:
            buff(class_='wikiTicketCalendar')

        # Finally prepend prepared CSS styles
        buff = tag(styles, buff)

        return buff
            counttickets[segment] = 0
        if self.showsummarypiechart:
            tr(
                tag.th(
                    tag.h4('Summary', class_=myclass_org),
                    tag.h5('of all tickets',
                           style=mystyle_org,
                           title=mytitle_org,
                           class_=myclass_org)))
        table(tag.thead(tr))  # Summary

        self.macroenv.tracenv.log.debug('tickets in table: ' +
                                        repr(orderedtickets))

        # table body
        tbody = tag.tbody()
        counter = 0

        for o in self.rows:
            if counter % 2 == 1:
                class_ = 'odd'
            else:
                class_ = 'even'
            counter += 1
            tr = tag.tr(class_=class_)

            tr(
                tag.td(
                    tag.h5(
                        tag.a(o,
                              href=self.macroenv.tracenv.href() +
Exemple #37
0
    def render_property_diff(self, name, old_context, old_props, new_context,
                             new_props, options):
        # Build 5 columns table showing modifications on merge sources
        # || source || added || removed || added (ni) || removed (ni) ||
        # || source || removed                                        ||
        rm = RepositoryManager(self.env)
        repos = rm.get_repository(old_context.resource.parent.id)

        def parse_sources(props):
            sources = {}
            for line in props[name].splitlines():
                path, revs = line.split(':', 1)
                spath = _path_within_scope(repos.scope, path)
                if spath is not None:
                    inheritable, non_inheritable = _partition_inheritable(revs)
                    sources[spath] = (set(Ranges(inheritable)),
                                      set(Ranges(non_inheritable)))
            return sources

        old_sources = parse_sources(old_props)
        new_sources = parse_sources(new_props)
        # Go through new sources, detect modified ones or added ones
        blocked = name.endswith('blocked')
        added_label = [_("merged: "), _("blocked: ")][blocked]
        removed_label = [_("reverse-merged: "), _("un-blocked: ")][blocked]
        added_ni_label = _("marked as non-inheritable: ")
        removed_ni_label = _("unmarked as non-inheritable: ")

        def revs_link(revs, context):
            if revs:
                revs = to_ranges(revs)
                return _get_revs_link(revs.replace(',', u',\u200b'), context,
                                      spath, revs)

        modified_sources = []
        for spath, (new_revs, new_revs_ni) in new_sources.iteritems():
            if spath in old_sources:
                (old_revs, old_revs_ni), status = old_sources.pop(spath), None
            else:
                old_revs = old_revs_ni = set()
                status = _(' (added)')
            added = new_revs - old_revs
            removed = old_revs - new_revs
            added_ni = new_revs_ni - old_revs_ni
            removed_ni = old_revs_ni - new_revs_ni
            try:
                all_revs = set(repos._get_node_revs(spath))
                # TODO: also pass first_rev here, for getting smaller a set
                #       (this is an optmization fix, result is already correct)
                added &= all_revs
                removed &= all_revs
                added_ni &= all_revs
                removed_ni &= all_revs
            except NoSuchNode:
                pass
            if added or removed:
                modified_sources.append(
                    (spath, [_get_source_link(spath, new_context),
                             status], added
                     and tag(added_label, revs_link(added, new_context)),
                     removed
                     and tag(removed_label, revs_link(removed, old_context)),
                     added_ni
                     and tag(added_ni_label, revs_link(added_ni, new_context)),
                     removed_ni and tag(removed_ni_label,
                                        revs_link(removed_ni, old_context))))
        # Go through remaining old sources, those were deleted
        removed_sources = []
        for spath, old_revs in old_sources.iteritems():
            removed_sources.append(
                (spath, _get_source_link(spath, old_context)))
        if modified_sources or removed_sources:
            modified_sources.sort()
            removed_sources.sort()
            changes = tag.table(tag.tbody([
                tag.tr(tag.td(c) for c in cols[1:])
                for cols in modified_sources
            ], [
                tag.tr(tag.td(src), tag.td(_('removed'), colspan=4))
                for spath, src in removed_sources
            ]),
                                class_='props')
        else:
            changes = tag.em(_(' (with no actual effect on merging)'))
        return tag.li(tag_('Property %(prop)s changed', prop=tag.strong(name)),
                      changes)
Exemple #38
0
    def filter_stream(self, req, method, filename, stream, data):

        # Tickets will be modified to show the child tickets as a list under the 'Description' section.
        if filename == 'ticket.html':

            # Get the ticket info.
            ticket = data.get('ticket')

            # Modify ticket.html with sub-ticket table, create button, etc...
            # As follows:
            # - If ticket has no child tickets and child tickets are NOT allowed then skip.
            # - If ticket has child tickets and child tickets are NOT allowed (ie. rules changed or ticket type changed after children were assigned),
            #   print list of tickets but do not allow any tickets to be created.
            # - If child tickets are allowed then print list of child tickets or 'No Child Tickets' if non are currently assigned.
            # 
            if ticket and ticket.exists:

                filter = Transformer('//div[@class="description"]')
                snippet = tag()
                
                # Are there any child tickets to display?
                childtickets = [ Ticket(self.env,n) for n in self.env.childtickets.get(ticket.id,[]) ]

                # (tempish) fix for #8612 : force sorting by ticket id
                childtickets = sorted(childtickets, key=lambda t: t.id)


                # trac.ini : Which columns to display in child ticket listing?
                columns = self.config.getlist('childtickets', 'parent.%s.table_headers' % ticket['type'], default=['summary','owner'])

                # trac.ini : child tickets are allowed.
                if self.config.getbool('childtickets', 'parent.%s.allow_child_tickets' % ticket['type']):

                    # trac.ini : Default 'type' of child tickets?
                    default_child_type = self.config.get('childtickets', 'parent.%s.default_child_type' % ticket['type'], default=self.config.get('ticket','default_type'))

                    self.env.log.debug("TracchildticketsModule : default_child_type: %s" % default_child_type)

                    # Can user create a new ticket? If not, just display title (ie. no 'create' button).
                    if 'TICKET_CREATE' in req.perm(ticket.resource):

                        # Always pass these fields
                        default_child_fields = (
                                tag.input(type="hidden", name="parent", value='#'+str(ticket.id)),
                                )

                        #Pass extra fields defined in inherit parameter of parent
                        inherited_child_fields = [
                                tag.input(type="hidden",name="%s"%field,value=ticket[field]) for field in self.config.getlist('childtickets','parent.%s.inherit' % ticket['type'])
                                ]

                        # If child types are restricted then create a set of buttons for the allowed types (This will override 'default_child_type).
                        restrict_child_types = self.config.getlist('childtickets','parent.%s.restrict_child_type' % ticket['type'],default=[])
                        if not restrict_child_types:
                            # ... create a default submit button
                            submit_button_fields = (
                                    tag.input(type="submit",name="childticket",value="New Child Ticket",title="Create a child ticket"),
                                    tag.input(type="hidden", name="type", value=default_child_type),
                                    )
                        else:
                            submit_button_fields = [ tag.input(type="submit",name="type",value="%s" % ticket_type,title="Create a %s child ticket" % ticket_type) for ticket_type in restrict_child_types ]
        
                        snippet.append(tag.div(
                            tag.form(
                                tag.div( default_child_fields, inherited_child_fields, submit_button_fields, class_="inlinebuttons"),                            
                                method="get", action=req.href.newticket(),
                                ),
                            tag.h3("Child Tickets",id="comment:child_tickets"),
                            ))
                    else:
                        snippet.append(tag.div(tag.h3("Child Tickets",id="comment:child_tickets")))

                # trac.ini : child tickets are NOT allowed but (somehow?!) this parent ticket has children assigned.
                elif childtickets:
                    snippet.append(tag.div(tag.h3("Child Tickets",id="comment:child_tickets")))

                # Test if the ticket has children: If so, then list in pretty table.
                if childtickets:
                    snippet.append(
                            tag.div(
                                tag.table(
                                    tag.thead(
                                        tag.tr(
                                            tag.th("Ticket",class_="id"),
                                            [ tag.th(s.title(),class_=s) for s in columns ])
                                        ),
                                    tag.tbody([ self._table_row(req,tkt,columns) for tkt in childtickets ]),
                                    class_="listing tickets",
                                    ),
                                )
                            )
                elif self.config.getbool('childtickets', 'parent.%s.allow_child_tickets' % ticket['type']):
                    snippet.append(tag.div(tag.p("NO SUB-TICKETS.")))

                return stream | filter.append(snippet)

        return stream
Exemple #39
0
    def render_property_diff(self, name, old_context, old_props,
                             new_context, new_props, options):
        # Build 5 columns table showing modifications on merge sources
        # || source || added || removed || added (ni) || removed (ni) ||
        # || source || removed                                        ||
        rm = RepositoryManager(self.env)
        repos = rm.get_repository(old_context.resource.parent.id)
        def parse_sources(props):
            sources = {}
            for line in props[name].splitlines():
                path, revs = line.split(':', 1)
                spath = _path_within_scope(repos.scope, path)
                if spath is not None:
                    inheritable, non_inheritable = _partition_inheritable(revs)
                    sources[spath] = (set(Ranges(inheritable)),
                                      set(Ranges(non_inheritable)))
            return sources
        old_sources = parse_sources(old_props)
        new_sources = parse_sources(new_props)
        # Go through new sources, detect modified ones or added ones
        blocked = name.endswith('blocked')
        added_label = [_("merged: "), _("blocked: ")][blocked]
        removed_label = [_("reverse-merged: "), _("un-blocked: ")][blocked]
        added_ni_label = _("marked as non-inheritable: ")
        removed_ni_label = _("unmarked as non-inheritable: ")

        sources = []
        changed_revs = {}
        changed_nodes = []
        for spath, (new_revs, new_revs_ni) in new_sources.iteritems():
            new_spath = spath not in old_sources
            if new_spath:
                old_revs = old_revs_ni = set()
            else:
                old_revs, old_revs_ni = old_sources.pop(spath)
            added = new_revs - old_revs
            removed = old_revs - new_revs
            # unless new revisions differ from old revisions
            if not added and not removed:
                continue
            added_ni = new_revs_ni - old_revs_ni
            removed_ni = old_revs_ni - new_revs_ni
            revs = sorted(added | removed | added_ni | removed_ni)
            try:
                node = repos.get_node(spath, revs[-1])
                changed_nodes.append((node, revs[0]))
            except NoSuchNode:
                pass
            sources.append((spath, new_spath, added, removed, added_ni,
                            removed_ni))
        if changed_nodes:
            changed_revs = repos._get_changed_revs(changed_nodes)

        def revs_link(revs, context):
            if revs:
                revs = to_ranges(revs)
                return _get_revs_link(revs.replace(',', u',\u200b'),
                                      context, spath, revs)
        modified_sources = []
        for spath, new_spath, added, removed, added_ni, removed_ni in sources:
            if spath in changed_revs:
                revs = set(changed_revs[spath])
                added &= revs
                removed &= revs
                added_ni &= revs
                removed_ni &= revs
            if added or removed:
                if new_spath:
                    status = _(" (added)")
                else:
                    status = None
                modified_sources.append((
                    spath, [_get_source_link(spath, new_context), status],
                    added and tag(added_label, revs_link(added, new_context)),
                    removed and tag(removed_label,
                                    revs_link(removed, old_context)),
                    added_ni and tag(added_ni_label,
                                     revs_link(added_ni, new_context)),
                    removed_ni and tag(removed_ni_label,
                                       revs_link(removed_ni, old_context))
                    ))
        # Go through remaining old sources, those were deleted
        removed_sources = []
        for spath, old_revs in old_sources.iteritems():
            removed_sources.append((spath,
                                    _get_source_link(spath, old_context)))
        if modified_sources or removed_sources:
            modified_sources.sort()
            removed_sources.sort()
            changes = tag.table(tag.tbody(
                [tag.tr(tag.td(c) for c in cols[1:])
                 for cols in modified_sources],
                [tag.tr(tag.td(src), tag.td(_('removed'), colspan=4))
                 for spath, src in removed_sources]), class_='props')
        else:
            changes = tag.em(_(' (with no actual effect on merging)'))
        return tag.li(tag_('Property %(prop)s changed', prop=tag.strong(name)),
                      changes)
Exemple #40
0
    def render_property(self, name, mode, context, props):
        """Parse svn:mergeinfo and svnmerge-* properties, converting branch
        names to links and providing links to the revision log for merged
        and eligible revisions.
        """
        has_eligible = name in ('svnmerge-integrated', 'svn:mergeinfo')
        revs_label = _('blocked') if name.endswith('blocked') else _('merged')
        revs_cols = 2 if has_eligible else None
        reponame = context.resource.parent.id
        target_path = context.resource.id
        repos = RepositoryManager(self.env).get_repository(reponame)
        target_rev = context.resource.version
        if has_eligible:
            node = repos.get_node(target_path, target_rev)
            branch_starts = {}
            for path, rev in node.get_copy_ancestry():
                if path not in branch_starts:
                    branch_starts[path] = rev + 1
        rows = []
        eligible_infos = []
        if name.startswith('svnmerge-'):
            sources = props[name].split()
        else:
            sources = props[name].splitlines()
        for line in sources:
            path, revs = line.split(':', 1)
            spath = _path_within_scope(repos.scope, path)
            if spath is None:
                continue
            revs = revs.strip()
            inheritable, non_inheritable = _partition_inheritable(revs)
            revs = ','.join(inheritable)
            deleted = False
            try:
                node = repos.get_node(spath, target_rev)
                resource = context.resource.parent.child('source', spath)
                if 'LOG_VIEW' in context.perm(resource):
                    row = [
                        _get_source_link(spath, context),
                        _get_revs_link(revs_label, context, spath, revs)
                    ]
                    if non_inheritable:
                        non_inheritable = ','.join(non_inheritable)
                        row.append(
                            _get_revs_link(
                                _('non-inheritable'), context, spath,
                                non_inheritable,
                                _('merged on the directory '
                                  'itself but not below')))
                    if has_eligible:
                        first_rev = branch_starts.get(spath)
                        if not first_rev:
                            first_rev = node.get_branch_origin()
                        eligible = set(xrange(first_rev or 1, target_rev + 1))
                        eligible -= set(Ranges(revs))
                        blocked = _get_blocked_revs(props, name, spath)
                        if blocked:
                            eligible -= set(Ranges(blocked))
                        if eligible:
                            node = repos.get_node(spath, max(eligible))
                            eligible_infos.append((spath, node, eligible, row))
                            continue
                        eligible = to_ranges(eligible)
                        row.append(
                            _get_revs_link(_('eligible'), context, spath,
                                           eligible))
                    rows.append((False, spath, [tag.td(each) for each in row]))
                    continue
            except NoSuchNode:
                deleted = True
            revs = revs.replace(',', u',\u200b')
            rows.append(
                (deleted, spath,
                 [tag.td('/' + spath),
                  tag.td(revs, colspan=revs_cols)]))

        # fetch eligible revisions for each path at a time
        changed_revs = {}
        changed_nodes = [(node, min(eligible))
                         for spath, node, eligible, row in eligible_infos]
        if changed_nodes:
            changed_revs = repos._get_changed_revs(changed_nodes)
        for spath, node, eligible, row in eligible_infos:
            if spath in changed_revs:
                eligible &= set(changed_revs[spath])
            else:
                eligible.clear()
            row.append(
                _get_revs_link(_("eligible"), context, spath,
                               to_ranges(eligible)))
            rows.append((False, spath, [tag.td(each) for each in row]))

        if not rows:
            return None
        rows.sort()
        if rows and rows[-1][0]:
            toggledeleted = tag.a(_("(toggle deleted branches)"),
                                  class_='trac-toggledeleted',
                                  href='#')
        else:
            toggledeleted = None
        return tag(
            toggledeleted,
            tag.table(tag.tbody([
                tag.tr(row, class_='trac-deleted' if deleted else None)
                for deleted, spath, row in rows
            ]),
                      class_='props'))
Exemple #41
0
    def render_property_diff(self, name, old_context, old_props, new_context,
                             new_props, options):
        # Build 5 columns table showing modifications on merge sources
        # || source || added || removed || added (ni) || removed (ni) ||
        # || source || removed                                        ||
        rm = RepositoryManager(self.env)
        repos = rm.get_repository(old_context.resource.parent.id)

        def parse_sources(props):
            sources = {}
            value = props[name]
            lines = value.splitlines() if name == 'svn:mergeinfo' \
                                       else value.split()
            for line in lines:
                path, revs = line.split(':', 1)
                spath = _path_within_scope(repos.scope, path)
                if spath is not None:
                    inheritable, non_inheritable = _partition_inheritable(revs)
                    sources[spath] = (set(Ranges(inheritable)),
                                      set(Ranges(non_inheritable)))
            return sources

        old_sources = parse_sources(old_props)
        new_sources = parse_sources(new_props)
        # Go through new sources, detect modified ones or added ones
        blocked = name.endswith('blocked')
        added_label = [_("merged: "), _("blocked: ")][blocked]
        removed_label = [_("reverse-merged: "), _("un-blocked: ")][blocked]
        added_ni_label = _("marked as non-inheritable: ")
        removed_ni_label = _("unmarked as non-inheritable: ")

        sources = []
        changed_revs = {}
        changed_nodes = []
        for spath, (new_revs, new_revs_ni) in new_sources.iteritems():
            new_spath = spath not in old_sources
            if new_spath:
                old_revs = old_revs_ni = set()
            else:
                old_revs, old_revs_ni = old_sources.pop(spath)
            added = new_revs - old_revs
            removed = old_revs - new_revs
            # unless new revisions differ from old revisions
            if not added and not removed:
                continue
            added_ni = new_revs_ni - old_revs_ni
            removed_ni = old_revs_ni - new_revs_ni
            revs = sorted(added | removed | added_ni | removed_ni)
            try:
                node = repos.get_node(spath, revs[-1])
                changed_nodes.append((node, revs[0]))
            except NoSuchNode:
                pass
            sources.append(
                (spath, new_spath, added, removed, added_ni, removed_ni))
        if changed_nodes:
            changed_revs = repos._get_changed_revs(changed_nodes)

        def revs_link(revs, context):
            if revs:
                revs = to_ranges(revs)
                return _get_revs_link(revs.replace(',', u',\u200b'), context,
                                      spath, revs)

        modified_sources = []
        for spath, new_spath, added, removed, added_ni, removed_ni in sources:
            if spath in changed_revs:
                revs = set(changed_revs[spath])
                added &= revs
                removed &= revs
                added_ni &= revs
                removed_ni &= revs
            if added or removed:
                if new_spath:
                    status = _(" (added)")
                else:
                    status = None
                modified_sources.append(
                    (spath, [_get_source_link(spath, new_context),
                             status], added
                     and tag(added_label, revs_link(added, new_context)),
                     removed
                     and tag(removed_label, revs_link(removed, old_context)),
                     added_ni
                     and tag(added_ni_label, revs_link(added_ni, new_context)),
                     removed_ni and tag(removed_ni_label,
                                        revs_link(removed_ni, old_context))))
        # Go through remaining old sources, those were deleted
        removed_sources = []
        for spath, old_revs in old_sources.iteritems():
            removed_sources.append(
                (spath, _get_source_link(spath, old_context)))
        if modified_sources or removed_sources:
            modified_sources.sort()
            removed_sources.sort()
            changes = tag.table(tag.tbody([
                tag.tr(tag.td(c) for c in cols[1:])
                for cols in modified_sources
            ], [
                tag.tr(tag.td(src), tag.td(_('removed'), colspan=4))
                for spath, src in removed_sources
            ]),
                                class_='props')
        else:
            changes = tag.em(_(' (with no actual effect on merging)'))
        return tag.li(tag_('Property %(prop)s changed', prop=tag.strong(name)),
                      changes)
Exemple #42
0
    def expand_macro(self, formatter, name, arguments):

        self.ref = formatter
        self.tz_info = formatter.req.tz
        self.thistime = datetime.datetime.now(self.tz_info)

        # Add CSS stylesheet
        add_stylesheet(self.ref.req,
            'wikiticketcalendar/css/wikiticketcalendar.css')


        # Parse arguments from macro invocation
        args, kwargs = parse_args(arguments, strict=False)

        # Find out whether use http param, current or macro param year/month
        http_param_year = formatter.req.args.get('year','')
        http_param_month = formatter.req.args.get('month','')

        if http_param_year == "":
            # not clicked on a prev or next button
            if len(args) >= 1 and args[0] <> "*":
                # year given in macro parameters
                year = int(args[0])
            else:
                # use current year
                year = self.thistime.year
        else:
            # year in http params (clicked by user) overrides everything
            year = int(http_param_year)

        if http_param_month == "":
            # not clicked on a prev or next button
            if len(args) >= 2 and args[1] <> "*":
                # month given in macro parameters
                month = int(args[1])
            else:
                # use current month
                month = self.thistime.month
        else:
            # month in http params (clicked by user) overrides everything
            month = int(http_param_month)

        showbuttons = True
        if len(args) >= 3 or kwargs.has_key('nav'):
            try:
                showbuttons = kwargs['nav'] in ["True", "true", "yes", "1"]
            except KeyError:
                showbuttons = args[2] in ["True", "true", "yes", "1"]

        wiki_page_format = "%Y-%m-%d"
        if len(args) >= 4 and args[3] != "*" or kwargs.has_key('wiki'):
            try:
                wiki_page_format = str(kwargs['wiki'])
            except KeyError:
                wiki_page_format = str(args[3])

        show_t_open_dates = True
        if len(args) >= 5 or kwargs.has_key('cdate'):
            try:
                show_t_open_dates = kwargs['cdate'] in \
                                               ["True", "true", "yes", "1"]
            except KeyError:
                show_t_open_dates = args[4] in ["True", "true", "yes", "1"]

        # template name tried to create new pages
        # optional, default (empty page) is used, if name is invalid
        wiki_page_template = ""
        if len(args) >= 6 or kwargs.has_key('base'):
            try:
                wiki_page_template = kwargs['base']
            except KeyError:
                wiki_page_template = args[5]

        # TracQuery support for ticket selection
        query_args = "id!=0"
        if len(args) >= 7 or kwargs.has_key('query'):
            # prefer query arguments provided by kwargs
            try:
                query_args = kwargs['query']
            except KeyError:
                query_args = args[6]
        self.tickets = self._ticket_query(formatter, query_args)

        # compress long ticket lists
        list_condense = 0
        if len(args) >= 8 or kwargs.has_key('short'):
            # prefer query arguments provided by kwargs
            try:
                list_condense = int(kwargs['short'])
            except KeyError:
                list_condense = int(args[7])

        # control calendar display width
        cal_width = "100%;"
        if len(args) >= 9 or kwargs.has_key('width'):
            # prefer query arguments provided by kwargs
            try:
                cal_width = kwargs['width']
            except KeyError:
                cal_width = args[8]


        # Can use this to change the day the week starts on,
        # but this is a system-wide setting.
        calendar.setfirstweekday(calendar.MONDAY)
        cal = calendar.monthcalendar(year, month)

        curr_day = None
        if year == self.thistime.year and month == self.thistime.month:
            curr_day = self.thistime.day

        # Compile regex pattern before use for better performance
        pattern_del  = '(?:<span .*?>)|(?:</span>)'
        pattern_del += '|(?:<p>)|(?:<p .*?>)|(?:</p>)'
        pattern_del += '|(?:</table>)|(?:<td.*?\n)|(?:<tr.*?</tr>)'
        self.end_RE  = re.compile('(?:</a>)')
        self.del_RE  = re.compile(pattern_del)
        self.item_RE = re.compile('(?:<img .*?>)')
        self.open_RE = re.compile('(?:<a .*?>)')
        self.tab_RE  = re.compile('(?:<table .*?>)')

        # for prev/next navigation links
        prevMonth = month - 1
        nextMonth = month + 1
        nextYear = prevYear = year
        # check for year change (KISS version)
        if prevMonth == 0:
            prevMonth = 12
            prevYear -= 1
        if nextMonth == 13:
            nextMonth = 1
            nextYear += 1

        # for fast-forward/-rewind navigation links
        ffYear = frYear = year
        if month < 4:
            frMonth = month + 9
            frYear -= 1
        else:
            frMonth = month - 3
        if month > 9:
            ffMonth = month - 9
            ffYear += 1
        else:
            ffMonth = month + 3


        # Finally building the output
        # Begin with caption and optional navigation links
        buff = tag.caption()

        if showbuttons is True:
            # calendar navigation buttons
            nx = 'next'
            pv = 'prev'
            nav_pvY = self._mknav('&nbsp;&lt;&lt;', pv, month, year-1)
            nav_frM = self._mknav('&nbsp;&lt;&nbsp;', pv, frMonth, frYear)
            nav_pvM = self._mknav('&nbsp;&laquo;&nbsp;', pv, prevMonth,
                                                                 prevYear)
            nav_nxM = self._mknav('&nbsp;&raquo;&nbsp;', nx, nextMonth,
                                                                 nextYear)
            nav_ffM = self._mknav('&nbsp;&gt;&nbsp;', nx, ffMonth, ffYear)
            nav_nxY = self._mknav('&nbsp;&gt;&gt;', nx, month, year+1)

            # add buttons for going to previous months and year
            buff(nav_pvY, nav_frM, nav_pvM)

        # The caption will always be there.
        buff(tag.strong(to_unicode(format_date(self._mkdatetime(
                                               year, month), '%B %Y'))))

        if showbuttons is True:
            # add buttons for going to next months and year
            buff(nav_nxM, nav_ffM, nav_nxY)

        buff = tag.table(buff)
        width=":".join(['min-width', cal_width]) 
        buff(class_='wikiTicketCalendar', style=width)

        heading = tag.tr()
        heading(align='center')

        for day in calendar.weekheader(2).split()[:-2]:
            col = tag.th(day)
            col(class_='workday', scope='col')
            heading(col)
        for day in calendar.weekheader(2).split()[-2:]:
            col = tag.th(day)
            col(class_='weekend', scope='col')
            heading(col)

        heading = buff(tag.thead(heading))

        # Building main calendar table body
        buff = tag.tbody()
        for row in cal:
            line = tag.tr()
            line(align='right')
            for day in row:
                if not day:
                    cell = tag.td('')
                    cell(class_='fill')
                    line(cell)
                else:
                    # check for wikipage with name specified in
                    # 'wiki_page_format'
                    wiki = format_date(self._mkdatetime(year, month, day),
                                                         wiki_page_format)
                    url = self.env.href.wiki(wiki)
                    if WikiSystem(self.env).has_page(wiki):
                        a_class = "day_haspage"
                        title = _("Go to page %s") % wiki
                    else:
                        a_class = "day"
                        url += "?action=edit"
                        # adding template name, if specified
                        if wiki_page_template != "":
                            url += "&template=" + wiki_page_template
                        title = _("Create page %s") % wiki
                    if day == curr_day:
                        td_class = 'today'
                    else:
                        td_class = 'day'

                    cell = tag.a(tag.b(day), href=url)
                    cell(class_=a_class, title_=title)
                    cell = tag.td(cell)
                    cell(class_=td_class, valign='top')

                    day_dt = self._mkdatetime(year, month, day)
                    day_ts = to_utimestamp(day_dt)
                    day_ts_eod = day_ts + 86399999999

                    # check for milestone(s) on that day
                    db = self.env.get_db_cnx()
                    cursor = db.cursor()
                    cursor.execute("""
                        SELECT name
                          FROM milestone
                         WHERE due >= %s and due <= %s
                    """, (day_ts, day_ts_eod))
                    while (1):
                        row = cursor.fetchone()
                        if row is None:
                            cell(tag.br())
                            break
                        else:
                            name = to_unicode(row[0])
                            url = self.env.href.milestone(name)
                            milestone = '* ' + name
                            milestone = tag.div(tag.a(milestone, href=url))
                            milestone(class_='milestone')

                            cell(milestone)

                    match = []
                    match_od = []
                    ticket_heap = tag('')
                    ticket_list = tag.div('')
                    ticket_list(align='left', class_='condense')

                    # get tickets with due date set to day
                    for t in self.tickets:
                        due = t.get(self.due_field_name)
                        if due is None or due in ['', '--']:
                            continue
                        else:
                            if self.due_field_fmt == 'ts':
                                if not isinstance(due, datetime.datetime):
                                    continue
                                due_ts = to_utimestamp(due)
                                if due_ts < day_ts or \
                                    due_ts > day_ts_eod:
                                    continue
                            else:
                                duedate = format_date(day_dt,
                                                      self.due_field_fmt)
                                if not due == duedate:
                                    continue

                        id = t.get('id')
                        ticket, short = self._gen_ticket_entry(t)
                        ticket_heap(ticket)
                        if not id in match:
                            if len(match) == 0:
                                ticket_list(short)
                            else:
                                ticket_list(', ', short)
                            match.append(id)

                    # optionally get tickets created on day
                    if show_t_open_dates is True:
                        ticket_od_list = tag.div('')
                        ticket_od_list(align='left',
                                       class_='opendate_condense')

                        for t in self.tickets:
                            ticket_ts = to_utimestamp(t.get('time'))
                            if ticket_ts < day_ts or ticket_ts > day_ts_eod:
                                continue

                            a_class = 'opendate_'
                            id = t.get('id')
                            ticket, short = self._gen_ticket_entry(t, a_class)
                            ticket_heap(ticket)
                            if not id in match:
                                if len(match_od) == 0:
                                    ticket_od_list(short)
                                else:
                                    ticket_od_list(', ', short)
                                match_od.append(id)

                    matches = len(match) + len(match_od)
                    if list_condense > 0 and matches >= list_condense:
                        if len(match_od) > 0:
                            if len(match) > 0:
                                ticket_list(', ')
                            ticket_list = tag(ticket_list, ticket_od_list)
                        line(cell(ticket_list))
                    else:
                        line(cell(ticket_heap))

            buff(line)

        buff = tag.div(heading(buff))
        if cal_width.startswith('+') is True:
            width=":".join(['width', cal_width]) 
            buff(class_='wikiTicketCalendar', style=width)
        else:
            buff(class_='wikiTicketCalendar')

        return buff
Exemple #43
0
 def render(self, ticketset):
   return_div = tag.div(class_=self.cssclass+' projectplanrender' )
   
   # check for missing parameters 
   missingparameter = False
   if self.rows == [] or self.rows == None:
     return_div(tag.div('Missing parameter "rows": use a semicolon-separated list to input the "'+self.rowtype+'".', class_='ppwarning')) 
     missingparameter = True
   if self.rowtype == None or  str(self.rowtype).strip() == '':
     return_div(tag.div('Missing parameter "rowtype": specifies the ticket attribute that should be showed at the rows.', class_='ppwarning')) 
     missingparameter = True
   if self.cols == [] or self.cols == None:
     return_div(tag.div('Missing parameter: use a semicolon-separated list to input the "cols".', class_='ppwarning'))
     missingparameter = True
   if self.coltype == None or  str(self.coltype).strip() == '':
     return_div(tag.div('Missing parameter "coltype": specifies the ticket attribute that should be showed in the columns.', class_='ppwarning')) 
     missingparameter = True
   if missingparameter:
     return return_div
   
   
   #ul = tag.ul()
   #for tid in ticketset.getIDSortedList():
     #ticket = ticketset.getTicket(tid)
     #ul( tag.li(tid, " ",ticket.getfield('component') , " ", ticket.getfield('owner') ))
   #return_div(ul)
   def getstatistictitle( statusdict ):
     mytitle = ''
     mysum = 0
     for status in statusdict:
       mytitle += "%s: %s\n" % (status, str(statusdict[status]) )
       mysum += int(statusdict[status])
     mytitle += "%s: %s" % ('number', mysum)
     return mytitle
   
   def setKV( myStruct, myKey, newValue ):
     '''
       shortcut to set the values correctly
       used to reduce the code needed while using a list as key of a dict
     '''
     myStruct[str(myKey)] = newValue
   
   def tableKeyPrettyPrint( mylist ) :
     '''
       transform a list of keys to a user readable string
       in: ['a','b'] --> out: 'a|b'
     '''
     return '|'.join(mylist)
   
   def tableKeyQueryParameter( parameter, mylist ) :
     '''
       transform a list of keys to a Trac query string parameter  (OR)
       in: x, ['a','b'] --> out: 'x=a&x=b'
     '''
     return '&'.join([ "%s=%s" % (parameter, s) for s in mylist ])
   
   
   chartheight=80
   chartwidth=170
   
   data = {}
   statistics = {}
   
   # init table data 
   for row in self.rows :
     colstatistics = {}
     colkeys = {}
     for col in self.cols :
       # colkeys[col] = []
       setKV( colkeys, col, [] )
       # colstatistics[col] = {}
       setKV( colstatistics, col, {} )
     # data[row] = colkeys
     setKV( data, row, colkeys )
     # statistics[row] = colstatistics
     setKV( statistics, row, colstatistics )
   
   for tid in ticketset.getIDSortedList():
     ticket = ticketset.getTicket(tid)
     ticket_rowtype = ticket.getfield(self.rowtype)
     ticket_coltype =  ticket.getfield(self.coltype)
     
     # determine the data cell where the ticket has to be added, keep in mind that rows and cols are list of lists
     for row in self.rows :
       for col in self.cols :
         if ticket_rowtype in row and ticket_coltype in col :
           data[str(row)][str(col)].append(ticket) # save tickets at precise values of row and col
           self.log_debug('row:%s col:%s append:%s' % (row,col,tid))
     
     # if ticket_rowtype in self.rows and ticket_coltype in self.cols :
   
   # create HTML table
   table = tag.table( class_="data pptableticketperday" , border = "1", style = 'width:auto;')
   
   # create HTML table head
   thead = tag.thead()
   tr = tag.tr()
   tr( tag.th("%s vs %s" % (self.rowtype,self.coltype) ) )
   for colkey in self.cols :
     tr( tag.th(tag.h4(tag.a( tableKeyPrettyPrint(colkey), href=self.macroenv.tracenv.href()+('/query?%s&order=%s' % ( tableKeyQueryParameter(self.coltype, colkey),self.rowtype)) )),title="%s is %s" % (self.coltype, tableKeyPrettyPrint(colkey) ) ) ) # first line with all colkeys
   if self.showsummarypiechart:
     tr( tag.th(tag.h4( "Ticket Overview" ) ) )  
   thead(tr)
   table(thead)
   
   # create HTML table body
   tbody = tag.tbody()
   counter=0
   
   for rowkey in self.rows :
     # switch line color
     if counter % 2 == 1:
       class_ = 'odd'
     else:
       class_ = 'even'
     counter += 1
     tr = tag.tr( class_=class_ ) # new line
     
     td = tag.td() # new cell
     td(tag.h5(tag.a( tableKeyPrettyPrint(rowkey), href=self.macroenv.tracenv.href()+('/query?%s&order=%s' % ( tableKeyQueryParameter( self.rowtype,rowkey),self.coltype)) )),title="%s is %s" % (self.rowtype, tableKeyPrettyPrint(rowkey) ) ) # first cell contains row key
     tr(td)
     for colkey in self.cols :
       td = tag.td()
       for ticket in data[str(rowkey)][str(colkey)] :
         td( tag.span(self.createTicketLink(ticket), class_ = 'ticket_inner' ), " " , mytitle="%s is %s and %s is %s" % (self.rowtype,rowkey,self.coltype,colkey) ) # mytitle might be used later by javascript
         if not statistics[str(rowkey)][str(colkey)].has_key( ticket.getstatus() ) :
           statistics[str(rowkey)][str(colkey)][ticket.getstatus()] = 0
         statistics[str(rowkey)][str(colkey)][ticket.getstatus()] += 1
       tr(td)
     
     # compute statistics
     rowstatistics = {}
     count = 0
     for colkey in statistics[str(rowkey)] :
       for status in statistics[str(rowkey)][str(colkey)] :
         if not rowstatistics.has_key(status) : 
           rowstatistics[status] = 0
         try:
           rowstatistics[status] += statistics[str(rowkey)][str(colkey)][status]
           count += statistics[str(rowkey)][str(colkey)][status]
         except:
           pass
       
     if self.showsummarypiechart:
       tr(tag.td(tag.img(src=self.createGoogleChartFromDict('ColorForStatus', rowstatistics, '%s tickets' % (count,), height=chartheight )), class_='ppstatistics' , title=getstatistictitle(rowstatistics)) ) # Summary
     
     tbody(tr)
   table(tbody)
   
   # create HTML table foot
   if self.showsummarypiechart :
     fullstatistics = {}
     tfoot = tag.tfoot()
     tr = tag.tr()
     
     tr( tag.td(tag.h5('Ticket Overview') ) )
     
     # create statistics for col
     fullcount = 0
     for colkey in self.cols :
       colstatistics = {}
       colcount = 0
       for rowkey in self.rows :
         for status in statistics[str(rowkey)][str(colkey)] :
           if not fullstatistics.has_key(status) : 
             fullstatistics[status] = 0
           if not colstatistics.has_key(status) : 
             colstatistics[status] = 0
           try:
             colstatistics[status] += statistics[str(rowkey)][str(colkey)][status]
             colcount += statistics[str(rowkey)][str(colkey)][status]
             fullstatistics[status] += statistics[str(rowkey)][str(colkey)][status]
             fullcount += statistics[str(rowkey)][str(colkey)][status]
           except:
             pass
       tr(tag.td(tag.img(src=self.createGoogleChartFromDict('ColorForStatus', colstatistics, '%s tickets' % (colcount,), height=chartheight)), title=getstatistictitle(colstatistics) )) # Col Summary
     tr(tag.td(tag.img(src=self.createGoogleChartFromDict('ColorForStatus', fullstatistics, '%s tickets' % (fullcount,), height=chartheight)), class_='ppstatistics', title=getstatistictitle(fullstatistics))) # Full Summary
     tfoot(tr)
     table(tfoot)
   
   return_div(table)
   
   return return_div 
Exemple #44
0
    def expand_macro(self, formatter, name, arguments):

        self.ref = formatter
        self.tz_info = formatter.req.tz
        self.thistime = datetime.datetime.now(self.tz_info)

        # Parse arguments from macro invocation
        args, kwargs = parse_args(arguments, strict=False)

        # Find out whether use http param, current or macro param year/month
        http_param_year = formatter.req.args.get('year', '')
        http_param_month = formatter.req.args.get('month', '')

        if http_param_year == "":
            # not clicked on a prev or next button
            if len(args) >= 1 and args[0] <> "*":
                # year given in macro parameters
                year = int(args[0])
            else:
                # use current year
                year = self.thistime.year
        else:
            # year in http params (clicked by user) overrides everything
            year = int(http_param_year)

        if http_param_month == "":
            # not clicked on a prev or next button
            if len(args) >= 2 and args[1] <> "*":
                # month given in macro parameters
                month = int(args[1])
            else:
                # use current month
                month = self.thistime.month
        else:
            # month in http params (clicked by user) overrides everything
            month = int(http_param_month)

        showbuttons = True
        if len(args) >= 3 or kwargs.has_key('nav'):
            try:
                showbuttons = kwargs['nav'] in ["True", "true", "yes", "1"]
            except KeyError:
                showbuttons = args[2] in ["True", "true", "yes", "1"]

        wiki_page_format = "%Y-%m-%d"
        if len(args) >= 4 and args[3] != "*" or kwargs.has_key('wiki'):
            try:
                wiki_page_format = str(kwargs['wiki'])
            except KeyError:
                wiki_page_format = str(args[3])
        # Support relative paths in macro arguments for wiki page links.
        wiki_page_format = self._resolve_relative_name(wiki_page_format,
                                                       formatter.resource.id)

        list_condense = 0
        show_t_open_dates = True
        wiki_page_template = ""
        wiki_subpages = []

        # Read optional check plan.
        check = []
        if kwargs.has_key('check'):
            check = kwargs['check'].split('.')

        if name == 'WikiTicketCalendar':
            if len(args) >= 5 or kwargs.has_key('cdate'):
                try:
                    show_t_open_dates = kwargs['cdate'] in \
                                               ["True", "true", "yes", "1"]
                except KeyError:
                    show_t_open_dates = args[4] in \
                                               ["True", "true", "yes", "1"]

        # Optional page template to create new wiki pages.
        # The default (empty page) is used, if the template name is invalid.
        if len(args) >= 6 or kwargs.has_key('base'):
            try:
                wiki_page_template = kwargs['base']
            except KeyError:
                wiki_page_template = args[5]

        if name == 'WikiTicketCalendar':
            # TracQuery support for ticket selection
            query_args = "id!=0"
            if len(args) >= 7 or kwargs.has_key('query'):
                # prefer query arguments provided by kwargs
                try:
                    query_args = kwargs['query']
                except KeyError:
                    query_args = args[6]
            tickets = WikiCalendarTicketProvider(self.env)
            self.tickets = tickets.harvest(formatter.req, query_args)

            # compress long ticket lists
            if len(args) >= 8 or kwargs.has_key('short'):
                # prefer query arguments provided by kwargs
                try:
                    list_condense = int(kwargs['short'])
                except KeyError:
                    list_condense = int(args[7])

            # control calendar display width
            cal_width = "100%;"
            if len(args) >= 9 or kwargs.has_key('width'):
                # prefer query arguments provided by kwargs
                try:
                    cal_width = kwargs['width']
                except KeyError:
                    cal_width = args[8]

            # multiple wiki (sub)pages per day
            if kwargs.has_key('subpages'):
                wiki_subpages = kwargs['subpages'].split('|')

            # Can use this to change the day the week starts on,
            # but this is a system-wide setting.
            calendar.setfirstweekday(calendar.MONDAY)

        cal = calendar.monthcalendar(year, month)
        curr_day = None
        if year == self.thistime.year and month == self.thistime.month:
            curr_day = self.thistime.day

        # for prev/next navigation links
        prevMonth = month - 1
        nextMonth = month + 1
        nextYear = prevYear = year
        # check for year change (KISS version)
        if prevMonth == 0:
            prevMonth = 12
            prevYear -= 1
        if nextMonth == 13:
            nextMonth = 1
            nextYear += 1

        # for fast-forward/-rewind navigation links
        ffYear = frYear = year
        if month < 4:
            frMonth = month + 9
            frYear -= 1
        else:
            frMonth = month - 3
        if month > 9:
            ffMonth = month - 9
            ffYear += 1
        else:
            ffMonth = month + 3

        last_week_prevMonth = calendar.monthcalendar(prevYear, prevMonth)[-1]
        first_week_nextMonth = calendar.monthcalendar(nextYear, nextMonth)[0]

        # Switch to user's locale, if available.
        try:
            loc_req = str(formatter.req.locale)
        except AttributeError:
            # Available since in Trac 0.12 .
            loc_req = None
        if loc_req:
            loc = locale.getlocale()
            loc_prop = locale.normalize(loc_req)
            try:
                locale.setlocale(locale.LC_TIME, loc_prop)
            except locale.Error:
                try:
                    # Re-try with UTF-8 as last resort.
                    loc_prop = '.'.join([loc_prop.split('.')[0], 'utf8'])
                    locale.setlocale(locale.LC_TIME, loc_prop)
                except locale.Error:
                    loc_prop = None
            self.env.log.debug('Locale setting for calendar: ' + str(loc_prop))

        # Finally building the output
        # Begin with caption and optional navigation links
        buff = tag.tr()

        if showbuttons is True:
            # calendar navigation buttons
            nx = 'next'
            pv = 'prev'
            nav_pvY = self._mknav('&lt;&lt;', pv, month, year - 1)
            nav_frM = self._mknav('&nbsp;&lt;', pv, frMonth, frYear)
            nav_pvM = self._mknav('&nbsp;&laquo;', pv, prevMonth, prevYear)
            nav_nxM = self._mknav('&raquo;&nbsp;', nx, nextMonth, nextYear)
            nav_ffM = self._mknav('&gt;&nbsp;', nx, ffMonth, ffYear)
            nav_nxY = self._mknav('&gt;&gt;', nx, month, year + 1)

            # add buttons for going to previous months and year
            buff(nav_pvY, nav_frM, nav_pvM)

        # The caption will always be there.
        heading = tag.td(
            to_unicode(format_date(self._mkdatetime(year, month), '%B %Y')))
        buff = buff(heading(class_='y'))

        if showbuttons is True:
            # add buttons for going to next months and year
            buff(nav_nxM, nav_ffM, nav_nxY)
        buff = tag.caption(tag.table(tag.tbody(buff)))
        buff = tag.table(buff)
        if name == 'WikiTicketCalendar':
            if cal_width.startswith('+') is True:
                width = ":".join(['min-width', cal_width])
                buff(class_='wikitcalendar', style=width)
            else:
                buff(class_='wikitcalendar')
        if name == 'WikiCalendar':
            buff(class_='wiki-calendar')

        heading = tag.tr()
        heading(align='center')

        for day in calendar.weekheader(2).split()[:-2]:
            col = tag.th(to_unicode(day))
            col(class_='workday', scope='col')
            heading(col)
        for day in calendar.weekheader(2).split()[-2:]:
            col = tag.th(to_unicode(day))
            col(class_='weekend', scope='col')
            heading(col)

        heading = buff(tag.thead(heading))

        # Building main calendar table body
        buff = tag.tbody()
        w = -1
        for week in cal:
            w = w + 1
            line = tag.tr()
            line(align='right')
            d = -1
            for day in week:
                d = d + 1
                if day:
                    # check for wikipage with name specified in
                    # 'wiki_page_format'
                    wiki = format_date(self._mkdatetime(year, month, day),
                                       wiki_page_format)
                    if day == curr_day:
                        a_class = 'day today'
                        td_class = 'today'
                    else:
                        a_class = 'day'
                        td_class = 'day'

                    day_dt = self._mkdatetime(year, month, day)
                    if uts:
                        day_ts = to_utimestamp(day_dt)
                        day_ts_eod = day_ts + 86399999999
                    else:
                        day_ts = to_timestamp(day_dt)
                        day_ts_eod = day_ts + 86399

                    # check for milestone(s) on that day
                    db = self.env.get_db_cnx()
                    cursor = db.cursor()
                    cursor.execute(
                        """
                        SELECT name
                          FROM milestone
                         WHERE due >= %s and due <= %s
                    """, (day_ts, day_ts_eod))
                    milestones = tag()
                    for row in cursor:
                        if not a_class.endswith('milestone'):
                            a_class += ' milestone'
                        milestone = to_unicode(row[0])
                        url = self.env.href.milestone(milestone)
                        milestone = '* ' + milestone
                        milestones = tag(
                            milestones,
                            tag.div(tag.a(milestone, href=url),
                                    class_='milestone'))
                    day = tag.span(day)
                    day(class_='day')
                    if len(wiki_subpages) > 0:
                        pages = tag(day, Markup('<br />'))
                        for page in wiki_subpages:
                            label = tag(' ', page[0])
                            page = '/'.join([wiki, page])
                            url = self.env.href.wiki(page)
                            pages(
                                self._gen_wiki_links(page, label, 'subpage',
                                                     url, wiki_page_template,
                                                     check))
                    else:
                        url = self.env.href.wiki(wiki)
                        pages = self._gen_wiki_links(wiki, day, a_class, url,
                                                     wiki_page_template, check)
                    cell = tag.td(pages)
                    cell(class_=td_class, valign='top')
                    if name == 'WikiCalendar':
                        line(cell)
                    else:
                        if milestones:
                            cell(milestones)
                        else:
                            cell(tag.br())

                        match = []
                        match_od = []
                        ticket_heap = tag('')
                        ticket_list = tag.div('')
                        ticket_list(align='left', class_='condense')

                        # get tickets with due date set to day
                        for t in self.tickets:
                            due = t.get(self.tkt_due_field)
                            if due is None or due in ['', '--']:
                                continue
                            else:
                                if self.tkt_due_format == 'ts':
                                    if not isinstance(due, datetime.datetime):
                                        continue
                                    if uts:
                                        due_ts = to_utimestamp(due)
                                    else:
                                        due_ts = to_timestamp(due)
                                    if due_ts < day_ts or due_ts > day_ts_eod:
                                        continue
                                else:
                                    # Beware: Format might even be unicode str
                                    duedate = format_date(
                                        day_dt, str(self.tkt_due_format))
                                    if not due == duedate:
                                        continue

                            id = t.get('id')
                            ticket, short = self._gen_ticket_entry(t)
                            ticket_heap(ticket)
                            if not id in match:
                                if len(match) == 0:
                                    ticket_list(short)
                                else:
                                    ticket_list(', ', short)
                                match.append(id)

                        # optionally get tickets created on day
                        if show_t_open_dates is True:
                            ticket_od_list = tag.div('')
                            ticket_od_list(align='left',
                                           class_='opendate_condense')

                            for t in self.tickets:
                                if uts:
                                    ticket_ts = to_utimestamp(t.get('time'))
                                else:
                                    ticket_ts = to_timestamp(t.get('time'))
                                if ticket_ts < day_ts or \
                                        ticket_ts > day_ts_eod:
                                    continue

                                a_class = 'opendate_'
                                id = t.get('id')
                                ticket, short = self._gen_ticket_entry(
                                    t, a_class)
                                ticket_heap(ticket)
                                if not id in match:
                                    if len(match_od) == 0:
                                        ticket_od_list(short)
                                    else:
                                        ticket_od_list(', ', short)
                                    match_od.append(id)

                        matches = len(match) + len(match_od)
                        if list_condense > 0 and matches >= list_condense:
                            if len(match_od) > 0:
                                if len(match) > 0:
                                    ticket_list(', ')
                                ticket_list = tag(ticket_list, ticket_od_list)
                            line(cell(ticket_list))
                        else:
                            line(cell(ticket_heap))
                else:
                    if name == 'WikiCalendar':
                        if w == 0:
                            day = last_week_prevMonth[d]
                            wiki = format_date(
                                self._mkdatetime(prevYear, prevMonth, day),
                                wiki_page_format)
                        else:
                            day = first_week_nextMonth[d]
                            wiki = format_date(
                                self._mkdatetime(nextYear, nextMonth, day),
                                wiki_page_format)
                        url = self.env.href.wiki(wiki)
                        a_class = 'day adjacent_month'
                        pages = self._gen_wiki_links(wiki, day, a_class, url,
                                                     wiki_page_template)

                        cell = tag.td(pages)
                        cell(class_='day adjacent_month')
                        line(cell)
                    else:
                        cell = tag.td('')
                        cell(class_='day adjacent_month')
                        line(cell)
            buff(line)

        if loc_req and loc_prop:
            # We may have switched to users locale, resetting now.
            try:
                locale.setlocale(locale.LC_ALL, loc)
                self.env.log.debug('Locale setting restored: ' + str(loc))
            except locale.Error:
                pass

        buff = tag.div(heading(buff))
        if name == 'WikiTicketCalendar':
            if cal_width.startswith('+') is True:
                width = ":".join(['width', cal_width])
                buff(class_='wikitcalendar', style=width)
            else:
                buff(class_='wikitcalendar')
        if name == 'WikiCalendar':
            buff(class_='wiki-calendar')
        # Add common CSS stylesheet
        if self.internal_css and not self.ref.req.args.get('wikicalendar'):
            # Put definitions directly into the output.
            f = open('/'.join([self.htdocs_path, 'wikicalendar.css']), 'Ur')
            css = tag.style(Markup('<!--\n'), '\n'.join(f.readlines()),
                            Markup('-->\n'))(type="text/css")
            f.close()
            # Add hint to prevent multiple inclusions.
            self.ref.req.args['wikicalendar'] = True
            return tag(css, buff)
        elif not self.ref.req.args.get('wikicalendar'):
            add_stylesheet(self.ref.req, 'wikicalendar/wikicalendar.css')
        return buff
    def filter_stream(self, req, method, filename, stream, data):

        # Tickets will be modified to show the child tickets as a list under the 'Description' section.
        if filename == 'ticket.html':

            # Get the ticket info.
            ticket = data.get('ticket')

            # Modify ticket.html with sub-ticket table, create button, etc...
            # As follows:
            # - If ticket has no child tickets and child tickets are NOT allowed then skip.
            # - If ticket has child tickets and child tickets are NOT allowed (ie. rules changed or ticket type changed after children were assigned),
            #   print list of tickets but do not allow any tickets to be created.
            # - If child tickets are allowed then print list of child tickets or 'No Child Tickets' if non are currently assigned.
            # 
            if ticket and ticket.exists:

                filter = Transformer('//div[@class="description"]')
                snippet = tag()

                # Are there any child tickets to display?
                childtickets = [ Ticket(self.env, n) for n in self.env.childtickets.get(ticket.id, []) ]

                # trac.ini : Which columns to display in child ticket listing?
                columns = self.config.getlist('childtickets', 'parent.%s.table_headers' % ticket['type'], default = ['summary', 'owner'])

                # Forcing default setting to inherit from the parent ticket
                default_child_milestone = ticket['milestone']
                default_child_type = ticket['type']

                # Test if the ticket has children: If so, then list in pretty table.
                if childtickets:
                    snippet.append(
                            tag.div(tag.h3("Child Tickets:", id = "comment:child_tickets"),
                                tag.table(
                                    tag.thead(
                                        tag.tr(
                                            tag.th("Ticket", class_ = "id"),
                                            [ tag.th(s.title(), class_ = s) for s in columns ])
                                        ),
                                    tag.tbody([ self._table_row(req, tkt, columns) for tkt in childtickets ]),
                                    class_ = "listing",
                                    ),
                                )
                            )
                else:
                    snippet.append(tag.div(tag.h3("Child Tickets:", id = "comment:child_tickets"), tag.p("NO SUB-TICKETS.")))

                # Can user create a new ticket? If not, just display title (ie. no 'create' button).
                if 'TICKET_CREATE' in req.perm(ticket.resource):
                        snippet.append(
                            tag.div(
                                tag.form(
                                    tag.div(
                                        tag.span(
                                            tag.input(type = "hidden", name = "parent", value = '#' + str(ticket.id)),
                                            tag.input(type = "hidden", name = "milestone", value = default_child_milestone),
                                            tag.input(type = "hidden", name = "type", value = default_child_type),
                                            tag.input(type = "submit", name = "childticket", value = "Create", title = "Create a child ticket"),
                                            class_ = "primaryButton"),
                                        class_ = "buttons"),
                                    method = "get", action = req.href.newticket()
                                    )
                                )
                            )

                return stream | filter.append(snippet)

        return stream
Exemple #46
0
 def render_property(self, name, mode, context, props):
     """Parse svn:mergeinfo and svnmerge-* properties, converting branch
     names to links and providing links to the revision log for merged
     and eligible revisions.
     """
     has_eligible = name in ('svnmerge-integrated', 'svn:mergeinfo')
     revs_label = (_('merged'), _('blocked'))[name.endswith('blocked')]
     revs_cols = has_eligible and 2 or None
     reponame = context.resource.parent.id
     target_path = context.resource.id
     repos = RepositoryManager(self.env).get_repository(reponame)
     target_rev = context.resource.version
     if has_eligible:
         node = repos.get_node(target_path, target_rev)
         branch_starts = {}
         for path, rev in node.get_copy_ancestry(): 
             if path not in branch_starts:
                 branch_starts[path] = rev + 1
     rows = []
     if name.startswith('svnmerge-'):
         sources = props[name].split()
     else:
         sources = props[name].splitlines()
     for line in sources:
         path, revs = line.split(':', 1)
         spath = _path_within_scope(repos.scope, path)
         if spath is None:
             continue
         revs = revs.strip()
         inheritable, non_inheritable = _partition_inheritable(revs)
         revs = ','.join(inheritable)
         deleted = False
         try:
             node = repos.get_node(spath, target_rev)
             resource = context.resource.parent.child('source', spath)
             if 'LOG_VIEW' in context.perm(resource):
                 row = [_get_source_link(spath, context),
                        _get_revs_link(revs_label, context, spath, revs)]
                 if non_inheritable:
                     non_inheritable = ','.join(non_inheritable)
                     row.append(_get_revs_link(_('non-inheritable'), context,
                                               spath, non_inheritable,
                                               _('merged on the directory '
                                                 'itself but not below')))
                 if has_eligible:
                     first_rev = branch_starts.get(spath)
                     if not first_rev:
                         first_rev = node.get_branch_origin()
                     eligible = set(xrange(first_rev or 1, target_rev + 1))
                     eligible -= set(Ranges(revs))
                     blocked = _get_blocked_revs(props, name, spath)
                     if blocked:
                         eligible -= set(Ranges(blocked))
                     if eligible:
                         nrevs = repos._get_node_revs(spath, max(eligible),
                                                      min(eligible))
                         eligible &= set(nrevs)
                     eligible = to_ranges(eligible)
                     row.append(_get_revs_link(_('eligible'), context,
                                               spath, eligible))
                 rows.append((False, spath, [tag.td(each) for each in row]))
                 continue
         except NoSuchNode:
             deleted = True
         revs = revs.replace(',', u',\u200b')
         rows.append((deleted, spath,
                      [tag.td('/' + spath),
                       tag.td(revs, colspan=revs_cols)]))
     if not rows:
         return None
     rows.sort()
     has_deleted = rows and rows[-1][0] or None
     return tag(has_deleted and tag.a(_('(toggle deleted branches)'),
                                      class_='trac-toggledeleted',
                                      href='#'),
                tag.table(tag.tbody(
                    [tag.tr(row, class_=deleted and 'trac-deleted' or None)
                     for deleted, spath, row in rows]), class_='props'))
Exemple #47
0
    def expand_macro(self, formatter, name, args):
        """
        Called by the formatter to render the parsed
        wiki text.
        """

        def to_html(text):
            """
            Format the parsed text from the rows into HTML.
            """
            if not text:
                return ''

            # simple check to determine whether format_to_html or 
            # format_to_oneliner should be used. If there are multiple
            # lines, use format_to_html, otherwise use format_to_oneliner

            stripped_text = text.strip()
            splitlines = stripped_text.splitlines()

            if len(splitlines) > 1:
                formatted_text = format_to_html(self.env, formatter.context, text)
            else:
                formatted_text = '<br />'.join( [format_to_oneliner(self.env, formatter.context, line) \
                    for line in text.splitlines()] ) 
            return Markup( formatted_text )

        if not args:
            return Markup()

        # use the formatter to find the TablePluginStyles
        if not formatter.wiki.has_page('TablePluginStyles'):
            # if our
            build_table_plugin_styles_page(self.env)

        if formatter.wiki.has_page('TablePluginStyles'):
            # at this point, the new style page should exist
            # so use the styles defined there.
            config_args = self._parse_wiki_style_page(self.env)
        else:
            # nice error handling in here possible incase
            # the page cannot be created for whatever reason?
            pass

        config_table_styles, config_css_styles = self._parse_styles(config_args)

        args_table_styles, args_css_styles = self._parse_styles(args)
        global_css_styles = dict(config_css_styles.items() + args_css_styles.items())

        column_list = []
        row_count = 0

        row_dict = {}
        row_list = []

        heading = False
        body_name = ''
        heading_set = False
        body_set_first = False
        first_row_as_header = False
        is_row = False

        table_id = ''
        table_data = ''

        table_style = ''
        column_style_dict = {}

        for attribute in self._parse_args(args):
            if 'table' in attribute:
                # get the table id to use
                table_id = attribute['table']['name']
                table_data = attribute['table']['data']
                table_style = attribute['table']['style'].replace('@', '')
            elif 'css' in attribute:
                pass
            elif 'column' in attribute:
                column_name = attribute['column']['name']
                column_list.append(column_name)
                if attribute['column']['style']:
                    column_style_dict[column_name] = attribute['column']['style']
            elif 'header' in attribute:
                heading = True
                heading_set = True
            elif 'body' in attribute:
                body_name = str(uuid4())
                if not heading_set and not first_row_as_header:
                    body_set_first = True
                heading = False
            elif 'row' in attribute:
                is_row = True
                row_count = 0
                row_style = attribute['row']['style']
            else:
                if not heading_set and not body_set_first:
                    first_row_as_header = True
                for key, value in attribute.items():
                    value['heading'] = heading
                    if body_name:
                        value['body_name'] = body_name
                    if is_row:
                        # if its a row, apply row style
                        original_style = value['style']
                        value['style'] = ' '.join([original_style, row_style])
                if row_count == (len(column_list) - 1):
                    row_dict.update(attribute)
                    row_list.append(row_dict)
                    row_dict = {}
                    row_count = 0
                    is_row = False
                else:
                    row_dict.update(attribute)
                    row_count += 1

        thead = tag.thead()
        for row in row_list:
            if body_set_first:
                break
            header_row = tag.tr()
            for column in column_list:
                header_cell = ''
                if row[column]['heading'] or first_row_as_header:
                    header_cell = tag.th()
                    header_cell(to_html(row[column]['data']), class_=row[column]['style'].replace('@', ''))
                    header_row(header_cell)
            if header_cell:
                thead(header_row)
            if first_row_as_header:
                break

        if table_style:
            table_id = table_style
            table_data = config_table_styles[table_style]['data']


        css_data = self._build_css_template(global_css_styles)

        full_style_data = ''
        full_style_data += table_data
        full_style_data += css_data

        tstyle = tag.style()
        tstyle = tag.style(full_style_data)

        tbody = tag.tbody()
        body_name = ''
        body_set = False

        tbody_list = []
        for row in row_list:
            if first_row_as_header:
                heading_set = False
                first_row_as_header = False
                continue
            trow = tag.tr()
            tcol = ''
            for column in column_list:
                if row[column]['heading']:
                    continue
                if row[column]['body_name'] == body_name and not body_set:
                    body_set = True
                elif row[column]['body_name'] != body_name and not body_set:
                    body_name = row[column]['body_name']
                    body_set = True
                elif row[column]['body_name'] != body_name and body_set:
                    tbody_list.append(tbody)
                    tbody = tag.tbody()
                    trow = tag.tr()
                    body_name = row[column]['body_name']
                tcol = tag.td()
                # if there is a column style available,
                # add it to what is already there
                formatted_column_style = ''
                if column in column_style_dict:
                    column_style = column_style_dict[column].replace('@', '')
                    formatted_column_style = column_style.replace(';', ' ')
                class_styles = row[column]['style'].replace('@', '')
                formatted_class_styles = class_styles.replace(';', ' ')
                formatted_item = ' '.join([formatted_class_styles, formatted_column_style])
                tcol(to_html(row[column]['data']), class_=formatted_item)
                trow(tcol)
            if tcol:
                tbody(trow)
        tbody_list.append(tbody)

        return tag.table([tstyle, thead, tbody_list], class_=table_id)
Exemple #48
0
    def render(self, ticketset):
        # add needed javascript and css files
        self.addJsChartFiles()

        if self.firstsegment == None or self.lastsegment == None:
            return self.divWarning(
                'you have to set the time period via the macro parameters. Example: first=2012-02-03, last=2012-02-19 .'
            )

        tickets = ticketset.getIDList()

        # stop if no tickets available
        if len(tickets) == 0:
            return self.divWarning('No tickets available.')

        changes = {}
        initalvalues = {}
        creationdates = {}

        (firstday, lastday) = self.getBoundaries({})
        alldates = self.getAllRelevantDates(firstday, lastday)

        lastdaySecs = lastday
        firstday = self.normalizeToDay(firstday)
        lastday = self.normalizeToDay(lastday)

        (ticketCount, relevantChanges) = self.computeInformationAboutSegment(
            ticketset, firstday, lastday)

        # count only the tickets that are relevant within the requested time period (firstday,lastday)
        relevantTickets = ticketCount
        closedTickets = {}  # change this
        openTickets = {}  # change this
        changeDateStrings = relevantChanges.keys()
        changeDateStrings.sort()
        # ticketCount = 70 # DEBUG

        for changeDateStr in changeDateStrings:  # for each day
            self.macroenv.tracenv.log.debug(
                "changes %4s: %3s (%s)" %
                (changeDateStr, relevantChanges[changeDateStr], ticketCount))
            self.setKeyIfNotExistsInt(closedTickets, changeDateStr,
                                      -1 * relevantChanges[changeDateStr])
            ticketCount = ticketCount + relevantChanges[
                changeDateStr]  # reduce the number of open tickets
            self.setKeyIfNotExistsInt(openTickets, changeDateStr, ticketCount)

        # generate HTML
        holderid = "%s_%s_%d_%d" % (
            self.getNameOfRenderFrame(), 'holder', int(time.time() * 1000000),
            random.randint(1, 1024))  # compute unique element id
        currentday = firstday
        frame = tag.div(class_='invisible ppConfBurnDown',
                        id=self.getNameOfRenderFrame() + holderid)
        tableData = tag.table(class_="invisible data",
                              border="1",
                              style='width:auto;')
        trDays = tag.tr()
        trDaysAxis = tag.tr()
        trOpenTickets = tag.tr()
        trClosedTickets = tag.tr()
        trReopenedTickets = tag.tr()
        alldates.sort()
        lastOpenTicket = relevantTickets  # fallback: all tickets
        lastClosedTickets = 0
        counter = 0
        todaySecs = self.datetime2seconds(datetime.datetime.today())
        todayStr = self.getDateString(todaySecs)
        todayid = 0
        maxValue = 0
        if lastdaySecs <= todaySecs:  # if today is later then the shown time frame then mark the last column
            todayid = len(alldates)
        for currentday in alldates:
            if currentday == todayStr:  # capture the column with the current date
                todayid = counter
            counter = counter + 1
            trDays(
                tag.th(currentday.replace("\n", " "))
            )  # text for info box, no line breaks here, because it is limited to 3 lines
            trDaysAxis(tag.th(currentday))
            if openTickets.has_key(currentday):
                lastOpenTicket = openTickets[currentday]
            trOpenTickets(tag.td(lastOpenTicket))
            if closedTickets.has_key(currentday):
                lastClosedTickets = closedTickets[currentday]
            else:
                lastClosedTickets = 0
            trClosedTickets(tag.td(lastClosedTickets))
            maxValue = max(len(str(lastClosedTickets)),
                           len(str(lastOpenTicket)), maxValue)
            trReopenedTickets(tag.td('0'))

        tableData(tag.thead(trDays))
        tableData(tag.tfoot(trDaysAxis))
        tableData(tag.tbody(trOpenTickets, trClosedTickets, trReopenedTickets))

        (label1, label2) = self.getLabel()

        # caculate the scale factor for the info box within the chart
        maxGlobal = max(
            len(str(label1)) + maxValue,
            len(str(label2)) + maxValue)
        if self.segment in ['week', 'twoweek'
                            ]:  # they use long descriptions in the info box
            maxGlobal = max(maxGlobal, 27)

        # configuration of renderer
        frame(tag.div(str(relevantTickets), class_='maxTasks'))
        frame(tag.div(self.width, class_='width'))
        frame(tag.div(self.height, class_='height'))
        frame(tag.div(str(maxGlobal), class_='maxlength'))
        frame(tag.div(label1, class_='label1'))
        frame(tag.div(label2, class_='label2'))
        frame(
            tag.div(str(todayid),
                    class_='today'))  # number of column with the current date
        frame(tag.div(holderid, class_='holder'))  # where to put the chart in

        frame(tableData)
        outerframe = tag.div()  # div as global container
        #outerframe(outer) # DEBUG
        outerframe(frame)
        outerframe(tag.div(id=holderid), style="border-width:1px")
        return outerframe
Exemple #49
0
        def _body_rows():
            for idx, line in enumerate(_group_lines(stream)):
                row = tag.tr()
                if marks and idx + 1 in marks:
                    row(class_='hilite')
                for annotator, data in annotator_datas:
                    if annotator:
                        annotator.annotate_row(context, row, idx+1, line, data)
                    else:
                        row.append(tag.td())
                row.append(tag.td(line))
                yield row

        return tag.table(class_='code')(
            tag.thead(_head_row()),
            tag.tbody(_body_rows())
        )

    def get_max_preview_size(self):
        """:deprecated: use `max_preview_size` attribute directly."""
        return self.max_preview_size

    def get_charset(self, content='', mimetype=None):
        """Infer the character encoding from the `content` or the `mimetype`.

        `content` is either a `str` or an `unicode` object.

        The charset will be determined using this order:
         * from the charset information present in the `mimetype` argument
         * auto-detection of the charset from the `content`
         * the configured `default_charset`
Exemple #50
0
    def filter_stream(self, req, method, filename, stream, data):

        # Tickets will be modified to show the child tickets as a list under the 'Description' section.
        if filename == 'ticket.html':

            # Add our own styles for the ticket lists.
            add_stylesheet(req, 'ct/css/childtickets.css')

            # Get the ticket info.
            ticket = data.get('ticket')

            # Modify ticket.html with sub-ticket table, create button, etc...
            # As follows:
            # - If ticket has no child tickets and child tickets are NOT allowed then skip.
            # - If ticket has child tickets and child tickets are NOT allowed (ie. rules changed or ticket type changed after children were assigned),
            #   print list of tickets but do not allow any tickets to be created.
            # - If child tickets are allowed then print list of child tickets or 'No Child Tickets' if non are currently assigned.
            # 
            if ticket and ticket.exists:

                # The additional section on the ticket is built up of (potentially) three parts: header, ticket table, buttons. These
                # are all 'wrapped up' in a 'div' with the 'attachments' id (we'll just pinch this to make look and feel consistent with any
                # future changes!)
                filter = Transformer('//div[@id="ticket"]')
                snippet = tag.div()

                # Are there any child tickets to display?
                childtickets = [ Ticket(self.env,n) for n in self.childtickets.get(ticket.id,[]) ]

                # (tempish) fix for #8612 : force sorting by ticket id
                childtickets = sorted(childtickets, key=lambda t: t.id)

                # Are child tickets allowed?
                childtickets_allowed = self.config.getbool('childtickets', 'parent.%s.allow_child_tickets' % ticket['type'])

                # If there are no childtickets and the ticket should not have any child tickets, we can simply drop out here.
                if not childtickets_allowed and not childtickets:
                    return stream

                # Our 'main' display consists of two divs.
                buttondiv = tag.div()
                tablediv = tag.div()

                # Test if the ticket has children: If so, then list in pretty table.
                if childtickets:

                    # trac.ini : Which columns to display in child ticket listing?
                    columns = self.config.getlist('childtickets', 'parent.%s.table_headers' % ticket['type'], default=['summary','owner'])

                    tablediv = tag.div(
                                tag.table(
                                    tag.thead(
                                        tag.tr(
                                            tag.th("Ticket",class_="id"),
                                            [ tag.th(s.title(),class_=s) for s in columns ])
                                        ),
                                    tag.tbody([ self._table_row(req,tkt,columns) for tkt in childtickets ]),
                                    class_="listing tickets",
                                    ),
                                tag.br(),
                                )

                # trac.ini : child tickets are allowed - Set up 'create new ticket' buttons.
                if childtickets_allowed:

                    # Can user create a new ticket? If not, just display title (ie. no 'create' button).
                    if 'TICKET_CREATE' in req.perm(ticket.resource):

                        # Always pass these fields
                        default_child_fields = (
                                tag.input(type="hidden", name="parent", value='#'+str(ticket.id)),
                                )

                        #Pass extra fields defined in inherit parameter of parent
                        inherited_child_fields = [
                                tag.input(type="hidden",name="%s"%field,value=ticket[field]) for field in self.config.getlist('childtickets','parent.%s.inherit' % ticket['type'])
                                ]

                        # If child types are restricted then create a set of buttons for the allowed types (This will override 'default_child_type).
                        restrict_child_types = self.config.getlist('childtickets','parent.%s.restrict_child_type' % ticket['type'],default=[])

                        if not restrict_child_types:
                            # trac.ini : Default 'type' of child tickets?
                            default_child_type = self.config.get('childtickets', 'parent.%s.default_child_type' % ticket['type'], default=self.config.get('ticket','default_type'))

                            # ... create a default submit button
                            if ticket['status'] == 'closed':
                                submit_button_fields = (
                                        tag.input(type="submit",disabled="disabled",name="childticket",value="New Child Ticket",title="Create a child ticket"),
                                        tag.input(type="hidden", name="type", value=default_child_type),
                                        )
                            else:
                                submit_button_fields = (
                                        tag.input(type="submit",name="childticket",value="New Child Ticket",title="Create a child ticket"),
                                        tag.input(type="hidden",name="type",value=default_child_type),
                                        )
                        else:
                            if ticket['status'] == 'closed':
                                submit_button_fields = [ tag.input(type="submit",disabled="disabled",name="type",value="%s" % ticket_type,title="Create a %s child ticket" % ticket_type) for ticket_type in restrict_child_types ]
                            else:
                                submit_button_fields = [ tag.input(type="submit",name="type",value="%s" % ticket_type,title="Create a %s child ticket" % ticket_type) for ticket_type in restrict_child_types ]
                        buttondiv = tag.form(
                                    tag.div( default_child_fields, inherited_child_fields, submit_button_fields),
                                    method="get", action=req.href.newticket(),
                                    )

                snippet.append(tag.h2("Child Tickets",class_="foldable"))
                snippet.append(tag.div(tablediv, buttondiv, id="childtickets"))

                return stream | filter.after(snippet)

        return stream
Exemple #51
0
 def render_property_diff(self, name, old_context, old_props,
                          new_context, new_props, options):
     # Build 5 columns table showing modifications on merge sources
     # || source || added || removed || added (ni) || removed (ni) ||
     # || source || removed                                        ||
     rm = RepositoryManager(self.env)
     repos = rm.get_repository(old_context.resource.parent.id)
     def parse_sources(props):
         sources = {}
         for line in props[name].splitlines():
             path, revs = line.split(':', 1)
             spath = _path_within_scope(repos.scope, path)
             if spath is not None:
                 inheritable, non_inheritable = _partition_inheritable(revs)
                 sources[spath] = (set(Ranges(inheritable)),
                                   set(Ranges(non_inheritable)))
         return sources
     old_sources = parse_sources(old_props)
     new_sources = parse_sources(new_props)
     # Go through new sources, detect modified ones or added ones
     blocked = name.endswith('blocked')
     added_label = [_("merged: "), _("blocked: ")][blocked]
     removed_label = [_("reverse-merged: "), _("un-blocked: ")][blocked]
     added_ni_label = _("marked as non-inheritable: ")
     removed_ni_label = _("unmarked as non-inheritable: ")
     def revs_link(revs, context):
         if revs:
             revs = to_ranges(revs)
             return _get_revs_link(revs.replace(',', u',\u200b'),
                                   context, spath, revs)
     modified_sources = []
     for spath, (new_revs, new_revs_ni) in new_sources.iteritems():
         if spath in old_sources:
             (old_revs, old_revs_ni), status = old_sources.pop(spath), None
         else:
             old_revs = old_revs_ni = set()
             status = _(' (added)')
         added = new_revs - old_revs
         removed = old_revs - new_revs
         added_ni = new_revs_ni - old_revs_ni
         removed_ni = old_revs_ni - new_revs_ni
         try:
             all_revs = set(repos._get_node_revs(spath))
             # TODO: also pass first_rev here, for getting smaller a set
             #       (this is an optmization fix, result is already correct)
             added &= all_revs
             removed &= all_revs
             added_ni &= all_revs
             removed_ni &= all_revs
         except NoSuchNode:
             pass
         if added or removed:
             modified_sources.append((
                 spath, [_get_source_link(spath, new_context), status],
                 added and tag(added_label, revs_link(added, new_context)),
                 removed and tag(removed_label,
                                 revs_link(removed, old_context)),
                 added_ni and tag(added_ni_label, 
                                  revs_link(added_ni, new_context)),
                 removed_ni and tag(removed_ni_label,
                                    revs_link(removed_ni, old_context))
                 ))
     # Go through remaining old sources, those were deleted
     removed_sources = []
     for spath, old_revs in old_sources.iteritems():
         removed_sources.append((spath,
                                 _get_source_link(spath, old_context)))
     if modified_sources or removed_sources:
         modified_sources.sort()
         removed_sources.sort()
         changes = tag.table(tag.tbody(
             [tag.tr(tag.td(c) for c in cols[1:]) 
              for cols in modified_sources],
             [tag.tr(tag.td(src), tag.td(_('removed'), colspan=4))
              for spath, src in removed_sources]), class_='props')
     else:
         changes = tag.em(_(' (with no actual effect on merging)'))
     return tag.li(tag_('Property %(prop)s changed', prop=tag.strong(name)),
                   changes)
    def filter_stream(self, req, method, filename, stream, data):
        if not req.path_info.startswith('/ticket/'):
            return stream

        div = None
        link = None
        button = None

        if 'ticket' in data:
            # get parents data
            ticket = data['ticket']
            # title
            div = tag.div(class_='description')
            if 'TICKET_CREATE' in req.perm(ticket.resource) \
                    and ticket['status'] != 'closed':
                opt_inherit = self.env.config.getlist(
                    'subtickets', 'type.%(type)s.child_inherits' % ticket)
                if self.opt_add_style == 'link':
                    inh = {f: ticket[f] for f in opt_inherit}
                    link = tag.a(_('add'),
                                 href=req.href.newticket(parents=ticket.id,
                                                         **inh))
                    link = tag.span('(', link, ')', class_='addsubticket')
                else:
                    inh = [
                        tag.input(type='hidden', name=f, value=ticket[f])
                        for f in opt_inherit
                    ]

                    button = tag.form(tag.div(tag.input(
                        type="submit",
                        value=_("Create"),
                        title=_("Create a child ticket")),
                                              inh,
                                              tag.input(type="hidden",
                                                        name="parents",
                                                        value=str(ticket.id)),
                                              class_="inlinebuttons"),
                                      method="get",
                                      action=req.href.newticket())
            div.append(button)
            div.append(tag.h3(_('Subtickets '), link))

        if 'subtickets' in data:
            # table
            tbody = tag.tbody()
            div.append(tag.table(tbody, class_='subtickets'))
            # tickets
            self._create_subtickets_table(req, data['subtickets'], tbody)

        if div:
            add_stylesheet(req, 'subtickets/css/subtickets.css')
            '''
            If rendered in preview mode, DIV we're interested in isn't a child
            but the root and transformation won't succeed.
            According to HTML specification, id's must be unique within a
            document, so it's safe to omit the leading '.' in XPath expression
            to select all matching regardless of hierarchy their in. 
            '''
            stream |= Transformer('//div[@id="ticket"]').append(div)

        return stream
    def gen_calendar(self, tickets, query, month, width=None, nav=True):
        milestones = self._get_milestones()

        req = self.req
        locale = self._get_locale()
        first_week_day = self._get_first_week_day(locale)
        start_date_format = self.mod.start_date_format
        due_date_format = self.mod.due_date_format

        if not month:
            month = get_today(req.tz).replace(day=1)

        # init data
        today = get_today(req.tz)

        # generate calendar data
        weeks = self._get_month_calendar(month.year, month.month,
                                         first_week_day, locale)
        days = sorted(sum(weeks, []))
        tickets = self._filter_tickets(days, tickets, req.tz)
        milestones = self._filter_milestones(days, milestones, req.tz)
        cal = [[{'date': day,
                 'tickets': tickets[day], 'milestones': milestones[day]}
                for day in week]
               for week in weeks]

        def genli(t):
            if isinstance(t, Milestone):
                return self._create_milestone_item(t)
            else:
                return self._create_ticket_item(t)

        def gentd(week_idx, day_info):
            day = day_info['date']
            tt = day_info['milestones'] + day_info['tickets']
            if len(tt) < 6:
                ttshow = tt
                ttall = []
            else:
                ttshow = tt[:4]
                ttall = tt

            tdclass = []
            if day == today:
                tdclass.append('today')
            if is_weekend(day, locale):
                tdclass.append('weekend')

            formatted_day = format_date(day, format='long', locale=locale)

            td = tag.td(
                class_=' '.join(tdclass),
                data_for_start_date=day.strftime(start_date_format),
                data_for_due_date=day.strftime(due_date_format),
                data_fdate=formatted_day)

            label = []
            if day == today:
                label.append(tag.span(_("Today"), class_='today'))
            label.append(tag.span(unicode(day.day),
                                  class_=('day normal', 'day')[day == today]))
            td(tag.div(label))
            if ttshow:
                td(tag.ul([genli(t) for t in ttshow]))

            if ttall:
                id = 'calendar-more-%s' % str(day)
                td(tag.a(_("%d more tickets...") % (len(ttall) - 4),
                         href='#' + id,
                         class_='show-all-list'),
                   tag.div(tag.h4(formatted_day),
                           tag.ul([genli(t) for t in ttall]),
                           class_='ticketcalendar-popup-list',
                           id=id,
                           data_title=format_date(day, locale=locale,
                                                  format='full')))

            return td

        day_names = get_day_names(locale=locale, width='abbreviated')
        day_names = [day_names[(idx + first_week_day) % 7]
                     for idx in xrange(7)]

        header = tag.div(class_='ticketcalendar-header')
        if nav:
            def nav_href(d):
                return self.get_box_href(query, d)

            def nav_pager(d):
                return tag.span(
                    tag.a(u'\u25c4', href=nav_href(d - timedelta(days=1))),
                    tag.a(_("Current month"),
                          href=nav_href(get_today(req.tz))),
                    tag.a(u'\u25ba', href=nav_href(d + timedelta(days=31))),
                    class_='ticketcalendar-pager')

            def nav_macro():
                macro = (
                    '[[TicketCalendar(type=box,month=%(month)s,'
                    'query=%(query)s,order=%(order)s%(extra)s)]]' %
                    (dict(month=month.strftime('%Y-%m'),
                          query=self.build_query_string(query.constraints),
                          order=query.order,
                          extra=query.desc and ',desc=1' or '')))
                text = tag.input(type='text', readonly='readonly', size='80',
                                 value=macro, style='width:0;display:none')
                return tag.span(_("Macro"), text,
                                class_='ticketcalendar-macro')

            header(tag.div(nav_macro(), nav_pager(month),
                           class_='ticketcalendar-nav'))

        header(tag.h4(_("%(month_name)s, %(year)s",
                        month_name=_get_month_name(month, locale),
                        year=month.year)))

        calendar = tag.table(
             tag.thead(tag.tr(tag.th(name) for name in day_names)),
             tag.tbody([tag.tr([gentd(idx, d) for d in w])
                               for idx, w in enumerate(cal)]),
             class_='calendar')

        can_create = 'TICKET_CREATE' in req.perm

        ticket_box = tag.div(
            tag.h4(tag.span('', class_='tc-today-date')),
            tag.ul(
                tag.li(tag.a(
                    tag_("New ticket with \"%(date)s\" as the start date",
                         date=tag.span('', data='start-date')),
                    data_href=req.href('newticket',
                                       [(self.mod.start_date_name, '')]),
                    class_='newticket-start-date')),
                tag.li(tag.a(
                    tag_("New ticket with \"%(date)s\" as the due date",
                         date=tag.span('', data='due-date')),
                    data_href=req.href('newticket',
                                       [(self.mod.due_date_name, '')]),
                    class_='newticket-due-date'))),
            title=_("Create new ticket"),
            class_='ticketcalendar-newticket-box',
            style='display:none',
            data_writable=(None, 'writable')[can_create])

        class_ = ('ticketcalendar',
                  'ticketcalendar ticketcalendar-can-create')[can_create]
        return tag.div(header, calendar, ticket_box, class_=class_,
                       style=width and ('width: %s' % width) or None)
Exemple #54
0
    def expand_macro(self, formatter, name, arguments):
        """Returns macro content."""
        env = self.env
        req = formatter.req
        tz = req.tz

        # Parse arguments from macro invocation.
        args, kwargs = parse_args(arguments, strict=False)

        # Enable week number display regardless of argument position.
        week_pref = 'w' in args and args.pop(args.index('w'))

        week_pref = week_pref and week_pref or kwargs.get('w')
        week_start = None
        week_num_start = None
        # Parse per-instance week calculation rules, if available.
        if week_pref:
            if ':' not in week_pref:
                # Treat undelimitted setting as week start.
                week_pref += ':'
            w_start, wn_start = week_pref.split(':')
            try:
                week_start = int(w_start)
            except ValueError:
                week_start = None
            else:
                week_start = week_start > -1 and week_start < 7 and \
                             week_start or None
            try:
                week_num_start = int(wn_start)
            except ValueError:
                week_num_start = None
            else:
                week_num_start = week_num_start in (1, 4, 7) and \
                                 week_num_start or None

        # Respect user's locale, if available.
        try:
            locale = Locale.parse(str(req.locale))
        except (AttributeError, UnknownLocaleError):
            # Attribute 'req.locale' vailable since Trac 0.12.
            locale = None
        if has_babel:
            if locale:
                if not locale.territory:
                    # Search first locale, which has the same `language` and
                    # territory in preferred languages.
                    for l in req.languages:
                        l = l.replace('-', '_').lower()
                        if l.startswith(locale.language.lower() + '_'):
                            try:
                                l = Locale.parse(l)
                                if l.territory:
                                    locale = l
                                    break  # first one rules
                            except UnknownLocaleError:
                                pass
                if not locale.territory and locale.language in LOCALE_ALIASES:
                    locale = Locale.parse(LOCALE_ALIASES[locale.language])
            else:
                # Default fallback.
                locale = Locale('en', 'US')
            env.log.debug('Locale setting for wiki calendar: %s' %
                          locale.get_display_name('en'))
        if not week_start:
            if week_pref and week_pref.lower().startswith('iso'):
                week_start = 0
                week_num_start = 4
            elif has_babel:
                week_start = locale.first_week_day
            else:
                import calendar
                week_start = calendar.firstweekday()
        # ISO calendar will remain as default.
        if not week_num_start:
            if week_start == 6:
                week_num_start = 1
            else:
                week_num_start = 4
        env.log.debug('Effective settings: first_week_day=%s, '
                      '1st_week_of_year_rule=%s' %
                      (week_start, week_num_start))

        # Find year and month of interest.
        year = req.args.get('year')
        # Not clicked on any previous/next button, next look for macro args.
        if not year and len(args) >= 1 and args[0] != "*":
            year = args[0]
        year = year and year.isnumeric() and int(year) or None

        month = req.args.get('month')
        # Not clicked on any previous/next button, next look for macro args.
        if not month and len(args) >= 2 and args[1] != "*":
            month = args[1]
        month = month and month.isnumeric() and int(month) or None

        now = datetime.now(tz)
        # Force offset from start-of-day to avoid a false 'today' marker,
        # but use it only on request of different month/year.
        now.replace(second=1)
        today = None
        if (month and month != now.month) or (year and year != now.year):
            today = now.replace(year=year, month=month, day=1)
        # Use current month and year, if nothing else has been requested.
        if not today:
            today = now.replace(hour=0, minute=0, second=0, microsecond=0)

        showbuttons = True
        if len(args) >= 3 or kwargs.has_key('nav'):
            try:
                showbuttons = kwargs['nav'] in _TRUE_VALUES
            except KeyError:
                showbuttons = args[2] in _TRUE_VALUES

        wiki_page_format = "%Y-%m-%d"
        if len(args) >= 4 and args[3] != "*" or kwargs.has_key('wiki'):
            try:
                wiki_page_format = str(kwargs['wiki'])
            except KeyError:
                wiki_page_format = str(args[3])
        # Support relative paths in macro arguments for wiki page links.
        wiki_page_format = resolve_relative_name(wiki_page_format,
                                                 formatter.resource.id)

        list_condense = 0
        show_t_open_dates = True
        wiki_subpages = []

        # Read optional check plan.
        check = []
        if kwargs.has_key('check'):
            check = kwargs['check'].split('.')

        if name == 'WikiTicketCalendar':
            if len(args) >= 5 or kwargs.has_key('cdate'):
                try:
                    show_t_open_dates = kwargs['cdate'] in _TRUE_VALUES
                except KeyError:
                    show_t_open_dates = args[4] in _TRUE_VALUES

            # TracQuery support for ticket selection
            query_args = "id!=0"
            if len(args) >= 7 or kwargs.has_key('query'):
                # prefer query arguments provided by kwargs
                try:
                    query_args = kwargs['query']
                except KeyError:
                    query_args = args[6]

            # compress long ticket lists
            if len(args) >= 8 or kwargs.has_key('short'):
                # prefer query arguments provided by kwargs
                try:
                    list_condense = int(kwargs['short'])
                except KeyError:
                    list_condense = int(args[7])

            # control calendar display width
            cal_width = "100%;"
            if len(args) >= 9 or kwargs.has_key('width'):
                # prefer query arguments provided by kwargs
                try:
                    cal_width = kwargs['width']
                except KeyError:
                    cal_width = args[8]

            # multiple wiki (sub)pages per day
            if kwargs.has_key('subpages'):
                wiki_subpages = kwargs['subpages'].split('|')

        # Prepare datetime objects for previous/next navigation link creation.
        prev_year = month_offset(today, -12)
        prev_quarter = month_offset(today, -3)
        prev_month = month_offset(today, -1)
        next_month = month_offset(today, 1)
        next_quarter = month_offset(today, 3)
        next_year = month_offset(today, 12)

        # Find first and last calendar day, probably in last/next month,
        # using datetime objects exactly at start-of-day here.
        # Note: Calendar days are numbered 0 (Mo) - 6 (Su).
        first_day_month = today.replace(day=1, second=0)
        first_day = first_day_month - timedelta(
            week_index(first_day_month, week_start))
        last_day_month = next_month.replace(day=1) - timedelta(1)
        if ((last_day_month - first_day).days + 1) % 7 > 0:
            last_day = last_day_month + timedelta(7 - (
                (last_day_month - first_day).days + 1) % 7)
        else:
            last_day = last_day_month

        # Find relevant tickets.
        if name == 'WikiTicketCalendar':
            daystr = (uts and '..' or ':').join([
                format_datetime(first_day, locale=locale),
                format_datetime(last_day, locale=locale)
            ])
            provider = WikiCalendarTicketProvider(env)
            query_args = query_args and query_args + '&' or ''
            tkt_due = provider.harvest(
                req, query_args + '='.join([self.tkt_due_field, daystr]))
            if show_t_open_dates:
                tkt_new = provider.harvest(
                    req, query_args + '='.join(['created', daystr]))

        # Finally building the output now.
        # Begin with caption and optional navigation links.
        buff = tag.tr()

        if showbuttons is True:
            # Create calendar navigation buttons.
            nx = 'next'
            pv = 'prev'
            nav_pv_y = _nav_link(req, '&lt;&lt;', pv, prev_year, locale)
            nav_pv_q = _nav_link(req, '&nbsp;&laquo;', pv, prev_quarter,
                                 locale)
            nav_pv_m = _nav_link(req, '&nbsp;&lt;', pv, prev_month, locale)
            nav_nx_m = _nav_link(req, '&gt;&nbsp;', nx, next_month, locale)
            nav_nx_q = _nav_link(req, '&raquo;&nbsp;', nx, next_quarter,
                                 locale)
            nav_nx_y = _nav_link(req, '&gt;&gt;', nx, next_year, locale)

            # Add buttons for going to previous months and year.
            buff(nav_pv_y, nav_pv_q, nav_pv_m)

        # The caption will always be there.
        if has_babel:
            heading = tag.td(format_datetime(today, 'MMMM y', locale=locale))
        else:
            heading = tag.td(format_date(today, '%B %Y'))
        buff = buff(heading(class_='y'))

        if showbuttons is True:
            # Add buttons for going to next months and year.
            buff(nav_nx_m, nav_nx_q, nav_nx_y)
        buff = tag.caption(tag.table(tag.tbody(buff)))
        buff = tag.table(buff)
        if name == 'WikiTicketCalendar':
            if cal_width.startswith('+') is True:
                width = ":".join(['min-width', cal_width])
                buff(class_='wikitcalendar', style=width)
            else:
                buff(class_='wikitcalendar')
        if name == 'WikiCalendar':
            buff(class_='wiki-calendar')

        heading = tag.tr()
        heading(align='center')
        if week_pref:
            # Add an empty cell matching the week number column below.
            heading(tag.th())

        day_names = [(idx, day_name) for idx, day_name in get_day_names(
            'abbreviated', 'format', locale).iteritems()]
        # Read day names after shifting into correct position.
        for idx, name_ in day_names[week_start:7] + day_names[0:week_start]:
            col = tag.th(name_)
            if has_babel:
                weekend = idx >= locale.weekend_start and \
                          idx <= locale.weekend_end
            else:
                weekend = idx > 4
            col(class_=('workday', 'weekend')[weekend], scope='col')
            heading(col)
        heading = buff(tag.thead(heading))

        # Building main calendar table body
        buff = tag.tbody()
        day = first_day
        while day.date() <= last_day.date():
            # Insert a new row for every week.
            if (day - first_day).days % 7 == 0:
                line = tag.tr()
                line(align='right')
                if week_pref:
                    cell = tag.td(
                        week_num(env, day, week_start, week_num_start))
                    line(cell(class_='week'))
            if not (day < first_day_month or day > last_day_month):
                wiki = format_date(day, wiki_page_format)
                if day == today:
                    a_class = 'day today'
                    td_class = 'today'
                else:
                    a_class = 'day'
                    td_class = 'day'

                if uts:
                    day_ts = to_utimestamp(day)
                    day_ts_eod = day_ts + 86399999999
                else:
                    day_ts = to_timestamp(day)
                    day_ts_eod = day_ts + 86399

                # Check for milestone(s) on that day.
                #db = env.get_read_db()
                #cursor = db.cursor()
                #cursor.execute("""
                #    SELECT name
                #      FROM milestone
                #     WHERE due >= %s and due <= %s
                #""", (day_ts, day_ts_eod))
                cursor = self.env.db_query(
                    """
                    SELECT name
                      FROM milestone
                     WHERE due >= %s and due <= %s
                """, (day_ts, day_ts_eod))
                milestones = tag()
                for row in cursor:
                    if not a_class.endswith('milestone'):
                        a_class += ' milestone'
                    milestone = to_unicode(row[0])
                    url = env.href.milestone(milestone)
                    milestone = '* ' + milestone
                    milestones = tag(
                        milestones,
                        tag.div(tag.a(milestone, href=url),
                                class_='milestone'))
                label = tag.span(day.day)
                label(class_='day')
                # Generate wiki page links with name specified in
                # 'wiki_page_format', and check their existence.
                if len(wiki_subpages) > 0:
                    pages = tag(label, Markup('<br />'))
                    for page in wiki_subpages:
                        label = tag(' ', page[0])
                        page = '/'.join([wiki, page])
                        pages(
                            self._wiki_link(req, args, kwargs, page, label,
                                            'subpage', check))
                else:
                    pages = self._wiki_link(req, args, kwargs, wiki, label,
                                            a_class, check)
                cell = tag.td(pages)
                cell(class_=td_class, valign='top')
                if name == 'WikiCalendar':
                    line(cell)
                else:
                    if milestones:
                        cell(milestones)
                    else:
                        cell(tag.br())

                    match = []
                    match_od = []
                    ticket_heap = tag('')
                    ticket_list = tag.div('')
                    ticket_list(align='left', class_='condense')

                    # Get tickets with due date set to day.
                    for t in tkt_due:
                        due = t.get(self.tkt_due_field)
                        if due is None or due in ('', '--'):
                            continue
                        else:
                            if self.tkt_due_format == 'ts':
                                if not isinstance(due, datetime):
                                    continue
                                if uts:
                                    due_ts = to_utimestamp(due)
                                else:
                                    due_ts = to_timestamp(due)
                                if due_ts < day_ts or due_ts > day_ts_eod:
                                    continue
                            else:
                                # Beware: Format might even be unicode string,
                                # but str is required by the function.
                                duedate = format_date(day,
                                                      str(self.tkt_due_format))
                                if not due == duedate:
                                    continue

                        tkt_id = t.get('id')
                        ticket, short = _ticket_links(env, formatter, t)
                        ticket_heap(ticket)
                        if not tkt_id in match:
                            if len(match) == 0:
                                ticket_list(short)
                            else:
                                ticket_list(', ', short)
                            match.append(tkt_id)

                    # Optionally, get tickets created on day too.
                    if show_t_open_dates:
                        ticket_od_list = tag.div('')
                        ticket_od_list(align='left',
                                       class_='opendate_condense')

                        for t in tkt_new:
                            if uts:
                                ticket_ts = to_utimestamp(t.get('time'))
                            else:
                                ticket_ts = to_timestamp(t.get('time'))
                            if ticket_ts < day_ts or ticket_ts > day_ts_eod:
                                continue

                            a_class = 'opendate_'
                            tkt_id = t.get('id')
                            ticket, short = _ticket_links(
                                env, formatter, t, a_class)
                            ticket_heap(ticket)
                            if not tkt_id in match:
                                if len(match_od) == 0:
                                    ticket_od_list(short)
                                else:
                                    ticket_od_list(', ', short)
                                match_od.append(tkt_id)

                    matches = len(match) + len(match_od)
                    if list_condense > 0 and matches >= list_condense:
                        if len(match_od) > 0:
                            if len(match) > 0:
                                ticket_list(', ')
                            ticket_list = tag(ticket_list, ticket_od_list)
                        line(cell(ticket_list))
                    else:
                        line(cell(ticket_heap))
            else:
                if name == 'WikiCalendar':
                    wiki = format_date(day, wiki_page_format)
                    a_class = 'day adjacent_month'
                    pages = self._wiki_link(req, args, kwargs, wiki, day.day,
                                            a_class)
                    cell = tag.td(pages, class_='day adjacent_month')
                    line(cell)
                else:
                    cell = tag.td('', class_='day adjacent_month')
                    line(cell)
            # Append completed week rows.
            if (day - first_day).days % 7 == 6:
                buff(line)
            day += timedelta(1)

        buff = tag.div(heading(buff))
        if name == 'WikiTicketCalendar':
            if cal_width.startswith('+') is True:
                width = ":".join(['width', cal_width])
                buff(class_='wikitcalendar', style=width)
            else:
                buff(class_='wikitcalendar')
        if name == 'WikiCalendar':
            buff(class_='wiki-calendar')
        # Add common CSS stylesheet.
        if self.internal_css and not req.args.get('wikicalendar'):
            # Put definitions directly into the output.
            f = open('/'.join([self.htdocs_path, 'wikicalendar.css']), 'Ur')
            css = tag.style(Markup('<!--\n'), '\n'.join(f.readlines()),
                            Markup('-->\n'))(type="text/css")
            f.close()
            # Add hint to prevent multiple inclusions.
            req.args['wikicalendar'] = True
            return tag(css, buff)
        elif not req.args.get('wikicalendar'):
            add_stylesheet(req, 'wikicalendar/wikicalendar.css')
        return buff