Index: openacs-4/contrib/packages/project-manager/project-manager.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/Attic/project-manager.info,v diff -u -r1.16 -r1.16.2.1 --- openacs-4/contrib/packages/project-manager/project-manager.info 12 Mar 2004 13:44:41 -0000 1.16 +++ openacs-4/contrib/packages/project-manager/project-manager.info 20 May 2004 17:30:02 -0000 1.16.2.1 @@ -6,30 +6,31 @@ Project Managers f f - project-manager - - + + Jade Rubick Project management tool for OpenACS - 2004-03-05 + 2004-05-19 + Integrated Bakery Resources Track tasks, estimates and actual progress for a project. See the <a href="http://openacs.org/projects/dotwrk/project_management/">project page</a> for more information. - + - + - + + Index: openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-custom-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/sql/postgresql/Attic/project-manager-custom-drop.sql,v diff -u -r1.3 -r1.3.2.1 --- openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-custom-drop.sql 26 Feb 2004 15:15:40 -0000 1.3 +++ openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-custom-drop.sql 20 May 2004 17:30:02 -0000 1.3.2.1 @@ -9,3 +9,4 @@ -- drop any custom tables here. select content_type__drop_attribute ('pm_project', 'customer_id', 't'); + Index: openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-functions-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/sql/postgresql/Attic/project-manager-functions-create.sql,v diff -u -r1.13 -r1.13.2.1 --- openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-functions-create.sql 12 Mar 2004 13:44:42 -0000 1.13 +++ openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-functions-create.sql 20 May 2004 17:30:02 -0000 1.13.2.1 @@ -19,9 +19,13 @@ returns varchar as ' declare p_pm_project_id alias for $1; - v_pm_project_name varchar; +<<<<<<< project-manager-functions-create.sql + v_pm_project_name pm_projects.project_name%TYPE; +======= + v_pm_project_name pm_projectsx.name%TYPE; +>>>>>>> 1.16 begin - select project_name || ''_'' || p_pm_project_id into v_pm_project_name + select name || ''_'' || p_pm_project_id into v_pm_project_name from pm_projectsx where item_id = p_pm_project_id; return v_pm_project_name; @@ -33,7 +37,7 @@ select define_function_args('pm_project__new_root_folder', 'package_id'); -create function pm_project__new_root_folder (integer) +create or replace function pm_project__new_root_folder (integer) returns integer as ' declare p_package_id alias for $1; @@ -51,7 +55,7 @@ v_folder_name, -- name ''Projects'', -- label ''Project Repository'', -- description - null -- parent_id + p_package_id -- parent_id ); -- Register the standard content types @@ -80,7 +84,7 @@ select define_function_args('pm_project__get_root_folder', 'package_id,create_if_not_present_p'); -create function pm_project__get_root_folder (integer, boolean) +create or replace function pm_project__get_root_folder (integer, boolean) returns integer as ' declare p_package_id alias for $1; @@ -130,14 +134,15 @@ -- is null. Otherwise a project folder will be created as a sub-folder -- of an existing project folder. -select define_function_args('pm_project__new_project_item', 'project_name, project_code, parent_id, goal, description, planned_start_date, planned_end_date, actual_start_date, actual_end_date, logger_project, ongoing_p, status_id, customer_id, creation_date, creation_user, creation_ip, package_id'); +select define_function_args('pm_project__new_project_item', 'project_name, project_code, parent_id, goal, description, mime_type, planned_start_date, planned_end_date, actual_start_date, actual_end_date, logger_project, ongoing_p, status_id, customer_id, creation_date, creation_user, creation_ip, package_id'); create or replace function pm_project__new_project_item ( varchar, -- project_name varchar, -- project_code integer, -- parent_id varchar, -- goal varchar, -- description + varchar, -- mime_type timestamptz, -- planned_start_date timestamptz, -- planned_end_date timestamptz, -- actual_start_date @@ -158,18 +163,19 @@ p_parent_id alias for $3; p_goal alias for $4; p_description alias for $5; - p_planned_start_date alias for $6; - p_planned_end_date alias for $7; - p_actual_start_date alias for $8; - p_actual_end_date alias for $9; - p_logger_project alias for $10; - p_ongoing_p alias for $11; - p_status_id alias for $12; - p_customer_id alias for $13; - p_creation_date alias for $14; - p_creation_user alias for $15; - p_creation_ip alias for $16; - p_package_id alias for $17; + p_mime_type alias for $6; + p_planned_start_date alias for $7; + p_planned_end_date alias for $8; + p_actual_start_date alias for $9; + p_actual_end_date alias for $10; + p_logger_project alias for $11; + p_ongoing_p alias for $12; + p_status_id alias for $13; + p_customer_id alias for $14; + p_creation_date alias for $15; + p_creation_user alias for $16; + p_creation_ip alias for $17; + p_package_id alias for $18; v_item_id cr_items.item_id%TYPE; v_revision_id cr_revisions.revision_id%TYPE; @@ -202,7 +208,7 @@ ''pm_project'', -- content_type p_project_name, -- title p_description, -- description - ''text/plain'', -- mime_type + p_mime_type, -- mime_type null, -- nls_language null -- data ); @@ -211,7 +217,7 @@ p_project_name, -- title p_description, -- description now(), -- publish_date - ''text/plain'', -- mime_type + p_mime_type, -- mime_type NULL, -- nls_language NULL, -- data v_item_id, -- item_id @@ -283,7 +289,7 @@ select define_function_args('pm_project__new_project_revision', 'item_id, project_name, project_code, parent_id, goal, description, planned_start_date, planned_end_date, actual_start_date, actual_end_date, logger_project, ongoing_p, status_id, organization_id, creation_date, creation_user, creation_ip, package_id'); -create function pm_project__new_project_revision ( +create or replace function pm_project__new_project_revision ( integer, -- item_id varchar, -- project_name varchar, -- project_code @@ -373,7 +379,7 @@ select define_function_args('pm_project__new_unique_name', 'package_id'); -create function pm_project__new_unique_name (integer) +create or replace function pm_project__new_unique_name (integer) returns text as ' declare p_package_id alias for $1; @@ -427,12 +433,13 @@ -- If it is not associated with a project, then it is placed in the root -- project repository folder. -select define_function_args('pm_task__new_task_item', 'project_id, title, description, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, status_id, creation_date, creation_user, creation_ip, package_id'); +select define_function_args('pm_task__new_task_item', 'project_id, title, description, html_p, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, status_id, creation_date, creation_user, creation_ip, package_id'); -create function pm_task__new_task_item ( +create or replace function pm_task__new_task_item ( integer, -- project_id varchar, -- title varchar, -- description + varchar, -- html_p timestamptz, -- end_date numeric, -- percent_complete numeric, -- estimated_hours_work @@ -449,16 +456,17 @@ p_project_id alias for $1; p_title alias for $2; p_description alias for $3; - p_end_date alias for $4; - p_percent_complete alias for $5; - p_estimated_hours_work alias for $6; - p_estimated_hours_work_min alias for $7; - p_estimated_hours_work_max alias for $8; - p_status_id alias for $9; - p_creation_date alias for $10; - p_creation_user alias for $11; - p_creation_ip alias for $12; - p_package_id alias for $13; + p_mime_type alias for $4; + p_end_date alias for $5; + p_percent_complete alias for $6; + p_estimated_hours_work alias for $7; + p_estimated_hours_work_min alias for $8; + p_estimated_hours_work_max alias for $9; + p_status_id alias for $10; + p_creation_date alias for $11; + p_creation_user alias for $12; + p_creation_ip alias for $13; + p_package_id alias for $14; v_item_id cr_items.item_id%TYPE; v_revision_id cr_revisions.revision_id%TYPE; @@ -484,7 +492,7 @@ ''pm_task'', -- content_type p_title, -- title p_description, -- description - ''text/plain'', -- mime_type + p_mime_type, -- mime_type null, -- nls_language null -- data ); @@ -493,7 +501,7 @@ p_title, -- title p_description, -- description now(), -- publish_date - ''text/plain'', -- mime_type + p_mime_type, -- mime_type NULL, -- nls_language NULL, -- data v_item_id, -- item_id @@ -525,13 +533,14 @@ end;' language 'plpgsql'; -select define_function_args('pm_task__new_task_revision', 'task_id, project_id, title, description, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, creation_date, creation_user, creation_ip, package_id'); +select define_function_args('pm_task__new_task_revision', 'task_id, project_id, title, description, mime_type, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, creation_date, creation_user, creation_ip, package_id'); -create function pm_task__new_task_revision ( +create or replace function pm_task__new_task_revision ( integer, -- task_id (the item_id) integer, -- project_id varchar, -- title varchar, -- description + varchar, -- mime_type timestamptz, -- end_date numeric, -- percent_complete numeric, -- estimated_hours_work @@ -550,30 +559,31 @@ p_project_id alias for $2; p_title alias for $3; p_description alias for $4; - p_end_date alias for $5; - p_percent_complete alias for $6; - p_estimated_hours_work alias for $7; - p_estimated_hours_work_min alias for $8; - p_estimated_hours_work_max alias for $9; - p_actual_hours_worked alias for $10; - p_status_id alias for $11; - p_creation_date alias for $12; - p_creation_user alias for $13; - p_creation_ip alias for $14; - p_package_id alias for $15; - + p_mime_type alias for $5; + p_end_date alias for $6; + p_percent_complete alias for $7; + p_estimated_hours_work alias for $8; + p_estimated_hours_work_min alias for $9; + p_estimated_hours_work_max alias for $10; + p_actual_hours_worked alias for $11; + p_status_id alias for $12; + p_creation_date alias for $13; + p_creation_user alias for $14; + p_creation_ip alias for $15; + p_package_id alias for $16; v_revision_id cr_revisions.revision_id%TYPE; v_id cr_items.item_id%TYPE; begin select acs_object_id_seq.nextval into v_id from dual; -- We want to put the task under the project item + update cr_items set parent_id = p_project_id where item_id = p_task_id; v_revision_id := content_revision__new ( p_title, -- title p_description, -- description now(), -- publish_date - ''text/plain'', -- mime_type + p_mime_type, -- mime_type NULL, -- nls_language NULL, -- data p_task_id, -- item_id Index: openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-table-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/sql/postgresql/Attic/project-manager-table-create.sql,v diff -u -r1.19 -r1.19.2.1 --- openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-table-create.sql 12 Mar 2004 13:44:42 -0000 1.19 +++ openacs-4/contrib/packages/project-manager/sql/postgresql/project-manager-table-create.sql 20 May 2004 17:30:02 -0000 1.19.2.1 @@ -135,7 +135,7 @@ create table pm_project_assignment ( project_id integer constraint pm_proj_role_map_project_fk - references pm_projects + references cr_items on delete cascade, role_id integer constraint pm_project_role_map_role_fk Index: openacs-4/contrib/packages/project-manager/tcl/project-manager-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/tcl/Attic/project-manager-procs.tcl,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/contrib/packages/project-manager/tcl/project-manager-procs.tcl 12 Mar 2004 13:44:43 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/tcl/project-manager-procs.tcl 20 May 2004 17:30:04 -0000 1.2.2.1 @@ -20,9 +20,199 @@ } { Extended nvl, for dates only } { - if { [string equal $value "{} {} {} {} {} {}"]} { + if {[string equal $value "{} {} {} {} {} {}"] \ + || [empty_string_p $value]} { return $value_if_null } else { return $value_if_not_null } } +<<<<<<< project-manager-procs.tcl + + +ad_proc -public pm::util::string_truncate_and_pad { + -length + {-ellipsis "..."} + -string +} { + Truncates a string to a given length, or pads it to match a given length + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-14 + + @param length + + @param ellipsis + + @param string + + @return + + @error +} { + + set new_string [string_truncate -len $length -ellipsis $ellipsis -- $string] + set new_string_length [string length $new_string] + + if {$new_string_length < $length} { + set new_string "$new_string[string repeat " " [expr $length - $new_string_length]]" + } + + return $new_string +} +======= + + +ad_proc -public pm::util::string_truncate_and_pad { + -length + {-ellipsis "..."} + -string +} { + Truncates a string to a given length, or pads it to match a given length + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-14 + + @param length + + @param ellipsis + + @param string + + @return + + @error +} { + + set new_string [string_truncate -len $length -ellipsis $ellipsis -- $string] + set new_string_length [string length $new_string] + + if {$new_string_length < $length} { + set new_string "$new_string[string repeat " " [expr $length - $new_string_length]]" + } + + return $new_string +} + + +ad_proc -private pm::util::word_diff { + {-old:required} + {-new:required} + {-split_by {}} + {-filter_proc {ad_quotehtml}} + {-start_old {}} + {-end_old {}} + {-start_new {}} + {-end_new {}} +} { + This procedure has been BACKPORTED from OpenACS HEAD. That means + you should not use it in your own applications. If you do, you'll + need to update your application once OpenACS 5.2 is available, and + create a dependency on OpenACS 5.2 in your .info file. + + Does a word (or character) diff on two lines of text and indicates text + that has been deleted/changed or added by enclosing it in + start/end_old/new. + + @param old The original text. + @param new The modified text. + + @param split_by If split_by is a space, the diff will be made + on a word-by-word basis. If it is the empty string, it will be made on + a char-by-char basis. + + @param filter_proc A filter to run the old/new text through before + doing the diff and inserting the HTML fragments below. Keep in mind + that if the input text is HTML, and the start_old, etc... fragments are + inserted at arbitrary locations depending on where the diffs are, you + might end up with invalid HTML unless the original HTML is quoted. + + @param start_old HTML fragment to place before text that has been removed. + @param end_old HTML fragment to place after text that has been removed. + @param start_new HTML fragment to place before new text. + @param end_new HTML fragment to place after new text. + + @see ad_quotehtml + @author Gabriel Burca +} { + + if {$filter_proc != ""} { + set old [$filter_proc $old] + set new [$filter_proc $new] + } + + set old_f [ns_tmpnam] + set new_f [ns_tmpnam] + set old_fd [open $old_f "w"] + set new_fd [open $new_f "w"] + puts $old_fd [join [split $old $split_by] "\n"] + puts $new_fd [join [split $new $split_by] "\n"] + close $old_fd + close $new_fd + + # Diff output is 1 based, our lists are 0 based, so insert a dummy + # element to start the list with. + set old_w [linsert [split $old $split_by] 0 {}] + set sv 1 + +# For debugging purposes: +# set diff_pipe [open "| diff -f $old_f $new_f" "r"] +# while {![eof $diff_pipe]} { +# append res "[gets $diff_pipe]
" +# } + + set diff_pipe [open "| diff -f $old_f $new_f" "r"] + while {![eof $diff_pipe]} { + gets $diff_pipe diff + if {[regexp {^d(\d+)(\s+(\d+))?$} $diff full m1 m2]} { + if {$m2 != ""} {set d_end $m2} else {set d_end $m1} + for {set i $sv} {$i < $m1} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + for {set i $m1} {$i <= $d_end} {incr i} { + append res "${split_by}${start_old}[lindex $old_w $i]${end_old}" + } + set sv [expr $d_end + 1] + } elseif {[regexp {^c(\d+)(\s+(\d+))?$} $diff full m1 m2]} { + if {$m2 != ""} {set d_end $m2} else {set d_end $m1} + for {set i $sv} {$i < $m1} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + for {set i $m1} {$i <= $d_end} {incr i} { + append res "${split_by}${start_old}[lindex $old_w $i]${end_old}" + } + while {![eof $diff_pipe]} { + gets $diff_pipe diff + if {$diff == "."} { + break + } else { + append res "${split_by}${start_new}${diff}${end_new}" + } + } + set sv [expr $d_end + 1] + } elseif {[regexp {^a(\d+)$} $diff full m1]} { + set d_end $m1 + for {set i $sv} {$i < $m1} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + while {![eof $diff_pipe]} { + gets $diff_pipe diff + if {$diff == "."} { + break + } else { + append res "${split_by}${start_new}${diff}${end_new}" + } + } + set sv [expr $d_end + 1] + } + } + + for {set i $sv} {$i < [llength $old_w]} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + + file delete -- $old_f $new_f + + return $res +} +>>>>>>> 1.4 Index: openacs-4/contrib/packages/project-manager/tcl/project-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/tcl/Attic/project-procs-postgresql.xql,v diff -u -r1.4 -r1.4.2.1 --- openacs-4/contrib/packages/project-manager/tcl/project-procs-postgresql.xql 12 Mar 2004 13:44:43 -0000 1.4 +++ openacs-4/contrib/packages/project-manager/tcl/project-procs-postgresql.xql 20 May 2004 17:30:04 -0000 1.4.2.1 @@ -53,6 +53,7 @@ :parent_id, :goal, :description, + :mime_type, to_timestamp(:planned_start_date,'YYYY MM DD HH24 MI SS'), to_timestamp(:planned_end_date,'YYYY MM DD HH24 MI SS'), null, @@ -101,12 +102,22 @@ else t.actual_hours_worked end as worked, t.estimated_hours_work as to_work, t.item_id as my_iid, - to_char(end_date,'J') as task_deadline_j + to_char(end_date,'J') as task_deadline_j, + to_char(earliest_start,'J') as old_earliest_start_j, + to_char(earliest_finish,'J') as old_earliest_finish_j, + to_char(latest_start,'J') as old_latest_start_j, + to_char(latest_finish,'J') as old_latest_finish_j, + s.status_type from - pm_tasks_revisionsx t, cr_items i + pm_tasks_revisionsx t, + cr_items i, + pm_tasks ti, + pm_task_status s where t.item_id in ([join $task_list ", "]) and - i.live_revision = t.revision_id + i.live_revision = t.revision_id and + i.item_id = ti.task_id and + ti.status = s.status_id Index: openacs-4/contrib/packages/project-manager/tcl/project-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/tcl/Attic/project-procs.tcl,v diff -u -r1.6.2.1 -r1.6.2.2 --- openacs-4/contrib/packages/project-manager/tcl/project-procs.tcl 25 Mar 2004 18:36:05 -0000 1.6.2.1 +++ openacs-4/contrib/packages/project-manager/tcl/project-procs.tcl 20 May 2004 17:30:04 -0000 1.6.2.2 @@ -86,13 +86,17 @@ {-task_item_id ""} {-project_item_id ""} {-update_status_p "t"} + {-party_id ""} } { Adds a logger entry to a project. If task_item_id is passed in, also links it up with that task, and updates the task hours. - + @author Jade Rubick (jader@bread.com) @creation-date 2004-03-05 + + @see logger::entry::new + @see pm::project::compute_status @param entry_id If passed in, determines the entry_id for the newly logged entry @@ -117,6 +121,9 @@ This can be set to f when editing a task, because these things are done later anyway. + @param party_id If set, the party that creates the new logger + entry. If not set, defaults to ad_conn user_id + @return 0 if there no task it is logged against, otherwise returns the total number of hours logged to that task @@ -132,13 +139,20 @@ set entry_id [db_nextval acs_object_id_seq] } + if {[exists_and_not_null party_id]} { + set creation_user $party_id + } else { + set creation_user [ad_conn user_id] + } + # add in the new entry logger::entry::new -entry_id $entry_id \ -project_id $logger_project_id \ -variable_id $variable_id \ -value $value \ -time_stamp $timestamp_ansi \ - -description $description + -description $description \ + -party_id $creation_user # if we have a pm_task_id, then we need to note that this # entry is logged to a particular task. @@ -173,6 +187,7 @@ {-parent_id ""} {-goal ""} {-description ""} + {-mime_type "text/plain"} {-planned_start_date ""} {-planned_end_date ""} {-actual_start_date ""} @@ -206,7 +221,6 @@ # create a logger project set logger_project [logger::project::new \ -name $project_name \ - -description $description \ -project_lead $creation_user \ ] @@ -265,8 +279,19 @@ } { Stub for project edit - - + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-03 + + @param project_item_id + + @param project_name + + @return + + @error +} { + + set returnval [db_exec_plsql update_project " select pm_project__new_project_revision ( :project_item_id, :project_name, @@ -278,29 +303,18 @@ to_timestamp(:planned_end_date,'YYYY MM DD HH24 MI SS'), null, null, + :logger_project, :ongoing_p, :status_id, - :customer_id, + :organization_id, now(), - :user_id, - :peeraddr, + :creation_user, + :creation_ip, :package_id ); - - + "] - @author Jade Rubick (jader@bread.com) - @creation-date 2004-03-03 - - @param project_item_id - - @param project_name - - @return - - @error -} { - + return $returnval } @@ -552,7 +566,8 @@ latest_finish(i) = latest_start(i) + activity_time(i) - Tasks in ongoing projects are given null completion dates. + Tasks in ongoing projects are given null completion dates, + unless they already have deadlines.

@@ -575,6 +590,9 @@ For a project with subprojects, the statistics are based on the tasks of both of those projects. +

+ Tasks which are closed are not updated + @author Jade Rubick (jader@bread.com) @creation-date 2004-02-19 @@ -595,6 +613,11 @@ # to improve this in the future, be more intelligent about what is updated. # i.e., this procedure updates everything, which is necessary sometimes, # but not if you only edit one task. + # + # I added in an optimization to only save when something has + # changed -- JR + # I added in another optimization that only saves tasks that are + # open -- JR # ------------------------------------------------------------------------- # Add in resource limits. (it's not realistic that 300 tasks can be done in # one day) @@ -667,16 +690,34 @@ db_foreach tasks_query { } { + # We now save information about all the tasks, so that we can + # save on database hits later. Specifically, what we'll do is + # we won't need to save changes if the earliest_start, + # earliest finish, latest_start and latest_finish all haven't + # changed at all. We also save whether the task is open (o) or + # closed(c). + + set old_ES_j($my_iid) $old_earliest_start_j + set old_EF_j($my_iid) $old_earliest_finish_j + set old_LS_j($my_iid) $old_latest_start_j + set old_LF_j($my_iid) $old_latest_finish_j + set old_task_status($my_iid) $status_type + + # ns_log Notice "old_task_status: $my_iid $status_type" + set activity_time($my_iid) [expr $to_work - $worked] if {[exists_and_not_null task_deadline_j]} { - # ns_log notice "$my_iid has a deadline $task_jdeadline_j" + # ns_log notice "$my_iid has a deadline $task_deadline_j" set latest_finish($my_iid) $task_deadline_j - set latest_start($my_iid) [latest_start $task_deadline_j $activity_time($my_iid) $hours_day] - + set latest_start($my_iid) [pm::project::latest_start \ + -end_date_j $task_deadline_j \ + -hours_to_complete $activity_time($my_iid) \ + -hours_day $hours_day] + } } @@ -709,7 +750,7 @@ db_1row project_info { } if {[string equal $ongoing_p t] && ![empty_string_p $end_date_j]} { - ns_log Error "Project cannot be ongoing and have a non-null end-date" + ns_log Error "Project cannot be ongoing and have a non-null end-date. Setting end date to blank" set end_date_j "" } @@ -797,6 +838,11 @@ set max_earliest_start 0 + # testing if this fixes the bug + if {![exists_and_not_null depends($task_item)]} { + set depends($task_item) [list] + } + foreach dependent_item $depends($task_item) { set my_earliest_start [my_earliest_start $earliest_start($dependent_item) $activity_time($dependent_item) $hours_day] @@ -807,7 +853,7 @@ } set earliest_start($task_item) $max_earliest_start - # set earliest_finish($task_item) [expr $max_earliest_start + [expr $activity_time($task_item) / double($hours_day)]] + set earliest_finish($task_item) [earliest_finish $max_earliest_start $activity_time($task_item) $hours_day] # ns_log Notice \ @@ -851,7 +897,7 @@ # Note the latest_finish dates may be set to an arbitrary deadline. # Also note that it is possible for a project to be ongoing. # In that case, the latest_start and latest_finish dates should - # be set to null. + # be set to null, unless there is a hard deadline (end_date). # ----------------------------------------------------------------- # If these represent the dependency hierarchy: # 2155 @@ -1209,7 +1255,23 @@ set lf "" } - db_dml update_task { } + # Only update the task if something has actually + # changed. Hopefully this should help speed things up. + + if { \ + [string equal $es $old_ES_j($task_item)] && \ + [string equal $ef $old_EF_j($task_item)] && \ + [string equal $ls $old_LS_j($task_item)] && \ + [string equal $lf $old_LF_j($task_item)]} { + # do nothing + } else { + # if the task is open... + if {[string equal "o" $old_task_status($task_item)]} { + db_dml update_task { } + } + } + + } @@ -1278,3 +1340,37 @@ (select live_revision from cr_items where item_id = :project_item_id) " -default "no_project"] } + + +ad_proc -public pm::project::get_list_of_open { +} { + Returns a list of lists, of all open project ids and their names + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-13 + + @return list of lists, with project id and name + + @error +} { + + set return_val [db_list_of_lists get_vals " + SELECT + case when o.name is null then p.title else o.name || ' - ' || p.title end, + p.item_id + FROM pm_projectsx p + LEFT JOIN + organizations o + ON p.customer_id = o.organization_id, + cr_items i, + pm_project_status s + WHERE + p.project_id = i.live_revision and + s.status_id = p.status_id and + s.status_type = 'o' + ORDER BY + lower(o.name), lower(p.title) + "] + + return $return_val +} Index: openacs-4/contrib/packages/project-manager/tcl/task-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/tcl/Attic/task-procs-postgresql.xql,v diff -u -r1.4 -r1.4.2.1 --- openacs-4/contrib/packages/project-manager/tcl/task-procs-postgresql.xql 12 Mar 2004 13:44:43 -0000 1.4 +++ openacs-4/contrib/packages/project-manager/tcl/task-procs-postgresql.xql 20 May 2004 17:30:04 -0000 1.4.2.1 @@ -27,6 +27,27 @@ + + + select status + from pm_tasks + where task_id = :task_item_id + + + + + + SELECT + case when status_type = 'c' then 0 else 1 end as open_p + FROM + pm_tasks t, + pm_task_status s + WHERE + task_id = :task_item_id and + t.status = s.status_id + + + select status_id @@ -53,13 +74,36 @@ + + + SELECT + r.item_id, + r.title as task_title + FROM + pm_tasks_revisionsx r, + cr_items i, + pm_tasks t, + pm_task_status s + WHERE + r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id and + t.status = s.status_id and + s.status_type = 'o' + $union_clause + ORDER BY + task_title + + + select pm_task__new_task_revision ( :task_item_id, :project_item_id, :title, :description, + :mime_type, [pm::util::datenvl -value $end_date -value_if_null "null" -value_if_not_null "to_timestamp('$end_date','YYYY MM DD HH24 MI SS')"], :percent_complete, :estimated_hours_work, @@ -76,20 +120,21 @@ - select pm_task__new_task_item ( - :project_id, - :title, - :description, - :end_date, - :percent_complete, - :estimated_hours_work, - :estimated_hours_work_min, - :estimated_hours_work_max, - :status_id, - coalesce (:creation_date,current_timestamp), - :creation_user, - :creation_ip, - :package_id) + select pm_task__new_task_item ( + :project_id, + :title, + :description, + :mime_type, + [pm::util::datenvl -value $end_date -value_if_null "null" -value_if_not_null "to_timestamp('$end_date','YYYY MM DD HH24 MI SS')"], + :percent_complete, + :estimated_hours_work, + :estimated_hours_work_min, + :estimated_hours_work_max, + :status_id, + coalesce (:creation_date,current_timestamp), + :creation_user, + :creation_ip, + :package_id) Index: openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/tcl/Attic/task-procs.tcl,v diff -u -r1.4 -r1.4.2.1 --- openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 12 Mar 2004 13:44:43 -0000 1.4 +++ openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 20 May 2004 17:30:04 -0000 1.4.2.1 @@ -14,6 +14,135 @@ +ad_proc -public pm::task::dependency_options { + {-edit_p "f"} + -project_item_id + {-task_item_id ""} + {-dependency_task_ids ""} + {-number "0"} + {-current_number "0"} +} { + Returns a list of lists suitable for use in a select list for + ad_form. Contains a list of possible tasks that this task can + depend upon. + +

+ + There is one special case that we handle: if you are creating new + tasks (not editing), you can have them depend on each other. + So if you create two tasks at the same time, you may want task + 2 to depend on task 1. Instead of a task_item_id, we then + specify a value of this form: + +

+ numX +
+ + where X represents the number of the new task, ranging from 1 + to n. + +

+ + To be more efficient when creating multiple tasks at the same + time, we should cache the database calls. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-13 + + @param edit_p Is this for a task being edited? Or a new task? + + @param project_item_id The project we're finding tasks from + + @param task_item_id The task ID. This is used because we do not + want a task to depend on itself, so it is excluded from the list. + + @param dependency_task_ids For edited tasks, the current task_ids + that it depends on. Used because sometimes it can be closed, and + it wouldn't otherwise appear on the list. This is a list. + + @param number When the list is returned, it includes entries for + number new tasks, in the numX format described in these docs. + + @param current_number The current number. Used for new tasks. It + prevents allowing dependencies on the task being created. + + @return + + @error +} { + + # get tasks this task can depend on + + if {[exists_and_not_null dependency_task_ids]} { + + set union_clause " + UNION + SELECT + r.item_id, + r.title as task_title + FROM + pm_tasks_revisionsx r, + cr_items i, + pm_tasks t + WHERE + r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id + and t.task_id in ([join $dependency_task_ids ","])" + } else { + set union_clause "" + } + + set keys [list] + + db_foreach get_dependency_tasks { } { + set options($task_title) $item_id + lappend keys $task_title + } + + set keys [lsort $keys] + + + set dependency_options_full "{\"--None--\" \"\"} " + + if {!$edit_p} { + # now set up dependency options + + for {set j 1} {$j <= $number} {incr j} { + if {![string equal $current_number $j]} { + append dependency_options_full "{\"New Task \#$j\" \"num$j\"} " + } + } + } + + # for editing tasks, we skip ourselves (because depending on + # ourselves just sometimes isn't an option) + + if {[string equal $edit_p t]} { + foreach key $keys { + + # make sure we're not dependent on ourselves + + if {![string equal $task_item_id $options($key)]} { + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an error. + append dependency_options_full "{{$key} $options($key)} " + } + } + } else { + foreach key $keys { + + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an error. + append dependency_options_full "{{$key} $options($key)} " + } + } + + + return $dependency_options_full +} + + ad_proc -public pm::task::dependency_delete_all { -task_item_id:required @@ -92,8 +221,17 @@ project.item_id = :project_item_id "] - set loop_limit [llength $project_tasks] + # we do not allow tasks to depend on items outside of their + # project. So if it's not in the list of tasks for that project, + # we reject it + if {[lsearch $project_tasks $parent_id] < 0} { + set loop_limit 0 + set valid_p FALSE + } else { + set loop_limit [llength $project_tasks] + } + if {$loop_limit > 0} { set dep_list [list] @@ -132,7 +270,7 @@ db_dml insert_dep "insert into pm_task_dependency (dependency_id, task_id, parent_task_id, dependency_type) values (:dependency_id, :task_item_id, :parent_id, 'finish_before_start')" } else { - ns_log Notice "Task $task_item_id was not added due to looping" + ns_log Notice "Task dependency for $task_item_id on $parent_id was not added due to looping or being outside of the current project" } } @@ -184,7 +322,13 @@ array set task_state [nsv_array get task_node_status] - set used $task_state($tNode) + # this should only happen if dependencies span projects + # they shouldn't, but I check anyway. + if {![info exists task_state($tNode)]} { + set used 0 + } else { + set used $task_state($tNode) + } if {[string equal $used 1]} { return FALSE @@ -225,9 +369,9 @@ @return task_item_id - @error + @error Returns -1 if there is no such task } { - set return_val [db_string get_item_id { }] + set return_val [db_string get_item_id { } -default "-1"] return $return_val } @@ -246,15 +390,37 @@ @return task_item_id - @error + @error If there is no such task item, then returns -1 } { - set return_val [db_string get_revision_id { }] + set return_val [db_string get_revision_id { } -default "-1"] return $return_val } +ad_proc -public pm::task::current_status { + -task_item_id:required +} { + Returns the current status value for open tasks +} { + set return_val [db_string get_current_status { }] + + return $return_val +} + + +ad_proc -public pm::task::open_p { + -task_item_id:required +} { + Returns 1 if the task is open, 0 otherwise +} { + set return_val [db_string open_p { }] + + return $return_val +} + + ad_proc -public pm::task::default_status_open {} { Returns the default status value for open tasks } { @@ -279,6 +445,7 @@ -project_item_id:required -title:required -description:required + {-mime_type "text/plain"} -end_date:required -percent_complete:required -estimated_hours_work:required @@ -303,6 +470,8 @@ @param description + @param mime_type + @param end_date @param percent_complete @@ -327,16 +496,26 @@ @error } { - if {$percent_complete >= 100} { - set status_id [pm::task::default_status_closed] + if {![exists_and_not_null status_id]} { + set status_id [pm::task::current_status \ + -task_item_id $task_item_id] } - if {![exists_and_not_null status_id]} { - set status_id [pm::task::default_status_open] + if {$estimated_hours_work_min > $estimated_hours_work_max} { + set temp $estimated_hours_work_max + set estimated_hours_work_max $estimated_hours_work_min + set estimated_hours_work_min $temp } set return_val [db_exec_plsql new_task_revision { *SQL }] + # if the we've done 100% of the work, then we close the task + if {$percent_complete >= 100} { + pm::task::close -task_item_id $task_item_id + } else { + pm::task::open -task_item_id $task_item_id + } + return $return_val } @@ -346,6 +525,7 @@ -project_id:required -title:required {-description ""} + {-mime_type "text/plain"} {-end_date ""} {-percent_complete "0"} {-estimated_hours_work "0"} @@ -361,13 +541,39 @@ set status_id [pm::task::default_status_open] } + if {$estimated_hours_work_min > $estimated_hours_work_max} { + set temp $estimated_hours_work_max + set estimated_hours_work_max $estimated_hours_work_min + set estimated_hours_work_min $temp + } + set return_val [db_exec_plsql new_task_item { *SQL }] return $return_val } +ad_proc -public pm::task::delete { + -task_item_id:required +} { + Deletes a given task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-10 + + @param task_item_id + + @return 1, no matter once + + @error No error thrown if there is no such task. +} { + db_exec_plsql delete_task "select pm_task__delete_task_item(:task_item_id)" + + return 1 +} + + ad_proc -public pm::task::get_url { object_id } { @@ -496,3 +702,1527 @@ return $total_logged_hours } +<<<<<<< task-procs.tcl + + +ad_proc -public pm::task::link { + -task_item_id_1:required + -task_item_id_2:required +} { + Links two tasks together + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-10 + + @param task_item_id_1 + + @param task_item_id_2 + + @return + + @error +} { + + if {[string equal $task_item_id_1 $task_item_id_2]} { + # do nothing + ns_log Notice "Project-manager: Cannot link a task to itself!" + } elseif {$task_item_id_1 < $task_item_id_2} { + db_dml link_tasks " + INSERT INTO + pm_task_xref + (task_id_1, task_id_2) + VALUES + (:task_item_id_1, :task_item_id_2)" + } else { + db_dml link_tasks " + INSERT INTO + pm_task_xref + (task_id_1, task_id_2) + VALUES + (:task_item_id_2, :task_item_id_1)" + } + +} + + +ad_proc -public pm::task::assign_remove_everyone { + -task_item_id:required +} { + Removes all assignments for a task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-09 + + @param task_item_id + + @return + + @error +} { + db_dml remove_assignment " + delete from pm_task_assignment where task_id = :task_item_id" +} + + +ad_proc -public pm::task::assign { + -task_item_id:required + -party_id:required + {-role_id ""} +} { + Assigns party_id to task_item_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-05 + + @param task_item_id + + @param party_id + + @param role_id the role under which the person is assigned + + @return + + @error +} { + if {![exists_and_not_null role_id]} { + set role_id [pm::role::default] + } + + db_dml add_assignment " + insert into pm_task_assignment + (task_id, + role_id, + party_id) + values + (:task_item_id, + :role_id, + :party_id) + " +} + + +ad_proc -public pm::task::open { + -task_item_id:required +} { + Opens a task, and sends notifications, unless it was already + open. If it was already open, does nothing. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-22 + + @param task_item_id + + @return + + @error +} { + # find out what the status of the task was, and while we're at it, + # get other interesting information about the task, in case we + # want to close it. Then we can put this info in the email. + + db_1row get_status " + SELECT + t.status, + s.status_type, + s.description as status_description, + r.title as task_title, + r.estimated_hours_work, + r.estimated_hours_work_min, + r.estimated_hours_work_max, + to_char(r.earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, + to_char(r.earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, + to_char(r.latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, + to_char(r.latest_finish, 'YYYY-MM-DD HH24:MI:SS') as latest_finish_ansi, + r.description as task_description, + project_revision.title as project_name + FROM + pm_tasks t, + cr_items task_item, + pm_task_status s, + pm_tasks_revisionsx r, + cr_items project_item, + cr_revisions project_revision + WHERE + r.parent_id = project_item.item_id and + t.task_id = task_item.item_id and + task_item.live_revision = r.revision_id and + project_item.live_revision = project_revision.revision_id and + r.item_id = t.task_id and + t.status = s.status_id and + t.task_id = :task_item_id" + + if {[string equal $status_type "o"]} { + + # this is already open + return + + } + + # set the new status + + set status_code [pm::task::default_status_open] + + db_dml update_status " + UPDATE + pm_tasks + SET + status = :status_code + WHERE + task_id = :task_item_id" + + # send out an email notification + + set earliest_start [lc_time_fmt $earliest_start_ansi "%x"] + set earliest_finish [lc_time_fmt $earliest_finish_ansi "%x"] + set latest_start [lc_time_fmt $latest_start_ansi "%x"] + set latest_finish [lc_time_fmt $latest_finish_ansi "%x"] + + set assignees [db_list get_assignees " + select + email + FROM + pm_task_assignment a, + parties p + WHERE + task_id = :task_item_id and + a.party_id = p.party_id + "] + + if {[llength $assignees] > 0} { + + set to_address [join $assignees ", "] + + set user_id [ad_conn user_id] + + set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] + + set task_url "[parameter::get_from_package_key -package_key acs-kernel -parameter SystemURL][ad_conn package_url]task-one?task_id=$task_item_id" + + set subject "Task reopened (was $status_description): $task_title" + + if {[parameter::get_from_package_key -package_key project-manager -parameter UseUncertainCompletionTimesP]} { + set estimated_work "\nHrs work (min): $estimated_hours_work_min\nHrs work (max): $estimated_hours_work_max" + } else { + set estimated_work "\nHrs work: $estimated_hours_work" + + } + + set notification_text "Task reopened, was $status_description\n\n" + + append notification_text " +------------- +Task ID: \#$task_item_id +Description: $task_title +Project: $project_name + +Link: $task_url + +--------------- +Estimated work: +---------------$estimated_work + +------ +Dates: +------ +Earliest start: $earliest_start +Earliest finish: $earliest_finish +Latest start: $latest_start +Latest finish $latest_finish + +----------- +Description +----------- +$task_description" + + + append notification_text "\n" + + acs_mail_lite::send \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject \ + -body $notification_text + } + + return +} + +ad_proc -public pm::task::close { + -task_item_id:required +} { + Closes a task, and sends notifications, unless it was already + closed. If it was already closed, does nothing. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-22 + + @param task_item_id + + @return + + @error +} { + # find out what the status of the task was + + db_1row get_status " + SELECT + t.status, + s.status_type, + s.description as status_description, + r.title as task_title, + r.estimated_hours_work, + r.estimated_hours_work_min, + r.estimated_hours_work_max, + to_char(r.earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, + to_char(r.earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, + to_char(r.latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, + to_char(r.latest_finish, 'YYYY-MM-DD HH24:MI:SS') as latest_finish_ansi, + r.description as task_description, + project_revision.title as project_name + FROM + pm_tasks t, + cr_items task_item, + pm_task_status s, + pm_tasks_revisionsx r, + cr_items project_item, + cr_revisions project_revision + WHERE + r.parent_id = project_item.item_id and + t.task_id = task_item.item_id and + task_item.live_revision = r.revision_id and + project_item.live_revision = project_revision.revision_id and + r.item_id = t.task_id and + t.status = s.status_id and + t.task_id = :task_item_id" + + if {[string equal $status_type "c"]} { + + # this is already closed + return + + } + + # set the new status + + set status_code [pm::task::default_status_closed] + + db_dml update_status " + UPDATE + pm_tasks + SET + status = :status_code + WHERE + task_id = :task_item_id" + + # send out an email notification + + set earliest_start [lc_time_fmt $earliest_start_ansi "%x"] + set earliest_finish [lc_time_fmt $earliest_finish_ansi "%x"] + set latest_start [lc_time_fmt $latest_start_ansi "%x"] + set latest_finish [lc_time_fmt $latest_finish_ansi "%x"] + + + set assignees [db_list get_assignees " + select + email + FROM + pm_task_assignment a, + parties p + WHERE + task_id = :task_item_id and + a.party_id = p.party_id + "] + + if {[llength $assignees] > 0} { + + set to_address [join $assignees ", "] + + set user_id [ad_conn user_id] + + set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] + + set last_time_stamp "" + set work_log "----------------------\nWork done on this task\n----------------------\n\n" + + db_foreach get_logged_time " + SELECT + to_char(le.time_stamp, 'fmDyfm fmMMfm-fmDDfm-YYYY') as time_stamp_pretty, + le.value, + le.description, + r.title as task_name, + submitter.first_names || ' ' || submitter.last_name as user_name + FROM + logger_entries le, + cr_items i, + cr_revisions r, + pm_task_logger_proj_map m, + logger_projects lp, + acs_objects ao, + acs_users_all submitter + WHERE + r.item_id = m.task_item_id and + i.live_revision = r.revision_id and + r.item_id = :task_item_id and + le.project_id = lp.project_id and + ao.object_id = le.entry_id and + le.entry_id = m.logger_entry and + ao.creation_user = submitter.user_id + ORDER BY + le.time_stamp desc" { + if {![string equal $time_stamp_pretty $last_time_stamp]} { + append work_log "* $time_stamp_pretty\n\n" + } + append work_log "[pm::util::string_truncate_and_pad -length 25 -string "$user_name:"] $description ($value hrs)\n" + + set last_time_stamp $time_stamp_pretty + } + + set task_url "[parameter::get_from_package_key -package_key acs-kernel -parameter SystemURL][ad_conn package_url]task-one?task_id=$task_item_id" + + set subject "Task closed (was $status_description) $task_title" + + if {[parameter::get_from_package_key -package_key project-manager -parameter UseUncertainCompletionTimesP]} { + set estimated_work "\nHrs work (min): $estimated_hours_work_min\nHrs work (max): $estimated_hours_work_max" + } else { + set estimated_work "\nHrs work: $estimated_hours_work" + + } + + set notification_text "Task closed, was $status_description\n\n" + + append notification_text " +------------- +Task ID: \#$task_item_id +Description: $task_title +Project: $project_name + +Link: $task_url +" + append notification_text "\n\n$work_log" + + append notification_text " +--------------- +Estimated work: +---------------$estimated_work + +------ +Dates: +------ +Earliest start: $earliest_start +Earliest finish: $earliest_finish +Latest start: $latest_start +Latest finish $latest_finish + +----------- +Description +----------- +$task_description" + + + acs_mail_lite::send \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject \ + -body $notification_text + } + + return +} + + + +ad_proc -public pm::task::email_status {} { + + set send_email_p [parameter::get_from_package_key -package_key "project-manager" -parameter SendDailyEmail -default "0"] + + if {[string equal $send_email_p "0"]} { + ns_log Notice "Parameter SendDailyEmail for project manager says skip email today" + return + } + + acs_mail_lite::send \ + -to_addr jader@bread.com \ + -from_addr jader@bread.com \ + -subject "Reminder: pm::task::email_status is starting..." \ + -body "It is starting" + + set parties [list] + + # what if the person assigned is no longer a part of the subsite? + # right now, we still email them. + + db_foreach get_all_open_tasks " + SELECT + ts.task_id, + ts.task_id as item_id, + ts.task_number, + t.task_revision_id, + t.title, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(current_timestamp,'J') as today_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.percent_complete, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as actual_hours_worked, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + p.first_names || ' ' || p.last_name as full_name, + p.party_id, + (select one_line from pm_roles r where ta.role_id = r.role_id) as role + FROM + pm_tasks ts, + pm_tasks_revisionsx t, + pm_task_assignment ta, + acs_users_all p, + cr_items i, + pm_task_status s + WHERE + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision and + ts.status = s.status_id and + s.status_type = 'o' and + t.item_id = ta.task_id and + ta.party_id = p.party_id + ORDER BY + t.latest_start asc" { + set earliest_start_pretty [lc_time_fmt $earliest_start "%x"] + set earliest_finish_pretty [lc_time_fmt $earliest_finish "%x"] + set latest_start_pretty [lc_time_fmt $latest_start "%x"] + set latest_finish_pretty [lc_time_fmt $latest_finish "%x"] + + if {[exists_and_not_null earliest_start_j]} { + set slack_time [pm::task::slack_time \ + -earliest_start_j $earliest_start_j \ + -today_j $today_j \ + -latest_start_j $latest_start_j] + + } + + if {[lsearch $parties $party_id] == -1} { + lappend parties $party_id + } + + lappend task_list($party_id) $task_id + set titles_arr($task_id) $title + set ls_arr($task_id) $latest_start_pretty + set lf_arr($task_id) $latest_finish_pretty + set slack_arr($task_id) $slack_time + + # how many tasks does this person have? + if {[info exists task_count($party_id)]} { + incr task_count($party_id) + } else { + set task_count($party_id) 1 + } + } + + # transitions are < this value + set OVERDUE_THRESHOLD 0 + set PRESSING_THRESHOLD 7 + set LONGTERM_THRESHOLD 90 + + set TASK_LENGTH 70 + set TASK_ID_LENGTH 9 + + foreach party $parties { + + set subject "Daily Task status report" + set address [db_string get_email "select email from parties where party_id = :party" -default "jade-errors@bread.com"] + + set overdue [list] + set pressing [list] + set longterm [list] + + foreach task $task_list($party) { + + if {$slack_arr($task) < $OVERDUE_THRESHOLD} { + set which_pile overdue + } elseif {$slack_arr($task) < $PRESSING_THRESHOLD} { + set which_pile pressing + } elseif {$slack_arr($task) < $PRESSING_THRESHOLD} { + set which_pile longterm + } else { + set which_pile "" + } + + if {![empty_string_p $which_pile]} { + + set trimmed_task [pm::util::string_truncate_and_pad -length $TASK_ID_LENGTH -string $task] + set trimmed_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $titles_arr($task)] + + lappend $which_pile "$trimmed_task $trimmed_title" + lappend $which_pile "[string repeat " " $TASK_ID_LENGTH] LS: $ls_arr($task) LF: $lf_arr($task) Slack: $slack_arr($task)" + lappend $which_pile "" + } + + } + + set description [list] + + set overdue_title "OVERDUE TASKS" + set overdue_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $overdue_title] + + set overdue_description "consult with people affected, and let them know deadlines are affected" + + set pressing_title "PRESSING TASKS" + set pressing_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $pressing_title] + + set pressing_description "you need to start working on these soon to avoid affecting deadlines" + + set longterm_title "LONG TERM TASKS" + set longterm_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $longterm_title] + set longterm_description "look over these to plan ahead" + + # okay, let's now set up the email body + + lappend description "This is a daily reminder of tasks that are assigned to you" + lappend description "You current have $task_count($party) tasks assigned to you" + + lappend description "" + lappend description "\# $overdue_title" + + set length [string length $overdue_description] + lappend description [string repeat "_" $length] + + lappend description $overdue_description + + lappend description "" + foreach overdue_item $overdue { + lappend description $overdue_item + } + + lappend description "" + lappend description "\# $pressing_title" + + set length [string length $pressing_description] + lappend description [string repeat "_" $length] + + lappend description $pressing_description + + + lappend description "" + foreach pressing_item $pressing { + lappend description $pressing_item + } + + lappend description "" + lappend description "\# $longterm_title" + + set length [string length $longterm_description] + lappend description [string repeat "_" $length] + + lappend description $longterm_description + + lappend description "" + foreach longterm_item $longterm { + lappend description $longterm_item + } + + acs_mail_lite::send \ + -to_addr $address \ + -from_addr $address \ + -subject $subject \ + -body [join $description "\n"] + + } + + # consider also sending out emails to people who have assigned + # tickets to nobody + +} + + + +ad_proc -private pm::task::email_status_init { +} { + Schedules the daily emailings + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-14 + + @return + + @error +} { + ns_log Notice "Scheduling daily email notifications for project manager to 5:00 am" + ad_schedule_proc -thread t -debug t -schedule_proc ns_schedule_daily "5 0" pm::task::email_status +} +======= + + +ad_proc -public pm::task::link { + -task_item_id_1:required + -task_item_id_2:required +} { + Links two tasks together + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-10 + + @param task_item_id_1 + + @param task_item_id_2 + + @return + + @error +} { + + if {[string equal $task_item_id_1 $task_item_id_2]} { + # do nothing + ns_log Notice "Project-manager: Cannot link a task to itself!" + } elseif {$task_item_id_1 < $task_item_id_2} { + db_dml link_tasks " + INSERT INTO + pm_task_xref + (task_id_1, task_id_2) + VALUES + (:task_item_id_1, :task_item_id_2)" + } else { + db_dml link_tasks " + INSERT INTO + pm_task_xref + (task_id_1, task_id_2) + VALUES + (:task_item_id_2, :task_item_id_1)" + } + +} + + +ad_proc -public pm::task::assign_remove_everyone { + -task_item_id:required +} { + Removes all assignments for a task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-09 + + @param task_item_id + + @return + + @error +} { + db_dml remove_assignment " + delete from pm_task_assignment where task_id = :task_item_id" +} + + +ad_proc -public pm::task::assign { + -task_item_id:required + -party_id:required + {-role_id ""} +} { + Assigns party_id to task_item_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-05 + + @param task_item_id + + @param party_id + + @param role_id the role under which the person is assigned + + @return + + @error +} { + if {![exists_and_not_null role_id]} { + set role_id [pm::role::default] + } + + db_dml add_assignment " + insert into pm_task_assignment + (task_id, + role_id, + party_id) + values + (:task_item_id, + :role_id, + :party_id) + " +} + + +ad_proc -public pm::task::open { + -task_item_id:required +} { + Opens a task, and sends notifications, unless it was already + open. If it was already open, does nothing. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-22 + + @param task_item_id + + @return + + @error +} { + # find out what the status of the task was, and while we're at it, + # get other interesting information about the task, in case we + # want to close it. Then we can put this info in the email. + + db_1row get_status " + SELECT + t.status, + s.status_type, + s.description as status_description, + r.title as task_title, + r.estimated_hours_work, + r.estimated_hours_work_min, + r.estimated_hours_work_max, + to_char(r.earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, + to_char(r.earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, + to_char(r.latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, + to_char(r.latest_finish, 'YYYY-MM-DD HH24:MI:SS') as latest_finish_ansi, + r.description as task_description, + project_revision.title as project_name + FROM + pm_tasks t, + cr_items task_item, + pm_task_status s, + pm_tasks_revisionsx r, + cr_items project_item, + cr_revisions project_revision + WHERE + r.parent_id = project_item.item_id and + t.task_id = task_item.item_id and + task_item.live_revision = r.revision_id and + project_item.live_revision = project_revision.revision_id and + r.item_id = t.task_id and + t.status = s.status_id and + t.task_id = :task_item_id" + + if {[string equal $status_type "o"]} { + + # this is already open + return + + } + + # set the new status + + set status_code [pm::task::default_status_open] + + db_dml update_status " + UPDATE + pm_tasks + SET + status = :status_code + WHERE + task_id = :task_item_id" + + # send out an email notification + + set earliest_start [lc_time_fmt $earliest_start_ansi "%x"] + set earliest_finish [lc_time_fmt $earliest_finish_ansi "%x"] + set latest_start [lc_time_fmt $latest_start_ansi "%x"] + set latest_finish [lc_time_fmt $latest_finish_ansi "%x"] + + set assignees [db_list get_assignees " + select + email + FROM + pm_task_assignment a, + parties p + WHERE + task_id = :task_item_id and + a.party_id = p.party_id + "] + + if {[llength $assignees] > 0} { + + set to_address [join $assignees ", "] + + set user_id [ad_conn user_id] + + set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] + + set task_url "[parameter::get_from_package_key -package_key acs-kernel -parameter SystemURL][ad_conn package_url]task-one?task_id=$task_item_id" + + set subject "Task reopened (was $status_description): $task_title" + + if {[parameter::get_from_package_key -package_key project-manager -parameter UseUncertainCompletionTimesP]} { + set estimated_work "\nHrs work (min): $estimated_hours_work_min\nHrs work (max): $estimated_hours_work_max" + } else { + set estimated_work "\nHrs work: $estimated_hours_work" + + } + + set notification_text "Task reopened, was $status_description\n\n" + + append notification_text " +------------- +Task ID: \#$task_item_id +Description: $task_title +Project: $project_name + +Link: $task_url + +--------------- +Estimated work: +---------------$estimated_work + +------ +Dates: +------ +Earliest start: $earliest_start +Earliest finish: $earliest_finish +Latest start: $latest_start +Latest finish $latest_finish + +----------- +Description +----------- +$task_description" + + + append notification_text "\n" + + acs_mail_lite::send \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject \ + -body $notification_text + } + + return +} + +ad_proc -public pm::task::close { + -task_item_id:required +} { + Closes a task, and sends notifications, unless it was already + closed. If it was already closed, does nothing. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-22 + + @param task_item_id + + @return + + @error +} { + # find out what the status of the task was + + db_1row get_status " + SELECT + t.status, + s.status_type, + s.description as status_description, + r.title as task_title, + r.estimated_hours_work, + r.estimated_hours_work_min, + r.estimated_hours_work_max, + to_char(r.earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, + to_char(r.earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, + to_char(r.latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, + to_char(r.latest_finish, 'YYYY-MM-DD HH24:MI:SS') as latest_finish_ansi, + r.description as task_description, + project_revision.title as project_name + FROM + pm_tasks t, + cr_items task_item, + pm_task_status s, + pm_tasks_revisionsx r, + cr_items project_item, + cr_revisions project_revision + WHERE + r.parent_id = project_item.item_id and + t.task_id = task_item.item_id and + task_item.live_revision = r.revision_id and + project_item.live_revision = project_revision.revision_id and + r.item_id = t.task_id and + t.status = s.status_id and + t.task_id = :task_item_id" + + if {[string equal $status_type "c"]} { + + # this is already closed + return + + } + + # set the new status + + set status_code [pm::task::default_status_closed] + + db_dml update_status " + UPDATE + pm_tasks + SET + status = :status_code + WHERE + task_id = :task_item_id" + + # send out an email notification + + set earliest_start [lc_time_fmt $earliest_start_ansi "%x"] + set earliest_finish [lc_time_fmt $earliest_finish_ansi "%x"] + set latest_start [lc_time_fmt $latest_start_ansi "%x"] + set latest_finish [lc_time_fmt $latest_finish_ansi "%x"] + + + set assignees [db_list get_assignees " + select + email + FROM + pm_task_assignment a, + parties p + WHERE + task_id = :task_item_id and + a.party_id = p.party_id + "] + + if {[llength $assignees] > 0} { + + set to_address [join $assignees ", "] + + set user_id [ad_conn user_id] + + set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] + + set last_time_stamp "" + set work_log "----------------------\nWork done on this task\n----------------------\n\n" + + db_foreach get_logged_time " + SELECT + to_char(le.time_stamp, 'fmDyfm fmMMfm-fmDDfm-YYYY') as time_stamp_pretty, + le.value, + le.description, + r.title as task_name, + submitter.first_names || ' ' || submitter.last_name as user_name + FROM + logger_entries le, + cr_items i, + cr_revisions r, + pm_task_logger_proj_map m, + logger_projects lp, + acs_objects ao, + acs_users_all submitter + WHERE + r.item_id = m.task_item_id and + i.live_revision = r.revision_id and + r.item_id = :task_item_id and + le.project_id = lp.project_id and + ao.object_id = le.entry_id and + le.entry_id = m.logger_entry and + ao.creation_user = submitter.user_id + ORDER BY + le.time_stamp desc" { + if {![string equal $time_stamp_pretty $last_time_stamp]} { + append work_log "* $time_stamp_pretty\n\n" + } + append work_log "[pm::util::string_truncate_and_pad -length 25 -string "$user_name:"] $description ($value hrs)\n" + + set last_time_stamp $time_stamp_pretty + } + + set task_url "[parameter::get_from_package_key -package_key acs-kernel -parameter SystemURL][ad_conn package_url]task-one?task_id=$task_item_id" + + set subject "Task closed (was $status_description) $task_title" + + if {[parameter::get_from_package_key -package_key project-manager -parameter UseUncertainCompletionTimesP]} { + set estimated_work "\nHrs work (min): $estimated_hours_work_min\nHrs work (max): $estimated_hours_work_max" + } else { + set estimated_work "\nHrs work: $estimated_hours_work" + + } + + set notification_text "Task closed, was $status_description\n\n" + + append notification_text " +------------- +Task ID: \#$task_item_id +Description: $task_title +Project: $project_name + +Link: $task_url +" + append notification_text "\n\n$work_log" + + append notification_text " +--------------- +Estimated work: +---------------$estimated_work + +------ +Dates: +------ +Earliest start: $earliest_start +Earliest finish: $earliest_finish +Latest start: $latest_start +Latest finish $latest_finish + +----------- +Description +----------- +$task_description" + + + acs_mail_lite::send \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject \ + -body $notification_text + } + + return +} + + + +ad_proc -public pm::task::email_status {} { + + set send_email_p [parameter::get_from_package_key -package_key "project-manager" -parameter SendDailyEmail -default "0"] + + if {[string equal $send_email_p "0"]} { + ns_log Notice "Parameter SendDailyEmail for project manager says skip email today" + return + } + + # also don't send reminders on weekends. + + set today_j [db_string get_today "select to_char(current_timestamp,'J')"] + if {![pm::project::is_workday_p $today_j]} { + return + } + + set parties [list] + + # what if the person assigned is no longer a part of the subsite? + # right now, we still email them. + + db_foreach get_all_open_tasks " + SELECT + ts.task_id, + ts.task_id as item_id, + ts.task_number, + t.task_revision_id, + t.title, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(current_timestamp,'J') as today_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.percent_complete, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as actual_hours_worked, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + p.first_names || ' ' || p.last_name as full_name, + p.party_id, + (select one_line from pm_roles r where ta.role_id = r.role_id) as role + FROM + pm_tasks ts, + pm_tasks_revisionsx t, + pm_task_assignment ta, + acs_users_all p, + cr_items i, + pm_task_status s + WHERE + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision and + ts.status = s.status_id and + s.status_type = 'o' and + t.item_id = ta.task_id and + ta.party_id = p.party_id + ORDER BY + t.latest_start asc" { + set earliest_start_pretty [lc_time_fmt $earliest_start "%x"] + set earliest_finish_pretty [lc_time_fmt $earliest_finish "%x"] + set latest_start_pretty [lc_time_fmt $latest_start "%x"] + set latest_finish_pretty [lc_time_fmt $latest_finish "%x"] + + if {[exists_and_not_null earliest_start_j]} { + set slack_time [pm::task::slack_time \ + -earliest_start_j $earliest_start_j \ + -today_j $today_j \ + -latest_start_j $latest_start_j] + + } + + if {[lsearch $parties $party_id] == -1} { + lappend parties $party_id + } + + lappend task_list($party_id) $task_id + set titles_arr($task_id) $title + set ls_arr($task_id) $latest_start_pretty + set lf_arr($task_id) $latest_finish_pretty + set slack_arr($task_id) $slack_time + + # how many tasks does this person have? + if {[info exists task_count($party_id)]} { + incr task_count($party_id) + } else { + set task_count($party_id) 1 + } + } + + # transitions are < this value + set OVERDUE_THRESHOLD 0 + set PRESSING_THRESHOLD 7 + set LONGTERM_THRESHOLD 90 + + set TASK_LENGTH 70 + set TASK_ID_LENGTH 9 + + foreach party $parties { + + set subject "Daily Task status report" + set address [db_string get_email "select email from parties where party_id = :party" -default "jade-errors@bread.com"] + + set overdue [list] + set pressing [list] + set longterm [list] + + foreach task $task_list($party) { + + if {$slack_arr($task) < $OVERDUE_THRESHOLD} { + set which_pile overdue + } elseif {$slack_arr($task) < $PRESSING_THRESHOLD} { + set which_pile pressing + } elseif {$slack_arr($task) < $PRESSING_THRESHOLD} { + set which_pile longterm + } else { + set which_pile "" + } + + if {![empty_string_p $which_pile]} { + + set trimmed_task [pm::util::string_truncate_and_pad -length $TASK_ID_LENGTH -string $task] + set trimmed_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $titles_arr($task)] + + lappend $which_pile "$trimmed_task $trimmed_title" + lappend $which_pile "[string repeat " " $TASK_ID_LENGTH] LS: $ls_arr($task) LF: $lf_arr($task) Slack: $slack_arr($task)" + lappend $which_pile "" + } + + } + + set description [list] + + set overdue_title "OVERDUE TASKS" + set overdue_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $overdue_title] + + set overdue_description "consult with people affected, and let them know deadlines are affected" + + set pressing_title "PRESSING TASKS" + set pressing_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $pressing_title] + + set pressing_description "you need to start working on these soon to avoid affecting deadlines" + + set longterm_title "LONG TERM TASKS" + set longterm_title [pm::util::string_truncate_and_pad -length $TASK_LENGTH -string $longterm_title] + set longterm_description "look over these to plan ahead" + + # okay, let's now set up the email body + + lappend description "This is a daily reminder of tasks that are assigned to you" + lappend description "You current have $task_count($party) tasks assigned to you" + + lappend description "" + lappend description "\# $overdue_title" + + set length [string length $overdue_description] + lappend description [string repeat "_" $length] + + lappend description $overdue_description + + lappend description "" + foreach overdue_item $overdue { + lappend description $overdue_item + } + + lappend description "" + lappend description "\# $pressing_title" + + set length [string length $pressing_description] + lappend description [string repeat "_" $length] + + lappend description $pressing_description + + + lappend description "" + foreach pressing_item $pressing { + lappend description $pressing_item + } + + lappend description "" + lappend description "\# $longterm_title" + + set length [string length $longterm_description] + lappend description [string repeat "_" $length] + + lappend description $longterm_description + + lappend description "" + foreach longterm_item $longterm { + lappend description $longterm_item + } + + acs_mail_lite::send \ + -to_addr $address \ + -from_addr $address \ + -subject $subject \ + -body [join $description "\n"] + + } + + # consider also sending out emails to people who have assigned + # tickets to nobody + +} + + + +ad_proc -private pm::task::email_status_init { +} { + Schedules the daily emailings + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-14 + + @return + + @error +} { + ns_log Notice "Scheduling daily email notifications for project manager to 5:00 am" + ad_schedule_proc -thread t -debug t -schedule_proc ns_schedule_daily "5 0" pm::task::email_status +} + + + +ad_proc -public pm::task::email_alert { + -task_item_id:required + {-user_id ""} + {-assignee_id ""} + {-assignee_role_name ""} + {-edit_p "t"} + {-comment ""} + {-description ""} + {-old_description ""} + {-subject ""} + {-work ""} + {-work_min ""} + {-work_max ""} + {-project_name ""} + {-earliest_start ""} + {-earliest_finish ""} + {-latest_start ""} + {-latest_finish ""} + {-url ""} +} { + Sends out an email notification when changes have been made to a task + +

+ + If any of the following are missing, fills in from the database: + subject, work, work_min, work_max, project_name, earliest_start, + earliest_finish, latest_start, latest_finish + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-03 + + @param task_item_id + + @param user_id The user making the change + + @param assignee_id The party_id of the user assigned to the task. + + @param assignee_role_name The role name for what the party is + assigned to do + + @param edit_p Is this an edited task, or a new one? t for edited, + f otherwise. + + @param description + + @param old_description + + @param subject The one line description of the task + + @param work Estimated hours work + + @param work_min Estimated minimimum hours work + + @param work_max Estimated maximum hours work + + @param project_name + + @param earliest_start + + @param earliest_finish + + @param latest_start + + @param latest_finish + + @param url Optionally, a URL that the user is directed to + + @return + + @error +} { + + set task_term [parameter::get -parameter "Taskname" -default "Task"] + set task_term_lower [parameter::get -parameter "taskname" -default "task"] + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "0"] + + # from address + + if {![exists_and_not_null $user_id]} { + set user_id [ad_conn user_id] + } + + db_1row get_from_address_and_more { + SELECT + p.email as from_address, + p2.first_names || ' ' || p2.last_name as mod_username + FROM + parties p, + persons p2 + WHERE + p.party_id = :user_id and + p.party_id = p2.person_id + } + + # to address + + if {![exists_and_not_null assignee_id]} { + + # bug: we should get the list of assignees here. + ns_log Error "the proc pm::task::email_alert is not complete: assignee" + + } + + set to_address [db_string get_email "select email from parties where party_id = :assignee_id"] + + + # if they left out any of the task info, then we get it from the database + if { \ + ![exists_and_not_null subject] || \ + ![exists_and_not_null work] || \ + ![exists_and_not_null work_min] || \ + ![exists_and_not_null work_max] || \ + ![exists_and_not_null project_name] || \ + ![exists_and_not_null earliest_start] || \ + ![exists_and_not_null earliest_finish] || \ + ![exists_and_not_null latest_start] || \ + ![exists_and_not_null latest_finish] \ + } { + + db_1row get_task_info { + SELECT + t.title as subject, + to_char(t.earliest_start,'MM-DD-YYYY') as earliest_start, + to_char(t.earliest_finish,'MM-DD-YYYY') as earliest_finish, + to_char(t.latest_start,'MM-DD-YYYY') as latest_start, + to_char(t.latest_finish,'MM-DD-YYYY') as latest_finish, + t.estimated_hours_work as work, + t.estimated_hours_work_min as work_min, + t.estimated_hours_work_max as work_max, + t.percent_complete, + p.title as project_name + FROM + pm_tasks_revisionsx t, + cr_items i, + cr_items project, + pm_projectsx p + WHERE + t.item_id = :task_item_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id and + t.parent_id = project.item_id and + project.item_id = p.item_id and + project.live_revision = p.revision_id + } + + } + + + if {[string equal $edit_p "t"]} { + set subject_out "Edited $task_term \#$task_item_id: $subject" + set intro_text "$mod_username edited this $task_term_lower" + } else { + set subject_out "New $task_term \#$task_item_id: $subject" + set intro_text "$mod_username assigned you to a new $task_term_lower" + } + + if {[empty_string_p $comment]} { + set comment_text "" + } else { + set comment_text "--------\nCOMMENT:\n--------\n$comment\n\n" + } + + if {[exists_and_not_null url]} { + set task_url $url + } else { + set task_url "unavailable" + } + + + + if {![string equal $description $old_description] && [string equal $edit_p t]} { + set description_out "$description \n\n-------\nOld description:\n-------\n\n[ad_html_to_text $old_description]" + + append intro_text "\nSee below to see the changes in the description" + + } else { + set description_out [ad_html_to_text $description] + } + + if {[string equal $use_uncertain_completion_times_p 1]} { + set estimated_work "\nHrs work (min): $work_min" + append estimated_work "\nHrs work (max): $work_max" + } else { + set estimated_work "\nHrs work: $work" + } + + set notification_text "$intro_text\n\n$comment_text-------------" + append notification_text "\nTask overview\n-------------" + append notification_text "\nTask ID: \#$task_item_id" + append notification_text "\nSubject: $subject" + append notification_text "\nProject: $project_name" + append notification_text "\nYour role: $assignee_role_name" + append notification_text "\nLink: $task_url" + append notification_text "\n\n\n\n---------------" + append notification_text "\nEstimated work:\n---------------$estimated_work" + append notification_text "\n\n------\nDates:" + append notification_text "\n------\nEarliest start: $earliest_start" + append notification_text "\nEarliest finish: $earliest_finish" + append notification_text "\nLatest start: $latest_start" + append notification_text "\nLatest finish *$latest_finish" + append notification_text "\n\n-----------\nDescription\n-----------" + append notification_text "\n$description_out" + + acs_mail_lite::send \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject_out \ + -body $notification_text + + +} + + +>>>>>>> 1.8 Index: openacs-4/contrib/packages/project-manager/www/add-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/add-edit-2.tcl,v diff -u -r1.4 -r1.4.2.1 --- openacs-4/contrib/packages/project-manager/www/add-edit-2.tcl 12 Mar 2004 13:44:44 -0000 1.4 +++ openacs-4/contrib/packages/project-manager/www/add-edit-2.tcl 20 May 2004 17:30:05 -0000 1.4.2.1 @@ -38,8 +38,12 @@ # --------------------------------------------------------------- # # the unique identifier for this package set package_id [ad_conn package_id] +set subsite_id [ad_conn subsite_id] set user_id [ad_maybe_redirect_for_registration] +set user_group_id [application_group::group_id_from_package_id \ + -package_id $subsite_id] + # terminology set project_term [parameter::get -parameter "ProjectName" -default "Project"] set project_term_lower [parameter::get -parameter "projectname" -default "project"] Index: openacs-4/contrib/packages/project-manager/www/add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/add-edit.tcl,v diff -u -r1.16 -r1.16.2.1 --- openacs-4/contrib/packages/project-manager/www/add-edit.tcl 12 Mar 2004 13:44:44 -0000 1.16 +++ openacs-4/contrib/packages/project-manager/www/add-edit.tcl 20 May 2004 17:30:05 -0000 1.16.2.1 @@ -134,15 +134,15 @@ if {[exists_and_not_null project_id]} { if {![empty_string_p [category_tree::get_mapped_trees $package_id]]} { ad_form -extend -name add_edit -form { - {category_ids:integer(category),multiple,optional {label "Categories"} + {category_ids:integer(category),multiple {label "Categories"} {html {size 4}} {value {$project_item_id $package_id}} } } } } else { if {![empty_string_p [category_tree::get_mapped_trees $package_id]]} { ad_form -extend -name add_edit -form { - {category_ids:integer(category),multiple,optional {label "Categories"} + {category_ids:integer(category),multiple {label "Categories"} {html {size 4}} {value {}} } } @@ -256,7 +256,6 @@ set project_item_id [pm::project::get_project_item_id \ -project_id $project_id] - pm::project::compute_parent_status $project_item_id if {[exists_and_not_null category_ids]} { @@ -266,9 +265,11 @@ if {$use_project_customizations_p} { ad_returnredirect "add-edit-2?[export_url_vars project_id old_project_id]" + pm::project::compute_parent_status $project_item_id ad_script_abort } else { ad_returnredirect "one?[export_url_vars project_id]" + pm::project::compute_parent_status $project_item_id ad_script_abort } } Index: openacs-4/contrib/packages/project-manager/www/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/index.tcl,v diff -u -r1.13 -r1.13.2.1 --- openacs-4/contrib/packages/project-manager/www/index.tcl 12 Mar 2004 13:44:44 -0000 1.13 +++ openacs-4/contrib/packages/project-manager/www/index.tcl 20 May 2004 17:30:05 -0000 1.13.2.1 @@ -142,7 +142,7 @@ customer_name { label "Customer" display_template " -@projects.customer_name@@projects.customer_name@ +@projects.customer_name@@projects.customer_name@ " } project_name { @@ -183,7 +183,7 @@ } } \ -orderby { - default_value project_name,asc + default_value latest_finish_date,asc project_name { label "Project name" orderby_desc "upper(p.title) desc" Index: openacs-4/contrib/packages/project-manager/www/log.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/log.tcl,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/contrib/packages/project-manager/www/log.tcl 12 Mar 2004 13:44:44 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/www/log.tcl 20 May 2004 17:30:05 -0000 1.2.2.1 @@ -14,13 +14,25 @@ {edit:boolean "f"} {return_url "."} } -validate { - project_id_required_in_add_mode { + #project_id_required_in_add_mode { # For the sake of simplicity of the form # we are requiring a project_id to be provided in add mode - if { ![exists_and_not_null entry_id] && ![exists_and_not_null project_id] } { - ad_complain "When adding a log entry a project_id must be provided (either entry_id or project_id must be present)." - } + #if { ![exists_and_not_null entry_id] && ![exists_and_not_null project_id] } { + # ad_complain "When adding a log entry a project_id must be provided (either entry_id or project_id must be present)." + #} + #} +} + +if { ![exists_and_not_null project_id] } { + + if {[exists_and_not_null entry_id]} { + # do nothing + } else { + set project_id [pm::project::get_logger_project \ + -project_item_id $pm_project_id] + } + } set package_id [ad_conn package_id] @@ -106,13 +118,6 @@ } -if { [exists_and_not_null pm_task_id] } { - set context [list [list "[ad_conn package_url]task-one?task_id=$pm_task_id" "One Task"] $page_title] -} else { - set context [list [list "[ad_conn package_url]one?project_item_id=$pm_project_id" "One Project"] $page_title] -} - - # Build the log entry form elements set actions [list] if { $edit_p } { @@ -189,12 +194,17 @@ else percent_complete end as percent_complete, estimated_hours_work, estimated_hours_work_min, - estimated_hours_work_max + estimated_hours_work_max, + s.description as status_description FROM pm_tasks_revisionsx p, - cr_items i + cr_items i, + pm_task_status s, + pm_tasks t WHERE i.item_id = p.item_id and p.item_id = :pm_task_id and + i.item_id = t.task_id and + t.status = s.status_id and p.revision_id = i.live_revision" ad_form -extend -name log_entry_form -form { @@ -205,6 +215,11 @@ {value $task_title} } + {status_description:text(inform) + {label "Status"} + {value $status_description} + } + } if {[string equal $use_uncertain_completion_times_p 1]} { @@ -249,6 +264,15 @@ } + +if { [exists_and_not_null pm_task_id] } { + set context [list [list "[ad_conn package_url]task-one?task_id=$pm_task_id" "$task_title"] $page_title] +} else { + + set context [list [list "[ad_conn package_url]one?project_item_id=$pm_project_id" "$project_array(name)"] $page_title] +} + + ########### # # Execute the form @@ -297,6 +321,17 @@ cr_items where item_id = :pm_task_id)" + + if {$percent_complete >= 100} { + + pm::task::close -task_item_id $pm_task_id + + } else { + + pm::task::open -task_item_id $pm_task_id + + } + } } else { @@ -308,7 +343,7 @@


