From raeburn at source.lon-capa.org Mon Dec 8 21:29:03 2025 From: raeburn at source.lon-capa.org (raeburn) Date: Tue, 09 Dec 2025 02:29:03 -0000 Subject: [LON-CAPA-cvs] cvs: loncom /interface createaccount.pm domainprefs.pm loncommon.pm lonconfigsettings.pm lonsupportreq.pm resetpw.pm Message-ID: raeburn Tue Dec 9 02:29:03 2025 EDT Modified files: /loncom/interface domainprefs.pm createaccount.pm loncommon.pm lonconfigsettings.pm lonsupportreq.pm resetpw.pm Log: - Supported third party Captcha services now recaptcha v2 and v3, hcaptcha, and turnstile. -------------- next part -------------- Index: loncom/interface/domainprefs.pm diff -u loncom/interface/domainprefs.pm:1.453 loncom/interface/domainprefs.pm:1.454 --- loncom/interface/domainprefs.pm:1.453 Wed Aug 13 19:13:09 2025 +++ loncom/interface/domainprefs.pm Tue Dec 9 02:29:03 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.453 2025/08/13 19:13:09 raeburn Exp $ +# $Id: domainprefs.pm,v 1.454 2025/12/09 02:29:03 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -10478,10 +10478,14 @@ sub captcha_choice { my ($context,$settings,$itemcount,$customcss,$rowstyle) = @_; - my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext, - $vertext,$currver); + my ($currpub,$currpriv,$currtype,$currver,%checked,$rowname, + $dispprov,$dispver,$dispkeys,$threshold,$threshtext,$threshentry); my %lt = &captcha_phrases(); - $keyentry = 'hidden'; + $threshtext = ''; + $threshentry = 'hidden'; + $dispkeys = 'none'; + $dispprov = 'none'; + $dispver = 'none'; my $colspan=2; if ($context eq 'cancreate') { $rowname = &mt('CAPTCHA validation'); @@ -10497,14 +10501,24 @@ } else { $checked{'original'} = ' checked="checked"'; } - if ($settings->{'captcha'} eq 'recaptcha') { - $pubtext = $lt{'pub'}; - $privtext = $lt{'priv'}; - $keyentry = 'text'; - $vertext = $lt{'ver'}; - $currver = $settings->{'recaptchaversion'}; - if ($currver ne '2') { - $currver = 1; + if (($settings->{'captcha'} eq 'recaptcha') || + ($settings->{'captcha'} eq 'hcaptcha') || + ($settings->{'captcha'} eq 'turnstile')) { + $checked{'successor'} = ' checked="checked"'; + $currtype = $settings->{'captcha'}; + $dispkeys = 'block'; + $dispprov = 'block'; + if ($settings->{'captcha'} eq 'recaptcha') { + $dispver = 'block'; + $currver = $settings->{'recaptchaversion'}; + if ($currver eq '1') { + $currver = 2; + } + if ($currver eq '3') { + $threshold = $settings->{'captchathreshold'}; + $threshtext = $lt{'threshold'}; + $threshentry = 'text'; + } } } if (ref($settings->{'recaptchakeys'}) eq 'HASH') { @@ -10530,32 +10544,61 @@ } my $output = ''. ''.$rowname.''."\n". - ''; return $output; @@ -13036,16 +13079,16 @@ $pubkey = $loginhash{'login'}{$item}{'public'}; $privkey = $loginhash{'login'}{$item}{'private'}; } - my $chgtxt .= &mt('ReCAPTCHA keys changes').'
'."\n"; - foreach my $option ('original','recaptcha','notused') { + ''."\n". + $output .= ''."\n". '
'.$lt{'captcha'}.''."\n"; + foreach my $option ('original','successor','notused') { $output .= ''; unless ($option eq 'notused') { $output .= (' 'x2)."\n"; } } # -# Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit: -# https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple -# servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu) -# specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain. +# Note: If reCaptcha is to be used for LON-CAPA servers in a domain, a domain coordinator should visit: +# https://cloud.google.com/security/products/recaptcha and generate a site key and secret key. For domains +# with multiple servers a single key pair will be used for all servers, so the internet domain +# (e.g., yourcollege.edu) specified for use with the key should be broad enough to accommodate all servers +# in the LON-CAPA domain. If a change is made from using reCaptcha v2 to using v3, then a new pair +# needs to be generated via the Google Cloud dashboard. +# +# Similarly, if hCaptcha is to be used, a site key and secret key will need to be generated by adding a +# new site at https://dashboard.hcaptcha.com/, and if Turnstile is to be used a site key and secret key +# will need to be created by visiting https://dash.cloudflare.com and adding a new Turnstile widget. # - $output .= '
'."\n". - ''.$pubtext.' '."\n". - '
'."\n". - ''.$privtext.' '."\n". - '
'. - ''.$vertext.' '."\n". - '
'. + '
'. + ''.$lt{'type'}.''."\n"; + foreach my $type ('recaptcha','hcaptcha','turnstile') { + my $provider = $lt{$type}; + my $checked; + if ($currtype eq $type) { + $checked = ' checked="checked"'; + } + $output .= '   '; + } + $output .= '

'. + '
'.$lt{'ver'}.''."\n". + ''; + foreach my $poss ('2','3') { + my $checked; + if ($currver eq $poss) { + $checked = ' checked="checked"' + } + $output .= '  '; + } + $output .= ''. + ''.$threshtext.''."\n". + ' '."\n". + '

'. + '
'.$lt{'keys'}.''."\n". + ''.$lt{'pub'}.': '. + ''. + '
'."\n". + ''.$lt{'priv'}.': '. + ''."\n". + '

'."\n". '
'."\n". '
'.$role_selects.'' .'
'. Index: loncom/interface/courseprefs.pm diff -u loncom/interface/courseprefs.pm:1.136 loncom/interface/courseprefs.pm:1.137 --- loncom/interface/courseprefs.pm:1.136 Sat Jun 14 02:50:25 2025 +++ loncom/interface/courseprefs.pm Sat Dec 13 05:56:01 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set configuration settings for a course # -# $Id: courseprefs.pm,v 1.136 2025/06/14 02:50:25 raeburn Exp $ +# $Id: courseprefs.pm,v 1.137 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -4641,7 +4641,9 @@ } else { $categoriesform .= &mt('No categories defined in this domain.'); } - $r->print($start_page.$categoriesform.$end_page); + $r->print($start_page."\n". + '
'."\n". + $categoriesform.'
'.$end_page); return; } @@ -5053,7 +5055,9 @@ my $title = 'Version Constraints'; my $start_page = &Apache::loncommon::start_page($title,undef,{'only_body' => 1,}); - $r->print($start_page.$top_header); + $r->print($start_page."\n". + '
'."\n". + $top_header); if ($output) { $r->print($output); if (defined($navmap) || $supptools) { @@ -5066,7 +5070,7 @@ &mt('No version requirements from resource content or settings.'). '

'); } - $r->print(&Apache::loncommon::end_page()); + $r->print('
'.&Apache::loncommon::end_page()); my ($currmajor,$currminor) = split(/\./,$loncaparev); if (($currmajor != $reqdmajor) || ($currminor != $reqdminor)) { return 1; Index: loncom/interface/createaccount.pm diff -u loncom/interface/createaccount.pm:1.91 loncom/interface/createaccount.pm:1.92 --- loncom/interface/createaccount.pm:1.91 Tue Dec 9 02:29:03 2025 +++ loncom/interface/createaccount.pm Sat Dec 13 05:56:01 2025 @@ -4,7 +4,7 @@ # kerberos, or SSO) or an e-mail address. Requests to use an e-mail address as # username may be processed automatically, or may be queued for approval. # -# $Id: createaccount.pm,v 1.91 2025/12/09 02:29:03 raeburn Exp $ +# $Id: createaccount.pm,v 1.92 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -107,7 +107,7 @@ &Apache::loncommon::start_page('Already logged in',undef,$args); my $end_page = &Apache::loncommon::end_page(); - $r->print($start_page."\n".'
'. + $r->print($start_page."\n".'
'. '

'.&mt('You are already logged in').'

'. '

'.&mt('Please either [_1]continue the current session[_2] or [_3]log out[_4].', '','','',''). @@ -382,6 +382,7 @@ ({href=>$url, text=>$pagetitle}); $r->print(&Apache::lonhtmlcommon::breadcrumbs('Create account')); + $r->print("\n".'

'."\n"); return; } @@ -397,7 +398,7 @@ 'cmiddlename','cgeneration','cpermanentemail','cid']). ''); } - $r->print(&Apache::loncommon::end_page()); + $r->print('
'.&Apache::loncommon::end_page()); } sub get_usertype { @@ -914,7 +915,7 @@ $contact_email,$courseid,$emailusername,$usertype, $uname); } - return '
'.$output.'
'; + return '
'.$output.'
'; } sub call_rulecheck { Index: loncom/interface/lonaboutme.pm diff -u loncom/interface/lonaboutme.pm:1.171 loncom/interface/lonaboutme.pm:1.172 --- loncom/interface/lonaboutme.pm:1.171 Sun Mar 16 21:04:09 2025 +++ loncom/interface/lonaboutme.pm Sat Dec 13 05:56:01 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # Personal Information Page # -# $Id: lonaboutme.pm,v 1.171 2025/03/16 21:04:09 raeburn Exp $ +# $Id: lonaboutme.pm,v 1.172 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -126,12 +126,13 @@ $r->print('\noindent{\large\textbf{'.&mt('No user personal information page available').'}}\\\\\\\\'); } else { $r->print(&Apache::loncommon::start_page("Personal Information Page")); + $r->print("\n".'
'."\n"); $r->print('

'.&mt('No user personal information page available') .'

'. &mt('This is a result of one of the following:').'
    '. '
  • '.&mt('The administrator of this domain has disabled personal information page functionality for this specific user.').'
  • '. '
  • '.&mt('The domain has been configured to disable, by default, personal information page functionality for all users in the domain.').'
  • '. '
'); - $r->print(&Apache::loncommon::end_page()); + $r->print('
'.&Apache::loncommon::end_page()); } return OK; } @@ -189,9 +190,10 @@ my $start_page = &Apache::loncommon::start_page( "Course Information",undef,$args); $r->print($start_page); + $r->print("\n".'
'."\n"); $r->print('

'.&mt('Group Portfolio').'

'); &print_portfiles_link($r,$is_course); - $r->print(&Apache::loncommon::end_page()); + $r->print('
'.&Apache::loncommon::end_page()); } return OK; } @@ -257,7 +259,8 @@ if ($target eq 'tex') { $r->print('\noindent{\large\textbf{'.&mt('No user personal information page available').'}}\\\\\\\\'); } else { - $r->print($blocktext); + $r->print("\n".'
'."\n"); + $r->print($blocktext.'
'); } $r->print(&Apache::loncommon::end_page()); return OK; @@ -266,6 +269,7 @@ #----------------Print Privacy note (edit mode) or last modified date. if ($target ne 'tex') { + $r->print("\n".'
'."\n"); #Print Privacy Note if ($allowed) { $r->print('
' @@ -435,7 +439,7 @@ if ($env{'form.popup'}) { $r->print('

'.&mt('Close window').'

'); } - $r->print(&Apache::loncommon::end_page()); + $r->print('
'.&Apache::loncommon::end_page()); } else { $r->print('\end{document}'); } @@ -558,6 +562,7 @@ $args->{bread_crumbs} = $brcrum; } $output = &Apache::loncommon::start_page('Viewable group portfolio files',undef,$args). + "\n".'
'."\n". '

'.&mt('Group Portfolio files').'

'; } else { if ($env{'request.course.id'} && $env{'form.register'}) { @@ -577,6 +582,7 @@ $output = &Apache::loncommon::start_page('Viewable portfolio files', undef,$args). + "\n".'
'."\n". '

'.&mt('Portfolio files for [_1]',$name).'

