Пример #1
0
 def format(self):
     if not self.changesets:
         message = _("No changesets for #%s" % self.tkt_id)
         yield tag.span(format_to_oneliner(self.env, self.context, message, 
                                           shorten=False),
                        class_='ticketchangesets hint')
         return
     n = len(self.changesets)
     ix = 0 # current index for adding separation markers between repos
     for (reponame, changesets) in self.changesets:
         if n > 1:
             if self.hint == 'ticket':
                 if reponame and reponame != '(default)':
                     yield tag.h3(reponame, class_='change')
                 else:
                     yield tag.h3(_("Default Repository"), class_='change')
             elif ix > 0:
                 yield ', '
         revs = changesets.wiki_revs(reponame, self.compact)
         log = changesets.wiki_log(reponame)
         message = revs + ' (' + log + ')'
         yield tag.span(format_to_oneliner(self.env, self.context, message,
                                           shorten=False),
                        class_='ticketchangesets')
         ix += 1
Пример #2
0
 def expand_macro(self, formatter, name, arguments):
     self.mc.options(arguments)
     extras = self.mc.extras()
     extra = ''
     if 'extra' in extras:
         extra = extras['extra']
     return tag.div(
         tag.h3('[[%s(%s)]]' % (name, arguments)),
         tag.table(tag.tr(tag.th('Name'), tag.th('Value'),
                          tag.th('Qualified'), tag.th('Default?'),
                          tag.th('Macroarg?'), tag.th('Extra?'),
                          tag.th('Known?'), tag.th('Default'),
                          tag.th('Documentation')),
                   self._show_option('text', self.mo_text,
                                     TracMacroConfigExample.mo_text),
                   self._show_option('bool', self.mo_bool,
                                     TracMacroConfigExample.mo_bool),
                   self._show_option('int', self.mo_int,
                                     TracMacroConfigExample.mo_int),
                   self._show_option('list', self.mo_list,
                                     TracMacroConfigExample.mo_list),
                   self._show_option('nodtext', self.mo_nodtext,
                                     TracMacroConfigExample.mo_nodtext),
                   self._show_option('nodbool', self.mo_nodbool,
                                     TracMacroConfigExample.mo_nodbool),
                   self._show_option('nodint', self.mo_nodint,
                                     TracMacroConfigExample.mo_nodint),
                   self._show_option('nodlist', self.mo_nodlist,
                                     TracMacroConfigExample.mo_nodlist),
                   self._show_extra('extra', extra),
                   border=1,
                   cellpadding=1,
                   cellspacing=0))
Пример #3
0
 def expand_macro(self, formatter, name, arguments):
     self.mc.options(arguments)
     extras = self.mc.extras()
     extra = ''
     if 'extra' in extras:
         extra = extras['extra']
     return tag.div(
         tag.h3('[[%s(%s)]]' % ( name, arguments )),
         tag.table(
           tag.tr(
             tag.th('Name'), tag.th('Value'), tag.th('Qualified'),
             tag.th('Default?'), tag.th('Macroarg?'), tag.th('Extra?'),
             tag.th('Known?'), tag.th('Default'), tag.th('Documentation')
           ),
           self._show_option('text', self.mo_text,
                             TracMacroConfigExample.mo_text),
           self._show_option('bool', self.mo_bool,
                             TracMacroConfigExample.mo_bool),
           self._show_option('int', self.mo_int,
                             TracMacroConfigExample.mo_int),
           self._show_option('list', self.mo_list,
                             TracMacroConfigExample.mo_list),
           self._show_option('nodtext', self.mo_nodtext,
                             TracMacroConfigExample.mo_nodtext),
           self._show_option('nodbool', self.mo_nodbool,
                             TracMacroConfigExample.mo_nodbool),
           self._show_option('nodint', self.mo_nodint,
                             TracMacroConfigExample.mo_nodint),
           self._show_option('nodlist', self.mo_nodlist,
                             TracMacroConfigExample.mo_nodlist),
           self._show_extra('extra', extra),
           border=1, cellpadding=1, cellspacing=0
         )
     )
