Exemplo n.º 1
0
 def _render(self, req, ticket, exists):
     if exists:
         message = self.changesets.format()
         return tag.div(tag.h2(_("Repository Changesets"),
                               class_='foldable'),
                        tag.div(message, id='changelog'),
                        class_=self.collapsed and 'collapsed')
     else:
         message = _("(none)")
         return tag.div(tag.h2(_("Repository Changesets"), ' ', message,
                               class_='foldable'))
Exemplo n.º 2
0
    def run(self):
        """
        Main routine of the wiki macro.
        """
        out = tag.div(class_="wiki-toc trac-nav")

        # header
        out.append(tag.h2(tag.a("TracNav", href=TRACNAVHOME)))

        # add TOCs
        for name in (self.names or ["TOC"]):
            toc = self.parse_toc(self.get_toc(name))
            if not toc:
                toc = self.parse_toc(' * TOC "%s" is empty!' % name)
            found, filtered = self.filter_toc(toc)
            if (not self.collapse) or (not found):
                self.display_all(name, toc, out)
            else:
                self.display_all(name, filtered, out)

        # add our stylesheet
        add_stylesheet(self.req, 'tracnav/css/tracnav.css')

        # done
        return out
Exemplo n.º 3
0
    def _reminder_tags(self, req, data):
        if 'ticket' not in data or not data['ticket'].id:
            return None

        ticket = data['ticket']

        if ticket['status'] == 'closed':
            return None

        li_tags = [
            tag.li(self._format_reminder(req, ticket, *args))
            for args in self._get_reminders(ticket.id)
        ]
        if li_tags:
            list_tags = tag.ul(li_tags, class_="reminders")
        else:
            list_tags = []

        add_form = self._reminder_add_form(req)

        if not list_tags and not add_form:
            return None

        return \
            tag.div(
                tag.h2("Reminders", class_="foldable"),
                tag.div(
                    list_tags,
                    add_form,
                ),
                id="reminders",
            )
Exemplo n.º 4
0
    def _reminder_tags(self, req, data):
        if 'ticket' not in data or not data['ticket'].id:
            return None

        ticket = data['ticket']

        if ticket['status'] == 'closed':
            return None

        li_tags = [tag.li(self._format_reminder(req, ticket, *args)) for args in self._get_reminders(ticket.id)]
        if li_tags:
            list_tags = tag.ul(li_tags, class_="reminders")
        else:
            list_tags = []

        add_form = self._reminder_add_form(req)

        if not list_tags and not add_form:
            return None

        return \
            tag.div(
                tag.h2("Reminders", class_="foldable"),
                tag.div(
                    list_tags,
                    add_form,
                ),
                id="reminders",
            )
Exemplo n.º 5
0
    def filter_stream(self, req, method, filename, stream, data):
        
        if self._is_ticket(req):
            
            if self._is_external(req):
                self._talk_about(req)
            
            ticket = self._get_ticket_from_request(req)
            links = self._get_incoming_links_for_ticket(ticket)
            
            if len(links) != 0:
        
                ticket = self._get_ticket_from_request(req)
                
                div = tag.div(id="trashtalk")
    
                for link in links:
                    a = tag.a(href=link['external_url'])
                    a(link['external_url'])
                    div(a)
                    div(" (%s)" % link['click_count'])
                    div(tag.br)
                
                stream |= Transformer('//div[@id="ticket"]').after(div).after(tag.h2("Incoming Links"))

        return stream
Exemplo n.º 6
0
    def process_request(self, req):
        match = re.match(r'^/l10nhelp/(.*)$', req.path_info)
        template = 'l10nhelp/%s.html' % match.group(1)
        data = {}

        data['ajax_request'] = ajax_request = \
            req.get_header('X-Requested-With') == 'XMLHttpRequest' and \
            req.args.get('ajax_request') == '1'

        last_modified = self.template_available(template)
        # Include cache headers to ease on server requests since this data does
        # not change besides the locale to render it
        req.check_modified(last_modified, extra=req.locale)

        if not last_modified:
            if ajax_request:
                req.write(tag(tag.h2(_('Error')), tag.p(_("Help Not Found"))))
                raise RequestDone
            raise ResourceNotFound(_("Help Not Found"))

        if not ajax_request:
            data.update( {'template': template} )
            return 'l10n_help_base.html', data, None

        output = self.rendered_templates.get((req.locale, template))
        if output is None:
            output = WeakReferenceRenderer(self.env, template, data)
            self.rendered_templates[(req.locale, template)] = output
        req.write(output.render(req))
        raise RequestDone
    def filter_stream(self, req, method, filename, stream, data):
        if re.match('/milestone/[^ ]', req.path_info):
            help_page_url = req.href.help('DefineGuide', 'DefineAgile', 'BurndownCharts')
            stream = stream | Transformer("//*[@id='milestone-overview']").after(tag(
                                                                                    tag.h2("Burn Down Chart ", 
                                                                                        tag.a(
                                                                                            tag.i(class_="fa fa-question-circle color-muted", id_="burndown_more_info"),
                                                                                        href=help_page_url, target="_blank")
                                                                                        ), 
                                                                                    tag.div(id_='milestone-burndown', class_='milestone-info')
                                                                                    )
                                                                                )

        return stream
