| <!--! |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| <!--! |
| groups - a dict, where: |
| key - is the value shared by all results in this group |
| value - is the list of corresponding tickets |
| |
| headers - a sequence of header structure: |
| .name - field name for this header |
| .label - what to display for this header |
| |
| fields - dict of field name to field structure: |
| .label - field label |
| |
| query - the actual Query instance used to perform the query |
| |
| --> |
| <div xmlns="http://www.w3.org/1999/xhtml" |
| xmlns:py="http://genshi.edgewall.org/" |
| xmlns:i18n="http://genshi.edgewall.org/i18n" |
| xmlns:xi="http://www.w3.org/2001/XInclude"> |
| <div py:if="paginator.has_more_pages"> |
| <div class="report-result" style="float: left; margin-right: 1.6em;"> |
| Results <span class="numresults">(${paginator.displayed_items()})</span> |
| </div> |
| <xi:include py:if="paginator.show_index" href="page_index.html" /> |
| </div> |
| <py:def function="group_heading(groupname, results, is_first=False)"> |
| <div class="report-result" py:if="groupname is not None" |
| style="${'border: 1px #DDDDDD solid; border-bottom: none; font-weight: bold; padding: 4px 5px;' if is_first else None}" |
| i18n:msg="grouplabel, groupname, count" |
| py:with="grouplabel = fields[query.group].label; |
| groupname = authorinfo(groupname) if query.group in ['owner', 'reporter'] else (groupname or _('None')); |
| count = ngettext('%(num)s match', '%(num)s matches', len(results))"> |
| ${grouplabel}: ${groupname} <span class="numrows">(${count})</span> |
| </div> |
| </py:def> |
| <py:def function="column_headers()"> |
| <tr class="trac-columns"> |
| <th py:for="header in headers" |
| class="$header.name${(' desc' if query.desc else ' asc') if query.order == header.name else ''}" py:with=""> |
| <?python asc = _('(ascending)'); desc = _('(descending)') ?> |
| <a title="${_('Sort by %(col)s %(direction)s', col=header.label, |
| direction=(desc if query.order == header.name and not query.desc else asc))}" |
| href="$header.href"> |
| ${header.label} |
| <i py:if="query.order == header.name" |
| class="${'icon-chevron-down' if query.desc else 'icon-chevron-up'}"></i> |
| </a> |
| </th> |
| </tr> |
| </py:def> |
| <!--! TODO: Find an elegant solution for styling --> |
| <style> |
| .table-bordered.query thead:first-child tr:first-child th:first-child, |
| .table-bordered.query tbody:first-child tr:first-child td:first-child { |
| border-top-left-radius: 0px; |
| } |
| </style> |
| ${group_heading(*groups[0], is_first=True) if groups else None} |
| <table class="listing tickets table table-bordered table-condensed query" |
| style="border-radius: 0px 0px 4px 4px"> |
| <thead py:strip="group_index"> |
| ${column_headers()} |
| </thead> |
| <py:for each="group_index, (groupname, results) in enumerate(groups)"> |
| <tbody py:if="group_index"> |
| <tr py:if="groupname is not None" class="trac-group"> |
| <th colspan="${len(headers)}"> |
| ${group_heading(groupname, results)} |
| </th> |
| </tr> |
| ${column_headers()} |
| </tbody> |
| <tbody> |
| <tr py:if="not results" class="even"> |
| <td colspan="${len(headers)}"> |
| No tickets found |
| </td> |
| </tr> |
| <py:for each="idx, result in enumerate(results)"> |
| <py:with vars="ticket_context = context.child('ticket', result.id)"> |
| <py:if test="'TICKET_VIEW' in perm(ticket_context.resource)"> |
| |
| <tr class="${'odd' if idx % 2 else 'even'} prio${result.priority_value}${ |
| ' added' if 'added' in result else ''}${ |
| ' changed' if 'changed' in result else ''}${ |
| ' removed' if 'removed' in result else ''}"> |
| <py:for each="idx, header in enumerate(headers)" py:choose=""> |
| <py:with vars="name = header.name; value = result[name]"> |
| <td py:when="name == 'id'" class="id"><a href="$result.href" title="View ticket" |
| class="${classes(closed=result.status == 'closed')}">#$result.id</a></td> |
| <td py:otherwise="" class="$name" py:choose=""> |
| <a py:when="name == 'summary'" href="$result.href" title="View ticket">$value</a> |
| <py:when test="isinstance(value, datetime)">${pretty_dateinfo(value, dateonly=True)}</py:when> |
| <py:when test="name == 'reporter'">${authorinfo(value)}</py:when> |
| <py:when test="name == 'cc'">${format_emails(ticket_context, value)}</py:when> |
| <py:when test="name == 'owner' and value">${authorinfo(value)}</py:when> |
| <py:when test="name == 'milestone'"><a py:if="value" title="View milestone" href="${href.milestone(value)}">${value}</a></py:when> |
| <py:when test="header.wikify">${wiki_to_oneliner(ticket_context, value)}</py:when> |
| <py:otherwise>$value</py:otherwise> |
| </td> |
| </py:with> |
| </py:for> |
| </tr> |
| |
| <py:with vars="result_rows = [t for t in row if result[t]]"> |
| <py:choose> |
| <tr py:when="ticket_context.resource in context" class="fullrow"> |
| <td colspan="${len(headers)}"> |
| <p class="meta"><em>(this ticket)</em></p> |
| </td> |
| </tr> |
| <tr py:otherwise="" py:for="r in result_rows" class="fullrow"> |
| <th class="meta">${fields.get(r, {'label': r or 'none'}).label}</th> |
| <td colspan="${len(headers)-1}" xml:space="preserve"> |
| ${wiki_to_html(ticket_context, result[r])} |
| </td> |
| </tr> |
| </py:choose> |
| </py:with> |
| </py:if> |
| </py:with> |
| </py:for> |
| <tr py:if="group_index == len(groups)-1 and last_group_is_partial"> |
| <td colspan="${len(headers)}"> |
| <i>(more results for this group on next page)</i> |
| </td> |
| </tr> |
| </tbody> |
| </py:for> |
| </table> |
| <xi:include py:if="paginator.show_index" href="page_index.html" /> |
| </div> |
| |