Пример #4
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))
Пример #5
0
class MacroListMacro(WikiMacroBase):
    _domain = 'messages'
    _description = cleandoc_(
    """Display a list of all installed Wiki macros, including documentation if
    available.
    
    Optionally, the name of a specific macro can be provided as an argument. In
    that case, only the documentation for that macro will be rendered.
    
    Note that this macro will not be able to display the documentation of
    macros if the `PythonOptimize` option is enabled for mod_python!
    """)

    def expand_macro(self, formatter, name, content):
        from trac.wiki.formatter import system_message

        content = content.strip() if content else ''
        name_filter = content.strip('*')

        def get_macro_descr():
            for macro_provider in formatter.wiki.macro_providers:
                names = list(macro_provider.get_macros() or [])
                if name_filter and not any(name.startswith(name_filter)
                                           for name in names):
                    continue
                try:
                    name_descriptions = [
                        (name, macro_provider.get_macro_description(name))
                        for name in names]
                except Exception, e:
                    yield system_message(
                        _("Error: Can't get description for macro %(name)s",
                          name=names[0]), e), names
                else:
                    for descr, pairs in groupby(name_descriptions,
                                                key=lambda p: p[1]):
                        if descr:
                            if isinstance(descr, (tuple, list)):
                                descr = dgettext(descr[0], descr[1])
                            else:
                                descr = to_unicode(descr) or ''
                            if content == '*':
                                descr = format_to_oneliner(
                                    self.env, formatter.context, descr,
                                    shorten=True)
                            else:
                                descr = format_to_html(
                                    self.env, formatter.context, descr)
                        yield descr, [name for name, descr in pairs]

        return tag.div(class_='trac-macrolist')(
            (tag.h3(tag.code('[[', names[0], ']]'), id='%s-macro' % names[0]),
             len(names) > 1 and tag.p(tag.strong(_("Aliases:")),
                                      [tag.code(' [[', alias, ']]')
                                       for alias in names[1:]]) or None,
             description or tag.em(_("Sorry, no documentation found")))
            for description, names in sorted(get_macro_descr(),
                                             key=lambda item: item[1][0]))
Пример #6
0
    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
Пример #7
0
 def setTitle(self, title):
     if self.title is None:
         self.title = tag.title()
         self.head.append(self.title)
     if self.header is None:
         self.header = tag.h3()
         self.body.append(self.header)
     self.title.children = [title]
     self.header.children = [title]
Пример #8
0
 def __project_display(self, req, milestone):
     row = self.__SmpModel.get_project_milestone(milestone)
     
     if row:
         return tag.span(
                         tag.h3(wiki_to_oneliner("Project: %s" % (row[0],), self.env, req=req))
                         )
     else:
         return []
Пример #9
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()))
Пример #10
0
    def expand_macro(self, formatter, name, content):
        prefix = limit = None
        if content:
            argv = [arg.strip() for arg in content.split(',')]
            if len(argv) > 0:
                prefix = argv[0]
                if len(argv) > 1:
                    limit = int(argv[1])

        cursor = formatter.db.cursor()

        sql = 'SELECT name, ' \
              '  max(version) AS max_version, ' \
              '  max(time) AS max_time ' \
              'FROM wiki'
        args = []
        if prefix:
            sql += ' WHERE name LIKE %s'
            args.append(prefix + '%')
        sql += ' GROUP BY name ORDER BY max_time DESC'
        if limit:
            sql += ' LIMIT %s'
            args.append(limit)
        cursor.execute(sql, args)

        entries_per_date = []
        prevdate = None
        for name, version, ts in cursor:
            if not 'WIKI_VIEW' in formatter.perm('wiki', name, version):
                continue
            time = datetime.fromtimestamp(ts, utc)
            date = format_date(time)
            if date != prevdate:
                prevdate = date
                entries_per_date.append((date, []))
            version = int(version)
            diff_href = None
            if version > 1:
                diff_href = formatter.href.wiki(name, action='diff',
                                                version=version)
            page_name = formatter.wiki.format_page_name(name)
            entries_per_date[-1][1].append((page_name, name, version,
                                            diff_href))

        return tag.div([tag.h3(date) +
                        tag.ul([tag.li(tag.a(page_name,
                                             href=formatter.href.wiki(name)),
                                       ' ',
                                       diff_href and 
                                       tag.small('(', tag.a('diff',
                                                            href=diff_href),
                                                 ')') or
                                       None)
                                for page_name, name, version, diff_href
                                in entries])
                        for date, entries in entries_per_date])
Пример #11
0
    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))
                        _func(children[id], depth + 1)

                _func(data['subtickets'])

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

        return stream
