Index: openacs-4/packages/tasks/tasks.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/tasks.info,v diff -u -r1.11 -r1.12 --- openacs-4/packages/tasks/tasks.info 16 Feb 2006 07:21:32 -0000 1.11 +++ openacs-4/packages/tasks/tasks.info 1 Mar 2006 13:49:14 -0000 1.12 @@ -7,22 +7,23 @@ f f - + Matthew Geddert Keep track of tasks to do. 2006-02-15 This package uses project manager tcl and sql as the base for a simple task program without project manager's complexity. 0 - - + + + Index: openacs-4/packages/tasks/lib/tasks-portlet.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/lib/tasks-portlet.adp,v diff -u -r1.4 -r1.5 --- openacs-4/packages/tasks/lib/tasks-portlet.adp 21 Feb 2006 12:16:46 -0000 1.4 +++ openacs-4/packages/tasks/lib/tasks-portlet.adp 1 Mar 2006 13:49:15 -0000 1.5 @@ -7,16 +7,12 @@
- +
Index: openacs-4/packages/tasks/lib/tasks-portlet.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/lib/tasks-portlet.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/tasks/lib/tasks-portlet.tcl 21 Feb 2006 12:16:46 -0000 1.4 +++ openacs-4/packages/tasks/lib/tasks-portlet.tcl 1 Mar 2006 13:49:15 -0000 1.5 @@ -1,7 +1,2 @@ -foreach optional_param {party_id query search_id tasks_previous tasks_future page page_size page_flush_p} { - if {![info exists $optional_param]} { - set $optional_param {} - } -} -set portlet_layout [parameter::get -parameter "DefaultPortletLayout"] \ No newline at end of file +set portlet_layout [parameter::get -parameter "DefaultPortletLayout"] Index: openacs-4/packages/tasks/lib/tasks-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/lib/tasks-postgresql.xql,v diff -u -r1.11 -r1.12 --- openacs-4/packages/tasks/lib/tasks-postgresql.xql 21 Feb 2006 12:16:46 -0000 1.11 +++ openacs-4/packages/tasks/lib/tasks-postgresql.xql 1 Mar 2006 13:49:15 -0000 1.12 @@ -2,130 +2,75 @@ postgresql7.2 - + - select t.task_id, - t.title, - t.description, - t.mime_type, - t.priority, - t.party_id, - p.title as process_title, - p.process_id, - tasks__relative_date(t.due_date) as due_date, - tasks__relative_date(t.completed_date) as completed_date, - t.status_id, - t.process_instance_id, - t.assignee_id, - contact__name(t.assignee_id) as assignee_name, - contact__name(t.party_id) as contact_name, - CASE WHEN t.due_date < now() THEN 't' ELSE 'f' END as due_date_passed_p, - s.title as status, - t.object_id - from - t_task_status s, - acs_objects ao, - t_tasks t - left outer join t_process_instances pi - on (pi.process_instance_id = t.process_instance_id) - left outer join t_processes p - on (p.process_id = pi.process_id) - where s.status_id = t.status_id - and t.status_id <> 2 - and ao.object_id = t.task_id - and ao.package_id = :package_id - and t.start_date < now() - and t.due_date between ( now() - '$tasks_previous days'::interval ) and ( now() + '$tasks_future days'::interval ) - and t.assignee_id = :user_id - and t.party_id in ( select parties.party_id - from parties - left join cr_items on (parties.party_id = cr_items.item_id) - left join cr_revisions on (cr_items.latest_revision = cr_revisions.revision_id), - group_distinct_member_map - where parties.party_id = group_distinct_member_map.member_id - $group_where_clause - [contact::search_clause -and -search_id $search_id -query $query -party_id "parties.party_id" -revision_id "revision_id"] ) - [template::list::page_where_clause -and -name tasks -key t.task_id] - [template::list::filter_where_clauses -and -name tasks] - [template::list::orderby_clause -orderby -name tasks] + select '1' + from t_task_status s, + acs_objects ao, + t_tasks t + where s.status_id = t.status_id + and ao.object_id = t.task_id + and t.task_id = :task_action_id + $limitations_clause - + - select t.task_id - from t_task_status s, acs_objects ao, t_tasks t - where s.status_id = t.status_id - and t.status_id <> 2 - and ao.object_id = t.task_id - and ao.package_id = :package_id - and t.start_date < now() - and t.due_date between ( now() - '$tasks_previous days'::interval ) and ( now() + '$tasks_future days'::interval ) - and t.assignee_id = :user_id - and t.party_id in ( select parties.party_id - from parties - left join cr_items on (parties.party_id = cr_items.item_id) - left join cr_revisions on (cr_items.latest_revision = cr_revisions.revision_id), - group_distinct_member_map - where parties.party_id = group_distinct_member_map.member_id - $group_where_clause - [contact::search_clause -and -search_id $search_id -query $query -party_id "parties.party_id" -revision_id "revision_id"] ) - [template::list::filter_where_clauses -and -name tasks] - [template::list::orderby_clause -orderby -name tasks] + select p.process_id, + p.title, + o.creation_user, + person__name(o.creation_user) as creator_name, + p.description + from t_processes p, + acs_objects o + where p.process_id = o.object_id + and p.workflow_id is not null + and o.package_id = :package_id + order by lower(p.title) - + - select t.task_id, - t.title, - t.description, - t.mime_type, - t.priority, - t.party_id, - p.title as process_title, - p.process_id, - tasks__relative_date(t.due_date) as due_date, - tasks__relative_date(t.completed_date) as completed_date, - t.status_id, - t.process_instance_id, - t.assignee_id, - contact__name(t.assignee_id) as assignee_name, - contact__name(t.party_id) as contact_name, - CASE WHEN t.due_date < now() THEN 't' ELSE 'f' END as due_date_passed_p, - s.title as status, - t.object_id - from - t_task_status s, - acs_objects ao, - t_tasks t - left outer join t_process_instances pi - on (pi.process_instance_id = t.process_instance_id) - left outer join t_processes p - on (p.process_id = pi.process_id) - where s.status_id = t.status_id - and t.status_id <> 2 - and ao.object_id = t.task_id - and ao.package_id = :package_id - and t.start_date < now() - $employee_where_clause + select t.task_id, + t.title, + t.description, + t.mime_type, + t.priority, + p.title as process_title, + p.process_id, + t.due_date, + t.completed_date, + t.status_id, + t.process_instance_id, + t.assignee_id, + CASE WHEN t.due_date::date <= now()::date THEN 't' ELSE 'f' END as due_date_passed_p, + s.title as status, + t.object_id, + acs_object__name(t.object_id) as object_name + from t_task_status s, + acs_objects ao, + t_tasks t + left outer join t_process_instances pi on (pi.process_instance_id = t.process_instance_id) + left outer join t_processes p on (p.process_id = pi.process_id) + where s.status_id = t.status_id + and ao.object_id = t.task_id [template::list::page_where_clause -and -name tasks -key t.task_id] - [template::list::filter_where_clauses -and -name tasks] [template::list::orderby_clause -orderby -name tasks] - + select t.task_id - from t_task_status s, acs_objects ao, t_tasks t - where s.status_id = t.status_id - and t.status_id <> 2 - and ao.object_id = t.task_id - and ao.package_id = :package_id - and t.start_date < now() - $employee_where_clause - [template::list::filter_where_clauses -and -name tasks] + from t_task_status s, + acs_objects ao, + t_tasks t + where s.status_id = t.status_id + and ao.object_id = t.task_id + $limitations_clause + [template::list::orderby_clause -orderby -name tasks] Index: openacs-4/packages/tasks/lib/tasks.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/lib/tasks.adp,v diff -u -r1.4 -r1.5 --- openacs-4/packages/tasks/lib/tasks.adp 18 Oct 2005 15:32:25 -0000 1.4 +++ openacs-4/packages/tasks/lib/tasks.adp 1 Mar 2006 13:49:15 -0000 1.5 @@ -1,11 +1,40 @@ -

- -#tasks.Add_Task# -#tasks.Assign_Process# -

+ + + + + + + + - - - -
+ + +

#tasks.Assign_Process#

+ +
+

#tasks.Cancel#
+

+
+ + + +

+ #tasks.Add_Task# + #tasks.Assign_Process# +

