--- loncom/interface/loncommon.pm 2023/11/26 20:47:16 1.1422 +++ loncom/interface/loncommon.pm 2024/04/14 17:12:27 1.1429 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.1422 2023/11/26 20:47:16 raeburn Exp $ +# $Id: loncommon.pm,v 1.1429 2024/04/14 17:12:27 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1372,7 +1372,7 @@ sub helpLatexCheatsheet { $out .= '<span>' .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600) .'</span> <span>' - .&help_open_topic('Authoring_Multilingual_Problems',&mt('How to create problems in different languages'),$stayOnPage,undef,600) + .&help_open_topic('Authoring_Multilingual_Problems',&mt('Languages'),$stayOnPage,undef,600) .'</span>'; } $out .= '</span>'; # End cheatsheet @@ -1764,8 +1764,6 @@ the id of the element to resize, second surrounds everything that comes after the textarea, this routine needs to be attached to the <body> for the onload and onresize events. -=back - =cut sub resize_textarea_js { @@ -2439,10 +2437,76 @@ sub show_crsfiles_js { END } +sub crsauthor_rights { + my ($rightsfile,$path,$docroot,$cnum,$cdom) = @_; + my $sourcerights = "$path/$rightsfile"; + my $now = time; + if (!-e $sourcerights) { + my $cid = $cdom.'_'.$cnum; + if (!-e "$docroot/priv/$cdom") { + mkdir("$docroot/priv/$cdom",0755); + } + if (!-e "$docroot/priv/$cdom/$cnum") { + mkdir("$docroot/priv/$cdom/$cnum",0755); + } + if (open(my $fh,">$sourcerights")) { + print $fh <<END; +<accessrule effect="deny" realm="" type="course" role="" /> +<accessrule effect="allow" realm="$cid" type="course" role="" /> +END + close($fh); + } + } + if (!-e "$sourcerights.meta") { + if (open(my $fh,">$sourcerights.meta")) { + my $author=$env{'environment.firstname'}.' '. + $env{'environment.middlename'}.' '. + $env{'environment.lastname'}.' '. + $env{'environment.generation'}; + $author =~ s/\s+$//; + print $fh <<"END"; + +<abstract></abstract> +<author>$author</author> +<authorspace>$cnum:$cdom</authorspace> +<copyright>private</copyright> +<creationdate>$now</creationdate> +<customdistributionfile></customdistributionfile> +<dependencies></dependencies> +<domain>$cdom</domain> +<highestgradelevel>0</highestgradelevel> +<keywords></keywords> +<language>notset </language> +<lastrevisiondate>$now</lastrevisiondate> +<lowestgradelevel>0</lowestgradelevel> +<mime>rights</mime> +<modifyinguser>$env{'user.name'}:$env{'user.domain'}</modifyinguser> +<notes></notes> +<obsolete></obsolete> +<obsoletereplacement></obsoletereplacement> +<owner>$cnum:$cdom</owner> +<rule>deny:::course,allow:$cid::course</rule> +<sourceavail></sourceavail> +<standards></standards> +<subject></subject> +<title>Course Authoring Rights</title> +END + close($fh); + } + } + return; +} + =pod =item * &iframe_wrapper_headjs() +emits javascript containing two global vars to facilitate handling of resizing +by code in iframe_wrapper_resizejs() used when an iframe is present in a page +with standard LON-CAPA menus. + +=cut + # # Where iframe is in use, if window.onload() executes before the custom resize function # has been defined (jQuery), two global javascript vars (LCnotready and LCresizedef) @@ -2450,11 +2514,6 @@ END # do not obscure the Functions menu. # -=back - -=cut - - sub iframe_wrapper_headjs { return <<"ENDJS"; <script type="text/javascript"> @@ -2472,6 +2531,14 @@ ENDJS =item * &iframe_wrapper_resizejs() +emits javascript used to handle resizing for a page containing +an iframe, to ensure that the iframe does not obscure any +standard LON-CAPA menu items. + +=back + +=cut + # # jQuery to use when iframe is in use and a page resize occurs. # This script will ensure that the iframe does not obscure any @@ -2481,10 +2548,6 @@ ENDJS # e.g., by inclusion in second arg passed to &start_page(). # -=back - -=cut - sub iframe_wrapper_resizejs { my $offset = 5; &get_unprocessed_cgi($ENV{'QUERY_STRING'},['inhibitmenu']); @@ -2501,7 +2564,7 @@ sub iframe_wrapper_resizejs { if (\$('div.LC_menus_content:first').length) { if (\$('div.LC_menus_content:first').hasClass ("shown")) { header = \$('div.LC_menus_content:first'); - offset = 9; + offset = 12; } } else if (\$('div.LC_head_subbox:first').length) { header = \$('div.LC_head_subbox:first'); @@ -6593,20 +6656,32 @@ sub nocodemirror { Input: $uri (optional) Returns: %editors hash in which keys are editors - permitted in current Authoring Space. + permitted in current Authoring Space, + or in current course for web pages + created in a course. + Value for each key is 1. Possible keys - are: edit, xml, and daxe. If no specific + are: edit, xml, and daxe. + + For a regular Authoring Space, if no specific set of editors has been set for the Author who owns the Authoring Space, then the domain default will be used. If no domain default has been set, then the keys will be edit and xml. + For a course author, or for web pages created + in a course, if no specific set of editors has + been set for the course, then the domain + course default will be used. If no domain + course default has been set, then the keys + will be edit and xml. + =cut sub permitted_editors { my ($uri) = @_; - my ($is_author,$is_coauthor,$auname,$audom,%editors); + my ($is_author,$is_coauthor,$is_course,$auname,$audom,%editors); if ($env{'request.role'} =~ m{^au\./}) { $is_author = 1; } elsif ($env{'request.role'} =~ m{^(?:ca|aa)\./($match_domain)/($match_username)}) { @@ -6620,20 +6695,32 @@ sub permitted_editors { } } } elsif ($env{'request.course.id'}) { - if ($env{'request.editurl'} =~ m{^/priv/($match_domain)/($match_username)/}) { + my ($cdom,$cnum); + $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if (($env{'request.editurl'} =~ m{^/priv/\Q$cdom/$cnum\E/}) || + ($env{'request.editurl'} =~ m{^/uploaded/\Q$cdom/$cnum\E/(docs|supplemental)/})) { + $is_course = 1; + } elsif ($env{'request.editurl'} =~ m{^/priv/($match_domain)/($match_username)/}) { ($audom,$auname) = ($1,$2); } elsif ($env{'request.uri'} =~ m{^/priv/($match_domain)/($match_username)/}) { ($audom,$auname) = ($1,$2); } elsif (($uri eq '/daxesave') && + (($env{'form.path'} =~ m{^/daxeopen/priv/\Q$cdom/$cnum\E/}) || + ($env{'form.path'} =~ m{^/daxeopen/uploaded/\Q$cdom/$cnum\E/(docs|supplemental)/}))) { + $is_course = 1; + } elsif (($uri eq '/daxesave') && ($env{'form.path'} =~ m{^/daxeopen/priv/($match_domain)/($match_username)/})) { ($audom,$auname) = ($1,$2); } - if (($audom ne '') && ($auname ne '')) { - if (($env{'user.domain'} eq $audom) && - ($env{'user.name'} eq $auname)) { - $is_author = 1; - } else { - $is_coauthor = 1; + unless ($is_course) { + if (($audom ne '') && ($auname ne '')) { + if (($env{'user.domain'} eq $audom) && + ($env{'user.name'} eq $auname)) { + $is_author = 1; + } else { + $is_coauthor = 1; + } } } } @@ -6653,6 +6740,19 @@ sub permitted_editors { xml => 1, ); } + } elsif ($is_course) { + if (exists($env{'course.'.$env{'request.course.id'}.'.internal.crseditors'})) { + map { $editors{$_} = 1; } split(/,/,$env{'course.'.$env{'request.course.id'}.'.internal.crseditors'}); + } else { + my %domdefaults = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'}); + if (exists($domdefaults{'crseditors'})) { + map { $editors{$_} = 1; } split(/,/,$domdefaults{'crseditors'}); + } else { + %editors = ( edit => 1, + xml => 1, + ); + } + } } else { %editors = ( edit => 1, xml => 1, @@ -6887,21 +6987,33 @@ sub bodytag { $bodytag .= Apache::lonhtmlcommon::scripttag( Apache::lonmenu::utilityfunctions($httphost), 'start'); - if ($args->{'collapsible_header'}) { - my $alttext = &mt('menu state: collapsed'); - my $tooltip = &mt('display standard menus'); + my $collapsible; + if ($args->{'collapsible_header'} ne '') { + $collapsible = 1; + my ($menustate,$tiptext,$divclass); + if ($args->{'start_collapsed'}) { + $menustate = 'collapsed'; + $tiptext = 'display'; + $divclass = 'hidden'; + } else { + $menustate = 'expanded'; + $tiptext = 'hide'; + $divclass = 'shown'; + } + my $alttext = &mt('menu state: '.$menustate); + my $tooltip = &mt($tiptext.' standard menus'); $bodytag .= <<"END"; <div id="LC_expandingContainer" style="display:inline;"> <div id="LC_collapsible" class="LC_collapse_trigger" style="position: absolute;top: -5px;left: 0px; z-index:101; display:inline;"> -<a href="#" style="text-decoration:none;"><img class="LC_collapsible_indicator" alt="$alttext" title="$tooltip" src="/res/adm/pages/collapsed.png" style="border:0;margin:0;padding:0;max-width:100%;height:auto" /></a></div> -<div class="LC_menus_content hidden"> +<a href="#" style="text-decoration:none;"><img class="LC_collapsible_indicator" alt="$alttext" title="$tooltip" src="/res/adm/pages/$menustate.png" style="border:0;margin:0;padding:0;max-width:100%;height:auto" /></a></div> +<div class="LC_menus_content $divclass"> END } unless ($args->{'no_primary_menu'}) { my ($left,$right) = Apache::lonmenu::primary_menu($crstype,$ltimenu,$menucoll,$menuref, $args->{'links_disabled'}, $args->{'links_target'}, - $args->{'collapsible_header'}); + $collapsible); if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { if ($dc_info) { @@ -6960,8 +7072,9 @@ END $bodytag .= '<hr style="clear:both" />'; $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); } - if ($args->{'collapsible_header'}) { - $bodytag .= '<div id="LC_collapsible_separator"></div>'. + if ($args->{'collapsible_header'} ne '') { + $bodytag .= $args->{'collapsible_header'}. + '<div id="LC_collapsible_separator"></div>'. '</div></div>'; } return $bodytag; @@ -7157,7 +7270,7 @@ form, .inline { } .LC_menus_content.shown{ - display: inline; + display: block; } .LC_menus_content.hidden {