-You have already added this entry once. If you want to edit this entry, click here. +You have already added this entry once. If you want to edit this entry, click here. [ad_footer] " @@ -329,7 +364,7 @@ set pm_task_id [db_string task_entry_p "select task_item_id from pm_task_logger_proj_map where logger_entry = :entry_id" -default "-1"] - if {![string equal $pm_task_id -1]} { + if {![string equal $pm_task_id -1] && [exists_and_not_null percent_complete]} { db_dml update_percent " UPDATE @@ -346,13 +381,34 @@ pm::task::update_hours \ -task_item_id $pm_task_id - pm::project::compute_status $pm_project_id + + if {$percent_complete >= 100} { + set status_code [pm::task::default_status_closed] + } else { + set status_code [pm::task::default_status_open] + } + + db_dml update_percent " + UPDATE + pm_tasks + SET + status = :status_code + WHERE + task_id = :pm_task_id" + + } set pm_task_id $old_pm_task_id } -after_submit { ad_returnredirect "[ad_conn url]?[export_vars { project_id variable_id return_url pm_project_id pm_task_id}]" + # ad_returnredirect $return_url + + if {![string equal $pm_task_id -1]} { + pm::project::compute_status $pm_project_id + } + ad_script_abort } Index: openacs-4/contrib/packages/project-manager/www/one-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/one-postgresql.xql,v diff -u -r1.23 -r1.23.2.1 --- openacs-4/contrib/packages/project-manager/www/one-postgresql.xql 12 Mar 2004 13:44:45 -0000 1.23 +++ openacs-4/contrib/packages/project-manager/www/one-postgresql.xql 20 May 2004 17:30:05 -0000 1.23.2.1 @@ -10,6 +10,7 @@ p.project_code, p.goal, p.description, + p.mime_type, to_char(p.planned_start_date,'YYYY-MM-DD HH24:MI') as planned_start_date, to_char(p.planned_end_date,'YYYY-MM-DD HH24:MI') as planned_end_date, p.logger_project, @@ -84,10 +85,26 @@ t.estimated_hours_work_max, t.actual_hours_worked FROM - (select * from pm_tasks_revisionsx LEFT JOIN pm_task_assignment ON item_id = task_id) t LEFT JOIN persons u ON t.party_id = u.person_id, cr_items i LEFT JOIN pm_task_dependency d ON i.item_id = d.task_id + (select * from pm_tasks_revisionsx + LEFT JOIN + pm_task_assignment ON item_id = task_id) t + LEFT JOIN + persons u + ON + t.party_id = u.person_id, + cr_items i + LEFT JOIN + pm_task_dependency d + ON + i.item_id = d.task_id, + pm_tasks ti, + pm_task_status s WHERE t.parent_id = :project_item_id and - t.revision_id = i.live_revision + t.revision_id = i.live_revision and + t.item_id = ti.task_id and + ti.status = s.status_id and + s.status_type = :status_type [template::list::orderby_clause -name tasks -orderby] Index: openacs-4/contrib/packages/project-manager/www/one.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/one.adp,v diff -u -r1.31 -r1.31.2.1 --- openacs-4/contrib/packages/project-manager/www/one.adp 12 Mar 2004 13:44:45 -0000 1.31 +++ openacs-4/contrib/packages/project-manager/www/one.adp 20 May 2004 17:30:05 -0000 1.31.2.1 @@ -1,265 +1,276 @@ - - - @project_term@ #@project_item_id@: @project.project_name;noquote@ - @context@ + @my_title;noquote@ + @context;noquote@

(not current, select live version below)

-
- -
- - - - - - +
- - Edit - - -   @project_term@ - -
+ + - + + + + +
-
- - +
+ + - - - +   @project_term@ - - - - - - + + + + + + - -
+ + Edit + -
Name@project.project_name@
Code@project.project_code@
- + + - - - - - - - - - - -
Goal@project.goal@
Description@project.description@
-
- -

- - - - - - - - - -
Dates
- - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - -
Start@project.planned_start_date@
Earliest finish@project.earliest_finish_date@Name@project.project_name@
Code@project.project_code@
Ongoing
Deadline@project.planned_end_date@
Goal@project.goal@
Ongoing
Latest finish@project.latest_finish_date@Ongoing
Task hours completed@project.actual_hours_completed@ of @project.estimated_hours_total@
-
- -

- - + +

Description@project.description;noquote@
+ + + +

+ - + - +
Project informationDates
- - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Customer@custom.customer_name@Start@project.planned_start_date@
Earliest finish@project.earliest_finish_date@Ongoing
Latest finish@project.latest_finish_date@Ongoing
Task hours completed@project.actual_hours_completed@ of @project.estimated_hours_total@
- - -

- - - - - - - - -
Categories
- - - - -
- -
    - - -
  • @categories:item@ - - -
- -
-
- -

- - - - - +

-

- + + +
Subprojects
Add subproject + +

+ + + + - - - - -
Project information
+

+ + + + + +
Customer@custom.customer_name@
+
+ + +

+ + + + + + + + + +
Categories
+ + + + +
+ +
    + + +
  • @categories:item@ + + +
+ +
+
+ +

+ + + + + + + + + +
Subprojects
Add subproject + + + +
-

- - - - - - - - - +

+

@task_term@
+ + + + + + + +
Comments
+ @comments;noquote@ +

+ @comments_link;noquote@ +

+ + - +   - - - -
    -
  • -
    - Add - - - - Tasks - -
    -
  • -
- - + + + + TASKS + - + + + + + + + + + + + + +
@task_term@
+ +
+
    +
  • +
    + Add + + + + + Tasks + +
    +
  • +
+ + + + +
+ +

+ + + + + + + + + + + + + + +
Logged hours
+ + Log hours + + + @log_note@ +
+ +
+ + + -

- - - - - - - - - - - - - - -
Logged hours
- - Log hours - - - @log_note@ -
- -
-

-
- +

REVISIONS

-

-

Comments

- @comments;noquote@ -

- @comments_link;noquote@

Index: openacs-4/contrib/packages/project-manager/www/one.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/one.tcl,v diff -u -r1.30 -r1.30.2.1 --- openacs-4/contrib/packages/project-manager/www/one.tcl 12 Mar 2004 13:44:45 -0000 1.30 +++ openacs-4/contrib/packages/project-manager/www/one.tcl 20 May 2004 17:30:05 -0000 1.30.2.1 @@ -28,9 +28,11 @@ {orderby_subproject ""} {orderby_tasks ""} {orderby_versions ""} + {status_type "o"} } -properties { categories:onelist + my_title:onevalue context:onevalue project:multirow tasks:multirow @@ -64,10 +66,24 @@ -project_item_id $project_item_id] } } + status_type_exists { + if {![string equal $status_type "o"] && ![string equal $status_type "c"]} { + set status_type "o" + } + } } set original_project_id $project_id +<<<<<<< one.tcl +# for edits of tasks. We want to come back to here. +set return_url "[ad_conn url]?[ad_conn query]" + +======= +# for edits of tasks. We want to come back to here. +set return_url [ad_return_url -qualified] + +>>>>>>> 1.35 # --------------------------------------------------------------- # # the unique identifier for this package @@ -79,7 +95,7 @@ # ---------------- set comments [general_comments_get_comments -print_content_p 1 -print_attachments_p 1 $project_item_id "[ad_conn url]?project_item_id=$project_item_id"] -set comments_link [general_comments_create_link -object_name cr_items -link_text "Add a comment" -context_id $package_id $project_item_id "[ad_conn url]?project_item_id=$project_item_id"] +set comments_link [general_comments_create_link -object_name "Project" -link_text "Add a comment" -context_id $package_id $project_item_id "[ad_conn url]?project_item_id=$project_item_id"] # terminology @@ -107,6 +123,11 @@ } db_1row project_query { } -column_array project + +set richtext_list [list $project(description) $project(mime_type)] + +set project(description) [template::util::richtext::get_property html_value $richtext_list] + set project_root [db_exec_plsql get_root_folder { }] set project(planned_start_date) [lc_time_fmt $project(planned_start_date) "%x"] @@ -124,15 +145,16 @@ set log_note "Last 30 days" +set my_title "$project_term \#$project_item_id: $project(project_name)" + set edit_url "[ad_conn package_url]add-edit?[export_url_vars project_item_id]" # set up context bar, needs parent_id - if {[string equal $project(parent_id) $project_root]} { - set context [list "View"] + set context [list "$project(project_name)"] } else { - set context [list [list "one?project_item_id=$project(parent_id)" "Parent"] "View"] + set context [list [list "one?project_item_id=$project(parent_id)" "Parent"] "$project(project_name)"] } # Tasks, using list-builder --------------------------------- @@ -168,15 +190,15 @@ } slack_time { label "Slack" - display_template "@tasks.slack_time@" + display_template "@tasks.slack_time@" } earliest_start { label "Earliest Start" - display_template "@tasks.earliest_start_pretty@@tasks.earliest_start_pretty@" + display_template "@tasks.earliest_start_pretty@@tasks.earliest_start_pretty@" } earliest_finish { label "Earliest Finish" - display_template "@tasks.earliest_finish_pretty@@tasks.earliest_finish_pretty@" + display_template "@tasks.earliest_finish_pretty@@tasks.earliest_finish_pretty@" } latest_start { label "Latest Start" @@ -202,23 +224,73 @@ project_item_id project_id {my_key 1} + {return_url} } \ -sub_class { narrow } \ -filters { - project_item_id {} - orderby_subproject {} - orderby_versions {} - orderby_people {} + status_type { + label "Status" + values {{"Open" "o"} {"Closed" "c"}} + where_clause {s.status_type = :status_type} + } + project_item_id { + hide_p 1 + } + orderby_subproject { + hide_p 1 + } + orderby_versions { + hide_p 1 + } + orderby_people { + hide_p 1 + } } \ -orderby { - title {orderby title} +<<<<<<< one.tcl + default_value latest_start,asc + title { + label "Subject" + orderby_asc "title asc" + orderby_desc "title desc" + default_direction asc + } earliest_start {orderby earliest_start} earliest_finish {orderby earliest_finish} latest_start {orderby latest_start} latest_finish {orderby latest_finish} +======= default_value latest_start,asc + title { + label "Subject" + orderby_asc "title asc" + orderby_desc "title desc" + default_direction asc + } + earliest_start { + label "Earliest start" + orderby_asc "earliest_start, u.first_names, u.last_name" + orderby_desc "earliest_start desc, u.first_names, u.last_name" + default_direction asc + } + earliest_finish { + orderby_asc "earliest_finish, u.first_names, u.last_name" + orderby_desc "earliest_finish desc, u.first_names, u.last_name" + default_direction asc + } + latest_start { + orderby_asc "latest_start, u.first_names, u.last_name" + orderby_desc "latest_start desc, u.first_names, u.last_name" + default_direction asc + } + latest_finish { + orderby_asc "latest_finish, u.first_names, u.last_name" + orderby_desc "latest_finish desc, u.first_names, u.last_name" + default_direction asc + } +>>>>>>> 1.35 } \ -orderby_name orderby_tasks \ -html { @@ -385,10 +457,10 @@ db_1row custom_query { } -column_array custom +set customer_link "[site_node::get_package_url -package_key organizations]one?organization_id=$custom(customer_id)" # end of customizations - # ----------------------------------------------------------------- # Logger forms and so on - shows time logged, and allows you to log # other time Index: openacs-4/contrib/packages/project-manager/www/process-dependency-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/process-dependency-add-edit.tcl,v diff -u -r1.6 -r1.6.2.1 --- openacs-4/contrib/packages/project-manager/www/process-dependency-add-edit.tcl 12 Mar 2004 13:44:45 -0000 1.6 +++ openacs-4/contrib/packages/project-manager/www/process-dependency-add-edit.tcl 20 May 2004 17:30:05 -0000 1.6.2.1 @@ -1,13 +1,3 @@ -ns_log notice it's my page! -set mypage [ns_getform] -if {[string equal "" $mypage]} { - ns_log notice no form was submitted on my page -} else { - ns_log notice the following form was submitted on my page - ns_set print $mypage -} - - ad_page_contract { Form to add task dependencies @@ -156,10 +146,10 @@ # get dependency types -set options [list] -db_foreach get_dependency_types { } -column_array dependencies { - lappend options "{\"$dependencies(description)\" $dependencies(short_name)}" -} +#set options [list] +#db_foreach get_dependency_types { } -column_array dependencies { +# lappend options "{\"$dependencies(description)\" $dependencies(short_name)}" +#} # set up list of tasks that this task can be depend on @@ -206,9 +196,7 @@ {value {$tasks(description)}} } - {dependency_type.$tasks(task_id):text(select) - {label \"Dependency type\"} - {options {[join $options " "]}} + {dependency_type.$tasks(task_id):text(hidden) {value {finish_before_start}} } Index: openacs-4/contrib/packages/project-manager/www/process-task-add-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/process-task-add-edit-2.tcl,v diff -u -r1.6 -r1.6.2.1 --- openacs-4/contrib/packages/project-manager/www/process-task-add-edit-2.tcl 12 Mar 2004 13:44:45 -0000 1.6 +++ openacs-4/contrib/packages/project-manager/www/process-task-add-edit-2.tcl 20 May 2004 17:30:05 -0000 1.6.2.1 @@ -26,6 +26,11 @@ {use_dependency:integer,multiple ""} } -validate { + no_estimated_hours { + if {![exists_and_not_null estimated_hours_work] && ![exists_and_not_null estimated_hours_work_min] && ![exists_and_not_null estimated_hours_work_max]} { + ad_complain + } + } process_id_missing { if {![exists_and_not_null process_id]} { ad_complain @@ -60,6 +65,8 @@ } } } -errors { + no_estimated_hours {You must enter estimated hours. If nothing + else, enter 0 for the estimated hours} process_id_missing {I don't know which process these tasks are for!} task_title_too_long {A task subject is too long. It must be 198 characters or less} description_too_long {A description subject is too long. It must be 3998 characters or less} Index: openacs-4/contrib/packages/project-manager/www/process-task-assign-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/process-task-assign-add-edit.tcl,v diff -u -r1.8 -r1.8.2.1 --- openacs-4/contrib/packages/project-manager/www/process-task-assign-add-edit.tcl 12 Mar 2004 13:44:45 -0000 1.8 +++ openacs-4/contrib/packages/project-manager/www/process-task-assign-add-edit.tcl 20 May 2004 17:30:05 -0000 1.8.2.1 @@ -58,9 +58,13 @@ # the unique identifier for this package set package_id [ad_conn package_id] +set subsite_id [ad_conn subsite_id] set user_id [ad_maybe_redirect_for_registration] +set user_group_id [application_group::group_id_from_package_id \ + -package_id $subsite_id] + # permissions and more set title "Add a process $task_term_lower (assignment)" Index: openacs-4/contrib/packages/project-manager/www/process-task-delete-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/process-task-delete-2.tcl,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/contrib/packages/project-manager/www/process-task-delete-2.tcl 26 Jan 2004 15:39:40 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/www/process-task-delete-2.tcl 20 May 2004 17:30:05 -0000 1.2.2.1 @@ -17,7 +17,7 @@ set user_id [ad_maybe_redirect_for_registration] # permissions -permission::require_permission -party_id $user_id -object_id $package_id -privilege delete +permission::require_permission -party_id $user_id -object_id $package_id -privilege write db_dml delete_process_tasks { } Index: openacs-4/contrib/packages/project-manager/www/process-task-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/process-task-delete.tcl,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/contrib/packages/project-manager/www/process-task-delete.tcl 26 Jan 2004 15:39:40 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/www/process-task-delete.tcl 20 May 2004 17:30:05 -0000 1.2.2.1 @@ -36,6 +36,6 @@ set context_bar [ad_context_bar "Delete process $task_term_lower"] # permissions -permission::require_permission -party_id $user_id -object_id $package_id -privilege delete +permission::require_permission -party_id $user_id -object_id $package_id -privilege write set hidden_vars [export_vars -form {process_task_id:multiple,sign process_id}] Index: openacs-4/contrib/packages/project-manager/www/task-add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-add-edit-postgresql.xql,v diff -u -r1.15 -r1.15.2.1 --- openacs-4/contrib/packages/project-manager/www/task-add-edit-postgresql.xql 12 Mar 2004 13:44:45 -0000 1.15 +++ openacs-4/contrib/packages/project-manager/www/task-add-edit-postgresql.xql 20 May 2004 17:30:05 -0000 1.15.2.1 @@ -20,27 +20,6 @@ - - - select pm_task__new_task_revision ( - :p_task_item_id, - :project_item_id, - :p_task_title, - :p_description, - [pm::util::datenvl -value [set end_date_$i] -value_if_null "null," -value_if_not_null "to_timestamp('[set end_date_$i]','YYYY MM DD HH24 MI SS'),"] - :p_percent, - :p_work, - :p_work_min, - :p_work_max, - :p_hours, - current_timestamp, - :user_id, - :peeraddr, - :package_id - ); - - - select @@ -51,9 +30,11 @@ select + t.parent_id as my_project_item_id, t.task_revision_id, t.title as my_task_title, t.description as my_description, + t.mime_type as my_mime_type, to_char(t.end_date,'YYYY MM DD') as my_end_date, t.percent_complete as my_percent_complete, t.estimated_hours_work as my_estimated_work, @@ -67,6 +48,8 @@ WHERE t.item_id in ([join $task_id ","]) and t.revision_id = i.live_revision + ORDER BY + t.item_id @@ -94,22 +77,6 @@ - - - select - r.item_id, - r.title as task_title - FROM - pm_tasks_revisionsx r, - cr_items i - WHERE - r.parent_id = :project_item_id and - r.revision_id = i.live_revision - ORDER BY - upper(r.title) - - - select Index: openacs-4/contrib/packages/project-manager/www/task-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-add-edit.adp,v diff -u -r1.12.2.1 -r1.12.2.2 --- openacs-4/contrib/packages/project-manager/www/task-add-edit.adp 12 Mar 2004 22:28:12 -0000 1.12.2.1 +++ openacs-4/contrib/packages/project-manager/www/task-add-edit.adp 20 May 2004 17:30:05 -0000 1.12.2.2 @@ -1,24 +1,31 @@ @title;noquote@ @context@ - - + +
- + - + - + - + - + + + Comment:
+
+ + +
+ Error +
+
+ + + + + +
 #@num.rownum@   + +  #@num.rownum@   + + + #@num.task_id@ + + @@ -30,6 +37,17 @@