+
+ + +
+
+ +
+ Index: openacs-4/packages/tasks/lib/tasks.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/lib/tasks.tcl,v diff -u -r1.22 -r1.23 --- openacs-4/packages/tasks/lib/tasks.tcl 21 Feb 2006 12:16:46 -0000 1.22 +++ openacs-4/packages/tasks/lib/tasks.tcl 1 Mar 2006 13:49:15 -0000 1.23 @@ -17,139 +17,318 @@ # page For pagination # page_flush For pagination # page_size How many rows are we going to show -# order_by For the order_by clause -# format The display format of the list. Normal -# emp_f Filter to specify if you are going to show the tasks of the organizations only (1) or -# or also the employess tasks (2), default to 2. -# show_filters_p Boolean to specify if you want to show the filters menu or not. Default to 0 # tasks_previous Filter for tasks in the past in days # tasks_future Filter for tasks in the future in days +# status_id ... +# hide_elements List the template::list elements you don't want displated. if checkbox is listed bulk actions will be disabled for this include -foreach optional_param {party_id query search_id tasks_previous tasks_future page page_size page_flush_p elements} { +set url [ad_conn url] + +set optional_params {start_date end_date page_size hide_elements} +set required_params {object_query object_ids object_id assignee_query assignee_ids assignee_id} +set special_params {task_action_id task_action party_id process_id} +set ad_form_params {__confirmed_p __refreshing_p __key_signature __new_p} +set task_form_vars [concat [ns_queryget task_form_vars] task_form_vars] + +set filters_list [list] +set page_elements [list] +set submitted_vars [tasks::get_submitted_as_list] +foreach {key value} $submitted_vars { + # we only pass on vars that cannot be submitted by the include + # this way somebody cannot pass a variable via the http request + # what is hard coded by the include by the programmer + if { [lsearch [concat $optional_params $required_params $special_params $ad_form_params $task_form_vars] $key] < 0 && [string is false [regexp {^formbutton:} $key match]] } { + # the variable is not expected to be submitted via + # the include statement, so we can set this variable + + # we have one special variable, namely task_id + # because it is able to used with bulk actions + # if the key is task_id, we check it the variable + # already exists and it it does we add it as a list + # otherwise we just overrite the previous key with + # the new one + + if { $key == "task_id" && [exists_and_not_null task_id] } { + lappend task_id $value + } else { + set $key $value + } + if { $key ne "return_url" } { + lappend page_elements $key + } + if { [lsearch [list groupby orderby format page] $key] < 0 } { + # the variable is not a reserved filter name + lappend filters_list $key {} + } + } +} + + +set return_url [export_vars -base $url -url $page_elements] +set add_url [export_vars -base $url -url [concat $page_elements {{task_action add}}]] +set add_process_url [export_vars -base $url -url [concat $page_elements {{task_action add_process}}]] + + +foreach optional_param [concat $optional_params $special_params] { if {![info exists $optional_param]} { set $optional_param {} } } -set tasks_url "/tasks/" - -set row_list [list] -foreach element $elements { - lappend row_list $element - lappend row_list {} +set export_vars_list [list] +foreach page_element [concat $page_elements $special_params] { + lappend export_vars_list $page_element [set $page_element] } -if { ![exists_and_not_null format] } { - set format "normal" + +if { [exists_and_not_null page_size] } { + # The default page size for tasks + set page_size "25" } if { ![exists_and_not_null show_filters_p] } { - # Boolean to especify to show the filters or not + # Boolean to specify to show the filters or not set show_filters_p 0 } -if { ![exists_and_not_null emp_f] } { - # Show tasks of the employees - set emp_f 2 + + + + + +set limitations_clause "" + +# we require one of the following: +# +# 1. object_query - an sql query which returns all valid object_ids for which to display tasks +# or +# 2. object_ids - a tcl list of object_ids for which to display tasks +# or +# 3. object_id - an object_id for which to display tasks +# +# only one can be provided to be valid. If none are provided the only +# other valid option is to specify specific assignees +if { + ( [info exists object_query] && ![info exists object_ids] && ![info exists object_id] ) || + ( ![info exists object_query] && [info exists object_ids] && ![info exists object_id] ) || + ( ![info exists object_query] && [info exists object_ids] && ![info exists object_id] ) +} { + # we only have one provided object_id list, this is correct set up +} else { +# error "packages/tasks/lib/tasks - invalid include you must specify one (and only one) of the following: object_query, object_ids, object_id :: $object_id" } -# If we are not viewing the tasks of a party, view the tasks of the user -if {![exists_and_not_null party_id]} { +set single_object_p 0 +if { [info exists object_ids] } { + set object_query [template::util::tcl_to_sql_list $object_ids] +} elseif { [info exists object_id] } { + set single_object_p 1 + set object_query '$object_id' +} - # the user_id is used for the filter. user_id2 for comparison - if {![exists_and_not_null user_id]} { - set user_id [ad_conn user_id] +append limitations_clause "\n and t.object_id in ( $object_query )" + +# you may specify a list of assignees as well if you like, they are similar to the object +# queries and ids this is not required. You may only specify one of the following, assignee_query, assignee_ids, assignee_id + +if { [info exists assignee_query] || [info exists assignee_ids] || [info exists assignee_id] } { + if { + ( [info exists assignee_query] && ![info exists assignee_ids] && ![info exists assignee_id] ) || + ( ![info exists assignee_query] && [info exists assignee_ids] && ![info exists assignee_id] ) || + ( ![info exists assignee_query] && [info exists assignee_ids] && ![info exists assignee_id] ) + } { + # we only have one provided object_id list, this is correct set up + } else { + error "packages/tasks/lib/tasks - invalid include you must specify one (and only one) of the following: assignee_query, assignee_ids, assignee_id" } - set contact_id $user_id - set user_id2 $user_id - if {$user_id == [ad_conn user_id]} { - set user_id2 "" + + if { [info exists assignee_ids] } { + set assignee_query [template::util::tcl_to_sql_list $object_ids] + } elseif { [info exists object_id] } { + set assignee_query '$object_id' } - set party_id "" - unset party_id - set page_query_name own_tasks_pagination - set query_name own_tasks -} else { - set contact_id $party_id - set user_id2 "" - set page_query_name contact_tasks_pagination - set query_name contact_tasks + + if { [exists_and_not_null assignee_query] } { + append limitations_clause "\n and t.assignee_id in ( $assignee_query )" + } } -set package_id [apm_package_id_from_key tasks] +append limitations_clause "\n and ao.package_id = [ad_conn package_id]" -if { ![exists_and_not_null tasks_previous] } { - set tasks_previous 0 +if { $start_date ne "" } { + append limitations_clause "\n and t.due_date >= '$start_date'" } -if { ![exists_and_not_null tasks_future] } { - set tasks_future 7 + +if { $end_date ne "" } { + append limitations_clause "\n and t.due_date <= '$end_date'" } -if { ![exists_and_not_null orderby] } { - set orderby "priority,desc" + + + + + + + + +# before doing anything we check for the special vars task_action and task_action_id +# these actions are performed here because it requires less code to maintain just this +# one page, instead of routing to specialized pages. +# +# we are also able to verify that this user is in fact able to perform this action +# with this task here on this page much more simply that on a secondary trigger page + +set task_action [ns_queryget task_action] +set task_action_id [ns_queryget task_action_id] +set show_form_p 0 +if { $task_action ne "" && $task_action_id ne "" && [string is integer $task_action_id] } { + # somebody is attempting to perform an action on the tasks. + # we need to first validate that this task is in fact accessible + # to this user through this page. + if { [db_0or1row task_available_for_action {}] } { + set task [tasks::task::title -task_id $task_action_id] + set task_url [export_vars -base $url -url [concat $page_elements {{task_id $task_action_id} {task_action edit}}]] + switch $task_action { + complete { + tasks::task::complete -task_id $task_action_id + set task_title $task + util_user_message -html -message "[_ tasks.task_completed]" + } + interval_increase { + tasks::task::modify_interval -task_id $task_action_id -method "increase" + util_user_message -html -message "[_ tasks.task_delayed]" + } + interval_decrease { + tasks::task::modify_interval -task_id $task_action_id -method "decrease" + util_user_message -html -message "[_ tasks.task_moved_up]" + } + edit { + set show_form_p 1 + } + } + if { [exists_and_not_null edit_task_id] } { + # in order to prevent double-click errors we have to redirect back to this url + # above the return_url has already been cleaned for us. + ad_returnredirect $return_url + ad_script_abort + } + } else { + # we can return a permissions error here if we want to + # for now we will just display the page and silently + # ignore this error + } +} elseif { $task_action eq "add" } { + set show_form_p 1 +} elseif { $task_action eq "add_process" } { + + template::list::create \ + -name processes \ + -multirow processes \ + -elements { + assign { + label "" + display_template { + Assign + } + } + title { + label "Title" + } + description { + label "Description" + } + creator_name { + label "Manager" + link_url_eval $creator_url + } + } -filters {} + + db_multirow -extend { creator_url assign_url} -unclobber processes processes {} { + set creator_url "/o/$creation_user" + + set assign_url [export_vars -base $url -url [concat $page_elements {process_id {task_action assign_process}}]] + } + +} elseif { $task_action eq "assign_process" && [ns_queryget process_id] ne "" } { + set process_id [ns_queryget process_id] + tasks::require_belong_to_package -objects $process_id + + + tasks::process::assign -object_id $object_id -process_id $process_id + # util_user_message -html -message "[_ tasks.process_assigned]" + ad_returnredirect $return_url + ad_script_abort } -if { ![exists_and_not_null status_id] } { - set status_id "1" -} -if { ![exists_and_not_null package_id] } { - set package_id [ad_conn package_id] -} -if {[exists_and_not_null search_id]} { - set group_where_clause "" + +if { [string is true $show_form_p] } { + set page_flush_p 1 } else { - set group_where_clause "and group_distinct_member_map.group_id = [contacts::default_group]" + set page_flush_p 1 +# set page_flush_p 0 } -set filters_list [list user_id [list where_clause "t.assignee_id = :user_id"] \ - search_id {} \ - query {} \ - page_size {} \ - tasks_previous {} \ - tasks_future {} \ - party_id {} \ - process_instance {}] -# We are going to verify if the party_id is an organization -# if it is, then we would retrieve the tasks also of the -# employees of the organization. -set employee_where_clause "and t.party_id = :party_id" -if { [apm_package_installed_p organizations] && [exists_and_not_null contact_id]} { - set org_p [organization::organization_p -party_id $contact_id] - if { $org_p } { - lappend filters_list emp_f { - label "[_ tasks.Tasks_Assigned_to]" - values { {"[_ tasks.Organization]" 1} { "[_ tasks.Employees]" 2 }} - } - } - if { $org_p && [string equal $emp_f 2] } { - set emp_list [contact::util::get_employees -organization_id $contact_id] - lappend emp_list $contact_id - set employee_where_clause " and t.party_id in ([template::util::tcl_to_sql_list $emp_list])" +# [template::list::filter_where_clauses -and -name tasks] + + +# and t.due_date between ( now() - '$tasks_previous days'::interval ) and ( now() + '$tasks_future days'::interval ) + +# and t.status_id <> 2 + + + + + + +#if { ![exists_and_not_null tasks_previous] } { +# set tasks_previous 0 +#} +#if { ![exists_and_not_null tasks_future] } { +# set tasks_future 7 +#} +#if { ![exists_and_not_null orderby] } { +# set orderby "priority,desc" +#} +#if { ![exists_and_not_null status_id] } { +# set status_id "1" +#} + + + + + + + + + +set row_list [list] +foreach element [list checkbox deleted_p priority title process_title object_name date assignee] { + if { $single_object_p && $element == "object_name" } { + } elseif { [lsearch $hide_elements $element] < 0 } { + lappend row_list $element {} } } -set done_url [export_vars -url -base "${tasks_url}contact" {orderby {status_id 2} {party_id $contact_id}}] -set not_done_url [export_vars -url -base "${tasks_url}contact" {orderby {status_id 1} {party_id $contact_id}}] -set return_url "[ad_conn url]?[ad_conn query]" -set add_url [export_vars -base "${tasks_url}task" {return_url orderby status_id {party_id $contact_id}}] -# set bulk_actions [list "[_ tasks.Reassign]" "${tasks_url}reassign-task" "[_ tasks.Reassign_selected]"\ - "[_ tasks.Change_Assignee]" "${tasks_url}change-assignee" "[_ tasks.Change_Assignee]"] -set bulk_actions [list "[_ tasks.Change_Assignee]" "${tasks_url}change-assignee" "[_ tasks.Change_Assignee]"] +if { [lsearch $hide_elements checkbox] >= 0 } { + set bulk_actions [list] +} else { + set bulk_actions [list "[_ tasks.Change_Assignee]" "tasks-change-assignee" "[_ tasks.Change_Assignee]"] + lappend bulk_actions "[_ tasks.Delete]" "tasks-delete" "[_ tasks.Delete]" +} template::list::create \ -name tasks \ -multirow tasks \ -bulk_actions $bulk_actions \ - -bulk_action_method post \ - -bulk_action_export_vars { } \ - -selected_format $format \ + -bulk_action_export_vars {return_url} \ -key task_id \ + -selected_format "normal" \ -orderby_name tasks_orderby \ -page_size $page_size \ - -page_flush_p 0 \ - -page_query_name $page_query_name \ + -page_flush_p $page_flush_p \ + -page_query_name tasks_pagination \ -elements { deleted_p { label {[_ tasks.Not_Done]} @@ -186,17 +365,17 @@ } } - contact_name { + object_name { label "[_ tasks.Contact]" - link_url_eval $contact_url + link_url_eval $object_url } date { label "[_ tasks.Date]" display_template { @tasks.completed_date;noquote@ - « @tasks.due_date;noquote@ » + « @tasks.due_date;noquote@ » } @@ -247,7 +426,7 @@ assignee { label "[_ tasks.Assignee]" orderby_desc "lower(contact__name(t.assignee_id)) desc, t.due_date asc, t.priority, lower(t.title)" - orderby_asc "lower(contact__name(.assignee_id)) asc, t.due_date asc, t.priority, lower(t.title)" + orderby_asc "lower(contact__name(t.assignee_id)) asc, t.due_date asc, t.priority, lower(t.title)" default_direction asc } } -formats { @@ -258,30 +437,46 @@ } } -db_multirow -extend {assignee_url contact_url complete_url done_p task_plus_url task_minus_url description_html task_url} -unclobber tasks $query_name {} { - set contact_url [contact::url -party_id $party_id] - set assignee_url [contact::url -party_id $assignee_id] - regsub -all "/tasks/" $assignee_url "/contacts/" assignee_url - set complete_url [export_vars -base "${tasks_url}mark-completed" -url {task_id orderby {party_id $contact_id} return_url}] + +db_multirow -extend {assignee_url assignee_name object_url complete_url done_p interval_increase_url interval_decrease_url description_html task_url} -unclobber tasks tasks {} { + + set due_date [tasks::relative_date -date $due_date] + set completed_date [tasks::relative_date -date $completed_date] + + set assignee_name [contact::name -party_id $assignee_id] + + set object_url "/o/$object_id" + set assignee_url "/o/$assignee_id" + set task_url [export_vars -base $url -url [concat $page_elements {{task_action_id $task_id} {task_action edit}}]] + set complete_url [export_vars -base $url -url [concat $page_elements {{task_action_id $task_id} {task_action complete}}]] + set interval_increase_url [export_vars -base $url -url [concat $page_elements {{task_action_id $task_id} {task_action interval_increase}}]] + set interval_decrease_url [export_vars -base $url -url [concat $page_elements {{task_action_id $task_id} {task_action interval_decrease}}]] + if { $status_id == "2" } { set done_p 1 } else { set done_p 0 } - set task_url [export_vars -base "${tasks_url}task" -url {{party_id $contact_id} orderby status_id task_id}] - set task_plus_url [export_vars -base "${tasks_url}task-interval" -url {{action plus} {days 7} {party_id $contact_id} task_id status_id orderby return_url}] - set task_minus_url [export_vars -base "${tasks_url}task-interval" -url {{action minus} {days 7} {party_id $contact_id} task_id status_id orderby return_url}] - regsub -all "\r|\n" $description {LiNeBrEaK} description + if { $done_p } { + set due_date $completed_date + } + regsub -all "\r" $description "\n" description + while { [regsub -all "\n\n" $description "\n" description] } {} + regsub -all "\n" $description {LiNeBrEaK} description + set description_html [ad_html_text_convert \ -from $mime_type \ -to "text/html" \ -truncate_len "400" \ -more "[_ tasks.more]" \ -- $description] - regsub -all {LiNeBrEaKLiNeBrEaK} $description_html {LiNeBrEaK} description_html - regsub -all {LiNeBrEaK} $description_html {\ \ \¶\ } description_html - regsub -all " " $due_date {\ } due_date - regsub -all " " $completed_date {\ } completed_date + + regsub -all {LiNeBrEaK} $description_html "\\ \\ \\¶\\ " description_html + regsub -all " " $due_date {\ } due_date + regsub -all " " $completed_date {\ } completed_date } +#ad_return_error "AS" "
$limitations_clause
" + +ad_return_template Index: openacs-4/packages/tasks/sql/postgresql/tasks-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/sql/postgresql/tasks-create.sql,v diff -u -r1.6 -r1.7 --- openacs-4/packages/tasks/sql/postgresql/tasks-create.sql 26 Oct 2005 18:54:29 -0000 1.6 +++ openacs-4/packages/tasks/sql/postgresql/tasks-create.sql 1 Mar 2006 13:49:15 -0000 1.7 @@ -18,6 +18,8 @@ workflow_id integer constraint t_process_workflow_fk references workflows + -- the user assigned to this process + assignee_id integer ); create table t_process_instances ( @@ -30,9 +32,6 @@ constraint t_process_instances_process_fk references t_processes, case_id integer, - party_id integer - constraint t_process_instances_party_fk - references parties, object_id integer constraint t_process_instances_tasks_object_fk references acs_objects @@ -76,9 +75,6 @@ closing_action_id integer constraint t_process_tasks_close_action_fk references workflow_actions, - party_id integer - constraint t_process_tasks_party_fk - references parties, object_id integer constraint t_process_tasks_object_fk references acs_objects, @@ -110,16 +106,7 @@ process_task_id integer constraint t_tasks_process_task_fk references t_process_tasks, - -- The party_id is the party whom this task is associated with (e.g. the contact) - party_id integer - constraint t_tasks_party_fk - references parties, - -- The object_id of the Object that triggered this task. If you created an offer - -- and want to have a reminder to phone, the party_id would be the recipient of the offer - -- the object_id would be the offer_id and the creation_user (assignee who is doing the job) - -- would be yourself. - -- As we are very bad in design we realized too late that it might make sense to change the - -- assignee at a later stage, we now modify the creation_user for this. + -- the object_id this tasks is applied to (such as a person, organization, page, etc.) object_id integer constraint t_tasks_object_fk references acs_objects, @@ -135,6 +122,7 @@ start_date timestamptz, due_date timestamptz, completed_date timestamptz, + -- the user assigned to this task assignee_id integer ); @@ -233,111 +221,33 @@ ELSE to_char(p_date,''Mon DD (Dy)'') END ELSE to_char(p_date,''Mon DD, YYYY'') END; - return v_date; end;' language 'plpgsql'; -create or replace function tasks__completion_date ( - integer -) returns timestamptz -as ' -declare - p_task_id alias for $1; - v_complete_p boolean; - v_date varchar; - v_previous_p boolean; - revision record; -begin - v_complete_p := ''1'' from pm_tasks where task_id = p_task_id and status = ''2''; - v_date := NULL; - - IF v_complete_p THEN - v_previous_p := ''t''; - FOR revision IN - select ptr.percent_complete, ao.creation_date - from cr_revisions cr, pm_tasks_revisions ptr, acs_objects ao - where cr.item_id = p_task_id - and cr.revision_id = ao.object_id - and cr.revision_id = ptr.task_revision_id - order by ao.creation_date desc - LOOP - IF revision.percent_complete = ''100'' AND v_previous_p THEN - v_date := revision.creation_date; - ELSE - v_previous_p := ''f''; - EXIT; - END IF; - END LOOP; - - END IF; - - return v_date; -end;' language 'plpgsql'; - - -create or replace function tasks__completion_user ( - integer -) returns integer -as ' -declare - p_task_id alias for $1; - v_complete_p boolean; - v_user varchar; - v_previous_p boolean; - revision record; -begin - v_complete_p := ''1'' from pm_tasks where task_id = p_task_id and status = ''2''; - v_user := NULL; - - IF v_complete_p THEN - v_previous_p := ''t''; - FOR revision IN - select ptr.percent_complete, ao.creation_user - from cr_revisions cr, pm_tasks_revisions ptr, acs_objects ao - where cr.item_id = p_task_id - and cr.revision_id = ao.object_id - and cr.revision_id = ptr.task_revision_id - order by ao.creation_date desc - LOOP - IF revision.percent_complete = ''100'' AND v_previous_p THEN - v_user := revision.creation_user; - ELSE - v_previous_p := ''f''; - EXIT; - END IF; - END LOOP; - - END IF; - - return v_user; -end;' language 'plpgsql'; - - ----------------------------- -select define_function_args('tasks_task__new','task_id,process_instance_id,process_task_id,party_id,object_id,title,description,mime_type,comment,status_id,priority,start_date,due_date,package_id,creation_user,creation_ip,context_id,assignee_id'); +select define_function_args('tasks_task__new','task_id,process_instance_id,process_task_id,object_id,title,description,mime_type,comment,status_id,priority,start_date,due_date,package_id,creation_user,creation_ip,context_id,assignee_id'); -create or replace function tasks_task__new (integer,integer,integer,integer,integer,varchar,text,varchar,text,integer,integer,timestamptz,timestamptz,integer,integer,varchar,integer,integer) +create or replace function tasks_task__new (integer,integer,integer,integer,varchar,text,varchar,text,integer,integer,timestamptz,timestamptz,integer,integer,varchar,integer,integer) returns integer as ' declare p_task_id alias for $1; p_process_instance_id alias for $2; p_process_task_id alias for $3; - p_party_id alias for $4; - p_object_id alias for $5; - p_title alias for $6; - p_description alias for $7; - p_mime_type alias for $8; - p_comment alias for $9; - p_status_id alias for $10; - p_priority alias for $11; - p_start_date alias for $12; - p_due_date alias for $13; - p_package_id alias for $14; - p_creation_user alias for $15; - p_creation_ip alias for $16; - p_context_id alias for $17; - p_assignee_id alias for $18; + p_object_id alias for $4; + p_title alias for $5; + p_description alias for $6; + p_mime_type alias for $7; + p_comment alias for $8; + p_status_id alias for $9; + p_priority alias for $10; + p_start_date alias for $11; + p_due_date alias for $12; + p_package_id alias for $13; + p_creation_user alias for $14; + p_creation_ip alias for $15; + p_context_id alias for $16; + p_assignee_id alias for $17; v_task_id integer; v_start_date timestamptz; begin @@ -360,11 +270,11 @@ end if; insert into t_tasks - (task_id, process_instance_id, process_task_id, party_id, object_id, + (task_id, process_instance_id, process_task_id, object_id, title, description, mime_type, comment, status_id, priority, start_date, due_date, assignee_id) values - (v_task_id, p_process_instance_id, p_process_task_id, p_party_id, + (v_task_id, p_process_instance_id, p_process_task_id, p_object_id, p_title, p_description, p_mime_type, p_comment, p_status_id, p_priority, v_start_date, p_due_date, p_assignee_id); @@ -373,30 +283,29 @@ ' language 'plpgsql'; -select define_function_args('tasks_process_task__new','task_id,process_id,open_action_id,closing_action_id,party_id,object_id,title,description,mime_type,comment,status_id,priority,start,due,package_id,creation_user,creation_ip,context_id,assignee_id'); +select define_function_args('tasks_process_task__new','task_id,process_id,open_action_id,closing_action_id,object_id,title,description,mime_type,comment,status_id,priority,start,due,package_id,creation_user,creation_ip,context_id,assignee_id'); -create or replace function tasks_process_task__new (integer,integer,integer,integer,integer,integer,varchar,text,varchar,text,integer,integer,numeric,numeric,integer,integer,varchar,integer,integer) +create or replace function tasks_process_task__new (integer,integer,integer,integer,integer,varchar,text,varchar,text,integer,integer,numeric,numeric,integer,integer,varchar,integer,integer) returns integer as ' declare p_task_id alias for $1; p_process_id alias for $2; p_open_action_id alias for $3; p_closing_action_id alias for $4; - p_party_id alias for $5; - p_object_id alias for $6; - p_title alias for $7; - p_description alias for $8; - p_mime_type alias for $9; - p_comment alias for $10; - p_status_id alias for $11; - p_priority alias for $12; - p_start alias for $13; - p_due alias for $14; - p_package_id alias for $15; - p_creation_user alias for $16; - p_creation_ip alias for $17; - p_context_id alias for $18; - p_assignee_id alias for $19; + p_object_id alias for $5; + p_title alias for $6; + p_description alias for $7; + p_mime_type alias for $8; + p_comment alias for $9; + p_status_id alias for $10; + p_priority alias for $11; + p_start alias for $12; + p_due alias for $13; + p_package_id alias for $14; + p_creation_user alias for $15; + p_creation_ip alias for $16; + p_context_id alias for $17; + p_assignee_id alias for $18; v_task_id integer; begin v_task_id:= acs_object__new( @@ -412,33 +321,34 @@ ); insert into t_process_tasks - (task_id, process_id, open_action_id, closing_action_id, party_id, + (task_id, process_id, open_action_id, closing_action_id, object_id, title, description, mime_type, comment, status_id, priority, start, due, assignee_id) values (v_task_id, p_process_id, p_open_action_id, p_closing_action_id, - p_party_id, p_object_id, p_title, p_description, p_mime_type, + p_object_id, p_title, p_description, p_mime_type, p_comment, p_status_id, p_priority, p_start, p_due, p_assignee_id); return v_task_id; end; ' language 'plpgsql'; -select define_function_args('tasks_process__new','process_id,title,description,mime_type,workflow_id,package_id,creation_user,creation_ip,context_id'); +select define_function_args('tasks_process__new','process_id,title,description,mime_type,workflow_id,assignee_id,package_id,creation_user,creation_ip,context_id'); -create or replace function tasks_process__new (integer,varchar,text,varchar,integer,integer,integer,varchar,integer) +create or replace function tasks_process__new (integer,varchar,text,varchar,integer,integer,integer,integer,varchar,integer) returns integer as ' declare p_process_id alias for $1; p_title alias for $2; p_description alias for $3; p_mime_type alias for $4; p_workflow_id alias for $5; - p_package_id alias for $6; - p_creation_user alias for $7; - p_creation_ip alias for $8; - p_context_id alias for $9; + p_assignee_id alias for $6; + p_package_id alias for $7; + p_creation_user alias for $8; + p_creation_ip alias for $9; + p_context_id alias for $10; v_process_id integer; begin v_process_id:= acs_object__new( @@ -454,29 +364,28 @@ ); insert into t_processes - (process_id, title, description, mime_type, workflow_id) + (process_id, title, description, mime_type, workflow_id, assignee_id) values - (v_process_id, p_title, p_description, p_mime_type, p_workflow_id); + (v_process_id, p_title, p_description, p_mime_type, p_workflow_id, p_assignee_id); return v_process_id; end; ' language 'plpgsql'; -select define_function_args('tasks_process_instance__new','process_instance_id,process_id,case_id,party_id,object_id,package_id,creation_user,creation_ip,context_id'); +select define_function_args('tasks_process_instance__new','process_instance_id,process_id,case_id,object_id,package_id,creation_user,creation_ip,context_id'); -create or replace function tasks_process_instance__new (integer,integer,integer,integer,integer,integer,integer,varchar,integer) +create or replace function tasks_process_instance__new (integer,integer,integer,integer,integer,integer,varchar,integer) returns integer as ' declare p_process_instance_id alias for $1; p_process_id alias for $2; p_case_id alias for $3; - p_party_id alias for $4; - p_object_id alias for $5; - p_package_id alias for $6; - p_creation_user alias for $7; - p_creation_ip alias for $8; - p_context_id alias for $9; + p_object_id alias for $4; + p_package_id alias for $5; + p_creation_user alias for $6; + p_creation_ip alias for $7; + p_context_id alias for $8; v_process_instance_id integer; begin v_process_instance_id:= acs_object__new( @@ -492,9 +401,9 @@ ); insert into t_process_instances - (process_instance_id, process_id, case_id, party_id, object_id) + (process_instance_id, process_id, case_id, object_id) values - (v_process_instance_id, p_process_id, p_case_id, p_party_id, p_object_id); + (v_process_instance_id, p_process_id, p_case_id, p_object_id); return v_process_instance_id; end; Index: openacs-4/packages/tasks/sql/postgresql/tasks-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/sql/postgresql/tasks-drop.sql,v diff -u -r1.1 -r1.2 --- openacs-4/packages/tasks/sql/postgresql/tasks-drop.sql 25 Sep 2005 23:49:23 -0000 1.1 +++ openacs-4/packages/tasks/sql/postgresql/tasks-drop.sql 1 Mar 2006 13:49:15 -0000 1.2 @@ -1,7 +1,18 @@ -drop table t_process_tasks; drop table t_tasks; +drop table t_process_tasks; drop table t_task_status; drop table t_process_instances; drop table t_processes; +select acs_object_type__drop_type('tasks_task','t'); +select acs_object_type__drop_type('tasks_process','t'); +select acs_object_type__drop_type('tasks_process_instance','t'); +select acs_object_type__drop_type('tasks_process_task','t'); + +select drop_package('tasks'); +select drop_package('tasks_task'); +select drop_package('tasks_process'); +select drop_package('tasks_process_instance'); +select drop_package('tasks_process_task'); + drop sequence t_task_status_seq; Index: openacs-4/packages/tasks/tcl/tasks-callback-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/tcl/tasks-callback-procs.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/tasks/tcl/tasks-callback-procs.tcl 14 Oct 2005 15:55:29 -0000 1.4 +++ openacs-4/packages/tasks/tcl/tasks-callback-procs.tcl 1 Mar 2006 13:49:15 -0000 1.5 @@ -75,9 +75,14 @@ ns_log notice "\#\#\# entering tasks-action-callback: $case_id, $object_id, $action_id" db_1row process_id { - select process_instance_id, process_id, party_id, object_id - from t_process_instances - where case_id = :case_id + select tp.process_instance_id, + tp.process_id, + tp.object_id, + o.package_id + from t_process_instances tp, + acs_objects o + where tp.process_instance_id = o.object_id + and tp.case_id = :case_id } set tasks [db_list_of_lists process_tasks { @@ -95,7 +100,6 @@ set new_task_id [tasks::task::new \ -process_instance_id $process_instance_id \ -process_task_id $process_task_id \ - -party_id $party_id \ -object_id $object_id \ -title $title \ -description $description \ @@ -104,7 +108,8 @@ -status_id $status_id \ -priority $priority \ -start_date $start_date \ - -due_date $due_date] + -due_date $due_date \ + -package_id $package_id] } } @@ -119,3 +124,75 @@ } { return "tasks" } + + +ad_proc -public -callback contacts::redirect -impl tasks { + {-party_id ""} + {-action ""} +} { + redirect the contact to the correct tasks stuff +} { + + if { [exists_and_not_null party_id] } { + + switch $action { + tasks { set file "/packages/tasks/www/contact" } + tasks-mark-completed { set file "/packages/tasks/www/mark-completed" } + tasks-change-assignee { set file "/packages/tasks/www/change-assignee" } + tasks-delete { set file "/packages/tasks/www/delete" } + } + + if { [exists_and_not_null file] } { + if { [ns_queryget object_id] eq "" } { + rp_form_put object_id $party_id + } + rp_internal_redirect ${file} + } + + } + if { [regexp "^[ad_conn package_url](.*)$" [ad_conn url] match url_request] } { + ns_log notice "tasks implementation of contact::redirecturl_request $url_request" + switch $url_request { + processes { set file "/packages/tasks/www/processes" } + process { set file "/packages/tasks/www/process" } + process-add-edit { set file "/packages/tasks/www/process-add-edit" } + process-delete { set file "/packages/tasks/www/process-delete" } + process-task { set file "/packages/tasks/www/process-task" } + process-task-delete { set file "/packages/tasks/www/process-task-delete" } + tasks { set file "/packages/tasks/www/index" } + tasks-change-assignee { set file "/packages/tasks/www/change-assignee" } + } + if { [exists_and_not_null file] } { + rp_internal_redirect $file + } + } + +} + + +ad_proc -public -callback subsite::url -impl tasks_task { + {-package_id:required} + {-object_id:required} + {-type ""} +} { + return the page_url for an object of type tasks_task +} { +# +# I NEED TO FIX THIS, THIS COMES FROM PROJECT MANAGER +# + if { [apm_package_key_from_id $package_id] eq "contacts" } { + set party_id [db_string get_it { select party_id from t_tasks where task_id = :object_id } -default {}] + if { [exists_and_not_null party_id] } { + if {$type=="edit"} { + return "[contact::url -party_id $party_id -package_id $package_id]task/$object_id" + } else { + return "[contact::url -party_id $party_id -package_id $package_id]task/$object_id" + } + } + } else { + + } + + + +} Index: openacs-4/packages/tasks/tcl/tasks-install-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/tcl/tasks-install-procs.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/packages/tasks/tcl/tasks-install-procs.tcl 25 Sep 2005 23:54:16 -0000 1.2 +++ openacs-4/packages/tasks/tcl/tasks-install-procs.tcl 1 Mar 2006 13:49:15 -0000 1.3 @@ -55,5 +55,79 @@ acs_sc::impl::new_from_spec -spec $spec } + 0.1d8 0.1d9 { + + ns_log notice "Attempting to upgrade from 0.1d8 to 0.1d9 if this fails please look at the proc tasks::install::after_upgrade for details..." + + # Tasks is being converted from an application to a service with this release. + # this means that it can only deal with being mounted once and currently its + # assumed that tasks is only used in conjunction with contacts. The service + # tasks from this version forward allows inclusion of tasks in any other package + # much like the way general-comments, ams or categories works. + + # this switch is being made because version 1.2b4 of contacts is no longer + # singleton and this is the cleanest way of providing tasks to contacts + # instances site wide and tasks will be used in other packages for tasks + # relations. + + # this will fail if more than one instance exists + set tasks_package_id [apm_package_id_from_key "tasks"] + + + # now we make sure that all the associated parties are + # a part of the '-2' group. This was the default group + # for contacts until version 1.2b4 which is when contacts + # was no longer singleton and allowed users to use groups + # other than '-2'. We are assuming that this upgrade + # is taking place at the same time as the contacts upgrade + # which was released a few days ago. I know its bad to assume + # and sorry if this hurts you ... but this is necessary for + # the move to make tasks a service package that cannot be + # mounted numerous times. + + set count_of_non_parties [db_string get_it { + select count(*) + from t_tasks + where object_id not in ( select member_id from group_distinct_member_map where group_id = '-2' ) + }] + + if { $count_of_non_parties > 0 } { + error "Cannot upgrade from 0.1d8 to 0.1d9 because tasks is becoming a service and the upgrade scripts do not know how to deal with your setup. look at the tasks::install::after_upgrade for details" + ad_script_abort + } + + + + # if we only have one or zero we are happy. + if { $tasks_package_id == "0" } { + ns_log notice "No upgrade of task objects necessary because none exist and any newly created ones will be properly taken care of" + } else { + # there is one package_id we can likely do the upgrade. All parties related + # to tasks are in the '-2' group so we can assume that contacts was used + # in the 1.2b3 or before setup. Thus we get the package_id of the contacts + # instance. + + set contacts_package_id [site_node::get_from_object_id -object_id [site_node::get_from_url -url "/contacts/" -exact]] + if { ![exists_and_not_null contacts_package_id] } { + error "Cannot upgrade from 0.1d9 because there are tasks assigned to this package, but there is no contacts instance mounted at /contacts/" + } else { + db_dml update_objects { + update acs_objects + set package_id = :contacts_package_id + where object_type in ( 'tasks_task', 'tasks_process', 'tasks_process_instance', 'tasks_process_task' ) + } + db_dml update_objects { + update acs_objects + set context_id = :contacts_package_id + where object_type in ( 'tasks_task', 'tasks_process', 'tasks_process_instance', 'tasks_process_task' ) + } + } + + # now we unmount the tasks instance (since this is now a service that does not need to be mounted) + site_node_delete_package_instance -node_id [site_node::get_from_object_id -object_id $tasks_package_id] + + } + + } } } Index: openacs-4/packages/tasks/tcl/tasks-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/tcl/tasks-procs.tcl,v diff -u -r1.8 -r1.9 --- openacs-4/packages/tasks/tcl/tasks-procs.tcl 17 Nov 2005 16:04:39 -0000 1.8 +++ openacs-4/packages/tasks/tcl/tasks-procs.tcl 1 Mar 2006 13:49:15 -0000 1.9 @@ -14,12 +14,97 @@ namespace eval tasks::process::task {} namespace eval tasks::process::instance {} +ad_proc -public tasks::require_belong_to_package { + {-objects ""} + {-package_id ""} +} { + if { $package_id eq "" } { + set package_id [ad_conn package_id] + } + if { ![tasks::belong_to_package -objects $objects -package_id $package_id] } { + ad_return_complain 1 [_ tasks.Your_submission_is_not_valid] + } + +} + +ad_proc -public tasks::belong_to_package { + {-objects ""} + {-package_id ""} +} { + if { $package_id eq "" } { + set package_id [ad_conn package_id] + } + if { [llength $objects] == 0 } { + return 1 + } else { + return [db_0or1row objects_belong_to_package_p {}] + } +} + +ad_proc -public tasks::get_submitted_as_list { +} { + set form_variables [list] + set form [ns_getform] + if { $form eq "" } { + set form_size 0 + } else { + set form_size [ns_set size $form] + } + for { set form_counter_i 0 } { $form_counter_i < $form_size } { incr form_counter_i } { + set key [ns_set key $form $form_counter_i] + set value [ns_set value $form $form_counter_i] + if { $value ne "" } { + lappend form_variables $key $value + } + } + return $form_variables +} + + +ad_proc -public tasks::relative_date { + {-date:required} +} { + if { [regexp {^[0-9]{4}-[0-9]{2}-[0-9]{2}} $date match] } { + + # get year, month, day + set date_list [dt_ansi_to_list [lindex $date 0]] + set date_julian [dt_ansi_to_julian [lindex $date_list 0] [lindex $date_list 1] [lindex $date_list 2]] + + set today_date [dt_sysdate] + set today_list [dt_ansi_to_list $today_date] + set today_julian [dt_ansi_to_julian [lindex $today_list 0] [lindex $today_list 1] [lindex $today_list 2]] + + set days [expr $date_julian - $today_julian] + + if { $days == 0 } { + set date [_ acs-datetime.Today] + } elseif { $days == -1 } { + set date [_ tasks.Yesterday] + } elseif { $days == 1 } { + set date [_ tasks.Tomorrow] + } elseif { 1 < $days && $days <= 5 } { + set weekday [lc_time_fmt $date "%f"] + set todays_weekday [lc_time_fmt $today_date "%f"] + if { $todays_weekday <= 5 && $weekday <= 5 } { + set date [lindex [_ acs-datetime.days_of_week] $weekday] + } else { + set date [lc_time_fmt $date [_ tasks.localization-d_near_fmt]] + } + } elseif { ( -30 < $days && $days < -1 ) || ( 5 < $days && $days <= 180 ) } { + set date [lc_time_fmt $date [_ tasks.localization-d_near_fmt]] + } else { + set date [lc_time_fmt $date [_ tasks.localization-d_far_fmt]] + } + + } + return $date +} + ad_proc -public tasks::task::new { {-task_id ""} {-process_instance_id ""} {-process_task_id ""} - {-party_id ""} - {-object_id ""} + -object_id:required -title:required {-description ""} {-mime_type "text/plain"} @@ -33,7 +118,7 @@ {-assignee_id ""} } { if { [empty_string_p $package_id] } { - set package_id [apm_package_id_from_key "tasks"] + set package_id [ad_conn package_id] } set extra_vars [ns_set create] @@ -45,13 +130,25 @@ set assignee_id [ad_conn user_id] } - oacs_util::vars_to_ns_set -ns_set $extra_vars -var_list {task_id process_instance_id process_task_id party_id object_id title description mime_type comment status_id priority start_date due_date package_id context_id assignee_id} + oacs_util::vars_to_ns_set -ns_set $extra_vars -var_list {task_id process_instance_id process_task_id object_id title description mime_type comment status_id priority start_date due_date package_id context_id assignee_id} set task_id [package_instantiate_object -extra_vars $extra_vars tasks_task] return $task_id } +ad_proc -public tasks::task::title { + -task_id +} { + return [db_string get_task_title {} -default {}] +} + +ad_proc -public tasks::task::delete { + -task_id +} { + db_dml delete_task {} +} + ad_proc -public tasks::task::edit { -task_id:required -title:required @@ -66,6 +163,19 @@ set modifying_user [ad_conn user_id] set modifying_ip [ad_conn peeraddr] + set previous_status_id [db_string get_status_id {}] + + if { $status_id == $previous_status_id } { + # there is no need to updated the completed_date + set completed_clause "" + } elseif { $status_id == "2" } { + # the edit is completing the task for the first time + set completed_clause ", completed_date = now()" + } else { + # the edit is no longer completed + set completed_clause ", completed_date = NULL" + } + db_dml update_task {} db_dml update_object {} } @@ -82,13 +192,49 @@ } } +ad_proc -public tasks::task::modify_interval { + -task_id:required + -method:required + {-days "7"} +} { + increase or decrease a task interval +} { + if { $method == "increase" } { + set operand "+" + } elseif { $method == "decrease" } { + set operand "-" + } else { + error "an invalid method was supplied to tasks::task::modify_interval, you specified ${method}, but it must be 'increase' or 'decrease'" + } + + db_1row get_task_info " + select t.title as task, t.description, t.mime_type, t.priority, + to_char((t.due_date $operand '$days days'::interval),'YYYY-MM-DD') as due_date, + t.status_id as status, t.comment, t.assignee_id + from t_tasks t + where t.task_id = :task_id + " + + set task_id [tasks::task::edit \ + -task_id ${task_id} \ + -title ${task} \ + -description ${description} \ + -mime_type $mime_type \ + -comment ${comment} \ + -due_date ${due_date} \ + -status_id ${status} \ + -assignee_id ${assignee_id} \ + -priority ${priority}] + +} + + ad_proc -public tasks::process::task::new { {-task_id ""} -process_id:required -open_action_id:required -closing_action_id:required - {-party_id ""} {-object_id ""} -title:required {-description ""} @@ -112,7 +258,7 @@ set extra_vars [ns_set create] set context_id $package_id - oacs_util::vars_to_ns_set -ns_set $extra_vars -var_list {task_id process_id open_action_id closing_action_id party_id object_id title description mime_type comment status_id priority start due package_id context_id assignee_id} + oacs_util::vars_to_ns_set -ns_set $extra_vars -var_list {task_id process_id open_action_id closing_action_id object_id title description mime_type comment status_id priority start due package_id context_id assignee_id} set task_id [package_instantiate_object -extra_vars $extra_vars tasks_process_task] @@ -122,7 +268,6 @@ ad_proc -public tasks::process::task::edit { -task_id:required -open_action_id:required - {-party_id ""} {-object_id ""} -title:required {-description ""} @@ -142,6 +287,47 @@ } +ad_proc -public tasks::process::assign { + -process_id:required + -object_id:required + {-package_id ""} +} { + if { [empty_string_p $package_id] } { + set package_id [ad_conn package_id] + } + ns_log notice "the process_id is $process_id and the object_id is $object_id" + + set workflow_id [db_string get_workflow_id {}] + + db_transaction { + set case_id [db_nextval acs_object_id_seq] + + set instance_id [tasks::process::instance::new \ + -process_id $process_id \ + -case_id $case_id \ + -package_id $package_id \ + -object_id $object_id] + + workflow::case::new -no_notification \ + -workflow_id $workflow_id \ + -case_id $case_id \ + -object_id $instance_id + + } + + # ideally in the future we could specify the case_id + # that workflow::case::new would use, and thus we + # could create an object_id before creating + # the process instance but for now we + # need this hack + +# set case_id [db_string get_case {} -default {}] + +# db_dml update_instance_case {} + + return $instance_id +} + ad_proc -public tasks::process::new { {-process_id ""} -title:required @@ -168,6 +354,7 @@ -title:required {-description ""} {-mime_type "text/plain"} + {-assignee_id ""} } { set modifying_user [ad_conn user_id] set modifying_ip [ad_conn peeraddr] @@ -181,8 +368,7 @@ {-process_instance_id ""} -process_id:required -case_id:required - {-party_id ""} - {-object_id ""} + -object_id:required {-package_id ""} } { if { [empty_string_p $package_id] } { @@ -191,111 +377,9 @@ set extra_vars [ns_set create] set context_id $package_id - oacs_util::vars_to_ns_set -ns_set $extra_vars -var_list {process_instance_id process_id case_id party_id object_id package_id context_id} + oacs_util::vars_to_ns_set -ns_set $extra_vars -var_list {process_instance_id process_id case_id object_id package_id context_id} set task_id [package_instantiate_object -extra_vars $extra_vars tasks_process_instance] return $task_id } - - - -ad_proc -public tasks::new { - -party_id:required - {-object_id ""} - {-process_id ""} - -title:required - {-description ""} - {-mime_type "text/plain"} - {-comment ""} - -due_date:required - {-priority 0} - {-status "o"} - {-user_id ""} - {-ip_addr ""} - {-package_id ""} -} { - insert new task -} { - if {[empty_string_p $package_id]} { - set package_id [ad_conn package_id] - } - if {[empty_string_p $user_id]} { - set user_id [ad_conn user_id] - } - if {[empty_string_p $ip_addr]} { - set ip_addr [ad_conn peeraddr] - } - - set task_id [db_exec_plsql create_task {}] - - return $task_id -} - -ad_proc -public tasks::edit { - -task_id:required - -title:required - {-description ""} - {-mime_type "text/plain"} - {-comment ""} - -due_date:required - {-priority 0} - {-status "o"} - {-user_id ""} - {-ip_addr ""} -} { - update task -} { - if {[empty_string_p $user_id]} { - set user_id [ad_conn user_id] - } - if {[empty_string_p $ip_addr]} { - set ip_addr [ad_conn peeraddr] - } - - db_dml update_task {} - db_dml update_object {} -} - - -ad_proc -public tasks::project_id { - {-package_id ""} -} { - Returns this tasks instance project_id -} { - if { [string is false [exists_and_not_null package_id]] } { - set package_id [ad_conn package_id] - } - set project_id [db_string get_project_id { - select pm_projectsx.item_id - from pm_projectsx, - cr_folders cf - where pm_projectsx.parent_id = cf.folder_id - and cf.package_id = :package_id - } -default {}] - if { [string is false [exists_and_not_null project_id]] } { - tasks::initialize -package_id $package_id - set project_id [tasks::project_id -package_id $package_id] - } - return $project_id -} - -ad_proc -public tasks::initialize { - {-package_id ""} -} { - Returns this tasks instance project_id -} { - if { [string is false [exists_and_not_null package_id]] } { - set package_id [ad_conn package_id] - } - if { [string is false [db_0or1row project_exists_p { select 1 from cr_folders where package_id = :package_id and label = 'Projects' }]] } { - pm::project::new -project_name "[_ tasks.Tasks_Instance]" \ - -status_id "1" \ - -organization_id "" \ - -creation_user [ad_conn user_id] \ - -creation_ip [ad_conn peeraddr] \ - -ongoing_p "t" \ - -package_id $package_id - } -} - Index: openacs-4/packages/tasks/tcl/tasks-procs.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/tcl/tasks-procs.xql,v diff -u -r1.2 -r1.3 --- openacs-4/packages/tasks/tcl/tasks-procs.xql 26 Oct 2005 18:54:29 -0000 1.2 +++ openacs-4/packages/tasks/tcl/tasks-procs.xql 1 Mar 2006 13:49:15 -0000 1.3 @@ -1,6 +1,35 @@ + + + + select 1 + from acs_objects + where object_id in ([template::util::tcl_to_sql_list $objects]) + limit 1 + + + + + + + + select title from t_tasks where task_id = :task_id + + + + + + + + update t_tasks + set status_id = null + where task_id = :task_id + + + + @@ -24,6 +53,16 @@ + + + + select status_id + from t_tasks + where task_id = :task_id + + + + @@ -36,6 +75,7 @@ priority = :priority, due_date = :due_date, assignee_id = :assignee_id + $completed_clause where task_id = :task_id @@ -58,7 +98,6 @@ update t_process_tasks set open_action_id = :open_action_id, - party_id = :party_id, object_id = :object_id, title = :title, description = :description, @@ -86,13 +125,46 @@ + + + + select workflow_id + from t_processes + where process_id = :process_id + + + + + + + + + select case_id + from workflow_cases + where workflow_id = :workflow_id + and object_id = :object_id + + + + + + + + update t_process_instances + set case_id = :case_id + where instance_id = :instance_id + + + + update t_processes set title = :title, description = :description, - mime_type = :mime_type + mime_type = :mime_type, + assignee_id = :assignee_id where process_id = :process_id Index: openacs-4/packages/tasks/www/change-assignee.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/change-assignee.tcl,v diff -u -r1.1 -r1.2 --- openacs-4/packages/tasks/www/change-assignee.tcl 26 Oct 2005 18:54:29 -0000 1.1 +++ openacs-4/packages/tasks/www/change-assignee.tcl 1 Mar 2006 13:49:15 -0000 1.2 @@ -10,6 +10,8 @@ {return_url ""} } +tasks::require_belong_to_package -objects $task_id + set required_p 0 if { ![exists_and_not_null task_id] } { @@ -67,4 +69,4 @@ } } -after_submit { ad_returnredirect $return_url -} \ No newline at end of file +} Index: openacs-4/packages/tasks/www/contact.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/contact.adp,v diff -u -r1.11 -r1.12 --- openacs-4/packages/tasks/www/contact.adp 24 Oct 2005 21:39:24 -0000 1.11 +++ openacs-4/packages/tasks/www/contact.adp 1 Mar 2006 13:49:15 -0000 1.12 @@ -1,21 +1,21 @@ -@party_id@ +@object_id@
+ package_id=@package_id@ />
+<% +# emp_f="@emp_f@" +# tasks_interval="@tasks_interval@" +# query="" +%> Index: openacs-4/packages/tasks/www/contact.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/contact.tcl,v diff -u -r1.10 -r1.11 --- openacs-4/packages/tasks/www/contact.tcl 17 Nov 2005 16:04:39 -0000 1.10 +++ openacs-4/packages/tasks/www/contact.tcl 1 Mar 2006 13:49:15 -0000 1.11 @@ -14,32 +14,10 @@ still allow people to view everyone. } { - {tasks_orderby ""} - {page:optional "1"} - {page_size:optional "25"} - {party_id ""} - {searchterm ""} - {mine_p "t"} - {status_id "1"} - {tasks_interval "30"} - {emp_f ""} - {process_instance:integer,optional} - {cgl_orderby ""} - {tasks_orderby ""} - {page "1"} + {object_id ""} } -properties { - task_term:onevalue - context:onevalue - tasks:multirow - hidden_vars:onevalue } -set user_id [ad_conn user_id] set package_id [ad_conn package_id] -set admin_p [permission::permission_p -object_id $package_id -privilege admin] -set context [list] -set elements "checkbox deleted_p priority title process_title date assignee" -if { [string equal $emp_f "2"]} { - lappend elements contact_name -} +#ad_return_error object $object_id Index: openacs-4/packages/tasks/www/delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/delete.tcl,v diff -u -r1.3 -r1.4 --- openacs-4/packages/tasks/www/delete.tcl 25 Sep 2005 23:49:23 -0000 1.3 +++ openacs-4/packages/tasks/www/delete.tcl 1 Mar 2006 13:49:15 -0000 1.4 @@ -5,48 +5,19 @@ @cvs-id $Id$ } { - {task_id:integer,multiple} - {confirm_p:boolean 1} + {task_id:integer,multiple,notnull} {return_url:notnull} } +tasks::require_belong_to_package -objects $task_id -set num_entries [llength $task_id] -set user_id [ad_conn user_id] - -if { [string is false $confirm_p] } { - - if { $num_entries == 0 } { - ad_returnredirect ./ - return - } - set task_pretty [ad_decode $num_entries 1 "[_ tasks.Task]" "[_ tasks.Tasks]"] - set title "[_ tasks.Delete_task_pretty]" - set context [list $title] - set task2_pretty [ad_decode $num_entries 1 "[_ tasks.this_task]" "[_ tasks.these_tasks]"] - set context [list $title] - set question "[_ tasks.lt_Are_you_sure_you_want_1]" - set yes_url "delete?[export_vars { task_id:multiple { confirm_p 1 } return_url}]" - set no_url "${return_url}" - return -} - - set task_titles [list] foreach task_id $task_id { - lappend task_titles [db_string get_task_title { - select t.title - from t_tasks - where t.task_id = :task_id - }] - db_dml mark_delete { - update t_tasks - set status_id = null - where task_id = :task_id - } + lappend task_titles [tasks::task::title -task_id $task_id] + tasks::task::delete -task_id $task_id } -if { $num_entries > 1 } { +if { [llength $task_titles] > 1 } { set task_list "" set num 1 foreach task_title $task_titles { Index: openacs-4/packages/tasks/www/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/index.adp,v diff -u -r1.10 -r1.11 --- openacs-4/packages/tasks/www/index.adp 21 Feb 2006 12:16:47 -0000 1.10 +++ openacs-4/packages/tasks/www/index.adp 1 Mar 2006 13:49:15 -0000 1.11 @@ -6,15 +6,8 @@ + object_query=@object_query;noquote@ /> + - \ No newline at end of file + Index: openacs-4/packages/tasks/www/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/index.tcl,v diff -u -r1.8 -r1.9 --- openacs-4/packages/tasks/www/index.tcl 21 Feb 2006 12:16:47 -0000 1.8 +++ openacs-4/packages/tasks/www/index.tcl 1 Mar 2006 13:49:15 -0000 1.9 @@ -16,6 +16,8 @@ {page_flush_p "0"} } + + set title "[_ tasks.Tasks]" set context {} set user_id [ad_conn user_id] @@ -62,3 +64,14 @@ } -after_submit { } + +set object_query " +select parties.party_id + from parties + left join cr_items on (parties.party_id = cr_items.item_id) + left join cr_revisions on (cr_items.latest_revision = cr_revisions.revision_id ), + group_distinct_member_map + where parties.party_id = group_distinct_member_map.member_id + and group_distinct_member_map.group_id in ('[join [contacts::default_groups] "','"]') +[contact::search_clause -and -search_id $search_id -query $query -party_id "parties.party_id" -revision_id "revision_id"] +" Index: openacs-4/packages/tasks/www/mail-merge.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/mail-merge.tcl,v diff -u -r1.1 -r1.2 --- openacs-4/packages/tasks/www/mail-merge.tcl 27 Jul 2005 13:44:59 -0000 1.1 +++ openacs-4/packages/tasks/www/mail-merge.tcl 1 Mar 2006 13:49:15 -0000 1.2 @@ -9,6 +9,8 @@ {return_url:notnull} } +tasks::require_belong_to_package -objects $process_id + set party_ids [db_list get_party_ids " select distinct party_id from pm_task_assignment Index: openacs-4/packages/tasks/www/mark-completed.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/mark-completed.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/packages/tasks/www/mark-completed.tcl 25 Sep 2005 23:49:23 -0000 1.2 +++ openacs-4/packages/tasks/www/mark-completed.tcl 1 Mar 2006 13:49:15 -0000 1.3 @@ -12,6 +12,8 @@ {return_url:notnull} } +tasks::require_belong_to_package -objects $task_id + set num_entries [llength $task_id] if { [string is false $confirm_p] } { Index: openacs-4/packages/tasks/www/process-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/process-add-edit.tcl,v diff -u -r1.3 -r1.4 --- openacs-4/packages/tasks/www/process-add-edit.tcl 26 Oct 2005 18:54:29 -0000 1.3 +++ openacs-4/packages/tasks/www/process-add-edit.tcl 1 Mar 2006 13:49:15 -0000 1.4 @@ -16,6 +16,9 @@ title:onevalue } +if { ![ad_form_new_p -key process_id] } { + tasks::require_belong_to_package -objects $process_id +} set package_id [ad_conn package_id] set user_id [ad_maybe_redirect_for_registration] Index: openacs-4/packages/tasks/www/process-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/process-delete.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/packages/tasks/www/process-delete.tcl 25 Sep 2005 23:49:23 -0000 1.2 +++ openacs-4/packages/tasks/www/process-delete.tcl 1 Mar 2006 13:49:15 -0000 1.3 @@ -18,6 +18,8 @@ } -errors { } +tasks::require_belong_to_package -objects $process_id + set package_id [ad_conn package_id] permission::require_permission -object_id $package_id -privilege delete @@ -29,8 +31,10 @@ where process_id = :process_id } + set title "Delete process: $title" set context [list "Delete: $title"] + set process $title set yes_url [export_vars -base process-delete {process_id assignee_id {confirm_p 1} return_url}] set no_url $return_url Index: openacs-4/packages/tasks/www/process-task-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/process-task-delete.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/packages/tasks/www/process-task-delete.tcl 25 Sep 2005 23:49:23 -0000 1.2 +++ openacs-4/packages/tasks/www/process-task-delete.tcl 1 Mar 2006 13:49:15 -0000 1.3 @@ -13,6 +13,8 @@ {orderby ""} } +tasks::require_belong_to_package -objects $process_task_id +tasks::require_belong_to_package -objects $process_id set num_entries [llength $process_task_id] Index: openacs-4/packages/tasks/www/process-task.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/process-task.tcl,v diff -u -r1.3 -r1.4 --- openacs-4/packages/tasks/www/process-task.tcl 26 Oct 2005 18:54:29 -0000 1.3 +++ openacs-4/packages/tasks/www/process-task.tcl 1 Mar 2006 13:49:15 -0000 1.4 @@ -24,6 +24,7 @@ } } +tasks::require_belong_to_package -objects $process_id set package_id [ad_conn package_id] set user_id [ad_maybe_redirect_for_registration] Index: openacs-4/packages/tasks/www/process.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/process.tcl,v diff -u -r1.3 -r1.4 --- openacs-4/packages/tasks/www/process.tcl 26 Oct 2005 18:54:29 -0000 1.3 +++ openacs-4/packages/tasks/www/process.tcl 1 Mar 2006 13:49:15 -0000 1.4 @@ -25,6 +25,9 @@ process_id:notnull {You must specify a process to use. Please back up and select a process} } +tasks::require_belong_to_package -objects $process_id + + # --------------------------------------------------------------- # the unique identifier for this package @@ -95,7 +98,7 @@ } } \ -bulk_actions { - "Delete" "process-task-delete" "Delete tasks" "#tasks.Change_Assignee#" change-assignee "#tasks.Change_Assignee#" + "Delete" "process-task-delete" "Delete tasks" "#tasks.Change_Assignee#" tasks-change-assignee "#tasks.Change_Assignee#" } \ -bulk_action_export_vars { process_id Index: openacs-4/packages/tasks/www/processes-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/tasks/www/processes-postgresql.xql,v diff -u -r1.2 -r1.3 --- openacs-4/packages/tasks/www/processes-postgresql.xql 25 Sep 2005 23:49:23 -0000 1.2 +++ openacs-4/packages/tasks/www/processes-postgresql.xql 1 Mar 2006 13:49:15 -0000 1.3 @@ -13,6 +13,7 @@ from t_processes p, acs_objects o where p.process_id = o.object_id and p.workflow_id is not null + and o.package_id = :package_id order by lower(p.title)