diff options
author | Fathi Boudra <fathi.boudra@linaro.org> | 2014-06-02 17:14:02 +0300 |
---|---|---|
committer | Fathi Boudra <fathi.boudra@linaro.org> | 2014-06-02 17:14:02 +0300 |
commit | 46f29f243b1e7642e860b40214d5f893aad678e1 (patch) | |
tree | 7ac82cee0957299e51c36f22ce1b172670513348 /template/en/default/reports |
Initial commit - Bugzilla 4.4.4
Signed-off-by: Fathi Boudra <fathi.boudra@linaro.org>
Diffstat (limited to 'template/en/default/reports')
23 files changed, 1934 insertions, 0 deletions
diff --git a/template/en/default/reports/chart.csv.tmpl b/template/en/default/reports/chart.csv.tmpl new file mode 100644 index 0000000..7293abb --- /dev/null +++ b/template/en/default/reports/chart.csv.tmpl @@ -0,0 +1,32 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% colsepchar = user.settings.csv_colsepchar.value %] + +[% data = chart.data %] +Date\Series +[% FOREACH label = chart.labels %] + [% colsepchar %][% label FILTER csv %] +[% END %] +[%# The data, which is in the correct format for GD, is conceptually the wrong + # way round for CSV output. So, we need to invert it here, which is why + # these loops aren't just plain FOREACH. + #%] +[% i = 0 %] +[% WHILE i < data.0.size %] + [% j = 0 %] + [% WHILE j < data.size %] + [% IF j > 0 %] + [% colsepchar %] + [% END %] + [% data.$j.$i %] + [% j = j + 1 %] + [% END %] + [% i = i + 1 %] + +[% END %] diff --git a/template/en/default/reports/chart.html.tmpl b/template/en/default/reports/chart.html.tmpl new file mode 100644 index 0000000..ab33463 --- /dev/null +++ b/template/en/default/reports/chart.html.tmpl @@ -0,0 +1,55 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + #%] + +[% DEFAULT width = 600 + height = 350 +%] + +[% time = time FILTER time('%Y-%m-%d %H:%M:%S') FILTER html %] + +[% PROCESS global/header.html.tmpl + title = "Chart" + header_addl_info = time +%] + +<div align="center"> + + [% imageurl = BLOCK %]chart.cgi? + [% imagebase FILTER html %]&ctype=png&action=plot&width= + [% width %]&height=[% height -%] + [% END %] + + <img alt="Graphical report results" src="[% imageurl %]" + width="[% width %]" height="[% height %]"> + <p> + [% sizeurl = BLOCK %]chart.cgi? + [% imagebase FILTER html %]&action=wrap + [% END %] + <a href="[% sizeurl %]&width=[% width %]&height= + [% height + 100 %]">Taller</a><br> + <a href="[% sizeurl %]&width=[% width - 100 %]&height= + [% height %]">Thinner</a> * + <a href="[% sizeurl %]&width=[% width + 100 %]&height= + [% height %]">Fatter</a> <br> + <a href="[% sizeurl %]&width=[% width %]&height= + [% height - 100 %]">Shorter</a><br> + </p> + + <p> + <a href="chart.cgi? + [% imagebase FILTER html %]&ctype=csv&action=plot">CSV</a> | + <a href="chart.cgi?[% imagebase FILTER html %]&action=assemble">Edit + this chart</a> + </p> + +</div> + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/chart.png.tmpl b/template/en/default/reports/chart.png.tmpl new file mode 100644 index 0000000..a464acc --- /dev/null +++ b/template/en/default/reports/chart.png.tmpl @@ -0,0 +1,47 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% y_label = "$terms.Bugs" %] +[% x_label = "Time" %] + +[% IF chart.cumulate %] + [% USE graph = GD.Graph.area(width, height) %] + [% graph.set(cumulate => "true") %] +[% ELSE %] + [% USE graph = GD.Graph.lines(width, height) %] +[% END %] + +[% FILTER null; + x_label_skip = (30 * chart.data.0.size / width); + + graph.set(x_label => x_label, + y_label => y_label, + y_tick_number => 8, + y_max_value => chart.y_max_value, + x_label_position => 0.5, + x_labels_vertical => 1, + x_label_skip => x_label_skip, + legend_placement => "RT", + line_width => 2, + dclrs => ["lred", "lgreen", "lblue", "lyellow", + "lpurple", "lorange", "black", "green", + "blue", "dpink", "lbrown", "gray", + "red", "dpurple", "gold", "marine"]); + + # Workaround for the fact that set_legend won't take chart.labels directly, + # because chart.labels is an array reference rather than an array. + graph.set_legend(chart.labels.0, chart.labels.1, chart.labels.2, + chart.labels.3, chart.labels.4, chart.labels.5, + chart.labels.6, chart.labels.7, chart.labels.8, + chart.labels.9, chart.labels.10, chart.labels.11, + chart.labels.12, chart.labels.13, chart.labels.14, + chart.labels.15); + + graph.plot(chart.data).png | stdout(1); + END; +-%] diff --git a/template/en/default/reports/components.html.tmpl b/template/en/default/reports/components.html.tmpl new file mode 100644 index 0000000..2a5d239 --- /dev/null +++ b/template/en/default/reports/components.html.tmpl @@ -0,0 +1,94 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # product: object. The product for which we want to display component + # descriptions. + #%] + +[% title = BLOCK %] + Components for [% product.name FILTER html %] +[% END %] + +[% PROCESS global/header.html.tmpl + style_urls = [ "skins/standard/reports.css" ] + title = title +%] + +[% IF Param("useqacontact") %] + [% numcols = 3 %] +[% ELSE %] + [% numcols = 2 %] +[% END %] + +<table cellpadding="0" cellspacing="0" id="components_header_table"> + <tr> + <td class="instructions"> + Select a component to see open [% terms.bugs %] in that component: + </td> + <td class="product_container"> + <span class="product_name">[% product.name FILTER html %]</span> + <div class="product_desc"> + [% product.description FILTER html_light %] + </div> + </td> + </tr> +</table> + +<span class="components_header">Components</span> + +<table summary="Components table" + class="component_table" cellspacing="0" cellpadding="0"> + <thead> + <tr> + <th> </th> + <th>Default Assignee</th> + [% IF Param("useqacontact") %] + <th>Default QA Contact</th> + [% END %] + </tr> + </thead> + + <tbody> + [% FOREACH comp = product.components %] + [% INCLUDE describe_comp %] + [% END %] + </tbody> +</table> + +[% PROCESS global/footer.html.tmpl %] + +[%############################################################################%] +[%# BLOCK for components %] +[%############################################################################%] + +[% BLOCK describe_comp %] + <tr id="[% comp.name FILTER html %]"> + <td rowspan="2" class="component_name"> + <a href="buglist.cgi?product= + [%- product.name FILTER uri %]&component= + [%- comp.name FILTER uri %]&resolution=---"> + [% comp.name FILTER html %]</a> + </td> + <td class="component_assignee"> + [% INCLUDE global/user.html.tmpl who = comp.default_assignee %] + </td> + [% IF Param("useqacontact") %] + <td class="component_qa_contact"> + [% IF comp.default_qa_contact %] + [% INCLUDE global/user.html.tmpl who = comp.default_qa_contact %] + [% END %] + </td> + [% END %] + </tr> + <tr> + <td colspan="[% numcols - 1 %]" class="component_description"> + [% comp.description FILTER html_light %] + </td> + </tr> +[% END %] diff --git a/template/en/default/reports/create-chart.html.tmpl b/template/en/default/reports/create-chart.html.tmpl new file mode 100644 index 0000000..471a9cb --- /dev/null +++ b/template/en/default/reports/create-chart.html.tmpl @@ -0,0 +1,258 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # chart: Chart object representing the currently assembled chart. + # category: hash (keyed by category) of hashes (keyed by subcategory) of + # hashes (keyed by name), with value being the series_id of the + # series. Contains details of all series the user can see. + #%] + +[% PROCESS global/header.html.tmpl + title = "Create Chart" +%] + +[% PROCESS "reports/series-common.html.tmpl" + donames = 1 +%] + +<script type="text/javascript"> +[%# This function takes necessary action on selection of a subcategory %] +function subcatSelected() { + var cat = document.chartform.category.value; + var subcat = document.chartform.subcategory.value; + var names = series[cat][subcat]; + + var namewidget = document.chartform.name; + + namewidget.options.length = 0; + var i = 0; + + for (x in names) { + namewidget.options[i] = new Option(x, names[x]); + i++; + } + + namewidget.disabled = false; + namewidget.options[0].selected = true; + + checkNewState(); +} +</script> + +[% gttext = "Grand Total" %] + +<form method="get" action="chart.cgi" name="chartform"> + + <table cellpadding="2" cellspacing="2" border="0"> + [% IF NOT category OR category.size == 0 %] + <tr> + <td> + <i>No data sets exist, or none are visible to you.</i> + </td> + </tr> + [% ELSE %] + <tr> + <th><label for="category">Category</label>:</th> + <th></th> + <th><label for="subcategory">Sub-category</label>:</th> + <th></th> + <th><label for="name" accesskey="N">Name</label>:</th> + <th><br> + </th> + </tr> + <tr> + + [% PROCESS series_select sel = { name => 'category', + size => 5, + onchange = "catSelected(); + subcatSelected();" } %] + + <td> + <noscript> + <input type="submit" name="action-assemble" value="Update -->" + id="action-assemble"> + </noscript> + </td> + + [% PROCESS series_select sel = { name => 'subcategory', + size => 5, + onchange = "subcatSelected()" } %] + + <td> + <noscript> + <input type="submit" name="action-assemble" value="Update -->" + id="action-assemble2"> + </noscript> + </td> + + [% PROCESS series_select sel = { name => 'name', + size => 5, + multiple => 1, + # We want to use the series ID as value, + # not its name. + value_in_hash => 1 } %] + + <td align="center" valign="middle"> + <input type="submit" name="action-add" value="Add To List" + id="action-add"><br> + </td> + </tr> + [% END %] + </table> + + <h3>List Of Data Sets To Plot</h3> + + [% IF chart.lines.size %] + <table cellspacing="2" cellpadding="2"> + <tr> + <th style="width: 5em;">Select</th> + <th>Label</th> + <th></th> + <th>Data Set</th> + <th></th> + </tr> + + [%# The external loop has two counters; one which keeps track of where we + # are in the old labels array, and one which keeps track of the new + # indexes for the form elements. They are different if chart.lines has + # empty slots in it. + #%] + [% labelidx = 0 %] + [% newidx = 0 %] + + [% FOREACH line = chart.lines %] + [% IF NOT line %] + [%# chart.lines has an empty slot, so chart.labels will too. We + # increment labelidx only to keep the labels in sync with the data. + #%] + [% labelidx = labelidx + 1 %] + [% NEXT %] + [% END %] + + [% FOREACH series = line %] + <tr> + [% IF loop.first %] + <td align="center" rowspan="[% line.size %]"> + <input type="checkbox" value="1" name="select[% newidx %]"> + </td> + <td rowspan="[% line.size %]"> + <input type="text" size="20" name="label[% newidx %]" + value="[% (chart.labels.$labelidx OR series.name) + FILTER html %]"> + </td> + [% END %] + + <td> + [% "{" IF line.size > 1 %] + </td> + + <td> + [% series.category FILTER html %] / + [%+ series.subcategory FILTER html %] / + [%+ series.name FILTER html %] + <input type="hidden" name="line[% newidx %]" + value="[% series.series_id %]"> + </td> + + <td align="center"> + [% IF user.id == series.creator_id OR user.in_group("admin") %] + <a href="chart.cgi?action=edit&series_id= + [% series.series_id %]">Edit</a> | + <a href="chart.cgi?action=confirm-delete&series_id= + [%- series.series_id %]">Delete</a> | + [% END %] + <a href="buglist.cgi?cmdtype=dorem&namedcmd= + [% series.category FILTER uri %]%20/%20 + [% series.subcategory FILTER uri %]%20/%20 + [% series.name FILTER uri -%]&series_id= + [% series.series_id %]&remaction=runseries">Run Search</a> + </td> + </tr> + [% END %] + [% labelidx = labelidx + 1 %] + [% newidx = newidx + 1 %] + [% END %] + + [% IF chart.gt %] + <tr> + <td align="center"> + <input type="checkbox" value="1" name="select65536"> + <input type="hidden" value="1" name="gt"> + </td> + <td> + <input type="text" size="20" name="labelgt" + value="[% (chart.labelgt OR gttext) FILTER html %]"> + </td> + <td></td> + <td> + <i>[% gttext FILTER html %]</i> + </td> + <td></td> + </tr> + [% END %] + <tr> + <td colspan="6"> </td> + </tr> + + <tr> + <td valign="bottom" style="text-align: center;"> + <input type="submit" name="action-sum" value="Sum" + style="width: 5em;" id="action-sum"><br> + <input type="submit" name="action-remove" value="Remove" + style="width: 5em;" id="action-remove"> + </td> + + <td style="text-align: right; vertical-align: bottom;"> + <label for="cumulate"><b>Cumulate</b></label>: + <input type="checkbox" name="cumulate" id="cumulate" value="1" + [% " checked" IF chart.cumulate %]> + </td> + + <td></td> + <td valign="bottom"> + <label for="datefrom"><b>Date Range</b></label>: + <input type="text" size="12" name="datefrom" id="datefrom" + value="[% time2str("%Y-%m-%d", chart.datefrom) IF chart.datefrom%]"> + <label for="dateto"><b>to</b></label> + <input type="text" size="12" name="dateto" id="dateto" + value="[% time2str("%Y-%m-%d", chart.dateto) IF chart.dateto %]"> + </td> + + <td style="text-align: right" valign="bottom"> + <input type="submit" name="action-wrap" value="Chart This List" + id="action-wrap"> + </td> + </tr> + </table> + [% ELSE %] + <p><i>None</i></p> + [% END %] +</form> + +[% IF user.in_group('editbugs') %] + <h3>Create New Data Set</h3> + <p> + You can either create a new data set based on one of your saved searches + or start with a clean slate. + </p> + + <form action="chart.cgi" id="create_series" name="create_series" method="GET"> + <input type="hidden" name="action" value="convert_search"> + <label for="series_from_search">Based on:</label> + <select id="series_from_search" name="series_from_search"> + <option value="">(Clean slate)</option> + [% FOREACH q = user.queries %] + <option value="[% q.name FILTER html %]">[% q.name FILTER html %]</option> + [% END %] + </select> + <input id="submit_create" type="submit" value="Create a new data set"> + </form> +[% END %] + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/delete-series.html.tmpl b/template/en/default/reports/delete-series.html.tmpl new file mode 100644 index 0000000..7ff8876 --- /dev/null +++ b/template/en/default/reports/delete-series.html.tmpl @@ -0,0 +1,47 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% series_name = BLOCK %] + [% series.category FILTER html %] / + [%+ series.subcategory FILTER html %] / + [%+ series.name FILTER html %] +[% END %] + +[% PROCESS global/header.html.tmpl title = "Delete Series" + style_urls = ['skins/standard/admin.css'] %] + +<p> + You are going to completely remove the <b>[% series_name FILTER none %]</b> series + from the database. All data related to this series will be permanently deleted. +</p> +<p> + [% IF series.creator %] + This series has been created by <a href="mailto:[% series.creator.email FILTER html %]"> + [% series.creator.email FILTER html %]</a> + [% ELSE %] + This series has been automatically created by [% terms.Bugzilla %] + [% END %] + + [% IF series.public %] + and is public. + [% ELSIF series.creator %] + and is only visible by this user. + [% ELSE %] + and cannot be displayed by anybody. + [% END %] +</p> + +<p class="areyoureallyreallysure">Are you sure you want to delete this series?</p> + +<p> + <a href="chart.cgi?action=delete&series_id=[% series.series_id FILTER html %]&token= + [%- issue_hash_token([series.id, series.name]) FILTER uri %]">Yes, delete</a> | + <a href="chart.cgi">No, go back to the charts page</a> +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/duplicates-simple.html.tmpl b/template/en/default/reports/duplicates-simple.html.tmpl new file mode 100644 index 0000000..6f58654 --- /dev/null +++ b/template/en/default/reports/duplicates-simple.html.tmpl @@ -0,0 +1,35 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # You need to fulfill the interface to duplicates-table.html.tmpl. + #%] + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> + [% IF product.size %] + [% title = BLOCK %] + Most Frequently Reported [% terms.Bugs %] for [% product.join(', ') FILTER html %] + [% END %] + [% ELSE %] + [% title = "Most Frequently Reported $terms.Bugs" %] + [% END%] + + <head> + <title>[% title FILTER html %]</title> + <link href="[% 'skins/standard/global.css' FILTER mtime %]" + rel="stylesheet" type="text/css"> + <link href="[% 'skins/standard/duplicates.css' FILTER mtime %]" + rel="stylesheet" type="text/css"> + </head> + + <body> + [% PROCESS "reports/duplicates-table.html.tmpl" %] + </body> +</html> diff --git a/template/en/default/reports/duplicates-table.html.tmpl b/template/en/default/reports/duplicates-table.html.tmpl new file mode 100644 index 0000000..45cf8c3 --- /dev/null +++ b/template/en/default/reports/duplicates-table.html.tmpl @@ -0,0 +1,109 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # bugs: list of hashes. May be empty. Each hash has three members: + # bug: A Bugzilla::Bug object + # count: integer. The number of dupes + # delta: integer. The change in count in the last $changedsince days + # + # bug_ids: list of integers. May be empty. The IDs of the bugs in $bugs. + # + # sortby: string. the column on which we are sorting the buglist. + # reverse: boolean. True if we are reversing the current sort. + # maxrows: integer. Max number of rows to display. + # changedsince: integer. The number of days ago for the changedsince column. + # openonly: boolean. True if we are only showing open bugs. + # product: array of strings. Restrict to these products only. + #%] + +[%# *** Column Headers *** %] + +[% SET columns = [ + { name => "id", description => "$terms.Bug #" }, + { name => "count", description => "Dupe<br>Count" }, + { name => "delta", + description => "Change in last<br>$changedsince day(s)" }, + { name => "component", description => field_descs.component }, + { name => "bug_severity", description => field_descs.bug_severity }, + { name => "op_sys", description => field_descs.op_sys }, + { name => "target_milestone", description => field_descs.target_milestone }, + { name => "short_desc", description => field_descs.short_desc }, +] %] + +[% SET base_args = [] %] +[% FOREACH param = ['maxrows', 'openonly', 'format', 'sortvisible', + 'changedsince', 'product'] +%] + [% NEXT IF NOT ${param}.defined %] + [% FOREACH value = ${param} %] + [% filtered_value = value FILTER uri %] + [% base_args.push("$param=$filtered_value") %] + [% END %] +[% END %] +[% IF sortvisible %] + [% bug_ids_string = bug_ids.nsort.join(',') FILTER uri %] + [% base_args.push("bug_id=$bug_ids_string") %] +[% END %] +[% base_args_string = base_args.join('&') %] + +[% IF bugs.size %] + <table id="duplicates_table" cellpadding="0" cellspacing="0"> + <thead> + <tr> + [% FOREACH column = columns %] + [% IF column.name == sortby %] + [%# We add this to the column object so it doesn't affect future + # iterations of the loop. + #%] + [% column.reverse_sort = reverse ? 0 : 1 %] + [% END %] + <th class="[% column.name FILTER html %]"> + <a href="duplicates.cgi?sortby=[% column.name FILTER uri %] + [% IF column.reverse_sort.defined %] + [%- %]&reverse=[% column.reverse_sort FILTER uri %] + [% END %] + [% IF base_args_string %] + [% "&$base_args_string" FILTER none %] + [% END %]" + >[% column.description FILTER none %]</a> + </th> + [% END %] + </tr> + </thead> + + [%# *** Buglist *** %] + + <tbody> + [% FOREACH item = bugs %] + [% SET bug = item.bug %] + <tr [% " class='resolved'" IF NOT bug.isopened %]> + <td class="id"> + [% bug.id FILTER bug_link(bug) FILTER none %] + </td> + <td class="count">[% item.count FILTER html %]</td> + <td class="delta">[% item.delta FILTER html %]</td> + <td class="component">[% bug.component FILTER html %]</td> + <td class="bug_severity"> + [%- display_value('bug_severity', bug.bug_severity) FILTER html %] + </td> + <td class="op_sys"> + [%- display_value('op_sys', bug.op_sys) FILTER html %] + </td> + <td class="target_milestone"> + [% display_value('target_milestone', + bug.target_milestone) FILTER html %] + </td> + <td class="short_desc">[% bug.short_desc FILTER html %]</td> + </tr> + [% END %] + </tbody> + </table> +[% ELSE %] + <h3>No duplicate [% terms.bugs %] found.</h3> +[% END %] diff --git a/template/en/default/reports/duplicates.html.tmpl b/template/en/default/reports/duplicates.html.tmpl new file mode 100644 index 0000000..4efdcf9 --- /dev/null +++ b/template/en/default/reports/duplicates.html.tmpl @@ -0,0 +1,165 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # sortby: string. the column on which we are sorting the buglist. + # reverse: boolean. True if we are reversing the current sort. + # maxrows: integer. Max number of rows to display. + # changedsince: integer. The number of days ago for the changedsince column. + # openonly: boolean. True if we are only showing open bugs. + # product: array of strings. The set of products we check for dups. + # + # Additionally, you need to fulfill the interface to + # duplicates-table.html.tmpl. + #%] + +[% IF product.size %] + [% title = BLOCK %] + Most Frequently Reported [% terms.Bugs %] for + [%+ product.join(', ') FILTER html %] + [% END %] +[% ELSE %] + [% title = "Most Frequently Reported $terms.Bugs" %] +[% END%] + +[% PROCESS global/header.html.tmpl + title = title + style_urls = ['skins/standard/duplicates.css'] +%] + +<p> + <a href="#explanation">What is this data?</a> + <br> + <a href="#params">Change parameters</a> +</p> + +[% PROCESS "reports/duplicates-table.html.tmpl" %] + +[%# *** Parameters *** %] + +[% bug_ids_string = bug_ids.join(',') %] + +<h3 id="params">Change Parameters</h3> + +<form method="get" action="duplicates.cgi"> + <input type="hidden" name="sortby" value="[% sortby FILTER html %]"> + <input type="hidden" name="reverse" value="[% reverse FILTER html %]"> + <input type="hidden" name="bug_id" value="[% bug_ids_string FILTER html %]"> + <table> + <tr> + <td>When sorting or restricting, work with:</td> + <td> + <input type="radio" name="sortvisible" id="entirelist" value="0" + [% ' checked="checked"' IF NOT sortvisible %]> + <label for="entirelist"> + entire list + </label> + <br> + <input type="radio" name="sortvisible" id="visiblelist" value="1" + [% ' checked="checked"' IF sortvisible %]> + <label for="visiblelist"> + currently visible list + </label> + </td> + <td rowspan="4" valign="top">Restrict to products:</td> + <td rowspan="4" valign="top"> + <select name="product" size="5" multiple="multiple"> + [% FOREACH p = user.get_selectable_products %] + <option name="[% p.name FILTER html %]" + [% ' selected="selected"' IF product.contains(p.name) %] + >[% p.name FILTER html %]</option> + [% END %] + </select> + </td> + </tr> + + <tr> + <td><label for="maxrows">Max rows:</label></td> + <td> + <input size="4" name="maxrows" id="maxrows" + value="[% maxrows FILTER html %]"> + </td> + </tr> + + <tr> + <td> + <label for="changedsince">Change column is change in the last:</label> + </td> + <td> + <input size="4" name="changedsince" id="changedsince" + value="[% changedsince FILTER html %]"> days + </td> + </tr> + + <tr> + <td> + <label for="openonly"> + Open [% terms.bugs %] only: + </label> + </td> + <td> + <input type="checkbox" name="openonly" id="openonly" value="1" + [% ' checked="checked"' IF openonly %]> + </td> + </tr> + + </table> + + <input type="submit" id="change" value="Change"> +</form> + +<form method="post" action="buglist.cgi"> + <input type="hidden" name="bug_id" value="[% bug_ids_string FILTER html %]"> + Or just give this to me as a <input type="submit" id="list" + value="[% terms.bug %] list">. + (Note: the order may not be the same.) +</form> + +<hr> + +<h3 id="explanation"> + What are "Most Frequently Reported [% terms.Bugs %]"? +</h3> + +<p> + The Most Frequent [% terms.Bugs %] page lists the known open + [%+ terms.bugs %] which are reported most frequently, + counting the number of direct and indirect duplicates of [% terms.bugs %]. + This information is provided in order to assist in minimizing + the amount of duplicate [% terms.bugs %] entered into [% terms.Bugzilla %], + which saves time for Quality Assurance engineers who have to triage + the [% terms.bugs %]. +</p> + +<b>How do I use this list?</b> + +<ul> + <li>Review the most frequent [% terms.bugs %] list.</li> + <li>If your problem is listed:</li> + + <ul> + <li>Click on the [% terms.bug %] number to confirm that you have found the + same [% terms.bug %], and comment if you have additional information + or move on with your testing of the product. + </li> + </ul> + + <li>If your problem not listed:</li> + + <ul> + <li><a href="query.cgi">Try and locate a similar [% terms.bug %]</a> + that has already been filed.</li> + <li>If you find your [% terms.bug %] in [% terms.Bugzilla %], + feel free to comment with any new or additional data you may have.</li> + <li>If you cannot find your problem already documented in + [%+ terms.Bugzilla %], + <a href="enter_bug.cgi">file a new [% terms.bug %]</a>.</li> + </ul> +</ul> + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/edit-series.html.tmpl b/template/en/default/reports/edit-series.html.tmpl new file mode 100644 index 0000000..c789262 --- /dev/null +++ b/template/en/default/reports/edit-series.html.tmpl @@ -0,0 +1,63 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% title = "Edit Series" %] +[% subheader = BLOCK %] + [% default.category FILTER html %] / + [%+ default.subcategory FILTER html %] / + [%+ default.name FILTER html %] +[% END %] + +[% PROCESS global/header.html.tmpl %] + +[% IF changes_saved %] + <p> + <font color="red"> + Series updated. + </font> + </p> +[% END %] + +<form method="get" action="chart.cgi" name="chartform"> + + [% PROCESS reports/series.html.tmpl + button_name = "Change Data Set" %] + <input type="hidden" name="action" value="alter"> + <input type="hidden" name="token" + value="[% issue_hash_token([default.id, default.name]) FILTER html %]"> + + [% IF default.series_id %] + <input type="hidden" name="series_id" value="[% default.series_id %]"> + [% END %] +</form> + +<p> + <b>Creator</b>: + [% IF default.creator %] + <a href="mailto:[% default.creator.email FILTER html %]"> + [% default.creator.email FILTER html %]</a> + [% ELSE %] + (automatically created by [% terms.Bugzilla %]) + [% END %] +</p> + +<p>Note: it is not yet possible to edit the search associated with this data +set. +</p> + +<p> + <a href="query.cgi?[% default.query FILTER html %]">View + series search parameters</a> | + <a href="buglist.cgi?cmdtype=dorem&namedcmd= + [% default.category FILTER uri %]- + [% default.subcategory FILTER uri %]- + [% default.name FILTER uri %]&remaction=runseries&series_id= + [% default.series_id %]">Run series search</a> +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/keywords.html.tmpl b/template/en/default/reports/keywords.html.tmpl new file mode 100644 index 0000000..0624041 --- /dev/null +++ b/template/en/default/reports/keywords.html.tmpl @@ -0,0 +1,71 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # keywords: array keyword objects. May be empty. Each has has four members: + # id: id of the keyword + # name: the name of the keyword + # description: keyword description. Can contain some limited HTML code. + # bug_count: number of bugs with that keyword + # caneditkeywords: boolean. True if this user can edit keywords + %] + +[% PROCESS global/header.html.tmpl + title = "$terms.Bugzilla Keyword Descriptions" +%] + +[% FOREACH keyword = keywords %] + [% IF loop.index % 50 == 0 %] + [% IF loop.index != 0 %] + </table> + [% END %] + + <table border="1" cellpadding="4" cellspacing="0"> + <tr bgcolor="#6666FF"> + <th align="left">Name</th> + <th align="left">Description</th> + <th align="left">Open [% terms.Bugs %]</th> + <th align="left">Total [% terms.Bugs %]</th> + </tr> + [% END %] + + <tr id="[% keyword.name FILTER html %]"> + <th> + [% keyword.name FILTER html %] + </th> + <td>[% keyword.description FILTER html_light %]</td> + <td align="center"> + [% IF keyword.bug_count > 0 %] + <a href="buglist.cgi?keywords=[% keyword.name FILTER uri %]&resolution=---"> + Search</a> + [% ELSE %] + none + [% END %] + </td> + <td align="right"> + [% IF keyword.bug_count > 0 %] + <a href="buglist.cgi?keywords=[% keyword.name FILTER uri %]"> + [% keyword.bug_count %]</a> + [% ELSE %] + none + [% END %] + </td> + </tr> +[% END %] + +[% IF keywords.size > 0 %] + </table> +[% END %] + +[% IF caneditkeywords %] + <p> + <a href="editkeywords.cgi">Edit keywords</a>. + </p> +[% END %] + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/menu.html.tmpl b/template/en/default/reports/menu.html.tmpl new file mode 100644 index 0000000..af83ffb --- /dev/null +++ b/template/en/default/reports/menu.html.tmpl @@ -0,0 +1,75 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # This template has no interface. It's a list of the available report + # types in Bugzilla. + #%] + +[% PROCESS global/header.html.tmpl + title = "Reporting and Charting Kitchen" + doc_section = "reporting.html" + style_urls = ['skins/standard/reports.css'] +%] + +<p> + [% terms.Bugzilla %] allows you to view and track the state of the [% terms.bug %] database in + all manner of exciting ways. +</p> + +<h2>Current State</h2> + +<ul> + <li id="report_search"> + <strong><a href="query.cgi">Search</a></strong> - + list sets of [% terms.bugs %]. + </li> + <li id="report_tabular"> + <strong> + <a href="query.cgi?format=report-table">Tabular reports</a> + </strong> - + tables of [% terms.bug %] counts in 1, 2 or 3 dimensions, as HTML or CSV. + </li> + [% IF feature_enabled('graphical_reports') %] + <li id="report_graphical"> + <strong> + <a href="query.cgi?format=report-graph">Graphical reports</a> + </strong> - + line graphs, bar and pie charts. + </li> + [% END %] + <li id="report_duplicates"> + <strong><a href="duplicates.cgi">Duplicates</a></strong> - + list of most frequently reported [% terms.bugs %]. + </li> + [% Hook.process('current_state') %] +</ul> + +[% IF feature_enabled('new_charts') OR feature_enabled('old_charts') %] + <h2>Change Over Time</h2> + + <ul> + [% IF feature_enabled('old_charts') %] + <li id="old_charts"> + <strong><a href="reports.cgi">Old Charts</a></strong> - + plot the status and/or resolution of [% terms.bugs %] against + time, for each product in your database. + </li> + [% END %] + [% IF feature_enabled('new_charts') AND user.in_group(Param("chartgroup")) %] + <li id="new_charts"> + <strong><a href="chart.cgi">New Charts</a></strong> - + plot any arbitrary search against time. Far more powerful. + </li> + [% END %] + </ul> +[% END %] + +[% Hook.process('end') %] + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/old-charts.html.tmpl b/template/en/default/reports/old-charts.html.tmpl new file mode 100644 index 0000000..12a0cdd --- /dev/null +++ b/template/en/default/reports/old-charts.html.tmpl @@ -0,0 +1,62 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # products: an array of product names the user is allowed to view. + # datasets: an array of hashes with available statuses and resolutions. + # url_image: URL of the generated graph. + #%] + +[% PROCESS global/header.html.tmpl + title = "$terms.Bug Charts" + h1 = "Welcome to the $terms.Bugzilla Charting Kitchen" + doc_section = "reporting.html#charts" +%] + +<div align="center"> + [% IF url_image %] + <img src="[% url_image FILTER html %]"> + <br clear="both"> + [% ELSE %] + <form id="choose_product" method="get" action="reports.cgi"> + <table border="1" cellpadding="5" cellspacing="2"> + <tr> + <th>Product:</th> + <td align="center"> + <select id="product" name="product"> + [% FOREACH product = products %] + <option value="[% product FILTER html %]">[% product FILTER html %]</option> + [% END %] + </select> + </td> + </tr> + <tr> + <th>Chart datasets:</th> + <td align="center"> + <select id="datasets" name="datasets" multiple="multiple" size="5"> + [%# We cannot use translated statuses and resolutions from field-descs.none.html + # because old charts do not distinguish statuses from resolutions. %] + [% FOREACH dataset = datasets %] + <option value="[% dataset.value FILTER html %]" + [% " selected=\"selected\"" IF dataset.selected %]> + [% dataset.value FILTER html %]</option> + [% END %] + </select> + </td> + </tr> + <tr> + <th colspan="2"> + <input type="submit" id="submit" value="Continue"> + </th> + </tr> + </table> + </form> + [% END %] +</div> + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/report-bar.png.tmpl b/template/en/default/reports/report-bar.png.tmpl new file mode 100644 index 0000000..70d482e --- /dev/null +++ b/template/en/default/reports/report-bar.png.tmpl @@ -0,0 +1,48 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% y_label = "$terms.Bugs" %] + +[% col_field_disp = field_descs.$col_field || col_field %] + +[% FOR i IN [ 0 .. data.0.0.max ] %] + [% data.0.0.$i = display_value(col_field, data.0.0.$i) %] +[% END %] + +[% FOR i IN [ 0 .. row_names.max ] %] + [% row_names.$i = display_value(row_field, row_names.$i) %] +[% END %] + +[% FILTER null; + USE graph = GD.Graph.bars(width, height); + + graph.set(x_label => col_field_disp, + y_label => y_label, + y_tick_number => 8, + y_number_format => "%d", + x_label_position => 0.5, + x_labels_vertical => x_labels_vertical, + bar_spacing => 8, + shadow_depth => 4, + shadowclr => 'dred', + show_values => 1, + legend_placement => "RT"); + + graph.set(cumulate => "true", + show_values => 0) IF cumulate; + + # Workaround for the fact that set_legend won't take row_names directly, + # because row_names is an array reference rather than an array. + graph.set_legend(row_names.0, row_names.1, row_names.2, row_names.3, + row_names.4, row_names.5, row_names.6, row_names.7, + row_names.8, row_names.9, row_names.10, row_names.11, + row_names.12, row_names.13, row_names.14, row_names.15); + + graph.plot(data.0).png | stdout(1); + END; +-%] diff --git a/template/en/default/reports/report-line.png.tmpl b/template/en/default/reports/report-line.png.tmpl new file mode 100644 index 0000000..073e69b --- /dev/null +++ b/template/en/default/reports/report-line.png.tmpl @@ -0,0 +1,50 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% y_label = "$terms.Bugs" %] + +[% col_field_disp = field_descs.$col_field || col_field %] + +[% FOR i IN [ 0 .. data.0.0.max ] %] + [% data.0.0.$i = display_value(col_field, data.0.0.$i) %] +[% END %] + +[% FOR i IN [ 0 .. row_names.max ] %] + [% row_names.$i = display_value(row_field, row_names.$i) %] +[% END %] + +[% IF cumulate %] + [% USE graph = GD.Graph.area(width, height) %] + [% graph.set(cumulate => "true") %] +[% ELSE %] + [% USE graph = GD.Graph.lines(width, height) %] +[% END %] + +[% FILTER null; + graph.set(x_label => col_field_disp, + y_label => y_label, + y_tick_number => 8, + x_label_position => 0.5, + x_labels_vertical => x_labels_vertical, + legend_placement => "RT", + line_width => 2, + dclrs => ["lred", "lgreen", "lblue", "lyellow", + "lpurple", "lorange", "black", "green", + "blue", "dpink", "lbrown", "gray", + "red", "dpurple", "gold", "marine"]); + + # Workaround for the fact that set_legend won't take row_names directly, + # because row_names is an array reference rather than an array. + graph.set_legend(row_names.0, row_names.1, row_names.2, row_names.3, + row_names.4, row_names.5, row_names.6, row_names.7, + row_names.8, row_names.9, row_names.10, row_names.11, + row_names.12, row_names.13, row_names.14, row_names.15); + + graph.plot(data.0).png | stdout(1); + END; +-%] diff --git a/template/en/default/reports/report-pie.png.tmpl b/template/en/default/reports/report-pie.png.tmpl new file mode 100644 index 0000000..9d3f16f --- /dev/null +++ b/template/en/default/reports/report-pie.png.tmpl @@ -0,0 +1,25 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% col_field_disp = field_descs.$col_field || col_field %] + +[% FOR i IN [ 0 .. data.0.0.max ] %] + [% data.0.0.$i = display_value(col_field, data.0.0.$i) %] +[% END %] + +[% FILTER null; + USE graph = GD.Graph.pie(width, height); + + graph.set(title => col_field_disp, + pie_height => 20, + suppress_angle => 2, + start_angle => 180); + + graph.plot(data.0).png | stdout(1); + END; +-%] diff --git a/template/en/default/reports/report-simple.html.tmpl b/template/en/default/reports/report-simple.html.tmpl new file mode 100644 index 0000000..17b87c6 --- /dev/null +++ b/template/en/default/reports/report-simple.html.tmpl @@ -0,0 +1,25 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # You need to fulfill the interface to report-table.html.tmpl. + #%] + +<html> + + [% title = "$terms.Bug List" %] + + <head> + <title>[% title FILTER html %]</title> + </head> + + <body> + [% PROCESS "reports/report-table.html.tmpl" %] + </body> + +</html> diff --git a/template/en/default/reports/report-table.csv.tmpl b/template/en/default/reports/report-table.csv.tmpl new file mode 100644 index 0000000..e2a92b5 --- /dev/null +++ b/template/en/default/reports/report-table.csv.tmpl @@ -0,0 +1,61 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% colsepchar = user.settings.csv_colsepchar.value %] + +[% num_bugs = BLOCK %]Number of [% terms.bugs %][% END %] +[% tbl_field_disp = field_descs.$tbl_field || tbl_field %] +[% col_field_disp = field_descs.$col_field || col_field %] +[% row_field_disp = field_descs.$row_field || row_field %] + +[% IF tbl_field %] + [% IF tbl_field == 'assigned_to' OR tbl_field == 'reporter' + OR tbl_field == 'qa_contact' + %] + [% tbl_disp = tbl FILTER email %] + [% ELSE %] + [% tbl_disp = tbl %] + [% END %] + [% tbl_field_disp FILTER csv %]: [% tbl_disp FILTER csv %] +[% END %] +[% IF row_field %] + [% row_field_disp FILTER csv %] +[% END %] +[% " / " IF col_field AND row_field %] +[% col_field_disp FILTER csv %] +[% IF col_field -%] + [% FOREACH col = col_names -%] + [% colsepchar %] + [% PROCESS value_display value = col field = col_field %] + [% END -%] +[% ELSE -%] + [% colsepchar %][% num_bugs FILTER csv %] +[% END %] + +[% FOREACH row = row_names %] + [% PROCESS value_display value = row field = row_field %] + [% FOREACH col = col_names %] + [% colsepchar %] + [% IF data.$tbl AND data.$tbl.$col AND data.$tbl.$col.$row %] + [% data.$tbl.$col.$row -%] + [% ELSE %] + [% -%]0 + [% END %] + [% END %] + +[% END %] + +[% BLOCK value_display %] + [% SET disp_value = display_value(field, value) %] + [% IF field == 'assigned_to' OR field == 'reporter' + OR field == 'qa_contact' + %] + [% disp_value = value FILTER email %] + [% END %] + [% disp_value FILTER csv %] +[% END %] diff --git a/template/en/default/reports/report-table.html.tmpl b/template/en/default/reports/report-table.html.tmpl new file mode 100644 index 0000000..2747166 --- /dev/null +++ b/template/en/default/reports/report-table.html.tmpl @@ -0,0 +1,256 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # buglistbase: The base query for this table, in URL form + # col_field: string. Name of the field being plotted as columns. + # row_field: string. Name of the field being plotted as rows. + # tbl_field: string. Name of the field being plotted as tables. + # col_names: array. List of values for the field being plotted as columns. + # row_names: array. List of values for the field being plotted as rows. + # data: <depends on format>. Data to plot. Only data.$tbl is accessed. + # tbl: Name of a hash in data which is the table to be plotted. + #%] + +[% col_field_disp = field_descs.$col_field || col_field %] +[% row_field_disp = field_descs.$row_field || row_field %] + +[% urlbase = BLOCK %]buglist.cgi?[% buglistbase FILTER html %][% END %] +[% IF tbl == "-total-" %] + [% IF tbl_vals %] + [% urlbase = urlbase _ "&" _ tbl_vals %] + [% END %] +[% ELSIF tbl_field %] + [% urlbase = BLOCK %][% urlbase %]&[% tbl_field FILTER uri %]=[% tbl FILTER uri %][% END %] +[% END %] + +<script type="text/javascript"> +function bz_encode (str, decode) { + // First decode HTML entities, if requested. + if (decode) + str = str.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"') + .replace(/ /g, " ").replace(/&/g, "&").replace(/\s+$/,""); + + // encodeURIComponent() doesn't escape single quotes. + return encodeURIComponent(str).replace(/'/g, escape); +}; + +YAHOO.util.Event.addListener(window, "load", function() { + this.Linkify = function(elLiner, oRecord, oColumn, oData) { + if (oData == 0) + elLiner.innerHTML = "."; + else if (oRecord.getData("row_title") == "Total") + elLiner.innerHTML = '<a href="[% urlbase FILTER js %]&[% col_field FILTER uri FILTER js %]=' + + bz_encode(oColumn.field) + + '[% "&" _ row_vals IF row_vals %]">' + oData + '</a>'; + else + elLiner.innerHTML = '<a href="[% urlbase FILTER js %]&[% row_field FILTER uri FILTER js %]=' + + bz_encode(oRecord.getData("row_title"), 1) + + '&[% col_field FILTER uri FILTER js %]=' + + bz_encode(oColumn.field) + '">' + oData + '</a>'; + }; + + this.LinkifyTotal = function(elLiner, oRecord, oColumn, oData) { + if (oData == 0) + elLiner.innerHTML = "."; + else if (oRecord.getData("row_title") == "Total") + elLiner.innerHTML = '<a href="[% urlbase FILTER js %][% "&" _ row_vals IF row_vals %] + [%~ "&" _ col_vals IF col_vals %]">' + + oData + '</a>'; + else + elLiner.innerHTML = '<a href="[% urlbase FILTER js %]&[% row_field FILTER uri FILTER js %]=' + + bz_encode(oRecord.getData("row_title"), 1) + + '[% "&" _ col_vals IF col_vals %]">' + oData + '</a>'; + + YAHOO.util.Dom.addClass(elLiner.parentNode, "ttotal"); + }; + + var totalRowFormatter = function( elTr, oRecord ) { + if ( oRecord.getData('row_title') == "Total" ) { + YAHOO.util.Dom.addClass( elTr, 'ttotal' ); + } + return true; + }; + + var totalNumberSorter = function( a, b, desc, field ){ + var a_value = a.getData(field); + var b_value = b.getData(field); + var a_total_test = a.getData("row_title"); + var b_total_test = b.getData("row_title"); + var comp_result = YAHOO.util.Sort.compare(a_value, b_value, desc); + if( a_total_test == "Total" ){ + comp_result = 1; + }else if( b_total_test == "Total" ){ + comp_result = -1; + } + return comp_result; + }; + + + var myColumnDefs = [ + {key:"row_title", label:"", sortable:true, sortOptions: { sortFunction:totalNumberSorter }}, + [% FOREACH col = col_names %] + {key:"[% col FILTER js %]", label:"[% display_value(col_field, col) FILTER html FILTER js %]", sortable:true, + formatter:this.Linkify, sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC, sortFunction:totalNumberSorter }}, + [% END %] + {key:"total", label:"Total", sortable:true, formatter:this.LinkifyTotal, + sortOptions: { defaultDir: YAHOO.widget.DataTable.CLASS_DESC, sortFunction:totalNumberSorter }} + ]; + this.parseString = function(str) { + return YAHOO.lang.trim(str); + }; + + this.parseNumber = function(str) { + if (str.match(/^\s*\.\s*$/m)) + return 0; + + // Do not use <\/a>$. For some reason, IE6 doesn't understand it. + // We use [^\d]+$ instead. + var res = str.match(/>(\d+)[^\d]+$/m); + if (res && res[1]) + return parseFloat(res[1]); + }; + + this.myDataSource = new YAHOO.util.DataSource(YAHOO.util.Dom.get("tabular_report")); + this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE; + this.myDataSource.responseSchema = { + fields: [ + {key:"row_title", parser:this.parseString}, + [% FOREACH col = col_names %] + {key:"[% col FILTER js %]", parser:this.parseNumber}, + [% END %] + {key:"total", parser:this.parseNumber} + ] + }; + this.myDataTable = new YAHOO.widget.DataTable("tabular_report_container_ + [% tbl FILTER js %]", myColumnDefs, this.myDataSource, + {formatRow: totalRowFormatter}); +}); +</script> + +[% IF tbl_field %] + <h2>[% tbl_disp FILTER email FILTER html %]</h2> +[% END %] + +<table> + <tr> + <td> + </td> + <td align="center"> + <strong>[% col_field_disp FILTER html %]</strong> + </td> + </tr> + + <tr> + <td valign="middle"> + <strong>[% row_field_disp FILTER html %]</strong> + </td> + <td> + + +[% classes = [ [ "t1", "t2" ] , [ "t3", "t4" ] ] %] +[% col_idx = 0 %] +[% row_idx = 0 %] +[% grand_total = 0 %] +<div id="tabular_report_container_[% tbl FILTER html %]"> +<table id="tabular_report" border="1"> + [% IF col_field %] + <thead> + <tr> + <th class="[% classes.$row_idx.$col_idx %]"> + </th> + [% FOREACH col = col_names %] + [% col_totals.$col = 0 %] + [% NEXT IF col == "" %] + + [% col_idx = 1 - col_idx %] + <th class="[% classes.$row_idx.$col_idx %]"> + [% PROCESS value_display value = col field = col_field %] + </th> + [% END %] + <th class="ttotal"> + Total + </th> + </tr> + </thead> + [% END %] + <tbody> + [% FOREACH row = row_names %] + [% row_total = 0 %] + + [% row_idx = 1 - row_idx %] + <tr> + <td class="[% classes.$row_idx.$col_idx %]" align="right"> + [% PROCESS value_display value = row field = row_field %] + </td> + [% FOREACH col = col_names %] + [% row_total = row_total + data.$tbl.$col.$row %] + [% NEXT IF col == "" %] + [% col_totals.$col = (col_totals.$col || 0) + data.$tbl.$col.$row %] + + [% col_idx = 1 - col_idx %] + <td class="[% classes.$row_idx.$col_idx %]" align="center"> + [% IF data.$tbl.$col.$row AND data.$tbl.$col.$row > 0 %] + <a href="[% urlbase %]& + [% row_field FILTER uri %]=[% row FILTER uri %]& + [% col_field FILTER uri %]=[% col FILTER uri %]"> + [% data.$tbl.$col.$row %]</a> + [% ELSE %] + . + [% END %] + </td> + [% END %] + <td class="ttotal" align="right"> + <a href="[% urlbase %]& + [% row_field FILTER uri %]=[% row FILTER uri %] + [% "&$col_vals" IF col_vals %]"> + [% row_total %]</a> + [% grand_total = grand_total + row_total %] + </td> + </tr> + [% END %] + <tr> + [% row_idx = 1 - row_idx %] + <td class="ttotal"> + Total + </td> + [% FOREACH col = col_names %] + [% NEXT IF col == "" %] + + <td class="ttotal" align="center"> + <a href="[% urlbase %]& + [% col_field FILTER uri %]=[% col FILTER uri %] + [% "&$row_vals" IF row_vals %]"> + [% col_totals.$col %]</a> + </td> + [% END %] + <td class="ttotal" align="right"> + <strong> + <a href="[% urlbase %] + [% "&$row_vals" IF row_vals %] + [% "&$col_vals" IF col_vals %]">[% grand_total %]</a> + </strong> + </td> + </tr> + </tbody> +</table> +</div> + + </td> + </tr> +</table> + +[% BLOCK value_display %] + [% SET disp_value = display_value(field, value) %] + [% IF field == 'assigned_to' OR field == 'reporter' + OR field == 'qa_contact' + %] + [% disp_value = value FILTER email %] + [% END %] + [% disp_value FILTER html FILTER replace('^ $',' ') %] +[% END %] diff --git a/template/en/default/reports/report.csv.tmpl b/template/en/default/reports/report.csv.tmpl new file mode 100644 index 0000000..a4f8589 --- /dev/null +++ b/template/en/default/reports/report.csv.tmpl @@ -0,0 +1,12 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] +[% FOREACH tbl = tbl_names %] + [% PROCESS "reports/report-table.csv.tmpl" %] + + +[% END %] diff --git a/template/en/default/reports/report.html.tmpl b/template/en/default/reports/report.html.tmpl new file mode 100644 index 0000000..2ca5dd9 --- /dev/null +++ b/template/en/default/reports/report.html.tmpl @@ -0,0 +1,152 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # col_field: string. Name of the field being plotted as columns. + # row_field: string. Name of the field being plotted as rows. + # tbl_field: string. Name of the field being plotted as tables. + # tbl_names: array. List of values for the field being plotted as tables. + # time: integer. Seconds since the epoch. + # data: <depends on format>. Data to plot. + # format: string. Format of the individual reports. + # width: integer. For image charts, height of the image. + # height: integer. For image charts, width of the image. + # imagebase: string. Base URL for chart image. + # switchbase: string. Base URL for format switching. + # cumulate: boolean. For bar/line charts, whether to cumulate data sets. + #%] + +[% DEFAULT width = 1024 + height = 600 +%] + +[% IF min_width AND width < min_width %] + [% width = min_width %] +[% END %] + +[%# We ignore row_field for pie charts %] +[% IF format == "pie" %] + [% row_field = "" %] +[% END %] + +[% tbl_field_disp = field_descs.$tbl_field || tbl_field %] +[% col_field_disp = field_descs.$col_field || col_field %] +[% row_field_disp = field_descs.$row_field || row_field %] +[% switchbase = switchbase FILTER html %] + +[% title = BLOCK %] + Report: + [% IF tbl_field %] + [% tbl_field_disp FILTER html %] + [% END %] + [% " / " IF tbl_field AND (col_field OR row_field) %] + [% IF row_field %] + [% row_field_disp FILTER html %] + [% END %] + [% " / " IF col_field AND row_field %] + [% col_field_disp FILTER html %] +[% END %] + +[% time = time FILTER time('%Y-%m-%d %H:%M:%S') FILTER html %] + +[% PROCESS global/header.html.tmpl + header_addl_info = time + style_urls = ['skins/standard/reports.css'] + yui = ['datatable'] +%] + +[% IF debug %] + [% FOREACH query = queries %] + <p>[% query.sql FILTER html %]</p> + [% END %] +[% END %] + +<div align="center"> + + [% FOREACH tbl = tbl_names %] + [% IF tbl == "-total-" %] + [% tbl_disp = "Total" %] + [% ELSE %] + [% tbl_disp = tbl %] + [% END %] + + [% IF format == "table" %] + [% PROCESS "reports/report-table.html.tmpl" %] + [% ELSE %] + [% IF tbl %] + <h2>[% tbl_disp FILTER email FILTER html %]</h2> + [% END %] + + [% imageurl = BLOCK %]report.cgi?[% imagebase FILTER html %]&format= + [% format FILTER uri %]&ctype=png&action=plot& + [% IF tbl_field %] + [% IF tbl != "-total-" %] + [% tbl_field FILTER uri %]=[% tbl FILTER uri %]& + [% ELSE %] + [% FOREACH tblname = tbl_names %] + [% IF tblname != "-total-" %] + [% tbl_field FILTER uri %]=[% tblname FILTER uri %]& + [% END %] + [% END %] + [% END %] + [% END %]width=[% width %]&height=[% height %] + [% END %] + + <img id="graphical_report" alt="Graphical report results" src="[% imageurl %]"> + [% END %] + <br> + [% END %] + + [% formats = [ { name => "pie", description => "Pie" }, + { name => "bar", description => "Bar" }, + { name => "line", description => "Line" }, + { name => "table", description => "Table" } ] %] + + [% formaturl = "report.cgi?$switchbase&width=$width&height=$height&action=wrap" %] + [% FOREACH other_format = formats %] + [% NEXT IF other_format.name == "pie" AND row_field AND col_field %] + [% UNLESS other_format.name == format %] + <a href="[% formaturl %]&format=[% other_format.name %]"> + [% END %] + [% other_format.description FILTER html %] + [% "</a>" UNLESS other_format.name == format %] | + [% END %] + <a href="[% formaturl %]&ctype=csv&format=table">CSV</a> + + <table> + <tr> + <td> + [% IF format == "table" %] + <a href="query.cgi?[% switchbase %]&format=report-table">Edit this report</a> + [% ELSE %] + <a href="query.cgi?[% switchbase %]&chart_format= + [%~ format FILTER uri %]&format=report-graph&cumulate=[% cumulate %]"> + Edit this report</a> + [% END %] + </td> + <td>|</td> + <td> + [% IF saved_report_id %] + <a href="report.cgi?action=del&saved_report_id=[% saved_report_id FILTER uri %]&token= + [%~ issue_hash_token(['delete_report', saved_report_id]) FILTER uri %]">Forget this report</a> + [% ELSE %] + <form method="get" action="report.cgi"> + <input type="submit" id="remember" value="Remember report"> as + <input type="hidden" name="query" value="[% switchbase %]&format=[% format FILTER uri %]&action=wrap"> + <input type="hidden" name="action" value="add"> + <input type="hidden" name="token" value="[% issue_hash_token(['save_report']) FILTER html %]"> + <input type="text" id="name" name="name" size="20" value="" maxlength="64"> + </form> + [% END %] + </td> + </tr> + </table> + +</div> + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/reports/series-common.html.tmpl b/template/en/default/reports/series-common.html.tmpl new file mode 100644 index 0000000..35d3c04 --- /dev/null +++ b/template/en/default/reports/series-common.html.tmpl @@ -0,0 +1,107 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # donames: boolean. True if we have a multi-select for names as well as + # categories and subcategories. + # category: hash (keyed by category) of hashes (keyed by subcategory) of + # hashes (keyed by name), with value being the series_id of the + # series. Contains details of all series the user can see. + #%] + +[% subcategory = category.${default.category} %] +[% name = subcategory.${default.subcategory} %] + +<script type="text/javascript"> +[%# This structure holds details of the series the user can select from. %] +var series = { +[% FOREACH c = category.keys.sort %] + "[%+ c FILTER js %]" : { + [% FOREACH s = category.$c.keys.sort %] + "[%+ s FILTER js %]" : { + [% IF donames %] + [% FOREACH n = category.$c.$s.keys.sort %] + "[% n FILTER js %]": + [% category.$c.$s.$n FILTER js %][% ", " UNLESS loop.last %] + [% END %] + [% END %] + }[% ", " UNLESS loop.last %] + [% END %] + }[% ", " UNLESS loop.last %] +[% END %] +}; + +[%# This function takes necessary action on selection of a category %] +function catSelected() { + var cat = document.chartform.category.value; + var subcats = series[cat]; + + var subcatwidget = document.chartform.subcategory; + + subcatwidget.options.length = 0; + var i = 0; + + for (x in subcats) { + subcatwidget.options[i] = new Option(x, x); + i++; + } + + [% IF newtext %] + subcatwidget.options[i] = new Option("[% newtext FILTER js %]", ""); + [% END %] + + subcatwidget.disabled = false; + subcatwidget.options[0].selected = true; + + if (document.chartform.action[1]) { + [%# On the query form, select the right radio button. %] + document.chartform.action[1].checked = true; + } + + checkNewState(); +} + +[%# This function updates the disabled state of the two "new" textboxes %] +function checkNewState() { + var fm = document.chartform; + if (fm.newcategory) { + fm.newcategory.disabled = + (fm.category.value != "" || + fm.action[1] && fm.action[1].checked == false); + fm.newsubcategory.disabled = + (fm.subcategory.value != "" || + fm.action[1] && fm.action[1].checked == false); + } +} +</script> + +[%###########################################################################%] +[%# Block for SELECT fields - pinched from search/form.html.tmpl #%] +[%###########################################################################%] + +[% BLOCK series_select %] + <td align="left"> + <select name="[% sel.name %]" id="[% sel.name %]" + size="[% sel.size %]" style="width: 15em" + [%+ 'multiple="multiple"' IF sel.multiple %] + [%+ "disabled=\"disabled\"" UNLESS ${sel.name}.keys.size || newtext %] + [%+ "onchange=\"$sel.onchange\"" IF sel.onchange %]> + [% FOREACH x = ${sel.name}.keys.sort %] + [% value = sel.value_in_hash ? ${sel.name}.$x : x %] + <option value="[% value FILTER html %]" + [% " selected" IF default.${sel.name} == value %]> + [% x FILTER html %]</option> + [% END %] + [% IF newtext %] + <option value="">[% newtext FILTER html %]</option> + [% ELSIF NOT ${sel.name}.keys.size %] + <option value="" disabled="disabled"></option> + [% END %] + </select> + </td> +[% END %] diff --git a/template/en/default/reports/series.html.tmpl b/template/en/default/reports/series.html.tmpl new file mode 100644 index 0000000..a6bf0d9 --- /dev/null +++ b/template/en/default/reports/series.html.tmpl @@ -0,0 +1,85 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # default: hash. Defaults for category, subcategory, name etc. + # button_name: string. What the button will say. + # category: hash (keyed by category) of hashes (keyed by subcategory) of + # hashes (keyed by name), with value being the series_id of the + # series. Contains details of all series the user can see. + #%] + +[% PROCESS "reports/series-common.html.tmpl" + newtext = "New (name below)" + %] + +<table cellpadding="2" cellspacing="2" border="0" + style="text-align: left; margin-left: 20px"> + <tbody> + <tr> + <th>Category:</th> + <th></th> + <th>Sub-category:</th> + <th>Name:</th> + <td></td> + </tr> + <tr> + [% PROCESS series_select sel = { name => 'category', + size => 5, + onchange => "catSelected()" } %] + <td> + <noscript> + <input type="submit" name="action-edit" value="Update -->" + id="action-edit"> + </noscript> + </td> + + [% PROCESS series_select sel = { name => 'subcategory', + size => 5, + onchange => "checkNewState()" } %] + + <td valign="top" name="name"> + <input type="text" name="name" maxlength="64" + value="[% default.name.0 FILTER html %]" size="25"> + </td> + + <td valign="top"> + <span style="font-weight: bold;">Run every</span> + <input type="text" size="2" name="frequency" + value="[% (default.frequency.0 OR 7) FILTER html %]"> + <span style="font-weight: bold;"> day(s)</span><br> + [%# Change 'admin' here and in Series.pm, or remove the check + completely, if you want to change who can make series public. %] + [% IF user.in_group('admin') %] + <input type="checkbox" name="public" + [%+ "checked='checked'" IF default.public.0 %]> + <span style="font-weight: bold;">Visible to all<br> + (within group restrictions)</span> + [% END %] + </td> + </tr> + + <tr> + <td> + <input type="text" style="width: 100%" name="newcategory" + maxlength="64" value="[% default.newcategory.0 FILTER html %]"> + </td> + <td></td> + <td> + <input type="text" style="width: 100%" name="newsubcategory" + maxlength="64" + value="[% default.newsubcategory.0 FILTER html %]"> + </td> + <td></td> + <td> + <input type="submit" name="submit-button" id="submit-button" + value="[% button_name FILTER html %]"> + </td> + </tr> + </tbody> +</table> |