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.18 -r1.19 --- openacs-4/packages/bug-tracker/www/bug.tcl 21 Jan 2003 09:32:41 -0000 1.18 +++ openacs-4/packages/bug-tracker/www/bug.tcl 5 Mar 2003 17:41:04 -0000 1.19 @@ -27,424 +27,311 @@ permission::require_permission -object_id $package_id -privilege read +set page_title "[bug_tracker::conn Bug] #$bug_number" +set context_bar [bug_tracker::context_bar $page_title] -##### -# -# Workflow definition -# -##### +# Is this project using multiple versions? +set versions_p [bug_tracker::versions_p] -set workflow_states { open resolved closed } +# Paches enabled for this project? +set patches_p [bug_tracker::patches_p] -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 } -} - -# By action -array set workflow_action_privileges { - edit { write } - comment { read } - reassign { write } - resolve { write } - reopen { write } - close { write } -} - -# 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 } -} - -# By action -array set workflow_new_status { - {} {} - edit {} - comment {} - reassign {} - resolve resolved - reopen open - close closed -} - -# 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 {} -} - -# By current state or new state (after action) -array set workflow_hide_fields { - open { resolution fixed_in_version } - resolved {} - closed {} -} - - ##### # -# Permissions +# Get basic info # ##### -foreach role $workflow_roles { - set user_role($role) 0 -} +# Get the bug_id +db_1row permission_info {} -column_array bug -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 case_id [workflow::case::get_id \ + -object_id $bug(bug_id) \ + -workflow_short_name [bug_tracker::bug::workflow_short_name]] -# 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 -} - -# 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 workflow_id [bug_tracker::bug::get_instance_workflow_id] -array set action_permission_p [list {} 1] +set role_ids [workflow::get_roles -workflow_id $workflow_id] -foreach loop_action $workflow_actions { - set action_permission_p($loop_action) 0 - - 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 - } - } - - 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 - } - } - } -} - ##### # # Action # ##### -set action [form get_action bug] +set action_id [form get_action bug] +if { ![empty_string_p $action_id] } { + set action_short_name [workflow::action::get_element -action_id $action_id -element short_name] +} else { + set action_short_name {} +} + # Registration required for all actions -if { ![empty_string_p $action] } { +if { ![empty_string_p $action_id] } { 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 +if { ![workflow::case::action::available_p -case_id $case_id -action_id $action_id] } { + bug_tracker::security_violation -user_id $user_id -bug_id $bug(bug_id) -action $action_id } + # 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] - } +if { [empty_string_p $action_id] } { + foreach available_action_id [workflow::case::get_available_actions -case_id $case_id] { + workflow::action::get -action_id $available_action_id -array available_action + lappend actions [list " $available_action(pretty_name) " $available_action(action_id)] } } + ##### # # Create the form # ##### -form create bug -mode display -actions $actions -cancel_url $return_url +# Set the variable that we need for the elements below -element create bug bug_number_display \ - -datatype integer \ - -widget inform \ - -mode display \ - -label "Bug #" -element create bug component_id \ - -datatype integer \ - -widget select \ - -mode display \ - -label "Component" \ - -options [bug_tracker::components_get_options] +# set patch label +set patch_label [ad_decode $show_patch_status "open" "Open Patches (show all)" "all" "All Patches (show only open)" "Patches"] -element create bug bug_type \ - -datatype text \ - -widget select \ - -mode display \ - -label "Type of bug" \ - -options [bug_tracker::bug_type_get_options] \ - -optional +ad_form -name bug -cancel_url $return_url -mode display -has_edit 1 -actions $actions -form { + {bug_number_display:integer(inform) + {label "[bug_tracker::conn Bug] \#"} + {mode display} + } + {component_id:integer(select) + {label "[bug_tracker::conn Component]"} + {options {[bug_tracker::components_get_options]}} + {mode display} + optional + } + {summary:text(text) + {label "Summary"} + {after_html ""} + {before_html ""} + {mode display} + {html {size 50}} + } +} -element create bug summary \ - -datatype text \ - -widget text \ - -mode display \ - -label "Summary" \ - -html { size 50 } \ - -before_html "" \ - -after_html "" -element create bug submitter \ - -datatype text \ - -widget inform \ - -mode display \ - -label "Submitted by" +ad_form -extend -name bug -form { + {pretty_state:text(inform) + {label "Status"} + {before_html ""} + {after_html ""} + {mode display} + } + {resolution:text(select) + {label "Resolution"} + {options {[bug_tracker::resolution_get_options]}} + {mode display} + optional + } +} -element create bug status \ - -widget select \ - -mode display \ - -datatype text \ - -options [bug_tracker::status_get_options] \ - -label "Status" \ - -before_html "" \ - -after_html "" +foreach {category_id category_name} [bug_tracker::category_types] { + ad_form -extend -name bug -form [list \ + [list "${category_id}:integer(select)" \ + [list label $category_name] \ + [list options [bug_tracker::category_get_options -parent_id $category_id]] \ + [list mode display] \ + ] \ + ] +} -element create bug resolution \ - -widget select \ - -mode display \ - -datatype text \ - -label "Resolution" \ - -options [ad_decode $action resolve [bug_tracker::resolution_get_options] [concat {{"" ""}} [bug_tracker::resolution_get_options]]] \ - -optional -element create bug severity \ - -datatype integer \ - -widget select \ - -mode display \ - -label "Severity" \ - -options [bug_tracker::severity_codes_get_options] \ - -optional +ad_form -extend -name bug -form { + {found_in_version:text(select) + {label "Found in Version"} + {options {[bug_tracker::version_get_options -include_unknown]}} + {mode display} + optional + } +} -element create bug priority \ - -datatype integer \ - -widget select \ - -mode display \ - -label "Priority" \ - -options [bug_tracker::priority_codes_get_options] \ - -optional +workflow::case::role::add_assignee_widgets -case_id $case_id -form_name bug -element create bug found_in_version \ - -datatype text \ - -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 \ - -mode display \ - -label [ad_decode $show_patch_status "open" "Open Patches (show all)" "all" "All Patches (show only open)" "Patches"] - -element create bug user_agent \ - -datatype text \ - -widget inform \ - -mode display \ - -label "User Agent" - -element create bug assignee \ - -widget search \ - -mode display \ - -datatype search \ - -result_datatype integer \ - -label {Assigned to} \ - -options [bug_tracker::users_get_options] \ - -optional \ - -search_query { - select distinct u.first_names || ' ' || u.last_name || ' (' || u.email || ')' as name, u.user_id - 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 +# More fixed form elements +ad_form -extend -name bug -form { + {patches:text(inform) + {label $patch_label} + {mode display} + } + {user_agent:text(inform) + {label "User Agent"} + {mode display} + } + {fix_for_version:text(select) + {label "Fix for Version"} + {options {[bug_tracker::version_get_options -include_undecided]}} + {mode display} + optional + } + {fixed_in_version:text(select) + {label "Fixed in Version"} + {options {[bug_tracker::version_get_options -include_undecided]}} + {mode display} + optional + } + {description:richtext(richtext) + {label "Description"} + {html {cols 60 rows 13}} + optional + } + {return_url:text(hidden) + {value $return_url} + } + {bug_number:key} + {entry_id:integer(hidden) + optional + } } -element create bug fix_for_version \ - -datatype text \ - -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 select \ - -mode display \ - -label "Fixed in Version" \ - -options [bug_tracker::version_get_options -include_undecided] \ - -optional - -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 - -# Hidden elements - -element create bug return_url \ - -datatype text \ - -widget hidden \ - -value $return_url - -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 { [llength [array names filter]] > 0 } { + set filters [list] + foreach name [array names filter] { + lappend filters [list "filter.${name}:text(hidden)" [list value $filter($name)]] + } + ad_form -extend -name bug -form $filters } # Set editable fields -foreach field $workflow_edit_fields($action) { - element set_properties bug $field -mode edit -} - - +if { ![empty_string_p $action_id] } { + foreach field [workflow::action::get_element -action_id $action_id -element edit_fields] { + element set_properties bug $field -mode edit + } + if {[string compare $action_short_name "edit"] == 0} { + foreach {category_id category_name} [bug_tracker::category_types] { + element set_properties bug $category_id -mode edit + } + } +} -##### -# -# Valid form submission: Store in DB and get out of here -# -##### +# on_submit block +ad_form -extend -name bug -on_submit { -if { [form is_valid bug] } { - - # Get values from form - array set row [list] - - foreach column $workflow_edit_fields($action) { - set row($column) [element get_value bug $column] + array set row [list] + + if { ![empty_string_p $action_id] } { + foreach field [workflow::action::get_element -action_id $action_id -element edit_fields] { + set row($field) [element get_value bug $field] + } + foreach {category_id category_name} [bug_tracker::category_types] { + set row($category_id) [element get_value bug $category_id] + } } - - # Set new status - if { ![empty_string_p $workflow_new_status($action)] } { - set row(status) $workflow_new_status($action) - } - + + set description [element get_value bug description] + 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 + -action_id $action_id \ + -description [template::util::richtext::get_property contents $description] \ + -desc_format [template::util::richtext::get_property format $description] \ + -array row \ + -entry_id [element get_value bug entry_id] ad_returnredirect $return_url ad_script_abort + +} -edit_request { + # Dummy + # If we don't have this, ad_form complains + # Unfortunately, ad_form doesn't let us do what we want, namely have a block that executes + # whenever the form is displayed, whether initially or because of a validation error. } - - - -##### -# -# Display form -# -##### - -# Get bug info from DB, hide form elements, set values +# Not-valid block (request, error) 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) + bug_tracker::bug::get -bug_id $bug(bug_id) -array bug -action_id $action_id + + + # Make list of form fields + set element_names { + bug_number component_id summary pretty_state resolution + found_in_version user_agent fix_for_version fixed_in_version + bug_number_display entry_id } - # Patches + # update the element_name list and bug array with category stuff + foreach {category_id category_name} [bug_tracker::category_types] { + lappend element_names $category_id + set bug($category_id) [cr::keyword::item_get_assigned -item_id $bug(bug_id) -parent_id $category_id] + if {[string compare $bug($category_id) ""] == 0} { + set bug($category_id) [bug_tracker::get_default_keyword -parent_id $category_id] + } + } + + # Display value for 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)}) { + foreach element $bug(hide_fields) { element set_properties bug $element -widget hidden } + if { !$versions_p } { + foreach element { found_in_version fix_for_version fixed_in_version } { + if { [info exists bug:$element] } { + element set_properties bug $element -widget hidden + } + } + } + + if { !$patches_p } { + foreach element { patches } { + if { [info exists bug:$element] } { + element set_properties bug $element -widget hidden + } + } + } + # Optionally hide user agent if { !$user_agent_p } { element set_properties bug user_agent -widget hidden } + # Set regular element values - foreach element { - 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 - } { + foreach element $element_names { + # check that the element exists - if { [info exists bug:$element] } { + if { [info exists bug:$element] && [info exists bug($element)] } { if { [form is_request bug] || [string equal [element get_property bug $element mode] "display"] } { element set_value bug $element $bug($element) } } } + + # Add empty option to resolution code + if { ![empty_string_p $action_id] } { + if { [lsearch [workflow::action::get_element -action_id $action_id -element edit_fields] "resolution"] == -1 } { + element set_properties bug resolution -options [concat {{{} {}}} [element get_property bug resolution options]] + } + } else { + element set_properties bug resolution -widget hidden + } + + # Get values for the role assignment widgets + workflow::case::role::set_assignee_values -case_id $case_id -form_name bug # Set values for elements with separate display value foreach element { - assignee submitter patches + patches } { # check that the element exists if { [info exists bug:$element] } { @@ -454,10 +341,10 @@ # 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]" + -before_html "[workflow::case::get_activity_html -case_id $case_id][ad_decode $action_id "" "" "
$bug(now_pretty) [bug_tracker::bug_action_pretty $action_short_name] by [bug_tracker::conn user_first_names] [bug_tracker::conn user_last_name]
"]" # Set page title - set page_title "Bug #$bug_number: $bug(summary)" + set page_title "[bug_tracker::conn Bug] #$bug_number: $bug(summary)" # Context bar if { [info exists filter] } { @@ -470,43 +357,37 @@ set context_bar [bug_tracker::context_bar $page_title] } - # User agent + # User agent show/hide URLs 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"] + if { [empty_string_p $action_id] } { + set notification_link [bug_tracker::bug::get_watch_link -bug_id $bug(bug_id)] } # Filter management set filter_parsed [bug_tracker::parse_filters filter] - if { [empty_string_p $action] } { + if { [empty_string_p $action_id] } { set human_readable_filter [bug_tracker::conn filter_human_readable] set where_clauses [bug_tracker::conn filter_where_clauses] + set from_bug_clause [bug_tracker::conn filter_from_bug_clause] set order_by_clause [bug_tracker::conn filter_order_by_clause] lappend where_clauses "b.project_id = :package_id" + + set workflow_id [bug_tracker::bug::get_instance_workflow_id] + set initial_state [workflow::fsm::get_initial_state -workflow_id $workflow_id] + + set action_role [db_string select_resolve_role {}] - 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_numbers [db_list filter_bug_numbers {}] set filter_bug_index [lsearch -exact $filter_bug_numbers $bug_number] @@ -528,8 +409,8 @@ multirow append navlinks "" ">" } } - } - + } } ad_return_template +