Commit 8fa9965e authored by Frédéric Buclin's avatar Frédéric Buclin

Bug 616185: Move tags (aka lists of bugs) to their own DB tables

r/a=mkanat
parent 95bfc797
...@@ -1895,6 +1895,17 @@ sub _check_strict_isolation_for_user { ...@@ -1895,6 +1895,17 @@ sub _check_strict_isolation_for_user {
} }
} }
sub _check_tag_name {
my ($invocant, $tag) = @_;
$tag = clean_text($tag);
$tag || ThrowUserError('no_tag_to_edit');
ThrowUserError('tag_name_too_long') if length($tag) > MAX_LEN_QUERY_NAME;
trick_taint($tag);
# Tags are all lowercase.
return lc($tag);
}
sub _check_target_milestone { sub _check_target_milestone {
my ($invocant, $target, undef, $params) = @_; my ($invocant, $target, undef, $params) = @_;
my $product = blessed($invocant) ? $invocant->product_obj my $product = blessed($invocant) ? $invocant->product_obj
...@@ -2866,6 +2877,78 @@ sub remove_see_also { ...@@ -2866,6 +2877,78 @@ sub remove_see_also {
$self->{see_also} = \@new_see_also; $self->{see_also} = \@new_see_also;
} }
sub add_tag {
my ($self, $tag) = @_;
my $dbh = Bugzilla->dbh;
my $user = Bugzilla->user;
$tag = $self->_check_tag_name($tag);
my $tag_id = $user->tags->{$tag}->{id};
# If this tag doesn't exist for this user yet, create it.
if (!$tag_id) {
$dbh->do('INSERT INTO tags (user_id, name) VALUES (?, ?)',
undef, ($user->id, $tag));
$tag_id = $dbh->selectrow_array('SELECT id FROM tags
WHERE name = ? AND user_id = ?',
undef, ($tag, $user->id));
# The list has changed.
delete $user->{tags};
}
# Do nothing if this tag is already set for this bug.
return if grep { $_ eq $tag } @{$self->tags};
# Increment the counter. Do it before the SQL call below,
# to not count the tag twice.
$user->tags->{$tag}->{bug_count}++;
$dbh->do('INSERT INTO bug_tag (bug_id, tag_id) VALUES (?, ?)',
undef, ($self->id, $tag_id));
push(@{$self->{tags}}, $tag);
}
sub remove_tag {
my ($self, $tag) = @_;
my $dbh = Bugzilla->dbh;
my $user = Bugzilla->user;
$tag = $self->_check_tag_name($tag);
my $tag_id = exists $user->tags->{$tag} ? $user->tags->{$tag}->{id} : undef;
# Do nothing if the user doesn't use this tag, or didn't set it for this bug.
return unless ($tag_id && grep { $_ eq $tag } @{$self->tags});
$dbh->do('DELETE FROM bug_tag WHERE bug_id = ? AND tag_id = ?',
undef, ($self->id, $tag_id));
$self->{tags} = [grep { $_ ne $tag } @{$self->tags}];
# Decrement the counter, and delete the tag if no bugs are using it anymore.
if (!--$user->tags->{$tag}->{bug_count}) {
$dbh->do('DELETE FROM tags WHERE name = ? AND user_id = ?',
undef, ($tag, $user->id));
# The list has changed.
delete $user->{tags};
}
}
sub tags {
my $self = shift;
my $dbh = Bugzilla->dbh;
my $user = Bugzilla->user;
# This method doesn't support several users using the same bug object.
if (!exists $self->{tags}) {
$self->{tags} = $dbh->selectcol_arrayref(
'SELECT name FROM bug_tag
INNER JOIN tags ON tags.id = bug_tag.tag_id
WHERE bug_id = ? AND user_id = ?',
undef, ($self->id, $user->id));
}
return $self->{tags};
}
##################################################################### #####################################################################
# Simple Accessors # Simple Accessors
##################################################################### #####################################################################
......
...@@ -82,9 +82,6 @@ use Memoize; ...@@ -82,9 +82,6 @@ use Memoize;
DEFAULT_QUERY_NAME DEFAULT_QUERY_NAME
DEFAULT_MILESTONE DEFAULT_MILESTONE
QUERY_LIST
LIST_OF_BUGS
SAVE_NUM_SEARCHES SAVE_NUM_SEARCHES
COMMENT_COLS COMMENT_COLS
...@@ -288,10 +285,6 @@ use constant DEFAULT_QUERY_NAME => '(Default query)'; ...@@ -288,10 +285,6 @@ use constant DEFAULT_QUERY_NAME => '(Default query)';
# The default "defaultmilestone" created for products. # The default "defaultmilestone" created for products.
use constant DEFAULT_MILESTONE => '---'; use constant DEFAULT_MILESTONE => '---';
# The possible types for saved searches.
use constant QUERY_LIST => 0;
use constant LIST_OF_BUGS => 1;
# How many of the user's most recent searches to save. # How many of the user's most recent searches to save.
use constant SAVE_NUM_SEARCHES => 10; use constant SAVE_NUM_SEARCHES => 10;
......
...@@ -953,7 +953,6 @@ use constant ABSTRACT_SCHEMA => { ...@@ -953,7 +953,6 @@ use constant ABSTRACT_SCHEMA => {
DELETE => 'CASCADE'}}, DELETE => 'CASCADE'}},
name => {TYPE => 'varchar(64)', NOTNULL => 1}, name => {TYPE => 'varchar(64)', NOTNULL => 1},
query => {TYPE => 'LONGTEXT', NOTNULL => 1}, query => {TYPE => 'LONGTEXT', NOTNULL => 1},
query_type => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0},
], ],
INDEXES => [ INDEXES => [
namedqueries_userid_idx => {FIELDS => [qw(userid name)], namedqueries_userid_idx => {FIELDS => [qw(userid name)],
...@@ -979,6 +978,36 @@ use constant ABSTRACT_SCHEMA => { ...@@ -979,6 +978,36 @@ use constant ABSTRACT_SCHEMA => {
], ],
}, },
tags => {
FIELDS => [
id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1},
name => {TYPE => 'varchar(64)', NOTNULL => 1},
user_id => {TYPE => 'INT3', NOTNULL => 1,
REFERENCES => {TABLE => 'profiles',
COLUMN => 'userid',
DELETE => 'CASCADE'}},
],
INDEXES => [
tags_user_id_idx => {FIELDS => [qw(user_id name)], TYPE => 'UNIQUE'},
],
},
bug_tag => {
FIELDS => [
bug_id => {TYPE => 'INT3', NOTNULL => 1,
REFERENCES => {TABLE => 'bugs',
COLUMN => 'bug_id',
DELETE => 'CASCADE'}},
tag_id => {TYPE => 'INT3', NOTNULL => 1,
REFERENCES => {TABLE => 'tags',
COLUMN => 'id',
DELETE => 'CASCADE'}},
],
INDEXES => [
bug_tag_bug_id_idx => {FIELDS => [qw(bug_id tag_id)], TYPE => 'UNIQUE'},
],
},
component_cc => { component_cc => {
FIELDS => [ FIELDS => [
......
...@@ -438,10 +438,6 @@ sub update_table_definitions { ...@@ -438,10 +438,6 @@ sub update_table_definitions {
# PUBLIC is a reserved word in Oracle. # PUBLIC is a reserved word in Oracle.
$dbh->bz_rename_column('series', 'public', 'is_public'); $dbh->bz_rename_column('series', 'public', 'is_public');
# 2005-10-21 LpSolit@gmail.com - Bug 313020
$dbh->bz_add_column('namedqueries', 'query_type',
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0});
# 2005-11-04 LpSolit@gmail.com - Bug 305927 # 2005-11-04 LpSolit@gmail.com - Bug 305927
$dbh->bz_alter_column('groups', 'userregexp', $dbh->bz_alter_column('groups', 'userregexp',
{TYPE => 'TINYTEXT', NOTNULL => 1, DEFAULT => "''"}); {TYPE => 'TINYTEXT', NOTNULL => 1, DEFAULT => "''"});
...@@ -549,10 +545,6 @@ sub update_table_definitions { ...@@ -549,10 +545,6 @@ sub update_table_definitions {
# 2007-09-09 LpSolit@gmail.com - Bug 99215 # 2007-09-09 LpSolit@gmail.com - Bug 99215
_fix_attachment_modification_date(); _fix_attachment_modification_date();
# This had the wrong definition in DB::Schema.
$dbh->bz_alter_column('namedqueries', 'query_type',
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0});
$dbh->bz_drop_index('longdescs', 'longdescs_thetext_idx'); $dbh->bz_drop_index('longdescs', 'longdescs_thetext_idx');
_populate_bugs_fulltext(); _populate_bugs_fulltext();
...@@ -650,6 +642,9 @@ sub update_table_definitions { ...@@ -650,6 +642,9 @@ sub update_table_definitions {
$dbh->bz_add_column('bug_see_also', 'id', $dbh->bz_add_column('bug_see_also', 'id',
{TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1}); {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
# 2011-01-29 LpSolit@gmail.com - Bug 616185
_migrate_user_tags();
################################################################ ################################################################
# New --TABLE-- changes should go *** A B O V E *** this point # # New --TABLE-- changes should go *** A B O V E *** this point #
################################################################ ################################################################
...@@ -3472,6 +3467,43 @@ sub _fix_series_indexes { ...@@ -3472,6 +3467,43 @@ sub _fix_series_indexes {
{FIELDS => [qw(category subcategory name)], TYPE => 'UNIQUE'}); {FIELDS => [qw(category subcategory name)], TYPE => 'UNIQUE'});
} }
sub _migrate_user_tags {
my $dbh = Bugzilla->dbh;
return unless $dbh->bz_column_info('namedqueries', 'query_type');
my $tags = $dbh->selectall_arrayref('SELECT userid, name, query
FROM namedqueries
WHERE query_type != 0');
my $sth_tags = $dbh->prepare('INSERT INTO tags (user_id, name) VALUES (?, ?)');
my $sth_bug_tag = $dbh->prepare('INSERT INTO bug_tag (bug_id, tag_id)
VALUES (?, ?)');
my $sth_nq = $dbh->prepare('UPDATE namedqueries SET query = ?
WHERE userid = ? AND name = ?');
foreach my $tag (@$tags) {
my ($user_id, $name, $query) = @$tag;
# Tags are all lowercase.
my $tag_name = lc($name);
$sth_tags->execute($user_id, $tag_name);
my $tag_id = $dbh->selectrow_array(
'SELECT id FROM tags WHERE user_id = ? AND name = ?',
undef, ($user_id, $tag_name));
$query =~ s/^bug_id=//;
my @bug_ids = split(/[\s,]+/, $query);
$sth_bug_tag->execute($_, $tag_id) foreach @bug_ids;
# Existing tags may be used in whines, or shared with
# other users. So we convert them rather than delete them.
my $encoded_name = url_quote($tag_name);
$sth_nq->execute("tag=$encoded_name", $user_id, $name);
}
$dbh->bz_drop_column('namedqueries', 'query_type');
}
1; 1;
__END__ __END__
......
...@@ -45,17 +45,15 @@ use constant DB_COLUMNS => qw( ...@@ -45,17 +45,15 @@ use constant DB_COLUMNS => qw(
userid userid
name name
query query
query_type
); );
use constant VALIDATORS => { use constant VALIDATORS => {
name => \&_check_name, name => \&_check_name,
query => \&_check_query, query => \&_check_query,
query_type => \&_check_query_type,
link_in_footer => \&_check_link_in_footer, link_in_footer => \&_check_link_in_footer,
}; };
use constant UPDATE_COLUMNS => qw(name query query_type); use constant UPDATE_COLUMNS => qw(name query);
############### ###############
# Constructor # # Constructor #
...@@ -141,12 +139,6 @@ sub _check_query { ...@@ -141,12 +139,6 @@ sub _check_query {
return $cgi->query_string; return $cgi->query_string;
} }
sub _check_query_type {
my ($invocant, $type) = @_;
# Right now the only query type is LIST_OF_BUGS.
return $type ? LIST_OF_BUGS : QUERY_LIST;
}
######################### #########################
# Database Manipulation # # Database Manipulation #
######################### #########################
...@@ -301,7 +293,6 @@ sub shared_with_users { ...@@ -301,7 +293,6 @@ sub shared_with_users {
# Simple Accessors # # Simple Accessors #
#################### ####################
sub type { return $_[0]->{'query_type'}; }
sub url { return $_[0]->{'query'}; } sub url { return $_[0]->{'query'}; }
sub user { sub user {
...@@ -317,7 +308,6 @@ sub user { ...@@ -317,7 +308,6 @@ sub user {
sub set_name { $_[0]->set('name', $_[1]); } sub set_name { $_[0]->set('name', $_[1]); }
sub set_url { $_[0]->set('query', $_[1]); } sub set_url { $_[0]->set('query', $_[1]); }
sub set_query_type { $_[0]->set('query_type', $_[1]); }
1; 1;
......
...@@ -363,6 +363,24 @@ sub queries_available { ...@@ -363,6 +363,24 @@ sub queries_available {
return $self->{queries_available}; return $self->{queries_available};
} }
sub tags {
my $self = shift;
my $dbh = Bugzilla->dbh;
if (!defined $self->{tags}) {
# We must use LEFT JOIN instead of INNER JOIN as we may be
# in the process of inserting a new tag to some bugs,
# in which case there are no bugs with this tag yet.
$self->{tags} = $dbh->selectall_hashref(
'SELECT name, id, COUNT(bug_id) AS bug_count
FROM tags
LEFT JOIN bug_tag ON bug_tag.tag_id = tags.id
WHERE user_id = ? ' . $dbh->sql_group_by('id', 'name'),
'name', undef, $self->id);
}
return $self->{tags};
}
########################## ##########################
# Saved Recent Bug Lists # # Saved Recent Bug Lists #
########################## ##########################
...@@ -2074,6 +2092,11 @@ internally, such code must call this method to flush the cached result. ...@@ -2074,6 +2092,11 @@ internally, such code must call this method to flush the cached result.
An arrayref of group ids. The user can share their own queries with these An arrayref of group ids. The user can share their own queries with these
groups. groups.
=item C<tags>
Returns a hashref with tag IDs as key, and a hashref with tag 'id',
'name' and 'bug_count' as value.
=back =back
=head2 Account Lockout =head2 Account Lockout
......
...@@ -231,24 +231,15 @@ sub DiffDate { ...@@ -231,24 +231,15 @@ sub DiffDate {
} }
sub LookupNamedQuery { sub LookupNamedQuery {
my ($name, $sharer_id, $query_type, $throw_error) = @_; my ($name, $sharer_id) = @_;
$throw_error = 1 unless defined $throw_error;
Bugzilla->login(LOGIN_REQUIRED); Bugzilla->login(LOGIN_REQUIRED);
my $constructor = $throw_error ? 'check' : 'new'; my $query = Bugzilla::Search::Saved->check(
my $query = Bugzilla::Search::Saved->$constructor(
{ user => $sharer_id, name => $name }); { user => $sharer_id, name => $name });
return $query if (!$query and !$throw_error);
if (defined $query_type and $query->type != $query_type) {
ThrowUserError("missing_query", { queryname => $name,
sharer_id => $sharer_id });
}
$query->url $query->url
|| ThrowUserError("buglist_parameters_required", { queryname => $name }); || ThrowUserError("buglist_parameters_required");
return wantarray ? ($query->url, $query->id) : $query->url; return wantarray ? ($query->url, $query->id) : $query->url;
} }
...@@ -266,15 +257,13 @@ sub LookupNamedQuery { ...@@ -266,15 +257,13 @@ sub LookupNamedQuery {
# empty, or we will throw a UserError. # empty, or we will throw a UserError.
# link_in_footer (optional) - 1 if the Named Query should be # link_in_footer (optional) - 1 if the Named Query should be
# displayed in the user's footer, 0 otherwise. # displayed in the user's footer, 0 otherwise.
# query_type (optional) - 1 if the Named Query contains a list of
# bug IDs only, 0 otherwise (default).
# #
# All parameters are validated before passing them into the database. # All parameters are validated before passing them into the database.
# #
# Returns: A boolean true value if the query existed in the database # Returns: A boolean true value if the query existed in the database
# before, and we updated it. A boolean false value otherwise. # before, and we updated it. A boolean false value otherwise.
sub InsertNamedQuery { sub InsertNamedQuery {
my ($query_name, $query, $link_in_footer, $query_type) = @_; my ($query_name, $query, $link_in_footer) = @_;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
$query_name = trim($query_name); $query_name = trim($query_name);
...@@ -283,13 +272,11 @@ sub InsertNamedQuery { ...@@ -283,13 +272,11 @@ sub InsertNamedQuery {
if ($query_obj) { if ($query_obj) {
$query_obj->set_name($query_name); $query_obj->set_name($query_name);
$query_obj->set_url($query); $query_obj->set_url($query);
$query_obj->set_query_type($query_type);
$query_obj->update(); $query_obj->update();
} else { } else {
Bugzilla::Search::Saved->create({ Bugzilla::Search::Saved->create({
name => $query_name, name => $query_name,
query => $query, query => $query,
query_type => $query_type,
link_in_footer => $link_in_footer link_in_footer => $link_in_footer
}); });
} }
...@@ -461,10 +448,7 @@ if ($cmdtype eq "dorem") { ...@@ -461,10 +448,7 @@ if ($cmdtype eq "dorem") {
my $query_id; my $query_id;
($buffer, $query_id) = LookupNamedQuery(scalar $cgi->param("namedcmd"), ($buffer, $query_id) = LookupNamedQuery(scalar $cgi->param("namedcmd"),
$user->id); $user->id);
if (!$query_id) { if ($query_id) {
# The user has no query of this name. Play along.
}
else {
# Make sure the user really wants to delete his saved search. # Make sure the user really wants to delete his saved search.
my $token = $cgi->param('token'); my $token = $cgi->param('token');
check_hash_token($token, [$query_id, $qname]); check_hash_token($token, [$query_id, $qname]);
...@@ -503,93 +487,54 @@ elsif (($cmdtype eq "doit") && defined $cgi->param('remtype')) { ...@@ -503,93 +487,54 @@ elsif (($cmdtype eq "doit") && defined $cgi->param('remtype')) {
$user = Bugzilla->login(LOGIN_REQUIRED); $user = Bugzilla->login(LOGIN_REQUIRED);
my $query_name = $cgi->param('newqueryname'); my $query_name = $cgi->param('newqueryname');
my $new_query = $cgi->param('newquery'); my $new_query = $cgi->param('newquery');
my $query_type = QUERY_LIST;
my $token = $cgi->param('token'); my $token = $cgi->param('token');
check_hash_token($token, ['savedsearch']); check_hash_token($token, ['savedsearch']);
# If list_of_bugs is true, we are adding/removing individual bugs # If list_of_bugs is true, we are adding/removing tags to/from
# to a saved search. We get the existing list of bug IDs (if any) # individual bugs.
# and add/remove the passed ones.
if ($cgi->param('list_of_bugs')) { if ($cgi->param('list_of_bugs')) {
# We add or remove bugs based on the action choosen. # We add/remove tags based on the action choosen.
my $action = trim($cgi->param('action') || ''); my $action = trim($cgi->param('action') || '');
$action =~ /^(add|remove)$/ $action =~ /^(add|remove)$/
|| ThrowUserError('unknown_action', {action => $action}); || ThrowUserError('unknown_action', {action => $action});
# If we are removing bugs, then we must have an existing my $method = "${action}_tag";
# saved search selected.
if ($action eq 'remove') {
$query_name && ThrowUserError('no_bugs_to_remove');
}
my %bug_ids;
my $is_new_name = 0;
if ($query_name) {
my ($query, $query_id) =
LookupNamedQuery($query_name, undef, QUERY_LIST, !THROW_ERROR);
# Make sure this name is not already in use by a normal saved search.
if ($query) {
ThrowUserError('query_name_exists', {name => $query_name,
query_id => $query_id});
}
$is_new_name = 1;
}
# If no new tag name has been given, use the selected one. # If no new tag name has been given, use the selected one.
$query_name ||= $cgi->param('oldqueryname'); $query_name ||= $cgi->param('oldqueryname')
or ThrowUserError('no_tag_to_edit', {action => $action});
# Don't throw an error if it's a new tag name: if the tag already
# exists, add/remove bugs to it, else create it. But if we are
# considering an existing tag, then it has to exist and we throw
# an error if it doesn't (hence the usage of !$is_new_name).
my ($old_query, $query_id) =
LookupNamedQuery($query_name, undef, LIST_OF_BUGS, !$is_new_name);
if ($old_query) {
# We get the encoded query. We need to decode it.
my $old_cgi = new Bugzilla::CGI($old_query);
foreach my $bug_id (split /[\s,]+/, scalar $old_cgi->param('bug_id')) {
$bug_ids{$bug_id} = 1 if detaint_natural($bug_id);
}
}
my $keep_bug = ($action eq 'add') ? 1 : 0; my @buglist;
my $changes = 0; # Validate all bug IDs before editing tags in any of them.
foreach my $bug_id (split(/[\s,]+/, $cgi->param('bug_ids'))) { foreach my $bug_id (split(/[\s,]+/, $cgi->param('bug_ids'))) {
next unless $bug_id; next unless $bug_id;
my $bug = Bugzilla::Bug->check($bug_id); push(@buglist, Bugzilla::Bug->check($bug_id));
$bug_ids{$bug->id} = $keep_bug;
$changes = 1;
} }
ThrowUserError('no_bug_ids',
{'action' => $action, foreach my $bug (@buglist) {
'tag' => $query_name}) $bug->$method($query_name);
unless $changes;
# Only keep bug IDs we want to add/keep. Disregard deleted ones.
my @bug_ids = grep { $bug_ids{$_} == 1 } keys %bug_ids;
# If the list is now empty, we could as well delete it completely.
if (!scalar @bug_ids) {
ThrowUserError('no_bugs_in_list', {name => $query_name,
query_id => $query_id});
} }
$new_query = "bug_id=" . join(',', sort {$a <=> $b} @bug_ids);
$query_type = LIST_OF_BUGS; $vars->{'message'} = 'tag_updated';
} $vars->{'action'} = $action;
my $tofooter = 1; $vars->{'tag'} = $query_name;
my $existed_before = InsertNamedQuery($query_name, $new_query, $vars->{'buglist'} = [map { $_->id } @buglist];
$tofooter, $query_type);
if ($existed_before) {
$vars->{'message'} = "buglist_updated_named_query";
} }
else { else {
$vars->{'message'} = "buglist_new_named_query"; 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 # Make sure to invalidate any cached query data, so that the footer is
# correctly displayed # correctly displayed
$user->flush_queries_cache(); $user->flush_queries_cache();
$vars->{'queryname'} = $query_name;
}
$vars->{'queryname'} = $query_name;
print $cgi->header(); print $cgi->header();
$template->process("global/message.html.tmpl", $vars) $template->process("global/message.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
......
...@@ -865,6 +865,17 @@ ...@@ -865,6 +865,17 @@
The cookie that was remembering your login is now gone. The cookie that was remembering your login is now gone.
[% END %] [% END %]
[% ELSIF message_tag == "tag_updated" %]
[% title = "Tag Updated" %]
The '[% tag FILTER html %]' 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" %] [% ELSIF message_tag == "term" %]
[% terms.$term FILTER html %] [% terms.$term FILTER html %]
......
...@@ -51,12 +51,6 @@ ...@@ -51,12 +51,6 @@
//--> //-->
</script> </script>
[%# Get existing lists of bugs for this user %]
[% lists_of_bugs = [] %]
[% FOREACH q = user.queries %]
[% NEXT UNLESS q.type == constants.LIST_OF_BUGS %]
[% lists_of_bugs.push(q.name) %]
[% END %]
<div class="label"></div> <div class="label"></div>
<ul class="links"><li class="form"> <ul class="links"><li class="form">
<form id="list_of_bugs" action="buglist.cgi" method="get"> <form id="list_of_bugs" action="buglist.cgi" method="get">
...@@ -66,7 +60,7 @@ ...@@ -66,7 +60,7 @@
<input type="hidden" name="token" value="[% issue_hash_token(['savedsearch']) FILTER html %]"> <input type="hidden" name="token" value="[% issue_hash_token(['savedsearch']) FILTER html %]">
<select id="lob_action" name="action" onchange="update_text();"> <select id="lob_action" name="action" onchange="update_text();">
<option value="add">Add</option> <option value="add">Add</option>
[% IF lists_of_bugs.size %] [% IF user.tags.size %]
<option value="remove">Remove</option> <option value="remove">Remove</option>
[% END %] [% END %]
</select> </select>
...@@ -77,15 +71,15 @@ ...@@ -77,15 +71,15 @@
the named tag the named tag
[% END %] [% END %]
[% IF lists_of_bugs.size %] [% IF user.tags.size %]
<select id="lob_oldqueryname" name="oldqueryname"> <select id="lob_oldqueryname" name="oldqueryname">
[% FOREACH query = lists_of_bugs %] [% FOREACH tag = user.tags.keys %]
<option value="[% query FILTER html %]">[% query FILTER html %]</option> <option value="[% tag FILTER html %]">[% tag FILTER html %]</option>
[% END %] [% END %]
</select> </select>
[% END %] [% END %]
<span id="lob_new_query_text"> <span id="lob_new_query_text">
[% " or create and add the tag" IF lists_of_bugs.size %] [% " or create and add the tag" IF user.tags.size %]
<input class="txt" type="text" id="lob_newqueryname" <input class="txt" type="text" id="lob_newqueryname"
size="20" maxlength="64" name="newqueryname" size="20" maxlength="64" name="newqueryname"
onkeyup="manage_old_lists();"> onkeyup="manage_old_lists();">
......
...@@ -1211,24 +1211,9 @@ ...@@ -1211,24 +1211,9 @@
to view. to view.
[% END %] [% END %]
[% ELSIF error == "no_bug_ids" %] [% ELSIF error == "no_tag_to_edit" %]
[% title = BLOCK %]No [% terms.Bugs %] Selected[% END %]
You didn't choose any [% terms.bugs %] to
[% IF action == "add" %] add to [% ELSE %] remove from [% END %]
the [% tag FILTER html %] tag.
[% ELSIF error == "no_bugs_in_list" %]
[% title = "Delete Tag?" %]
This will remove all [% terms.bugs %] from the
<em>[% name FILTER html %]</em> tag. This will delete the tag completely. Click
<a href="buglist.cgi?cmdtype=dorem&amp;remaction=forget&amp;namedcmd=
[%- name FILTER uri %]&amp;token=
[%- issue_hash_token([query_id, name]) FILTER uri %]">here</a>
if you really want to delete it.
[% ELSIF error == "no_bugs_to_remove" %]
[% title = "No Tag Selected" %] [% title = "No Tag Selected" %]
You didn't select a tag from which to remove [% terms.bugs %]. You tried to create or remove a tag with no name.
[% ELSIF error == "no_initial_bug_status" %] [% ELSIF error == "no_initial_bug_status" %]
[% title = "No Initial $terms.Bug Status" %] [% title = "No Initial $terms.Bug Status" %]
...@@ -1430,15 +1415,6 @@ ...@@ -1430,15 +1415,6 @@
named '[% comp FILTER html %]'. named '[% comp FILTER html %]'.
[% END %] [% END %]
[% ELSIF error == "query_name_exists" %]
[% title = "Search Name Already In Use" %]
The name <em>[% name FILTER html %]</em> is already used by another
saved search. You first have to
<a href="buglist.cgi?cmdtype=dorem&amp;remaction=forget&amp;namedcmd=
[%- name FILTER uri %]&amp;token=
[% issue_hash_token([query_id, name]) FILTER uri %]">delete</a>
it if you really want to use this name.
[% ELSIF error == "query_name_missing" %] [% ELSIF error == "query_name_missing" %]
[% title = "No Search Name Specified" %] [% title = "No Search Name Specified" %]
[% docslinks = {'query.html#list' => "$terms.Bug lists"} %] [% docslinks = {'query.html#list' => "$terms.Bug lists"} %]
...@@ -1588,6 +1564,11 @@ ...@@ -1588,6 +1564,11 @@
[% title = "User Protected" %] [% title = "User Protected" %]
The user [% login FILTER html %] may not be impersonated by sudoers. The user [% login FILTER html %] may not be impersonated by sudoers.
[% ELSIF error == "tag_name_too_long" %]
[% title = "Tag Name Too Long" %]
The tag name must be less than [% constants.MAX_LEN_QUERY_NAME FILTER html %]
characters long.
[% ELSIF error == "token_does_not_exist" %] [% ELSIF error == "token_does_not_exist" %]
[% title = "Token Does Not Exist" %] [% title = "Token Does Not Exist" %]
The token you submitted does not exist, has expired, or has The token you submitted does not exist, has expired, or has
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment