--- loncom/interface/loncommon.pm 2009/10/16 00:17:25 1.898 +++ loncom/interface/loncommon.pm 2011/12/23 16:55:34 1.1046 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.898 2009/10/16 00:17:25 raeburn Exp $ +# $Id: loncommon.pm,v 1.1046 2011/12/23 16:55:34 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -409,7 +409,7 @@ sub studentbrowser_javascript { +ENDRESBRW +} + sub selectstudent_link { - my ($form,$unameele,$udomele,$courseadvonly)=@_; - my $callargs = "'".$form."','".$unameele."','".$udomele."'"; + my ($form,$unameele,$udomele,$courseadvonly,$clickerid)=@_; + my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','". + &Apache::lonhtmlcommon::entity_encode($unameele)."','". + &Apache::lonhtmlcommon::entity_encode($udomele)."'"; if ($env{'request.course.id'}) { if (!&Apache::lonnet::allowed('srm',$env{'request.course.id'}) && !&Apache::lonnet::allowed('srm',$env{'request.course.id'}. '/'.$env{'request.course.sec'})) { return ''; } + $callargs.=",'".&Apache::lonhtmlcommon::entity_encode($clickerid)."'"; if ($courseadvonly) { $callargs .= ",'',1,1"; } @@ -452,7 +475,7 @@ sub selectstudent_link { &mt('Select User').''; } if ($env{'request.role'}=~/^(au|dc|su)/) { - $callargs .= ",1"; + $callargs .= ",'',1"; return ''. ''. &mt('Select User').''; @@ -460,6 +483,19 @@ sub selectstudent_link { return ''; } +sub selectresource_link { + my ($form,$reslink,$arg)=@_; + + my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','". + &Apache::lonhtmlcommon::entity_encode($reslink)."'"; + unless ($env{'request.course.id'}) { return $arg; } + return ''. + ''. + $arg.''; +} + + + sub authorbrowser_javascript { return <<"ENDAUTHORBRW"; + +ENDJS + +} + sub userbrowser_javascript { my $id_functions = &javascript_index_functions(); return <<"ENDUSERBRW"; @@ -661,7 +739,28 @@ ENDUSERBRW } sub setsec_javascript { - my ($sec_element,$formname) = @_; + my ($sec_element,$formname,$role_element) = @_; + my (@courserolenames,@communityrolenames,$rolestr,$courserolestr, + $communityrolestr); + if ($role_element ne '') { + my @allroles = ('st','ta','ep','in','ad'); + foreach my $crstype ('Course','Community') { + if ($crstype eq 'Community') { + foreach my $role (@allroles) { + push(@communityrolenames,&Apache::lonnet::plaintext($role,$crstype)); + } + push(@communityrolenames,&Apache::lonnet::plaintext('co')); + } else { + foreach my $role (@allroles) { + push(@courserolenames,&Apache::lonnet::plaintext($role,$crstype)); + } + push(@courserolenames,&Apache::lonnet::plaintext('cc')); + } + } + $rolestr = '"'.join('","',@allroles).'"'; + $courserolestr = '"'.join('","',@courserolenames).'"'; + $communityrolestr = '"'.join('","',@communityrolenames).'"'; + } my $setsections = qq| function setSect(sectionlist) { var sectionsArray = new Array(); @@ -695,22 +794,68 @@ function setSect(sectionlist) { } } } + +function setRole(crstype) { |; + if ($role_element eq '') { + $setsections .= ' return; +} +'; + } else { + $setsections .= qq| + var elementLength = document.$formname.$role_element.length; + var allroles = Array($rolestr); + var courserolenames = Array($courserolestr); + var communityrolenames = Array($communityrolestr); + if (elementLength != undefined) { + if (document.$formname.$role_element.options[5].value == 'cc') { + if (crstype == 'Course') { + return; + } else { + allroles[5] = 'co'; + for (var i=0; i<6; i++) { + document.$formname.$role_element.options[i].value = allroles[i]; + document.$formname.$role_element.options[i].text = communityrolenames[i]; + } + } + } else { + if (crstype == 'Community') { + return; + } else { + allroles[5] = 'cc'; + for (var i=0; i<6; i++) { + document.$formname.$role_element.options[i].value = allroles[i]; + document.$formname.$role_element.options[i].text = courserolenames[i]; + } + } + } + } + return; +} +|; + } return $setsections; } - sub selectcourse_link { - my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype)=@_; + my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype, + $typeelement) = @_; + my $type = $selecttype; my $linktext = &mt('Select Course'); if ($selecttype eq 'Community') { - $linktext = &mt('Select Community'); + $linktext = &mt('Select Community'); + } elsif ($selecttype eq 'Course/Community') { + $linktext = &mt('Select Course/Community'); + $type = ''; + } elsif ($selecttype eq 'Select') { + $linktext = &mt('Select'); + $type = ''; } return '' ."".$linktext.'' .''; } @@ -839,7 +984,7 @@ sub select_language { $langchoices{$code} = &plainlanguagedescription($id); } } - return &select_form($selected,$name,%langchoices); + return &select_form($selected,$name,\%langchoices); } =pod @@ -1011,7 +1156,7 @@ END =pod -=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height) +=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height,$imgid) Returns a string corresponding to an HTML link to the given help $topic, where $topic corresponds to the name of a .tex file in @@ -1029,15 +1174,19 @@ a new window using Javascript. (Default $width and $height are optional numerical parameters that will override the width and height of the popped up window, which may -be useful for certain help topics with big pictures included. +be useful for certain help topics with big pictures included. + +$imgid is the id of the img tag used for the help icon. This may be +used in a javascript call to switch the image src. See +lonhtmlcommon::htmlareaselectactive() for an example. =cut sub help_open_topic { - my ($topic, $text, $stayOnPage, $width, $height) = @_; + my ($topic, $text, $stayOnPage, $width, $height, $imgid) = @_; $text = "" if (not defined $text); $stayOnPage = 0 if (not defined $stayOnPage); - $width = 350 if (not defined $width); + $width = 500 if (not defined $width); $height = 400 if (not defined $height); my $filename = $topic; $filename =~ s/ /_/g; @@ -1048,7 +1197,9 @@ sub help_open_topic { $topic=~s/\W/\_/g; if (!$stayOnPage) { - $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))"; + $link = "javascript:openMyModal('/adm/help/${filename}.hlp',$width,$height,'yes');"; + } elsif ($stayOnPage eq 'popup') { + $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))"; } else { $link = "/adm/help/${filename}.hlp"; } @@ -1063,10 +1214,13 @@ sub help_open_topic { # (Always) Add the graphic my $title = &mt('Online Help'); my $helpicon=&lonhttpdurl("/adm/help/help.png"); + if ($imgid ne '') { + $imgid = ' id="'.$imgid.'"'; + } $template.=' ' .''.&mt('Help: [_1]',$topic).''; if ($text ne "") { $template.=''; @@ -1078,27 +1232,22 @@ sub help_open_topic { # This is a quicky function for Latex cheatsheet editing, since it # appears in at least four places sub helpLatexCheatsheet { - my ($topic,$text,$not_author) = @_; + my ($topic,$text,$not_author,$stayOnPage) = @_; my $out; my $addOther = ''; if ($topic) { - $addOther = ''.&Apache::loncommon::help_open_topic($topic,&mt($text), - undef, undef, 600). - ' '; + $addOther = ''.&help_open_topic($topic,&mt($text),$stayOnPage, undef, 600).' '; } $out = '' # Start cheatsheet .$addOther .'' - .&Apache::loncommon::help_open_topic('Greek_Symbols',&mt('Greek Symbols'), - undef,undef,600) + .&help_open_topic('Greek_Symbols',&mt('Greek Symbols'),$stayOnPage,undef,600) .' ' - .&Apache::loncommon::help_open_topic('Other_Symbols',&mt('Other Symbols'), - undef,undef,600) + .&help_open_topic('Other_Symbols',&mt('Other Symbols'),$stayOnPage,undef,600) .''; unless ($not_author) { $out .= ' ' - .&Apache::loncommon::help_open_topic('Authoring_Output_Tags',&mt('Output Tags'), - undef,undef,600) + .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600) .''; } $out .= ''; # End cheatsheet @@ -1109,7 +1258,7 @@ sub general_help { my $helptopic='Student_Intro'; if ($env{'request.role'}=~/^(ca|au)/) { $helptopic='Authoring_Intro'; - } elsif ($env{'request.role'}=~/^cc/) { + } elsif ($env{'request.role'}=~/^(cc|co)/) { $helptopic='Course_Coordination_Intro'; } elsif ($env{'request.role'}=~/^dc/) { $helptopic='Domain_Coordination_Intro'; @@ -1141,12 +1290,7 @@ ENDOUTPUT sub help_open_menu { my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text) = @_; - $stayOnPage = 0 if (not defined $stayOnPage); - # only use pop-up help (stayOnPage == 0) - # if environment.remote is on (using remote control UI) - if ($env{'environment.remote'} eq 'off' ) { - $stayOnPage=1; - } + $stayOnPage = 1; my $output; if ($component_help) { if (!$text) { @@ -1167,8 +1311,8 @@ sub help_open_menu { sub top_nav_help { my ($text) = @_; $text = &mt($text); - my $stay_on_page = - ($env{'environment.remote'} eq 'off' ); + my $stay_on_page = 1; + my $link = ($stay_on_page) ? "javascript:helpMenu('display')" : "javascript:helpMenu('open')"; my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page); @@ -1183,10 +1327,7 @@ END sub help_menu_js { my ($text) = @_; - - my $stayOnPage = - ($env{'environment.remote'} eq 'off' ); - + my $stayOnPage = 1; my $width = 620; my $height = 600; my $helptopic=&general_help(); @@ -1243,10 +1384,7 @@ sub help_open_bug { unless ($env{'user.adv'}) { return ''; } unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; } $text = "" if (not defined $text); - $stayOnPage = 0 if (not defined $stayOnPage); - if ($env{'environment.remote'} eq 'off' ) { $stayOnPage=1; - } $width = 600 if (not defined $width); $height = 600 if (not defined $height); @@ -1287,10 +1425,7 @@ sub help_open_faq { unless ($env{'user.adv'}) { return ''; } unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; } $text = "" if (not defined $text); - $stayOnPage = 0 if (not defined $stayOnPage); - if ($env{'environment.remote'} eq 'off' ) { $stayOnPage=1; - } $width = 350 if (not defined $width); $height = 400 if (not defined $height); @@ -1658,14 +1793,17 @@ sub create_workbook { my $workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); if (! defined($workbook)) { $r->log_error("Error creating excel spreadsheet $filename: $!"); - $r->print('

'.&mt("Unable to create new Excel file. ". - "This error has been logged. ". - "Please alert your LON-CAPA administrator"). - '

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

' + .&mt('Problems occurred in creating the new Excel file.') + .' '.&mt('This error has been logged.') + .' '.&mt('Please alert your LON-CAPA administrator.') + .'

' + ); return (undef); } # - $workbook->set_tempdir('/home/httpd/perl/tmp'); + $workbook->set_tempdir(LONCAPA::tempdir()); # my $format = &Apache::loncommon::define_excel_formats($workbook); return ($workbook,$filename,$format); @@ -1701,9 +1839,13 @@ sub create_text_file { $fh = Apache::File->new('>/home/httpd'.$filename); if (! defined($fh)) { $r->log_error("Couldn't open $filename for output $!"); - $r->print(&mt('Problems occurred in creating the output file. ' - .'This error has been logged. ' - .'Please alert your LON-CAPA administrator.')); + $r->print( + '

' + .&mt('Problems occurred in creating the output file.') + .' '.&mt('This error has been logged.') + .' '.&mt('Please alert your LON-CAPA administrator.') + .'

