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.41 -r1.42 --- openacs-4/contrib/packages/project-manager/www/task-add-edit.tcl 24 Jul 2004 08:33:56 -0000 1.41 +++ openacs-4/contrib/packages/project-manager/www/task-add-edit.tcl 13 Jan 2005 13:54:36 -0000 1.42 @@ -2,1181 +2,431 @@ Add/edit form for tasks -

+ Needs to handle the following cases: +

- 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. - -

- - I'd also like to move the assignments to this page, in the same manner - as the processes. - @author jader@bread.com @creation-date 2003-07-28 @cvs-id $Id$ @return context Context bar @return title Page title. - @return num 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 assignments - @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 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 task_title - @param process_id The process we're using to create this task - @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) - @param send_email_p Send out emails to assignees of new task(s) + @param task_item_id list of tasks to edit, if there are any + @project_item_id The project these tasks are assigned to. + @param process_id The id for the process used, if any + @param process_task_id The process task IDs if there is a process used. + @param return_url + @param new_tasks if we are creating new tasks, how many to create } { - - my_key:integer,optional - process_task_ids:array,optional + {task_item_id:integer,multiple ""} {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:html,array,optional - {old_description ""} - comment:html,array,optional - name:array,optional - end_date:array,optional - percent_complete:array,optional - actual_hours_worked:array,optional - new_hours_logged:array,optional - new_description_logged:array,optional - 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 - skip_task_p:array,optional - {using_process_p "f"} + {process_task_id:integer,multiple ""} {return_url ""} - {send_mail_p "t"} + {new_tasks "1"} } -properties { - context:onevalue - title:onevalue - num:multirow - use_uncertain_completion_times_p:onevalue - edit_p:onevalue - using_process_p:onevalue - } -validate { - number_is_in_range -requires {number:integer} { - # todo: make 100 a parameter - if {$number < 1 || $number > 100} { - ad_complain - } - } - percent_is_in_range { - for {set i 1} {$i <= $number} {incr i} { - if {[exists_and_not_null percent_complete($i)]} { - if {$percent_complete($i) < 0 || $percent_complete($i) > 100} { - ad_complain - } - } - } - } } -errors { - project_exists {You must enter a project} - number_is_in_range {Number must be between 1 and 100} - percent_is_in_range {Percent completed must be between 0 and 100} } -# --------------------------------------------------------------- # -set user_id [ad_maybe_redirect_for_registration] -set package_id [ad_conn package_id] +# --------------------------------------------------------------- +# Set up +# --------------------------------------------------------------- +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] +# use hour units or day units +set use_day_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] +set hours_day [pm::util::hours_day] -# --------------------------------------------------------------- # +if {[string is true $use_day_p]} { + set work_units "days" +} else { + set work_units "hrs" +} + +# --------------------------------------------------------------- # terminology -# --------------------------------------------------------------- # +# --------------------------------------------------------------- set project_term [parameter::get -parameter "ProjectName" -default "Project"] set task_term [parameter::get -parameter "TaskName" -default "Task"] set task_term_lower [parameter::get -parameter "taskname" -default "task"] set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] -# --------------------------------------------------------------- # +# ------------------------- +# Set up flags to use later +# ------------------------- -# -------------------------------------------------------------------- -# 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 -# set the number of tasks we're going to be entering. We save this for -# later, so we can get the values -# -------------------------------------------------------------------- - -set process_tasks [list] - -if {[exists_and_not_null process_id]} { - - # we need the ADP page to know we're using processes, so we can - # modify the interface a little bit - set using_process_p t - - db_foreach get_process_tasks { } { - set one_line_v($process_tid) $one_line - set description_v($process_tid) $description - set estimated_hours_work_v($process_tid) $estimated_hours_work - set estimated_hours_work_min_v($process_tid) $estimated_hours_work_min - 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] -} - - - -# --------------------------------------------------------------- # - - - -# 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 - -# 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 -# --------------------------------------------------------------- # - -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 task_id - - set i 1 - set number 0 - foreach tid $task_id { - template::multirow append num $i [lindex $task_id [expr $i-1]] - incr i - incr number - } - +if {[exists_and_not_null task_item_id]} { set edit_p t - } else { - # create a multirow we can use to iterate - template::multirow create num number task_id - - for {set i 1} {$i <= $number} {incr i} { - template::multirow append num $i [lindex $task_id [expr $i-1]] - } - set edit_p f } - -# ------------------------------------------------------- # -# The evilest hack of all time. -# ------------------------------------------------------- -# This is a workaround the fact that using multiple dates -# with ad_form is extremely difficult. Dates are formatted -# like arrays, with values like end_date.day, end_date.month, -# end_date.year, and end_date.format . The problem is we want -# to have multiple end_dates. Using the multiple method, we -# then get entries like this: end_date.1.year, end_date.2.year, -# end_date.2.day, etc.. -# -# 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, but my posting on -# the forums didn't result in any other suggestions. -# ------------------------------------------------------- # - -if {[info exists end_date]} { - - set searchToken [array startsearch end_date] - - while {[array anymore end_date $searchToken]} { - - 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) {} {} {}] - # ns_log Notice "end_date_$i: [set end_date_$i]" - } +if {[exists_and_not_null process_id]} { + set using_process_p t +} else { + set using_process_p f } -# ------------------------------------------------------- # -# 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 we are editing tasks, each task has its own project. We also want +# to look up all the old information to store it for later. We use +# this for comparison, to see what has changed. +# -------------------------------------------------------------------- -if {[info exists description] && ![exists_and_not_null process_id]} { +if {[string is true $edit_p]} { - set searchToken [array startsearch description] + # get old values + pm::task::get \ + -tasks_item_id $task_item_id \ + -one_line_array task_one_line \ + -description_array task_description \ + -description_mime_type_array task_description_mime_type \ + -estimated_hours_work_array task_estimated_hours_work \ + -estimated_hours_work_min_array task_estimated_hours_work_min \ + -estimated_hours_work_max_array task_estimated_hours_work_max \ + -dependency_array task_dependency \ + -percent_complete_array task_percent_complete \ + -end_date_day_array task_end_date_day \ + -end_date_month_array task_end_date_month \ + -end_date_year_array task_end_date_year \ + -project_item_id_array task_project_item_id \ + -priority_array task_priority - 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" - - } - +} elseif {[empty_string_p $project_item_id]} { + + ad_return_error "Project missing" "For new tasks, a project must be passed in" + ad_script_abort } -# ------------------------------------------------------- # -# 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 is true $edit_p] && [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" - - } - -} 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]] -} - - -# ns_log Notice "comment_list $comment_list" - - - - -# --------------------------------------------------------------- # +# --------------------------------------------------------------- # permissions and title setup, etc -# we should update the permissions to not just use package_id, so -# users can have permissions on particular tasks but not others. -# Right now it's an open system. If you have write permissions on -# the package_id, you have permissions to write anywhere -# --------------------------------------------------------------- # +# --------------------------------------------------------------- -if {[exists_and_not_null task_id]} { +if {[string is true $edit_p]} { set title "Edit a $task_term_lower" set context [list [list $return_url "Go back"] "Edit $task_term"] + permission::require_permission \ -party_id $user_id \ -object_id $package_id \ -privilege write } else { - set title "Add a $task_term_lower" + set title "Add $task_term_lower" 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 \ -privilege create } -# we use this to pass through the task_ids -set task_id_pass [string map {" " "-"} $task_id] +# ------------------------------------------------------------- +# Start creating the multirow we'll use to create the interface +# ------------------------------------------------------------- -# set up options for editing projects -set project_options [pm::project::get_list_of_open] +template::multirow create \ + tasks \ + task_item_id \ + process_task_id \ + one_line \ + description \ + description_mime_type \ + work_hrs \ + work_min_hrs \ + work_max_hrs \ + work_days \ + work_min_days \ + work_max_days \ + percent_complete \ + end_date_html \ + depends \ + assignee_html \ + dependency_html \ + logger_variable_html \ + project_html \ + priority -# --------------------------------------------------------------- # -# Begin our form -# --------------------------------------------------------------- # +if {[string is true $edit_p]} { -ad_form -name add_edit -form { - my_key:key(acs_object_id_seq) +# set today_html [pm::task::today_html \ + \# -month_target log_month \ + \# -day_target log_day \ + \# -year_target log_year] - {task_id:text(hidden) - {value $task_id_pass} - } - {send_email_p:text(select) - {options {{"Yes" t} {"No" f}}} - {value t} - } + # ------- + # EDITING + # ------- - {edit_p:text(hidden) - {value $edit_p} - } + set number 1 + set total_number [llength $task_item_id] - {return_url:text(hidden) - {value $return_url} - } - {number:text(hidden) - {value $number} - } -} - - -# ---------------------------------- -# 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 - lappend old_description $my_description - set mime_type_arr($i) $my_mime_type - set template_arr($i) [list $my_description $my_mime_type] - 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 - - # 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 deps [list] + foreach task $task_item_id { + if {[lsearch $deps $task_dependency($task)] == -1 && \ + ![empty_string_p $task_dependency($task)]} { + lappend deps $task_dependency($task) } - - 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) "" - - # ----------------------------------------------------- - # if we are editing the tasks, then we want to show the - # percent_complete, and give the users the chance to - # 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 \ - [list [list percent_complete.$i:text \ - {label "Percent complete"} \ - {html {size 4}} \ - {value {$percent_complete_arr($i)}} \ - ] \ - [list new_hours_logged.$i:text,optional \ - {label "Hours logged"} \ - {html {size 4}} \ - ] \ - [list new_description_logged.$i:text,optional \ - {label "Description"} \ - {html {size 30}} \ - ] \ - ] - - # -------------------------------------- - # we don't skip tasks when we're editing - # -------------------------------------- - ad_form -extend \ - -name add_edit \ - -form \ - [list [list \ - skip_task_p.$i:text(hidden) \ - {value {f}} \ - ] \ - ] - - # ------------------------------------------------------ - # 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}} \ - ] \ - ] - + foreach task $task_item_id { -} else { + set this_project $task_project_item_id($task) + + set project_options [pm::project::select_list_of_open \ + -selected $this_project] - # ---------------------------------------------------------- - # if we are using a process, then we want to fill in all the - # default values for the user. - # ---------------------------------------------------------- + # find out the default logger variable for this project + set logger_project [pm::project::get_logger_project \ + -project_item_id $this_project] + set logger_variable_id [logger::project::get_primary_variable \ + -project_id $logger_project] + set today_date [db_string today "select to_date(sysdate,'YYYY-MM-DD') from dual"] + set today_html$task "
y-m-d " - # get the values + #set end_date_html [pm::task::date_html \ + \# -selected_day $task_end_date_day($task) \ + \# -selected_month $task_end_date_month($task) \ + \# -selected_year $task_end_date_year($task)] - 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) "" + set end_date_html "
y-m-d " - if {[exists_and_not_null process_id]} { + set assignee_html [pm::task::assignee_html \ + -task_item_id $task \ + -number $number] - set ptask_id [lindex $process_tasks [expr $i-1]] + set dependency_options_full [pm::task::options_list_html \ + -edit_p $edit_p \ + -task_item_id $task \ + -project_item_id $this_project \ + -dependency_task_id $task_dependency($task) \ + -dependency_task_ids "$deps" \ + -number $total_number \ + -current_number $number] - set task_title_arr($i) $one_line_v($ptask_id) - set description_arr($i) $description_v($ptask_id) + set variable_widget [logger::ui::variable_select_widget \ + -project_id $logger_project \ + -current_variable_id $logger_variable_id \ + -select_name logger_variable.$number] - set mime_type_arr($i) "text/plain" - set template_arr($i) [list "$description_v($ptask_id)" "text/plain"] + set project_html "$project_term: + " - 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) + set task_estimated_days_work($task) \ + [pm::util::days_work \ + -hours_work $task_estimated_hours_work($task)] + set task_estimated_days_work_min($task) \ + [pm::util::days_work \ + -hours_work $task_estimated_hours_work_min($task)] - # keeps track of what process_task_id this was based on - # so we can later get info on what assignments the process - # task had, and what dependencies as well - set process_task_id_arr($i) $ptask_id - - - # We also want to make it optional for the user whether or - # not they use any given task when they are using a - # process. Often, they will want to skips some of the - # tasks, and this gives them that option - - ad_form -extend \ - -name add_edit \ - -form \ - [list [list \ - skip_task_p.$i:text(select) \ - {label \"Skip this task?\"} \ - {options {{No f} {Yes t}}} \ - {value {f}} \ - {help_text {If you skip this task, it will not be created}} \ - ] \ - ] - + set task_estimated_days_work_max($task) \ + [pm::util::days_work \ + -hours_work $task_estimated_hours_work_max($task)] + + + template::multirow append tasks \ + $task \ + "" \ + $task_one_line($task) \ + $task_description($task) \ + $task_description_mime_type($task) \ + $task_estimated_hours_work($task) \ + $task_estimated_hours_work_min($task) \ + $task_estimated_hours_work_max($task) \ + $task_estimated_days_work($task) \ + $task_estimated_days_work_min($task) \ + $task_estimated_days_work_max($task) \ + $task_percent_complete($task) \ + $end_date_html \ + $task_dependency($task) \ + $assignee_html \ + $dependency_options_full \ + $variable_widget \ + $project_html \ + $task_priority($task) - } else { - - # we never skip when there is no process being used - - ad_form -extend \ - -name add_edit \ - -form \ - [list [list \ - skip_task_p.$i:text(hidden) \ - {value {f}} \ - ] \ - ] - - } - - # ----------------------------------------------------- - # for new tasks, we hide the percent_complete - # ----------------------------------------------------- - - ad_form -extend \ - -name add_edit \ - -form \ - [list [list percent_complete.$i:text(hidden) \ - {label "Percent complete \#$i"} \ - {html {size 4}} \ - {value {$percent_complete_arr($i)}} \ - ] \ - ] - - # ----------------------------------------------------------- - # 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 ""} \ - ] \ - ] - - + incr number } - # 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 {}} \ - ] \ - ] +} elseif {[string is true $using_process_p]} { -} + # ------------- + # USING PROCESS + # ------------- -# get dependency types + set process_name [pm::process::process_name \ + -process_id $process_id] -#set options [list] -#db_foreach get_dependency_types { } -column_array dependencies { -# lappend options "{\"$dependencies(description)\" $dependencies(short_name)}" -#} + # get all the process task info + pm::process::get \ + -process_id $process_id \ + -process_task_id $process_task_id \ + -one_line_array process_one_line \ + -description_array process_description \ + -description_mime_type_array process_description_mime_type \ + -estimated_hours_work_array process_estimated_hours_work \ + -estimated_hours_work_min_array process_estimated_hours_work_min \ + -estimated_hours_work_max_array process_estimated_hours_work_max \ + -dependency_array process_dependency \ + -tasks_list process_tasks - -# ---------------------------------------------- -# 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. - - # --------------------------------------------------- - # set up the tasks that this task can be dependent on - # For new tasks, that includes the other new tasks - # We have to check later that the user doesn't enter - # any loops! - # --------------------------------------------------- - - if {[string is false $edit_p]} { - - # if we have a process, we need to bring in the dependencies - # from the process. - # - # We have the following: - # process_tasks: a list of all the process task ids, which act - # as keys for the other information. - # dependency_v(process_task_id) which process these tasks rely on. - # - - if {[exists_and_not_null process_id]} { - - # what is the task that the process says this task - # depends on? - set process_index [expr $i - 1] - set this_process [lindex $process_tasks $process_index] - - if {[exists_and_not_null dependency_v($this_process)]} { - set process_depend $dependency_v($this_process) - } else { - set process_depend "XXX" - } - - # lsearch gives us the index value inside the - # process_tasks list. That corresponds to the task minus - # one. So we add one to this index, as long as the value - # is not -1 (which indicates that process_depend is not in - # the process_tasks list) - # can have more than one match, so we use -all - - set which_dep_task_list [lsearch -all $process_tasks $process_depend] - - foreach which_dep $which_dep_task_list { - - # indexes are from 0, we want from 1 - incr which_dep - - # num1 is a convention, used to indicate dependencies - # on tasks that haven't been created yet. - set dependency_arr($i) "num$which_dep" - } - + # we now have an array (process_dependency) that contains all the + # templates for where the dependencies should lie. However, the + # user may not have selected all the process tasks to be + # created. We also need to keep track of which new task + # corresponds with which process task, so we can make sure the + # default process + set number 1 + foreach pt $process_tasks { + set task_num($pt) $number + incr number + } + foreach pt $process_tasks { + if {[exists_and_not_null process_dependency($pt)]} { + # keep track of which task the new task should by default + # depend upon + set task_parent_num($pt) $task_num($process_dependency($pt)) + } else { + set task_parent_num($pt) "" } - - } + set new_tasks [llength $process_tasks] - set dependency_options_full [pm::task::options_list \ - -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] +# set end_date_html [pm::task::date_html] - # if the current project is closed, we need to append it to the - # list of open projects - if {![pm::project::open_p -project_item_id "$project_item_id_arr($i)"] && [exists_and_not_null project_item_id_arr($i)]} { - set project_options_plus [db_list_of_lists get_closed_project " - SELECT - case when o.name is null then p.title || ' -- Closed' else o.name || ' - ' || p.title || ' -- Closed' end as title, - p.item_id - FROM - pm_projectsx p LEFT JOIN - organizations o ON p.customer_id = o.organization_id - WHERE - p.item_id = $project_item_id_arr($i) - "] + set end_date_html "
y-m-d " + - set project_options_plus [concat $project_options_plus $project_options] - } else { - set project_options_plus $project_options - } + set number 1 + set total_number [llength $process_tasks] - ad_form -extend \ - -name add_edit \ - -form \ - [list \ - [list \ - task_title.$i:text \ - {label "Subject \#$i"} \ - {html {size 40}} \ - {value {$task_title_arr($i)}} - ] \ - [list project_item_ids.$i:text(select) \ - {label "Project"} \ - {options $project_options_plus} \ - {value {$project_item_id_arr($i)}} \ - ] \ - [list task_item_id.$i:text(hidden) \ - {label "Task item id"} \ - {value {$task_item_id_arr($i)}} \ - ] \ - [list process_task_ids.$i:text(hidden) \ - {label "Process task id"} \ - {value {$process_task_id_arr($i)}} \ - ] \ - [list \ - description.$i:richtext,optional,nospell \ - {label "Description"} \ - {html {rows 7 cols 40}} \ - {value {$template_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(hidden),optional \ - {label \"Dependency type\"} \ - {value {finish_before_start}} \ - ] \ - [list \ - dependency_task_id.$i:text(select),optional \ - {label \"Dependency\"} \ - {options {$dependency_options_full}} \ - {value {$dependency_arr($i)}} \ - {help_text {$task_term the dependency is based on}} \ - ] \ - ] + foreach pt $process_tasks { - if {$use_uncertain_completion_times_p} { - ad_form -extend \ - -name add_edit \ - -form \ - [list \ - [list \ - 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:text \ - {label "Hours estimate - max"} \ - {html {size 5}} \ - {value {$estimated_hours_max_arr($i)}} \ - ] \ - ] - } else { - ad_form -extend -name add_edit \ - -form \ - [list \ - [list \ - estimated_hours_work.$i:text \ - {label "Hours estimate"} \ - {html {size 5}} \ - {value {$estimated_hours_arr($i)}} \ - ] \ - ] - } -} + set assignee_html [pm::task::assignee_html \ + -number $number \ + -process_task_id $pt] + set dependency_options_full [pm::task::options_list_html \ + -edit_p $edit_p \ + -project_item_id $project_item_id \ + -depends_on_new $task_parent_num($pt) \ + -number $new_tasks \ + -current_number $number] + set project_html "" -ad_form -extend -name add_edit -select_query_name task_query -on_submit { - - set user_id [ad_conn user_id] - set peeraddr [ad_conn peeraddr] + set process_estimated_days_work($pt) \ + [pm::util::days_work \ + -hours_work $process_estimated_hours_work($pt)] -} -new_data { + set process_estimated_days_work_min($pt) \ + [pm::util::days_work \ + -hours_work $process_estimated_hours_work_min($pt)] - # -------------------------------------------------------------- - # each task we add in returns a task_revision_id - # -------------------------------------------------------------- + set process_estimated_days_work_max($pt) \ + [pm::util::days_work \ + -hours_work $process_estimated_hours_work_max($pt)] - set task_id [list] - for {set i 1} {$i <= $number} {incr i} { - - if {![exists_and_not_null estimated_hours_work($i)]} { - set estimated_hours_work($i) [expr .5 * ($estimated_hours_work_max($i) - $estimated_hours_work_min($i)) + $estimated_hours_work_min($i)] - } + # make sure deps are working. - if {![exists_and_not_null estimated_hours_work_min($i)]} { - set estimated_hours_work_min($i) $estimated_hours_work($i) - } + template::multirow append tasks \ + "" \ + $process_task_id \ + $process_one_line($pt) \ + $process_description($pt) \ + $process_description_mime_type($pt) \ + $process_estimated_hours_work($pt) \ + $process_estimated_hours_work_min($pt) \ + $process_estimated_hours_work_max($pt) \ + $process_estimated_days_work($pt) \ + $process_estimated_days_work_min($pt) \ + $process_estimated_days_work_max($pt) \ + "0" \ + $end_date_html \ + $process_dependency($pt) \ + $assignee_html \ + $dependency_options_full \ + "" \ + $project_html - if {![exists_and_not_null estimated_hours_work_max($i)]} { - set estimated_hours_work_max($i) $estimated_hours_work($i) - } - - - if {![exists_and_not_null end_date_$i]} { - 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) - set p_end_date [set end_date_$i] - set p_dep_type $dependency_type($i) - set p_parent_task_id $dependency_task_id($i) - set p_skip_p $skip_task_p($i) - - # we don't do anything for the comments field, because they - # are not added in for new tasks. - - # ns_log Notice "end date: $p_end_date" - - # add in the new task - - if {[string equal $p_skip_p "f"]} { - set this_revision_id [pm::task::new \ - -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 \ - -estimated_hours_work_min $p_work_min \ - -estimated_hours_work_max $p_work_max \ - -creation_user $user_id \ - -creation_ip $peeraddr \ - -package_id $package_id] - - 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]} { - - # if the p_parent_task_id contains num at the beginning, then - # the task is supposed to depend on other tasks that - # are currently being created. We have to wait until - # the tasks have been created - if {[regexp {num.*} $p_parent_task_id]} { - regexp {num(.*)} $p_parent_task_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 - pm::task::dependency_add \ - -task_item_id $this_task_id \ - -parent_id $p_parent_task_id \ - -dependency_type $p_dep_type \ - -project_item_id $p_project_item_id - } - } - - lappend process_task_id $process_task_ids($i) - lappend revisions $this_revision_id - lappend task_id $this_task_id - } + incr number } - 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 +} else { - foreach dep_task $parent_new_task { + # --- + # NEW + # --- - set this_task_id $dependent_task_id($dep_task) - if {[info exists dependent_task_id($dep_parent($dep_task))]} { - set parent_task_id $dependent_task_id($dep_parent($dep_task)) - set p_dep_type $dep_type($dep_task) +set today_date [db_string today "select to_date(sysdate,'YYYY-MM-DD') from dual"] + # set end_date_html [pm::task::date_html] - pm::task::dependency_add \ - -task_item_id $this_task_id \ - -parent_id $parent_task_id \ - -dependency_type $p_dep_type \ - -project_item_id $p_project_item_id - } + for {set i 1} {$i <= $new_tasks} {incr i} { + set end_date_html "
y-m-d " - } + set assignee_html [pm::task::assignee_html \ + -number $i] - } + set dependency_options_full [pm::task::options_list_html \ + -edit_p $edit_p \ + -project_item_id $project_item_id \ + -number $new_tasks \ + -current_number $i] -} -edit_data { + set project_html "" - set timestamp_ansi [db_string get_today " - SELECT - to_char(current_date, 'YYYY-MM-DD')"] + # sorry this isn't internationalized. The choice is to cludge + # around dates, or to cludge around ad_forms poor support for + # multiple dates. - # -------------------------------------------------------------- - # each task we edit returns a task_revision_id - # -------------------------------------------------------------- + template::multirow append tasks \ + "" \ + "" \ + "" \ + "" \ + "text/plain" \ + 0 \ + 0 \ + 0 \ + 0 \ + 0 \ + 0 \ + 0 \ + $end_date_html \ + "" \ + $assignee_html \ + $dependency_options_full \ + "" \ + $project_html \ + 0 - for {set i 1} {$i <= $number} {incr i} { - - if {![exists_and_not_null end_date_$i]} { - set end_date_$i "{} {} {} {} {} {}" - } - - if {![exists_and_not_null estimated_hours_work($i)]} { - set estimated_hours_work($i) [expr .5 * ($estimated_hours_work_max($i) - $estimated_hours_work_min($i)) + $estimated_hours_work_min($i)] - } - - if {![exists_and_not_null estimated_hours_work_min($i)]} { - set estimated_hours_work_min($i) $estimated_hours_work($i) - } - - if {![exists_and_not_null estimated_hours_work_max($i)]} { - set estimated_hours_work_max($i) $estimated_hours_work($i) - } - - # 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) - set p_mime_type $description_format($i) - - set p_comment $comment($i) - set p_comment_type $comment_format($i) - - set p_percent $percent_complete($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_parent_task_id $dependency_task_id($i) - - set p_new_hours $new_hours_logged($i) - set p_new_description $new_description_logged($i) - - if {![empty_string_p $p_new_hours] && \ - $p_new_hours > 0} { - - set logger_project [pm::project::get_logger_project \ - -project_item_id $p_project_item_id] - set variable_id [logger::variable::get_default_variable_id] - - # add in the new log entry - set p_hours [pm::project::log_hours \ - -logger_project_id $logger_project \ - -variable_id $variable_id \ - -value $p_new_hours \ - -description $p_new_description \ - -timestamp_ansi $timestamp_ansi \ - -task_item_id $p_task_item_id \ - -project_item_id $p_project_item_id \ - -update_status_p f] - - if {[string equal p_hours -1]} { - ns_log Error "Error in logging hours in task-add-edit" - set p_hours 0 - } - } else { - set p_hours [pm::task::update_hours \ - -task_item_id $p_task_item_id \ - -update_tasks_p f] - } - - # do the actual edit - set this_revision_id [pm::task::edit \ - -task_item_id $p_task_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 \ - -estimated_hours_work_min $p_work_min \ - -estimated_hours_work_max $p_work_max \ - -actual_hours_worked $p_hours \ - -update_user $user_id \ - -update_ip $peeraddr \ - -package_id $package_id] - - - lappend revisions $this_revision_id - - pm::task::dependency_delete_all \ - -task_item_id $p_task_item_id - - if {![empty_string_p $p_parent_task_id]} { - - pm::task::dependency_add \ - -task_item_id $p_task_item_id \ - -parent_id $p_parent_task_id \ - -dependency_type jfdsafesa\ - -project_item_id $p_project_item_id - } - - # add in general comments for the task - - if {![empty_string_p $p_comment]} { - - pm::util::general_comment_add \ - -object_id $p_task_item_id \ - -title "$p_task_title" \ - -comment "$p_comment" \ - -mime_type "$p_comment_type" \ - -user_id $user_id \ - -peeraddr $peeraddr \ - -send_email_p "f" - - } - } +} -} -after_submit { - ad_returnredirect -message "Task(s) saved. Now choose assignees" "task-assign-add-edit?[export_vars -url {comment_list edit_p return_url process_task_id:multiple revisions:multiple task_id:multiple old_description send_email_p}]" - # 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 - - } - - ad_script_abort - -} - +set export_vars [export_vars -form {edit_p using_process_p return_url}]