'; } $r->print($output); Index: loncom/interface/lonblockingmenu.pm diff -u loncom/interface/lonblockingmenu.pm:1.32 loncom/interface/lonblockingmenu.pm:1.33 --- loncom/interface/lonblockingmenu.pm:1.32 Tue Dec 31 19:28:29 2024 +++ loncom/interface/lonblockingmenu.pm Sat Dec 13 05:56:01 2025 @@ -2,7 +2,7 @@ # Routines for configuring blocking of access to collaborative functions, # and specific resources during an exam # -# $Id: lonblockingmenu.pm,v 1.32 2024/12/31 19:28:29 raeburn Exp $ +# $Id: lonblockingmenu.pm,v 1.33 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -567,8 +567,8 @@ $r->print( &Apache::loncommon::start_page('Blocking communication/content access',$js). - &Apache::lonhtmlcommon::breadcrumbs('Blocking communication/content access')); - + &Apache::lonhtmlcommon::breadcrumbs('Blocking communication/content access')."\n". + '
'."\n"); my $usertype; if ($crstype eq 'Community') { $usertype = 'members'; @@ -690,7 +690,7 @@ END } - $r->print(''. + $r->print('
'. &Apache::loncommon::end_page()); return OK; } Index: loncom/interface/loncommon.pm diff -u loncom/interface/loncommon.pm:1.1487 loncom/interface/loncommon.pm:1.1488 --- loncom/interface/loncommon.pm:1.1487 Tue Dec 9 02:29:03 2025 +++ loncom/interface/loncommon.pm Sat Dec 13 05:56:01 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.1487 2025/12/09 02:29:03 raeburn Exp $ +# $Id: loncommon.pm,v 1.1488 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -5359,7 +5359,7 @@ $userview=~s/\<\/html\>//gi; $userview=~s/\//gi; $userview=~s/\<\/head\>//gi; - $userview=~s/\Q
'. + &mt('Skip to main content').''; &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']); @@ -7526,6 +7528,24 @@ display: inline; } +.LC_skip-to-main-content-link { + position: absolute; + left: -9999px; + z-index: 999; + padding: 1em; + font-size: 1.2em; + font-weight: bold; + background-color: $pgbg_or_bgcolor; + color: $font; + opacity: 0; +} + +.LC_skip-to-main-content-link:focus { + left: 0%; + transform: translateX(0%); + opacity: 1; +} + .LC_heading_2 { font-size: 1.17em; } @@ -11158,7 +11178,7 @@ my $page = &Apache::loncommon::start_page($title,'',\%displayargs)."\n". - '
'. + '
'. '

'.$msg.'

'. '
'. &Apache::loncommon::end_page(); @@ -19387,7 +19407,8 @@ sub check_release_result { my ($switchwarning,$switchserver) = @_; my $output = &start_page('Selected course unavailable on this server'). - ''.&Apache::loncommon::end_page()); return; } Index: loncom/interface/loncoursegroups.pm diff -u loncom/interface/loncoursegroups.pm:1.132 loncom/interface/loncoursegroups.pm:1.133 --- loncom/interface/loncoursegroups.pm:1.132 Sat Jul 29 20:33:25 2023 +++ loncom/interface/loncoursegroups.pm Sat Dec 13 05:56:01 2025 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: loncoursegroups.pm,v 1.132 2023/07/29 20:33:25 raeburn Exp $ +# $Id: loncoursegroups.pm,v 1.133 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1527,6 +1527,7 @@ {'add_entries' => $loaditems,}); my $output = <<"END"; $start_page +
END @@ -1566,6 +1567,7 @@ return(< +
$end_page ENDFOOT } Index: loncom/interface/loncourserespicker.pm diff -u loncom/interface/loncourserespicker.pm:1.21 loncom/interface/loncourserespicker.pm:1.22 --- loncom/interface/loncourserespicker.pm:1.21 Thu Dec 26 17:12:36 2024 +++ loncom/interface/loncourserespicker.pm Sat Dec 13 05:56:01 2025 @@ -1,6 +1,6 @@ # The LearningOnline Network # -# $Id: loncourserespicker.pm,v 1.21 2024/12/26 17:12:36 raeburn Exp $ +# $Id: loncourserespicker.pm,v 1.22 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -984,12 +984,14 @@ my $outcome; if (!defined($navmap)) { if ($context eq 'imsexport') { - $outcome = &Apache::loncommon::start_page('Export '.$crstype.' to IMS Package'). - '

'.&mt('IMS Export Failed').'

'; + $outcome = &Apache::loncommon::start_page('Export '.$crstype.' to IMS Package')."\n". + '
'."\n". + '

'.&mt('IMS Export Failed').'

'; } elsif ($context eq 'examblock') { $outcome = &Apache::loncommon::start_page('Selection of Resources for Blocking', - undef,{'only_body' => 1,}). - '

'.&mt('Resource Display Failed').'

'; + undef,{'only_body' => 1,})."\n". + '
'."\n". + '

'.&mt('Resource Display Failed').'

'; } elsif ($context eq 'dumpdocs') { $outcome = '

'.&mt('Copying to Authoring Space unavailable').'