Exemplo n.º 8
0
    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
Exemplo n.º 9
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)])
Exemplo n.º 10
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
Exemplo n.º 11
0
 def buildbot_status(status):
     content = tag.h2("Buildbot: ")
     content.append(status)
     return FILTER.append(tag.div(content, class_="buildbot"))
Exemplo n.º 12
0
    def filter_stream(self, req, method, filename, stream, data):

        # this is shamelessly stollen from MasterTickets
        if data and filename in ["report_view.html", "query_results.html", "ticket.html", "query.html"]:
            self._link_parent(req, filename, 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')
            add_stylesheet(req, 'common/css/report.css')
            add_stylesheet(req, 'common/css/roadmap.css')
            add_script(req, 'ct/js/childtickets.js')

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

                priorities = dict([(p.name, int(p.value)) for p in Priority.select(self.env)])
                # Are there any child tickets to display?
                childtickets = self._get_childtickets(ticket, priorities)

                # 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()
                progresshtml = tag.div()

                # Test if the ticket has children: If so, then list in pretty table.
                if childtickets:
                    progresshtml = self._construct_progress(req, ticket)
                    tablediv = self._contruct_tickets_table(req, ticket, childtickets, priorities)

                # trac.ini : child tickets are allowed - Set up 'create new ticket' buttons.
                if childtickets_allowed and 'TICKET_CREATE' in req.perm(ticket.resource):
                    buttondiv = self._contruct_buttons(req, ticket)
            
                snippet.append(tag.h2("Child Tickets",class_="foldable"))
                snippet.append(tag.div(progresshtml, tablediv, buttondiv, id="childtickets"))

                return stream | filter.after(snippet)

        return stream
        def expand_macro(self, formatter, name, args):
            # Create a HTML div tag to contain our return tables formatted in HTML
            returnDiv = tag.div()
	    # Create a connection to the database.
	    db = self.env.get_read_db()
	    cursor = db.cursor()
	    # Execute the SQL query on the #define ticket database. This query returns all tickets which have been updated with a '[number]:' tag since review.
	    cursor.execute("""SELECT t.id AS ticket, summary, milestone AS __group__, last_committed AS modified, t.owner as owner, t.component as component, t.status as status
                                FROM ticket t 
                                LEFT OUTER JOIN (
                                        SELECT ticket, MAX(time) AS last_reviewed
                                        FROM ticket_change
                                        WHERE field = 'comment' AND newvalue LIKE '%= Review%'
                                        GROUP BY ticket
                                ) rev ON rev.ticket = t.id
                                LEFT OUTER JOIN (
                                        SELECT ticket, MAX(time) AS last_committed
                                        FROM ticket_change
                                        WHERE field = 'comment' AND newvalue LIKE '[%]:%'
                                        GROUP BY ticket
                                ) ch ON ch.ticket = t.id
                                INNER JOIN milestone m ON m.name = milestone
                                WHERE last_committed > COALESCE(last_reviewed, 0)
                                ORDER BY milestone, component,  modified""")

	    currentMilestone = None
	    # i is used to track odd or even row numbers so the table row class can be set as either odd or even.
	    i = 0

	    # This loop iterates through the values returned by the SQL query.
	    for ticket, summary, __group__, modified, owner, component, status in cursor:
                    i+=1
		    if currentMilestone != __group__:
                            i = 0
                            if currentMilestone != None:
                                    # Print a blank line between tables but not before the first table
                                    returnDiv.append(tag.br())
			    # Start a new group.
			    currentMilestone = __group__
			    # Create a table header for the table to hold the values returned by the query.
			    currentTable = tag.table(self.table_header(),
						     class_="listing tickets")
			    # Create a heading for the group and append it to returnDiv then append currentTable.
			    returnDiv.append(tag.h2(currentMilestone or "No milestone set", class_="report-result"))
			    returnDiv.append(currentTable)
		    oddeven = (i%2 and 'odd' or 'even')
		    # oddeven is used to change the css class of the table rows to improve legibility.
		    ticket_resource = Resource('ticket',ticket)
		    # ticket_resource is used to specify the ticket resource from the trac environment. 
		    currentTable.append(tag.tr(tag.td(tag.a(get_resource_shortname(self.env, ticket_resource),
							    href=get_resource_url(self.env, ticket_resource, formatter.href))),
					       tag.td(summary),
					       tag.td(format_datetime(modified, tzinfo=formatter.req.tz)),
					       tag.td(owner),
					       tag.td(component),
					       tag.td(status), class_=oddeven))
		    # The above populates the rows with the results returned by our query.

            

	    return returnDiv
    def filter_stream(self, req, method, filename, stream, data):
        """
        We add JavaScript files and other DOM elements via the filter stream, 
        but actually query the DB and parse the data after the initial page 
        load via AJAX for a page load performance boost. See IRequestHandler 
        methods.

        We only add these scripts and elements if the milestone has a minimum 
        of atleast one ticket.

        We also only render the completed work DOM elements if a minimum of 
        one ticket has been closed.
        """

        if req.path_info.startswith('/milestone/'):

            milestone = self._get_milestone(req.args['id'])
            if milestone and self._milestone_has_ticket(milestone.name):

                add_script(req, 'common/js/jqPlot/jquery.jqplot.js')
                add_script(req, 'common/js/jqPlot/excanvas.min.js')
                add_script(req, 'common/js/jqPlot/plugins/jqplot.pieRenderer.min.js')
                add_stylesheet(req, 'common/js/jqPlot/jquery.jqplot.css')
                add_stylesheet(req, 'workload/css/workload.css')
                add_script(req, 'workload/js/workload.js')
                add_script_data(req, {'milestone_name': milestone.name})

                if not milestone.completed:
                    workload_tag = tag(
                        tag.h2("Remaining Work ", class_="inline-block"),
                        tag.i(id_='workload-help',class_='fa fa-question-circle color-muted'),
                        tag.div(
                            tag.div(id_='milestone-workload',
                                    class_='milestone-info span6 center',
                                    style="display:inline;"
                            ),
                            tag.div(id_='milestone-workload-hours',
                                    class_='milestone-info span6 center',
                                    style="display:inline;"
                            ),
                        id_="workload-charts",
                        class_="row-fluid"
                        ),
                        tag.div(
                            tag.p("Remaining work pie charts are generated to help projects recognise the effort necessary to complete the milestone."),
                            tag.p("The open tickets chart counts the number of open tickets each project member has to complete within the milestone."),
                            tag.p("The remaining hours chart reflects the cumulative estimated hours of efforts required to close these tickets."),
                            tag.p("In both charts only the top {0} members with the highest ticket/hours count are displayed. Remaining members have their data aggregated into a 'other' group.".format(self.user_limit)),
                            id_="workload-dialog", class_="hidden"
                        ),
                    )
                    stream = stream | Transformer("//*[@id='field-analysis']").after(workload_tag)

                if self._milestone_has_closed_ticket(milestone.name):

                    workdone_tag = tag(
                        tag.h2("Completed Work ", class_="inline-block"),
                        tag.i(id_='workdone-help', class_='fa fa-question-circle color-muted'),
                        tag.div(
                            tag.div(id_='milestone-workdone',
                                    class_='milestone-info span6 center',
                                    style="display:inline;"
                            ),
                            tag.div(id_='milestone-workdone-hours',
                                    class_='milestone-info span6 center',
                                    style="display:inline;"
                            ),
                        id_="workdone-charts",
                        class_="row-fluid"
                        ),
                        tag.div(
                            tag.p("Completed work pie charts are generated to help projects analyse the contribution of members during the milestone."),
                            tag.p("The closed tickets charts counts the number of tickets each project member has completed during the milestone."),
                            tag.p("The hours logged chart reflects the cumulative hours of work that were required to close these tickets."),
                            tag.p("In both charts only the top {0} members with the highest ticket/hours count are displayed. Remaining members have their data aggregated into a 'other' group.".format(self.user_limit)),
                            id_="workdone-dialog", class_="hidden"
                        ),
                    )

                    div = 'workload-charts' if not milestone.completed else 'field-analysis'
                    stream = stream | Transformer("//*[@id='{0}']".format(div)).after(workdone_tag)

        return stream