summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrédéric Buclin <LpSolit@gmail.com>2012-05-07 17:58:22 +0200
committerFrédéric Buclin <LpSolit@gmail.com>2012-05-07 17:58:22 +0200
commit92a81752931c5fd7cdbf4b63305389844193d029 (patch)
tree13cae837e5d0491e9ad5d6426b558de741d261eb
parent4e5dcf363dd1ffa63f0d7a190fa61891061ddea2 (diff)
downloadbugzilla-92a81752931c5fd7cdbf4b63305389844193d029.tar.gz
bugzilla-92a81752931c5fd7cdbf4b63305389844193d029.tar.xz
Bug 616191: Implement UI to easily tag bugs from the bug report directly (and get rid of the current form in the footer)
r=timello a=LpSolit
-rw-r--r--Bugzilla/Field.pm3
-rw-r--r--Bugzilla/Install.pm5
-rw-r--r--Bugzilla/Template.pm4
-rwxr-xr-xbuglist.cgi53
-rw-r--r--js/field.js34
-rwxr-xr-xprocess_bug.cgi12
-rw-r--r--skins/standard/IE-fixes.css2
-rw-r--r--skins/standard/global.css4
-rw-r--r--skins/standard/search_form.css2
-rw-r--r--skins/standard/show_bug.css2
-rw-r--r--template/en/default/bug/edit.html.tmpl11
-rw-r--r--template/en/default/bug/field-help.none.tmpl7
-rw-r--r--template/en/default/bug/field.html.tmpl16
-rw-r--r--template/en/default/filterexceptions.pl4
-rw-r--r--template/en/default/global/field-descs.none.tmpl2
-rw-r--r--template/en/default/global/messages.html.tmpl12
-rw-r--r--template/en/default/global/per-bug-queries.html.tmpl88
-rw-r--r--template/en/default/global/setting-descs.none.tmpl1
-rw-r--r--template/en/default/global/useful-links.html.tmpl2
-rw-r--r--template/en/default/search/field.html.tmpl16
-rw-r--r--template/en/default/search/form.html.tmpl1
21 files changed, 85 insertions, 196 deletions
diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm
index 4ec592164..c244e66d9 100644
--- a/Bugzilla/Field.pm
+++ b/Bugzilla/Field.pm
@@ -248,7 +248,8 @@ use constant DEFAULT_FIELDS => (
{name => "owner_idle_time", desc => "Time Since Assignee Touched"},
{name => 'see_also', desc => "See Also",
type => FIELD_TYPE_BUG_URLS},
- {name => 'tag', desc => 'Tags', buglist => 1},
+ {name => 'tag', desc => 'Tags', buglist => 1,
+ type => FIELD_TYPE_KEYWORDS},
);
################
diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm
index bd591ecc8..f2c3902e4 100644
--- a/Bugzilla/Install.pm
+++ b/Bugzilla/Install.pm
@@ -61,8 +61,6 @@ sub SETTINGS {
csv_colsepchar => { options => [',',';'], default => ',' },
# 2005-10-26 wurblzap@gmail.com -- Bug 291459
zoom_textareas => { options => ["on", "off"], default => "on" },
- # 2005-10-21 LpSolit@gmail.com -- Bug 313020
- per_bug_queries => { options => ['on', 'off'], default => 'off' },
# 2006-05-01 olav@bkor.dhs.org -- Bug 7710
state_addselfcc => { options => ['always', 'never', 'cc_unless_role'],
default => 'cc_unless_role' },
@@ -192,6 +190,9 @@ sub update_settings {
$settings{$setting}->{subclass}, undef,
!$any_settings);
}
+
+ # Delete the obsolete 'per_bug_queries' user preference. Bug 616191.
+ $dbh->do('DELETE FROM setting WHERE name = ?', undef, 'per_bug_queries');
}
sub update_system_groups {
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index 78c537cc3..e5bd8edb7 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -928,7 +928,9 @@ sub create {
'use_keywords' => sub { return Bugzilla::Keyword->any_exist; },
# All the keywords.
- 'all_keywords' => sub { return Bugzilla::Keyword->get_all(); },
+ 'all_keywords' => sub {
+ return [map { $_->name } Bugzilla::Keyword->get_all()];
+ },
'feature_enabled' => sub { return Bugzilla->feature(@_); },
diff --git a/buglist.cgi b/buglist.cgi
index 89ba3fe46..f0e778464 100755
--- a/buglist.cgi
+++ b/buglist.cgi
@@ -23,10 +23,8 @@ use Bugzilla::Search;
use Bugzilla::Search::Quicksearch;
use Bugzilla::Search::Recent;
use Bugzilla::Search::Saved;
-use Bugzilla::User;
use Bugzilla::Bug;
use Bugzilla::Product;
-use Bugzilla::Keyword;
use Bugzilla::Field;
use Bugzilla::Status;
use Bugzilla::Token;
@@ -445,51 +443,18 @@ elsif (($cmdtype eq "doit") && defined $cgi->param('remtype')) {
my $new_query = $cgi->param('newquery');
my $token = $cgi->param('token');
check_hash_token($token, ['savedsearch']);
- # If list_of_bugs is true, we are adding/removing tags to/from
- # individual bugs.
- if ($cgi->param('list_of_bugs')) {
- # We add/remove tags based on the action choosen.
- my $action = trim($cgi->param('action') || '');
- $action =~ /^(add|remove)$/
- || ThrowUserError('unknown_action', {action => $action});
-
- my $method = "${action}_tag";
-
- # If no new tag name has been given, use the selected one.
- $query_name ||= $cgi->param('oldqueryname')
- or ThrowUserError('no_tag_to_edit', {action => $action});
-
- my @buglist;
- # Validate all bug IDs before editing tags in any of them.
- foreach my $bug_id (split(/[\s,]+/, $cgi->param('bug_ids'))) {
- next unless $bug_id;
- push(@buglist, Bugzilla::Bug->check($bug_id));
- }
-
- foreach my $bug (@buglist) {
- $bug->$method($query_name);
- }
-
- $vars->{'message'} = 'tag_updated';
- $vars->{'action'} = $action;
- $vars->{'tag'} = $query_name;
- $vars->{'buglist'} = [map { $_->id } @buglist];
+ my $existed_before = InsertNamedQuery($query_name, $new_query, 1);
+ if ($existed_before) {
+ $vars->{'message'} = "buglist_updated_named_query";
}
else {
- my $existed_before = InsertNamedQuery($query_name, $new_query, 1);
- if ($existed_before) {
- $vars->{'message'} = "buglist_updated_named_query";
- }
- else {
- $vars->{'message'} = "buglist_new_named_query";
- }
-
- # Make sure to invalidate any cached query data, so that the footer is
- # correctly displayed
- $user->flush_queries_cache();
-
- $vars->{'queryname'} = $query_name;
+ $vars->{'message'} = "buglist_new_named_query";
}
+ $vars->{'queryname'} = $query_name;
+
+ # Make sure to invalidate any cached query data, so that the footer is
+ # correctly displayed
+ $user->flush_queries_cache();
print $cgi->header();
$template->process("global/message.html.tmpl", $vars)
diff --git a/js/field.js b/js/field.js
index 9583db02c..1e5595081 100644
--- a/js/field.js
+++ b/js/field.js
@@ -870,27 +870,29 @@ YAHOO.bugzilla.userAutocomplete = {
}
};
-YAHOO.bugzilla.keywordAutocomplete = {
- dataSource : null,
- init_ds : function(){
- this.dataSource = new YAHOO.util.LocalDataSource( YAHOO.bugzilla.keyword_array );
+YAHOO.bugzilla.fieldAutocomplete = {
+ dataSource : [],
+ init_ds : function( field ) {
+ this.dataSource[field] =
+ new YAHOO.util.LocalDataSource( YAHOO.bugzilla.field_array[field] );
},
init : function( field, container ) {
- if( this.dataSource == null ){
- this.init_ds();
+ if( this.dataSource[field] == null ) {
+ this.init_ds( field );
}
- var keywordAutoComp = new YAHOO.widget.AutoComplete(field, container, this.dataSource);
- keywordAutoComp.maxResultsDisplayed = YAHOO.bugzilla.keyword_array.length;
- keywordAutoComp.minQueryLength = 0;
- keywordAutoComp.useIFrame = true;
- keywordAutoComp.delimChar = [","," "];
- keywordAutoComp.resultTypeList = false;
- keywordAutoComp.queryDelay = 0;
- /* Causes all the possibilities in the keyword to appear when a user
+ var fieldAutoComp =
+ new YAHOO.widget.AutoComplete(field, container, this.dataSource[field]);
+ fieldAutoComp.maxResultsDisplayed = YAHOO.bugzilla.field_array[field].length;
+ fieldAutoComp.minQueryLength = 0;
+ fieldAutoComp.useIFrame = true;
+ fieldAutoComp.delimChar = [","," "];
+ fieldAutoComp.resultTypeList = false;
+ fieldAutoComp.queryDelay = 0;
+ /* Causes all the possibilities in the field to appear when a user
* focuses on the textbox
*/
- keywordAutoComp.textboxFocusEvent.subscribe( function(){
- var sInputValue = YAHOO.util.Dom.get('keywords').value;
+ fieldAutoComp.textboxFocusEvent.subscribe( function(){
+ var sInputValue = YAHOO.util.Dom.get(field).value;
if( sInputValue.length === 0 ){
this.sendQuery(sInputValue);
this.collapseContainer();
diff --git a/process_bug.cgi b/process_bug.cgi
index 30e30b622..29cc54e9f 100755
--- a/process_bug.cgi
+++ b/process_bug.cgi
@@ -28,10 +28,6 @@ use Bugzilla::Bug;
use Bugzilla::User;
use Bugzilla::Util;
use Bugzilla::Error;
-use Bugzilla::Field;
-use Bugzilla::Product;
-use Bugzilla::Component;
-use Bugzilla::Keyword;
use Bugzilla::Flag;
use Bugzilla::Status;
use Bugzilla::Token;
@@ -330,6 +326,14 @@ if (defined $cgi->param('id')) {
my ($flags, $new_flags) = Bugzilla::Flag->extract_flags_from_cgi(
$first_bug, undef, $vars);
$first_bug->set_flags($flags, $new_flags);
+
+ # Tags can only be set to one bug at once.
+ if (should_set('tag')) {
+ my @new_tags = split(/[\s,]+/, $cgi->param('tag'));
+ my ($tags_removed, $tags_added) = diff_arrays($first_bug->tags, \@new_tags);
+ $first_bug->remove_tag($_) foreach @$tags_removed;
+ $first_bug->add_tag($_) foreach @$tags_added;
+ }
}
##############################
diff --git a/skins/standard/IE-fixes.css b/skins/standard/IE-fixes.css
index 727667f73..9574d5f9e 100644
--- a/skins/standard/IE-fixes.css
+++ b/skins/standard/IE-fixes.css
@@ -44,7 +44,7 @@ form#Create #comp_desc {
display: inline;
}
-#keyword_container .yui-ac-content {
+#keywords_container .yui-ac-content {
_height: 30em; /* ie6 */
}
diff --git a/skins/standard/global.css b/skins/standard/global.css
index 905a97158..07b289ec2 100644
--- a/skins/standard/global.css
+++ b/skins/standard/global.css
@@ -526,12 +526,12 @@ input.required, select.required, span.required_explanation {
overflow-x: hidden;
}
-#keyword_container {
+#keywords_container {
padding-top: .2em;
}
-#keyword_container .yui-ac-content {
+#keywords_container .yui-ac-content {
margin-left: -1px;
}
diff --git a/skins/standard/search_form.css b/skins/standard/search_form.css
index aa04b6ffe..e3a2ba1c4 100644
--- a/skins/standard/search_form.css
+++ b/skins/standard/search_form.css
@@ -99,7 +99,7 @@
width: inherit;
}
-#keyword_container {
+#keywords_container {
padding-bottom: 0;
}
diff --git a/skins/standard/show_bug.css b/skins/standard/show_bug.css
index 9c15599ee..fb47335be 100644
--- a/skins/standard/show_bug.css
+++ b/skins/standard/show_bug.css
@@ -118,7 +118,7 @@ table#flags {
float: right;
}
-.text_input, .bz_userfield, #keyword_container {
+.text_input, .bz_userfield, #keywords_container, #tag_container {
width: 100%;
}
.bz_bug .bz_alias_short_desc_container {
diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl
index d7c564fdb..d8803e677 100644
--- a/template/en/default/bug/edit.html.tmpl
+++ b/template/en/default/bug/edit.html.tmpl
@@ -523,11 +523,20 @@
[% INCLUDE bug/field.html.tmpl
bug = bug, field = bug_fields.keywords, value = bug.keywords
editable = bug.check_can_change_field("keywords", 0, 1),
- no_tds = 1
+ no_tds = 1, possible_values = all_keywords
%]
</td>
</tr>
[% END %]
+
+ [% IF user.id %]
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = bug, field = bug_fields.tag, value = bug.tags.join(", "),
+ editable = 1, possible_values = user.tags.keys
+ %]
+ </tr>
+ [% END %]
[% END %]
[%############################################################################%]
diff --git a/template/en/default/bug/field-help.none.tmpl b/template/en/default/bug/field-help.none.tmpl
index a74de2e32..f76fa9639 100644
--- a/template/en/default/bug/field-help.none.tmpl
+++ b/template/en/default/bug/field-help.none.tmpl
@@ -137,6 +137,13 @@ status_whiteboard =>
"Each $terms.bug has a free-form single line text entry box for"
_ " adding tags and status information.",
+tag =>
+ "Unlike ${vars.field_descs.keywords} which are global and visible by
+ all users, ${vars.field_descs.tag} are personal and can only be
+ viewed and edited by their author.
+ Editing them won't send any notification to other users. Use them
+ to tag and keep track of ${terms.bugs}.",
+
target_milestone =>
"The $vars.field_descs.target_milestone field is used to define when the"
_ " engineer the $terms.bug is assigned to expects to fix it.",
diff --git a/template/en/default/bug/field.html.tmpl b/template/en/default/bug/field.html.tmpl
index 0cc75c288..e6660256f 100644
--- a/template/en/default/bug/field.html.tmpl
+++ b/template/en/default/bug/field.html.tmpl
@@ -171,19 +171,21 @@
</script>
[% END %]
[% CASE constants.FIELD_TYPE_KEYWORDS %]
- <div id="keyword_container">
+ <div id="[% field.name FILTER html %]_container">
<input type="text" id="[% field.name FILTER html %]" size="40"
class="text_input" name="[% field.name FILTER html %]"
value="[% value FILTER html %]">
- <div id="keyword_autocomplete"></div>
+ <div id="[% field.name FILTER html %]_autocomplete"></div>
</div>
<script type="text/javascript" defer="defer">
- YAHOO.bugzilla.keyword_array = [
- [%- FOREACH keyword = all_keywords %]
- [%-# %]"[% keyword.name FILTER js %]"
+ if (typeof YAHOO.bugzilla.field_array === "undefined")
+ YAHOO.bugzilla.field_array = [];
+ YAHOO.bugzilla.field_array["[% field.name FILTER js %]"] = [
+ [%- FOREACH val = possible_values %]
+ [%-# %]"[% val FILTER js %]"
[%- "," IF NOT loop.last %][% END %]];
- YAHOO.bugzilla.keywordAutocomplete.init('[% field.name FILTER js %]',
- 'keyword_autocomplete');
+ YAHOO.bugzilla.fieldAutocomplete.init('[% field.name FILTER js %]',
+ '[% field.name FILTER js %]_autocomplete');
</script>
[% END %]
[% ELSE %]
diff --git a/template/en/default/filterexceptions.pl b/template/en/default/filterexceptions.pl
index 31a686a00..e3cfec8a2 100644
--- a/template/en/default/filterexceptions.pl
+++ b/template/en/default/filterexceptions.pl
@@ -177,10 +177,6 @@
'series.frequency * 2',
],
-'global/per-bug-queries.html.tmpl' => [
- '" value=\"$bugids\"" IF bugids',
-],
-
'global/select-menu.html.tmpl' => [
'options',
'size',
diff --git a/template/en/default/global/field-descs.none.tmpl b/template/en/default/global/field-descs.none.tmpl
index 27926c802..5f956c714 100644
--- a/template/en/default/global/field-descs.none.tmpl
+++ b/template/en/default/global/field-descs.none.tmpl
@@ -118,7 +118,7 @@
"settings" => "Settings",
"short_desc" => "Summary",
"status_whiteboard" => "Whiteboard",
- "tag.name" => "Tags",
+ "tag" => "Tags",
"target_milestone" => "Target Milestone",
"version" => "Version",
"work_time" => "Hours Worked",
diff --git a/template/en/default/global/messages.html.tmpl b/template/en/default/global/messages.html.tmpl
index dcaf4b81a..fe5029ebc 100644
--- a/template/en/default/global/messages.html.tmpl
+++ b/template/en/default/global/messages.html.tmpl
@@ -849,18 +849,6 @@
The cookie that was remembering your login is now gone.
[% END %]
- [% ELSIF message_tag == "tag_updated" %]
- [% title = "Tag Updated" %]
- The '<a href="buglist.cgi?tag=[% tag FILTER uri %]">[% tag FILTER html %]</a>'
- tag has been
- [% IF action == "add" %]
- added to
- [% ELSE %]
- removed from
- [% END %]
- [%+ buglist.size > 1 ? terms.bugs : terms.bug %]
- [%+ buglist.join(", ") FILTER html %].
-
[% ELSIF message_tag == "term" %]
[% terms.$term FILTER html %]
diff --git a/template/en/default/global/per-bug-queries.html.tmpl b/template/en/default/global/per-bug-queries.html.tmpl
deleted file mode 100644
index 766c71332..000000000
--- a/template/en/default/global/per-bug-queries.html.tmpl
+++ /dev/null
@@ -1,88 +0,0 @@
-[%# 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.
- #%]
-
-[% IF user.id && user.settings.per_bug_queries.value == "on" %]
- <li id="links-special">
- <script type="text/javascript">
- <!--
- function update_text() {
- // 'lob' means list_of_bugs.
- var lob_action = document.getElementById('lob_action');
- var action = lob_action.options[lob_action.selectedIndex].value;
- var text = document.getElementById('lob_direction');
- var new_query_text = document.getElementById('lob_new_query_text');
-
- if (action == "add") {
- text.innerHTML = "to";
- new_query_text.style.display = 'inline';
- }
- else {
- text.innerHTML = "from";
- new_query_text.style.display = 'none';
- }
- }
-
- function manage_old_lists() {
- var old_lists = document.getElementById('lob_oldqueryname');
- // If there is no saved searches available, returns.
- if (!old_lists) return;
-
- var new_query = document.getElementById('lob_newqueryname').value;
-
- if (new_query != "") {
- old_lists.disabled = true;
- }
- else {
- old_lists.disabled = false;
- }
- }
- //-->
- </script>
-
- <div class="label"></div>
- <ul class="links"><li class="form">
- <form id="list_of_bugs" action="buglist.cgi" method="get">
- <input type="hidden" name="cmdtype" value="doit">
- <input type="hidden" name="remtype" value="asnamed">
- <input type="hidden" name="list_of_bugs" value="1">
- <input type="hidden" name="token" value="[% issue_hash_token(['savedsearch']) FILTER html %]">
- <select id="lob_action" name="action" onchange="update_text();">
- <option value="add">Add</option>
- [% IF user.tags.size %]
- <option value="remove">Remove</option>
- [% END %]
- </select>
-
- [% IF Param('docs_urlbase') %]
- <a href="[% docs_urlbase FILTER html %]query.html#individual-buglists">the named tag</a>
- [% ELSE %]
- the named tag
- [% END %]
-
- [% IF user.tags.size %]
- <select id="lob_oldqueryname" name="oldqueryname">
- [% FOREACH tag = user.tags.keys %]
- <option value="[% tag FILTER html %]">[% tag FILTER html %]</option>
- [% END %]
- </select>
- [% END %]
- <span id="lob_new_query_text">
- [% " or create and add the tag" IF user.tags.size %]
- <input class="txt" type="text" id="lob_newqueryname"
- size="20" maxlength="64" name="newqueryname"
- onkeyup="manage_old_lists();">
- </span>
- <span id="lob_direction">to</span>
- [%+ terms.bugs %]
- <input type="text" name="bug_ids" size="12" maxlength="80"
- [%- " value=\"$bugids\"" IF bugids %]>
- <input type="submit" value="Commit" id="commit_list_of_bugs">
- </form>
- </li></ul>
- </li>
-[% END %]
diff --git a/template/en/default/global/setting-descs.none.tmpl b/template/en/default/global/setting-descs.none.tmpl
index 28ecad755..f2dd43de5 100644
--- a/template/en/default/global/setting-descs.none.tmpl
+++ b/template/en/default/global/setting-descs.none.tmpl
@@ -18,7 +18,6 @@
"off" => "Off",
"oldest_to_newest" => "Oldest to Newest",
"on" => "On",
- "per_bug_queries" => "Enable tags for $terms.bugs",
"post_bug_submit_action" => "After changing $terms.abug",
"next_bug" => "Show next $terms.bug in my list",
"same_bug" => "Show the updated $terms.bug",
diff --git a/template/en/default/global/useful-links.html.tmpl b/template/en/default/global/useful-links.html.tmpl
index ea14be8fe..1b5ba9a30 100644
--- a/template/en/default/global/useful-links.html.tmpl
+++ b/template/en/default/global/useful-links.html.tmpl
@@ -58,8 +58,6 @@
[%# Individual bugs addition %]
- [% PROCESS "global/per-bug-queries.html.tmpl" %]
-
[%# Sections of links to more things users can do on this installation. %]
[% Hook.process("end") %]
</ul>
diff --git a/template/en/default/search/field.html.tmpl b/template/en/default/search/field.html.tmpl
index d3f71ae3f..dd5e1fac7 100644
--- a/template/en/default/search/field.html.tmpl
+++ b/template/en/default/search/field.html.tmpl
@@ -35,20 +35,22 @@
types = types,
selected = type_selected
%]
- <div id="keyword_container">
+ <div id="[% field.name FILTER html %]_container">
<input name="[% field.name FILTER html %]"
id="[% field.name FILTER html %]" size="40"
[% IF onchange %] onchange="[% onchange FILTER html %]"[% END %]
value="[% value FILTER html %]">
- <div id="keyword_autocomplete"></div>
+ <div id="[% field.name FILTER html %]_autocomplete"></div>
</div>
<script type="text/javascript" defer="defer">
- YAHOO.bugzilla.keyword_array = [
- [%- FOREACH keyword = all_keywords %]
- [%-# %]"[% keyword.name FILTER js %]"
+ if (typeof YAHOO.bugzilla.field_array === "undefined")
+ YAHOO.bugzilla.field_array = [];
+ YAHOO.bugzilla.field_array["[% field.name FILTER js %]"] = [
+ [%- FOREACH val = possible_values %]
+ [%-# %]"[% val FILTER js %]"
[%- "," IF NOT loop.last %][% END %]];
- YAHOO.bugzilla.keywordAutocomplete.init('[% field.name FILTER js %]',
- 'keyword_autocomplete');
+ YAHOO.bugzilla.fieldAutocomplete.init('[% field.name FILTER js %]',
+ '[% field.name FILTER js %]_autocomplete');
</script>
[% CASE constants.FIELD_TYPE_DATETIME %]
[% INCLUDE "bug/field-label.html.tmpl"
diff --git a/template/en/default/search/form.html.tmpl b/template/en/default/search/form.html.tmpl
index 4b7ac4b07..fc6f597cf 100644
--- a/template/en/default/search/form.html.tmpl
+++ b/template/en/default/search/form.html.tmpl
@@ -142,6 +142,7 @@ TUI_hide_default('information_query');
%]
<div class="search_field_row">
[% type = field_container.field.name _ "_type" %]
+ [% possible_values = field_container.field.name == 'keywords' ? all_keywords : [] %]
[% INCLUDE "search/field.html.tmpl"
field => field_container.field
types => field_container.qtypes || query_types