Gustaf Neumann
XoWiki Content Flow - an XoWiki based workflow system implementing state-based behavior of wiki pages and forms
2017-08-06
WU Vienna
BSD-Style
2
-
+
Index: openacs-4/packages/xowf/catalog/xowf.en_US.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/catalog/xowf.en_US.ISO-8859-1.xml,v
diff -u -N -r1.2.2.53 -r1.2.2.54
--- openacs-4/packages/xowf/catalog/xowf.en_US.ISO-8859-1.xml 22 Jun 2021 10:03:37 -0000 1.2.2.53
+++ openacs-4/packages/xowf/catalog/xowf.en_US.ISO-8859-1.xml 14 Jul 2021 17:36:15 -0000 1.2.2.54
@@ -238,4 +238,5 @@
Detailed summary
of
Structure
+ Download all displayed file submissions
Index: openacs-4/packages/xowf/tcl/test-item-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/tcl/test-item-procs.tcl,v
diff -u -N -r1.7.2.149 -r1.7.2.150
--- openacs-4/packages/xowf/tcl/test-item-procs.tcl 6 Jul 2021 09:32:52 -0000 1.7.2.149
+++ openacs-4/packages/xowf/tcl/test-item-procs.tcl 14 Jul 2021 17:36:16 -0000 1.7.2.150
@@ -139,7 +139,7 @@
Class create test_item_name -superclass text \
-extend_slot_default validator name -ad_doc {
Name sanitizer for test items
- }
+ }
test_item_name instproc check=name {value} {
set valid [regexp {^[[:alnum:]:/_-]+$} $value]
if {!$valid} {
@@ -441,7 +441,7 @@
if {[string is true -strict $correct]} {
lappend if_fc "answer=t" "options={{} $input_field_name}"
} else {
- lappend if_fc "answer=f"
+ lappend if_fc "answer=f"
}
if {$value(feedback_correct) ne ""} {
lappend if_fc "feedback_answer_correct=[::xowiki::formfield::FormField fc_encode $value(feedback_correct)]"
@@ -642,8 +642,8 @@
lappend answer [:comp_correct_when_from_value [dict get $value $fieldName.correct_when]]
lappend solution [dict get $value $fieldName.solution]
lappend render_hints [list \
- words [dict get $value $fieldName.options] \
- lines [dict get $value $fieldName.lines]]
+ words [dict get $value $fieldName.options] \
+ lines [dict get $value $fieldName.lines]]
}
dict set fc_dict shuffle_kind [${:parent_field} get_named_sub_component_value shuffle]
@@ -1516,7 +1516,7 @@
set export_dict ""
set user [$submission set creation_user]
if {![info exists ::__running_ids]} {
- set ::__running_ids ""
+ set ::__running_ids ""
}
if {![dict exists $::__running_ids $user]} {
dict set ::__running_ids $user [incr ::__running_id]
@@ -1960,9 +1960,9 @@
}
}
lappend details [dict create \
- attributeName $a \
- achieved $points \
- achievable $achievablePoints]
+ attributeName $a \
+ achieved $points \
+ achievable $achievablePoints]
}
return [list achievedPoints $totalPoints \
details $details \
@@ -2448,6 +2448,66 @@
#----------------------------------------------------------------------
# Class: Answer_manager
+ # Method: get_non_empty_file_formfields
+ #----------------------------------------------------------------------
+ :method get_non_empty_file_formfields {
+ {-submission:object}
+ } {
+ set objs [lmap {name obj} [$submission set __form_fields] {set obj}]
+
+ #
+ # Filter out the form-fields, which have a nonempty
+ # revision_id.
+ #
+ return [::xowiki::formfield::child_components \
+ -filter {[$_ hasclass "::xowiki::formfield::file"]
+ && [dict exists [$_ value] revision_id]
+ && [dict get [$_ value] revision_id] ne ""} \
+ $objs]
+ }
+
+ #----------------------------------------------------------------------
+ # Class: Answer_manager
+ # Method: pretty_formfield_name
+ #----------------------------------------------------------------------
+ :method pretty_formfield_name {f_obj} {
+ regsub {_[.]answer([0-9]+)} [$f_obj name] {-\1} exercise_name
+ #ns_log notice "PRETTY '[$f_obj name]' -> '$exercise_name'"
+ return $exercise_name
+ }
+
+ #----------------------------------------------------------------------
+ # Class: Answer_manager
+ # Method: export_file_submission
+ #----------------------------------------------------------------------
+ :method export_file_submission {
+ {-submission:object}
+ {-zipFile:object}
+ {-check_for_file_submission_exists:boolean false}
+ } {
+ #
+ # Get all nonempty file form-fields and add these to a zip
+ # file. The filename is composed of the user, the exercise and
+ # the provided file-name.
+ #
+ foreach f_obj [:get_non_empty_file_formfields -submission $submission] {
+ set exercise_name [:pretty_formfield_name $f_obj]
+ foreach file_revision_id [dict get [$f_obj value] revision_id] {
+ set file_object [::xo::db::CrClass get_instance_from_db -revision_id $file_revision_id]
+ set download_file_name ""
+ append download_file_name \
+ [$submission set online-exam-userName] "-" \
+ $exercise_name "-" \
+ [$file_object title]
+ $zipFile addFile \
+ [$file_object full_file_name] \
+ [$zipFile cget -name]/[ad_sanitize_filename $download_file_name]
+ }
+ }
+ }
+
+ #----------------------------------------------------------------------
+ # Class: Answer_manager
# Method: render_submission=exam_protocol
#----------------------------------------------------------------------
:method render_submission=exam_protocol {
@@ -2458,6 +2518,7 @@
{-form_objs:integer,0..n ""}
{-grading_scheme:object}
{-recutil:object,0..1 ""}
+ {-zipFile:object,0..1 ""}
{-revision_id:integer,0..1 ""}
{-submission:object}
{-totalPoints:double}
@@ -2507,6 +2568,10 @@
-recutil $recutil
}
+ if {$zipFile ne ""} {
+ :export_file_submission -submission $submission -zipFile $zipFile
+ }
+
set achieved_points {}
if {$with_signature || $autograde} {
set answerAttributes [xowf::test_item::renaming_form_loader \
@@ -2545,11 +2610,11 @@
-revision_id $revision_id]
set question_form [subst {
-
-
$question_form
-
$markup
-
+
+
$question_form
+
$markup
+
}]
}
@@ -2724,6 +2789,32 @@
}
#
+ # Create zip file from file submissions
+ #
+ set create_zip_file [::xo::cc query_parameter create-file-submission-zip-file:boolean 0]
+ if {$create_zip_file} {
+ package req nx::zip
+
+ [$examWf package_id] get_lang_and_name -name [$examWf set name] lang stripped_name
+
+ if {[string equal [nx::zip::Archive info lookup parameters create name] -name]} {
+ set zipFile [nx::zip::Archive new -name [ad_sanitize_filename $stripped_name]]
+ } else {
+ set zipFile [::nx::zip::Archive new]
+ #
+ # Post-register property, since it is not yet available in
+ # this version of nx.
+ #
+ $zipFile object property name
+ $zipFile configure -name [ad_sanitize_filename $stripped_name]
+ }
+ } else {
+ set zipFile ""
+ }
+
+ set file_submission_exists 0
+
+ #
# Iterate over the items sorted by orderby.
#
$items orderby $orderby
@@ -2739,6 +2830,7 @@
-form_objs $form_objs \
-grading_scheme $grading_scheme \
-recutil $recutil \
+ -zipFile $zipFile \
-revision_id $revision_id \
-totalPoints $totalPoints \
-runtime_panel_view $runtime_panel_view \
@@ -2750,6 +2842,16 @@
} else {
append HTML $html
}
+
+ #
+ # Check if we have found a file submission
+ #
+ if {!$file_submission_exists
+ && [llength [:get_non_empty_file_formfields -submission $submission]] > 0
+ } {
+ set file_submission_exists 1
+ }
+
}
if {$export} {
@@ -2760,6 +2862,38 @@
append HTML [:grading_table -csv ${:grade_csv} ${:grade_dict}]
}
+ if {$create_zip_file} {
+ $zipFile ns_returnZipFile [$zipFile cget -name].zip
+ $zipFile destroy
+ ad_script_abort
+ }
+
+ #
+ # If we have already some file submission we are showing a link
+ # for bulk-downloading the submissions
+ #
+ if {$file_submission_exists} {
+ #
+ # Avoid empty entries for query parameters
+ #
+ if {[llength $form_objs] > 0} {
+ set fos $form_objs
+ }
+ foreach value {revision_id filter_id} var {rid id} {
+ if {[set $value] ne ""} {
+ set $var [set $value]
+ }
+ }
+ set href [$examWf pretty_link -query [export_vars {
+ {m print-answers} {create-file-submission-zip-file 1}
+ fos rid id
+ }]]
+ append HTML \
+ "" \
+ "" \
+ " #xowf.Download_file_submissions#"
+ }
+
return [list do_stream $do_stream HTML $HTML]
}
@@ -2796,10 +2930,11 @@
$f make_correct
#ns_log notice "FIELD $f [$f name] [$f info class] -> VALUE [$f set value]"
if {[$f exists correction]} {
- set correction [$f set correction]
+ set correction [$f set correction]
} else {
- set correction ""
- ns_log warning "form-field [$f name] of type [$f info class] does not provide variable correction via 'make_correct'"
+ set correction ""
+ ns_log warning "form-field [$f name] of type [$f info class] " \
+ "does not provide variable correction via 'make_correct'"
}
lappend answer \
[list name $att \
@@ -2926,12 +3061,12 @@
# if {0 && $autograde} {
# lappend form_field_objs \
- # [$wf create_raw_form_field \
- # -name _online-exam-total-score \
- # -spec number,label=#xowf.Total-Score#] \
- # [$wf create_raw_form_field \
- # -name _online-exam-grade \
- # -spec number,label=#xowf.Grade#]
+ # [$wf create_raw_form_field \
+ # -name _online-exam-total-score \
+ # -spec number,label=#xowf.Total-Score#] \
+ # [$wf create_raw_form_field \
+ # -name _online-exam-grade \
+ # -spec number,label=#xowf.Grade#]
# }
lappend form_field_objs \
@@ -3189,7 +3324,7 @@
# Provide bulk notification message dialog to send message to all users
#
set dialog_info [::xowiki::includelet::personal-notification-messages \
- modal_message_dialog -to_user_id $user_list]
+ modal_message_dialog -to_user_id $user_list]
append dialogs [dict get $dialog_info dialog] \n
set notification_dialog_button [dict get $dialog_info link]
set bulk_notification_HTML "$notification_dialog_button #xowiki.Send_message_to# [llength $user_list] #xowf.Participants#
"
@@ -3306,7 +3441,7 @@
if (answers.length == 2 && answers[1] > 0) {
var disabledLinkItems = document.querySelectorAll(".list-group-item.link-disabled");
disabledLinkItems.forEach(function(linkItem) {
- linkItem.classList.remove("link-disabled");
+ linkItem.classList.remove("link-disabled");
});
}
}
@@ -3406,20 +3541,20 @@
if (countdown_days != 0) {
HTML += '' + countdown_days + ' '
- + (countdown_days != 1 ? '[_ xowf.Days]' : '[_ xowf.Day]')
- + ' ';
+ + (countdown_days != 1 ? '[_ xowf.Days]' : '[_ xowf.Day]')
+ + ' ';
}
if (countdown_hours != 0 || countdown_days != 0) {
HTML += '' + countdown_hours + ' '
- + (countdown_hours != 1 ? '[_ xowf.Hours]' : '[_ xowf.Hour]')
- + ' ';
+ + (countdown_hours != 1 ? '[_ xowf.Hours]' : '[_ xowf.Hour]')
+ + ' ';
}
HTML += '' + countdown_minutes + ' '
- + (countdown_minutes != 1 ? '[_ xowf.Minutes]' : '[_ xowf.Minute]')
- + ' '
- + '' + countdown_seconds + ' '
- + (countdown_seconds != 1 ? '[_ xowf.Seconds]' : '[_ xowf.Second]')
- + ' [_ xowf.remaining]' ;
+ + (countdown_minutes != 1 ? '[_ xowf.Minutes]' : '[_ xowf.Minute]')
+ + ' '
+ + '' + countdown_seconds + ' '
+ + (countdown_seconds != 1 ? '[_ xowf.Seconds]' : '[_ xowf.Second]')
+ + ' [_ xowf.remaining]' ;
countdown.innerHTML = HTML;
}, 1000);
@@ -3648,7 +3783,7 @@
for {set count 1} {$count <= $question_count} {incr count} {
set visited_css [expr {($count - 1) in $visited ? "visited" : ""}]
set flag_label [expr {($count - 1) in $flagged
- ? " " : ""}]
+ ? " " : ""}]
set extra_css [:pagination_button_css \
-CSSclass "$CSSclass $visited_css" \
-cond [expr {$current_position == $count - 1 }] \
@@ -4009,7 +4144,7 @@
#ns_log notice "CHECK obj $obj form_obj $form_obj parent_obj [$obj parent_id]"
#append full_form \
- # [$form_obj substitute_markup -context_obj $form_obj [$form_obj property form]]
+ # [$form_obj substitute_markup -context_obj $form_obj [$form_obj property form]]
#ns_log notice "FORM=$full_form"
@@ -4441,15 +4576,15 @@
:method total {-property:required title_infos} {
set total 0
foreach title_info $title_infos {
- if {[dict exists $title_info $property]} {
- set value [dict get $title_info $property]
- if {$value eq ""} {
- ns_log notice "missing $property in '$title_info'"
- set value 0
- }
- set total [expr {$total + $value}]
+ if {[dict exists $title_info $property]} {
+ set value [dict get $title_info $property]
+ if {$value eq ""} {
+ ns_log notice "missing $property in '$title_info'"
+ set value 0
}
+ set total [expr {$total + $value}]
}
+ }
return $total
}
Index: openacs-4/packages/xowf/www/resources/test-item.css
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/www/resources/Attic/test-item.css,v
diff -u -N -r1.1.2.34 -r1.1.2.35
--- openacs-4/packages/xowf/www/resources/test-item.css 7 May 2021 09:24:44 -0000 1.1.2.34
+++ openacs-4/packages/xowf/www/resources/test-item.css 14 Jul 2021 17:36:16 -0000 1.1.2.35
@@ -321,3 +321,12 @@
form.Form-inclass-exam div.collapse {
margin-left: 2em;
}
+
+
+/*
+ * Download file submission from potentially multiple exams
+ */
+
+div.xowiki-content .download-submissions {
+ margin-top: 2em;
+}