--- loncom/interface/domainprefs.pm 2009/02/10 18:01:40 1.88 +++ loncom/interface/domainprefs.pm 2016/09/18 19:22:48 1.160.6.71 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.88 2009/02/10 18:01:40 bisitz Exp $ +# $Id: domainprefs.pm,v 1.160.6.71 2016/09/18 19:22:48 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -28,6 +28,132 @@ ############################################################### ############################################################## +=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, and to display/store +default quota sizes for Authoring Spaces. + +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, community, and textbook). 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,6 +163,9 @@ use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonlocal; use Apache::lonmsg(); +use Apache::lonconfigsettings; +use Apache::lonuserutils(); +use Apache::loncoursequeueadmin(); use LONCAPA qw(:DEFAULT :match); use LONCAPA::Enrollment; use LONCAPA::lonauthcgi(); @@ -45,6 +174,9 @@ use Locale::Language; use DateTime::TimeZone; use DateTime::Locale; +my $registered_cleanup; +my $modified_urls; + sub handler { my $r=shift; if ($r->header_only) { @@ -53,6 +185,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)) { @@ -63,6 +196,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']); @@ -70,16 +207,28 @@ 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','serverstatuses', - 'requestcourses'],$dom); + 'quotas','autoenroll','autoupdate','autocreate', + 'directorysrch','usercreation','usermodification', + 'contacts','defaults','scantron','coursecategories', + 'serverstatuses','requestcourses','coursedefaults', + 'usersessions','loadbalancing','requestauthor', + 'selfenrollment','inststatus'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', - 'autoupdate','directorysrch','contacts', - 'usercreation','usermodification','scantron', - 'requestcourses','coursecategories','serverstatuses'); + 'autoupdate','autocreate','directorysrch','contacts', + 'usercreation','selfcreation','usermodification','scantron', + 'requestcourses','requestauthor','coursecategories', + 'serverstatuses','coursedefaults','selfenrollment', + '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', @@ -92,53 +241,84 @@ sub handler { col2 => '',}, {col1 => 'Administrator Settings', col2 => '',}], + print => \&print_rolecolors, + modify => \&modify_rolecolors, }, - 'login' => + 'login' => { text => 'Log-in page options', help => 'Domain_Configuration_Login_Page', - header => [{col1 => 'Item', - col2 => '',}], + header => [{col1 => 'Log-in Page Items', + col2 => '',}, + {col1 => 'Log-in Help', + col2 => 'Value'}, + {col1 => 'Custom HTML in document head', + col2 => 'Value'}], + print => \&print_login, + modify => \&modify_login, }, 'defaults' => - { text => 'Default authentication/language/timezone', + { text => 'Default authentication/language/timezone/portal/types', help => 'Domain_Configuration_LangTZAuth', header => [{col1 => 'Setting', - col2 => 'Value'}], + col2 => 'Value'}, + {col1 => 'Institutional user types', + col2 => 'Assignable to e-mail usernames'}], + print => \&print_defaults, + modify => \&modify_defaults, }, 'quotas' => - { text => 'User blogs, home pages and portfolios', + { text => 'Blogs, personal web pages, webDAV/quotas, portfolios', help => 'Domain_Configuration_Quotas', header => [{col1 => 'User affiliation', col2 => 'Available tools', - col3 => 'Portfolio quota',}], + col3 => 'Quotas, MB; (Authoring requires role)',}], + print => \&print_quotas, + modify => \&modify_quotas, }, 'autoenroll' => { text => 'Auto-enrollment settings', help => 'Domain_Configuration_Auto_Enrollment', header => [{col1 => 'Configuration setting', col2 => 'Value(s)'}], + print => \&print_autoenroll, + modify => \&modify_autoenroll, }, 'autoupdate' => { text => 'Auto-update settings', help => 'Domain_Configuration_Auto_Updates', header => [{col1 => 'Setting', col2 => 'Value',}, + {col1 => 'Setting', + col2 => 'Affiliation'}, {col1 => 'User population', - col2 => 'Updataeable user data'}], + col2 => 'Updatable user data'}], + print => \&print_autoupdate, + modify => \&modify_autoupdate, + }, + 'autocreate' => + { text => 'Auto-course creation settings', + help => 'Domain_Configuration_Auto_Creation', + header => [{col1 => 'Configuration Setting', + col2 => 'Value',}], + print => \&print_autocreate, + modify => \&modify_autocreate, }, 'directorysrch' => { text => 'Institutional directory searches', help => 'Domain_Configuration_InstDirectory_Search', header => [{col1 => 'Setting', col2 => 'Value',}], + print => \&print_directorysrch, + modify => \&modify_directorysrch, }, 'contacts' => { text => 'Contact Information', help => 'Domain_Configuration_Contact_Info', header => [{col1 => 'Setting', col2 => 'Value',}], + print => \&print_contacts, + modify => \&modify_contacts, }, - 'usercreation' => { text => 'User creation', help => 'Domain_Configuration_User_Creation', @@ -148,38 +328,78 @@ sub handler { col2 => 'Usernames which may be created',}, {col1 => 'Context', col2 => 'Assignable authentication types'}], + print => \&print_usercreation, + modify => \&modify_usercreation, + }, + 'selfcreation' => + { text => 'Users self-creating accounts', + help => 'Domain_Configuration_Self_Creation', + header => [{col1 => 'Self-creation with institutional username', + col2 => 'Enabled?'}, + {col1 => 'Institutional user type (login/SSO self-creation)', + col2 => 'Information user can enter'}, + {col1 => 'Self-creation with e-mail as username', + col2 => 'Settings'}], + print => \&print_selfcreation, + modify => \&modify_selfcreation, }, 'usermodification' => { text => 'User modification', help => 'Domain_Configuration_User_Modification', header => [{col1 => 'Target user has role', - col2 => 'User information updateable in author context'}, + col2 => 'User information updatable in author context'}, {col1 => 'Target user has role', - col2 => 'User information updateable in course context'}, - {col1 => "Status of user", - col2 => 'Information settable when self-creating account (if directory data blank)'}], + col2 => 'User information updatable in course context'}], + print => \&print_usermodification, + modify => \&modify_usermodification, }, 'scantron' => - { text => 'Scantron format file', + { text => 'Bubblesheet format file', help => 'Domain_Configuration_Scantron_Format', header => [ {col1 => 'Item', col2 => '', }], + print => \&print_scantron, + modify => \&modify_scantron, }, 'requestcourses' => {text => 'Request creation of courses', help => 'Domain_Configuration_Request_Courses', header => [{col1 => 'User affiliation', - col2 => 'Requestable course types',}], + col2 => 'Availability/Processing of requests',}, + {col1 => 'Setting', + col2 => 'Value'}, + {col1 => 'Available textbooks', + col2 => ''}, + {col1 => 'Available templates', + col2 => ''}, + {col1 => 'Validation (not official courses)', + col2 => 'Value'},], + print => \&print_quotas, + modify => \&modify_quotas, + }, + 'requestauthor' => + {text => 'Request Authoring Space', + help => 'Domain_Configuration_Request_Author', + header => [{col1 => 'User affiliation', + col2 => 'Availability/Processing of requests',}, + {col1 => 'Setting', + col2 => 'Value'}], + print => \&print_quotas, + modify => \&modify_quotas, }, 'coursecategories' => - { text => 'Cataloging of courses', + { text => 'Cataloging of courses/communities', help => 'Domain_Configuration_Cataloging_Courses', - header => [{col1 => 'Category settings', + header => [{col1 => 'Catalog type/availability', + col2 => '',}, + {col1 => 'Category settings for standard catalog', col2 => '',}, {col1 => 'Categories', col2 => '', }], + print => \&print_coursecategories, + modify => \&modify_coursecategories, }, 'serverstatuses' => {text => 'Access to server status pages', @@ -188,107 +408,137 @@ sub handler { col2 => 'Other named users', col3 => 'Specific IPs', }], + print => \&print_serverstatuses, + modify => \&modify_serverstatuses, + }, + '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',},], + print => \&print_coursedefaults, + modify => \&modify_coursedefaults, + }, + 'selfenrollment' => + {text => 'Self-enrollment in Course/Community', + help => 'Domain_Configuration_Selfenrollment', + header => [{col1 => 'Configuration Rights', + col2 => 'Configured by Course Personnel or Domain Coordinator?'}, + {col1 => 'Defaults', + col2 => 'Value'}, + {col1 => 'Self-enrollment validation (optional)', + col2 => 'Value'},], + print => \&print_selfenrollment, + modify => \&modify_selfenrollment, + }, + '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'}], + print => \&print_usersessions, + modify => \&modify_usersessions, + }, + 'loadbalancing' => + {text => 'Dedicated Load Balancer(s)', + help => 'Domain_Configuration_Load_Balancing', + header => [{col1 => 'Balancers', + col2 => 'Default destinations', + col3 => 'User affiliation', + col4 => 'Overrides'}, + ], + print => \&print_loadbalancing, + modify => \&modify_loadbalancing, }, ); + 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'}, + {col1 => 'Custom HTML in document head', + col2 => 'Value'}], + print => \&print_login, + modify => \&modify_login, + }; + } + 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('

