Remove products.defaultmilestone and allow to configure default milestone using the generic field UI

hinted-selects
Vitaliy Filippov 2014-08-14 16:13:29 +04:00
parent cc41c14ddb
commit eccb6bc9eb
22 changed files with 76 additions and 263 deletions

View File

@ -2262,15 +2262,6 @@ sub _set_target_milestone
my $field_obj = Bugzilla->get_field('target_milestone');
if (!defined $target || $target eq '')
{
if (!$field_obj->nullable && $field_obj->check_visibility($self))
{
$self->{target_milestone_obj} = $self->product_obj->default_milestone_obj;
$self->{target_milestone} = $self->product_obj->default_milestone;
if (!$self->{target_milestone})
{
ThrowUserError('object_not_specified', { class => $field_obj->value_type });
}
}
$self->{target_milestone_obj} = undef;
$self->{target_milestone} = undef;
return undef;

View File

@ -831,22 +831,26 @@ sub bz_drop_field_tables {
$self->bz_drop_table($field->name);
}
sub bz_drop_column {
sub bz_drop_column
{
my ($self, $table, $column) = @_;
my $current_def = $self->bz_column_info($table, $column);
if ($current_def) {
my @statements = $self->_bz_real_schema->get_drop_column_ddl(
$table, $column);
print get_text('install_column_drop',
{ table => $table, column => $column }) . "\n"
if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
foreach my $sql (@statements) {
# Because this is a deletion, we don't want to die hard if
# we fail because of some local customization. If something
# is already gone, that's fine with us!
eval { $self->do($sql); } or warn "Failed SQL: [$sql] Error: $@";
if ($current_def)
{
my @statements = $self->_bz_real_schema->get_drop_column_ddl($table, $column);
if ($current_def->{REFERENCES})
{
unshift @statements, $self->_bz_real_schema->get_drop_fk_sql(
$table, $column, $current_def->{REFERENCES}
);
}
if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE)
{
print get_text('install_column_drop', { table => $table, column => $column }) . "\n"
}
foreach my $sql (@statements)
{
$self->do($sql);
}
$self->_bz_real_schema->delete_column($table, $column);
$self->_bz_store_real_schema;

View File

@ -1050,7 +1050,6 @@ use constant ABSTRACT_SCHEMA => {
votesperuser => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0},
maxvotesperbug => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => '10000'},
votestoconfirm => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0},
defaultmilestone => {TYPE => 'INT4', REFERENCES => {TABLE => 'milestones', COLUMN => 'id'}},
allows_unconfirmed => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
wiki_url => {TYPE => 'varchar(255)', NOTNULL => 1, DEFAULT => "''"},
# CustIS Bug 59357 - Prefer no time-tracking in some products

View File

@ -217,7 +217,7 @@ use constant CAN_TWEAK => {
nullable => { map { $_ => 1 } qw(alias bug_severity deadline keywords op_sys priority rep_platform status_whiteboard target_milestone version) },
visibility_field_id => { map { $_ => 1 } qw(bug_severity op_sys priority rep_platform status_whiteboard target_milestone version) },
value_field_id => { map { $_ => 1 } qw(bug_severity op_sys priority rep_platform) },
default_field_id => { map { $_ => 1 } qw(bug_severity keywords op_sys priority component rep_platform status_whiteboard) },
default_field_id => { map { $_ => 1 } qw(bug_severity keywords op_sys priority component rep_platform status_whiteboard target_milestone) },
};
################
@ -990,6 +990,7 @@ sub update_visibility_values
return 1;
}
# FIXME: Make this function report saved changes
sub update_control_lists
{
my $self = shift;
@ -1030,8 +1031,8 @@ sub update_control_lists
$mod = { del => [], add => [] };
for my $f (Bugzilla->get_fields({ obsolete => 0, default_field_id => $self->id }))
{
# FIXME: default version is hardcoded to depend on component, default milestone is hardcoded to depend on product
next if $f eq 'version' || $f eq 'target_milestone';
# FIXME: default version is hardcoded to depend on component
next if $f eq 'version';
my $default = $params->{'default_'.$f->name};
$default = $f->_check_default_value($default);
if (!$default)
@ -1257,9 +1258,13 @@ sub populate_field_definitions
{
$field->set_is_mandatory($def->{is_mandatory});
}
$field->set_value_field($dbh->selectrow_array('SELECT id FROM fielddefs WHERE name=?', undef, $def->{value_field})) if $def->{value_field};
$field->set_null_field($dbh->selectrow_array('SELECT id FROM fielddefs WHERE name=?', undef, $def->{null_field})) if $def->{null_field};
$field->set_default_field($dbh->selectrow_array('SELECT id FROM fielddefs WHERE name=?', undef, $def->{default_field})) if $def->{default_field};
for (qw(value_field null_field default_field))
{
if ($def->{$_} && !$field->{$_.'_id'})
{
$field->set($_.'_id', $dbh->selectrow_array('SELECT id FROM fielddefs WHERE name=?', undef, $def->{$_}));
}
}
$field->update();
}
else

View File

@ -178,6 +178,24 @@ sub remove_from_db
$self->set_visibility_values(undef);
# Delete controlled value records
$self->field->update_control_lists($self->id, {});
# Delete records about this value used as default
my $dbh = Bugzilla->dbh;
$dbh->do("DELETE FROM field_defaults WHERE field_id=? AND default_value=?", undef, $self->field->id, $self->id);
if ($self->field->type == FIELD_TYPE_MULTI_SELECT)
{
$dbh->do(
"UPDATE field_defaults SET default_value=REPLACE(default_value, ?, ?) WHERE field_id=?".
" AND default_value LIKE ?", undef, ','.$self->id.',', ',', $self->field->id, '%,'.$self->id.',%'
);
$dbh->do(
"UPDATE field_defaults SET default_value=SUBSTR(default_value, ?) WHERE field_id=?".
" AND default_value LIKE ?", undef, length($self->id)+2, $self->field->id, $self->id.',%'
);
$dbh->do(
"UPDATE field_defaults SET default_value=SUBSTR(default_value, 1, LENGTH(default_value)-?) WHERE field_id=?".
" AND default_value LIKE ?", undef, length($self->id)+1, $self->field->id, '%,'.$self->id
);
}
$self->field->touch;
$self->SUPER::remove_from_db();
}

View File

@ -223,8 +223,6 @@ sub update_table_definitions
_populate_milestones_table();
_add_products_defaultmilestone();
# 2000-03-24 Added unique indexes into the cc and keyword tables. This
# prevents certain database inconsistencies, and, moreover, is required for
# new generalized list code to work.
@ -741,29 +739,32 @@ WHERE description LIKE\'%[CC:%\'');
}
# Move fieldvaluecontrol.is_default to field_defaults
if ($dbh->bz_column_info(fieldvaluecontrol => 'is_default'))
if ($dbh->bz_column_info('fieldvaluecontrol', 'is_default'))
{
print "Moving default value information to the new table field_defaults...\n";
$dbh->do(
"INSERT INTO field_defaults (field_id, visibility_value_id, default_value)".
" SELECT field_id, visibility_value_id, ".$dbh->sql_group_concat('value_id', "','").
" FROM fieldvaluecontrol WHERE is_default=1"
);
$dbh->bz_drop_column(fieldvaluecontrol => 'is_default');
$dbh->bz_drop_column('fieldvaluecontrol', 'is_default');
}
# Copy products.defaultmilestone information into field_defaults
my $fid = Bugzilla->get_field('target_milestone')->id;
if ($fid && !$dbh->selectrow_array("SELECT * FROM field_defaults WHERE field_id=$fid"))
$dbh->bz_add_column('products', defaultmilestone => {TYPE => 'INT4', REFERENCES => {TABLE => 'milestones', COLUMN => 'id'}});
if ($dbh->bz_column_info('products', 'defaultmilestone'))
{
print "Copying default milestone information into field_defaults...\n";
print "Moving default milestone information into field_defaults...\n";
my $fid = Bugzilla->get_field('target_milestone')->id;
$dbh->do(
"INSERT INTO field_defaults (field_id, visibility_value_id, default_value)".
" SELECT $fid, id, defaultmilestone FROM products"
"REPLACE INTO field_defaults (field_id, visibility_value_id, default_value)".
" SELECT $fid, id, defaultmilestone FROM products WHERE defaultmilestone IS NOT NULL"
);
$dbh->bz_drop_column('products', 'defaultmilestone');
}
# Copy components.default_version information into field_defaults
$fid = Bugzilla->get_field('version')->id;
my $fid = Bugzilla->get_field('version')->id;
if ($fid && !$dbh->selectrow_array("SELECT * FROM field_defaults WHERE field_id=$fid"))
{
print "Copying default version information into field_defaults...\n";
@ -1211,15 +1212,6 @@ sub _populate_milestones_table
}
}
sub _add_products_defaultmilestone
{
my $dbh = Bugzilla->dbh;
# 2000-03-23 Added a defaultmilestone field to the products table, so that
# we know which milestone to initially assign bugs to.
$dbh->bz_add_column('products', 'defaultmilestone');
}
sub _copy_from_comments_to_longdescs {
my $dbh = Bugzilla->dbh;
# 2000-11-27 For Bugzilla 2.5 and later. Copy data from 'comments' to
@ -4017,7 +4009,8 @@ sub _change_select_fields_to_ids
for my $col (@$change_to_id)
{
my ($subject, $col, $tab, $depend) = @$col;
if ($dbh->bz_column_info($subject, $col)->{TYPE} !~ /INT/i)
my $info = $dbh->bz_column_info($subject, $col);
if ($info && $info->{TYPE} !~ /INT/i)
{
$started ||= (print "-- Changing select fields to store IDs instead of names --\n");
# Change column to nullable varchar(255)

View File

@ -143,52 +143,6 @@ sub update
return $changes;
}
sub remove_from_db
{
my $self = shift;
my $dbh = Bugzilla->dbh;
# The default milestone cannot be deleted.
if ($self->id eq $self->product->default_milestone)
{
ThrowUserError('milestone_is_default', { milestone => $self });
}
if ($self->bug_count)
{
# We don't want to delete bugs when deleting a milestone.
# Bugs concerned are reassigned to the default milestone.
my $bug_ids = $dbh->selectcol_arrayref(
'SELECT bug_id FROM bugs WHERE product_id = ? AND target_milestone = ?',
undef, ($self->product->id, $self->id)
);
my $timestamp = $dbh->selectrow_array('SELECT NOW()');
$dbh->do(
'UPDATE bugs SET target_milestone = ?, delta_ts = ? WHERE ' . $dbh->sql_in('bug_id', $bug_ids),
undef, ($self->product->default_milestone, $timestamp)
);
require Bugzilla::Bug;
my $def = Bugzilla::Milestone->new($self->product->default_milestone);
foreach my $bug_id (@$bug_ids)
{
Bugzilla::Bug::LogActivityEntry(
$bug_id, 'target_milestone', $self->name,
$def && $def->name, Bugzilla->user->id, $timestamp
);
}
}
# Remove visibility values
$self->set_visibility_values(undef);
$dbh->do('DELETE FROM milestones WHERE id = ?', undef, $self->id);
Bugzilla->get_field(FIELD_NAME)->touch;
}
################################
# Validators
################################

View File

@ -61,7 +61,6 @@ use constant DB_COLUMNS => qw(
votesperuser
maxvotesperbug
votestoconfirm
defaultmilestone
allows_unconfirmed
cc_group
);
@ -83,7 +82,6 @@ use constant UPDATE_COLUMNS => qw(
votesperuser
maxvotesperbug
votestoconfirm
defaultmilestone
allows_unconfirmed
cc_group
);
@ -94,7 +92,6 @@ use constant VALIDATORS => {
name => \&_check_name,
description => \&_check_description,
version => \&_check_version,
defaultmilestone => \&_check_default_milestone,
isactive => \&Bugzilla::Object::check_boolean,
votesperuser => \&_check_votes_per_user,
maxvotesperbug => \&_check_votes_per_bug,
@ -196,23 +193,6 @@ sub update
# FIXME when renaming a product, try to rename it in all named queries
# Update is_default for milestone in fieldvaluecontrol
if ($changes->{defaultmilestone})
{
Bugzilla->get_field('target_milestone')->update_default_value(
$self->id, [ $changes->{defaultmilestone}->[1] || () ]
);
}
# Convert default milestone to name
if ($changes->{defaultmilestone})
{
$changes->{defaultmilestone} = [
$changes->{defaultmilestone}->[0] ? Bugzilla::Milestone->new($changes->{defaultmilestone}->[0])->name : '',
$changes->{defaultmilestone}->[1] ? Bugzilla::Milestone->new($changes->{defaultmilestone}->[1])->name : '',
];
}
# We also have to fix votes.
if ($changes->{maxvotesperbug} || $changes->{votesperuser} || $changes->{votestoconfirm})
{
@ -603,32 +583,6 @@ sub _check_version
return $version;
}
sub _check_default_milestone
{
my ($invocant, $milestone) = @_;
# Do not create milestones when creating a product
return undef unless ref $invocant;
# Do nothing if target milestones are not in use
return $invocant->default_milestone if !Bugzilla->get_field('target_milestone')->enabled;
$milestone = trim($milestone) || undef;
if ($milestone)
{
# The default milestone must be one of the existing milestones.
my $mil_obj = new Bugzilla::Milestone({ name => $milestone, product => $invocant });
$mil_obj || ThrowUserError('product_must_define_defaultmilestone', {
product => $invocant->name,
milestone => $milestone,
});
$milestone = $mil_obj->id;
}
delete $invocant->{default_milestone_obj};
return $milestone;
}
sub _check_votes_per_user
{
return _check_votes(@_, 0);
@ -746,13 +700,6 @@ sub set_votes_to_confirm { $_[0]->set('votestoconfirm', $_[1]); }
sub set_allows_unconfirmed { $_[0]->set('allows_unconfirmed', $_[1]); }
sub set_classification { $_[0]->set('classification_id', $_[1]); }
sub set_default_milestone
{
my ($self, $m) = @_;
$self->set('defaultmilestone', $m);
delete $self->{default_milestone_obj};
}
sub set_cc_group
{
my ($self, $g) = @_;
@ -1085,7 +1032,6 @@ sub is_active { return $_[0]->{isactive}; }
sub votes_per_user { return $_[0]->{votesperuser}; }
sub max_votes_per_bug { return $_[0]->{maxvotesperbug}; }
sub votes_to_confirm { return $_[0]->{votestoconfirm}; }
sub default_milestone { return $_[0]->{defaultmilestone}; }
sub classification_id { return $_[0]->{classification_id}; }
sub wiki_url { return $_[0]->{wiki_url}; }
sub notimetracking { return $_[0]->{notimetracking}; }
@ -1096,16 +1042,6 @@ sub cc_group { return $_[0]->{cc_group}; }
#### Subroutines ######
###############################
sub default_milestone_obj
{
my $self = shift;
if (!exists $self->{default_milestone_obj} && $self->default_milestone)
{
$self->{default_milestone_obj} = Bugzilla::Milestone->new($self->default_milestone);
}
return $self->{default_milestone_obj};
}
sub classification_obj
{
my $self = shift;
@ -1225,7 +1161,6 @@ Bugzilla::Product - Bugzilla product class.
my $votestoconfirm = $product->votes_to_confirm;
my $wiki_url = $product->wiki_url;
my $notimetracking = $product->notimetracking;
my $defaultmilestone = $product->default_milestone;
my $classificationid = $product->classification_id;
my $allows_unconfirmed = $product->allows_unconfirmed;

View File

@ -136,6 +136,7 @@ elsif ($action eq 'update')
}
if ($field->can_tweak('default_field_id'))
{
# FIXME Disallow to change default field if it will lead to losing all the default values
$field->set_default_field($cgi->param('default_field_id'));
}
for (

View File

@ -140,10 +140,6 @@ if ($action eq 'del') {
$vars->{'milestone'} = $milestone;
$vars->{'product'} = $product;
# The default milestone cannot be deleted.
if ($product->default_milestone eq $milestone->name) {
ThrowUserError("milestone_is_default", { milestone => $milestone });
}
$vars->{'token'} = issue_session_token('delete_milestone');
$template->process("admin/milestones/confirm-delete.html.tmpl", $vars)

View File

@ -310,7 +310,6 @@ if ($action eq 'update')
$product->set_extproduct(scalar $cgi->param('extproduct'));
$product->set_cc_group(scalar $cgi->param('cc_group') || '');
$product->set_description(scalar $cgi->param('description'));
$product->set_default_milestone(scalar $cgi->param('defaultmilestone'));
$product->set_is_active(scalar $cgi->param('is_active'));
if (Bugzilla->get_field('votes')->enabled)
{

View File

@ -454,18 +454,7 @@ elsif (defined $vercookie && grep { $_ eq $vercookie } @{$vars->{version}})
$default{version} = $vercookie;
}
# Get list of milestones.
if (Bugzilla->get_field('target_milestone')->enabled)
{
if ($ARGS->{target_milestone})
{
$default{target_milestone} = $ARGS->{target_milestone};
}
else
{
$default{target_milestone} = $product->default_milestone && $product->default_milestone_obj->name;
}
}
$default{target_milestone} = $ARGS->{target_milestone};
# Construct the list of allowable statuses.
my $initial_statuses = Bugzilla::Status->can_change_to();

View File

@ -170,7 +170,6 @@ my @products = (
description => "used by Selenium test.. DON'T DELETE",
versions => ['unspecified', 'QAVersion'],
milestones => ['QAMilestone'],
defaultmilestone => '---',
components => [
{ name => "QA-Selenium-TEST",
description => "used by Selenium test.. DON'T DELETE",
@ -187,7 +186,6 @@ my @products = (
"Alternate product used by Selenium. <b>Do not edit!</b>",
versions => ['unspecified', 'Another1', 'Another2'],
milestones => ['AnotherMS1', 'AnotherMS2', 'Milestone'],
defaultmilestone => '---',
components => [
{ name => "c1",
@ -213,7 +211,6 @@ my @products = (
classification => 'Class2_QA',
versions => ['unspecified', 'C2Ver'],
milestones => ['C2Mil'],
defaultmilestone => '---',
components => [
{ name => "Helium",
description => "Feel free to add bugs to me",
@ -229,7 +226,6 @@ my @products = (
description => 'Only the QA group may enter bugs here.',
versions => ['unspecified'],
milestones => [],
defaultmilestone => '---',
components => [
{ name => "c1",
description => "Same name as Another Product's component",
@ -244,7 +240,6 @@ my @products = (
description => 'Only the QA group may search for bugs here.',
versions => ['unspecified'],
milestones => [],
defaultmilestone => '---',
components => [
{ name => "c1",
description => "Still same name as the Another component",
@ -271,9 +266,6 @@ for my $product (@products) {
$new_product
= new Bugzilla::Product( { name => $product->{product_name} } );
$dbh->do( 'INSERT INTO milestones (product_id, value) VALUES (?, ?)',
undef, ( $new_product->id, $product->{defaultmilestone} ) );
# Now clear the internal list of accessible products.
delete Bugzilla->user->{selectable_products};

View File

@ -44,7 +44,6 @@ $sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Add Product");
$sel->type_ok("product", "Kill me!");
$sel->type_ok("description", "I will disappear very soon. Do not add bugs to it.");
$sel->type_ok("defaultmilestone", "0.1a");
$sel->click_ok("allows_unconfirmed");
$sel->type_ok("votesperuser", "1");
$sel->type_ok("maxvotesperbug", "1");
@ -159,7 +158,6 @@ my $bug1_id = $sel->get_value("//input[\@name='id' and \@type='hidden']");
edit_product($sel, "Kill me!");
$sel->type_ok("product", "Kill me nicely");
$sel->type_ok("description", "I will disappear very soon. Do not add bugs to it (except for testing).");
$sel->select_ok("defaultmilestone", "label=0.2");
$sel->type_ok("votesperuser", "2");
$sel->type_ok("maxvotesperbug", 5);
$sel->type_ok("votestoconfirm", "0");
@ -168,7 +166,6 @@ $sel->wait_for_page_to_load_ok(WAIT_TIME);
$sel->title_is("Updating Product 'Kill me nicely'");
$sel->is_text_present_ok("Updated product name from 'Kill me!' to 'Kill me nicely'");
$sel->is_text_present_ok("Updated description");
$sel->is_text_present_ok("Updated default milestone");
$sel->is_text_present_ok("Updated votes per user");
$sel->is_text_present_ok("Updated maximum votes per bug");
$sel->is_text_present_ok("Updated number of votes needed to confirm a bug");

View File

@ -655,8 +655,7 @@ DoubleCrossCheck("versions", "product_id", "id",
["bugs", "product_id", "version", "bug_id"]);
DoubleCrossCheck("milestones", "product_id", "id",
["bugs", "product_id", "target_milestone", "bug_id"],
["products", "id", "defaultmilestone", "name"]);
["bugs", "product_id", "target_milestone", "bug_id"]);
###########################################################################
# Perform login checks

View File

@ -98,8 +98,8 @@
[% SET any_field = 0 %]
[% FOR f = Bugzilla.get_fields({ obsolete => 0, default_field_id => this_field.id, sort => 1 }) %]
[%# FIXME: default version is hardcoded to depend on component, default milestone is hardcoded to depend on product %]
[% IF f.name != 'version' && f.name != 'target_milestone' && (f.visibility_field_id != f.default_field_id || f.has_visibility_value(this_value_id)) %]
[%# FIXME: default version is hardcoded to depend on component %]
[% IF f.name != 'version' && (f.visibility_field_id != f.default_field_id || f.has_visibility_value(this_value_id)) %]
[% IF NOT any_field %]
<tr>
<th align="left" valign="top">

View File

@ -63,25 +63,22 @@
</table>
<h2>Confirmation</h2>
[% IF milestone.bug_count %]
<table border="0" cellpadding="20" width="70%" bgcolor="red">
<tr><td>
There
[% IF milestone.bug_count > 1 %]
are [% milestone.bug_count FILTER none %] [%+ terms.bugs %]
You can't delete this milestone, because there
[% IF milestone.bug_count > 1 %]
are [% milestone.bug_count FILTER none %] [%+ terms.bugs %]
[% ELSE %]
is 1 [% terms.bug %]
[% END %]
entered for this milestone! When you delete this milestone,
<b><blink>ALL</blink></b> of these [% terms.bugs %] will be retargeted
to "[% product.default_milestone_obj.name FILTER html %]", the default milestone for
the [% product.name FILTER html %] product.
targetted to it.
</td></tr>
</table>
[% END %]
[% ELSE %]
<p>Do you really want to delete this milestone?<p>
@ -93,6 +90,8 @@
<input type="hidden" name="token" value="[% token FILTER html %]">
</form>
[% END %]
[% PROCESS admin/milestones/footer.html.tmpl %]
[% PROCESS global/footer.html.tmpl %]
[% PROCESS global/footer.html.tmpl %]

View File

@ -77,15 +77,6 @@
})
%]
[%# We want to override the usual 'Delete' link for the default milestone %]
[% overrides.action.name.${product.default_milestone_obj.name} = {
override_content => 1
content => "(Default milestone)"
override_contentlink => 1
contentlink => undef
}
%]
[% Hook.process('before_table') %]
[% PROCESS admin/table.html.tmpl
@ -94,7 +85,7 @@
overrides = overrides
%]
[% IF ! showbugcounts %]
[% IF !showbugcounts %]
<p><a href="editmilestones.cgi?product=[% product.name FILTER url_quote %]&amp;showbugcounts=1">
Redisplay table with [% terms.bug %] counts (slower)</a></p>

View File

@ -125,17 +125,3 @@
</td>
</tr>
[% END %]
[% IF Bugzilla.get_field('target_milestone').enabled && product.milestones.size -%]
<tr>
<th align="left"><label for="defaultmilestone">Default milestone:</label></th>
<td>
<select name="defaultmilestone" id="defaultmilestone">
<option value="">---</option>
[% FOREACH m = product.milestones %]
<option value="[% m.name | html %]" [% " selected=\"selected\"" IF m.id == product.defaultmilestone %]>[%- m.name | html -%]</option>
[% END %]
</select>
</td>
</tr>
[% END %]

View File

@ -62,20 +62,7 @@
[% IF changes.isactive.defined %]
<p>
Product is now
[% IF product.is_active %]
open for
[% ELSE %]
closed to
[% END %]
new [% terms.bugs %].
</p>
[% END %]
[% IF changes.defaultmilestone.defined %]
<p>
Updated default milestone from '[% changes.defaultmilestone.0 FILTER html %]' to
'[% changes.defaultmilestone.1 FILTER html %]'.
Product is now [% product.is_active ? 'open' : 'closed' %] for new [% terms.bugs %].
</p>
[% END %]

View File

@ -678,10 +678,6 @@
[% BLOCK msg_milestone_deleted %]
[% title = "Milestone Deleted" %]
The milestone <em>[% milestone.name | html %]</em> has been deleted.
[% IF milestone.bug_count %]
[%+ terms.Bugs %] targetted to this milestone have been retargetted to
the default milestone <em>"[% product.default_milestone_obj.name | html %]"</em>.
[% END %]
[% END %]
[% BLOCK msg_milestone_updated %]

View File

@ -1244,15 +1244,6 @@
You must enter a name for this milestone.
[% END %]
[% BLOCK error_milestone_is_default %]
[% title = "Default milestone not deletable" %]
[% admindocslinks = {'products.html' => 'Administering products',
'milestones.html' => 'About Milestones'} %]
Sorry, but [% milestone.name FILTER html %] is the default milestone
for the '[% milestone.product.name FILTER html %]' product, and so
it cannot be deleted.
[% END %]
[% BLOCK error_milestone_name_too_long %]
[% title = "Milestone Name Is Too Long" %]
The name of a milestone is limited to [% constants.MAX_MILESTONE_SIZE FILTER html %]
@ -1619,15 +1610,6 @@
characters. '[% name FILTER html %]' is too long ([% name.length %] characters).
[% END %]
[% BLOCK error_product_must_define_defaultmilestone %]
[% title = "Must define new default milestone" %]
[% admindocslinks = {'products.html' => 'Administering products',
'milestones.html' => 'About Milestones'} %]
You must <a href="editmilestones.cgi?action=add&amp;product=[% product FILTER url_quote %]">
create the milestone '[% milestone FILTER html %]'</a> before
it can be made the default milestone for product '[% product FILTER html %]'.
[% END %]
[% BLOCK error_product_admin_denied %]
[% title = "Product Access Denied" %]
You are not allowed to edit properties of product '[% product FILTER html %]'.