--- loncom/interface/domainprefs.pm 2008/07/21 16:24:31 1.66 +++ loncom/interface/domainprefs.pm 2013/01/09 21:30:27 1.186 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.66 2008/07/21 16:24:31 raeburn Exp $ +# $Id: domainprefs.pm,v 1.186 2013/01/09 21:30:27 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -28,6 +28,131 @@ ############################################################### ############################################################## +=pod + +=head1 NAME + +Apache::domainprefs.pm + +=head1 SYNOPSIS + +Handles configuration of a LON-CAPA domain. + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + + +=head1 OVERVIEW + +Each institution using LON-CAPA will typically have a single domain designated +for use by individuals affiliated with the institution. Accordingly, each domain +may define a default set of logos and a color scheme which can be used to "brand" +the LON-CAPA instance. In addition, an institution will typically have a language +and timezone which are used for the majority of courses. + +LON-CAPA provides a mechanism to display and modify these defaults, as well as a +host of other domain-wide settings which determine the types of functionality +available to users and courses in the domain. + +There is also a mechanism to configure cataloging of courses in the domain, and +controls on the operation of automated processes which govern such things as +roster updates, user directory updates and processing of course requests. + +The domain coordination manual which is built dynamically on install/update of +LON-CAPA from the relevant help items provides more information about domain +configuration. + +Most of the domain settings are stored in the configuration.db GDBM file which is +housed on the primary library server for the domain in /home/httpd/lonUsers/$dom, +where $dom is the domain. The configuration.db stores settings in a number of +frozen hashes of hashes. In a few cases, domain information must be uploaded to +the domain as files (e.g., image files for logos etc., or plain text files for +bubblesheet formats). In this case the domainprefs.pm must be running in a user +session hosted on the primary library server in the domain, as these files are +stored in author space belonging to a special $dom-domainconfig user. + +domainprefs.pm in combination with lonconfigsettings.pm will retrieve and display +the current settings, and provides an interface to make modifications. + +=head1 SUBROUTINES + +=over + +=item print_quotas() + +Inputs: 4 + +$dom,$settings,$rowtotal,$action. + +$dom is the domain, $settings is a reference to a hash of current settings for +the current context, $rowtotal is a reference to the scalar used to record the +number of rows displayed on the page, and $action is the context (quotas, +requestcourses or requestauthor). + +The print_quotas routine was orginally created to display/store information +about default quota sizes for portfolio spaces for the different types of +institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.), +but is now also used to manage availability of user tools: +i.e., blogs, aboutme page, and portfolios, and the course request tool, +used by course owners to request creation of a course. + +Outputs: 1 + +$datatable - HTML containing form elements which allow settings to be changed. + +In the case of course requests, radio buttons are displayed for each institutional +affiliate type (and also default, and _LC_adv) for each of the course types +(official, unofficial and community). In each case the radio buttons allow the +selection of one of four values: + +0, approval, validate, autolimit=N (where N is blank, or a positive integer). +which have the following effects: + +0 + +=over + +- course requests are not allowed for this course types/affiliation + +=back + +approval + +=over + +- course requests must be approved by a Doman Coordinator in the +course's domain + +=back + +validate + +=over + +- an institutional validation (e.g., check requestor is instructor +of record) needs to be passed before the course will be created. The required +validation is in localenroll.pm on the primary library server for the course +domain. + +=back + +autolimit + +=over + +- course requests will be processed automatically up to a limit of +N requests for the course type for the particular requestor. +If N is undefined, there is no limit to the number of course requests +which a course owner may submit and have processed automatically. + +=back + +=item modify_quotas() + +=back + +=cut + package Apache::domainprefs; use strict; @@ -37,11 +162,17 @@ use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonlocal; use Apache::lonmsg(); -use LONCAPA; +use Apache::lonconfigsettings; +use LONCAPA qw(:DEFAULT :match); use LONCAPA::Enrollment; +use LONCAPA::lonauthcgi(); use File::Copy; use Locale::Language; use DateTime::TimeZone; +use DateTime::Locale; + +my $registered_cleanup; +my $modified_urls; sub handler { my $r=shift; @@ -51,6 +182,7 @@ sub handler { return OK; } + my $context = 'domain'; my $dom = $env{'request.role.domain'}; my $domdesc = &Apache::lonnet::domain($dom,'description'); if (&Apache::lonnet::allowed('mau',$dom)) { @@ -61,6 +193,10 @@ sub handler { "/adm/domainprefs:mau:0:0:Cannot modify domain settings"; return HTTP_NOT_ACCEPTABLE; } + + $registered_cleanup=0; + @{$modified_urls}=(); + &Apache::lonhtmlcommon::clear_breadcrumbs(); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['phase','actions']); @@ -68,19 +204,32 @@ sub handler { if ( exists($env{'form.phase'}) ) { $phase = $env{'form.phase'}; } + my %servers = &Apache::lonnet::internet_dom_servers($dom); my %domconfig = &Apache::lonnet::get_dom('configuration',['login','rolecolors', - 'quotas','autoenroll','autoupdate','directorysrch', - 'usercreation','usermodification','contacts','defaults', - 'scantron','coursecategories'],$dom); + 'quotas','autoenroll','autoupdate','autocreate', + 'directorysrch','usercreation','usermodification', + 'contacts','defaults','scantron','coursecategories', + 'serverstatuses','requestcourses','helpsettings', + 'coursedefaults','usersessions','loadbalancing', + 'requestauthor'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', - 'autoupdate','directorysrch','contacts', + 'autoupdate','autocreate','directorysrch','contacts', 'usercreation','usermodification','scantron', - 'coursecategories'); + 'requestcourses','requestauthor','coursecategories', + 'serverstatuses','helpsettings', + 'coursedefaults','usersessions'); + my %existing; + if (ref($domconfig{'loadbalancing'}) eq 'HASH') { + %existing = %{$domconfig{'loadbalancing'}}; + } + if ((keys(%servers) > 1) || (keys(%existing) > 0)) { + push(@prefs_order,'loadbalancing'); + } my %prefs = ( 'rolecolors' => { text => 'Default color schemes', - help => 'Domconfig_Color_Schemes', + help => 'Domain_Configuration_Color_Schemes', header => [{col1 => 'Student Settings', col2 => '',}, {col1 => 'Coordinator Settings', @@ -90,54 +239,65 @@ sub handler { {col1 => 'Administrator Settings', col2 => '',}], }, - 'login' => + 'login' => { text => 'Log-in page options', - help => 'Domconfig_Login_Page', - header => [{col1 => 'Item', - col2 => '',}], + help => 'Domain_Configuration_Login_Page', + header => [{col1 => 'Log-in Page Items', + col2 => '',}, + {col1 => 'Log-in Help', + col2 => 'Value'}], }, 'defaults' => - { text => 'Default authentication/language/timezone', - help => 'Domconfig_LangTZAuth', + { text => 'Default authentication/language/timezone/portal', + help => 'Domain_Configuration_LangTZAuth', header => [{col1 => 'Setting', col2 => 'Value'}], }, 'quotas' => - { text => 'Default quotas for user portfolios', - help => 'Domconfig_Quotas', - header => [{col1 => 'User type', - col2 => 'Default quota'}], + { text => 'Blogs, personal web pages, webDAV, portfolios', + help => 'Domain_Configuration_Quotas', + header => [{col1 => 'User affiliation', + col2 => 'Available tools', + col3 => 'Portfolio quota',}], }, 'autoenroll' => { text => 'Auto-enrollment settings', - help => 'Domconfig_Auto_Enrollment', + help => 'Domain_Configuration_Auto_Enrollment', header => [{col1 => 'Configuration setting', col2 => 'Value(s)'}], }, 'autoupdate' => { text => 'Auto-update settings', - help => 'Domconfig_Auto_Updates', + help => 'Domain_Configuration_Auto_Updates', header => [{col1 => 'Setting', col2 => 'Value',}, + {col1 => 'Setting', + col2 => 'Affiliation'}, {col1 => 'User population', - col2 => 'Updataeable user data'}], + col2 => 'Updateable user data'}], + }, + 'autocreate' => + { text => 'Auto-course creation settings', + help => 'Domain_Configuration_Auto_Creation', + header => [{col1 => 'Configuration Setting', + col2 => 'Value',}], }, 'directorysrch' => { text => 'Institutional directory searches', - help => 'Domconfig_InstDirectory_Search', + help => 'Domain_Configuration_InstDirectory_Search', header => [{col1 => 'Setting', col2 => 'Value',}], }, 'contacts' => { text => 'Contact Information', - help => 'Domconfig_Contact_Info', + help => 'Domain_Configuration_Contact_Info', header => [{col1 => 'Setting', col2 => 'Value',}], }, 'usercreation' => { text => 'User creation', - help => 'Domconfig_User_Creation', + help => 'Domain_Configuration_User_Creation', header => [{col1 => 'Format rule type', col2 => 'Format rules in force'}, {col1 => 'User account creation', @@ -145,9 +305,9 @@ sub handler { {col1 => 'Context', col2 => 'Assignable authentication types'}], }, - 'usermodification' => + 'usermodification' => { text => 'User modification', - help => 'Domconfig_User_Modification', + help => 'Domain_Configuration_User_Modification', header => [{col1 => 'Target user has role', col2 => 'User information updateable in author context'}, {col1 => 'Target user has role', @@ -155,122 +315,150 @@ sub handler { {col1 => "Status of user", col2 => 'Information settable when self-creating account (if directory data blank)'}], }, - 'scantron' => - { text => 'Scantron format file', - help => 'Domconfig_Scantron_Format', + 'scantron' => + { text => 'Bubblesheet format file', + help => 'Domain_Configuration_Scantron_Format', header => [ {col1 => 'Item', col2 => '', }], }, - 'coursecategories' => - { text => 'Cataloging of courses', - help => 'Domconfig_Cataloging_Courses', - header => [{col1 => 'Category settings', + 'requestcourses' => + {text => 'Request creation of courses', + help => 'Domain_Configuration_Request_Courses', + header => [{col1 => 'User affiliation', + col2 => 'Availability/Processing of requests',}, + {col1 => 'Setting', + col2 => 'Value'}], + }, + 'requestauthor' => + {text => 'Request authoring space', + help => 'Domain_Configuration_Request_Author', + header => [{col1 => 'User affiliation', + col2 => 'Availability/Processing of requests',}, + {col1 => 'Setting', + col2 => 'Value'}], + }, + 'coursecategories' => + { text => 'Cataloging of courses/communities', + help => 'Domain_Configuration_Cataloging_Courses', + header => [{col1 => 'Category settings', col2 => '',}, {col1 => 'Categories', col2 => '', }], - } + }, + 'serverstatuses' => + {text => 'Access to server status pages', + help => 'Domain_Configuration_Server_Status', + header => [{col1 => 'Status Page', + col2 => 'Other named users', + col3 => 'Specific IPs', + }], + }, + 'helpsettings' => + {text => 'Help page settings', + help => 'Domain_Configuration_Help_Settings', + header => [{col1 => 'Help Settings (logged-in users)', + col2 => 'Value'}], + }, + 'coursedefaults' => + {text => 'Course/Community defaults', + help => 'Domain_Configuration_Course_Defaults', + header => [{col1 => 'Defaults which can be overridden in each course by a CC', + col2 => 'Value',}, + {col1 => 'Defaults which can be overridden for each course by a DC', + col2 => 'Value',},], + }, + 'privacy' => + {text => 'User Privacy', + help => 'Domain_Configuration_User_Privacy', + header => [{col1 => 'Setting', + col2 => 'Value',}], + }, + 'usersessions' => + {text => 'User session hosting/offloading', + help => 'Domain_Configuration_User_Sessions', + header => [{col1 => 'Domain server', + col2 => 'Servers to offload sessions to when busy'}, + {col1 => 'Hosting of users from other domains', + col2 => 'Rules'}, + {col1 => "Hosting domain's own users elsewhere", + col2 => 'Rules'}], + }, + 'loadbalancing' => + {text => 'Dedicated Load Balancer(s)', + help => 'Domain_Configuration_Load_Balancing', + header => [{col1 => 'Balancers', + col2 => 'Default destinations', + col3 => 'User affiliation', + col4 => 'Overrides'}, + ], + }, ); + if (keys(%servers) > 1) { + $prefs{'login'} = { text => 'Log-in page options', + help => 'Domain_Configuration_Login_Page', + header => [{col1 => 'Log-in Service', + col2 => 'Server Setting',}, + {col1 => 'Log-in Page Items', + col2 => ''}, + {col1 => 'Log-in Help', + col2 => 'Value'}], + }; + } + + + my @roles = ('student','coordinator','author','admin'); my @actions = &Apache::loncommon::get_env_multiple('form.actions'); &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:changePage(document.$phase,'pickactions')", - text=>"Pick functionality"}); + text=>"Settings to display/modify"}); my $confname = $dom.'-domainconfig'; + if ($phase eq 'process') { - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"javascript:changePage(document.$phase,'display')", - text=>"Domain Configuration"}, - {href=>"javascript:changePage(document.$phase,'$phase')", - text=>"Updated"}); - &print_header($r,$phase); - foreach my $item (@prefs_order) { - if (grep(/^\Q$item\E$/,@actions)) { - $r->print('

'.&mt($prefs{$item}{'text'}).'

'. - &process_changes($r,$dom,$confname,$item, - \@roles,%domconfig)); - } - } - $r->print('

'); - &print_footer($r,$phase,'display','Back to configuration display', - \@actions); - $r->print('