'); + my $result = &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order, + \%prefs,\%domconfig,$confname,\@roles); + if ((ref($result) eq 'HASH') && (keys(%{$result}))) { + $r->rflush(); + &devalidate_remote_domconfs($dom,$result); + } } 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'). - ''); + my $js = &recaptcha_js(). + &toggle_display_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(); + } + if (grep(/^requestcourses$/,@actions)) { + my $javascript_validations; + my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'}); + $js .= < +$javascript_validations + +$coursebrowserjs +END } - $r->print(''); - $r->print(&Apache::loncommon::end_page()); + &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js); } else { - if ($phase eq '') { - $phase = 'pickactions'; +# 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(); @@ -307,6 +557,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.').'
'. @@ -316,83 +567,66 @@ 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,$lastactref) = @_; + my %domconfig; + if (ref($values) eq 'HASH') { + %domconfig = %{$values}; + } my $output; if ($action eq 'login') { - $output = &modify_login($r,$dom,$confname,%domconfig); + $output = &modify_login($r,$dom,$confname,$lastactref,%domconfig); } elsif ($action eq 'rolecolors') { $output = &modify_rolecolors($r,$dom,$confname,$roles, - %domconfig); + $lastactref,%domconfig); } elsif ($action eq 'quotas') { - $output = &modify_quotas($dom,$action,%domconfig); + $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); } elsif ($action eq 'autoenroll') { - $output = &modify_autoenroll($dom,%domconfig); + $output = &modify_autoenroll($dom,$lastactref,%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') { $output = &modify_usercreation($dom,%domconfig); + } elsif ($action eq 'selfcreation') { + $output = &modify_selfcreation($dom,%domconfig); } elsif ($action eq 'usermodification') { $output = &modify_usermodification($dom,%domconfig); } elsif ($action eq 'contacts') { - $output = &modify_contacts($dom,%domconfig); + $output = &modify_contacts($dom,$lastactref,%domconfig); } elsif ($action eq 'defaults') { - $output = &modify_defaults($dom,$r); + $output = &modify_defaults($dom,$lastactref,%domconfig); } elsif ($action eq 'scantron') { - $output = &modify_scantron($r,$dom,$confname,%domconfig); + $output = &modify_scantron($r,$dom,$confname,$lastactref,%domconfig); } elsif ($action eq 'coursecategories') { - $output = &modify_coursecategories($dom,%domconfig); + $output = &modify_coursecategories($dom,$lastactref,%domconfig); } elsif ($action eq 'serverstatuses') { $output = &modify_serverstatuses($dom,%domconfig); } elsif ($action eq 'requestcourses') { - $output = &modify_quotas($dom,$action,%domconfig); + $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); + } elsif ($action eq 'requestauthor') { + $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); + } elsif ($action eq 'coursedefaults') { + $output = &modify_coursedefaults($dom,$lastactref,%domconfig); + } elsif ($action eq 'selfenrollment') { + $output = &modify_selfenrollment($dom,$lastactref,%domconfig) + } elsif ($action eq 'usersessions') { + $output = &modify_usersessions($dom,$lastactref,%domconfig); + } elsif ($action eq 'loadbalancing') { + $output = &modify_loadbalancing($dom,%domconfig); } return $output; } @@ -403,8 +637,10 @@ sub print_config_box { my $output; if ($action eq 'coursecategories') { $output = &coursecategories_javascript($settings); - } - $output .= + } elsif ($action eq 'defaults') { + $output = &defaults_javascript($settings); + } + $output .= ''."\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 'defaults') || + (($action eq 'login') && ($numheaders < 4))) { $colspan = ' colspan="2"'; } + if ($action eq 'usersessions') { + $rightcolspan = ' colspan="3"'; + } $output .= ' @@ -477,13 +741,73 @@ sub print_config_box {
'. @@ -412,31 +648,45 @@ sub print_config_box { &Apache::loncommon::help_open_topic($item->{'help'}).'
- + '; $rowtotal ++; - if ($action eq 'autoupdate') { - $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal); - } elsif ($action eq 'usercreation') { - $output .= &print_usercreation('top',$dom,$settings,\$rowtotal); - } elsif ($action eq 'usermodification') { - $output .= &print_usermodification('top',$dom,$settings,\$rowtotal); + if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') || + ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') || + ($action eq 'selfenrollment') || ($action eq 'usersessions')) { + $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'coursecategories') { - $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal); - } else { + $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal); + } elsif ($action eq 'login') { + if ($numheaders == 4) { + $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') || ($action eq 'requestauthor')) { + $output .= &print_quotas($dom,$settings,\$rowtotal,$action); + } elsif ($action eq 'rolecolors') { $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal); } $output .= ' @@ -447,15 +697,20 @@ sub print_config_box { @@ -464,11 +719,20 @@ sub print_config_box {
'.&mt($item->{'header'}->[0]->{'col1'}).''.&mt($item->{'header'}->[0]->{'col2'}).''.&mt($item->{'header'}->[0]->{'col2'}).'
- '; - $output .= ' + '; $rowtotal ++; - if ($action eq 'autoupdate') { - $output .= &print_autoupdate('bottom',$dom,$settings,\$rowtotal); - } elsif ($action eq 'usercreation') { - $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).' + if (($action eq 'autoupdate') || ($action eq 'usercreation') || + ($action eq 'selfcreation') || ($action eq 'selfenrollment') || + ($action eq 'usersessions') || ($action eq 'coursecategories')) { + if ($action eq 'coursecategories') { + $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal); + $colspan = ' colspan="2"'; + } else { + $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal); + } + $output .= '
'.&mt($item->{'header'}->[1]->{'col1'}).''.&mt($item->{'header'}->[1]->{'col1'}).' '.&mt($item->{'header'}->[1]->{'col2'}).'
- '. - &print_usercreation('bottom',$dom,$settings,\$rowtotal); + + '."\n"; + if ($action eq 'coursecategories') { + $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); + } else { + $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal); + } $rowtotal ++; - } elsif ($action eq 'usermodification') { - $output .= &print_usermodification('middle',$dom,$settings,\$rowtotal).' + } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') || + ($action eq 'defaults')) { + $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal); + } elsif ($action eq 'login') { + if ($numheaders == 4) { + $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
'.&mt($item->{'header'}->[2]->{'col2'}).'
- '. - - &print_usermodification('bottom',$dom,$settings,\$rowtotal); + '. + &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal); + $rowtotal ++; + } else { + $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal); + } + $output .= ' +
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
'.&mt($item->{'header'}->[2]->{'col2'}).'
+ + + + + + '; + if ($numheaders == 4) { + $output .= ' + + + '; + } else { + $output .= ' + + + '; + } $rowtotal ++; - } elsif ($action eq 'coursecategories') { - $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); - } else { + $output .= &print_login('headtag',$dom,$confname,$phase,$settings,\$rowtotal); + } elsif ($action eq 'requestcourses') { + $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); + $rowtotal ++; + $output .= &print_studentcode($settings,\$rowtotal).' +
'.&mt($item->{'header'}->[3]->{'col1'}).''.&mt($item->{'header'}->[3]->{'col2'}).'
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
+ + + + + + + + '. + &textbookcourses_javascript($settings). + &print_textbookcourses($dom,'textbooks',$settings,\$rowtotal).' +
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
+ + + + + + + + '. + &print_textbookcourses($dom,'templates',$settings,\$rowtotal).' +
'.&mt($item->{'header'}->[3]->{'col1'}).''.&mt($item->{'header'}->[3]->{'col2'}).'
+ + + + + + + + + '. + &print_validation_rows('requestcourses',$dom,$settings,\$rowtotal); + } elsif ($action eq 'requestauthor') { + $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); + $rowtotal ++; + } elsif ($action eq 'rolecolors') { $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
'.&mt($item->{'header'}->[4]->{'col1'}).''.&mt($item->{'header'}->[4]->{'col2'}).'
@@ -541,33 +865,33 @@ sub print_config_box { } $output .= ''; if ($item->{'header'}->[0]->{'col3'}) { - $output .= ''. - &mt($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') { + if ($action eq 'quotas') { $output .= &print_quotas($dom,$settings,\$rowtotal,$action); - } elsif ($action eq 'autoenroll') { - $output .= &print_autoenroll($dom,$settings,\$rowtotal); - } elsif ($action eq 'directorysrch') { - $output .= &print_directorysrch($dom,$settings,\$rowtotal); - } elsif ($action eq 'contacts') { - $output .= &print_contacts($dom,$settings,\$rowtotal); - } elsif ($action eq 'defaults') { - $output .= &print_defaults($dom,\$rowtotal); + } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || ($action eq 'directorysrch') || + ($action eq 'contacts') || ($action eq 'serverstatuses') || ($action eq 'loadbalancing')) { + $output .= $item->{'print'}->($dom,$settings,\$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 'requestcourses') { - $output .= &print_quotas($dom,$settings,\$rowtotal,$action); + } elsif ($action eq 'helpsettings') { + $output .= &print_helpsettings($dom,$confname,$settings,\$rowtotal); } } $output .= ' @@ -578,262 +902,379 @@ 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}; - $defaults{'showlogo'}{$item} = 1; - } - 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', + 'helpdesk' => 'on', + 'adminmail' => 'off', + 'newuser' => 'off', + ); + my @toggles = ('coursecatalog','adminmail','helpdesk','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 (defined($settings->{$item})) { - $designs{$item} = $settings->{$item}; - $is_custom{$item} = 1; - } - if (defined($settings->{'showlogo'}{$item})) { - $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item}; - } + $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}; + } + } + 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; + } } } - } else { - if ($designhash{$dom.'.login.font'} ne '') { - $designs{'font'} = $designhash{$dom.'.login.font'}; - $is_custom{'font'} = 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 (@images) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{$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 ++; } - foreach my $item (@bgs) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + $datatable .= &captcha_choice('login',$settings,$itemcount); + } elsif ($caller eq 'headtag') { + my %domservers = &Apache::lonnet::get_servers($dom); + my $choice = $choices{'headtag'}; + $css_class = ' class="LC_odd_row"'; + $datatable .= ''.$choice.''. + ''. + ''. + ''. + ''."\n"; + my (%currurls,%currexempt); + if (ref($settings) eq 'HASH') { + if (ref($settings->{'headtag'}) eq 'HASH') { + foreach my $lonhost (keys(%{$settings->{'headtag'}})) { + if (ref($settings->{'headtag'}{$lonhost}) eq 'HASH') { + $currurls{$lonhost} = $settings->{'headtag'}{$lonhost}{'url'}; + $currexempt{$lonhost} = $settings->{'headtag'}{$lonhost}{'exempt'}; + } + } } } - foreach my $item (@links) { - if ($designhash{$dom.'.login.'.$item} ne '') { - $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item}; - $is_custom{$item} = 1; + my %lt = &Apache::lonlocal::texthash( + del => 'Delete?', + rep => 'Replace:', + upl => 'Upload:', + curr => 'View contents', + none => 'None', + ); + my $switchserver = &check_switchserver($dom,$confname); + foreach my $lonhost (sort(keys(%domservers))) { + my $exempt = &check_exempt_addresses($currexempt{$lonhost}); + $datatable .= ''; + if ($currurls{$lonhost}) { + $datatable .= ''. + ''; } + $datatable .= '
'.$choices{'hostid'}.''.$choices{'current'}.''.$choices{'action'}.''.$choices{'exempt'}.'
'.$domservers{$lonhost}.''.$lt{'curr'}.' '.$lt{'rep'}.''; + } else { + $datatable .= ''.$lt{'none'}.''.$lt{'upl'}; + } + $datatable .='
'; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; } + $datatable .= '
'; } - 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 => "Header", - mainbg => "Page", - sidebg => "Login box", - link => "Link", - alink => "Active link", - vlink => "Visited link", + coursecatalog => 'Display Course/Community Catalog link?', + adminmail => "Display Administrator's E-mail Address?", + helpdesk => 'Display "Contact Helpdesk" link', + 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", + headtag => "Custom markup", + action => "Action", + current => "Current", ); return %choices; } @@ -848,16 +1289,7 @@ sub print_rolecolors { my %designhash = &Apache::loncommon::get_domainconf($dom); my %defaultdesign = %Apache::loncommon::defaultdesign; my (%is_custom,%designs); - my %defaults = ( - img => $defaultdesign{$role.'.img'}, - font => $defaultdesign{$role.'.font'}, - ); - foreach my $item (@bgs) { - $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item}; - } - foreach my $item (@links) { - $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item}; - } + my %defaults = &role_defaults($role,\@bgs,\@links,\@images); if (ref($settings) eq 'HASH') { if (ref($settings->{$role}) eq 'HASH') { if ($settings->{$role}->{'img'} ne '') { @@ -868,6 +1300,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}; @@ -886,6 +1322,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; @@ -910,9 +1350,48 @@ sub print_rolecolors { return $datatable; } +sub role_defaults { + my ($role,$bgs,$links,$images,$logintext) = @_; + my %defaults; + unless ((ref($bgs) eq 'ARRAY') && (ref($links) eq 'ARRAY') && (ref($images) eq 'ARRAY')) { + return %defaults; + } + my %defaultdesign = %Apache::loncommon::defaultdesign; + if ($role eq 'login') { + %defaults = ( + font => $defaultdesign{$role.'.font'}, + ); + if (ref($logintext) eq 'ARRAY') { + foreach my $item (@{$logintext}) { + $defaults{'logintext'}{$item} = $defaultdesign{$role.'.'.$item}; + } + } + foreach my $item (@{$images}) { + $defaults{'showlogo'}{$item} = 1; + } + } else { + %defaults = ( + img => $defaultdesign{$role.'.img'}, + font => $defaultdesign{$role.'.font'}, + fontmenu => $defaultdesign{$role.'.fontmenu'}, + ); + } + foreach my $item (@{$bgs}) { + $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item}; + } + foreach my $item (@{$links}) { + $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item}; + } + foreach my $item (@{$images}) { + $defaults{$item} = $defaultdesign{$role.'.'.$item}; + } + return %defaults; +} + 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'}.''; @@ -921,13 +1400,28 @@ 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 ++; @@ -938,11 +1432,10 @@ sub display_color_options { if ($role eq 'login') { if ($img eq 'login') { $login_hdr_pick = - &login_header_options($img,$role,$defaults,$is_custom,$choices, - $loginheader); + &login_header_options($img,$role,$defaults,$is_custom,$choices); $logincolors = &login_text_colors($img,$role,$logintext,$phase,$choices, - $designs); + $designs,$defaults); } elsif ($img ne 'domlogo') { $datatable.= &logo_display_options($img,$defaults,$designs); } @@ -975,11 +1468,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); @@ -987,7 +1480,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; } } } @@ -1016,22 +1509,24 @@ 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 { - $datatable .= '
'. - &mt('Upload:'); + $datatable .= ' '. + &mt('Upload:').'
'; } } else { - $datatable .= '
'. - &mt('Upload:'); + $datatable .= ' '. + &mt('Upload:').'
'; } 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 .= ''; } @@ -1052,13 +1547,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 .= ''.$choices->{$item}; + my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item}; if ($designs->{'bgs'}{$item}) { - $datatable .= '    '; + $datatable .= ' '; } - $datatable .= '
'; @@ -1080,13 +1576,12 @@ sub display_color_options { $datatable .= ''. ''; foreach my $item (@{$links}) { - $datatable .= ''; } $$rowtotal += $itemcount; @@ -1120,20 +1615,10 @@ sub logo_display_options { } 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'}. '   '; @@ -1150,17 +1635,13 @@ sub login_header_options { } sub login_text_colors { - my ($img,$role,$logintext,$phase,$choices,$designs) = @_; + my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_; my $color_menu = '
'."\n". - &color_pick($phase,$role,$item,$choices->{$item}, - $designs->{'links'}{$item}); + my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item}; + $datatable .= ''.$choices->{$item}."\n"; if ($designs->{'links'}{$item}) { - $datatable.='    '; + $datatable.=' '; } - $datatable .= '
'; foreach my $item (@{$logintext}) { - my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'logintext'}{$item}); - $color_menu .= ''. - ''; + $color_menu .= ''; } $color_menu .= '
'.$link; - if ($designs->{'logintext'}{$item}) { - $color_menu .= '    '; - } - $color_menu .= '
 '.$choices->{$item}; + my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item}; + $color_menu .= '

'; return $color_menu; @@ -1169,80 +1650,32 @@ 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') { + # 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 .= ''.$logincolors.' '.&mt('Replace:').'
'; + if ($img eq 'login') { # suppress image for Log-in header + $output .= ''.$logincolors; } else { - $output .= ''.$logincolors.&mt('Upload:').'
'; - } - return $output; -} - -sub color_pick { - my ($phase,$role,$item,$desc,$curcol) = @_; - my $link = ''.$desc.''; - 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=''; + if ($img_import) { + $output .= ''; } - } - - function get_id (span_id) { - if (document.getElementById) { - return document.getElementById(span_id); + $output .= ''.$alt_text.''; + if ($is_custom) { + $output .= ''.$logincolors.' '.&mt('Replace:').'
'; + } else { + $output .= ''.$logincolors.&mt('Upload:').'
'; } - 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; } @@ -1254,26 +1687,37 @@ sub print_quotas { } else { $context = $action; } - my ($datatable,$defaultquota,@usertools); + my ($datatable,$defaultquota,$authorquota,@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'); + @usertools = ('official','unofficial','community','textbook'); + @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','portfolio'); + @usertools = ('aboutme','blog','webdav','portfolio'); + %titles = &tool_titles(); } - my %titles = &tool_titles(); if (ref($types) eq 'ARRAY') { foreach my $type (@{$types}) { - my $currdefquota; - unless ($context eq 'requestcourses') { + my ($currdefquota,$currauthorquota); + unless (($context eq 'requestcourses') || + ($context eq 'requestauthor')) { if (ref($settings) eq 'HASH') { if (ref($settings->{defaultquota}) eq 'HASH') { - $currdefquota = $settings->{defaultquota}->{$type}; + $currdefquota = $settings->{defaultquota}->{$type}; } else { $currdefquota = $settings->{$type}; } + if (ref($settings->{authorquota}) eq 'HASH') { + $currauthorquota = $settings->{authorquota}->{$type}; + } } } if (defined($usertypes->{$type})) { @@ -1282,45 +1726,137 @@ sub print_quotas { $datatable .= ''. ''.$usertypes->{$type}.''. ''; + if ($context eq 'requestcourses') { + $datatable .= ''; + } + my %cell; foreach my $item (@usertools) { - my $checked; - unless ($context eq 'requestcourses') { - $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" '; + 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 .= '  '; + $datatable .= '
'.$titles{$item}.'
'.$cell{$item}.'
'; } $datatable .= ''; - unless ($context eq 'requestcourses') { + unless (($context eq 'requestcourses') || + ($context eq 'requestauthor')) { $datatable .= - ''. + ''. + ''.&mt('Portfolio').': '. ' Mb'; + '" size="5" />'.(' ' x 2). + ''.&mt('Authoring').': '. + ''; } $datatable .= ''; } } } - unless ($context eq 'requestcourses') { + unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { $defaultquota = '20'; + $authorquota = '500'; if (ref($settings) eq 'HASH') { if (ref($settings->{'defaultquota'}) eq 'HASH') { $defaultquota = $settings->{'defaultquota'}->{'default'}; } elsif (defined($settings->{'default'})) { $defaultquota = $settings->{'default'}; } + if (ref($settings->{'authorquota'}) eq 'HASH') { + $authorquota = $settings->{'authorquota'}->{'default'}; + } } } $typecount ++; @@ -1328,66 +1864,541 @@ sub print_quotas { $datatable .= ''. ''.$othertitle.''. ''; + if ($context eq 'requestcourses') { + $datatable .= ''; + } + my %defcell; foreach my $item (@usertools) { - my $checked; - unless ($context eq 'requestcourses') { - $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" '; + 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 .= '  '; } - $datatable .= '  '; + } + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'.$titles{$item}.'
'.$defcell{$item}.'
'; } $datatable .= ''; - unless ($context eq 'requestcourses') { - $datatable .= ''. + unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + $datatable .= ''. + ''.&mt('Portfolio').': '. ' Mb'; + $defaultquota.'" size="5" />'.(' ' x2). + ''.&mt('Authoring').': '. + ''; } $datatable .= ''; $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; $datatable .= ''. - '
'.&mt('LON-CAPA Advanced Users').''. - '
'; + ''.&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 .= '  '; } - $datatable .= '  '; } - $datatable .= '('.&mt('overrides affiliation'). - ')'; + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'. + '
'; + } + my %advcell; foreach my $item (@usertools) { - my $checked; - unless ($context eq 'requestcourses') { - $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" '; + 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 .= ''; $$rowtotal += $typecount; return $datatable; } +sub print_requestmail { + my ($dom,$action,$settings,$rowtotal) = @_; + my ($now,$datatable,%currapp); + $now = time; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'notify'}) eq 'HASH') { + if ($settings->{'notify'}{'approval'} ne '') { + map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'}); + } + } + } + my $numinrow = 2; + my $css_class; + $css_class = ($$rowtotal%2? ' class="LC_odd_row"':''); + my $text; + if ($action eq 'requestcourses') { + $text = &mt('Receive notification of course requests requiring approval'); + } elsif ($action eq 'requestauthor') { + $text = &mt('Receive notification of Authoring Space requests requiring approval'); + } else { + $text = &mt('Receive notification of queued requests for self-created user accounts requiring approval'); + } + $datatable = ''. + ' '.$text.''. + ' '; + my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox', + $action.'notifyapproval',%currapp); + if ($numdc > 0) { + $datatable .= $table; + } else { + $datatable .= &mt('There are no active Domain Coordinators'); + } + $datatable .=''; + return $datatable; +} + +sub print_studentcode { + my ($settings,$rowtotal) = @_; + my $rownum = 0; + my ($output,%current); + my @crstypes = ('official','unofficial','community','textbook'); + if (ref($settings) eq 'HASH') { + if (ref($settings->{'uniquecode'}) eq 'HASH') { + foreach my $type (@crstypes) { + $current{$type} = $settings->{'uniquecode'}{$type}; + } + } + } + $output .= ''. + ''.&mt('Generate unique six character code as course identifier?').''. + ''; + foreach my $type (@crstypes) { + my $check = ' '; + if ($current{$type}) { + $check = ' checked="checked" '; + } + $output .= ''.(' 'x2).' '; + } + $output .= ''; + $$rowtotal ++; + return $output; +} + +sub print_textbookcourses { + my ($dom,$type,$settings,$rowtotal) = @_; + my $rownum = 0; + my $css_class; + my $itemcount = 1; + my $maxnum = 0; + my $bookshash; + if (ref($settings) eq 'HASH') { + $bookshash = $settings->{$type}; + } + my %ordered; + if (ref($bookshash) eq 'HASH') { + foreach my $item (keys(%{$bookshash})) { + if (ref($bookshash->{$item}) eq 'HASH') { + my $num = $bookshash->{$item}{'order'}; + $ordered{$num} = $item; + } + } + } + my $confname = $dom.'-domainconfig'; + my $switchserver = &check_switchserver($dom,$confname); + my $maxnum = scalar(keys(%ordered)); + my $datatable; + if (keys(%ordered)) { + my @items = sort { $a <=> $b } keys(%ordered); + for (my $i=0; $i<@items; $i++) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $key = $ordered{$items[$i]}; + my %coursehash=&Apache::lonnet::coursedescription($key); + my $coursetitle = $coursehash{'description'}; + my ($subject,$title,$author,$publisher,$image,$imgsrc,$cdom,$cnum); + if (ref($bookshash->{$key}) eq 'HASH') { + $subject = $bookshash->{$key}->{'subject'}; + $title = $bookshash->{$key}->{'title'}; + if ($type eq 'textbooks') { + $publisher = $bookshash->{$key}->{'publisher'}; + $author = $bookshash->{$key}->{'author'}; + $image = $bookshash->{$key}->{'image'}; + if ($image ne '') { + my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$}); + my $imagethumb = "$path/tn-".$imagefile; + $imgsrc = ''.&mt('Textbook image').''; + } + } + } + my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type".'_'."$key','$type'".');"'; + $datatable .= '' + .''.(' 'x2). + ''. + ''. + ''.&mt('Subject:').' '. + (' 'x2). + ''.&mt('Title:').' '; + if ($type eq 'textbooks') { + $datatable .= (' 'x2). + ''.&mt('Publisher:').' '. + (' 'x2). + ''.&mt('Author(s):').' '. + (' 'x2). + ''.&mt('Thumbnail:'); + if ($image) { + $datatable .= ''. + $imgsrc. + ' '. + ' '.&mt('Replace:').' '; + } + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; + } + } + $datatable .= ' '. + ''.&mt('LON-CAPA course:').' '. + $coursetitle.''."\n"; + $itemcount ++; + } + } + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$type"."_addbook_pos','$type'".');"'; + $datatable .= ''."\n". + ''."\n". + ' '."\n". + ''.&mt('Add').''."\n". + ''. + ''.&mt('Subject:').' '."\n". + (' 'x2). + ''.&mt('Title:').' '."\n". + (' 'x2); + if ($type eq 'textbooks') { + $datatable .= ''.&mt('Publisher:').' '."\n". + (' 'x2). + ''.&mt('Author(s):').' '."\n". + (' 'x2). + ''.&mt('Image:').' '; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; + } + } + $datatable .= ''."\n". + ''.&mt('LON-CAPA course:').' '. + &Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom'). + ''. + &Apache::loncommon::selectcourse_link + ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course'); + ''."\n". + ''."\n"; + $itemcount ++; + return $datatable; +} + +sub textbookcourses_javascript { + my ($settings) = @_; + return unless(ref($settings) eq 'HASH'); + my (%ordered,%total,%jstext); + foreach my $type ('textbooks','templates') { + $total{$type} = 0; + if (ref($settings->{$type}) eq 'HASH') { + foreach my $item (keys(%{$settings->{$type}})) { + if (ref($settings->{$type}->{$item}) eq 'HASH') { + my $num = $settings->{$type}->{$item}{'order'}; + $ordered{$type}{$num} = $item; + } + } + $total{$type} = scalar(keys(%{$settings->{$type}})); + } + my @jsarray = (); + foreach my $item (sort {$a <=> $b } (keys(%{$ordered{$type}}))) { + push(@jsarray,$ordered{$type}{$item}); + } + $jstext{$type} = ' var '.$type.' = Array('."'".join("','",@jsarray)."'".');'."\n"; + } + return <<"ENDSCRIPT"; + + +ENDSCRIPT +} + 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,$failsafe); if (ref($settings) eq 'HASH') { if (exists($settings->{'run'})) { if ($settings->{'run'} eq '0') { @@ -1406,9 +2417,24 @@ 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'}; } + if (exists($settings->{'autofailsafe'})) { + $failsafe = $settings->{'autofailsafe'}; + } } else { if ($autorun) { $runon = ' checked="checked" '; @@ -1436,8 +2462,20 @@ sub print_autoenroll { &mt('username').': '. '  '.&mt('domain'). - ': '.$domform.''; - $$rowtotal += 2; + ': '.$domform.''. + ''. + ''.&mt('Automatically assign co-ownership').''. + ' '. + ''. + ''. + ''.&mt('Failsafe for no drops when institutional data missing').''. + ''. + ''; + $$rowtotal += 4; return $datatable; } @@ -1479,9 +2517,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; @@ -1502,6 +2548,61 @@ sub print_autoupdate { return $datatable; } +sub print_autocreate { + my ($dom,$settings,$rowtotal) = @_; + my (%createon,%createoff,%currhash); + 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} = ' '; + } + } + } + if ($settings->{'xmldc'} ne '') { + $currhash{$settings->{'xmldc'}} = 1; + } + } else { + foreach my $item (@types) { + $createoff{$item} = ' checked="checked" '; + $createon{$item} = ' '; + } + } + $$rowtotal += 2; + my $numinrow = 2; + my $datatable=''. + ''.&mt('Create pending official courses from XML files').''. + ' '. + ''. + ''. + ''.&mt('Create pending requests for official courses (if validated)').''. + ' '. + ''; + my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio', + 'autocreate_xmldc',%currhash); + $datatable .= ''; + if ($numdc > 1) { + $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)'). + ''; + } else { + $datatable .= &mt('Course creation processed as:'). + ''; + } + $datatable .= $dctable.''; + $$rowtotal += $rows; + return $datatable; +} + sub print_directorysrch { my ($dom,$settings,$rowtotal) = @_; my $srchon = ' '; @@ -1562,8 +2663,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; } } @@ -1578,7 +2679,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" '; @@ -1619,11 +2720,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','updatesmail','idconflictsmail'); foreach my $type (@mailings) { $otheremails{$type} = ''; } + $bccemails{'helpdeskmail'} = ''; if (ref($settings) eq 'HASH') { foreach my $item (@contacts) { if (exists($settings->{$item})) { @@ -1639,7 +2742,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 { @@ -1647,22 +2755,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" '; + $checked{'updatesmail'}{'adminemail'} = ' checked="checked" '; + $checked{'idconflictsmail'}{'adminemail'} = ' checked="checked" '; } my ($titles,$short_titles) = &contact_titles(); my $rownum = 0; my $css_class; foreach my $item (@contacts) { - $rownum ++; $css_class = $rownum%2?' class="LC_odd_row"':''; $datatable .= ''. ''.$titles->{$item}. ''. ''; + $rownum ++; } foreach my $type (@mailings) { - $rownum ++; $css_class = $rownum%2?' class="LC_odd_row"':''; $datatable .= ''. ''. @@ -1678,20 +2789,1367 @@ sub print_contacts { } $datatable .= '
'.&mt('Others').':  '. ''. - ''."\n"; + 'value="'.$otheremails{$type}.'" />'; + if ($type eq 'helpdeskmail') { + $datatable .= '
'.&mt('Bcc:').(' 'x6). + ''; + } + $datatable .= ''."\n"; + $rownum ++; } + my %choices; + $choices{'reporterrors'} = &mt('E-mail error reports to [_1]', + &Apache::loncommon::modal_link('http://loncapa.org/core.html', + &mt('LON-CAPA core group - MSU'),600,500)); + $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]', + &Apache::loncommon::modal_link('http://loncapa.org/core.html', + &mt('LON-CAPA core group - MSU'),600,500)); + my @toggles = ('reporterrors','reportupdates'); + my %defaultchecked = ('reporterrors' => 'on', + 'reportupdates' => 'on'); + (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, + \%choices,$rownum); + $datatable .= $reports; $$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,$onclick, + $additional,$align) = @_; + 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} = ' '; + } + } + } + if ($onclick) { + $onclick = ' onclick="'.$onclick.'"'; + } + foreach my $item (@{$toggles}) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= + ''. + ''.$choices->{$item}. + ''; + if ($align eq 'left') { + $datatable .= ''; + } else { + $datatable .= ''; + } + $datatable .= + ''. + ' '. + ''.$additional. + ''. + ''; + $itemcount ++; + } + return ($datatable,$itemcount); +} + +sub print_coursedefaults { + my ($position,$dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles); + my $itemcount = 1; + my %choices = &Apache::lonlocal::texthash ( + uploadquota => 'Default quota for files uploaded directly to course/community using Course Editor (MB)', + anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys', + coursecredits => 'Credits can be specified for courses', + uselcmath => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)', + usejsme => 'Molecule editor uses JSME (HTML5) in place of JME (Java)', + postsubmit => 'Disable submit button/keypress following student submission', + canclone => "People who may clone a course (besides course's owner and coordinators)", + mysqltables => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver', + ); + my %staticdefaults = ( + anonsurvey_threshold => 10, + uploadquota => 500, + postsubmit => 60, + mysqltables => 172800, + ); + if ($position eq 'top') { + %defaultchecked = ( + 'uselcmath' => 'on', + 'usejsme' => 'on', + 'canclone' => 'none', + ); + @toggles = ('uselcmath','usejsme'); + ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, + \%choices,$itemcount); + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= + ''. + ''.$choices{'canclone'}. + ''; + my $currcanclone = 'none'; + my $onclick; + my @cloneoptions = ('none','domain'); + my %clonetitles = ( + none => 'No additional course requesters', + domain => "Any course requester in course's domain", + instcode => 'Course requests for official courses ...', + ); + my (%codedefaults,@code_order,@posscodes); + if (&Apache::lonnet::auto_instcode_defaults($dom,\%codedefaults, + \@code_order) eq 'ok') { + if (@code_order > 0) { + push(@cloneoptions,'instcode'); + $onclick = ' onclick="toggleDisplay(this.form,'."'cloneinstcode'".');"'; + } + } + if (ref($settings) eq 'HASH') { + if ($settings->{'canclone'}) { + if (ref($settings->{'canclone'}) eq 'HASH') { + if (ref($settings->{'canclone'}{'instcode'}) eq 'ARRAY') { + if (@code_order > 0) { + $currcanclone = 'instcode'; + @posscodes = @{$settings->{'canclone'}{'instcode'}}; + } + } + } elsif ($settings->{'canclone'} eq 'domain') { + $currcanclone = $settings->{'canclone'}; + } + } + } + foreach my $option (@cloneoptions) { + my ($checked,$additional); + if ($currcanclone eq $option) { + $checked = ' checked="checked"'; + } + if ($option eq 'instcode') { + if (@code_order) { + my $show = 'none'; + if ($checked) { + $show = 'block'; + } + $additional = '
'. + &mt('Institutional codes for new and cloned course have identical:'). + '
'; + foreach my $item (@code_order) { + my $codechk; + if ($checked) { + if (grep(/^\Q$item\E$/,@posscodes)) { + $codechk = ' checked="checked"'; + } + } + $additional .= ''; + } + $additional .= (' 'x2).'('.&mt('check as many as needed').')
'; + } + } + $datatable .= + ' '.$additional.'
'; + } + $datatable .= ''. + ''; + $itemcount ++; + } else { + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql); + my $currusecredits = 0; + my $postsubmitclient = 1; + my @types = ('official','unofficial','community','textbook'); + if (ref($settings) eq 'HASH') { + $currdefresponder = $settings->{'anonsurvey_threshold'}; + if (ref($settings->{'uploadquota'}) eq 'HASH') { + foreach my $type (keys(%{$settings->{'uploadquota'}})) { + $curruploadquota{$type} = $settings->{'uploadquota'}{$type}; + } + } + if (ref($settings->{'coursecredits'}) eq 'HASH') { + foreach my $type (@types) { + next if ($type eq 'community'); + $defcredits{$type} = $settings->{'coursecredits'}->{$type}; + if ($defcredits{$type} ne '') { + $currusecredits = 1; + } + } + } + if (ref($settings->{'postsubmit'}) eq 'HASH') { + if ($settings->{'postsubmit'}->{'client'} eq 'off') { + $postsubmitclient = 0; + foreach my $type (@types) { + $deftimeout{$type} = $staticdefaults{'postsubmit'}; + } + } else { + foreach my $type (@types) { + if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') { + if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) { + $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type}; + } else { + $deftimeout{$type} = $staticdefaults{'postsubmit'}; + } + } else { + $deftimeout{$type} = $staticdefaults{'postsubmit'}; + } + } + } + } else { + foreach my $type (@types) { + $deftimeout{$type} = $staticdefaults{'postsubmit'}; + } + } + if (ref($settings->{'mysqltables'}) eq 'HASH') { + foreach my $type (keys(%{$settings->{'mysqltables'}})) { + $currmysql{$type} = $settings->{'mysqltables'}{$type}; + } + } else { + foreach my $type (@types) { + $currmysql{$type} = $staticdefaults{'mysqltables'}; + } + } + } else { + foreach my $type (@types) { + $deftimeout{$type} = $staticdefaults{'postsubmit'}; + } + } + if (!$currdefresponder) { + $currdefresponder = $staticdefaults{'anonsurvey_threshold'}; + } elsif ($currdefresponder < 1) { + $currdefresponder = 1; + } + foreach my $type (@types) { + if ($curruploadquota{$type} eq '') { + $curruploadquota{$type} = $staticdefaults{'uploadquota'}; + } + } + $datatable .= + ''. + $choices{'anonsurvey_threshold'}. + ''. + ''. + ''. + ''."\n"; + $itemcount ++; + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''. + $choices{'uploadquota'}. + ''. + ''. + ''; + foreach my $type (@types) { + $datatable .= ''; + } + $datatable .= '
'.&mt($type).'
'. + '
'."\n"; + $itemcount ++; + my $onclick = "toggleDisplay(this.form,'credits');"; + my $display = 'none'; + if ($currusecredits) { + $display = 'block'; + } + my $additional = '
'. + ''.&mt('Default credits').'
'; + foreach my $type (@types) { + next if ($type eq 'community'); + $additional .= ''; + } + $additional .= '
'.&mt($type).'
'. + '
'."\n"; + %defaultchecked = ('coursecredits' => 'off'); + @toggles = ('coursecredits'); + my $current = { + 'coursecredits' => $currusecredits, + }; + (my $table,$itemcount) = + &radiobutton_prefs($current,\@toggles,\%defaultchecked, + \%choices,$itemcount,$onclick,$additional,'left'); + $datatable .= $table; + $onclick = "toggleDisplay(this.form,'studentsubmission');"; + my $display = 'none'; + if ($postsubmitclient) { + $display = 'block'; + } + $additional = '
'. + &mt('Number of seconds submit is disabled').'
'. + ''.&mt('Enter 0 to remain disabled until page reload.').'
'. + ''; + foreach my $type (@types) { + $additional .= ''; + } + $additional .= '
'.&mt($type).'
'. + '
'."\n"; + %defaultchecked = ('postsubmit' => 'on'); + @toggles = ('postsubmit'); + $current = { + 'postsubmit' => $postsubmitclient, + }; + ($table,$itemcount) = + &radiobutton_prefs($current,\@toggles,\%defaultchecked, + \%choices,$itemcount,$onclick,$additional,'left'); + $datatable .= $table; + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''. + $choices{'mysqltables'}. + ''. + ''. + ''; + foreach my $type (@types) { + $datatable .= ''; + } + $datatable .= '
'.&mt($type).'
'. + '
'."\n"; + $itemcount ++; + + } + $$rowtotal += $itemcount; + return $datatable; +} + +sub print_selfenrollment { + my ($position,$dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable); + my $itemcount = 1; + my @types = ('official','unofficial','community','textbook'); + if (($position eq 'top') || ($position eq 'middle')) { + my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles(); + my %descs = &Apache::lonuserutils::selfenroll_default_descs(); + my @rows; + my $key; + if ($position eq 'top') { + $key = 'admin'; + if (ref($rowsref) eq 'ARRAY') { + @rows = @{$rowsref}; + } + } elsif ($position eq 'middle') { + $key = 'default'; + @rows = ('types','registered','approval','limit'); + } + foreach my $row (@rows) { + if (defined($titlesref->{$row})) { + $itemcount ++; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''.$titlesref->{$row}.''. + ''. + ''; + my (%current,%currentcap); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$key}) eq 'HASH') { + foreach my $type (@types) { + if (ref($settings->{$key}->{$type}) eq 'HASH') { + $current{$type} = $settings->{$key}->{$type}->{$row}; + } + if (($row eq 'limit') && ($key eq 'default')) { + if (ref($settings->{$key}->{$type}) eq 'HASH') { + $currentcap{$type} = $settings->{$key}->{$type}->{'cap'}; + } + } + } + } + } + my %roles = ( + '0' => &Apache::lonnet::plaintext('dc'), + ); + + foreach my $type (@types) { + unless (($row eq 'registered') && ($key eq 'default')) { + $datatable .= ''; + } + } + unless (($row eq 'registered') && ($key eq 'default')) { + $datatable .= ''; + } + foreach my $type (@types) { + if ($type eq 'community') { + $roles{'1'} = &mt('Community personnel'); + } else { + $roles{'1'} = &mt('Course personnel'); + } + $datatable .= ''; + } + $datatable .= ''; + } + $datatable .= '
'.&mt($type).'
'; + if ($position eq 'top') { + my %checked; + if ($current{$type} eq '0') { + $checked{'0'} = ' checked="checked"'; + } else { + $checked{'1'} = ' checked="checked"'; + } + foreach my $role ('1','0') { + $datatable .= ' '; + } + } else { + if ($row eq 'types') { + my %checked; + if ($current{$type} =~ /^(all|dom)$/) { + $checked{$1} = ' checked="checked"'; + } else { + $checked{''} = ' checked="checked"'; + } + foreach my $val ('','dom','all') { + $datatable .= ' '; + } + } elsif ($row eq 'registered') { + my %checked; + if ($current{$type} eq '1') { + $checked{'1'} = ' checked="checked"'; + } else { + $checked{'0'} = ' checked="checked"'; + } + foreach my $val ('0','1') { + $datatable .= ' '; + } + } elsif ($row eq 'approval') { + my %checked; + if ($current{$type} =~ /^([12])$/) { + $checked{$1} = ' checked="checked"'; + } else { + $checked{'0'} = ' checked="checked"'; + } + for my $val (0..2) { + $datatable .= ' '; + } + } elsif ($row eq 'limit') { + my %checked; + if ($current{$type} =~ /^(allstudents|selfenrolled)$/) { + $checked{$1} = ' checked="checked"'; + } else { + $checked{'none'} = ' checked="checked"'; + } + my $cap; + if ($currentcap{$type} =~ /^\d+$/) { + $cap = $currentcap{$type}; + } + foreach my $val ('none','allstudents','selfenrolled') { + $datatable .= ' '; + } + $datatable .= '
'. + ''.&mt('Maximum allowed: '). + ''. + ''; + } + } + $datatable .= '
'; + } + } elsif ($position eq 'bottom') { + $datatable .= &print_validation_rows('selfenroll',$dom,$settings,\$itemcount); + } + $$rowtotal += $itemcount; + return $datatable; +} + +sub print_validation_rows { + my ($caller,$dom,$settings,$rowtotal) = @_; + my ($itemsref,$namesref,$fieldsref); + if ($caller eq 'selfenroll') { + ($itemsref,$namesref,$fieldsref) = &Apache::lonuserutils::selfenroll_validation_types(); + } elsif ($caller eq 'requestcourses') { + ($itemsref,$namesref,$fieldsref) = &Apache::loncoursequeueadmin::requestcourses_validation_types(); + } + my %currvalidation; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'validation'}) eq 'HASH') { + %currvalidation = %{$settings->{'validation'}}; + } + } + my $datatable; + my $itemcount = 0; + foreach my $item (@{$itemsref}) { + my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''. + $namesref->{$item}. + ''. + ''; + if (($item eq 'url') || ($item eq 'button')) { + $datatable .= ''. + ''; + } elsif ($item eq 'fields') { + my @currfields; + if (ref($currvalidation{$item}) eq 'ARRAY') { + @currfields = @{$currvalidation{$item}}; + } + foreach my $field (@{$fieldsref}) { + my $check = ''; + if (grep(/^\Q$field\E$/,@currfields)) { + $check = ' checked="checked"'; + } + $datatable .= ' '; + } + } elsif ($item eq 'markup') { + $datatable .= ''; + } + $datatable .= ''."\n"; + if (ref($rowtotal)) { + $itemcount ++; + } + } + if ($caller eq 'requestcourses') { + my %currhash; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'validation'}) eq 'HASH') { + if ($settings->{'validation'}{'dc'} ne '') { + $currhash{$settings->{'validation'}{'dc'}} = 1; + } + } + } + my $numinrow = 2; + my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio', + 'validationdc',%currhash); + my $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''; + if ($numdc > 1) { + $datatable .= &mt('Course creation processed as: (choose Dom. Coord.)'); + } else { + $datatable .= &mt('Course creation processed as: '); + } + $datatable .= ''.$dctable.''; + $itemcount ++; + } + if (ref($rowtotal)) { + $$rowtotal += $itemcount; + } + 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); + my $curroffloadnow; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'offloadnow'}) eq 'HASH') { + $curroffloadnow = $settings->{'offloadnow'}; + } + } + $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$rowtotal); + } else { + $datatable .= ''. + &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 .= ''; + $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,$curroffloadnow,$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'); + my $checkednow; + if (ref($curroffloadnow) eq 'HASH') { + if ($curroffloadnow->{$server}) { + $checkednow = ' checked="checked"'; + } + } + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ' + + '. + &mt('[_1] when busy, offloads to:' + ,''.$server.'').'
'. + ''."\n". + ''. + "\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}.''."\n". + ''.$current{$type}.''."\n". + ''.$canselect{$type}.''."\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 = 8; + 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 .= ''. + ''. + '

'; + 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 .= + ''; + 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}.'
'. + ''.$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), + '_LC_ipchangesso' => &mt('SSO users from [_1], with IP mismatch',$dom), + '_LC_ipchange' => &mt('Non-SSO users with IP mismatch'), + ); + my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange'); + 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; + my %ruletitles = &offloadtype_text(); + if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) { + @rulenames = ('balancer','offloadedto','specific'); + } else { + @rulenames = ('default','homeserver'); + 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', + 'balancer' => 'Session hosted on Load Balancer, after re-authentication', + 'offloadedto' => 'Session hosted on offload server, after re-authentication', + 'particular' => 'Session hosted (after re-auth) on server:', + ); + 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', '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', + 'updatesmail' => 'E-mail from nightly check of LON-CAPA module integrity/updates', + 'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID', ); my %short_titles = &Apache::lonlocal::texthash ( adminemail => 'Admin E-mail address', @@ -1702,15 +4160,51 @@ sub contact_titles { sub tool_titles { my %titles = &Apache::lonlocal::texthash ( - aboutme => 'Personal Home Page', + aboutme => 'Personal web page', blog => 'Blog', + webdav => 'WebDAV', portfolio => 'Portfolio', official => 'Official courses (with institutional codes)', unofficial => 'Unofficial courses', + community => 'Communities', + textbook => 'Textbook courses', + ); + return %titles; +} + +sub courserequest_titles { + my %titles = &Apache::lonlocal::texthash ( + official => 'Official', + unofficial => 'Unofficial', + community => 'Communities', + textbook => 'Textbook', + 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 institutional validation).', + ); + return %conditions; +} + + sub print_usercreation { my ($position,$dom,$settings,$rowtotal) = @_; my $numinrow = 4; @@ -1736,42 +4230,22 @@ sub print_usercreation { $rowcount ++; } } - my ($emailrules,$emailruleorder) = - &Apache::lonnet::inst_userrules($dom,'email'); - if (ref($emailrules) eq 'HASH') { - if (keys(%{$emailrules}) > 0) { - $datatable .= &user_formats_row('email',$settings,$emailrules, - $emailruleorder,$numinrow,$rowcount); - $$rowtotal ++; - $rowcount ++; - } - } if ($rowcount == 0) { $datatable .= ''.&mt('No format rules have been defined for usernames or IDs in this domain.').''; $$rowtotal ++; $rowcount ++; } } elsif ($position eq 'middle') { - my @creators = ('author','course','selfcreate'); + my @creators = ('author','course','requestcrs'); my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username'); my %lt = &usercreation_types(); my %checked; - my @selfcreate; if (ref($settings) eq 'HASH') { if (ref($settings->{'cancreate'}) eq 'HASH') { foreach my $item (@creators) { $checked{$item} = $settings->{'cancreate'}{$item}; } - if (ref($settings->{'cancreate'}{'selfcreate'}) eq 'ARRAY') { - @selfcreate = @{$settings->{'cancreate'}{'selfcreate'}}; - } elsif ($settings->{'cancreate'}{'selfcreate'} ne '') { - if ($settings->{'cancreate'}{'selfcreate'} eq 'any') { - @selfcreate = ('email','login','sso'); - } elsif ($settings->{'cancreate'}{'selfcreate'} ne 'none') { - @selfcreate = ($settings->{'cancreate'}{'selfcreate'}); - } - } } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') { foreach my $item (@creators) { if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) { @@ -1783,10 +4257,8 @@ sub print_usercreation { my $rownum = 0; foreach my $item (@creators) { $rownum ++; - if ($item ne 'selfcreate') { - if ($checked{$item} eq '') { - $checked{$item} = 'any'; - } + if ($checked{$item} eq '') { + $checked{$item} = 'any'; } my $css_class; if ($rownum%2) { @@ -1797,30 +4269,18 @@ sub print_usercreation { $datatable .= ''. ''.$lt{$item}. ''; - my @options; - if ($item eq 'selfcreate') { - push(@options,('email','login','sso')); - } else { - @options = ('any'); - if (ref($rules) eq 'HASH') { - if (keys(%{$rules}) > 0) { - push(@options,('official','unofficial')); - } + my @options = ('any'); + if (ref($rules) eq 'HASH') { + if (keys(%{$rules}) > 0) { + push(@options,('official','unofficial')); } - push(@options,'none'); } + push(@options,'none'); foreach my $option (@options) { my $type = 'radio'; my $check = ' '; - if ($item eq 'selfcreate') { - $type = 'checkbox'; - if (grep(/^\Q$option\E$/,@selfcreate)) { - $check = ' checked="checked" '; - } - } else { - if ($checked{$item} eq $option) { - $check = ' checked="checked" '; - } + if ($checked{$item} eq $option) { + $check = ' checked="checked" '; } $datatable .= ' '. ''. + ''. + ''.$title{'togglecatscomm'}.''. + ' '. + ''. + ''. + ''.$title{'categorizecomm'}.''. + ''. + ' '. + ''. ''; - $$rowtotal += 2; + $$rowtotal += 4; } else { my $css_class; my $itemcount = 1; @@ -2310,7 +5243,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; @@ -2330,18 +5271,38 @@ sub print_coursecategories { } $datatable .= ''; } - $datatable .= ''; - if ($parent eq 'instcode') { - $datatable .= ''.&mt('Official courses') - .'
(' - .&mt('with institutional codes').')' - .' ' - .''; + $datatable .= ''; + 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 - .'