--- loncom/interface/domainprefs.pm 2024/02/25 06:15:54 1.160.6.118.2.19 +++ loncom/interface/domainprefs.pm 2024/09/01 02:45:08 1.160.6.118.2.25 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.160.6.118.2.19 2024/02/25 06:15:54 raeburn Exp $ +# $Id: domainprefs.pm,v 1.160.6.118.2.25 2024/09/01 02:45:08 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -95,8 +95,7 @@ about default quota sizes for portfolio institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.), but is now also used to manage availability of user tools: i.e., blogs, aboutme page, and portfolios, and the course request tool, -used by course owners to request creation of a course, and to display/store -default quota sizes for Authoring Spaces. +used by course owners to request creation of a course. Outputs: 1 @@ -222,7 +221,7 @@ sub handler { 'coursedefaults','usersessions','loadbalancing', 'requestauthor','selfenrollment','inststatus', 'passwords','ltitools','toolsec','lti','ltisec', - 'wafproxy','ipaccess'],$dom); + 'wafproxy','ipaccess','authordefaults'],$dom); my %encconfig = &Apache::lonnet::get_dom('encconfig',['ltitools','lti','linkprot'],$dom,undef,1); my ($checked_is_home,$is_home); @@ -292,7 +291,7 @@ sub handler { 'contacts','usercreation','selfcreation','usermodification', 'scantron','requestcourses','requestauthor','coursecategories', 'serverstatuses','helpsettings','coursedefaults', - 'ltitools','selfenrollment','usersessions','lti'); + 'authordefaults','ltitools','selfenrollment','usersessions','lti'); my %existing; if (ref($domconfig{'loadbalancing'}) eq 'HASH') { %existing = %{$domconfig{'loadbalancing'}}; @@ -368,11 +367,11 @@ sub handler { modify => \&modify_passwords, }, 'quotas' => - { text => 'Blogs, personal pages/timezones, webDAV/quotas, portfolio', + { text => 'Blogs, personal pages/timezones, portfolio/quotas', help => 'Domain_Configuration_Quotas', header => [{col1 => 'User affiliation', col2 => 'Available tools', - col3 => 'Quotas, MB; (Authoring requires role)',}], + col3 => 'Portfolio quota (MB)',}], print => \&print_quotas, modify => \&modify_quotas, }, @@ -458,6 +457,8 @@ sub handler { header => [{col1 => 'Target user has role', col2 => 'User information updatable in author context'}, {col1 => 'Target user has role', + col2 => 'User information updatable by co-author manager'}, + {col1 => 'Target user has role', col2 => 'User information updatable in course context'}], print => \&print_usermodification, modify => \&modify_usermodification, @@ -612,6 +613,16 @@ sub handler { print => \&print_ipaccess, modify => \&modify_ipaccess, }, + 'authordefaults' => + {text => 'Authoring Space defaults', + help => 'Domain_Configuration_Author_Defaults', + header => [{col1 => 'Defaults which can be overridden by Author', + col2 => 'Settings',}, + {col1 => 'Defaults which can be overridden by a Dom. Coord.', + col2 => 'Settings',},], + print => \&print_authordefaults, + modify => \&modify_authordefaults, + }, ); if (keys(%servers) > 1) { $prefs{'login'} = { text => 'Log-in page options', @@ -809,6 +820,8 @@ sub process_changes { $output = &modify_wafproxy($dom,$action,$lastactref,%domconfig); } elsif ($action eq 'ipaccess') { $output = &modify_ipaccess($dom,$lastactref,%domconfig); + } elsif ($action eq 'authordefaults') { + $output = &modify_authordefaults($dom,$lastactref,%domconfig); } return $output; } @@ -854,6 +867,8 @@ sub print_config_box { $output .= &saml_javascript(); } elsif ($action eq 'ipaccess') { $output .= &ipaccess_javascript($settings); + } elsif ($action eq 'authordefaults') { + $output .= &authordefaults_javascript(); } $output .= ' @@ -895,7 +910,7 @@ sub print_config_box { ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') || ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'directorysrch') || ($action eq 'helpsettings') || ($action eq 'contacts') || ($action eq 'wafproxy') || - ($action eq 'lti') || ($action eq 'ltitools')) { + ($action eq 'lti') || ($action eq 'ltitools') || ($action eq 'authordefaults')) { $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'passwords') { $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal); @@ -932,7 +947,7 @@ sub print_config_box { ($action eq 'usersessions') || ($action eq 'coursecategories') || ($action eq 'contacts') || ($action eq 'passwords') || ($action eq 'defaults') || ($action eq 'lti') || - ($action eq 'ltitools')) { + ($action eq 'ltitools') || ($action eq 'usermodification')) { if ($action eq 'coursecategories') { $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal); $colspan = ' colspan="2"'; @@ -1003,7 +1018,7 @@ sub print_config_box { $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal); } $rowtotal ++; - } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') || + } elsif (($action eq 'coursedefaults') || ($action eq 'authordefaults') || ($action eq 'directorysrch') || ($action eq 'helpsettings') || ($action eq 'wafproxy')) { $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal); @@ -2277,7 +2292,7 @@ sub print_quotas { } else { $context = $action; } - my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations); + my ($datatable,$defaultquota,@usertools,@options,%validations); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $typecount = 0; my ($css_class,%titles); @@ -2291,12 +2306,12 @@ sub print_quotas { @options = ('norequest','approval','automatic'); %titles = &authorrequest_titles(); } else { - @usertools = ('aboutme','blog','webdav','portfolio','timezone'); + @usertools = ('aboutme','blog','portfolio','portaccess','timezone'); %titles = &tool_titles(); } if (ref($types) eq 'ARRAY') { foreach my $type (@{$types}) { - my ($currdefquota,$currauthorquota); + my $currdefquota; unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { if (ref($settings) eq 'HASH') { @@ -2305,9 +2320,6 @@ sub print_quotas { } else { $currdefquota = $settings->{$type}; } - if (ref($settings->{authorquota}) eq 'HASH') { - $currauthorquota = $settings->{authorquota}->{$type}; - } } } if (defined($usertypes->{$type})) { @@ -2425,13 +2437,9 @@ sub print_quotas { ($context eq 'requestauthor')) { $datatable .= ''; } $datatable .= ''; @@ -2440,16 +2448,12 @@ sub print_quotas { } unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { $defaultquota = '20'; - $authorquota = '500'; if (ref($settings) eq 'HASH') { if (ref($settings->{'defaultquota'}) eq 'HASH') { $defaultquota = $settings->{'defaultquota'}->{'default'}; } elsif (defined($settings->{'default'})) { $defaultquota = $settings->{'default'}; } - if (ref($settings->{'authorquota'}) eq 'HASH') { - $authorquota = $settings->{'authorquota'}->{'default'}; - } } } $typecount ++; @@ -2561,12 +2565,9 @@ sub print_quotas { $datatable .= ''; unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { $datatable .= ''; + $defaultquota.'" size="5" />'; } $datatable .= ''; $typecount ++; @@ -3726,6 +3727,39 @@ $jstext ENDSCRIPT } +sub authordefaults_javascript { + my %alert = &Apache::lonlocal::texthash ( + reqd => 'Warning: at least one editor needs to be available.', + rest => 'Unchecking this editor disallowed while others unchecked.', + ); + &js_escape(\%alert); + return <<"ENDSCRIPT"; + + +ENDSCRIPT +} + sub print_autoenroll { my ($dom,$settings,$rowtotal) = @_; my $autorun = &Apache::lonnet::auto_run(undef,$dom), @@ -5998,7 +6032,7 @@ sub print_coursedefaults { my $itemcount = 1; my %choices = &Apache::lonlocal::texthash ( uploadquota => 'Default quota for files uploaded directly to course/community using Course Editor (MB)', - coursequota => 'Default cumulative quota for all group portfolio spaces in course', + coursequota => 'Default cumulative quota for all group portfolio spaces in course (MB)', anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys', coursecredits => 'Credits can be specified for courses', uselcmath => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)', @@ -6011,6 +6045,7 @@ sub print_coursedefaults { ltiauth => 'Student username in LTI launch of deep-linked URL can be accepted without re-authentication', domexttool => 'External Tools defined in the domain may be used in courses/communities (by type)', exttool => 'External Tools can be defined and configured in courses/communities (by type)', + crseditors => 'Available editors for web pages and/or problems created in a course/community', ); my %staticdefaults = ( anonsurvey_threshold => 10, @@ -6020,6 +6055,7 @@ sub print_coursedefaults { mysqltables => 172800, domexttool => 1, exttool => 0, + crseditors => ['edit','xml'], ); if ($position eq 'top') { %defaultchecked = ( @@ -6139,6 +6175,7 @@ sub print_coursedefaults { my $ltiauth = 0; my %domexttool; my %exttool; + my %crseditors; my @types = ('official','unofficial','community','textbook'); if (ref($settings) eq 'HASH') { if ($settings->{'ltiauth'}) { @@ -6164,6 +6201,15 @@ sub print_coursedefaults { } } } + if (ref($settings->{'crseditors'}) eq 'ARRAY') { + foreach my $editor (@{$settings->{'crseditors'}}) { + $crseditors{$editor} = ' checked="checked"'; + } + } else { + foreach my $editor (@{$staticdefaults{'crseditors'}}) { + $crseditors{$editor} = ' checked="checked"'; + } + } $currdefresponder = $settings->{'anonsurvey_threshold'}; if (ref($settings->{'uploadquota'}) eq 'HASH') { foreach my $type (keys(%{$settings->{'uploadquota'}})) { @@ -6224,6 +6270,9 @@ sub print_coursedefaults { $domexttool{$type} = ' checked="checked"'; } } + foreach my $editor (@{$staticdefaults{'crseditors'}}) { + $crseditors{$editor} = ' checked="checked"'; + } } if (!$currdefresponder) { $currdefresponder = $staticdefaults{'anonsurvey_threshold'}; @@ -6351,9 +6400,9 @@ sub print_coursedefaults { foreach my $type (@types) { $datatable .= ''."\n"; + &mt($type).''."\n"; } $datatable .= '
'. - ''.&mt('Portfolio').': '. + ''. ''.(' ' x 2). - ''.&mt('Authoring').': '. - '
'. - ''.&mt('Portfolio').': '. + ''. ''.(' ' x2). - ''.&mt('Authoring').': '. - '
'. ''. - ''. - &mt($type).'
'."\n"; $itemcount ++; @@ -6366,9 +6415,26 @@ sub print_coursedefaults { foreach my $type (@types) { $datatable .= ''. ''. - ''. - &mt($type).''."\n"; + &mt($type).''."\n"; + } + $datatable .= ''."\n"; + $itemcount ++; + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''. + $choices{'crseditors'}. + ''. + ''. + ''; + my @editors = ('edit','xml','daxe'); + my %editornames = &crseditor_titles(); + foreach my $editor (@editors) { + $datatable .= ''."\n"; } $datatable .= '
'. + ''. + '
'."\n"; } @@ -6376,6 +6442,234 @@ sub print_coursedefaults { return $datatable; } +sub crseditor_titles { + return &Apache::lonlocal::texthash( + edit => 'Standard editor (Edit)', + xml => 'Text editor (EditXML)', + daxe => 'Daxe editor (Daxe)', + ); +} + +sub print_authordefaults { + my ($position,$dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable,%checkedon,%checkedoff); + my $itemcount = 1; + my %titles = &authordefaults_titles(); + if ($position eq 'top') { + my %defaultchecked = ( + 'nocodemirror' => 'off', + 'daxecollapse' => 'off', + 'domcoordacc' => 'on', + ); + my @toggles = ('nocodemirror','daxecollapse','domcoordacc'); + ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, + \%titles,$itemcount); + my %staticdefaults = ( + 'copyright' => 'default', + 'sourceavail' => 'closed', + ); + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my %currrights; + foreach my $item ('copyright','sourceavail') { + $currrights{$item} = $staticdefaults{$item}; + if (ref($settings) eq 'HASH') { + if (exists($settings->{$item})) { + $currrights{$item} = $settings->{$item}; + } + } + } + $datatable .= ''. + ''.$titles{'copyright'}. + ''. + &selectbox('copyright',$currrights{'copyright'},'', + \&Apache::loncommon::copyrightdescription, + (grep !/^priv|custom$/,(&Apache::loncommon::copyrightids))). + ''."\n"; + $itemcount ++; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''.$titles{'sourceavail'}. + ''. + &selectbox('sourceavail',$currrights{'sourceavail'},'', + \&Apache::loncommon::source_copyrightdescription, + (&Apache::loncommon::source_copyrightids)). + ''."\n"; + } else { + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + my $curreditors; + my %staticdefaults = ( + editors => ['edit','xml'], + authorquota => 500, + webdav => 0, + ); + my $curreditors = $staticdefaults{'editors'}; + if ((ref($settings) eq 'HASH') && + (ref($settings->{'editors'}) eq 'ARRAY')) { + $curreditors = $settings->{'editors'}; + } else { + $curreditors = $staticdefaults{'editors'}; + } + my @editors = ('edit','xml','daxe'); + $datatable = ''."\n". + ''.$titles{'editors'}.''."\n". + ''."\n". + ''; + foreach my $editor (@editors) { + my $checked; + if (grep(/^\Q$editor\E$/,@{$curreditors})) { + $checked = ' checked="checked"'; + } + $datatable .= ' '; + } + $datatable .= ''."\n".''."\n".''."\n"; + $itemcount ++; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + my @insttypes; + if (ref($types) eq 'ARRAY') { + @insttypes = @{$types}; + } + my $typecount = 0; + my %domconf = &Apache::lonnet::get_dom('configuration',['quotas'],$dom); + my @items = ('webdav','authorquota'); + my %quotas; + if (ref($domconf{'quotas'}) eq 'HASH') { + %quotas = %{$domconf{'quotas'}}; + foreach my $item (@items) { + if (ref($quotas{$item}) eq 'HASH') { + foreach my $type (@insttypes,'default') { + if ($item eq 'authorquota') { + if ($quotas{$item}{$type} !~ /^\d+$/) { + $quotas{$item}{$type} = $staticdefaults{$item}; + } + } elsif ($item eq 'webdav') { + if ($quotas{$item}{$type} !~ /^(0|1)$/) { + $quotas{$item}{$type} = $staticdefaults{$item}; + } + } + } + } else { + foreach my $type (@insttypes,'default') { + $quotas{$item}{$type} = $staticdefaults{$item}; + } + } + } + } else { + foreach my $item (@items) { + foreach my $type (@insttypes,'default') { + $quotas{$item}{$type} = $staticdefaults{$item}; + } + } + } + if (ref($usertypes) eq 'HASH') { + my $numinrow = 4; + my $onclick = ''; + $datatable .= &insttypes_row(\%quotas,$types,$usertypes,$dom, + $numinrow,$othertitle,'authorquota', + \$itemcount,$onclick); + $itemcount ++; + $datatable .= &insttypes_row(\%quotas,$types,$usertypes,$dom, + $numinrow,$othertitle,'webdav', + \$itemcount); + $itemcount ++; + } + my $checkedno = ' checked="checked"'; + my ($checkedon,$checkedoff); + if (ref($quotas{'webdav'}) eq 'HASH') { + if ($quotas{'webdav'}{'_LC_adv'} =~ /^0|1$/) { + if ($quotas{'webdav'}{'_LC_adv'}) { + $checkedon = $checkedno; + } else { + $checkedoff = $checkedno; + } + undef($checkedno); + } + } + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''.$titles{'webdav_LC_adv'}.'
'. + $titles{'webdav_LC_adv_over'}. + ''. + ''; + foreach my $option ('none','off','on') { + my ($text,$val,$checked); + if ($option eq 'none') { + $text = $titles{'none'}; + $val = ''; + $checked = $checkedno; + } elsif ($option eq 'off') { + $text = $titles{'overoff'}; + $val = 0; + $checked = $checkedoff; + } elsif ($option eq 'on') { + $text = $titles{'overon'}; + $val = 1; + $checked = $checkedon; + } + $datatable .= '  '; + } + $datatable .= ''; + $itemcount ++; + my %defchecked = ( + 'archive' => 'off', + ); + my @toggles = ('archive'); + (my $archive,$itemcount) = &radiobutton_prefs($settings,['archive'], + {'archive' => 'off'}, + \%titles,$itemcount); + $datatable .= $archive."\n"; + $itemcount ++; + } + $$rowtotal += $itemcount; + return $datatable; +} + +sub authordefaults_titles { + return &Apache::lonlocal::texthash( + copyright => 'Copyright/Distribution', + sourceavail => ' Source Available', + editors => 'Available Editors', + webdav => 'WebDAV', + authorquota => 'Authoring Space quotas (MB)', + nocodemirror => 'Deactivate CodeMirror for EditXML editor', + daxecollapse => 'Daxe editor: LON-CAPA standard menus start collapsed', + domcoordacc => 'Dom. Coords. can enter Authoring Spaces in domain', + edit => 'Standard editor (Edit)', + xml => 'Text editor (EditXML)', + daxe => 'Daxe editor (Daxe)', + webdav_LC_adv => 'WebDAV access for LON-CAPA "advanced" users', + webdav_LC_adv_over => '(overrides access based on affiliation, if set)', + none => 'No override set', + overon => 'Override -- webDAV on', + overoff => 'Override -- webDAV off', + archive => 'Authors can download tar.gz file of Authoring Space', + ); +} + +sub selectbox { + my ($name,$value,$readonly,$functionref,@idlist)=@_; + my $selout = ''; + return $selout; +} + sub print_selfenrollment { my ($position,$dom,$settings,$rowtotal) = @_; my ($css_class,$datatable); @@ -8253,8 +8547,8 @@ sub tool_titles { my %titles = &Apache::lonlocal::texthash ( aboutme => 'Personal web page', blog => 'Blog', - webdav => 'WebDAV', portfolio => 'Portfolio', + portaccess => 'Share portfolio files', timezone => 'Can set time zone', official => 'Official courses (with institutional codes)', unofficial => 'Unofficial courses', @@ -9155,6 +9449,15 @@ sub print_usermodification { $$rowtotal ++; $rowcount ++; } + } elsif ($position eq 'middle') { + $rowcount = 0; + $context = 'coauthor'; + foreach my $role ('ca','aa') { + $datatable .= &modifiable_userdata_row($context,$role,$settings, + $numinrow,$rowcount); + $$rowtotal ++; + $rowcount ++; + } } elsif ($position eq 'bottom') { $context = 'course'; $rowcount = 0; @@ -10575,6 +10878,8 @@ sub modifiable_userdata_row { } else { if ($context eq 'lti') { $prefix = 'lti'; + } elsif ($context eq 'coauthor') { + $prefix = 'cacanmodify'; } $output .= '