--- loncom/interface/courseprefs.pm 2023/06/03 11:21:37 1.124
+++ loncom/interface/courseprefs.pm 2025/01/07 16:19:19 1.133
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set configuration settings for a course
#
-# $Id: courseprefs.pm,v 1.124 2023/06/03 11:21:37 raeburn Exp $
+# $Id: courseprefs.pm,v 1.133 2025/01/07 16:19:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -372,6 +372,12 @@ sub handler {
my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
my %linkprot=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
+ my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
+ unless ($phase eq 'process') {
+ if (ref($domdefs{'linkprotsuggested'}) eq 'HASH') {
+ $values{'suggested'} = $domdefs{'linkprotsuggested'};
+ }
+ }
my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1);
my %ltitools = &Apache::lonnet::dump('ltitools',$cdom,$cnum,undef,undef,undef,1);
my %ltitoolsenc = &Apache::lonnet::dump('nohist_toolsenc',$cdom,$cnum,undef,undef,undef,1);
@@ -694,6 +700,8 @@ sub get_allitems {
if ($item eq 'feedback') {
push(@allitems,(map { $_.'.text'; } @{$prefs{$item}{'ordered'}}));
}
+ } elsif (($item eq 'linkprot') || ($item eq 'ltitools')) {
+ push(@allitems,$item);
}
}
}
@@ -791,9 +799,38 @@ sub print_config_box {
';
+ if ($action eq 'linkprot') {
+ if ((ref($settings) eq 'HASH') && (ref($settings->{'suggested'}) eq 'HASH')) {
+ my $hints;
+ my $hintcount = 0;
+ foreach my $key (sort { $a <=> $b } keys(%{$settings->{'suggested'}})) {
+ if ((ref($settings->{'suggested'}->{$key}) eq 'HASH')) {
+ if (($settings->{'suggested'}->{$key}-{'name'} ne '') &&
+ ($settings->{'suggested'}->{$key}-{'info'} ne '')) {
+ my $css_class = $hintcount%2?' class="LC_odd_row"':' class="LC_even_row"';
+ $hints .= ''.
+ $settings->{'suggested'}->{$key}->{'name'}.' | '.
+ ''.
+ $settings->{'suggested'}->{$key}->{'info'}.
+ ' | ';
+ $hintcount ++;
+ }
+ }
+ }
+ if ($hintcount) {
+ $output .= ''.
+ ''.&mt('Recommendation(s) for specific launcher application(s)').' | '.
+ ' '."\n".
+ ''.
+ ''.&mt('Launcher Application').' | '.
+ ''.&mt('Recommendation(s)').' | '."\n".
+ $hints;
+ }
+ }
+ }
if (exists $item->{'header'}->[0]->{'col1'} ||
exists $item->{'header'}->[0]->{'col2'}) {
- $output .= '
+ $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).' | ';
if (($action eq 'courseinfo') || ($action eq 'localization') ||
@@ -820,7 +857,7 @@ sub print_config_box {
} elsif ($action eq 'appearance') {
$output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'grading') {
- $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
+ $output .= &print_grading($cdom,$cnum,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'printouts') {
$output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'spreadsheet') {
@@ -1548,6 +1585,33 @@ sub process_changes {
} elsif ($values->{$entry}) {
$changes->{$entry} = '';
}
+ } elsif ($entry eq 'grading') {
+ if ($env{'form.'.$entry} eq 'standard') {
+ if ($env{'form.hidetotals'}) {
+ my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
+ if (keys(%sections)) {
+ my @secs = &Apache::loncommon::get_env_multiple('form.hidetotals_sections');
+ if (grep(/^all$/,@secs)) {
+ $newvalues{'hidetotals'} = 'all';
+ } elsif (@secs) {
+ $newvalues{'hidetotals'} = '';
+ foreach my $sec (sort {$a <=> $b} @secs) {
+ if (exists($sections{$sec})) {
+ $newvalues{'hidetotals'} .= $sec.','
+ }
+ }
+ $newvalues{'hidetotals'} =~ s/,$//;
+ }
+ } else {
+ $newvalues{'hidetotals'} = 'all';
+ }
+ }
+ }
+ if ($newvalues{'hidetotals'} ne $values->{'hidetotals'}) {
+ $changes->{'hidetotals'} = $newvalues{'hidetotals'};
+ $changes->{'grading'} = $env{'form.'.$entry};
+ }
+ $newvalues{$entry} = $env{'form.'.$entry};
} else {
$newvalues{$entry} = $env{'form.'.$entry};
}
@@ -1914,7 +1978,7 @@ sub process_ltitools {
if ($env{'form.ltitools_add'}) {
my $title = $env{'form.ltitools_add_title'};
$title =~ s/(`)/'/g;
- my ($newid,$error) = &get_ltitools_id($context,$cdom,$cnum,$title);
+ my ($newid,$error) = &Apache::lonnet::get_ltitools_id($context,$cdom,$cnum,$title);
if ($newid) {
my $position = $env{'form.ltitools_add_pos'};
$position =~ s/\D+//g;
@@ -2368,73 +2432,6 @@ sub process_ltitools {
return $errors;
}
-sub get_ltitools_id {
- my ($context,$cdom,$cnum,$title) = @_;
- my ($lockhash,$tries,$gotlock,$id,$error);
-
- # get lock on ltitools db
- $lockhash = {
- lock => $env{'user.name'}.
- ':'.$env{'user.domain'},
- };
- $tries = 0;
- if ($context eq 'domain') {
- $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
- } else {
- $gotlock = &Apache::lonnet::newput('ltitools',$lockhash,$cdom,$cnum);
- }
- while (($gotlock ne 'ok') && ($tries<10)) {
- $tries ++;
- sleep (0.1);
- if ($context eq 'domain') {
- $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
- } else {
- $gotlock = &Apache::lonnet::newput('ltitools',$lockhash,$cdom,$cnum);
- }
- }
- if ($gotlock eq 'ok') {
- my %currids;
- if ($context eq 'domain') {
- %currids = &Apache::lonnet::dump_dom('ltitools',$cdom);
- } else {
- %currids = &Apache::lonnet::dump('ltitools',$cdom,$cnum);
- }
- if ($currids{'lock'}) {
- delete($currids{'lock'});
- if (keys(%currids)) {
- my @curr = sort { $a <=> $b } keys(%currids);
- if ($curr[-1] =~ /^\d+$/) {
- $id = 1 + $curr[-1];
- }
- } else {
- $id = 1;
- }
- if ($id) {
- if ($context eq 'domain') {
- unless (&Apache::lonnet::newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') {
- $error = 'nostore';
- }
- } else {
- unless (&Apache::lonnet::newput('ltitools',{ $id => $title },$cdom,$cnum) eq 'ok') {
- $error = 'nostore';
- }
- }
- } else {
- $error = 'nonumber';
- }
- }
- my $dellockoutcome;
- if ($context eq 'domain') {
- $dellockoutcome = &Apache::lonnet::del_dom('ltitools',['lock'],$cdom);
- } else {
- $dellockoutcome = &Apache::lonnet::del('ltitools',['lock'],$cdom,$cnum);
- }
- } else {
- $error = 'nolock';
- }
- return ($id,$error);
-}
-
sub process_ltitools_image {
my ($r,$context,$dom,$cnum,$confname,$caller,$itemid,$configuserok,$switch,$author_ok,$currimg) = @_;
my $filename = $env{'form.'.$caller.'.filename'};
@@ -2696,6 +2693,40 @@ sub store_changes {
unless (($key eq 'co-owners') || ($key eq 'discussion_post_fonts') || ($key eq 'extresource')) {
$displayval = $changes->{$item}{$key};
}
+ if (($item eq 'grading') && ($key eq 'grading')) {
+ if ($displayval eq 'standard') {
+ my $hidetotals;
+ if (exists($changes->{$item}{'hidetotals'})) {
+ if ($changes->{$item}{'hidetotals'} eq '') {
+ if (exists($values->{'hidetotals'})) {
+ push(@delkeys,'hidetotals');
+ }
+ } else {
+ $hidetotals = $changes->{$item}{'hidetotals'};
+ }
+ } elsif (exists($values->{'hidetotals'})) {
+ $hidetotals = $values->{'hidetotals'};
+ }
+ if ($hidetotals eq '') {
+ $displayval = &mt('standard with "hide course totals" set to "No"');
+ if (exists($values->{'hidetotals'})) {
+ push(@delkeys,'hidetotals');
+ }
+ } elsif ($hidetotals =~ /^([\w,]+)$/) {
+ my $secstr = $1;
+ my @secs = split(/,/,$secstr);
+ if (grep(/^all$/,@secs)) {
+ $displayval = &mt('standard with "hide course totals" set to "Yes" for all users');
+ $hidetotals = 'all';
+ } else {
+ $displayval = &mt('standard with "hide course totals" set to "Yes" for users in section(s): [_1]',join(', ',@secs));
+ }
+ $storehash{'hidetotals'} = $hidetotals;
+ }
+ } elsif (exists($values->{'hidetotals'})) {
+ push(@delkeys,'hidetotals');
+ }
+ }
if ($item eq 'feedback') {
if ($key =~ /^(question|policy|comment)(\.email)\.text$/) {
$text = $prefs->{$item}->{'itemtext'}{$1.$2};
@@ -2704,14 +2735,14 @@ sub store_changes {
$displayname = &mt('Recipients of '.$text.' questions');
}
} elsif ($item eq 'discussion') {
- if ($key =~ /^p(lc|ch)\.roles\.denied/) {
+ if ($key =~ /^p(lc|ch|ac)\.roles\.denied/) {
$displayname = &mt("$text (role-based)");
if ($displayval ne '') {
my @roles = split(',',$displayval);
@roles = map { &Apache::lonnet::plaintext($_); } @roles;
$displayval = join(', ',@roles);
}
- } elsif ($key =~ /^p(lc|ch)\.users\.denied/) {
+ } elsif ($key =~ /^p(lc|ch|ac)\.users\.denied/) {
$displayname = &mt("$text (specific user(s))");
} else {
if ($key eq 'allow_discussion_post_editing') {
@@ -3289,7 +3320,13 @@ sub store_ltitools {
}
}
}
- $output .= ''.&mt('Configurable in course:');
+ $output .= '';
+ if ($context eq 'domain') {
+ $output .= &mt('Configurable in course');
+ } else {
+ $output .= &mt('Configurable for each instance of tool in course');
+ }
+ $output .= ':';
my @possconfig = ('label','title','target','linktext','explanation','append');
my $numconfig = 0;
if (ref($changes->{$itemid}{'crsconf'}) eq 'HASH') {
@@ -3656,7 +3693,7 @@ function syllabusinfo() {
}
}
ENDSCRIPT
- my $menuitems_js;
+ my ($menuitems_js,$grading_js);
unless ($noedit) {
my $collections;
my $next = 1;
@@ -3738,6 +3775,48 @@ function toggleAddmenucoll() {
}
}
ENDSCRIPT
+ $grading_js = <<"ENDSCRIPT";
+function toggleGrading(form) {
+ if (document.getElementById('hidetotalsdiv')) {
+ var totalsdivid = document.getElementById('hidetotalsdiv');
+ var selname = form.elements['grading'];
+ if (selname) {
+ var current = selname.options[selname.selectedIndex].value
+ if (current == 'standard') {
+ totalsdivid.style.display = 'inline-block';
+ } else {
+ totalsdivid.style.display = 'none';
+ }
+ }
+ }
+ return;
+}
+
+function toggleHiddenTotalsSec(form) {
+ if (document.getElementById('sectotalsdiv')) {
+ var sectotalsdivid = document.getElementById('sectotalsdiv');
+ var radioname = form.elements['hidetotals'];
+ if (radioname) {
+ if (radioname.length > 0) {
+ var setvis;
+ for (var i=0; i'."\n".
+ $grading_js."\n".&linkprot_javascript()."\n".'//]]>'."\n".
''."\n".$stubrowse_js."\n".$ltitools_js."\n";
return $jscript;
}
@@ -5219,8 +5298,7 @@ sub update_releasereq {
}
$modified_courses = [];
}
- undef($registered_cleanup);
- return;
+ return OK;
}
sub show_autocoowners {
@@ -5635,7 +5713,7 @@ sub select_recipient {
}
sub select_sections {
- my ($item,$num,$sections,$selected,$noedit) = @_;
+ my ($item,$num,$sections,$selected,$noedit,$allval) = @_;
my ($output,@currsecs,$allsec,$disabled);
if (ref($selected) eq 'ARRAY') {
@currsecs = @{$selected};
@@ -5651,16 +5729,24 @@ sub select_sections {
my $mult;
if (@{$sections} > 1) {
$mult = ' multiple="multiple"';
+ my $size;
if (@{$sections} > 3) {
- $mult .= ' size="4"';
+ $size = 4;
+ } else {
+ $size = 1 + scalar(@{$sections});
}
+ $mult .= ' size="'.$size.'"';
}
- $output = ' '.
- '';
+ '';
foreach my $item ('label','title','target','linktext','explanation','append') {
$datatable .= ' '.
''.
- ' '.
+ ' '.
''.&mt('Parameter name').':'.
''.
' ';
@@ -7538,7 +7638,7 @@ sub print_linkprotection {
$onclickpassback.$checkedpassback{'no'}.$disabled.' />'.&mt('No').' '.
''.
- ' '.
+ '
'.
' '.&mt('Grade format').
''.(' 'x2).
@@ -7551,7 +7651,7 @@ sub print_linkprotection {
$onclickreturnurl.$checkedreturnurl{'no'}.$disabled.' />'.&mt('No').' '.
''.
- ' '.
+ ' '.
''.&mt('Parameter name').':'.
''.
' ';
@@ -7775,7 +7875,7 @@ sub item_table_row_end {
}
sub yesno_radio {
- my ($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit) = @_;
+ my ($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit,$onclick,$reverse) = @_;
my $itemon = ' ';
my $itemoff = ' checked="checked" ';
if (($valueyes eq '') && ($valueno eq '')) {
@@ -7797,12 +7897,22 @@ sub yesno_radio {
my $disabled;
if ($noedit) {
$disabled = ' disabled="disabled"';
+ } elsif ($onclick) {
+ $onclick = ' onclick="'.$onclick.'"';
+ }
+ if ($reverse) {
+ return ' '.
+ '';
+ } else {
+ return ' '.
+ '';
}
- return ' '.
- '';
}
sub select_from_options {
@@ -7858,7 +7968,7 @@ sub select_from_options {
}
sub make_item_rows {
- my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype,$caller,$noedit) = @_;
+ my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype,$caller,$noedit,$cnum) = @_;
my $datatable;
if ((ref($items) eq 'HASH') && (ref($ordered) eq 'ARRAY')) {
my $count = 0;
@@ -7921,16 +8031,65 @@ sub make_item_rows {
}
$datatable .= &yesno_radio($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit);
} elsif ($items->{$item}{input} eq 'selectbox') {
- my $id;
+ my ($id,$onchange);
if ($caller eq 'menuitems') {
$id = $item;
+ } elsif ($caller eq 'grading') {
+ if ($item eq 'grading') {
+ $onchange = ' onchange="javascript:toggleGrading(this.form);"';
+ $id = $item;
+ }
}
my $curr = $settings->{$item};
$datatable .=
&select_from_options($item,$items->{$item}{'order'},
$items->{$item}{'options'},$curr,
$items->{$item}{'nullval'},
- undef,undef,undef,$noedit,$id);
+ undef,undef,$onchange,$noedit,$id);
+ if ($item eq 'grading') {
+ my ($unsetdefault,$valueyes,$valueno,$sectionbox);
+ my $gradingsty = 'none';
+ my $gradingsecsty = 'none';
+ $unsetdefault = 0;
+ my (@selsec,@sections,%current);
+ if ($curr eq 'standard') {
+ $gradingsty = 'inline-block';
+ if (ref($settings) eq 'HASH') {
+ $current{'hidetotals'} = $settings->{'hidetotals'};
+ if ($settings->{'hidetotals'} =~ /^([\w,]+)$/) {
+ my $secstr = $1;
+ unless ($secstr eq 'all') {
+ @selsec = split(/,/,$secstr);
+ }
+ $current{'hidetotals'} = 1;
+ }
+ }
+ }
+ $valueyes = "1";
+ $valueno = "0";
+ my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
+ if (keys(%sections)) {
+ @sections = sort( { $a <=> $b } keys(%sections));
+ }
+ my $onclick = 'javascript:toggleHiddenTotalsSec(this.form);';
+ my $sectionbox = ' ';
+ my $reverse = 1;
+ if (@sections) {
+ $sectionbox .= ' ... '.&mt('hidden in sections').': '.
+ ' '.
+ &select_sections('hidetotals','',\@sections,\@selsec,$noedit,'all').
+ ' ';
+ }
+ $sectionbox .= ' ';
+ $datatable .= ' '.
+ ''.
+ ''.
+ &yesno_radio('hidetotals',\%current,$unsetdefault,$valueyes,$valueno,$noedit,
+ $onclick,$reverse).' '.
+ $sectionbox.
+ '';
+ }
} elsif ($items->{$item}{input} eq 'textbox') {
my $disabled;
if ($noedit) {
|