summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormkanat%bugzilla.org <>2006-09-21 06:57:57 +0200
committermkanat%bugzilla.org <>2006-09-21 06:57:57 +0200
commitc6433b10999a9bfe1f26bea4deaba11db3251fc0 (patch)
tree49a274adb031a18a9b3bd7f2641cc9d92a9f5449
parentf90a0b775e927aad00631ce80d282186a3022af5 (diff)
downloadbugzilla-c6433b10999a9bfe1f26bea4deaba11db3251fc0.tar.gz
bugzilla-c6433b10999a9bfe1f26bea4deaba11db3251fc0.tar.xz
Bug 38922: Default (Initial) CC list for each component
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=myk
-rwxr-xr-xBugzilla/Bug.pm9
-rw-r--r--Bugzilla/Component.pm23
-rw-r--r--Bugzilla/DB/Schema.pm13
-rwxr-xr-xeditcomponents.cgi79
-rwxr-xr-xprocess_bug.cgi13
-rw-r--r--template/en/default/admin/components/create.html.tmpl19
-rw-r--r--template/en/default/admin/components/edit.html.tmpl19
-rw-r--r--template/en/default/admin/components/updated.html.tmpl20
-rw-r--r--template/en/default/bug/create/create.html.tmpl26
-rw-r--r--template/en/default/bug/knob.html.tmpl4
10 files changed, 210 insertions, 15 deletions
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm
index d309d0bc2..5ac2f2b0b 100755
--- a/Bugzilla/Bug.pm
+++ b/Bugzilla/Bug.pm
@@ -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];
}
diff --git a/Bugzilla/Component.pm b/Bugzilla/Component.pm
index abd3711f5..4b9856feb 100644
--- a/Bugzilla/Component.pm
+++ b/Bugzilla/Component.pm
@@ -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
diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm
index 938ef042a..4235be5ad 100644
--- a/Bugzilla/DB/Schema.pm
+++ b/Bugzilla/DB/Schema.pm
@@ -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
# --------------
diff --git a/editcomponents.cgi b/editcomponents.cgi
index c87bc0313..cc81cece7 100755
--- a/editcomponents.cgi
+++ b/editcomponents.cgi
@@ -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)
diff --git a/process_bug.cgi b/process_bug.cgi
index 1824dd7f3..e671b9d76 100755
--- a/process_bug.cgi
+++ b/process_bug.cgi
@@ -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;
diff --git a/template/en/default/admin/components/create.html.tmpl b/template/en/default/admin/components/create.html.tmpl
index 83c28ab85..013ee861e 100644
--- a/template/en/default/admin/components/create.html.tmpl
+++ b/template/en/default/admin/components/create.html.tmpl
@@ -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">
diff --git a/template/en/default/admin/components/edit.html.tmpl b/template/en/default/admin/components/edit.html.tmpl
index 9392cfd69..6ee3a69fe 100644
--- a/template/en/default/admin/components/edit.html.tmpl
+++ b/template/en/default/admin/components/edit.html.tmpl
@@ -17,6 +17,7 @@
# Rights Reserved.
#
# Contributor(s): Gavin Shelley <bugzilla@chimpychompy.org>
+ # Akamai Technologies <bugzilla-dev@akamai.com>
#%]
[%# INTERFACE:
@@ -82,6 +83,24 @@
</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>
[% IF comp.bug_count > 0 %]
diff --git a/template/en/default/admin/components/updated.html.tmpl b/template/en/default/admin/components/updated.html.tmpl
index 43214f979..a6f2c8b9d 100644
--- a/template/en/default/admin/components/updated.html.tmpl
+++ b/template/en/default/admin/components/updated.html.tmpl
@@ -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 %]
diff --git a/template/en/default/bug/create/create.html.tmpl b/template/en/default/bug/create/create.html.tmpl
index 26e95523b..eb3aea2e4 100644
--- a/template/en/default/bug/create/create.html.tmpl
+++ b/template/en/default/bug/create/create.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>&nbsp;</td>
diff --git a/template/en/default/bug/knob.html.tmpl b/template/en/default/bug/knob.html.tmpl
index 36712911e..00ffcb053 100644
--- a/template/en/default/bug/knob.html.tmpl
+++ b/template/en/default/bug/knob.html.tmpl
@@ -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 %]