' + ); } return ($fh,$filename) } @@ -1732,7 +1874,7 @@ sub domain_select { return &multiple_select_form($name,$value,4,\%domains); } else { $domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))]; - return &select_form($name,$value,%domains); + return &select_form($name,$value,\%domains); } } @@ -1794,29 +1936,36 @@ sub multiple_select_form { =pod -=item * &select_form($defdom,$name,%hash) +=item * &select_form($defdom,$name,$hashref,$onchange) Returns a string containing a \n"; + my ($def,$name,$hashref,$onchange) = @_; + return unless (ref($hashref) eq 'HASH'); + if ($onchange) { + $onchange = ' onchange="'.$onchange.'"'; + } + my $selectform = ""; return $selectform; @@ -1834,9 +1983,9 @@ sub display_filter { &mt('Filter [_1]', &select_form($env{'form.displayfilter'}, 'displayfilter', - ('currentfolder' => 'Current folder/page', + {'currentfolder' => 'Current folder/page', 'containing' => 'Containing phrase', - 'none' => 'None'))). + 'none' => 'None'})). ''; } @@ -1881,7 +2030,7 @@ sub select_level_form { =pod -=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange) +=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) Returns a string containing a \n"; foreach my $dom (@domains) { @@ -2199,12 +2355,16 @@ function changed_text(choice,currentform } function set_auth_radio_buttons(newvalue,currentform) { + var numauthchoices = currentform.login.length; + if (typeof numauthchoices == "undefined") { + return; + } var i=0; - while (i < currentform.login.length) { + while (i < numauthchoices) { if (currentform.login[i].value == newvalue) { break; } i++; } - if (i == currentform.login.length) { + if (i == numauthchoices) { return; } current.radiovalue = newvalue; @@ -3171,8 +3331,7 @@ sub filemimetype { sub filecategoryselect { my ($name,$value)=@_; return &select_form($value,$name, - '' => &mt('Any category'), - map { $_,$_ } sort(keys(%category_extensions))); + {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))}); } =pod @@ -3337,12 +3496,24 @@ sub get_previous_attempt { } $prevattempts=&start_data_table().&start_data_table_header_row(); $prevattempts.=''.&mt('History').''; + my (%typeparts,%lasthidden); + my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'}); foreach my $key (sort(keys(%lasthash))) { my ($ign,@parts) = split(/\./,$key); if ($#parts > 0) { my $data=$parts[-1]; + next if ($data eq 'foilorder'); pop(@parts); - $prevattempts.=''.&mt('Part ').join('.',@parts).'
'.$data.' '; + $prevattempts.=''.&mt('Part ').join('.',@parts).'
'.$data.' '; + if ($data eq 'type') { + unless ($showsurv) { + my $id = join(',',@parts); + $typeparts{$ign.'.'.$id} = $lasthash{$key}; + if (($lasthash{$key} eq 'anonsurvey') || ($lasthash{$key} eq 'anonsurveycred')) { + $lasthidden{$ign.'.'.$id} = 1; + } + } + } } else { if ($#parts == 0) { $prevattempts.=''.$parts[0].''; @@ -3354,21 +3525,93 @@ sub get_previous_attempt { $prevattempts.=&end_data_table_header_row(); if ($getattempt eq '') { for ($version=1;$version<=$returnhash{'version'};$version++) { - $prevattempts.=&start_data_table_row(). - ''.&mt('Transaction [_1]',$version).''; - foreach my $key (sort(keys(%lasthash))) { - my $value = &format_previous_attempt_value($key, - $returnhash{$version.':'.$key}); - $prevattempts.=''.$value.' '; - } - $prevattempts.=&end_data_table_row(); + my @hidden; + if (%typeparts) { + foreach my $id (keys(%typeparts)) { + if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) { + push(@hidden,$id); + } + } + } + $prevattempts.=&start_data_table_row(). + ''.&mt('Transaction [_1]',$version).''; + if (@hidden) { + foreach my $key (sort(keys(%lasthash))) { + next if ($key =~ /\.foilorder$/); + my $hide; + foreach my $id (@hidden) { + if ($key =~ /^\Q$id\E/) { + $hide = 1; + last; + } + } + if ($hide) { + my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/); + if (($data eq 'award') || ($data eq 'awarddetail')) { + my $value = &format_previous_attempt_value($key, + $returnhash{$version.':'.$key}); + $prevattempts.=''.$value.' '; + } else { + $prevattempts.=' '; + } + } else { + if ($key =~ /\./) { + my $value = &format_previous_attempt_value($key, + $returnhash{$version.':'.$key}); + $prevattempts.=''.$value.' '; + } else { + $prevattempts.=' '; + } + } + } + } else { + foreach my $key (sort(keys(%lasthash))) { + next if ($key =~ /\.foilorder$/); + my $value = &format_previous_attempt_value($key, + $returnhash{$version.':'.$key}); + $prevattempts.=''.$value.' '; + } + } + $prevattempts.=&end_data_table_row(); } } + my @currhidden = keys(%lasthidden); $prevattempts.=&start_data_table_row().''.&mt('Current').''; foreach my $key (sort(keys(%lasthash))) { - my $value = &format_previous_attempt_value($key,$lasthash{$key}); - if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)} - $prevattempts.=''.$value.' '; + next if ($key =~ /\.foilorder$/); + if (%typeparts) { + my $hidden; + foreach my $id (@currhidden) { + if ($key =~ /^\Q$id\E/) { + $hidden = 1; + last; + } + } + if ($hidden) { + my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/); + if (($data eq 'award') || ($data eq 'awarddetail')) { + my $value = &format_previous_attempt_value($key,$lasthash{$key}); + if ($key =~/$regexp$/ && (defined &$gradesub)) { + $value = &$gradesub($value); + } + $prevattempts.=''.$value.' '; + } else { + $prevattempts.=' '; + } + } else { + my $value = &format_previous_attempt_value($key,$lasthash{$key}); + if ($key =~/$regexp$/ && (defined &$gradesub)) { + $value = &$gradesub($value); + } + $prevattempts.=''.$value.' '; + } + } else { + my $value = &format_previous_attempt_value($key,$lasthash{$key}); + if ($key =~/$regexp$/ && (defined &$gradesub)) { + $value = &$gradesub($value); + } + $prevattempts.=''.$value.' '; + } } $prevattempts.= &end_data_table_row().&end_data_table(); } else { @@ -3387,10 +3630,33 @@ sub get_previous_attempt { sub format_previous_attempt_value { my ($key,$value) = @_; - if ($key =~ /timestamp/) { + if (($key =~ /timestamp/) || ($key=~/duedate/)) { $value = &Apache::lonlocal::locallocaltime($value); } elsif (ref($value) eq 'ARRAY') { $value = '('.join(', ', @{ $value }).')'; + } elsif ($key =~ /answerstring$/) { + my %answers = &Apache::lonnet::str2hash($value); + my @anskeys = sort(keys(%answers)); + if (@anskeys == 1) { + my $answer = $answers{$anskeys[0]}; + if ($answer =~ m{\0}) { + $answer =~ s{\0}{,}g; + } + my $tag_internal_answer_name = 'INTERNAL'; + if ($anskeys[0] eq $tag_internal_answer_name) { + $value = $answer; + } else { + $value = $anskeys[0].'='.$answer; + } + } else { + foreach my $ans (@anskeys) { + my $answer = $answers{$ans}; + if ($answer =~ m{\0}) { + $answer =~ s{\0}{,}g; + } + $value .= $ans.'='.$answer.'
';; + } + } } else { $value = &unescape($value); } @@ -3541,10 +3807,13 @@ sub submlink { } if (!$symb) { $symb=&Apache::lonnet::symbread(); } $symb=&escape($symb); - if ($target) { $target="target=\"$target\""; } - return ''.$text.''; + if ($target) { $target=" target=\"$target\""; } + return + ''.$text.''; } ############################################## @@ -3666,10 +3935,13 @@ sub findallcourses { $udom = $env{'user.domain'}; } if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) { - my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname); + my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1}); + my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef, + $extra); if (!%roles) { %roles = ( cc => 1, + co => 1, in => 1, ep => 1, ta => 1, @@ -4070,16 +4342,38 @@ sub get_domainconf { if (defined($cached)) { return %{$result}; } my %domconfig = &Apache::lonnet::get_dom('configuration', - ['login','rolecolors'],$udom); + ['login','rolecolors','autoenroll'],$udom); my (%designhash,%legacy); if (keys(%domconfig) > 0) { if (ref($domconfig{'login'}) eq 'HASH') { if (keys(%{$domconfig{'login'}})) { foreach my $key (keys(%{$domconfig{'login'}})) { if (ref($domconfig{'login'}{$key}) eq 'HASH') { - foreach my $img (keys(%{$domconfig{'login'}{$key}})) { - $designhash{$udom.'.login.'.$key.'_'.$img} = - $domconfig{'login'}{$key}{$img}; + if ($key eq 'loginvia') { + if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') { + foreach my $hostname (keys(%{$domconfig{'login'}{'loginvia'}})) { + if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') { + if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) { + my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'}; + $designhash{$udom.'.login.loginvia'} = $server; + if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') { + + $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'}; + } else { + $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'}; + } + if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) { + $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}; + } + } + } + } + } + } else { + foreach my $img (keys(%{$domconfig{'login'}{$key}})) { + $designhash{$udom.'.login.'.$key.'_'.$img} = + $domconfig{'login'}{$key}{$img}; + } } } else { $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key}; @@ -4106,6 +4400,11 @@ sub get_domainconf { } else { $legacy{'rolecolors'} = 1; } + if (ref($domconfig{'autoenroll'}) eq 'HASH') { + if ($domconfig{'autoenroll'}{'co-owners'}) { + $designhash{$udom.'.autoassign.co-owners'}=$domconfig{'autoenroll'}{'co-owners'}; + } + } if (keys(%legacy) > 0) { my %legacyhash = &get_legacy_domconf($udom); foreach my $item (keys(%legacyhash)) { @@ -4144,7 +4443,7 @@ sub get_legacy_domconf { close($fh); } } - if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') { + if (-e $Apache::lonnet::perlvar{'lonDocRoot'}.'/adm/lonDomLogos/'.$udom.'.gif') { $legacyhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif"; } return %legacyhash; @@ -4202,7 +4501,10 @@ sub designparm { return $env{'environment.color.'.$which}; } $domain=&determinedomain($domain); - my %domdesign = &get_domainconf($domain); + my %domdesign; + unless ($domain eq 'public') { + %domdesign = &get_domainconf($domain); + } my $output; if ($domdesign{$domain.'.'.$which} ne '') { $output = $domdesign{$domain.'.'.$which}; @@ -4227,27 +4529,39 @@ sub designparm { =item * &authorspace() -Inputs: ./. +Inputs: $url (usually will be undef). -Returns: Path to the Construction Space of the current user's - accessed author space - The author space will be that of the current user - when accessing the own author space - and that of the co-author/assistent co-author - when accessing the co-author's/assistent co-author's - space +Returns: Path to Construction Space containing the resource or + directory being viewed (or for which action is being taken). + If $url is provided, and begins /priv// + the path will be that portion of the $context argument. + Otherwise the path will be for the author space of the current + user when the current role is author, or for that of the + co-author/assistant co-author space when the current role + is co-author or assistant co-author. =cut sub authorspace { + my ($url) = @_; + if ($url ne '') { + if ($url =~ m{^(/priv/$match_domain/$match_username/)}) { + return $1; + } + } my $caname = ''; - if ($env{'request.role'} =~ /^ca|^aa/) { - (undef,$caname) = + my $cadom = ''; + if ($env{'request.role'} =~ /^(?:ca|aa)/) { + ($cadom,$caname) = ($env{'request.role'}=~/($match_domain)\/($match_username)$/); - } else { + } elsif ($env{'request.role'} =~ m{^au\./($match_domain)/}) { $caname = $env{'user.name'}; + $cadom = $env{'user.domain'}; + } + if (($caname ne '') && ($cadom ne '')) { + return "/priv/$cadom/$caname/"; } - return '/priv/'.$caname.'/'; + return; } ############################################## @@ -4265,7 +4579,7 @@ Returns: HTML div with $content sub head_subbox { my ($content)=@_; my $output = - '
' + '
' .$content .'
' } @@ -4275,7 +4589,9 @@ sub head_subbox { =item * &CSTR_pageheader() -Inputs: ./. +Input: (optional) filename from which breadcrumb trail is built. + In most cases no input as needed, as $env{'request.filename'} + is appropriate for use in building the breadcrumb trail. Returns: HTML div with CSTR path and recent box To be included on Construction Space pages @@ -4283,12 +4599,19 @@ Returns: HTML div with CSTR path and rec =cut sub CSTR_pageheader { - # this is for resources; directories have customtitle, and crumbs - # and select recent are created in lonpubdir.pm - my ($uname,$thisdisfn)= - ($env{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|); - my $formaction='/priv/'.$uname.'/'.$thisdisfn; - $formaction=~s/\/+/\//g; + my ($trailfile) = @_; + if ($trailfile eq '') { + $trailfile = $env{'request.filename'}; + } + +# this is for resources; directories have customtitle, and crumbs +# and select recent are created in lonpubdir.pm + + my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; + my ($udom,$uname,$thisdisfn)= + ($trailfile =~ m{^\Q$londocroot\E/priv/([^/]+)/([^/]+)/(.*)$}); + my $formaction = "/priv/$udom/$uname/$thisdisfn"; + $formaction =~ s{/+}{/}g; my $parentpath = ''; my $lastitem = ''; @@ -4298,18 +4621,30 @@ sub CSTR_pageheader { } else { $lastitem = $thisdisfn; } - return + + my $output = '
' .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it? .''.&mt('Construction Space:').' ' .'
' #FIXME lonpubdir: target="_parent" - .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv','','+1',1)."$lastitem
" + .'" target="_top">' #FIXME lonpubdir: target="_parent" + .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef); + + if ($lastitem) { + $output .= + '' + .$lastitem + .''; + } + $output .= + '
' #FIXME lonpubdir: &Apache::lonhtmlcommon::crumbs($uname.$thisdisfn.'/','_top','/priv','','+1',1)."
" .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()') .'
' .&Apache::lonmenu::constspaceform() .'
'; + + return $output; } ############################################### @@ -4349,9 +4684,6 @@ Inputs: =item * $bgcolor, used to override the bgcolor on a webpage to a specific value -=item * $no_inline_link, if true and in remote mode, don't show the - 'Switch To Inline Menu' link - =item * $args, optional argument valid values are no_auto_mt_title -> prevents &mt()ing the title arg inherit_jsmath -> when creating popup window in a page, @@ -4369,8 +4701,13 @@ other decorations will be returned. sub bodytag { my ($title,$function,$addentries,$bodyonly,$domain,$forcereg, - $no_nav_bar,$bgcolor,$no_inline_link,$args)=@_; + $no_nav_bar,$bgcolor,$args)=@_; + my $public; + if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public')) + || ($env{'user.name'} eq '') && ($env{'user.domain'} eq '')) { + $public = 1; + } if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); } $function = &get_users_function() if (!$function); @@ -4406,8 +4743,6 @@ sub bodytag { } if (!$realm) { $realm=' '; } -# Set messages - my $messages=&domainlogo($domain); my $extra_body_attr = &make_attr_string($forcereg,\%design); @@ -4420,7 +4755,7 @@ sub bodytag { } my $name = &plainname($env{'user.name'},$env{'user.domain'}); - if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') { + if ($public) { undef($role); } else { $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'}); @@ -4434,90 +4769,75 @@ sub bodytag { $env{'course.'.$env{'request.course.id'}. '.domain'}.'/'})) { my $cid = $env{'request.course.id'}; - $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'}; + $dc_info = $cid.' '.$env{'course.'.$cid.'.internal.coursecode'}; $dc_info =~ s/\s+$//; - $dc_info = '('.$dc_info.')'; } $role = '('.$role.')' if $role; &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']); - if ($env{'environment.remote'} eq 'off') { - # No Remote - if ($env{'request.state'} eq 'construct') { - $forcereg=1; - } - - # if ($env{'request.state'} eq 'construct') { - # $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls - # } - - my $titletable = '' - ."" - .'
$titleinfo $dc_info
'; - - if ($no_nav_bar) { - $bodytag .= $titletable; - } else { - $bodytag .= qq|
$name $role
- $realm $dc_info
| unless $env{'form.inhibitmenu'}; - -#SD $titletable is obsolete -#SD if ($env{'request.state'} eq 'construct') { -#SD $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$titletable); -#SD } else { -#SD $bodytag .= &Apache::lonmenu::menubuttons($forcereg).$titletable; -#SD } - if ( $env{'form.inhibitmenu'} eq 'yes' - || $ENV{'REQUEST_URI'} eq '/adm/logout' - || $env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { - - return $bodytag; - } + if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') { + return $bodytag; + } + + if ($env{'request.state'} eq 'construct') { $forcereg=1; } + + # if ($env{'request.state'} eq 'construct') { + # $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls + # } + - $bodytag .= Apache::lonhtmlcommon::scripttag( - Apache::lonmenu::utilityfunctions(), - 'start'); - $bodytag .= Apache::lonmenu::primary_menu(); - $bodytag .= Apache::lonmenu::secondary_menu(); - #SD remove next line - #$bodytag .= Apache::lonmenu::menubuttons($forcereg); - $bodytag .= Apache::lonmenu::serverform(); - $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); - $bodytag .= Apache::lonmenu::innerregister($forcereg) if $forcereg; + + if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { + if ($dc_info) { + $dc_info = qq|$dc_info|; + } + $bodytag .= qq|
$name $role
+ $realm $dc_info
|; + return $bodytag; } - return $bodytag; - } -# -# Top frame rendering, Remote is up -# + unless ($env{'request.symb'} =~ m/\.page___\d+___/) { + $bodytag .= qq|
$name $role
|; + } - my $imgsrc = $img; - if ($img =~ /^\/adm/) { - $imgsrc = &lonhttpdurl($img); - } - my $upperleft=''.$function.''; - - # Explicit link to get inline menu - my $menu= ($no_inline_link?'' - :''.&mt('Switch to Inline Menu Mode').''); - $bodytag .= qq|
$name $role - $realm $dc_info
-
    -
  1. $menu
  2. -
