--- loncom/interface/loncommon.pm 2012/11/16 16:54:45 1.1097 +++ loncom/interface/loncommon.pm 2013/04/25 17:58:40 1.1124 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.1097 2012/11/16 16:54:45 bisitz Exp $ +# $Id: loncommon.pm,v 1.1124 2013/04/25 17:58:40 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -67,6 +67,8 @@ use Apache::lonhtmlcommon(); use Apache::loncoursedata(); use Apache::lontexconvert(); use Apache::lonclonecourse(); +use Apache::lonuserutils(); +use Apache::lonuserstate(); use LONCAPA qw(:DEFAULT :match); use DateTime::TimeZone; use DateTime::Locale::Catalog; @@ -529,7 +531,8 @@ ENDAUTHORBRW } sub coursebrowser_javascript { - my ($domainfilter,$sec_element,$formname,$role_element,$crstype) = @_; + my ($domainfilter,$sec_element,$formname,$role_element,$crstype, + $credits_element) = @_; my $wintitle = 'Course_Browser'; if ($crstype eq 'Community') { $wintitle = 'Community_Browser'; @@ -592,8 +595,9 @@ sub coursebrowser_javascript { } $id_functions ENDSTDBRW - if (($sec_element ne '') || ($role_element ne '')) { - $output .= &setsec_javascript($sec_element,$formname,$role_element); + if (($sec_element ne '') || ($role_element ne '') || ($credits_element ne '')) { + $output .= &setsec_javascript($sec_element,$formname,$role_element, + $credits_element); } $output .= ' // ]]> @@ -750,7 +754,7 @@ ENDUSERBRW } sub setsec_javascript { - my ($sec_element,$formname,$role_element) = @_; + my ($sec_element,$formname,$role_element,$credits_element) = @_; my (@courserolenames,@communityrolenames,$rolestr,$courserolestr, $communityrolestr); if ($role_element ne '') { @@ -845,6 +849,14 @@ function setRole(crstype) { } |; } + if ($credits_element) { + $setsections .= qq| +function setCredits(defaultcredits) { + document.$formname.$credits_element.value = defaultcredits; + return; +} +|; + } return $setsections; } @@ -999,6 +1011,7 @@ sub select_language { $langchoices{$code} = &plainlanguagedescription($id); } } + %langchoices = &Apache::lonlocal::texthash(%langchoices); return &select_form($selected,$name,\%langchoices); } @@ -1057,6 +1070,12 @@ linked_select_forms takes the following =item * $menuorder, the order of values in the first menu +=item * $onchangefirst, additional javascript call to execute for an onchange + event for the first <select> tag + +=item * $onchangesecond, additional javascript call to execute for an onchange + event for the second <select> tag + =back Below is an example of such a hash. Only the 'text', 'default', and @@ -1110,6 +1129,8 @@ sub linked_select_forms { $secondselectname, $hashref, $menuorder, + $onchangefirst, + $onchangesecond ) = @_; my $second = "document.$formname.$secondselectname"; my $first = "document.$formname.$firstselectname"; @@ -1166,7 +1187,7 @@ function select1_changed() { </script> END # output the initial values for the selection lists - $result .= "<select size=\"1\" name=\"$firstselectname\" onchange=\"select1_changed()\">\n"; + $result .= "<select size=\"1\" name=\"$firstselectname\" onchange=\"select1_changed();$onchangefirst\">\n"; my @order = sort(keys(%{$hashref})); if (ref($menuorder) eq 'ARRAY') { @order = @{$menuorder}; @@ -1179,7 +1200,11 @@ END $result .= "</select>\n"; my %select2 = %{$hashref->{$firstdefault}->{'select2'}}; $result .= $middletext; - $result .= "<select size=\"1\" name=\"$secondselectname\">\n"; + $result .= "<select size=\"1\" name=\"$secondselectname\""; + if ($onchangesecond) { + $result .= ' onchange="'.$onchangesecond.'"'; + } + $result .= ">\n"; my $seconddefault = $hashref->{$firstdefault}->{'default'}; my @secondorder = sort(keys(%select2)); @@ -2166,7 +2191,7 @@ sub select_level_form { =pod -=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) +=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms) Returns a string containing a <select name='$name' size='1'> form to allow a user to select the domain to preform an operation in. @@ -2179,25 +2204,31 @@ If the $showdomdesc flag is set, the dom The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted. -The optional $incdoms is a reference to an array of domains which will be the only available options. +The optional $incdoms is a reference to an array of domains which will be the only available options. + +The optional $excdoms is a reference to an array of domains which will be excluded from the available options. =cut #------------------------------------------- sub select_dom_form { - my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) = @_; + my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms) = @_; if ($onchange) { $onchange = ' onchange="'.$onchange.'"'; } - my @domains; + my (@domains,%exclude); if (ref($incdoms) eq 'ARRAY') { @domains = sort {lc($a) cmp lc($b)} (@{$incdoms}); } else { @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains()); } if ($includeempty) { @domains=('',@domains); } + if (ref($excdoms) eq 'ARRAY') { + map { $exclude{$_} = 1; } @{$excdoms}; + } my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n"; foreach my $dom (@domains) { + next if ($exclude{$dom}); $selectdomain.="<option value=\"$dom\" ". ($dom eq $defdom ? 'selected="selected" ' : '').'>'.$dom; if ($showdomdesc) { @@ -2511,7 +2542,7 @@ END return $result; } -sub authform_authorwarning{ +sub authform_authorwarning { my $result=''; $result='<i>'. &mt('As a general rule, only authors or co-authors should be '. @@ -2520,16 +2551,16 @@ sub authform_authorwarning{ return $result; } -sub authform_nochange{ +sub authform_nochange { my %in = ( formname => 'document.cu', kerb_def_dom => 'MSU.EDU', @_, ); - my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); my $result; - if (keys(%can_assign) == 0) { - $result = &mt('Under you current role you are not permitted to change login settings for this user'); + if (!$authnum) { + $result = &mt('Under your current role you are not permitted to change login settings for this user'); } else { $result = '<label>'.&mt('[_1] Do not change login data', '<input type="radio" name="login" value="nochange" '. @@ -2549,7 +2580,7 @@ sub authform_kerberos { ); my ($check4,$check5,$krbcheck,$krbarg,$krbver,$result,$authtype, $autharg,$jscall); - my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); if ($in{'kerb_def_auth'} eq 'krb5') { $check5 = ' checked="checked"'; } else { @@ -2599,7 +2630,7 @@ sub authform_kerberos { if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = '<input type="hidden" name="login" value="krb" />'; + $authtype = '<input type="radio" name="login" value="krb" />'; } } } @@ -2611,9 +2642,9 @@ sub authform_kerberos { $krbcheck.' />'; } if (($can_assign{'krb4'} && $can_assign{'krb5'}) || - ($can_assign{'krb4'} && !$can_assign{'krb5'} && + ($can_assign{'krb4'} && !$can_assign{'krb5'} && $in{'curr_authtype'} eq 'krb5') || - (!$can_assign{'krb4'} && $can_assign{'krb5'} && + (!$can_assign{'krb4'} && $can_assign{'krb5'} && $in{'curr_authtype'} eq 'krb4')) { $result .= &mt ('[_1] Kerberos authenticated with domain [_2] '. @@ -2649,14 +2680,14 @@ sub authform_kerberos { return $result; } -sub authform_internal{ +sub authform_internal { my %in = ( formname => 'document.cu', kerb_def_dom => 'MSU.EDU', @_, ); my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall); - my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'int') { if ($can_assign{'int'}) { @@ -2685,7 +2716,7 @@ sub authform_internal{ if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = '<input type="hidden" name="login" value="int" />'; + $authtype = '<input type="radio" name="login" value="int" />'; } } } @@ -2704,14 +2735,14 @@ sub authform_internal{ return $result; } -sub authform_local{ +sub authform_local { my %in = ( formname => 'document.cu', kerb_def_dom => 'MSU.EDU', @_, ); my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall); - my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'loc') { if ($can_assign{'loc'}) { @@ -2740,7 +2771,7 @@ sub authform_local{ if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = '<input type="hidden" name="login" value="loc" />'; + $authtype = '<input type="radio" name="login" value="loc" />'; } } } @@ -2758,14 +2789,14 @@ sub authform_local{ return $result; } -sub authform_filesystem{ +sub authform_filesystem { my %in = ( formname => 'document.cu', kerb_def_dom => 'MSU.EDU', @_, ); my ($fsyscheck,$result,$authtype,$autharg,$jscall); - my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); + my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'}); if (defined($in{'curr_authtype'})) { if ($in{'curr_authtype'} eq 'fsys') { if ($can_assign{'fsys'}) { @@ -2791,7 +2822,7 @@ sub authform_filesystem{ if (defined($in{'mode'})) { if ($in{'mode'} eq 'modifycourse') { if ($authnum == 1) { - $authtype = '<input type="hidden" name="login" value="fsys" />'; + $authtype = '<input type="radio" name="login" value="fsys" />'; } } } @@ -4979,7 +5010,7 @@ sub CSTR_pageheader { my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; my ($udom,$uname,$thisdisfn)= - ($trailfile =~ m{^\Q$londocroot\E/priv/([^/]+)/([^/]+)/(.*)$}); + ($trailfile =~ m{^\Q$londocroot\E/priv/([^/]+)/([^/]+)(?:|/(.*))$}); my $formaction = "/priv/$udom/$uname/$thisdisfn"; $formaction =~ s{/+}{/}g; @@ -5585,11 +5616,11 @@ td.LC_table_cell_checkbox { text-align: left; } -.LC_head_subbox { +.LC_head_subbox, .LC_actionbox { clear:both; background: #F8F8F8; /* $sidebg; */ border: 1px solid $sidebg; - margin: 0 0 10px 0; + margin: 0 0 10px 0; padding: 3px; text-align: left; } @@ -5722,7 +5753,8 @@ table.LC_nested tr.LC_empty_row td { padding: 8px; } -table.LC_data_table tr.LC_empty_row td { +table.LC_data_table tr.LC_empty_row td, +table.LC_data_table tr.LC_footer_row td { background-color: $sidebg; } @@ -6284,7 +6316,6 @@ div.LC_docs_entry_move { table.LC_data_table tr > td.LC_docs_entry_commands, table.LC_data_table tr > td.LC_docs_entry_parameter { - background: #DDDDDD; font-size: x-small; } @@ -6449,6 +6480,11 @@ div.LC_edit_problem_saves { padding-bottom: 5px; } +.LC_edit_opt { + padding-left: 1em; + white-space: nowrap; +} + img.stift { border-width: 0; vertical-align: middle; @@ -6657,7 +6693,7 @@ ol.LC_docs_parameters li.LC_docs_paramet } ul#LC_secondary_menu { - clear: both; + clear: right; color: $fontmenu; background: $tabbg; list-style: none; @@ -6665,15 +6701,52 @@ ul#LC_secondary_menu { margin: 0; width: 100%; text-align: left; + float: left; } ul#LC_secondary_menu li { font-weight: bold; line-height: 1.8em; + border-right: 1px solid black; + float: left; +} + +ul#LC_secondary_menu li.LC_hoverable:hover, ul#LC_secondary_menu li.hover { + background-color: $data_table_light; +} + +ul#LC_secondary_menu li a { padding: 0 0.8em; +} + +ul#LC_secondary_menu li ul { + display: none; +} + +ul#LC_secondary_menu li:hover ul, ul#LC_secondary_menu li.hover ul { + display: block; + position: absolute; + margin: 0; + padding: 0; + list-style:none; + float: none; + background-color: $data_table_light; + z-index: 2; + margin-left: -1px; +} + +ul#LC_secondary_menu li ul li { + font-size: 90%; + vertical-align: top; + border-left: 1px solid black; border-right: 1px solid black; - display: inline; - vertical-align: middle; + background-color: $data_table_light; + list-style:none; + float: none; +} + +ul#LC_secondary_menu li ul li:hover, ul#LC_secondary_menu li ul li.hover { + background-color: $data_table_dark; } ul.LC_TabContent { @@ -7120,6 +7193,27 @@ ul.LC_funclist li { cursor:pointer; } +/* + styles used by TTH when "Default set of options to pass to tth/m + when converting TeX" in course settings has been set + + option passed: -t + +*/ + +td div.comp { margin-top: -0.6ex; margin-bottom: -1ex;} +td div.comb { margin-top: -0.6ex; margin-bottom: -.6ex;} +td div.hrcomp { line-height: 0.9; margin-top: -0.8ex; margin-bottom: -1ex;} +td div.norm {line-height:normal;} + +/* + option passed -y3 +*/ + +span.roman {font-family: serif; font-style: normal; font-weight: normal;} +span.overacc2 {position: relative; left: .8em; top: -1.2ex;} +span.overacc1 {position: relative; left: .6em; top: -1.2ex;} + END } @@ -8142,7 +8236,19 @@ sub get_sections { my %sectioncount; my $now = time; - if (!defined($possible_roles) || (grep(/^st$/,@$possible_roles))) { + my $check_students = 1; + my $only_students = 0; + if (ref($possible_roles) eq 'ARRAY') { + if (grep(/^st$/,@{$possible_roles})) { + if (@{$possible_roles} == 1) { + $only_students = 1; + } + } else { + $check_students = 0; + } + } + + if ($check_students) { my ($classlist) = &Apache::loncoursedata::get_classlist($cdom,$cnum); my $sec_index = &Apache::loncoursedata::CL_SECTION(); my $status_index = &Apache::loncoursedata::CL_STATUS(); @@ -8169,6 +8275,9 @@ sub get_sections { } } } + if ($only_students) { + return %sectioncount; + } my %courseroles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum); foreach my $user (sort(keys(%courseroles))) { if ($user !~ /^(\w{2})/) { next; } @@ -8316,7 +8425,7 @@ sub get_course_users { active => 'Active', future => 'Future', ); - my %nothide; + my (%nothide,@possdoms); if ($hidepriv) { my %coursehash=&Apache::lonnet::coursedescription($cdom.'_'.$cnum); foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) { @@ -8326,6 +8435,10 @@ sub get_course_users { $nothide{$user} = 1; } } + my @possdoms = ($cdom); + if ($coursehash{'checkforpriv'}) { + push(@possdoms,split(/,/,$coursehash{'checkforpriv'})); + } } foreach my $person (sort(keys(%coursepersonnel))) { my $match = 0; @@ -8361,7 +8474,7 @@ sub get_course_users { } if ($uname ne '' && $udom ne '') { if ($hidepriv) { - if ((&Apache::lonnet::privileged($uname,$udom)) && + if ((&Apache::lonnet::privileged($uname,$udom,\@possdoms)) && (!$nothide{$uname.':'.$udom})) { next; } @@ -8966,7 +9079,10 @@ sub user_rule_formats { my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($domain,$check); if ((ref($rules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) { if (@{$ruleorder} > 0) { - $output = '<br />'.&mt("$text{$check} with the following format(s) may <span class=\"LC_cusr_emph\">only</span> be used for verified users at [_1]:",$domdesc).' <ul>'; + $output = '<br />'. + &mt($text{$check}.' with the following format(s) may [_1]only[_2] be used for verified users at [_3]:', + '<span class="LC_cusr_emph">','</span>',$domdesc). + ' <ul>'; foreach my $rule (@{$ruleorder}) { if (ref($curr_rules) eq 'ARRAY') { if (grep(/^\Q$rule\E$/,@{$curr_rules})) { @@ -9449,18 +9565,23 @@ sub ask_for_embedded_content { my $heading = &mt('Upload embedded files'); my $buttontext = &mt('Upload'); - my $navmap; + my ($navmap,$cdom,$cnum); if ($env{'request.course.id'}) { - $navmap = Apache::lonnavmaps::navmap->new(); + if ($actionurl eq '/adm/dependencies') { + $navmap = Apache::lonnavmaps::navmap->new(); + } + $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; } - if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { + if (($actionurl eq '/adm/portfolio') || + ($actionurl eq '/adm/coursegrp_portfolio')) { my $current_path='/'; if ($env{'form.currentpath'}) { $current_path = $env{'form.currentpath'}; } if ($actionurl eq '/adm/coursegrp_portfolio') { - $udom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - $uname = $env{'course.'.$env{'request.course.id'}.'.num'}; + $udom = $cdom; + $uname = $cnum; $url = '/userfiles/groups/'.$env{'form.group'}.'/portfolio'; } else { $udom = $env{'user.domain'}; @@ -9492,8 +9613,6 @@ sub ask_for_embedded_content { } } elsif ($actionurl eq '/adm/dependencies') { if ($env{'request.course.id'} ne '') { - $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; if (ref($args) eq 'HASH') { $url = $args->{'docs_url'}; $title = $args->{'docs_title'}; @@ -9507,8 +9626,15 @@ sub ask_for_embedded_content { $heading = &mt('Status of dependencies in [_1]',"$title ($filename)"); } } + } elsif ($actionurl eq "/public/$cdom/$cnum/syllabus") { + $udom = $cdom; + $uname = $cnum; + $url = "/uploaded/$cdom/$cnum/portfolio/syllabus"; + $toplevel = $url; + $path = $url; + $fileloc = &Apache::lonnet::filelocation('',$toplevel).'/'; + $fileloc =~ s{^/}{}; } - my $now = time(); foreach my $embed_file (keys(%{$allfiles})) { my $absolutepath; if ($embed_file =~ m{^\w+://}) { @@ -9547,7 +9673,8 @@ sub ask_for_embedded_content { my $dirptr = 16384; foreach my $path (keys(%subdependencies)) { $currsubfile{$path} = {}; - if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { + if (($actionurl eq '/adm/portfolio') || + ($actionurl eq '/adm/coursegrp_portfolio')) { my ($sublistref,$listerror) = &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath); if (ref($sublistref) eq 'ARRAY') { @@ -9563,9 +9690,15 @@ sub ask_for_embedded_content { } } elsif (($actionurl eq '/adm/dependencies') || (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') && - ($args->{'context'} eq 'paste'))) { + ($args->{'context'} eq 'paste')) || + ($actionurl eq "/public/$cdom/$cnum/syllabus")) { if ($env{'request.course.id'} ne '') { - my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$}); + my $dir; + if ($actionurl eq "/public/$cdom/$cnum/syllabus") { + $dir = $fileloc; + } else { + ($dir) = ($fileloc =~ m{^(.+/)[^/]+$}); + } if ($dir ne '') { my ($sublistref,$listerror) = &Apache::lonnet::dirlist($dir.$path,$cdom,$cnum,$getpropath,undef,'/'); @@ -9613,7 +9746,8 @@ sub ask_for_embedded_content { } } my %currfile; - if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { + if (($actionurl eq '/adm/portfolio') || + ($actionurl eq '/adm/coursegrp_portfolio')) { my ($dirlistref,$listerror) = &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath); if (ref($dirlistref) eq 'ARRAY') { @@ -9629,7 +9763,8 @@ sub ask_for_embedded_content { } } elsif (($actionurl eq '/adm/dependencies') || (($actionurl eq '/adm/coursedocs') && (ref($args) eq 'HASH') && - ($args->{'context'} eq 'paste'))) { + ($args->{'context'} eq 'paste')) || + ($actionurl eq "/public/$cdom/$cnum/syllabus")) { if ($env{'request.course.id'} ne '') { my ($dir) = ($fileloc =~ m{^(.+/)[^/]+$}); if ($dir ne '') { @@ -9678,28 +9813,38 @@ sub ask_for_embedded_content { ($args->{'context'} eq 'paste')) { $counter = scalar(keys(%existing)); $numpathchg = scalar(keys(%pathchanges)); - return ($output,$counter,$numpathchg,\%existing); + return ($output,$counter,$numpathchg,\%existing); + } elsif (($actionurl eq "/public/$cdom/$cnum/syllabus") && + (ref($args) eq 'HASH') && ($args->{'context'} eq 'rewrites')) { + $counter = scalar(keys(%existing)); + $numpathchg = scalar(keys(%pathchanges)); + return ($output,$counter,$numpathchg,\%existing,\%mapping); } foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) { if ($actionurl eq '/adm/dependencies') { next if ($embed_file =~ m{^\w+://}); } $upload_output .= &start_data_table_row(). - '<td><img src="'.&icon($embed_file).'" /> '. + '<td valign="top"><img src="'.&icon($embed_file).'" /> '. '<span class="LC_filename">'.$embed_file.'</span>'; unless ($mapping{$embed_file} eq $embed_file) { - $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'.&mt('changed from: [_1]',$mapping{$embed_file}).'</span>'; + $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'. + &mt('changed from: [_1]',$mapping{$embed_file}).'</span>'; } - $upload_output .= '</td><td>'; + $upload_output .= '</td>'; if ($args->{'ignore_remote_references'} && $embed_file =~ m{^\w+://}) { - $upload_output.='<span class="LC_warning">'.&mt("URL points to other server.").'</span>'; + $upload_output.='<td align="right">'. + '<span class="LC_info LC_fontsize_medium">'. + &mt("URL points to web address").'</span>'; $numremref++; } elsif ($args->{'error_on_invalid_names'} && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) { - $upload_output.='<span class="LC_warning">'.&mt('Invalid characters').'</span>'; + $upload_output.='<td align="right"><span class="LC_warning">'. + &mt('Invalid characters').'</span>'; $numinvalid++; } else { - $upload_output .= &embedded_file_element('upload_embedded',$counter, + $upload_output .= '<td>'. + &embedded_file_element('upload_embedded',$counter, $embed_file,\%mapping, $allfiles,$codebase,'upload'); $counter ++; @@ -9728,8 +9873,9 @@ sub ask_for_embedded_content { $counter ++; } else { $upload_output .= &start_data_table_row(). - '<td><span class="LC_filename">'.$embed_file.'</span></td>'; - '<td><span class="LC_warning">'.&mt('Already exists').'</span></td>'. + '<td valign="top"><img src="'.&icon($embed_file).'" /> '. + '<span class="LC_filename">'.$embed_file.'</span></td>'. + '<td align="right"><span class="LC_info LC_fontsize_medium">'.&mt('Already exists').'</span></td>'. &Apache::loncommon::end_data_table_row()."\n"; } } @@ -9824,7 +9970,7 @@ sub ask_for_embedded_content { $output = '<b>'.&mt('Referenced files').'</b>:<br />'; if ($applies > 1) { $output .= - &mt('No files need to be uploaded, as one of the following applies to each reference:').'<ul>'; + &mt('No dependencies need to be uploaded, as one of the following applies to each reference:').'<ul>'; if ($numremref) { $output .= '<li>'.&mt('reference is to a URL which points to another server').'</li>'."\n"; } @@ -9880,13 +10026,13 @@ sub ask_for_embedded_content { } elsif ($actionurl eq '/adm/dependencies') { $output .= '<input type="hidden" name="action" value="process_changes" />'; } - $output .= '<input type ="submit" value="'.$buttontext.'" />'."\n".'</form>'."\n"; + $output .= '<input type ="submit" value="'.$buttontext.'" />'."\n".'</form>'."\n"; } elsif ($numpathchg) { my %pathchange = (); $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output); if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { $output .= '<p>'.&mt('or').'</p>'; - } + } } return ($output,$counter,$numpathchg); } @@ -10022,21 +10168,23 @@ sub upload_embedded { $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1).'<br />'; next; } elsif ($fname=~/\.(\d+)\.(\w+)$/) { - $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'<br />'; + $output .= &mt('Filename not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'<br />'; next; } $env{'form.embedded_item_'.$i.'.filename'}=$fname; + my $subdir = $path; + $subdir =~ s{/+$}{}; if ($context eq 'portfolio') { my $result; if ($state eq 'existingfile') { $result= &Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile', - $dirpath.$env{'form.currentpath'}.$path); + $dirpath.$env{'form.currentpath'}.$subdir); } else { $result= &Apache::lonnet::userfileupload('embedded_item_'.$i,'', $dirpath. - $env{'form.currentpath'}.$path); + $env{'form.currentpath'}.$subdir); if ($result !~ m|^/uploaded/|) { $output .= '<span class="LC_error">' .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].' @@ -10048,10 +10196,10 @@ sub upload_embedded { $path.$fname.'</span>').'<br />'; } } - } elsif ($context eq 'coursedoc') { + } elsif (($context eq 'coursedoc') || ($context eq 'syllabus')) { my $result = - &Apache::lonnet::userfileupload('embedded_item_'.$i,'coursedoc', - $dirpath.'/'.$path); + &Apache::lonnet::userfileupload('embedded_item_'.$i,$context, + $dirpath.'/'.$subdir); if ($result !~ m|^/uploaded/|) { $output .= '<span class="LC_error">' .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].' @@ -10061,6 +10209,7 @@ sub upload_embedded { } else { $output .= &mt('Uploaded [_1]','<span class="LC_filename">'. $path.$fname.'</span>').'<br />'; + &Apache::lonnet::make_public_indefinitely($result); } } else { # Save the file @@ -10192,7 +10341,7 @@ sub modify_html_form { } sub modify_html_refs { - my ($context,$dirpath,$uname,$udom,$dir_root) = @_; + my ($context,$dirpath,$uname,$udom,$dir_root,$url) = @_; my $container; if ($context eq 'portfolio') { $container = $env{'form.container'}; @@ -10201,6 +10350,8 @@ sub modify_html_refs { } elsif ($context eq 'manage_dependencies') { (undef,undef,$container) = &Apache::lonnet::decode_symb($env{'form.symb'}); $container = "/$container"; + } elsif ($context eq 'syllabus') { + $container = $url; } else { $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'}; } @@ -10214,7 +10365,7 @@ sub modify_html_refs { } } if (($context eq 'portfolio') || ($context eq 'coursedoc') || - ($context eq 'manage_dependencies')) { + ($context eq 'manage_dependencies') || ($context eq 'syllabus')) { unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/}) { if (wantarray) { return ('',0,0); @@ -10270,6 +10421,7 @@ sub modify_html_refs { if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) { my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi); $count += $numchg; + $allfiles{$newname} = $allfiles{$ref}; } if ($env{'form.embedded_codebase_'.$i} ne '') { $codebase = &unescape($env{'form.embedded_codebase_'.$i}); @@ -10278,10 +10430,11 @@ sub modify_html_refs { } } } + my $skiprewrites; if ($count || $codebasecount) { my $saveresult; if (($context eq 'portfolio') || ($context eq 'coursedoc') || - ($context eq 'manage_dependencies')) { + ($context eq 'manage_dependencies') || ($context eq 'syllabus')) { my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult); if ($url eq $container) { my ($fname) = ($container =~ m{/([^/]+)$}); @@ -10294,6 +10447,11 @@ sub modify_html_refs { '<span class="LC_filename">'. $container.'</span>').'</p>'; } + if ($context eq 'syllabus') { + unless ($saveresult eq 'ok') { + $skiprewrites = 1; + } + } } else { if (open(my $fh,">$container")) { print $fh $content; @@ -10309,6 +10467,47 @@ sub modify_html_refs { } } } + if (($context eq 'syllabus') && (!$skiprewrites)) { + my ($actionurl,$state); + $actionurl = "/public/$udom/$uname/syllabus"; + my ($ignore,$num,$numpathchanges,$existing,$mapping) = + &ask_for_embedded_content($actionurl,$state,\%allfiles, + \%codebase, + {'context' => 'rewrites', + 'ignore_remote_references' => 1,}); + if (ref($mapping) eq 'HASH') { + my $rewrites = 0; + foreach my $key (keys(%{$mapping})) { + next if ($key =~ m{^https?://}); + my $ref = $mapping->{$key}; + my $newname = "/uploaded/$udom/$uname/portfolio/syllabus/$key"; + my $attrib; + if (ref($allfiles{$mapping->{$key}}) eq 'ARRAY') { + $attrib = join('|',@{$allfiles{$mapping->{$key}}}); + } + if ($content =~ m{($attrib\s*=\s*['"]?)\Q$ref\E(['"]?)}) { + my $numchg = ($content =~ s{($attrib\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi); + $rewrites += $numchg; + } + } + if ($rewrites) { + my $saveresult; + my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult); + if ($url eq $container) { + my ($fname) = ($container =~ m{/([^/]+)$}); + $output .= '<p>'.&mt('Rewrote [quant,_1,link] as [quant,_1,absolute link] in [_2].', + $count,'<span class="LC_filename">'. + $fname.'</span>').'</p>'; + } else { + $output .= '<p class="LC_error">'. + &mt('Error: could not update links in [_1].', + '<span class="LC_filename">'. + $container.'</span>').'</p>'; + + } + } + } + } } else { &logthis('Failed to parse '.$container. ' to modify references: '.$parse_result); @@ -10724,8 +10923,8 @@ sub process_decompression { my ($docudom,$docuname,$file,$destination,$dir_root,$hiddenelem) = @_; my ($dir,$error,$warning,$output); if ($file !~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/) { - $error = &mt('File name not a supported archive file type.'). - '<br />'.&mt('File name should end with one of: [_1].', + $error = &mt('Filename not a supported archive file type.'). + '<br />'.&mt('Filename should end with one of: [_1].', '.zip, .tar, .bz2, .gz, .tar.gz, .tar.bz2, .tgz'); } else { my $docuhome = &Apache::lonnet::homeserver($docuname,$docudom); @@ -11299,11 +11498,11 @@ sub process_extracted_files { if ($env{'form.folderpath'}) { my @items = split('&',$env{'form.folderpath'}); $folders{'0'} = $items[-2]; - $containers{'0'}='sequence'; - } elsif ($env{'form.pagepath'}) { - my @items = split('&',$env{'form.pagepath'}); - $folders{'0'} = $items[-2]; - $containers{'0'}='page'; + if ($env{'form.folderpath'} =~ /\:1$/) { + $containers{'0'}='page'; + } else { + $containers{'0'}='sequence'; + } } my @archdirs = &get_env_multiple('form.archive_directory'); if ($numitems) { @@ -11564,7 +11763,7 @@ sub cleanup_empty_dirs { my $numitems = 0; foreach my $item (@dircontents) { if (-d "$path/$item") { - &recurse_dirs("$path/$item"); + &cleanup_empty_dirs("$path/$item"); if (-e "$path/$item") { $numitems ++; } @@ -13113,7 +13312,7 @@ sub commit_customrole { } sub commit_standardrole { - my ($udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context) = @_; + my ($udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context,$credits) = @_; my ($output,$logmsg,$linefeed); if ($context eq 'auto') { $linefeed = "\n"; @@ -13122,7 +13321,7 @@ sub commit_standardrole { } if ($three eq 'st') { my $result = &commit_studentrole(\$logmsg,$udom,$uname,$url,$three,$start,$end, - $one,$two,$sec,$context); + $one,$two,$sec,$context,$credits); if (($result =~ /^error/) || ($result eq 'not_in_class') || ($result eq 'unknown_course') || ($result eq 'refused')) { $output = $logmsg.' '.&mt('Error: ').$result."\n"; @@ -13153,7 +13352,8 @@ sub commit_standardrole { } sub commit_studentrole { - my ($logmsg,$udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context) = @_; + my ($logmsg,$udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context, + $credits) = @_; my ($result,$linefeed,$oldsecurl,$newsecurl); if ($context eq 'auto') { $linefeed = "\n"; @@ -13200,7 +13400,11 @@ sub commit_studentrole { } } if (($expire_role_result eq 'ok') || ($secchange == 0)) { - $modify_section_result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,'','',$cid,'',$context); + $modify_section_result = + &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef, + undef,undef,undef,$sec, + $end,$start,'','',$cid, + '',$context,$credits); if ($modify_section_result =~ /^ok/) { if ($secchange == 1) { if ($sec eq '') { @@ -13222,7 +13426,7 @@ sub commit_studentrole { } } } else { - if ($secchange) { + if ($secchange) { $$logmsg .= &mt('Error when attempting section change for [_1] from old section "[_2]" to new section: "[_3]" in course [_4] -error:',$uname,$oldsec,$sec,$cid).' '.$modify_section_result.$linefeed; } else { $$logmsg .= &mt('Error when attempting to modify role for [_1] for section: "[_2]" in course [_3] -error:',$uname,$sec,$cid).' '.$modify_section_result.$linefeed; @@ -13231,7 +13435,7 @@ sub commit_studentrole { $result = $modify_section_result; } elsif ($secchange == 1) { if ($oldsec eq '') { - $$logmsg .= &mt('Error when attempting to expire existing role without a section for [_1] in course [_3] -error: ',$uname,$cid).' '.$expire_role_result.$linefeed; + $$logmsg .= &mt('Error when attempting to expire existing role without a section for [_1] in course [_2] -error: ',$uname,$cid).' '.$expire_role_result.$linefeed; } else { $$logmsg .= &mt('Error when attempting to expire existing role for [_1] in section [_2] in course [_3] -error: ',$uname,$oldsec,$cid).' '.$expire_role_result.$linefeed; } @@ -13257,6 +13461,26 @@ sub commit_studentrole { return $result; } +sub show_role_extent { + my ($scope,$context,$role) = @_; + $scope =~ s{^/}{}; + my @courseroles = &Apache::lonuserutils::roles_by_context('course',1); + push(@courseroles,'co'); + my @authorroles = &Apache::lonuserutils::roles_by_context('author'); + if (($context eq 'course') || (grep(/^\Q$role\E/,@courseroles))) { + $scope =~ s{/}{_}; + return '<span class="LC_cusr_emph">'.$env{'course.'.$scope.'.description'}.'</span>'; + } elsif (($context eq 'author') || (grep(/^\Q$role\E/,@authorroles))) { + my ($audom,$auname) = split(/\//,$scope); + return &mt('[_1] Author Space','<span class="LC_cusr_emph">'. + &Apache::loncommon::plainname($auname,$audom).'</span>'); + } else { + $scope =~ s{/$}{}; + return &mt('Domain: [_1]','<span class="LC_cusr_emph">'. + &Apache::lonnet::domain($scope,'description').'</span>'); + } +} + ############################################################ ############################################################ @@ -13420,6 +13644,7 @@ sub construct_course { 'pch.users.denied', 'plc.users.denied', 'hidefromcat', + 'checkforpriv', 'categories'], $$crsudom,$$crsunum); } @@ -13449,6 +13674,9 @@ sub construct_course { } else { $cenv{'internal.courseowner'} = $args->{'curruser'}; } + if ($args->{'defaultcredits'}) { + $cenv{'internal.defaultcredits'} = $args->{'defaultcredits'}; + } my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner. if ($args->{'crssections'}) { $cenv{'internal.sectionnums'} = ''; @@ -13473,6 +13701,11 @@ sub construct_course { # do not hide course coordinator from staff listing, # even if privileged $cenv{'nothideprivileged'}=$args->{'ccuname'}.':'.$args->{'ccdomain'}; +# add course coordinator's domain to domains to check for privileged users +# if different to course domain + if ($$crsudom ne $args->{'ccdomain'}) { + $cenv{'checkforpriv'} = $args->{'ccdomain'}; + } # add crosslistings if ($args->{'crsxlist'}) { $cenv{'internal.crosslistings'}=''; @@ -14063,6 +14296,32 @@ sub update_content_constraints { return; } +sub allmaps_incourse { + my ($cdom,$cnum,$chome,$cid) = @_; + if ($cdom eq '' || $cnum eq '' || $chome eq '' || $cid eq '') { + $cid = $env{'request.course.id'}; + $cdom = $env{'course.'.$cid.'.domain'}; + $cnum = $env{'course.'.$cid.'.num'}; + $chome = $env{'course.'.$cid.'.home'}; + } + my %allmaps = (); + my $lastchange = + &Apache::lonnet::get_coursechange($cdom,$cnum); + if ($lastchange > $env{'request.course.tied'}) { + my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum"); + unless ($ferr) { + &update_content_constraints($cdom,$cnum,$chome,$cid); + } + } + my $navmap = Apache::lonnavmaps::navmap->new(); + if (defined($navmap)) { + foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_map() },1,0,1)) { + $allmaps{$res->src()} = 1; + } + } + return \%allmaps; +} + sub parse_supplemental_title { my ($title) = @_; @@ -14086,6 +14345,74 @@ sub parse_supplemental_title { return $title; } +sub symb_to_docspath { + my ($symb) = @_; + return unless ($symb); + my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($symb); + if ($resurl=~/\.(sequence|page)$/) { + $mapurl=$resurl; + } elsif ($resurl eq 'adm/navmaps') { + $mapurl=$env{'course.'.$env{'request.course.id'}.'.url'}; + } + my $mapresobj; + my $navmap = Apache::lonnavmaps::navmap->new(); + if (ref($navmap)) { + $mapresobj = $navmap->getResourceByUrl($mapurl); + } + $mapurl=~s{^.*/([^/]+)\.(\w+)$}{$1}; + my $type=$2; + my $path; + if (ref($mapresobj)) { + my $pcslist = $mapresobj->map_hierarchy(); + if ($pcslist ne '') { + foreach my $pc (split(/,/,$pcslist)) { + next if ($pc <= 1); + my $res = $navmap->getByMapPc($pc); + if (ref($res)) { + my $thisurl = $res->src(); + $thisurl=~s{^.*/([^/]+)\.\w+$}{$1}; + my $thistitle = $res->title(); + $path .= '&'. + &Apache::lonhtmlcommon::entity_encode($thisurl).'&'. + &Apache::lonhtmlcommon::entity_encode($thistitle). + ':'.$res->randompick(). + ':'.$res->randomout(). + ':'.$res->encrypted(). + ':'.$res->randomorder(). + ':'.$res->is_page(); + } + } + } + $path =~ s/^\&//; + my $maptitle = $mapresobj->title(); + if ($mapurl eq 'default') { + $maptitle = 'Main Course Documents'; + } + $path .= (($path ne '')? '&' : ''). + &Apache::lonhtmlcommon::entity_encode($mapurl).'&'. + &Apache::lonhtmlcommon::entity_encode($maptitle). + ':'.$mapresobj->randompick(). + ':'.$mapresobj->randomout(). + ':'.$mapresobj->encrypted(). + ':'.$mapresobj->randomorder(). + ':'.$mapresobj->is_page(); + } else { + my $maptitle = &Apache::lonnet::gettitle($mapurl); + my $ispage = (($type eq 'page')? 1 : ''); + if ($mapurl eq 'default') { + $maptitle = 'Main Course Documents'; + } + $path = &Apache::lonhtmlcommon::entity_encode($mapurl).'&'. + &Apache::lonhtmlcommon::entity_encode($maptitle).':::::'.$ispage; + } + unless ($mapurl eq 'default') { + $path = 'default&'. + &Apache::lonhtmlcommon::entity_encode('Main Course Documents'). + ':::::&'.$path; + } + return $path; +} + sub captcha_display { my ($context,$lonhost) = @_; my ($output,$error); @@ -14204,7 +14531,7 @@ sub check_captcha { output_folder => $captcha_params{'output_dir'}, data_folder => $captcha_params{'db_dir'}, ); - my $captcha_chk = $captcha->check_code($code,$md5sum); + $captcha_chk = $captcha->check_code($code,$md5sum); my %captcha_hash = ( 0 => 'Code not checked (file error)', -1 => 'Failed: code expired',