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.24 -r1.25 --- openacs-4/contrib/packages/project-manager/www/task-add-edit.tcl 11 Dec 2003 21:39:44 -0000 1.24 +++ openacs-4/contrib/packages/project-manager/www/task-add-edit.tcl 26 Jan 2004 15:39:40 -0000 1.25 @@ -1,10 +1,14 @@ -ns_log notice task add edit page -set mypage [ns_getform] -if {[string equal "" $mypage]} { - ns_log notice no form was submitted on my page -} else { - ns_log notice the following form was submitted on my page - ns_set print $mypage +set debug 1 + +if {[string equal $debug 1]} { + ns_log notice task add edit page + set mypage [ns_getform] + if {[string equal "" $mypage]} { + ns_log notice no form was submitted on my page + } else { + ns_log notice the following form was submitted on my page + ns_set print $mypage + } } ad_page_contract { @@ -20,7 +24,7 @@ @return num num is used as a multirow datasource to iterate over the ad_form elements @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 dependencies and assignments + @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 number The number of Tasks to create @@ -30,7 +34,6 @@ @param my_key if set, then ad_form knows that this is an edit @param task_title @param process_id The process we're using to create this task - @param use_dependency_p Whether or not to use dependencies with this task @param use_uncertain_completion_times_p Whether or not to use PERT-style completion time uncertainty 1 = yes } { @@ -40,11 +43,10 @@ project_id:integer,optional {number:integer "1"} task_revision_id:integer,optional - task_id:integer,multiple,optional + {task_id ""} task_item_id:array,optional task_title:array,optional {process_id:integer ""} - use_dependency_p:array,optional description:array,optional name:array,optional end_date:array,optional @@ -53,6 +55,8 @@ estimated_hours_work:array,optional estimated_hours_work_min:array,optional estimated_hours_work_max:array,optional + dependency_type:array,optional + dependency_task_id:array,optional } -properties { @@ -120,13 +124,20 @@ set number [llength $process_tasks] } +# we use this to get around the lack of a hidden multiple in ad_form +set task_id_pass [string map {"-" " "} $task_id] +set task_id $task_id_pass if {![ad_form_new_p -key task_id]} { + # Editing! # ----------------------------------------------------- # create a multirow we can use to iterate # we also set the number variable for future use # ----------------------------------------------------- template::multirow create num number + + # TODO:get task IDS + # set i 1 set number 0 @@ -202,6 +213,8 @@ permission::require_permission -party_id $user_id -object_id $package_id -privilege create } +# we use this to pass through the task_ids +set task_id_pass [string map {" " "-"} $task_id] ad_form -name add_edit -form { my_key:key(acs_object_id_seq) @@ -210,6 +223,10 @@ {value $project_item_id} } + {task_id:text(hidden) + {value $task_id_pass} + } + {project_id:text(hidden) {value $project_id} } @@ -241,12 +258,6 @@ set actual_hours_worked_arr($i) $actual_hours_worked set task_item_id_arr($i) [lindex $task_id [expr $i - 1]] - if {[exists_and_not_null parent_task_id]} { - set use_dependency_arr($i) [list checked ""] - } else { - set use_dependency_arr($i) "" - } - # we are not using a process set process_task_id_arr($i) "" @@ -284,10 +295,9 @@ for {set i 1} {$i <= $number} {incr i} { set task_title_arr($i) "" set description_arr($i) "" - set estimated_hours_arr($i) "" - set estimated_hours_min_arr($i) "" - set estimated_hours_max_arr($i) "" - set use_dependency_arr($i) "" + 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 @@ -304,12 +314,6 @@ 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) - - if {[exists_and_not_null dependency_v($ptask_id)]} { - set use_dependency_arr($i) [list checked ""] - } else { - set use_dependency_arr($i) "" - } # keeps track of what process_task_id this was based on # so we can later get info on what assignments the process @@ -340,17 +344,55 @@ } } +# 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 + +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] + + + + # ---------------------------------------------- # extend the form with all the items that repeat # ---------------------------------------------- for {set i 1} {$i <= $number} {incr i} { - + + # ---------------------------------------------------------------- # reading this code, you may wonder why we put the .$i at the end. # DaveB showed me this trick. It lets you make a multiple out of # the items by stuffing them in an array. Long live DaveB. + # ---------------------------------------------------------------- + # set up the tasks that can be viewed. Take out the current task. + # TODO: add in process defaults + set dependency_options_full "" + append dependency_options_full "{\"--None--\" \"\"} " + # adds in the NEW tasks as options. We have to check later to make sure + # the user doesn't enter any loops! + for {set j 1} {$j <= $number} {incr j} { + if {![string equal $i $j]} { + append dependency_options_full "{\"New Task \#$j\" \"num$j\"} " + } + } + foreach key $dependency_keys { + append dependency_options_full "{\"$key\" $dependency_options($key)} " + } + ad_form -extend \ -name add_edit \ -form \ @@ -376,18 +418,24 @@ {value {$description_arr($i)}} \ ] \ [list \ - use_dependency_p.$i:text(checkbox) \ - {label "Use dependency"} \ - {options {{"" "on"}}} \ - {html $use_dependency_arr($i)} \ - ] \ - [list \ end_date.$i:date,to_sql(linear_date),optional \ {label "Deadline"} \ {format "MONTH DD YYYY"} \ {value $end_date_arr($i)} \ {help} \ ] \ + [list \ + dependency_type.$i:text(select),optional \ + {label \"Dependency type\"} \ + {options {[join $options " "]}} \ + {value {finish_before_start}} \ + ] \ + [list \ + dependency_task_id.$i:text(select),optional \ + {label \"Dependency\"} \ + {options {$dependency_options_full}} \ + {help_text {$task_term the dependency is based on}} \ + ] \ ] if {$use_uncertain_completion_times_p} { @@ -435,12 +483,9 @@ # -------------------------------------------------------------- # each task we add in returns a task_revision_id - # we set up two lists, one for tasks that will need dependencies - # another for tasks that don't # -------------------------------------------------------------- - set revision_has_dependencies [list] - set revision_no_dependencies [list] + set task_id [list] for {set i 1} {$i <= $number} {incr i} { @@ -462,38 +507,112 @@ } # set up variables, pulling from arrays - set p_task_title $task_title($i) - set p_description $description($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) + set p_task_title $task_title($i) + set p_description $description($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) + set p_dep_type $dependency_type($i) + set p_dep_id $dependency_task_id($i) + set parent_task_id $p_dep_id - ns_log Notice "adding task: pii: $project_item_id tt:$p_task_title d:$p_description ed: end_date($i) w:$p_work m:$p_work_min mx:$p_work_max" + ns_log Notice "adding task: pii: $project_item_id tt:$p_task_title d:$p_description ed: end_date($i) w:$p_work m:$p_work_min mx:$p_work_max dep_type:$p_dep_type dep_id:$p_dep_id" + # add in the new task set this_revision_id [db_exec_plsql new_task_item { *SQL* }] + set this_task_id [db_string get_task_item_id {}] + set dep_task_id($i) $this_task_id - if {[info exists use_dependency_p($i)] && [string equal $use_dependency_p($i) "on"]} { - lappend revision_has_dependencies $this_revision_id - } else { - lappend revision_no_dependencies $this_revision_id + if {[exists_and_not_null p_dep_id]} { + + # if the p_dep_id contains num at the beginning, then + # the task is supposed to depend on other tasks that + # are currently being created. We have to do all sorts of + # things like make sure there are no loops, etc.. + if {[regexp {num.*} $p_dep_id]} { + regexp {num(.*)} $p_dep_id match d_parent + + # dep_parent tracks who is parent of what + set dep_parent($i) $d_parent + set dep_type($i) $p_dep_type + lappend parent_new_task $i + # we wait until after all the tasks have been created to create these + # dependencies + } else { + + # add in the new dependency + set dependency_id [db_nextval pm_task_dependency_seq] + db_dml new_dependency { *SQL* } + } } lappend process_task_id $process_task_ids($i) + lappend revisions $this_revision_id + lappend task_id $this_task_id } + if {[exists_and_not_null parent_new_task]} { + # there are tasks that depend on newly created tasks. + # 1. check for loops + # 2. if no loops, create dependencies + + # the way we check for a loop is to follow the dependencies + # until we get to a task that has already been created. + # we make the assumption that the following is true: + # starting condition: no tasks are created + # when adding a task: no loop is created if you depend on a task already present + # therefore, if you add a task without creating a loop in the newly + # created tasks, you are safe. + + # we check that the new items don't depend on each other by following them + # if they loop more than $number times, then we have a loop + set loop_limit $number + + foreach dep_task $parent_new_task { + + set passes_p f + + set my_task $dep_task + while {$loop_limit >= 0} { + + if {[exists_and_not_null dep_parent($my_task)]} { + set my_task $dep_parent($my_task) + } else { + set passes_p t + break + } + + set loop_limit [expr $loop_limit - 1] + } + + if {[string equal $passes_p t]} { + # add in the new dependency + set dependency_id [db_nextval pm_task_dependency_seq] + set this_task_id $dep_task_id($dep_task) + set parent_task_id $dep_task_id($dep_parent($dep_task)) + set p_dep_type $dep_type($dep_task) + db_dml new_dependency { *SQL* } + } else { + ns_log Notice "PM: Adding in dependency failed for $dep_task_id($dep_task) due to looping" + } + + } + + + + } + + ns_log Notice "Project_item_id $project_item_id" + project_manager::project::compute_parent_status $project_item_id + } -edit_data { ns_log Notice "edit_data" # -------------------------------------------------------------- # each task we edit returns a task_revision_id - # we set up two lists, one for tasks that will need dependencies - # another for tasks that don't # -------------------------------------------------------------- - set revision_has_dependencies [list] - set revision_no_dependencies [list] - for {set i 1} {$i <= $number} {incr i} { if {![exists_and_not_null estimated_hours_work($i)]} { @@ -527,14 +646,13 @@ ns_log Notice "Added in $this_revision_id" + lappend revisions $this_revision_id + + ns_log Notice "in new: task_id $task_id" + # BUG: we need to make sure we take care of deleting dependencies # if unchecked, adding dependencies, etc.. - if {[info exists use_dependency_p($i)] && [string equal $use_dependency_p($i) "t"]} { - lappend revision_has_dependencies $this_revision_id - } else { - lappend revision_no_dependencies $this_revision_id - } } project_manager::project::compute_parent_status $project_item_id @@ -543,12 +661,9 @@ } -after_submit { - # now go through the use_dependency_p items. For each that is checked, - # we add that to a list of ids that we pass to the dependency-add-edit - # page. + ns_log Notice "TASK_ID: $task_id" - - ad_returnredirect "task-assign-add-edit?[export_vars -url {revision_has_dependencies:multiple revision_no_dependencies:multiple project_item_id process_task_id:multiple}]" + ad_returnredirect "task-assign-add-edit?[export_vars -url {project_item_id process_task_id:multiple revisions:multiple task_id:multiple}]" ad_script_abort }