| unless $env{'form.inhibitmenu'}; - # - return(< -$upperleft - $messages  - -$titleinfo $dc_info $menu - - -ENDBODY + $bodytag .= Apache::lonhtmlcommon::scripttag( + Apache::lonmenu::utilityfunctions(), 'start'); + + $bodytag .= Apache::lonmenu::primary_menu(); + + if ($dc_info) { + $dc_info = &dc_courseid_toggle($dc_info); + } + $bodytag .= qq|
$realm $dc_info
|; + + #don't show menus for public users + if (!$public){ + $bodytag .= Apache::lonmenu::secondary_menu(); + $bodytag .= Apache::lonmenu::serverform(); + $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); + if ($env{'request.state'} eq 'construct') { + $bodytag .= &Apache::lonmenu::innerregister($forcereg, + $args->{'bread_crumbs'}); + } elsif ($forcereg) { + $bodytag .= &Apache::lonmenu::innerregister($forcereg); + } + }else{ + # this is to seperate menu from content when there's no secondary + # menu. Especially needed for public accessible ressources. + $bodytag .= '
'; + $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); + } + + return $bodytag; +} + +sub dc_courseid_toggle { + my ($dc_info) = @_; + return ' '. + ''. + &mt('(More ...)').''. + '
'.$dc_info.'
'; } sub make_attr_string { @@ -4541,22 +4861,8 @@ sub make_attr_string { delete($attr_ref->{$key}); } } - $attr_ref->{'onload'} = - &Apache::lonmenu::loadevents(). $on_load; - $attr_ref->{'onunload'}= - &Apache::lonmenu::unloadevents().$on_unload; - } - -# Accessibility font enhance - if ($env{'browser.fontenhance'} eq 'on') { - my $style; - foreach my $key (keys(%{$attr_ref})) { - if (lc($key) eq 'style') { - $style.=$attr_ref->{$key}.';'; - delete($attr_ref->{$key}); - } - } - $attr_ref->{'style'}=$style.'; font-size: x-large;'; + $attr_ref->{'onload'} = $on_load; + $attr_ref->{'onunload'}= $on_unload; } my $attr_string; @@ -4630,10 +4936,6 @@ sub standard_css { my $vlink = &designparm($function.'.vlink', $domain); my $link = &designparm($function.'.link', $domain); - my $loginbg = &designparm('login.sidebg',$domain); - my $bgcol = &designparm('login.bgcol',$domain); - my $textcol = &designparm('login.textcol',$domain); - my $sans = 'Verdana,Arial,Helvetica,sans-serif'; my $mono = 'monospace'; my $data_table_head = $sidebg; @@ -4651,49 +4953,70 @@ sub standard_css { my $mail_other_hover = '#669999'; my $table_header = '#DDDDDD'; my $feedback_link_bg = '#BBBBBB'; - my $lg_border_color = '#C8C8C8'; + my $lg_border_color = '#C8C8C8'; + my $button_hover = '#BF2317'; my $border = ($env{'browser.type'} eq 'explorer' || - $env{'browser.type'} eq 'safari' ) ? '0 2px 0 2px' - : '0 3px 0 4px'; + $env{'browser.type'} eq 'safari' ) ? '0 2px 0 2px' + : '0 3px 0 4px'; return < td text-align: left; } -table.LC_data_table tr.LC_odd_row > td, +table.LC_data_table tr.LC_odd_row > td { + background-color: $data_table_light; + padding: 2px; + vertical-align: top; +} + table.LC_pick_box tr > td.LC_odd_row { background-color: $data_table_light; + vertical-align: top; +} + +table.LC_data_table tr.LC_even_row > td { + background-color: $data_table_dark; padding: 2px; + vertical-align: top; } -table.LC_data_table tr.LC_even_row > td, table.LC_pick_box tr > td.LC_even_row { background-color: $data_table_dark; - padding: 2px; + vertical-align: top; } table.LC_data_table tr.LC_data_table_highlight td { @@ -5012,13 +5329,20 @@ table.LC_data_table tr td.LC_leftcol_hea table.LC_data_table tr.LC_empty_row td, table.LC_nested tr.LC_empty_row td { - background-color: #FFFFFF; font-weight: bold; font-style: italic; text-align: center; padding: 8px; } +table.LC_data_table tr.LC_empty_row td { + background-color: $sidebg; +} + +table.LC_nested tr.LC_empty_row td { + background-color: #FFFFFF; +} + table.LC_caption { } @@ -5086,6 +5410,7 @@ table.LC_createuser tr.LC_info_row td { table.LC_calendar { border: 1px solid #000000; border-collapse: collapse; + width: 98%; } table.LC_calendar_pickdate { @@ -5095,6 +5420,7 @@ table.LC_calendar_pickdate { table.LC_calendar tr td { border: 1px solid #000000; vertical-align: top; + width: 14%; } table.LC_calendar tr td.LC_calendar_day_empty { @@ -5105,47 +5431,47 @@ table.LC_calendar tr td.LC_calendar_day_ background-color: $data_table_highlight; } -table.LC_mail_list tr.LC_mail_new { +table.LC_data_table tr td.LC_mail_new { background-color: $mail_new; } -table.LC_mail_list tr.LC_mail_new:hover { +table.LC_data_table tr.LC_mail_new:hover { background-color: $mail_new_hover; } -table.LC_mail_list tr.LC_mail_even { -} - -table.LC_mail_list tr.LC_mail_odd { -} - -table.LC_mail_list tr.LC_mail_read { +table.LC_data_table tr td.LC_mail_read { background-color: $mail_read; } -table.LC_mail_list tr.LC_mail_read:hover { +/* +table.LC_data_table tr.LC_mail_read:hover { background-color: $mail_read_hover; } +*/ -table.LC_mail_list tr.LC_mail_replied { +table.LC_data_table tr td.LC_mail_replied { background-color: $mail_replied; } -table.LC_mail_list tr.LC_mail_replied:hover { +/* +table.LC_data_table tr.LC_mail_replied:hover { background-color: $mail_replied_hover; } +*/ -table.LC_mail_list tr.LC_mail_other { +table.LC_data_table tr td.LC_mail_other { background-color: $mail_other; } -table.LC_mail_list tr.LC_mail_other:hover { +/* +table.LC_data_table tr.LC_mail_other:hover { background-color: $mail_other_hover; } +*/ table.LC_data_table tr > td.LC_browser_file, table.LC_data_table tr > td.LC_browser_file_published { - background: #CCFF88; + background: #AAEE77; } table.LC_data_table tr > td.LC_browser_file_locked, @@ -5154,40 +5480,40 @@ table.LC_data_table tr > td.LC_browser_f } table.LC_data_table tr > td.LC_browser_file_obsolete { - background: #AAAAAA; + background: #888888; } table.LC_data_table tr > td.LC_browser_file_modified, table.LC_data_table tr > td.LC_browser_file_metamodified { - background: #FFFF77; + background: #F8F866; } table.LC_data_table tr.LC_browser_folder > td { - background: #CCCCFF; + background: #E0E8FF; } table.LC_data_table tr > td.LC_roles_is { -/* background: #77FF77; */ + /* background: #77FF77; */ } table.LC_data_table tr > td.LC_roles_future { - background: #FFFF77; + border-right: 8px solid #FFFF77; } table.LC_data_table tr > td.LC_roles_will { - background: #FFAA77; + border-right: 8px solid #FFAA77; } table.LC_data_table tr > td.LC_roles_expired { - background: #FF7777; + border-right: 8px solid #FF7777; } table.LC_data_table tr > td.LC_roles_will_not { - background: #AAFF77; + border-right: 8px solid #AAFF77; } table.LC_data_table tr > td.LC_roles_selected { - background: #11CC55; + border-right: 8px solid #11CC55; } span.LC_current_location { @@ -5195,6 +5521,11 @@ span.LC_current_location { background: $pgbg; } +span.LC_current_nav_location { + font-weight:bold; + background: $sidebg; +} + span.LC_parm_menu_item { font-size: larger; } @@ -5215,12 +5546,21 @@ span.LC_parm_part { color: blue; } -span.LC_parm_folder, span.LC_parm_symb { +span.LC_parm_folder, +span.LC_parm_symb { font-size: x-small; font-family: $mono; color: #AAAAAA; } +ul.LC_parm_parmlist li { + display: inline-block; + padding: 0.3em 0.8em; + vertical-align: top; + width: 150px; + border-top:1px solid $lg_border_color; +} + td.LC_parm_overview_level_menu, td.LC_parm_overview_map_menu, td.LC_parm_overview_parm_selectors, @@ -5305,7 +5645,7 @@ table.LC_pick_box { table.LC_pick_box td.LC_pick_box_title { background: $sidebg; font-weight: bold; - text-align: right; + text-align: left; vertical-align: top; width: 184px; padding: 8px; @@ -5343,40 +5683,6 @@ table.LC_pick_box td.LC_oddrow_value { background-color: $data_table_light; } -table.LC_helpform_receipt { - width: 620px; - border-collapse: separate; - background: white; - border: 1px solid black; - border-spacing: 1px; -} - -table.LC_helpform_receipt td.LC_pick_box_title { - background: $tabbg; - font-weight: bold; - text-align: right; - width: 184px; - padding: 8px; -} - -table.LC_helpform_receipt td.LC_evenrow_value { - text-align: left; - padding: 8px; - background-color: $data_table_light; -} - -table.LC_helpform_receipt td.LC_oddrow_value { - text-align: left; - padding: 8px; - background-color: $data_table_light; -} - -table.LC_helpform_receipt td.LC_pick_box_separator { - padding: 0; - height: 1px; - background: black; -} - span.LC_helpform_receipt_cat { font-weight: bold; } @@ -5415,35 +5721,23 @@ table.LC_group_priv td { padding: 0; } -table.LC_notify_front_page { - background: white; - border: 1px solid black; - padding: 8px; -} - -table.LC_notify_front_page td { - padding: 8px; -} - .LC_navbuttons { margin: 2ex 0ex 2ex 0ex; } .LC_topic_bar { font-weight: bold; - width: 100%; background: $tabbg; - vertical-align: middle; - margin: 2ex 0ex 2ex 0ex; + margin: 1em 0em 1em 2em; padding: 3px; + font-size: 1.2em; } .LC_topic_bar span { + left: 0.5em; + position: absolute; vertical-align: middle; -} - -.LC_topic_bar img { - vertical-align: bottom; + font-size: 1.2em; } table.LC_course_group_status { @@ -5472,12 +5766,12 @@ div.LC_feedback_link img { vertical-align:middle; } -div.LC_feedback_link a{ +div.LC_feedback_link a { text-decoration: none; } div.LC_comblock { - display:inline; + display:inline; color:$font; font-size:90%; } @@ -5555,12 +5849,12 @@ span.LC_prior_string, span.LC_prior_custom, span.LC_prior_reaction, span.LC_prior_math { - font-family: monospace; + font-family: $mono; white-space: pre; } span.LC_prior_string { - font-family: monospace; + font-family: $mono; white-space: pre; } @@ -5569,7 +5863,7 @@ table.LC_prior_option { border-collapse: collapse; } -table.LC_prior_rank, +table.LC_prior_rank, table.LC_prior_match { border-collapse: collapse; } @@ -5593,17 +5887,6 @@ span.LC_cusr_subheading { font-size: 85%; } -table.LC_docs_documents { - background: #BBBBBB; - border-width: 0; - border-collapse: collapse; -} - -table.LC_docs_documents td.LC_docs_document { - border: 2px solid black; - padding: 4px; -} - div.LC_docs_entry_move { border: 1px solid #BBBBBB; background: #DDDDDD; @@ -5695,56 +5978,41 @@ div.LC_clear_float_footer { } div.LC_grade_show_user { - margin-top: 20px; - border: 1px solid black; +/* border-left: 5px solid $sidebg; */ + border-top: 5px solid #000000; + margin: 50px 0 0 0; + padding: 15px 0 5px 10px; } -div.LC_grade_user_name { - background: #DDDDEE; - border-bottom: 1px solid black; - font-weight: bold; - font-size: large; +div.LC_grade_show_user_odd_row { +/* border-left: 5px solid #000000; */ } -div.LC_grade_show_user_odd_row div.LC_grade_user_name { - background: #DDEEDD; +div.LC_grade_show_user div.LC_Box { + margin-right: 50px; } -div.LC_grade_show_problem, div.LC_grade_submissions, div.LC_grade_message_center, -div.LC_grade_info_links, -div.LC_grade_assign { +div.LC_grade_info_links { margin: 5px; width: 99%; background: #FFFFFF; } -div.LC_grade_show_problem_header, div.LC_grade_submissions_header, -div.LC_grade_message_center_header, -div.LC_grade_assign_header { +div.LC_grade_message_center_header { font-weight: bold; font-size: large; } -div.LC_grade_show_problem_problem, div.LC_grade_submissions_body, -div.LC_grade_message_center_body, -div.LC_grade_assign_body { +div.LC_grade_message_center_body { border: 1px solid black; width: 99%; background: #FFFFFF; } -span.LC_grade_check_note { - font-weight: normal; - font-size: medium; - display: inline; - position: absolute; - right: 1em; -} - table.LC_scantron_action { width: 100%; } @@ -5778,15 +6046,8 @@ div.LC_edit_problem_header_title { } table.LC_edit_problem_header_title { - font-size: larger; - font-weight: bold; width: 100%; - border-color: $pgbg; - border-style: solid; - border-width: $border; background: $tabbg; - border-collapse: collapse; - padding: 0; } div.LC_edit_problem_discards { @@ -5799,38 +6060,25 @@ div.LC_edit_problem_saves { padding-bottom: 5px; } -img.stift{ +img.stift { border-width: 0; vertical-align: middle; } -table#LC_mainmenu{ - margin-top:10px; - width:80%; -} - -table#LC_mainmenu td.LC_mainmenu_col_fieldset{ +table td.LC_mainmenu_col_fieldset { vertical-align: top; - width: 45%; -} - -.LC_mainmenu_fieldset_category { - color: $font; - background: $pgbg; - font-size: small; - font-weight: bold; } div.LC_createcourse { - margin: 10px 10px 10px 10px; + margin: 10px 10px 10px 10px; } -/* ---- Remove when done ---- -# The following styles is part of the redesign of LON-CAPA and are -# subject to change during this project. -# Don't rely on their current functionality as they might be -# changed or removed. -# --------------------------*/ +.LC_dccid { + margin: 0.2em 0 0 0; + padding: 0; + font-size: 90%; + display:none; +} a:hover, ol.LC_primary_menu a:hover, @@ -5839,291 +6087,369 @@ ol#LC_PathBreadcrumbs a:hover, ul#LC_secondary_menu a:hover, .LC_FormSectionClearButton input:hover ul.LC_TabContent li:hover a { - color:#BF2317; - text-decoration:none; + color:$button_hover; + text-decoration:none; } h1 { - padding: 0; - line-height:130%; + padding: 0; + line-height:130%; } -h2,h3,h4,h5,h6 { - margin: 5px 0 5px 0; - padding: 0; - line-height:130%; +h2, +h3, +h4, +h5, +h6 { + margin: 5px 0 5px 0; + padding: 0; + line-height:130%; } .LC_hcell { - padding:3px 15px 3px 15px; - margin: 0; - background-color:$tabbg; - color:$fontmenu; - border-bottom:solid 1px $lg_border_color; + padding:3px 15px 3px 15px; + margin: 0; + background-color:$tabbg; + color:$fontmenu; + border-bottom:solid 1px $lg_border_color; } .LC_Box > .LC_hcell { - margin: 0 -10px 10px -10px; + margin: 0 -10px 10px -10px; } .LC_noBorder { - border: 0; -} - -.LC_Right { - float: right; - margin: 0; - padding: 0; + border: 0; } .LC_FormSectionClearButton input { - background-color:transparent; - border: none; - cursor:pointer; - text-decoration:underline; + background-color:transparent; + border: none; + cursor:pointer; + text-decoration:underline; } .LC_help_open_topic { - color: #FFFFFF; - background-color: #EEEEFF; - margin: 1px; - padding: 4px; - border: 1px solid #000033; - white-space: nowrap; -/* vertical-align: middle; */ + color: #FFFFFF; + background-color: #EEEEFF; + margin: 1px; + padding: 4px; + border: 1px solid #000033; + white-space: nowrap; + /* vertical-align: middle; */ } -dl,ul,div,fieldset { - margin: 10px 10px 10px 0; -/* overflow: hidden; */ +dl, +ul, +div, +fieldset { + margin: 10px 10px 10px 0; + /* overflow: hidden; */ } fieldset > legend { - font-weight: bold; - padding: 0 5px 0 5px; + font-weight: bold; + padding: 0 5px 0 5px; } #LC_nav_bar { - float: left; - margin: 0.2em 0 0 0; + float: left; + background-color: $pgbg_or_bgcolor; + margin: 0 0 2px 0; } -#LC_nav_bar em{ - font-weight: bold; - font-style: normal; +#LC_realm { + margin: 0.2em 0 0 0; + padding: 0; + font-weight: bold; + text-align: center; + background-color: $pgbg_or_bgcolor; +} + +#LC_nav_bar em { + font-weight: bold; + font-style: normal; } ol.LC_primary_menu { - float: right; - margin: 0.2em 0 0 0; + float: right; + margin: 0; + background-color: $pgbg_or_bgcolor; } ol#LC_PathBreadcrumbs { - margin: 0; + margin: 0; } ol.LC_primary_menu li { - display: inline; - padding: 5px 5px 0 10px; - vertical-align: top; + display: inline; + padding: 5px 5px 0 10px; + vertical-align: top; } ol.LC_primary_menu li img { - vertical-align: bottom; + vertical-align: bottom; + height: 1.1em; } ol.LC_primary_menu a { - font-size: 90%; - color: RGB(80, 80, 80); - text-decoration: none; + color: RGB(80, 80, 80); + text-decoration: none; +} + +ol.LC_primary_menu a.LC_new_message { + font-weight:bold; + color: darkred; +} + +ol.LC_docs_parameters { + margin-left: 0; + padding: 0; + list-style: none; +} + +ol.LC_docs_parameters li { + margin: 0; + padding-right: 20px; + display: inline; +} + +ol.LC_docs_parameters li:before { + content: "\\002022 \\0020"; +} + +li.LC_docs_parameters_title { + font-weight: bold; +} + +ol.LC_docs_parameters li.LC_docs_parameters_title:before { + content: ""; } ul#LC_secondary_menu { - clear: both; - color: $fontmenu; - background: $tabbg; - list-style: none; - padding: 0; - margin: 0; - width: 100%; + clear: both; + color: $fontmenu; + background: $tabbg; + list-style: none; + padding: 0; + margin: 0; + width: 100%; + text-align: left; } ul#LC_secondary_menu li { - font-weight: bold; - line-height: 1.8em; - padding: 0 0.8em; - border-right: 1px solid black; - display: inline; - vertical-align: middle; + font-weight: bold; + line-height: 1.8em; + padding: 0 0.8em; + border-right: 1px solid black; + display: inline; + vertical-align: middle; } ul.LC_TabContent { - display:block; - background: $sidebg; - border-bottom: solid 1px $lg_border_color; - list-style:none; - margin: 0 -10px; - padding: 0; + display:block; + background: $sidebg; + border-bottom: solid 1px $lg_border_color; + list-style:none; + margin: -1px -10px 0 -10px; + padding: 0; } ul.LC_TabContent li, ul.LC_TabContentBigger li { - float:left; + float:left; } ul#LC_secondary_menu li a { - color: $fontmenu; - text-decoration: none; + color: $fontmenu; + text-decoration: none; } ul.LC_TabContent { - min-height:1.5em; + min-height:20px; } ul.LC_TabContent li { - vertical-align:middle; - padding: 0 10px 0 10px; - background-color:$tabbg; - border-bottom:solid 1px $lg_border_color; + vertical-align:middle; + padding: 0 16px 0 10px; + background-color:$tabbg; + border-bottom:solid 1px $lg_border_color; + border-left: solid 1px $font; } ul.LC_TabContent .right { - float:right; + float:right; +} + +ul.LC_TabContent li a, +ul.LC_TabContent li { + color:rgb(47,47,47); + text-decoration:none; + font-size:95%; + font-weight:bold; + min-height:20px; +} + +ul.LC_TabContent li a:hover, +ul.LC_TabContent li a:focus { + color: $button_hover; + background:none; + outline:none; } -ul.LC_TabContent li a, ul.LC_TabContent li { - color:rgb(47,47,47); - text-decoration:none; - font-size:95%; - font-weight:bold; - padding-right: 16px; +ul.LC_TabContent li:hover { + color: $button_hover; + cursor:pointer; } -ul.LC_TabContent li:hover, ul.LC_TabContent li.active { - background:#FFFFFF url(/adm/lonIcons/open.gif) no-repeat scroll right center; - border-bottom:solid 2px #FFFFFF; - padding-right: 16px; +ul.LC_TabContent li.active { + color: $font; + background:#FFFFFF url(/adm/lonIcons/open.gif) no-repeat scroll right center; + border-bottom:solid 1px #FFFFFF; + cursor: default; } +ul.LC_TabContent li.active a { + color:$font; + background:#FFFFFF; + outline: none; +} #maincoursedoc { - clear:both; + clear:both; } ul.LC_TabContentBigger { - display:block; - list-style:none; - padding: 0; + display:block; + list-style:none; + padding: 0; } ul.LC_TabContentBigger li { - vertical-align:bottom; - height: 30px; - font-size:110%; - font-weight:bold; - color: #737373; + vertical-align:bottom; + height: 30px; + font-size:110%; + font-weight:bold; + color: #737373; } +ul.LC_TabContentBigger li.active { + position: relative; + top: 1px; +} ul.LC_TabContentBigger li a { - background:url('/adm/lonIcons/tabbgleft.gif') left bottom no-repeat; - height: 30px; - line-height: 30px; - text-align: center; - display: block; - text-decoration: none; + background:url('/adm/lonIcons/tabbgleft.gif') left bottom no-repeat; + height: 30px; + line-height: 30px; + text-align: center; + display: block; + text-decoration: none; + outline: none; } -ul.LC_TabContentBigger li:hover a, ul.LC_TabContentBigger li.active a { - background:url('/adm/lonIcons/tabbgleft.gif') left top no-repeat; - color:$font; - text-decoration: underline; + background:url('/adm/lonIcons/tabbgleft.gif') left top no-repeat; + color:$font; } - ul.LC_TabContentBigger li b { - background: url('/adm/lonIcons/tabbgright.gif') no-repeat right bottom; - display: block; - float: left; - padding: 0 30px; + background: url('/adm/lonIcons/tabbgright.gif') no-repeat right bottom; + display: block; + float: left; + padding: 0 30px; + border-bottom: 1px solid $lg_border_color; +} + +ul.LC_TabContentBigger li:hover b { + color:$button_hover; } -ul.LC_TabContentBigger li:hover b, ul.LC_TabContentBigger li.active b { - background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat; - color:$font; - border-bottom: 1px solid #FFFFFF; + background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat; + color:$font; + border: 0; } ul.LC_CourseBreadcrumbs { background: $sidebg; - line-height: 32px; + height: 2em; padding-left: 10px; - margin: 0 0 10px 0; + margin: 0; list-style-position: inside; - } -ol#LC_MenuBreadcrumbs, +ol#LC_MenuBreadcrumbs, ol#LC_PathBreadcrumbs { - padding-left: 10px; - margin: 0; - list-style-position: inside; + padding-left: 10px; + margin: 0; + height: 2.5em; /* equal to #LC_breadcrumbs line-height */ } -ol#LC_MenuBreadcrumbs li, -ol#LC_PathBreadcrumbs li, +ol#LC_MenuBreadcrumbs li, +ol#LC_PathBreadcrumbs li, ul.LC_CourseBreadcrumbs li { - display: inline; - white-space: nowrap; + display: inline; + white-space: normal; } ol#LC_MenuBreadcrumbs li a, ul.LC_CourseBreadcrumbs li a { - text-decoration: none; - font-size:90%; + text-decoration: none; + font-size:90%; +} + +ol#LC_MenuBreadcrumbs h1 { + display: inline; + font-size: 90%; + line-height: 2.5em; + margin: 0; + padding: 0; } ol#LC_PathBreadcrumbs li a { - text-decoration:none; - font-size:100%; - font-weight:bold; + text-decoration:none; + font-size:100%; + font-weight:bold; } .LC_Box { - border: solid 1px $lg_border_color; - padding: 0 10px 10px 10px; + border: solid 1px $lg_border_color; + padding: 0 10px 10px 10px; +} + +.LC_DocsBox { + border: solid 1px $lg_border_color; + padding: 0 0 10px 10px; } .LC_AboutMe_Image { - float:left; - margin-right:10px; + float:left; + margin-right:10px; } .LC_Clear_AboutMe_Image { - clear:left; + clear:left; } dl.LC_ListStyleClean dt { - padding-right: 5px; - display: table-header-group; + padding-right: 5px; + display: table-header-group; } dl.LC_ListStyleClean dd { - display: table-row; + display: table-row; } .LC_ListStyleClean, .LC_ListStyleSimple, .LC_ListStyleNormal, -.LC_ListStyle_Border, .LC_ListStyleSpecial { - /*display:block; */ - list-style-position: inside; - list-style-type: none; - overflow: hidden; - padding: 0; + /* display:block; */ + list-style-position: inside; + list-style-type: none; + overflow: hidden; + padding: 0; } .LC_ListStyleSimple li, @@ -6132,211 +6458,229 @@ dl.LC_ListStyleClean dd { .LC_ListStyleNormal dd, .LC_ListStyleSpecial li, .LC_ListStyleSpecial dd { - margin: 0; - padding: 5px 5px 5px 10px; - clear: both; + margin: 0; + padding: 5px 5px 5px 10px; + clear: both; } .LC_ListStyleClean li, .LC_ListStyleClean dd { - padding-top: 0; - padding-bottom: 0; + padding-top: 0; + padding-bottom: 0; } .LC_ListStyleSimple dd, .LC_ListStyleSimple li { - border-bottom: solid 1px $lg_border_color; + border-bottom: solid 1px $lg_border_color; } .LC_ListStyleSpecial li, .LC_ListStyleSpecial dd { - list-style-type: none; - background-color: RGB(220, 220, 220); - margin-bottom: 4px; + list-style-type: none; + background-color: RGB(220, 220, 220); + margin-bottom: 4px; } table.LC_SimpleTable { - margin:5px; - border:solid 1px $lg_border_color; + margin:5px; + border:solid 1px $lg_border_color; } table.LC_SimpleTable tr { - padding: 0; - border:solid 1px $lg_border_color; + padding: 0; + border:solid 1px $lg_border_color; } table.LC_SimpleTable thead { - background:rgb(220,220,220); + background:rgb(220,220,220); } div.LC_columnSection { - display: block; - clear: both; - overflow: hidden; - margin: 0; + display: block; + clear: both; + overflow: hidden; + margin: 0; } div.LC_columnSection>* { - float: left; - margin: 10px 20px 10px 0; - overflow:hidden; -} - -.LC_loginpage_container { - text-align:left; - margin : 0 auto; - width:90%; - padding: 10px; - height: auto; - background-color:#FFFFFF; - border:1px solid #CCCCCC; -} - - -.LC_loginpage_loginContainer { - float:left; - width: 182px; - padding: 2px; - border:1px solid #CCCCCC; - background-color:$loginbg; -} - -.LC_loginpage_loginContainer h2 { - margin-top: 0; - display:block; - background:$bgcol; - color:$textcol; - padding-left:5px; -} - -.LC_loginpage_loginInfo { - float:left; - width:182px; - border:1px solid #CCCCCC; - padding:2px; -} - -.LC_loginpage_space { - clear: both; - margin-bottom: 20px; - border-bottom: 1px solid #CCCCCC; -} - -.LC_loginpage_floatLeft { - float: left; - width: 200px; - margin: 0; + float: left; + margin: 10px 20px 10px 0; + overflow:hidden; } table em { - font-weight: bold; - font-style: normal; + font-weight: bold; + font-style: normal; } table.LC_tableBrowseRes, table.LC_tableOfContent { - border:none; - border-spacing: 1px; - padding: 3px; - background-color: #FFFFFF; - font-size: 90%; + border:none; + border-spacing: 1px; + padding: 3px; + background-color: #FFFFFF; + font-size: 90%; } -table.LC_tableOfContent{ - border-collapse: collapse; +table.LC_tableOfContent { + border-collapse: collapse; } table.LC_tableBrowseRes a, table.LC_tableOfContent a { - background-color: transparent; - text-decoration: none; -} - -table.LC_tableBrowseRes tr.LC_trOdd, -table.LC_tableOfContent tr.LC_trOdd{ - background-color: #EEEEEE; + background-color: transparent; + text-decoration: none; } table.LC_tableOfContent img { - border: none; - height: 1.3em; - vertical-align: text-bottom; - margin-right: 0.3em; + border: none; + height: 1.3em; + vertical-align: text-bottom; + margin-right: 0.3em; } a#LC_content_toolbar_firsthomework { - background-image:url(/res/adm/pages/open-first-problem.gif); -} - -a#LC_content_toolbar_launchnav { - background-image:url(/res/adm/pages/start-navigation.gif); -} - -a#LC_content_toolbar_closenav { - background-image:url(/res/adm/pages/close-navigation.gif); + background-image:url(/res/adm/pages/open-first-problem.gif); } a#LC_content_toolbar_everything { - background-image:url(/res/adm/pages/show-all.gif); + background-image:url(/res/adm/pages/show-all.gif); } a#LC_content_toolbar_uncompleted { - background-image:url(/res/adm/pages/show-incomplete-problems.gif); + background-image:url(/res/adm/pages/show-incomplete-problems.gif); } #LC_content_toolbar_clearbubbles { - background-image:url(/res/adm/pages/mark-discussionentries-read.gif); + background-image:url(/res/adm/pages/mark-discussionentries-read.gif); } a#LC_content_toolbar_changefolder { - background : url(/res/adm/pages/close-all-folders.gif) top center ; + background : url(/res/adm/pages/close-all-folders.gif) top center ; } a#LC_content_toolbar_changefolder_toggled { - background-image:url(/res/adm/pages/open-all-folders.gif); + background-image:url(/res/adm/pages/open-all-folders.gif); +} + +a#LC_content_toolbar_edittoplevel { + background-image:url(/res/adm/pages/edittoplevel.gif); } ul#LC_toolbar li a:hover { - background-position: bottom center; + background-position: bottom center; } ul#LC_toolbar { - padding: 0; - margin: 2px; - list-style:none; - position:relative; - background-color:white; + padding: 0; + margin: 2px; + list-style:none; + position:relative; + background-color:white; } ul#LC_toolbar li { - border:1px solid white; - padding: 0; - margin: 0; - float: left; - display:inline; - vertical-align:middle; -} + border:1px solid white; + padding: 0; + margin: 0; + float: left; + display:inline; + vertical-align:middle; +} a.LC_toolbarItem { - display:block; - padding: 0; - margin: 0; - height: 32px; - width: 32px; - color:white; - border: none; - background-repeat:no-repeat; - background-color:transparent; + display:block; + padding: 0; + margin: 0; + height: 32px; + width: 32px; + color:white; + border: none; + background-repeat:no-repeat; + background-color:transparent; +} + +ul.LC_funclist { + margin: 0; + padding: 0.5em 1em 0.5em 0; +} + +ul.LC_funclist > li:first-child { + font-weight:bold; + margin-left:0.8em; +} + +ul.LC_funclist + ul.LC_funclist { + /* + left border as a seperator if we have more than + one list + */ + border-left: 1px solid $sidebg; + /* + this hides the left border behind the border of the + outer box if element is wrapped to the next 'line' + */ + margin-left: -1px; } ul.LC_funclist li { - float: left; + display: inline; white-space: nowrap; - height: 35px; /* at least as high as heighest list item */ - margin: 0 15px 15px 10px; + margin: 0 0 0 25px; + line-height: 150%; } +.LC_hidden { + display: none; +} + +.LCmodal-overlay { + position:fixed; + top:0; + right:0; + bottom:0; + left:0; + height:100%; + width:100%; + margin:0; + padding:0; + background:#999; + opacity:.75; + filter: alpha(opacity=75); + -moz-opacity: 0.75; + z-index:101; +} + +* html .LCmodal-overlay { + position: absolute; + height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); +} + +.LCmodal-window { + position:fixed; + top:50%; + left:50%; + margin:0; + padding:0; + z-index:102; + } + +* html .LCmodal-window { + position:absolute; +} + +.LCclose-window { + position:absolute; + width:32px; + height:32px; + right:8px; + top:8px; + background:transparent url('/res/adm/pages/process-stop.png') no-repeat scroll right top; + text-indent:-99999px; + overflow:hidden; + cursor:pointer; +} END } @@ -6389,15 +6733,31 @@ sub headtag { if (!$args->{'frameset'}) { $result .= &Apache::lonhtmlcommon::htmlareaheaders(); } - if ($args->{'force_register'}) { - $result .= &Apache::lonmenu::registerurl(1); + if ($args->{'force_register'} && $env{'request.noversionuri'} !~ m{^/res/adm/pages/}) { + $result .= Apache::lonxml::display_title(); } if (!$args->{'no_nav_bar'} && !$args->{'only_body'} && !$args->{'frameset'}) { $result .= &help_menu_js(); + $result.=&modal_window(); + $result.=&togglebox_script(); + $result.=&wishlist_window(); + $result.=&LCprogressbarUpdate_script(); + } else { + if ($args->{'add_modal'}) { + $result.=&modal_window(); + } + if ($args->{'add_wishlist'}) { + $result.=&wishlist_window(); + } + if ($args->{'add_togglebox'}) { + $result.=&togglebox_script(); + } + if ($args->{'add_progressbar'}) { + $result.=&LCprogressbarUpdate_script(); + } } - if (ref($args->{'redirect'})) { my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}}; $url = &Apache::lonenc::check_encrypt($url); @@ -6416,7 +6776,7 @@ ADDMETA $result .= ' LON-CAPA '.$title.'' .'' .$head_extra; - return $result; + return $result.''; } =pod @@ -6451,10 +6811,6 @@ Inputs: none sub xml_begin { my $output=''; - if ($env{'internal.start_page'}==1) { - &Apache::lonhtmlcommon::init_htmlareafields(); - } - if ($env{'browser.mathml'}) { $output='' #.''."\n" @@ -6473,43 +6829,6 @@ sub xml_begin { =pod -=item * &endheadtag() - -Returns a uniform for LON-CAPA web pages. - -Inputs: none - -=cut - -sub endheadtag { - return ''; -} - -=pod - -=item * &head() - -Returns a uniform complete .. section for LON-CAPA web pages. - -Inputs: - -=over 4 - -$title - optional title for the page - -$head_extra - optional extra HTML to put inside the - -=back - -=cut - -sub head { - my ($title,$head_extra,$args) = @_; - return &headtag($title,$head_extra,$args).&endheadtag(); -} - -=pod - =item * &start_page() Returns a complete .. section for LON-CAPA web pages. @@ -6547,14 +6866,12 @@ $args - additional optional args support skip_phases -> hash ref of head -> skip the generation body -> skip all generation - no_inline_link -> if true and in remote mode, don't show the - 'Switch To Inline Menu' link no_auto_mt_title -> prevent &mt()ing the title arg inherit_jsmath -> when creating popup window in a page, should it have jsmath forced on by the current page bread_crumbs -> Array containing breadcrumbs - bread_crumbs_components -> if exists show it as headline else show only the breadcrumbs + bread_crumbs_component -> if exists show it as headline else show only the breadcrumbs =back @@ -6565,21 +6882,12 @@ $args - additional optional args support sub start_page { my ($title,$head_extra,$args) = @_; #&Apache::lonnet::logthis("start_page ".join(':',caller(0))); - my %head_args; - foreach my $arg ('redirect','force_register','domain','function', - 'bgcolor','frameset','no_nav_bar','only_body', - 'no_auto_mt_title') { - if (defined($args->{$arg})) { - $head_args{$arg} = $args->{$arg}; - } - } $env{'internal.start_page'}++; my $result; + if (! exists($args->{'skip_phases'}{'head'}) ) { - $result.= - &xml_begin(). - &headtag($title,$head_extra,\%head_args).&endheadtag(); + $result .= &xml_begin() . &headtag($title, $head_extra, $args); } if (! exists($args->{'skip_phases'}{'body'}) ) { @@ -6593,8 +6901,7 @@ sub start_page { $args->{'function'}, $args->{'add_entries'}, $args->{'only_body'}, $args->{'domain'}, $args->{'force_register'}, $args->{'no_nav_bar'}, - $args->{'bgcolor'}, $args->{'no_inline_link'}, - $args); + $args->{'bgcolor'}, $args); } } @@ -6610,8 +6917,9 @@ sub start_page { # $result .= &build_functionlist(); #} - # Don't add anything more if only_body wanted - return $result if $args->{'only_body'}; + # Don't add anything more if only_body wanted or in const space + return $result if $args->{'only_body'} + || $env{'request.state'} eq 'construct'; #Breadcrumbs if (exists($args->{'bread_crumbs'}) or exists($args->{'bread_crumbs_component'})) { @@ -6633,28 +6941,6 @@ sub start_page { return $result; } - -=pod - -=item * &head() - -Returns a complete section for LON-CAPA web pages. - -Inputs: $args - additional optional args supported are: - js_ready -> return a string ready for being used in - a javascript writeln - html_encode -> return a string ready for being used in - a html attribute - frameset -> if true will start with a - rather than - dicsussion -> if true will get discussion from - lonxml::xmlend - (you can pass the target and parser arguments - through optional 'target' and 'parser' args - to this routine) - -=cut - sub end_page { my ($args) = @_; $env{'internal.end_page'}++; @@ -6667,7 +6953,6 @@ sub end_page { } $result .= &Apache::lonxml::xmlend($target,$parser); } - if ($args->{'frameset'}) { $result .= ''; } else { @@ -6686,6 +6971,281 @@ sub end_page { return $result; } +sub wishlist_window { + return(<<'ENDWISHLIST'); + +ENDWISHLIST +} + +sub modal_window { + return(<<'ENDMODAL'); + +ENDMODAL +} + +sub modal_link { + my ($link,$linktext,$width,$height,$target,$scrolling)=@_; + unless ($width) { $width=480; } + unless ($height) { $height=400; } + unless ($scrolling) { $scrolling='yes'; } + return ''. + $linktext.''; +} + +sub modal_adhoc_script { + my ($funcname,$width,$height,$content)=@_; + return (< +// + +ENDADHOC +} + +sub modal_adhoc_inner { + my ($funcname,$width,$height,$content)=@_; + my $innerwidth=$width-20; + $content=&js_ready( + &start_page('Dialog',undef,{'only_body'=>1,'bgcolor'=>'#FFFFFF'}). + &start_scrollbox($width.'px',$innerwidth.'px',$height.'px'). + $content. + &end_scrollbox(). + &end_page() + ); + return &modal_adhoc_script($funcname,$width,$height,$content); +} + +sub modal_adhoc_window { + my ($funcname,$width,$height,$content,$linktext)=@_; + return &modal_adhoc_inner($funcname,$width,$height,$content). + "".$linktext.""; +} + +sub modal_adhoc_launch { + my ($funcname,$width,$height,$content)=@_; + return &modal_adhoc_inner($funcname,$width,$height,$content).(< +// + +ENDLAUNCH +} + +sub modal_adhoc_close { + return (< +// + +ENDCLOSE +} + +sub togglebox_script { + return(< +// + +ENDTOGGLE +} + +sub start_togglebox { + my ($id,$heading,$headerbg,$hidetext,$showtext)=@_; + unless ($heading) { $heading=''; } else { $heading.=' '; } + unless ($showtext) { $showtext=&mt('show'); } + unless ($hidetext) { $hidetext=&mt('hide'); } + unless ($headerbg) { $headerbg='#FFFFFF'; } + return &start_data_table(). + &start_data_table_header_row(). + ''.$heading. + '['.$showtext.']'. + &end_data_table_header_row(). + ''; +} + +sub end_togglebox { + return ''.&end_data_table(); +} + +sub LCprogressbar_script { + my ($id)=@_; + return(< +// + +ENDPROGRESS +} + +sub LCprogressbarUpdate_script { + return(< +.ui-progressbar { position:relative; } +.pblabel { position: absolute; width: 100%; text-align: center; line-height: 1.9em; } + + +ENDPROGRESSUPDATE +} + +my $LClastpercent; +my $LCidcnt; +my $LCcurrentid; + +sub LCprogressbar { + my ($r)=(@_); + $LClastpercent=0; + $LCidcnt++; + $LCcurrentid=$$.'_'.$LCidcnt; + my $starting=&mt('Starting'); + my $content=(< +
+ $starting +
+