Error + + +

+ + + Subject:*
+ + +
+ Error +

Subject:*
@@ -41,7 +59,7 @@

- Description:
+ Description:

@@ -50,13 +68,23 @@

-

- @@ -105,18 +133,19 @@ - + - @@ -128,6 +157,18 @@ % + + + + + @@ -149,30 +190,35 @@ -
Work required: + Work required: *

-

- [i] - You must enter a number here (make your best - guess) -

-
+ +

+ [i] + You must enter a number here (make your best + guess) +

+

Log entry

+

Log entry:

+ +

+ [i] + Enter 100% to close the @task_term_lower@, or less + to open it. +

+
Time:
- + +
+ +

+ [i] + You can optionally log time worked here. +

+
+ + Error - + - - - - - - - + - -
- Deadline: - + Deadline:
+ Error @@ -186,17 +232,9 @@
- - - - - - - + + +
- Dependency: +

Dependency:
@@ -215,9 +253,21 @@ You may enter a @task_term_lower@ that needs to be completed before this @task_term_lower@

+
+

Project:
+ + +
+ Error +
+
+

@@ -231,8 +281,11 @@ - - - - + + + + + +
+ Index: openacs-4/contrib/packages/project-manager/www/task-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-add-edit.tcl,v diff -u -r1.27.2.1 -r1.27.2.2 --- openacs-4/contrib/packages/project-manager/www/task-add-edit.tcl 23 Mar 2004 07:53:15 -0000 1.27.2.1 +++ openacs-4/contrib/packages/project-manager/www/task-add-edit.tcl 20 May 2004 17:30:05 -0000 1.27.2.2 @@ -2,6 +2,13 @@ Add/edit form for tasks +