Пример #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()

        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()))
Пример #13
0
    def expand_macro(self, formatter, name, content):
        from trac.wiki.formatter import system_message

        content = content.strip() if content else ''
        name_filter = content.strip('*')

        def get_macro_descr():
            for macro_provider in formatter.wiki.macro_providers:
                names = list(macro_provider.get_macros() or [])
                if name_filter and not any(
                        name.startswith(name_filter) for name in names):
                    continue
                try:
                    name_descriptions = [
                        (name, macro_provider.get_macro_description(name))
                        for name in names
                    ]
                except Exception as e:
                    yield system_message(
                        _("Error: Can't get description for macro %(name)s",
                          name=names[0]), e), names
                else:
                    for descr, pairs in groupby(name_descriptions,
                                                key=lambda p: p[1]):
                        if descr:
                            if isinstance(descr, (tuple, list)):
                                descr = dgettext(descr[0],
                                                 to_unicode(descr[1])) \
                                        if descr[1] else ''
                            else:
                                descr = to_unicode(descr) or ''
                            if content == '*':
                                descr = format_to_oneliner(self.env,
                                                           formatter.context,
                                                           descr,
                                                           shorten=True)
                            else:
                                descr = format_to_html(self.env,
                                                       formatter.context,
                                                       descr)
                        yield descr, [name for name, descr in pairs]

        return tag.div(class_='trac-macrolist')(
            (tag.h3(tag.code('[[', names[0], ']]'), id='%s-macro' % names[0]),
             len(names) > 1 and tag.p(
                 tag.strong(_("Aliases:")),
                 [tag.code(' [[', alias, ']]')
                  for alias in names[1:]]) or None,
             description or tag.em(_("Sorry, no documentation found")))
            for description, names in sorted(get_macro_descr(),
                                             key=lambda item: item[1][0]))
Пример #14
0
    def expand_macro(self, formatter, name, content):
        prefix = limit = None
        if content:
            argv = [arg.strip() for arg in content.split(',')]
            if len(argv) > 0:
                prefix = argv[0]
                if len(argv) > 1:
                    limit = int(argv[1])

        cursor = formatter.db.cursor()

        sql = 'SELECT name, ' \
              '  max(version) AS max_version, ' \
              '  max(time) AS max_time ' \
              'FROM wiki'
        args = []
        if prefix:
            sql += ' WHERE name LIKE %s'
            args.append(prefix + '%')
        sql += ' GROUP BY name ORDER BY max_time DESC'
        if limit:
            sql += ' LIMIT %s'
            args.append(limit)
        cursor.execute(sql, args)

        entries_per_date = []
        prevdate = None
        for name, version, ts in cursor:
            if not 'WIKI_VIEW' in formatter.perm('wiki', name, version):
                continue
            date = format_date(from_utimestamp(ts))
            if date != prevdate:
                prevdate = date
                entries_per_date.append((date, []))
            version = int(version)
            diff_href = None
            if version > 1:
                diff_href = formatter.href.wiki(name, action='diff',
                                                version=version)
            page_name = formatter.wiki.format_page_name(name)
            entries_per_date[-1][1].append((page_name, name, version,
                                            diff_href))
        return tag.div(
            (tag.h3(date),
             tag.ul(
                 tag.li(tag.a(page, href=formatter.href.wiki(name)), ' ',
                        diff_href and
                        tag.small('(', tag.a('diff', href=diff_href), ')') or
                        None)
                 for page, name, version, diff_href in entries))
            for date, entries in entries_per_date)
