- Methods: All Methods Documented Methods Hide Methods
- Source: Display Source Hide Source
- Variables: Show Variables Hide Variables
Class ::xowf::WorkflowPage
::xowf::WorkflowPage create ...
Defined in
Class Relations
::xotcl::Class create ::xowf::WorkflowPage \ -superclass ::xotcl::ObjectMethods (to be applied on instances)
answer_is_correct (scripted, public)
<instance of xowf::WorkflowPage> answer_is_correctCheck, if answer is correct based on "answer" and "correct_when" attributes of form fields and provided user input.
- Testcases:
- No testcase defined.
set correct 0 :log "WorkflowPage(${:name}).answer_is_correct autocorrect '[:get_from_template auto_correct]' -- [string is true -strict [:get_from_template auto_correct]]" if {[string is true -strict [:get_from_template auto_correct]]} { :log "==== answer_is_correct '[:instantiated_form_fields]'" foreach f [:instantiated_form_fields] { #:log [$f serialize] #:log "checking correctness [$f name] [$f info class] answer?[$f exists value] correct_when ?[$f exists correct_when]" if {[$f exists value]} { set r [$f answer_is_correct] #:log [$f serialize] if {$r != 1} { #:log [$f serialize] #:log "checking correctness [$f name] failed ([$f answer_is_correct])" set correct -1 break } set correct 1 } } } return $correctcall_action (scripted, public)
<instance of xowf::WorkflowPage> call_action [ -action action ] \ [ -attributes attributes ]Call the specified action in the current workflow instance. The specified attributes are provided like form_parameters to the action of the workflow.
- Switches:
- -action (optional)
- -attributes (optional)
- Testcases:
- No testcase defined.
if {![:is_wf_instance]} { error "Page [self] is not a Workflow Instance" } set actionObj [:get_action_obj -action $action] return [$actionObj invoke -attributes $attributes]call_action_foreach (scripted, public)
<instance of xowf::WorkflowPage> call_action_foreach \ -action action [ -attributes attributes ] page_namesCall the specified action for each of the specified pages denoted by the list of page names
- Switches:
- -action (required)
- -attributes (optional)
- Parameters:
- page_names (required)
- Testcases:
- No testcase defined.
foreach page_name $page_names { set page [${:package_id} get_page_from_name -parent_id [:parent_id] -name $page_name] if {$page ne ""} { $page call_action -action $action -attributes $attributes } else { ns_log notice "WF: could not call action $action, since $page_name in [:parent_id] failed" } }childpage (scripted, public)
<instance of xowf::WorkflowPage> childpage -name name \ [ -form form ]Return the child page of the current object with the provided name. In case the child object does not exist, create it as an instance of the provided form.
- Switches:
- -name (required)
- -form (optional)
- Returns:
- page object
- Testcases:
- create_test_items
if {[info exists form]} { set child_page_id [::${:package_id} lookup -use_package_path false -default_lang en -name $name -parent_id ${:item_id}] if {$child_page_id == 0} { ns_log notice "child page '$name' does not exist" set form_obj [::${:package_id} instantiate_forms -default_lang "en" -forms $form] if {[llength $form_obj] == 0} { error "childpage: cannot instantiate $form" } set p [$form_obj create_form_page_instance -name $name -nls_language en_US -parent_id ${:item_id} -package_id ${:package_id} -instance_attributes {}] $p save_new } else { #ns_log notice "child page '$name' exists already (item_id $child_page_id)" set p [::xo::db::CrClass get_instance_from_db -item_id $child_page_id] } return $p } else { error "cannot create '$name': API supports so far only form pages" }footer (scripted, public)
<instance of xowf::WorkflowPage> footerProvide a tailored footer for workflow definition pages and workflow instance pages containing controls for instantiating forms or providing links to the workflow definition.
- Testcases:
- create_workflow_with_instance
if {[info exists :__no_form_page_footer]} { next } else { set parent_id [:parent_id] set form_item_id ${:page_template} #:msg "is wf page [:is_wf], is wf instance page [:is_wf_instance]" if {[:is_wf]} { # # page containing a work flow definition # #set ctx [::xowf::Context require [self]] set work_flow_form [::xo::db::CrClass get_instance_from_db -item_id $form_item_id] set work_flow_base [$work_flow_form pretty_link] set wf [self] set wf_base [$wf pretty_link] set button_objs [list] # create new workflow instance button with start form #if {[:parent_id] != [::${:package_id} folder_id]} { # set parent_id [:parent_id] #} set link [::${:package_id} make_link -link $wf_base $wf create-new parent_id return_url] lappend button_objs [::xowiki::includelet::form-menu-button-new new -volatile -parent_id $parent_id -form $wf -link $link] # list workflow instances button set obj [::xowiki::includelet::form-menu-button-wf-instances new -volatile -package_id ${:package_id} -parent_id $parent_id -base $wf_base -form $wf] if {[info exists return_url]} { $obj return_url $return_url } lappend button_objs $obj # work flow definition button set obj [::xowiki::includelet::form-menu-button-form new -volatile -package_id ${:package_id} -parent_id $parent_id -base $work_flow_base -form $work_flow_form] if {[info exists return_url]} {$obj return_url $return_url} lappend button_objs $obj # make menu return [:include [list form-menu -form_item_id ${:item_id} -button_objs $button_objs]] } elseif {[:is_wf_instance]} { # # work flow instance # set entry_form_item_id [:wf_property wf_form_id] set work_flow_form [::xo::db::CrClass get_instance_from_db -item_id $form_item_id] set work_flow_base [$work_flow_form pretty_link] set button_objs [list] #:msg entry_form_item_id=$entry_form_item_id-exists?=[nsf::is object $entry_form_item_id] # form definition button if {![nsf::is object $entry_form_item_id]} { # In case, the id is a form object, it is a dynamic form, # that we can't edit; therefore, we provide no link. # # Here, we have an id that we use for fetching... # set form [::xo::db::CrClass get_instance_from_db -item_id $entry_form_item_id] set base [$form pretty_link] set obj [::xowiki::includelet::form-menu-button-form new -volatile -package_id ${:package_id} -parent_id $parent_id -base $base -form $form] if {[info exists return_url]} { $obj return_url $return_url } lappend button_objs $obj } # # work flow definition button # set obj [::xowiki::includelet::form-menu-button-wf new -volatile -package_id ${:package_id} -parent_id $parent_id -base $work_flow_base -form $work_flow_form] if {[info exists return_url]} {$obj return_url $return_url} lappend button_objs $obj # make menu return [:include [list form-menu -form_item_id ${:page_template} -button_objs $button_objs]] } else { next } }get_action_obj (scripted, public)
<instance of xowf::WorkflowPage> get_action_obj -action actionCheck if the action can be executed in the current state, and if so, return the action_obj.
- Switches:
- -action (required)
- Testcases:
- create_workflow_with_instance
set ctx [::xowf::Context require [self]] # # First try to call the action in the current state # foreach a [$ctx get_actions] { if {[namespace tail $a] eq "$action"} { # In the current state, the specified action is allowed :log "--xowf action $action allowed -- name='${:name}'" return $a } } # # Some actions are state-safe, these can be called in every state # set actionObj [$ctx wf_definition_object $action] if {[nsf::is object $actionObj] && [$actionObj state_safe]} { # The action is defined as state-safe, so if can be called in every state :log "--xowf action $action state_safe -- name='${:name}'" return $actionObj } error "No state-safe action '$action' available in workflow instance [self] of [${:page_template} name] in state [$ctx get_current_state]\n Available actions: [[$ctx current_state] get_actions]"get_revision_sets (scripted, public)
<instance of xowf::WorkflowPage> get_revision_sets \ [ -with_instance_attributes ]Return a list of ns_sets containing revision_id, creation_date, creation_user, creation_ip, and state for the current workflow instance.
- Switches:
- -with_instance_attributes (optional)
- Testcases:
- create_test_items
set item_id ${:item_id} if {$with_instance_attributes} { set revision_sets [::xo::dc sets -prepare integer wf_revisions { SELECT revision_id, creation_date, last_modified, creation_user, creation_ip, state, assignee, instance_attributes FROM cr_revisions cr, acs_objects o, xowiki_form_page x, xowiki_page_instance pi WHERE cr.item_id = :item_id AND o.object_id = cr.revision_id AND x.xowiki_form_page_id = cr.revision_id AND pi.page_instance_id = cr.revision_id ORDER BY cr.revision_id ASC }] } else { set revision_sets [::xo::dc sets -prepare integer wf_revisions { SELECT revision_id, creation_date, last_modified, creation_user, creation_ip, state, assignee FROM cr_revisions cr, acs_objects o, xowiki_form_page x WHERE cr.item_id = :item_id AND o.object_id = cr.revision_id AND x.xowiki_form_page_id = cr.revision_id ORDER BY cr.revision_id ASC }] } return $revision_setsis_wf (scripted, public)
<instance of xowf::WorkflowPage> is_wfCheck, if the current page is a workflow page (page, defining a workflow)
- Testcases:
- create_test_items, create_workflow_with_instance
if {[info exists :__wf(workflow_definition)]} { return 1 } elseif {[:property workflow_definition] ne ""} { array set :__wf ${:instance_attributes} return 1 } else { return 0 }is_wf_instance (scripted, public)
<instance of xowf::WorkflowPage> is_wf_instanceCheck, if the current page is a workflow instance (page, referring to a workflow)
- Testcases:
- create_test_items, create_workflow_with_instance
if {[array exists :__wfi]} { return 1 } # # We cannot call get_template_object here, because this will lead # to a recursive loop. # if {![nsf::is object ::${:page_template}]} { ::xo::db::CrClass get_instance_from_db -item_id ${:page_template} } if {${:state} ne "" && [${:page_template} hasclass ::xowf::WorkflowPage] && [${:page_template} is_wf] } { array set :__wfi [${:page_template} instance_attributes] return 1 } return 0post_process_dom_tree (scripted, public)
<instance of xowf::WorkflowPage> post_process_dom_tree dom_doc \ dom_root form_fieldspost-process form in edit mode to provide feedback in feedback mode
- Parameters:
- dom_doc (required)
- dom_root (required)
- form_fields (required)
- Testcases:
- create_workflow_with_instance
# In feedback mode, we set the CSS class to correct or incorrect if {[info exists :__feedback_mode]} { unset :__feedback_mode ::xo::Page requireCSS /resources/xowf/feedback.css set form [lindex [$dom_root selectNodes "//form"] 0] $form setAttribute class "[$form getAttribute class] feedback" # # In cases, where the HTML exercise was given, we process the HTML # to flag the result. # # TODO: What should we do with the feedback. "util_user_message" is # not optimal... # foreach f $form_fields { if {[$f exists __rendered]} continue if {[$f exists evaluated_answer_result]} { set result [$f set evaluated_answer_result] foreach n [$dom_root selectNodes "//form//*\[@name='[$f name]'\]"] { set oldCSSClass [expr {[$n hasAttribute class] ? [$n getAttribute class] : ""}] $n setAttribute class [string trim "$oldCSSClass [$f form_widget_CSSclass]"] $f form_widget_CSSclass $result set helpText [$f help_text] if {$helpText ne ""} { #set divNode [$dom_doc createElement div] #$divNode setAttribute class [$f form_widget_CSSclass] #$divNode appendChild [$dom_doc createTextNode $helpText] #[$n parentNode] insertBefore $divNode [$n nextSibling] #set spanNode [$dom_doc createElement span] #$spanNode setAttribute class "glyphicon glyphicon-ok [$f form_widget_CSSclass]" #[$n parentNode] insertBefore $spanNode [$n nextSibling] set parentNode [$n parentNode] set oldClass [$parentNode getAttribute class ""] $parentNode setAttribute class "selection [$f form_widget_CSSclass]" $parentNode setAttribute title $helpText #util_user_message -message "field [$f name], value [$f value]: $helpText" } } } } # # Provide feedback for the whole exercise. # if {[:answer_is_correct]} { set feedback [:get_from_template feedback_correct] } else { set feedback [:get_from_template feedback_incorrect] } if {$feedback ne ""} { $dom_root appendFromScript { html::div -class feedback { html::t -disableOutputEscaping $feedback } } } }post_process_form_fields (scripted, public)
<instance of xowf::WorkflowPage> post_process_form_fields \ form_fieldsPropagate the feedback mode setting of this workflow page to the supplied formfields.
- Parameters:
- form_fields (required)
- Testcases:
- create_workflow_with_instance
#:log ------------------post_process_form_fields-feedback_mode=[info exists :__feedback_mode] if {[info exists :__feedback_mode]} { # # Provide feedback for every alternative # foreach f $form_fields { $f set_feedback ${:__feedback_mode} } } #:log ------------------post_process_form_fields-feedback_mode=[info exists :__feedback_mode]-DONErender_form_action_buttons (scripted, public)
<instance of xowf::WorkflowPage> render_form_action_buttons \ [ -formfieldButtonClass formfieldButtonClass ] \ [ -CSSclass CSSclass ]Render the defined actions in the current state with submit buttons
- Switches:
- -formfieldButtonClass (optional, defaults to
"::xowiki::formfield::submit_button"
)- -CSSclass (optional)
- Testcases:
- create_workflow_with_instance
if {[:is_wf_instance]} { set ctx [::xowf::Context require [self]] set buttons {} foreach action [$ctx get_actions] { set success 0 foreach role [$action roles] { set success [:check_role $role] if {$success} break } if {$success} { set f [$formfieldButtonClass new -name __action_[namespace tail $action] -form_button_wrapper_CSSclass [$action wrapper_CSSclass] -label_noquote [$action label_noquote] -CSSclass $CSSclass -destroy_on_cleanup ] if {[$action extra_css_class] ne ""} { #$f append form_button_CSSclass " " [$action extra_css_class] $f form_button_CSSclass "" $f CSSclass_list_add form_button_CSSclass [$action extra_css_class] } $f CSSclass_list_add form_button_CSSclass prevent-double-click #ns_log notice "RENDER BUTTON has CSSclass [$f CSSclass] // [$f form_button_CSSclass]" if {[$action exists title]} { $f title [$action title] } $f value [$action label] lappend buttons $f } } # # Render the button widgets. # :render_form_action_buttons_widgets -CSSclass $CSSclass $buttons } else { next }render_form_action_buttons_widgets (scripted, public)
<instance of xowf::WorkflowPage> render_form_action_buttons_widgets \ [ -CSSclass CSSclass ] buttonsWith the given set of buttons, produce the HTML for the button container and the included inputs.
- Switches:
- -CSSclass (optional)
- Parameters:
- buttons (required)
- Testcases:
- create_workflow_with_instance
if {[llength $buttons] > 0} { # # Build button groups based on "form_button_wrapper_CSSclass". # set previous_wrapper_class "NONE" set wrapper_groups {} set group_num 0 foreach f $buttons { set wrapper_class [$f form_button_wrapper_CSSclass] if {$wrapper_class eq $previous_wrapper_class} { dict lappend wrapper_groups [list $wrapper_class $group_num] $f continue } incr group_num dict lappend wrapper_groups [list $wrapper_class $group_num] $f set previous_wrapper_class $wrapper_class } foreach wrapper_group [dict keys $wrapper_groups] { ::html::div -class [lindex $wrapper_group 0] { foreach f [dict get $wrapper_groups $wrapper_group] { $f render_input } } } }render_icon (scripted, public)
<instance of xowf::WorkflowPage> render_iconProvide an icon or text for describing the kind of application.
- Testcases:
- create_workflow_with_instance
if {[:info procs render_icon] ne ""} { # # In case, we have a per-object method (i.e., defined via the # workflow), use this with highest precedence. # next } elseif {[:is_wf_instance]} { set page_template ${:page_template} set title [::$page_template title] regsub {[.]wf$} $title "" title return [list text $title is_richtext false] } elseif {[:is_wf]} { return [list text "Workflow" is_richtext false] } else { next }render_thumbnails (scripted, public)
<instance of xowf::WorkflowPage> render_thumbnails upload_infoRenderer of the thumbnail file(s)
- Parameters:
- upload_info (required)
- dict containing the "file_object" and "file_name"
- Returns:
- HTML content
- Testcases:
- No testcase defined.
dict with upload_info { set parent_id ${:item_id} set feedbackFiles [xo::dc list_of_lists . { select item_id, name from cr_items where parent_id = :parent_id }] if {[regexp {^([^/]+)/} $file_name . qn]} { set HTML [:QM render_feedback_files -question_name $qn -feedbackFiles $feedbackFiles] } else { set HTML "$file_name created" } } return $HTMLschedule_action (scripted, public)
<instance of xowf::WorkflowPage> schedule_action -time time \ [ -party_id party_id ] -action action [ -attributes attributes ]Schedule the specified action for the current workflow instance at the given time. The specified attributes are provided like form_parameters to the action of the workflow.
- Switches:
- -time (required)
- time when the atjob should be executed
- -party_id (optional)
- party_id for the user executing the atjob
- -action (required)
- workflow action to be executed
- -attributes (optional)
- arguments provided to the workflow action (attribute value pairs)
- Testcases:
- No testcase defined.
if {![:is_wf_instance]} { error "Page [self] is not a Workflow Instance" } if {![info exists party_id]} { set party_id [::xo::cc user_id] } :schedule_job -time $time -party_id $party_id [list call_action -action $action -attributes $attributes]schedule_job (scripted, public)
<instance of xowf::WorkflowPage> schedule_job -time time \ [ -party_id party_id ] cmdSchedule the specified Tcl command for the current package instance at the given time.
- Switches:
- -time (required)
- -party_id (optional)
- Parameters:
- cmd (required)
- Testcases:
- No testcase defined.
:log "-at $time" set j [::xowf::atjob new -time $time -party_id $party_id -cmd $cmd -url [:pretty_link] -object [self]] $j persistsolution_set (scripted, public)
<instance of xowf::WorkflowPage> solution_setCompute solution set in form of attribute=value pairs based on "answer" attribute of form fields.
- Testcases:
- No testcase defined.
set solutions [list] foreach f [:instantiated_form_fields] { if {![$f exists answer]} continue lappend solutions [$f name]=[$f answer] } return [join [lsort $solutions] ", "]stats_record_count (scripted, public)
<instance of xowf::WorkflowPage> stats_record_count nameRecord that the specified question was used.
- Parameters:
- name (required)
- Testcases:
- create_test_items
dict incr :__stats_count $namestats_record_detail (scripted, public)
<instance of xowf::WorkflowPage> stats_record_detail \ [ -label label ] [ -value value ] [ -name name ] \ [ -correctly_answered on|off ]Record the stat detail of the question.
- Switches:
- -label (optional)
- -value (optional)
- -name (optional)
- -correctly_answered (optional, boolean)
- Testcases:
- create_test_items
dict set :__stats_label $name label $value $label if {[info exists :__stats_success] && [dict exists ${:__stats_success} $name $value]} { set details [dict get ${:__stats_success} $name $value] } else { set details "" } dict incr details $correctly_answered dict set :__stats_success $name $value $detailswf_context (scripted, public)
<instance of xowf::WorkflowPage> wf_context [ ctx ]Return for a workflow page the workflow context object. The same function can be used as well for setting the workflow context at the first places (e.g. on initialization of the wf-context).
- Parameters:
- ctx (optional)
- Testcases:
- create_workflow_with_instance
if {$ctx ne ""} { set :_wf_context $ctx } return ${:_wf_context}www-edit (scripted, public)
<instance of xowf::WorkflowPage> www-edit args [ args... ]Hook for editing workflow pages
- Parameters:
- args (required)
- Testcases:
- create_workflow_with_instance
if {[:is_wf_instance]} { set ctx [::xowf::Context require [self]] set s [$ctx current_state] :include_header_info -css [$s extra_css] -js [$s extra_js] } nextwww-view (scripted, public)
<instance of xowf::WorkflowPage> www-view [ content ]Provide additional view modes: - edit: instead of viewing a page, it is opened in edit mode - view_user_input: show user the provided input - view_user_input_with_feedback: show user the provided input with feedback
- Parameters:
- content (optional)
- Testcases:
- create_test_items, create_workflow_with_instance
# The edit method calls view with an HTML content as argument. # To avoid a loop, when "view" is redirected to "edit", # we make sure that we only check the redirect on views # without content. #:msg "view [self args] [:is_wf_instance]" if {[:is_wf_instance] && $content eq ""} { set ctx [::xowf::Context require [self]] set method [$ctx get_view_method] set s [$ctx current_state] :include_header_info -css [$s extra_css] -js [$s extra_js] if {$method ne "" && $method ne "view"} { #:msg "view redirects to $method in state [$ctx get_current_state]" switch -- $method { view_user_input { #:msg "calling edit with disable_input_fields=1" return [:www-edit -disable_input_fields 1] } view_user_input_with_feedback { set :__feedback_mode 1 #:msg "calling edit with disable_input_fields=1" return [:www-edit -disable_input_fields 1] } default { #:msg "calling $method" return [::${:package_id} invoke -method $method] } } } } next
- Methods: All Methods Documented Methods Hide Methods
- Source: Display Source Hide Source
- Variables: Show Variables Hide Variables