+ + I plan to eventually get rid of the task-select-project page, because + the ability to choose the project is now within this page. However, + I'm waiting to do that until after my company updates our projects + with the customer in each field. + @author jader@bread.com @creation-date 2003-07-28 @cvs-id $Id$ @@ -12,31 +19,54 @@ @return edit_p if t then we are editing. Used to show different portions of the form @param process_task_ids Specifies what process task ids were used if a process were used. We pass this on to future pages to determine things such as assignments - @param project_item_id Specifies which project this task is associated with - @param project_id Specifies which project revision this task is associated with + @param project_item_id Specifies which project each task is associated with. If this is a new task, this specifies the project that it will be assigned under. + @param my_key if set, then ad_form knows that this is an edit + @param process_task_ids + @param project_item_id This is optionally passed in to this page to + indictate the project that the tasks should be associated with. + @param project_item_ids Used internally to keep track of the projects + associated with each task @param number The number of Tasks to create - @param added_tasks @param task_revision_id Specifies the revision this task represents (each revision of a task has a separate id) @param task_id Specifies the item for the task (every revision of a task shares the same task_id) Also used as the key for the ad_form. For this reason, when editing, we have to pass in task_iid instead - @param my_key if set, then ad_form knows that this is an edit @param task_title - @param skip_task_p Whether or not to skip this particular task. Used by processes, if t, then the task is not created @param process_id The process we're using to create this task - @param use_uncertain_completion_times_p Whether or not to use PERT-style completion time uncertainty 1 = yes - @return using_process_p Lets the UI know if there is a process being used (t if so) + @param description + @param old_description + @param comment + @param name + @param end_date + @param percent_complete + @param actual_hours_worked + @param new_hours_logged + @param new_description_logged + @param estimated_hours_work + @param estimated_hours_work_min + @param estimated_hours_work_max + @param dependency_type + @param dependency_task_id + @param skip_task_p Whether or not to skip this particular task. Used by processes, if t, then the task is not created + @param using_process_p Lets the UI know if there is a process being used (t if so) + } { my_key:integer,optional process_task_ids:array,optional - project_item_id:integer,optional - project_id:integer,optional + {project_item_id:integer ""} + project_item_ids:array,optional {number:integer "1"} task_revision_id:integer,optional {task_id:multiple ""} task_item_id:array,optional task_title:array,optional {process_id:integer ""} - description:array,optional +<<<<<<< task-add-edit.tcl + description:html,array,optional +======= + description:html,array,optional + {old_description ""} + comment:html,array,optional +>>>>>>> 1.33 name:array,optional end_date:array,optional percent_complete:array,optional @@ -50,6 +80,7 @@ dependency_task_id:array,optional skip_task_p:array,optional {using_process_p "f"} + {return_url ""} } -properties { @@ -61,12 +92,6 @@ using_process_p:onevalue } -validate { - project_exists { - if {![exists_and_not_null project_item_id] && \ - ![exists_and_not_null project_id]} { - ad_complain - } - } number_is_in_range -requires {number:integer} { # todo: make 100 a parameter if {$number < 1 || $number > 100} { @@ -90,6 +115,7 @@ set package_id [ad_conn package_id] + # --------------------------------------------------------------- # # terminology # --------------------------------------------------------------- # @@ -100,11 +126,20 @@ # --------------------------------------------------------------- # +<<<<<<< task-add-edit.tcl if {![exists_and_not_null project_id]} { set project_id [db_string get_project_id { }] } + +# ns_log Notice "return_url: $return_url" + + + + +======= +>>>>>>> 1.33 # -------------------------------------------------------------------- # If we are using a process, then we need to get the information on # the process now. This is necessary because we need to do things like @@ -128,12 +163,27 @@ set estimated_hours_work_max_v($process_tid) $estimated_hours_work_max set dependency_v($process_tid) $process_parent_task + # make sure that we don't have empty values for estimated + # hours work + if {[empty_string_p $estimated_hours_work_v($process_tid)]} { + set estimated_hours_work_v($process_tid) 0 + } + if {[empty_string_p $estimated_hours_work_min_v($process_tid)]} { + set estimated_hours_work_min_v($process_tid) 0 + } + if {[empty_string_p $estimated_hours_work_max_v($process_tid)]} { + set estimated_hours_work_max_v($process_tid) 0 + } + + lappend process_tasks $process_tid } set number [llength $process_tasks] } + + # --------------------------------------------------------------- # @@ -142,6 +192,10 @@ set task_id_pass [string map {"-" " "} $task_id] set task_id $task_id_pass +# we sort this because we want to keep the ordering +# consistent. Otherwise, we can run into problems when editing +# multiple tasks. Their values can get crossed. +set task_id [lsort -integer $task_id] # --------------------------------------------------------------- # # Create a multirow: num @@ -154,12 +208,12 @@ # create a multirow we can use to iterate # we also set the number variable for future use # ----------------------------------------------------- - template::multirow create num number + template::multirow create num number task_id set i 1 set number 0 foreach tid $task_id { - template::multirow append num $i + template::multirow append num $i [lindex $task_id [expr $i-1]] incr i incr number } @@ -168,10 +222,10 @@ } else { # create a multirow we can use to iterate - template::multirow create num number + template::multirow create num number task_id for {set i 1} {$i <= $number} {incr i} { - template::multirow append num $i + template::multirow append num $i [lindex $task_id [expr $i-1]] } set edit_p f @@ -205,19 +259,201 @@ set keyname [array nextelement end_date $searchToken] set keyvalu $end_date($keyname) + # ns_log Notice "keyname: $keyname keyvalu: $keyvalu" + # element_num is 1...n, element_type is year, format, day, month regexp {(.*)\.(.*)} $keyname match element_num element_type + # ns_log Notice "element_num: $element_num element_type: $element_type" + set end_date_[set element_type]($element_num) $keyvalu + # ns_log notice "set end_date_[set element_type] to $keyvalu" } for {set i 1} {$i <= $number} {incr i} { # set up date variable names set end_date_$i [list $end_date_year($i) $end_date_month($i) $end_date_day($i) {} {} {}] +<<<<<<< task-add-edit.tcl + # ns_log Notice "end_date_$i: [set end_date_$i]" } } +# ------------------------------------------------------- # +# The second evilest hack of all time. +# ------------------------------------------------------- +# This is a workaround the fact that using multiple richtext items +# with ad_form is extremely difficult. The description field +# will come in like an array, with values like +# description.1 = 1234 bold +# description.1.format = text/enhanced +# description.1.spellcheck = :nospell: +# The problem is we want +# to have multiple descriptions. +# +# What this loop does is go through the array, and rename the +# values into other variables. We then feed these variables into +# the SQL function that creates the new tasks. This works. I'm +# sure there must be a better way to do it. +# ------------------------------------------------------- # + +if {[info exists description] && ![exists_and_not_null process_id]} { + + set searchToken [array startsearch description] + + while {[array anymore description $searchToken]} { + + # these next two lines are important + set element_num "" + set element_type "" + + set keyname [array nextelement description $searchToken] + set keyvalu $description($keyname) + + # ns_log Notice "keyname: $keyname keyvalu: $keyvalu" + + # element_num is 1...n, element_type is format, spellcheck + regexp {(.*)\.(.*)} $keyname match element_num element_type + + # ns_log Notice "element_num: $element_num element_type: $element_type" + + set description_[set element_type]($element_num) $keyvalu + + # ns_log notice "set description_[set element_type] to $keyvalu" + +======= + # ns_log Notice "end_date_$i: [set end_date_$i]" + } +} + +# ------------------------------------------------------- # +# The second evilest hack of all time. +# ------------------------------------------------------- +# This is a workaround the fact that using multiple richtext items +# with ad_form is extremely difficult. The description field +# will come in like an array, with values like +# description.1 = 1234 bold +# description.1.format = text/enhanced +# description.1.spellcheck = :nospell: +# The problem is we want +# to have multiple descriptions. +# +# What this loop does is go through the array, and rename the +# values into other variables. We then feed these variables into +# the SQL function that creates the new tasks. This works. I'm +# sure there must be a better way to do it. +# ------------------------------------------------------- # + +if {[info exists description] && ![exists_and_not_null process_id]} { + + set searchToken [array startsearch description] + + while {[array anymore description $searchToken]} { + + # these next two lines are important + set element_num "" + set element_type "" + + set keyname [array nextelement description $searchToken] + set keyvalu $description($keyname) + + # ns_log Notice "keyname: $keyname keyvalu: $keyvalu" + + # element_num is 1...n, element_type is format, spellcheck + regexp {(.*)\.(.*)} $keyname match element_num element_type + + # ns_log Notice "element_num: $element_num element_type: $element_type" + + set description_[set element_type]($element_num) $keyvalu + + # ns_log notice "set description_[set element_type] to $keyvalu" + + } + +} + +# ------------------------------------------------------- # +# The third evilest hack of all time. +# ------------------------------------------------------- +# This is a workaround the fact that using multiple richtext items +# with ad_form is extremely difficult. The comment field +# will come in like an array (if the task is edited), +# with values like +# comment.1 = 1234 bold +# comment.1.format = text/enhanced +# comment.1.spellcheck = :nospell: +# The problem is we want +# to have multiple comments. +# +# What this loop does is go through the array, and rename the +# values into other variables. We then feed these variables into +# the SQL function that creates the new tasks. This works. I'm +# sure there must be a better way to do it. +# ------------------------------------------------------- # +if {[string equal $edit_p t] && [info exists comment]} { + + set searchToken [array startsearch comment] + + while {[array anymore comment $searchToken]} { + + # these next two lines are important + set element_num "" + set element_type "" + + set keyname [array nextelement comment $searchToken] + set keyvalu $comment($keyname) + + # ns_log Notice "keyname: $keyname keyvalu: $keyvalu" + + # element_num is 1...n, element_type is format, spellcheck + regexp {(.*)\.(.*)} $keyname match element_num element_type + + # if element_num is null, then this is actually the value for + # the comment + if {[empty_string_p $element_num]} { + set comment_[set keyname] $keyvalu + } + + # ns_log Notice "element_num: $element_num element_type: $element_type" + + set comment_[set element_type]($element_num) $keyvalu + + # ns_log notice "set comment_[set element_type] to $keyvalu" + +>>>>>>> 1.33 + } +<<<<<<< task-add-edit.tcl + +======= + +} else { + + for {set i 1} {$i <= $number} {incr i} { + # we explicitly set all the values to plaintext and empty for + # new tasks + set comment_format($i) "text/plain" + set comment_$i "" + } +} + +for {set i 1} {$i <= $number} {incr i} { + + set format $comment_format($i) + set richtext_list [list [set comment_$i] $format] + lappend comment_list [ad_html_to_text [template::util::richtext::get_property html_value $richtext_list]] +>>>>>>> 1.33 +} + +<<<<<<< task-add-edit.tcl + +======= + +# ns_log Notice "comment_list $comment_list" + + + + +>>>>>>> 1.33 # --------------------------------------------------------------- # # permissions and title setup, etc # we should update the permissions to not just use package_id, so @@ -229,7 +465,7 @@ if {[exists_and_not_null task_id]} { set title "Edit a $task_term_lower" - set context [list [list "one?item_id=$project_item_id&project_id=$project_id" "One $project_term"] "Edit $task_term"] + set context [list [list $return_url "Go back"] "Edit $task_term"] permission::require_permission \ -party_id $user_id \ -object_id $package_id \ @@ -238,7 +474,7 @@ } else { set title "Add a $task_term_lower" - set context [list [list "one?item_id=$project_item_id&project_id=$project_id" "One $project_term"] "New $task_term"] + set context [list [list "one?item_id=$project_item_id" "One $project_term"] "New $task_term"] permission::require_permission \ -party_id $user_id \ -object_id $package_id \ @@ -249,6 +485,8 @@ # we use this to pass through the task_ids set task_id_pass [string map {" " "-"} $task_id] +# set up options for editing projects +set project_options [pm::project::get_list_of_open] # --------------------------------------------------------------- # @@ -258,16 +496,25 @@ ad_form -name add_edit -form { my_key:key(acs_object_id_seq) - {project_item_id:text(hidden) - {value $project_item_id} - } - {task_id:text(hidden) {value $task_id_pass} } + {edit_p:text(hidden) + {value $edit_p} + } + +<<<<<<< task-add-edit.tcl + {return_url:text(hidden) + {value $return_url} + } + {project_id:text(hidden) {value $project_id} +======= + {return_url:text(hidden) + {value $return_url} +>>>>>>> 1.33 } {number:text(hidden) @@ -281,22 +528,60 @@ # we set the values for edited tasks # ---------------------------------- + +# we set the initial value to 0, because we need at least one value to +# pass to SQL. Otherwise, when we do the IN (123, 234, 455), there +# won't be any values inside, and it will fail. +set my_dependencies [list 0] + + if {![ad_form_new_p -key task_id]} { + # this form is being edited, not new + + # note we are indexing values from 1... set i 1 + set old_description [list] db_foreach get_old_tasks { *SQL* } { set task_title_arr($i) $my_task_title set description_arr($i) $my_description +<<<<<<< task-add-edit.tcl + set mime_type_arr($i) $my_mime_type + set template_arr($i) [list $my_description $my_mime_type] +======= + lappend old_description $my_description + set mime_type_arr($i) $my_mime_type + set template_arr($i) [list $my_description $my_mime_type] +>>>>>>> 1.33 set estimated_hours_arr($i) $my_estimated_work set estimated_hours_min_arr($i) $my_estimated_work_min set estimated_hours_max_arr($i) $my_estimated_work_max - set end_date_arr($i) $my_end_date + + # We need the date to be in the right format in order to pass + # through the validate filter. + + # the end date comes in this format 2004 05 17 + # we need to get it in the {2004} {05} {17} {} {} {} format + regexp {(.*) (.*) (.*)} $my_end_date match year month day + if {[exists_and_not_null year]} { + set end_date_arr($i) "$year $month $day {} {} {}" + } else { + set end_date_arr($i) "{} {} {} {} {} {}" + } + set percent_complete_arr($i) $my_percent_complete set actual_hours_worked_arr($i) $my_actual_hours_worked + set project_item_id_arr($i) $my_project_item_id set task_item_id_arr($i) [lindex $task_id [expr $i - 1]] set dependency_arr($i) $my_dependency + # we keep track of this to make sure that depedencies that + # are from closed tasks are still shown on the list of + # possible dependencies to select from + if {[exists_and_not_null my_dependency]} { + lappend my_dependencies $my_dependency + } # we are not using a process set process_task_id_arr($i) "" @@ -307,6 +592,11 @@ # log hours as well. # ----------------------------------------------------- + # we also want to pass throught he old description so that + # we can do a word diff on the next page, so people can see + # what has changed + + ad_form -extend \ -name add_edit \ -form \ @@ -337,9 +627,34 @@ ] \ ] + # ------------------------------------------------------ + # we allow people to enter general comments when editing + # ------------------------------------------------------ + ad_form -extend \ + -name add_edit \ + -form \ + [list [list \ + comment.$i:richtext,optional,nospell \ + {label "Comment"} \ + {html {rows 7 cols 40}} \ + ] \ + ] + incr i } + + # we want to add in the old_description values as well + ad_form -extend \ + -name add_edit \ + -form \ + [list [list \ + comment.$i:text(hidden) \ + {value {$old_description}} \ + ] \ + ] + + } else { # ---------------------------------------------------------- @@ -352,13 +667,16 @@ for {set i 1} {$i <= $number} {incr i} { set task_title_arr($i) "" set description_arr($i) "" + set mime_type_arr($i) "text/plain" + set template_arr($i) [list "" "text/plain"] set estimated_hours_arr($i) "0" set estimated_hours_min_arr($i) "0" set estimated_hours_max_arr($i) "0" set parent_arr($i) "" set end_date_arr($i) "" set percent_complete_arr($i) 0 set actual_hours_worked_arr($i) 0 + set project_item_id_arr($i) $project_item_id set task_item_id_arr($i) "" set process_task_id_arr($i) "" set dependency_arr($i) "" @@ -369,6 +687,10 @@ set task_title_arr($i) $one_line_v($ptask_id) set description_arr($i) $description_v($ptask_id) + + set mime_type_arr($i) "text/plain" + set template_arr($i) [list "$description_v($ptask_id)" "text/plain"] + set estimated_hours_arr($i) $estimated_hours_work_v($ptask_id) set estimated_hours_min_arr($i) $estimated_hours_work_min_v($ptask_id) set estimated_hours_max_arr($i) $estimated_hours_work_max_v($ptask_id) @@ -396,6 +718,7 @@ {help_text {If you skip this task, it will not be created}} \ ] \ ] + } else { @@ -426,31 +749,45 @@ ] \ ] - } -} + # ----------------------------------------------------------- + # we only allow people to enter general comments when editing + # we also want to pass throught he old description so that + # we can do a word diff on the next page, so people can see + # what has changed + # ----------------------------------------------------------- + ad_form -extend \ + -name add_edit \ + -form \ + [list [list \ + comment.$i:text(hidden) \ + {value ""} \ + ] \ + ] -# get dependency types -set options [list] -db_foreach get_dependency_types { } -column_array dependencies { - lappend options "{\"$dependencies(description)\" $dependencies(short_name)}" -} + } -# get tasks this task can depend on + # we want to add in the old_description values as well + ad_form -extend \ + -name add_edit \ + -form \ + [list [list \ + comment.$i:text(hidden) \ + {value {}} \ + ] \ + ] -set dependency_keys [list] -db_foreach get_dependency_tasks { } -column_array dependency_tasks { - - set dependency_options($dependency_tasks(task_title)) $dependency_tasks(item_id) - lappend dependency_keys $dependency_tasks(task_title) } -set dependency_keys [lsort $dependency_keys] +# get dependency types +#set options [list] +#db_foreach get_dependency_types { } -column_array dependencies { +# lappend options "{\"$dependencies(description)\" $dependencies(short_name)}" +#} - # ---------------------------------------------- # extend the form with all the items that repeat # ---------------------------------------------- @@ -472,9 +809,6 @@ # any loops! # --------------------------------------------------- - set dependency_options_full "" - append dependency_options_full "{\"--None--\" \"\"} " - if {[string equal $edit_p f]} { # if we have a process, we need to bring in the dependencies @@ -516,33 +850,39 @@ } - # now set up dependency options - for {set j 1} {$j <= $number} {incr j} { - if {![string equal $i $j]} { - append dependency_options_full "{\"New Task \#$j\" \"num$j\"} " - } - } - } - # for editing tasks, we skip ourselves (because depending on - # ourselves just sometimes isn't an option) - if {[string equal $edit_p t]} { - foreach key $dependency_keys { +<<<<<<< task-add-edit.tcl # make sure we're not dependent on ourselves if {![string equal $task_item_id_arr($i) $dependency_options($key)]} { - append dependency_options_full "{\"$key\" $dependency_options($key)} " + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an error. + append dependency_options_full "{{$key} $dependency_options($key)} " } } } else { foreach key $dependency_keys { - append dependency_options_full "{\"$key\" $dependency_options($key)} " + + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an error. + append dependency_options_full "{{$key} $dependency_options($key)} " } } +======= + set dependency_options_full [pm::task::dependency_options \ + -edit_p $edit_p \ + -task_item_id $task_item_id_arr($i) \ + -project_item_id $project_item_id_arr($i) \ + -dependency_task_ids "$my_dependencies" \ + -number $number \ + -current_number $i] +>>>>>>> 1.33 + # ns_log Notice "end_date.$i : $end_date_arr($i)" + ad_form -extend \ -name add_edit \ -form \ @@ -553,6 +893,11 @@ {html {size 40}} \ {value {$task_title_arr($i)}} ] \ + [list project_item_ids.$i:text(select) \ + {label "Project"} \ + {options $project_options} \ + {value {$project_item_id_arr($i)}} \ + ] \ [list task_item_id.$i:text(hidden) \ {label "Task item id"} \ {value {$task_item_id_arr($i)}} \ @@ -562,10 +907,10 @@ {value {$process_task_id_arr($i)}} \ ] \ [list \ - description.$i:text(textarea),optional \ + description.$i:richtext,optional,nospell \ {label "Description"} \ {html {rows 7 cols 40}} \ - {value {$description_arr($i)}} \ + {value {$template_arr($i)}} \ ] \ [list \ end_date.$i:date,to_sql(linear_date),optional \ @@ -575,9 +920,8 @@ {help} \ ] \ [list \ - dependency_type.$i:text(select),optional \ + dependency_type.$i:text(hidden),optional \ {label \"Dependency type\"} \ - {options {[join $options " "]}} \ {value {finish_before_start}} \ ] \ [list \ @@ -587,21 +931,21 @@ {value {$dependency_arr($i)}} \ {help_text {$task_term the dependency is based on}} \ ] \ - ] + ] if {$use_uncertain_completion_times_p} { ad_form -extend \ -name add_edit \ -form \ [list \ [list \ - estimated_hours_work_min.$i:integer \ + estimated_hours_work_min.$i:text \ {label "Hours estimate - min"} \ {html {size 5}} \ {value {$estimated_hours_min_arr($i)}} \ ] \ [list \ - estimated_hours_work_max.$i:integer \ + estimated_hours_work_max.$i:text \ {label "Hours estimate - max"} \ {html {size 5}} \ {value {$estimated_hours_max_arr($i)}} \ @@ -612,7 +956,7 @@ -form \ [list \ [list \ - estimated_hours_work.$i:integer \ + estimated_hours_work.$i:text \ {label "Hours estimate"} \ {html {size 5}} \ {value {$estimated_hours_arr($i)}} \ @@ -623,6 +967,7 @@ + ad_form -extend -name add_edit -select_query_name task_query -on_submit { set user_id [ad_conn user_id] @@ -652,12 +997,21 @@ if {![exists_and_not_null end_date_$i]} { - set end_date_$i [db_null] + set end_date_$i "{} {} {} {} {} {}" } # set up variables, pulling from arrays + set p_project_item_id $project_item_ids($i) + set p_task_title $task_title($i) + set p_description $description($i) + + # ns_log Notice "Format: $description_format($i)" + + + set p_mime_type $description_format($i) + set p_work $estimated_hours_work($i) set p_work_min $estimated_hours_work_min($i) set p_work_max $estimated_hours_work_max($i) @@ -666,21 +1020,23 @@ set p_parent_task_id $dependency_task_id($i) set p_skip_p $skip_task_p($i) - ns_log Notice "end date: $p_end_date" +<<<<<<< task-add-edit.tcl + # ns_log Notice "end date: $p_end_date" +======= + # we don't do anything for the comments field, because they + # are not added in for new tasks. - # Make sure we do not insert bogus stuff into the database. + # ns_log Notice "end date: $p_end_date" +>>>>>>> 1.33 - if {$p_end_date == "{} {} {} {} {} {}"} { - set p_end_date [db_null] - } - # add in the new task if {[string equal $p_skip_p "f"]} { set this_revision_id [pm::task::new \ - -project_id $project_item_id \ + -project_id $p_project_item_id \ -title $p_task_title \ -description $p_description \ + -mime_type $p_mime_type \ -end_date $p_end_date \ -percent_complete "0" \ -estimated_hours_work $p_work \ @@ -692,8 +1048,6 @@ set this_task_id [db_string get_task_item_id {}] - - set dependent_task_id($i) $this_task_id if {[exists_and_not_null p_parent_task_id]} { @@ -718,7 +1072,7 @@ -task_item_id $this_task_id \ -parent_id $p_parent_task_id \ -dependency_type $p_dep_type \ - -project_item_id $project_item_id + -project_item_id $p_project_item_id } } @@ -744,21 +1098,22 @@ -task_item_id $this_task_id \ -parent_id $parent_task_id \ -dependency_type $p_dep_type \ - -project_item_id $project_item_id + -project_item_id $p_project_item_id } } } - pm::project::compute_parent_status $project_item_id - } -edit_data { set timestamp_ansi [db_string get_today " SELECT to_char(current_date, 'YYYY-MM-DD')"] + # insert the comment into the database + set is_live [ad_parameter AutoApproveCommentsP {general-comments} {t}] + # -------------------------------------------------------------- # each task we edit returns a task_revision_id # -------------------------------------------------------------- @@ -782,9 +1137,21 @@ } # set up variables, pulling from arrays + set p_project_item_id $project_item_ids($i) + set p_task_item_id $task_item_id($i) set p_task_title $task_title($i) set p_description $description($i) +<<<<<<< task-add-edit.tcl + set p_mime_type $description_format($i) + +======= + set p_mime_type $description_format($i) + + set p_comment $comment($i) + set p_comment_type $comment_format($i) + +>>>>>>> 1.33 set p_percent $percent_complete($i) set p_work $estimated_hours_work($i) set p_work_min $estimated_hours_work_min($i) @@ -798,7 +1165,7 @@ $p_new_hours > 0} { set logger_project [pm::project::get_logger_project \ - -project_item_id $project_item_id] + -project_item_id $p_project_item_id] set variable_id [logger::variable::get_default_variable_id] # add in the new log entry @@ -809,7 +1176,7 @@ -description $p_new_description \ -timestamp_ansi $timestamp_ansi \ -task_item_id $p_task_item_id \ - -project_item_id $project_item_id \ + -project_item_id $p_project_item_id \ -update_status_p f] if {[string equal p_hours -1]} { @@ -825,9 +1192,10 @@ # do the actual edit set this_revision_id [pm::task::edit \ -task_item_id $p_task_item_id \ - -project_item_id $project_item_id \ + -project_item_id $p_project_item_id \ -title $p_task_title \ -description $p_description \ + -mime_type $p_mime_type \ -end_date "[set end_date_[set i]]" \ -percent_complete $p_percent \ -estimated_hours_work $p_work \ @@ -850,16 +1218,113 @@ -task_item_id $p_task_item_id \ -parent_id $p_parent_task_id \ -dependency_type jfdsafesa\ - -project_item_id $project_item_id + -project_item_id $p_project_item_id } + # add in general comments for the task + + if {![empty_string_p $p_comment]} { + + set comment_id [db_nextval acs_object_id_seq] + + db_transaction { + db_exec_plsql insert_comment { + select acs_message__new ( + :comment_id, -- 1 p_message_id + NULL, -- 2 p_reply_to + current_timestamp, -- 3 p_sent_date + NULL, -- 4 p_sender + NULL, -- 5 p_rfc822_id + :p_task_title, -- 6 p_title + NULL, -- 7 p_description + :p_comment_type, -- 8 p_mime_type + NULL, -- 9 p_text + NULL, -- empty_blob(), -- 10 p_data + 0, -- 11 p_parent_id + :p_task_item_id, -- 12 p_context_id + :user_id, -- 13 p_creation_user + :peeraddr, -- 14 p_creation_ip + 'acs_message', -- 15 p_object_type + :is_live -- 16 p_is_live + ) + } + + db_dml add_entry { + insert into general_comments + (comment_id, + object_id, + category) + values + (:comment_id, + :p_task_item_id, + null) + } + + db_1row get_revision { + select content_item__get_latest_revision(:comment_id) as revision_id + } + + db_dml set_content { + update cr_revisions + set content = :p_comment + where revision_id = :revision_id + } + + db_exec_plsql grant_permission { + begin + perform acs_permission__grant_permission ( + /* object_id => */ :comment_id, + /* grantee_id => */ :user_id, + /* privilege => */ 'read' + ); + perform acs_permission__grant_permission ( + /* object_id => */ :comment_id, + /* grantee_id => */ :user_id, + /* privilege => */ 'write' + ); + return 0; + end; + } + } + } + } - pm::project::compute_parent_status $project_item_id +<<<<<<< task-add-edit.tcl +} -after_submit { + # ns_log Notice "tae: return_url: $return_url" + + ad_returnredirect "task-assign-add-edit?[export_vars -url {project_item_id return_url process_task_id:multiple revisions:multiple task_id:multiple}]" + pm::project::compute_parent_status $project_item_id +======= } -after_submit { - ad_returnredirect "task-assign-add-edit?[export_vars -url {project_item_id process_task_id:multiple revisions:multiple task_id:multiple}]" + ad_returnredirect "task-assign-add-edit?[export_vars -url {comment_list edit_p return_url process_task_id:multiple revisions:multiple task_id:multiple old_description}]" +>>>>>>> 1.33 + +<<<<<<< task-add-edit.tcl +======= + # compile a list of which projects the tasks are assigned to + # there is a bug here, because we don't update a project when a + # task is edited and changed to another project. + + set project_item_id_list [list] + for {set i 1} {$i <= $number} {incr i} { + + if {[string equal [lsearch $project_item_id_list $project_item_ids($i)] -1]} { + lappend project_item_id_list $project_item_ids($i) + } + + } + + foreach proj_item $project_item_id_list { + + pm::project::compute_parent_status $proj_item + + } + +>>>>>>> 1.33 ad_script_abort } Index: openacs-4/contrib/packages/project-manager/www/task-assign-add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-assign-add-edit-postgresql.xql,v diff -u -r1.5.2.1 -r1.5.2.2 --- openacs-4/contrib/packages/project-manager/www/task-assign-add-edit-postgresql.xql 12 Mar 2004 19:28:03 -0000 1.5.2.1 +++ openacs-4/contrib/packages/project-manager/www/task-assign-add-edit-postgresql.xql 20 May 2004 17:30:05 -0000 1.5.2.2 @@ -1,5 +1,6 @@ + select @@ -15,24 +16,39 @@ + select + title + FROM + pm_projects p, cr_revisions r, cr_items i + WHERE + r.item_id = :project_item_id and + i.item_id = r.item_id and + p.project_id = i.live_revision and + p.project_id = r.revision_id + select - title as one_line, - description, - item_id, - to_char(end_date, 'YYYY-MM-DD HH24:MI:SS') as end_date_ansi, - estimated_hours_work, - estimated_hours_work_min, - estimated_hours_work_max, - to_char(earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, - to_char(earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, - to_char(latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, - to_char(latest_finish, 'YYYY-MM-DD HH24:MI:SS') as latest_finish_ansi + t.title as one_line, + t.description, + t.item_id, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + to_char(t.earliest_start, 'YYYY-MM-DD HH24:MI:SS') as earliest_start_ansi, + to_char(t.earliest_finish, 'YYYY-MM-DD HH24:MI:SS') as earliest_finish_ansi, + to_char(t.latest_start, 'YYYY-MM-DD HH24:MI:SS') as latest_start_ansi, + to_char(t.latest_finish, 'YYYY-MM-DD HH24:MI:SS') as + latest_finish_ansi, + proj_rev.title as project_name FROM - pm_tasks_revisionsx t + pm_tasks_revisionsx t, + cr_items proj, + cr_revisions proj_rev WHERE - revision_id in ([join $revisions ","]) + t.revision_id in ([join $revisions ","]) and + t.parent_id = proj.item_id and + proj.live_revision = proj_rev.revision_id ORDER BY item_id @@ -122,19 +138,4 @@ process_task_id = :ptid - - - - select - title - FROM - pm_projects p, cr_revisions r, cr_items i - WHERE - r.item_id = :project_item_id and - i.item_id = r.item_id and - p.project_id = i.live_revision and - p.project_id = r.revision_id - - - Index: openacs-4/contrib/packages/project-manager/www/task-assign-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-assign-add-edit.adp,v diff -u -r1.5 -r1.5.2.1 --- openacs-4/contrib/packages/project-manager/www/task-assign-add-edit.adp 12 Mar 2004 13:44:45 -0000 1.5 +++ openacs-4/contrib/packages/project-manager/www/task-assign-add-edit.adp 20 May 2004 17:30:05 -0000 1.5.2.1 @@ -1,5 +1,5 @@ - - @context_bar;noquote@ + + @context@ @title@ @@ -40,7 +40,7 @@

- + Index: openacs-4/contrib/packages/project-manager/www/task-assign-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-assign-add-edit.tcl,v diff -u -r1.8.2.1 -r1.8.2.2 --- openacs-4/contrib/packages/project-manager/www/task-assign-add-edit.tcl 12 Mar 2004 19:28:03 -0000 1.8.2.1 +++ openacs-4/contrib/packages/project-manager/www/task-assign-add-edit.tcl 20 May 2004 17:30:05 -0000 1.8.2.2 @@ -6,7 +6,7 @@ @creation-date 2003-09-10 @cvs-id $Id$ - @return context_bar Context bar. + @return context Context bar. @return title Page title. @return num a multirow that contains the number of assignments @return tasks a multirow that contains the ticket info @@ -18,40 +18,118 @@ my_key:integer,optional {process_task_id:multiple,optional ""} - task_id:multiple,optional + {task_id:multiple,optional ""} revisions:multiple - {project_item_id:integer ""} role_id:array,optional party_id:array,optional +<<<<<<< task-assign-add-edit.tcl + {return_url ""} +======= + {return_url ""} + {edit_p "t"} + {comment_list ""} + {old_description:html ""} +>>>>>>> 1.15 } -properties { tasks:multirow num:multirow - context_bar:onevalue + context:onevalue title:onevalue task_term_lower:onevalue - project_item_id:onevalue } + # --------------------------------------------------------------- # +<<<<<<< task-assign-add-edit.tcl +if {[string equal [llength task_id] 1] && [exists_and_not_null return_url]} { + + # if the task is closed, then we don't need to reassign things + if {[string equal 0 [pm::task::open_p -task_item_id $task_id]]} { + ad_returnredirect $return_url + } +} + +======= +>>>>>>> 1.15 # hack to get around lack of multiple hidden support with ad_form +set old_description [string map {"-" " "} $old_description] +set comment_list [string map {"-" " "} $comment_list] set process_task_id [string map {"-" " "} $process_task_id] set revisions [string map {"-" " "} $revisions] set task_id [string map {"-" " "} $task_id] +<<<<<<< task-assign-add-edit.tcl + +# The number of assignments is set to 9, or the number of assignees + +# 2 if there are more than 5 assignees +set NUMBER_OF_ASSIGNMENTS 9 + +# find out the maximum number of assignees +db_foreach get_count "select count(task_id) as my_count from pm_task_assignment where task_id in ([join $task_id ", "]) group by task_id" { + if {$my_count > $NUMBER_OF_ASSIGNMENTS} { + set NUMBER_OF_ASSIGNMENTS [expr $my_count + 2] + } +} + +======= + +# We have passed in a list of comments and old_description. We will +# key them by task number + +set index 0 +foreach t_id $task_id { + set comment_value($t_id) [lindex $comment_list $index] + set old_description_value($t_id) [lindex $old_description $index] + incr index +} + + + + +if {[string equal [llength task_id] 1] && [exists_and_not_null return_url]} { + + set open_p 0 + foreach t_id $task_id { + + # if the task is closed, then we don't need to reassign things + if {[string equal 1 [pm::task::open_p -task_item_id $t_id]]} { + set open_p 1 + } + } + + if {[string equal $open_p 0]} { + ad_returnredirect $return_url + } + +} + + + +# The number of assignments is set to 9, or the number of assignees + +# 2 if there are more than 5 assignees +set NUMBER_OF_ASSIGNMENTS 9 + +# find out the maximum number of assignees +db_foreach get_count "select count(task_id) as my_count from pm_task_assignment where task_id in ([join $task_id ", "]) group by task_id" { + if {$my_count > $NUMBER_OF_ASSIGNMENTS} { + set NUMBER_OF_ASSIGNMENTS [expr $my_count + 2] + } +} + +>>>>>>> 1.15 db_multirow tasks get_task_info { } # create a multirow we can use to iterate template::multirow create num number -# currently hardcoded the number of assignments -for {set i 0} {$i <= 5} {incr i} { +for {set i 0} {$i <= $NUMBER_OF_ASSIGNMENTS} {incr i} { template::multirow append num $i } @@ -73,8 +151,19 @@ # permissions +<<<<<<< task-assign-add-edit.tcl set title "Add $task_term_lower assignments" -set context_bar [ad_context_bar [list "one?project_item_id=$project_item_id" "One $project_term"] "New $task_term dependency"] +set context [list [list "one?project_item_id=$project_item_id" "One $project_term"] "New $task_term dependency"] +======= +if {[string equal $edit_p "t"]} { + set title "Edit $task_term_lower assignments" + set context [list "Edit $task_term assignments"] +} else { + set title "Add $task_term_lower assignments" + set context [list "Add $task_term assignments"] +} + +>>>>>>> 1.15 permission::require_permission -party_id $user_id -object_id $package_id -privilege create @@ -87,6 +176,8 @@ set process_task_id_pass [string map {" " "-"} $process_task_id] set revisions_pass [string map {" " "-"} $revisions] +set comment_pass [string map {" " "-"} $comment_list] +set old_description_pass [string map {" " "-"} $old_description] set task_id_pass [string map {" " "-"} $task_id] ad_form -name add_edit -form { @@ -96,34 +187,42 @@ {process_task_id:text(hidden) {value $process_task_id_pass}} + {return_url:text(hidden) + {value $return_url} + } + {revisions:text(hidden) {value $revisions_pass}} {task_id:text(hidden) {value $task_id_pass}} - {project_item_id:text(hidden) - {value $project_item_id}} - - + {comment_list:text(hidden) + {value $comment_pass}} + + {old_description:text(hidden) + {value $old_description_pass}} + + {edit_p:text(hidden) + {value $edit_p}} + } -on_submit { set user_id [ad_conn user_id] set peeraddr [ad_conn peeraddr] } -new_data { - #role_id - #party_id - + # we have to decode these items back into lists set process_task_id [string map {"-" " "} $process_task_id] set revisions [string map {"-" " "} $revisions] set task_id [string map {"-" " "} $task_id] + # we get more information about the tasks, for notification purposes db_foreach get_more_task_info {} { + set project_names($item_id) $project_name set one_lines($item_id) $one_line set descriptions($item_id) $description - set end_dates_pretty($item_id) [lc_time_fmt $end_date_ansi "%x"] set est_hours_work($item_id) $estimated_hours_work set est_hours_work_min($item_id) $estimated_hours_work_min set est_hours_work_max($item_id) $estimated_hours_work_max @@ -188,15 +287,24 @@ db_dml delete_assignments { } - set project_name [db_string get_project_name { } -default "N/A"] - # set up role names foreach r [db_list_of_lists get_roles { }] { set des [lindex $r 0] set val [lindex $r 1] set role_oneline($val) $des } +<<<<<<< task-assign-add-edit.tcl + # ideally, we want to replace this with notifications, but I never + # got it working correctly, so I use acs_mail_lite + + set from_address [db_string get_email "select email from parties where party_id = :user_id"] + +======= + # ideally, we want to replace this with notifications, but I never + # got it working correctly, so I use acs_mail_lite + +>>>>>>> 1.15 foreach pl $party_list { regexp {(.*),(.*)} $pl match task_id_v num_value @@ -205,8 +313,13 @@ set r_id $assignment_role($pl) set p_id $assignment_party($pl) - set subject "New Task \#$t_id: $one_lines($t_id)" +<<<<<<< task-assign-add-edit.tcl + set to_address [db_string get_email "select email from parties where party_id = :p_id"] + set subject "Task \#$t_id: $one_lines($t_id)" + + set task_url "[parameter::get_from_package_key -package_key acs-kernel -parameter SystemURL][ad_conn package_url]task-one?task_id=$t_id" + if {[string equal $use_uncertain_completion_times_p 1]} { set estimated_work " Hrs work (min): $est_hours_work_min($t_id) @@ -223,6 +336,7 @@ Description: $one_lines($t_id) Project: $project_name Your role: $role_oneline($r_id) +Link: $task_url --------------- Estimated work: @@ -231,7 +345,6 @@ ------ Dates: ------ -Deadline: [ad_decode $end_dates_pretty($t_id) "" "None" $end_dates_pretty($t_id)] Earliest start: $earliest_starts($item_id) Earliest finish: $earliest_finishes($item_id) Latest start: $latest_starts($item_id) @@ -242,26 +355,79 @@ ----------- $descriptions($t_id)" - #notification::request::new \ - # -type_id "[notification::type::get_type_id -short_name pm_task_notif]" \ - # -object_id $t_id \ - # -user_id $p_id \ - # -interval_id [notification::interval::get_id_from_name -name instant] \ - # -delivery_method_id [notification::delivery::get_id -short_name email] - notification::new \ - -type_id [notification::type::get_type_id -short_name pm_task_notif] \ - -object_id $t_id \ - -response_id $t_id \ - -notif_subject $subject \ - -notif_text $notification_text + acs_mail_lite::send \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject \ + -body $notification_text + # we only want to do this for new people + # notification::request::new \ + # -type_id "[notification::type::get_type_id -short_name pm_task_notif]" \ + # -object_id $t_id \ + # -user_id $p_id \ + # -interval_id [notification::interval::get_id_from_name -name instant] \ + # -delivery_method_id [notification::delivery::get_id -short_name email] + + # send out notifications + # notification::new \ + # -type_id [notification::type::get_type_id -short_name pm_task_notif] \ + # -object_id $t_id \ + # -response_id $t_id \ + # -notif_subject $subject \ + # -notif_text $notification_text +======= + # If there is a comment for this task, then display it + # prominently in the email + set my_comment $comment_value($t_id) + set my_old_description $old_description_value($t_id) + + pm::task::email_alert \ + -task_item_id $t_id \ + -user_id $user_id \ + -assignee_id $p_id \ + -assignee_role_name $role_oneline($r_id) \ + -edit_p $edit_p \ + -comment $my_comment \ + -description $descriptions($t_id) \ + -old_description $my_old_description \ + -subject $one_lines($t_id) \ + -work_min $est_hours_work_min($t_id) \ + -work_max $est_hours_work_max($t_id) \ + -work $est_hours_work($t_id) \ + -project_name $project_names($t_id) \ + -earliest_start $earliest_starts($item_id) \ + -earliest_finish $earliest_finishes($item_id) \ + -latest_start $latest_starts($item_id) \ + -latest_finish $latest_finishes($item_id) \ + -url "[parameter::get_from_package_key -package_key acs-kernel -parameter SystemURL][ad_conn package_url]task-one?task_id=$t_id" + + # we only want to do this for new people + # notification::request::new \ + # -type_id "[notification::type::get_type_id -short_name pm_task_notif]" \ + # -object_id $t_id \ + # -user_id $p_id \ + # -interval_id [notification::interval::get_id_from_name -name instant] \ + # -delivery_method_id [notification::delivery::get_id -short_name email] + + # send out notifications + # notification::new \ + # -type_id [notification::type::get_type_id -short_name pm_task_notif] \ + # -object_id $t_id \ + # -response_id $t_id \ + # -notif_subject $subject \ + # -notif_text $notification_text +>>>>>>> 1.15 + db_dml add_assignment { } } } -edit_data { + # I believe this block is never executed. + # do something #role_id #party_id @@ -334,7 +500,24 @@ } -after_submit { - ad_returnredirect "one?project_item_id=$project_item_id" +<<<<<<< task-assign-add-edit.tcl + if {[exists_and_not_null return_url]} { + ad_returnredirect $return_url + } else { + ad_returnredirect "one?project_item_id=$project_item_id" + } +======= + if {[exists_and_not_null return_url]} { + ad_returnredirect $return_url + } else { + + if {[llength $task_id] > 1} { + ad_returnredirect "tasks" + } else { + ad_returnredirect "task-one?task_id=$task_id" + } + } +>>>>>>> 1.15 ad_script_abort } @@ -359,12 +542,19 @@ lappend users_values $pid } + } + + # if nobody is assigned to this task yet, we want to, by default, + # add in the person entering the task (as a watcher) + if {[llength $users_values] < 1} { + lappend users_values [ad_conn user_id] + lappend roles_values [db_string get_watcher "select role_id from pm_roles where is_observer_p = 't' limit 1"] } set users_length [string length $users_values] set roles_length [string length $roles_values] - for {set i 0} {$i <= 5} {incr i} { + for {set i 0} {$i <= $NUMBER_OF_ASSIGNMENTS} {incr i} { if {$i < $users_length && $i < $roles_length} { set uv [lindex $users_values $i] Index: openacs-4/contrib/packages/project-manager/www/task-one-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-one-postgresql.xql,v diff -u -r1.19 -r1.19.2.1 --- openacs-4/contrib/packages/project-manager/www/task-one-postgresql.xql 12 Mar 2004 13:44:45 -0000 1.19 +++ openacs-4/contrib/packages/project-manager/www/task-one-postgresql.xql 20 May 2004 17:30:05 -0000 1.19.2.1 @@ -1,23 +1,14 @@ - - - SELECT - t.parent_id as project_item_id - FROM - pm_tasks_revisionsx t, cr_items i - WHERE - i.item_id = t.item_id and - t.revision_id = :task_revision_id - - SELECT t.item_id, + t.parent_id as project_item_id, t.title as task_title, t.description, + t.mime_type, to_char(t.end_date,'Mon DD ''YY') as end_date, to_char(t.earliest_start,'Mon DD ''YY') as earliest_start, to_char(t.earliest_start,'J') as earliest_start_j, @@ -31,42 +22,24 @@ t.estimated_hours_work_max, t.percent_complete, i.live_revision, - p.first_names || ' ' || p.last_name as creation_user + p.first_names || ' ' || p.last_name as creation_user, + proj_rev.title as project_name FROM pm_tasks_revisionsx t, cr_items i, - persons p + persons p, + cr_items proj, + cr_revisions proj_rev WHERE t.item_id = :task_id and t.revision_id = :task_revision_id and t.item_id = i.item_id and - t.creation_user = p.person_id + t.creation_user = p.person_id and + t.parent_id = proj.item_id and + proj.live_revision = proj_rev.revision_id - - - SELECT - t.item_id, - t.revision_id, - i.live_revision, - t.title as task_title, - t.description || ' -- ' || p.first_names || ' ' || p.last_name as description, - to_char(t.end_date,'MM/DD/YYYY') as end_date, - t.percent_complete, - t.estimated_hours_work_min, - t.estimated_hours_work_max, - t.actual_hours_worked - FROM - pm_tasks_revisionsx t, cr_items i, persons p - WHERE - t.item_id = :task_id and - t.item_id = i.item_id and - t.creation_user = p.person_id - [template::list::orderby_clause -name revisions -orderby] - - - SELECT @@ -116,7 +89,7 @@ r.role_id from pm_task_assignment a, - cc_users u, + acs_users_all u, pm_roles r where a.task_id = :task_id and @@ -145,7 +118,7 @@ pm_task_xref x, pm_tasks_revisionsx r, cr_items i WHERE x.task_id_2 = :task_id and - x.task_id_2 = r.item_id and + x.task_id_1 = r.item_id and r.revision_id = i.live_revision UNION SELECT @@ -166,7 +139,7 @@ pm_task_xref x2, pm_tasks_revisionsx r2, cr_items i2 WHERE x2.task_id_1 = :task_id and - x2.task_id_1 = r2.item_id and + x2.task_id_2 = r2.item_id and i2.live_revision = r2.revision_id Index: openacs-4/contrib/packages/project-manager/www/task-one.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-one.adp,v diff -u -r1.23 -r1.23.2.1 --- openacs-4/contrib/packages/project-manager/www/task-one.adp 12 Mar 2004 13:44:45 -0000 1.23 +++ openacs-4/contrib/packages/project-manager/www/task-one.adp 20 May 2004 17:30:05 -0000 1.23.2.1 @@ -1,227 +1,232 @@ - - - - @task_term@ #@item_id@: @task_info.task_title@ - @context@ -

- -
+ @task_term@ #@task_id@: + @task_info.task_title;noquote@ @closed_message@ + @context;noquote@ + + + +
- - - - +
- - Edit - - - Print - -
- - - - - - - - + -
@task_term@ #@item_id@: @task_info.task_title@ - -
+
+ + Edit + + + Print + +
+ + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@task_term@ #@task_id@: @task_info.task_title@ + + + + +
-
Description
@task_info.description;noquote@
-- @task_info.creation_user@
Dates
Deadline@task_info.end_date@
Earliest start@task_info.earliest_start@
Earliest finish@task_info.earliest_finish@
Latest start@task_info.latest_start@
Latest finish@task_info.latest_start@
-
- -

- - - @notification_chunk;noquote@ - - -

- -
- - - - - - - - -
Assignees
- -
- -

- - - - - - - - -
@task_term@s this depends on.
- -
- -

- - - - - - - - -
@task_term@s depending on this @task_term@
- -
+ + + + + + + + + -

+

+ + + -
Description
@task_info.description;noquote@
-- @task_info.creation_user@
- - - - - - -
Related @task_term@s
- -
+ + Comments + -

- - - - - - - - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - +
Logged hours
- Total work: - - @task_info.estimated_hours_work_min@ - - @task_info.estimated_hours_work_max@ hrs estimated - - - @task_info.estimated_hours_work@ hrs estimated - -
@comments;noquote@ +

+ @comments_link;noquote@ +

Dates
- @task_info.percent_complete@% complete
- - Slack: @task_info.slack_time@
-
- - Slack: n/a - -
Earliest start@task_info.earliest_start@
Earliest finish@task_info.earliest_finish@
Latest start@task_info.latest_start@
Latest finish@task_info.latest_start@
Actions
+ +
- - - - Log hours - - + + +

+ + + + @notification_chunk;noquote@ + + + + + +   + + - - @log_note@ - - - - - - - - - - - - -

- -
+ + + + + + + +
Assignees
+ +
+ +

+ + + + + + + + +
@task_term@s this depends on.
+ +
+ +

+ + + + + + + + +
@task_term@s depending on this @task_term@
+ +
+ +

+ + + + + + + + +
Related @task_term@s
+ +
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + +
Logged hours
+ Total work: + + @task_info.estimated_hours_work_min@ - + @task_info.estimated_hours_work_max@ hrs estimated + + + @task_info.estimated_hours_work@ hrs estimated + + + @task_info.percent_complete@% complete
+ + Slack: @task_info.slack_time@
+
+ + Slack: n/a + +
+ + Log hours + + + @log_note@ +
+ +
+ + + + + -

- -

- - - - @comments;noquote@ -

- @comments_link;noquote@ - -

- Index: openacs-4/contrib/packages/project-manager/www/task-one.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-one.tcl,v diff -u -r1.24 -r1.24.2.1 --- openacs-4/contrib/packages/project-manager/www/task-one.tcl 12 Mar 2004 13:44:45 -0000 1.24 +++ openacs-4/contrib/packages/project-manager/www/task-one.tcl 20 May 2004 17:30:05 -0000 1.24.2.1 @@ -16,24 +16,22 @@ @param project_item_id the item_id for the project. Used for navigational links @param project_id the revision_id for the project. Used for navigational links @param context_bar value for context bar creation - @param orderby_revisions specifies how the revisions table will be sorted @param orderby_dependency specifies how the dependencies will be sorted @param orderby_dependency2 specifies how the dependencies will be sorted (for tasks that have dependencies on this task) } { task_id:integer,optional task_revision_id:integer,optional - orderby_revisions:optional orderby_dependency:optional orderby_dependency2:optional } -properties { + closed_message:onevalue notification_chunk:onevalue task_info:onerow project_item_id:onevalue project_id:onevalue context:onevalue write_p:onevalue create_p:onevalue - revisions:multirow dependency:multirow dependency2:multirow people:multirow @@ -43,6 +41,7 @@ watcher_term:onevalue comments:onevalue comments_link:onevalue + print_link:onevalue use_uncertain_completion_times_p:onevalue } -validate { task_id_exists { @@ -79,21 +78,13 @@ set project_term [parameter::get -parameter "ProjectName" -default "Project"] set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] -db_1row get_project_ids { } -set context [list "one?project_item_id=$project_item_id $project_term" "View"] - # the unique identifier for this package set package_id [ad_conn package_id] set user_id [ad_maybe_redirect_for_registration] -set comments [general_comments_get_comments -print_content_p 1 -print_attachments_p 1 $task_id "[ad_conn url]?task_id=$task_id"] -set comments_link [general_comments_create_link -object_name pm_task -link_text "Add a comment" -context_id $package_id $task_id "[ad_conn url]?task_id=$task_id"] - - - # permissions permission::require_permission -party_id $user_id -object_id $package_id -privilege read @@ -105,20 +96,51 @@ # Task info ---------------------------------------------------------- db_1row task_query { } -column_array task_info -set task_info(description) [ad_text_to_html -- $task_info(description)] +# we do this for the hours include portion +set project_item_id $task_info(project_item_id) + +set context [list [list "one?project_item_id=$task_info(project_item_id)" "$task_info(project_name)"] "$task_info(task_title)"] + + +set richtext_list [list $task_info(description) $task_info(mime_type)] + +set task_info(description) [template::util::richtext::get_property html_value $richtext_list] + if {[exists_and_not_null task_info(earliest_start_j)]} { set task_info(slack_time) [pm::task::slack_time \ -earliest_start_j $task_info(earliest_start_j) \ -today_j $task_info(today_j) \ -latest_start_j $task_info(latest_start_j)] } +if {$task_info(percent_complete) >= 100} { + set closed_message "-- Closed" +} else { + set closed_message "" +} + + +# set link to comments + +set comments [general_comments_get_comments -print_content_p 1 -print_attachments_p 1 $task_id "[ad_conn url]?task_id=$task_id"] + +set comments_link [general_comments_create_link -object_name "$task_term: $task_info(task_title)" -link_text "Add a comment" -context_id $package_id $task_id "[ad_conn url]?task_id=$task_id"] + +set print_link "task-print?&task_id=$task_id&project_item_id=$task_info(project_item_id)" + + +# how to get back here +set return_url [ad_return_url -qualified] + +set task_edit_url "task-add-edit?my_key=1&task_id=$task_id&return_url=$return_url" + + set logger_project [pm::project::get_logger_project \ - -project_item_id $project_item_id] + -project_item_id $task_info(project_item_id)] set logger_variable_id [logger::variable::get_default_variable_id] -set log_url "[ad_conn package_url]log?project_id=$logger_project&pm_project_id=$project_item_id&pm_task_id=$task_id" +set log_url "[ad_conn package_url]log?project_id=$logger_project&pm_project_id=$task_info(project_item_id)&pm_task_id=$task_id" set log_note "Task logged time listed below" @@ -133,64 +155,6 @@ ] -# Task Revisions, using list-builder --------------------------------- - -template::list::create \ - -name revisions \ - -multirow revisions \ - -key revision_id \ - -elements { - revision_id { - label "Subject" - display_col task_title - link_url_col item_url - link_html { title "View this revision" } - display_template {@revisions.task_title@@revisions.task_title@} - } - description { - label "Description" - } - percent_complete { - label "Status" - display_template "@revisions.percent_complete@\%" - } - actual_hours_worked { - label "Hour to date" - display_template "@revisions.actual_hours_worked@ hrs" - } - estimated_hours_work_min { - label "Work estimate" - display_template "@revisions.estimated_hours_work_min@ - @revisions.estimated_hours_work_max@ hrs" - } - end_date { - label "Deadline" - } - } \ - -orderby { - revision_id {orderby revision_id} - percent_complete {orderby percent_complete} - end_date {orderby end_date} - default_value revision_id,desc - } \ - -orderby_name orderby_revisions \ - -sub_class { - narrow - } \ - -filters { - task_revision_id {} - orderby_dependency {} - orderby_dependency2 {} - } \ - -html { - width 100% - } - - -db_multirow -extend { item_url } revisions task_revisions_query { -} { - set item_url [export_vars -base "task-one" -override {{task_revision_id $revision_id}} -exclude {revision_id} { revision_id task_id}] -} - # Dependency info ------------------------------------------------ template::list::create \ @@ -239,7 +203,6 @@ } \ -filters { task_revision_id {} - orderby_revisions {} orderby_dependency2 {} } \ -html { @@ -299,7 +262,6 @@ } \ -filters { task_revision_id {} - orderby_revisions {} orderby_dependency {} } \ -html { @@ -323,7 +285,7 @@ -elements { first_names { label { - Who + Who } display_template { @people.user_info@ @@ -388,7 +350,10 @@ label "LS" } latest_finish_pretty { - label "ES" + label "LF" + display_template { + @xrefs.latest_finish_pretty@ + } } } \ -sub_class { Index: openacs-4/contrib/packages/project-manager/www/task-print-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-print-postgresql.xql,v diff -u -r1.3 -r1.3.2.1 --- openacs-4/contrib/packages/project-manager/www/task-print-postgresql.xql 12 Mar 2004 13:44:45 -0000 1.3 +++ openacs-4/contrib/packages/project-manager/www/task-print-postgresql.xql 20 May 2004 17:30:05 -0000 1.3.2.1 @@ -31,7 +31,8 @@ t.item_id, t.title as task_title, t.description, - to_char(t.end_date,'Mon DD ''YY') as end_date, + t.mime_type, + to_char(current_timestamp,'Mon DD ''YY') as current_time, to_char(t.earliest_start,'Mon DD ''YY') as earliest_start, to_char(t.earliest_start,'J') as earliest_start_j, to_char(t.earliest_finish,'Mon DD ''YY') as earliest_finish, @@ -99,7 +100,7 @@ select r.one_line, - u.first_names || ' ' || u.last_name || ' (' || u.email || ')' as user_info, + u.first_names || ' ' || u.last_name as user_info, r.role_id from pm_task_assignment a, Index: openacs-4/contrib/packages/project-manager/www/task-print.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-print.adp,v diff -u -r1.3 -r1.3.2.1 --- openacs-4/contrib/packages/project-manager/www/task-print.adp 12 Mar 2004 13:44:45 -0000 1.3 +++ openacs-4/contrib/packages/project-manager/www/task-print.adp 20 May 2004 17:30:05 -0000 1.3.2.1 @@ -1,16 +1,18 @@ - + + +@task_term@ #@task_id@: @task_info.task_title@ + -@task_term@ #@task_id@: @task_info.task_title@ -@context_bar;noquote@ + -
+ + +
-
- - + - + +
@task_term@ #@task_id@: @task_info.task_title@@task_term@ #@task_id@: @task_info.task_title@
@@ -24,30 +26,59 @@
Work + +

Comments

@comments;noquote@ +
+ +

@show_comment_link;noquote@ + +

+
+ + + + + - + - + - + - + + - + + + + + + + +
@task_info.percent_complete@% completeAssignees
@task_info.estimated_hours_work_min@ - @task_info.estimated_hours_work_max@ hrs estimated
Slack time: @task_info.slack_time@Work
Dates@task_info.percent_complete@% complete
Deadline -@task_info.end_date@@task_info.estimated_hours_work_min@ - @task_info.estimated_hours_work_max@ hrs estimated
Slack time: @task_info.slack_time@
Dates
+ + + + + + + @@ -66,33 +97,33 @@ -
Now +@task_info.current_time@
Earliest start @task_info.earliest_start@
Latest finish @task_info.latest_start@
-
-

+ +@task_term@(s) this depends on. + -

+ + + + -
+ +@task_term@(s) depending on this @task_term@ + - - -

- -

@task_term@(s) this depends on.
- -

- -

@task_term@(s) depending on this @task_term@
+ + + + -
+ - + + + -
-@comments;noquote@ - -
+ + Index: openacs-4/contrib/packages/project-manager/www/task-print.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-print.tcl,v diff -u -r1.3 -r1.3.2.1 --- openacs-4/contrib/packages/project-manager/www/task-print.tcl 12 Mar 2004 13:44:45 -0000 1.3 +++ openacs-4/contrib/packages/project-manager/www/task-print.tcl 20 May 2004 17:30:05 -0000 1.3.2.1 @@ -25,6 +25,7 @@ orderby_revisions:optional orderby_dependency:optional orderby_dependency2:optional + {show_comment_p "f"} } -properties { task_info:onerow @@ -79,6 +80,7 @@ set comments_link [general_comments_create_link -object_name pm_task -link_text "Add a comment" -context_id $package_id $task_id "[ad_conn url]?task_id=$task_id"] +set show_comment_link "show comments" # permissions @@ -90,7 +92,11 @@ # Task info ---------------------------------------------------------- db_1row task_query { } -column_array task_info -set task_info(description) [ad_text_to_html -- $task_info(description)] + +set richtext_list [list $task_info(description) $task_info(mime_type)] + +set task_info(description) [template::util::richtext::get_property html_value $richtext_list] + set task_info(slack_time) [pm::task::slack_time \ -earliest_start_j $task_info(earliest_start_j) \ -today_j $task_info(today_j) \ Index: openacs-4/contrib/packages/project-manager/www/task-select-project-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-select-project-postgresql.xql,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/contrib/packages/project-manager/www/task-select-project-postgresql.xql 12 Mar 2004 13:44:45 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/www/task-select-project-postgresql.xql 20 May 2004 17:30:05 -0000 1.2.2.1 @@ -5,13 +5,24 @@ SELECT p.item_id as project_item_id, - p.title as project_name - FROM pm_projectsx p, cr_items i, pm_project_status s + p.title as project_name, + p.description as description, + p.mime_type, + o.organization_id as customer_id, + o.name as customer_name + FROM + pm_projectsx p + LEFT JOIN + organizations o + ON + p.customer_id = o.organization_id, + cr_items i, + pm_project_status s WHERE p.project_id = i.live_revision and p.parent_id = :root_folder and - p.status_id = s.status_id and - s.status_type = 'o' - ORDER BY p.title + p.status_id = s.status_id + [template::list::filter_where_clauses -and -name projects] + [template::list::orderby_clause -orderby -name projects]
Index: openacs-4/contrib/packages/project-manager/www/task-select-project.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-select-project.adp,v diff -u -r1.2 -r1.2.4.1 --- openacs-4/contrib/packages/project-manager/www/task-select-project.adp 10 Nov 2003 19:34:54 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/www/task-select-project.adp 20 May 2004 17:30:05 -0000 1.2.4.1 @@ -1,8 +1,29 @@ -@context_bar;noquote@ +@context@ @title@ -@form_definition_beg;noquote@ - @select_widget;noquote@ - -@form_definition_end;noquote@ + + + + + + + + + + +
+ +
+ Project Search:
+ + @hidden_vars;noquote@ +
+ + + +
+ + + +
Index: openacs-4/contrib/packages/project-manager/www/task-select-project.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/task-select-project.tcl,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/contrib/packages/project-manager/www/task-select-project.tcl 26 Jan 2004 15:39:40 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/www/task-select-project.tcl 20 May 2004 17:30:05 -0000 1.2.2.1 @@ -14,15 +14,17 @@ } { {process_id:integer ""} - + {return_url ""} + {status_type "o"} + {searchterm ""} + {orderby ""} + } -properties { context_bar:onevalue title:onevalue - select_widget:onevalue - select_widget_name:onevalue - form_definition_beg:onevalue - form_definition_end:onevalue + choices:onevalue + searchterm_copy:onevalue } -validate { } -errors { @@ -33,19 +35,34 @@ set user_id [ad_maybe_redirect_for_registration] set package_id [ad_conn package_id] +permission::require_permission -object_id $package_id -privilege write + +if {[empty_string_p $searchterm]} { + unset searchterm +} + + # terminology set project_term [parameter::get -parameter "ProjectName" -default "Project"] set task_term [parameter::get -parameter "TaskName" -default "Task"] -set task_term_lower [parameter::get -parameter "taskname" -default "task"] -set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] +# set task_term_lower [parameter::get -parameter "taskname" -default "task"] +# set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] -set title "Edit a $task_term_lower" +set title "Select a $project_term to assign this $task_term to" +if {![exists_and_not_null searchterm]} { + set searchterm_copy "" + set searchterm_where_clause "" +} else { + set searchterm_copy $searchterm + set searchterm_where_clause "upper(p.title) like upper('%$searchterm%')" +} + if {[exists_and_not_null process_id]} { - set context_bar [ad_context_bar [list "processes" "Processes"] "Use"] + set context [list [list "processes" "Processes"] "Use"] } else { - set context_bar [ad_context_bar [list "tasks" "Tasks"] "Select Project"] + set context [list [list "tasks" "Tasks"] "Select Project"] } # need to change this to show all the projects you're on by @@ -54,17 +71,77 @@ set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] -set select_widget_name project_item_id -set select_widget "" + searchterm { + label "Project Search term" + where_clause $searchterm_where_clause + } + + status_type { + label "Status" + values {{"Open" o} {"Closed" c}} + where_clause { + s.status_type = :status_type + } + } + return_url { + hide_p 1 + } + } \ + -orderby { + default_value customer_name,asc + project_item_id { + label "Project" + orderby_desc "upper(p.title) desc" + orderby_asc "upper(p.title) asc" + default_direction asc + } + customer_name { + label "Customer" + orderby_desc "upper(o.name) desc, upper(p.title) desc" + orderby_asc "upper(o.name) asc, upper(p.title) asc" + default_direction asc + } + } \ + -orderby_name orderby \ + -html { + width 100% + } -set form_definition_beg "
" -append form_definition_beg [export_vars -form {process_id}] -set form_definition_end "
" +db_multirow -extend { item_url description_html } projects select_a_project { +} { + set item_url [export_vars -base "task-add-edit" {project_item_id process_id return_url}] + set richtext_list [list $description $mime_type] + set description_html [template::util::richtext::get_property html_value $richtext_list] +} + Index: openacs-4/contrib/packages/project-manager/www/tasks-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/tasks-postgresql.xql,v diff -u -r1.5 -r1.5.2.1 --- openacs-4/contrib/packages/project-manager/www/tasks-postgresql.xql 12 Mar 2004 13:44:45 -0000 1.5 +++ openacs-4/contrib/packages/project-manager/www/tasks-postgresql.xql 20 May 2004 17:30:05 -0000 1.5.2.1 @@ -6,10 +6,12 @@ SELECT ts.task_id, + ts.task_id as item_id, ts.task_number, t.task_revision_id, t.title, t.description, + t.parent_id as project_item_id, to_char(t.earliest_start,'J') as earliest_start_j, to_char(current_timestamp,'J') as today_j, to_char(t.latest_start,'J') as latest_start_j, @@ -29,13 +31,16 @@ (select one_line from pm_roles r where ta.role_id = r.role_id) as role FROM pm_tasks ts, + cr_items i, pm_tasks_revisionsx t LEFT JOIN pm_task_assignment ta ON t.item_id = ta.task_id LEFT JOIN persons p ON ta.party_id = p.person_id WHERE - ts.task_id = t.item_id + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision [template::list::filter_where_clauses -and -name tasks] [template::list::orderby_clause -orderby -name tasks] Index: openacs-4/contrib/packages/project-manager/www/tasks.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/tasks.adp,v diff -u -r1.5 -r1.5.2.1 --- openacs-4/contrib/packages/project-manager/www/tasks.adp 12 Mar 2004 13:44:45 -0000 1.5 +++ openacs-4/contrib/packages/project-manager/www/tasks.adp 20 May 2004 17:30:05 -0000 1.5.2.1 @@ -1,7 +1,7 @@ - + @task_term@s @context@ @@ -11,14 +11,11 @@ - - My tasks
- Other tasks -

- +

- Search:
- + Search:
+ + @hidden_vars;noquote@
Index: openacs-4/contrib/packages/project-manager/www/tasks.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/Attic/tasks.tcl,v diff -u -r1.5 -r1.5.2.1 --- openacs-4/contrib/packages/project-manager/www/tasks.tcl 12 Mar 2004 13:44:45 -0000 1.5 +++ openacs-4/contrib/packages/project-manager/www/tasks.tcl 20 May 2004 17:30:05 -0000 1.5.2.1 @@ -14,18 +14,28 @@ @return project_term Terminology for projects @return project_term_lower Terminology for projects (lower case) + @param mine_p is used to make the default be the user, but + still allow people to view everyone. + } { orderby:optional party_id:optional {searchterm ""} {mine_p "t"} {status_id ""} + role_id:optional } -properties { task_term:onevalue context:onevalue tasks:multirow + hidden_vars:onevalue } +# if someone clicks on a party, then we want to see those tasks. +if {[exists_and_not_null party_id]} { + set mine_p "f" +} + # --------------------------------------------------------------- # # terminology @@ -34,6 +44,12 @@ set project_term [parameter::get -parameter "ProjectName" -default "Project"] set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +set exporting_vars { status_id party_id orderby mine_p } +set hidden_vars [export_vars -form $exporting_vars] +# how to get back here +set return_url [ad_return_url -qualified] + # set up context bar set context [list "Tasks"] @@ -60,6 +76,24 @@ # Tasks, using list-builder --------------------------------- +if {![empty_string_p $searchterm]} { + + # if we're searching, we disregard who we were searching for. + if {[info exists party_id]} { + unset party_id + } + set mine_p "f" + + if {[regexp {([0-9]+)} $searchterm match query_digits]} { + set search_term_where " (upper(t.title) like upper('%$searchterm%') + or t.item_id = :query_digits) " + } else { + set search_term_where " upper(t.title) like upper('%$searchterm%')" + } +} else { + set search_term_where "" +} + template::list::create \ -name tasks \ -multirow tasks \ @@ -76,37 +110,96 @@ } full_name { label "Who" - display_template "unassigned@tasks.full_name@ (@tasks.role@)" + display_template "unassigned@tasks.full_name@ (@tasks.role@)
" } slack_time { - label "Slack time" + label "Slack" display_template "@tasks.slack_time@@tasks.slack_time@" } latest_start_pretty { label "Latest Start" } latest_finish_pretty { label "Latest Finish" + display_template { + @tasks.latest_finish_pretty@ + } } actual_hours_worked { label "Hours completed" - display_template "@tasks.actual_hours_worked@/@tasks.estimated_hours_work@" + display_template "@tasks.actual_hours_worked@/@tasks.estimated_hours_work@ (@tasks.percent_complete@\%)" } + project_item_id { + label "P" + display_template "P" + } + log_url { + label "L" + display_template {L} + } + project_item_id { + label "P" + display_template "P" + } + log_url { + label "L" + display_template {L} + } } \ - -actions { - "Add task" "task-select-project" "Add a task" + -actions [list "Add task" [export_vars -base task-select-project {return_url}] "Add a task"] \ + -bulk_actions { + "Log hours" "log-bulk" "Log hours for several tasks" } \ + -actions [list "Add task" [export_vars -base task-select-project {return_url}] "Add a task"] \ + -bulk_actions { + "Log hours" "log-bulk" "Log hours for several tasks" + } \ + -bulk_action_export_vars { + {return_url} + } \ -sub_class { narrow } \ -filters { searchterm { label "Search" + where_clause {$search_term_where} } - + role_id { + label "Roles" + values {[db_list_of_lists get_roles " + SELECT + one_line, + role_id + FROM + pm_roles + ORDER BY + role_id"]} + where_clause { + ta.role_id = :role_id + } + } party_id { label "People" - values {[db_list_of_lists get_people "select distinct(first_names || ' ' || last_name) as fullname, u.person_id from persons u, pm_task_assignment a where u.person_id = a.party_id order by fullname"]} + values {[db_list_of_lists get_people " + SELECT + distinct(first_names || ' ' || last_name) as fullname, + u.person_id + FROM + persons u, + pm_task_assignment a, + cr_items t, + pm_tasks ts, + pm_tasks_revisionsx r + WHERE + u.person_id = a.party_id and + t.item_id = a.task_id and + t.item_id = ts.task_id and + ts.status = :status_id and + t.item_id = r.item_id and + t.live_revision = r.revision_id + ORDER BY + fullname"]} where_clause { ta.party_id = :party_id } @@ -116,7 +209,6 @@ values {[db_list_of_lists get_status_values "select description, status_id from pm_task_status order by status_type desc, description"]} where_clause {ts.status = :status_id} } - mine_p { label "Show others' tasks" } @@ -155,14 +247,14 @@ } latest_start_pretty { label "Latest start" - orderby_desc "t.latest_start desc" - orderby_asc "t.latest_start" + orderby_desc "t.latest_start desc, p.first_names, p.last_names" + orderby_asc "t.latest_start, p.first_names, p.last_name" default_direction asc } latest_finish_pretty { label "Latest finish" - orderby_desc "t.latest_finish desc" - orderby_asc "t.latest_finish" + orderby_desc "t.latest_finish desc, p.first_names, p.last_names" + orderby_asc "t.latest_finish, p.first_names, p.last_name" default_direction asc } actual_hours_worked { @@ -178,10 +270,14 @@ } -db_multirow -extend { item_url latest_start_pretty latest_finish_pretty slack_time} tasks tasks { + + +db_multirow -extend { item_url latest_start_pretty latest_finish_pretty slack_time log_url} tasks tasks { } { set item_url [export_vars -base "task-one" {task_id}] + set log_url [export_vars -base "log" {{pm_task_id $task_id} {pm_project_id $project_item_id} {return_url $return_url}}] + set latest_start_pretty [lc_time_fmt $latest_start "%x"] set latest_finish_pretty [lc_time_fmt $latest_finish "%x"] Index: openacs-4/contrib/packages/project-manager/www/admin/default-project-roles-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/admin/Attic/default-project-roles-postgresql.xql,v diff -u -r1.1 -r1.1.4.1 --- openacs-4/contrib/packages/project-manager/www/admin/default-project-roles-postgresql.xql 12 Sep 2003 01:20:57 -0000 1.1 +++ openacs-4/contrib/packages/project-manager/www/admin/default-project-roles-postgresql.xql 20 May 2004 17:30:06 -0000 1.1.4.1 @@ -8,7 +8,7 @@ role_id, party_id FROM - pm_project_default_roles + pm_default_roles Index: openacs-4/contrib/packages/project-manager/www/lib/nav-bar.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/project-manager/www/lib/Attic/nav-bar.tcl,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/contrib/packages/project-manager/www/lib/nav-bar.tcl 12 Mar 2004 13:44:47 -0000 1.2 +++ openacs-4/contrib/packages/project-manager/www/lib/nav-bar.tcl 20 May 2004 17:30:07 -0000 1.2.2.1 @@ -23,6 +23,10 @@ lappend link_list [list "${package_url}processes"] lappend link_list {} lappend link_list "Processes" + + lappend link_list [list "${package_url}task-select-project"] + lappend link_list {} + lappend link_list "New task" } if { $admin_p } {