+ENDPROGBAR + &r_print($r,$content.&LCprogressbar_script($LCcurrentid)); +} + +sub LCprogressbarUpdate { + my ($r,$val,$text)=@_; + unless ($val) { + if ($LClastpercent) { + $val=$LClastpercent; + } else { + $val=0; + } + } + if ($val<0) { $val=0; } + if ($val>100) { $val=0; } + $LClastpercent=$val; + unless ($text) { $text=$val.'%'; } + $text=&js_ready($text); + &r_print($r,< +// + +ENDUPDATE +} + +sub LCprogressbarClose { + my ($r)=@_; + $LClastpercent=0; + &r_print($r,< +// + +ENDCLOSE +} + +sub r_print { + my ($r,$to_print)=@_; + if ($r) { + $r->print($to_print); + $r->rflush(); + } else { + print($to_print); + } +} + sub html_encode { my ($result) = @_; @@ -6693,6 +7253,7 @@ sub html_encode { return $result; } + sub js_ready { my ($result) = @_; @@ -6729,6 +7290,24 @@ sub validate_page { } } + +sub start_scrollbox { + my ($outerwidth,$width,$height,$id)=@_; + unless ($outerwidth) { $outerwidth='520px'; } + unless ($width) { $width='500px'; } + unless ($height) { $height='200px'; } + my ($table_id,$div_id); + if ($id ne '') { + $table_id = " id='table_$id'"; + $div_id = " id='div_$id'"; + } + return "
"; +} + +sub end_scrollbox { + return '
'; +} + sub simple_error_page { my ($r,$title,$msg) = @_; my $page = @@ -6744,31 +7323,48 @@ sub simple_error_page { { my @row_count; + + sub start_data_table_count { + unshift(@row_count, 0); + return; + } + + sub end_data_table_count { + shift(@row_count); + return; + } + sub start_data_table { - my ($add_class) = @_; + my ($add_class,$id) = @_; my $css_class = (join(' ','LC_data_table',$add_class)); - unshift(@row_count,0); - return ''."\n"; + my $table_id; + if (defined($id)) { + $table_id = ' id="'.$id.'"'; + } + &start_data_table_count(); + return '
'."\n"; } sub end_data_table { - shift(@row_count); + &end_data_table_count(); return '
'."\n";; } sub start_data_table_row { - my ($add_class) = @_; + my ($add_class, $id) = @_; $row_count[0]++; my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row'; - $css_class = (join(' ',$css_class,$add_class)); - return ''."\n";; + $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq ''); + $id = (' id="'.$id.'"') unless ($id eq ''); + return ''."\n"; } sub continue_data_table_row { - my ($add_class) = @_; + my ($add_class, $id) = @_; my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row'; - $css_class = (join(' ',$css_class,$add_class)); - return ''."\n";; + $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq ''); + $id = (' id="'.$id.'"') unless ($id eq ''); + return ''."\n"; } sub end_data_table_row { @@ -6866,14 +7462,14 @@ sub get_users_function { if ($env{'request.role'}=~/^(st)/) { $function='student'; } - if ($env{'request.role'}=~/^(cc|in|ta|ep)/) { + if ($env{'request.role'}=~/^(cc|co|in|ta|ep)/) { $function='coordinator'; } if ($env{'request.role'}=~/^(su|dc|ad|li)/) { $function='admin'; } if (($env{'request.role'}=~/^(au|ca|aa)/) || - ($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) { + ($ENV{'REQUEST_URI'}=~ m{/^(/priv)})) { $function='author'; } return $function; @@ -6931,13 +7527,14 @@ role status: active, previous or future. sub check_user_status { my ($udom,$uname,$cdom,$crs,$role,$sec) = @_; - my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname); + my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1}); + my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,$extra); my @uroles = keys %userinfo; my $srchstr; my $active_chk = 'none'; my $now = time; if (@uroles > 0) { - if (($role eq 'cc') || ($sec eq '') || (!defined($sec))) { + if (($role eq 'cc') || ($role eq 'co') || ($sec eq '') || (!defined($sec))) { $srchstr = '/'.$cdom.'/'.$crs.'_'.$role; } else { $srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role; @@ -7514,7 +8111,7 @@ sub get_secgrprole_info { } sub user_picker { - my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype) = @_; + my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype,$context) = @_; my $currdom = $dom; my %curr_selected = ( srchin => 'dom', @@ -7605,10 +8202,15 @@ sub user_picker { $srchtypesel .= "\n \n"; my ($newuserscript,$new_user_create); - + my $context_dom = $env{'request.role.domain'}; + if ($context eq 'requestcrs') { + if ($env{'form.coursedom'} ne '') { + $context_dom = $env{'form.coursedom'}; + } + } if ($forcenewuser) { if (ref($srch) eq 'HASH') { - if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $env{'request.role.domain'}) { + if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $context_dom) { if ($cancreate) { $new_user_create = '

&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" />

'; } else { @@ -7647,7 +8249,7 @@ function setSearch(createnew,callingForm } } for (var i=0; i{$a}) && ref($slots->{$b})) { - return $slots->{$a}{'starttime'} <=> $slots->{$b}{'starttime'} + return $slots->{$a}{$sortkey} <=> $slots->{$b}{$sortkey} } if (ref($slots->{$a})) { return -1;} if (ref($slots->{$b})) { return 1;} @@ -8020,6 +8631,131 @@ sub sorted_slots { return @sorted; } +=pod + +=item * get_future_slots() + +Inputs: + +=over 4 + +cnum - course number + +cdom - course domain + +now - current UNIX time + +symb - optional symb + +=back + +Returns: + +=over 4 + +sorted_reservable - ref to array of student_schedulable slots currently + reservable, ordered by end date of reservation period. + +reservable_now - ref to hash of student_schedulable slots currently + reservable. + + Keys in inner hash are: + (a) symb: either blank or symb to which slot use is restricted. + (b) endreserve: end date of reservation period. + +sorted_future - ref to array of student_schedulable slots reservable in + the future, ordered by start date of reservation period. + +future_reservable - ref to hash of student_schedulable slots reservable + in the future. + + Keys in inner hash are: + (a) symb: either blank or symb to which slot use is restricted. + (b) startreserve: start date of reservation period. + +=back + +=cut + +sub get_future_slots { + my ($cnum,$cdom,$now,$symb) = @_; + my (%reservable_now,%future_reservable,@sorted_reservable,@sorted_future); + my %slots = &Apache::lonnet::get_course_slots($cnum,$cdom); + foreach my $slot (keys(%slots)) { + next unless($slots{$slot}->{'type'} eq 'schedulable_student'); + if ($symb) { + next if (($slots{$slot}->{'symb'} ne '') && + ($slots{$slot}->{'symb'} ne $symb)); + } + if (($slots{$slot}->{'starttime'} > $now) && + ($slots{$slot}->{'endtime'} > $now)) { + if (($slots{$slot}->{'allowedsections'}) || ($slots{$slot}->{'allowedusers'})) { + my $userallowed = 0; + if ($slots{$slot}->{'allowedsections'}) { + my @allowed_sec = split(',',$slots{$slot}->{'allowedsections'}); + if (!defined($env{'request.role.sec'}) + && grep(/^No section assigned$/,@allowed_sec)) { + $userallowed=1; + } else { + if (grep(/^\Q$env{'request.role.sec'}\E$/,@allowed_sec)) { + $userallowed=1; + } + } + unless ($userallowed) { + if (defined($env{'request.course.groups'})) { + my @groups = split(/:/,$env{'request.course.groups'}); + foreach my $group (@groups) { + if (grep(/^\Q$group\E$/,@allowed_sec)) { + $userallowed=1; + last; + } + } + } + } + } + if ($slots{$slot}->{'allowedusers'}) { + my @allowed_users = split(',',$slots{$slot}->{'allowedusers'}); + my $user = $env{'user.name'}.':'.$env{'user.domain'}; + if (grep(/^\Q$user\E$/,@allowed_users)) { + $userallowed = 1; + } + } + next unless($userallowed); + } + my $startreserve = $slots{$slot}->{'startreserve'}; + my $endreserve = $slots{$slot}->{'endreserve'}; + my $symb = $slots{$slot}->{'symb'}; + if (($startreserve < $now) && + (!$endreserve || $endreserve > $now)) { + my $lastres = $endreserve; + if (!$lastres) { + $lastres = $slots{$slot}->{'starttime'}; + } + $reservable_now{$slot} = { + symb => $symb, + endreserve => $lastres + }; + } elsif (($startreserve > $now) && + (!$endreserve || $endreserve > $startreserve)) { + $future_reservable{$slot} = { + symb => $symb, + startreserve => $startreserve + }; + } + } + } + my @unsorted_reservable = keys(%reservable_now); + if (@unsorted_reservable > 0) { + @sorted_reservable = + &sorted_slots(\@unsorted_reservable,\%reservable_now,'endreserve'); + } + my @unsorted_future = keys(%future_reservable); + if (@unsorted_future > 0) { + @sorted_future = + &sorted_slots(\@unsorted_future,\%future_reservable,'startreserve'); + } + return (\@sorted_reservable,\%reservable_now,\@sorted_future,\%future_reservable); +} =pod @@ -8161,68 +8897,313 @@ sub get_env_multiple { sub ask_for_embedded_content { my ($actionurl,$state,$allfiles,$codebase,$args)=@_; - my $upload_output = ' -
'; - $upload_output .= $state; - $upload_output .= 'Upload embedded files:
'.&start_data_table(); - + my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges); my $num = 0; - foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%{$allfiles})) { + my $numremref = 0; + my $numinvalid = 0; + my $numpathchg = 0; + my $numexisting = 0; + my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath); + 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'}; + $url = '/userfiles/groups/'.$env{'form.group'}.'/portfolio'; + } else { + $udom = $env{'user.domain'}; + $uname = $env{'user.name'}; + $url = '/userfiles/portfolio'; + } + $toplevel = $url.'/'; + $url .= $current_path; + $getpropath = 1; + } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') || + ($actionurl eq '/adm/imsimport')) { + my ($udom,$uname,$rest) = ($args->{'current_path'} =~ m{/priv/($match_domain)/($match_username)/?(.*)$}); + $url = $Apache::lonnet::perlvar{'lonDocRoot'}."/priv/$udom/$uname/"; + $toplevel = $url; + if ($rest ne '') { + $url .= $rest; + } + } elsif ($actionurl eq '/adm/coursedocs') { + if (ref($args) eq 'HASH') { + $url = $args->{'docs_url'}; + $toplevel = $url; + } + } + my $now = time(); + foreach my $embed_file (keys(%{$allfiles})) { + my $absolutepath; + if ($embed_file =~ m{^\w+://}) { + $newfiles{$embed_file} = 1; + $mapping{$embed_file} = $embed_file; + } else { + if ($embed_file =~ m{^/}) { + $absolutepath = $embed_file; + $embed_file =~ s{^(/+)}{}; + } + if ($embed_file =~ m{/}) { + my ($path,$fname) = ($embed_file =~ m{^(.+)/([^/]*)$}); + $path = &check_for_traversal($path,$url,$toplevel); + my $item = $fname; + if ($path ne '') { + $item = $path.'/'.$fname; + $subdependencies{$path}{$fname} = 1; + } else { + $dependencies{$item} = 1; + } + if ($absolutepath) { + $mapping{$item} = $absolutepath; + } else { + $mapping{$item} = $embed_file; + } + } else { + $dependencies{$embed_file} = 1; + if ($absolutepath) { + $mapping{$embed_file} = $absolutepath; + } else { + $mapping{$embed_file} = $embed_file; + } + } + } + } + foreach my $path (keys(%subdependencies)) { + my %currsubfile; + 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') { + foreach my $line (@{$sublistref}) { + my ($file_name,$rest) = split(/\&/,$line,2); + $currsubfile{$file_name} = 1; + } + } + } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) { + if (opendir(my $dir,$url.'/'.$path)) { + my @subdir_list = grep(!/^\./,readdir($dir)); + map {$currsubfile{$_} = 1;} @subdir_list; + } + } + foreach my $file (keys(%{$subdependencies{$path}})) { + if ($currsubfile{$file}) { + my $item = $path.'/'.$file; + unless ($mapping{$item} eq $item) { + $pathchanges{$item} = 1; + } + $existing{$item} = 1; + $numexisting ++; + } else { + $newfiles{$path.'/'.$file} = 1; + } + } + } + my %currfile; + 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') { + foreach my $line (@{$dirlistref}) { + my ($file_name,$rest) = split(/\&/,$line,2); + $currfile{$file_name} = 1; + } + } + } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) { + if (opendir(my $dir,$url)) { + my @dir_list = grep(!/^\./,readdir($dir)); + map {$currfile{$_} = 1;} @dir_list; + } + } + foreach my $file (keys(%dependencies)) { + if ($currfile{$file}) { + unless ($mapping{$file} eq $file) { + $pathchanges{$file} = 1; + } + $existing{$file} = 1; + $numexisting ++; + } else { + $newfiles{$file} = 1; + } + } + foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) { $upload_output .= &start_data_table_row(). - ''.$embed_file.''; + ''.$embed_file.''; + unless ($mapping{$embed_file} eq $embed_file) { + $upload_output .= '
'.&mt('changed from: [_1]',$mapping{$embed_file}).''; + } + $upload_output .= ''; if ($args->{'ignore_remote_references'} && $embed_file =~ m{^\w+://}) { $upload_output.=''.&mt("URL points to other server.").''; + $numremref++; } elsif ($args->{'error_on_invalid_names'} && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) { - $upload_output.=''.&mt("Invalid characters").''; - + $upload_output.=''.&mt('Invalid characters').''; + $numinvalid++; } else { - $upload_output .=' - - '; - my $attrib = join(':',@{$$allfiles{$embed_file}}); - $upload_output .= - "\n\t\t". - ''; - if (exists($$codebase{$embed_file})) { - $upload_output .= - "\n\t\t". - ''; - } - } - $upload_output .= ''.&Apache::loncommon::end_data_table_row(); - $num++; - } - $upload_output .= &Apache::loncommon::end_data_table().'
- - - '.&mt('(only files for which a location has been provided will be uploaded)').' -
'; - return $upload_output; + $upload_output .= &embedded_file_element('upload_embedded',$num, + $embed_file,\%mapping, + $allfiles,$codebase); + $num++; + } + $upload_output .= ''.&Apache::loncommon::end_data_table_row()."\n"; + } + foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) { + $upload_output .= &start_data_table_row(). + ''.$embed_file.''. + ''.&mt('Already exists').''. + &Apache::loncommon::end_data_table_row()."\n"; + } + if ($upload_output) { + $upload_output = &start_data_table(). + $upload_output. + &end_data_table()."\n"; + } + my $applies = 0; + if ($numremref) { + $applies ++; + } + if ($numinvalid) { + $applies ++; + } + if ($numexisting) { + $applies ++; + } + if ($num) { + $output = '
'."\n". + $state. + '

