Index: openacs-4/packages/bug-tracker/bug-tracker.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/bug-tracker.info,v diff -u -r1.8 -r1.9 --- openacs-4/packages/bug-tracker/bug-tracker.info 9 Dec 2002 21:23:50 -0000 1.8 +++ openacs-4/packages/bug-tracker/bug-tracker.info 13 Jan 2003 15:25:12 -0000 1.9 @@ -7,13 +7,14 @@ f f - + + oracle postgresql Lars Pind Tracks bugs and features, versions and maintainers, in software projects. Contains the best of SDM, Bugzilla, FogBUGZ, and bughost.com. - 2002-09-11 + 2003-01-10 Musea Technologies @@ -41,6 +42,8 @@ + + @@ -54,14 +57,21 @@ - + + + + + + + + @@ -74,21 +84,14 @@ - + + - - - - - - - - Index: openacs-4/packages/bug-tracker/lib/nav-bar.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/lib/nav-bar.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/bug-tracker/lib/nav-bar.tcl 11 Sep 2002 14:03:20 -0000 1.4 +++ openacs-4/packages/bug-tracker/lib/nav-bar.tcl 13 Jan 2003 15:25:45 -0000 1.5 @@ -32,7 +32,7 @@ multirow append links "Bugs" "${url_prefix}.?[export_vars { filter:array }]" -if { [ad_permission_p [ad_conn package_id] create] } { +if { [ad_permission_p [ad_conn package_id] create] || [ad_conn user_id] == 0 } { multirow append links "New Bug" "${url_prefix}bug-add" } @@ -42,7 +42,7 @@ multirow append links "Patches" "[ad_conn package_url]patch-list" -if { [ad_permission_p [ad_conn package_id] create] } { +if { [ad_permission_p [ad_conn package_id] create] || [ad_conn user_id] == 0 } { multirow append links "New Patch" "[ad_conn package_url]patch-add" } Index: openacs-4/packages/bug-tracker/tcl/bug-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/tcl/bug-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/bug-tracker/tcl/bug-procs-postgresql.xql 13 Jan 2003 15:26:06 -0000 1.1 @@ -0,0 +1,104 @@ + + + + postgresql7.1 + + + + select b.bug_id, + b.bug_number, + b.summary, + o.creation_user as submitter_user_id, + submitter.first_names as submitter_first_names, + submitter.last_name as submitter_last_name, + submitter.email as submitter_email, + b.component_id, + c.component_name, + o.creation_date, + to_char(o.creation_date, 'fmMM/DDfm/YYYY') as creation_date_pretty, + b.severity, + sc.sort_order || ' - ' || sc.severity_name as severity_pretty, + b.priority, + pc.sort_order || ' - ' || pc.priority_name as priority_pretty, + b.status, + b.resolution, + b.bug_type, + b.user_agent, + b.original_estimate_minutes, + b.latest_estimate_minutes, + b.elapsed_time_minutes, + b.found_in_version, + coalesce((select version_name + from bt_versions found_in_v + where found_in_v.version_id = b.found_in_version), 'Unknown') as found_in_version_name, + b.fix_for_version, + coalesce((select version_name + from bt_versions fix_for_v + where fix_for_v.version_id = b.fix_for_version), 'Undecided') as fix_for_version_name, + b.fixed_in_version, + coalesce((select version_name + from bt_versions fixed_in_v + where fixed_in_v.version_id = b.fixed_in_version), 'Unknown') as fixed_in_version_name, + b.assignee, + asgnu.first_names as assignee_first_names, + asgnu.last_name as assignee_last_name, + asgnu.email as assignee_email, + to_char(now(), 'fmMM/DDfm/YYYY') as now_pretty + from bt_bugs b left outer join + cc_users asgnu on (asgnu.user_id = b.assignee), + acs_objects o, + bt_components c, + bt_priority_codes pc, + bt_severity_codes sc, + cc_users submitter + where b.bug_id = :bug_id + and o.object_id = b.bug_id + and c.component_id = b.component_id + and pc.priority_id = b.priority + and sc.severity_id = b.severity + and submitter.user_id = o.creation_user + + + + + + select ba.action_id, + ba.action as loop_action, + ba.resolution, + ba.actor as actor_user_id, + actor.first_names as actor_first_names, + actor.last_name as actor_last_name, + actor.email as actor_email, + ba.action_date, + to_char(ba.action_date, 'fmMM/DDfm/YYYY') as action_date_pretty, + ba.comment, + ba.comment_format + from bt_bug_actions ba, + cc_users actor + where ba.bug_id = :bug_id + and actor.user_id = ba.actor + order by action_date + + + + + + select bt_bug__new( + :bug_id, + :package_id, + :component_id, + :bug_type, + :severity, + :priority, + :found_in_version, + :summary, + :description, + :desc_format, + :user_agent, + :user_id, + :ip_address + ) + + + + Index: openacs-4/packages/bug-tracker/tcl/bug-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/tcl/bug-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/bug-tracker/tcl/bug-procs.tcl 13 Jan 2003 15:26:06 -0000 1.1 @@ -0,0 +1,234 @@ +ad_library { + + Bug Tracker Bug Library + + Procedures that deal with a single bug + + @creation-date 2003-01-10 + @author Lars Pind + @cvs-id $Id: bug-procs.tcl,v 1.1 2003/01/13 15:26:06 lars Exp $ + +} + +namespace eval bug_tracker::bug {} + +ad_proc -public bug_tracker::bug::get { + {-bug_id:required} + {-array:required} +} { + Get the fields for a bug +} { + # Select the info into the upvar'ed Tcl Array + upvar $array row + + db_1row select_bug_data {} -column_array row + + set row(bug_number_display) "#$row(bug_number)" + set row(submitter_display) "[acs_community_member_link -user_id $row(submitter_user_id) \ + -label "$row(submitter_first_names) $row(submitter_last_name)" \ + ] ($row(submitter_email))" + set row(assignee_display) [ad_decode $row(assignee) "" "Unassigned" " + [acs_community_member_link -user_id $row(assignee) \ + -label "$row(assignee_first_names) $row(assignee_last_name)"] + ($row(assignee_email))"] +} + +ad_proc -public bug_tracker::bug::get_activity_html { + -bug_id:required +} { + Get the activity log for a bug as an HTML chunk +} { + set action_html {} + + db_foreach actions {} { + append action_html "$action_date_pretty [bug_tracker::bug_action_pretty $loop_action $resolution] by $actor_first_names $actor_last_name +
[bug_tracker::bug_convert_comment_to_html -comment $comment -format $comment_format]
" + } + + return $action_html +} + +ad_proc -public bug_tracker::bug::insert { + -bug_id:required + -package_id:required + -component_id:required + -bug_type:required + -severity:required + -priority:required + -found_in_version:required + -summary:required + -description:required + -desc_format:required + {-user_agent ""} + {-user_id ""} + {-ip_address ""} +} { + Inserts a new bug into the database. Usually, you'll want to use bug_tracker::bug::new + because that one sends out notifications, etc. + + @see bug_tracker::bug::new + @return bug_id The same bug_id passed in, just for convenience. + +} { + if { ![exists_and_not_null user_id] } { + set user_id [ad_conn user_id] + } + if { ![exists_and_not_null user_agent] } { + set user_agent [ns_set get [ns_conn headers] "User-Agent"] + } + if { ![exists_and_not_null ip_address] } { + set ip_address [ns_conn peeraddr] + } + + db_exec_plsql bug_new {} + + return $bug_id +} + +ad_proc -public bug_tracker::bug::new { + -bug_id:required + -package_id:required + -component_id:required + -bug_type:required + -severity:required + -priority:required + -found_in_version:required + -summary:required + -description:required + -desc_format:required + {-user_agent ""} + {-user_id ""} + {-ip_address ""} +} { + Create a new bug, then send out notifications, starts workflow, etc. + + Calls bug_tracker::bug::insert. + + @see bug_tracker::bug::insert. + @return bug_id The same bug_id passed in, just for convenience. +} { + bug_tracker::bug::insert \ + -bug_id $bug_id \ + -package_id $package_id \ + -component_id $component_id \ + -bug_type $bug_type \ + -severity $severity \ + -priority $priority \ + -found_in_version $found_in_version \ + -summary $summary \ + -description $description \ + -desc_format $desc_format \ + -user_agent $user_agent \ + -user_id $user_id \ + -ip_address $ip_address + + bug_tracker::bug_notify -bug_id $bug_id -action "open" -comment $description -comment_format $desc_format + + # Sign up the submitter of the bug for instant alerts. We do this after calling + # the alert procedure so that the submitter isn't alerted about his own submittal of the bug + bug_tracker::add_instant_alert -bug_id $bug_id -user_id $user_id + + return $bug_id +} + + +ad_proc -public bug_tracker::bug::update { + -bug_id:required + -action:required + {-user_id ""} + -description:required + -desc_format:required + -array:required +} { + Update a bug in the DB. Usually, you'll want to use bug_tracker::bug::edit + because that one sends out notifications, etc. + + @see bug_tracker::bug::edit + @return bug_id The same bug_id passed in, just for convenience. +} { + upvar $array row + + if { ![exists_and_not_null user_id] } { + set user_id [ad_conn user_id] + } + + set update_exprs [list] + + foreach column [array names row] { + set var_$column $row($column) + lappend update_exprs "$column = :var_$column" + } + + db_transaction { + if { [llength $update_exprs] > 0 } { + db_dml update_bug "update bt_bugs \n set [join $update_exprs ",\n "] \n where bug_id = :bug_id" + } + + set action_id [db_nextval "acs_object_id_seq"] + + set resolution {} + if { [exists_and_not_null row(resolution)] } { + set resolution $row(resolution) + } + + db_dml bug_action { + insert into bt_bug_actions + (action_id, bug_id, action, resolution, actor, comment, comment_format) + values + (:action_id, :bug_id, :action, :resolution, :user_id, :description, :desc_format) + } + } + + return $bug_id +} + +ad_proc -public bug_tracker::bug::edit { + -bug_id:required + -action:required + {-user_id ""} + -description:required + -desc_format:required + -array:required +} { + Edit a bug, then send out notifications, etc. + + Calls bug_tracker::bug::update. + + @see bug_tracker::bug::update + @return bug_id The same bug_id passed in, just for convenience. +} { + upvar $array row + + db_transaction { + # Update the bug infor + update \ + -bug_id $bug_id \ + -action $action \ + -user_id $user_id \ + -description $description \ + -desc_format $desc_format \ + -array row + + # Setup any assignee for alerts on the bug + if { [info exists row(assignee)] && ![empty_string_p $row(assignee)] } { + bug_tracker::add_instant_alert \ + -bug_id $bug_id \ + -user_id $row(assignee) + } + } + + set resolution {} + if { [exists_and_not_null row(resolution)] } { + set resolution $row(resolution) + } + + # Send out notifications + bug_tracker::bug_notify \ + -bug_id $bug_id \ + -action $action \ + -comment $description \ + -comment_format $desc_format \ + -resolution $resolution + + return $bug_id +} Index: openacs-4/packages/bug-tracker/tcl/bug-tracker-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/tcl/bug-tracker-procs.tcl,v diff -u -r1.16 -r1.17 --- openacs-4/packages/bug-tracker/tcl/bug-tracker-procs.tcl 9 Dec 2002 21:24:12 -0000 1.16 +++ openacs-4/packages/bug-tracker/tcl/bug-tracker-procs.tcl 13 Jan 2003 15:26:06 -0000 1.17 @@ -8,650 +8,650 @@ } -namespace eval bug_tracker { +namespace eval ::bug_tracker {} - ad_proc conn { args } { - - global bt_conn - - set flag [lindex $args 0] - if { [string index $flag 0] != "-" } { - set var $flag - set flag "-get" - } else { - set var [lindex $args 1] +ad_proc ::bug_tracker::conn { args } { + + global bt_conn + + set flag [lindex $args 0] + if { [string index $flag 0] != "-" } { + set var $flag + set flag "-get" + } else { + set var [lindex $args 1] + } + + switch -- $flag { + -set { + set bt_conn($var) [lindex $args 2] } - - switch -- $flag { - -set { - set bt_conn($var) [lindex $args 2] - } - - -get { - if { [info exists bt_conn($var)] } { - return $bt_conn($var) - } else { - switch -- $var { - project_name - project_description - current_version_id - current_version_name { - array set info [get_project_info] + + -get { + if { [info exists bt_conn($var)] } { + return $bt_conn($var) + } else { + switch -- $var { + project_name - project_description - current_version_id - current_version_name { + array set info [get_project_info] + foreach name [array names info] { + set bt_conn($name) $info($name) + } + return $bt_conn($var) + } + user_first_names - user_last_name - user_email - user_version_id - user_version_name { + if { [ad_conn user_id] == 0 } { + return "" + } else { + array set info [get_user_prefs] foreach name [array names info] { set bt_conn($name) $info($name) } return $bt_conn($var) } - user_first_names - user_last_name - user_email - user_version_id - user_version_name { - if { [ad_conn user_id] == 0 } { - return "" - } else { - array set info [get_user_prefs] - foreach name [array names info] { - set bt_conn($name) $info($name) - } - return $bt_conn($var) - } - } - component_id - filter - filter_human_readable - filter_where_clauses - filter_order_by_clause { - return {} - } - default { - error "Unknown variable $var" - } } + component_id - filter - filter_human_readable - filter_where_clauses - filter_order_by_clause { + return {} + } + default { + error "Unknown variable $var" + } } } - - default { - error "bt_conn: unknown flag $flag" - } } - } - ad_proc get_bug_id { - {-bug_number:required} - {-project_id:required} - } { - return [db_string bug_id { select bug_id from bt_bugs where bug_number = :bug_number and project_id = :project_id }] + default { + error "bt_conn: unknown flag $flag" + } } +} + +ad_proc ::bug_tracker::get_bug_id { + {-bug_number:required} + {-project_id:required} +} { + return [db_string bug_id { select bug_id from bt_bugs where bug_number = :bug_number and project_id = :project_id }] +} + +##### +# +# Cached project info procs +# +##### + +ad_proc ::bug_tracker::get_project_info_internal { + package_id +} { + set found_p [db_0or1row project_info { + select pck.instance_name as project_name, + prj.description as project_description, + ver.version_id as current_version_id, + coalesce(ver.version_name, 'None') as current_version_name + from apm_packages pck, + bt_projects prj + left outer join bt_versions ver + on (ver.project_id = prj.project_id and active_version_p = 't') + where pck.package_id = :package_id + and prj.project_id = pck.package_id + } -column_array result] - ##### - # - # Cached project info procs - # - ##### - - ad_proc get_project_info_internal { - package_id - } { - set found_p [db_0or1row project_info { - select pck.instance_name as project_name, - prj.description as project_description, - ver.version_id as current_version_id, - coalesce(ver.version_name, 'None') as current_version_name - from apm_packages pck, - bt_projects prj - left outer join bt_versions ver - on (ver.project_id = prj.project_id and active_version_p = 't') - where pck.package_id = :package_id - and prj.project_id = pck.package_id - } -column_array result] - - if { !$found_p } { - set count [db_string count_project { select count(*) from bt_projects where project_id = :package_id }] - if { $count == 0 } { - db_exec_plsql create_project { - select bt_project__new(:package_id) - } - # we call ourselves again, so we'll get the info this time - return [get_project_info_internal $package_id] - } else { - error "Couldn't find project in database" + if { !$found_p } { + set count [db_string count_project { select count(*) from bt_projects where project_id = :package_id }] + if { $count == 0 } { + db_exec_plsql create_project { + select bt_project__new(:package_id) } + # we call ourselves again, so we'll get the info this time + return [get_project_info_internal $package_id] } else { - return [array get result] + error "Couldn't find project in database" } + } else { + return [array get result] } - - ad_proc get_project_info { - -package_id - } { - if { ![info exists package_id] } { - set package_id [ad_conn package_id] - } - - # temp hack: don't cache - return [get_project_info_internal $package_id] - - # return [util_memoize "bt_get_project_info_internal $package_id"] +} + +ad_proc ::bug_tracker::get_project_info { + -package_id +} { + if { ![info exists package_id] } { + set package_id [ad_conn package_id] } + + # temp hack: don't cache + return [get_project_info_internal $package_id] + + # return [util_memoize "bt_get_project_info_internal $package_id"] +} + +ad_proc ::bug_tracker::set_project_name { + -package_id + project_name +} { + if { ![info exists package_id] } { + set package_id [ad_conn package_id] + } - ad_proc set_project_name { - -package_id - project_name - } { - if { ![info exists package_id] } { - set package_id [ad_conn package_id] - } - - db_dml project_name_update { - update apm_packages - set instance_name = :project_name - where package_id = :package_id - } - - # Flush cache - util_memoize_flush "bt_get_project_info_internal $package_id" + db_dml project_name_update { + update apm_packages + set instance_name = :project_name + where package_id = :package_id } + # Flush cache + util_memoize_flush "bt_get_project_info_internal $package_id" +} - ##### - # - # Cached user prefs procs - # - ##### - ad_proc get_user_prefs_internal { - package_id - user_id - } { - set found_p [db_0or1row user_info { - select u.first_names as user_first_names, - u.last_name as user_last_name, - u.email as user_email, - ver.version_id as user_version_id, - coalesce(ver.version_name, 'None') as user_version_name - from cc_users u, - bt_user_prefs up - left outer join bt_versions ver - on (ver.version_id = up.user_version) - where u.user_id = :user_id - and up.user_id = u.user_id - and up.project_id = :package_id - } -column_array result] - - if { !$found_p } { - set count [db_string count_user_prefs { select count(*) from bt_user_prefs where project_id = :package_id and user_id = :user_id }] - if { $count == 0 } { - db_dml create_user_prefs { - insert into bt_user_prefs (user_id, project_id) values (:user_id, :package_id) - } - # we call ourselves again, so we'll get the info this time - return [get_user_prefs_internal $package_id $user_id] - } else { - error "Couldn't find user in database" +##### +# +# Cached user prefs procs +# +##### + +ad_proc ::bug_tracker::get_user_prefs_internal { + package_id + user_id +} { + set found_p [db_0or1row user_info { + select u.first_names as user_first_names, + u.last_name as user_last_name, + u.email as user_email, + ver.version_id as user_version_id, + coalesce(ver.version_name, 'None') as user_version_name + from cc_users u, + bt_user_prefs up + left outer join bt_versions ver + on (ver.version_id = up.user_version) + where u.user_id = :user_id + and up.user_id = u.user_id + and up.project_id = :package_id + } -column_array result] + + if { !$found_p } { + set count [db_string count_user_prefs { select count(*) from bt_user_prefs where project_id = :package_id and user_id = :user_id }] + if { $count == 0 } { + db_dml create_user_prefs { + insert into bt_user_prefs (user_id, project_id) values (:user_id, :package_id) } + # we call ourselves again, so we'll get the info this time + return [get_user_prefs_internal $package_id $user_id] } else { - return [array get result] + error "Couldn't find user in database" } + } else { + return [array get result] } - - ad_proc get_user_prefs { - -package_id - -user_id - } { - if { ![info exists package_id] } { - set package_id [ad_conn package_id] - } - - if { ![info exists user_id] } { - set user_id [ad_conn user_id] - } - - return [util_memoize "bug_tracker::get_user_prefs_internal $package_id $user_id"] +} + +ad_proc ::bug_tracker::get_user_prefs { + -package_id + -user_id +} { + if { ![info exists package_id] } { + set package_id [ad_conn package_id] } - ad_proc get_user_prefs_flush { - -package_id - -user_id - } { - if { ![info exists package_id] } { - set package_id [ad_conn package_id] - } - - if { ![info exists user_id] } { - set user_id [ad_conn user_id] - } - - util_memoize_flush "bug_tracker::get_user_prefs_internal $package_id $user_id" + if { ![info exists user_id] } { + set user_id [ad_conn user_id] } - - - ##### - # - # Bug Types - # - ##### - - ad_proc bug_type_get_options {} { - return { { "Bug" bug } { "Suggestion" suggestion } { "Todo" todo } } + + return [util_memoize "bug_tracker::get_user_prefs_internal $package_id $user_id"] +} + +ad_proc ::bug_tracker::get_user_prefs_flush { + -package_id + -user_id +} { + if { ![info exists package_id] } { + set package_id [ad_conn package_id] } - - ad_proc bug_type_pretty { - bug_type - } { - array set bug_types { - bug "Bug" - suggestion "Suggestion" - todo "Todo" - } - if { [info exists bug_types($bug_type)] } { - return $bug_types($bug_type) - } else { - return "" - } + + if { ![info exists user_id] } { + set user_id [ad_conn user_id] } + + util_memoize_flush "bug_tracker::get_user_prefs_internal $package_id $user_id" +} - ##### - # - # Status - # - ##### - - ad_proc status_get_options {} { - return { { "Open" open } { "Resolved" resolved } { "Closed" closed } } +##### +# +# Bug Types +# +##### + +ad_proc ::bug_tracker::bug_type_get_options {} { + return { { "Bug" bug } { "Suggestion" suggestion } { "Todo" todo } } +} + +ad_proc ::bug_tracker::bug_type_pretty { + bug_type +} { + array set bug_types { + bug "Bug" + suggestion "Suggestion" + todo "Todo" } - - ad_proc status_pretty { - status - } { - array set status_codes { - open "Open" - resolved "Resolved" - closed "Closed" - } - if { [info exists status_codes($status)] } { - return $status_codes($status) - } else { - return "" - } + if { [info exists bug_types($bug_type)] } { + return $bug_types($bug_type) + } else { + return "" } +} - ad_proc patch_status_get_options {} { - return { { "Open" open } { "Accepted" accepted } { "Refused" refused } { "Deleted" deleted }} + +##### +# +# Status +# +##### + +ad_proc ::bug_tracker::status_get_options {} { + return { { "Open" open } { "Resolved" resolved } { "Closed" closed } } +} + +ad_proc ::bug_tracker::status_pretty { + status +} { + array set status_codes { + open "Open" + resolved "Resolved" + closed "Closed" } + if { [info exists status_codes($status)] } { + return $status_codes($status) + } else { + return "" + } +} - ad_proc patch_status_pretty { - status - } { - array set status_codes { - open "Open" - accepted "Accepted" - refused "Refused" - deleted "Deleted" - } - if { [info exists status_codes($status)] } { - return $status_codes($status) - } else { - return "" - } - } - - ##### - # - # Resolution - # - ##### - - ad_proc resolution_get_options {} { - return { - { "Fixed" fixed } { "By Design" bydesign } { "Won't Fix" wontfix } { "Postponed" postponed } - { "Duplicate" duplicate } { "Not Reproducable" norepro } { "Need Info" needinfo } - } +ad_proc ::bug_tracker::patch_status_get_options {} { + return { { "Open" open } { "Accepted" accepted } { "Refused" refused } { "Deleted" deleted }} +} + +ad_proc ::bug_tracker::patch_status_pretty { + status +} { + array set status_codes { + open "Open" + accepted "Accepted" + refused "Refused" + deleted "Deleted" } - - ad_proc resolution_pretty { - resolution - } { - array set resolution_codes { - fixed "Fixed" - bydesign "By Design" - wontfix "Won't Fix" - postponed "Postponed" - duplicate "Duplicate" - norepro "Not Reproducable" - needinfo "Need Info" - } - if { [info exists resolution_codes($resolution)] } { - return $resolution_codes($resolution) - } else { - return "" - } + if { [info exists status_codes($status)] } { + return $status_codes($status) + } else { + return "" } +} - - - ##### - # - # Severity/Priority codes - # - ##### - - ad_proc severity_codes_get_options { - } { - set package_id [ad_conn package_id] - - set severity_list [db_list_of_lists severities { - select sort_order || ' - ' || severity_name, severity_id - from bt_severity_codes - where project_id = :package_id - order by sort_order - }] - - return $severity_list +##### +# +# Resolution +# +##### + +ad_proc ::bug_tracker::resolution_get_options {} { + return { + { "Fixed" fixed } { "By Design" bydesign } { "Won't Fix" wontfix } { "Postponed" postponed } + { "Duplicate" duplicate } { "Not Reproducable" norepro } { "Need Info" needinfo } } - - ad_proc severity_get_default { - } { - set package_id [ad_conn package_id] - - set default_severity_id [db_string default_severity { - select severity_id - from bt_severity_codes - where project_id = :package_id - and default_p = 't' - order by sort_order - limit 1 - } -default ""] - - return $default_severity_id +} + +ad_proc ::bug_tracker::resolution_pretty { + resolution +} { + array set resolution_codes { + fixed "Fixed" + bydesign "By Design" + wontfix "Won't Fix" + postponed "Postponed" + duplicate "Duplicate" + norepro "Not Reproducable" + needinfo "Need Info" } - - ad_proc priority_codes_get_options { - } { - set package_id [ad_conn package_id] - - set priority_list [db_list_of_lists priorities { - select sort_order || ' - ' || priority_name, priority_id - from bt_priority_codes - where project_id = :package_id - order by sort_order - }] - - return $priority_list + if { [info exists resolution_codes($resolution)] } { + return $resolution_codes($resolution) + } else { + return "" } +} - ad_proc priority_get_default { - } { - set package_id [ad_conn package_id] - - set default_priority_id [db_string default_priority { - select priority_id - from bt_priority_codes - where project_id = :package_id - and default_p = 't' - order by sort_order - limit 1 - } -default ""] - - return $default_priority_id - } +##### +# +# Severity/Priority codes +# +##### + +ad_proc ::bug_tracker::severity_codes_get_options { +} { + set package_id [ad_conn package_id] - ##### - # - # Versions - # - ##### - - ad_proc version_get_options { - -include_unknown:boolean - -include_undecided:boolean - } { - set package_id [ad_conn package_id] + set severity_list [db_list_of_lists severities { + select sort_order || ' - ' || severity_name, severity_id + from bt_severity_codes + where project_id = :package_id + order by sort_order + }] - set versions_list [db_list_of_lists versions \ - { select version_name, version_id from bt_versions where project_id = :package_id order by version_name }] + return $severity_list +} + +ad_proc ::bug_tracker::severity_get_default { +} { + set package_id [ad_conn package_id] - if { $include_unknown_p } { - set versions_list [concat { { "Unknown" "" } } $versions_list] - } - - if { $include_undecided_p } { - set versions_list [concat { { "Undecided" "" } } $versions_list] - } - - return $versions_list - } + set default_severity_id [db_string default_severity { + select severity_id + from bt_severity_codes + where project_id = :package_id + and default_p = 't' + order by sort_order + limit 1 + } -default ""] + return $default_severity_id +} + +ad_proc ::bug_tracker::priority_codes_get_options { +} { + set package_id [ad_conn package_id] - ##### - # - # Components - # - ##### + set priority_list [db_list_of_lists priorities { + select sort_order || ' - ' || priority_name, priority_id + from bt_priority_codes + where project_id = :package_id + order by sort_order + }] - ad_proc components_get_options { - -include_unknown:boolean - } { - set package_id [ad_conn package_id] + return $priority_list +} + +ad_proc ::bug_tracker::priority_get_default { +} { + set package_id [ad_conn package_id] - set components_list [db_list_of_lists components \ - { select component_name, component_id from bt_components where project_id = :package_id order by component_name }] + set default_priority_id [db_string default_priority { + select priority_id + from bt_priority_codes + where project_id = :package_id + and default_p = 't' + order by sort_order + limit 1 + } -default ""] - if { $include_unknown_p } { - set components_list [concat { { "Unknown" "" } } $components_list] - } - - return $components_list - } + return $default_priority_id +} + + + +##### +# +# Versions +# +##### + +ad_proc ::bug_tracker::version_get_options { + -include_unknown:boolean + -include_undecided:boolean +} { + set package_id [ad_conn package_id] + set versions_list [db_list_of_lists versions \ + { select version_name, version_id from bt_versions where project_id = :package_id order by version_name }] + + if { $include_unknown_p } { + set versions_list [concat { { "Unknown" "" } } $versions_list] + } - ##### - # - # Description - # - ##### + if { $include_undecided_p } { + set versions_list [concat { { "Undecided" "" } } $versions_list] + } - ad_proc bug_convert_comment_to_html { - -comment - -format - } { - switch $format { - html { - return [ad_html_text_convert -from html -to html -- $comment] - } - pre { - return "
[ad_html_text_convert -from html -to html -- $comment]
" - } - default { - return [ad_html_text_convert -from text -to html -- $comment] - } - } - } + return $versions_list +} + + +##### +# +# Components +# +##### + +ad_proc ::bug_tracker::components_get_options { + -include_unknown:boolean +} { + set package_id [ad_conn package_id] + + set components_list [db_list_of_lists components \ + { select component_name, component_id from bt_components where project_id = :package_id order by component_name }] + + if { $include_unknown_p } { + set components_list [concat { { "Unknown" "" } } $components_list] + } - ad_proc bug_convert_comment_to_text { - -comment - -format - } { - switch $format { - html { - return [ad_html_text_convert -from html -to text -- $comment] - } - default { - return [ad_html_text_convert -from text -to text -- $comment] - } + return $components_list +} + + +##### +# +# Description +# +##### + +ad_proc ::bug_tracker::bug_convert_comment_to_html { + -comment + -format +} { + switch $format { + html { + return [ad_html_text_convert -from html -to html -- $comment] } + pre { + return "
[ad_html_text_convert -from html -to html -- $comment]
" + } + default { + return [ad_html_text_convert -from text -to html -- $comment] + } } - - ##### - # - # Actions - # - ##### - - ad_proc bug_action_pretty { - action - {resolution ""} - } { - array set action_codes { - open "Opened" - edit "Edited" - reassign "Reassigned" - comment "Comment" - resolve "Resolved" - reopen "Reopened" - close "Closed" - patched "Patched" +} + +ad_proc ::bug_tracker::bug_convert_comment_to_text { + -comment + -format +} { + switch $format { + html { + return [ad_html_text_convert -from html -to text -- $comment] } - if { [info exists action_codes($action)] } { + default { + return [ad_html_text_convert -from text -to text -- $comment] + } + } +} - set action_pretty $action_codes($action) +##### +# +# Actions +# +##### - if { [string equal $action "resolve"] } { - set resolution_pretty [resolution_pretty $resolution] - if { ![empty_string_p $resolution_pretty] } { - append action_pretty " ($resolution_pretty)" - } - } +ad_proc ::bug_tracker::bug_action_pretty { + action + {resolution ""} +} { + array set action_codes { + open "Opened" + edit "Edited" + reassign "Reassigned" + comment "Comment" + resolve "Resolved" + reopen "Reopened" + close "Closed" + patched "Patched" + } + if { [info exists action_codes($action)] } { - return $action_pretty - } else { - return "" - } - } - - ad_proc patch_action_pretty { - action - } { + set action_pretty $action_codes($action) - array set action_codes { - open "Opened" - edit "Edited" - comment "Comment" - accept "Accepted" - reopen "Reopened" - refuse "Refused" - delete "Deleted" + if { [string equal $action "resolve"] } { + set resolution_pretty [resolution_pretty $resolution] + if { ![empty_string_p $resolution_pretty] } { + append action_pretty " ($resolution_pretty)" + } } - if { [info exists action_codes($action)] } { - return $action_codes($action) - } else { - return "" - } + return $action_pretty + } else { + return "" } +} - ##### - # - # Users (assignee) - # - ##### - - ad_proc users_get_options { - -package_id - } { - if { ![info exists package_id] } { - set package_id [ad_conn package_id] - } +ad_proc ::bug_tracker::patch_action_pretty { + action +} { - set user_id [ad_conn user_id] + array set action_codes { + open "Opened" + edit "Edited" + comment "Comment" + accept "Accepted" + reopen "Reopened" + refuse "Refused" + delete "Deleted" + } - # This picks out users who are already assigned to some bug in this - set sql { - select distinct q.* - from ( - select u.first_names || ' ' || u.last_name || ' (' || u.email || ')' as name, u.user_id - from bt_bugs b, cc_users u - where b.project_id = :package_id - and u.user_id = b.assignee - union - select u.first_names || ' ' || u.last_name || ' (' || u.email || ')' as name, u.user_id - from cc_users u - where u.user_id = :user_id - ) q - order by name - } + if { [info exists action_codes($action)] } { + return $action_codes($action) + } else { + return "" + } +} - set users_list [db_list_of_lists users $sql] - - set users_list [concat { { "Unassigned" "" } } $users_list] - lappend users_list { "Search..." ":search:"} +##### +# +# Users (assignee) +# +##### - return $users_list +ad_proc ::bug_tracker::users_get_options { + -package_id +} { + if { ![info exists package_id] } { + set package_id [ad_conn package_id] } + + set user_id [ad_conn user_id] + + # This picks out users who are already assigned to some bug in this + set sql { + select distinct q.* + from ( + select u.first_names || ' ' || u.last_name || ' (' || u.email || ')' as name, u.user_id + from bt_bugs b, cc_users u + where b.project_id = :package_id + and u.user_id = b.assignee + union + select u.first_names || ' ' || u.last_name || ' (' || u.email || ')' as name, u.user_id + from cc_users u + where u.user_id = :user_id + ) q + order by name + } + + set users_list [db_list_of_lists users $sql] + + set users_list [concat { { "Unassigned" "" } } $users_list] + lappend users_list { "Search..." ":search:"} + + return $users_list +} - ##### - # - # Notification - # - ##### - - ad_proc bug_notify { - {-bug_id:required} - {-action ""} - {-comment ""} - {-comment_format ""} - {-resolution ""} - {-patch_summary ""} - } { - set package_id [ad_conn package_id] - - db_1row bug { - select b.bug_id, - b.bug_number, - b.summary, - b.project_id, - o.creation_user as submitter_user_id, - submitter.first_names as submitter_first_names, - submitter.last_name as submitter_last_name, - submitter.email as submitter_email, - b.component_id, - c.component_name, - o.creation_date, - to_char(o.creation_date, 'fmMM/DDfm/YYYY') as creation_date_pretty, - b.severity, - sc.sort_order || ' - ' || sc.severity_name as severity_pretty, - b.priority, - pc.sort_order || ' - ' || pc.priority_name as priority_pretty, - b.status, - b.resolution, - b.bug_type, - b.user_agent, - b.original_estimate_minutes, - b.latest_estimate_minutes, - b.elapsed_time_minutes, - b.found_in_version, - coalesce((select version_name - from bt_versions found_in_v - where found_in_v.version_id = b.found_in_version), 'Unknown') as found_in_version_name, - b.fix_for_version, - coalesce((select version_name - from bt_versions fix_for_v - where fix_for_v.version_id = b.fix_for_version), 'Undecided') as fix_for_version_name, - b.fixed_in_version, - coalesce((select version_name - from bt_versions fixed_in_v - where fixed_in_v.version_id = b.fixed_in_version), 'Unknown') as fixed_in_version_name, - b.assignee as assignee_user_id, - assignee.first_names as assignee_first_names, - assignee.last_name as assignee_last_name, - assignee.email as assignee_email, - to_char(now(), 'fmMon/DDfm/YYYY') as now_pretty - from bt_bugs b left outer join - cc_users assignee on (assignee.user_id = b.assignee), - acs_objects o, - bt_components c, - bt_priority_codes pc, - bt_severity_codes sc, - cc_users submitter - where b.bug_id = :bug_id - and b.project_id = :package_id - and o.object_id = b.bug_id - and c.component_id = b.component_id - and pc.priority_id = b.priority - and sc.severity_id = b.severity - and submitter.user_id = o.creation_user - } -column_array bug +##### +# +# Notification +# +##### - set subject "Bug #$bug(bug_number). [ad_html_to_text -- [string_truncate -len 30 $bug(summary)]]: [bug_action_pretty $action $resolution] by [conn user_first_names] [conn user_last_name]" +ad_proc ::bug_tracker::bug_notify { + {-bug_id:required} + {-action ""} + {-comment ""} + {-comment_format ""} + {-resolution ""} + {-patch_summary ""} +} { + set package_id [ad_conn package_id] - set body "Bug no: #$bug(bug_number) + db_1row bug { + select b.bug_id, + b.bug_number, + b.summary, + b.project_id, + o.creation_user as submitter_user_id, + submitter.first_names as submitter_first_names, + submitter.last_name as submitter_last_name, + submitter.email as submitter_email, + b.component_id, + c.component_name, + o.creation_date, + to_char(o.creation_date, 'fmMM/DDfm/YYYY') as creation_date_pretty, + b.severity, + sc.sort_order || ' - ' || sc.severity_name as severity_pretty, + b.priority, + pc.sort_order || ' - ' || pc.priority_name as priority_pretty, + b.status, + b.resolution, + b.bug_type, + b.user_agent, + b.original_estimate_minutes, + b.latest_estimate_minutes, + b.elapsed_time_minutes, + b.found_in_version, + coalesce((select version_name + from bt_versions found_in_v + where found_in_v.version_id = b.found_in_version), 'Unknown') as found_in_version_name, + b.fix_for_version, + coalesce((select version_name + from bt_versions fix_for_v + where fix_for_v.version_id = b.fix_for_version), 'Undecided') as fix_for_version_name, + b.fixed_in_version, + coalesce((select version_name + from bt_versions fixed_in_v + where fixed_in_v.version_id = b.fixed_in_version), 'Unknown') as fixed_in_version_name, + b.assignee as assignee_user_id, + assignee.first_names as assignee_first_names, + assignee.last_name as assignee_last_name, + assignee.email as assignee_email, + to_char(now(), 'fmMon/DDfm/YYYY') as now_pretty + from bt_bugs b left outer join + cc_users assignee on (assignee.user_id = b.assignee), + acs_objects o, + bt_components c, + bt_priority_codes pc, + bt_severity_codes sc, + cc_users submitter + where b.bug_id = :bug_id + and b.project_id = :package_id + and o.object_id = b.bug_id + and c.component_id = b.component_id + and pc.priority_id = b.priority + and sc.severity_id = b.severity + and submitter.user_id = o.creation_user + } -column_array bug + + set subject "Bug #$bug(bug_number). [ad_html_to_text -- [string_truncate -len 30 $bug(summary)]]: [bug_action_pretty $action $resolution] by [conn user_first_names] [conn user_last_name]" + + set body "Bug no: #$bug(bug_number) Summary: $bug(summary) Component: $bug(component_name) @@ -665,426 +665,439 @@ " - if { ![string equal $action "patched"] } { - if { ![empty_string_p $comment] } { - append body "Comment:\n\n[bug_convert_comment_to_text -comment $comment -format $comment_format]\n\n" - } - - } else { - append body "\n\nSummary: $patch_summary\n\n" + if { ![string equal $action "patched"] } { + if { ![empty_string_p $comment] } { + append body "Comment:\n\n[bug_convert_comment_to_text -comment $comment -format $comment_format]\n\n" } - - append body "--\nTo comment on, edit, resolve, close, or reopen this bug, go to:\n[ad_url][ad_conn package_url]bug?[export_vars -url { { bug_number $bug(bug_number) } }]\n" + } else { + append body "\n\nSummary: $patch_summary\n\n" + } - # Use the Notification service to alert (could be immediately, or daily, or weekly) - # people who have signed up for notification on this bug - notification::new \ - -type_id [notification::type::get_type_id -short_name bug_tracker_bug_notif] \ - -object_id $bug(bug_id) \ - -response_id $bug(bug_id) \ - -notif_subject $subject \ - -notif_text $body - - # Use the Notification service to alert people who have signed up for notification - # in this bug tracker package instance - notification::new \ - -type_id [notification::type::get_type_id -short_name bug_tracker_project_notif] \ - -object_id $bug(project_id) \ - -response_id $bug(bug_id) \ - -notif_subject $subject \ - -notif_text $body - } + + append body "--\nTo comment on, edit, resolve, close, or reopen this bug, go to:\n[ad_url][ad_conn package_url]bug?[export_vars -url { { bug_number $bug(bug_number) } }]\n" - ad_proc add_instant_alert { - {-bug_id:required} - {-user_id:required} - } { - notification::request::new \ - -type_id [notification::type::get_type_id -short_name bug_tracker_bug_notif] \ - -user_id $user_id \ - -object_id $bug_id \ - -interval_id [notification::get_interval_id -name "daily"] \ - -delivery_method_id [notification::get_delivery_method_id -name "email"] - } + # Use the Notification service to alert (could be immediately, or daily, or weekly) + # people who have signed up for notification on this bug + notification::new \ + -type_id [notification::type::get_type_id -short_name bug_tracker_bug_notif] \ + -object_id $bug(bug_id) \ + -response_id $bug(bug_id) \ + -notif_subject $subject \ + -notif_text $body + + # Use the Notification service to alert people who have signed up for notification + # in this bug tracker package instance + notification::new \ + -type_id [notification::type::get_type_id -short_name bug_tracker_project_notif] \ + -object_id $bug(project_id) \ + -response_id $bug(bug_id) \ + -notif_subject $subject \ + -notif_text $body +} - ad_proc get_notification_link { - {-type:required} - {-object_id:required} - {-pretty_name:required} - {-url:required} - } { - Returns a list with the url, label, and title for a notifications link (subscribe or unsubscribe). - } { +ad_proc ::bug_tracker::add_instant_alert { + {-bug_id:required} + {-user_id:required} +} { + notification::request::new \ + -type_id [notification::type::get_type_id -short_name bug_tracker_bug_notif] \ + -user_id $user_id \ + -object_id $bug_id \ + -interval_id [notification::get_interval_id -name "instant"] \ + -delivery_method_id [notification::get_delivery_method_id -name "email"] +} - set user_id [ad_conn user_id] +ad_proc ::bug_tracker::get_notification_link { + {-type:required} + {-object_id:required} + {-pretty_name:required} + {-url:required} +} { + Returns a list with the url, label, and title for a notifications link (subscribe or unsubscribe). +} { - set notification_link [list] - # Only present the link to logged in users. - if { $user_id != 0 } { - set type_id [notification::type::get_type_id -short_name $type] - if { [empty_string_p $type_id] } { - ns_log Error "Can't find notification of type '$type'" - return "" - } + set user_id [ad_conn user_id] - set request_id [notification::request::get_request_id -type_id $type_id -object_id $object_id -user_id $user_id] - - if { ![empty_string_p $request_id] } { - # The user is already subscribed - lappend notification_link [notification::display::unsubscribe_url -request_id $request_id -url $url] - lappend notification_link "Unsubscribe" - lappend notification_link "Unsubscribe from notifications for this $pretty_name" - } else { - # The user is not subscribed - lappend notification_link [notification::display::subscribe_url \ - -type bug_tracker_project_notif \ - -object_id $object_id \ - -url $url \ - -user_id $user_id \ - -pretty_name "a $pretty_name" - ] - lappend notification_link "Subscribe" - lappend notification_link "Subscribe to notifications for this $pretty_name" - } + set notification_link [list] + # Only present the link to logged in users. + if { $user_id != 0 } { + set type_id [notification::type::get_type_id -short_name $type] + if { [empty_string_p $type_id] } { + ns_log Error "Can't find notification of type '$type'" + return "" } - return $notification_link - } + set request_id [notification::request::get_request_id -type_id $type_id -object_id $object_id -user_id $user_id] - ad_proc map_patch_to_bug { - {-patch_id:required} - {-bug_id:required} - } { - db_dml map_patch_to_bug { - insert into bt_patch_bug_map (patch_id, bug_id) values (:patch_id, :bug_id) - } - } - - ad_proc unmap_patch_from_bug { - {-patch_number:required} - {-bug_number:required} - } { - set package_id [ad_conn package_id] - db_dml unmap_patch_from_bug { - delete from bt_patch_bug_map - where bug_id = (select bug_id from bt_bugs - where bug_number = :bug_number - and project_id = :package_id) - and patch_id = (select patch_id from bt_patches - where patch_number = :patch_number - and project_id = :package_id) + if { ![empty_string_p $request_id] } { + # The user is already subscribed + lappend notification_link [notification::display::unsubscribe_url -request_id $request_id -url $url] + lappend notification_link "Unsubscribe" + lappend notification_link "Unsubscribe from notifications for this $pretty_name" + } else { + # The user is not subscribed + lappend notification_link [notification::display::subscribe_url \ + -type bug_tracker_project_notif \ + -object_id $object_id \ + -url $url \ + -user_id $user_id \ + -pretty_name "a $pretty_name" + ] + lappend notification_link "Subscribe" + lappend notification_link "Subscribe to notifications for this $pretty_name" } } - ad_proc get_mapped_bugs { - {-patch_number:required} - {-only_open_p "0"} - } { - Return a list of lists with the bug number in the first element and the bug - summary in the second. - } { - set bug_list [list] - set package_id [ad_conn package_id] + return $notification_link +} - set open_clause [ad_decode $only_open_p "1" "\n and bt_bugs.status = 'open'" ""] +ad_proc ::bug_tracker::map_patch_to_bug { + {-patch_id:required} + {-bug_id:required} +} { + db_dml map_patch_to_bug { + insert into bt_patch_bug_map (patch_id, bug_id) values (:patch_id, :bug_id) + } +} - db_foreach get_bugs_for_patch "select bt_bugs.bug_number, - bt_bugs.summary - from bt_bugs, bt_patch_bug_map - where bt_bugs.bug_id = bt_patch_bug_map.bug_id - and bt_patch_bug_map.patch_id = (select patch_id - from bt_patches - where patch_number = :patch_number - and project_id = :package_id - ) - $open_clause" { +ad_proc ::bug_tracker::unmap_patch_from_bug { + {-patch_number:required} + {-bug_number:required} +} { + set package_id [ad_conn package_id] + db_dml unmap_patch_from_bug { + delete from bt_patch_bug_map + where bug_id = (select bug_id from bt_bugs + where bug_number = :bug_number + and project_id = :package_id) + and patch_id = (select patch_id from bt_patches + where patch_number = :patch_number + and project_id = :package_id) + } +} - lappend bug_list [list "$summary" "$bug_number"] - } +ad_proc ::bug_tracker::get_mapped_bugs { + {-patch_number:required} + {-only_open_p "0"} +} { + Return a list of lists with the bug number in the first element and the bug + summary in the second. +} { + set bug_list [list] + set package_id [ad_conn package_id] - return $bug_list + set open_clause [ad_decode $only_open_p "1" "\n and bt_bugs.status = 'open'" ""] + + db_foreach get_bugs_for_patch "select bt_bugs.bug_number, + bt_bugs.summary + from bt_bugs, bt_patch_bug_map + where bt_bugs.bug_id = bt_patch_bug_map.bug_id + and bt_patch_bug_map.patch_id = (select patch_id + from bt_patches + where patch_number = :patch_number + and project_id = :package_id + ) + $open_clause" { + + lappend bug_list [list "$summary" "$bug_number"] } - ad_proc get_bug_links { - {-patch_id:required} - {-patch_number:required} - {-write_or_submitter_p:required} - } { - set bug_list [get_mapped_bugs -patch_number $patch_number] - set bug_link_list [list] + return $bug_list +} - if { [llength $bug_list] == "0"} { - return "" - } else { - - foreach bug_item $bug_list { +ad_proc ::bug_tracker::get_bug_links { + {-patch_id:required} + {-patch_number:required} + {-write_or_submitter_p:required} +} { + set bug_list [get_mapped_bugs -patch_number $patch_number] + set bug_link_list [list] - set bug_number [lindex $bug_item 1] - set bug_summary [lindex $bug_item 0] + if { [llength $bug_list] == "0"} { + return "" + } else { + + foreach bug_item $bug_list { - set unmap_url "unmap-patch-from-bug?[export_vars -url { patch_number bug_number } ]" - if { $write_or_submitter_p } { - set unmap_link "(unmap)" - } else { - set unmap_link "" - } - lappend bug_link_list "$bug_summary $unmap_link" - } + set bug_number [lindex $bug_item 1] + set bug_summary [lindex $bug_item 0] - if { [llength $bug_link_list] != 0 } { - set bugs_string [join $bug_link_list ", "] + set unmap_url "unmap-patch-from-bug?[export_vars -url { patch_number bug_number } ]" + if { $write_or_submitter_p } { + set unmap_link "(unmap)" } else { - set bugs_string "No bugs." + set unmap_link "" } + lappend bug_link_list "$bug_summary $unmap_link" + } - return $bugs_string + if { [llength $bug_link_list] != 0 } { + set bugs_string [join $bug_link_list ", "] + } else { + set bugs_string "No bugs." } - } - ad_proc get_patch_links { - {-bug_id:required} - {-show_patch_status "open"} - } { - set patch_list [list] + return $bugs_string + } +} - switch -- $show_patch_status { - open { - set status_where_clause "and bt_patches.status = :show_patch_status" - } - all { - set status_where_clause "" - } - } +ad_proc ::bug_tracker::get_patch_links { + {-bug_id:required} + {-show_patch_status "open"} +} { + set patch_list [list] - db_foreach get_patches_for_bug \ - "select bt_patches.patch_number, - bt_patches.summary, - bt_patches.status - from bt_patch_bug_map, bt_patches - where bt_patch_bug_map.bug_id = :bug_id - and bt_patch_bug_map.patch_id = bt_patches.patch_id - $status_where_clause - " { - - set status_indicator [ad_decode $show_patch_status "all" "($status)" ""] - lappend patch_list "$summary $status_indicator" - } if_no_rows { - set patches_string "No patches." + switch -- $show_patch_status { + open { + set status_where_clause "and bt_patches.status = :show_patch_status" } - - if { [llength $patch_list] != 0 } { - set patches_string [join $patch_list ", "] + all { + set status_where_clause "" } - - return $patches_string } - ad_proc get_patch_submitter { - {-patch_number:required} - } { - set package_id [ad_conn package_id] - return [db_string patch_submitter_id "select acs_objects.creation_user - from bt_patches, acs_objects - where bt_patches.patch_number = :patch_number - and bt_patches.project_id = :package_id - and bt_patches.patch_id = acs_objects.object_id"] + db_foreach get_patches_for_bug \ + "select bt_patches.patch_number, + bt_patches.summary, + bt_patches.status + from bt_patch_bug_map, bt_patches + where bt_patch_bug_map.bug_id = :bug_id + and bt_patch_bug_map.patch_id = bt_patches.patch_id + $status_where_clause + " { + + set status_indicator [ad_decode $show_patch_status "all" "($status)" ""] + lappend patch_list "$summary $status_indicator" + } if_no_rows { + set patches_string "No patches." } - ad_proc update_patch_status { - {-patch_number:required} - {-new_status:required} - } { - set package_id [ad_conn package_id] - db_dml update_patch_status "update bt_patches - set status = :new_status - where bt_patches.project_id = :package_id - and bt_patches.patch_number = :patch_number" + if { [llength $patch_list] != 0 } { + set patches_string [join $patch_list ", "] } - ad_proc get_uploaded_patch_file_content { - - } { - set patch_file [ns_queryget patch_file] - - if { [empty_string_p $patch_file] } { - # No patch file was uploaded - return "" - } + return $patches_string +} - set tmp_file [ns_queryget patch_file.tmpfile] - set tmp_file_channel [open $tmp_file r] - set content [read $tmp_file_channel] +ad_proc ::bug_tracker::get_patch_submitter { + {-patch_number:required} +} { + set package_id [ad_conn package_id] + return [db_string patch_submitter_id "select acs_objects.creation_user + from bt_patches, acs_objects + where bt_patches.patch_number = :patch_number + and bt_patches.project_id = :package_id + and bt_patches.patch_id = acs_objects.object_id"] +} - return $content +ad_proc ::bug_tracker::update_patch_status { + {-patch_number:required} + {-new_status:required} +} { + set package_id [ad_conn package_id] + db_dml update_patch_status "update bt_patches + set status = :new_status + where bt_patches.project_id = :package_id + and bt_patches.patch_number = :patch_number" +} + +ad_proc ::bug_tracker::get_uploaded_patch_file_content { + +} { + set patch_file [ns_queryget patch_file] + + if { [empty_string_p $patch_file] } { + # No patch file was uploaded + return "" } - ad_proc parse_filters { filter_array_name } { - Parses the array named in 'filter_array_name', setting local - variables for the filter parameters, and constructing a chunk - that can be used in a query, plus a human readable - string. Sets the result in bug_tracker::conn as - 'filter_human_readable', 'filter_where_clauses', and - 'filter_order_by_clause'. - } { - upvar $filter_array_name filter + set tmp_file [ns_queryget patch_file.tmpfile] + set tmp_file_channel [open $tmp_file r] + set content [read $tmp_file_channel] - set where_clauses [list] + return $content +} - set valid_filters { - status - bug_type - fix_for_version:integer - severity:integer - priority:integer - assignee:integer - component_id:integer - actionby:integer - {orderby ""} - } - - foreach name $valid_filters { - if { [llength $name] > 1 } { - set default [lindex $name 1] - set name [lindex $name 0] - } else { - if { [info exists default] } { - unset default - } - } - if { [llength [split $name ":"]] > 1 } { - set filters [split [lindex [split $name ":"] 1] ,] - set name [lindex [split $name ":"] 0] - } else { - set filters [list] - } - if { [info exists filter($name)] } { - upvar __filter_$name var - set var $filter($name) +ad_proc ::bug_tracker::parse_filters { filter_array_name } { + Parses the array named in 'filter_array_name', setting local + variables for the filter parameters, and constructing a chunk + that can be used in a query, plus a human readable + string. Sets the result in bug_tracker::conn as + 'filter_human_readable', 'filter_where_clauses', and + 'filter_order_by_clause'. +} { + upvar $filter_array_name filter - if { [lsearch -exact $filters "integer"] != -1 && ![empty_string_p $var]} { - validate_integer $name $var - } - } elseif { [info exists default] } { - upvar __filter_$name var - set var $default + set where_clauses [list] + + set valid_filters { + status + bug_type + fix_for_version:integer + severity:integer + priority:integer + assignee:integer + component_id:integer + actionby:integer + {orderby ""} + } + + foreach name $valid_filters { + if { [llength $name] > 1 } { + set default [lindex $name 1] + set name [lindex $name 0] + } else { + if { [info exists default] } { + unset default } - # also upvar it under its real name - upvar __filter_$name __filter_$name } - - - if { ![info exists __filter_status] } { - if { [info exists __filter_actionby] } { - set __filter_status "" - } else { - set __filter_status "open" - } - } - - if { ![empty_string_p $__filter_status] } { - lappend where_clauses "b.status = :__filter_status" - set human_readable_filter "All $__filter_status bugs" + if { [llength [split $name ":"]] > 1 } { + set filters [split [lindex [split $name ":"] 1] ,] + set name [lindex [split $name ":"] 0] } else { - lappend where_clauses "b.status != 'closed'" - set human_readable_filter "All open and resolved bugs" + set filters [list] } - - if { [info exists __filter_bug_type] } { - lappend where_clauses "b.bug_type = :__filter_bug_type" - append human_readable_filter " of type [bug_tracker::bug_type_pretty $__filter_bug_type]" - } - - if { [info exists __filter_assignee] } { - if { [empty_string_p $__filter_assignee] } { - lappend where_clauses "b.assignee is null" - append human_readable_filter " that are unassigned" - } else { - lappend where_clauses "b.assignee = :__filter_assignee" - if { $__filter_assignee == [ad_conn user_id] } { - append human_readable_filter " assigned to me" - } else { - append human_readable_filter " assigned to [db_string assignee_name { select first_names || ' ' || last_name from cc_users where user_id = :__filter_assignee }]" - } + if { [info exists filter($name)] } { + upvar __filter_$name var + set var $filter($name) + + if { [lsearch -exact $filters "integer"] != -1 && ![empty_string_p $var]} { + validate_integer $name $var } + } elseif { [info exists default] } { + upvar __filter_$name var + set var $default } - + # also upvar it under its real name + upvar __filter_$name __filter_$name + } + + + if { ![info exists __filter_status] } { if { [info exists __filter_actionby] } { - lappend where_clauses "((b.status = 'open' and b.assignee = :__filter_actionby) or (b.status = 'resolved' and o.creation_user = :__filter_actionby))" - if { $__filter_actionby == [ad_conn user_id] } { - append human_readable_filter " awaiting action by me" + set __filter_status "" + } else { + set __filter_status "open" + } + } + + if { ![empty_string_p $__filter_status] } { + lappend where_clauses "b.status = :__filter_status" + set human_readable_filter "All $__filter_status bugs" + } else { + lappend where_clauses "b.status != 'closed'" + set human_readable_filter "All open and resolved bugs" + } + + if { [info exists __filter_bug_type] } { + lappend where_clauses "b.bug_type = :__filter_bug_type" + append human_readable_filter " of type [bug_tracker::bug_type_pretty $__filter_bug_type]" + } + + if { [info exists __filter_assignee] } { + if { [empty_string_p $__filter_assignee] } { + lappend where_clauses "b.assignee is null" + append human_readable_filter " that are unassigned" + } else { + lappend where_clauses "b.assignee = :__filter_assignee" + if { $__filter_assignee == [ad_conn user_id] } { + append human_readable_filter " assigned to me" } else { - append human_readable_filter " awaiting action by [db_string actionby_name { select first_names || ' ' || last_name from cc_users where user_id = :__filter_actionby }]" + append human_readable_filter " assigned to [db_string assignee_name { select first_names || ' ' || last_name from cc_users where user_id = :__filter_assignee }]" } } - - if { [info exists __filter_severity] } { - lappend where_clauses "b.severity = :__filter_severity" - append human_readable_filter " where severity is [db_string severity_name { select severity_name from bt_severity_codes where severity_id = :__filter_severity }]" + } + + if { [info exists __filter_actionby] } { + lappend where_clauses "((b.status = 'open' and b.assignee = :__filter_actionby) or (b.status = 'resolved' and o.creation_user = :__filter_actionby))" + if { $__filter_actionby == [ad_conn user_id] } { + append human_readable_filter " awaiting action by me" + } else { + append human_readable_filter " awaiting action by [db_string actionby_name { select first_names || ' ' || last_name from cc_users where user_id = :__filter_actionby }]" } - - if { [info exists __filter_priority] } { - lappend where_clauses "b.priority = :__filter_priority" - append human_readable_filter " with a priority of [db_string priority_name { select priority_name from bt_priority_codes where priority_id = :__filter_priority }]" - } - - if { ![empty_string_p [conn component_id]] } { - set __filter_component_id [conn component_id] - } + } + + if { [info exists __filter_severity] } { + lappend where_clauses "b.severity = :__filter_severity" + append human_readable_filter " where severity is [db_string severity_name { select severity_name from bt_severity_codes where severity_id = :__filter_severity }]" + } + + if { [info exists __filter_priority] } { + lappend where_clauses "b.priority = :__filter_priority" + append human_readable_filter " with a priority of [db_string priority_name { select priority_name from bt_priority_codes where priority_id = :__filter_priority }]" + } + + if { ![empty_string_p [conn component_id]] } { + set __filter_component_id [conn component_id] + } - if { [info exists __filter_component_id] } { - lappend where_clauses "b.component_id = :__filter_component_id" - append human_readable_filter " in [db_string component_name { select component_name from bt_components where component_id = :__filter_component_id }]" - conn -set component_id $__filter_component_id + if { [info exists __filter_component_id] } { + lappend where_clauses "b.component_id = :__filter_component_id" + append human_readable_filter " in [db_string component_name { select component_name from bt_components where component_id = :__filter_component_id }]" + conn -set component_id $__filter_component_id + } + + if { [info exists __filter_fix_for_version] } { + if { [empty_string_p $__filter_fix_for_version] } { + lappend where_clauses "b.fix_for_version is null" + append human_readable_filter " where fix for version is undecided" + } else { + lappend where_clauses "b.fix_for_version = :__filter_fix_for_version" + append human_readable_filter " to be fixed in version [db_string version_name { select version_name from bt_versions where version_id = :__filter_fix_for_version }]" } - - if { [info exists __filter_fix_for_version] } { - if { [empty_string_p $__filter_fix_for_version] } { - lappend where_clauses "b.fix_for_version is null" - append human_readable_filter " where fix for version is undecided" - } else { - lappend where_clauses "b.fix_for_version = :__filter_fix_for_version" - append human_readable_filter " to be fixed in version [db_string version_name { select version_name from bt_versions where version_id = :__filter_fix_for_version }]" - } + } + + switch -exact -- $__filter_orderby { + severity { + set order_by_clause "sc.sort_order, b.bug_number desc" + append human_readable_filter ", most severe bugs first" } - - switch -exact -- $__filter_orderby { - severity { - set order_by_clause "sc.sort_order, b.bug_number desc" - append human_readable_filter ", most severe bugs first" - } - priority { - set order_by_clause "pc.sort_order, b.bug_number desc" - append human_readable_filter ", highest priority bugs first" - } - default { - set order_by_clause "b.bug_number desc" - } + priority { + set order_by_clause "pc.sort_order, b.bug_number desc" + append human_readable_filter ", highest priority bugs first" } - - conn -set filter [array get filter] - conn -set filter_human_readable $human_readable_filter - conn -set filter_where_clauses $where_clauses - conn -set filter_order_by_clause $order_by_clause + default { + set order_by_clause "b.bug_number desc" + } } - ad_proc context_bar { args } { - Context bar that takes the component information into account - } { - set component_id [conn component_id] - if { ![empty_string_p $component_id] } { - db_1row component_name { - select component_name, url_name from bt_components where component_id = :component_id - } - if { [llength $args] == 0 } { - return [eval ad_context_bar [list $component_name]] - } else { - return [eval ad_context_bar [list [list "[ad_conn package_url]com/$url_name/" $component_name]] $args] - } + conn -set filter [array get filter] + conn -set filter_human_readable $human_readable_filter + conn -set filter_where_clauses $where_clauses + conn -set filter_order_by_clause $order_by_clause +} + +ad_proc ::bug_tracker::context_bar { args } { + Context bar that takes the component information into account +} { + set component_id [conn component_id] + if { ![empty_string_p $component_id] } { + db_1row component_name { + select component_name, url_name from bt_components where component_id = :component_id + } + if { [llength $args] == 0 } { + return [eval ad_context_bar [list $component_name]] } else { - return [eval ad_context_bar $args] + return [eval ad_context_bar [list [list "[ad_conn package_url]com/$url_name/" $component_name]] $args] } + } else { + return [eval ad_context_bar $args] } - } +ad_proc ::bug_tracker::security_violation { + -user_id:required + -bug_id:required + -action:required +} { + ns_log Notice "$user_id doesn't have permission to '$action' on bug $bug_id" + ad_return_forbidden \ + "Security Violation" \ + "
+ You don't have permission to '$action' on this bug. +
+ This incident has been logged. +
" + ad_script_abort +} Index: openacs-4/packages/bug-tracker/www/bug-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/www/bug-add.tcl,v diff -u -r1.7 -r1.8 --- openacs-4/packages/bug-tracker/www/bug-add.tcl 13 Sep 2002 08:30:32 -0000 1.7 +++ openacs-4/packages/bug-tracker/www/bug-add.tcl 13 Jan 2003 15:26:29 -0000 1.8 @@ -5,20 +5,13 @@ @creation-date 2002-03-25 @cvs-id $Id$ } { - cancel:optional {return_url ""} } if { [empty_string_p $return_url] } { set return_url "." } -# If the user hit cancel, ignore everything else -if { [exists_and_not_null cancel] } { - ad_returnredirect $return_url - ad_script_abort -} - ad_require_permission [ad_conn package_id] create # User needs to be logged in here @@ -38,7 +31,7 @@ # Create the form -form create bug +form create bug -cancel_url . element create bug bug_id \ -datatype integer \ @@ -123,39 +116,20 @@ if { [form is_valid bug] } { - db_transaction { - - form get_values bug bug_id component_id bug_type severity priority found_in_version summary description desc_format - - set ip_address [ns_conn peeraddr] - set user_agent [ns_set get [ns_conn headers] "User-Agent"] - - db_exec_plsql new_bug { - select bt_bug__new( - :bug_id, - :package_id, - :component_id, - :bug_type, - :severity, - :priority, - :found_in_version, - :summary, - :description, - :desc_format, - :user_agent, - :user_id, - :ip_address - ) - } - - } + form get_values bug bug_id component_id bug_type severity priority found_in_version summary description desc_format - bug_tracker::bug_notify -bug_id $bug_id -action "open" -comment $description -comment_format $desc_format - - # Sign up the submitter of the bug for instant alerts. We do this after calling - # the alert procedure so that the submitter isn't alerted about his own submittal of the bug - bug_tracker::add_instant_alert -bug_id $bug_id -user_id $user_id - + bug_tracker::bug::new \ + -bug_id $bug_id \ + -package_id $package_id \ + -component_id $component_id \ + -bug_type $bug_type \ + -severity $severity \ + -priority $priority \ + -found_in_version $found_in_version \ + -summary $summary \ + -description $description \ + -desc_format $desc_format + ad_returnredirect $return_url ad_script_abort } Index: openacs-4/packages/bug-tracker/www/bug.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/www/bug.adp,v diff -u -r1.3 -r1.4 --- openacs-4/packages/bug-tracker/www/bug.adp 11 Sep 2002 14:03:25 -0000 1.3 +++ openacs-4/packages/bug-tracker/www/bug.adp 13 Jan 2003 15:26:29 -0000 1.4 @@ -1,9 +1,9 @@ @page_title@ @context_bar@ -@notification_link@ +@notification_link@ - +
@@ -17,22 +17,17 @@
- -

+ +

- -
-
- @button_form_export_vars@ - - - -
-
+ +

+ You're not logged in. For more options, log in now. +

- +
(show user agent) Index: openacs-4/packages/bug-tracker/www/bug.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/www/bug.tcl,v diff -u -r1.16 -r1.17 --- openacs-4/packages/bug-tracker/www/bug.tcl 9 Dec 2002 21:24:22 -0000 1.16 +++ openacs-4/packages/bug-tracker/www/bug.tcl 13 Jan 2003 15:26:29 -0000 1.17 @@ -5,223 +5,303 @@ @creation-date 2002-03-20 @cvs-id $Id$ } { - mode:optional bug_number:integer,notnull - edit:optional - comment:optional - reassign:optional - resolve:optional - reopen:optional - cancel:optional - close:optional {user_agent_p:boolean 0} {show_patch_status "open"} filter:array,optional } +##### +# +# Setup +# +##### + set return_url "[ad_conn url]?[export_vars -url { bug_number filter:array }]" -# If the user hit cancel, ignore everything else -if { [exists_and_not_null cancel] } { - ad_returnredirect $return_url - ad_script_abort -} +set project_name [bug_tracker::conn project_name] +set package_id [ad_conn package_id] +set package_key [ad_conn package_key] -ad_require_permission [ad_conn package_id] read +set user_id [ad_conn user_id] -if { ![info exists mode] } { - if { [exists_and_not_null edit] } { - set mode "edit" - } elseif { [exists_and_not_null comment] } { - set mode "comment" - } elseif { [exists_and_not_null reassign] } { - set mode "reassign" - } elseif { [exists_and_not_null resolve] } { - set mode "resolve" - } elseif { [exists_and_not_null reopen] } { - set mode "reopen" - } elseif { [exists_and_not_null close] } { - set mode "close" - } else { - set mode "view" - } +permission::require_permission -object_id $package_id -privilege read + + + +##### +# +# Workflow definition +# +##### + +set workflow_states { open resolved closed } + +set workflow_actions { edit comment reassign resolve reopen close } + +set workflow_roles { submitter assignee } + + +# By state +array set workflow_enabled_actions { + open { comment edit reassign resolve } + resolved { comment edit resolve reopen close } + closed { comment edit reopen } } -switch -- $mode { - edit { - set edit_fields { component_id bug_type summary severity priority found_in_version assignee fix_for_version resolution fixed_in_version } - } - comment { - set edit_fields {} - } - reassign { - set edit_fields { assignee } - } - resolve { - set edit_fields { resolution fixed_in_version } - } - default { - set edit_fields {} - } +# By action +array set workflow_action_privileges { + edit { write } + comment { read } + reassign { write } + resolve { write } + reopen { write } + close { write } } -foreach field $edit_fields { - set field_editable_p($field) 1 + +# By action +array set workflow_action_label { + edit "Edit" + comment "Comment" + reassign "Reassign" + resolve "Resolve" + reopen "Reopen" + close "Close" } +# By action +array set workflow_action_allowed_roles { + edit { assignee submitter } + comment { assignee submitter } + reassign { assignee } + resolve {} + reopen { submitter } + close {} +} +# By action +array set workflow_action_assigned_roles { + edit {} + comment {} + reassign {} + resolve { assignee } + reopen {} + close { submitter } +} -if { ![string equal $mode "view"] } { - ad_maybe_redirect_for_registration -} +# By action +array set workflow_new_status { + {} {} + edit {} + comment {} + reassign {} + resolve resolved + reopen open + close closed +} -set write_p [ad_permission_p [ad_conn package_id] write] +# By action +array set workflow_edit_fields { + {} {} + edit { component_id bug_type summary severity priority found_in_version assignee fix_for_version resolution fixed_in_version } + comment {} + reassign { assignee } + resolve { resolution fixed_in_version } + reopen {} + close {} +} -set project_name [bug_tracker::conn project_name] -set package_id [ad_conn package_id] -set package_key [ad_conn package_key] +# By current state or new state (after action) +array set workflow_hide_fields { + open { resolution fixed_in_version } + resolved {} + closed {} +} -set user_id [ad_conn user_id] - +##### # -# Filter management +# Permissions # +##### -set filter_parsed [bug_tracker::parse_filters filter] +foreach role $workflow_roles { + set user_role($role) 0 +} -if { [string equal $mode view] } { +db_1row permission_info { + select b.bug_id, + b.status, + o.creation_user as submitter_user_id, + b.assignee + from bt_bugs b, + acs_objects o + where b.bug_number = :bug_number + and b.project_id = :package_id + and o.object_id = b.bug_id +} -column_array bug - set human_readable_filter [bug_tracker::conn filter_human_readable] - set where_clauses [bug_tracker::conn filter_where_clauses] - set order_by_clause [bug_tracker::conn filter_order_by_clause] +# If the user has submitted the bug he gets write permission +if { [info exists bug(submitter_user_id)] && ($bug(submitter_user_id) == $user_id) } { + set user_role(submitter) 1 +} - lappend where_clauses "b.project_id = :package_id" +# If the user is assigned to the bug, he gets write permission +if { [info exists bug(assignee)] && ($bug(assignee) == $user_id) } { + set user_role(assignee) 1 +} - set filter_bug_numbers [db_list filter_bug_numbers " - select bug_number - from bt_bugs b join - acs_objects o on (object_id = bug_id) join - bt_priority_codes pc on (pc.priority_id = b.priority) join - bt_severity_codes sc on (sc.severity_id = b.severity) - where [join $where_clauses " and "] - order by $order_by_clause - "] +array set action_permission_p [list {} 1] - set filter_bug_index [lsearch -exact $filter_bug_numbers $bug_number] - - multirow create navlinks url label +foreach loop_action $workflow_actions { + set action_permission_p($loop_action) 0 - if { $filter_bug_index != -1 } { - - if { $filter_bug_index > 0 } { - multirow append navlinks "bug?[export_vars { { bug_number {[lindex $filter_bug_numbers [expr $filter_bug_index -1]]} } filter:array }]" "<" - } else { - multirow append navlinks "" "<" + foreach role [concat $workflow_action_assigned_roles($loop_action) $workflow_action_allowed_roles($loop_action)] { + if { $user_role($role) } { + set action_permission_p($loop_action) 1 + break } - - multirow append navlinks "" "[expr $filter_bug_index+1] of [llength $filter_bug_numbers]" - - if { $filter_bug_index < [expr [llength $filter_bug_numbers]-1] } { - multirow append navlinks "bug?[export_vars { { bug_number {[lindex $filter_bug_numbers [expr $filter_bug_index +1]]} } filter:array }]" ">" - } else { - multirow append navlinks "" ">" + } + + if { !$action_permission_p($loop_action) } { + foreach priv $workflow_action_privileges($loop_action) { + if { [permission::permission_p -object_id $bug(bug_id) -privilege $priv] } { + set action_permission_p($loop_action) 1 + break + } } } } -# Create the form +##### +# +# Action +# +##### -switch -- $mode { - view { - form create bug -has_submit 1 - } - default { - form create bug +set action [form get_action bug] + +# Registration required for all actions +if { ![empty_string_p $action] } { + ad_maybe_redirect_for_registration +} + +# Check permissions +if { !$action_permission_p($action) } { + bug_tracker::security_violation -user_id $user_id -bug_id $bug(bug_id) -action $action +} + +# Buttons +set actions [list] +if { [empty_string_p $action] } { + foreach enabled_action $workflow_enabled_actions(${bug(status)}) { + if { $action_permission_p($enabled_action) } { + lappend actions [list " $workflow_action_label($enabled_action) " $enabled_action] + } } } -element create bug bug_number \ - -datatype integer \ - -widget hidden +##### +# +# Create the form +# +##### -element create bug bug_number_i \ +form create bug -mode display -actions $actions -cancel_url $return_url + +element create bug bug_number_display \ -datatype integer \ -widget inform \ + -mode display \ -label "Bug #" element create bug component_id \ -datatype integer \ - -widget [ad_decode [info exists field_editable_p(component_id)] 1 select inform] \ + -widget select \ + -mode display \ -label "Component" \ -options [bug_tracker::components_get_options] element create bug bug_type \ -datatype text \ - -widget [ad_decode [info exists field_editable_p(bug_type)] 1 select inform] \ + -widget select \ + -mode display \ -label "Type of bug" \ -options [bug_tracker::bug_type_get_options] \ -optional element create bug summary \ -datatype text \ - -widget [ad_decode [info exists field_editable_p(summary)] 1 text inform] \ + -widget text \ + -mode display \ -label "Summary" \ - -html { size 50 } + -html { size 50 } \ + -before_html "" \ + -after_html "" element create bug submitter \ -datatype text \ -widget inform \ + -mode display \ -label "Submitted by" element create bug status \ - -widget [ad_decode [info exists field_editable_p(status)] 1 select inform] \ + -widget select \ + -mode display \ -datatype text \ -options [bug_tracker::status_get_options] \ - -label "Status" + -label "Status" \ + -before_html "" \ + -after_html "" element create bug resolution \ - -widget [ad_decode [info exists field_editable_p(resolution)] 1 select inform] \ + -widget select \ + -mode display \ -datatype text \ -label "Resolution" \ - -options [ad_decode $mode resolve [bug_tracker::resolution_get_options] [concat {{"" ""}} [bug_tracker::resolution_get_options]]] \ + -options [ad_decode $action resolve [bug_tracker::resolution_get_options] [concat {{"" ""}} [bug_tracker::resolution_get_options]]] \ -optional element create bug severity \ -datatype integer \ - -widget [ad_decode [info exists field_editable_p(severity)] 1 select inform] \ + -widget select \ + -mode display \ -label "Severity" \ -options [bug_tracker::severity_codes_get_options] \ -optional element create bug priority \ -datatype integer \ - -widget [ad_decode [info exists field_editable_p(priority)] 1 select inform] \ + -widget select \ + -mode display \ -label "Priority" \ -options [bug_tracker::priority_codes_get_options] \ -optional element create bug found_in_version \ -datatype text \ - -widget [ad_decode [info exists field_editable_p(found_in_version)] 1 select inform] \ + -widget select \ + -mode display \ -label "Found in Version" \ -options [bug_tracker::version_get_options -include_unknown] \ -optional element create bug patches \ -datatype text \ -widget inform \ - -label [ad_decode $show_patch_status "open" "Open Patches (show all)" "all" "All Patches (show only open)" "Patches"] + -mode display \ + -label [ad_decode $show_patch_status "open" "Open Patches (show all)" "all" "All Patches (show only open)" "Patches"] -if { $user_agent_p } { - element create bug user_agent \ - -datatype text \ - -widget inform \ - -label "User Agent" -} +element create bug user_agent \ + -datatype text \ + -widget inform \ + -mode display \ + -label "User Agent" element create bug assignee \ - -widget [ad_decode [info exists field_editable_p(assignee)] 1 search inform] \ + -widget search \ + -mode display \ -datatype search \ -result_datatype integer \ -label {Assigned to} \ @@ -232,392 +312,224 @@ from cc_users u where upper(coalesce(u.first_names || ' ', '') || coalesce(u.last_name || ' ', '') || u.email || ' ' || coalesce(u.screen_name, '')) like upper('%'||:value||'%') order by name -} +} element create bug fix_for_version \ -datatype text \ - -widget [ad_decode [info exists field_editable_p(fix_for_version)] 1 select inform] \ + -widget select \ + -mode display \ -label "Fix for Version" \ -options [bug_tracker::version_get_options -include_undecided] \ -optional element create bug fixed_in_version \ -datatype text \ - -widget [ad_decode [info exists field_editable_p(fixed_in_version)] 1 select inform] \ + -widget select \ + -mode display \ -label "Fixed in Version" \ -options [bug_tracker::version_get_options -include_undecided] \ -optional -switch -- $mode { - edit - comment - reassign - resolve - reopen - close { - element create bug description \ - -datatype text \ - -widget comment \ - -label "Description" \ - -html { cols 60 rows 13 } \ - -optional - - element create bug desc_format \ - -datatype text \ - -widget select \ - -label "Description format" \ - -options { { "Plain" plain } { "HTML" html } { "Preformatted" pre } } +element create bug description \ + -datatype text \ + -widget comment \ + -history [bug_tracker::bug::get_activity_html -bug_id $bug(bug_id)] \ + -label "Description" \ + -html { cols 60 rows 13 } \ + -format_element desc_format \ + -format_options { { "Plain" plain } { "HTML" html } { "Preformatted" pre } } \ + -optional - } - default { - element create bug description \ - -datatype text \ - -widget inform \ - -label "Description" - } -} +# Hidden elements - element create bug return_url \ -datatype text \ -widget hidden \ -value $return_url -element create bug mode \ - -datatype text \ - -widget hidden \ - -value $mode +element create bug bug_number \ + -datatype integer \ + -widget hidden +# Export filters foreach name [array names filter] { element create bug filter.$name -datatype text -widget hidden -value $filter($name) } -# If nothing else ... -set page_title "Bug #$bug_number" +# Set editable fields +foreach field $workflow_edit_fields($action) { + element set_properties bug $field -mode edit +} -set show_user_agent_url "bug?[export_vars { bug_number { user_agent_p 1 }}]" -set hide_user_agent_url "bug?[export_vars { bug_number }]" -if { ![form is_valid bug] } { - db_1row bug { - select b.bug_id, - b.bug_number, - b.summary, - o.creation_user as submitter_user_id, - submitter.first_names as submitter_first_names, - submitter.last_name as submitter_last_name, - submitter.email as submitter_email, - b.component_id, - c.component_name, - o.creation_date, - to_char(o.creation_date, 'fmMM/DDfm/YYYY') as creation_date_pretty, - b.severity, - sc.sort_order || ' - ' || sc.severity_name as severity_pretty, - b.priority, - pc.sort_order || ' - ' || pc.priority_name as priority_pretty, - b.status, - b.resolution, - b.bug_type, - b.user_agent, - b.original_estimate_minutes, - b.latest_estimate_minutes, - b.elapsed_time_minutes, - b.found_in_version, - coalesce((select version_name - from bt_versions found_in_v - where found_in_v.version_id = b.found_in_version), 'Unknown') as found_in_version_name, - b.fix_for_version, - coalesce((select version_name - from bt_versions fix_for_v - where fix_for_v.version_id = b.fix_for_version), 'Undecided') as fix_for_version_name, - b.fixed_in_version, - coalesce((select version_name - from bt_versions fixed_in_v - where fixed_in_v.version_id = b.fixed_in_version), 'Unknown') as fixed_in_version_name, - b.assignee, - asgnu.first_names as assignee_first_names, - asgnu.last_name as assignee_last_name, - asgnu.email as assignee_email, - to_char(now(), 'fmMM/DDfm/YYYY') as now_pretty - from bt_bugs b left outer join - cc_users asgnu on (asgnu.user_id = b.assignee), - acs_objects o, - bt_components c, - bt_priority_codes pc, - bt_severity_codes sc, - cc_users submitter - where b.bug_number = :bug_number - and b.project_id = :package_id - and o.object_id = b.bug_id - and c.component_id = b.component_id - and pc.priority_id = b.priority - and sc.severity_id = b.severity - and submitter.user_id = o.creation_user - } -column_array bug - - switch -- $mode { - resolve { - set bug(status) "resolved" - } - reopen { - set bug(status) "open" - } - } - set pretty(bug_number) "#$bug(bug_number)" - set pretty(component_id) $bug(component_name) - set pretty(bug_type) [bug_tracker::bug_type_pretty $bug(bug_type)] - set pretty(summary) "$bug(summary)" - set pretty(submitter) "[acs_community_member_link -user_id $bug(submitter_user_id) \ - -label "$bug(submitter_first_names) $bug(submitter_last_name)" \ - ] ($bug(submitter_email))" - set pretty(status) [bug_tracker::status_pretty $bug(status)] - set pretty(resolution) [bug_tracker::resolution_pretty $bug(resolution)] - set pretty(severity) $bug(severity_pretty) - set pretty(priority) $bug(priority_pretty) - set pretty(found_in_version) $bug(found_in_version_name) - set pretty(patches) "[bug_tracker::get_patch_links -bug_id $bug(bug_id) -show_patch_status $show_patch_status]   \[ Upload a patch \]" - set pretty(user_agent) $bug(user_agent) - set pretty(fix_for_version) $bug(fix_for_version_name) - set pretty(fixed_in_version) $bug(fixed_in_version_name) - set pretty(assignee) [ad_decode $bug(assignee) "" "Unassigned" " - [acs_community_member_link -user_id $bug(assignee) \ - -label "$bug(assignee_first_names) $bug(assignee_last_name)"] - ($bug(assignee_email))"] -} -if { [form is_request bug] } { - element set_properties bug bug_number -value $bug(bug_number) +##### +# +# Valid form submission: Store in DB and get out of here +# +##### - # Description/Actions/History +if { [form is_valid bug] } { - set bug_id $bug(bug_id) + # Get values from form + array set row [list] - set action_html "" - - db_foreach actions { - select ba.action_id, - ba.action, - ba.resolution, - ba.actor as actor_user_id, - actor.first_names as actor_first_names, - actor.last_name as actor_last_name, - actor.email as actor_email, - ba.action_date, - to_char(ba.action_date, 'fmMM/DDfm/YYYY') as action_date_pretty, - ba.comment, - ba.comment_format - from bt_bug_actions ba, - cc_users actor - where ba.bug_id = :bug_id - and actor.user_id = ba.actor - order by action_date - } { - append action_html "$action_date_pretty [bug_tracker::bug_action_pretty $action $resolution] by $actor_first_names $actor_last_name -
[bug_tracker::bug_convert_comment_to_html -comment $comment -format $comment_format]
" + foreach column $workflow_edit_fields($action) { + set row($column) [element get_value bug $column] } - if { [string equal $mode "view"] } { - element set_properties bug description -value $action_html - } else { - element set_properties bug description \ - -history $action_html \ - -header "$bug(now_pretty) [bug_tracker::bug_action_pretty $mode] by [bug_tracker::conn user_first_names] [bug_tracker::conn user_last_name]" \ - -value "" + # Set new status + if { ![empty_string_p $workflow_new_status($action)] } { + set row(status) $workflow_new_status($action) } - set page_title "Bug #$bug_number: $bug(summary)" + bug_tracker::bug::edit \ + -bug_id $bug(bug_id) \ + -action $action \ + -description [element get_value bug description] \ + -desc_format [ns_queryget desc_format] \ + -array row - # If the user has submitted the bug he gets full write access on the bug - set write_p [expr $write_p || ($bug(submitter_user_id) == [ad_conn user_id])] - if { !$write_p && [info exists bug(assignee)] && $bug(assignee) == [ad_conn user_id] } { - set write_p 1 - } + ad_returnredirect $return_url + ad_script_abort +} - if { [string equal $mode "view"] } { - set button_form_export_vars [export_vars -form { bug_number filter:array }] - multirow create button name label - multirow append button "comment" "Comment" - if { $write_p } { - multirow append button "edit" "Edit" - switch -- $bug(status) { - open { - multirow append button "reassign" "Reassign" - multirow append button "resolve" "Resolve" - } - resolved { - multirow append button "resolve" "Resolve" - multirow append button "reopen" "Reopen" - multirow append button "close" "Close" - } - closed { - multirow append button "reopen" "Reopen" - } - } - } +##### +# +# Display form +# +##### + +# Get bug info from DB, hide form elements, set values +if { ![form is_valid bug] } { + + # Get the bug data + bug_tracker::bug::get -bug_id $bug(bug_id) -array bug + + # Maybe bump to new state + if { ![empty_string_p $workflow_new_status($action)] } { + set bug(status) $workflow_new_status($action) } - if { ![string equal $mode "view"] && ![string equal $mode "comment"] && !$write_p } { - ns_log notice "[ad_conn user_id] doesn't have write on object $bug(bug_id)" - ad_return_forbidden "Security Violation" "
- You don't have permission to edit this bug. -
- This incident has been logged. -
" - ad_script_abort + # Patches + set bug(patches_display) "[bug_tracker::get_patch_links -bug_id $bug(bug_id) -show_patch_status $show_patch_status]   \[ Upload a patch \]" + + # Hide elements that should be hidden depending on the bug status + foreach element $workflow_hide_fields(${bug(status)}) { + element set_properties bug $element -widget hidden } -} -if { ![form is_valid bug] } { - # set the values of all the inform widgets + # Optionally hide user agent + if { !$user_agent_p } { + element set_properties bug user_agent -widget hidden + } - element set_properties bug bug_number_i -value $pretty(bug_number) - + # Set regular element values foreach element { - component_id bug_type summary submitter status resolution severity - priority found_in_version patches user_agent fix_for_version fixed_in_version assignee + bug_number component_id bug_type summary status resolution severity assignee + priority found_in_version user_agent fix_for_version fixed_in_version + bug_number_display } { # check that the element exists if { [info exists bug:$element] } { - if { [info exists field_editable_p($element)] } { - if { [form is_request bug] } { - element set_value bug $element $bug($element) - } - } else { - element set_value bug $element $pretty($element) + if { [form is_request bug] || [string equal [element get_property bug $element mode] "display"] } { + element set_value bug $element $bug($element) } } - } - - if { [string equal $bug(status) "open"] && ![string equal $mode "resolve"] || [string equal $mode "reopen"] } { - element set_properties bug resolution -widget hidden - element set_properties bug fixed_in_version -widget hidden } - -} - - - -# Notifications for a project. Provide a link for logged in users in view mode -if { [string equal $mode "view"] } { - set notification_link [bug_tracker::get_notification_link \ - -type bug_tracker_project_notif \ - -object_id $bug(bug_id) \ - -url $return_url \ - -pretty_name "bug"] -} else { - set notification_link "" -} - -if { [info exists filter] } { - if { [array names filter] == [list "actionby"] && $filter(actionby) == [ad_conn user_id] } { - set context_bar [bug_tracker::context_bar [list ".?[export_vars { filter:array }]" "My bugs"] $page_title] - } else { - set context_bar [bug_tracker::context_bar [list ".?[export_vars { filter:array }]" "Filtered bug list"] $page_title] - } -} else { - set context_bar [bug_tracker::context_bar $page_title] -} - -if { [form is_valid bug] } { - - # Find out whether the user has permission to modify - - if { !$write_p } { - # No write permission, is this the submitter? - db_1row submitter { - select o.creation_user as submitter_user_id, - b.bug_id, - b.assignee - from bt_bugs b, - acs_objects o - where o.object_id = b.bug_id - and b.bug_number = :bug_number - and b.project_id = :package_id - } -column_array bug - - # If the user has submitted the bug he gets full write access on the bug - if { [info exists bug(submitter_user_id)] && ($bug(submitter_user_id) == [ad_conn user_id]) } { - set write_p 1 + # Set values for elements with separate display value + foreach element { + assignee submitter patches + } { + # check that the element exists + if { [info exists bug:$element] } { + element set_properties bug $element -display_value $bug(${element}_display) } - - if { [info exists bug(assignee)] && ($bug(assignee) == [ad_conn user_id]) } { - set write_p 1 - } } - if { !$write_p && ![string equal $mode "comment"] } { - ns_log notice "$bug(submitter_user_id) doesn't have write on object $bug(bug_id)" - ad_return_forbidden \ - "Security Violation" \ - "
- You don't have permission to edit this bug. -
- This incident has been logged. -
" - ad_script_abort - } + # Set values for description field + element set_properties bug description \ + -header "$bug(now_pretty) [bug_tracker::bug_action_pretty $action] by [bug_tracker::conn user_first_names] [bug_tracker::conn user_last_name]" - set update_exprs [list] + # Set page title + set page_title "Bug #$bug_number: $bug(summary)" - foreach column $edit_fields { - set $column [element get_value bug $column] - lappend update_exprs "$column = :$column" - } - - switch -- $mode { - resolve { - set status "resolved" - lappend update_exprs "status = :status" + # Context bar + if { [info exists filter] } { + if { [array names filter] == [list "actionby"] && $filter(actionby) == $user_id } { + set context_bar [bug_tracker::context_bar [list ".?[export_vars { filter:array }]" "My bugs"] $page_title] + } else { + set context_bar [bug_tracker::context_bar [list ".?[export_vars { filter:array }]" "Filtered bug list"] $page_title] } - reopen { - set status "open" - lappend update_exprs "status = :status" - } - close { - set status "closed" - lappend update_exprs "status = :status" - } + } else { + set context_bar [bug_tracker::context_bar $page_title] } - - if { ![info exists resolution] || ![string equal $mode "resolve"] } { - set resolution {} + + # User agent + set show_user_agent_url "bug?[export_vars { bug_number { user_agent_p 1 }}]" + set hide_user_agent_url "bug?[export_vars { bug_number }]" + + # Login + set login_url "/register/?[export_vars { return_url }]" + + # Single-bug notifications + if { [empty_string_p $action] } { + set notification_link [bug_tracker::get_notification_link \ + -type bug_tracker_bug_notif \ + -object_id $bug(bug_id) \ + -url $return_url \ + -pretty_name "bug"] } - db_transaction { - set bug_id [bug_tracker::get_bug_id -bug_number $bug_number -project_id $package_id] - if { [llength $update_exprs] > 0 } { - db_dml update_bug "update bt_bugs \n set [join $update_exprs ",\n "] \n where bug_id = :bug_id" + # Filter management + set filter_parsed [bug_tracker::parse_filters filter] + + if { [empty_string_p $action] } { + + set human_readable_filter [bug_tracker::conn filter_human_readable] + set where_clauses [bug_tracker::conn filter_where_clauses] + set order_by_clause [bug_tracker::conn filter_order_by_clause] + + lappend where_clauses "b.project_id = :package_id" + + set filter_bug_numbers [db_list filter_bug_numbers " + select bug_number + from bt_bugs b join + acs_objects o on (object_id = bug_id) join + bt_priority_codes pc on (pc.priority_id = b.priority) join + bt_severity_codes sc on (sc.severity_id = b.severity) + where [join $where_clauses " and "] + order by $order_by_clause + "] + + set filter_bug_index [lsearch -exact $filter_bug_numbers $bug_number] + + multirow create navlinks url label + + if { $filter_bug_index != -1 } { + + if { $filter_bug_index > 0 } { + multirow append navlinks "bug?[export_vars { { bug_number {[lindex $filter_bug_numbers [expr $filter_bug_index -1]]} } filter:array }]" "<" + } else { + multirow append navlinks "" "<" + } + + multirow append navlinks "" "[expr $filter_bug_index+1] of [llength $filter_bug_numbers]" + + if { $filter_bug_index < [expr [llength $filter_bug_numbers]-1] } { + multirow append navlinks "bug?[export_vars { { bug_number {[lindex $filter_bug_numbers [expr $filter_bug_index +1]]} } filter:array }]" ">" + } else { + multirow append navlinks "" ">" + } } + } - set action_id [db_nextval "acs_object_id_seq"] - set user_id [ad_conn user_id] - - foreach column { description desc_format } { - set $column [element get_value bug $column] - } - - db_dml bug_action { - insert into bt_bug_actions - (action_id, bug_id, action, resolution, actor, comment, comment_format) - values - (:action_id, :bug_id, :mode, :resolution, :user_id, :description, :desc_format) - } - - # Setup any assignee for alerts on the bug - if { [info exists assignee] && ![empty_string_p $assignee] } { - bug_tracker::add_instant_alert -bug_id $bug_id -user_id $assignee - } - } - - bug_tracker::bug_notify -bug_id $bug_id \ - -action $mode \ - -comment $description \ - -comment_format $desc_format \ - -resolution $resolution - - ad_returnredirect $return_url - ad_script_abort } ad_return_template Index: openacs-4/packages/bug-tracker/www/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/www/index.adp,v diff -u -r1.3 -r1.4 --- openacs-4/packages/bug-tracker/www/index.adp 2 Jan 2003 17:21:49 -0000 1.3 +++ openacs-4/packages/bug-tracker/www/index.adp 13 Jan 2003 15:26:29 -0000 1.4 @@ -9,18 +9,23 @@ -

@stats.header@

+

@stats.header@

- +
- + + + + + + Index: openacs-4/packages/bug-tracker/www/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/www/index.tcl,v diff -u -r1.13 -r1.14 --- openacs-4/packages/bug-tracker/www/index.tcl 2 Jan 2003 17:21:49 -0000 1.13 +++ openacs-4/packages/bug-tracker/www/index.tcl 13 Jan 2003 15:26:29 -0000 1.14 @@ -170,7 +170,7 @@ # Get stats # -db_multirow -extend { name name_url stat_name header } stats by_status { +db_multirow -extend { name name_url stat_name header selected_p } stats by_status { select b.status as unique_id, count(b.bug_id) as num_bugs from bt_bugs b @@ -182,9 +182,10 @@ set stat_name "Status" set name "[bug_tracker::status_pretty $unique_id]" set name_url "?[export_vars { { filter.status $unique_id } }]" + set selected_p [expr { [info exists filter(status)] && [string equal $filter(status) $unique_id] }] } -db_multirow -extend { name name_url stat_name header } -append stats stats_by_bug_type { +db_multirow -extend { name name_url stat_name header selected_p } -append stats stats_by_bug_type { select b.bug_type as unique_id, count(b.bug_id) as num_bugs from bt_bugs b @@ -197,9 +198,10 @@ set stat_name "Type of bug" set name [bug_tracker::bug_type_pretty $unique_id] set name_url "?[export_vars { { filter.bug_type $unique_id } }]" + set selected_p [expr { [info exists filter(bug_type)] && [string equal $filter(bug_type) $unique_id] }] } -db_multirow -extend { name_url stat_name header } -append stats stats_by_fix_for_version { +db_multirow -extend { name_url stat_name header selected_p } -append stats stats_by_fix_for_version { select b.fix_for_version as unique_id, v.version_name as name, count(b.bug_id) as num_bugs @@ -216,11 +218,12 @@ set name "Undecided" } set name_url "?[export_vars { { filter.fix_for_version $unique_id } }]" + set selected_p [expr { [info exists filter(fix_for_version)] && [string equal $filter(fix_for_version) $unique_id] }] } set stat_name_val "Severity" -db_multirow -extend { name_url stat_name header } -append stats stats_by_severity { +db_multirow -extend { name_url stat_name header selected_p } -append stats stats_by_severity { select b.severity as unique_id, p.sort_order || ' - ' || p.severity_name as name, count(b.bug_id) as num_bugs @@ -234,11 +237,12 @@ set header "Open bugs summary:" set stat_name $stat_name_val set name_url "?[export_vars { { filter.severity $unique_id } }]" + set selected_p [expr { [info exists filter(severity)] && [string equal $filter(severity) $unique_id] }] } set stat_name_val "Priority" -db_multirow -extend { name_url stat_name header } -append stats stats_by_priority { +db_multirow -extend { name_url stat_name header selected_p } -append stats stats_by_priority { select b.priority as unique_id, p.sort_order || ' - ' || p.priority_name as name, count(b.bug_id) as num_bugs @@ -252,9 +256,10 @@ set header "Open bugs summary:" set stat_name $stat_name_val set name_url "?[export_vars { { filter.priority $unique_id } }]" + set selected_p [expr { [info exists filter(priority)] && [string equal $filter(priority) $unique_id] }] } -db_multirow -extend { name_url stat_name header } -append stats stats_by_assignee { +db_multirow -extend { name_url stat_name header selected_p } -append stats stats_by_assignee { select b.assignee as unique_id, assignee.first_names || ' ' || assignee.last_name as name, count(b.bug_id) as num_bugs @@ -271,9 +276,10 @@ set name "Unassigned" } set name_url "?[export_vars -url { { filter.assignee $unique_id } }]" + set selected_p [expr { [info exists filter(assignee)] && [string equal $filter(assignee) $unique_id] }] } -db_multirow -extend { name_url stat_name header } -append stats stats_by_actionby { +db_multirow -extend { name_url stat_name header selected_p } -append stats stats_by_actionby { select o.creation_user as unique_id, submitter.first_names || ' ' || submitter.last_name as name, count(b.bug_id) as num_bugs @@ -288,9 +294,10 @@ set header "Open bugs summary:" set stat_name "To Be Verified By" set name_url "?[export_vars -url { { filter.status resolved } { filter.actionby $unique_id } }]" + set selected_p [expr { [info exists filter(status)] && [string equal $filter(status) resolved] && [info exists filter(actionby)] && [string equal $filter(actionby) $unique_id] }] } -db_multirow -extend { name_url stat_name header } -append stats stats_by_component { +db_multirow -extend { name_url stat_name header selected_p } -append stats stats_by_component { select coalesce('com/'||c.url_name||'/', trim(to_char(c.component_id,'99999999'))) as unique_id, c.component_name as name, count(b.bug_id) as num_bugs @@ -308,6 +315,7 @@ } else { set name_url "[ad_conn package_url]?[export_vars -url { { filter.component_id $unique_id } }]" } + set selected_p [expr { [info exists filter(component_id)] && [string equal $filter(component_id) $unique_id] }] } ad_return_template Index: openacs-4/packages/bug-tracker/www/patch-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bug-tracker/www/patch-add.tcl,v diff -u -r1.5 -r1.6 --- openacs-4/packages/bug-tracker/www/patch-add.tcl 9 Dec 2002 21:24:22 -0000 1.5 +++ openacs-4/packages/bug-tracker/www/patch-add.tcl 13 Jan 2003 15:26:29 -0000 1.6 @@ -9,20 +9,20 @@ @cvs-id $Id$ } { bug_number:integer,optional - cancel:optional component_id:optional - {return_url ""} + {return_url ""} } -# If the user hit cancel, ignore everything else -if { [exists_and_not_null cancel] } { - set bug_view_url "bug?[export_vars { bug_number }]" - ad_returnredirect $bug_view_url - ad_script_abort -} - ad_require_permission [ad_conn package_id] create +if { [empty_string_p $return_url] } { + if { [exists_and_not_null bug_number] } { + set return_url "bug?[export_vars { bug_number }]" + } else { + set return_url "patch-list" + } +} + # User needs to be logged in here ad_maybe_redirect_for_registration @@ -35,7 +35,7 @@ set user_id [ad_conn user_id] # Create the form -form create patch -html { enctype multipart/form-data } +form create patch -html { enctype multipart/form-data } -cancel_url $return_url element create patch patch_id \ -datatype integer \ @@ -140,12 +140,12 @@ ) } + set patch_number [db_string patch_number_for_id "select patch_number + from bt_patches + where patch_id = :patch_id"] + # Redirect to the view page for the created patch by default if { [empty_string_p $return_url] } { - set patch_number [db_string patch_number_for_id "select patch_number - from bt_patches - where patch_id = :patch_id"] - set redirect_url "patch?[export_vars { patch_number }]" } else { set redirect_url $return_url
@stats.stat_name@
@stats.name@