Index: openacs-4/packages/acs-templating/tcl/filter-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/filter-procs.tcl,v diff -u -r1.8 -r1.9 --- openacs-4/packages/acs-templating/tcl/filter-procs.tcl 22 Sep 2003 18:44:11 -0000 1.8 +++ openacs-4/packages/acs-templating/tcl/filter-procs.tcl 30 Sep 2003 11:56:42 -0000 1.9 @@ -9,16 +9,31 @@ # License. Full text of the license is available from the GNU Project: # http://www.fsf.org/copyleft/gpl.html -ad_proc -public template::forward { url } { +ad_proc -public template::forward { url args} { Redirect and abort processing + + if "template::forward your_url t" is used. The url will be cached + + @see ad_cache_returnredirect + } { # DRB: The code that was here before didn't preserve the protocol, always # using HTTP even if HTTPS was used to establish the connection. Besides # which ad_returnredirect has funky checks for even funkier browsers, and # is therefore not only the standard way to redirect in OpenACS 4 but # more robust as well. - ad_returnredirect $url + set cache_p [lindex $args 0] + + if { [string equal $cache_p "t"] } { + set persistent_p [lindex $args 1] + set excluded_vars [lindex $args 2] + + ad_cache_returnredirect $url $persistent_p $excluded_vars + } else { + ad_returnredirect $url + } + ad_script_abort } Index: openacs-4/packages/acs-templating/tcl/wizard-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/wizard-procs.tcl,v diff -u -r1.3 -r1.4 --- openacs-4/packages/acs-templating/tcl/wizard-procs.tcl 1 Sep 2002 02:24:57 -0000 1.3 +++ openacs-4/packages/acs-templating/tcl/wizard-procs.tcl 30 Sep 2003 11:56:42 -0000 1.4 @@ -2,300 +2,623 @@ # Copyright (C) 1999-2000 ArsDigita Corporation # Authors: Karl Goldstein (karlg@arsdigita.com) +# heavily modified by Jun Yamog on June 2003 -# $Id$ +# wizard-procs.tcl,v 1.1.2.1 2001/01/04 20:14:57 brech Exp # This is free software distributed under the terms of the GNU Public # License. Full text of the license is available from the GNU Project: # http://www.fsf.org/copyleft/gpl.html ad_proc -public template::wizard { command args } { - - eval wizard::$command $args + alias proc to call the real template::wizard::proc +} { + eval wizard::$command $args } +# create a wizard from a set of steps -ad_proc -public template::wizard::create { args } { - create a wizard from a set of steps +ad_proc -public template::wizard::create { args } { +
example: + template::wizard create -action "wizard" -name my_wizard -params { + my_param1 my_param2 + } -steps { + 1 -label "Step 1" -url "step1" + 2 -label "Step 2" -url "step2" + 3 -label "Step 3" -url "step3" + } ++
Get a wizard's param value
++ "template::wizard get_param" has the advantage over ad_page_contract of getting the + param value during the response time. What does this mean? It will properly + get the current value of the param which was set by "template::wizard set_param", + while ad_page_contract will not pick that up since it will get what is the request + http var value. This is because "template::wizard get_param" gets the value + from the tcl var while ad_page_contract gets the value from the http var. + So while processing in tcl that value may change. +
} { - set level [template::adp_level] + set level [template::adp_level] - upvar #$level wizard:params params + upvar #$level wizard:params params - set params($name) $value + if { [info exists params($name)] } { + set value $params($name) + } else { + set value [ns_queryget $name] + } + return $value + } -ad_proc -public template::wizard::add { step_id args } { - Append a step to a wizard +ad_proc -public template::wizard::set_param { name value } { +Set a wizard's param for passthrough
+ +Normally you place this in the steps of the wizard where the + form has been processed. A param + is normally used when you want to reuse a value across the steps.
+ +Note: if you are to use "template::wizard set_param" on a wizard file ex. + (wizard.tcl). Make sure to do it before "template::wizard get_current_step". + So when "template::wizard get_current_step" redirects it will properly set + the correct values of the param to the new value.
} { - get_reference + set level [template::adp_level] - lappend steps $step_id + upvar #$level wizard:params params + set params($name) $value - # add the reference to the steps lookup array for the wizard - upvar #$level wizard:$step_id opts wizard:rowcount rowcount - incr rowcount - set opts(id) $step_id - set opts(rownum) $rowcount - set opts(link) [get_forward_url $opts(id)] +} - # copy the reference for access as a multirow data source as well - upvar #$level wizard:$rowcount props - template::util::get_opts $args +ad_proc -public template::wizard::set_finish_url { finish_url } { +if the finish url is set, when a the finish button is pressed + it will redirect to this url
+} { + get_reference + set wizard_finish_url $finish_url - array set props [array get opts] } +ad_proc -private template::wizard::add { step_id args } { + Append a step to a wizard +} { + get_reference + + lappend steps $step_id + + # add the reference to the steps lookup array for the wizard + upvar #$level wizard:$step_id opts wizard:rowcount rowcount + incr rowcount + set opts(id) $step_id + set opts(rownum) $rowcount + set opts(link) [get_forward_url $opts(id)] + + # copy the reference for access as a multirow data source as well + upvar #$level wizard:$rowcount props + + template::util::get_opts $args + + array set props [array get opts] +} + + ad_proc -public template::wizard::get_current_step {} { - Set the step to display for this particular request This is +Set the step to display for this particular request This is determined by the wizard_step parameter. If not set, the first step - is used. + is used.
+ +Make sure that you call any "template::wizard set_param" if needed before + calling get_current_step. get_current_step will redirect to the wizard -action + properly setting all -params value and its other needed http state vars
+ +The wizard will rewrite the url always. Only self submitting forms + are preserved. Once the form is finished processing the wizard will take + over and rewrite the url.
} { + get_reference - get_reference + upvar #$level wizard:current_id current_id + set current_id [ns_queryget wizard_step${wizard_name} [lindex $steps 0]] - upvar #$level wizard:current_id current_id - set current_id [ns_queryget wizard_step [lindex $steps 0]] + upvar #$level wizard:visited_step visited_step + set visited_step [get_visited_step] - # get a reference to the step - upvar #$level wizard:$current_id step + # if there is no step state, we are likely in the first step. + # lets redirect with the proper state vars + if {[string equal [ns_queryget wizard_step${wizard_name}] ""]} { + template::forward [get_forward_url $current_id] + } - upvar #$level wizard:current_url current_url + # get a reference to the step + upvar #$level wizard:$current_id step - set current_url $step(url) + upvar #$level wizard:current_url current_url - # check for a "back" submission and forward immediately if so - - if { [ns_queryexists wizard_submit_back] } { + # lets see if this step exists, if not we are finished with wizard and pass the steps + if [info exists step(url)] { + set current_url $step(url) + } else { + # if we have set_finish_url then we redirect to that url when we are finished + # otherwise increment the parent wizard step + if {[info exists wizard_finish_url]} { + template::forward $wizard_finish_url + } else { - set last_index [expr [lsearch -exact $steps $current_id] - 1] - set last_id [lindex $steps $last_index] - template::forward [get_forward_url $last_id] - } + # lets set the current wizard name to the parent wizard + set parent_wizard [lindex $wizards 0] + set wizard_name $parent_wizard + + # lets now increment step of the parent wizard + set parent_step [expr [ns_queryget wizard_step${parent_wizard}] + 1] + template::forward [get_forward_url $parent_step] + } + + } + + # check for a "back" submission and forward immediately if so + # also check if we are backing up the current wizard or another wizard + + if { [ns_queryexists wizard_submit_back] && [string equal $wizard_name [ns_queryget wizard_name]]} { + + set last_index [expr [lsearch -exact $steps $current_id] - 1] + set last_id [lindex $steps $last_index] + template::forward [get_forward_url $last_id] + } } -ad_proc -public template::wizard::current_step {} { +ad_proc -private template::wizard::current_step {} { + convinience method to get the step for the http params or from the + wizard step definition +} { - get_reference + get_reference - return [ns_queryget wizard_step [lindex $steps 0]] + return [ns_queryget wizard_step${wizard_name} [lindex $steps 0]] } + +ad_proc -public template::wizard::get_visited_step {} { + get the last visited step +} { + + get_reference + + # lets create the visited steps for the current + # lets see if the current step is greater what we have visited + # otherwise we keep the current value + set last_visitedstep [get_param wizard_visitedstep${wizard_name}] + set current_step [current_step] + if { ($last_visitedstep < $current_step) || [string equal $last_visitedstep ""] } { + return $current_step + } else { + return $last_visitedstep + } + +} + +ad_proc -public template::wizard::set_visited_step {step_id} { + set the last visited step +} { + + get_reference + set_param wizard_visitedstep${wizard_name} $step_id +} + + +ad_proc -public template::wizard::get_current_name {} { + get the current wizard name +} { + + get_reference + + return $wizard_name +} + + +ad_proc -private template::wizard::get_wizards_levels {} { + internal helper proc to get the different levels of wizards + from current to parent +} { + variable parse_level + set level [expr $parse_level - 1] + + set levels {} + for {set i $level} {$i > 1} {set i [expr $i - 1]} { + upvar #$i wizard:name parent_wizard + if [info exists parent_wizard] { + lappend levels $i + } else { + break + } + } + + return $levels + +} + + +ad_proc -private template::wizard::get_wizards {} { + we will get all the wizards that we have passed through +} { + + set wizards {} + set levels [get_wizards_levels] + + foreach i $levels { + upvar #$i wizard:name parent_wizard + if [info exists parent_wizard] { + lappend wizards $parent_wizard + } + } + + return $wizards +} + + ad_proc -public template::wizard::submit { form_id args } { - Add the appropriate buttons to the submit wizard +Add the appropriate buttons to the submit wizard Also create a list of all the buttons The optional -buttons parameter is a list of name-value pairs, in form {name label} {name label...} - The valid button names are back, next, repeat, finish + The valid button names are back, next, repeat, finish
+ +Also writes the params to the form as hidden elements to keep the + state of the wizard.
+ +The following values are acceptable for the buttons: back, next and finish. + Back buttons are not rendered if the step is the first step, like wise next + buttons are not displayed if its the last step. Finish can appear on any step + and will finish the current wizard even if not all steps are done.
+ } { - variable default_button_labels + variable default_button_labels - get_reference - upvar 2 wizard_submit_buttons buttons - set buttons [list] + get_reference + upvar 2 wizard_submit_buttons buttons + set buttons [list] - template::util::get_opts $args - - # Handle the -buttons parameter - if { ![info exists opts(buttons)] } { - upvar 0 default_button_labels button_labels - } else { - foreach pair $opts(buttons) { - # If provided with just a name, use default label - if { [llength $pair] == 1 } { - set button_labels($pair) $default_button_labels($pair) - } else { - set button_labels([lindex $pair 0]) [lindex $pair 1] - } + set param_level [template::adp_level] + upvar #$param_level wizard:params params + + template::util::get_opts $args + + # Handle the -buttons parameter + if { ![info exists opts(buttons)] } { + # jkyamog - is this really correct? when no buttons is present we put all of the buttons? + upvar 0 default_button_labels button_labels + } else { + foreach pair $opts(buttons) { + # If provided with just a name, use default label + if { [llength $pair] == 1 } { + set button_labels($pair) $default_button_labels($pair) + } else { + set button_labels([lindex $pair 0]) [lindex $pair 1] + } + } } - } - set current_id [ns_queryget wizard_step [lindex $steps 0]] + # Add a hidden element for the current wizard name + template::element create $form_id wizard_name -widget hidden -value $wizard_name -datatype keyword - # Add a hidden element with the current ID - template::element create $form_id wizard_step -widget hidden -value $current_id -datatype keyword + set current_id [current_step] - set step_index [expr [lsearch -exact $steps $current_id] + 1] + # Add a hidden element with the current ID + template::element create $form_id wizard_step${wizard_name} -widget hidden -value $current_id -datatype keyword - # If not the first one and it is allowed than add a "Back" button - if { $step_index > 1 && [info exists button_labels(back)] } { - template::element create $form_id wizard_submit_back -widget submit \ - -label $button_labels(back) -optional -datatype text - lappend buttons wizard_submit_back - } + set step_index [expr [lsearch -exact $steps $current_id] + 1] - # If iteration is allowed than add a "Repeat" button - upvar #$level wizard:$current_id step - if { [info exists step(repeat)] && [info exists button_labels(repeat)]} { - template::element create $form_id wizard_submit_repeat -widget submit \ - -label $button_labels(repeat) -optional -datatype text - lappend buttons wizard_submit_repeat - } + # If not the first one and it is allowed than add a "Back" button + if { $step_index > 1 && [info exists button_labels(back)] } { + template::element create $form_id wizard_submit_back -widget submit \ + -label $button_labels(back) -optional -datatype text - # If not the last one than add a "Next" button - if { $step_index < [llength $steps] && [info exists button_labels(next)] } { - template::element create $form_id wizard_submit_next -widget submit \ - -label $button_labels(next) -optional -datatype text - lappend buttons wizard_submit_next - } + lappend buttons wizard_submit_back + } - # Always finish - if { [info exists button_labels(finish) ] } { - template::element create $form_id wizard_submit_finish -widget submit \ - -label $button_labels(finish) -optional -datatype text - lappend buttons wizard_submit_finish - } + # If iteration is allowed than add a "Repeat" button + upvar #$level wizard:$current_id step + if { [info exists step(repeat)] && [info exists button_labels(repeat)]} { + template::element create $form_id wizard_submit_repeat -widget submit \ + -label $button_labels(repeat) -optional -datatype text + lappend buttons wizard_submit_repeat + } - # Create hidden variables for wizard parameters - foreach param $properties(params) { - if { ![template::element::exists $form_id $param] } { - template::element create $form_id $param -widget hidden -datatype text -optional -param + # If not the last one than add a "Next" button + if { $step_index < [llength $steps] && [info exists button_labels(next)] } { + template::element create $form_id wizard_submit_next -widget submit \ + -label $button_labels(next) -optional -datatype text + lappend buttons wizard_submit_next + } + + # Always finish + if { [info exists button_labels(finish) ] } { + template::element create $form_id wizard_submit_finish -widget submit \ + -label $button_labels(finish) -optional -datatype text + lappend buttons wizard_submit_finish } - } + + + # Create hidden variables for wizard parameters + set levels [get_wizards_levels] + lappend levels $level + + foreach onelevel $levels { + upvar #$onelevel wizard:properties properties + foreach param $properties(params) { + if { ![template::element::exists $form_id $param] } { + if { [info exists params($param)] } { + template::element create $form_id $param -widget hidden -datatype text -optional -param -value $params($param) + } else { + template::element create $form_id $param -widget hidden -datatype text -optional -param + } + } + } + + } + + # Create hidden variables for the other wizard steps and visited steps + foreach one_wizard $wizards { + if { ![template::element::exists $form_id wizard_step${one_wizard}] } { + template::element create $form_id wizard_step${one_wizard} -widget hidden \ + -datatype keyword -value [ns_queryget wizard_step${one_wizard}] + } + if { ![template::element::exists $form_id wizard_visitedstep${one_wizard}] } { + template::element create $form_id wizard_visitedstep${one_wizard} -widget hidden \ + -datatype keyword -value [ns_queryget wizard_visitedstep${one_wizard}] + } + } + } -ad_proc -public template::wizard::get_reference {} { +ad_proc -private template::wizard::get_reference {} { Get a reference to the wizard steps (internal helper) } { + + uplevel { - uplevel { + variable parse_level + set level $parse_level - variable parse_level - set level $parse_level - - upvar #$level wizard:steps steps wizard:properties properties - if { ! [info exists steps] } { - error "Wizard does not exist" + upvar #$level wizard:steps steps wizard:properties properties wizard:name wizard_name wizard:wizards wizards wizard:finish_url wizard_finish_url + if { ! [info exists steps] } { + error "Wizard does not exist" + } } - } } + ad_proc -public template::wizard::exists {} { @return 1 if a wizard is currently defined } { + variable parse_level - variable parse_level + if { ![info exists parse_level] } { + return 0 + } - if { ![info exists parse_level] } { - return 0 - } + upvar #$parse_level wizard:steps steps - upvar #$parse_level wizard:steps steps - - return [info exists steps] + return [info exists steps] } -ad_proc -public template::wizard::forward {} { +ad_proc -public template::wizard::forward { {cache_p "f"} {persistent_p "f"} {excluded_vars ""} } { call when a step has been validated and completed. checks which submit button was pressed and proceeds accordingly. } { - get_reference + get_reference - upvar #$level wizard:current_id current_id - set current_index [expr [lsearch -exact $steps $current_id] + 1] + upvar #$level wizard:current_id current_id + set current_index [expr [lsearch -exact $steps $current_id] + 1] - if { [ns_queryexists wizard_submit_next] } { + if { [ns_queryexists wizard_submit_next] } { - # figure out the next step and go there + # figure out the next step and go there - set next_id [lindex $steps $current_index] - template::forward [get_forward_url $next_id] + set next_id [lindex $steps $current_index] + template::forward [get_forward_url $next_id] $cache_p $persistent_p $excluded_vars - } elseif { [ns_queryexists wizard_submit_back] } { + } elseif { [ns_queryexists wizard_submit_back] } { - set last_id [lindex $steps [expr $current_index - 2]] - template::forward [get_forward_url $last_id] + set last_id [lindex $steps [expr $current_index - 2]] + template::forward [get_forward_url $last_id] $cache_p $persistent_p $excluded_vars - } elseif { [ns_queryexists wizard_submit_repeat] } { - - template::forward "[get_forward_url $current_id]&wizard_submit_repeat=t" + } elseif { [ns_queryexists wizard_submit_repeat] } { + + template::forward "[get_forward_url $current_id]&wizard_submit_repeat=t" $cache_p $persistent_p $excluded_vars - } elseif { [ns_queryexists wizard_submit_finish] } { + } elseif { [ns_queryexists wizard_submit_finish] } { - template::forward $properties(action) - } + # template::forward $properties(action) + # NOTE : we are changing the behaviour of wizard, when its finish it will not reset and go back + # to step 1, it will blindly go forward and we will catch this on get_current_step + set next_id [expr $current_index + 1] + template::forward [get_forward_url $next_id] $cache_p $persistent_p $excluded_vars + } } - ad_proc -public template::wizard::get_forward_url { step_id } { Build the redirect URL for the next step } { - variable parse_level - get_reference + variable parse_level + get_reference - set level [template::adp_level] + set level [template::adp_level] - upvar #$level wizard:params params + upvar #$level wizard:params params - set url [ns_conn url]?wizard_step=$step_id + set url [ns_conn url]?wizard_step=$step_id - # check for passthrough parameters + set multiple_listed [list] - if { [info exists properties(params)] } { - foreach param $properties(params) { + # check for passthrough parameters - if { [info exists params($param)] } { - set value $params($param) - } else { - set value [ns_queryget $param] - } - append url "&$param=[ns_urlencode $value]" + if { [info exists properties(params)] } { + foreach param $properties(params) { + upvar #$level $param value + set flags [split [lindex [split $param ":"] 1] ","] + if { [lsearch -exact [split [lindex [split $param ":"] 1] ","] "array"] != -1 || [array exists value] } { + # Array + foreach {index array_value} [array get value] { + if { [info exists array_value] && ![empty_string_p $array_value] } { + append url "&$param.$index=[ns_urlencode $array_value]" + } else { + append url "&$param.$index=" + } + } + } else { + # Normal Variable + if { [lsearch -exact [split [lindex [split $param ":"] 1] ","] "multiple"] != -1 } { + # Multiple + set param [lindex [split $param ":"] 0] + if { [lsearch -exact $multiple_listed $param] == -1 } { + foreach check_param $properties(params) { + if { [string equal [lindex [split $check_param ":"] 0] $param] } { + set value_list [ns_querygetall $param] + for { set i 0 } { $i < [llength $value_list] } { incr i } { + append url "&$param=[ns_urlencode [lindex $value_list $i]]" + } + } + } + lappend multiple_listed $param + } + } else { + # Normal Var + if { [info exists params($param)] } { + append url "&$param=[ns_urlencode $params($param)]" + } else { + append url "&$param=[ns_urlencode [ns_queryget $param]]" + } + } + } + } } - } - return $url + return $url } ad_proc -public template::wizard::get_action_url {} { Retreive the URL to the action } { - get_reference +get_reference - return $properties(action) +return $properties(action) } + + +ad_proc -public template::wizard::load_last_visited_step { + -key:required +} { + loads the last visited step from the db + + @creation-date june 2003 + @author Jun Yamog + + @param key unique identifier for a particular wizard normally the main object_id the wizard + is manipulating + + use this step before get_current_step +} { + + get_reference + + # check the old visited step on the the state manager + set visited_step [ad_get_client_property -default "" $key ${wizard_name}visited] + if {![string equal $visited_step ""]} { + template::wizard::set_visited_step $visited_step + } + +} + + +ad_proc -public template::wizard::save_last_visited_step { + -key:required +} { + saves the last visisted step to the db + + @creation-date june 2003 + @author Jun Yamog + + @param key unique identifier for a particular wizard normally the main object_id the wizard + is manipulating + + use this step after get_current_step +} { + + get_reference + + # save the state of the visited step for this wizard + if { ![string equal $key ""] } { + ad_set_client_property $key ${wizard_name}visited [template::wizard::get_visited_step] + } + +} +