'.&mt('Upload embedded files'). + ':

'.$upload_output.'
'."\n". + ''."\n"; + if ($actionurl eq '') { + $output .= ''; + } + } elsif ($applies) { + $output = ''.&mt('Referenced files').':
'; + if ($applies > 1) { + $output .= + &mt('No files need to be uploaded, as one of the following applies to each reference:').'
    '; + if ($numremref) { + $output .= '
  • '.&mt('reference is to a URL which points to another server').'
  • '."\n"; + } + if ($numinvalid) { + $output .= '
  • '.&mt('reference is to file with a name containing invalid characters').'
  • '."\n"; + } + if ($numexisting) { + $output .= '
  • '.&mt('reference is to an existing file at the specified location').'
  • '."\n"; + } + $output .= '

'; + } elsif ($numremref) { + $output .= '

'.&mt('None to upload, as all references are to URLs pointing to another server.').'

'; + } elsif ($numinvalid) { + $output .= '

'.&mt('None to upload, as all references are to files with names containing invalid characters.').'

'; + } elsif ($numexisting) { + $output .= '

'.&mt('None to upload, as all references are to existing files.').'

'; + } + $output .= $upload_output.'
'; + } + my ($pathchange_output,$chgcount); + $chgcount = $num; + if (keys(%pathchanges) > 0) { + foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%pathchanges)) { + if ($num) { + $output .= &embedded_file_element('pathchange',$chgcount, + $embed_file,\%mapping, + $allfiles,$codebase); + } else { + $pathchange_output .= + &start_data_table_row(). + ''. + ''.$mapping{$embed_file}.''. + ''.$embed_file. + &embedded_file_element('pathchange',$numpathchg,$embed_file, + \%mapping,$allfiles,$codebase). + ''.&end_data_table_row(); + } + $numpathchg ++; + $chgcount ++; + } + } + if ($num) { + if ($numpathchg) { + $output .= ''."\n"; + } + if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') || + ($actionurl eq '/adm/imsimport')) { + $output .= ''."\n"; + } elsif ($actionurl eq '/adm/portfolio' || $actionurl eq '/adm/coursegrp_portfolio') { + $output .= ''; + } + $output .= ''."\n". + &mt('(only files for which a location has been provided will be uploaded)').'
'."\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 .= '

