Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
bugzilla
Commits
88d26275
Commit
88d26275
authored
Aug 21, 2004
by
bugreport%peshkin.net
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 224208 Add a higher level of categorization (.ie departments, locations, etc.)
patch by Albert Ting r=joel, glob a=myk
parent
2f9f28d0
Hide whitespace changes
Inline
Side-by-side
Showing
38 changed files
with
1607 additions
and
103 deletions
+1607
-103
Bug.pm
Bugzilla/Bug.pm
+7
-3
Search.pm
Bugzilla/Search.pm
+16
-1
buglist.cgi
buglist.cgi
+6
-0
bugzilla.dtd
bugzilla.dtd
+3
-1
checksetup.pl
checksetup.pl
+19
-0
colchange.cgi
colchange.cgi
+7
-2
defparams.pl
defparams.pl
+17
-0
editclassifications.cgi
editclassifications.cgi
+391
-0
editproducts.cgi
editproducts.cgi
+193
-32
enter_bug.cgi
enter_bug.cgi
+53
-4
globals.pl
globals.pl
+85
-4
productform.js
js/productform.js
+75
-1
long_list.cgi
long_list.cgi
+6
-3
query.cgi
query.cgi
+20
-3
report.cgi
report.cgi
+7
-1
add.html.tmpl
template/en/default/admin/classifications/add.html.tmpl
+45
-0
del.html.tmpl
template/en/default/admin/classifications/del.html.tmpl
+60
-0
delete.html.tmpl
template/en/default/admin/classifications/delete.html.tmpl
+31
-0
edit.html.tmpl
template/en/default/admin/classifications/edit.html.tmpl
+70
-0
new.html.tmpl
template/en/default/admin/classifications/new.html.tmpl
+32
-0
reclassify.html.tmpl
...ate/en/default/admin/classifications/reclassify.html.tmpl
+84
-0
select.html.tmpl
template/en/default/admin/classifications/select.html.tmpl
+70
-0
update.html.tmpl
template/en/default/admin/classifications/update.html.tmpl
+37
-0
edit.html.tmpl
...ate/en/default/admin/products/groupcontrol/edit.html.tmpl
+2
-0
edit.html.tmpl
template/en/default/bug/edit.html.tmpl
+5
-0
show-multiple.html.tmpl
template/en/default/bug/show-multiple.html.tmpl
+8
-2
filterexceptions.pl
template/en/default/filterexceptions.pl
+1
-0
choose-classification.html.tmpl
template/en/default/global/choose-classification.html.tmpl
+65
-0
field-descs.none.tmpl
template/en/default/global/field-descs.none.tmpl
+1
-0
useful-links.html.tmpl
template/en/default/global/useful-links.html.tmpl
+10
-1
user-error.html.tmpl
template/en/default/global/user-error.html.tmpl
+38
-0
form.html.tmpl
template/en/default/search/form.html.tmpl
+102
-4
search-advanced.html.tmpl
template/en/default/search/search-advanced.html.tmpl
+2
-33
search-help.html.tmpl
template/en/default/search/search-help.html.tmpl
+6
-1
search-report-graph.html.tmpl
template/en/default/search/search-report-graph.html.tmpl
+7
-1
search-report-select.html.tmpl
template/en/default/search/search-report-select.html.tmpl
+1
-1
search-report-table.html.tmpl
template/en/default/search/search-report-table.html.tmpl
+7
-1
search-specific.html.tmpl
template/en/default/search/search-specific.html.tmpl
+18
-4
No files found.
Bugzilla/Bug.pm
View file @
88d26275
...
...
@@ -48,6 +48,7 @@ sub fields {
# Keep this ordering in sync with bugzilla.dtd
my
@fields
=
qw(bug_id alias creation_ts short_desc delta_ts
reporter_accessible cclist_accessible
classification_id classification
product component version rep_platform op_sys
bug_status resolution
bug_file_loc status_whiteboard keywords
...
...
@@ -137,7 +138,8 @@ sub initBug {
my
$query
=
"
SELECT
bugs.bug_id, alias, bugs.product_id, products.name, version,
bugs.bug_id, alias, products.classification_id, classifications.name,
bugs.product_id, products.name, version,
rep_platform, op_sys, bug_status, resolution, priority,
bug_severity, bugs.component_id, components.name, assigned_to,
reporter, bug_file_loc, short_desc, target_milestone,
...
...
@@ -147,8 +149,9 @@ sub initBug {
reporter_accessible, cclist_accessible,
estimated_time, remaining_time
from bugs left join votes using(bug_id),
products, components
classifications,
products, components
where bugs.bug_id = $bug_id
AND classifications.id = products.classification_id
AND products.id = bugs.product_id
AND components.id = bugs.component_id
group by bugs.bug_id"
;
...
...
@@ -159,7 +162,8 @@ sub initBug {
if
((
@row
=
&::
FetchSQLData
())
&&
$self
->
{
'who'
}
->
can_see_bug
(
$bug_id
))
{
my
$count
=
0
;
my
%
fields
;
foreach
my
$field
(
"bug_id"
,
"alias"
,
"product_id"
,
"product"
,
"version"
,
foreach
my
$field
(
"bug_id"
,
"alias"
,
"classification_id"
,
"classification"
,
"product_id"
,
"product"
,
"version"
,
"rep_platform"
,
"op_sys"
,
"bug_status"
,
"resolution"
,
"priority"
,
"bug_severity"
,
"component_id"
,
"component"
,
"assigned_to"
,
"reporter"
,
"bug_file_loc"
,
"short_desc"
,
...
...
Bugzilla/Search.pm
View file @
88d26275
...
...
@@ -96,6 +96,11 @@ sub init {
push
@wherepart
,
"bugs.product_id = map_products.id"
;
}
if
(
lsearch
(
$fieldsref
,
'map_classifications.name'
)
>=
0
)
{
push
@supptables
,
"classifications AS map_classifications"
;
push
@wherepart
,
"map_products.classification_id = map_classifications.id"
;
}
if
(
lsearch
(
$fieldsref
,
'map_components.name'
)
>=
0
)
{
push
@supptables
,
"components AS map_components"
;
push
@wherepart
,
"bugs.component_id = map_components.id"
;
...
...
@@ -152,7 +157,7 @@ sub init {
my
@legal_fields
=
(
"product"
,
"version"
,
"rep_platform"
,
"op_sys"
,
"bug_status"
,
"resolution"
,
"priority"
,
"bug_severity"
,
"assigned_to"
,
"reporter"
,
"component"
,
"assigned_to"
,
"reporter"
,
"component"
,
"classification"
,
"target_milestone"
,
"bug_group"
);
foreach
my
$field
(
$params
->
param
())
{
...
...
@@ -761,6 +766,16 @@ sub init {
$term
);
},
"^classification,(?!changed)"
=>
sub
{
# Generate the restriction condition
$f
=
$ff
=
"classifications.name"
;
$funcsbykey
{
",$t"
}
->
();
$term
=
build_subselect
(
"map_products.classification_id"
,
"classifications.id"
,
"classifications"
,
$term
);
},
"^keywords,"
=>
sub
{
&::
GetVersionTable
();
my
@list
;
...
...
buglist.cgi
View file @
88d26275
...
...
@@ -458,6 +458,7 @@ DefineColumn("short_desc" , "bugs.short_desc" , "Summary"
DefineColumn
(
"status_whiteboard"
,
"bugs.status_whiteboard"
,
"Status Summary"
);
DefineColumn
(
"component"
,
"map_components.name"
,
"Component"
);
DefineColumn
(
"product"
,
"map_products.name"
,
"Product"
);
DefineColumn
(
"classification"
,
"map_classifications.name"
,
"Classification"
);
DefineColumn
(
"version"
,
"bugs.version"
,
"Version"
);
DefineColumn
(
"op_sys"
,
"bugs.op_sys"
,
"OS"
);
DefineColumn
(
"target_milestone"
,
"bugs.target_milestone"
,
"Target Milestone"
);
...
...
@@ -554,6 +555,11 @@ if (grep('relevance', @displaycolumns) && !$fulltext) {
my
@selectcolumns
=
(
"bug_id"
,
"bug_severity"
,
"priority"
,
"bug_status"
,
"resolution"
);
# if using classification, we also need to look in product.classification_id
if
(
Param
(
"useclassification"
))
{
push
(
@selectcolumns
,
"product"
);
}
# remaining and actual_time are required for precentage_complete calculation:
if
(
lsearch
(
\
@displaycolumns
,
"percentage_complete"
)
>=
0
)
{
push
(
@selectcolumns
,
"remaining_time"
);
...
...
bugzilla.dtd
View file @
88d26275
...
...
@@ -5,7 +5,7 @@
maintainer CDATA #REQUIRED
exporter CDATA #IMPLIED
>
<!ELEMENT bug (bug_id, (alias?, creation_ts, short_desc, delta_ts, reporter_accessible, cclist_accessible, product, component, version, rep_platform, op_sys, bug_status, resolution?, bug_file_loc?, status_whiteboard?, keywords*, priority, bug_severity, target_milestone?, dependson*, blocked*, votes?, reporter, assigned_to, qa_contact?, cc*, (estimated_time, remaining_time, actual_time)?, groups*, long_desc*, attachment*)?)>
<!ELEMENT bug (bug_id, (alias?, creation_ts, short_desc, delta_ts, reporter_accessible, cclist_accessible,
classification_id, classification,
product, component, version, rep_platform, op_sys, bug_status, resolution?, bug_file_loc?, status_whiteboard?, keywords*, priority, bug_severity, target_milestone?, dependson*, blocked*, votes?, reporter, assigned_to, qa_contact?, cc*, (estimated_time, remaining_time, actual_time)?, groups*, long_desc*, attachment*)?)>
<!ATTLIST bug
error (NotFound | NotPermitted | InvalidBugId) #IMPLIED
>
...
...
@@ -16,6 +16,8 @@
<!ELEMENT exporter (#PCDATA)>
<!ELEMENT urlbase (#PCDATA)>
<!ELEMENT bug_status (#PCDATA)>
<!ELEMENT classification_id (#PCDATA)>
<!ELEMENT classification (#PCDATA)>
<!ELEMENT product (#PCDATA)>
<!ELEMENT priority (#PCDATA)>
<!ELEMENT version (#PCDATA)>
...
...
checksetup.pl
View file @
88d26275
...
...
@@ -1786,10 +1786,17 @@ $table{logincookies} =
index(lastused)'
;
$table
{
classifications
}
=
'id smallint not null auto_increment primary key,
name varchar(64) not null,
description mediumtext,
unique(name)'
;
$table
{
products
}
=
'id smallint not null auto_increment primary key,
name varchar(64) not null,
classification_id smallint not null default 1,
description mediumtext,
milestoneurl tinytext not null,
disallownew tinyint not null,
...
...
@@ -2153,6 +2160,7 @@ sub AddFDef ($$$) {
# be created with their associated schema change.
AddFDef
(
"bug_id"
,
"Bug \#"
,
1
);
AddFDef
(
"short_desc"
,
"Summary"
,
1
);
AddFDef
(
"classification"
,
"Classification"
,
1
);
AddFDef
(
"product"
,
"Product"
,
1
);
AddFDef
(
"version"
,
"Version"
,
1
);
AddFDef
(
"rep_platform"
,
"Platform"
,
1
);
...
...
@@ -4021,6 +4029,7 @@ AddField("profiles", "extern_id", "varchar(64)");
AddGroup
(
'tweakparams'
,
'Can tweak operating parameters'
);
AddGroup
(
'editusers'
,
'Can edit or disable users'
);
AddGroup
(
'creategroups'
,
'Can create and destroy groups.'
);
AddGroup
(
'editclassifications'
,
'Can create, destroy, and edit classifications.'
);
AddGroup
(
'editcomponents'
,
'Can create, destroy, and edit components.'
);
AddGroup
(
'editkeywords'
,
'Can create, destroy, and edit keywords.'
);
AddGroup
(
'admin'
,
'Administrators'
);
...
...
@@ -4388,6 +4397,16 @@ if (GetFieldDef('bugs', 'short_desc')->[2]) { # if it allows nulls
$dbh
->
do
(
"UPDATE groups SET last_changed = NOW() WHERE name = 'admin'"
);
# 2003-10-24 - alt@sonic.net, bug 224208
# Support classification level and make sure there is a default classification
AddField
(
'products'
,
'classification_id'
,
'smallint DEFAULT 1'
);
$sth
=
$dbh
->
prepare
(
"SELECT name FROM classifications WHERE id=1"
);
$sth
->
execute
;
if
(
!
$sth
->
rows
)
{
$dbh
->
do
(
"INSERT INTO classifications (id,name,description) "
.
"VALUES(1,'Unclassified','Unassigned to any classifications')"
);
}
#
# Final checks...
...
...
colchange.cgi
View file @
88d26275
...
...
@@ -47,8 +47,13 @@ my $cgi = Bugzilla->cgi;
my
@masterlist
=
(
"opendate"
,
"changeddate"
,
"bug_severity"
,
"priority"
,
"rep_platform"
,
"assigned_to"
,
"assigned_to_realname"
,
"reporter"
,
"reporter_realname"
,
"bug_status"
,
"resolution"
,
"product"
,
"component"
,
"version"
,
"op_sys"
,
"votes"
);
"resolution"
);
if
(
Param
(
"useclassification"
))
{
push
(
@masterlist
,
"classification"
);
}
push
(
@masterlist
,
(
"product"
,
"component"
,
"version"
,
"op_sys"
,
"votes"
));
if
(
Param
(
"usebugaliases"
))
{
unshift
(
@masterlist
,
"alias"
);
...
...
defparams.pl
View file @
88d26275
...
...
@@ -321,6 +321,23 @@ sub find_languages {
},
{
name
=>
'useclassification'
,
desc
=>
'If this is on, Bugzilla will associate each product with a '
.
'specific classification. But you must have "editclassification" '
.
'permissions enabled in order to edit classifications'
,
type
=>
'b'
,
default
=>
0
},
{
name
=>
'showallproducts'
,
desc
=>
'If this is on and useclassification is set, Bugzilla will add a'
.
'"All" link in the "New Bug" page to list all available products'
,
type
=>
'b'
,
default
=>
0
},
{
name
=>
'makeproductgroups'
,
desc
=>
'If this is on, Bugzilla will associate a bug group with each '
.
'product in the database, and use it for querying bugs.'
,
...
...
editclassifications.cgi
0 → 100755
View file @
88d26275
#!/usr/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil; cperl-indent-level: 4 -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Albert Ting
#
# Contributor(s): Albert Ting <alt@sonic.net>
#
# Direct any questions on this source code to mozilla.org
use
strict
;
use
lib
"."
;
use
Bugzilla
;
use
Bugzilla::
Constants
;
require
"CGI.pl"
;
require
"globals.pl"
;
my
$cgi
=
Bugzilla
->
cgi
;
my
$dbh
=
Bugzilla
->
dbh
;
use
vars
qw ($template
$vars
);
# TestClassification: just returns if the specified classification does exists
# CheckClassification: same check, optionally emit an error text
sub
TestClassification
($)
{
my
$cl
=
shift
;
trick_taint
(
$cl
);
# does the classification exist?
my
$sth
=
$dbh
->
prepare
(
"SELECT name
FROM classifications
WHERE name=?"
);
$sth
->
execute
(
$cl
);
my
@row
=
$sth
->
fetchrow_array
();
return
$row
[
0
];
}
sub
CheckClassification
($)
{
my
$cl
=
shift
;
unless
(
$cl
)
{
ThrowUserError
(
"classification_not_specified"
);
}
if
(
!
TestClassification
(
$cl
))
{
ThrowUserError
(
"classification_doesnt_exist"
,
{
name
=>
$cl
});
}
}
sub
LoadTemplate
($)
{
my
$action
=
shift
;
$action
=~
/(\w+)/
;
$action
=
$1
;
print
$cgi
->
header
();
$template
->
process
(
"admin/classifications/$action.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
exit
;
}
#
# Preliminary checks:
#
Bugzilla
->
login
(
LOGIN_REQUIRED
);
print
$cgi
->
header
();
ThrowUserError
(
"auth_cant_edit_classifications"
)
unless
UserInGroup
(
"editclassifications"
);
ThrowUserError
(
"auth_classification_not_enabled"
)
unless
Param
(
"useclassification"
);
#
# often used variables
#
my
$action
=
trim
(
$cgi
->
param
(
'action'
)
||
''
);
my
$classification
=
trim
(
$cgi
->
param
(
'classification'
)
||
''
);
trick_taint
(
$classification
);
$vars
->
{
'classification'
}
=
$classification
;
#
# action='' -> Show nice list of classifications
#
unless
(
$action
)
{
my
@classifications
;
# left join is tricky
# - must select "classifications" fields if you want a REAL value
# - must use "count(products.classification_id)" if you want a true
# count. If you use count(classifications.id), it will return 1 for NULL
# - must use "group by classifications.id" instead of
# products.classification_id. Otherwise it won't look for all
# classification ids, just the ones used by the products.
my
$sth
=
$dbh
->
prepare
(
"SELECT classifications.id,classifications.name,
classifications.description,
COUNT(classification_id) as total
FROM classifications
LEFT JOIN products ON classifications.id=products.classification_id
GROUP BY classifications.id
ORDER BY name"
);
$sth
->
execute
();
while
(
my
(
$id
,
$classification
,
$description
,
$total
)
=
$sth
->
fetchrow_array
())
{
my
$cl
=
{};
$cl
->
{
'id'
}
=
$id
;
$cl
->
{
'classification'
}
=
$classification
;
$cl
->
{
'description'
}
=
$description
if
(
defined
$description
);
$cl
->
{
'total'
}
=
$total
;
push
(
@classifications
,
$cl
);
}
$vars
->
{
'classifications'
}
=
\
@classifications
;
LoadTemplate
(
"select"
);
}
#
# action='add' -> present form for parameters for new classification
#
# (next action will be 'new')
#
if
(
$action
eq
'add'
)
{
LoadTemplate
(
$action
);
}
#
# action='new' -> add classification entered in the 'action=add' screen
#
if
(
$action
eq
'new'
)
{
if
(
TestClassification
(
$classification
))
{
ThrowUserError
(
"classification_already_exists"
,
{
name
=>
$classification
});
}
my
$description
=
trim
(
$cgi
->
param
(
'description'
)
||
''
);
trick_taint
(
$description
);
# Add the new classification.
my
$sth
=
$dbh
->
prepare
(
"INSERT INTO classifications (name,description)
VALUES (?,?)"
);
$sth
->
execute
(
$classification
,
$description
);
# Make versioncache flush
unlink
"data/versioncache"
;
LoadTemplate
(
$action
);
}
#
# action='del' -> ask if user really wants to delete
#
# (next action would be 'delete')
#
if
(
$action
eq
'del'
)
{
CheckClassification
(
$classification
);
my
$sth
;
# display some data about the classification
$sth
=
$dbh
->
prepare
(
"SELECT id, description
FROM classifications
WHERE name=?"
);
$sth
->
execute
(
$classification
);
my
(
$classification_id
,
$description
)
=
$sth
->
fetchrow_array
();
ThrowUserError
(
"classification_not_deletable"
)
if
(
$classification_id
eq
"1"
);
$sth
=
$dbh
->
prepare
(
"SELECT name
FROM products
WHERE classification_id=$classification_id"
);
$sth
->
execute
();
ThrowUserError
(
"classification_has_products"
)
if
(
$sth
->
fetchrow_array
());
$vars
->
{
'description'
}
=
$description
if
(
defined
$description
);
LoadTemplate
(
$action
);
}
#
# action='delete' -> really delete the classification
#
if
(
$action
eq
'delete'
)
{
CheckClassification
(
$classification
);
my
$sth
;
my
$classification_id
=
get_classification_id
(
$classification
);
if
(
$classification_id
==
1
)
{
ThrowUserError
(
"cant_delete_default_classification"
,
{
name
=>
$classification
});
}
# lock the tables before we start to change everything:
$dbh
->
do
(
"LOCK TABLES classifications WRITE, products WRITE"
);
# delete
$sth
=
$dbh
->
prepare
(
"DELETE FROM classifications WHERE id=?"
);
$sth
->
execute
(
$classification_id
);
# update products just in case
$sth
=
$dbh
->
prepare
(
"UPDATE products
SET classification_id=1
WHERE classification_id=?"
);
$sth
->
execute
(
$classification_id
);
$dbh
->
do
(
"UNLOCK TABLES"
);
unlink
"data/versioncache"
;
LoadTemplate
(
$action
);
}
#
# action='edit' -> present the edit classifications from
#
# (next action would be 'update')
#
if
(
$action
eq
'edit'
)
{
CheckClassification
(
$classification
);
my
@products
=
();
my
$has_products
=
0
;
my
$sth
;
# get data of classification
$sth
=
$dbh
->
prepare
(
"SELECT id,description
FROM classifications
WHERE name=?"
);
$sth
->
execute
(
$classification
);
my
(
$classification_id
,
$description
)
=
$sth
->
fetchrow_array
();
$vars
->
{
'description'
}
=
$description
if
(
defined
$description
);
$sth
=
$dbh
->
prepare
(
"SELECT name,description
FROM products
WHERE classification_id=?
ORDER BY name"
);
$sth
->
execute
(
$classification_id
);
while
(
my
(
$product
,
$prod_description
)
=
$sth
->
fetchrow_array
())
{
my
$prod
=
{};
$has_products
=
1
;
$prod
->
{
'name'
}
=
$product
;
$prod
->
{
'description'
}
=
$prod_description
if
(
defined
$prod_description
);
push
(
@products
,
$prod
);
}
$vars
->
{
'products'
}
=
\
@products
if
(
$has_products
);
LoadTemplate
(
$action
);
}
#
# action='update' -> update the classification
#
if
(
$action
eq
'update'
)
{
my
$classificationold
=
trim
(
$cgi
->
param
(
'classificationold'
)
||
''
);
my
$description
=
trim
(
$cgi
->
param
(
'description'
)
||
''
);
my
$descriptionold
=
trim
(
$cgi
->
param
(
'descriptionold'
)
||
''
);
my
$checkvotes
=
0
;
my
$sth
;
CheckClassification
(
$classificationold
);
my
$classification_id
=
get_classification_id
(
$classificationold
);
trick_taint
(
$description
);
# Note that we got the $classification_id using $classificationold
# above so it will remain static even after we rename the
# classification in the database.
$dbh
->
do
(
"LOCK TABLES classifications WRITE"
);
if
(
$description
ne
$descriptionold
)
{
$sth
=
$dbh
->
prepare
(
"UPDATE classifications
SET description=?
WHERE id=?"
);
$sth
->
execute
(
$description
,
$classification_id
);
$vars
->
{
'updated_description'
}
=
1
;
}
if
(
$classification
ne
$classificationold
)
{
unless
(
$classification
)
{
$dbh
->
do
(
"UNLOCK TABLES"
);
ThrowUserError
(
"classification_not_specified"
)
}
if
(
TestClassification
(
$classification
))
{
$dbh
->
do
(
"UNLOCK TABLES"
);
ThrowUserError
(
"classification_already_exists"
,
{
name
=>
$classification
});
}
$sth
=
$dbh
->
prepare
(
"UPDATE classifications
SET name=? WHERE id=?"
);
$sth
->
execute
(
$classification
,
$classification_id
);
$vars
->
{
'updated_classification'
}
=
1
;
}
$dbh
->
do
(
"UNLOCK TABLES"
);
unlink
"data/versioncache"
;
LoadTemplate
(
$action
);
}
#
# action='reclassify' -> reclassify products for the classification
#
if
(
$action
eq
'reclassify'
)
{
CheckClassification
(
$classification
);
my
$sth
;
# display some data about the classification
$sth
=
$dbh
->
prepare
(
"SELECT id, description
FROM classifications
WHERE name=?"
);
$sth
->
execute
(
$classification
);
my
(
$classification_id
,
$description
)
=
$sth
->
fetchrow_array
();
$vars
->
{
'description'
}
=
$description
if
(
defined
$description
);
$sth
=
$dbh
->
prepare
(
"UPDATE products
SET classification_id=?
WHERE name=?"
);
if
(
defined
$cgi
->
param
(
'add_products'
))
{
if
(
defined
$cgi
->
param
(
'prodlist'
))
{
foreach
my
$prod
(
$cgi
->
param
(
"prodlist"
))
{
trick_taint
(
$prod
);
$sth
->
execute
(
$classification_id
,
$prod
);
}
}
}
elsif
(
defined
$cgi
->
param
(
'remove_products'
))
{
if
(
defined
$cgi
->
param
(
'myprodlist'
))
{
foreach
my
$prod
(
$cgi
->
param
(
"myprodlist"
))
{
trick_taint
(
$prod
);
$sth
->
execute
(
1
,
$prod
);
}
}
}
elsif
(
defined
$cgi
->
param
(
'migrate_products'
))
{
if
(
defined
$cgi
->
param
(
'clprodlist'
))
{
foreach
my
$prod
(
$cgi
->
param
(
"clprodlist"
))
{
trick_taint
(
$prod
);
$sth
->
execute
(
$classification_id
,
$prod
);
}
}
}
my
@selected_products
=
();
my
@class_products
=
();
$sth
=
$dbh
->
prepare
(
"SELECT classifications.id,
products.name,
classifications.name,
classifications.id > 1 as unknown
FROM products,classifications
WHERE classifications.id=products.classification_id
ORDER BY unknown, products.name, classifications.name"
);
$sth
->
execute
();
while
(
my
(
$clid
,
$name
,
$clname
)
=
$sth
->
fetchrow_array
()
)
{
if
(
$clid
==
$classification_id
)
{
push
(
@selected_products
,
$name
);
}
else
{
my
$cl
=
{};
if
(
$clid
==
1
)
{
$cl
->
{
'name'
}
=
"[$clname] $name"
;
}
else
{
$cl
->
{
'name'
}
=
"$name [$clname]"
;
}
$cl
->
{
'value'
}
=
$name
;
push
(
@class_products
,
$cl
);
}
}
$vars
->
{
'selected_products'
}
=
\
@selected_products
;
$vars
->
{
'class_products'
}
=
\
@class_products
;
LoadTemplate
(
$action
);
}
#
# No valid action found
#
ThrowCodeError
(
"action_unrecognized"
,
$vars
);
editproducts.cgi
View file @
88d26275
...
...
@@ -86,20 +86,80 @@ sub CheckProduct ($)
}
}
# TestClassification: just returns if the specified classification does exists
# CheckClassification: same check, optionally emit an error text
sub
TestClassification
($)
{
my
$cl
=
shift
;
# does the classification exist?
SendSQL
(
"SELECT name
FROM classifications
WHERE name="
.
SqlQuote
(
$cl
));
return
FetchOneColumn
();
}
sub
CheckClassification
($)
{
my
$cl
=
shift
;
# do we have a classification?
unless
(
$cl
)
{
print
"Sorry, you haven't specified a classification."
;
PutTrailer
();
exit
;
}
unless
(
TestClassification
$cl
)
{
print
"Sorry, classification '$cl' does not exist."
;
PutTrailer
();
exit
;
}
}
sub
CheckClassificationProduct
($$)
{
my
$cl
=
shift
;
my
$prod
=
shift
;
CheckClassification
(
$cl
);
CheckProduct
(
$prod
);
# does the classification exist?
SendSQL
(
"SELECT products.name
FROM products,classifications
WHERE products.name="
.
SqlQuote
(
$prod
)
.
" AND classifications.name="
.
SqlQuote
(
$cl
));
my
$res
=
FetchOneColumn
();
unless
(
$res
)
{
print
"Sorry, classification->product '$cl'->'$prod' does not exist."
;
PutTrailer
();
exit
;
}
}
#
# Displays the form to edit a products parameters
#
sub
EmitFormElements
($$$$$$$$)
sub
EmitFormElements
($$$$$$$$
$
)
{
my
(
$product
,
$description
,
$milestoneurl
,
$disallownew
,
my
(
$
classification
,
$
product
,
$description
,
$milestoneurl
,
$disallownew
,
$votesperuser
,
$maxvotesperbug
,
$votestoconfirm
,
$defaultmilestone
)
=
@_
;
$product
=
value_quote
(
$product
);
$description
=
value_quote
(
$description
);
if
(
Param
(
'useclassification'
))
{
print
" <TH ALIGN=\"right\">Classification:</TH>\n"
;
print
" <TD><b>"
,
html_quote
(
$classification
),
"</b></TD>\n"
;
print
"</TR><TR>\n"
;
}
print
" <TH ALIGN=\"right\">Product:</TH>\n"
;
print
" <TD><INPUT SIZE=64 MAXLENGTH=64 NAME=\"product\" VALUE=\"$product\"></TD>\n"
;
print
"</TR><TR>\n"
;
...
...
@@ -197,23 +257,83 @@ unless (UserInGroup("editcomponents")) {
#
# often used variables
#
my
$classification
=
trim
(
$::FORM
{
classification
}
||
''
);
my
$product
=
trim
(
$::FORM
{
product
}
||
''
);
my
$action
=
trim
(
$::FORM
{
action
}
||
''
);
my
$headerdone
=
0
;
my
$localtrailer
=
"<A HREF=\"editproducts.cgi\">edit</A> more products"
;
my
$classhtmlvarstart
=
""
;
my
$classhtmlvar
=
""
;
if
(
Param
(
'useclassification'
)
&&
(
defined
$classification
))
{
$classhtmlvar
=
"&classification="
.
url_quote
(
$classification
);
$classhtmlvarstart
=
"?classification="
.
url_quote
(
$classification
);
}
if
(
Param
(
'useclassification'
)
&&
(
defined
$classification
))
{
$localtrailer
.=
", <A HREF=\"editproducts.cgi"
.
$classhtmlvarstart
.
"\">edit</A> in this classification"
;
}
#
# product = '' -> Show nice list of products
#
if
(
Param
(
'useclassification'
))
{
unless
(
$classification
)
{
PutHeader
(
"Select classification"
);
SendSQL
(
"SELECT classifications.name,classifications.description,COUNT(classification_id) as total
FROM classifications
LEFT JOIN products ON classifications.id=products.classification_id
GROUP BY classifications.id
ORDER BY name"
);
print
"<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0><TR BGCOLOR=\"#6666FF\">\n"
;
print
" <TH ALIGN=\"left\">Edit products of ...</TH>\n"
;
print
" <TH ALIGN=\"left\">Description</TH>\n"
;
print
" <TH ALIGN=\"left\">Total</TH>\n"
;
print
"</TR>"
;
while
(
MoreSQLData
()
)
{
my
(
$classification
,
$description
,
$count
)
=
FetchSQLData
();
$description
||=
"<FONT COLOR=\"red\">missing</FONT>"
;
print
"<TR>\n"
;
print
" <TD VALIGN=\"top\"><A HREF=\"editproducts.cgi?classification="
,
url_quote
(
$classification
),
"\"><B>$classification</B></A></TD>\n"
;
print
" <TD VALIGN=\"top\">$description</TD>\n"
;
$count
||=
"none"
;
print
" <TD VALIGN=\"top\">$count</TD>\n"
;
}
print
"</TR></TABLE>\n"
;
PutTrailer
();
exit
;
}
}
#
# action='' -> Show nice list of products
#
unless
(
$action
)
{
PutHeader
(
"Select product"
);
if
(
Param
(
'useclassification'
))
{
PutHeader
(
"Select product in "
.
$classification
);
}
else
{
PutHeader
(
"Select product"
);
}
SendSQL
(
"SELECT products.name,
description,disallownew,
my
$query
=
"SELECT products.name,products.
description,disallownew,
votesperuser,maxvotesperbug,votestoconfirm,COUNT(bug_id)
FROM products LEFT JOIN bugs ON products.id = bugs.product_id
GROUP BY products.name
ORDER BY products.name"
);
FROM products"
;
if
(
Param
(
'useclassification'
))
{
$query
.=
",classifications"
;
}
$query
.=
" LEFT JOIN bugs ON products.id = bugs.product_id"
;
if
(
Param
(
'useclassification'
))
{
$query
.=
" WHERE classifications.name="
.
SqlQuote
(
$classification
)
.
" AND classifications.id=products.classification_id"
;
}
$query
.=
" GROUP BY products.name ORDER BY products.name"
;
SendSQL
(
$query
);
print
"<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0><TR BGCOLOR=\"#6666FF\">\n"
;
print
" <TH ALIGN=\"left\">Edit product ...</TH>\n"
;
print
" <TH ALIGN=\"left\">Description</TH>\n"
;
...
...
@@ -231,19 +351,19 @@ unless ($action) {
$disallownew
=
$disallownew
?
'closed'
:
'open'
;
$bugs
||=
'none'
;
print
"<TR>\n"
;
print
" <TD VALIGN=\"top\"><A HREF=\"editproducts.cgi?action=edit&product="
,
url_quote
(
$product
),
"\"><B>$product</B></A></TD>\n"
;
print
" <TD VALIGN=\"top\"><A HREF=\"editproducts.cgi?action=edit&product="
,
url_quote
(
$product
),
$classhtmlvar
,
"\"><B>$product</B></A></TD>\n"
;
print
" <TD VALIGN=\"top\">$description</TD>\n"
;
print
" <TD VALIGN=\"top\">$disallownew</TD>\n"
;
print
" <TD VALIGN=\"top\" ALIGN=\"right\">$votesperuser</TD>\n"
;
print
" <TD VALIGN=\"top\" ALIGN=\"right\">$maxvotesperbug</TD>\n"
;
print
" <TD VALIGN=\"top\" ALIGN=\"right\">$votestoconfirm</TD>\n"
;
print
" <TD VALIGN=\"top\" ALIGN=\"right\">$bugs</TD>\n"
;
print
" <TD VALIGN=\"top\"><A HREF=\"editproducts.cgi?action=del&product="
,
url_quote
(
$product
),
"\">Delete</A></TD>\n"
;
print
" <TD VALIGN=\"top\"><A HREF=\"editproducts.cgi?action=del&product="
,
url_quote
(
$product
),
$classhtmlvar
,
"\">Delete</A></TD>\n"
;
print
"</TR>"
;
}
print
"<TR>\n"
;
print
" <TD VALIGN=\"top\" COLSPAN=7>Add a new product</TD>\n"
;
print
" <TD VALIGN=\"top\" ALIGN=\"
middle\"><A HREF=\"editproducts.cgi?action=add
\">Add</A></TD>\n"
;
print
" <TD VALIGN=\"top\" ALIGN=\"
center\"><A HREF=\"editproducts.cgi?action=add&classification="
,
url_quote
(
$classification
),
"
\">Add</A></TD>\n"
;
print
"</TR></TABLE>\n"
;
PutTrailer
();
...
...
@@ -262,12 +382,15 @@ unless ($action) {
if
(
$action
eq
'add'
)
{
PutHeader
(
"Add product"
);
if
(
Param
(
'useclassification'
))
{
CheckClassification
(
$classification
);
}
#print "This page lets you add a new product to bugzilla.\n";
print
"<FORM METHOD=POST ACTION=editproducts.cgi>\n"
;
print
"<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n"
;
EmitFormElements
(
''
,
''
,
''
,
0
,
0
,
10000
,
0
,
"---"
);
EmitFormElements
(
$classification
,
''
,
''
,
''
,
0
,
0
,
10000
,
0
,
"---"
);
print
"</TR><TR>\n"
;
print
" <TH ALIGN=\"right\">Version:</TH>\n"
;
...
...
@@ -282,6 +405,7 @@ if ($action eq 'add') {
print
"<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"new\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME='subcategory' VALUE='-All-'>\n"
;
print
"<INPUT TYPE=HIDDEN NAME='open_name' VALUE='All Open'>\n"
;
print
"<INPUT TYPE=HIDDEN NAME='classification' VALUE='"
,
html_quote
(
$classification
),
"'>\n"
;
print
"</FORM>"
;
my
$other
=
$localtrailer
;
...
...
@@ -349,10 +473,15 @@ if ($action eq 'new') {
$votestoconfirm
||=
0
;
my
$defaultmilestone
=
$::FORM
{
defaultmilestone
}
||
"---"
;
my
$classification_id
=
1
;
if
(
Param
(
'useclassification'
))
{
$classification_id
=
get_classification_id
(
$classification
);
}
# Add the new product.
SendSQL
(
"INSERT INTO products ( "
.
"name, description, milestoneurl, disallownew, votesperuser, "
.
"maxvotesperbug, votestoconfirm, defaultmilestone"
.
"maxvotesperbug, votestoconfirm, defaultmilestone
, classification_id
"
.
" ) VALUES ( "
.
SqlQuote
(
$product
)
.
","
.
SqlQuote
(
$description
)
.
","
.
...
...
@@ -366,9 +495,11 @@ if ($action eq 'new') {
SqlQuote
(
$votesperuser
)
.
","
.
SqlQuote
(
$maxvotesperbug
)
.
","
.
SqlQuote
(
$votestoconfirm
)
.
","
.
SqlQuote
(
$defaultmilestone
)
.
")"
);
SqlQuote
(
$defaultmilestone
)
.
","
.
SqlQuote
(
$classification_id
)
.
")"
);
SendSQL
(
"SELECT LAST_INSERT_ID()"
);
my
$product_id
=
FetchOneColumn
();
SendSQL
(
"INSERT INTO versions ( "
.
"value, product_id"
.
" ) VALUES ( "
.
...
...
@@ -455,7 +586,8 @@ if ($action eq 'new') {
PutTrailer
(
$localtrailer
,
"<a href=\"editproducts.cgi?action=add\">add</a> a new product"
,
"<a href=\"editcomponents.cgi?action=add&product="
.
url_quote
(
$product
)
.
"\">add</a> components to this new product"
);
url_quote
(
$product
)
.
$classhtmlvar
.
"\">add</a> components to this new product"
);
exit
;
}
...
...
@@ -470,15 +602,23 @@ if ($action eq 'new') {
if
(
$action
eq
'del'
)
{
PutHeader
(
"Delete product"
);
CheckProduct
(
$product
);
my
$classification_id
=
1
;
if
(
Param
(
'useclassification'
))
{
CheckClassificationProduct
(
$classification
,
$product
);
$classification_id
=
get_classification_id
(
$classification
);
}
# display some data about the product
SendSQL
(
"SELECT id, description, milestoneurl, disallownew
FROM products
WHERE name="
.
SqlQuote
(
$product
));
my
(
$product_id
,
$description
,
$milestoneurl
,
$disallownew
)
=
FetchSQLData
();
SendSQL
(
"SELECT classifications.description,
products.id, products.description, milestoneurl, disallownew
FROM products,classifications
WHERE products.name="
.
SqlQuote
(
$product
)
.
" AND classifications.id="
.
SqlQuote
(
$classification_id
));
my
(
$class_description
,
$product_id
,
$prod_description
,
$milestoneurl
,
$disallownew
)
=
FetchSQLData
();
my
$milestonelink
=
$milestoneurl
?
"<a href=\"$milestoneurl\">$milestoneurl</a>"
:
"<font color=\"red\">missing</font>"
;
$description
||=
"<FONT COLOR=\"red\">description missing</FONT>"
;
$prod_description
||=
"<FONT COLOR=\"red\">description missing</FONT>"
;
$class_description
||=
"<FONT COLOR=\"red\">description missing</FONT>"
;
$disallownew
=
$disallownew
?
'closed'
:
'open'
;
print
"<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0>\n"
;
...
...
@@ -486,13 +626,23 @@ if ($action eq 'del') {
print
" <TH VALIGN=\"top\" ALIGN=\"left\">Part</TH>\n"
;
print
" <TH VALIGN=\"top\" ALIGN=\"left\">Value</TH>\n"
;
if
(
Param
(
'useclassification'
))
{
print
"</TR><TR>\n"
;
print
" <TD VALIGN=\"top\">Classification:</TD>\n"
;
print
" <TD VALIGN=\"top\">$classification</TD>\n"
;
print
"</TR><TR>\n"
;
print
" <TD VALIGN=\"top\">Description:</TD>\n"
;
print
" <TD VALIGN=\"top\">$class_description</TD>\n"
;
}
print
"</TR><TR>\n"
;
print
" <TD VALIGN=\"top\">Product:</TD>\n"
;
print
" <TD VALIGN=\"top\">$product</TD>\n"
;
print
"</TR><TR>\n"
;
print
" <TD VALIGN=\"top\">Description:</TD>\n"
;
print
" <TD VALIGN=\"top\">$description</TD>\n"
;
print
" <TD VALIGN=\"top\">$
prod_
description</TD>\n"
;
if
(
Param
(
'usetargetmilestone'
))
{
print
"</TR><TR>\n"
;
...
...
@@ -548,7 +698,7 @@ if ($action eq 'del') {
#
if
(
Param
(
'usetargetmilestone'
))
{
print
"</TD>\n</TR><TR>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product="
,
url_quote
(
$product
),
"\">Edit milestones:</A></TH>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product="
,
url_quote
(
$product
),
$classhtmlvar
,
"\">Edit milestones:</A></TH>\n"
;
print
" <TD>"
;
SendSQL
(
"SELECT value
FROM milestones
...
...
@@ -603,6 +753,8 @@ one.";
print
"<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"delete\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"product\" VALUE=\""
.
html_quote
(
$product
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"classification\" VALUE=\""
.
html_quote
(
$classification
)
.
"\">\n"
;
print
"</FORM>"
;
PutTrailer
(
$localtrailer
);
...
...
@@ -706,25 +858,32 @@ if ($action eq 'delete') {
if
(
$action
eq
'edit'
)
{
PutHeader
(
"Edit product"
);
CheckProduct
(
$product
);
my
$classification_id
=
1
;
if
(
Param
(
'useclassification'
))
{
CheckClassificationProduct
(
$classification
,
$product
);
$classification_id
=
get_classification_id
(
$classification
);
}
# get data of product
SendSQL
(
"SELECT id,description,milestoneurl,disallownew,
SendSQL
(
"SELECT classifications.description,
products.id,products.description,milestoneurl,disallownew,
votesperuser,maxvotesperbug,votestoconfirm,defaultmilestone
FROM products
WHERE name="
.
SqlQuote
(
$product
));
my
(
$product_id
,
$description
,
$milestoneurl
,
$disallownew
,
FROM products,classifications
WHERE products.name="
.
SqlQuote
(
$product
)
.
" AND classifications.id="
.
SqlQuote
(
$classification_id
));
my
(
$class_description
,
$product_id
,
$prod_description
,
$milestoneurl
,
$disallownew
,
$votesperuser
,
$maxvotesperbug
,
$votestoconfirm
,
$defaultmilestone
)
=
FetchSQLData
();
print
"<FORM METHOD=POST ACTION=editproducts.cgi>\n"
;
print
"<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n"
;
EmitFormElements
(
$
product
,
$
description
,
$milestoneurl
,
EmitFormElements
(
$
classification
,
$product
,
$prod_
description
,
$milestoneurl
,
$disallownew
,
$votesperuser
,
$maxvotesperbug
,
$votestoconfirm
,
$defaultmilestone
);
print
"</TR><TR VALIGN=top>\n"
;
print
" <TH ALIGN=\"right\"><A HREF=\"editcomponents.cgi?product="
,
url_quote
(
$product
),
"\">Edit components:</A></TH>\n"
;
print
" <TH ALIGN=\"right\"><A HREF=\"editcomponents.cgi?product="
,
url_quote
(
$product
),
$classhtmlvar
,
"\">Edit components:</A></TH>\n"
;
print
" <TD>"
;
SendSQL
(
"SELECT name,description
FROM components
...
...
@@ -744,7 +903,7 @@ if ($action eq 'edit') {
print
"</TD>\n</TR><TR>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editversions.cgi?product="
,
url_quote
(
$product
),
"\">Edit versions:</A></TH>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editversions.cgi?product="
,
url_quote
(
$product
),
$classhtmlvar
,
"\">Edit versions:</A></TH>\n"
;
print
" <TD>"
;
SendSQL
(
"SELECT value
FROM versions
...
...
@@ -767,7 +926,7 @@ if ($action eq 'edit') {
#
if
(
Param
(
'usetargetmilestone'
))
{
print
"</TD>\n</TR><TR>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product="
,
url_quote
(
$product
),
"\">Edit milestones:</A></TH>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product="
,
url_quote
(
$product
),
$classhtmlvar
,
"\">Edit milestones:</A></TH>\n"
;
print
" <TD>"
;
SendSQL
(
"SELECT value
FROM milestones
...
...
@@ -787,7 +946,7 @@ if ($action eq 'edit') {
}
print
"</TD>\n</TR><TR>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editproducts.cgi?action=editgroupcontrols&product="
,
url_quote
(
$product
),
"\">Edit Group Access Controls</A></TH>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editproducts.cgi?action=editgroupcontrols&product="
,
url_quote
(
$product
),
$classhtmlvar
,
"\">Edit Group Access Controls</A></TH>\n"
;
print
"<TD>\n"
;
SendSQL
(
"SELECT id, name, isactive, entry, membercontrol, othercontrol, canedit "
.
"FROM groups, "
.
...
...
@@ -820,10 +979,12 @@ if ($action eq 'edit') {
print
"</TD>\n</TR></TABLE>\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"classification\" VALUE=\""
.
html_quote
(
$classification
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"productold\" VALUE=\""
.
html_quote
(
$product
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"descriptionold\" VALUE=\""
.
html_quote
(
$description
)
.
"\">\n"
;
html_quote
(
$
prod_
description
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"milestoneurlold\" VALUE=\""
.
html_quote
(
$milestoneurl
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"disallownewold\" VALUE=\"$disallownew\">\n"
;
...
...
@@ -843,7 +1004,6 @@ if ($action eq 'edit') {
exit
;
}
#
# action='updategroupcontrols' -> update the product
#
...
...
@@ -1325,6 +1485,7 @@ if ($action eq 'editgroupcontrols') {
}
$vars
->
{
'header_done'
}
=
$headerdone
;
$vars
->
{
'product'
}
=
$product
;
$vars
->
{
'classification'
}
=
$classification
;
$vars
->
{
'groups'
}
=
\
@groups
;
$vars
->
{
'const'
}
=
{
'CONTROLMAPNA'
=>
CONTROLMAPNA
,
...
...
enter_bug.cgi
View file @
88d26275
...
...
@@ -53,6 +53,7 @@ use vars qw(
$userid
%versions
$proddesc
$classdesc
)
;
# If we're using bug groups to restrict bug entry, we need to know who the
...
...
@@ -67,12 +68,47 @@ if (!defined $product) {
GetVersionTable
();
Bugzilla
->
login
();
my
%
products
;
if
(
!
Param
(
'useclassification'
)
)
{
# just pick the default one
$::FORM
{
'classification'
}
=
(
keys
%::
classdesc
)[
0
];
}
if
(
!
defined
$::FORM
{
'classification'
})
{
my
%
classdesc
;
my
%
classifications
;
foreach
my
$c
(
GetSelectableClassifications
())
{
$classdesc
{
$c
}
=
$::classdesc
{
$c
};
$classifications
{
$c
}
=
$::classifications
{
$c
};
}
my
$classification_size
=
scalar
(
keys
%
classdesc
);
if
(
$classification_size
==
0
)
{
ThrowUserError
(
"no_products"
);
}
elsif
(
$classification_size
>
1
)
{
$vars
->
{
'classdesc'
}
=
\%
classdesc
;
$vars
->
{
'classifications'
}
=
\%
classifications
;
$vars
->
{
'target'
}
=
"enter_bug.cgi"
;
$vars
->
{
'format'
}
=
$::FORM
{
'format'
};
print
"Content-type: text/html\n\n"
;
$template
->
process
(
"global/choose-classification.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
exit
;
}
$::FORM
{
'classification'
}
=
(
keys
%
classdesc
)[
0
];
$::MFORM
{
'classification'
}
=
[
$::FORM
{
'classification'
}];
}
my
%
products
;
foreach
my
$p
(
@enterable_products
)
{
if
(
CanEnterProduct
(
$p
))
{
$products
{
$p
}
=
$::proddesc
{
$p
};
if
(
CanEnterProduct
(
$p
))
{
if
(
IsInClassification
(
$::FORM
{
'classification'
},
$p
)
||
$::FORM
{
'classification'
}
eq
"__all"
)
{
$products
{
$p
}
=
$::proddesc
{
$p
};
}
}
}
...
...
@@ -81,7 +117,19 @@ if (!defined $product) {
ThrowUserError
(
"no_products"
);
}
elsif
(
$prodsize
>
1
)
{
my
%
classifications
;
if
(
!
Param
(
'useclassification'
)
)
{
@
{
$classifications
{
"all"
}}
=
keys
%
products
;
}
elsif
(
$::FORM
{
'classification'
}
eq
"__all"
)
{
%
classifications
=
%::
classifications
;
}
else
{
$classifications
{
$::FORM
{
'classification'
}}
=
$::classifications
{
$::FORM
{
'classification'
}};
}
$vars
->
{
'proddesc'
}
=
\%
products
;
$vars
->
{
'classifications'
}
=
\%
classifications
;
$vars
->
{
'classdesc'
}
=
\%::
classdesc
;
$vars
->
{
'target'
}
=
"enter_bug.cgi"
;
$vars
->
{
'format'
}
=
$cgi
->
param
(
'format'
);
...
...
@@ -252,6 +300,7 @@ SendSQL("SELECT name, description, login_name, realname
ORDER BY name"
);
while
(
MoreSQLData
())
{
my
(
$name
,
$description
,
$login
,
$realname
)
=
FetchSQLData
();
push
@components
,
{
name
=>
$name
,
description
=>
$description
,
...
...
globals.pl
View file @
88d26275
...
...
@@ -55,6 +55,7 @@ sub globals_pl_sillyness {
$zz
=
@
main::
legal_versions
;
$zz
=
@
main::
milestoneurl
;
$zz
=
%
main::
proddesc
;
$zz
=
%
main::
classdesc
;
$zz
=
@
main::
prodmaxvotes
;
$zz
=
$
main::
template
;
$zz
=
$
main::
userid
;
...
...
@@ -184,6 +185,19 @@ sub GenerateVersionTable {
$carray
{
$c
}
=
1
;
}
SendSQL
(
"SELECT products.name, classifications.name "
.
"FROM products, classifications "
.
"WHERE classifications.id = products.classification_id "
.
"ORDER BY classifications.name"
);
while
(
@line
=
FetchSQLData
())
{
my
(
$p
,
$c
)
=
(
@line
);
if
(
!
defined
$::classifications
{
$c
})
{
$::classifications
{
$c
}
=
[]
;
}
my
$ref
=
$::classifications
{
$c
};
push
@$ref
,
$p
;
}
my
$dotargetmilestone
=
1
;
# This used to check the param, but there's
# enough code that wants to pretend we're using
# target milestones, even if they don't get
...
...
@@ -191,6 +205,13 @@ sub GenerateVersionTable {
# about them anyway.
my
$mpart
=
$dotargetmilestone
?
", milestoneurl"
:
""
;
SendSQL
(
"select name, description from classifications ORDER BY name"
);
while
(
@line
=
FetchSQLData
())
{
my
(
$n
,
$d
)
=
(
@line
);
$::classdesc
{
$n
}
=
$d
;
}
SendSQL
(
"select name, description, votesperuser, disallownew$mpart from products ORDER BY name"
);
while
(
@line
=
FetchSQLData
())
{
my
(
$p
,
$d
,
$votesperuser
,
$dis
,
$u
)
=
(
@line
);
...
...
@@ -275,8 +296,10 @@ sub GenerateVersionTable {
'*::legal_bug_status'
,
'*::legal_resolution'
]));
print
$fh
(
Data::
Dumper
->
Dump
([
\
@::settable_resolution
,
\%::
proddesc
,
\%::
classifications
,
\%::
classdesc
,
\
@::enterable_products
,
\%::
prodmaxvotes
],
[
'*::settable_resolution'
,
'*::proddesc'
,
'*::classifications'
,
'*::classdesc'
,
'*::enterable_products'
,
'*::prodmaxvotes'
]));
if
(
$dotargetmilestone
)
{
...
...
@@ -494,6 +517,24 @@ sub CanEditProductId {
return
(
!
defined
(
$result
));
}
sub
IsInClassification
{
my
(
$classification
,
$productname
)
=
@_
;
if
(
!
Param
(
'useclassification'
))
{
return
1
;
}
else
{
my
$query
=
"SELECT classifications.name "
.
"FROM products,classifications "
.
"WHERE products.classification_id=classifications.id "
;
$query
.=
"AND products.name = "
.
SqlQuote
(
$productname
);
PushGlobalSQLState
();
SendSQL
(
$query
);
my
(
$ret
)
=
FetchSQLData
();
PopGlobalSQLState
();
return
(
$ret
eq
$classification
);
}
}
#
# This function determines if a user can enter bugs in the named
# product.
...
...
@@ -527,18 +568,21 @@ sub GetEnterableProducts {
return
(
@products
);
}
#
# This function returns an alphabetical list of product names to which
# the user can enter bugs. If the $by_id parameter is true, also retrieves IDs
# and pushes them onto the list as id, name [, id, name...] for easy slurping
# into a hash by the calling code.
sub
GetSelectableProducts
{
my
(
$by_id
)
=
@_
;
my
(
$by_id
,
$by_classification
)
=
@_
;
my
$extra_sql
=
$by_id
?
"id, "
:
""
;
my
$query
=
"SELECT $extra_sql name "
.
"FROM products "
.
my
$extra_from_sql
=
$by_classification
?
", classifications"
:
""
;
my
$query
=
"SELECT $extra_sql products.name "
.
"FROM products $extra_from_sql "
.
"LEFT JOIN group_control_map "
.
"ON group_control_map.product_id = products.id "
;
if
(
Param
(
'useentrygroupdefault'
))
{
...
...
@@ -551,7 +595,13 @@ sub GetSelectableProducts {
$query
.=
"AND group_id NOT IN("
.
join
(
','
,
values
(
%
{
Bugzilla
->
user
->
groups
}))
.
") "
;
}
$query
.=
"WHERE group_id IS NULL ORDER BY name"
;
$query
.=
"WHERE group_id IS NULL "
;
if
(
$by_classification
)
{
$query
.=
"AND classifications.id = products.classification_id "
;
$query
.=
"AND classifications.name = "
;
$query
.=
SqlQuote
(
$by_classification
)
.
" "
;
}
$query
.=
"ORDER BY name"
;
PushGlobalSQLState
();
SendSQL
(
$query
);
my
@products
=
();
...
...
@@ -609,6 +659,18 @@ sub GetSelectableProductHash {
return
$selectables
;
}
#
# This function returns an alphabetical list of classifications that has products the user can enter bugs.
sub
GetSelectableClassifications
{
my
@selectable_classes
=
();
foreach
my
$c
(
keys
%::
classdesc
)
{
if
(
scalar
(
GetSelectableProducts
(
0
,
$c
))
>
0
)
{
push
(
@selectable_classes
,
$c
);
}
}
return
(
@selectable_classes
);
}
sub
GetFieldDefs
{
my
$extra
=
""
;
...
...
@@ -740,6 +802,25 @@ sub DBNameToIdAndCheck {
{
name
=>
$name
},
"abort"
);
}
sub
get_classification_id
{
my
(
$classification
)
=
@_
;
PushGlobalSQLState
();
SendSQL
(
"SELECT id FROM classifications WHERE name = "
.
SqlQuote
(
$classification
));
my
(
$classification_id
)
=
FetchSQLData
();
PopGlobalSQLState
();
return
$classification_id
;
}
sub
get_classification_name
{
my
(
$classification_id
)
=
@_
;
die
"non-numeric classification_id '$classification_id' passed to get_classification_name"
unless
(
$classification_id
=~
/^\d+$/
);
PushGlobalSQLState
();
SendSQL
(
"SELECT name FROM classifications WHERE id = $classification_id"
);
my
(
$classification
)
=
FetchSQLData
();
PopGlobalSQLState
();
return
$classification
;
}
...
...
js/productform.js
View file @
88d26275
...
...
@@ -21,6 +21,72 @@
/* this file contains functions to update form controls based on a
* collection of javascript arrays containing strings */
/* selectClassification reads the selection from f.classification and updates
* f.product accordingly
* - f: a form containing classification, product, component, varsion and
* target_milestone select boxes.
* globals (3vil!):
* - prods, indexed by classification name
* - first_load: boolean, specifying if it is the first time we load
* the query page.
* - last_sel: saves our last selection list so we know what has
* changed, and optimize for additions.
*/
function
selectClassification
(
classfield
,
product
,
component
,
version
,
milestone
)
{
/* this is to avoid handling events that occur before the form
* itself is ready, which could happen in buggy browsers.
*/
if
(
!
classfield
)
{
return
;
}
/* if this is the first load and nothing is selected, no need to
* merge and sort all components; perl gives it to us sorted.
*/
if
((
first_load
)
&&
(
classfield
.
selectedIndex
==
-
1
))
{
first_load
=
false
;
return
;
}
/* don't reset first_load as done in selectProduct. That's because we
want selectProduct to handle the first_load attribute
*/
/* - sel keeps the array of classifications we are selected.
* - merging says if it is a full list or just a list of classifications
* that were added to the current selection.
*/
var
merging
=
false
;
var
sel
=
Array
();
/* if nothing selected, pick all */
var
findall
=
classfield
.
selectedIndex
==
-
1
;
sel
=
get_selection
(
classfield
,
findall
,
false
);
if
(
!
findall
)
{
/* save sel for the next invocation of selectClassification() */
var
tmp
=
sel
;
/* this is an optimization: if we have just added classifications to an
* existing selection, no need to clear the form controls and add
* everybody again; just merge the new ones with the existing
* options.
*/
if
((
last_sel
.
length
>
0
)
&&
(
last_sel
.
length
<
sel
.
length
))
{
sel
=
fake_diff_array
(
sel
,
last_sel
);
merging
=
true
;
}
last_sel
=
tmp
;
}
/* save original options selected */
var
saved_prods
=
get_selection
(
product
,
false
,
true
);
/* do the actual fill/update, reselect originally selected options */
updateSelect
(
prods
,
sel
,
product
,
merging
);
restoreSelection
(
product
,
saved_prods
);
selectProduct
(
product
,
component
,
version
,
milestone
);
}
/* selectProduct reads the selection from the product control and
* updates version, component and milestone controls accordingly.
*
...
...
@@ -68,7 +134,15 @@ function selectProduct(product, component, version, milestone) {
/* if nothing selected, pick all */
var
findall
=
product
.
selectedIndex
==
-
1
;
sel
=
get_selection
(
product
,
findall
,
false
);
if
(
useclassification
)
{
/* update index based on the complete product array */
sel
=
get_selection
(
product
,
findall
,
true
);
for
(
var
i
=
0
;
i
<
sel
.
length
;
i
++
)
{
sel
[
i
]
=
prods
[
sel
[
i
]];
}
}
else
{
sel
=
get_selection
(
product
,
findall
,
false
);
}
if
(
!
findall
)
{
/* save sel for the next invocation of selectProduct() */
var
tmp
=
sel
;
...
...
long_list.cgi
View file @
88d26275
...
...
@@ -43,6 +43,7 @@ my $generic_query = "
SELECT
bugs.bug_id,
COALESCE(bugs.alias, ''),
classifications.name,
products.name,
bugs.version,
bugs.rep_platform,
...
...
@@ -63,9 +64,10 @@ my $generic_query = "
bugs.estimated_time,
bugs.remaining_time,
date_format(creation_ts,'%Y.%m.%d %H:%i')
FROM bugs,profiles assign,profiles report, products, components
FROM bugs,profiles assign,profiles report,
classifications,
products, components
WHERE assign.userid = bugs.assigned_to AND report.userid = bugs.reporter
AND bugs.product_id=products.id AND bugs.component_id=components.id"
;
AND bugs.product_id=products.id AND bugs.component_id=components.id
AND products.classification_id = classifications.id"
;
my
$buglist
=
$cgi
->
param
(
'buglist'
)
||
$cgi
->
param
(
'bug_id'
)
||
...
...
@@ -81,7 +83,8 @@ foreach my $bug_id (split(/[:,]/, $buglist)) {
my
%
bug
;
my
@row
=
FetchSQLData
();
foreach
my
$field
(
"bug_id"
,
"alias"
,
"product"
,
"version"
,
"rep_platform"
,
foreach
my
$field
(
"bug_id"
,
"alias"
,
"classification"
,
"product"
,
"version"
,
"rep_platform"
,
"op_sys"
,
"bug_status"
,
"resolution"
,
"priority"
,
"bug_severity"
,
"component"
,
"assigned_to"
,
"reporter"
,
"bug_file_loc"
,
"short_desc"
,
"target_milestone"
,
...
...
query.cgi
View file @
88d26275
...
...
@@ -127,7 +127,7 @@ sub PrefillForm {
# Nothing must be undef, otherwise the template complains.
foreach
my
$name
(
"bug_status"
,
"resolution"
,
"assigned_to"
,
"rep_platform"
,
"priority"
,
"bug_severity"
,
"product"
,
"reporter"
,
"op_sys"
,
"
classification"
,
"
product"
,
"reporter"
,
"op_sys"
,
"component"
,
"version"
,
"chfield"
,
"chfieldfrom"
,
"chfieldto"
,
"chfieldvalue"
,
"target_milestone"
,
"email"
,
"emailtype"
,
"emailreporter"
,
...
...
@@ -274,9 +274,24 @@ for (my $i = 0; $i < @products; ++$i) {
# Assign hash back to product array.
$products
[
$i
]
=
\%
product
;
}
$vars
->
{
'product'
}
=
\
@products
;
# Create data structures representing each classification
if
(
Param
(
'useclassification'
))
{
my
@classifications
=
();
foreach
my
$c
(
sort
(
GetSelectableClassifications
()))
{
# Create hash to hold attributes for each classification.
my
%
classification
=
(
'name'
=>
$c
,
'products'
=>
[
GetSelectableProducts
(
0
,
$c
)
]
);
# Assign hash back to classification array.
push
@classifications
,
\%
classification
;
}
$vars
->
{
'classification'
}
=
\
@classifications
;
}
# We use 'component_' because 'component' is a Template Toolkit reserved word.
$vars
->
{
'component_'
}
=
\
@components
;
...
...
@@ -300,7 +315,9 @@ push @chfields, "[Bug creation]";
# This is what happens when you have variables whose definition depends
# on the DB schema, and then the underlying schema changes...
foreach
my
$val
(
@::log_columns
)
{
if
(
$val
eq
'product_id'
)
{
if
(
$val
eq
'classification_id'
)
{
$val
=
'classification'
;
}
elsif
(
$val
eq
'product_id'
)
{
$val
=
'product'
;
}
elsif
(
$val
eq
'component_id'
)
{
$val
=
'component'
;
...
...
report.cgi
View file @
88d26275
...
...
@@ -113,6 +113,7 @@ $columns{'bug_status'} = "bugs.bug_status";
$columns
{
'resolution'
}
=
"bugs.resolution"
;
$columns
{
'component'
}
=
"map_components.name"
;
$columns
{
'product'
}
=
"map_products.name"
;
$columns
{
'classification'
}
=
"map_classifications.name"
;
$columns
{
'version'
}
=
"bugs.version"
;
$columns
{
'op_sys'
}
=
"bugs.op_sys"
;
$columns
{
'votes'
}
=
"bugs.votes"
;
...
...
@@ -134,8 +135,13 @@ $columns{''} = "42217354";
||
ThrowCodeError
(
"report_axis_invalid"
,
{
fld
=>
"z"
,
val
=>
$tbl_field
});
my
@axis_fields
=
(
$row_field
,
$col_field
,
$tbl_field
);
my
@selectnames
=
map
(
$columns
{
$_
},
@axis_fields
);
# add product if person is requesting classification
if
(
lsearch
(
\
@axis_fields
,
"classification"
)
>=
0
)
{
if
(
lsearch
(
\
@axis_fields
,
"product"
)
<
0
)
{
push
(
@selectnames
,(
$columns
{
'product'
}));
}
}
# Clone the params, so that Bugzilla::Search can modify them
my
$params
=
new
Bugzilla::
CGI
(
$cgi
);
...
...
template/en/default/admin/classifications/add.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Add new classification"
%]
<form method=post action="editclassifications.cgi">
<table border=0 cellpadding=4 cellspacing=0>
<tr>
<th align="right">Classification:</th>
<td><input size=64 maxlength=64 name="classification"></td>
</tr>
<tr>
<th align="right">Description:</th>
<td><textarea rows=4 cols=64 wrap=virtual name="description"></textarea></td>
</tr>
</table>
<hr>
<input type=submit value="Add">
<input type=hidden name="action" value="new">
</FORM>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/classifications/del.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Delete classification"
%]
<table border=1 cellpadding=4 cellspacing=0>
<tr bgcolor="#6666ff">
<th valign="top" align="left">Part</th>
<th valign="top" align="left">Value</th>
</tr><tr>
<td valign="top">Classification:</td>
<td valign="top">[% classification FILTER html %]</td>
</tr><tr>
<td valign="top">Description:</td>
<td valign="top">
[% IF description %]
[% description FILTER html %]
[% ELSE %]
<font color="red">description missing</font>
[% END %]
</td>
</tr>
</table>
<h2>Confirmation</h2>
<p>Do you really want to delete this classification?<p>
<form method=post action="editclassifications.cgi">
<input type=submit value="Yes, delete">
<input type=hidden name="action" value="delete">
<input type=hidden name="classification" value="[% classification FILTER html %]">
</form>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/classifications/delete.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Classification deleted"
%]
Classification [% classification FILTER html %] deleted.<br>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/classifications/edit.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Edit classification"
%]
<form method=post action="editclassifications.cgi">
<table border=0 cellpadding=4 cellspacing=0>
<tr>
<th align="right">Classification:</th>
<td><input size=64 maxlength=64 name="classification" value="[% classification FILTER html %]"></TD>
</tr>
<tr>
<th align="right">Description:</th>
<td><textarea rows=4 cols=64 name="description">[% description FILTER html %]</textarea></TD>
</tr>
<tr valign=top>
<th align="right"><a href="editproducts.cgi?classification=[% classification FILTER html %]">Edit products</a></th>
<td>
[% IF products AND products.size > 0 %]
<table>
[% FOREACH product = products %]
<tr>
<th align=right valign=top>[% product.name FILTER html %]</th>
<td valign=top>
[% IF product.description %]
[% product.description FILTER html %]
[% ELSE %]
<font color="red">description missing</font>
[% END %]
</td>
</tr>
[% END %]
</table>
[% ELSE %]
<font color="red">none</font>
[% END %]
</td>
</tr>
</table>
<input type=hidden name="classificationold" value="[% classification FILTER html %]">
<input type=hidden name="descriptionold" value="[% description FILTER html %]">
<input type=hidden name="action" value="update">
<input type=submit value="Update">
</form>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/classifications/new.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Adding new classification"
%]
OK, done.
<p>Back to the <a href="./">main [% terms.bugs %] page</a>,
<a href="editproducts.cgi?action=add&classification=[% classification FILTER html %]">add</a> products to this new classification,
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/classifications/reclassify.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Reclassify products"
%]
[% main_classification = classification %]
<form method=post action="editclassifications.cgi">
<table border=0 cellpadding=4 cellspacing=0>
<tr>
<td valign="top">Classification:</td>
<td valign="top" colspan=3>[% main_classification FILTER html %]</td>
</tr><tr>
<td valign="top">Description:</td>
<td valign="top" colspan=3>
[% IF description %]
[% description FILTER html %]
[% ELSE %]
<font color="red">description missing</font>
[% END %]
</td>
</tr><tr>
<td valign="top">Products:</td>
<td valign="top">Products</td>
<td></td>
<td valign="top">[% main_classification FILTER html %] Products</td>
</tr><tr>
<td></td>
<td valign="top">
<select name="prodlist" id="prodlist" multiple="multiple" size="20">
[% FOREACH cl = class_products %]
<option value="[% cl.value FILTER html %]">
[% cl.name FILTER html %]
</option>
[% END %]
</select></td>
<td align="center">
<input type=submit value=" Add >> " name="add_products"><br><br>
<input type=submit value="<< Remove" name="remove_products">
</td>
<td valign="middle" rowspan=2>
<select name="myprodlist" id="myprodlist" multiple="multiple" size="20">
[% FOREACH product = selected_products %]
<option value="[% product FILTER html %]">
[% product FILTER html %]
</option>
[% END %]
</select></td>
</tr>
</table>
<input type=hidden name="action" value="reclassify">
<input type=hidden name="classification" value="[% main_classification FILTER html %]">
</form>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>,
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/classifications/select.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Select classification"
%]
[% filt_classification = classification FILTER html %]
<table border=1 cellpadding=4 cellspacing=0>
<tr bgcolor="#6666ff">
<th align="left">Edit Classification ...</th>
<th align="left">Description</th>
<th align="left">Products</th>
<th align="left">Action</th>
</tr>
[% FOREACH cl = classifications %]
<tr>
<td valign="top"><a href="editclassifications.cgi?action=edit&classification=[% cl.classification FILTER html %]"><b>[% cl.classification FILTER html %]</b></a></td>
<td valign="top">
[% IF cl.description %]
[% cl.description FILTER html %]
[% ELSE %]
<font color="red">none</font>
[% END %]
</td>
[% IF (cl.id == 1) %]
<td valign="top">[% cl.total FILTER html %]</td>
[% ELSE %]
<td valign="top"><a href="editclassifications.cgi?action=reclassify&classification=[% cl.classification FILTER html %]">reclassify ([% cl.total FILTER html %])</a></td>
[% END %]
[%# don't allow user to delete the default id. %]
[% IF (cl.id == 1) %]
<td valign="top"> </td>
[% ELSE %]
<td valign="top"><a href="editclassifications.cgi?action=del&classification=[% cl.classification FILTER html %]">delete</a></td>
[% END %]
</tr>
[% END %]
<tr>
<td valign="top" colspan=3>Add a new classification</td>
<td valign="top" align="center"><a href="editclassifications.cgi?action=add">Add</a></td>
</tr>
</table>
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/classifications/update.html.tmpl
0 → 100644
View file @
88d26275
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[% PROCESS global/header.html.tmpl
title = "Update classification"
%]
[% IF updated_description %]
Updated description.<br>
[% END %]
[% IF updated_classification %]
Updated classification name.<br>
[% END %]
<p>Back to the <a href="./">main [% terms.bugs %] page</a>
or <a href="editclassifications.cgi"> edit</a> more classifications.
[% PROCESS global/footer.html.tmpl %]
template/en/default/admin/products/groupcontrol/edit.html.tmpl
View file @
88d26275
...
...
@@ -22,6 +22,7 @@
[% PROCESS global/variables.none.tmpl %]
[% filt_product = product FILTER html %]
[% filt_classification = classification FILTER html %]
[% PROCESS global/header.html.tmpl
title = "Edit Group Controls for '$filt_product'"
%]
...
...
@@ -29,6 +30,7 @@
<form method="post" action="editproducts.cgi">
<input type="hidden" name="action" value="updategroupcontrols">
<input type="hidden" name="product" value="[% filt_product %]">
<input type="hidden" name="classification" value="[% filt_classification %]">
<table id="form" cellspacing="0" cellpadding="4" border="1">
<tr bgcolor="#6666ff">
...
...
template/en/default/bug/edit.html.tmpl
View file @
88d26275
...
...
@@ -119,6 +119,11 @@
<table cellspacing="1" cellpadding="1" border="0">
<tr>
<td align="right">
[% IF Param('useclassification') %]
[% IF bug.classification_id != "1" %]
<b>[[% bug.classification FILTER html %]]</b>
[% END %]
[% END %]
<b>[% terms.Bug %]#:</b>
</td>
<td>
...
...
template/en/default/bug/show-multiple.html.tmpl
View file @
88d26275
...
...
@@ -62,8 +62,14 @@
([% bug.alias FILTER html %])
[% END %]
</td>
[% PROCESS cell attr = { description => "Product",
name => "product" } %]
<td>
<b> Product: </b>
[% IF Param("useclassification") %]
[[% bug.classification FILTER html %]]
[% END %]
[% bug.product FILTER html %]
</td>
[% PROCESS cell attr = { description => "Version",
name => "version" } %]
[% PROCESS cell attr = { description => "Platform",
...
...
template/en/default/filterexceptions.pl
View file @
88d26275
...
...
@@ -500,6 +500,7 @@
],
'admin/products/groupcontrol/edit.html.tmpl'
=>
[
'filt_classification'
,
'filt_product'
,
'group.bugcount'
,
'group.id'
,
...
...
template/en/default/global/choose-classification.html.tmpl
0 → 100644
View file @
88d26275
<!-- 1.0@bugzilla.org -->
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Albert Ting
#
# Contributor(s): Albert Ting <alt@sonic.net>
#%]
[%# INTERFACE:
# classdesc: hash. May be empty. The hash keys are the classifications, and the values
# are their descriptions.
#%]
[% IF target == "enter_bug.cgi" %]
[% title = "Select Classification" %]
[% h2 = "Please select the classification." %]
[% END %]
[% DEFAULT title = "Choose the classification" %]
[% PROCESS global/header.html.tmpl %]
<table>
[% IF Param('showallproducts') %]
<tr>
<th align="right" valign="center" height=50>
<a href="[% target FILTER url_quote %]?classification=__all
[% IF format %]&format=[% format FILTER url_quote %][% END %]">
All</a>:
</th>
<td valign="center"> Show all products</td>
</tr>
[% END %]
[% FOREACH p = classdesc.keys.sort %]
[% IF classifications.$p.size > 0 %]
<tr>
<th align="right" valign="top">
<a href="[% target FILTER url_quote %]?classification=[% p FILTER url_quote %]
[% IF format %]&format=[% format FILTER url_quote %][% END %]">
[% p FILTER html %]</a>:
</th>
[% IF classdesc.$p %]
<td valign="top"> [% classdesc.$p FILTER html %]</td>
[% END %]
</tr>
[% END %]
[% END %]
</table>
[% PROCESS global/footer.html.tmpl %]
template/en/default/global/field-descs.none.tmpl
View file @
88d26275
...
...
@@ -32,6 +32,7 @@
"bug_status" => "Status",
"changeddate" => "Last Changed Date",
"cc" => "CC",
"classification" => "Classification",
"cclist_accessible" => "CC list accessible?",
"component_id" => "Component ID",
"component" => "Component",
...
...
template/en/default/global/useful-links.html.tmpl
View file @
88d26275
...
...
@@ -77,8 +77,17 @@
IF user.groups.tweakparams %]
[% ' | <a href="editusers.cgi">Users</a>' IF user.groups.editusers
|| user.can_bless %]
[% ' | <a href="editproducts.cgi">Products</a>'
[% IF Param('useclassification') %]
[% IF user.groups.editclassifications %]
[% ' | <a href="editclassifications.cgi">Classifications</a>' %]
[% END %]
[% IF user.groups.editcomponents %]
[% ' | <a href="editproducts.cgi">Products</a>' %]
[% END %]
[% ELSE %]
[% ' | <a href="editproducts.cgi">Products</a>'
IF user.groups.editcomponents %]
[% END %]
[% ' | <a href="editflagtypes.cgi">Flags</a>'
IF user.groups.editcomponents %]
[% ' | <a href="editgroups.cgi">Groups</a>'
...
...
template/en/default/global/user-error.html.tmpl
View file @
88d26275
...
...
@@ -142,6 +142,40 @@
[% title = "Comment Too Long" %]
Comments cannot be longer than 65,535 characters.
[% ELSIF error == "auth_classification_not_enabled" %]
[% title = "Classification Not Enabled" %]
Sorry, classification is not enabled.
[% ELSIF error == "auth_cant_edit_classifications" %]
[% title = "Access Denied" %]
Sorry, you aren't a member of the 'editclassifications' group, and so
you aren't allowed to add, modify or delete classifications.
[% ELSIF error == "classification_not_specified" %]
[% title = "You Must Supply A Classification Name" %]
You must enter a classification name.
[% ELSIF error == "classification_already_exists" %]
[% title = "Classification Already Exists" %]
A classification with the name '[% name FILTER html %]' already exists.
[% ELSIF error == "classification_doesnt_exist" %]
[% title = "Classification Does Not Exist" %]
The classification '[% name FILTER html %]' does not exist.
[% ELSIF error == "classification_not_deletable" %]
[% title = "Default Classification Can Not Be Deleted" %]
You can not delete the default classification
[% ELSIF error == "classification_has_products" %]
Sorry, there are products for this classification. You
must reassign those products to another classification before you
can delete this one.
[% ELSIF error == "cant_delete_default_classification" %]
Sorry, but you can not delete the default classification,
'[% name FILTER html %]'.
[% ELSIF error == "auth_cant_edit_components" %]
[% title = "Access Denied" %]
Sorry, you aren't a member of the 'editcomponents' group, and so
...
...
@@ -463,6 +497,10 @@
[% title = "Invalid group name" %]
The group you specified, [% name FILTER html %], is not valid here.
[% ELSIF error == "invalid_group_name" %]
[% title = "Invalid group name" %]
The group you specified, [% name FILTER html %], is not valid here.
[% ELSIF error == "invalid_maxrows" %]
[% title = "Invalid Max Rows" %]
The maximum number of rows, '[% maxrows FILTER html %]', must be
...
...
template/en/default/search/form.html.tmpl
View file @
88d26275
...
...
@@ -21,6 +21,81 @@
# Gervase Markham <gerv@gerv.net>
#%]
<script type="text/javascript" language="JavaScript">
var first_load = true; [%# is this the first time we load the page? %]
var last_sel = new Array(); [%# caches last selection %]
[% IF Param('useclassification') %]
var useclassification = true;
var prods = new Array();
[% ELSE %]
var useclassification = false;
[% END %]
var cpts = new Array();
var vers = new Array();
[% IF Param('usetargetmilestone') %]
var tms = new Array();
[% END %]
[%# Create an array of products, indexed by the classification #%]
[% nclass = 0 %]
[% FOREACH c = classification %]
prods[[% nclass FILTER js %]] = [
[%- FOREACH item = c.products %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
[% nclass = nclass+1 %]
[% END %]
[%# Create three arrays of components, versions and target milestones, indexed
# numerically according to the product they refer to. #%]
[% n = 0 %]
[% FOREACH p = product %]
[% IF Param('useclassification') %]
prods['[% p.name FILTER js %]'] = [% n %]
[% END %]
cpts[[% n %]] = [
[%- FOREACH item = p.components %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
vers[[% n %]] = [
[%- FOREACH item = p.versions -%]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
[% IF Param('usetargetmilestone') %]
tms[[% n %]] = [
[%- FOREACH item = p.milestones %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
[% END %]
[% n = n+1 %]
[% END %]
/*
* doOnSelectProduct determines which selection should get updated
*
* - selectmode = 0 - init
* selectmode = 1 - classification selected
* selectmode = 2 - product selected
*
* globals:
* queryform - string holding the name of the selection form
*/
function doOnSelectProduct(selectmode) {
var f = document.forms[queryform];
milestone = (typeof(f.target_milestone) == "undefined" ?
null : f.target_milestone);
if (selectmode == 0) {
if (useclassification) {
selectClassification(f.classification, f.product, f.component, f.version, milestone);
} else {
selectProduct(f.product, f.component, f.version, milestone);
}
} else if (selectmode == 1) {
selectClassification(f.classification, f.product, f.component, f.version, milestone);
} else {
selectProduct(f.product, f.component, f.version, milestone);
}
}
</script>
[% PROCESS global/variables.none.tmpl %]
[% query_variants = [
...
...
@@ -56,7 +131,7 @@
<input name="short_desc" size="40" accesskey="s"
value="[% default.short_desc.0 FILTER html %]">
<script language="JavaScript" type="text/javascript"> <!--
document.forms[
'queryform'
].short_desc.focus();
document.forms[
queryform
].short_desc.focus();
// -->
</script>
</td>
...
...
@@ -67,12 +142,35 @@
</td>
</tr>
[%# *** Product Component Version Target *** %]
[%# *** Classification Product Component Version Target *** %]
<tr>
<td colspan="4">
<table>
<tr>
[% IF Param('useclassification') %]
<td valign="top">
<table>
<tr valign="bottom">
<th align="left"><u>C</u>lassification:</th>
</tr>
<tr valign="top">
<td align="left">
<label for="classification">
<select name="classification" multiple="multiple" size="5" id="classification"
onchange="doOnSelectProduct(1);">
[% FOREACH cat = classification %]
<option value="[% cat.name FILTER html %]"
[% " selected" IF lsearch(default.classification, cat.name) != -1 %]>
[% cat.name FILTER html %]
</option>
[% END %]
</select>
</label>
</td>
</tr>
</table>
</td>
[% END %]
<td valign="top">
<table>
<tr valign="bottom">
...
...
@@ -83,7 +181,7 @@
<td align="left">
<label for="product" accesskey="p">
<select name="product" multiple="multiple" size="5" id="product"
onchange="doOnSelectProduct();">
onchange="doOnSelectProduct(
2
);">
[% FOREACH p = product %]
<option value="[% p.name FILTER html %]"
[% " selected" IF lsearch(default.product, p.name) != -1 %]>
...
...
template/en/default/search/search-advanced.html.tmpl
View file @
88d26275
...
...
@@ -32,44 +32,13 @@
[% js_data = BLOCK %]
function doOnSelectProduct() {
var f = document.forms['queryform'];
milestone = (typeof(f.target_milestone) == "undefined" ?
null : f.target_milestone);
selectProduct(f.product, f.component, f.version, milestone);
}
var first_load = true; [%# is this the first time we load the page? %]
var last_sel = new Array(); [%# caches last selection %]
var cpts = new Array();
var vers = new Array();
[% IF Param('usetargetmilestone') %]
var tms = new Array();
[% END %]
[%# Create three arrays of components, versions and target milestones, indexed
# numerically according to the product they refer to. #%]
[% n = 0 %]
[% FOREACH p = product %]
cpts[[% n %]] = [
[%- FOREACH item = p.components %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
vers[[% n %]] = [
[%- FOREACH item = p.versions -%]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
[% IF Param('usetargetmilestone') %]
tms[[% n %]] = [
[%- FOREACH item = p.milestones %]'[% item FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
[% END %]
[% n = n+1 %]
[% END %]
var queryform = "queryform"
[% END %]
[% PROCESS global/header.html.tmpl
title = "Search for $terms.bugs"
h1 = ""
onload = "doOnSelectProduct(); initHelp();"
onload = "doOnSelectProduct(
0
); initHelp();"
javascript = js_data
javascript_urls = [ "js/productform.js" ]
style = "td.selected_tab {
...
...
template/en/default/search/search-help.html.tmpl
View file @
88d26275
...
...
@@ -25,8 +25,13 @@
{ id => "short_desc",
html => "The $terms.bug summary is a short sentence which succinctly
describes <br> what the $terms.bug is about." },
{ id => "classification",
html => "$terms.Bugs are categorised into Classifications, Products and Components. classifications is the<br>
top-level categorisation." },
{ id => "product",
html => "$terms.Bugs are categorised into Products and Components. Product is
html => Param('useclassification') ?
"$terms.Bugs are categorised into Products and Components. Select a Classification to narrow down this list" :
"$terms.Bugs are categorised into Products and Components. Product is
the<br>top-level categorisation." },
{ id => "component",
html => "Components are second-level categories; each belongs to a<br>
...
...
template/en/default/search/search-report-graph.html.tmpl
View file @
88d26275
...
...
@@ -26,9 +26,15 @@
[% PROCESS global/variables.none.tmpl %]
[% js_data = BLOCK %]
var queryform = "reportform"
[% END %]
[% PROCESS global/header.html.tmpl
title = "Generate Graphical Report"
onload = "selectProduct(document.forms['reportform']);chartTypeChanged()"
onload = "doOnSelectProduct(0); chartTypeChanged()"
javascript = js_data
javascript_urls = [ "js/productform.js" ]
%]
[% PROCESS "search/search-report-select.html.tmpl" %]
...
...
template/en/default/search/search-report-select.html.tmpl
View file @
88d26275
...
...
@@ -27,7 +27,7 @@
[% PROCESS "global/field-descs.none.tmpl" %]
[% BLOCK select %]
[% rep_fields = ["product", "component", "version", "rep_platform",
[% rep_fields = ["
classification", "
product", "component", "version", "rep_platform",
"op_sys", "bug_status", "resolution", "bug_severity",
"priority", "target_milestone", "assigned_to",
"reporter", "qa_contact", "votes" ] %]
...
...
template/en/default/search/search-report-table.html.tmpl
View file @
88d26275
...
...
@@ -26,9 +26,15 @@
[% PROCESS global/variables.none.tmpl %]
[% js_data = BLOCK %]
var queryform = "reportform"
[% END %]
[% PROCESS global/header.html.tmpl
title = "Generate Tabular Report"
onload = "selectProduct(document.forms['reportform']);"
onload = "doOnSelectProduct(0)"
javascript = js_data
javascript_urls = [ "js/productform.js" ]
%]
[% PROCESS "search/search-report-select.html.tmpl" %]
...
...
template/en/default/search/search-specific.html.tmpl
View file @
88d26275
...
...
@@ -75,10 +75,24 @@ for "crash secure SSL flash".
<td>
<select name="product" id="product">
<option value="">All</option>
[% FOREACH p = product %]
<option value="[% p.name FILTER html %]"
[% " selected" IF lsearch(default.product, p.name) != -1 %]>
[% p.name FILTER html %]</option>
[% IF Param('useclassification') %]
[% FOREACH c = classification %]
<optgroup label="[% c.name FILTER html %]">
[% FOREACH p = c.products %]
<option value="[% p FILTER html %]"
[% " selected" IF lsearch(default.product, p) != -1 %]>
[% p FILTER html %]
</option>
[% END %]
</optgroup>
[% END %]
[% ELSE %]
[% FOREACH p = product %]
<option value="[% p.name FILTER html %]"
[% " selected" IF lsearch(default.product, p.name) != -1 %]>
[% p.name FILTER html %]
</option>
[% END %]
[% END %]
</select>
</td>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment