--- loncom/interface/loncommon.pm 2006/04/25 21:24:06 1.355 +++ loncom/interface/loncommon.pm 2006/08/02 20:18:10 1.440 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.355 2006/04/25 21:24:06 albertel Exp $ +# $Id: loncommon.pm,v 1.440 2006/08/02 20:18:10 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -64,6 +64,7 @@ use HTML::Entities; use Apache::lonhtmlcommon(); use Apache::loncoursedata(); use Apache::lontexconvert(); +use LONCAPA; my $readit; @@ -107,10 +108,10 @@ BEGIN { my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}. '/language.tab'; if ( open(my $fh,"<$langtabfile") ) { - while (<$fh>) { - next if /^\#/; - chomp; - my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_)); + while (my $line = <$fh>) { + next if ($line=~/^\#/); + chomp($line); + my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$line)); $language{$key}=$val.' - '.$enc; if ($sup) { $supported_language{$key}=$sup; @@ -124,10 +125,10 @@ BEGIN { my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}. '/copyright.tab'; if ( open (my $fh,"<$copyrightfile") ) { - while (<$fh>) { - next if /^\#/; - chomp; - my ($key,$val)=(split(/\s+/,$_,2)); + while (my $line = <$fh>) { + next if ($line=~/^\#/); + chomp($line); + my ($key,$val)=(split(/\s+/,$line,2)); $cprtag{$key}=$val; } close($fh); @@ -138,10 +139,10 @@ BEGIN { my $sourcecopyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}. '/source_copyright.tab'; if ( open (my $fh,"<$sourcecopyrightfile") ) { - while (<$fh>) { - next if /^\#/; - chomp; - my ($key,$val)=(split(/\s+/,$_,2)); + while (my $line = <$fh>) { + next if ($line =~ /^\#/); + chomp($line); + my ($key,$val)=(split(/\s+/,$line,2)); $scprtag{$key}=$val; } close($fh); @@ -159,10 +160,10 @@ BEGIN { { my $designfile = $designdir.'/'.$filename; if ( open (my $fh,"<$designfile") ) { - while (<$fh>) { - next if /^\#/; - chomp; - my ($key,$val)=(split(/\=/,$_)); + while (my $line = <$fh>) { + next if ($line =~ /^\#/); + chomp($line); + my ($key,$val)=(split(/\=/,$line)); if ($val) { $designhash{$domain.'.'.$key}=$val; } } close($fh); @@ -178,10 +179,10 @@ BEGIN { my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}. '/filecategories.tab'; if ( open (my $fh,"<$categoryfile") ) { - while (<$fh>) { - next if /^\#/; - chomp; - my ($extension,$category)=(split(/\s+/,$_,2)); + while (my $line = <$fh>) { + next if ($line =~ /^\#/); + chomp($line); + my ($extension,$category)=(split(/\s+/,$line,2)); push @{$category_extensions{lc($category)}},$extension; } close($fh); @@ -193,10 +194,10 @@ BEGIN { my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}. '/filetypes.tab'; if ( open (my $fh,"<$typesfile") ) { - while (<$fh>) { - next if (/^\#/); - chomp; - my ($ending,$emb,$mime,$descr)=split(/\s+/,$_,4); + while (my $line = <$fh>) { + next if ($line =~ /^\#/); + chomp($line); + my ($ending,$emb,$mime,$descr)=split(/\s+/,$line,4); if ($descr ne '') { $fe{$ending}=lc($emb); $fd{$ending}=$descr; @@ -284,7 +285,7 @@ sub browser_and_searcher_javascript { } url += 'element=' + elementname + ''; var title = 'Browser'; - var options = 'scrollbars=1,resizable=1,menubar=1,location=1'; + var options = 'scrollbars=1,resizable=1,menubar=0,toolbar=1,location=1'; options += ',width=700,height=600'; editbrowser = open(url,title,options,'1'); editbrowser.focus(); @@ -305,7 +306,7 @@ sub browser_and_searcher_javascript { } url += 'element=' + elementname + ''; var title = 'Search'; - var options = 'scrollbars=1,resizable=1,menubar=0'; + var options = 'scrollbars=1,resizable=1,menubar=0,toolbar=1,location=1'; options += ',width=700,height=600'; editsearcher = open(url,title,options,'1'); editsearcher.focus(); @@ -385,10 +386,11 @@ sub selectstudent_link { sub coursebrowser_javascript { my ($domainfilter)=@_; + my $crs_or_grp_alert = &mt('Please select the type of LON-CAPA entity - Course or Group - for which you wish to add/modify a user role'); return (< var stdeditbrowser; - function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag) { + function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag,crstype) { var url = '/adm/pickcourse?'; var filter; if (filter != null) { @@ -414,6 +416,18 @@ sub coursebrowser_javascript { if (multflag !=null && multflag != '') { url += '&multiple='+multflag; } + if (crstype == 'Course/Group') { + if (formname == 'cu') { + crstype = document.cu.crstype.options[document.cu.crstype.selectedIndex].value; + if (crstype == "") { + alert("$crs_or_grp_alert"); + return; + } + } + } + if (crstype !=null && crstype != '') { + url += '&type='+crstype; + } var title = 'Course_Browser'; var options = 'scrollbars=1,resizable=1,menubar=0'; options += ',width=700,height=600'; @@ -425,9 +439,9 @@ ENDSTDBRW } sub selectcourse_link { - my ($form,$unameele,$udomele,$desc,$extra_element,$multflag)=@_; + my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype)=@_; return "".&mt('Select Course').""; + '","'.$udomele.'","'.$desc.'","'.$extra_element.'","'.$multflag.'","'.$selecttype.'");'."'>".&mt('Select [_1]',$selecttype).""; } sub check_uncheck_jscript { @@ -658,14 +672,14 @@ sub help_open_topic { { $template .= "". - "
$text"; + "$text"; } # Add the graphic my $title = &mt('Online Help'); my $helpicon=&lonhttpdurl("/adm/help/gif/smallHelp.gif"); $template .= <<"ENDTEMPLATE"; - (Help: $topic) + (Help: $topic) ENDTEMPLATE if ($text ne '') { $template.='
' }; return $template; @@ -692,39 +706,95 @@ sub helpLatexCheatsheet { .''; } -sub help_open_menu { - my ($color,$topic,$component_help,$function,$faq,$bug,$stayOnPage,$width,$height,$text) = @_; - $text = "" if (not defined $text); - $stayOnPage = 0 if (not defined $stayOnPage); - if ($env{'browser.interface'} eq 'textual' || - $env{'environment.remote'} eq 'off' ) { - $stayOnPage=1; +sub general_help { + my $helptopic='Student_Intro'; + if ($env{'request.role'}=~/^(ca|au)/) { + $helptopic='Authoring_Intro'; + } elsif ($env{'request.role'}=~/^cc/) { + $helptopic='Course_Coordination_Intro'; } - $width = 620 if (not defined $width); - $height = 600 if (not defined $height); - my $link=''; - my $title = &mt('Get help'); + return $helptopic; +} + +sub update_help_link { + my ($topic,$component_help,$faq,$bug,$stayOnPage) = @_; my $origurl = $ENV{'REQUEST_URI'}; $origurl=~s|^/~|/priv/|; my $timestamp = time; - foreach (\$color,\$function,\$topic,\$component_help,\$faq,\$bug,\$origurl) { - $$_ = &Apache::lonnet::escape($$_); + foreach my $datum (\$topic,\$component_help,\$faq,\$bug,\$origurl) { + $$datum = &escape($$datum); } - if (!$stayOnPage) { - $link = "javascript:helpMenu('open')"; - } else { - $link = "javascript:helpMenu('display')"; + + my $banner_link = "/adm/helpmenu?page=banner&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage"; + my $output .= <<"ENDOUTPUT"; + +ENDOUTPUT + return $output; +} + +# now just updates the help link and generates a blue icon +sub help_open_menu { + my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text) + = @_; + + $stayOnPage = 0 if (not defined $stayOnPage); + if ($env{'browser.interface'} eq 'textual' || + $env{'environment.remote'} eq 'off' ) { + $stayOnPage=1; } - my $banner_link = "/adm/helpmenu?page=banner&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage"; - my $details_link = "/adm/helpmenu?page=body&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp"; - my $template; - if ($text ne "") { - $template .= - "". - "
$text"; + my $output; + if ($component_help) { + if (!$text) { + $output=&help_open_topic($component_help,undef,$stayOnPage, + $width,$height); + } else { + my $help_text; + $help_text=&unescape($topic); + $output='
'. + &help_open_topic($component_help,$help_text,$stayOnPage, + $width,$height).'
'; + } } + my $banner_link = &update_help_link($topic,$component_help,$faq,$bug,$stayOnPage); + return $output.$banner_link; +} + +sub top_nav_help { + my ($text) = @_; + + $text = &mt($text); + + my $stayOnPage = + ($env{'browser.interface'} eq 'textual' || + $env{'environment.remote'} eq 'off' ); + my $link= ($stayOnPage) ? "javascript:helpMenu('display')" + : "javascript:helpMenu('open')"; + my $banner_link = &update_help_link(undef,undef,undef,undef,$stayOnPage); + + my $title = &mt('Get help'); + + return <<"END"; +$banner_link + $text +END +} + +sub help_menu_js { + my ($text) = @_; + + my $stayOnPage = + ($env{'browser.interface'} eq 'textual' || + $env{'environment.remote'} eq 'off' ); + + my $width = 620; + my $height = 600; + my $helptopic=&general_help(); + my $details_link = '/adm/help/'.$helptopic.'.hlp'; my $nothing=&Apache::lonhtmlcommon::javascript_nothing(); - my $helpicon=&lonhttpdurl("/adm/lonIcons/helpgateway.gif"); my $start_page = &Apache::loncommon::start_page('Help Menu', undef, {'frameset' => 1, @@ -736,10 +806,11 @@ sub help_open_menu { &Apache::loncommon::end_page({'frameset' => 1, 'js_ready' => 1,}); - $template .= <<"ENDTEMPLATE"; - - (Help Menu) + ENDTEMPLATE - if ($component_help) { - if (!$text) { - $template=&help_open_topic($component_help,undef,$stayOnPage, - $width,$height).' '.$template; - } else { - my $help_text; - $help_text=&Apache::lonnet::unescape($topic); - $template='
'. - &help_open_topic($component_help,$help_text,$stayOnPage, - $width,$height).''.$template. - '
'; - } - } - if ($text ne '') { $template.='
' }; return $template; } @@ -801,8 +857,8 @@ sub help_open_bug { $topic=~s/\W+/\+/g; my $link=''; my $template=''; - my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='. - &Apache::lonnet::escape($ENV{'REQUEST_URI'}).'&component='.$topic; + my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='. + &escape($ENV{'REQUEST_URI'}).'&component='.$topic; if (!$stayOnPage) { $link = "javascript:void(open('$url', 'Bugzilla', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))"; @@ -816,14 +872,14 @@ sub help_open_bug { { $template .= "". - "
$text"; + "$text"; } # Add the graphic my $title = &mt('Report a Bug'); my $bugicon=&lonhttpdurl("/adm/lonMisc/smallBug.gif"); $template .= <<"ENDTEMPLATE"; - (Bug: $topic) + (Bug: $topic) ENDTEMPLATE if ($text ne '') { $template.='
' }; return $template; @@ -861,14 +917,14 @@ sub help_open_faq { { $template .= "". - "
$text"; + "$text"; } # Add the graphic my $title = &mt('View the FAQ'); my $faqicon=&lonhttpdurl("/adm/lonMisc/smallFAQ.gif"); $template .= <<"ENDTEMPLATE"; - (FAQ: $topic) + (FAQ: $topic) ENDTEMPLATE if ($text ne '') { $template.='
' }; return $template; @@ -1153,8 +1209,8 @@ sub get_domains { # The code below was stolen from "The Perl Cookbook", p 102, 1st ed. my @domains; my %seen; - foreach (sort values(%Apache::lonnet::hostdom)) { - push (@domains,$_) unless $seen{$_}++; + foreach my $dom (sort(values(%Apache::lonnet::hostdom))) { + push(@domains,$dom) unless $seen{$dom}++; } return @domains; } @@ -1208,7 +1264,7 @@ sub multiple_select_form { my @order = ref($order) ? @$order : sort(keys(%$hash)); foreach my $key (@order) { - $output.='\n"; } @@ -1238,10 +1294,11 @@ sub select_form { } else { @keys=sort(keys(%hash)); } - foreach (@keys) { - $selectform.="\n"; + foreach my $key (@keys) { + $selectform.= + '\n"; } $selectform.=""; return $selectform; @@ -1305,10 +1362,10 @@ sub select_dom_form { my @domains = get_domains(); if ($includeempty) { @domains=('',@domains); } my $selectdomain = ""; return $selectdomain; @@ -1330,9 +1387,9 @@ given $domain. sub get_library_servers { my $domain = shift; my %library_servers; - foreach (keys(%Apache::lonnet::libserv)) { - if ($Apache::lonnet::hostdom{$_} eq $domain) { - $library_servers{$_} = $Apache::lonnet::hostname{$_}; + foreach my $hostid (keys(%Apache::lonnet::libserv)) { + if ($Apache::lonnet::hostdom{$hostid} eq $domain) { + $library_servers{$hostid} = $Apache::lonnet::hostname{$hostid}; } } return %library_servers; @@ -1354,9 +1411,10 @@ sub home_server_option_list { my $domain = shift; my %servers = &get_library_servers($domain); my $result = ''; - foreach (sort keys(%servers)) { + foreach my $hostid (sort(keys(%servers))) { $result.= - '\n"; + '\n"; } return $result; } @@ -1846,8 +1904,8 @@ sub initialize_keywords { } untie %thesaurus_db; # Remove special values from %Keywords. - foreach ('total.count','average.count') { - delete($Keywords{$_}) if (exists($Keywords{$_})); + foreach my $value ('total.count','average.count') { + delete($Keywords{$value}) if (exists($Keywords{$value})); } return 1; } @@ -1902,12 +1960,20 @@ sub get_related_words { return (); } my @Words=(); + my $count=0; if (exists($thesaurus_db{$keyword})) { - $_ = $thesaurus_db{$keyword}; - (undef,@Words) = split/:/; # The first element is the number of times - # the word appears. We do not need it now. - for (my $i=0;$i<=$#Words;$i++) { - ($Words[$i],undef)= split/\,/,$Words[$i]; + # The first element is the number of times + # the word appears. We do not need it now. + my (undef,@RelatedWords) = (split(/:/,$thesaurus_db{$keyword})); + my (undef,$mostfrequentcount)=split(/\,/,$RelatedWords[0]); + my $threshold=$mostfrequentcount/10; + foreach my $possibleword (@RelatedWords) { + my ($word,$wordcount)=split(/\,/,$possibleword); + if ($wordcount>$threshold) { + push(@Words,$word); + $count++; + if ($count>10) { last; } + } } } untie %thesaurus_db; @@ -1986,6 +2052,9 @@ sub nickname { sub getnames { my ($uname,$udom)=@_; + if ($udom eq 'public' && $uname eq 'public') { + return ('lastname' => &mt('Public')); + } my $id=$uname.':'.$udom; my ($names,$cached)=&Apache::lonnet::is_cached_new('namescache',$id); if ($cached) { @@ -2021,10 +2090,11 @@ sub screenname { # ------------------------------------------------------------- Message Wrapper sub messagewrapper { - my ($link,$username,$domain)=@_; + my ($link,$username,$domain,$subject,$text)=@_; return ''.$link.''; } # --------------------------------------------------------------- Notes Wrapper @@ -2184,7 +2254,8 @@ category =cut sub filecategorytypes { - return @{$category_extensions{lc($_[0])}}; + my ($cat) = @_; + return @{$category_extensions{lc($cat)}}; } =pod @@ -2259,13 +2330,13 @@ sub fileextensions { sub display_languages { my %languages=(); - foreach (&preferred_languages()) { - $languages{$_}=1; + foreach my $lang (&preferred_languages()) { + $languages{$lang}=1; } &get_unprocessed_cgi($ENV{'QUERY_STRING'},['displaylanguage']); if ($env{'form.displaylanguage'}) { - foreach (split(/\s*(\,|\;|\:)\s*/,$env{'form.displaylanguage'})) { - $languages{$_}=1; + foreach my $lang (split(/\s*(\,|\;|\:)\s*/,$env{'form.displaylanguage'})) { + $languages{$lang}=1; } } return %languages; @@ -2300,11 +2371,11 @@ sub preferred_languages { } # turn "en-ca" into "en-ca,en" my @genlanguages; - foreach (@languages) { - unless ($_=~/\w/) { next; } - push (@genlanguages,$_); - if ($_=~/(\-|\_)/) { - push (@genlanguages,(split(/(\-|\_)/,$_))[0]); + foreach my $lang (@languages) { + unless ($lang=~/\w/) { next; } + push (@genlanguages,$lang); + if ($lang=~/(\-|\_)/) { + push(@genlanguages,(split(/(\-|\_)/,$lang))[0]); } } return @genlanguages; @@ -2360,14 +2431,14 @@ sub get_previous_attempt { my %lasthash=(); my $version; for ($version=1;$version<=$returnhash{'version'};$version++) { - foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) { - $lasthash{$_}=$returnhash{$version.':'.$_}; + foreach my $key (sort(split(/\:/,$returnhash{$version.':keys'}))) { + $lasthash{$key}=$returnhash{$version.':'.$key}; } } $prevattempts='
'; $prevattempts.=''; - foreach (sort(keys %lasthash)) { - my ($ign,@parts) = split(/\./,$_); + foreach my $key (sort(keys(%lasthash))) { + my ($ign,@parts) = split(/\./,$key); if ($#parts > 0) { my $data=$parts[-1]; pop(@parts); @@ -2383,27 +2454,27 @@ sub get_previous_attempt { if ($getattempt eq '') { for ($version=1;$version<=$returnhash{'version'};$version++) { $prevattempts.=''; - foreach (sort(keys %lasthash)) { + foreach my $key (sort(keys(%lasthash))) { my $value; - if ($_ =~ /timestamp/) { - $value=scalar(localtime($returnhash{$version.':'.$_})); + if ($key =~ /timestamp/) { + $value=scalar(localtime($returnhash{$version.':'.$key})); } else { - $value=$returnhash{$version.':'.$_}; + $value=$returnhash{$version.':'.$key}; } - $prevattempts.=''; + $prevattempts.=''; } } } $prevattempts.=''; - foreach (sort(keys %lasthash)) { + foreach my $key (sort(keys(%lasthash))) { my $value; - if ($_ =~ /timestamp/) { - $value=scalar(localtime($lasthash{$_})); + if ($key =~ /timestamp/) { + $value=scalar(localtime($lasthash{$key})); } else { - $value=$lasthash{$_}; + $value=$lasthash{$key}; } - $value=&Apache::lonnet::unescape($value); - if ($_ =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)} + $value=&unescape($value); + if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)} $prevattempts.=''; } $prevattempts.='
History
Transaction '.$version.''.&Apache::lonnet::unescape($value).' '.&unescape($value).' 
Current'.$value.' 
'; @@ -2435,14 +2506,14 @@ sub relative_to_absolute { } } $thisdir=~s-/[^/]*$--; - foreach (@rlinks) { - unless (($_=~/^http:\/\//i) || - ($_=~/^\//) || - ($_=~/^javascript:/i) || - ($_=~/^mailto:/i) || - ($_=~/^\#/)) { - my $newlocation=&Apache::lonnet::hreflocation($thisdir,$_); - $output=~s/(\"|\'|\=\s*)$_(\"|\'|\s|\>)/$1$newlocation$2/; + foreach my $link (@rlinks) { + unless (($link=~/^http:\/\//i) || + ($link=~/^\//) || + ($link=~/^javascript:/i) || + ($link=~/^mailto:/i) || + ($link=~/^\#/)) { + my $newlocation=&Apache::lonnet::hreflocation($thisdir,$link); + $output=~s/(\"|\'|\=\s*)\Q$link\E(\"|\'|\s|\>)/$1$newlocation$2/; } } # -------------------------------------------------- Deal with Applet codebases @@ -2524,7 +2595,7 @@ sub submlink { if (!$symb) { $symb=$cursymb; } } if (!$symb) { $symb=&Apache::lonnet::symbread(); } - $symb=&Apache::lonnet::escape($symb); + $symb=&escape($symb); if ($target) { $target="target=\"$target\""; } return ' 'margin-top: 0px', @@ -2798,34 +2875,37 @@ sub bodytag { 'alink' => &designparm($function.'.alink',$domain), 'vlink' => &designparm($function.'.vlink',$domain), 'link' => &designparm($function.'.link',$domain),); - @$addentries{keys(%design)} = @design{keys(%design)}; + @design{keys(%$addentries)} = @$addentries{keys(%$addentries)}; # role and realm - my ($role,$realm) - =&Apache::lonnet::plaintext((split(/\./,$env{'request.role'}))[0]); + my ($role,$realm) = split(/\./,$env{'request.role'},2); + if ($role eq 'ca') { + my ($rdom,$rname) = ($realm =~ m-^/(\w+)/(\w+)$-); + $realm = &plainname($rname,$rdom).':'.$rdom; + } # realm if ($env{'request.course.id'}) { - $realm= - $env{'course.'.$env{'request.course.id'}.'.description'}; + if ($env{'request.role'} !~ /^cr/) { + $role = &Apache::lonnet::plaintext($role,&course_type()); + } + $realm = $env{'course.'.$env{'request.course.id'}.'.description'}; + } else { + $role = &Apache::lonnet::plaintext($role); } - unless ($realm) { $realm=' '; } + + if (!$realm) { $realm=' '; } # Set messages my $messages=&domainlogo($domain); # Port for miniserver my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'}; if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; } - my $extra_body_attr = &make_attr_string($forcereg,$addentries); + my $extra_body_attr = &make_attr_string($forcereg,\%design); # construct main body tag - my $bodytag = < -END + my $bodytag = "". + &Apache::lontexconvert::init_math_support(); - $bodytag .= &Apache::lontexconvert::init_math_support(); - - my $upperleft=''.$function.''; if ($bodyonly || ($env{'request.state'} eq 'construct' && $env{'environment.remote'} ne 'off' )) { @@ -2838,75 +2918,95 @@ END $bodytag.='

LON-CAPA: '.$title.'

'; } return $bodytag; - } elsif ($env{'environment.remote'} eq 'off') { -# No Remote - my $roleinfo=(< - - $env{'environment.firstname'} - $env{'environment.middlename'} - $env{'environment.lastname'} - $env{'environment.generation'} -   -
-$role  -
-$realm  + } + + my $name = &plainname($env{'user.name'},$env{'user.domain'}); + if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') { + undef($role); + } else { + $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'}); + } + + my $roleinfo=(< +
+ $name +   +
+
+$role  +
+
+$realm  +
ENDROLE - my $titleinfo = ''.$title.''; - if ($customtitle) { - $titleinfo = $customtitle; - } + my $titleinfo = ''.$title.''; + if ($customtitle) { + $titleinfo = $customtitle; + } + # + # Extra info if you are the DC + my $dc_info = ''; + if ($env{'user.adv'} && exists($env{'user.role.dc./'. + $env{'course.'.$env{'request.course.id'}. + '.domain'}.'/'})) { + my $cid = $env{'request.course.id'}; + $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'}; + $dc_info =~ s/\s+$//; + $dc_info = '('.$dc_info.')'; + } + + if ($env{'environment.remote'} eq 'off') { + # No Remote if ($env{'request.state'} eq 'construct') { + $forcereg=1; + } + + if (!$customtitle && $env{'request.state'} eq 'construct') { + # 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; - unless ($customtitle) { #this is for resources; directories have customtitle, and crumbs and select recent are created in lonpubdir.pm - my $parentpath = ''; - my $lastitem = ''; - if ($thisdisfn =~ m-(.+/)([^/]*)$-) { - $parentpath = $1; - $lastitem = $2; - } else { - $lastitem = $thisdisfn; - } - $titleinfo = &Apache::loncommon::help_open_menu('','','','',3,'Authoring'). - 'Construction Space: '. - '
' - .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv','','+1',1)."$lastitem
" - .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()') - .'
' - .&Apache::lonmenu::constspaceform(); - } - $forcereg=1; + my $parentpath = ''; + my $lastitem = ''; + if ($thisdisfn =~ m-(.+/)([^/]*)$-) { + $parentpath = $1; + $lastitem = $2; + } else { + $lastitem = $thisdisfn; + } + $titleinfo = + &Apache::loncommon::help_open_menu('','',3,'Authoring'). + 'Construction Space: '. + '
' + .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv','','+1',1)."$lastitem
" + .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()') + .'
' + .&Apache::lonmenu::constspaceform(); } + my $titletable; if (!$notitle) { $titletable = - ''. - ''.$roleinfo.'
'. - $titleinfo.'
'; + ''. + "".$roleinfo. + '
$titleinfo $dc_info
'; } - if ($env{'request.state'} eq 'construct') { - if ($notopbar) { - $bodytag .= $titletable; - } else { + if ($notopbar) { + $bodytag .= $titletable; + } else { + if ($env{'request.state'} eq 'construct') { $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg, $titletable); - } - } else { - if ($notopbar) { - $bodytag .= $titletable; } else { $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg). - $titletable; + $titletable; } } return $bodytag; @@ -2915,51 +3015,27 @@ ENDROLE # # Top frame rendering, Remote is up # - my $titleinfo = ' '.$title.''; - if ($customtitle) { - $titleinfo = $customtitle; - } - # - # Extra info if you are the DC - my $dc_info = ''; - if ($env{'user.adv'} && exists($env{'user.role.dc./'. - $env{'course.'.$env{'request.course.id'}. - '.domain'}.'/'})) { - my $cid = $env{'request.course.id'}; - $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'}; - $dc_info = '('.$dc_info.')'; - } + + my $upperleft=''.$function.''; + # Explicit link to get inline menu - my $menu='
 
'.&mt('Switch to Inline Menu Mode').''; + my $menu= ($no_inline_link?'' + :'
'.&mt('Switch to Inline Menu Mode').''); # if ($notitle) { return $bodytag; } return(< - -$upperleft -$messages  + + + - - + +$roleinfo - - - -
-$titleinfo $dc_info $menu - - - $env{'environment.firstname'} - $env{'environment.middlename'} - $env{'environment.lastname'} - $env{'environment.generation'} -   -
$titleinfo $dc_info $menu
-$role  -
$realm 

+ ENDBODY } @@ -3077,16 +3153,20 @@ sub standard_css { my $tabbg = &designparm($function.'.tabbg', $domain); my $font = &designparm($function.'.font', $domain); my $sidebg = &designparm($function.'.sidebg',$domain); - my $pgbg = $bgcolor || + my $pgbg_or_bgcolor = + $bgcolor || &designparm($function.'.pgbg', $domain); + my $pgbg = &designparm($function.'.pgbg', $domain); my $alink = &designparm($function.'.alink', $domain); my $vlink = &designparm($function.'.vlink', $domain); my $link = &designparm($function.'.link', $domain); my $sans = 'Arial,Helvetica,sans-serif'; + my $mono = 'monospace'; my $data_table_head = $tabbg; my $data_table_light = '#EEEEEE'; my $data_table_dark = '#DDD'; + my $data_table_darker = '#CCC'; my $data_table_highlight = '#FFFF00'; my $mail_new = '#FFBB77'; my $mail_new_hover = '#DD9955'; @@ -3096,38 +3176,91 @@ sub standard_css { my $mail_replied_hover = '#888855'; my $mail_other = '#99BBBB'; my $mail_other_hover = '#669999'; + my $table_header = '#DDDDDD'; + my $border = ($env{'browser.type'} eq 'explorer') ? '0px 2px 0px 2px' + : '0px 3px 0px 4px'; return < h1, h2, h3, th { font-family: $sans } a:focus { color: red; background: yellow } table.thinborder { border-collapse: collapse; } -table.thinborder tr th, table.thinborder tr td { border-style: solid; border-width: 1px} +table.thinborder tr th { border-style: solid; border-width: 1px; background: $tabbg;} +table.thinborder tr td { border-style: solid; border-width: 1px} + form, .inline { display: inline; } .center { text-align: center; } -.filename {font-family: monospace;} +.LC_filename {font-family: $mono;} .LC_error { color: red; font-size: larger; } +.LC_warning { + color: red; +} .LC_success { color: green; } +.LC_icon { + border: 0px; +} -table#LC_top_nav, table#LC_menubuttons, table#LC_nav_location { +table#LC_top_nav, table#LC_menubuttons { width: 100%; background: $pgbg; - border: 0px; - border-spacing: 1px; - padding: 0px; - margin: 0px; + border: 2px; border-collapse: separate; + padding: 0px; +} + +table#LC_title_bar, table.LC_breadcrumbs, table#LC_nav_location, +table#LC_title_bar.LC_with_remote { + width: 100%; + border-color: $pgbg; + border-style: solid; + border-width: $border; + + background: $pgbg; + font-family: $sans; + border-collapse: collapse; + padding: 0px; +} + +table.LC_docs_path { + width: 100%; + border: 0; + background: $pgbg; + font-family: $sans; + border-collapse: collapse; + padding: 0px; +} + +table#LC_title_bar td { + background: $tabbg; +} +table#LC_title_bar td.LC_title_bar_who { + background: $tabbg; + color: $font; + font: small $sans; + text-align: right; +} +span.LC_title_bar_title { + font: bold x-large $sans; +} +table#LC_title_bar td.LC_title_bar_domain_logo { + background: $sidebg; + text-align: right; + padding: 0px; +} +table#LC_title_bar td.LC_title_bar_role_logo { + background: $sidebg; + padding: 0px; } + table#LC_menubuttons_mainmenu { background: $pgbg; border: 0px; border-spacing: 1px; - padding: 0px; + padding: 0px 1px; margin: 0px; border-collapse: separate; } @@ -3136,11 +3269,45 @@ table#LC_menubuttons img, table#LC_menub } table#LC_top_nav td { background: $tabbg; + border: 0px; + font-size: small; } table#LC_top_nav td a, div#LC_top_nav a { color: $font; font-family: $sans; } +table#LC_top_nav td.LC_top_nav_logo { + background: $tabbg; + text-align: left; + white-space: nowrap; + width: 31px; +} +table#LC_top_nav td.LC_top_nav_logo img { + border: 0px; + vertical-align: bottom; +} +table#LC_top_nav td.LC_top_nav_exit, +table#LC_top_nav td.LC_top_nav_help { + width: 2.0em; +} +table.LC_breadcrumbs td, table.LC_docs_path td { + background: $tabbg; + color: $font; + font-family: $sans; + font-size: smaller; +} +table.LC_breadcrumbs td.LC_breadcrumbs_component, +table.LC_docs_path td.LC_docs_path_component { + background: $tabbg; + color: $font; + font-family: $sans; + font-size: larger; + text-align: right; +} +td.LC_table_cell_checkbox { + text-align: center; +} + .LC_menubuttons_inline_text { color: $font; font-family: $sans; @@ -3163,22 +3330,42 @@ td.LC_menubuttons_img { font-weight: bold; } +table.LC_aboutme_port { + border: 0px; + border-collapse: collapse; + border-spacing: 0px; +} table.LC_data_table, table.LC_mail_list { border: 1px solid #000000; - border-collapse: seperate; + border-collapse: separate; + border-spacing: 1px; +} +.LC_data_table_dense { + font-size: small; } table.LC_data_table tr th, table.LC_calendar tr th, table.LC_mail_list tr th { font-weight: bold; background-color: $data_table_head; + font-size: smaller; } -table.LC_data_table tr td { +table.LC_data_table tr td, +table.LC_aboutme_port tr td { background-color: $data_table_light; + padding: 2px; } -table.LC_data_table tr.LC_even_row td { +table.LC_data_table tr.LC_even_row td, +table.LC_aboutme_port tr.LC_even_row td { background-color: $data_table_dark; } -table.LC_data_table tr.LC_empty td { +table.LC_data_table tr.LC_data_table_highlight td { + background-color: $data_table_darker; +} +table.LC_data_table tr.LC_empty_row td { background-color: #FFFFFF; + font-weight: bold; + font-style: italic; + text-align: center; + padding: 8px; } table.LC_calendar { @@ -3223,7 +3410,250 @@ table.LC_mail_list tr.LC_mail_other { table.LC_mail_list tr.LC_mail_other:hover { background-color: $mail_other_hover; } - + +table#LC_portfolio_actions { + width: auto; + background: $pgbg; + border: 0px; + border-spacing: 2px 2px; + padding: 0px; + margin: 0px; + border-collapse: separate; +} +table#LC_portfolio_actions td.LC_label { + background: $tabbg; + text-align: right; +} +table#LC_portfolio_actions td.LC_value { + background: $tabbg; +} + +table#LC_cstr_controls { + width: 100%; + border-collapse: collapse; +} +table#LC_cstr_controls tr td { + border: 4px solid $pgbg; + padding: 4px; + text-align: center; + background: $tabbg; +} +table#LC_cstr_controls tr th { + border: 4px solid $pgbg; + background: $table_header; + text-align: center; + font-family: $sans; + font-size: smaller; +} + +table#LC_browser { + +} +table#LC_browser tr th { + background: $table_header; +} +table#LC_browser tr td { + padding: 2px; +} +table#LC_browser tr.LC_browser_file, +table#LC_browser tr.LC_browser_file_published { + background: #CCFF88; +} +table#LC_browser tr.LC_browser_file_locked, +table#LC_browser tr.LC_browser_file_unpublished { + background: #FFAA99; +} +table#LC_browser tr.LC_browser_file_obsolete { + background: #AAAAAA; +} +table#LC_browser tr.LC_browser_file_modified { + background: #FFFF77; +} +table#LC_browser tr.LC_browser_folder { + background: #CCCCFF; +} +span.LC_current_location { + font-size: x-large; + background: $pgbg; +} + +span.LC_parm_menu_item { + font-size: larger; + font-family: $sans; +} +span.LC_parm_scope_all { + color: red; +} +span.LC_parm_scope_folder { + color: green; +} +span.LC_parm_scope_resource { + color: orange; +} +span.LC_parm_part { + color: blue; +} +span.LC_parm_folder, span.LC_parm_symb { + font-size: x-small; + font-family: $mono; + color: #AAAAAA; +} + +td.LC_parm_overview_level_menu, td.LC_parm_overview_map_menu, +td.LC_parm_overview_parm_selectors, td.LC_parm_overview_parm_restrictions { + border: 1px solid black; + border-collapse: collapse; +} +table.LC_parm_overview_restrictions td { + border-width: 1px 4px 1px 4px; + border-style: solid; + border-color: $pgbg; + text-align: center; +} +table.LC_parm_overview_restrictions th { + background: $tabbg; + border-width: 1px 4px 1px 4px; + border-style: solid; + border-color: $pgbg; +} +table#LC_helpmenu { + border: 0px; + height: 55px; + border-spacing: 0px; +} + +table#LC_helpmenu fieldset legend { + font-size: larger; + font-weight: bold; +} +table#LC_helpmenu_links { + width: 100%; + border: 1px solid black; + background: $pgbg; + padding: 0px; + border-spacing: 1px; +} +table#LC_helpmenu_links tr td { + padding: 1px; + background: $tabbg; + text-align: center; + font-weight: bold; +} + +table#LC_helpmenu_links a:link, table#LC_helpmenu_links a:visited, +table#LC_helpmenu_links a:active { + text-decoration: none; + color: $font; +} +table#LC_helpmenu_links a:hover { + text-decoration: underline; + color: $vlink; +} + +.LC_chrt_popup_exists { + border: 1px solid #339933; + margin: -1px; +} +.LC_chrt_popup_up { + border: 1px solid yellow; + margin: -1px; +} +.LC_chrt_popup { + border: 1px solid #8888FF; + background: #CCCCFF; +} + +table.LC_pick_box { + width: 100%; + border-collapse: separate; + background: white; + border: 1px solid black; + border-spacing: 1px; +} +table.LC_pick_box td.LC_pick_box_title { + background: $tabbg; + font-weight: bold; + text-align: right; + width: 184px; + padding: 8px; +} +table.LC_pick_box td.LC_pick_box_separator { + padding: 0px; + height: 1px; + background: black; +} +table.LC_pick_box td.LC_pick_box_submit { + text-align: right; +} + +table.LC_group_priv_box { + background: white; + border: 1px solid black; + border-spacing: 1px; +} +table.LC_group_priv_box td.LC_pick_box_title { + background: $tabbg; + font-weight: bold; + text-align: right; + width: 184px; +} +table.LC_group_priv_box td.LC_groups_fixed { + background: $data_table_light; + text-align: center; +} +table.LC_group_priv_box td.LC_groups_optional { + background: $data_table_dark; + text-align: center; +} +table.LC_group_priv_box td.LC_groups_functionality { + background: $data_table_darker; + text-align: center; + font-weight: bold; +} +table.LC_group_priv td { + text-align: left; + padding: 0px; +} + +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-family: $sans; + font-weight: bold; + width: 100%; + background: $tabbg; + vertical-align: middle; + margin: 2ex 0ex 2ex 0ex; +} +.LC_topic_bar span { + vertical-align: middle; +} +.LC_topic_bar img { + vertical-align: bottom; +} +table.LC_course_group_status { + margin: 20px; +} +table.LC_status_selector td { + vertical-align: top; + text-align: center; + padding: 4px; +} +table.LC_descriptive_input td.LC_description { + vertical-align: top; + text-align: right; + font-weight: bold; +} + END } @@ -3240,8 +3670,10 @@ Inputs: $title - optional title for the $args - optional arguments force_register - if is true call registerurl so the remote is informed - redirect -> array ref of seconds before redirect occurs - url to redirect to + redirect -> array ref of + 1- seconds before redirect occurs + 2- url to redirect to + 3- whether the side effect should occur (side effect of setting $env{'internal.head.redirect'} to the url redirected too) @@ -3257,21 +3689,36 @@ Inputs: $title - optional title for the sub headtag { my ($title,$head_extra,$args) = @_; + my $function = $args->{'function'} || &get_users_function(); + my $domain = $args->{'domain'} || &determinedomain(); + my $bgcolor = $args->{'bgcolor'} || &designparm($function.'.pgbg',$domain); + my $url = join(':',$env{'user.name'},$env{'user.domain'}, + #time(), + $env{'environment.color.timestamp'}, + $function,$domain,$bgcolor); + + $url = '/adm/css/'.&escape($url).'.css'; + my $result = ''. - &standard_css($args->{'function'},$args->{'domain'}, - $args->{'bgcolor'}). &font_settings(). &Apache::lonhtmlcommon::htmlareaheaders(); if ($args->{'force_register'}) { $result .= &Apache::lonmenu::registerurl(1); } + if (!$args->{'no_nav_bar'} + && !$args->{'only_body'} + && !$args->{'frameset'}) { + $result .= &help_menu_js(); + } if (ref($args->{'redirect'})) { - my ($time,$url) = @{$args->{'redirect'}}; + my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}}; $url = &Apache::lonenc::check_encrypt($url); - $env{'internal.head.redirect'} = $url; + if (!$inhibit_continue) { + $env{'internal.head.redirect'} = $url; + } $result.=< @@ -3281,7 +3728,9 @@ ADDMETA $title = 'The LearningOnline Network with CAPA'; } - $result .= ' LON-CAPA '.&mt($title).''.$head_extra; + $result .= ' LON-CAPA '.&mt($title).'' + .'' + .$head_extra; return $result; } @@ -3373,6 +3822,7 @@ Returns a uniform complete .. + =back =cut @@ -3419,6 +3869,9 @@ Inputs: $title - optional title for the 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 + =back =cut @@ -3428,7 +3881,7 @@ sub start_page { #&Apache::lonnet::logthis("start_page ".join(':',caller(0))); my %head_args; foreach my $arg ('redirect','force_register','domain','function', - 'bgcolor') { + 'bgcolor','frameset','no_nav_bar','only_body') { if (defined($args->{$arg})) { $head_args{$arg} = $args->{$arg}; } @@ -3454,7 +3907,7 @@ sub start_page { $args->{'only_body'}, $args->{'domain'}, $args->{'force_register'}, $args->{'body_title'}, $args->{'no_nav_bar'}, $args->{'bgcolor'}, - $args->{'no_title'}); + $args->{'no_title'}, $args->{'no_inline_link'}); } } @@ -3483,13 +3936,11 @@ Inputs: $args - additional optio a html attribute frameset -> if true will start with a rather than -=back =cut sub end_page { my ($args) = @_; - #&Apache::lonnet::logthis("end_page ".join(':',caller(0))); $env{'internal.end_page'}++; my $result; if ($args->{'discussion'}) { @@ -3532,7 +3983,7 @@ sub js_ready { $result =~ s/[\n\r]/ /xmsg; $result =~ s/\\/\\\\/xmsg; $result =~ s/'/\\'/xmsg; - $result =~ s{}{}xmsg; + $result =~ s{'; + return ''."\n"; } sub end_data_table { undef($row_count); - return '
'; + return ''."\n";; } sub start_data_table_row { + my ($add_class) = @_; $row_count++; - return ''; + my $css_class = ($row_count % 2)?'':'LC_even_row'; + $css_class = (join(' ',$css_class,$add_class)); + return ''."\n";; } sub end_data_table_row { - return ''; + return ''."\n";; + } + + sub start_data_table_empty_row { + $row_count++; + return ''."\n";; + } + + sub end_data_table_empty_row { + return ''."\n";; + } + + sub start_data_table_header_row { + return ''."\n";; + } + + sub end_data_table_header_row { + return ''."\n";; } } @@ -3601,9 +4074,7 @@ sub simple_error_page { =pod -=over 4 - -=item get_users_function +=item * &get_users_function() Used by &bodytag to determine the current users primary role. Returns either 'student','coordinator','admin', or 'author'. @@ -3630,14 +4101,14 @@ sub get_users_function { =pod -=item check_user_status +=item * &check_user_status Determines current status of supplied role for a specific user. Roles can be active, previous or future. Inputs: user's domain, user's username, course's domain, -course's number, optional section/group. +course's number, optional section ID. Outputs: role status: active, previous or future. @@ -3645,33 +4116,35 @@ role status: active, previous or future. =cut sub check_user_status { - my ($udom,$uname,$cdom,$crs,$role,$secgrp) = @_; + my ($udom,$uname,$cdom,$crs,$role,$sec) = @_; my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname); my @uroles = keys %userinfo; my $srchstr; my $active_chk = 'none'; + my $now = time; if (@uroles > 0) { - if (($role eq 'cc') || ($secgrp eq '') || (!defined($secgrp))) { + if (($role eq 'cc') || ($sec eq '') || (!defined($sec))) { $srchstr = '/'.$cdom.'/'.$crs.'_'.$role; } else { - $srchstr = '/'.$cdom.'/'.$crs.'/'.$secgrp.'_'.$role; } - if (grep/^$srchstr$/,@uroles) { + $srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role; + } + if (grep/^\Q$srchstr\E$/,@uroles) { my $role_end = 0; my $role_start = 0; $active_chk = 'active'; - if ($userinfo{$srchstr} =~ m/^($role)_(\d+)/) { - $role_end = $2; - if ($userinfo{$srchstr} =~ m/^($role)_($role_end)_(\d+)$/) { - $role_start = $3; + if ($userinfo{$srchstr} =~ m/^\Q$role\E_(\d+)/) { + $role_end = $1; + if ($userinfo{$srchstr} =~ m/^\Q$role\E_\Q$role_end\E_(\d+)$/) { + $role_start = $1; } } if ($role_start > 0) { - if (time < $role_start) { + if ($now < $role_start) { $active_chk = 'future'; } } if ($role_end > 0) { - if (time > $role_end) { + if ($now > $role_end) { $active_chk = 'previous'; } } @@ -3684,36 +4157,68 @@ sub check_user_status { =pod -=item get_sections +=item * &get_sections() Determines all the sections for a course including sections with students and sections containing other roles. -Incoming parameters: domain, course number, reference to -section hash (keys to be section/group IDs), reference to -array containing roles for which sections should be gathered -(optional). If the fourth argument is undefined, sections -are gathered for any role. +Incoming parameters: + +1. domain +2. course number +3. reference to array containing roles for which sections should +be gathered (optional). +4. reference to array containing status types for which sections +should be gathered (optional). + +If the third argument is undefined, sections are gathered for any role. +If the fourth argument is undefined, sections are gathered for any status. +Permissible values are 'active' or 'future' or 'previous'. -Returns number of sections. +Returns section hash (keys are section IDs, values are +number of users in each section), subject to the +optional roles filter, optional status filter =cut ############################################### sub get_sections { - my ($cdom,$cnum,$sectioncount,$possible_roles) = @_; - if (!($cdom && $cnum)) { return 0; } - my $numsections = 0; + my ($cdom,$cnum,$possible_roles,$possible_status) = @_; + if (!defined($cdom) || !defined($cnum)) { + my $cid = $env{'request.course.id'}; + + return if (!defined($cid)); + + $cdom = $env{'course.'.$cid.'.domain'}; + $cnum = $env{'course.'.$cid.'.num'}; + } + + my %sectioncount; + my $now = time; - if (!defined($possible_roles) || (grep/^st$/,@$possible_roles)) { + if (!defined($possible_roles) || (grep(/^st$/,@$possible_roles))) { my ($classlist) = &Apache::loncoursedata::get_classlist($cdom,$cnum); my $sec_index = &Apache::loncoursedata::CL_SECTION(); my $status_index = &Apache::loncoursedata::CL_STATUS(); - while (my ($student,$data) = each %$classlist) { - my ($section,$status) = ($data->[$sec_index], - $data->[$status_index]); - unless ($section eq '-1' || $section =~ /^\s*$/) { - if (!defined($$sectioncount{$section})) { $numsections++; } - $$sectioncount{$section}++; + my $start_index = &Apache::loncoursedata::CL_START(); + my $end_index = &Apache::loncoursedata::CL_END(); + my $status; + while (my ($student,$data) = each(%$classlist)) { + my ($section,$stu_status,$start,$end) = ($data->[$sec_index], + $data->[$status_index], + $data->[$start_index], + $data->[$end_index]); + if ($stu_status eq 'Active') { + $status = 'active'; + } elsif ($end < $now) { + $status = 'previous'; + } elsif ($start > $now) { + $status = 'future'; + } + if ($section ne '-1' && $section !~ /^\s*$/) { + if ((!defined($possible_status)) || (($status ne '') && + (grep/^\Q$status\E$/,@{$possible_status}))) { + $sectioncount{$section}++; + } } } } @@ -3722,172 +4227,41 @@ sub get_sections { if ($user !~ /^(\w{2})/) { next; } my ($role) = ($user =~ /^(\w{2})/); if ($possible_roles && !(grep(/^$role$/,@$possible_roles))) { next; } - my $section; + my ($section,$status); if ($role eq 'cr' && $user =~ m-^$role/[^/]*/[^/]*/[^/]*:[^:]*:[^:]*:(\w+)-) { $section=$1; } if ($user =~ /^$role:[^:]*:[^:]*:(\w+)/) { $section=$1; } if (!defined($section) || $section eq '-1') { next; } - if (!defined($$sectioncount{$section})) { $numsections++; } - $$sectioncount{$section}++; - } - return $numsections; -} - -############################################### - -=pod - -=item coursegroups - -Retrieve information about groups in a course, - -Input: -1. Reference to hash to populate with group information. -2. Optional course domain -3. Optional course number -4. Optional group name - -Course domain and number will be taken from user's -environment if not supplied. Optional group name will' -be passed to lonnet::get_coursegroups() as a regexp to -use in the call to the dump function. - -Output -Returns number of groups in the course (subject to the -optional group name filter). - -Side effects: -Populates the referenced curr_groups hash, with key, -value pairs. Keys are group names, corresponding values -are scalars containing group information in XML. This -can be sent to &get_group_settings() to be parsed. - -=cut - -############################################### - -sub coursegroups { - my ($curr_groups,$cdom,$cnum,$group) = @_; - my $numgroups; - if (!defined($cdom) || !defined($cnum)) { - my $cid = $env{'request.course.id'}; - $cdom = $env{'course.'.$cid.'.domain'}; - $cnum = $env{'course.'.$cid.'.num'}; - } - %{$curr_groups} = &Apache::lonnet::get_coursegroups($cdom,$cnum,$group); - my ($tmp) = keys(%{$curr_groups}); - if ($tmp=~/^error:/) { - unless ($tmp eq 'error: 2 tie(GDBM) Failed while attempting dump') { - &logthis('Error retrieving groups: '.$tmp.' in '.$cnum.':'. - $cdom); + my ($end,$start) = ($courseroles{$user} =~ /^([^:]*):([^:]*)$/); + if ($end == -1 && $start == -1) { + next; #deleted role } - $numgroups = 0; - } else { - $numgroups = keys(%{$curr_groups}); - } - return $numgroups; -} - -############################################### - -=pod - -=item get_group_settings - -Uses TokeParser to extract group information from the -XML used to describe course groups. - -Input: -Scalar containing XML - as retrieved from &coursegroups(). - -Output: -Hash containing group information as key=values for (a), and -hash of hashes for (b) - -Keys (in two categories): -(a) groupname, creator, creation, modified, startdate,enddate. -Corresponding values are name of the group, creator of the group -(username:domain), UNIX time for date group was created, and -settings were last modified, and default start and end access -times for group members. - -(b) functions returned in hash of hashes. -Outer hash key is functions. -Inner hash keys are chat,discussion,email,files,homepage,roster. -Corresponding values are either on or off, depending on -whether this type of functionality is available for the group. - -=cut - -############################################### - -sub get_group_settings { - my ($groupinfo)=@_; - my $parser=HTML::TokeParser->new(\$groupinfo); - my $token; - my $tool = ''; - my $role = ''; - my %content=(); - while ($token=$parser->get_token) { - if ($token->[0] eq 'S') { - my $entry=$token->[1]; - if ($entry eq 'functions' || $entry eq 'autosec') { - %{$content{$entry}} = (); - $tool = $entry; - } elsif ($entry eq 'role') { - if ($tool eq 'autosec') { - $role = $token->[2]{id}; - } - } else { - my $value=$parser->get_text('/'.$entry); - if ($entry eq 'name') { - if ($tool eq 'functions') { - my $function = $token->[2]{id}; - $content{$tool}{$function} = $value; - } - } elsif ($entry eq 'groupname') { - $content{$entry}=&Apache::lonnet::unescape($value); - } elsif (($entry eq 'roles') || ($entry eq 'types') || - ($entry eq 'sectionpick') || ($entry eq 'defpriv')) { - push(@{$content{$entry}},$value); - } elsif ($entry eq 'section') { - if ($tool eq 'autosec' && $role ne '') { - push(@{$content{$tool}{$role}},$value); - } - } else { - $content{$entry}=$value; - } + if (!defined($possible_status)) { + $sectioncount{$section}++; + } else { + if ((!$end || $end >= $now) && (!$start || $start <= $now)) { + $status = 'active'; + } elsif ($end < $now) { + $status = 'future'; + } elsif ($start > $now) { + $status = 'previous'; } - } elsif ($token->[0] eq 'E') { - if ($token->[1] eq 'functions' || $token->[1] eq 'autosec') { - $tool = ''; - } elsif ($token->[1] eq 'role') { - $role = ''; + if (($status ne '') && (grep/^\Q$status\E$/,@{$possible_status})) { + $sectioncount{$section}++; } - } } - return %content; -} - -sub check_group_access { - my ($group) = @_; - my $access = 1; - my $now = time; - my ($start,$end) = split(/\./,$env{'user.role.gr/'.$env{'request.course,id'}.'/'.$group}); - if (($end!=0) && ($end<$now)) { $access = 0; } - if (($start!=0) && ($start>$now)) { $access=0; } - return $access; + return %sectioncount; } ############################################### =pod - -=item get_course_users - + +=item * &get_course_users() + Retrieves usernames:domains for users in the specified course with specific role(s), and access status. @@ -3910,12 +4284,13 @@ Entries for end, start, section and stat of the possibility of multiple values for non-student roles. =cut - + ############################################### - + sub get_course_users { my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata) = @_; my %idx = (); + my %seclists; $idx{udom} = &Apache::loncoursedata::CL_SDOM(); $idx{uname} = &Apache::loncoursedata::CL_SNAME(); @@ -3931,12 +4306,28 @@ sub get_course_users { my $now = time; foreach my $student (keys(%{$classlist})) { my $match = 0; + my $secmatch = 0; + my $section = $$classlist{$student}[$idx{section}]; + if ($section eq '') { + $section = 'none'; + } if ((ref($sections) eq 'ARRAY') && (@{$sections} > 0)) { - unless(grep(/^\Q$$classlist{$student}[$idx{section}]\E$/, - @{$sections})) { - next; + if (grep(/^all$/,@{$sections})) { + $secmatch = 1; + } elsif ($$classlist{$student}[$idx{section}] eq '') { + if (grep(/^none$/,@{$sections})) { + $secmatch = 1; + } + } else { + if (grep(/^\Q$section\E$/,@{$sections})) { + $secmatch = 1; + } } - } + if (!$secmatch) { + next; + } + } + push(@{$seclists{$student}},$section); if (defined($$types{'active'})) { if ($$classlist{$student}[$idx{status}] eq 'Active') { push(@{$$users{st}{$student}},'active'); @@ -3955,36 +4346,69 @@ sub get_course_users { $match = 1; } } - if ($match && defined($userdata)) { + if ($match && ref($userdata) eq 'HASH') { $$userdata{$student} = $$classlist{$student}; } } } - if ((@{$roles} > 0) && (@{$roles} ne "st")) { - my @coursepersonnel = &Apache::lonnet::getkeys('nohist_userroles',$cdom,$cnum); - foreach my $person (@coursepersonnel) { + if ((@{$roles} > 1) || ((@{$roles} == 1) && ($$roles[0] ne "st"))) { + my %coursepersonnel = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum); + my $now = time; + foreach my $person (sort(keys(%coursepersonnel))) { my $match = 0; - my ($role,$user) = ($person =~ /^([^:]*):([^:]+:[^:]+)/); + my $secmatch = 0; + my $status; + my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/); $user =~ s/:$//; - if (($role) && (grep(/^\Q$role\E$/,@{$roles}))) { - my ($uname,$udom,$usec) = split(/:/,$user); - if ($usec ne '' && (ref($sections) eq 'ARRAY') && - @{$sections} > 0) { - unless(grep(/^\Q$usec\E$/,@{$sections})) { - next; - } + my ($end,$start) = split(/:/,$coursepersonnel{$person}); + if ($end == -1 || $start == -1) { + next; + } + if (($role) && ((grep(/^\Q$role\E$/,@{$roles})) || + (grep(/^cr$/,@{$roles}) && $role =~ /^cr\//))) { + my ($uname,$udom) = split(/:/,$user); + if ((ref($sections) eq 'ARRAY') && (@{$sections} > 0)) { + if (grep(/^all$/,@{$sections})) { + $secmatch = 1; + } elsif ($usec eq '') { + if (grep(/^none$/,@{$sections})) { + $secmatch = 1; + } + } else { + if (grep(/^\Q$usec\E$/,@{$sections})) { + $secmatch = 1; + } + } + if (!$secmatch) { + next; + } + } + if ($usec eq '') { + $usec = 'none'; } if ($uname ne '' && $udom ne '') { - my $status = &check_user_status($udom,$uname,$cdom,$cnum,$role); + if ($end < $now) { + $status = 'previous'; + } elsif ($start > $now) { + $status = 'future'; + } else { + $status = 'active'; + } foreach my $type (keys(%{$types})) { if ($status eq $type) { - @{$$users{$role}{$user}} = $type; + if (!grep(/^\Q$type\E$/,@{$$users{$role}{$user}})) { + push(@{$$users{$role}{$user}},$type); + } $match = 1; } } - if ($match && defined($userdata) && - !exists($$userdata{$uname.':'.$udom})) { - &get_user_info($udom,$uname,\%idx,$userdata); + if (($match) && (ref($userdata) eq 'HASH')) { + if (!exists($$userdata{$uname.':'.$udom})) { + &get_user_info($udom,$uname,\%idx,$userdata); + } + if (!grep(/^\Q$usec\E$/,@{$seclists{$uname.':'.$udom}})) { + push(@{$seclists{$uname.':'.$udom}},$usec); + } } } } @@ -3994,14 +4418,24 @@ sub get_course_users { my %csettings = &Apache::lonnet::get('environment',['internal.courseowner'],$cdom,$cnum); if ( defined($csettings{'internal.courseowner'}) ) { my $owner = $csettings{'internal.courseowner'}; - @{$$users{'ow'}{$owner.':'.$cdom}} = 'any'; + if ($owner !~ /^[^:]+:[^:]+$/) { + $owner = $owner.':'.$cdom; + } + @{$$users{'ow'}{$owner}} = 'any'; if (defined($userdata) && !exists($$userdata{$owner.':'.$cdom})) { &get_user_info($cdom,$owner,\%idx,$userdata); + if (!grep(/^none$/,@{$seclists{$owner.':'.$cdom}})) { + push(@{$seclists{$owner.':'.$cdom}},'none'); + } } } } } + foreach my $user (keys(%seclists)) { + @{$seclists{$user}} = (sort {$a <=> $b} @{$seclists{$user}}); + $$userdata{$user}[$idx{section}] = join(',',@{$seclists{$user}}); + } } return; } @@ -4015,6 +4449,43 @@ sub get_user_info { return; } +sub get_secgrprole_info { + my ($cdom,$cnum,$needroles,$type) = @_; + my %sections_count = &get_sections($cdom,$cnum); + my @sections = (sort {$a <=> $b} keys(%sections_count)); + my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum); + my @groups = sort(keys(%curr_groups)); + my $allroles = []; + my $rolehash; + my $accesshash = { + active => 'Currently has access', + future => 'Will have future access', + previous => 'Previously had access', + }; + if ($needroles) { + $rolehash = {'all' => 'all'}; + my %user_roles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum); + if (&Apache::lonnet::error(%user_roles)) { + undef(%user_roles); + } + foreach my $item (keys(%user_roles)) { + my ($role)=split(/\:/,$item,2); + if ($role eq 'cr') { next; } + if ($role =~ /^cr/) { + $$rolehash{$role} = (split('/',$role))[3]; + } else { + $$rolehash{$role} = &Apache::lonnet::plaintext($role,$type); + } + } + foreach my $key (sort(keys(%{$rolehash}))) { + push(@{$allroles},$key); + } + push (@{$allroles},'st'); + $$rolehash{'st'} = &Apache::lonnet::plaintext('st',$type); + } + return (\@sections,\@groups,$allroles,$rolehash,$accesshash); +} + =pod =item * get_unprocessed_cgi($query,$possible_names) @@ -4033,9 +4504,9 @@ will result in $env{'form.uname'} and $e sub get_unprocessed_cgi { my ($query,$possible_names)= @_; # $Apache::lonxml::debug=1; - foreach (split(/&/,$query)) { - my ($name, $value) = split(/=/,$_); - $name = &Apache::lonnet::unescape($name); + foreach my $pair (split(/&/,$query)) { + my ($name, $value) = split(/=/,$pair); + $name = &unescape($name); if (!defined($possible_names) || (grep {$_ eq $name} @$possible_names)) { $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; @@ -4251,8 +4722,7 @@ sub record_sep { if ($env{'form.upfiletype'} eq 'xml') { } elsif ($env{'form.upfiletype'} eq 'space') { my $i=0; - foreach (split(/\s+/,$record)) { - my $field=$_; + foreach my $field (split(/\s+/,$record)) { $field=~s/^(\"|\')//; $field=~s/(\"|\')$//; $components{&takeleft($i)}=$field; @@ -4260,8 +4730,7 @@ sub record_sep { } } elsif ($env{'form.upfiletype'} eq 'tab') { my $i=0; - foreach (split(/\t/,$record)) { - my $field=$_; + foreach my $field (split(/\t/,$record)) { $field=~s/^(\"|\')//; $field=~s/(\"|\')$//; $components{&takeleft($i)}=$field; @@ -4355,14 +4824,14 @@ sub csv_print_samples { my $samples = &get_samples($records,3); $r->print(&mt('Samples').'
'); - foreach (sort({$a <=> $b} keys(%{ $samples->[0] }))) { - $r->print(''); } + foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { + $r->print(''); } $r->print(''); foreach my $hash (@$samples) { $r->print(''); - foreach (sort({$a <=> $b} keys(%{ $samples->[0] }))) { + foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) { $r->print(''); } $r->print(''); @@ -4395,17 +4864,17 @@ sub csv_print_select_table { '
'.&mt('Column [_1]',($_+1)).''.&mt('Column [_1]',($sample+1)).'
'); - if (defined($$hash{$_})) { $r->print($$hash{$_}); } + if (defined($$hash{$sample})) { $r->print($$hash{$sample}); } $r->print('
'. ''. ''."\n"); - foreach (@$d) { - my ($value,$display,$defaultcol)=@{ $_ }; + foreach my $array_ref (@$d) { + my ($value,$display,$defaultcol)=@{ $array_ref }; $r->print(''); $r->print(''."\n"); $i++; @@ -4666,9 +5135,9 @@ sub DrawBarGraph { $Title = '' if (! defined($Title)); $xlabel = '' if (! defined($xlabel)); $ylabel = '' if (! defined($ylabel)); - $ValuesHash{$id.'.title'} = &Apache::lonnet::escape($Title); - $ValuesHash{$id.'.xlabel'} = &Apache::lonnet::escape($xlabel); - $ValuesHash{$id.'.ylabel'} = &Apache::lonnet::escape($ylabel); + $ValuesHash{$id.'.title'} = &escape($Title); + $ValuesHash{$id.'.xlabel'} = &escape($xlabel); + $ValuesHash{$id.'.ylabel'} = &escape($ylabel); $ValuesHash{$id.'.y_max_value'} = $Max; $ValuesHash{$id.'.NumBars'} = $NumBars; $ValuesHash{$id.'.NumSets'} = $NumSets; @@ -4748,9 +5217,9 @@ sub DrawXYGraph { $ylabel = '' if (! defined($ylabel)); my %ValuesHash = ( - $id.'.title' => &Apache::lonnet::escape($Title), - $id.'.xlabel' => &Apache::lonnet::escape($xlabel), - $id.'.ylabel' => &Apache::lonnet::escape($ylabel), + $id.'.title' => &escape($Title), + $id.'.xlabel' => &escape($xlabel), + $id.'.ylabel' => &escape($ylabel), $id.'.y_max_value'=> $Max, $id.'.labels' => join(',',@$Xlabels), $id.'.PlotType' => 'XY', @@ -4845,9 +5314,9 @@ sub DrawXYYGraph { $ylabel = '' if (! defined($ylabel)); my %ValuesHash = ( - $id.'.title' => &Apache::lonnet::escape($Title), - $id.'.xlabel' => &Apache::lonnet::escape($xlabel), - $id.'.ylabel' => &Apache::lonnet::escape($ylabel), + $id.'.title' => &escape($Title), + $id.'.xlabel' => &escape($xlabel), + $id.'.ylabel' => &escape($ylabel), $id.'.labels' => join(',',@$Xlabels), $id.'.PlotType' => 'XY', $id.'.NumSets' => 2, @@ -4919,7 +5388,7 @@ Inputs: sub chartlink { my ($linktext, $sname, $sdomain) = @_; my $link = ''.$linktext.''; } @@ -4949,6 +5418,7 @@ a hash ref describing the data to be sto 'chartoutputmode' => 'scalar', 'chartoutputdata' => 'scalar', 'Section' => 'array', + 'Group' => 'array', 'StudentData' => 'array', 'Maps' => 'array'); @@ -4982,11 +5452,11 @@ sub store_course_settings { if (ref($env{'form.'.$setting})) { $stored_form = join(',', map { - &Apache::lonnet::escape($_); + &escape($_); } sort(@{$env{'form.'.$setting}})); } else { $stored_form = - &Apache::lonnet::escape($env{'form.'.$setting}); + &escape($env{'form.'.$setting}); } # Determine if the array contents are the same. if ($stored_form ne $env{$envname}) { @@ -5020,7 +5490,7 @@ sub restore_course_settings { } elsif ($type eq 'array') { $env{'form.'.$setting} = [ map { - &Apache::lonnet::unescape($_); + &unescape($_); } split(',',$env{$envname}) ]; } @@ -5031,15 +5501,26 @@ sub restore_course_settings { ############################################################ ############################################################ -sub propath { - my ($udom,$uname)=@_; - $udom=~s/\W//g; - $uname=~s/\W//g; - my $subdir=$uname.'__'; - $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/; - my $proname="$Apache::lonnet::perlvar{'lonUsersDir'}/$udom/$subdir/$uname"; - return $proname; -} +sub course_type { + my ($cid) = @_; + if (!defined($cid)) { + $cid = $env{'request.course.id'}; + } + if (defined($env{'course.'.$cid.'.type'})) { + return $env{'course.'.$cid.'.type'}; + } else { + return 'Course'; + } +} + +sub group_term { + my $crstype = &course_type(); + my %names = ( + 'Course' => 'group', + 'Group' => 'team', + ); + return $names{$crstype}; +} sub icon { my ($file)=@_; @@ -5093,7 +5574,7 @@ sub escape_double { sub escape_url { my ($url) = @_; my @urlslices = split(/\//, $url,-1); - my $lastitem = &Apache::lonnet::escape(pop(@urlslices)); + my $lastitem = &escape(pop(@urlslices)); return join('/',@urlslices).'/'.$lastitem; } =pod
'.&mt('Attribute').''.&mt('Column').'
'.$display.'