Пример #15
0
    def expand_macro(self, formatter, name, content):
        args, kw = parse_args(content)
        prefix = args[0].strip() if args else None
        limit = _arg_as_int(args[1].strip(), min=1) if len(args) > 1 else None
        group = kw.get('group', 'date')

        sql = """SELECT name, max(version) AS max_version,
                        max(time) AS max_time FROM wiki"""
        args = []
        if prefix:
            with self.env.db_query as db:
                sql += " WHERE name %s" % db.prefix_match()
                args.append(db.prefix_match_value(prefix))
        sql += " GROUP BY name ORDER BY max_time DESC"
        if limit:
            sql += " LIMIT %s"
            args.append(limit)

        entries_per_date = []
        prevdate = None
        for name, version, ts in self.env.db_query(sql, args):
            if not 'WIKI_VIEW' in formatter.perm('wiki', name, version):
                continue
            req = formatter.req
            date = user_time(req, format_date, from_utimestamp(ts))
            if date != prevdate:
                prevdate = date
                entries_per_date.append((date, []))
            version = int(version)
            diff_href = None
            if version > 1:
                diff_href = formatter.href.wiki(name, action='diff',
                                                version=version)
            page_name = formatter.wiki.format_page_name(name)
            entries_per_date[-1][1].append((page_name, name, version,
                                            diff_href))

        items_per_date = (
            (date, (tag.li(tag.a(page, href=formatter.href.wiki(name)),
                           tag.small(' (', tag.a(_("diff"), href=diff_href),
                                     ')') if diff_href else None,
                           '\n')
                    for page, name, version, diff_href in entries))
            for date, entries in entries_per_date)

        if group == 'date':
            out = ((tag.h3(date), tag.ul(entries))
                   for date, entries in items_per_date)
        else:
            out = tag.ul(entries for date, entries in items_per_date)
        return tag.div(out)
Пример #16
0
    def expand_macro(self, formatter, name, content):
        args, kw = parse_args(content)
        prefix = args[0].strip() if args else None
        limit = int(args[1].strip()) if len(args) > 1 else None
        group = kw.get('group', 'date')

        sql = """SELECT name, max(version) AS max_version,
                        max(time) AS max_time FROM wiki"""
        args = []
        if prefix:
            with self.env.db_query as db:
                sql += " WHERE name %s" % db.prefix_match()
                args.append(db.prefix_match_value(prefix))
        sql += " GROUP BY name ORDER BY max_time DESC"
        if limit:
            sql += " LIMIT %s"
            args.append(limit)

        entries_per_date = []
        prevdate = None
        for name, version, ts in self.env.db_query(sql, args):
            if not 'WIKI_VIEW' in formatter.perm('wiki', name, version):
                continue
            req = formatter.req
            date = user_time(req, format_date, from_utimestamp(ts))
            if date != prevdate:
                prevdate = date
                entries_per_date.append((date, []))
            version = int(version)
            diff_href = None
            if version > 1:
                diff_href = formatter.href.wiki(name, action='diff',
                                                version=version)
            page_name = formatter.wiki.format_page_name(name)
            entries_per_date[-1][1].append((page_name, name, version,
                                            diff_href))

        items_per_date = (
            (date, (tag.li(tag.a(page, href=formatter.href.wiki(name)),
                           tag.small(' (', tag.a(_("diff"), href=diff_href),
                                     ')') if diff_href else None,
                           '\n')
                    for page, name, version, diff_href in entries))
            for date, entries in entries_per_date)

        if group == 'date':
            out = ((tag.h3(date), tag.ul(entries))
                   for date, entries in items_per_date)
        else:
            out = tag.ul(entries for date, entries in items_per_date)
        return tag.div(out)
Пример #17
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()))
Пример #18
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()))
Пример #19
0
    def expand_macro(self, formatter, name, content):
        prefix = limit = None
        if content:
            argv = [arg.strip() for arg in content.split(',')]
            if len(argv) > 0:
                prefix = argv[0]
                if len(argv) > 1:
                    limit = int(argv[1])

        sql = """SELECT name, max(version) AS max_version, 
                        max(time) AS max_time FROM wiki"""
        args = []
        if prefix:
            sql += " WHERE name LIKE %s"
            args.append(prefix + '%')
        sql += " GROUP BY name ORDER BY max_time DESC"
        if limit:
            sql += " LIMIT %s"
            args.append(limit)

        entries_per_date = []
        prevdate = None
        for name, version, ts in self.env.db_query(sql, args):
            if not 'WIKI_VIEW' in formatter.perm('wiki', name, version):
                continue
            req = formatter.req
            date = user_time(req, format_date, from_utimestamp(ts))
            if date != prevdate:
                prevdate = date
                entries_per_date.append((date, []))
            version = int(version)
            diff_href = None
            if version > 1:
                diff_href = formatter.href.wiki(name, action='diff',
                                                version=version)
            page_name = formatter.wiki.format_page_name(name)
            entries_per_date[-1][1].append((page_name, name, version,
                                            diff_href))
        return tag.div(
            (tag.h3(date),
             tag.ul(
                 tag.li(tag.a(page, href=formatter.href.wiki(name)), ' ',
                        diff_href and
                        tag.small('(', tag.a('diff', href=diff_href), ')') or
                        None)
                 for page, name, version, diff_href in entries))
            for date, entries in entries_per_date)
