--- loncom/interface/loncommon.pm 2006/06/30 01:21:36 1.410 +++ loncom/interface/loncommon.pm 2006/07/19 11:30:36 1.434 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.410 2006/06/30 01:21:36 albertel Exp $ +# $Id: loncommon.pm,v 1.434 2006/07/19 11:30:36 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -706,8 +706,68 @@ sub helpLatexCheatsheet { .''; } +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'; + } + 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 my $datum (\$topic,\$component_help,\$faq,\$bug,\$origurl) { + $$datum = &escape($$datum); + } + + 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) = @_; + 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 $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) = @_; + + my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height); + $text = "" if (not defined $text); $stayOnPage = 0 if (not defined $stayOnPage); if ($env{'browser.interface'} eq 'textual' || @@ -718,25 +778,15 @@ sub help_open_menu { $height = 600 if (not defined $height); my $link=''; my $title = &mt('Get help'); - my $origurl = $ENV{'REQUEST_URI'}; - $origurl=~s|^/~|/priv/|; - my $timestamp = time; - foreach my $datum (\$topic,\$component_help,\$faq,\$bug,\$origurl) { - $$datum = &escape($$datum); - } - if (!$stayOnPage) { - $link = "javascript:helpMenu('open')"; + if ($stayOnPage) { + $link = "javascript:helpMenu('display')"; } else { - $link = "javascript:helpMenu('display')"; + $link = "javascript:helpMenu('open')"; } - my $banner_link = "/adm/helpmenu?page=banner&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage"; - my $details_link = "/adm/helpmenu?page=body&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp"; + my $helptopic=&general_help(); + my $banner_link = &update_help_link($topic,$component_help,$faq,$bug,$stayOnPage); + my $details_link = '/adm/help/'.$helptopic.'.hlp'; my $template; - if ($text ne "") { - $template .= - "". - "
$text"; - } my $nothing=&Apache::lonhtmlcommon::javascript_nothing(); my $helpicon=&lonhttpdurl("/adm/lonIcons/helpgateway.gif"); my $start_page = @@ -754,6 +804,7 @@ sub help_open_menu { - (Help Menu) +$banner_link + $text ENDTEMPLATE - if ($component_help) { - if (!$text) { - $template=&help_open_topic($component_help,undef,$stayOnPage, - $width,$height).' '.$template; - } else { - my $help_text; - $help_text=&unescape($topic); - $template='
'. - &help_open_topic($component_help,$help_text,$stayOnPage, - $width,$height).''.$template. - '
'; - } - } - if ($text ne '') { $template.='
' }; return $template; } @@ -1918,12 +1956,20 @@ sub get_related_words { return (); } my @Words=(); + my $count=0; if (exists($thesaurus_db{$keyword})) { # The first element is the number of times # the word appears. We do not need it now. - (undef,@Words) = (split(/:/,$thesaurus_db{$keyword})); - for (my $i=0;$i<=$#Words;$i++) { - ($Words[$i],undef)= split(/\,/,$Words[$i]); + 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; @@ -2002,6 +2048,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) { @@ -2839,6 +2888,7 @@ sub bodytag { } else { $role = &Apache::lonnet::plaintext($role); } + if (!$realm) { $realm=' '; } # Set messages my $messages=&domainlogo($domain); @@ -2867,6 +2917,11 @@ sub bodytag { } 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=(< @@ -3107,6 +3162,7 @@ sub standard_css { 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'; @@ -3124,7 +3180,9 @@ sub standard_css { 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; } .LC_filename {font-family: $mono;} @@ -3175,11 +3233,11 @@ table#LC_title_bar td { table#LC_title_bar td.LC_title_bar_who { background: $tabbg; color: $font; - font: medium $sans; + font: small $sans; text-align: right; } span.LC_title_bar_title { - font: bold xx-large $sans; + font: bold x-large $sans; } table#LC_title_bar td.LC_title_bar_domain_logo { background: $sidebg; @@ -3213,21 +3271,25 @@ table#LC_top_nav td a, div#LC_top_nav a } table#LC_top_nav td.LC_top_nav_logo { background: $tabbg; - text-align: right; + text-align: left; white-space: nowrap; - font-weight: bold; + width: 31px; } table#LC_top_nav td.LC_top_nav_logo img { - margin-left: 0.2em; + 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_breadcrumb_component, +table.LC_breadcrumbs td.LC_breadcrumbs_component, table.LC_docs_path td.LC_docs_path_component { background: $tabbg; color: $font; @@ -3264,19 +3326,32 @@ td.LC_menubuttons_img { table.LC_data_table, table.LC_mail_list { border: 1px solid #000000; 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 { background-color: $data_table_light; + padding: 2px; } table.LC_data_table 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 { @@ -3461,6 +3536,110 @@ table#LC_helpmenu_links a:hover { 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 } @@ -3477,8 +3656,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) @@ -3497,15 +3678,15 @@ sub headtag { 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'}, + 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 = ''. - ''. &font_settings(). &Apache::lonhtmlcommon::htmlareaheaders(); @@ -3514,9 +3695,11 @@ sub headtag { } 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.=< @@ -3526,7 +3709,9 @@ ADDMETA $title = 'The LearningOnline Network with CAPA'; } - $result .= ' LON-CAPA '.&mt($title).''.$head_extra; + $result .= ' LON-CAPA '.&mt($title).'' + .'' + .$head_extra; return $result; } @@ -3825,8 +4010,10 @@ sub simple_error_page { { my $row_count; sub start_data_table { + my ($add_class) = @_; + my $css_class = (join(' ','LC_data_table',$add_class)); undef($row_count); - return ''."\n"; + return '
'."\n"; } sub end_data_table { @@ -3835,14 +4022,26 @@ sub simple_error_page { } sub start_data_table_row { + my ($add_class) = @_; $row_count++; - return ''."\n";; + my $css_class = ($row_count % 2)?'':'LC_even_row'; + $css_class = (join(' ',$css_class,$add_class)); + return ''."\n";; } sub end_data_table_row { 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";; } @@ -3898,33 +4097,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'; } } @@ -3941,20 +4142,28 @@ sub check_user_status { Determines all the sections for a course including sections with students and sections containing other roles. -Incoming parameters: domain, course number, -reference to array containing roles for which sections should -be gathered (optional). If the third 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 section hash (keys are section IDs, values are number of users in each section), subject to the -optional roles filter. +optional roles filter, optional status filter =cut ############################################### sub get_sections { - my ($cdom,$cnum,$possible_roles) = @_; + my ($cdom,$cnum,$possible_roles,$possible_status) = @_; if (!defined($cdom) || !defined($cnum)) { my $cid = $env{'request.course.id'}; @@ -3965,16 +4174,32 @@ sub get_sections { } my %sectioncount; + my $now = time; 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(); + my $start_index = &Apache::loncoursedata::CL_START(); + my $end_index = &Apache::loncoursedata::CL_END(); + my $status; while (my ($student,$data) = each(%$classlist)) { - my ($section,$status) = ($data->[$sec_index], - $data->[$status_index]); - unless ($section eq '-1' || $section =~ /^\s*$/) { - $sectioncount{$section}++; + 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}++; + } } } } @@ -3983,14 +4208,31 @@ 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; } - $sectioncount{$section}++; + my ($end,$start) = ($courseroles{$user} =~ /^([^:]*):([^:]*)$/); + if ($end == -1 && $start == -1) { + next; #deleted role + } + 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'; + } + if (($status ne '') && (grep/^\Q$status\E$/,@{$possible_status})) { + $sectioncount{$section}++; + } + } } return %sectioncount; } @@ -4029,6 +4271,7 @@ of the possibility of multiple values fo 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(); @@ -4044,12 +4287,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'); @@ -4068,36 +4327,57 @@ 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")) { + if ((@{$roles} > 1) || ((@{$roles} == 1) && ($$roles[0] ne "st"))) { my @coursepersonnel = &Apache::lonnet::getkeys('nohist_userroles',$cdom,$cnum); foreach my $person (@coursepersonnel) { my $match = 0; - my ($role,$user) = ($person =~ /^([^:]*):([^:]+:[^:]+)/); + my $secmatch = 0; + 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 ($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); + my $status = &check_user_status($udom,$uname,$cdom,$cnum,$role, + $usec); 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); + } } } } @@ -4111,10 +4391,17 @@ sub get_course_users { 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; }