'; } elsif ($context eq 'shorturls') { Index: loncom/interface/loncreatecourse.pm diff -u loncom/interface/loncreatecourse.pm:1.178 loncom/interface/loncreatecourse.pm:1.179 --- loncom/interface/loncreatecourse.pm:1.178 Tue Mar 18 18:57:28 2025 +++ loncom/interface/loncreatecourse.pm Sat Dec 13 05:56:01 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # Create a course # -# $Id: loncreatecourse.pm,v 1.178 2025/03/18 18:57:28 raeburn Exp $ +# $Id: loncreatecourse.pm,v 1.179 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -909,7 +909,9 @@ $r->print( $start_page .$crumbs + .'
' .&Apache::lonhtmlcommon::generate_menu(@menu) + .'
' .$end_page ); } Index: loncom/interface/loncreateuser.pm diff -u loncom/interface/loncreateuser.pm:1.486 loncom/interface/loncreateuser.pm:1.487 --- loncom/interface/loncreateuser.pm:1.486 Mon Dec 1 06:23:49 2025 +++ loncom/interface/loncreateuser.pm Sat Dec 13 05:56:01 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Create a user # -# $Id: loncreateuser.pm,v 1.486 2025/12/01 06:23:49 raeburn Exp $ +# $Id: loncreateuser.pm,v 1.487 2025/12/13 05:56:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -957,6 +957,7 @@ bread_crumbs_component => 'User Management', add_entries => \%loaditems,}; $r->print(&Apache::loncommon::start_page('User Management',$jscript,$args)); + $r->print("\n".'
'."\n"); my %lt=&Apache::lonlocal::texthash( 'srst' => 'Search for a user and enroll as a student', @@ -1287,6 +1288,7 @@ help => $helpitem} ); $r->print(&Apache::loncommon::start_page('User Management',$jscript,{bread_crumbs => $brcrum})); + $r->print("\n".'
'."\n"); if ($env{'form.action'} eq 'singleuser') { my $readonly; if (($context eq 'domain') && (!&Apache::lonnet::allowed('mau',$srch->{'srchdomain'}))) { @@ -1561,7 +1563,6 @@ } my $start_page = &Apache::loncommon::start_page('User Management',$js,$args); - my $forminfo =<<"ENDFORMINFO";
@@ -1631,6 +1632,7 @@ ); $r->print(< $response $forminfo ENDREDIR } - $r->print('
'."\n"); + $r->print('
'."\n"); return; } @@ -744,7 +744,7 @@

$accessheader

$message

-
+
@@ -777,7 +777,7 @@ $swinfo // ]]> -
+

$accessheader

$preamble

@@ -1397,7 +1397,7 @@ } } if ($nochoose) { - $r->print("
+ $r->print("

".&mt('Sorry ...')."

\n". &mt('This action is currently not authorized.').''); if ($error && $norolelist) { @@ -1411,6 +1411,7 @@ $r->print('
'.&Apache::loncommon::end_page()); return OK; } else { + $r->print('
'."\n"); if ($updateresult || $reqauthor || $hotlist) { my $showresult = '
'; if ($updateresult) { @@ -1684,7 +1685,7 @@ .&mt('This LON-CAPA server is version [_1]',$r->dir_config('lonVersion')) .'

'); } - $r->print(&Apache::loncommon::end_page()); + $r->print('
'."\n".&Apache::loncommon::end_page()); return OK; } Index: loncom/homework/daxepage.pm diff -u loncom/homework/daxepage.pm:1.18 loncom/homework/daxepage.pm:1.19 --- loncom/homework/daxepage.pm:1.18 Fri Feb 21 06:09:37 2025 +++ loncom/homework/daxepage.pm Sat Dec 13 05:56:03 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # Page with Daxe on the left side and the preview on the right side # -# $Id: daxepage.pm,v 1.18 2025/02/21 06:09:37 raeburn Exp $ +# $Id: daxepage.pm,v 1.19 2025/12/13 05:56:03 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -179,7 +179,7 @@ $request->print(<<"ENDFRAME"); $startpage $script -
+

$lt{'daxe'}

Index: loncom/homework/structuretags.pm diff -u loncom/homework/structuretags.pm:1.595 loncom/homework/structuretags.pm:1.596 --- loncom/homework/structuretags.pm:1.595 Sun Aug 24 21:43:23 2025 +++ loncom/homework/structuretags.pm Sat Dec 13 05:56:03 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # definition of tags that give a structure to a document # -# $Id: structuretags.pm,v 1.595 2025/08/24 21:43:23 raeburn Exp $ +# $Id: structuretags.pm,v 1.596 2025/12/13 05:56:03 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -597,7 +597,7 @@ \%body_args); $page_start .= $pageheader; if ($target eq 'web') { - $page_start .= '
'."\n"; + $page_start .= '
'."\n"; } if (!defined($found{'body'}) && $env{'request.state'} ne 'construct' Index: loncom/lonnet/perl/lonnet.pm diff -u loncom/lonnet/perl/lonnet.pm:1.1541 loncom/lonnet/perl/lonnet.pm:1.1542 --- loncom/lonnet/perl/lonnet.pm:1.1541 Mon Aug 4 18:42:04 2025 +++ loncom/lonnet/perl/lonnet.pm Sat Dec 13 05:56:04 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.1541 2025/08/04 18:42:04 raeburn Exp $ +# $Id: lonnet.pm,v 1.1542 2025/12/13 05:56:04 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -3734,7 +3734,7 @@ $output=~s|//(\s*)?\s||gs; $output=~s/^.*?\]*\>//si; $output=~s/\<\/body\s*\>.*?$//si; - $output=~s{\Q
\E}{
}gs; + $output=~s{\Q
\E}{
}gs; if (wantarray) { return ($output, $response); } else { Index: rat/lonpage.pm diff -u rat/lonpage.pm:1.146 rat/lonpage.pm:1.147 --- rat/lonpage.pm:1.146 Sun Aug 24 21:43:23 2025 +++ rat/lonpage.pm Sat Dec 13 05:56:04 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Page Handler # -# $Id: lonpage.pm,v 1.146 2025/08/24 21:43:23 raeburn Exp $ +# $Id: lonpage.pm,v 1.147 2025/12/13 05:56:04 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -425,7 +425,7 @@ } my $output=Apache::lonnet::ssi($src,%posthash); $output=~s|//(\s*)?\s||gs; - $output=~s{\Q
\E}{
}gs; + $output=~s{\Q
\E}{
}gs; if (($target eq 'tex') || ($target eq 'tex_answer')) { $output =~ s/^([^&]+)\\begin\{document}//; $output =~ s/\\end\{document}//; From raeburn at source.lon-capa.org Sat Dec 13 08:25:46 2025 From: raeburn at source.lon-capa.org (raeburn) Date: Sat, 13 Dec 2025 13:25:46 -0000 Subject: [LON-CAPA-cvs] cvs: loncom /interface loncommunicate.pm Message-ID: raeburn Sat Dec 13 13:25:46 2025 EDT Modified files: /loncom/interface loncommunicate.pm Log: - Replace tabs with spaces in several indents. Index: loncom/interface/loncommunicate.pm diff -u loncom/interface/loncommunicate.pm:1.48 loncom/interface/loncommunicate.pm:1.49 --- loncom/interface/loncommunicate.pm:1.48 Tue Jan 18 17:33:13 2022 +++ loncom/interface/loncommunicate.pm Sat Dec 13 13:25:46 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # Communicate # -# $Id: loncommunicate.pm,v 1.48 2022/01/18 17:33:13 raeburn Exp $ +# $Id: loncommunicate.pm,v 1.49 2025/12/13 13:25:46 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -90,23 +90,23 @@ {categorytitle => 'Send Messages', items => [ {url => '/adm/email?compose=individual', - permission => 'F', - icon => 'mail-message-new.png', + permission => 'F', + icon => 'mail-message-new.png', linktext => 'New Message', linktitle => 'Send a message to users.'}, {url => '/adm/email?compose=group', - permission => "$can_srm", + permission => "$can_srm", icon => 'mail-reply-all.png', linktext => 'New Broadcast Message', - help => 'Course_Broadcast_Message', + help => 'Course_Broadcast_Message', linktitle => "Send a broadcast message to members of this $crstype and/or other users."}, - {url => '/adm/email?compose=upload', - permission => "$can_srm", + {url => '/adm/email?compose=upload', + permission => "$can_srm", icon => 'fromfile.png', linktext => 'New Messages from File', - linktitle => 'Create a message from file and send to users.'}, + linktitle => 'Create a message from file and send to users.'}, ]}, ); } @@ -115,16 +115,16 @@ push(@reports,{categorytitle => 'Message Administration', items => [ {url => '/adm/email?recordftf=query', - permission => "$can_dff", + permission => "$can_dff", icon => 'messalog.png', linktext => 'Message Log for Selected Users', - help => 'Course_Face_To_Face_Records,Course_Critical_Message', + help => 'Course_Face_To_Face_Records,Course_Critical_Message', linktitle => "User notes, records of face-to-face discussions, critical messages, broadcast messages and archived messages in $crstype."}, {url => '/adm/setblock?caller=email', - permission => "$can_dcm", + permission => "$can_dcm", icon => 'comblock.png', - linktext => 'Communication Blocking', + linktext => 'Communication Blocking', linktitle => "Blocking of $usertype communication during exams."}, ]}); } From raeburn at source.lon-capa.org Sat Dec 13 08:33:33 2025 From: raeburn at source.lon-capa.org (raeburn) Date: Sat, 13 Dec 2025 13:33:33 -0000 Subject: [LON-CAPA-cvs] cvs: loncom /homework grades.pm /interface loncommunicate.pm lonconfigsettings.pm loncoursegroups.pm loncreatecourse.pm loncreateuser.pm londocs.pm lonhtmlcommon.pm lonmenu.pm lonmodifycourse.pm lonnotify.pm lonparmset.pm lonpreferences.pm lonstatistics.pm Message-ID: raeburn Sat Dec 13 13:33:33 2025 EDT Modified files: /loncom/interface lonconfigsettings.pm loncommunicate.pm loncoursegroups.pm loncreatecourse.pm loncreateuser.pm londocs.pm lonhtmlcommon.pm lonmenu.pm lonmodifycourse.pm lonnotify.pm lonparmset.pm lonpreferences.pm lonstatistics.pm /loncom/homework grades.pm Log: - WCAG compliance. Eliminate redundant text for screen readers. Preserve alt='', i.e., null attribute where alttext => '' is explicitly included in menu item hash. -------------- next part -------------- Index: loncom/interface/lonconfigsettings.pm diff -u loncom/interface/lonconfigsettings.pm:1.21.4.13.2.9 loncom/interface/lonconfigsettings.pm:1.21.4.13.2.10 --- loncom/interface/lonconfigsettings.pm:1.21.4.13.2.9 Mon Sep 19 19:28:31 2022 +++ loncom/interface/lonconfigsettings.pm Wed Jul 5 17:34:15 2023 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: lonconfigsettings.pm,v 1.21.4.13.2.9 2022/09/19 19:28:31 raeburn Exp $ +# $Id: lonconfigsettings.pm,v 1.21.4.13.2.10 2023/07/05 17:34:15 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -37,11 +37,12 @@ use Apache::lonlocal; use Apache::courseclassifier(); use LONCAPA qw(:DEFAULT :match); +use File::Copy; sub print_header { my ($r,$phase,$context,$jscript,$container,$instcode,$dom,$confname,$values) = @_; my ($pagetitle,$brcrumtitle,$action,$call_category_check,$instcode_check, - $linkprot_check,$crstype, at actions, at code_order); + $linkprot_check,$ltitools_check,$crstype, at actions, at code_order); if ($phase eq 'display') { @actions = &Apache::loncommon::get_env_multiple('form.actions'); } @@ -115,8 +116,8 @@ ENDSCRIPT } } - if (($context eq 'course') && ($phase eq 'display') && - (grep(/^linkprot$/, at actions))) { + if (($context eq 'course') && ((grep(/^linkprot$/, at actions)) || + (grep(/^ltitools$/, at actions)))) { my $allowed; my $home = &Apache::lonnet::homeserver($confname,$dom); unless ($home eq 'no_host') { @@ -124,102 +125,12 @@ foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } } if ($allowed) { - my (@changeable, at settable); - if (ref($values->{'linkprot'}) eq 'HASH') { - if (keys(%{$values->{'linkprot'}})) { - my @current = sort { $a <=> $b } keys(%{$values->{'linkprot'}}); - if (@current) { - for (my $i=0; $i<@current; $i++) { - my $num = $current[$i]; - if (ref($values->{'linkprot'}->{$num}) eq 'HASH') { - if ($values->{'linkprot'}->{$num}->{'usable'}) { - push(@changeable,$i); - } else { - push(@settable,$i); - } - } - } - } - } - } - my ($numrules,$intargjs); -$linkprot_check .= < 'checkbox'})."\n"; } elsif ($phase eq 'display') { - $js .= &Apache::lonhtmlcommon::color_picker(); + $js .= &Apache::lonhtmlcommon::color_picker(); $js .= &color_pick_js()."\n"; + if ($context eq 'domain') { + if (grep(/^(lti|ltitools)$/, at actions)) { + $js .= <isec_javascript($dom)."\n"; + } + } } $js .= &Apache::loncommon::viewport_size_js().' @@ -322,22 +238,52 @@ $onload .= "toggleHelpdeskRow(document.display,'overrides','$customclass','$optionsprefix');"; } if (grep(/^lti$/, at actions)) { + $onload .= "toggleLTI(document.display,'user','add');". + "toggleLTI(document.display,'crs','add');". + "toggleLTI(document.display,'sec','add');". + "toggleLTI(document.display,'lcauth','add');". + "toggleLTI(document.display,'lcmenu','add');". + "toggleLTI(document.display,'passback','add');". + "toggleLTI(document.display,'callback','add');"; + if (ref($values) eq 'HASH') { + if (ref($values->{'lti'}) eq 'HASH') { + my $numlti = scalar(keys(%{$values->{'lti'}})); + for (my $i=0; $i<$numlti; $i++) { + $onload .= "toggleLTI(document.display,'user','$i');". + "toggleLTI(document.display,'crs','$i');". + "toggleLTI(document.display,'sec','$i');". + "toggleLTI(document.display,'lcauth','$i');". + "toggleLTI(document.display,'lcmenu','$i');". + "toggleLTI(document.display,'passback','$i');". + "toggleLTI(document.display,'callback','$i');"; + } + } + } my %servers = &Apache::lonnet::get_servers($dom,'library'); foreach my $server (keys(%servers)) { - $onload .= "togglePrivKey(document.display,'$server');"; + $onload .= "togglePrivKey(document.display,'ltisec','$server');"; } - $onload .= "toggleLTIEncKey(document.display);"; + $onload .= "toggleLTIEncKey(document.display,'ltisec');"; } if (grep(/^ltitools$/, at actions)) { - $onload .= "toggleLTITools(document.display,'user','add');"; + $onload .= "toggleLTITools(document.display,'passback','add');". + "toggleLTITools(document.display,'roster','add');". + "toggleLTITools(document.display,'user','add');"; if (ref($values) eq 'HASH') { if (ref($values->{'ltitools'}) eq 'HASH') { my $numltitools = scalar(keys(%{$values->{'ltitools'}})); for (my $i=0; $i<$numltitools; $i++) { - $onload .= "toggleLTITools(document.display,'user','$i');"; + $onload .= "toggleLTITools(document.display,'passback','$i');". + "toggleLTITools(document.display,'roster','$i');". + "toggleLTITools(document.display,'user','$i');"; } } } + my %servers = &Apache::lonnet::get_servers($dom,'library'); + foreach my $server (keys(%servers)) { + $onload .= "togglePrivKey(document.display,'toolsec','$server');"; + } + $onload .= "toggleLTIEncKey(document.display,'toolsec');"; } if (grep(/^wafproxy$/, at actions)) { $onload .= "toggleWAF();checkWAF();updateWAF();"; @@ -364,7 +310,7 @@ $additem = {'add_entries' => \%loaditems,}; } } elsif ($context eq 'course') { - my $onload; + my ($onload,$ishome,$crshome_checked); if (grep(/^courseinfo$/, at actions)) { if (@code_order) { $onload = "courseSet('','load');toggleCloners(document.display.cloners_instcode);"; @@ -380,11 +326,9 @@ my %domdefs = &Apache::lonnet::get_domain_defaults($dom); $ltiauth = $domdefs{'crsltiauth'}; } - my $ishome; - my $chome = $env{'course.'.$env{'request.course.id'}.'.home'}; - unless (($chome eq 'no_host') || ($chome eq '')) { - my @ids=&Apache::lonnet::current_machine_ids(); - foreach my $id (@ids) { if ($id eq $chome) { $ishome=1; } } + unless ($crshome_checked) { + $ishome = &is_home(); + $crshome_checked = 1; } my $posslti = scalar(keys(%{$values->{'linkprot'}})); for (my $i=0; $i<=$posslti; $i++) { @@ -394,16 +338,42 @@ } if (ref($values->{'linkprot'}->{$i}) eq 'HASH') { if ($values->{'linkprot'}->{$i}->{'usable'}) { - $onload .= "toggleLinkProt(document.display,'$num','secret');"; + $onload .= "toggleChgSecret(document.display,'$num','secret','linkprot');"; } } - $onload .= "toggleLinkProtExtra(document.display,'returnurl','divurlparam','1','inline-block','$num');"; + $onload .= "toggleLinkProtExtra(document.display,'returnurl','divurlparam','1','inline-block','$num');". + "toggleLinkProtExtra(document.display,'passback','passbackparam','1','inline-block','$num');"; if ($ltiauth) { $onload .= "toggleLinkProtExtra(document.display,'requser','optional','1','block','$num');". "toggleLinkProtExtra(document.display,'mapuser','userfield','other','inline-block','$num');"; } if ($ishome) { - $onload .= "uncheckLinkProtMakeVis('visible','$num');"; + $onload .= "uncheckLinkProtMakeVis('linkprot','visible','$num');"; + } + } + } + } + } + if (grep(/^ltitools$/, at actions)) { + if (ref($values) eq 'HASH') { + if (ref($values->{'ltitools'}) eq 'HASH') { + unless ($crshome_checked) { + $ishome = &is_home(); + $crshome_checked = 1; + } + my $possltitools = scalar(keys(%{$values->{'ltitools'}})); + for (my $i=0; $i<=$possltitools; $i++) { + my $num = $i; + if ($i == $possltitools) { + $num = 'add'; + } + if (ref($values->{'ltitools'}->{$i}) eq 'HASH') { + if ($values->{'ltitools'}->{$i}->{'usable'}) { + $onload .= "toggleChgSecret(document.display,'$num','secret','ltitools');"; + } + } + if ($ishome) { + $onload .= "uncheckLinkProtMakeVis('ltitools','visible','$num');"; } } } @@ -437,6 +407,126 @@ return; } +sub ltisecret_js { + my ($name,$dom,$values) = @_; + return unless (ref($values) eq 'HASH'); + my $js; + if (($name eq 'linkprot') || ($name eq 'ltitools')) { + my (@changeable, at settable); + if (ref($values->{$name}) eq 'HASH') { + if (keys(%{$values->{$name}})) { + my @current = sort { $a <=> $b } keys(%{$values->{$name}}); + if (@current) { + for (my $i=0; $i<@current; $i++) { + my $num = $current[$i]; + if (ref($values->{$name}->{$num}) eq 'HASH') { + if ($values->{$name}->{$num}->{'usable'}) { + push(@changeable,$i); + } else { + push(@settable,$i); + } + } + } + } + } + } + my ($numrules,$intargjs); +$js .= < 0) { my $rowsum = 0; - my (%output,%rowtotal, at items); + my (%output,%rowtotal, at items,$got_check_uncheck,$got_change_secret); foreach my $item (@{$prefs_order}) { if (grep(/^\Q$item\E$/, at actions)) { push(@items,$item); @@ -613,15 +703,47 @@ $settings = $inststatus; } } - } elsif ($item eq 'lti') { - if (ref($values->{'ltisec'}) eq 'HASH') { - $settings = $values->{'ltisec'}; + } elsif (($item eq 'lti') || ($item eq 'ltitools')) { + unless ($got_change_secret) { + $r->print(''."\n"); + $got_change_secret = 1; + } + if ($item eq 'lti') { + if (ref($values->{'ltisec'}) eq 'HASH') { + if (ref($values->{'lti'}) eq 'HASH') { + $settings = {%{$values->{'lti'}},%{$values->{'ltisec'}}}; + } else { + $settings = $values->{'ltisec'}; + } + } elsif (ref($values->{'lti'}) eq 'HASH') { + $settings = $values->{'lti'}; + } + } elsif ($item eq 'ltitools') { + if (ref($values->{'toolsec'}) eq 'HASH') { + if (ref($values->{'ltitools'}) eq 'HASH') { + $settings = {%{$values->{'ltitools'}},%{$values->{'toolsec'}}}; + } else { + $settings = $values->{'toolsec'}; + } + } } } ($output{$item},$rowtotal{$item}) = &Apache::domainprefs::print_config_box($r,$dom,$confname, $phase,$item,$prefs->{$item},$settings); } else { + unless ($got_change_secret) { + $r->print(''."\n"); + $got_change_secret = 1; + } ($output{$item},$rowtotal{$item}) = &Apache::courseprefs::print_config_box($r,$dom,$confname,$phase, $item,$prefs->{$item},$values,$allitems,$crstype,$parm_permission); @@ -750,6 +872,274 @@ return $output; } +sub ltisec_javascript { + my ($dom) = @_; + my %servers = &Apache::lonnet::get_servers($dom,'library'); + my $primary = &Apache::lonnet::domain($dom,'primary'); + my $course_servers = "'".join("','",keys(%servers))."'"; + my $output = <<"ENDJS"; + +function toggleLTIEncKey(form,context) { + var shownhosts = new Array(); + var hiddenhosts = new Array(); + var forcourse = new Array($course_servers); + var fromdomain = '$primary'; + var crsradio; + if (context == 'ltisec') { + crsradio = form.elements['ltisec_crslinkprot']; + } else { + crsradio = form.elements['toolsec_crs']; + } + if (crsradio.length) { + for (var i=0; i 0) { + for (var j=0; j 0) { + for (var j=0; j 0) { + for (var i=0; i 0) { + for (var i=0; i 0) { + var setvis; + for (var i=0; i{$item}) eq 'HASH') { + my $num = $settings->{$item}{'order'}; + $ordered{$num} = $item; + } + } + $total = scalar(keys(%{$settings})); + my @jsarray = (); + foreach my $item (sort {$a <=> $b } (keys(%ordered))) { + push(@jsarray,$ordered{$item}); + } + my $jstext = ' var ltitools = Array('."'".join("','", at jsarray)."'".');'."\n"; + return <<"ENDSCRIPT"; + + +$togglejs + +ENDSCRIPT +} + +sub ltitools_toggle_js { + return <<"ENDSCRIPT"; + + +ENDSCRIPT +} + sub get_crumb_text { my %brcrumbtext = ( domain => 'Domain Settings', @@ -758,4 +1148,271 @@ return %brcrumbtext; } +sub publishlogo { + my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight, + $savefileas,$modified) = @_; + my ($output,$fname,$logourl,$madethumb); + if ($action eq 'upload') { + $fname=$env{'form.'.$formname.'.filename'}; + chop($env{'form.'.$formname}); + } else { + ($fname) = ($formname =~ /([^\/]+)$/); + } + if ($savefileas ne '') { + $fname = $savefileas; + } + $fname=&Apache::lonnet::clean_filename($fname); +# See if there is anything left + unless ($fname) { return ('error: no uploaded file'); } + $fname="$subdir/$fname"; + my $docroot=$r->dir_config('lonDocRoot'); + my $filepath="$docroot/priv"; + my $relpath = "$dom/$confname"; + my ($fnamepath,$file,$fetchthumb); + $file=$fname; + if ($fname=~m|/|) { + ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|); + } + my @parts=split(/\//,"$filepath/$relpath/$fnamepath"); + my $count; + for ($count=5;$count<=$#parts;$count++) { + $filepath.="/$parts[$count]"; + if ((-e $filepath)!=1) { + mkdir($filepath,02770); + } + } + # Check for bad extension and disallow upload + if ($file=~/\.(\w+)$/ && + (&Apache::loncommon::fileembstyle($1) eq 'hdn')) { + $output = + &mt('Invalid file extension ([_1]) - reserved for internal use.',$1); + } elsif ($file=~/\.(\w+)$/ && + !defined(&Apache::loncommon::fileembstyle($1))) { + $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1); + } elsif ($file=~/\.(\d+)\.(\w+)$/) { + $output = &mt('Filename not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2); + } elsif (-d "$filepath/$file") { + $output = &mt('Filename is a directory name - rename the file and re-upload'); + } else { + my $source = $filepath.'/'.$file; + my $logfile; + if (!open($logfile,">>",$source.'.log')) { + return (&mt('No write permission to Authoring Space')); + } + print $logfile +"\n================= Publish ".localtime()." ================\n". +$env{'user.name'}.':'.$env{'user.domain'}."\n"; +# Save the file + if (!open(FH,">",$source)) { + &Apache::lonnet::logthis('Failed to create '.$source); + return (&mt('Failed to create file')); + } + if ($action eq 'upload') { + if (!print FH ($env{'form.'.$formname})) { + &Apache::lonnet::logthis('Failed to write to '.$source); + return (&mt('Failed to write file')); + } + } else { + my $original = &Apache::lonnet::filelocation('',$formname); + if(!copy($original,$source)) { + &Apache::lonnet::logthis('Failed to copy '.$original.' to '.$source); + return (&mt('Failed to write file')); + } + } + close(FH); + chmod(0660, $source); # Permissions to rw-rw---. + + my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath; + my $copyfile=$targetdir.'/'.$file; + + my @parts=split(/\//,$targetdir); + my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]"; + for (my $count=5;$count<=$#parts;$count++) { + $path.="/$parts[$count]"; + if (!-e $path) { + print $logfile "\nCreating directory ".$path; + mkdir($path,02770); + } + } + my $versionresult; + if (-e $copyfile) { + $versionresult = &logo_versioning($targetdir,$file,$logfile); + } else { + $versionresult = 'ok'; + } + if ($versionresult eq 'ok') { + if (copy($source,$copyfile)) { + print $logfile "\nCopied original source to ".$copyfile."\n"; + $output = 'ok'; + $logourl = '/res/'.$dom.'/'.$confname.'/'.$fname; + if (ref($modified) eq 'ARRAY') { + push(@{$modified},[$copyfile,$source]); + } + my $metaoutput = + &write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile); + } else { + print $logfile "\nUnable to write ".$copyfile.':'.$!."\n"; + $output = &mt('Failed to copy file to RES space').", $!"; + } + if (($thumbwidth =~ /^\d+$/) && ($thumbheight =~ /^\d+$/)) { + my $inputfile = $filepath.'/'.$file; + my $outfile = $filepath.'/'.'tn-'.$file; + my ($fullwidth,$fullheight) = &Apache::lonnet::check_dimensions($inputfile); + if ($fullwidth ne '' && $fullheight ne '') { + if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) { + my $thumbsize = $thumbwidth.'x'.$thumbheight; + my @args = ('convert','-sample',$thumbsize,$inputfile,$outfile); + system({$args[0]} @args); + chmod(0660, $filepath.'/tn-'.$file); + if (-e $outfile) { + my $copyfile=$targetdir.'/tn-'.$file; + if (copy($outfile,$copyfile)) { + print $logfile "\nCopied source to ".$copyfile."\n"; + my $thumb_metaoutput = + &write_metadata($dom,$confname,$formname, + $targetdir,'tn-'.$file,$logfile); + if (ref($modified) eq 'ARRAY') { + push(@{$modified},[$copyfile,$outfile]); + } + $madethumb = 1; + } else { + print $logfile "\nUnable to write ".$copyfile. + ':'.$!."\n"; + } + } + } + } + } + } else { + $output = $versionresult; + } + } + return ($output,$logourl,$madethumb); +} + +sub logo_versioning { + my ($targetdir,$file,$logfile) = @_; + my $target = $targetdir.'/'.$file; + my ($maxversion,$fn,$extn,$output); + $maxversion = 0; + if ($file =~ /^(.+)\.(\w+)$/) { + $fn=$1; + $extn=$2; + } + opendir(DIR,$targetdir); + while (my $filename=readdir(DIR)) { + if ($filename=~/\Q$fn\E\.(\d+)\.\Q$extn\E$/) { + $maxversion=($1>$maxversion)?$1:$maxversion; + } + } + $maxversion++; + print $logfile "\nCreating old version ".$maxversion."\n"; + my $copyfile=$targetdir.'/'.$fn.'.'.$maxversion.'.'.$extn; + if (copy($target,$copyfile)) { + print $logfile "Copied old target to ".$copyfile."\n"; + $copyfile=$copyfile.'.meta'; + if (copy($target.'.meta',$copyfile)) { + print $logfile "Copied old target metadata to ".$copyfile."\n"; + $output = 'ok'; + } else { + print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n"; + $output = &mt('Failed to copy old meta').", $!, "; + } + } else { + print $logfile "Unable to write ".$copyfile.':'.$!."\n"; + $output = &mt('Failed to copy old target').", $!, "; + } + return $output; +} + +sub write_metadata { + my ($dom,$confname,$formname,$targetdir,$file,$logfile) = @_; + my (%metadatafields,%metadatakeys,$output); + $metadatafields{'title'}=$formname; + $metadatafields{'creationdate'}=time; + $metadatafields{'lastrevisiondate'}=time; + $metadatafields{'copyright'}='public'; + $metadatafields{'modifyinguser'}=$env{'user.name'}.':'. + $env{'user.domain'}; + $metadatafields{'authorspace'}=$confname.':'.$dom; + $metadatafields{'domain'}=$dom; + { + print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file; + my $mfh; + if (open($mfh,">",$targetdir.'/'.$file.'.meta')) { + foreach (sort(keys(%metadatafields))) { + unless ($_=~/\./) { + my $unikey=$_; + $unikey=~/^([A-Za-z]+)/; + my $tag=$1; + $tag=~tr/A-Z/a-z/; + print $mfh "\n\<$tag"; + foreach (split(/\,/,$metadatakeys{$unikey})) { + my $value=$metadatafields{$unikey.'.'.$_}; + $value=~s/\"/\'\'/g; + print $mfh ' '.$_.'="'.$value.'"'; + } + print $mfh '>'. + &HTML::Entities::encode($metadatafields{$unikey},'<>&"') + .''; + } + } + $output = 'ok'; + print $logfile "\nWrote metadata"; + close($mfh); + } else { + print $logfile "\nFailed to open metadata file"; + $output = &mt('Could not write metadata'); + } + } + return $output; +} + +sub change_secret_js { + return <<"ENDSCRIPT"; +function toggleChgSecret(form,num,item,name) { + var radioname = ''; + var currdivid = ''; + var newdivid = ''; + if ((document.getElementById(name+'_divcurr'+item+'_'+num)) && + (document.getElementById(name+'_divchg'+item+'_'+num))) { + currdivid = document.getElementById(name+'_divcurr'+item+'_'+num); + newdivid = document.getElementById(name+'_divchg'+item+'_'+num); + radioname = form.elements[name+'_change'+item+'_'+num]; + if (radioname) { + if (radioname.length > 0) { + var setvis; + for (var i=0; i '/adm/email?compose=individual', permission => 'F', icon => 'mail-message-new.png', + alttext => '', linktext => 'New Message', linktitle => 'Send a message to users.'}, {url => '/adm/email?compose=group', permission => "$can_srm", icon => 'mail-reply-all.png', + alttext => '', linktext => 'New Broadcast Message', help => 'Course_Broadcast_Message', linktitle => "Send a broadcast message to members of this $crstype and/or other users."}, @@ -105,6 +107,7 @@ {url => '/adm/email?compose=upload', permission => "$can_srm", icon => 'fromfile.png', + alttext => '', linktext => 'New Messages from File', linktitle => 'Create a message from file and send to users.'}, ]}, @@ -117,6 +120,7 @@ {url => '/adm/email?recordftf=query', permission => "$can_dff", icon => 'messalog.png', + alttext => '', linktext => 'Message Log for Selected Users', help => 'Course_Face_To_Face_Records,Course_Critical_Message', linktitle => "User notes, records of face-to-face discussions, critical messages, broadcast messages and archived messages in $crstype."}, @@ -124,6 +128,7 @@ {url => '/adm/setblock?caller=email', permission => "$can_dcm", icon => 'comblock.png', + alttext => '', linktext => 'Communication Blocking', linktitle => "Blocking of $usertype communication during exams."}, ]}); Index: loncom/interface/loncoursegroups.pm diff -u loncom/interface/loncoursegroups.pm:1.133 loncom/interface/loncoursegroups.pm:1.134 --- loncom/interface/loncoursegroups.pm:1.133 Sat Dec 13 05:56:01 2025 +++ loncom/interface/loncoursegroups.pm Sat Dec 13 13:33:33 2025 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: loncoursegroups.pm,v 1.133 2025/12/13 05:56:01 raeburn Exp $ +# $Id: loncoursegroups.pm,v 1.134 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -3811,21 +3811,21 @@ { linktext => "Modify default $gpterm settings", url => '/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state=change_settings&branch=settings', icon => 'grp_settings.png', - alttext => "Modify default $gpterm settings", + alttext => '', permission => '1', help => 'Course_Modify_Group', }, { linktext => 'Modify access, tools and privileges for members', url => '/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state=change_members&branch=members', icon => 'grp_tools.png', - alttext => 'Modify access, tools and privileges for members', + alttext => '', permission => '1', help => 'Course_Modify_Group_Membership', }, { linktext => "Add member(s) to the $gpterm", url => '/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state=add_members&branch=adds', icon => 'grp_add.png', - alttext => "Add member(s) to the $gpterm", + alttext => '', permission => '1', help => 'Course_Group_Add_Members', }]} Index: loncom/interface/loncreatecourse.pm diff -u loncom/interface/loncreatecourse.pm:1.179 loncom/interface/loncreatecourse.pm:1.180 --- loncom/interface/loncreatecourse.pm:1.179 Sat Dec 13 05:56:01 2025 +++ loncom/interface/loncreatecourse.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # Create a course # -# $Id: loncreatecourse.pm,v 1.179 2025/12/13 05:56:01 raeburn Exp $ +# $Id: loncreatecourse.pm,v 1.180 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -843,6 +843,7 @@ permission => $permission->{'create'}, #help => '', icon => 'crsnew.png', + alttext => '', linktitle => 'Create a new course by completing an online form.' }, { @@ -851,6 +852,7 @@ permission => $permission->{'create'} && $cancreate->{'Community'}, #help => '', icon => 'crsnew.png', + alttext => '', linktitle => 'Create a new collaborative community by completing an online form.' }, { @@ -859,6 +861,7 @@ permission => $permission->{'create'} && $cancreate->{'Placement'}, #help => '', icon => 'crsnew.png', + alttext => '', linktitle => 'Create a new placement test by completing an online form.' }, { @@ -867,6 +870,7 @@ permission => $permission->{'create'}, help => 'Batch_Creation', icon => 'uplcrs.png', + alttext => '', linktitle => 'Upload an attributes file containing specifications for one or more courses, communities or placement tests in XML format.' }, ] @@ -879,6 +883,7 @@ permission => $show_all_choices, #help => '', icon => 'rcrs.png', + alttext => '', linktitle => 'Display course, community creation and placement test requests submitted by authorized users, held pending approval by a Domain Coordinator.' }, { @@ -900,6 +905,7 @@ permission => $show_all_choices, #help => '', icon => 'document-properties.png', + alttext => '', linktitle => 'Display information about when, how and by whom courses, communities and placement tests were created in this domain.' }, ] Index: loncom/interface/loncreateuser.pm diff -u loncom/interface/loncreateuser.pm:1.487 loncom/interface/loncreateuser.pm:1.488 --- loncom/interface/loncreateuser.pm:1.487 Sat Dec 13 05:56:01 2025 +++ loncom/interface/loncreateuser.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Create a user # -# $Id: loncreateuser.pm,v 1.487 2025/12/13 05:56:01 raeburn Exp $ +# $Id: loncreateuser.pm,v 1.488 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -6844,6 +6844,7 @@ { linktext => $links{$linkcontext}{'singleuser'}, icon => 'edit-redo.png', + alttext => '', #help => 'Course_Change_Privileges', url => '/adm/createuser?action=singleuser', permission => ($permission->{'view'} || $permission->{'cusr'}), @@ -6857,6 +6858,7 @@ { linktext => $links{$linkcontext}{'upload'}, icon => 'uplusr.png', + alttext => '', #help => 'Course_Create_Class_List', url => '/adm/createuser?action=upload', permission => $permission->{'cusr'}, @@ -6865,6 +6867,7 @@ { linktext => $links{$linkcontext}{'listusers'}, icon => 'mngcu.png', + alttext => '', #help => 'Course_View_Class_List', url => '/adm/createuser?action=listusers', permission => ($permission->{'view'} || $permission->{'cusr'}), @@ -6882,6 +6885,7 @@ { linktext => 'User Access Log', icon => 'document-properties.png', + alttext => '', #help => 'Domain_User_Access_Logs', url => '/adm/createuser?action=accesslogs', permission => $permission->{'activity'}, @@ -6893,6 +6897,7 @@ { linktext => 'Custom Roles', icon => 'emblem-photos.png', + alttext => '', #help => 'Course_Editing_Custom_Roles', url => '/adm/createuser?action=custom', permission => $permission->{'custom'}, @@ -6901,6 +6906,7 @@ { linktext => 'Authoring Space Requests', icon => 'selfenrl-queue.png', + alttext => '', #help => 'Domain_Role_Approvals', url => '/adm/createuser?action=processauthorreq', permission => $permission->{'cusr'}, @@ -6909,6 +6915,7 @@ { linktext => 'LON-CAPA Account Requests', icon => 'list-add.png', + alttext => '', #help => 'Domain_Username_Approvals', url => '/adm/createuser?action=processusernamereq', permission => $permission->{'cusr'}, @@ -6917,6 +6924,7 @@ { linktext => 'Change Log', icon => 'document-properties.png', + alttext => '', #help => 'Course_User_Logs', url => '/adm/createuser?action=changelogs', permission => ($permission->{'cusr'} || $permission->{'view'}), @@ -6961,6 +6969,7 @@ linktext => $linktext{$crstype}{'single'}, #help => 'Course_Add_Student', icon => 'list-add.png', + alttext => '', url => '/adm/createuser?action=singlestudent', permission => $permission->{'cusr'}, linktitle => $linktitle{$crstype}{'single'}, @@ -6971,6 +6980,7 @@ { linktext => $linktext{$crstype}{'drop'}, icon => 'edit-undo.png', + alttext => '', #help => 'Course_Drop_Student', url => '/adm/createuser?action=drop', permission => $permission->{'cusr'}, @@ -6981,6 +6991,7 @@ { linktext => 'Helpdesk Access', icon => 'helpdesk-access.png', + alttext => '', #help => 'Course_Helpdesk_Access', url => '/adm/createuser?action=helpdesk', permission => (($permission->{'owner'} || $permission->{'co-owner'}) && @@ -6990,6 +7001,7 @@ { linktext => 'Custom Roles', icon => 'emblem-photos.png', + alttext => '', #help => 'Course_Editing_Custom_Roles', url => '/adm/createuser?action=custom', permission => $permission->{'custom'}, @@ -6998,6 +7010,7 @@ { linktext => $linktext{$crstype}{'groups'}, icon => 'grps.png', + alttext => '', #help => 'Course_Manage_Group', url => '/adm/coursegroups?refpage=cusr', permission => $permission->{'grp_manage'}, @@ -7006,6 +7019,7 @@ { linktext => 'Change Log', icon => 'document-properties.png', + alttext => '', #help => 'Course_User_Logs', url => '/adm/createuser?action=changelogs', permission => ($permission->{'view'} || $permission->{'cusr'}), @@ -7017,6 +7031,7 @@ { linktext => 'Enrollment Requests', icon => 'selfenrl-queue.png', + alttext => '', #help => 'Course_Approve_Selfenroll', url => '/adm/createuser?action=selfenrollqueue', permission => $permission->{'selfenrolladmin'} || $permission->{'selfenrollview'}, @@ -7031,6 +7046,7 @@ { linktext => 'Automated Enrollment', icon => 'roles.png', + alttext => '', #help => 'Course_Automated_Enrollment', permission => (&Apache::lonnet::auto_run($cnum,$cdom) && (($permission->{'cusr'}) || @@ -7044,6 +7060,7 @@ { linktext => 'User Self-Enrollment', icon => 'self_enroll.png', + alttext => '', #help => 'Course_Self_Enrollment', url => '/adm/createuser?action=selfenroll', permission => $permission->{'selfenrolladmin'} || $permission->{'selfenrollview'}, @@ -7067,6 +7084,7 @@ { linktext => 'Co-author-viewable list', icon => 'clst.png', + alttext => '', #help => 'Coauthor_Listing', url => '/adm/createuser?action=calist&forceedit=0', permission => $permission->{'cusr'}, @@ -7077,6 +7095,7 @@ { linktext => 'Change Log', icon => 'document-properties.png', + alttext => '', #help => 'Course_User_Logs', url => '/adm/createuser?action=changelogs', permission => $permission->{'cusr'}, @@ -7085,6 +7104,7 @@ { linktext => 'Co-author Managers', icon => 'camanager.png', + alttext => '', #help => 'Coauthor_Management', url => '/adm/createuser?action=camanagers', permission => $permission->{'author'}, @@ -7093,6 +7113,7 @@ { linktext => 'Configure Co-author Listing', icon => 'coauthors.png', + alttext => '', #help => 'Coauthor_Settings', url => '/adm/createuser?action=calist&forceedit=1', permission => ($permission->{'cusr'}), @@ -7104,6 +7125,7 @@ { linktext => 'Role Requests (other domains)', icon => 'edit-find.png', + alttext => '', #help => 'Role_Requests', url => '/adm/createuser?action=rolerequests', permission => $permission->{'cusr'}, @@ -7115,6 +7137,7 @@ { linktext => 'Queued Role Assignments (this domain)', icon => 'edit-find.png', + alttext => '', #help => 'Role_Approvals', url => '/adm/createuser?action=queuedroles', permission => $permission->{'cusr'}, Index: loncom/interface/londocs.pm diff -u loncom/interface/londocs.pm:1.731 loncom/interface/londocs.pm:1.732 --- loncom/interface/londocs.pm:1.731 Sat Dec 13 05:56:01 2025 +++ loncom/interface/londocs.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.731 2025/12/13 05:56:01 raeburn Exp $ +# $Id: londocs.pm,v 1.732 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -8540,6 +8540,7 @@ permission => 'F', help => 'Docs_Verify_Content', icon => 'verify.png', + alttext => '', linktitle => 'Verify contents can be retrieved/rendered', }, { linktext => $lt{'cv'}, @@ -8547,6 +8548,7 @@ permission => 'F', help => 'Docs_Check_Resource_Versions', icon => 'resversion.png', + alttext => '', linktitle => "View version information for resources in your $lc_crstype, and fix/unfix use of specific versions", }, { linktext => $lt{'ls'}, @@ -8554,6 +8556,7 @@ permission => 'F', #help => '', icon => 'symbs.png', + alttext => '', linktitle => "List the unique identifier used for each resource instance in your $lc_crstype" }, { linktext => $lt{'ct'}, @@ -8561,6 +8564,7 @@ permission => 'F', help => 'Docs_Short_URLs', icon => 'shorturls.png', + alttext => '', linktitle => "Set shortened URLs for a resource or folder in your $lc_crstype for use in deep-linking" }, ] @@ -8588,6 +8592,7 @@ permission => 'F', help => 'Docs_Course_Authorspace', icon => 'impcrsau.png', + alttext => '', linktitle => $lt{'ca'}, }); } @@ -8601,6 +8606,7 @@ permission => 'F', help => 'Docs_Export_Course_Docs', icon => 'imsexport.png', + alttext => '', linktitle => $lt{'imse'}, }, { linktext => $lt{'dcd'}, @@ -8608,6 +8614,7 @@ permission => $candump, help => 'Docs_Dump_Course_Docs', icon => 'dump.png', + alttext => '', linktitle => $lt{'dcd'}, }, ] @@ -8620,6 +8627,7 @@ permission => 'F', help => 'Docs_Export_Course_Author', icon => 'res.png', + alttext => '', linktitle => $lt{'cpc'}, }); } Index: loncom/interface/lonhtmlcommon.pm diff -u loncom/interface/lonhtmlcommon.pm:1.425 loncom/interface/lonhtmlcommon.pm:1.426 --- loncom/interface/lonhtmlcommon.pm:1.425 Sun Sep 7 04:21:13 2025 +++ loncom/interface/lonhtmlcommon.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common html routines # -# $Id: lonhtmlcommon.pm,v 1.425 2025/09/07 04:21:13 raeburn Exp $ +# $Id: lonhtmlcommon.pm,v 1.426 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -3875,14 +3875,14 @@ # NOTES: # - Empty elements, such as
are correctly terminated, # i.e. htmltag('br') returns
-# - Empty attributes (title="") are filtered out. +# - Empty attributes (e.g., title="") with the exception of alt="" are filtered out. # - The function will not check for deprecated attributes. # # OUTPUT: content enclosed in xhtml conform tags sub htmltag{ return qq|<$_[0]| - . join( '', map { qq| $_="${$_[2]}{$_}"| if ${$_[2]}{$_} } keys(%{ $_[2] }) ) + . join( '', map { qq| $_="${$_[2]}{$_}"| if ${$_[2]}{$_} || $_ eq 'alt' } keys(%{ $_[2] }) ) . ($_[1] ? qq|>$_[1]| : qq|/>|). "\n"; }; Index: loncom/interface/lonmenu.pm diff -u loncom/interface/lonmenu.pm:1.567 loncom/interface/lonmenu.pm:1.568 --- loncom/interface/lonmenu.pm:1.567 Wed Nov 26 19:43:20 2025 +++ loncom/interface/lonmenu.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Routines to control the menu # -# $Id: lonmenu.pm,v 1.567 2025/11/26 19:43:20 raeburn Exp $ +# $Id: lonmenu.pm,v 1.568 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -2000,7 +2000,7 @@ url => 'javascript:'.$act, permission => 'F', icon => $img, - alttext => $alttext, + alttext => '', linktitle => '', }; } else { Index: loncom/interface/lonmodifycourse.pm diff -u loncom/interface/lonmodifycourse.pm:1.108 loncom/interface/lonmodifycourse.pm:1.109 --- loncom/interface/lonmodifycourse.pm:1.108 Sat Dec 13 05:56:01 2025 +++ loncom/interface/lonmodifycourse.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # handler for DC-only modifiable course settings # -# $Id: lonmodifycourse.pm,v 1.108 2025/12/13 05:56:01 raeburn Exp $ +# $Id: lonmodifycourse.pm,v 1.109 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -520,6 +520,7 @@ permission => $permission->{'setparms'}, #help => '', icon => 'crsconf.png', + alttext => '', linktitle => '' }, { @@ -528,6 +529,7 @@ permission => $permission->{'setquota'}, #help => '', icon => 'groupportfolioquota.png', + alttext => '', linktitle => '' }, { @@ -536,6 +538,7 @@ permission => $permission->{'setanon'}, #help => '', icon => 'anonsurveythreshold.png', + alttext => '', linktitle => '' }, { @@ -544,6 +547,7 @@ permission => (($permission->{'catsettings'}) && (@additional_params > 0)), #help => '', icon => 'ccatconf.png', + alttext => '', linktitle => '' }, { @@ -552,11 +556,13 @@ permission => ($permission->{'viewparms'} && ($type ne 'Community') && ($type ne 'Placement')), #help => '', icon => 'roles.png', + alttext => '', linktitle => '' }, { linktext => $linktext{'selfenroll'}, icon => 'self_enroll.png', + alttext => '', #help => 'Course_Self_Enrollment', url => &phaseurl('selfenroll'), permission => &manage_selfenrollment($cdom,$cnum,$type,$coursehash,$permission), @@ -565,6 +571,7 @@ { linktext => $linktext{'setpostsubmit'}, icon => 'emblem-readonly.png', + alttext => '', #help => '', url => &phaseurl('setpostsubmit'), permission => $permission->{'setpostsubmit'}, @@ -573,6 +580,7 @@ { linktext => $linktext{'setltiauth'}, icon => 'system-lock-screen.png', + alttext => '', #help => '', url => &phaseurl('setltiauth'), permission => $permission->{'setltiauth'}, @@ -581,6 +589,7 @@ { linktext => $linktext{'setexttool'}, icon => 'exttool.png', + alttext => '', #help => '', url => &phaseurl('setexttool'), permission => $permission->{'setexttool'}, @@ -589,6 +598,7 @@ { linktext => $linktext{'setcrsauthor'}, icon => 'crsauthor.png', + alttext => '', #help => '', url => &phaseurl('setcrsauthor'), permission => $permission->{'setcrsauthor'}, @@ -597,6 +607,7 @@ { linktext => $linktext{'setcrseditors'}, icon => 'crseditors.png', + alttext => '', #help => '', url => &phaseurl('setcrseditors'), permission => $permission->{'setcrseditors'}, Index: loncom/interface/lonnotify.pm diff -u loncom/interface/lonnotify.pm:1.45 loncom/interface/lonnotify.pm:1.46 --- loncom/interface/lonnotify.pm:1.45 Sat Dec 13 05:56:01 2025 +++ loncom/interface/lonnotify.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Sending messages # -# $Id: lonnotify.pm,v 1.45 2025/12/13 05:56:01 raeburn Exp $ +# $Id: lonnotify.pm,v 1.46 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -153,6 +153,7 @@ permission => 1, #help => '', icon => 'mail-reply-all.png', + alttext => '', linktitle => 'Send a new e-mail to selected users from this domain' }, { linktext => 'Display sent e-mails', @@ -160,6 +161,7 @@ permission => 1, #help => '', icon => 'messalog.png', + alttext => '', linktitle => 'Display e-mail sent by Domain Coordinators in this domain' }, ] Index: loncom/interface/lonparmset.pm diff -u loncom/interface/lonparmset.pm:1.631 loncom/interface/lonparmset.pm:1.632 --- loncom/interface/lonparmset.pm:1.631 Sat Dec 13 05:56:01 2025 +++ loncom/interface/lonparmset.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set parameters for assessments # -# $Id: lonparmset.pm,v 1.631 2025/12/13 05:56:01 raeburn Exp $ +# $Id: lonparmset.pm,v 1.632 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -7165,30 +7165,35 @@ permission => $parm_permission->{'setrestrictmeta'}, linktitle => "Restrict metadata for this $lc_crstype." , icon =>'contact-new.png', + alttext => '', }, { linktext => 'Reset Student Access Times', url => '/adm/helper/resettimes.helper', permission => $mgr, linktitle => "Reset access times for folders/maps, resources or the $lc_crstype.", icon => 'start-here.png', + alttext => '', }, { linktext => "Show Start Times for Students' Quiz/Exam Timers", url => '/adm/accesstimes', permission => ($vgr || $mgr), linktitle => "Display when timer was started by students for folders/maps, resources or the $lc_crstype.", icon => 'accesstimes.png', + alttext => '', }, { linktext => 'Blocking Communication/Resource Access', url => '/adm/setblock', permission => ($vcb || $dcm), linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam', icon => 'comblock.png', + alttext => '', }, { linktext => 'Set Parameter Setting Default Actions', url => '/adm/parmset?action=setdefaults', permission => $parm_permission->{'setdefaults'}, linktitle =>'Set default actions for parameters.' , icon => 'folder-new.png' , + alttext => '', }]}, { categorytitle => 'New and Existing Parameter Settings for Resources', items => [ @@ -7197,6 +7202,7 @@ permission => $parm_permission->{'helper'}, linktitle =>'Set/Modify resource parameters in helper mode.' , icon => 'dialog-information.png' , + alttext => '', #help => 'Parameter_Helper', }, { linktext => $linktext{'newoverview'}, @@ -7204,6 +7210,7 @@ permission => $parm_permission->{'newoverview'}, linktitle => $linktitle{'newoverview'}, icon => 'edit-find.png', + alttext => '', #help => 'Parameter_Overview', }, { linktext => $linktext{'settable'}, @@ -7211,6 +7218,7 @@ permission => $parm_permission->{'settable'}, linktitle => $linktitle{'settable'}, icon => 'edit-copy.png', + alttext => '', #help => 'Table_Mode', }]}, { categorytitle => 'Existing Parameter Settings for Resources', @@ -7220,6 +7228,7 @@ permission => $parm_permission->{'setoverview'}, linktitle => $linktitle{'setoverview'}, icon => 'preferences-desktop-wallpaper.png', + alttext => '', #help => 'Parameter_Overview', }, { linktext => 'Change Log', @@ -7227,6 +7236,7 @@ permission => $parm_permission->{'parameterchangelog'}, linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." , icon => 'document-properties.png', + alttext => '', }]} ); $r->print(&Apache::lonhtmlcommon::generate_menu(@menu)); Index: loncom/interface/lonpreferences.pm diff -u loncom/interface/lonpreferences.pm:1.250 loncom/interface/lonpreferences.pm:1.251 --- loncom/interface/lonpreferences.pm:1.250 Sat Dec 13 05:56:01 2025 +++ loncom/interface/lonpreferences.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # Preferences # -# $Id: lonpreferences.pm,v 1.250 2025/12/13 05:56:01 raeburn Exp $ +# $Id: lonpreferences.pm,v 1.251 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -2684,7 +2684,7 @@ permission => $permissions{'aboutme'}, #help => 'Prefs_About_Me', icon => 'system-users.png', - alttext => 'About Me Icon', + alttext => '', linktitle => 'Edit information about yourself that should be displayed on your public profile.' }, { linktext => 'Screen Name', @@ -2692,7 +2692,7 @@ permission => 'F', #help => 'Prefs_Screen_Name_Nickname', icon => 'preferences-desktop-font.png', - alttext => 'Nickname Icon', + alttext => '', linktitle => 'Change the name that is displayed in your posts.' }, ] @@ -2704,7 +2704,7 @@ permission => 'F', #help => 'Prefs_Language', icon => 'preferences-desktop-locale.png', - alttext => 'Language Icon', + alttext => '', linktitle => 'Choose the default language for this user.' }, { linktext => $role.' Page', @@ -2712,7 +2712,7 @@ permission => 'F', #help => '', icon => 'role_hotlist.png', - alttext => 'Switch Role Icon', + alttext => '', linktitle => 'Configure the roles hotlist.' }, { linktext => 'Math display settings', @@ -2720,7 +2720,7 @@ permission => 'F', #help => '', icon => 'dismath.png', - alttext => 'Math Icon', + alttext => '', linktitle => 'Change how math is displayed.' }, { @@ -2729,7 +2729,7 @@ permission => $permissions{'timezone'}, #help => '', icon => 'timezone.png', - alttext => 'Clock Icon', + alttext => '', linktitle => 'Set your time zone.', } ] @@ -2741,7 +2741,7 @@ permission => 'F', #help => 'Change_Colors', icon => 'preferences-desktop-theme.png', - alttext => 'Colors Icon', + alttext => '', linktitle => 'Change LON-CAPA default colors.' }, { linktext => 'Menu Display', @@ -2749,7 +2749,7 @@ permission => 'F', #help => '', icon => 'preferences-system-windows.png', - alttext => 'Menus Icon', + alttext => '', linktitle => 'Change whether the menus are displayed with icons or icons and text.' } ] @@ -2761,7 +2761,7 @@ permission => 'F', #help => 'Prefs_Messages', icon => 'mail-reply-all.png', - alttext => 'Notifications Icon', + alttext => '', linktitle => 'Change messageforwarding or notifications settings.' }, { linktext => 'Discussion Display', @@ -2769,7 +2769,7 @@ permission => 'F', #help => 'Change_Discussion_Display', icon => 'chat.png', - alttext => 'Discussions Icon', + alttext => '', linktitle => 'Set display preferences for discussion posts for both discussion boards and individual resources in all your courses.' }, ] @@ -2784,7 +2784,7 @@ url => '/adm/preferences?action=authorsettings', permission => 'F', icon => 'codemirror.png', - alttext => 'Coding Icon', + alttext => '', linktitle => 'Settings for your authoring space.', }, ] @@ -2797,7 +2797,7 @@ permission => 'F', #help => '', icon => 'system-lock-screen.png', - alttext => 'Lock Icon', + alttext => '', linktitle => 'Restrict domain coordinator access.', }); } @@ -2810,7 +2810,7 @@ permission => 'F', #help => '', icon => 'network-workgroup.png', - alttext => 'Clicker Icon', + alttext => '', linktitle => 'Register your clicker.' }, ] @@ -2824,7 +2824,7 @@ permission => 'F', #help => 'Change_Password', icon => 'emblem-readonly.png', - alttext => 'Secure Icon', + alttext => '', linktitle => 'Change your password.', }); } @@ -2836,7 +2836,7 @@ permission => 'F', #help => '', icon => 'system-lock-screen.png', - alttext => 'Screen Lock Icon', + alttext => '', linktitle => 'Allow/disallow propagation of name changes from institutional directory service', }); } @@ -2850,7 +2850,7 @@ permission => 'F', #help => '', icon => 'course_ini.png', - alttext => 'Course Launch Icon', + alttext => '', linktitle => 'Set the default page to be displayed when you select a course role.', }); @@ -2863,7 +2863,7 @@ permission => 'F', #help => '', icon => 'blog.png', - alttext => 'Debugging Icon', + alttext => '', linktitle => 'Toggle Debug Messages.', }); } Index: loncom/interface/lonstatistics.pm diff -u loncom/interface/lonstatistics.pm:1.165 loncom/interface/lonstatistics.pm:1.166 --- loncom/interface/lonstatistics.pm:1.165 Tue Nov 10 19:28:32 2020 +++ loncom/interface/lonstatistics.pm Sat Dec 13 13:33:33 2025 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonstatistics.pm,v 1.165 2020/11/10 19:28:32 raeburn Exp $ +# $Id: lonstatistics.pm,v 1.166 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -762,12 +762,14 @@ {url => '/adm/statistics?reportSelected=problem_statistics', permission => 'F', icon => 'document-open.png', + alttext => '', linktext => ('Overall Problem Statistics'), linktitle => ('Student performance statistics on all problems.')}, {url => '/adm/statistics?reportSelected=problem_analysis', permission => 'F', icon => 'prob_ana.png', + alttext => '', linktext => ('Detailed Problem Analysis'), linktitle => ('Detailed statistics and graphs of student performance on problems.')}, ]}, @@ -776,12 +778,14 @@ {url => '/adm/statistics?reportSelected=submissiontime_analysis', permission => 'F', icon => 'subtimpl.png', + alttext => '', linktext => ('Submission Time Plots'), linktitle => ('Display and analysis of submission times on assessments.')}, {url => '/adm/statistics?reportSelected=correct_problems_plot', permission => 'F', icon => 'coprplot.png', + alttext => '', linktext => ('Correct Problems Plot'), linktitle => ('Display a histogram of student performance in the course.')}, ]}, @@ -790,13 +794,15 @@ {url => '/adm/statistics?reportSelected=student_submission_reports', permission => 'F', icon => 'edit-copy.png', + alttext => '', linktext => ('Student Submission Reports'), linktitle => ('Prepare reports of student submissions.')}, {url => '/adm/statistics?reportSelected=survey_reports', permission => 'F', icon => 'survey_rep.png', - linktext => ('Survey Reports'), + alttext => '', + linktext => ('Survey Reports'), linktitle => ('Prepare reports on survey results.')}, ]}); Index: loncom/homework/grades.pm diff -u loncom/homework/grades.pm:1.828 loncom/homework/grades.pm:1.829 --- loncom/homework/grades.pm:1.828 Tue Oct 7 20:18:06 2025 +++ loncom/homework/grades.pm Sat Dec 13 13:33:33 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.828 2025/10/07 20:18:06 raeburn Exp $ +# $Id: grades.pm,v 1.829 2025/12/13 13:33:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -12353,12 +12353,14 @@ url => $url1a, permission => $permissions{'either'}, icon => 'grade_students.png', + alttext => '', linktitle => 'Grade current resource for a selection of students.' }, { linktext => 'Grade ungraded submissions', url => $url1b, permission => $permissions{'either'}, icon => 'ungrade_sub.png', + alttext => '', linktitle => 'Grade all submissions that have not been graded yet.' }, @@ -12366,24 +12368,28 @@ url => $url1c, permission => $permissions{'either'}, icon => 'grading_table.png', + alttext => '', linktitle => 'Grade current resource for all students.' }, { linktext => 'Grade page/folder for one student', url => $url1d, permission => $permissions{'either'}, icon => 'grade_PageFolder.png', + alttext => '', linktitle => 'Grade all resources in current page/sequence/folder for one student.' }, { linktext => 'Download submissions', url => $url1e, permission => $permissions{'either'}, icon => 'download_sub.png', + alttext => '', linktitle => 'Download all students submissions.' }, { linktext => 'Fractional credit for late submission', url => $url1f, permission => $permissions{'either'}, icon => 'updategrace.png', + alttext => '', linktitle => 'Display fractional credit for late submission with possible update if grace parameter has been changed since submission', } ]}, @@ -12394,24 +12400,28 @@ url => $url2, permission => $permissions{'mgr'}, icon => 'uploadscores.png', + alttext => '', linktitle => 'Specify a file containing the class scores for current resource.' }, { linktext => 'Process Clicker', url => $url3, permission => $permissions{'mgr'}, icon => 'addClickerInfoFile.png', + alttext => '', linktitle => 'Specify a file containing the clicker information for this resource.' }, { linktext => 'Grade/Manage/Review Bubblesheets', url => $url4, permission => $permissions{'mgr'}, icon => 'bubblesheet.png', + alttext => '', linktitle => 'Grade bubblesheet exams, upload/download bubblesheet data files, and review previously graded bubblesheet exams.' }, { linktext => 'Verify Receipt Number', url => $url5, permission => $permissions{'either'}, icon => 'receipt_number.png', + alttext => '', linktitle => 'Verify a system-generated receipt number for correct problem solution.' } @@ -12428,6 +12438,7 @@ url => $url6, permission => $permissions{'either'}, icon => 'passback.png', + alttext => '', linktitle => 'Passback scores to launcher CMS for resources accessed via LTI-mediated deep-linking', }); } From raeburn at source.lon-capa.org Sun Dec 14 20:23:05 2025 From: raeburn at source.lon-capa.org (raeburn) Date: Mon, 15 Dec 2025 01:23:05 -0000 Subject: [LON-CAPA-cvs] cvs: loncom /interface portfolio.pm Message-ID: raeburn Mon Dec 15 01:23:05 2025 EDT Modified files: /loncom/interface portfolio.pm Log: - Roles-based conditions for existing Course/Community-based conditional access to a portfolio file can be updated. Index: loncom/interface/portfolio.pm diff -u loncom/interface/portfolio.pm:1.272 loncom/interface/portfolio.pm:1.273 --- loncom/interface/portfolio.pm:1.272 Sat Dec 13 05:56:01 2025 +++ loncom/interface/portfolio.pm Mon Dec 15 01:23:05 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # portfolio browser # -# $Id: portfolio.pm,v 1.272 2025/12/13 05:56:01 raeburn Exp $ +# $Id: portfolio.pm,v 1.273 2025/12/15 01:23:05 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1278,6 +1278,9 @@ &Apache::loncommon::get_env_multiple('form.preserve_role_'.$num); if (@delete_role_ids) { foreach my $id (@preserves) { + if (($id ne '') && (grep(/^$id$/, at delete_role_ids)) { + next; + } if (grep {$_ = $id} (@delete_role_ids)) { next; } @@ -1288,13 +1291,13 @@ } my $next_id = $env{'form.add_role_'.$num}; - if ($next_id) { + if ($next_id ne '') { push(@role_ids,$next_id); } foreach my $id (@role_ids) { my (@roles, at accesses, at sections, at groups); - if (($id == $next_id) && ($chg eq 'update')) { + if (($next_id ne '') && ($id == $next_id) && ($chg eq 'update')) { @roles = split(/,/,$env{'form.role_'.$num.'_'.$next_id}); @accesses = split(/,/,$env{'form.access_'.$num.'_'.$next_id}); @sections = split(/,/,$env{'form.section_'.$num.'_'.$next_id}); From raeburn at source.lon-capa.org Sun Dec 14 21:15:29 2025 From: raeburn at source.lon-capa.org (raeburn) Date: Mon, 15 Dec 2025 02:15:29 -0000 Subject: [LON-CAPA-cvs] cvs: loncom /interface portfolio.pm Message-ID: raeburn Mon Dec 15 02:15:29 2025 EDT Modified files: /loncom/interface portfolio.pm Log: - Fix typo and remove lines no longer needed after 1.273 changes. Add closing form tag for pop-up role/section/group selection window. Index: loncom/interface/portfolio.pm diff -u loncom/interface/portfolio.pm:1.273 loncom/interface/portfolio.pm:1.274 --- loncom/interface/portfolio.pm:1.273 Mon Dec 15 01:23:05 2025 +++ loncom/interface/portfolio.pm Mon Dec 15 02:15:29 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # portfolio browser # -# $Id: portfolio.pm,v 1.273 2025/12/15 01:23:05 raeburn Exp $ +# $Id: portfolio.pm,v 1.274 2025/12/15 02:15:29 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1278,12 +1278,9 @@ &Apache::loncommon::get_env_multiple('form.preserve_role_'.$num); if (@delete_role_ids) { foreach my $id (@preserves) { - if (($id ne '') && (grep(/^$id$/, at delete_role_ids)) { + if (($id ne '') && (grep(/^$id$/, at delete_role_ids))) { next; } - if (grep {$_ = $id} (@delete_role_ids)) { - next; - } push(@role_ids,$id); } } else { @@ -1979,6 +1976,7 @@ .'

' .'' + .'' ); return; } From raeburn at source.lon-capa.org Sun Dec 14 21:17:10 2025 From: raeburn at source.lon-capa.org (raeburn) Date: Mon, 15 Dec 2025 02:17:10 -0000 Subject: [LON-CAPA-cvs] cvs: loncom /interface portfolio.pm Message-ID: raeburn Mon Dec 15 02:17:10 2025 EDT Modified files: /loncom/interface portfolio.pm Log: - WCAG 2 compliance. -------------- next part -------------- Index: loncom/interface/portfolio.pm diff -u loncom/interface/portfolio.pm:1.274 loncom/interface/portfolio.pm:1.275 --- loncom/interface/portfolio.pm:1.274 Mon Dec 15 02:15:29 2025 +++ loncom/interface/portfolio.pm Mon Dec 15 02:17:10 2025 @@ -1,7 +1,7 @@ # The LearningOnline Network # portfolio browser # -# $Id: portfolio.pm,v 1.274 2025/12/15 02:15:29 raeburn Exp $ +# $Id: portfolio.pm,v 1.275 2025/12/15 02:17:10 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -93,6 +93,8 @@ 'createdir' => 'Create Subdirectory', 'createdir_label' => 'Create subdirectory in current directory', 'parse' => 'Upload embedded images/multimedia/css/linked files if HTML file', + 'subdir' => 'Subdirectory name', + 'file' => 'Choose a file', ); my $escuri = &HTML::Entities::encode($r->uri,'&<>"'); my $help_fileupload = &Apache::loncommon::help_open_topic('Portfolio AddFiles'); @@ -121,7 +123,7 @@ .'
' .''.$lt{'upload_label'}.'' .$groupitem - .'' + .'' .'' .'' .'' @@ -140,7 +142,7 @@ .'
' .'
' .''.$lt{'createdir_label'}.'' - .''.$groupitem + .''.$groupitem .'' .'' .'' @@ -186,7 +188,8 @@ $r->print('
print('">'. &Apache::lonhtmlcommon::select_recent($namespace,'currentpath', - 'this.form.submit();')); + 'this.form.submit();', + &mt('Select recently visited directory'))); $r->print(""); } @@ -250,7 +253,7 @@ $r->print(''.$size.''); $r->print(''.&Apache::lonlocal::locallocaltime($mtime).''); if ($select_mode ne 'true') { - $r->print('  '); # Display status + $r->print('  '); # Display status $r->print('' .&mt($curr_access).'   ' ); @@ -260,7 +263,7 @@ ); $r->print(&make_anchor($url, \%anchor_fields, $access_admin_text).''); } else { - $r->print('  '); # Display status + $r->print('  '); # Display status } $r->print(&Apache::loncommon::end_data_table_row().$/); } @@ -297,12 +300,12 @@ $r->print(&Apache::loncommon::start_data_table() .&Apache::loncommon::start_data_table_header_row() .''.&mt('Select').'' - .' ' - .' ' + .''.&mt('File type').'' + .''.&mt('Multiple versions?').'' .''.&mt('Name').'' .''.&mt('Size').'' .''.&mt('Last Modified').'' - .' ' + .''.&mt('Tag').'' .&Apache::loncommon::end_data_table_header_row() ); } else { @@ -329,12 +332,12 @@ $r->print(&Apache::loncommon::start_data_table() .&Apache::loncommon::start_data_table_header_row() .''.&mt('Actions'). &Apache::loncommon::help_open_topic('Portfolio FileAction').'' - .' ' - .' ' + .''.&mt('File type').'' + .''.&mt('Multiple versions?').'' .''.&mt('Name').&Apache::loncommon::help_open_topic('Portfolio OpenFile').'' .''.&mt('Size').'' .''.&mt('Last Modified').'' - .' ' + .''.&mt('Tag').'' .''.&mt('Current Access Status').$acl_helplink.'' .&Apache::loncommon::end_data_table_header_row()); } @@ -461,7 +464,7 @@ if ($$checked_files{$filename} eq 'selected') { $line.=' checked="checked" '; } - $line.=' />'; + $line.=' aria-label="'.&mt('Include file for assignment').'" />'; } else { $line = ' '; $zerobyte ++; @@ -480,10 +483,10 @@ $line .= ''; } if ($can_delete) { - $line .= ''; + $line .= ''; } if ($can_modify) { - my $cat=''.&mt('Metadata').''; + my $cat=''.&mt('Metadata').''; my %anchor_fields = ( 'rename' => $filename, currentpath => $current_path @@ -600,15 +603,18 @@ 'cancel' => &mt('Cancel'), }; } - $r->print('

'); + $r->print('

'); $r->print(&group_form_data().'

'); - $r->print('
-

- '. - &group_form_data()); - $r->print("\n".' -

'); + if ($button_text->{'cancel'} ne '') { + $r->print('
+

+ '. + &group_form_data()); + $r->print("\n".' +

'); + } + $r->print('
'); } sub display_file { @@ -916,7 +922,7 @@ my $uhome = &Apache::lonnet::homeserver($uname,$udom); my $prefix = &Apache::lonnet::url_prefix($r,$udom,$uhome,'web'); $header = - '

' + '

' .&mt('Allowing others to retrieve file: [_1]' ,'' .$port_path.$env{'form.currentpath'}.$env{'form.access'} @@ -938,22 +944,17 @@ $info .= &mt("Users with course editing rights may add a 'Group Portfolio' item using the Course Editor (Collaboration tab), to provide access to viewable group portfolio files.").'
'; } } else { - $header = '

'.&mt('Conditional access controls for file: [_1]',$port_path.$env{'form.currentpath'}.$env{'form.access'}).'

'. + $header = '

'.&mt('Conditional access controls for file: [_1]',$port_path.$env{'form.currentpath'}.$env{'form.access'}).'

'. &explain_conditionals().'
'; } if ($can_setacl) { &open_form($r,$url); $r->print($header.$info); - $r->print('
'.&Apache::loncommon::help_open_topic('Portfolio ShareFile SetAccess', &mt('Help on setting up share access'))); + $r->print('
'.&Apache::loncommon::help_open_topic('Portfolio ShareFile SetAccess', &mt('Help on setting up share access'))); $r->print(&Apache::loncommon::help_open_topic('Portfolio ShareFile ChangeSetting', &mt('Help on changing settings'))); - $r->print(&Apache::loncommon::help_open_topic('Portfolio ShareFile StopAccess', &mt('Help on removing share access'))); + $r->print(&Apache::loncommon::help_open_topic('Portfolio ShareFile StopAccess', &mt('Help on removing share access')).'
'); &access_setting_table($r,$url,$file_name,$access_controls{$file_name}, $action); - my $button_text = { - 'continue' => &mt('Proceed'), - 'cancel' => &mt('Return to directory'), - }; - &close_form($r,$url,$button_text); } elsif ($can_viewacl) { $r->print($header); if ($aclcount) { @@ -1263,8 +1264,8 @@ time => { start => $start, end => $end - }, - }; + }, + }; if ($scope eq 'guest') { $record->{'password'} = $env{'form.password'}; @@ -1291,7 +1292,6 @@ if ($next_id ne '') { push(@role_ids,$next_id); } - foreach my $id (@role_ids) { my (@roles, at accesses, at sections, at groups); if (($next_id ne '') && ($id == $next_id) && ($chg eq 'update')) { @@ -1401,22 +1401,21 @@ } $acl_count{$scope} ++; } - $r->print('
'); if ($action eq 'chgaccess') { &standard_settings($r,$now,$then,$url,$filename,\%acl_count,\%start, \%end,$public,$publicnum,$publictext,$guest,$guestnum, $guesttext,$access_controls,%conditionals); } else { - &condition_setting($r,$access_controls,$now,$then,\%acl_count, + &condition_setting($r,$url,$access_controls,$now,$then,\%acl_count, \@domains,\@users,\@courses,\@ips); } - $r->print('
'); } sub standard_settings { my ($r,$now,$then,$url,$filename,$acl_count,$start,$end,$public,$publicnum, $publictext,$guest,$guestnum,$guesttext,$access_controls,%conditionals)=@_; - $r->print('

'.&mt('Public access: [_1]',&mt($publictext)).'

'); + $r->print('
'. + '

'.&mt('Public access: [_1]',&mt($publictext)).'

'); $r->print(&Apache::loncommon::start_data_table()); $r->print(&Apache::loncommon::start_data_table_header_row()); $r->print(''.&mt('Action').''.&mt('Dates available').''); @@ -1431,8 +1430,8 @@ } $r->print(&Apache::loncommon::end_data_table_row()); $r->print(&Apache::loncommon::end_data_table()); - $r->print(' '); - $r->print('

'.&mt('Passphrase-protected access: [_1]',&mt($guesttext)).'

'); + $r->print('
'); + $r->print('

'.&mt('Passphrase-protected access: [_1]',&mt($guesttext)).'

'); $r->print(&Apache::loncommon::start_data_table()); $r->print(&Apache::loncommon::start_data_table_header_row()); $r->print(''.&mt('Action').''.&mt('Dates available'). @@ -1449,11 +1448,15 @@ &dateboxes('1',$now,$then).''); } $r->print(''); + $passwd.'" aria-label="'.&mt('passphrase').'" />'); $r->print(&Apache::loncommon::end_data_table_row()); $r->print(&Apache::loncommon::end_data_table()); - $r->print(' '. - ''); + $r->print('
'. + '
'."\n"); + my $button_text = { + 'continue' => &mt('Proceed'), + }; + &close_form($r,$url,$button_text); my $numconditionals = 0; my $conditionstext; my %cond_status; @@ -1478,7 +1481,9 @@ 'action' => 'chgconditions', 'currentpath' => $env{'form.currentpath'}, ); - $r->print('

'.&mt('Conditional access: [_1]',&mt($conditionstext)).'

'); + $r->print('
'. + '
'. + '

'.&mt('Conditional access: [_1]',&mt($conditionstext)).'

'); if ($numconditionals > 0) { my $count = 1; my $chg = 'none'; @@ -1493,19 +1498,25 @@ } else { $r->print(&make_anchor($url,\%anchor_fields,&mt('Add conditional access')).' '.&mt("based on domain, username, course/community affiliation or user's IP address.")); } + $r->print('
'. + '
'."\n"); } sub condition_setting { - my ($r,$access_controls,$now,$then,$acl_count,$domains,$users,$courses,$ips) = @_; - $r->print(''); + my ($r,$url,$access_controls,$now,$then,$acl_count,$domains,$users,$courses,$ips) = @_; + $r->print('
'); &access_element($r,'domains',$acl_count,$domains,$access_controls,$now,$then); - $r->print(' '); - &access_element($r,'users',$acl_count,$users,$access_controls,$now,$then); - $r->print(''); + $r->print('

'); &access_element($r,'course',$acl_count,$courses,$access_controls,$now,$then); - $r->print(' '); + $r->print('

'); + &access_element($r,'users',$acl_count,$users,$access_controls,$now,$then); + $r->print('

'); &access_element($r,'userip',$acl_count,$ips,$access_controls,$now,$then); - $r->print(''); + $r->print('

'); + my $button_text = { + 'continue' => &mt('Proceed'), + }; + &close_form($r,$url,$button_text); } sub acl_status { @@ -1527,7 +1538,7 @@ course => 'Course/Community', userip => 'IP', ); - $r->print('

'.&mt($typetext{$type}.'-based conditional access:').' '); + $r->print('

'.&mt($typetext{$type}.'-based conditional access:').' '); if ($$acl_count{$type}) { $r->print(&mt('[quant,_1,condition]',$$acl_count{$type})); } else { @@ -1672,7 +1683,8 @@ } $r->print(''.$course_description{'description'}.''); } elsif ($status eq 'new') { - $r->print(''.&Apache::loncommon::selectcourse_link('portform','crsnum_'.$num,'crsdom_'.$num,'description_'.$num,$num.'_1',undef,$showtype).'  '); + my $labeltext = &mt('new'); + $r->print(''.&Apache::loncommon::selectcourse_link('portform','crsnum_'.$num,'crsdom_'.$num,'description_'.$num,$num.'_1',undef,$showtype).'  '); } $r->print(''.&dateboxes($num,$start,$end)); my $newrole_id = 1; @@ -1695,11 +1707,11 @@ } $r->print(''); } - $r->print('
'.&mt('Add a roles-based condition'). + $r->print('
'); $newrole_id = $max_id; } else { $r->print(''); @@ -1723,7 +1735,8 @@ my ($r,$status,$item,$all_doms,$access_controls,$now,$then) = @_; my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then, 'domains'); - my $dom_select = ''. ' '; if ($status eq 'old') { my $content = $$access_controls{$item}; @@ -1755,7 +1768,8 @@ my $content = $$access_controls{$item}; $curr_user_list = &sort_users($content->{'users'}); } - $r->print(''.&actionbox($status,$num,$scope).''.&mt("Format for users' username:domain information:").'
sparty:msu,illini:uiuc ... etc.
'.&dateboxes($num,$start,$end).''); + my $labeltext = &mt('User(s) with conditional access'); + $r->print(''.&actionbox($status,$num,$scope).''.&mt("Format for users' username:domain information:").'
sparty:msu,illini:uiuc ... etc.
'.&dateboxes($num,$start,$end).''); } sub ips_row { @@ -1767,11 +1781,12 @@ my $content = $$access_controls{$item}; $curr_ips_list = &sort_ips($content->{'userip'}); } + my $labeltext = &mt('IP addresess(s) with conditional access'); $r->print(''.&actionbox($status,$num,$scope).''.&mt('Format for IP controls').'
'. &mt('[_1] or [_2] or [_3] or [_4] or [_5]','35.8.*','35.8.3.[34-56]', '*.msu.edu','35.8.3.34','somehostname.pa.msu.edu').'
'. &mt('Use a comma to separate different ranges.').'
'. - ''. + ''. ''.&dateboxes($num,$start,$end).''); } @@ -1787,15 +1802,50 @@ } elsif ($type eq 'userip') { $showtype = 'IP'; } + my $labeltext = &mt('number of '.$showtype.'-based condition(s)'); return &mt('Add new '.$showtype.'-based condition(s)?') .' '.&mt('Number to add: ') - .''; + .''; } sub actionbox { my ($status,$num,$scope) = @_; - my $output = '

'); $count ++; if ((!$seconddiv) && ($count >= $firstthird)) { $r->print(''."\n".'
'."\n"); @@ -855,7 +858,7 @@ } } } - $r->print('
'); + $r->print('

'); $r->print(&print_footer($r,$phase,'display','Display',undef,$container,$parm_permission)); $r->print(''); if ($container) { From raeburn at source.lon-capa.org Sun Dec 14 22:33:08 2025 From: raeburn at source.lon-capa.org (raeburn) Date: Mon, 15 Dec 2025 03:33:08 -0000 Subject: [LON-CAPA-cvs] cvs: loncom /interface loncourserespicker.pm Message-ID: raeburn Mon Dec 15 03:33:08 2025 EDT Modified files: /loncom/interface loncourserespicker.pm Log: - WCAG 2 compliance. Index: loncom/interface/loncourserespicker.pm diff -u loncom/interface/loncourserespicker.pm:1.22 loncom/interface/loncourserespicker.pm:1.23 --- loncom/interface/loncourserespicker.pm:1.22 Sat Dec 13 05:56:01 2025 +++ loncom/interface/loncourserespicker.pm Mon Dec 15 03:33:08 2025 @@ -1,6 +1,6 @@ # The LearningOnline Network # -# $Id: loncourserespicker.pm,v 1.22 2025/12/13 05:56:01 raeburn Exp $ +# $Id: loncourserespicker.pm,v 1.23 2025/12/15 03:33:08 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -986,16 +986,16 @@ if ($context eq 'imsexport') { $outcome = &Apache::loncommon::start_page('Export '.$crstype.' to IMS Package')."\n". '
'."\n". - '

'.&mt('IMS Export Failed').'

'; + '

'.&mt('IMS Export Failed').'

'; } elsif ($context eq 'examblock') { $outcome = &Apache::loncommon::start_page('Selection of Resources for Blocking', undef,{'only_body' => 1,})."\n". '
'."\n". - '

'.&mt('Resource Display Failed').'

'; + '

'.&mt('Resource Display Failed').'

'; } elsif ($context eq 'dumpdocs') { - $outcome = '

'.&mt('Copying to Authoring Space unavailable').'

'; + $outcome = '

'.&mt('Copying to Authoring Space unavailable').'

'; } elsif ($context eq 'shorturls') { - $outcome = '

'.&mt('Display/Setting of shortened URLs unavailable').'

'; + $outcome = '

'.&mt('Display/Setting of shortened URLs unavailable').'

'; } $outcome .= '
'; if ($crstype eq 'Community') {