Пример #20
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
Пример #21
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()))
Пример #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()))
Пример #23
0
    def filter_stream(self, req, method, filename, stream, data):
        if filename == "ticket.html" and 'ticket' in data:
            ticket = data['ticket']

            if ticket.id > 0 and self._have_schedule(ticket):

                add_stylesheet(req, 'ticketrelation/css/schedule.css')

                schedule = self._get_schedule_info(ticket)

                stream |= Transformer('//div[@id="ticket"]').after(
                    tag.div(
                        tag.h3(
                            tag.a('Schedule', id='schedule_label', href='#schedule_label'),
                        class_='foldable'),
                        tag.div(tag.schedule(**{':schedule': 'schedule', ':config': 'config'}), class_='schedule_container', id='schedule_container'),
                    id='schedule')
                )

                config = {
                    'url': req.base_url,
                    'startDate': None,
                    'finishDate': None,
                    'showUnavailable': 1
                }

                stream |= Transformer('//body').append(tag.script("""
                    $(window).load(function() {
                        var data = %s;
                        var config = %s;
                        var app = new Vue({
                            el: '#schedule_container',
                            data: {
                                schedule: data,
                                config: config,
                            }
                        });
                    });
                """ % (json.dumps(schedule, cls=DateTimeEncoder), json.dumps(config, cls=DateTimeEncoder))))

        return stream
Пример #24
0
    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