'.&mt('or').'

'; + } + } + return ($output,$num,$numpathchg); +} + +sub embedded_file_element { + my ($context,$num,$embed_file,$mapping,$allfiles,$codebase) = @_; + return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') && + (ref($codebase) eq 'HASH')); + my $output; + if ($context eq 'upload_embedded') { + $output = ''."\n"; + } + $output .= ''; + unless (($context eq 'upload_embedded') && + ($mapping->{$embed_file} eq $embed_file)) { + $output .=' + '; + } + my $attrib; + if (ref($allfiles->{$mapping->{$embed_file}}) eq 'ARRAY') { + $attrib = &escape(join(':',@{$allfiles->{$mapping->{$embed_file}}})); + } + $output .= + "\n\t\t". + ''; + if (exists($codebase->{$mapping->{$embed_file}})) { + $output .= + "\n\t\t". + ''; + } + return $output; } sub upload_embedded { my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota, - $current_disk_usage) = @_; - my $output; + $current_disk_usage,$hiddenstate,$actionurl) = @_; + my (%pathchange,$output,$modifyform,$footer,$returnflag); for (my $i=0; $i<$env{'form.number_embedded_items'}; $i++) { next if (!exists($env{'form.embedded_item_'.$i.'.filename'})); my $orig_uploaded_filename = $env{'form.embedded_item_'.$i.'.filename'}; - - $env{'form.embedded_orig_'.$i} = - &unescape($env{'form.embedded_orig_'.$i}); + foreach my $type ('orig','ref','attrib','codebase') { + if ($env{'form.embedded_'.$type.'_'.$i} ne '') { + $env{'form.embedded_'.$type.'_'.$i} = + &unescape($env{'form.embedded_'.$type.'_'.$i}); + } + } my ($path,$fname) = ($env{'form.embedded_orig_'.$i} =~ m{(.*/)([^/]*)}); # no path, whole string is fname if (!$fname) { $fname = $env{'form.embedded_orig_'.$i} }; - - $path = $env{'form.currentpath'}.$path; $fname = &Apache::lonnet::clean_filename($fname); # See if there is anything left next if ($fname eq ''); @@ -8234,12 +9215,12 @@ sub upload_embedded { if ($group ne '') { $port_path = "groups/$group/$port_path"; } - ($state,$msg) = &check_for_upload($path,$fname,$group,'embedded_item_'.$i, + ($state,$msg) = &check_for_upload($env{'form.currentpath'}.$path, + $fname,$group,'embedded_item_'.$i, $dir_root,$port_path,$disk_quota, $current_disk_usage,$uname,$udom); if ($state eq 'will_exceed_quota' - || $state eq 'file_locked' - || $state eq 'file_exists' ) { + || $state eq 'file_locked') { $output .= $msg; next; } @@ -8253,31 +9234,53 @@ sub upload_embedded { # Check if extension is valid if (($fname =~ /\.(\w+)$/) && (&Apache::loncommon::fileembstyle($1) eq 'hdn')) { - $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1); + $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1).'
'; next; } elsif (($fname =~ /\.(\w+)$/) && (!defined(&Apache::loncommon::fileembstyle($1)))) { - $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1); + $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1).'
'; 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); + $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'
'; next; } $env{'form.embedded_item_'.$i.'.filename'}=$fname; if ($context eq 'portfolio') { - my $result= - &Apache::lonnet::userfileupload('embedded_item_'.$i,'', - $dirpath.$path); + my $result; + if ($state eq 'existingfile') { + $result= + &Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile', + $dirpath.$env{'form.currentpath'}.$path); + } else { + $result= + &Apache::lonnet::userfileupload('embedded_item_'.$i,'', + $dirpath. + $env{'form.currentpath'}.$path); + if ($result !~ m|^/uploaded/|) { + $output .= '' + .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].' + ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}) + .'
'; + next; + } else { + $output .= &mt('Uploaded [_1]',''. + $path.$fname.'').'
'; + } + } + } elsif ($context eq 'coursedoc') { + my $result = + &Apache::lonnet::userfileupload('embedded_item_'.$i,'coursedoc', + $dirpath.'/'.$path); if ($result !~ m|^/uploaded/|) { $output .= '' - .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].' + .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].' ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}) - .'
'; - next; + .'
'; + next; } else { - $output .= '

