mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 07:05:24 +00:00
Bug 38922: Default (Initial) CC list for each component
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=myk
This commit is contained in:
parent
4a704b845a
commit
4aa61010ef
@ -115,7 +115,6 @@ sub VALIDATORS {
|
||||
alias => \&_check_alias,
|
||||
bug_file_loc => \&_check_bug_file_loc,
|
||||
bug_severity => \&_check_bug_severity,
|
||||
cc => \&_check_cc,
|
||||
comment => \&_check_comment,
|
||||
commentprivacy => \&_check_commentprivacy,
|
||||
deadline => \&_check_deadline,
|
||||
@ -353,6 +352,8 @@ sub run_create_validators {
|
||||
$class->_check_assigned_to($component, $params->{assigned_to});
|
||||
$params->{qa_contact} =
|
||||
$class->_check_qa_contact($component, $params->{qa_contact});
|
||||
$params->{cc} = $class->_check_cc($component, $params->{cc});
|
||||
|
||||
# Callers cannot set Reporter, currently.
|
||||
$params->{reporter} = Bugzilla->user->id;
|
||||
|
||||
@ -506,7 +507,7 @@ sub _check_bug_status {
|
||||
}
|
||||
|
||||
sub _check_cc {
|
||||
my ($invocant, $ccs) = @_;
|
||||
my ($invocant, $component, $ccs) = @_;
|
||||
return [] unless $ccs;
|
||||
|
||||
my %cc_ids;
|
||||
@ -515,6 +516,10 @@ sub _check_cc {
|
||||
my $id = login_to_id($person, THROW_ERROR);
|
||||
$cc_ids{$id} = 1;
|
||||
}
|
||||
|
||||
# Enforce Default CC
|
||||
$cc_ids{$_->id} = 1 foreach (@{$component->initial_cc});
|
||||
|
||||
return [keys %cc_ids];
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#
|
||||
# Contributor(s): Tiago R. Mello <timello@async.com.br>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
# Max Kanat-Alexander <mkanat@bugzilla.org>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
|
||||
use strict;
|
||||
|
||||
@ -154,6 +156,21 @@ sub flag_types {
|
||||
return $self->{'flag_types'};
|
||||
}
|
||||
|
||||
sub initial_cc {
|
||||
my $self = shift;
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
if (!defined $self->{'initial_cc'}) {
|
||||
my $cc_ids = $dbh->selectcol_arrayref(
|
||||
"SELECT user_id FROM component_cc WHERE component_id = ?",
|
||||
undef, $self->id);
|
||||
my $initial_cc = Bugzilla::User->new_from_list($cc_ids);
|
||||
$self->{'initial_cc'} = $initial_cc;
|
||||
}
|
||||
return $self->{'initial_cc'};
|
||||
}
|
||||
|
||||
###############################
|
||||
#### Accessors ####
|
||||
###############################
|
||||
@ -212,6 +229,7 @@ Bugzilla::Component - Bugzilla product component class.
|
||||
my $product_id = $component->product_id;
|
||||
my $default_assignee = $component->default_assignee;
|
||||
my $default_qa_contact = $component->default_qa_contact;
|
||||
my $initial_cc = $component->initial_cc
|
||||
my $bug_flag_types = $component->flag_types->{'bug'};
|
||||
my $attach_flag_types = $component->flag_types->{'attachment'};
|
||||
|
||||
@ -273,6 +291,11 @@ Component.pm represents a Product Component object.
|
||||
|
||||
Returns: A Bugzilla::User object.
|
||||
|
||||
=item C<initial_cc>
|
||||
|
||||
Returns an arrayref of L<Bugzilla::User> objects representing the
|
||||
Initial CC List.
|
||||
|
||||
=item C<flag_types()>
|
||||
|
||||
Description: Returns all bug and attachment flagtypes available for
|
||||
|
@ -22,6 +22,7 @@
|
||||
# Max Kanat-Alexander <mkanat@bugzilla.org>
|
||||
# Lance Larsh <lance.larsh@oracle.com>
|
||||
# Dennis Melentyev <dennis.melentyev@infopulse.com.ua>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
|
||||
package Bugzilla::DB::Schema;
|
||||
|
||||
@ -703,6 +704,18 @@ use constant ABSTRACT_SCHEMA => {
|
||||
],
|
||||
},
|
||||
|
||||
component_cc => {
|
||||
|
||||
FIELDS => [
|
||||
user_id => {TYPE => 'INT3', NOTNULL => 1},
|
||||
component_id => {TYPE => 'INT2', NOTNULL => 1},
|
||||
],
|
||||
INDEXES => [
|
||||
component_cc_user_id_idx => {FIELDS => [qw(component_id user_id)],
|
||||
TYPE => 'UNIQUE'},
|
||||
],
|
||||
},
|
||||
|
||||
# Authentication
|
||||
# --------------
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
# Contributor(s): Holger Schurig <holgerschurig@nikocity.de>
|
||||
# Terry Weissman <terry@mozilla.org>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
#
|
||||
# Direct any questions on this source code to
|
||||
#
|
||||
@ -39,6 +40,26 @@ use Bugzilla::Product;
|
||||
use Bugzilla::Component;
|
||||
use Bugzilla::Bug;
|
||||
|
||||
###############
|
||||
# Subroutines #
|
||||
###############
|
||||
|
||||
# Takes an arrayref of login names and returns an arrayref of user ids.
|
||||
sub check_initial_cc {
|
||||
my ($user_names) = @_;
|
||||
|
||||
my %cc_ids;
|
||||
foreach my $cc (@$user_names) {
|
||||
my $id = login_to_id($cc, THROW_ERROR);
|
||||
$cc_ids{$id} = 1;
|
||||
}
|
||||
return [keys %cc_ids];
|
||||
}
|
||||
|
||||
###############
|
||||
# Main Script #
|
||||
###############
|
||||
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $template = Bugzilla->template;
|
||||
@ -129,11 +150,13 @@ if ($action eq 'new') {
|
||||
Bugzilla::User::match_field ($cgi, {
|
||||
'initialowner' => { 'type' => 'single' },
|
||||
'initialqacontact' => { 'type' => 'single' },
|
||||
'initialcc' => { 'type' => 'multi' },
|
||||
});
|
||||
|
||||
my $default_assignee = trim($cgi->param('initialowner') || '');
|
||||
my $default_qa_contact = trim($cgi->param('initialqacontact') || '');
|
||||
my $description = trim($cgi->param('description') || '');
|
||||
my @initial_cc = $cgi->param('initialcc');
|
||||
|
||||
$comp_name || ThrowUserError('component_blank_name');
|
||||
|
||||
@ -161,9 +184,13 @@ if ($action eq 'new') {
|
||||
my $default_qa_contact_id = Bugzilla->params->{'useqacontact'} ?
|
||||
(login_to_id($default_qa_contact) || undef) : undef;
|
||||
|
||||
my $initial_cc_ids = check_initial_cc(\@initial_cc);
|
||||
|
||||
trick_taint($comp_name);
|
||||
trick_taint($description);
|
||||
|
||||
$dbh->bz_lock_tables('components WRITE', 'component_cc WRITE');
|
||||
|
||||
$dbh->do("INSERT INTO components
|
||||
(product_id, name, description, initialowner,
|
||||
initialqacontact)
|
||||
@ -171,6 +198,17 @@ if ($action eq 'new') {
|
||||
($product->id, $comp_name, $description,
|
||||
$default_assignee_id, $default_qa_contact_id));
|
||||
|
||||
$component = new Bugzilla::Component({ product_id => $product->id,
|
||||
name => $comp_name });
|
||||
|
||||
my $sth = $dbh->prepare("INSERT INTO component_cc
|
||||
(user_id, component_id) VALUES (?, ?)");
|
||||
foreach my $user_id (@$initial_cc_ids) {
|
||||
$sth->execute($user_id, $component->id);
|
||||
}
|
||||
|
||||
$dbh->bz_unlock_tables;
|
||||
|
||||
# Insert default charting queries for this product.
|
||||
# If they aren't using charting, this won't do any harm.
|
||||
my @series;
|
||||
@ -204,10 +242,6 @@ if ($action eq 'new') {
|
||||
$series->writeToDatabase();
|
||||
}
|
||||
|
||||
$component =
|
||||
new Bugzilla::Component({product_id => $product->id,
|
||||
name => $comp_name});
|
||||
|
||||
$vars->{'comp'} = $component;
|
||||
$vars->{'product'} = $product;
|
||||
$template->process("admin/components/created.html.tmpl",
|
||||
@ -263,13 +297,15 @@ if ($action eq 'delete') {
|
||||
}
|
||||
}
|
||||
|
||||
$dbh->bz_lock_tables('components WRITE', 'flaginclusions WRITE',
|
||||
'flagexclusions WRITE');
|
||||
$dbh->bz_lock_tables('components WRITE', 'component_cc WRITE',
|
||||
'flaginclusions WRITE', 'flagexclusions WRITE');
|
||||
|
||||
$dbh->do("DELETE FROM flaginclusions WHERE component_id = ?",
|
||||
undef, $component->id);
|
||||
$dbh->do("DELETE FROM flagexclusions WHERE component_id = ?",
|
||||
undef, $component->id);
|
||||
$dbh->do("DELETE FROM component_cc WHERE component_id = ?",
|
||||
undef, $component->id);
|
||||
$dbh->do("DELETE FROM components WHERE id = ?",
|
||||
undef, $component->id);
|
||||
|
||||
@ -292,8 +328,12 @@ if ($action eq 'delete') {
|
||||
|
||||
if ($action eq 'edit') {
|
||||
|
||||
$vars->{'comp'} =
|
||||
my $component =
|
||||
Bugzilla::Component::check_component($product, $comp_name);
|
||||
$vars->{'comp'} = $component;
|
||||
|
||||
$vars->{'initial_cc_names'} =
|
||||
join(', ', map($_->login, @{$component->initial_cc}));
|
||||
|
||||
$vars->{'product'} = $product;
|
||||
|
||||
@ -316,12 +356,14 @@ if ($action eq 'update') {
|
||||
Bugzilla::User::match_field ($cgi, {
|
||||
'initialowner' => { 'type' => 'single' },
|
||||
'initialqacontact' => { 'type' => 'single' },
|
||||
'initialcc' => { 'type' => 'multi' },
|
||||
});
|
||||
|
||||
my $comp_old_name = trim($cgi->param('componentold') || '');
|
||||
my $default_assignee = trim($cgi->param('initialowner') || '');
|
||||
my $default_qa_contact = trim($cgi->param('initialqacontact') || '');
|
||||
my $description = trim($cgi->param('description') || '');
|
||||
my @initial_cc = $cgi->param('initialcc');
|
||||
|
||||
my $component_old =
|
||||
Bugzilla::Component::check_component($product, $comp_old_name);
|
||||
@ -352,7 +394,10 @@ if ($action eq 'update') {
|
||||
my $default_assignee_id = login_to_id($default_assignee);
|
||||
my $default_qa_contact_id = login_to_id($default_qa_contact) || undef;
|
||||
|
||||
$dbh->bz_lock_tables('components WRITE', 'profiles READ');
|
||||
my $initial_cc_ids = check_initial_cc(\@initial_cc);
|
||||
|
||||
$dbh->bz_lock_tables('components WRITE', 'component_cc WRITE',
|
||||
'profiles READ');
|
||||
|
||||
if ($comp_name ne $component_old->name) {
|
||||
|
||||
@ -390,11 +435,29 @@ if ($action eq 'update') {
|
||||
$vars->{'updated_initialqacontact'} = 1;
|
||||
}
|
||||
|
||||
my @initial_cc_old = map($_->id, @{$component_old->initial_cc});
|
||||
my ($removed, $added) = diff_arrays(\@initial_cc_old, $initial_cc_ids);
|
||||
|
||||
foreach my $user_id (@$removed) {
|
||||
$dbh->do('DELETE FROM component_cc
|
||||
WHERE component_id = ? AND user_id = ?', undef,
|
||||
$component_old->id, $user_id);
|
||||
$vars->{'updated_initialcc'} = 1;
|
||||
}
|
||||
|
||||
foreach my $user_id (@$added) {
|
||||
$dbh->do("INSERT INTO component_cc (user_id, component_id)
|
||||
VALUES (?, ?)", undef, $user_id, $component_old->id);
|
||||
$vars->{'updated_initialcc'} = 1;
|
||||
}
|
||||
|
||||
$dbh->bz_unlock_tables();
|
||||
|
||||
my $component = new Bugzilla::Component($component_old->id);
|
||||
|
||||
$vars->{'comp'} = $component;
|
||||
$vars->{'initial_cc_names'} =
|
||||
join(', ', map($_->login, @{$component->initial_cc}));
|
||||
$vars->{'product'} = $product;
|
||||
$template->process("admin/components/updated.html.tmpl",
|
||||
$vars)
|
||||
|
@ -26,6 +26,7 @@
|
||||
# Jeff Hedlund <jeff.hedlund@matrixsi.com>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
# Lance Larsh <lance.larsh@oracle.com>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
|
||||
# Implementation notes for this file:
|
||||
#
|
||||
@ -1370,6 +1371,18 @@ foreach my $id (@idlist) {
|
||||
$query .= ", qa_contact = NULL";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
# And add in the Default CC for the Component.
|
||||
my $comp_obj = $component || new Bugzilla::Component($new_comp_id);
|
||||
my @new_init_cc = @{$comp_obj->initial_cc};
|
||||
foreach my $cc (@new_init_cc) {
|
||||
# NewCC must be defined or the code below won't insert
|
||||
# any CCs.
|
||||
$cgi->param('newcc') || $cgi->param('newcc', []);
|
||||
$cc_add{$cc->id} = $cc->login;
|
||||
}
|
||||
}
|
||||
|
||||
my %dependencychanged;
|
||||
|
@ -17,6 +17,7 @@
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
#%]
|
||||
|
||||
[%# INTERFACE:
|
||||
@ -76,6 +77,24 @@
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
<tr>
|
||||
<th align="right">
|
||||
<label for="initialcc">Default CC List:</label>
|
||||
</th>
|
||||
<td>
|
||||
[% INCLUDE global/userselect.html.tmpl
|
||||
name => "initialcc"
|
||||
id => "initialcc"
|
||||
value => ""
|
||||
size => 64
|
||||
multiple => 5
|
||||
%]
|
||||
<br>
|
||||
[% IF !Param("usemenuforusers") %]
|
||||
<em>Enter user names for the CC in a comma-separated list.</em>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<input type="submit" id="create" value="Add">
|
||||
|
@ -17,6 +17,7 @@
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
#%]
|
||||
|
||||
[%# INTERFACE:
|
||||
@ -81,6 +82,24 @@
|
||||
[% END %]
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<label for="initialcc">Default CC List:</label>
|
||||
</td>
|
||||
<td>
|
||||
[% INCLUDE global/userselect.html.tmpl
|
||||
name => "initialcc"
|
||||
id => "initialcc"
|
||||
value => initial_cc_names
|
||||
size => 64
|
||||
multiple => 5
|
||||
%]
|
||||
<br>
|
||||
[% IF !Param("usemenuforusers") %]
|
||||
<em>Enter user names for the CC in a comma-separated list.</em>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>[% terms.Bugs %]:</td>
|
||||
<td>
|
||||
|
@ -17,6 +17,8 @@
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
# Max Kanat-Alexander <mkanat@bugzilla.org>
|
||||
#%]
|
||||
|
||||
[%# INTERFACE:
|
||||
@ -32,10 +34,15 @@
|
||||
#
|
||||
# updated_initialqacontact: the default qa contact updated
|
||||
#
|
||||
# updated_initialcc: the default initial cc list
|
||||
#
|
||||
# comp: object; Bugzilla::Component object representing the component
|
||||
# user updated.
|
||||
# product: object; Bugzilla::Product object representing the product to
|
||||
# which the component belongs.
|
||||
#
|
||||
# initial_cc_names: a comma-separated list of the login names of
|
||||
# the Initial CC, if it was updated.
|
||||
#%]
|
||||
|
||||
[% title = BLOCK %]Updating Component '[% comp.name FILTER html %]' of Product
|
||||
@ -72,11 +79,20 @@
|
||||
<p>Updated Component name to: '[% comp.name FILTER html %]'.</p>
|
||||
[% END %]
|
||||
|
||||
[% IF updated_initialcc %]
|
||||
[% IF initial_cc_names %]
|
||||
<p>Updated Default CC list to:
|
||||
'[% initial_cc_names FILTER html %]'.</p>
|
||||
[% ELSE %]
|
||||
<p>Removed the Default CC list.</p>
|
||||
[% END %]
|
||||
[% END %]
|
||||
|
||||
[% UNLESS updated_description || updated_initialowner ||
|
||||
updated_initialqacontact || updated_name %]
|
||||
updated_initialqacontact || updated_name ||
|
||||
updated_initialcc %]
|
||||
<p>Nothing changed for component '[% comp.name FILTER html %]'.
|
||||
[% END %]
|
||||
|
||||
|
||||
[% PROCESS admin/components/footer.html.tmpl %]
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
# Ville Skyttä <ville.skytta@iki.fi>
|
||||
# Shane H. W. Travis <travis@sedsystems.ca>
|
||||
# Marc Schumann <wurblzap@gmail.com>
|
||||
# Akamai Technologies <bugzilla-dev@akamai.com>
|
||||
# Max Kanat-Alexander <mkanat@bugzilla.org>
|
||||
#%]
|
||||
|
||||
[% PROCESS "global/field-descs.none.tmpl" %]
|
||||
@ -28,7 +30,6 @@
|
||||
title = "Enter $terms.Bug: $product.name"
|
||||
style_urls = [ 'skins/standard/create_attachment.css' ]
|
||||
javascript_urls = [ "js/attachment.js" ]
|
||||
onload="set_assign_to();"
|
||||
%]
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -36,6 +37,7 @@
|
||||
|
||||
var initialowners = new Array([% product.components.size %]);
|
||||
var last_initialowner;
|
||||
var initialccs = new Array([% product.components.size %]);
|
||||
var components = new Array([% product.components.size %]);
|
||||
var flags = new Array([% product.components.size %]);
|
||||
[% IF Param("useqacontact") %]
|
||||
@ -60,6 +62,13 @@ var flags = new Array([% product.components.size %]);
|
||||
[% IF Param("useqacontact") %]
|
||||
initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]";
|
||||
[% END %]
|
||||
|
||||
[% SET initial_cc_list = [] %]
|
||||
[% FOREACH cc_user = c.initial_cc %]
|
||||
[% initial_cc_list.push(cc_user.login) %]
|
||||
[% END %]
|
||||
initialccs[[% count %]] = "[% initial_cc_list.join(', ') FILTER js %]";
|
||||
|
||||
[% count = count + 1 %]
|
||||
[%- END %]
|
||||
|
||||
@ -90,6 +99,9 @@ function set_assign_to() {
|
||||
form.assigned_to.value = owner;
|
||||
last_initialowner = owner;
|
||||
}
|
||||
|
||||
document.getElementById('initial_cc').innerHTML = initialccs[index];
|
||||
|
||||
[% IF Param("useqacontact") %]
|
||||
var contact = initialqacontacts[index];
|
||||
if (qa_contact == last_initialqacontact
|
||||
@ -317,6 +329,18 @@ function handleWantsAttachment(wants_attachment) {
|
||||
%]
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th align="right">Default CC:</th>
|
||||
<td colspan="2">
|
||||
<div id="initial_cc">
|
||||
<!-- This has to happen after everything above renders,
|
||||
and onload doesn't work. So this is as good a place
|
||||
as any to put it. -->
|
||||
<script type="text/javascript">set_assign_to();</script>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> </td>
|
||||
|
@ -104,8 +104,8 @@
|
||||
<input type="radio" id="knob-reassign-cmp" name="knob" value="reassignbycomponent">
|
||||
<label for="knob-reassign-cmp">
|
||||
Reassign [% terms.bug %] to default assignee
|
||||
[% " and QA contact" IF Param('useqacontact') %]
|
||||
of selected component
|
||||
[% " and QA contact" IF Param('useqacontact') %],
|
||||
and add Default CC, of selected component
|
||||
</label>
|
||||
<br>
|
||||
[% IF bug.isunconfirmed && bug.user.canconfirm %]
|
||||
|
Loading…
Reference in New Issue
Block a user