Пример #25
0
    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):
                    def _sort(children):
                        for sort in reversed(literal_eval(self.sort_children)):
                            transform_key = lambda x: x
                            if isinstance(sort, str):
                                sort_by = sort
                            else:
                                assert(isinstance(sort, list))
                                assert(isinstance(sort[0], str))
                                sort_by = sort[0]
                                if isinstance(sort[1], str):
                                    if sort[1] == "int":
                                        transform_key = int
                                    else:
                                        assert(sort[1] == "float")
                                        transform_key = float
                                else:
                                    assert(isinstance(sort[1], list))
                                    lookup_dict = {v: k for (k, v) in enumerate(sort[1])}
                                    def _lookup(value):
                                        try:
                                            return lookup_dict[value]
                                        except KeyError:
                                            return len(lookup_dict)
                                    transform_key = _lookup

                            if sort_by == 'id':
                                children = sorted(children,
                                                  key=lambda x: transform_key(Ticket(self.env, int(x)).id))
                            else:
                                children = sorted(children,
                                                  key=lambda x: transform_key(Ticket(self.env, int(x))[sort_by]))

                        return children

                    for id in _sort(children):
                        ticket = Ticket(self.env, id)

                        properties_to_show = []
                        # 1st column
                        attrs = {'href': req.href.ticket(id)}
                        if ticket['status'] == 'closed':
                            attrs['class_'] = 'closed'
                        link = tag.a('#%s' % id, **attrs)
                        properties_to_show.append(tag.td(link, ': %s' % ticket['summary'],
                                                         style='padding-left: %dpx;' % (depth * 15)))

                        for property in literal_eval(self.show_fields):
                            properties_to_show.append(tag.td(ticket[property]))

                        tbody.append(apply(tag.tr, properties_to_show))
                        _func(children[id], depth + 1)
                        

                _func(data['subtickets'])

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

            div_accumulations = None
            accumulations = literal_eval(self.show_accumulations)
            if 'subtickets' in data and accumulations:
                def _accumulate(children, field, method):
                    assert(method == 'sum')
                    result = 0
                    for id in children:
                        ticket = Ticket(self.env, id)
                        try:
                            result += float(ticket[field])
                        except ValueError:
                            pass
                        result += _accumulate(children[id], field, method)
                    return result

                div_accumulations = tag.div(class_='description')
                
                tbody = tag.tbody()
                div_accumulations(tag.table(tbody, class_='properties'))

                for accumulation in accumulations:
                    tbody.append(tag.tr(tag.td(accumulation[1]), 
                                        tag.td(_accumulate(data['subtickets'],
                                                           accumulation[0],
                                                           accumulation[2]))))

            if div_accumulations:
                stream |= Transformer('.//div[@id="ticket"]').append(div_accumulations)

        return stream
    def get_box(self, req):
        if req.authname == "anonymous":
            return

        # hoped that ITicketGroupStatsProvider should tell us what the
        # set of "active" statuses, but seems
        # not. DefaultTicketGroupStatsProvider has an idea, from the
        # ini file, but we want to provide new grouping from the
        # LogicaOrderTracker module so it has to be at the interface
        # level rather than component level.
        
        db = self.env.get_read_db()
        cursor = db.cursor()

        counts_ul = tag.ul()
        cursor.execute("""SELECT status, COUNT(status)
                          FROM ticket
                          WHERE owner = %s
                          GROUP BY status
                          ORDER BY 
                            CASE WHEN status = 'assigned'
                              THEN 1
                              ELSE 0
                            END DESC,
                            CASE WHEN status = 'closed'
                              THEN 1
                              ELSE 0
                            END ASC,
                            status ASC""", (req.authname,))
        for status, count in cursor:
            link = tag(tag.span(class_="ticket-state state-" + status), tag.a(status,href=req.href.query(owner=req.authname,
                                                    status=status)))
            counts_ul.append(tag.li(link, ": ", count))


        recent_ul = tag.ul()
        cursor.execute("""SELECT id
                          FROM ticket
                          WHERE ticket.owner = %s
                          GROUP BY id
                          ORDER BY max(changetime) DESC""", 
                       (req.authname,))
        
        shown_count = 0
        ts = TicketSystem(self.env)
        for ticket,  in cursor:
            resource = Resource('ticket', ticket)
            if "TICKET_VIEW" in req.perm(resource):
                shown_count = shown_count + 1
                if shown_count > 5:
                    break
                compact = ts.get_resource_description(resource, 'compact')
                summary = ts.get_resource_description(resource, 'summary')
                link = tag.a(tag.strong(compact), " ", tag.span(summary), href=req.href.ticket(ticket))
                recent_ul.append(tag.li(link))
       

        return tag(
          tag.div(
            tag.h3(
              tag.i(
                class_="fa fa-ticket"
              ),
            " Your Ticket Counts"
            ),
            counts_ul, class_='box-sidebar color-none', id="sidebar-count"
          ),
          tag.div(
            tag.h3(
              tag.i(
                class_="fa fa-star"
              ),
            " Your Recently Modified Tickets"
            ),
            recent_ul, class_='box-sidebar', id="sidebar-recent"
          )
        )
    def get_timeline_markup(self, req, call, maxrows=10):
        """
        Generates the markup needed when this component is called both 
        explicitly inside wiki pages and implicitly by the ISideBarBoxProvider.

        Note this code uses methods from the trac TimelineModule module.
        """

        chrome = Chrome(self.env)

        # last 14 days should be enough
        stop = datetime.now(req.tz)
        start = stop - timedelta(days=50)

        # use code from trac/timeline to generate event data
        timeline = TimelineModule(self.env)
        available_filters, filters = timeline.get_filters(req)
        include_authors, exclude_authors = timeline.authors()
        events = timeline.get_events(req, start, stop, filters, available_filters, 
                                     include_authors, exclude_authors, maxrows)
        show_gravatar = self.config.get('avatar','mode').lower() != 'off'

        # create the mark up
        context = Context.from_request(req)
        event_list = tag.ul(class_="timeline-list no-style")
        for event in events:
            event_title = event['render']('title', context)
            event_url = event['render']('url', context)
            event_list.append(tag.li(
                show_gravatar and tag.img(
                    src=req.href.avatar(event['author'] if event['author'] else 'anonymous'),
                    class_="avatar",
                ) or "",
                tag.span(
                    chrome.authorinfo(req, event['author']),
                    class_="author"
                ),
                tag.span(
                    pretty_age(event['date']),
                    class_="date",
                ),
                tag.div(
                    tag.i(class_="event-type fa fa-" + event['kind']),
                    tag.a(
                        event_title,
                        href=event_url,
                    ),
                    class_="event-summary"
                ),
                class_="cf"
            ))

        # if the markup is being generated via ISideBarBoxProvider we don't 
        # need to add a span3 class 
        div_classes = "box-sidebar"
        if call == "macro":
            div_classes += " span3 right"
        return tag.div(
                    tag.h3(
                        tag.i(
                            class_="fa fa-calendar"
                        ),
                        " Recent Project Activity"
                    ),
                    event_list,
                    class_=div_classes,
                )
