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 Managersff
- project-manager
-
-
+
+ Jade RubickProject management tool for OpenACS
- 2004-03-05
+ 2004-05-19
+ Integrated Bakery ResourcesTrack 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@
-
- You must enter a number here (make your best
- guess)
-
-
+
+
+
+
+ You must enter a number here (make your best
+ guess)
+
+
-
Log entry
+
Log entry:
@@ -128,6 +157,18 @@
%
+
+
+
+
+
+
+ Enter 100% to close the @task_term_lower@, or less
+ to open it.
+
+
+
+
Time:
@@ -149,30 +190,35 @@
-
-
+
+
+
+
+
+
+ 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@
-