--- loncom/interface/loncommon.pm 2009/11/23 14:04:36 1.918 +++ loncom/interface/loncommon.pm 2010/09/19 18:50:48 1.925.2.13 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common routines # -# $Id: loncommon.pm,v 1.918 2009/11/23 14:04:36 wenzelju Exp $ +# $Id: loncommon.pm,v 1.925.2.13 2010/09/19 18:50:48 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1877,7 +1877,7 @@ sub select_form { $selectform.= '\n"; + ">".$hash{$key}."\n"; } $selectform.=""; return $selectform; @@ -1978,7 +1978,16 @@ sub select_dom_form { ($dom eq $defdom ? 'selected="selected" ' : '').'>'.$dom; if ($showdomdesc) { if ($dom ne '') { - my $domdesc = &Apache::lonnet::domain($dom,'description'); + my $domdesc; + if ($name eq 'srchdomain') { + if ($dom eq 'gci') { + $domdesc = 'Faculty'; + } else { + $domdesc = 'Students'; + } + } else { + $domdesc = &Apache::lonnet::domain($dom,'description'); + } if ($domdesc ne '') { $selectdomain .= ' ('.$domdesc.')'; } @@ -2469,9 +2478,11 @@ sub authform_internal{ } $autharg = ''; - $result = &mt - ('[_1] Internally authenticated (with initial password [_2])', - ''.$autharg); + my $authtext = '[_1] Internally authenticated (with initial password [_2])'; + if ($in{'caller'} eq 'requestcrs') { + $authtext = "[_1] Students' password, if none in the uploaded file: [_2]"; + } + $result = &mt($authtext,''.$autharg); $result.="'; return $result; } @@ -4367,18 +4378,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',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; } ############################################### @@ -4455,6 +4478,10 @@ sub bodytag { 'link' => &designparm($function.'.link',$domain),); @design{keys(%$addentries)} = @$addentries{keys(%$addentries)}; + my $custommenu; + if ($env{'environment.remote'} eq 'off') { + $custommenu = &needs_gci_custom(); + } # role and realm my ($role,$realm) = split(/\./,$env{'request.role'},2); if ($role eq 'ca') { @@ -4464,14 +4491,22 @@ sub bodytag { # realm if ($env{'request.course.id'}) { if ($env{'request.role'} !~ /^cr/) { - $role = &Apache::lonnet::plaintext($role,&course_type()); + if (($custommenu) && ($role eq 'cm')) { + undef($role); + } else { + $role = &Apache::lonnet::plaintext($role,&course_type()); + } } if ($env{'request.course.sec'}) { $role .= (' 'x2).'- '.&mt('section:').' '.$env{'request.course.sec'}; } $realm = $env{'course.'.$env{'request.course.id'}.'.description'}; } else { - $role = &Apache::lonnet::plaintext($role); + if (($custommenu) && ($role eq 'cm')) { + undef($role); + } else { + $role = &Apache::lonnet::plaintext($role); + } } if (!$realm) { $realm=' '; } @@ -4522,7 +4557,17 @@ sub bodytag { # $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls # } - + my $role_selector; + if (($custommenu) && ($env{'request.course.id'}) && + ($env{'course.'.$env{'request.course.id'}.'.domain'} eq 'gcitest') && + ($env{'request.role'} !~ m{^st\./gcitest/$match_courseid})) { + $role_selector = &Apache::lonmenu::roles_selector( + $env{'course.' . $env{'request.course.id'} . '.domain'}, + $env{'course.' . $env{'request.course.id'} . '.num'} ); + if ($role_selector) { + $role_selector = '
'.$role_selector; + } + } if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { if ($dc_info) { @@ -4533,10 +4578,10 @@ sub bodytag { return $bodytag; } - $bodytag .= qq|
$name $role
|; + $bodytag .= qq|
$name $role $role_selector
|; $bodytag .= Apache::lonhtmlcommon::scripttag( - Apache::lonmenu::utilityfunctions(), 'start'); + Apache::lonmenu::utilityfunctions('',$custommenu), 'start'); $bodytag .= Apache::lonmenu::primary_menu(); @@ -4547,10 +4592,20 @@ sub bodytag { #don't show menus for public users if($env{'user.name'} ne 'public' && $env{'user.domain'} ne 'public'){ - $bodytag .= Apache::lonmenu::secondary_menu(); + if (($custommenu) && + ($env{'request.role'} !~ m{^st\./gcitest/$match_courseid})) { + $bodytag .= &Apache::lonmenu::gci_secondary_menu(); + } else { + $bodytag .= Apache::lonmenu::secondary_menu(); + } $bodytag .= Apache::lonmenu::serverform(); - $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); - $bodytag .= Apache::lonmenu::innerregister($forcereg) if $forcereg; + $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. @@ -4751,11 +4806,6 @@ body { color:$font; } -a:link, -a:visited { - font-size:100%; -} - a:focus { color: red; background: yellow; @@ -4782,6 +4832,7 @@ form, .inline { .LC_filename { font-family: $mono; white-space:pre; + font-size: 120%; } .LC_fileicon { @@ -4872,9 +4923,7 @@ table.LC_pastsubmission { margin: 2px; } -table#LC_top_nav, -table#LC_menubuttons, -table#LC_nav_location { +table#LC_menubuttons { width: 100%; background: $pgbg; border: 2px; @@ -4905,6 +4954,26 @@ table#LC_title_bar.LC_with_remote { margin: 0; } +dl.LC_GCI_Menu { + width:300px; + float:left; + margin-right:2em; +} + +dl.LC_GCI_Menu dt { + font-weight: bold; + font-size:0.9em; + margin-bottom:0.7em; +} + +dl.LC_GCI_Menu dd { + font-size:0.8em; + margin:0 0 2em 0; + padding-left:4.5em; + line-height:1.5em; + background:none no-repeat left top; +} + /* #SD START (work in progress)*/ ul.LC_bct { @@ -4954,41 +5023,6 @@ table#LC_menubuttons img { border: none; } -table#LC_top_nav td { - background: $tabbg; - border: none; - font-size: small; - vertical-align:top; - padding:2px 5px 2px 5px; -} - -table#LC_top_nav td a, -div#LC_top_nav a { - color: $font; -} - -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: none; - 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_top_nav td.LC_top_nav_login { - width: 4.0em; - text-align: center; -} - .LC_breadcrumbs_component { float: right; margin: 0 1em; @@ -5001,10 +5035,6 @@ td.LC_table_cell_checkbox { text-align: center; } -table#LC_mainmenu td.LC_mainmenu_column { - vertical-align: top; -} - .LC_fontsize_small { font-size: 70%; } @@ -5066,11 +5096,6 @@ td.LC_menubuttons_text { background: $tabbg; } -.LC_new_mail { - background: $tabbg; - font-weight: bold; -} - table.LC_data_table, table.LC_mail_list { border: 1px solid #000000; @@ -5256,12 +5281,6 @@ table.LC_mail_list 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 { background-color: $mail_read; } @@ -5667,12 +5686,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; } @@ -5705,17 +5724,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; @@ -5916,21 +5924,8 @@ img.stift { 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 { @@ -5993,12 +5988,6 @@ h6 { border: 0; } -.LC_Right { - float: right; - margin: 0; - padding: 0; -} - .LC_FormSectionClearButton input { background-color:transparent; border: none; @@ -6256,7 +6245,6 @@ dl.LC_ListStyleClean dd { .LC_ListStyleClean, .LC_ListStyleSimple, .LC_ListStyleNormal, -.LC_ListStyle_Border, .LC_ListStyleSpecial { /* display:block; */ list-style-position: inside; @@ -6391,11 +6379,6 @@ table.LC_tableOfContent a { text-decoration: none; } -table.LC_tableBrowseRes tr.LC_trOdd, -table.LC_tableOfContent tr.LC_trOdd { - background-color: #EEEEEE; -} - table.LC_tableOfContent img { border: none; height: 1.3em; @@ -6494,6 +6477,36 @@ ul.LC_funclist li { line-height: 150%; } +#gciheader { + float:left; + width:100%; + background:#DAE0D2 url("/gcimenu_bg.gif") repeat-x bottom; + font-size:93%; + line-height:normal; +} +#gciheader ul { + margin:0; + padding:10px 10px 0; + list-style:none; +} +#gciheader li { + float:left; + background:url("/gcimenu_left.gif") no-repeat left top; + margin:0; + padding:0 0 0 9px; +} +#gciheader a { + display:block; + background:url("/gcimenu_right.gif") no-repeat right top; + padding:5px 15px 4px 6px; +} +#gciheader #current { + background-image:url("/gcimenu_left_on.gif"); +} +#gciheader #current a { + background-image:url("/gcimenu_right_on.gif"); + padding-bottom:5px; +} END } @@ -6770,6 +6783,11 @@ sub start_page { # Don't add anything more if only_body wanted return $result if $args->{'only_body'}; + #Breadcrumbs for Construction Space provided by &bodytag. + if (($env{'environment.remote'} eq 'off') && ($env{'request.state'} eq 'construct')) { + return $result; + } + #Breadcrumbs if (exists($args->{'bread_crumbs'}) or exists($args->{'bread_crumbs_component'})) { &Apache::lonhtmlcommon::clear_breadcrumbs(); @@ -7715,9 +7733,9 @@ sub user_picker { 'whse' => "When searching by last,first you must include at least one character in the first name.", 'thfo' => "The following need to be corrected before the search can be run:", ); - my $domform = &select_dom_form($currdom,'srchdomain',1,1); + my $domform = &select_dom_form($currdom,'srchdomain',undef,1); my $srchinsel = ' \n"; @@ -7776,9 +7795,9 @@ sub user_picker { ); $new_user_create = '

' .&mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.") - .' ' - .&mt('Please contact the [_1]helpdesk[_2] for assistance.' - ,'','') + .'
' + .&mt('Enter a valid e-mail address as the username for the new user.').' '.&mt('Please contact the [_1]helpdesk[_2] for assistance.' + ,'','') .'


'; } } @@ -9648,6 +9667,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; } @@ -9760,12 +9781,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); @@ -9774,15 +9797,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) { @@ -9790,18 +9818,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(); + } } } } @@ -10046,19 +10082,19 @@ sub check_clone { my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom); my $clonemsg; my $can_clone = 0; - my $lctype = lc($args->{'type'}); + my $lctype = lc($args->{'crstype'}); if ($lctype ne 'community') { $lctype = 'course'; } if ($clonehome eq 'no_host') { - if ($args->{'type'} eq 'Community') { + 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->{'type'} eq 'Community') { + 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); @@ -10077,7 +10113,7 @@ sub check_clone { $can_clone = 1; } else { my $ccrole = 'cc'; - if ($args->{'type'} eq 'Community') { + if ($args->{'crstype'} eq 'Community') { $ccrole = 'co'; } my %roleshash = @@ -10088,7 +10124,7 @@ sub check_clone { if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) { $can_clone = 1; } else { - if ($args->{'type'} eq 'Community') { + 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'}); @@ -10427,6 +10463,21 @@ sub construct_course { $outcome .= ($fatal?$errtext:'write ok').$linefeed; } + if ($args->{'cloneroster'}) { + my ($numadded,$clisterror) = &Apache::lonclonecourse::copyroster($cloneid,$$courseid,$args->{'startaccess'},$args->{'endaccess'}); + if ($clisterror) { + $outcome .= "\0".&mt('An error occurred when copying the student roster from the old course to the new course; the error was: [_1].',$clisterror).$linefeed; + if ($numadded) { + $outcome .= &mt('Although [quant,_1,student] have received roles in the new course the roster does not report this. It is ').$linefeed; + } + } else { + if ($numadded) { + $outcome .= "\0".&mt('[quant,_1,student] copied from roster for old course to roster for new course.',$numadded).$linefeed; + } else { + $outcome .= "\0".&mt('No students have been enrolled in the new Concept Test.').' '.&mt('This is because either (a) an error occurred, or (b) there were no students with either current access or access which ended on/after the current default end date set for access to the old course.').$linefeed; + } + } + } return (1,$outcome); } @@ -10693,6 +10744,60 @@ sub _add_to_env { } } +sub new_roles_update { + my $rolecount = 0; + foreach my $envkey (keys(%env)) { + next unless ($envkey =~ /^user\.role\./); + $rolecount ++; + } + my $newrolecount = 0; + if (!$rolecount) { + my %userenv; + foreach my $crstype ('official','unofficial','community') { + $userenv{'canrequest.'.$crstype} = + &Apache::lonnet::usertools_access($env{'user.name'}, + $env{'user.domain'},$crstype,'reload','requestcourses'); + } + my $then=$env{'user.login.time'}; + my $refresh=time; + my (%userroles,%allroles,%allgroups,@newroles); + my %roleshash = + &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',['active','future','previous'],undef,undef,1); + foreach my $item (keys(%roleshash)) { + my ($uname,$udom,$role,$section) = split(':',$item); + my $where = '/'.$udom.'/'.$uname; + my ($tstart,$tend) = split(':',$roleshash{$item}); + if ($section ne '') { + $where .= '/'.$section; + } + my $spec = $role.'.'.$where; + &Apache::lonnet::set_arearole($role,$where,$tstart,$tend, + $env{'user.domain'},$env{'user.name'}); + $userroles{'user.role.'.$spec} = $tstart.'.'.$tend; + $newrolecount ++; + unless (grep(/^\Q$role\E$/,@newroles)) { + push(@newroles,$role); + } + my $status = + &Apache::lonnet::curr_role_status($tstart,$tend,$refresh,$then); + if ($status eq 'active') { + &Apache::lonnet::gather_roleprivs(\%allroles,\%allgroups,\%userroles, + $where,$role,$tstart,$tend); + } + } + if (@newroles) { + my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles, + \%allgroups); + &Apache::lonnet::appenv(\%userroles,[@newroles,'cm']); + $userenv{'user.adv'} = $adv; + $userenv{'user.author'} = $author; + $userenv{'user.refresh.time'} = $refresh; + } + &Apache::lonnet::appenv(\%userenv); + } + return $newrolecount; +} + # --- Get the symbolic name of a problem and the url sub get_symb { my ($request,$silent) = @_; @@ -10734,6 +10839,76 @@ sub clean_symb { return ($symb,$enc); } +sub needs_gci_custom { + my $custommenu; + my $numdc = &check_for_gci_dc(); + unless ($numdc) { + my $then=$env{'user.login.time'}; + my $now = time; + my %cnums = ( + review => '9615072b469884921gcil1', + submit => '1H96711d710194bfegcil1', + ); + if ($env{'user.role.st./gci/'.$cnums{'review'}}) { + my ($start,$end) = + split('.',$env{'user.role.st./gci/'.$cnums{'review'}}); + if (((!$start) || ($start && $start <= $now)) && + ((!$end) || ($end > $now))) { + $custommenu = 1; + if ($env{'user.role.cc./gci/'.$cnums{'review'}}) { + my ($ccstart,$ccend) = + split('.',$env{'user.role.cc./gci/'.$cnums{'review'}}); + if (((!$start) || ($start && $start <= $now)) && + ((!$end) || ($end > $now))) { + $custommenu = ''; + } + } + } + } + } + return $custommenu; +} + +sub check_for_gci_dc { + my $then=$env{'user.login.time'}; + my $numdc = 0; + foreach my $dom ('gci','gcitest') { + if ($env{'user.role.dc./'.$dom.'/'}) { + my $livedc = 1; + my ($tstart,$tend)=split(/\./,$env{'user.role.dc./'.$dom.'/'}); + if ($tstart && $tstart>$then) { $livedc = 0; } + if ($tend && $tend <$then) { $livedc = 0; } + if ($livedc) { + $numdc++; + } + } + } + return $numdc; +} + +sub existing_gcitest_courses { + my ($role) = @_; + my %courses; + my $cdom = 'gcitest'; + my $now = time; + foreach my $envkey (keys(%env)) { + my $cnum; + if ($envkey =~ m{^user\.role\.\Q$role\E\./\Q$cdom\E/($match_courseid)$}) { + $cnum = $1; + } else { + next; + } + my ($tstart,$tend) = split('.',$env{$envkey}); + if (((!$tstart) || ($tstart < $now)) && ((!$tend) || ($tend > $now))) { + my $descr = $env{'course.'.$cdom.'_'.$cnum.'.description'}; + if ($descr ne '') { + $courses{$cdom.'_'.$cnum}{'description'} = $descr; + } + } + } + return %courses; +} + =pod =back