[LON-CAPA-cvs] cvs: rat /client parameter.html loncom/interface lonparmset.pm
raeburn
raeburn at source.lon-capa.org
Mon Jun 30 16:29:07 EDT 2025
raeburn Mon Jun 30 20:29:07 2025 EDT
Modified files:
/loncom/interface lonparmset.pm
/rat/client parameter.html
Log:
- Bug 6623
Select boxes for grace period parameter support 0-52 weeks, 0-6 days,
0-23 hours, and 0-59 minutes, i.e., can be set to the nearest minute for
up to a year.
-------------- next part --------------
Index: loncom/interface/lonparmset.pm
diff -u loncom/interface/lonparmset.pm:1.622 loncom/interface/lonparmset.pm:1.623
--- loncom/interface/lonparmset.pm:1.622 Sat Jun 28 14:34:46 2025
+++ loncom/interface/lonparmset.pm Mon Jun 30 20:29:03 2025
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set parameters for assessments
#
-# $Id: lonparmset.pm,v 1.622 2025/06/28 14:34:46 raeburn Exp $
+# $Id: lonparmset.pm,v 1.623 2025/06/30 20:29:03 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -329,6 +329,7 @@
use Apache::longroup;
use Apache::lonrss;
use HTML::Entities;
+use POSIX qw (floor);
use Text::Wrap();
use LONCAPA qw(:DEFAULT :match);
@@ -1003,7 +1004,7 @@
foreach my $item (@items) {
if ($item =~ /^\d+:(0|1)\.?\d*:(0|1)$/) {
my ($totalsecs,$fraction,$grad) = split(/:/,$item);
- $result .= &interval_to_humanstr($totalsecs);
+ $result .= &grace_to_humanstr($totalsecs);
if (($fraction >=0) && ($fraction <=1)) {
$result .= ' | '.$fraction.' '.&mt('pts');
if ($grad == 1) {
@@ -1076,6 +1077,35 @@
return '<span style="white-space:nowrap">'.join('</span>, <span style="white-space:nowrap">', at timer).'</span>';
}
+sub grace_to_humanstr {
+ my ($totalsecs) = @_;
+ my @timer;
+ my $weeks = floor($totalsecs/604800);
+ $totalsecs -= $weeks*604800;
+ my $days = floor($totalsecs/86400);
+ $totalsecs -= $days*86400;
+ my $hours = floor($totalsecs/3600);
+ $totalsecs -= $hours*3600;
+ my $mins= floor($totalsecs/60);
+ $totalsecs -= $mins*60;
+ if ($weeks) {
+ push(@timer,&mt('[quant,_1,wk]',$weeks));
+ }
+ if ($days) {
+ push(@timer,&mt('[quant,_1,day]',$days));
+ }
+ if ($hours) {
+ push(@timer,&mt('[quant,_1,hr]',$hours));
+ }
+ if ($mins) {
+ push(@timer,&mt('[quant,_1,min]',$mins));
+ }
+ if (!@timer) { # Special case: all entries 0 -> display "0 mins" intead of empty field to keep this field editable
+ push(@timer,&mt('[quant,_1,min]',0));
+ }
+ return '<span style="white-space:nowrap">'.join('</span>, <span style="white-space:nowrap">', at timer).'</span>';
+}
+
# Returns HTML containing a link on a parameter value, for table mode.
# The link uses the javascript function 'pjump'.
#
@@ -1278,6 +1308,7 @@
var dlExitRegExp = /^deeplink_exit_/;
var dlExitTextRegExp = /^deeplink_exittext_/;
var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
+ var patternGrace = /^\d+:(0|1)\.?\d*:(0|1)\$/;
var numelements = document.parmform.elements.length;
if ((typeof(numelements) != 'undefined') && (numelements != null)) {
if (numelements) {
@@ -1487,29 +1518,37 @@
var divElem = document.parmform.elements[i].closest('div');
var timeSels = divElem.getElementsByTagName("select");
var total = 0;
+ var numnotnull = 0;
if (timeSels.length) {
for (var j=0; j<timeSels.length; j++) {
var sname = timeSels[j].getAttribute('name');
- var poss = parseInt(timeSels[j].options[timeSels[j].selectedIndex].value);
- if (sname == 'days_'+identifier) {
- if ((poss > 0) && (poss <= 31)) {
- total += (poss * 86400);
- }
- } else if (sname == 'hours_'+identifier) {
- if ((poss > 0) && (poss < 24)) {
- total += (poss * 3600);
- }
- } else if (sname == 'minutes_'+identifier) {
- if ((poss > 0) && (poss < 60)) {
- total += (poss * 60);
- }
- } else if (sname == 'seconds_'+identifier) {
- if ((poss > 0) && (poss < 60)) {
- total += poss;
+ var value = timeSels[j].options[timeSels[j].selectedIndex].value;
+ if ((value !== null) && (value !== '') && (value !== 'undefined')) {
+ numnotnull ++;
+ var poss = parseInt(value);
+ if (sname == 'weeks_'+identifier) {
+ if ((poss > 0) && (poss <= 52)) {
+ total += (poss * 604800);
+ }
+ } else if (sname == 'days_'+identifier) {
+ if ((poss > 0) && (poss <= 6)) {
+ total += (poss * 86400);
+ }
+ } else if (sname == 'hours_'+identifier) {
+ if ((poss > 0) && (poss < 24)) {
+ total += (poss * 3600);
+ }
+ } else if (sname == 'minutes_'+identifier) {
+ if ((poss > 0) && (poss < 60)) {
+ total += (poss * 60);
+ }
}
}
}
}
+ if (!numnotnull) {
+ total = '';
+ }
var inputElems = divElem.getElementsByTagName("input");
var frac = '';
var grad = '';
@@ -1519,10 +1558,13 @@
if (iname == 'frac_'+identifier) {
var ival = inputElems[j].value;
ival.trim();
- var poss = parseFloat(ival);
- if ((typeof poss === 'number') && (!isNaN(poss))) {
- if ((poss => 0) && (poss <= 1)) {
- frac = poss;
+ if ((ival != '') && (value != 'undefined')) {
+ var poss = parseFloat(ival);
+ if ((typeof poss === 'number') && (!isNaN(poss))) {
+ if ((poss => 0) && (poss <= 1)) {
+ frac = poss;
+ numnotnull ++;
+ }
}
}
} else if (iname == 'grad_'+identifier) {
@@ -1534,11 +1576,24 @@
}
}
}
- document.parmform.elements[i].value = total+':'+frac+':'+grad;
- if (document.parmform.elements['set_'+identifier].value) {
- document.parmform.elements['set_'+identifier].value += ',';
+ if (numnotnull) {
+ var possgrace = total+':'+frac+':'+grad;
+ if (patternGrace.test(possgrace)) {
+ document.parmform.elements[i].value = possgrace;
+ if (document.parmform.elements['set_'+identifier].value) {
+ document.parmform.elements['set_'+identifier].value += ',';
+ }
+ document.parmform.elements['set_'+identifier].value += document.parmform.elements[i].value;
+ } else {
+ if (frac == '') {
+ alert('Grace Period Past-Due: enter partial credit (number between 0 and 1.0).');
+ return false;
+ } else {
+ alert('Grace Period Past-Due: select a number in at least one of the time past due select boxes, or delete the value for partial credit.');
+ return false;
+ }
+ }
}
- document.parmform.elements['set_'+identifier].value += document.parmform.elements[i].value;
}
}
}
@@ -1595,13 +1650,15 @@
my %lt = &grace_titles();
&js_escape(\%lt);
my $overdue = '<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
- foreach my $which (['days', 86400, 31],
+ foreach my $which (['weeks', 604800, 52],
+ ['days', 86400, 6],
['hours', 3600, 23],
- ['minutes', 60, 59],
- ['seconds', 1, 59]) {
+ ['minutes', 60, 59]) {
my ($name, $factor, $max) = @{ $which };
my %select = ((map {$_ => $_} (0..$max)),
'select_form_order' => [0..$max]);
+ unshift(@{$select{'select_form_order'}},'');
+ $select{''} = '';
my $selector = &Apache::loncommon::select_form('',$name."_'+identifier+'",
\%select);
$selector =~ s/([\r\n\f]+)//g;
@@ -1618,7 +1675,7 @@
e.preventDefault();
var identifier = \$(this).closest("div").attr("id");
identifier = identifier.replace(graceRegExp,'');
- \$(this).closest('div').find('.LC_string_grace_inner').append('<div><input type="hidden" name="setgrace_'+identifier+'" value="" />$overdue<fieldset class="LC_grace"><legend>$lt{scor}</legend><input type="text" size="3" name="frac_'+identifier+'" value="" /> <label><input type="checkbox" value="1" name="grad_'+identifier+'" />$lt{grad}</label></fieldset><a href="#" class="LC_remove_grace">$lt{remo}</a></div>');
+ \$(this).closest('div').find('.LC_string_grace_inner').append('<div><input type="hidden" name="setgrace_'+identifier+'" value="" />$overdue<fieldset class="LC_grace"><legend>$lt{pcr}</legend><input type="text" size="3" name="frac_'+identifier+'" value="" /> <label><input type="checkbox" value="1" name="grad_'+identifier+'" />$lt{grad}</label></fieldset><a href="#" class="LC_remove_grace">$lt{remo}</a></div>');
});
\$(wrapper).delegate(".LC_remove_grace","click", function(e){
@@ -5298,7 +5355,6 @@
return $seconds;
}
-
# Returns HTML to enter a text value for a parameter.
#
# @param {string} $thiskey - parameter key
@@ -5677,18 +5733,22 @@
my %lt = &grace_titles();
my $output = '<div><input type="hidden" name="setgrace_'.$thiskey.'" value="" />'.
'<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
- foreach my $which (['days', 86400, 31],
+ foreach my $which (['weeks', 604800, 52],
+ ['days', 86400, 6],
['hours', 3600, 23],
- ['minutes', 60, 59],
- ['seconds', 1, 59]) {
+ ['minutes', 60, 59]) {
my ($name, $factor, $max) = @{ $which };
my $amount;
- if ($delta ne '') {
+ my %select = ((map {$_ => $_} (0..$max)),
+ 'select_form_order' => [0..$max]);
+ if ($delta eq '') {
+ unshift(@{$select{'select_form_order'}},'');
+ $select{''} = '';
+ $amount = '';
+ } else {
$amount = int($delta/$factor);
$delta %= $factor;
}
- my %select = ((map {$_ => $_} (0..$max)),
- 'select_form_order' => [0..$max]);
$output .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
\%select,'',$readonly);
$output .= ' '.$lt{$name}.' ';
@@ -5711,10 +5771,10 @@
remo => 'Remove',
pcr => 'Partial credit',
grad => 'gradual',
+ weeks => 'weeks',
days => 'days',
hours => 'hours',
minutes => 'minutes',
- seconds => 'seconds',
);
}
Index: rat/client/parameter.html
diff -u rat/client/parameter.html:1.96 rat/client/parameter.html:1.97
--- rat/client/parameter.html:1.96 Sat Jun 28 14:35:11 2025
+++ rat/client/parameter.html Mon Jun 30 20:29:06 2025
@@ -5,7 +5,7 @@
The LearningOnline Network with CAPA
Parameter Input Window
//
-// $Id: parameter.html,v 1.96 2025/06/28 14:35:11 raeburn Exp $
+// $Id: parameter.html,v 1.97 2025/06/30 20:29:06 raeburn Exp $
//
// Copyright Michigan State University Board of Trustees
//
@@ -328,10 +328,34 @@
}
result += '</select>';
return result;
-}
+}
+
+function intweek(weeks) {
+ var thisweek;
+ if ((typeof weeks === 'number') && (!isNaN(weeks))) {
+ thisweek=weeks;
+ }
+ var i;
+ var result ='';
+ var funcname = '';
+ if (pscat == 'grace') {
+ funcname = 'parent.gracestringeval()';
+ }
+ result += '<select name="weeks" onchange="'+funcname+';">';
+ for (i=0;i<=52;i++) {
+ result += '<option value="'+i+'"';
+ if (i==thisweek) {
+ result += ' selected="selected"';
+ }
+ result += '>'+i+'</option>';
+ }
+ result += '</select>';
+ return result;
+}
function intday(days) {
var thisdate;
+ var maxallowed;
if ((typeof days === 'number') && (!isNaN(days))) {
thisdate=days;
} else {
@@ -342,11 +366,13 @@
var funcname = '';
if (pscat == 'grace') {
funcname = 'parent.gracestringeval()';
+ maxallowed = 6;
} else {
funcname = 'parent.intcalc()';
+ maxallowed = 31;
}
result += '<select name="date" onchange="'+funcname+';">';
- for (i=0;i<=31;i++) {
+ for (i=0;i<=maxallowed;i++) {
result += '<option value="'+i+'"';
if (i==thisdate) {
result += ' selected="selected"';
@@ -721,8 +747,12 @@
for (var j=0; j<timeSels.length; j++) {
var sname = timeSels[j].getAttribute('name');
var poss = parseInt(timeSels[j].options[timeSels[j].selectedIndex].value);
- if (sname == 'date') {
- if ((poss > 0) && (poss <= 31)) {
+ if (sname == 'weeks') {
+ if ((poss > 0) && (poss <= 52)) {
+ total += (poss * 604800);
+ }
+ } else if (sname == 'date') {
+ if ((poss > 0) && (poss < 7)) {
total += (poss * 86400);
}
} else if (sname == 'hours') {
@@ -733,10 +763,6 @@
if ((poss > 0) && (poss < 60)) {
total += (poss * 60);
}
- } else if (sname == 'seconds') {
- if ((poss > 0) && (poss < 60)) {
- total += poss;
- }
}
}
}
@@ -775,6 +801,7 @@
}
function graceitem(current) {
+ var gweeks = 0;
var gdays = 0;
var ghours = 0;
var gmins = 0;
@@ -786,6 +813,8 @@
var graceItems = new Array;
graceItems = current.split(':');
gsecs=graceItems[0];
+ gweeks=Math.floor(gsecs/604800);
+ gsecs -= gweeks*604800;
gdays=Math.floor(gsecs/86400);
gsecs -= gdays*86400;
ghours=Math.floor(gsecs/3600);
@@ -799,10 +828,10 @@
}
return '<input type="hidden" name="setgrace" value="" />'+
'<fieldset class="LC_grace"><legend>Time past due</legend>'+
- '<span style="white-space:nowrap">'+intday(gdays)+' days </span>'+
- '<span style="white-space:nowrap">'+inthour(ghours)+' hours</span><br />'+
- '<span style="white-space:nowrap">'+intminute(gmins)+' mins</span>'+
- '<span style="white-space:nowrap">'+intsecond(gsecs)+' secs</span>'+
+ '<span style="white-space:nowrap">'+intweek(gweeks)+' weeks </span>'+
+ '<span style="white-space:nowrap">'+intday(gdays)+' days </span><br />'+
+ '<span style="white-space:nowrap">'+inthour(ghours)+' hours </span>'+
+ '<span style="white-space:nowrap">'+intminute(gmins)+' mins </span>'+
'</fieldset><fieldset class="LC_grace"><legend>Partial Credit</legend>'+
'<input type="text" size="3" name="frac" value="'+gfrac+'" onblur="parent.gracestringeval();" />'+
' <label><input type="checkbox" value="1" name="grad"'+checktext+' onclick="parent.gracestringeval();" />'+
More information about the LON-CAPA-cvs
mailing list