aboutsummaryrefslogtreecommitdiff
path: root/template/en/default/reports
diff options
context:
space:
mode:
authorFathi Boudra <fathi.boudra@linaro.org>2014-06-02 17:14:02 +0300
committerFathi Boudra <fathi.boudra@linaro.org>2014-06-02 17:14:02 +0300
commit46f29f243b1e7642e860b40214d5f893aad678e1 (patch)
tree7ac82cee0957299e51c36f22ce1b172670513348 /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')
-rw-r--r--template/en/default/reports/chart.csv.tmpl32
-rw-r--r--template/en/default/reports/chart.html.tmpl55
-rw-r--r--template/en/default/reports/chart.png.tmpl47
-rw-r--r--template/en/default/reports/components.html.tmpl94
-rw-r--r--template/en/default/reports/create-chart.html.tmpl258
-rw-r--r--template/en/default/reports/delete-series.html.tmpl47
-rw-r--r--template/en/default/reports/duplicates-simple.html.tmpl35
-rw-r--r--template/en/default/reports/duplicates-table.html.tmpl109
-rw-r--r--template/en/default/reports/duplicates.html.tmpl165
-rw-r--r--template/en/default/reports/edit-series.html.tmpl63
-rw-r--r--template/en/default/reports/keywords.html.tmpl71
-rw-r--r--template/en/default/reports/menu.html.tmpl75
-rw-r--r--template/en/default/reports/old-charts.html.tmpl62
-rw-r--r--template/en/default/reports/report-bar.png.tmpl48
-rw-r--r--template/en/default/reports/report-line.png.tmpl50
-rw-r--r--template/en/default/reports/report-pie.png.tmpl25
-rw-r--r--template/en/default/reports/report-simple.html.tmpl25
-rw-r--r--template/en/default/reports/report-table.csv.tmpl61
-rw-r--r--template/en/default/reports/report-table.html.tmpl256
-rw-r--r--template/en/default/reports/report.csv.tmpl12
-rw-r--r--template/en/default/reports/report.html.tmpl152
-rw-r--r--template/en/default/reports/series-common.html.tmpl107
-rw-r--r--template/en/default/reports/series.html.tmpl85
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 %]&amp;ctype=png&amp;action=plot&amp;width=
+ [% width %]&amp;height=[% height -%]
+ [% END %]
+
+ <img alt="Graphical report results" src="[% imageurl %]"
+ width="[% width %]" height="[% height %]">
+ <p>
+ [% sizeurl = BLOCK %]chart.cgi?
+ [% imagebase FILTER html %]&amp;action=wrap
+ [% END %]
+ <a href="[% sizeurl %]&amp;width=[% width %]&amp;height=
+ [% height + 100 %]">Taller</a><br>
+ <a href="[% sizeurl %]&amp;width=[% width - 100 %]&amp;height=
+ [% height %]">Thinner</a> *
+ <a href="[% sizeurl %]&amp;width=[% width + 100 %]&amp;height=
+ [% height %]">Fatter</a>&nbsp;&nbsp;&nbsp;&nbsp;<br>
+ <a href="[% sizeurl %]&amp;width=[% width %]&amp;height=
+ [% height - 100 %]">Shorter</a><br>
+ </p>
+
+ <p>
+ <a href="chart.cgi?
+ [% imagebase FILTER html %]&amp;ctype=csv&amp;action=plot">CSV</a> |
+ <a href="chart.cgi?[% imagebase FILTER html %]&amp;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>&nbsp;</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 %]&amp;component=
+ [%- comp.name FILTER uri %]&amp;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 --&gt;"
+ 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 --&gt;"
+ 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&amp;series_id=
+ [% series.series_id %]">Edit</a> |
+ <a href="chart.cgi?action=confirm-delete&amp;series_id=
+ [%- series.series_id %]">Delete</a> |
+ [% END %]
+ <a href="buglist.cgi?cmdtype=dorem&amp;namedcmd=
+ [% series.category FILTER uri %]%20/%20
+ [% series.subcategory FILTER uri %]%20/%20
+ [% series.name FILTER uri -%]&amp;series_id=
+ [% series.series_id %]&amp;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">&nbsp;</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&amp;series_id=[% series.series_id FILTER html %]&amp;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('&amp;') %]
+
+[% 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 %]
+ [%- %]&amp;reverse=[% column.reverse_sort FILTER uri %]
+ [% END %]
+ [% IF base_args_string %]
+ [% "&amp;$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&amp;namedcmd=
+ [% default.category FILTER uri %]-
+ [% default.subcategory FILTER uri %]-
+ [% default.name FILTER uri %]&amp;remaction=runseries&amp;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 %]&amp;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 _ "&amp;" _ tbl_vals %]
+ [% END %]
+[% ELSIF tbl_field %]
+ [% urlbase = BLOCK %][% urlbase %]&amp;[% 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(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"')
+ .replace(/&nbsp;/g, " ").replace(/&amp;/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 %]&amp;[% col_field FILTER uri FILTER js %]='
+ + bz_encode(oColumn.field)
+ + '[% "&amp;" _ row_vals IF row_vals %]">' + oData + '</a>';
+ else
+ elLiner.innerHTML = '<a href="[% urlbase FILTER js %]&amp;[% row_field FILTER uri FILTER js %]='
+ + bz_encode(oRecord.getData("row_title"), 1)
+ + '&amp;[% 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 %][% "&amp;" _ row_vals IF row_vals %]
+ [%~ "&amp;" _ col_vals IF col_vals %]">'
+ + oData + '</a>';
+ else
+ elLiner.innerHTML = '<a href="[% urlbase FILTER js %]&amp;[% row_field FILTER uri FILTER js %]='
+ + bz_encode(oRecord.getData("row_title"), 1)
+ + '[% "&amp;" _ 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 %]&amp;
+ [% row_field FILTER uri %]=[% row FILTER uri %]&amp;
+ [% col_field FILTER uri %]=[% col FILTER uri %]">
+ [% data.$tbl.$col.$row %]</a>
+ [% ELSE %]
+ .
+ [% END %]
+ </td>
+ [% END %]
+ <td class="ttotal" align="right">
+ <a href="[% urlbase %]&amp;
+ [% row_field FILTER uri %]=[% row FILTER uri %]
+ [% "&amp;$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 %]&amp;
+ [% col_field FILTER uri %]=[% col FILTER uri %]
+ [% "&amp;$row_vals" IF row_vals %]">
+ [% col_totals.$col %]</a>
+ </td>
+ [% END %]
+ <td class="ttotal" align="right">
+ <strong>
+ <a href="[% urlbase %]
+ [% "&amp;$row_vals" IF row_vals %]
+ [% "&amp;$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('^ $','&nbsp;') %]
+[% 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 %]&amp;format=
+ [% format FILTER uri %]&amp;ctype=png&amp;action=plot&amp;
+ [% IF tbl_field %]
+ [% IF tbl != "-total-" %]
+ [% tbl_field FILTER uri %]=[% tbl FILTER uri %]&amp;
+ [% ELSE %]
+ [% FOREACH tblname = tbl_names %]
+ [% IF tblname != "-total-" %]
+ [% tbl_field FILTER uri %]=[% tblname FILTER uri %]&amp;
+ [% END %]
+ [% END %]
+ [% END %]
+ [% END %]width=[% width %]&amp;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&amp;width=$width&amp;height=$height&amp;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 %]&amp;format=[% other_format.name %]">
+ [% END %]
+ [% other_format.description FILTER html %]
+ [% "</a>" UNLESS other_format.name == format %] |
+ [% END %]
+ <a href="[% formaturl %]&amp;ctype=csv&amp;format=table">CSV</a>
+
+ <table>
+ <tr>
+ <td>
+ [% IF format == "table" %]
+ <a href="query.cgi?[% switchbase %]&amp;format=report-table">Edit this report</a>
+ [% ELSE %]
+ <a href="query.cgi?[% switchbase %]&amp;chart_format=
+ [%~ format FILTER uri %]&amp;format=report-graph&amp;cumulate=[% cumulate %]">
+ Edit this report</a>
+ [% END %]
+ </td>
+ <td>|</td>
+ <td>
+ [% IF saved_report_id %]
+ <a href="report.cgi?action=del&amp;saved_report_id=[% saved_report_id FILTER uri %]&amp;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 %]&amp;format=[% format FILTER uri %]&amp;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 --&gt;"
+ 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> &nbsp;
+ <input type="text" size="2" name="frequency"
+ value="[% (default.frequency.0 OR 7) FILTER html %]">
+ <span style="font-weight: bold;">&nbsp;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>