'); + &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles); } elsif ($phase eq 'display') { - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"javascript:changePage(document.$phase,'display')", - text=>"Domain Configuration"}); - &print_header($r,$phase); - if (@actions > 0) { - my $rowsum = 0; - my (%output,%rowtotal,@items); - my $halfway = @actions/2; - foreach my $item (@prefs_order) { - if (grep(/^\Q$item\E$/,@actions)) { - push(@items,$item); - ($output{$item},$rowtotal{$item}) = - &print_config_box($r,$dom,$confname,$phase, - $item,$prefs{$item}, - $domconfig{$item}); - $rowsum += $rowtotal{$item}; - } - } - my $colend; - my $halfway = $rowsum/2; - my $aggregate = 0; - my $sumleft = 0; - my $sumright = 0; - my $crossover; - for (my $i=0; $i<@items; $i++) { - $aggregate += $rowtotal{$items[$i]}; - if ($aggregate > $halfway) { - $crossover = $i; - last; - } - } - for (my $i=0; $i<$crossover; $i++) { - $sumleft += $rowtotal{$items[$i]}; - } - for (my $i=$crossover+1; $i<@items; $i++) { - $sumright += $rowtotal{$items[$i]}; - } - if ((@items > 1) && ($env{'form.numcols'} == 2)) { - my $sumdiff = $sumright - $sumleft; - if ($sumdiff > 0) { - $colend = $crossover + 1; - } else { - $colend = $crossover; - } - } else { - $colend = @items; - } - $r->print('

'); - for (my $i=0; $i<$colend; $i++) { - $r->print($output{$items[$i]}); - } - $r->print(''); - if ($colend < @items) { - for (my $i=$colend; $i<@items; $i++) { - $r->print($output{$items[$i]}); - } - } - $r->print('

