[ad_html_text_convert -from html -to html -- $comment]" - } - default { - return [ad_html_text_convert -from text -to html -- $comment] - } - } + ns_log Notice "LARS: Format=$format, comment=$comment, formatted = [ad_html_text_convert -from $format -to text/html -- $comment]" + return [ad_html_text_convert -from $format -to text/html -- $comment] } -ad_proc ::bug_tracker::bug_convert_comment_to_text { - -comment - -format +ad_proc bug_tracker::bug_convert_comment_to_text { + {-comment:required} + {-format:required} } { - 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 [ad_html_text_convert -from $format -to text/plain -- $comment] } ##### @@ -482,7 +976,7 @@ # ##### -ad_proc ::bug_tracker::bug_action_pretty { +ad_proc bug_tracker::bug_action_pretty { action {resolution ""} } { @@ -513,7 +1007,7 @@ } } -ad_proc ::bug_tracker::patch_action_pretty { +ad_proc bug_tracker::patch_action_pretty { action } { @@ -536,7 +1030,7 @@ ##### # -# Users (assignee) +# Maintainers # ##### @@ -546,238 +1040,93 @@ 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 + select first_names || ' ' || last_name || ' (' || email || ')' as name, + user_id + from cc_users + where user_id in ( + select maintainer + from bt_projects + where project_id = :package_id + + union + + select maintainer + from bt_versions + where project_id = :package_id + + union + + select maintainer + from bt_components + where project_id = :package_id + ) + or user_id = :user_id 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 } - +ad_proc ::bug_tracker::users_get_searchquery { + -package_id +} { +} + +ad_proc -private bug_tracker::get_maintainer_role_id { + -package_id +} { + if { ![info exists package_id] } { + set package_id [ad_conn package_id] + } + # We're using the assignee widget for a certain role to assign the version maintainer + set workflow_id [bug_tracker::bug::get_instance_workflow_id -package_id [ad_conn package_id]] + set role_ids [workflow::get_roles -workflow_id $workflow_id] + # LARS HACK: + # We'll use the last role in sort order + return [lindex $role_ids end] +} + + ##### # -# Notification +# Patches # ##### -ad_proc ::bug_tracker::bug_notify { - {-bug_id:required} - {-action ""} - {-comment ""} - {-comment_format ""} - {-resolution ""} - {-patch_summary ""} +ad_proc bug_tracker::patches_p {} { + Is the patch submission feature turned on? } { - 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 - - 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) -Status: [status_pretty $bug(status)] -Severity: $bug(severity_pretty) -Priority: $bug(priority_pretty) -Found in version: $bug(found_in_version_name) - -Action: [bug_action_pretty $action $resolution] -By user: [conn user_first_names] [conn user_last_name] <[conn user_email]> - -" - - 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" - } - - - 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" - - # 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 ::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"] -} - -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 user_id [ad_conn user_id] - - 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 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" - } - } - - return $notification_link + return [parameter::get -package_id [ad_conn package_id] -parameter "PatchesP" -default 1] } -ad_proc ::bug_tracker::map_patch_to_bug { +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_dml map_patch_to_bug {} } -ad_proc ::bug_tracker::unmap_patch_from_bug { +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) - } + db_dml unmap_patch_from_bug {} } -ad_proc ::bug_tracker::get_mapped_bugs { +ad_proc bug_tracker::get_mapped_bugs { {-patch_number:required} {-only_open_p "0"} } { @@ -787,26 +1136,28 @@ set bug_list [list] set package_id [ad_conn package_id] - set open_clause [ad_decode $only_open_p "1" "\n and bt_bugs.status = 'open'" ""] + if { $only_open_p } { + set workflow_id [bug_tracker::bug::get_instance_workflow_id] + set initial_state [workflow::fsm::get_initial_state -workflow_id $workflow_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" { + set open_clause "\n and exists (select 1 + from workflow_cases cas, + workflow_case_fsm cfsm + where cas.case_id = cfsm.case_id + and cas.object_id = b.bug_id + and cfsm.current_state = :initial_state)" + } else { + set open_clause "" + } - lappend bug_list [list "$summary" "$bug_number"] + db_foreach get_bugs_for_patch {} { + lappend bug_list [list "[bug_tracker::conn Bug] #$bug_number: $summary" "$bug_number"] } return $bug_list } -ad_proc ::bug_tracker::get_bug_links { +ad_proc bug_tracker::get_bug_links { {-patch_id:required} {-patch_number:required} {-write_or_submitter_p:required} @@ -833,7 +1184,7 @@ } if { [llength $bug_link_list] != 0 } { - set bugs_string [join $bug_link_list ", "] + set bugs_string [join $bug_link_list "