Пример #28
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
Пример #29
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
Пример #30
0
    def _expand_recent_topics(self, formatter, name, content):
        self.log.debug("Rendering RecentTopics macro...")

        # Check permission
        if not formatter.perm.has_permission('DISCUSSION_VIEW'):
            return

        # Create request context.
        context = Context.from_request(formatter.req)
        context.realm = 'discussion-wiki'

        # Check if TracTags plugin is enabled.
        context.has_tags = is_tags_enabled(self.env)

        # Get database access.
        db = self.env.get_db_cnx()
        context.cursor = db.cursor()

        # Get API object.
        api = self.env[DiscussionApi]

        # Get list of Trac users.
        context.users = api.get_users(context)

        # Parse macro arguments.
        arguments = []
        forum_id = None
        limit = 10
        if content:
            arguments = [argument.strip() for argument in content.split(',')]
        if len(arguments) == 1:
            limit = arguments[0]
        elif len(arguments) == 2:
            forum_id = arguments[0]
            limit = arguments[1]
        else:
            raise TracError("Invalid number of macro arguments.")

        # Construct and execute SQL query.
        columns = ('forum', 'topic', 'time')
        values = []
        if forum_id:
            values.append(forum_id)
        if limit:
            values.append(limit)
        values = tuple(values)
        sql = ("SELECT forum, topic, MAX(time) as max_time "
               "FROM "
               "  (SELECT forum, topic, time "
               "  FROM message "
               "  UNION "
               "  SELECT forum, id as topic, time "
               "  FROM topic)" +
               (forum_id and " WHERE forum = %s" or "") +
               "  GROUP BY topic "
               "  ORDER BY max_time DESC" +
               (limit and " LIMIT %s" or ""))
        self.log.debug(sql % values)
        context.cursor.execute(sql, values)

        # Collect recent topics.
        entries = []
        for row in context.cursor:
            row = dict(zip(columns, row))
            entries.append(row)

        self.log.debug(entries)

        # Format entries data.
        entries_per_date = []
        prevdate = None
        for entry in entries:
            date = format_date(entry['time'])
            if date != prevdate:
                prevdate = date
                entries_per_date.append((date, []))
            forum_name = api.get_forum(context, entry['forum'])['name']
            topic_subject = api.get_topic_subject(context, entry['topic'])
            entries_per_date[-1][1].append((entry['forum'], forum_name,
              entry['topic'], topic_subject))

        # Format result.
        return tag.div((tag.h3(date), tag.ul(tag.li(tag.a(forum_name, href =
          formatter.href.discussion('forum', forum_id)), ': ', tag.a(
          topic_subject, href = formatter.href.discussion('topic', topic_id)))
          for forum_id, forum_name, topic_id, topic_subject in entries)) for
          date, entries in entries_per_date)
Пример #31
0
    def expand_macro(self, formatter, name, content):
        from trac.config import ConfigSection, Option

        args, kw = parse_args(content)
        filters = {}
        for name, index in (('section', 0), ('option', 1)):
            pattern = kw.get(name, '').strip()
            if pattern:
                filters[name] = fnmatch.translate(pattern)
                continue
            prefix = args[index].strip() if index < len(args) else ''
            if prefix:
                filters[name] = re.escape(prefix)
        has_option_filter = 'option' in filters
        for name in ('section', 'option'):
            filters[name] = re.compile(filters[name], re.IGNORECASE).match \
                            if name in filters \
                            else lambda v: True
        section_filter = filters['section']
        option_filter = filters['option']

        section_registry = ConfigSection.get_registry(self.compmgr)
        option_registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in option_registry.iteritems():
            if section_filter(section) and option_filter(key):
                options.setdefault(section, {})[key] = option
        if not has_option_filter:
            for section in section_registry:
                if section_filter(section):
                    options.setdefault(section, {})
        for section in options:
            options[section] = sorted(options[section].itervalues(),
                                      key=lambda option: option.name)
        sections = [(section, section_registry[section].doc
                              if section in section_registry else '')
                    for section in sorted(options)]

        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')

        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)))

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             options_table(section, options.get(section)))
            for section, section_doc in sections)
Пример #32
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, []) ]

                # 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