'); - $r->print(&print_footer($r,$phase,'process','Save',\@actions)); - } else { - $r->print(''. - ''."\n". - ''.&mt('No settings chosen'). - ''); - } - $r->print(''); - $r->print(&Apache::loncommon::end_page()); - } else { - if ($phase eq '') { - $phase = 'pickactions'; + my $js = &recaptcha_js(); + if ((keys(%servers) > 1) || (keys(%existing) > 0)) { + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($dom); + $js .= &lonbalance_targets_js($dom,$types,\%servers, + $domconfig{'loadbalancing'}). + &new_spares_js(). + &common_domprefs_js(). + &Apache::loncommon::javascript_array_indexof(); + } + &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js); + } else { +# check if domconfig user exists for the domain. + my $servadm = $r->dir_config('lonAdmEMail'); + my ($configuserok,$author_ok,$switchserver) = + &config_check($dom,$confname,$servadm); + unless ($configuserok eq 'ok') { + &Apache::lonconfigsettings::print_header($r,$phase,$context); + $r->print(&mt('The domain configuration user "[_1]" has yet to be created.', + $confname). + '
' + ); + if ($switchserver) { + $r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.'). + '
'. + &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.'). + '
'. + &mt('The "[_1]" user can be created automatically when a Domain Coordinator visits the web-based "Set domain configuration" screen, in a session hosted on the primary library server.',$confname). + '
'. + &mt('To do that now, use the following link: [_1]',$switchserver) + ); + } else { + $r->print(&mt('To create that user from the command line run the ./UPDATE script found in the top level directory of the extracted LON-CAPA tarball.'). + '
'. + &mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain') + ); + } + $r->print(&Apache::loncommon::end_page()); + return OK; } - my %helphash; - &print_header($r,$phase); if (keys(%domconfig) == 0) { my $primarylibserv = &Apache::lonnet::domain($dom,'primary'); my @ids=&Apache::lonnet::current_machine_ids(); @@ -289,6 +477,7 @@ sub handler { } } if ($custom_img_count > 0) { + &Apache::lonconfigsettings::print_header($r,$phase,$context); my $switch_server = &check_switchserver($dom,$confname); $r->print( &mt('Domain configuration settings have yet to be saved for this domain via the web-based domain preferences interface.').'
'. @@ -298,53 +487,23 @@ sub handler { if ($switch_server) { $r->print($switch_server.' '.&mt('to primary library server for domain: [_1]',$dom)); } + $r->print(&Apache::loncommon::end_page()); return OK; } } } - $r->print('

'.&mt('Functionality to display/modify').'

'); - $r->print(''."\n".'

  '. - '

'); - my ($numitems,$midpoint,$seconddiv,$count); - $numitems = @prefs_order; - $midpoint = int($numitems/2); - if ($numitems%2) { - $midpoint ++; - } - $count = 0; - foreach my $item (@prefs_order) { - $r->print('

'. - &Apache::loncommon::help_open_topic($prefs{$item}->{'help'}). - '

'); - $count ++; - if ((!$seconddiv) && ($count >= $midpoint)) { - $r->print('
'."\n".'
'."\n"); - $seconddiv = 1; - } - } - $r->print('

'. - &mt('Display options').'

'."\n". - '

'.&mt('Display using: ')."\n". - '  

'); - $r->print(&print_footer($r,$phase,'display','Go')); - $r->print(''); - $r->print(&Apache::loncommon::end_page()); + + &Apache::lonconfigsettings::display_choices($r,$phase,$context,\@prefs_order,\%prefs); } return OK; } sub process_changes { - my ($r,$dom,$confname,$action,$roles,%domconfig) = @_; + my ($r,$dom,$confname,$action,$roles,$values) = @_; + my %domconfig; + if (ref($values) eq 'HASH') { + %domconfig = %{$values}; + } my $output; if ($action eq 'login') { $output = &modify_login($r,$dom,$confname,%domconfig); @@ -352,11 +511,13 @@ sub process_changes { $output = &modify_rolecolors($r,$dom,$confname,$roles, %domconfig); } elsif ($action eq 'quotas') { - $output = &modify_quotas($dom,%domconfig); + $output = &modify_quotas($dom,$action,%domconfig); } elsif ($action eq 'autoenroll') { $output = &modify_autoenroll($dom,%domconfig); } elsif ($action eq 'autoupdate') { $output = &modify_autoupdate($dom,%domconfig); + } elsif ($action eq 'autocreate') { + $output = &modify_autocreate($dom,%domconfig); } elsif ($action eq 'directorysrch') { $output = &modify_directorysrch($dom,%domconfig); } elsif ($action eq 'usercreation') { @@ -371,6 +532,20 @@ sub process_changes { $output = &modify_scantron($r,$dom,$confname,%domconfig); } elsif ($action eq 'coursecategories') { $output = &modify_coursecategories($dom,%domconfig); + } elsif ($action eq 'serverstatuses') { + $output = &modify_serverstatuses($dom,%domconfig); + } elsif ($action eq 'requestcourses') { + $output = &modify_quotas($dom,$action,%domconfig); + } elsif ($action eq 'requestauthor') { + $output = &modify_quotas($dom,$action,%domconfig); + } elsif ($action eq 'helpsettings') { + $output = &modify_helpsettings($r,$dom,$confname,%domconfig); + } elsif ($action eq 'coursedefaults') { + $output = &modify_coursedefaults($dom,%domconfig); + } elsif ($action eq 'usersessions') { + $output = &modify_usersessions($dom,%domconfig); + } elsif ($action eq 'loadbalancing') { + $output = &modify_loadbalancing($dom,%domconfig); } return $output; } @@ -379,9 +554,10 @@ sub print_config_box { my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_; my $rowtotal = 0; my $output; + if ($action eq 'coursecategories') { $output = &coursecategories_javascript($settings); - } + } $output .= ' @@ -390,22 +566,29 @@ sub print_config_box { &Apache::loncommon::help_open_topic($item->{'help'}).''."\n". ''; $rowtotal ++; - if (($action eq 'autoupdate') || ($action eq 'rolecolors') || - ($action eq 'usercreation') || ($action eq 'usermodification') || - ($action eq 'coursecategories')) { + my $numheaders = 1; + if (ref($item->{'header'}) eq 'ARRAY') { + $numheaders = scalar(@{$item->{'header'}}); + } + if ($numheaders > 1) { my $colspan = ''; - if (($action eq 'rolecolors') || ($action eq 'coursecategories')) { + my $rightcolspan = ''; + if (($action eq 'rolecolors') || ($action eq 'coursecategories') || + (($action eq 'login') && ($numheaders < 3))) { $colspan = ' colspan="2"'; } + if ($action eq 'usersessions') { + $rightcolspan = ' colspan="3"'; + } $output .= ' '; $rowtotal ++; if ($action eq 'autoupdate') { - $output .= &print_autoupdate('bottom',$dom,$settings,\$rowtotal); + $output .= &print_autoupdate('middle',$dom,$settings,\$rowtotal).' +
- + '; - $rowtotal ++; + $rowtotal ++; if ($action eq 'autoupdate') { $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'usercreation') { @@ -414,8 +597,23 @@ sub print_config_box { $output .= &print_usermodification('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'coursecategories') { $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal); - } else { + } elsif ($action eq 'login') { + if ($numheaders == 3) { + $colspan = ' colspan="2"'; + $output .= &print_login('service',$dom,$confname,$phase,$settings,\$rowtotal); + } else { + $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal); + } + } elsif ($action eq 'requestcourses') { + $output .= &print_quotas($dom,$settings,\$rowtotal,$action); + } elsif ($action eq 'requestauthor') { + $output .= &print_quotas($dom,$settings,\$rowtotal,$action); + } elsif ($action eq 'usersessions') { + $output .= &print_usersessions('top',$dom,$settings,\$rowtotal); + } elsif ($action eq 'rolecolors') { $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'coursedefaults') { + $output .= &print_coursedefaults('top',$dom,$settings,\$rowtotal); } $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).''.&mt($item->{'header'}->[0]->{'col2'}).''.&mt($item->{'header'}->[0]->{'col2'}).'
@@ -431,7 +629,18 @@ sub print_config_box {
+ + + + + + + + '. + &print_autoupdate('bottom',$dom,$settings,\$rowtotal); + $rowtotal ++; } elsif ($action eq 'usercreation') { $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
@@ -456,13 +665,33 @@ sub print_config_box { '.&mt($item->{'header'}->[2]->{'col1'}).' '.&mt($item->{'header'}->[2]->{'col2'}).' '. - &print_usermodification('bottom',$dom,$settings,\$rowtotal); $rowtotal ++; } elsif ($action eq 'coursecategories') { $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); - } else { - $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).' + } elsif ($action eq 'login') { + if ($numheaders == 3) { + $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).' + + + + + + + + + '. + &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal); + $rowtotal ++; + } else { + $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal); + } + } elsif ($action eq 'requestcourses') { + $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); + } elsif ($action eq 'requestauthor') { + $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); + } elsif ($action eq 'usersessions') { + $output .= &print_usersessions('middle',$dom,$settings,\$rowtotal).'
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
@@ -471,7 +700,24 @@ sub print_config_box { - + '. + &print_usersessions('bottom',$dom,$settings,\$rowtotal); + $rowtotal ++; + } elsif ($action eq 'coursedefaults') { + $output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal); + } elsif ($action eq 'rolecolors') { + $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).' +
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
+ + + + + + + + '. &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
'. + &mt($item->{'header'}->[2]->{'col1'}).''. + &mt($item->{'header'}->[2]->{'col2'}).'
@@ -496,20 +742,51 @@ sub print_config_box { if (($action eq 'login') || ($action eq 'directorysrch')) { $output .= ' '.&mt($item->{'header'}->[0]->{'col1'}).''; + } elsif ($action eq 'serverstatuses') { + $output .= ' + '.&mt($item->{'header'}->[0]->{'col1'}). + '
('.&mt('Automatic access for Dom. Coords.').')'; + } else { $output .= ' - '.&mt($item->{'header'}->[0]->{'col1'}).''; + '.&mt($item->{'header'}->[0]->{'col1'}).''; } - $output .= ' - '.&mt($item->{'header'}->[0]->{'col2'}).' - '; + if (defined($item->{'header'}->[0]->{'col3'})) { + $output .= ''. + &mt($item->{'header'}->[0]->{'col2'}); + if ($action eq 'serverstatuses') { + $output .= '
('.&mt('user1:domain1,user2:domain2 etc.').')'; + } + } else { + $output .= ''. + &mt($item->{'header'}->[0]->{'col2'}); + } + $output .= ''; + if ($item->{'header'}->[0]->{'col3'}) { + if (defined($item->{'header'}->[0]->{'col4'})) { + $output .= ''. + &mt($item->{'header'}->[0]->{'col3'}); + } else { + $output .= ''. + &mt($item->{'header'}->[0]->{'col3'}); + } + if ($action eq 'serverstatuses') { + $output .= '
('.&mt('IP1,IP2 etc.').')'; + } + $output .= ''; + } + if ($item->{'header'}->[0]->{'col4'}) { + $output .= ''. + &mt($item->{'header'}->[0]->{'col4'}); + } + $output .= ''; $rowtotal ++; - if ($action eq 'login') { - $output .= &print_login($dom,$confname,$phase,$settings,\$rowtotal); - } elsif ($action eq 'quotas') { - $output .= &print_quotas($dom,$settings,\$rowtotal); + if ($action eq 'quotas') { + $output .= &print_quotas($dom,$settings,\$rowtotal,$action); } elsif ($action eq 'autoenroll') { $output .= &print_autoenroll($dom,$settings,\$rowtotal); + } elsif ($action eq 'autocreate') { + $output .= &print_autocreate($dom,$settings,\$rowtotal); } elsif ($action eq 'directorysrch') { $output .= &print_directorysrch($dom,$settings,\$rowtotal); } elsif ($action eq 'contacts') { @@ -518,6 +795,12 @@ sub print_config_box { $output .= &print_defaults($dom,\$rowtotal); } elsif ($action eq 'scantron') { $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'serverstatuses') { + $output .= &print_serverstatuses($dom,$settings,\$rowtotal); + } elsif ($action eq 'helpsettings') { + $output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'loadbalancing') { + $output .= &print_loadbalancing($dom,$settings,\$rowtotal); } } $output .= ' @@ -528,258 +811,323 @@ sub print_config_box { return ($output,$rowtotal); } -sub print_header { - my ($r,$phase) = @_; - my $alert = &mt('You must select at least one functionality type to display.'); - my $js = ' - -'; - my $additem; - if ($phase eq 'pickactions') { - my %loaditems = ( - 'onload' => "javascript:getViewportDims(document.$phase.width,document.$phase.height);setDisplayColumns();setFormElements(document.pickactions);", - ); - $additem = {'add_entries' => \%loaditems,}; - } else { - my %loaditems = ( - 'onload' => "javascript:getViewportDims(document.$phase.width,document.$phase.height);", - ); - $additem = {'add_entries' => \%loaditems,}; - } - $r->print(&Apache::loncommon::start_page('View/Modify Domain Settings', - $js,$additem)); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Domain Settings')); - $r->print(' -
- - - -
-'); - $r->print('
'); - return; -} - -sub print_footer { - my ($r,$phase,$newphase,$button_text,$actions) = @_; - $button_text = &mt($button_text); - $r->print(''. - ''. - ''); - if (($phase eq 'display') || ($phase eq 'process')) { - if (ref($actions) eq 'ARRAY') { - foreach my $item (@{$actions}) { - $r->print('')."\n"; - } - } - $r->print(''); - } - my $dest='"javascript:changePage(document.'.$phase.','."'$newphase'".')"'; - if ($phase eq 'process') { - $r->print('

'.$button_text.'

'); - } else { - my $onclick; - if ($phase eq 'display') { - $onclick = '"javascript:changePage(document.'.$phase.','."'$newphase'".')"'; - } else { - $onclick = '"javascript:changePage(document.'.$phase.','."'$newphase'".')"'; - } - $r->print('

'); - } - if ($phase eq 'process') { - $r->print('
'.&Apache::loncommon::end_page()); - } - return; -} - sub print_login { - my ($dom,$confname,$phase,$settings,$rowtotal) = @_; + my ($caller,$dom,$confname,$phase,$settings,$rowtotal) = @_; + my ($css_class,$datatable); my %choices = &login_choices(); - my %defaultchecked = ( - 'coursecatalog' => 'on', - 'adminmail' => 'off', - 'newuser' => 'off', - ); - my @toggles = ('coursecatalog','adminmail','newuser'); - my (%checkedon,%checkedoff); - foreach my $item (@toggles) { - if ($defaultchecked{$item} eq 'on') { - $checkedon{$item} = ' checked="checked" '; - $checkedoff{$item} = ' '; - } elsif ($defaultchecked{$item} eq 'off') { - $checkedoff{$item} = ' checked="checked" '; - $checkedon{$item} = ' '; + + if ($caller eq 'service') { + my %servers = &Apache::lonnet::internet_dom_servers($dom); + my $choice = $choices{'disallowlogin'}; + $css_class = ' class="LC_odd_row"'; + $datatable .= ''.$choice.''. + ''. + ''. + ''. + ''. + ''."\n"; + my %disallowed; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'loginvia'}) eq 'HASH') { + %disallowed = %{$settings->{'loginvia'}}; + } } - } - my $loginheader = 'image'; - my @images = ('img','logo','domlogo','login'); - my @logintext = ('textcol','bgcol'); - my @bgs = ('pgbg','mainbg','sidebg'); - my @links = ('link','alink','vlink'); - my %designhash = &Apache::loncommon::get_domainconf($dom); - my %defaultdesign = %Apache::loncommon::defaultdesign; - my (%is_custom,%designs); - my %defaults = ( - font => $defaultdesign{'login.font'}, - ); - foreach my $item (@images) { - $defaults{$item} = $defaultdesign{'login.'.$item}; - } - foreach my $item (@bgs) { - $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item}; - } - foreach my $item (@logintext) { - $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item}; - } - foreach my $item (@links) { - $defaults{'links'}{$item} = $defaultdesign{'login.'.$item}; - } - if (ref($settings) eq 'HASH') { + foreach my $lonhost (sort(keys(%servers))) { + my $direct = 'selected="selected"'; + if (ref($disallowed{$lonhost}) eq 'HASH') { + if ($disallowed{$lonhost}{'server'} ne '') { + $direct = ''; + } + } + $datatable .= ''. + ''. + ''; + my ($custom,$exempt); + if (ref($disallowed{$lonhost}) eq 'HASH') { + $custom = $disallowed{$lonhost}{'custompath'}; + $exempt = $disallowed{$lonhost}{'exempt'}; + } + $datatable .= ''. + ''. + ''; + } + $datatable .= '
'.$choices{'hostid'}.''.$choices{'server'}.''.$choices{'serverpath'}.''.$choices{'custompath'}.''.$choices{'exempt'}.'
'.$servers{$lonhost}.'
'; + return $datatable; + } elsif ($caller eq 'page') { + my %defaultchecked = ( + 'coursecatalog' => 'on', + 'adminmail' => 'off', + 'newuser' => 'off', + ); + my @toggles = ('coursecatalog','adminmail','newuser'); + my (%checkedon,%checkedoff); foreach my $item (@toggles) { - if ($settings->{$item} eq '1') { - $checkedon{$item} = ' checked="checked" '; + if ($defaultchecked{$item} eq 'on') { + $checkedon{$item} = ' checked="checked" '; $checkedoff{$item} = ' '; - } elsif ($settings->{$item} eq '0') { - $checkedoff{$item} = ' checked="checked" '; + } elsif ($defaultchecked{$item} eq 'off') { + $checkedoff{$item} = ' checked="checked" '; $checkedon{$item} = ' '; } } + my @images = ('img','logo','domlogo','login'); + my @logintext = ('textcol','bgcol'); + my @bgs = ('pgbg','mainbg','sidebg'); + my @links = ('link','alink','vlink'); + my %designhash = &Apache::loncommon::get_domainconf($dom); + my %defaultdesign = %Apache::loncommon::defaultdesign; + my (%is_custom,%designs); + my %defaults = ( + font => $defaultdesign{'login.font'}, + ); foreach my $item (@images) { - if ($settings->{$item} ne '') { - $designs{$item} = $settings->{$item}; - $is_custom{$item} = 1; - } + $defaults{$item} = $defaultdesign{'login.'.$item}; + $defaults{'showlogo'}{$item} = 1; } - foreach my $item (@logintext) { - if ($settings->{$item} ne '') { - $designs{'logintext'}{$item} = $settings->{$item}; - $is_custom{$item} = 1; - } + foreach my $item (@bgs) { + $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item}; } - if ($settings->{'loginheader'} ne '') { - $loginheader = $settings->{'loginheader'}; + foreach my $item (@logintext) { + $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item}; } - if ($settings->{'font'} ne '') { - $designs{'font'} = $settings->{'font'}; - $is_custom{'font'} = 1; + foreach my $item (@links) { + $defaults{'links'}{$item} = $defaultdesign{'login.'.$item}; } - foreach my $item (@bgs) { - if ($settings->{$item} ne '') { - $designs{'bgs'}{$item} = $settings->{$item}; - $is_custom{$item} = 1; + if (ref($settings) eq 'HASH') { + foreach my $item (@toggles) { + if ($settings->{$item} eq '1') { + $checkedon{$item} = ' checked="checked" '; + $checkedoff{$item} = ' '; + } elsif ($settings->{$item} eq '0') { + $checkedoff{$item} = ' checked="checked" '; + $checkedon{$item} = ' '; + } } - } - foreach my $item (@links) { - if ($settings->{$item} ne '') { - $designs{'links'}{$item} = $settings->{$item}; - $is_custom{$item} = 1; + foreach my $item (@images) { + if (defined($settings->{$item})) { + $designs{$item} = $settings->{$item}; + $is_custom{$item} = 1; + } + if (defined($settings->{'showlogo'}{$item})) { + $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item}; + } } - } - } else { - if ($designhash{$dom.'.login.font'} ne '') { - $designs{'font'} = $designhash{$dom.'.login.font'}; - $is_custom{'font'} = 1; - } - foreach my $item (@images) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + foreach my $item (@logintext) { + if ($settings->{$item} ne '') { + $designs{'logintext'}{$item} = $settings->{$item}; + $is_custom{$item} = 1; + } + } + if ($settings->{'font'} ne '') { + $designs{'font'} = $settings->{'font'}; + $is_custom{'font'} = 1; + } + foreach my $item (@bgs) { + if ($settings->{$item} ne '') { + $designs{'bgs'}{$item} = $settings->{$item}; + $is_custom{$item} = 1; + } + } + foreach my $item (@links) { + if ($settings->{$item} ne '') { + $designs{'links'}{$item} = $settings->{$item}; + $is_custom{$item} = 1; + } + } + } else { + if ($designhash{$dom.'.login.font'} ne '') { + $designs{'font'} = $designhash{$dom.'.login.font'}; + $is_custom{'font'} = 1; + } + foreach my $item (@images) { + if ($designhash{$dom.'.login.'.$item} ne '') { + $designs{$item} = $designhash{$dom.'.login.'.$item}; + $is_custom{$item} = 1; + } + } + foreach my $item (@bgs) { + if ($designhash{$dom.'.login.'.$item} ne '') { + $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item}; + $is_custom{$item} = 1; + } + } + foreach my $item (@links) { + if ($designhash{$dom.'.login.'.$item} ne '') { + $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item}; + $is_custom{$item} = 1; + } } } - foreach my $item (@bgs) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + my %alt_text = &Apache::lonlocal::texthash ( img => 'Log-in banner', + logo => 'Institution Logo', + domlogo => 'Domain Logo', + login => 'Login box'); + my $itemcount = 1; + foreach my $item (@toggles) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= + ''.$choices{$item}. + ''. + ' '. + ''; + $itemcount ++; + } + $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext); + $datatable .= ''; + } elsif ($caller eq 'help') { + my ($defaulturl,$defaulttype,%url,%type,%lt,%langchoices); + my $switchserver = &check_switchserver($dom,$confname); + my $itemcount = 1; + $defaulturl = '/adm/loginproblems.html'; + $defaulttype = 'default'; + %lt = &Apache::lonlocal::texthash ( + del => 'Delete?', + rep => 'Replace:', + upl => 'Upload:', + default => 'Default', + custom => 'Custom', + ); + %langchoices = &Apache::lonlocal::texthash(&get_languages_hash()); + my @currlangs; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'helpurl'}) eq 'HASH') { + foreach my $key (sort(keys(%{$settings->{'helpurl'}}))) { + next if ($settings->{'helpurl'}{$key} eq ''); + $url{$key} = $settings->{'helpurl'}{$key}.'?inhibitmenu=yes'; + $type{$key} = 'custom'; + unless ($key eq 'nolang') { + push(@currlangs,$key); + } + } + } elsif ($settings->{'helpurl'} ne '') { + $type{'nolang'} = 'custom'; + $url{'nolang'} = $settings->{'helpurl'}.'?inhibitmenu=yes'; + } + } + foreach my $lang ('nolang',sort(@currlangs)) { + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''; + if ($url{$lang} eq '') { + $url{$lang} = $defaulturl; + } + if ($type{$lang} eq '') { + $type{$lang} = $defaulttype; + } + $datatable .= ''; + if ($lang eq 'nolang') { + $datatable .= &mt('Log-in help page if no specific language file: [_1]', + &Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500)); + } else { + $datatable .= &mt('Log-in help page for language: [_1] is [_2]', + $langchoices{$lang}, + &Apache::loncommon::modal_link($url{$lang},$lt{$type{$lang}},600,500)); + } + $datatable .= ''."\n". + ''; + if ($type{$lang} eq 'custom') { + $datatable .= ' '.$lt{'rep'}.''; + } else { + $datatable .= $lt{'upl'}; + } + $datatable .='
'; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; } + $datatable .= ''; + $itemcount ++; } - foreach my $item (@links) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + my @addlangs; + foreach my $lang (sort(keys(%langchoices))) { + next if ((grep(/^\Q$lang\E$/,@currlangs)) || ($lang eq 'x_chef')); + push(@addlangs,$lang); + } + if (@addlangs > 0) { + my %toadd; + map { $toadd{$_} = $langchoices{$_} ; } @addlangs; + $toadd{''} = &mt('Select'); + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''. + &mt('Add log-in help page for a specific language:').' '. + &Apache::loncommon::select_form('','loginhelpurl_add_lang',\%toadd). + ''.$lt{'upl'}.'
'; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; } + $datatable .= ''; + $itemcount ++; } + $datatable .= &captcha_choice('login',$settings,$itemcount); } - my %alt_text = &Apache::lonlocal::texthash ( img => 'Log-in banner', - logo => 'Institution Logo', - domlogo => 'Domain Logo', - login => 'Login box'); - my $itemcount = 1; - my ($css_class,$datatable); - foreach my $item (@toggles) { - $css_class = $itemcount%2?' class="LC_odd_row"':''; - $datatable .= - ''.$choices{$item}. - ''. - ' '. - ''; - $itemcount ++; - } - $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext,$loginheader); - $datatable .= ''; return $datatable; } sub login_choices { my %choices = &Apache::lonlocal::texthash ( - coursecatalog => 'Display Course Catalog link?', - adminmail => "Display Administrator's E-mail Address?", - newuser => "Link to create a user account", - img => "Header", - logo => "Main Logo", - domlogo => "Domain Logo", - login => "Log-in Header", - textcol => "Text color", - bgcol => "Box color", - bgs => "Background colors", - links => "Link colors", - font => "Font color", - pgbg => "Page", - mainbg => "Main panel", - sidebg => "Side panel", - link => "Link", - alink => "Active link", - vlink => "Visited link", + coursecatalog => 'Display Course/Community Catalog link?', + adminmail => "Display Administrator's E-mail Address?", + disallowlogin => "Login page requests redirected", + hostid => "Server", + server => "Redirect to:", + serverpath => "Path", + custompath => "Custom", + exempt => "Exempt IP(s)", + directlogin => "No redirect", + newuser => "Link to create a user account", + img => "Header", + logo => "Main Logo", + domlogo => "Domain Logo", + login => "Log-in Header", + textcol => "Text color", + bgcol => "Box color", + bgs => "Background colors", + links => "Link colors", + font => "Font color", + pgbg => "Header", + mainbg => "Page", + sidebg => "Login box", + link => "Link", + alink => "Active link", + vlink => "Visited link", ); return %choices; } @@ -797,6 +1145,7 @@ sub print_rolecolors { my %defaults = ( img => $defaultdesign{$role.'.img'}, font => $defaultdesign{$role.'.font'}, + fontmenu => $defaultdesign{$role.'.fontmenu'}, ); foreach my $item (@bgs) { $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item}; @@ -814,6 +1163,10 @@ sub print_rolecolors { $designs{'font'} = $settings->{$role}->{'font'}; $is_custom{'font'} = 1; } + if ($settings->{$role}->{'fontmenu'} ne '') { + $designs{'fontmenu'} = $settings->{$role}->{'fontmenu'}; + $is_custom{'fontmenu'} = 1; + } foreach my $item (@bgs) { if ($settings->{$role}->{$item} ne '') { $designs{'bgs'}{$item} = $settings->{$role}->{$item}; @@ -832,6 +1185,10 @@ sub print_rolecolors { $designs{img} = $designhash{$dom.'.'.$role.'.img'}; $is_custom{'img'} = 1; } + if ($designhash{$dom.'.'.$role.'.fontmenu'} ne '') { + $designs{fontmenu} = $designhash{$dom.'.'.$role.'.fontmenu'}; + $is_custom{'fontmenu'} = 1; + } if ($designhash{$dom.'.'.$role.'.font'} ne '') { $designs{font} = $designhash{$dom.'.'.$role.'.font'}; $is_custom{'font'} = 1; @@ -858,7 +1215,8 @@ sub print_rolecolors { sub display_color_options { my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs, - $images,$bgs,$links,$alt_text,$rowtotal,$logintext,$loginheader) = @_; + $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_; + my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; my $css_class = $itemcount%2?' class="LC_odd_row"':''; my $datatable = ''. ''.$choices->{'font'}.''; @@ -867,32 +1225,53 @@ sub display_color_options { } else { $datatable .= ' '; } - my $fontlink = &color_pick($phase,$role,'font',$choices->{'font'},$designs->{'font'}); + my $current_color = $designs->{'font'} ? $designs->{'font'} : $defaults->{'font'}; + $datatable .= ''. - ' '.$fontlink. - '    '. - ''; + ' '. + ' '; + unless ($role eq 'login') { + $datatable .= ''. + ''.$choices->{'fontmenu'}.''; + if (!$is_custom->{'fontmenu'}) { + $datatable .= ''.&mt('Default in use:').' '.$defaults->{'fontmenu'}.''; + } else { + $datatable .= ' '; + } + $current_color = $designs->{'fontmenu'} ? + $designs->{'fontmenu'} : $defaults->{'fontmenu'}; + $datatable .= ''. + ' '. + ' '; + } my $switchserver = &check_switchserver($dom,$confname); foreach my $img (@{$images}) { $itemcount ++; $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= ''. - ''.$choices->{$img}.''; + ''.$choices->{$img}; my ($imgfile,$img_import,$login_hdr_pick,$logincolors); + if ($role eq 'login') { + if ($img eq 'login') { + $login_hdr_pick = + &login_header_options($img,$role,$defaults,$is_custom,$choices); + $logincolors = + &login_text_colors($img,$role,$logintext,$phase,$choices, + $designs); + } elsif ($img ne 'domlogo') { + $datatable.= &logo_display_options($img,$defaults,$designs); + } + } + $datatable .= ''; if ($designs->{$img} ne '') { $imgfile = $designs->{$img}; $img_import = ($imgfile =~ m{^/adm/}); } else { $imgfile = $defaults->{$img}; } - if ($img eq 'login') { - $login_hdr_pick = &login_header_options($img,$role,$defaults,$is_custom,$choices, - $loginheader); - $logincolors = - &login_text_colors($img,$role,$logintext,$phase,$choices,$designs); - } if ($imgfile) { my ($showfile,$fullsize); if ($imgfile =~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) { @@ -914,11 +1293,11 @@ sub display_color_options { $showfile = $imgfile; my $imgdir = $1; my $filename = $2; - if (-e "/home/httpd/html/$imgdir/tn-".$filename) { + if (-e "$londocroot/$imgdir/tn-".$filename) { $showfile = "/$imgdir/tn-".$filename; } else { - my $input = "/home/httpd/html".$imgfile; - my $output = '/home/httpd/html/'.$imgdir.'/tn-'.$filename; + my $input = $londocroot.$imgfile; + my $output = "$londocroot/$imgdir/tn-".$filename; if (!-e $output) { my ($width,$height) = &thumb_dimensions(); my ($fullwidth,$fullheight) = &check_dimensions($input); @@ -926,7 +1305,7 @@ sub display_color_options { if ($fullwidth > $width && $fullheight > $height) { my $size = $width.'x'.$height; system("convert -sample $size $input $output"); - $showfile = '/'.$imgdir.'/tn-'.$filename; + $showfile = "/$imgdir/tn-".$filename; } } } @@ -955,8 +1334,8 @@ sub display_color_options { } $datatable .= ''; if ($img eq 'login') { - $datatable .= $login_hdr_pick; - } + $datatable .= $login_hdr_pick; + } $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import, $showfile,$fullsize,$role,$img,$imgfile,$logincolors); } else { @@ -970,7 +1349,9 @@ sub display_color_options { if ($switchserver) { $datatable .= &mt('Upload to library server: [_1]',$switchserver); } else { - $datatable .=' '; + if ($img ne 'login') { # suppress file selection for Log-in header + $datatable .=' '; + } } $datatable .= ''; } @@ -981,7 +1362,7 @@ sub display_color_options { my $bgs_def; foreach my $item (@{$bgs}) { if (!$is_custom->{$item}) { - $bgs_def .= ''.$choices->{$item}.'    
'.$defaults->{'bgs'}{$item}.''; + $bgs_def .= ''.$choices->{$item}.'    
'.$defaults->{'bgs'}{$item}.''; } } if ($bgs_def) { @@ -991,13 +1372,14 @@ sub display_color_options { } $datatable .= ''. ''; + foreach my $item (@{$bgs}) { - my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item}); - $datatable .= ''; } $datatable .= '
'.$link; + $datatable .= ''; + my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item}; if ($designs->{'bgs'}{$item}) { - $datatable .= '    '; + $datatable .= ' '; } - $datatable .= '
'; @@ -1019,34 +1401,50 @@ sub display_color_options { $datatable .= ''. ''; foreach my $item (@{$links}) { - $datatable .= ''; } $$rowtotal += $itemcount; return $datatable; } +sub logo_display_options { + my ($img,$defaults,$designs) = @_; + my $checkedon; + if (ref($defaults) eq 'HASH') { + if (ref($defaults->{'showlogo'}) eq 'HASH') { + if ($defaults->{'showlogo'}{$img}) { + $checkedon = 'checked="checked" '; + } + } + } + if (ref($designs) eq 'HASH') { + if (ref($designs->{'showlogo'}) eq 'HASH') { + if (defined($designs->{'showlogo'}{$img})) { + if ($designs->{'showlogo'}{$img} == 0) { + $checkedon = ''; + } elsif ($designs->{'showlogo'}{$img} == 1) { + $checkedon = 'checked="checked" '; + } + } + } + } + return '
'."\n"; +} + sub login_header_options { - my ($img,$role,$defaults,$is_custom,$choices,$loginheader) = @_; - my $image_checked = ' checked="checked" '; - my $text_checked = ' '; - if ($loginheader eq 'text') { - $image_checked = ' '; - $text_checked = ' checked="checked" '; - } - my $output = '   '. - '
'."\n"; + my ($img,$role,$defaults,$is_custom,$choices) = @_; + my $output = ''; if ((!$is_custom->{'textcol'}) || (!$is_custom->{'bgcol'})) { - $output .= &mt('Text default(s)').':
'; + $output .= &mt('Text default(s):').'
'; if (!$is_custom->{'textcol'}) { $output .= $choices->{'textcol'}.': '.$defaults->{'logintext'}{'textcol'}. '   '; @@ -1082,25 +1480,31 @@ sub login_text_colors { sub image_changes { my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_; my $output; - if (!$is_custom) { - if ($img eq 'login') { + if ($img eq 'login') { + # suppress image for Log-in header + } elsif (!$is_custom) { + if ($img ne 'domlogo') { $output .= &mt('Default image:').'
'; } else { $output .= &mt('Default in use:').'
'; } } - if ($img_import) { - $output .= ''; - } - $output .= ''.$alt_text.''; - if ($is_custom) { - $output .= '
'; + if ($is_custom) { + $output .= ''. + ''; + unless (($context eq 'requestcourses') || + ($context eq 'requestauthor')) { + $datatable .= ''; + '" value="'.$currdefquota. + '" size="5" /> Mb'; + } + $datatable .= ''; } } } - my $defaultquota = '20'; - if (ref($settings) eq 'HASH') { - if (defined($settings->{'default'})) { - $defaultquota = $settings->{'default'}; + unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + $defaultquota = '20'; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'defaultquota'}) eq 'HASH') { + $defaultquota = $settings->{'defaultquota'}->{'default'}; + } elsif (defined($settings->{'default'})) { + $defaultquota = $settings->{'default'}; + } } } $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; $datatable .= ''. ''. - ''; + ''; + unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + $datatable .= ''; + } + $datatable .= ''; + $typecount ++; + $css_class = $typecount%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''. + ''; $$rowtotal += $typecount; return $datatable; } +sub print_requestmail { + my ($dom,$action,$settings,$rowtotal) = @_; + my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows); + $now = time; + $rows = 0; + %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now); + foreach my $server (keys(%dompersonnel)) { + foreach my $user (sort(keys(%{$dompersonnel{$server}}))) { + my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user); + if (!grep(/^$uname:$udom$/,@domcoord)) { + push(@domcoord,$uname.':'.$udom); + } + } + } + if (ref($settings) eq 'HASH') { + if (ref($settings->{'notify'}) eq 'HASH') { + if ($settings->{'notify'}{'approval'} ne '') { + @currapproval = split(',',$settings->{'notify'}{'approval'}); + } + } + } + if (@currapproval) { + foreach my $dc (@currapproval) { + unless (grep(/^\Q$dc\E$/,@domcoord)) { + push(@domcoord,$dc); + } + } + } + @domcoord = sort(@domcoord); + my $numinrow = 4; + my $numdc = @domcoord; + my $css_class = 'class="LC_odd_row"'; + my $text; + if ($action eq 'requestcourses') { + $text = &mt('Receive notification of course requests requiring approval'); + } else { + $text = &mt('Receive notification of authoring space requests requiring approval') + } + $datatable = ''. + ' '. + ' '; + $$rowtotal += $rows; + return $datatable; +} + sub print_autoenroll { my ($dom,$settings,$rowtotal) = @_; my $autorun = &Apache::lonnet::auto_run(undef,$dom), - my ($defdom,$runon,$runoff); + my ($defdom,$runon,$runoff,$coownerson,$coownersoff); if (ref($settings) eq 'HASH') { if (exists($settings->{'run'})) { if ($settings->{'run'} eq '0') { @@ -1218,6 +2031,18 @@ sub print_autoenroll { $runon = ' '; } } + if (exists($settings->{'co-owners'})) { + if ($settings->{'co-owners'} eq '0') { + $coownersoff = ' checked="checked" '; + $coownerson = ' '; + } else { + $coownerson = ' checked="checked" '; + $coownersoff = ' '; + } + } else { + $coownersoff = ' checked="checked" '; + $coownerson = ' '; + } if (exists($settings->{'sender_domain'})) { $defdom = $settings->{'sender_domain'}; } @@ -1248,8 +2073,16 @@ sub print_autoenroll { &mt('username').': '. '  '.&mt('domain'). - ': '.$domform.''; - $$rowtotal += 2; + ': '.$domform.''. + ''. + ''. + ''. + ''; + $$rowtotal += 3; return $datatable; } @@ -1291,9 +2124,17 @@ sub print_autoupdate { $classlistsoff.'value="0" />'.&mt('No').''. ''; $$rowtotal += 2; + } elsif ($position eq 'middle') { + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + my $numinrow = 3; + my $locknamesettings; + $datatable .= &insttypes_row($settings,$types,$usertypes, + $dom,$numinrow,$othertitle, + 'lockablenames'); + $$rowtotal ++; } else { my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); - my @fields = ('lastname','firstname','middlename','gen', + my @fields = ('lastname','firstname','middlename','generation', 'permanentemail','id'); my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); my $numrows = 0; @@ -1314,6 +2155,56 @@ sub print_autoupdate { return $datatable; } +sub print_autocreate { + my ($dom,$settings,$rowtotal) = @_; + my (%createon,%createoff); + my $curr_dc; + my @types = ('xml','req'); + if (ref($settings) eq 'HASH') { + foreach my $item (@types) { + $createoff{$item} = ' checked="checked" '; + $createon{$item} = ' '; + if (exists($settings->{$item})) { + if ($settings->{$item}) { + $createon{$item} = ' checked="checked" '; + $createoff{$item} = ' '; + } + } + } + $curr_dc = $settings->{'xmldc'}; + } else { + foreach my $item (@types) { + $createoff{$item} = ' checked="checked" '; + $createon{$item} = ' '; + } + } + $$rowtotal += 2; + my $datatable=''. + ''. + ''. + ''. + ''; + $$rowtotal ++ ; + } else { + $datatable .= $dctable.''; + } + return $datatable; +} + sub print_directorysrch { my ($dom,$settings,$rowtotal) = @_; my $srchon = ' '; @@ -1374,8 +2265,8 @@ sub print_directorysrch { $$rowtotal += 2; if (ref($usertypes) eq 'HASH') { if (keys(%{$usertypes}) > 0) { - $datatable .= &users_cansearch_row($settings,$types,$usertypes,$dom, - $numinrow,$othertitle); + $datatable .= &insttypes_row($settings,$types,$usertypes,$dom, + $numinrow,$othertitle,'cansearch'); $cansrchrow = 1; } } @@ -1390,7 +2281,7 @@ sub print_directorysrch { foreach my $title (@{$titleorder}) { if (defined($searchtitles->{$title})) { my $check = ' '; - if (ref($settings) eq 'HASH') { + if (ref($settings) eq 'HASH') { if (ref($settings->{'searchby'}) eq 'ARRAY') { if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) { $check = ' checked="checked" '; @@ -1431,11 +2322,13 @@ sub print_contacts { my ($dom,$settings,$rowtotal) = @_; my $datatable; my @contacts = ('adminemail','supportemail'); - my (%checked,%to,%otheremails); - my @mailings = ('errormail','packagesmail','helpdeskmail'); + my (%checked,%to,%otheremails,%bccemails); + my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail', + 'requestsmail'); foreach my $type (@mailings) { $otheremails{$type} = ''; } + $bccemails{'helpdeskmail'} = ''; if (ref($settings) eq 'HASH') { foreach my $item (@contacts) { if (exists($settings->{$item})) { @@ -1451,7 +2344,12 @@ sub print_contacts { } } $otheremails{$type} = $settings->{$type}{'others'}; + if ($type eq 'helpdeskmail') { + $bccemails{$type} = $settings->{$type}{'bcc'}; + } } + } elsif ($type eq 'lonstatusmail') { + $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; } } } else { @@ -1459,30 +2357,25 @@ sub print_contacts { $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'}; $checked{'errormail'}{'adminemail'} = ' checked="checked" '; $checked{'packagesmail'}{'adminemail'} = ' checked="checked" '; - $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" '; + $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" '; + $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; + $checked{'requestsmail'}{'adminemail'} = ' checked="checked" '; } my ($titles,$short_titles) = &contact_titles(); my $rownum = 0; my $css_class; foreach my $item (@contacts) { - if ($rownum%2) { - $css_class = ''; - } else { - $css_class = ' class="LC_odd_row" '; - } + $rownum ++; + $css_class = $rownum%2?' class="LC_odd_row"':''; $datatable .= ''. ''; - $rownum ++; } foreach my $type (@mailings) { - if ($rownum%2) { - $css_class = ''; - } else { - $css_class = ' class="LC_odd_row" '; - } + $rownum ++; + $css_class = $rownum%2?' class="LC_odd_row"':''; $datatable .= ''. ''. @@ -1497,21 +2390,866 @@ sub print_contacts { } $datatable .= '
'.&mt('Others').':  '. ''. - ''."\n"; - $rownum ++; + 'value="'.$otheremails{$type}.'" />'; + if ($type eq 'helpdeskmail') { + $datatable .= '
'.&mt('Bcc:').(' 'x6). + ''; + } + $datatable .= ''."\n"; } $$rowtotal += $rownum; return $datatable; } +sub print_helpsettings { + my ($dom,$confname,$settings,$rowtotal) = @_; + my ($datatable,$itemcount); + $itemcount = 1; + my (%choices,%defaultchecked,@toggles); + $choices{'submitbugs'} = &mt('Display link to: [_1]?', + &Apache::loncommon::modal_link('http://bugs.loncapa.org', + &mt('LON-CAPA bug tracker'),600,500)); + %defaultchecked = ('submitbugs' => 'on'); + @toggles = ('submitbugs',); + + ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, + \%choices,$itemcount); + return $datatable; +} + +sub radiobutton_prefs { + my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_; + return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') && + (ref($choices) eq 'HASH')); + + my (%checkedon,%checkedoff,$datatable,$css_class); + + foreach my $item (@{$toggles}) { + if ($defaultchecked->{$item} eq 'on') { + $checkedon{$item} = ' checked="checked" '; + $checkedoff{$item} = ' '; + } elsif ($defaultchecked->{$item} eq 'off') { + $checkedoff{$item} = ' checked="checked" '; + $checkedon{$item} = ' '; + } + } + if (ref($settings) eq 'HASH') { + foreach my $item (@{$toggles}) { + if ($settings->{$item} eq '1') { + $checkedon{$item} = ' checked="checked" '; + $checkedoff{$item} = ' '; + } elsif ($settings->{$item} eq '0') { + $checkedoff{$item} = ' checked="checked" '; + $checkedon{$item} = ' '; + } + } + } + foreach my $item (@{$toggles}) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= + ''. + ''. + ''; + $itemcount ++; + } + return ($datatable,$itemcount); +} + +sub print_coursedefaults { + my ($position,$dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable); + my $itemcount = 1; + if ($position eq 'top') { + my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles); + %choices = + &Apache::lonlocal::texthash ( + canuse_pdfforms => 'Course/Community users can create/upload PDF forms', + ); + %defaultchecked = ('canuse_pdfforms' => 'off'); + @toggles = ('canuse_pdfforms',); + ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, + \%choices,$itemcount); + $$rowtotal += $itemcount; + } else { + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + my %choices = + &Apache::lonlocal::texthash ( + anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys', + ); + my $currdefresponder; + if (ref($settings) eq 'HASH') { + $currdefresponder = $settings->{'anonsurvey_threshold'}; + } + if (!$currdefresponder) { + $currdefresponder = 10; + } elsif ($currdefresponder < 1) { + $currdefresponder = 1; + } + $datatable .= + ''. + ''; + } + return $datatable; +} + +sub print_usersessions { + my ($position,$dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable,%checked,%choices); + my (%by_ip,%by_location,@intdoms); + &build_location_hashes(\@intdoms,\%by_ip,\%by_location); + + my @alldoms = &Apache::lonnet::all_domains(); + my %serverhomes = %Apache::lonnet::serverhomeIDs; + my %servers = &Apache::lonnet::internet_dom_servers($dom); + my %altids = &id_for_thisdom(%servers); + my $itemcount = 1; + if ($position eq 'top') { + if (keys(%serverhomes) > 1) { + my %spareid = ¤t_offloads_to($dom,$settings,\%servers); + $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$rowtotal); + } else { + $datatable .= ''; + $itemcount ++; + } + } + } + $$rowtotal += $itemcount; + return $datatable; +} + +sub build_location_hashes { + my ($intdoms,$by_ip,$by_location) = @_; + return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') && + (ref($by_location) eq 'HASH')); + my %iphost = &Apache::lonnet::get_iphost(); + my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary'); + my $primary_ip = &Apache::lonnet::get_host_ip($primary_id); + if (ref($iphost{$primary_ip}) eq 'ARRAY') { + foreach my $id (@{$iphost{$primary_ip}}) { + my $intdom = &Apache::lonnet::internet_dom($id); + unless(grep(/^\Q$intdom\E$/,@{$intdoms})) { + push(@{$intdoms},$intdom); + } + } + } + foreach my $ip (keys(%iphost)) { + if (ref($iphost{$ip}) eq 'ARRAY') { + foreach my $id (@{$iphost{$ip}}) { + my $location = &Apache::lonnet::internet_dom($id); + if ($location) { + next if (grep(/^\Q$location\E$/,@{$intdoms})); + if (ref($by_ip->{$ip}) eq 'ARRAY') { + unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) { + push(@{$by_ip->{$ip}},$location); + } + } else { + $by_ip->{$ip} = [$location]; + } + } + } + } + } + foreach my $ip (sort(keys(%{$by_ip}))) { + if (ref($by_ip->{$ip}) eq 'ARRAY') { + @{$by_ip->{$ip}} = sort(@{$by_ip->{$ip}}); + my $first = $by_ip->{$ip}->[0]; + if (ref($by_location->{$first}) eq 'ARRAY') { + unless (grep(/^\Q$ip\E$/,@{$by_location->{$first}})) { + push(@{$by_location->{$first}},$ip); + } + } else { + $by_location->{$first} = [$ip]; + } + } + } + return; +} + +sub current_offloads_to { + my ($dom,$settings,$servers) = @_; + my (%spareid,%otherdomconfigs); + if (ref($servers) eq 'HASH') { + foreach my $lonhost (sort(keys(%{$servers}))) { + my $gotspares; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'spares'}) eq 'HASH') { + if (ref($settings->{'spares'}{$lonhost}) eq 'HASH') { + $spareid{$lonhost}{'primary'} = $settings->{'spares'}{$lonhost}{'primary'}; + $spareid{$lonhost}{'default'} = $settings->{'spares'}{$lonhost}{'default'}; + $gotspares = 1; + } + } + } + unless ($gotspares) { + my $gotspares; + my $serverhomeID = + &Apache::lonnet::get_server_homeID($servers->{$lonhost}); + my $serverhomedom = + &Apache::lonnet::host_domain($serverhomeID); + if ($serverhomedom ne $dom) { + if (ref($otherdomconfigs{$serverhomedom} eq 'HASH')) { + if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') { + if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') { + $spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'}; + $spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'}; + $gotspares = 1; + } + } + } else { + $otherdomconfigs{$serverhomedom} = + &Apache::lonnet::get_dom('configuration',['usersessions'],$serverhomedom); + if (ref($otherdomconfigs{$serverhomedom}) eq 'HASH') { + if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}) eq 'HASH') { + if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}) eq 'HASH') { + if (ref($otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{$lonhost}) eq 'HASH') { + $spareid{$lonhost}{'primary'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'primary'}; + $spareid{$lonhost}{'default'} = $otherdomconfigs{$serverhomedom}{'usersessions'}{'spares'}{'default'}; + $gotspares = 1; + } + } + } + } + } + } + } + unless ($gotspares) { + if ($lonhost eq $Apache::lonnet::perlvar{'lonHostID'}) { + $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'}; + $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'}; + } else { + my $server_hostname = &Apache::lonnet::hostname($lonhost); + my $server_homeID = &Apache::lonnet::get_server_homeID($server_hostname); + if ($server_homeID eq $Apache::lonnet::perlvar{'lonHostID'}) { + $spareid{$lonhost}{'primary'} = $Apache::lonnet::spareid{'primary'}; + $spareid{$lonhost}{'default'} = $Apache::lonnet::spareid{'default'}; + } else { + my %what = ( + spareid => 1, + ); + my ($result,$returnhash) = + &Apache::lonnet::get_remote_globals($lonhost,\%what); + if ($result eq 'ok') { + if (ref($returnhash) eq 'HASH') { + if (ref($returnhash->{'spareid'}) eq 'HASH') { + $spareid{$lonhost}{'primary'} = $returnhash->{'spareid'}->{'primary'}; + $spareid{$lonhost}{'default'} = $returnhash->{'spareid'}->{'default'}; + } + } + } + } + } + } + } + } + return %spareid; +} + +sub spares_row { + my ($dom,$servers,$spareid,$serverhomes,$altids,$rowtotal) = @_; + my $css_class; + my $numinrow = 4; + my $itemcount = 1; + my $datatable; + my %typetitles = &sparestype_titles(); + if ((ref($servers) eq 'HASH') && (ref($spareid) eq 'HASH') && (ref($altids) eq 'HASH')) { + foreach my $server (sort(keys(%{$servers}))) { + my $serverhome = &Apache::lonnet::get_server_homeID($servers->{$server}); + my ($othercontrol,$serverdom); + if ($serverhome ne $server) { + $serverdom = &Apache::lonnet::host_domain($serverhome); + $othercontrol = &mt('Session offloading controlled by domain: [_1]',''.$serverdom.''); + } else { + $serverdom = &Apache::lonnet::host_domain($server); + if ($serverdom ne $dom) { + $othercontrol = &mt('Session offloading controlled by domain: [_1]',''.$serverdom.''); + } + } + next unless (ref($spareid->{$server}) eq 'HASH'); + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ' + '."\n". + ''."\n". + ''."\n"; + } + $itemcount ++; + } + } + $$rowtotal += $itemcount; + return $datatable; +} + +sub possible_newspares { + my ($server,$currspares,$serverhomes,$altids) = @_; + my $serverhostname = &Apache::lonnet::hostname($server); + my %excluded; + if ($serverhostname ne '') { + %excluded = ( + $serverhostname => 1, + ); + } + if (ref($currspares) eq 'HASH') { + foreach my $type (keys(%{$currspares})) { + if (ref($currspares->{$type}) eq 'ARRAY') { + if (@{$currspares->{$type}} > 0) { + foreach my $curr (@{$currspares->{$type}}) { + my $hostname = &Apache::lonnet::hostname($curr); + $excluded{$hostname} = 1; + } + } + } + } + } + my @choices; + if ((ref($serverhomes) eq 'HASH') && (ref($altids) eq 'HASH')) { + if (keys(%{$serverhomes}) > 1) { + foreach my $name (sort(keys(%{$serverhomes}))) { + unless ($excluded{$name}) { + if (exists($altids->{$serverhomes->{$name}})) { + push(@choices,$altids->{$serverhomes->{$name}}); + } else { + push(@choices,$serverhomes->{$name}); + } + } + } + } + } + return sort(@choices); +} + +sub print_loadbalancing { + my ($dom,$settings,$rowtotal) = @_; + my $primary_id = &Apache::lonnet::domain($dom,'primary'); + my $intdom = &Apache::lonnet::internet_dom($primary_id); + my $numinrow = 1; + my $datatable; + my %servers = &Apache::lonnet::internet_dom_servers($dom); + my (%currbalancer,%currtargets,%currrules,%existing); + if (ref($settings) eq 'HASH') { + %existing = %{$settings}; + } + if ((keys(%servers) > 1) || (keys(%existing) > 0)) { + &get_loadbalancers_config(\%servers,\%existing,\%currbalancer, + \%currtargets,\%currrules); + } else { + return; + } + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($dom); + my $rownum = 6; + if (ref($types) eq 'ARRAY') { + $rownum += scalar(@{$types}); + } + my @css_class = ('LC_odd_row','LC_even_row'); + my $balnum = 0; + my $islast; + my (@toshow,$disabledtext); + if (keys(%currbalancer) > 0) { + @toshow = sort(keys(%currbalancer)); + if (scalar(@toshow) < scalar(keys(%servers)) + 1) { + push(@toshow,''); + } + } else { + @toshow = (''); + $disabledtext = &mt('No existing load balancer'); + } + foreach my $lonhost (@toshow) { + if ($balnum == scalar(@toshow)-1) { + $islast = 1; + } else { + $islast = 0; + } + my $cssidx = $balnum%2; + my $targets_div_style = 'display: none'; + my $disabled_div_style = 'display: block'; + my $homedom_div_style = 'display: none'; + $datatable .= ''. + ''; + my $rem = $i%($numinrow); + if ($rem == 0) { + if (($i > 0) && ($i < $numspares-1)) { + $targettable .= ''; + } + if ($i < $numspares-1) { + $targettable .= ''; + } + } + } + if ($targettable ne '') { + my $rem = $numspares%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $targettable .= ''; + } elsif ($colsleft == 1) { + $targettable .= ''; + } + $datatable .= ''.$typetitles{$sparetype}.'
'. + '
'."\n". - &color_pick($phase,$role,$item,$choices->{$item}, - $designs->{'links'}{$item}); + my $color = $designs->{'link'}{$item} ? $designs->{'link'}{$item} : $defaults->{'links'}{$item}; + $datatable .= ''."\n"; + if ($designs->{'links'}{$item}) { - $datatable.='    '; + $datatable.=' '; } - $datatable .= '
'.$logincolors.' '.&mt('Replace:').'
'; + if ($img eq 'login') { # suppress image for Log-in header + $output .= '
'.$logincolors; } else { - $output .= ''.$logincolors.&mt('Upload:').'
'; + if ($img_import) { + $output .= ''; + } + $output .= ''.$alt_text.'
'.$logincolors.' '.&mt('Replace:').'
'; + } else { + $output .= '
'.$logincolors.&mt('Upload:').'
'; + } } return $output; } @@ -1113,93 +1517,502 @@ sub color_pick { return $link; } -sub color_pick_js { - my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition(); - my $output = <<"ENDCOL"; - function pclose() { - parmwin=window.open("/adm/rat/empty.html","LONCAPAparms","height=350,width=350,scrollbars=no,menubar=no"); - parmwin.close(); - } - - $pjump_def - - function psub() { - pclose(); - if (document.parmform.pres_marker.value!='') { - if (document.parmform.pres_type.value!='') { - eval('document.display.'+ - document.parmform.pres_marker.value+ - '.value=document.parmform.pres_value.value;'); - } - } else { - document.parmform.pres_value.value=''; - document.parmform.pres_marker.value=''; - } - } - - function get_id (span_id) { - if (document.getElementById) { - return document.getElementById(span_id); - } - if (document.all) { - return document.all[span_id]; - } - return false; - } - - function colchg_span (span_id_str,new_color_item) { - var span_ref = get_id(span_id_str); - if (span_ref.style) { span_ref = span_ref.style; } - span_ref.background = new_color_item.value; - span_ref.backgroundColor = new_color_item.value; - span_ref.bgColor = new_color_item.value; - } - -ENDCOL - return $output; -} - sub print_quotas { - my ($dom,$settings,$rowtotal) = @_; - my $datatable; + my ($dom,$settings,$rowtotal,$action) = @_; + my $context; + if ($action eq 'quotas') { + $context = 'tools'; + } else { + $context = $action; + } + my ($datatable,$defaultquota,@usertools,@options,%validations); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $typecount = 0; - my $css_class; + my ($css_class,%titles); + if ($context eq 'requestcourses') { + @usertools = ('official','unofficial','community'); + @options =('norequest','approval','validate','autolimit'); + %validations = &Apache::lonnet::auto_courserequest_checks($dom); + %titles = &courserequest_titles(); + } elsif ($context eq 'requestauthor') { + @usertools = ('author'); + @options = ('norequest','approval','automatic'); + %titles = &authorrequest_titles(); + } else { + @usertools = ('aboutme','blog','webdav','portfolio'); + %titles = &tool_titles(); + } if (ref($types) eq 'ARRAY') { foreach my $type (@{$types}) { + my $currdefquota; + unless (($context eq 'requestcourses') || + ($context eq 'requestauthor')) { + if (ref($settings) eq 'HASH') { + if (ref($settings->{defaultquota}) eq 'HASH') { + $currdefquota = $settings->{defaultquota}->{$type}; + } else { + $currdefquota = $settings->{$type}; + } + } + } if (defined($usertypes->{$type})) { $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; - $datatable .= ''. + $datatable .= ''. '
'.$usertypes->{$type}.''; + if ($context eq 'requestcourses') { + $datatable .= ''; + } + my %cell; + foreach my $item (@usertools) { + if ($context eq 'requestcourses') { + my ($curroption,$currlimit); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + $curroption = $settings->{$item}->{$type}; + if ($curroption =~ /^autolimit=(\d*)$/) { + $currlimit = $1; + } + } + } + if (!$curroption) { + $curroption = 'norequest'; + } + $datatable .= ''; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{$type}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } elsif ($option eq 'autolimit') { + if ($curroption =~ /^autolimit/) { + $checked = ' checked="checked"'; + } + } + $cell{$item} .= ''; + if ($option eq 'autolimit') { + $cell{$item} .= ' '; + } + $cell{$item} .= ' '; + if ($option eq 'autolimit') { + $cell{$item} .= $titles{'unlimited'}; + } + } + } elsif ($context eq 'requestauthor') { + my $curroption; + if (ref($settings) eq 'HASH') { + $curroption = $settings->{$type}; + } + if (!$curroption) { + $curroption = 'norequest'; + } + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } + $datatable .= '  '; + } + } else { + my $checked = 'checked="checked" '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + if ($settings->{$item}->{$type} == 0) { + $checked = ''; + } elsif ($settings->{$item}->{$type} == 1) { + $checked = 'checked="checked" '; + } + } + } + $datatable .= '  '; + } + } + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'.$titles{$item}.'
'.$cell{$item}.'
'; + } + $datatable .= '
'. ' Mb
'.$othertitle.''. - ' Mb
'; + if ($context eq 'requestcourses') { + $datatable .= ''; + } + my %defcell; + foreach my $item (@usertools) { + if ($context eq 'requestcourses') { + my ($curroption,$currlimit); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + $curroption = $settings->{$item}->{'default'}; + if ($curroption =~ /^autolimit=(\d*)$/) { + $currlimit = $1; + } + } + } + if (!$curroption) { + $curroption = 'norequest'; + } + $datatable .= ''; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{'default'}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } elsif ($option eq 'autolimit') { + if ($curroption =~ /^autolimit/) { + $checked = ' checked="checked"'; + } + } + $defcell{$item} .= ''; + if ($option eq 'autolimit') { + $defcell{$item} .= ' '; + } + $defcell{$item} .= ' '; + if ($option eq 'autolimit') { + $defcell{$item} .= $titles{'unlimited'}; + } + } + } elsif ($context eq 'requestauthor') { + my $curroption; + if (ref($settings) eq 'HASH') { + $curroption = $settings->{'default'}; + } + if (!$curroption) { + $curroption = 'norequest'; + } + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } + $datatable .= '  '; + } + } else { + my $checked = 'checked="checked" '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + if ($settings->{$item}->{'default'} == 0) { + $checked = ''; + } elsif ($settings->{$item}->{'default'} == 1) { + $checked = 'checked="checked" '; + } + } + } + $datatable .= '  '; + } + } + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'.$titles{$item}.'
'.$defcell{$item}.'
'; + } + $datatable .= '
'. + ' Mb
'.&mt('LON-CAPA Advanced Users').' '; + if ($context eq 'requestcourses') { + $datatable .= &mt('(overrides affiliation, if set)'). + ''. + ''; + } else { + $datatable .= &mt('(overrides affiliation, if checked)'). + ''. + ''; + my $checked = ''; + if ($curroption eq '') { + $checked = ' checked="checked"'; + } + $advcell{$item} .= '  '; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{'_LC_adv'}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($val eq $curroption) { + $checked = ' checked="checked"'; + } elsif ($option eq 'autolimit') { + if ($curroption =~ /^autolimit/) { + $checked = ' checked="checked"'; + } + } + $advcell{$item} .= ''; + if ($option eq 'autolimit') { + $advcell{$item} .= ' '; + } + $advcell{$item} .= ' '; + if ($option eq 'autolimit') { + $advcell{$item} .= $titles{'unlimited'}; + } + } + } elsif ($context eq 'requestauthor') { + my $curroption; + if (ref($settings) eq 'HASH') { + $curroption = $settings->{'_LC_adv'}; + } + my $checked = ''; + if ($curroption eq '') { + $checked = ' checked="checked"'; + } + $datatable .= '  '; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + my $checked = ''; + if ($val eq $curroption) { + $checked = ' checked="checked"'; + } + $datatable .= '  '; + } + } else { + my $checked = 'checked="checked" '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + if ($settings->{$item}->{'_LC_adv'} == 0) { + $checked = ''; + } elsif ($settings->{$item}->{'_LC_adv'} == 1) { + $checked = 'checked="checked" '; + } + } + } + $datatable .= '  '; + } + } + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'. + '
'; + } + my %advcell; + foreach my $item (@usertools) { + if ($context eq 'requestcourses') { + my ($curroption,$currlimit); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + $curroption = $settings->{$item}->{'_LC_adv'}; + if ($curroption =~ /^autolimit=(\d*)$/) { + $currlimit = $1; + } + } + } + $datatable .= '
'.$titles{$item}.'
'.$advcell{$item}.'
'; + } + $datatable .= '
'.$text.''; + if (@domcoord > 0) { + $datatable .= ''; + for (my $i=0; $i<$numdc; $i++) { + my $rem = $i%($numinrow); + if ($rem == 0) { + if ($i > 0) { + $datatable .= ''; + } + $datatable .= ''; + $rows ++; + } + my $check = ' '; + if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) { + $check = ' checked="checked" '; + } + my ($uname,$udom) = split(':',$domcoord[$i]); + my $fullname = &Apache::loncommon::plainname($uname,$udom); + if ($i == $numdc-1) { + my $colsleft = $numinrow-$rem; + if ($colsleft > 1) { + $datatable .= ''; + } + $datatable .= '
'; + } else { + $datatable .= ''; + } + } else { + $datatable .= ''; + } + $datatable .= '
'; + } else { + $datatable .= &mt('There are no active Domain Coordinators'); + $rows ++; + } + $datatable .='
'.&mt('Automatically assign co-ownership').' '. + '
'.&mt('Create pending official courses from XML files').' '. + ''. + '
'.&mt('Create pending requests for official courses (if validated)').' '. + ''; + my ($numdc,$dctable) = &active_dc_picker($dom,$curr_dc); + if ($numdc > 1) { + $datatable .= '
'. + &mt('Course creation processed as: (choose Dom. Coord.)'). + ''.$dctable.'
'.$titles->{$item}. ''. '
'. $titles->{$type}.':
'.$choices->{$item}. + ''. + ' '. + '
'.$choices{'anonsurvey_threshold'}. + ''. + ''. + '
'. + &mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.'); + } + } else { + if (keys(%by_location) == 0) { + $datatable .= ''. + &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.'); + } else { + my %lt = &usersession_titles(); + my $numinrow = 5; + my $prefix; + my @types; + if ($position eq 'bottom') { + $prefix = 'remote'; + @types = ('version','excludedomain','includedomain'); + } else { + $prefix = 'hosted'; + @types = ('excludedomain','includedomain'); + } + my (%current,%checkedon,%checkedoff); + my @lcversions = &Apache::lonnet::all_loncaparevs(); + my @locations = sort(keys(%by_location)); + foreach my $type (@types) { + $checkedon{$type} = ''; + $checkedoff{$type} = ' checked="checked"'; + } + if (ref($settings) eq 'HASH') { + if (ref($settings->{$prefix}) eq 'HASH') { + foreach my $key (keys(%{$settings->{$prefix}})) { + $current{$key} = $settings->{$prefix}{$key}; + if ($key eq 'version') { + if ($current{$key} ne '') { + $checkedon{$key} = ' checked="checked"'; + $checkedoff{$key} = ''; + } + } elsif (ref($current{$key}) eq 'ARRAY') { + $checkedon{$key} = ' checked="checked"'; + $checkedoff{$key} = ''; + } + } + } + } + foreach my $type (@types) { + next if ($type ne 'version' && !@locations); + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ' + '.$lt{$type}.'
+   +   +
'; + if ($type eq 'version') { + my $selector = ' '; + $datatable .= &mt('remote server must be version: [_1] or later',$selector); + } else { + $datatable.= '
'.(' 'x2). + ''. + "\n". + '
'; + my $rem; + for (my $i=0; $i<@locations; $i++) { + my ($showloc,$value,$checkedtype); + if (ref($by_location{$locations[$i]}) eq 'ARRAY') { + my $ip = $by_location{$locations[$i]}->[0]; + if (ref($by_ip{$ip}) eq 'ARRAY') { + $value = join(':',@{$by_ip{$ip}}); + $showloc = join(', ',@{$by_ip{$ip}}); + if (ref($current{$type}) eq 'ARRAY') { + foreach my $loc (@{$by_ip{$ip}}) { + if (grep(/^\Q$loc\E$/,@{$current{$type}})) { + $checkedtype = ' checked="checked"'; + last; + } + } + } + } + } + $rem = $i%($numinrow); + if ($rem == 0) { + if ($i > 0) { + $datatable .= ''; + } + $datatable .= ''; + } + $datatable .= ''; + } + $rem = @locations%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $datatable .= ''; + } elsif ($colsleft == 1) { + $datatable .= ''; + } + $datatable .= '
'. + ''. + '  
'; + } + $datatable .= '
+ '. + &mt('[_1] when busy, offloads to:' + ,''.$server.''). + "\n"; + my (%current,%canselect); + my @choices = + &possible_newspares($server,$spareid->{$server},$serverhomes,$altids); + foreach my $type ('primary','default') { + if (ref($spareid->{$server}) eq 'HASH') { + if (ref($spareid->{$server}{$type}) eq 'ARRAY') { + my @spares = @{$spareid->{$server}{$type}}; + if (@spares > 0) { + if ($othercontrol) { + $current{$type} = join(', ',@spares); + } else { + $current{$type} .= ''; + my $numspares = scalar(@spares); + for (my $i=0; $i<@spares; $i++) { + my $rem = $i%($numinrow); + if ($rem == 0) { + if ($i > 0) { + $current{$type} .= ''; + } + $current{$type} .= ''; + } + $current{$type} .= ''."\n"; + } + my $rem = @spares%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $current{$type} .= ''; + } elsif ($colsleft == 1) { + $current{$type} .= ''."\n"; + } + $current{$type} .= '
'. + '  
'; + } + } + } + if ($current{$type} eq '') { + $current{$type} = &mt('None specified'); + } + if ($othercontrol) { + if ($type eq 'primary') { + $canselect{$type} = $othercontrol; + } + } else { + $canselect{$type} = + &mt('Add new [_1]'.$type.'[_2]:','','').' '. + ''."\n"; + } + } else { + $current{$type} = &mt('Could not be determined'); + if ($type eq 'primary') { + $canselect{$type} = $othercontrol; + } + } + if ($type eq 'default') { + $datatable .= ''; + } + $datatable .= '
'.$typetitles{$type}.''.$current{$type}.''.$canselect{$type}.'
'. + '

'; + if ($lonhost eq '') { + $datatable .= ''; + if (keys(%currbalancer) > 0) { + $datatable .= &mt('Add balancer:'); + } else { + $datatable .= &mt('Enable balancer:'); + } + $datatable .= ' '. + ''."\n". + ' '."\n"; + } else { + $datatable .= ''.$lonhost.'
'. + ''. + ''; + $targets_div_style = 'display: block'; + $disabled_div_style = 'display: none'; + if ($dom eq &Apache::lonnet::host_domain($lonhost)) { + $homedom_div_style = 'display: block'; + } + } + $datatable .= '

'. + '
'.$disabledtext.'
'."\n". + '
'.&mt('Offloads to:').'
'; + my ($numspares,@spares) = &count_servers($lonhost,%servers); + my @sparestypes = ('primary','default'); + my %typetitles = &sparestype_titles(); + foreach my $sparetype (@sparestypes) { + my $targettable; + for (my $i=0; $i<$numspares; $i++) { + my $checked; + if (ref($currtargets{$lonhost}) eq 'HASH') { + if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') { + if (grep(/^\Q$spares[$i]\E$/,@{$currtargets{$lonhost}{$sparetype}})) { + $checked = ' checked="checked"'; + } + } + } + my ($chkboxval,$disabled); + if (($lonhost ne '') && (exists($servers{$lonhost}))) { + $chkboxval = $spares[$i]; + } + if (exists($currbalancer{$spares[$i]})) { + $disabled = ' disabled="disabled"'; + } + $targettable .= + '
'. + '  
'.$targettable.'

'; + } + } + $datatable .= ''. + &loadbalancing_rules($dom,$intdom,$currrules{$lonhost}, + $othertitle,$usertypes,$types,\%servers, + \%currbalancer,$lonhost, + $targets_div_style,$homedom_div_style, + $css_class[$cssidx],$balnum,$islast); + $$rowtotal += $rownum; + $balnum ++; + } + $datatable .= ''; + return $datatable; +} + +sub get_loadbalancers_config { + my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_; + return unless ((ref($servers) eq 'HASH') && + (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') && + (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH')); + if (keys(%{$existing}) > 0) { + my $oldlonhost; + foreach my $key (sort(keys(%{$existing}))) { + if ($key eq 'lonhost') { + $oldlonhost = $existing->{'lonhost'}; + $currbalancer->{$oldlonhost} = 1; + } elsif ($key eq 'targets') { + if ($oldlonhost) { + $currtargets->{$oldlonhost} = $existing->{'targets'}; + } + } elsif ($key eq 'rules') { + if ($oldlonhost) { + $currrules->{$oldlonhost} = $existing->{'rules'}; + } + } elsif (ref($existing->{$key}) eq 'HASH') { + $currbalancer->{$key} = 1; + $currtargets->{$key} = $existing->{$key}{'targets'}; + $currrules->{$key} = $existing->{$key}{'rules'}; + } + } + } else { + my ($balancerref,$targetsref) = + &Apache::lonnet::get_lonbalancer_config($servers); + if ((ref($balancerref) eq 'HASH') && (ref($targetsref) eq 'HASH')) { + foreach my $server (sort(keys(%{$balancerref}))) { + $currbalancer->{$server} = 1; + $currtargets->{$server} = $targetsref->{$server}; + } + } + } + return; +} + +sub loadbalancing_rules { + my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers, + $currbalancer,$lonhost,$targets_div_style,$homedom_div_style, + $css_class,$balnum,$islast) = @_; + my $output; + my $num = 0; + my ($alltypes,$othertypes,$titles) = + &loadbalancing_titles($dom,$intdom,$usertypes,$types); + if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) { + foreach my $type (@{$alltypes}) { + $num ++; + my $current; + if (ref($currrules) eq 'HASH') { + $current = $currrules->{$type}; + } + if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) { + if ($dom ne &Apache::lonnet::host_domain($lonhost)) { + $current = ''; + } + } + $output .= &loadbalance_rule_row($type,$titles->{$type},$current, + $servers,$currbalancer,$lonhost,$dom, + $targets_div_style,$homedom_div_style, + $css_class,$balnum,$num,$islast); + } + } + return $output; +} + +sub loadbalancing_titles { + my ($dom,$intdom,$usertypes,$types) = @_; + my %othertypes = ( + '_LC_adv' => &mt('Advanced users from [_1]',$dom), + '_LC_author' => &mt('Users from [_1] with author role',$dom), + '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom), + '_LC_external' => &mt('Users not from [_1]',$intdom), + ); + my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external'); + if (ref($types) eq 'ARRAY') { + unshift(@alltypes,@{$types},'default'); + } + my %titles; + foreach my $type (@alltypes) { + if ($type =~ /^_LC_/) { + $titles{$type} = $othertypes{$type}; + } elsif ($type eq 'default') { + $titles{$type} = &mt('All users from [_1]',$dom); + if (ref($types) eq 'ARRAY') { + if (@{$types} > 0) { + $titles{$type} = &mt('Other users from [_1]',$dom); + } + } + } elsif (ref($usertypes) eq 'HASH') { + $titles{$type} = $usertypes->{$type}; + } + } + return (\@alltypes,\%othertypes,\%titles); +} + +sub loadbalance_rule_row { + my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom, + $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_; + my @rulenames = ('default','homeserver'); + my %ruletitles = &offloadtype_text(); + if ($type eq '_LC_external') { + push(@rulenames,'externalbalancer'); + } else { + push(@rulenames,'specific'); + } + push(@rulenames,'none'); + my $style = $targets_div_style; + if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) { + $style = $homedom_div_style; + } + my $space; + if ($islast && $num == 1) { + $space = '
 
'; + } + my $output = + ''.$space. + '
'.$title.'
'."\n". + ''.$space. + '
'."\n"; + for (my $i=0; $i<@rulenames; $i++) { + my $rule = $rulenames[$i]; + my ($checked,$extra); + if ($rulenames[$i] eq 'default') { + $rule = ''; + } + if ($rulenames[$i] eq 'specific') { + if (ref($servers) eq 'HASH') { + my $default; + if (($current ne '') && (exists($servers->{$current}))) { + $checked = ' checked="checked"'; + } + unless ($checked) { + $default = ' selected="selected"'; + } + $extra = + ': '; + } + } elsif ($rule eq $current) { + $checked = ' checked="checked"'; + } + $output .= ''.$extra.'
'."\n"; + } + $output .= '
'."\n"; + return $output; +} + +sub offloadtype_text { + my %ruletitles = &Apache::lonlocal::texthash ( + 'default' => 'Offloads to default destinations', + 'homeserver' => "Offloads to user's home server", + 'externalbalancer' => "Offloads to Load Balancer in user's domain", + 'specific' => 'Offloads to specific server', + 'none' => 'No offload', + ); + return %ruletitles; +} + +sub sparestype_titles { + my %typestitles = &Apache::lonlocal::texthash ( + 'primary' => 'primary', + 'default' => 'default', + ); + return %typestitles; +} + sub contact_titles { my %titles = &Apache::lonlocal::texthash ( 'supportemail' => 'Support E-mail address', - 'adminemail' => 'Default Server Admin E-mail address', + 'adminemail' => 'Default Server Admin E-mail address', 'errormail' => 'Error reports to be e-mailed to', 'packagesmail' => 'Package update alerts to be e-mailed to', - 'helpdeskmail' => 'Helpdesk requests to be e-mailed to' + 'helpdeskmail' => 'Helpdesk requests to be e-mailed to', + 'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)', + 'requestsmail' => 'E-mail from course requests requiring approval', ); my %short_titles = &Apache::lonlocal::texthash ( adminemail => 'Admin E-mail address', @@ -1520,6 +3258,51 @@ sub contact_titles { return (\%titles,\%short_titles); } +sub tool_titles { + my %titles = &Apache::lonlocal::texthash ( + aboutme => 'Personal web page', + blog => 'Blog', + webdav => 'WebDAV', + portfolio => 'Portfolio', + official => 'Official courses (with institutional codes)', + unofficial => 'Unofficial courses', + community => 'Communities', + ); + return %titles; +} + +sub courserequest_titles { + my %titles = &Apache::lonlocal::texthash ( + official => 'Official', + unofficial => 'Unofficial', + community => 'Communities', + norequest => 'Not allowed', + approval => 'Approval by Dom. Coord.', + validate => 'With validation', + autolimit => 'Numerical limit', + unlimited => '(blank for unlimited)', + ); + return %titles; +} + +sub authorrequest_titles { + my %titles = &Apache::lonlocal::texthash ( + norequest => 'Not allowed', + approval => 'Approval by Dom. Coord.', + automatic => 'Automatic approval', + ); + return %titles; +} + +sub courserequest_conditions { + my %conditions = &Apache::lonlocal::texthash ( + approval => '(Processing of request subject to approval by Domain Coordinator).', + validate => '(Processing of request subject to instittutional validation).', + ); + return %conditions; +} + + sub print_usercreation { my ($position,$dom,$settings,$rowtotal) = @_; my $numinrow = 4; @@ -1561,7 +3344,7 @@ sub print_usercreation { $rowcount ++; } } elsif ($position eq 'middle') { - my @creators = ('author','course','selfcreate'); + my @creators = ('author','course','requestcrs','selfcreate'); my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username'); my %lt = &usercreation_types(); @@ -1638,6 +3421,22 @@ sub print_usercreation { } $datatable .= ''; } + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($dom); + my $createsettings; + if (ref($settings) eq 'HASH') { + $createsettings = $settings->{cancreate}; + } + if (ref($usertypes) eq 'HASH') { + if (keys(%{$usertypes}) > 0) { + $datatable .= &insttypes_row($createsettings,$types,$usertypes, + $dom,$numinrow,$othertitle, + 'statustocreate'); + $$rowtotal ++; + $rownum ++; + } + } + $datatable .= &captcha_choice('cancreate',$createsettings,$rownum); } else { my @contexts = ('author','course','domain'); my @authtypes = ('int','krb4','krb5','loc'); @@ -1689,6 +3488,64 @@ sub print_usercreation { return $datatable; } +sub captcha_choice { + my ($context,$settings,$itemcount) = @_; + my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext); + my %lt = &captcha_phrases(); + $keyentry = 'hidden'; + if ($context eq 'cancreate') { + $rowname = &mt('CAPTCHA validation (e-mail as username)'); + } elsif ($context eq 'login') { + $rowname = &mt('"Contact helpdesk" CAPTCHA validation'); + } + if (ref($settings) eq 'HASH') { + if ($settings->{'captcha'}) { + $checked{$settings->{'captcha'}} = ' checked="checked"'; + } else { + $checked{'original'} = ' checked="checked"'; + } + if ($settings->{'captcha'} eq 'recaptcha') { + $pubtext = $lt{'pub'}; + $privtext = $lt{'priv'}; + $keyentry = 'text'; + } + if (ref($settings->{'recaptchakeys'}) eq 'HASH') { + $currpub = $settings->{'recaptchakeys'}{'public'}; + $currpriv = $settings->{'recaptchakeys'}{'private'}; + } + } else { + $checked{'original'} = ' checked="checked"'; + } + my $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $output = ''. + ''.$rowname.''."\n". + ''."\n". + '
'."\n"; + foreach my $option ('original','recaptcha','notused') { + $output .= ''; + unless ($option eq 'notused') { + $output .= (' 'x2)."\n"; + } + } +# +# Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit: +# https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple +# servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu) +# specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain. +# + $output .= '
'."\n". + ''.$pubtext.' '."\n". + '
'."\n". + ''.$privtext.' '."\n". + '
'."\n". + ''; + return $output; +} + sub user_formats_row { my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_; my $output; @@ -1750,11 +3607,12 @@ sub usercreation_types { my %lt = &Apache::lonlocal::texthash ( author => 'When adding a co-author', course => 'When adding a user to a course', + requestcrs => 'When requesting a course', selfcreate => 'User creates own account', any => 'Any', official => 'Institutional only ', unofficial => 'Non-institutional only', - email => 'Email address', + email => 'E-mail address', login => 'Institutional Login', sso => 'SSO', none => 'None', @@ -1823,9 +3681,10 @@ sub print_usermodification { sub print_defaults { my ($dom,$rowtotal) = @_; - my @items = ('auth_def','auth_arg_def','lang_def','timezone_def'); + my @items = ('auth_def','auth_arg_def','lang_def','timezone_def', + 'datelocale_def','portal_def'); my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); - my $titles = &defaults_titles(); + my $titles = &defaults_titles($dom); my $rownum = 0; my ($datatable,$css_class); foreach my $item (@items) { @@ -1858,9 +3717,22 @@ sub print_defaults { } elsif ($item eq 'timezone_def') { my $includeempty = 1; $datatable .= &Apache::loncommon::select_timezone($item,$domdefaults{$item},undef,$includeempty); - } else { + } elsif ($item eq 'datelocale_def') { + my $includeempty = 1; + $datatable .= &Apache::loncommon::select_datelocale($item,$domdefaults{$item},undef,$includeempty); + } elsif ($item eq 'lang_def') { + my %langchoices = &get_languages_hash(); + $langchoices{''} = 'No language preference'; + %langchoices = &Apache::lonlocal::texthash(%langchoices); + $datatable .= &Apache::loncommon::select_form($domdefaults{$item},$item, + \%langchoices); + } else { + my $size; + if ($item eq 'portal_def') { + $size = ' size="25"'; + } $datatable .= ''; + $domdefaults{$item}.'"'.$size.' />'; } $datatable .= ''; $rownum ++; @@ -1869,13 +3741,37 @@ sub print_defaults { return $datatable; } +sub get_languages_hash { + my %langchoices; + foreach my $id (&Apache::loncommon::languageids()) { + my $code = &Apache::loncommon::supportedlanguagecode($id); + if ($code ne '') { + $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id); + } + } + return %langchoices; +} + sub defaults_titles { + my ($dom) = @_; my %titles = &Apache::lonlocal::texthash ( 'auth_def' => 'Default authentication type', 'auth_arg_def' => 'Default authentication argument', 'lang_def' => 'Default language', 'timezone_def' => 'Default timezone', + 'datelocale_def' => 'Default locale for dates', + 'portal_def' => 'Portal/Default URL', ); + if ($dom) { + my $uprimary_id = &Apache::lonnet::domain($dom,'primary'); + my $uint_dom = &Apache::lonnet::internet_dom($uprimary_id); + my $protocol = $Apache::lonnet::protocol{$uprimary_id}; + $protocol = 'http' if ($protocol ne 'https'); + if ($uint_dom) { + $titles{'portal_def'} .= ' '.&mt('(for example: [_1])',$protocol.'://loncapa.'. + $uint_dom); + } + } return (\%titles); } @@ -1886,8 +3782,8 @@ sub print_scantronformat { %confhash); my $switchserver = &check_switchserver($dom,$confname); my %lt = &Apache::lonlocal::texthash ( - default => 'Default scantron format file error', - custom => 'Custom scantron format file error', + default => 'Default bubblesheet format file error', + custom => 'Custom bubblesheet format file error', ); my %scantronfiles = ( default => 'default.tab', @@ -1960,7 +3856,7 @@ sub print_scantronformat { } } } else { - $error{'default'} = &mt("Unable to copy default scantron formatfile to domain's RES space: [_1]",$switchserver); + $error{'default'} = &mt("Unable to copy default bubblesheet formatfile to domain's RES space: [_1]",$switchserver); } } if (ref($settings) eq 'HASH') { @@ -1989,7 +3885,7 @@ sub print_scantronformat { ''; if ($scantronurl) { $datatable .= ''. - &mt('Default scantron format file').''; + &mt('Default bubblesheet format file').''; } else { $datatable = &mt('File unavailable for display'); } @@ -2016,7 +3912,7 @@ sub print_scantronformat { } elsif ($scantronurl) { $datatable .= ''. ''. - &mt('Custom scantron format file').''. ' '. @@ -2045,7 +3941,7 @@ sub legacy_scantronformat { &publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron', '','',$newfile); if ($result ne 'ok') { - $error = &mt("An error occurred publishing the [_1] scantron format file in RES space. Error was: [_2].",$newfile,$result); + $error = &mt("An error occurred publishing the [_1] bubblesheet format file in RES space. Error was: [_2].",$newfile,$result); } } return ($url,$error); @@ -2059,6 +3955,11 @@ sub print_coursecategories { my $toggle_cats_dom = ' checked="checked" '; my $can_cat_crs = ' '; my $can_cat_dom = ' checked="checked" '; + my $toggle_catscomm_comm = ' '; + my $toggle_catscomm_dom = ' checked="checked" '; + my $can_catcomm_comm = ' '; + my $can_catcomm_dom = ' checked="checked" '; + if (ref($settings) eq 'HASH') { if ($settings->{'togglecats'} eq 'crs') { $toggle_cats_crs = $toggle_cats_dom; @@ -2068,14 +3969,25 @@ sub print_coursecategories { $can_cat_crs = $can_cat_dom; $can_cat_dom = ' '; } + if ($settings->{'togglecatscomm'} eq 'comm') { + $toggle_catscomm_comm = $toggle_catscomm_dom; + $toggle_catscomm_dom = ' '; + } + if ($settings->{'categorizecomm'} eq 'comm') { + $can_catcomm_comm = $can_catcomm_dom; + $can_catcomm_dom = ' '; + } } my %title = &Apache::lonlocal::texthash ( - togglecats => 'Show/Hide a course in the catalog', - categorize => 'Assign a category to a course', + togglecats => 'Show/Hide a course in catalog', + togglecatscomm => 'Show/Hide a community in catalog', + categorize => 'Assign a category to a course', + categorizecomm => 'Assign a category to a community', ); my %level = &Apache::lonlocal::texthash ( - dom => 'Set in "Modify Course" (Domain)', - crs => 'Set in "Modify Parameters" (Course)', + dom => 'Set in Domain', + crs => 'Set in Course', + comm => 'Set in Community', ); $datatable = ''. ''.$title{'togglecats'}.''. @@ -2091,8 +4003,22 @@ sub print_coursecategories { $can_cat_dom.' value="dom" />'.$level{'dom'}.' '. ''. + ''. + ''.$title{'togglecatscomm'}.''. + ' '. + ''. + ''. + ''.$title{'categorizecomm'}.''. + ''. + ' '. + ''. ''; - $$rowtotal += 2; + $$rowtotal += 4; } else { my $css_class; my $itemcount = 1; @@ -2114,7 +4040,15 @@ sub print_coursecategories { if (ref($cats[0]) eq 'ARRAY') { my $numtop = @{$cats[0]}; my $maxnum = $numtop; - if ((!grep(/^instcode$/,@{$cats[0]})) || ($cathash->{'instcode::0'} eq '')) { + my %default_names = ( + instcode => &mt('Official courses'), + communities => &mt('Communities'), + ); + + if ((!grep(/^instcode$/,@{$cats[0]})) || + ($cathash->{'instcode::0'} eq '') || + (!grep(/^communities$/,@{$cats[0]})) || + ($cathash->{'communities::0'} eq '')) { $maxnum ++; } my $lastidx; @@ -2135,14 +4069,33 @@ sub print_coursecategories { $datatable .= ''; } $datatable .= ''; - if ($parent eq 'instcode') { - $datatable .= ''.&mt('Official courses') - .'
(' - .&mt('with institutional codes').')' - .' ' - .''; + if ($parent eq 'instcode' || $parent eq 'communities') { + $datatable .= '' + .$default_names{$parent}.''; + if ($parent eq 'instcode') { + $datatable .= '
(' + .&mt('with institutional codes') + .')'; + } else { + $datatable .= '
'; + } + $datatable .= '' + .''; + if ($parent eq 'instcode') { + $datatable .= ' '; + } else { + $datatable .= '
' + .''; + } + $datatable .= ''; + if ($parent eq 'communities') { + $datatable .= '
'; + } + $datatable .= ''; } else { $datatable .= $parent .' 
' - .&mt('Official courses').''.'
(' - .&mt('with institutional codes').')' - .' ' - .''; } } } else { @@ -2204,6 +4164,58 @@ sub print_coursecategories { return $datatable; } +sub print_serverstatuses { + my ($dom,$settings,$rowtotal) = @_; + my $datatable; + my @pages = &serverstatus_pages(); + my (%namedaccess,%machineaccess); + foreach my $type (@pages) { + $namedaccess{$type} = ''; + $machineaccess{$type}= ''; + } + if (ref($settings) eq 'HASH') { + foreach my $type (@pages) { + if (exists($settings->{$type})) { + if (ref($settings->{$type}) eq 'HASH') { + foreach my $key (keys(%{$settings->{$type}})) { + if ($key eq 'namedusers') { + $namedaccess{$type} = $settings->{$type}->{$key}; + } elsif ($key eq 'machines') { + $machineaccess{$type} = $settings->{$type}->{$key}; + } + } + } + } + } + } + my $titles= &LONCAPA::lonauthcgi::serverstatus_titles(); + my $rownum = 0; + my $css_class; + foreach my $type (@pages) { + $rownum ++; + $css_class = $rownum%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''. + $titles->{$type}.''. + ''. + ''. + ''. + ''. + ''. + ''."\n"; + } + $$rowtotal += $rownum; + return $datatable; +} + +sub serverstatus_pages { + return ('userstatus','lonstatus','loncron','server-status','codeversions', + 'clusterstatus','metadata_keywords','metadata_harvest', + 'takeoffline','takeonline','showenv','toggledebug','ping','domconf'); +} + sub coursecategories_javascript { my ($settings) = @_; my ($output,$jstext,$cathash); @@ -2226,8 +4238,12 @@ sub coursecategories_javascript { $jstext = ' var categories = Array(1);'."\n". ' categories[0] = Array("instcode_pos");'."\n"; } + my $instcode_reserved = &mt('The name: "instcode" is a reserved category'); + my $communities_reserved = &mt('The name: "communities" is a reserved category'); + my $choose_again = '\\n'.&mt('Please use a different name for the new top level category'); $output = <<"ENDSCRIPT"; ENDSCRIPT @@ -2292,25 +4322,40 @@ ENDSCRIPT sub initialize_categories { my ($itemcount) = @_; - my $datatable; - my $css_class = $itemcount%2?' class="LC_odd_row"':''; - my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','instcode_pos','0'".');"'; - - $datatable = '' - .' ' - .&mt('Official courses (with institutional codes)') - .'' - .'