'.&mt('Uploaded [_1]',''. - $path.$fname.'').'

'; + $output .= &mt('Uploaded [_1]',''. + $path.$fname.'').'
'; } } else { # Save the file @@ -8285,12 +9288,12 @@ sub upload_embedded { my $fullpath = $dir_root.$dirpath.'/'.$path; my $dest = $fullpath.$fname; my $url = $url_root.$dirpath.'/'.$path.$fname; - my @parts=split(/\//,$fullpath); + my @parts=split(/\//,"$dirpath/$path"); my $count; my $filepath = $dir_root; - for ($count=4;$count<=$#parts;$count++) { - $filepath .= "/$parts[$count]"; - if ((-e $filepath)!=1) { + foreach my $subdir (@parts) { + $filepath .= "/$subdir"; + if (!-e $filepath) { mkdir($filepath,0770); } } @@ -8307,19 +9310,189 @@ sub upload_embedded { &mt('An error occurred while writing the file [_1] for embedded element [_2].',$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}). '
'; } else { - if ($context eq 'testbank') { - $output .= &mt('Embedded file uploaded successfully:'). - ' '. - $orig_uploaded_filename.'
'; - } else { - $output .= ''. - &mt('View embedded file: [_1]',''. - $orig_uploaded_filename.'').'
'; + $output .= &mt('Uploaded [_1]',''. + $url.'').'
'; + unless ($context eq 'testbank') { + $footer .= &mt('View embedded file: [_1]', + ''.$fname.'').'
'; } } close($fh); } } + if ($env{'form.embedded_ref_'.$i}) { + $pathchange{$i} = 1; + } + } + if ($output) { + $output = '

'.$output.'

'; + } + $output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange); + $returnflag = 'ok'; + if (keys(%pathchange) > 0) { + if ($context eq 'portfolio') { + $output .= '

'.&mt('or').'

'; + } elsif ($context eq 'testbank') { + $output .= '

'.&mt('Or [_1]continue[_2] the testbank import without modifying the reference(s).','','').'

'; + $returnflag = 'modify_orightml'; + } + } + return ($output.$footer,$returnflag); +} + +sub modify_html_form { + my ($context,$actionurl,$hiddenstate,$pathchange,$pathchgtable) = @_; + my $end = 0; + my $modifyform; + if ($context eq 'upload_embedded') { + return unless (ref($pathchange) eq 'HASH'); + if ($env{'form.number_embedded_items'}) { + $end += $env{'form.number_embedded_items'}; + } + if ($env{'form.number_pathchange_items'}) { + $end += $env{'form.number_pathchange_items'}; + } + if ($end) { + for (my $i=0; $i<$end; $i++) { + if ($i < $env{'form.number_embedded_items'}) { + next unless($pathchange->{$i}); + } + $modifyform .= + &start_data_table_row(). + ''. + ''.$env{'form.embedded_ref_'.$i}. + ''. + ''. + ''. + ''.$env{'form.embedded_orig_'.$i}. + ''. + &end_data_table_row(); + } + } + } else { + $modifyform = $pathchgtable; + if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) { + $hiddenstate .= ''; + } elsif (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { + $hiddenstate .= ''; + } + } + if ($modifyform) { + return '

'.&mt('Changes in content of HTML file required').'

'."\n". + '

'.&mt('Changes need to be made to the reference(s) used for one or more of the dependencies, if your HTML file is to work correctly:').'

    '."\n". + '
  1. '.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').'
  2. '."\n". + '
  3. '.&mt('To change absolute paths to relative paths, or replace directory traversal via "../" within the original reference.').'
  4. '."\n". + '

'."\n".'

'. + &mt('LON-CAPA can make the required changes to your HTML file.').'

