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.7 -r1.8 --- openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 5 May 2004 19:04:54 -0000 1.7 +++ openacs-4/contrib/packages/project-manager/tcl/task-procs.tcl 14 May 2004 23:08:56 -0000 1.8 @@ -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 @@ -1425,3 +1569,5 @@ } + +