'."\n". + '
'. + &start_data_table()."\n". + &start_data_table_header_row(). + ''.&mt('Change?').''. + ''.&mt('Current reference').''. + ''.&mt('Required reference').''. + &end_data_table_header_row()."\n". + $modifyform. + &end_data_table().'
'."\n".$hiddenstate. + ''. + '
'."\n"; + } + return; +} + +sub modify_html_refs { + my ($context,$dirpath,$uname,$udom,$dir_root) = @_; + my $container; + if ($context eq 'portfolio') { + $container = $env{'form.container'}; + } elsif ($context eq 'coursedoc') { + $container = $env{'form.primaryurl'}; + } else { + $container = $Apache::lonnet::perlvar{'lonDocRoot'}.$env{'form.filename'}; + } + my (%allfiles,%codebase,$output,$content); + my @changes = &get_env_multiple('form.namechange'); + return unless (@changes > 0); + if (($context eq 'portfolio') || ($context eq 'coursedoc')) { + return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/}); + $content = &Apache::lonnet::getfile($container); + return if ($content eq '-1'); + } else { + return unless ($container =~ /^\Q$dir_root\E/); + if (open(my $fh,"<$container")) { + $content = join('', <$fh>); + close($fh); + } else { + return; + } + } + my ($count,$codebasecount) = (0,0); + my $mm = new File::MMagic; + my $mime_type = $mm->checktype_contents($content); + if ($mime_type eq 'text/html') { + my $parse_result = + &Apache::lonnet::extract_embedded_items($container,\%allfiles, + \%codebase,\$content); + if ($parse_result eq 'ok') { + foreach my $i (@changes) { + my $orig = &unescape($env{'form.embedded_orig_'.$i}); + my $ref = &unescape($env{'form.embedded_ref_'.$i}); + if ($allfiles{$ref}) { + my $newname = $orig; + my ($attrib_regexp,$codebase); + $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i}); + if ($attrib_regexp =~ /:/) { + $attrib_regexp =~ s/\:/|/g; + } + 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; + } + if ($env{'form.embedded_codebase_'.$i} ne '') { + $codebase = &unescape($env{'form.embedded_codebase_'.$i}); + my $numchg = ($content =~ s/(codebase\s*=\s*["']?)\Q$codebase\E(["']?)/$1.$2/i); #' stupid emacs + $codebasecount ++; + } + } + } + if ($count || $codebasecount) { + my $saveresult; + if ($context eq 'portfolio' || $context eq 'coursedoc') { + my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult); + if ($url eq $container) { + my ($fname) = ($container =~ m{/([^/]+)$}); + $output = '

'.&mt('Updated [quant,_1,reference] in [_2].', + $count,''. + $fname.'').'

'; + } else { + $output = '

'. + &mt('Error: update failed for: [_1].', + ''. + $container.'').'

'; + } + } else { + if (open(my $fh,">$container")) { + print $fh $content; + close($fh); + $output = '

'.&mt('Updated [quant,_1,reference] in [_2].', + $count,''. + $container.'').'

'; + } else { + $output = '

'. + &mt('Error: could not update [_1].', + ''. + $container.'').'

'; + } + } + } + } else { + &logthis('Failed to parse '.$container. + ' to modify references: '.$parse_result); + } } return $output; } @@ -8343,22 +9516,73 @@ sub check_for_existing { sub check_for_upload { my ($path,$fname,$group,$element,$portfolio_root,$port_path, $disk_quota,$current_disk_usage,$uname,$udom) = @_; - my $filesize = (length($env{'form.'.$element})) / 1000; #express in k (1024?) + my $filesize = length($env{'form.'.$element}); + if (!$filesize) { + my $msg = ''. + &mt('Unable to upload [_1]. (size = [_2] bytes)', + ''.$fname.'', + $filesize).'
'. + &mt('Either the file you attempted to upload was empty, or your web browser was unable to read its contents.').'
'. + '
'; + return ('zero_bytes',$msg); + } + $filesize = $filesize/1000; #express in k (1024?) my $getpropath = 1; - my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname, - $getpropath); + my ($dirlistref,$listerror) = + &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,$getpropath); my $found_file = 0; my $locked_file = 0; - foreach my $line (@dir_list) { - my ($file_name)=split(/\&/,$line,2); - if ($file_name eq $fname){ - $file_name = $path.$file_name; - if ($group ne '') { - $file_name = $group.$file_name; - } - $found_file = 1; - if (&Apache::lonnet::is_locked($file_name,$udom,$uname) eq 'true') { - $locked_file = 1; + my @lockers; + my $navmap; + if ($env{'request.course.id'}) { + $navmap = Apache::lonnavmaps::navmap->new(); + } + if (ref($dirlistref) eq 'ARRAY') { + foreach my $line (@{$dirlistref}) { + my ($file_name,$rest)=split(/\&/,$line,2); + if ($file_name eq $fname){ + $file_name = $path.$file_name; + if ($group ne '') { + $file_name = $group.$file_name; + } + $found_file = 1; + if (&Apache::lonnet::is_locked($file_name,$udom,$uname,\@lockers) eq 'true') { + foreach my $lock (@lockers) { + if (ref($lock) eq 'ARRAY') { + my ($symb,$crsid) = @{$lock}; + if ($crsid eq $env{'request.course.id'}) { + if (ref($navmap)) { + my $res = $navmap->getBySymb($symb); + foreach my $part (@{$res->parts()}) { + my ($slot_status,$slot_time,$slot_name)=$res->check_for_slot($part); + unless (($slot_status == $res->RESERVED) || + ($slot_status == $res->RESERVED_LOCATION)) { + $locked_file = 1; + } + } + } else { + $locked_file = 1; + } + } else { + $locked_file = 1; + } + } + } + } else { + my @info = split(/\&/,$rest); + my $currsize = $info[6]/1000; + if ($currsize < $filesize) { + my $extra = $filesize - $currsize; + if (($current_disk_usage + $extra) > $disk_quota) { + my $msg = ''. + &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.', + ''.$fname.'',$filesize,$currsize).''. + '
'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.', + $disk_quota,$current_disk_usage); + return ('will_exceed_quota',$msg); + } + } + } } } } @@ -8376,15 +9600,162 @@ sub check_for_upload { return ('file_locked',$msg); } else { my $msg = ''; - $msg .= &mt('Unable to upload [_1]. A file by that name was found in [_2].',''.$fname.'',$port_path.$env{'form.currentpath'}); + $msg .= &mt(' A file by that name: [_1] was found in [_2].',''.$fname.'',$port_path.$env{'form.currentpath'}); $msg .= ''; - $msg .= '
'; - $msg .= &mt('To upload, rename or delete existing [_1] in [_2].',''.$fname.'', $port_path.$env{'form.currentpath'}); - return ('file_exists',$msg); + return ('existingfile',$msg); + } + } +} + +sub check_for_traversal { + my ($path,$url,$toplevel) = @_; + my @parts=split(/\//,$path); + my $cleanpath; + my $fullpath = $url; + for (my $i=0;$i<@parts;$i++) { + next if ($parts[$i] eq '.'); + if ($parts[$i] eq '..') { + $fullpath =~ s{([^/]+/)$}{}; + } else { + $fullpath .= $parts[$i].'/'; + } + } + if ($fullpath =~ /^\Q$url\E(.*)$/) { + $cleanpath = $1; + } elsif ($fullpath =~ /^\Q$toplevel\E(.*)$/) { + my $curr_toprel = $1; + my @parts = split(/\//,$curr_toprel); + my ($url_toprel) = ($url =~ /^\Q$toplevel\E(.*)$/); + my @urlparts = split(/\//,$url_toprel); + my $doubledots; + my $startdiff = -1; + for (my $i=0; $i<@urlparts; $i++) { + if ($startdiff == -1) { + unless ($urlparts[$i] eq $parts[$i]) { + $startdiff = $i; + $doubledots .= '../'; + } + } else { + $doubledots .= '../'; + } + } + if ($startdiff > -1) { + $cleanpath = $doubledots; + for (my $i=$startdiff; $i<@parts; $i++) { + $cleanpath .= $parts[$i].'/'; + } } } + $cleanpath =~ s{(/)$}{}; + return $cleanpath; } +=pod + +=item * &get_turnedin_filepath() + +Determines path in a user's portfolio file for storage of files uploaded +to a specific essayresponse or dropbox item. + +Inputs: 3 required + 1 optional. +$symb is symb for resource, $uname and $udom are for current user (required). +$caller is optional (can be "submission", if routine is called when storing +an upoaded file when "Submit Answer" button was pressed). + +Returns array containing $path and $multiresp. +$path is path in portfolio. $multiresp is 1 if this resource contains more +than one file upload item. Callers of routine should append partid as a +subdirectory to $path in cases where $multiresp is 1. + +Called by: homework/essayresponse.pm and homework/structuretags.pm + +=cut + +sub get_turnedin_filepath { + my ($symb,$uname,$udom,$caller) = @_; + my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb); + my $turnindir; + my %userhash = &Apache::lonnet::userenvironment($udom,$uname,'turnindir'); + $turnindir = $userhash{'turnindir'}; + my ($path,$multiresp); + if ($turnindir eq '') { + if ($caller eq 'submission') { + $turnindir = &mt('turned in'); + $turnindir =~ s/\W+/_/g; + my %newhash = ( + 'turnindir' => $turnindir, + ); + &Apache::lonnet::put('environment',\%newhash,$udom,$uname); + } + } + if ($turnindir ne '') { + $path = '/'.$turnindir.'/'; + my ($multipart,$turnin,@pathitems); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (defined($navmap)) { + my $mapres = $navmap->getResourceByUrl($map); + if (ref($mapres)) { + my $pcslist = $mapres->map_hierarchy(); + if ($pcslist ne '') { + foreach my $pc (split(/,/,$pcslist)) { + my $res = $navmap->getByMapPc($pc); + if (ref($res)) { + my $title = $res->compTitle(); + $title =~ s/\W+/_/g; + if ($title ne '') { + push(@pathitems,$title); + } + } + } + } + my $maptitle = $mapres->compTitle(); + $maptitle =~ s/\W+/_/g; + if ($maptitle ne '') { + push(@pathitems,$maptitle); + } + unless ($env{'request.state'} eq 'construct') { + my $res = $navmap->getBySymb($symb); + if (ref($res)) { + my $partlist = $res->parts(); + my $totaluploads = 0; + if (ref($partlist) eq 'ARRAY') { + foreach my $part (@{$partlist}) { + my @types = $res->responseType($part); + my @ids = $res->responseIds($part); + for (my $i=0; $i < scalar(@ids); $i++) { + if ($types[$i] eq 'essay') { + my $partid = $part.'_'.$ids[$i]; + if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') { + $totaluploads ++; + } + } + } + } + if ($totaluploads > 1) { + $multiresp = 1; + } + } + } + } + } else { + return; + } + } else { + return; + } + my $restitle=&Apache::lonnet::gettitle($symb); + $restitle =~ s/\W+/_/g; + if ($restitle eq '') { + $restitle = ($resurl =~ m{/[^/]+$}); + if ($restitle eq '') { + $restitle = time; + } + } + push(@pathitems,$restitle); + $path .= join('/',@pathitems); + } + return ($path,$multiresp); +} =pod @@ -9491,6 +10862,8 @@ sub extract_categories { my $trailstr; if ($name eq 'instcode') { $trailstr = &mt('Official courses (with institutional codes)'); + } elsif ($name eq 'communities') { + $trailstr = &mt('Communities'); } else { $trailstr = $name; } @@ -9603,12 +10976,14 @@ cathash - reference to hash of categorie currcat - scalar with an & separated list of categories assigned to a course. +type - scalar contains course type (Course or Community). + Returns: $output (markup to be displayed) =cut sub assign_categories_table { - my ($cathash,$currcat) = @_; + my ($cathash,$currcat,$type) = @_; my $output; if (ref($cathash) eq 'HASH') { my (@cats,@trails,%allitems,%idx,@jsarray,@path,$maxdepth); @@ -9617,15 +10992,20 @@ sub assign_categories_table { if (@cats > 0) { my $itemcount = 0; if (ref($cats[0]) eq 'ARRAY') { - $output = &Apache::loncommon::start_data_table(); my @currcategories; if ($currcat ne '') { @currcategories = split('&',$currcat); } + my $table; for (my $i=0; $i<@{$cats[0]}; $i++) { my $parent = $cats[0][$i]; - my $css_class = $itemcount%2?' class="LC_odd_row"':''; next if ($parent eq 'instcode'); + if ($type eq 'Community') { + next unless ($parent eq 'communities'); + } else { + next if ($parent eq 'communities'); + } + my $css_class = $itemcount%2?' class="LC_odd_row"':''; my $item = &escape($parent).'::0'; my $checked = ''; if (@currcategories > 0) { @@ -9633,18 +11013,26 @@ sub assign_categories_table { $checked = ' checked="checked"'; } } - $output .= ''. - ''.$parent.''. - ''; + my $parent_title = $parent; + if ($parent eq 'communities') { + $parent_title = &mt('Communities'); + } + $table .= ''. + ''.$parent_title.''. + ''; my $depth = 1; push(@path,$parent); - $output .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories); + $table .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories); pop(@path); - $output .= ''; + $table .= ''; $itemcount ++; } - $output .= &Apache::loncommon::end_data_table(); + if ($itemcount) { + $output = &Apache::loncommon::start_data_table(). + $table. + &Apache::loncommon::end_data_table(); + } } } } @@ -9889,11 +11277,24 @@ sub check_clone { my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom); my $clonemsg; my $can_clone = 0; - + my $lctype = lc($args->{'crstype'}); + if ($lctype ne 'community') { + $lctype = 'course'; + } if ($clonehome eq 'no_host') { - $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'}); + if ($args->{'crstype'} eq 'Community') { + $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a non-existent community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'}); + } else { + $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'}); + } } else { my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1}); + if ($args->{'crstype'} eq 'Community') { + if ($clonedesc{'type'} ne 'Community') { + $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a course not a community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'}); + return ($can_clone, $clonemsg, $cloneid, $clonehome); + } + } if (($env{'request.role.domain'} eq $args->{'clonedomain'}) && (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'}))) { $can_clone = 1; @@ -9906,15 +11307,25 @@ sub check_clone { } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) { $can_clone = 1; } else { + my $ccrole = 'cc'; + if ($args->{'crstype'} eq 'Community') { + $ccrole = 'co'; + } my %roleshash = &Apache::lonnet::get_my_roles($args->{'ccuname'}, $args->{'ccdomain'}, - 'userroles',['active'],['cc'], + 'userroles',['active'],[$ccrole], [$args->{'clonedomain'}]); - if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) { - $can_clone = 1; - } else { - $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'}); + if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) { + $can_clone = 1; + } elsif (&Apache::lonnet::is_course_owner($args->{'clonedomain'},$args->{'clonecourse'},$args->{'ccuname'},$args->{'ccdomain'})) { + $can_clone = 1; + } else { + if ($args->{'crstype'} eq 'Community') { + $clonemsg = &mt('No new community created.').$linefeed.&mt('The new community could not be cloned from the existing community because the new community owner ([_1]) does not have cloning rights in the existing community ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'}); + } else { + $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'}); + } } } } @@ -9969,11 +11380,19 @@ sub construct_course { # if anyone ever decides to not show this, and Utils::Course::new # will need to be suitably modified. $outcome .= &mt('New LON-CAPA [_1] ID: [_2]',$crstype,$$courseid).$linefeed; + if ($$courseid =~ /^error:/) { + return (0,$outcome); + } + # # Check if created correctly # ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid); my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom); + if ($crsuhome eq 'no_host') { + $outcome .= &mt('Course creation failed, unrecognized course home server.').$linefeed; + return (0,$outcome); + } $outcome .= &mt('Created on').': '.$crsuhome.$linefeed; # @@ -9992,6 +11411,10 @@ sub construct_course { $cenv{'url'}=$oldcenv{'url'}; # Restore title $cenv{'description'}=$oldcenv{'description'}; +# Restore creation date, creator and creation context. + $cenv{'internal.created'}=$oldcenv{'internal.created'}; + $cenv{'internal.creator'}=$oldcenv{'internal.creator'}; + $cenv{'internal.creationcontext'}=$oldcenv{'internal.creationcontext'}; # Mark as cloned $cenv{'clonedfrom'}=$cloneid; # Need to clone grading mode @@ -10238,7 +11661,7 @@ sub construct_course { $title=&mt('Syllabus'); $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus'; } else { - $title=&mt('Navigate Contents'); + $title=&mt('Table of Contents'); $url='/adm/navmaps'; } @@ -10255,6 +11678,8 @@ sub construct_course { ############################################################ ############################################################ +#SD +# only Community and Course, or anything else? sub course_type { my ($cid) = @_; if (!defined($cid)) { @@ -10276,6 +11701,16 @@ sub group_term { return $names{$crstype}; } +sub course_types { + my @types = ('official','unofficial','community'); + my %typename = ( + official => 'Official course', + unofficial => 'Unofficial course', + community => 'Community', + ); + return (\@types,\%typename); +} + sub icon { my ($file)=@_; my $curfext = lc((split(/\./,$file))[-1]); @@ -10410,15 +11845,12 @@ sub init_user_environment { my %userenv = &Apache::lonnet::dump('environment',$domain,$username); my ($tmp) = keys(%userenv); if ($tmp !~ /^(con_lost|error|no_such_host)/i) { - # default remote control to off - if ($userenv{'remote'} ne 'on') { $userenv{'remote'} = 'off'; } } else { undef(%userenv); } if (($userenv{'interface'}) && (!$form->{'interface'})) { $form->{'interface'}=$userenv{'interface'}; } - $env{'environment.remote'}=$userenv{'remote'}; if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; } # --------------- Do not trust query string to be put directly into environment @@ -10450,24 +11882,29 @@ sub init_user_environment { $initial_env{"browser.localres"} = $form->{'localres'}; } - if ($public) { - $initial_env{"environment.remote"} = "off"; - } if ($form->{'interface'}) { $form->{'interface'}=~s/\W//gs; $initial_env{"browser.interface"} = $form->{'interface'}; $env{'browser.interface'}=$form->{'interface'}; } + my %is_adv = ( is_adv => $env{'user.adv'} ); + my %domdef; + unless ($domain eq 'public') { + %domdef = &Apache::lonnet::get_domain_defaults($domain); + } + foreach my $tool ('aboutme','blog','portfolio') { $userenv{'availabletools.'.$tool} = - &Apache::lonnet::usertools_access($username,$domain,$tool,'reload'); + &Apache::lonnet::usertools_access($username,$domain,$tool,'reload', + undef,\%userenv,\%domdef,\%is_adv); } foreach my $crstype ('official','unofficial','community') { $userenv{'canrequest.'.$crstype} = &Apache::lonnet::usertools_access($username,$domain,$crstype, - 'reload','requestcourses'); + 'reload','requestcourses', + \%userenv,\%domdef,\%is_adv); } $env{'user.environment'} = "$lonids/$cookie.id"; @@ -10546,6 +11983,36 @@ sub clean_symb { return ($symb,$enc); } +sub build_release_hashes { + my ($checkparms,$checkresponsetypes,$checkcrstypes,$anonsurvey,$randomizetry) = @_; + return unless((ref($checkparms) eq 'HASH') && (ref($checkresponsetypes) eq 'HASH') && + (ref($checkcrstypes) eq 'HASH') && (ref($anonsurvey) eq 'HASH') && + (ref($randomizetry) eq 'HASH')); + foreach my $key (keys(%Apache::lonnet::needsrelease)) { + my ($item,$name,$value) = split(/:/,$key); + if ($item eq 'parameter') { + if (ref($checkparms->{$name}) eq 'ARRAY') { + unless(grep(/^\Q$name\E$/,@{$checkparms->{$name}})) { + push(@{$checkparms->{$name}},$value); + } + } else { + push(@{$checkparms->{$name}},$value); + } + } elsif ($item eq 'resourcetag') { + if ($name eq 'responsetype') { + $checkresponsetypes->{$value} = $Apache::lonnet::needsrelease{$key} + } + } elsif ($item eq 'course') { + if ($name eq 'crstype') { + $checkcrstypes->{$value} = $Apache::lonnet::needsrelease{$key}; + } + } + } + ($anonsurvey->{major},$anonsurvey->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'}); + ($randomizetry->{major},$randomizetry->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'}); + return; +} + =pod =back