Annotation of loncom/interface/courseprefs.pm, revision 1.28.2.4

1.1       raeburn     1: # The LearningOnline Network with CAPA
1.2       raeburn     2: # Handler to set configuration settings for a course
1.1       raeburn     3: #
1.28.2.4! raeburn     4: # $Id: courseprefs.pm,v 1.28.2.3 2010/09/17 23:59:27 raeburn Exp $
1.1       raeburn     5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#
                     23: # /home/httpd/html/adm/gpl.txt
                     24: #
                     25: # http://www.lon-capa.org/
                     26: #
                     27: #
                     28: ###############################################################
                     29: ##############################################################
                     30: 
1.23      raeburn    31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: courseprefs- Handler to set/modify course configuration
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
                     39: courseprefs provides an interface for setting general course configuration
                     40: 
                     41: =head1 DESCRIPTION
                     42: 
                     43: This module is used for configuration of a course
                     44: 
                     45: =head1 INTERNAL SUBROUTINES
                     46: 
                     47: =over
                     48: 
                     49: =item get_allitems()
                     50: 
                     51: =item print_config_box()
                     52: 
                     53: =item process_changes()
                     54: 
                     55: =item get_sec_str()
                     56: 
                     57: =item check_clone()
                     58: 
                     59: =item store_changes()
                     60: 
                     61: =item update_env()
                     62: 
                     63: =item display_disallowed()
                     64: 
                     65: =item get_course()
                     66: 
                     67: =item get_jscript()
                     68: 
                     69: =item cloners_javascript()
                     70: 
                     71: =item print_courseinfo()
                     72: 
                     73: =item new_cloners_dom_row()
                     74: 
                     75: =item can_modify_catsettings()
                     76: 
                     77: =item assign_course_categories()
                     78: 
                     79: =item print_localization()
                     80: 
                     81: =item get_lang_choices()
                     82: 
                     83: =item print_feedback()
                     84: 
                     85: =item user_table()
                     86: 
                     87: =item select_recipient()
                     88: 
                     89: =item select_sections()
                     90: 
                     91: =item print_discussion()
                     92: 
                     93: =item role_checkboxes()
                     94: 
                     95: =item print_classlists()
                     96: 
                     97: =item print_appearance()
                     98: 
                     99: =item print_grading()
                    100: 
                    101: =item print_printouts()
                    102: 
                    103: =item print_spreadsheet()
                    104: 
                    105: =item print_bridgetasks()
                    106: 
                    107: =item print_other()
                    108: 
                    109: =item get_other_items()
                    110: 
                    111: =item item_table_row_start()
                    112: 
                    113: =item item_table_row_end()
                    114: 
                    115: =item yes_no_radio()
                    116: 
                    117: =item select_from_options()
                    118: 
                    119: =item make_item_rows()
                    120: 
                    121: Creates table used to display and set course configuration items.
                    122: 
                    123: Inputs: $cdom,$items,$ordered,$settings,$rowtotal,$crstype
                    124: where $cdom is course's domain, $items is HASH ref for current config
                    125: item, $ordered is ARRAY ref of items to include in row in 
                    126: display order, $settings is HASH ref of current values forrow,
                    127: $rowtotal is SCALAR ref used to accumulate row count, $crstype is    
                    128: course type.
                    129: 
                    130: Returns: $datatable
                    131: HTML mark-up of data table which accumulates individual rows.  
                    132: 
                    133: =item nothidepriv_row()
                    134: 
                    135: Creates row containing form elements used to display and set
                    136: whether Domain coordinators who are currently included in  
                    137: advanced course user .db file for a course are to be hidden (e.g.,
                    138: in syllabus, or from course user lists).
                    139: 
                    140: Inputs: $cdom,$item,$settings,$crstype
                    141: where $cdom is course domain, item is nothideprivileged, $settings is
                    142: HASH ref of the current values for nothideprivileged, $crstype is 
                    143: course type (Course or Community). 
                    144: 
                    145: Return: $datatable
                    146: HTML mark-up for Privileged users (Domain Coordinators) in staff listing.
                    147: 
                    148: =item print_hdrfmt_row()
                    149: 
                    150: Creates row containing form elements used to display and set
                    151: substitution items and text to be used in the header included
                    152: on printouts.
                    153: 
                    154: Inputs: $item,$settings
                    155: where $item is print_header_format, and $settings is a HASH ref
                    156: of the current values stored for print_header_format.
                    157: 
                    158: Returns: $output
                    159: HTML mark-up containing Javascript functions: reOrder() and getIndexByName()
                    160: used to dynamically update position selectboxes, and HTML table elements
                    161: for the "Print header format" row.
                    162: 
                    163: =item position_selector()
                    164: 
                    165: Creates a select box which can be used to reorder substitutions
                    166: and text included in a printout header. 
                    167: 
                    168: Inputs: $pos,$num,$maxnum
                    169: where $pos is current position, $num is the unique identifier,
                    170: and $maxnum is the total number of items (both substitutions
                    171: and text in the printout header.
                    172: 
                    173: Returns: $output
                    174: HTML mark-up for the selectbox and a hidden form element containing 
                    175: the current position.   
                    176: 
                    177: =item substitution_selector()
                    178: 
                    179: Creates a combination of select box for choosing an item 
                    180: (student name, course ID or assignment note) to substitute, 
                    181: and a corresponding size limit in the header used for printouts.
                    182: 
                    183: Inputs: $num,$subst,$limit,$crstype
                    184: where $num is the unique identifier, $subst is the current 
                    185: substitution (n,c or a, for name, course or note respectively,
                    186: $limit is the current size limit (integer), and $crstype is
                    187: course type - course or community.
                    188: 
                    189: Returns: $output
                    190: HTML mark-up for selectbox and textbox (separate table cells).  
                    191: 
                    192: =item change_clone()
                    193: 
                    194: Modifies the list of courses a user can clone (stored
                    195: in the user's environment.db file), called when a
                    196: change is made to the list of users allowed to clone
                    197: a course.
                    198: 
                    199: Inputs: $action,$cloner
                    200: where $action is add or drop, and $cloner is identity of
                    201: user for whom cloning ability is to be changed in course.
                    202: 
                    203: Returns: nothing
                    204: 
                    205: =back
                    206: 
                    207: =cut
                    208: 
                    209: 
1.1       raeburn   210: package Apache::courseprefs;
                    211: 
                    212: use strict;
                    213: use Apache::Constants qw(:common :http);
                    214: use Apache::lonnet;
                    215: use Apache::loncommon();
                    216: use Apache::lonhtmlcommon();
                    217: use Apache::lonconfigsettings;
                    218: use Apache::lonlocal;
                    219: use LONCAPA qw(:DEFAULT :match);
                    220: 
                    221: sub handler {
                    222:     my $r=shift;
                    223:     if ($r->header_only) {
                    224:         &Apache::loncommon::content_type($r,'text/html');
                    225:         $r->send_http_header;
                    226:         return OK;
                    227:     }
                    228:     my $context = 'course';
                    229:     my $cid = $env{'request.course.id'};
                    230:     my ($cnum,$cdom) = &get_course($cid);
                    231:     my $crstype = &Apache::loncommon::course_type();
                    232:     my $parm_permission = &Apache::lonnet::allowed('opa',$cid);
                    233:     my $navmap = Apache::lonnavmaps::navmap->new();
                    234:     if ($parm_permission && $navmap) {
                    235:         &Apache::loncommon::content_type($r,'text/html');
                    236:         $r->send_http_header;
                    237:     } else {
                    238:         if ($navmap) {
1.9       raeburn   239:             if ($crstype eq 'Community') {
                    240:                 $env{'user.error.msg'}=
                    241:                     "/adm/courseprefs:opa:0:0:Cannot modify community settings";
                    242:             } else {
                    243:                 $env{'user.error.msg'}=
                    244:                     "/adm/courseprefs:opa:0:0:Cannot modify course settings";
                    245:             }
1.1       raeburn   246:         } else {
1.9       raeburn   247:             if ($crstype eq 'Community') {
                    248:                 $env{'user.error.msg'}=
                    249:                     "/adm/courseprefs::0:1:Course environment gone, reinitialize the community";
                    250:             } else {
                    251:                 $env{'user.error.msg'}=
                    252:                     "/adm/courseprefs::0:1:Course environment gone, reinitialize the course";
                    253: 
                    254:             }
1.1       raeburn   255:         }
                    256:         return HTTP_NOT_ACCEPTABLE;
                    257:     }
                    258: 
1.4       raeburn   259:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                    260:                                             ['phase','actions','origin']);
1.1       raeburn   261:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.4       raeburn   262:     if ($env{'form.origin'} eq 'params') {
                    263:         &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
                    264:                                                 text=>"Parameter Manager"});
                    265:     }
1.9       raeburn   266:     my ($brtext,$brtitle,$crsinfotext,$crsinfodesc,$crscateg,$crshide);
                    267:     my %lt;
                    268:     if ($crstype eq 'Community') {
                    269:         %lt = (
                    270:                 conf => 'Community Configuration',
                    271:                 edit => 'Edit Community Configuration',
                    272:                 gens => 'General community settings',
                    273:                 idnu => 'Community ID or number',
                    274:                 desc => 'Community Description',
1.24      raeburn   275:                 ownr => 'Community Owner',
1.25      raeburn   276:                 cown => 'Community Co-owners',
1.9       raeburn   277:                 catg => 'Categorize community',
                    278:                 excc => 'Exclude from community catalog',
                    279:                 clon => 'Users allowed to clone community',
                    280:                 rept => 'Replacement titles for standard community roles',
                    281:                 time => 'Timezone where the community is located',
                    282:                 date => 'Locale used for community calendar',
                    283:                 coco => 'Community Content',
                    284:                 copo => 'Community Policy',
1.13      bisitz    285:                 priv => 'Domain Coordinators in community',
1.9       raeburn   286:                 defd => 'Default dates for member access',
                    287:                 stuv => 'Member-viewable membership list options',
                    288:                 stul => 'Member agreement needed to be listed',
                    289:                 clas => 'Membership and Facilitator Listing',
                    290:                 priv => 'Privileged users (Domain Coordinators) in facilitator listing',
                    291:                 defc => 'Default Community Spreadsheet',
                    292:                 defs => 'Default User Spreadsheet',
                    293:                 seme => 'Send message to member when clicking Done on Tasks'
                    294:               );
                    295:     } else {
                    296:         %lt = (
                    297:                 conf => 'Course Configuration',
                    298:                 edit => 'Edit Course Configuration',
1.20      faziophi  299:                 gens => 'General course settings',
                    300:                 idnu => 'Course ID or number',
                    301:                 desc => 'Course Description',
1.24      raeburn   302:                 ownr => 'Course Owner',
1.25      raeburn   303:                 cown => 'Course Co-owners',
1.9       raeburn   304:                 catg => 'Categorize course',
                    305:                 excc => 'Exclude from course catalog',
                    306:                 clon => 'Users allowed to clone course',
                    307:                 rept => 'Replacement titles for standard course roles',
1.20      faziophi  308:                 time => 'Timezone in which the course takes place',
                    309:                 date => 'Locale used for course calendar',
1.9       raeburn   310:                 coco => 'Course Content',
                    311:                 copo => 'Course Policy',
1.13      bisitz    312:                 priv => 'Domain Coordinators in course',
1.9       raeburn   313:                 defd => 'Default dates for student access',
                    314:                 stuv => 'Student-viewable classlist options',
                    315:                 stul => 'Student agreement needed to be listed',
                    316:                 clas => 'Classlists and Staff Listing',
                    317:                 priv => 'Privileged users (Domain Coordinators) in staff listing',
                    318:                 defc => 'Default Course Spreadsheet',
                    319:                 defs => 'Default Student Spreadsheet',
                    320:                 seme => 'Send message to student when clicking Done on Tasks',
                    321:               );
                    322:     }
1.1       raeburn   323:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs',
1.9       raeburn   324:         text=>$lt{'conf'}});
1.1       raeburn   325:     my $breadcrumbs =
1.9       raeburn   326:         &Apache::lonhtmlcommon::breadcrumbs($lt{'edit'});
1.1       raeburn   327: 
                    328:     my $phase = 'pickactions';
                    329:     if ( exists($env{'form.phase'}) ) {
                    330:         $phase = $env{'form.phase'};
                    331:     }
                    332: 
                    333:     if ($phase eq 'categorizecourse') {
1.9       raeburn   334:         &assign_course_categories($r,$crstype);
1.1       raeburn   335:         return OK;
                    336:     }
                    337: 
                    338:     my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
                    339:     my @prefs_order = ('courseinfo','localization','feedback','discussion',
                    340:                        'classlists','appearance','grading','printouts',
                    341:                        'spreadsheet','bridgetasks','other');
                    342: 
                    343:     my %prefs = (
                    344:         'courseinfo' =>
1.9       raeburn   345:                    { text => $lt{'gens'},
1.1       raeburn   346:                      help => 'Course_Environment',
1.28.2.1  raeburn   347:                      header => [{col1 => 'Setting',
                    348:                                  col2 => 'Value'}],
1.25      raeburn   349:                      ordered => ['owner','co-owners','description','courseid',
                    350:                                  'categories','hidefromcat','externalsyllabus',
1.28.2.1  raeburn   351:                                  'url','rolenames','cloners'],
1.3       raeburn   352:                      itemtext => {
1.25      raeburn   353:                                    'owner'            => $lt{'ownr'},
                    354:                                    'co-owners'        => $lt{'cown'},
                    355:                                    'description'      => $lt{'desc'},
                    356:                                    'courseid'         => $lt{'idnu'},
                    357:                                    'categories'       => $lt{'catg'},
                    358:                                    'hidefromcat'      => $lt{'excc'},
                    359:                                    'cloners'          => $lt{'clon'}, 
                    360:                                    'externalsyllabus' => 'URL of Syllabus',
                    361:                                    'url'              => 'Top Level Map',
                    362:                                    'rolenames'        => $lt{'rept'},
1.3       raeburn   363:                                  },
1.1       raeburn   364:                     },
                    365:         'localization' =>
1.27      raeburn   366:                     { text => 'Language and Time Localization',
1.1       raeburn   367:                       help => 'Course_Environment',
1.28.2.1  raeburn   368:                       header => [{col1 => 'Setting',
                    369:                                   col2 => 'Value',}],
1.1       raeburn   370:                       ordered => ['languages','timezone','datelocale'],
1.3       raeburn   371:                       itemtext => {
1.20      faziophi  372:                                     languages  => 'Languages used',
1.9       raeburn   373:                                     timezone   => $lt{'time'}, 
                    374:                                     datelocale => $lt{'date'},
1.3       raeburn   375:                                   },
1.1       raeburn   376:                     },
                    377:         'feedback' =>
1.20      faziophi  378:                     { text => 'Feedback messages',
1.1       raeburn   379:                       help => 'Course_Environment',
                    380:                       header => [{col1 => 'Questions about:',
1.28.2.1  raeburn   381:                                   col2 => 'Recipients'},
                    382:                                  {col1 => 'Questions about:',
                    383:                                   col2 => 'Custom Text'}],
1.3       raeburn   384:                       ordered => ['question.email','comment.email','policy.email'],
                    385:                       itemtext => {
                    386:                                      'question.email' => 'Resource Content',
1.9       raeburn   387:                                      'comment.email'  => $lt{'coco'},
                    388:                                      'policy.email'   => $lt{'copo'},
1.3       raeburn   389:                                   },
1.1       raeburn   390:                     },
                    391:         'discussion' =>
                    392:                     { text => 'Discussion and Chat',
                    393:                       help => 'Course_Environment',
1.28.2.3  raeburn   394:                       ordered => ['pch.roles.denied','pch.users.denied',
                    395:                                   'plc.roles.denied','plc.users.denied',
1.1       raeburn   396:                                   'allow_limited_html_in_feedback',
                    397:                                   'allow_discussion_post_editing'],
1.3       raeburn   398:                       itemtext => {
1.28.2.3  raeburn   399:                          'pch.roles.denied'             => 'No Resource Discussion',
                    400:                          'pch.users.denied'             => 'No Resource Discussion',
                    401:                          'plc.roles.denied'             => 'No Chat room use',
                    402:                          'plc.users.denied'             => 'No Chat room use',
1.20      faziophi  403:                          allow_limited_html_in_feedback => 'Allow limited HTML in discussion',
                    404:                          allow_discussion_post_editing  => 'Users can edit/delete own discussion posts',
1.3       raeburn   405:                                   },
1.1       raeburn   406:                     },
                    407:         'classlists' =>
1.9       raeburn   408:                    { text => $lt{'clas'},
1.1       raeburn   409:                      help => 'Course_Environment',
                    410:                      header => [{col1 => 'Type',
1.9       raeburn   411:                                  col2 => $lt{'defd'}},
1.1       raeburn   412:                                 {col1 => 'Setting',
1.9       raeburn   413:                                  col2 => $lt{'priv'}},
1.1       raeburn   414:                                 {col1 => 'Setting',
1.9       raeburn   415:                                  col2 => $lt{'stuv'}}],
1.1       raeburn   416:                      ordered => ['default_enrollment_start_date',
                    417:                                  'default_enrollment_end_date',
                    418:                                  'nothideprivileged','student_classlist_view',
1.26      raeburn   419:                                  'student_classlist_opt_in','student_classlist_portfiles'],
1.3       raeburn   420:                      itemtext => {
                    421:                          default_enrollment_start_date => 'Start date',
                    422:                          default_enrollment_end_date   => 'End date',
1.9       raeburn   423:                          nothideprivileged             => $lt{'priv'},
                    424:                          student_classlist_view        => $lt{'stuv'},
1.26      raeburn   425:                          student_classlist_opt_in      => $lt{'stul'},
1.3       raeburn   426:                          student_classlist_portfiles   => 'Include link to accessible portfolio files',
                    427:                                   },
1.1       raeburn   428:                    },
                    429:         'appearance' =>
1.20      faziophi  430:                    { text => 'Display of resources ',
1.1       raeburn   431:                      help => 'Course_Environment',
1.28.2.1  raeburn   432:                      header => [{col1 => 'Setting',
                    433:                                  col2 => 'Value',}],
1.1       raeburn   434:                      ordered => ['default_xml_style','pageseparators',
                    435:                                  'disable_receipt_display','texengine',
                    436:                                  'tthoptions'],
1.3       raeburn   437:                       itemtext => {
1.17      faziophi  438:                           default_xml_style       => 'Default XML style file',
1.20      faziophi  439:                           pageseparators          => 'Visibly Separate Items on Pages',
                    440:                           disable_receipt_display => 'Disable display of problem receipts',
                    441:                           texengine               => 'Force use of a specific math rendering engine',
1.3       raeburn   442:                           tthoptions              => 'Default set of options to pass to tth/m when converting TeX',
                    443:                                   },
1.1       raeburn   444:                   },
                    445:         'grading' =>
                    446:                   { text => 'Grading',
                    447:                     help => 'Course_Environment',
1.28.2.1  raeburn   448:                     header => [{col1 => 'Setting',
                    449:                                 col2 => 'Value',}],
1.1       raeburn   450:                     ordered => ['grading','rndseed',
                    451:                                 'receiptalg','disablesigfigs'],
1.3       raeburn   452:                     itemtext => {
1.20      faziophi  453:                         grading        => 'Grading',
                    454:                         rndseed        => 'Randomization algorithm used',
                    455:                         receiptalg     => 'Receipt algorithm used',
                    456:                         disablesigfigs => 'Disable checking of Significant Figures',
1.3       raeburn   457:                                 },
                    458: 
1.1       raeburn   459:                   },
                    460:         'printouts' =>
1.20      faziophi  461:                   { text => 'Printout generation',
1.1       raeburn   462:                     help => 'Course_Environment',
1.28.2.1  raeburn   463:                     header => [{col1 => 'Setting',
                    464:                                 col2 => 'Value',}],
1.1       raeburn   465:                     ordered => ['problem_stream_switch','suppress_tries',
                    466:                                 'default_paper_size','print_header_format',
1.14      raeburn   467:                                 'disableexampointprint','canuse_pdfforms'],
1.3       raeburn   468:                     itemtext => {
                    469:                         problem_stream_switch => 'Allow problems to be split over pages',
                    470:                         suppress_tries        => 'Suppress number of tries in printing',
                    471:                         default_paper_size    => 'Default paper type',
                    472:                         print_header_format   => 'Print header format',
                    473:                         disableexampointprint => 'Disable automatically printing point values on exams',
1.14      raeburn   474:                         canuse_pdfforms    => 'Users can print problems as PDF forms and upload later for grading',
1.3       raeburn   475:                                 },
1.1       raeburn   476:                   },
                    477:         'spreadsheet' =>
                    478:                   { text => 'Spreadsheets',
                    479:                     help => 'Course_Environment',
1.28.2.1  raeburn   480:                     header => [{col1 => 'Setting',
                    481:                                 col2 => 'Value'}],
1.1       raeburn   482:                     ordered => ['spreadsheet_default_classcalc',
                    483:                                 'spreadsheet_default_studentcalc',
                    484:                                 'spreadsheet_default_assesscalc','hideemptyrows'],
1.3       raeburn   485:                     itemtext => {
1.9       raeburn   486:                                   spreadsheet_default_classcalc   => $lt{'defc'},
                    487:                                   spreadsheet_default_studentcalc => $lt{'defs'},
1.3       raeburn   488:                                   spreadsheet_default_assesscalc  => 'Default Assessment Spreadsheet',
                    489:                                   hideemptyrows                   => 'Hide Empty Rows in Spreadsheets',
                    490:                                 },
1.1       raeburn   491:                   },
                    492:         'bridgetasks' =>
                    493:                   { text => 'Bridge tasks',
                    494:                     help => 'Course_Environment',
1.28.2.1  raeburn   495:                     header => [{col1 => 'Setting',
                    496:                                 col2 => 'Value'}],
1.1       raeburn   497:                     ordered => ['task_messages','task_grading',
                    498:                                 'suppress_embed_prompt'],
1.3       raeburn   499:                     itemtext => {
1.9       raeburn   500:                         task_messages         => $lt{'seme'},
1.3       raeburn   501:                         task_grading          => 'Bridge Task grading by instructors and TAs in sections' ,
1.5       raeburn   502:                         suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio',
1.3       raeburn   503:                                 },
1.1       raeburn   504:                   },
                    505:         'other' =>
                    506:                   { text => 'Other settings',
                    507:                     help => 'Course_Environment',
                    508:                     header => [ {col1 => 'Item',
                    509:                                  col2 => 'Value',
                    510:                               }],
                    511:                   },
                    512:     );
                    513:     if ($phase eq 'process') {
1.3       raeburn   514:         my @allitems = &get_allitems(%prefs);
1.1       raeburn   515:         &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context,
1.3       raeburn   516:                                                  \@prefs_order,\%prefs,\%values,
                    517:                                                   $cnum,undef,\@allitems);
1.1       raeburn   518:     } elsif ($phase eq 'display') {
1.12      raeburn   519:         my $jscript = &get_jscript($cdom,$phase,$crstype);
1.3       raeburn   520:         my @allitems = &get_allitems(%prefs);
1.1       raeburn   521:         &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,
1.9       raeburn   522:             \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype);
1.1       raeburn   523:     } else {
                    524:         &Apache::lonconfigsettings::display_choices($r,$phase,$context,
                    525:                                                     \@prefs_order,\%prefs);
                    526:     }
                    527:     return OK;
                    528: }
                    529: 
1.3       raeburn   530: sub get_allitems {
                    531:     my (%prefs) = @_;
                    532:     my @allitems;
                    533:     foreach my $item (keys(%prefs)) {
                    534:         if (ref($prefs{$item}) eq 'HASH') {
                    535:             if (ref($prefs{$item}{'ordered'}) eq 'ARRAY') {
                    536:                 push(@allitems,@{$prefs{$item}{'ordered'}});
                    537:                 if ($item eq 'feedback') {
                    538:                     push(@allitems,(map { $_.'.text'; } @{$prefs{$item}{'ordered'}}));
                    539:                 }
                    540:             }
                    541:         }
                    542:     }
                    543:     return @allitems;
                    544: }
                    545: 
1.1       raeburn   546: sub print_config_box {
1.9       raeburn   547:     my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype) = @_;
1.1       raeburn   548:     my $ordered = $item->{'ordered'};
1.3       raeburn   549:     my $itemtext = $item->{'itemtext'};
1.1       raeburn   550:     my $rowtotal = 0;
                    551:     my $output =
1.28.2.1  raeburn   552:          '<table class="LC_nested_outer">
                    553:           <tr>
                    554:            <th align="left" valign="middle"><span class="LC_nobreak" style="font-size: larger;" >'.
                    555:            &mt($item->{text}).'&nbsp;'.
                    556:            &Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".
                    557:           '</tr>';
1.1       raeburn   558:     if (($action eq 'feedback') || ($action eq 'classlists')) {
                    559:         $output .= '
1.28.2.1  raeburn   560:           <tr>
                    561:            <td>
                    562:             <table class="LC_nested">';
1.18      faziophi  563:         if (exists $item->{'header'}->[0]->{'col1'} || 
                    564:             exists $item->{'header'}->[0]->{'col2'}) {
                    565: 			$output .= '          
                    566:           	<tr class="LC_info_row">
1.1       raeburn   567:               <td class="LC_left_item">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
                    568:               <td class="LC_right_item">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
1.18      faziophi  569:             </tr>';
                    570:         }
1.1       raeburn   571:         $rowtotal ++;
                    572:         if ($action eq 'feedback') {
1.3       raeburn   573:             $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1       raeburn   574:         } elsif ($action eq 'classlists') {
1.9       raeburn   575:             $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   576:         }
                    577:         $output .= '
                    578:            </table>
1.28.2.1  raeburn   579:           </td>
                    580:          </tr>
                    581:          <tr>
                    582:            <td>
1.1       raeburn   583:             <table class="LC_nested">
                    584:              <tr class="LC_info_row">
                    585:               <td class="LC_left_item">'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';
                    586:         $output .= '
                    587:               <td class="LC_right_item">'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
                    588:              </tr>';
                    589:         if ($action eq 'classlists') {
1.9       raeburn   590:             $output .= &print_classlists('middle',$cdom,$settings,$itemtext,\$rowtotal,$crstype).
1.1       raeburn   591:                        '
                    592:             </table>
1.28.2.1  raeburn   593:            </td>
                    594:           </tr>
                    595:           <tr>
                    596:            <td>
1.18      faziophi  597:             <table class="LC_nested">';
                    598:             if (exists $item->{'header'}->[0]->{'col1'} || 
                    599:             	exists $item->{'header'}->[0]->{'col2'}) {
                    600: 				$output .= '          
                    601: 				<tr class="LC_info_row">
                    602: 				  <td class="LC_left_item">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
                    603: 				  <td class="LC_right_item">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
                    604: 				</tr>';
1.28.2.1  raeburn   605:             }
1.1       raeburn   606:         }
                    607:     } else {
                    608:         $output .= '
1.28.2.1  raeburn   609:           <tr>
                    610:            <td>
1.18      faziophi  611:             <table class="LC_nested">';
                    612:         if (exists $item->{'header'}->[0]->{'col1'} || 
                    613:             exists $item->{'header'}->[0]->{'col2'}) {
                    614: 			$output .= '          
                    615:           	<tr class="LC_info_row">
1.1       raeburn   616:               <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
                    617:               <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
1.18      faziophi  618:             </tr>';
                    619:         }
1.1       raeburn   620:     }
                    621:     $rowtotal ++;
                    622:     if ($action eq 'courseinfo') {
1.9       raeburn   623:         $output .= &print_courseinfo($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   624:     } elsif ($action eq 'localization') {
1.3       raeburn   625:         $output .= &print_localization($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1       raeburn   626:     } elsif ($action eq 'feedback') {
1.3       raeburn   627:         $output .= &print_feedback('bottom',$cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1       raeburn   628:     } elsif ($action eq 'discussion') {
1.3       raeburn   629:         $output .= &print_discussion($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1       raeburn   630:     } elsif ($action eq 'classlists') {
1.9       raeburn   631:         $output .= &print_classlists('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   632:     } elsif ($action eq 'appearance') {
1.9       raeburn   633:         $output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   634:     } elsif ($action eq 'grading') {
1.9       raeburn   635:         $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   636:     } elsif ($action eq 'printouts') {
1.9       raeburn   637:         $output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   638:     } elsif ($action eq 'spreadsheet') {
1.9       raeburn   639:         $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   640:     } elsif ($action eq 'bridgetasks') {
1.9       raeburn   641:         $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1       raeburn   642:     } elsif ($action eq 'other') {
1.9       raeburn   643:         $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype);
1.1       raeburn   644:     }
                    645:     $output .= '
                    646:    </table>
1.28.2.1  raeburn   647:   </td>
                    648:  </tr>
                    649: </table><br />';
1.1       raeburn   650:     return ($output,$rowtotal);
                    651: }
                    652: 
                    653: sub process_changes {
1.9       raeburn   654:     my ($cdom,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;
1.3       raeburn   655:     my %newvalues;
                    656:     if (ref($item) eq 'HASH') {
                    657:         if (ref($changes) eq 'HASH') {
                    658:             my @ordered;
                    659:             if ($action eq 'other') {
                    660:                 @ordered = &get_other_items($cdom,$values,$allitems);
                    661:                 if ($env{'form.newp_name'} ne '') {
                    662:                     my $newp = $env{'form.newp_name'};
                    663:                     if ($env{'form.newp_value'} ne '') {
                    664:                         if (ref($allitems) eq 'ARRAY') {
                    665:                             unless ((grep(/^\Q$newp\E$/,@ordered)) || 
                    666:                                     (grep(/^\Q$newp\E$/,@{$allitems}))) {
                    667:                                 $changes->{$newp} = $env{'form.newp_value'};
                    668:                             }
                    669:                         }
                    670:                     }
                    671:                 }
                    672:             } elsif (ref($item->{'ordered'}) eq 'ARRAY') {
                    673:                 @ordered = @{$item->{'ordered'}};
                    674:             }
                    675:             if (@ordered > 0) {
                    676:                 if ($action eq 'feedback') {
                    677:                     foreach my $entry (@ordered) {
                    678:                         my $userstr = '';
                    679:                         my $total = $env{'form.'.$entry.'_total'};
                    680:                         if ($total) {
                    681:                             my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
                    682:                             for (my $i=0; $i<$total; $i++) {
                    683:                                 unless (grep(/^$i$/,@deletes)) {
                    684:                                     $userstr .= $env{'form.'.$entry.'_user_'.$i}.
                    685:                                                 &get_sec_str($entry,$i).',';
                    686:                                 }
                    687:                             }
                    688:                         } else {
                    689:                             $total = 0;
                    690:                         } 
                    691:                         if ($env{'form.'.$entry.'_uname_'.$total} ne '') {
                    692:                             my $uname = $env{'form.'.$entry.'_uname_'.$total};
                    693:                             my $udom = $env{'form.'.$entry.'_udom_'.$total};
                    694:                             if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') {
                    695:                                 $userstr =~ s/,$//;
                    696:                                 $disallowed->{'feedback'}{$entry} = $uname.':'.$udom;
                    697:                             } else {
                    698:                                 $userstr .= $uname.':'.$udom.&get_sec_str($entry,$total);
                    699:                             }
                    700:                         } else {
                    701:                             $userstr =~ s/,$//;
                    702:                         }
                    703:                         $newvalues{$entry} = $userstr;
                    704:                         if ($newvalues{$entry} ne $values->{$entry}) {
                    705:                             $changes->{$entry} = $newvalues{$entry};
                    706:                         }
                    707:                         my $ext_entry = $entry.'.text';
                    708:                         $newvalues{$ext_entry} = $env{'form.'.$ext_entry};
                    709:                         if ($newvalues{$ext_entry} ne $values->{$ext_entry}) {
                    710:                             $changes->{$ext_entry} = $newvalues{$ext_entry};
                    711:                         }
                    712:                     }
                    713:                 } else {
                    714:                     foreach my $entry (@ordered) {
                    715:                         if ($entry eq 'cloners') {
                    716:                             if ($env{'form.cloners_all'}) {
                    717:                                 $newvalues{$entry} = '*';
                    718:                             } else {
                    719:                                 my @clonedoms;
                    720:                                 if (exists($env{'form.cloners_activate'})) {
                    721:                                     my $actnum = $env{'form.cloners_activate'};
                    722:                                     if ($actnum ne '') {
1.28.2.4! raeburn   723:                                         if ($env{'form.cloners_dom_'.$actnum} ne '') {
        !           724:                                             my $clonedom = $env{'form.cloners_dom_'.$actnum};
1.3       raeburn   725:                                             if (&check_clone($clonedom,$disallowed) eq 'ok') {
                    726:                                                 $newvalues{$entry} = '*:'.$clonedom;
                    727:                                                 push(@clonedoms,$newvalues{$entry});
                    728:                                             }
                    729:                                         }
                    730:                                     }
                    731:                                 } else {
                    732:                                     my $num = $env{'form.cloners_total'};
                    733:                                     my @deletes = 
                    734:                                         &Apache::loncommon::get_env_multiple('form.cloners_delete');
                    735:                                     for (my $i=0; $i<$num; $i++) {
                    736:                                         if (!grep(/^$i$/,@deletes)) {
                    737:                                             my $clonedom = $env{'form.cloners_dom_'.$i};
                    738:                                             if (&check_clone($clonedom,$disallowed) eq 'ok') {
                    739:                                                 if (!grep(/^\*:\Q$clonedom\E$/,@clonedoms)) {
                    740:                                                     push (@clonedoms,'*:'.$clonedom);
                    741:                                                 }
                    742:                                             }
                    743:                                         }
                    744:                                     }
                    745:                                     if (@clonedoms) {
                    746:                                         $newvalues{$entry}=join(',',@clonedoms);
                    747:                                     }
                    748:                                 }
                    749:                                 if ($env{'form.cloners_newdom'} ne '') {
                    750:                                     my $clonedom = $env{'form.cloners_newdom'};
                    751:                                     if (&check_clone($clonedom,$disallowed) eq 'ok') {
                    752:                                         my $newdom = '*:'.$env{'form.cloners_newdom'};
                    753:                                         if (@clonedoms) { 
                    754:                                             if (!grep(/^\Q$newdom\E$/,@clonedoms)) {
                    755:                                                 $newvalues{$entry} .= ','.$newdom;
                    756:                                             }
                    757:                                         } else {
                    758:                                             $newvalues{$entry} = $newdom;
                    759:                                         }
                    760:                                     }
                    761:                                 }
                    762:                                 if ($env{'form.'.$entry} ne '') {
                    763:                                     my @cloners = split(',',$env{'form.'.$entry});
                    764:                                     my @okcloners;
                    765:                                     foreach my $cloner (@cloners) {
1.23      raeburn   766:                                         $cloner =~ s/^\s+//;
                    767:                                         $cloner =~ s/\s+$//;
                    768:                                         unless ($cloner eq '') {
                    769:                                             my ($uname,$udom) = split(':',$cloner);
                    770:                                             if (&check_clone($udom,$disallowed,$uname) eq 'ok') {
                    771:                                                 if (!grep(/^\Q$cloner\E$/,@okcloners)) {
                    772:                                                     push(@okcloners,$cloner);
                    773:                                                 }
1.3       raeburn   774:                                             }
                    775:                                         }
                    776:                                     }
                    777:                                     if (@okcloners) {
                    778:                                         my $okclonestr = join(',',@okcloners);
                    779:                                         if ($newvalues{$entry} ne '') {
                    780:                                             $newvalues{$entry} .= ','.$okclonestr;
                    781:                                         } else {
                    782:                                             $newvalues{$entry} = $okclonestr;
                    783:                                         }
                    784:                                     }
                    785:                                 }
                    786:                             }
                    787:                             if (ref($disallowed) eq 'HASH') {
                    788:                                 if (ref($disallowed->{'cloners'}) eq 'HASH') {
                    789:                                     foreach my $key (keys(%{$disallowed->{'cloners'}})) {
                    790:                                         $disallowed->{'cloners'}{$key} =~ s/,$//;
                    791:                                     }
                    792:                                 }
                    793:                             }
1.25      raeburn   794:                         } elsif ($entry eq 'co-owners') {
                    795:                             my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    796:                             my $coowners = $values->{'internal.co-owners'};
                    797:                             my @currcoown;
                    798:                             if ($coowners) {
                    799:                                 @currcoown = split(',',$coowners);
                    800:                             }
                    801:                             if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
                    802:                                 my $autocoowner;
                    803:                                 if (($crstype eq 'Course') && 
                    804:                                     ($values->{'internal.coursecode'})) {
                    805:                                     my %domconf =
                    806:                                         &Apache::lonnet::get_dom('configuration',['autoenroll'],$cdom);
                    807:                                     if (ref($domconf{'autoenroll'}) eq 'HASH') {
                    808:                                         $autocoowner = $domconf{'autoenroll'}{'co-owners'};
                    809:                                     }
                    810:                                 }
                    811:                                 unless ($autocoowner) {
                    812:                                     my @keepcoowners = &Apache::loncommon::get_env_multiple('form.coowners');
                    813:                                     my @pendingcoowners = &Apache::loncommon::get_env_multiple('form.pendingcoowners');
                    814:                                     my @invitecoowners =  &Apache::loncommon::get_env_multiple('form.invitecoowners');
                    815:                                     if (@invitecoowners) {
                    816:                                         push(@pendingcoowners,@invitecoowners);
                    817:                                     }
                    818:                                     $newvalues{'pendingco-owners'} = join(',',sort(@pendingcoowners));
                    819:                                     $newvalues{'co-owners'} = join(',',sort(@keepcoowners));
                    820:                                     if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) {
                    821:                                         $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'};
                    822:                                         push(@{$changes->{$entry}{'changed'}},'co-owners');
                    823:                                     }
                    824:                                     if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) {
                    825:                                         $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'};
                    826:                                         push(@{$changes->{$entry}{'changed'}},'pendingco-owners');
                    827:                                     }
                    828:                                 }
                    829:                             } else {
                    830:                                 my (@newpending,@newcoown);
                    831:                                 my $uname = $env{'user.name'};
                    832:                                 my $udom = $env{'user.domain'};
                    833:                                 my $pendingcoowners = $values->{'internal.pendingco-owners'};
                    834:                                 my @pendingcoown = split(',',$pendingcoowners);
                    835:                                 if ($env{'form.pending_coowoner'}) {
                    836:                                     foreach my $item (@pendingcoown) {
                    837:                                         unless ($item eq $uname.':'.$udom) {
                    838:                                             push(@newpending,$item);
                    839:                                         }
                    840:                                     }
                    841:                                     @newcoown = @currcoown;
                    842:                                     if ($env{'form.pending_coowoner'} eq 'accept') {
                    843:                                         unless (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {
                    844:                                             push(@newcoown,$uname.':'.$udom);
                    845:                                         }
                    846:                                     }
                    847:                                 } elsif ($env{'form.remove_coowoner'}) {
                    848:                                     foreach my $item (@currcoown) {
                    849:                                         unless ($item eq $uname.':'.$udom) {
                    850:                                             push(@newcoown,$item);
                    851:                                         }
                    852:                                     }
                    853:                                     if ($pendingcoowners ne '') {
                    854:                                         @newpending = @pendingcoown;
                    855:                                     }
                    856:                                 }
                    857:                                 $newvalues{'pendingco-owners'} = join(',',sort(@newpending));
                    858:                                 $newvalues{'co-owners'} = join(',',sort(@newcoown));
                    859:                                 if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) {
                    860:                                     $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'};
                    861:                                     push(@{$changes->{$entry}{'changed'}},'co-owners');
                    862:                                 }
                    863:                                 if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) {
                    864:                                     $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'};
                    865:                                     push(@{$changes->{$entry}{'changed'}},'pendingco-owners');
                    866:                                 }
                    867:                             }
1.3       raeburn   868:                         } elsif ($entry =~ /^default_enrollment_(start|end)_date$/) {
                    869:                             $newvalues{$entry}=&Apache::lonhtmlcommon::get_date_from_form($entry);
                    870:                         } elsif ($entry eq 'rolenames') {
                    871:                             my %adv_roles =
                    872:                                 &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
1.9       raeburn   873:                             my @stds;
                    874:                             if ($crstype eq 'Community') {
                    875:                                 @stds = ('co');
                    876:                             } else {
                    877:                                 @stds = ('cc');
                    878:                             }
                    879:                             push(@stds,('in','ta','ep','ad','st'));
1.3       raeburn   880:                             my (@replacements,@regulars);
                    881:                             foreach my $role (@stds) {
                    882:                                 if ($values->{$role.'.plaintext'} ne '') {
1.9       raeburn   883:                                     push(@replacements,$role);
1.3       raeburn   884:                                 } else {
                    885:                                     push(@regulars,$role);
                    886:                                 }
1.9       raeburn   887:                             }
1.3       raeburn   888:                             foreach my $stdrole (@stds) {
                    889:                                 my $ext_entry = $entry.'_'.$stdrole;
                    890:                                 my $stdname = &Apache::lonnet::plaintext($stdrole,$crstype,
                    891:                                                                          $env{'request.course.id'},1);
                    892:                                 if ($env{'form.'.$ext_entry} eq $stdname) {
                    893:                                     $newvalues{$ext_entry} = '';
                    894:                                 } else {
                    895:                                     $newvalues{$ext_entry} = $env{'form.'.$ext_entry};
                    896:                                 }
                    897:                                 if ($newvalues{$ext_entry} ne $values->{$stdrole.'.plaintext'}) {
                    898:                                     my $dupname = 0;
                    899:                                     if ($newvalues{$ext_entry} ne '') {
                    900:                                         if (grep(/^\Q$newvalues{$ext_entry}\E$/,@replacements)) {
                    901:                                             $dupname = 1;
                    902:                                             push(@{$disallowed->{'rolenames'}{'replacements'}},$newvalues{$ext_entry});
                    903:                                         }
                    904:                                         if (!$dupname) {
                    905:                                             if (grep(/^\Q$newvalues{$ext_entry}\E$/,@regulars)) {
                    906:                                                 $dupname = 1;
                    907:                                                 push(@{$disallowed->{rolenames}{'regulars'}},$newvalues{$ext_entry});
                    908:                                             }
                    909:                                         }
                    910:                                         if (!$dupname) {
                    911:                                             foreach my $role (keys(%adv_roles)) {
                    912:                                                 if ($role =~ m{^cr/$match_domain/$match_name/\Q$newvalues{$ext_entry}\E$}) {
                    913:                                                     $dupname = 1;
                    914:                                                     push(@{$disallowed->{rolenames}{'customrole'}},$newvalues{$ext_entry});
                    915:                                                     last;
                    916:                                                 }
                    917:                                             }
                    918:                                         }
                    919:                                     }
                    920:                                     if (!$dupname) {
                    921:                                         $changes->{$ext_entry} = $newvalues{$ext_entry};
                    922:                                     }
                    923:                                 }
                    924:                             }
                    925:                         } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied')) {
                    926:                             my @denied = &Apache::loncommon::get_env_multiple('form.'.$entry);
                    927:                             @denied = sort(@denied);
                    928:                             my $deniedstr = '';
                    929:                             if (@denied > 0) {
                    930:                                 $deniedstr = join(',',@denied);  
                    931:                             }
                    932:                             $newvalues{$entry} = $deniedstr;
                    933:                         } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied')) {
                    934:                             my $total = $env{'form.'.$entry.'_total'};
                    935:                             my $userstr = '';
                    936:                             my @denied;  
                    937:                             if ($total > 0) {
                    938:                                 my @deletes = 
                    939:                                     &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
                    940:                                 for (my $i=0; $i<$total; $i++) {
                    941:                                     unless (grep(/^$i$/,@deletes)) {
                    942:                                         $userstr .= $env{'form.'.$entry.'_user_'.$i}.',';
                    943:                                         push(@denied,$env{'form.'.$entry.'_user_'.$i});
                    944:                                     }
                    945:                                 }
                    946:                             } else {
                    947:                                 $total = 0;
                    948:                             }
                    949:                             if ($env{'form.'.$entry.'_uname_'.$total} ne '') {
                    950:                                 my $uname = $env{'form.'.$entry.'_uname_'.$total};
                    951:                                 my $udom = $env{'form.'.$entry.'_udom_'.$total};
                    952:                                 if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') {
                    953:                                     $userstr =~ s/,$//;
                    954:                                     $disallowed->{'discussion'}{$entry} = $uname.':'.$udom;
                    955:                                 } else {
                    956:                                     my $newuser .= $uname.':'.$udom;
                    957:                                     if (grep(/^\Q$newuser\E$/,@denied)) {
                    958:                                         $userstr =~ s/,$//;
                    959:                                     } else {
                    960:                                         $userstr .= $newuser;
                    961:                                     }
                    962:                                 }
                    963:                             } else {
                    964:                                 $userstr =~ s/,$//;
                    965:                             }
                    966:                             $newvalues{$entry} = $userstr;
                    967:                         } elsif ($entry eq 'allow_discussion_post_editing') {
                    968:                             my @canedit = &Apache::loncommon::get_env_multiple('form.'.$entry);
                    969:                             @canedit = sort(@canedit);
                    970:                             foreach my $role (@canedit) {
                    971:                                 my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$role);
                    972:                                 if ((grep(/^\s*$/,@secs)) || (@secs == 0)) {
                    973:                                     $newvalues{$entry} .= $role.',';
                    974:                                 } else {
                    975:                                     foreach my $sec (@secs) {
                    976:                                         $newvalues{$entry} .= $role.':'.$sec.',';
                    977:                                     }
                    978:                                 }
                    979:                             }
                    980:                             $newvalues{$entry} =~ s/,$//;
                    981:                         } elsif ($entry eq 'nothideprivileged') {
                    982:                             my @curr_nothide;
                    983:                             my @new_nothide;
                    984:                             if ($values->{$entry} ne '') {
                    985:                                 foreach my $user (split(/\s*\,\s*/,$values->{$entry})) {
                    986:                                     my $nothide;
                    987:                                     if ($user !~ /:/) {
                    988:                                         $nothide = join(':',split(/[\@]/,$user));
                    989:                                     } else {
                    990:                                         $nothide = $user;
                    991:                                     }
                    992:                                     if ((defined($nothide)) && 
                    993:                                         (!grep(/^\Q$nothide\E$/,@curr_nothide))) {
                    994:                                         push(@curr_nothide,$nothide);   
                    995:                                     }
                    996:                                 }
                    997:                             }
                    998:                             foreach my $key (keys(%env)) {
                    999:                                 if ($key =~ /^form\.\Q$entry\E_($match_username:$match_domain)$/) {
1.7       raeburn  1000:                                     if ($env{$key}) {
1.3       raeburn  1001:                                        my $nothide = $1;
                   1002:                                        if (!grep(/^\Q$nothide\E$/,@new_nothide)) {
                   1003:                                            push(@new_nothide,$nothide); 
                   1004:                                         }
                   1005:                                     }
                   1006:                                 }
                   1007:                             }
                   1008:                             @new_nothide = sort(@new_nothide);
                   1009:                             my @differences =
                   1010:                                 &Apache::loncommon::compare_arrays(\@curr_nothide,
                   1011:                                                                    \@new_nothide);
                   1012:                             if (@differences > 0) {
                   1013:                                 if (@new_nothide > 0) { 
                   1014:                                     $newvalues{$entry} = join(',',@new_nothide);
                   1015:                                 } else {
                   1016:                                     $newvalues{$entry} = '';
                   1017:                                 }
                   1018:                             } else {
                   1019:                                 $newvalues{$entry} = $values->{$entry}; 
                   1020:                             }
                   1021:                         } elsif ($entry eq 'print_header_format') {
                   1022:                             my $maxnum = $env{'form.printfmthdr_maxnum'};
                   1023:                             my @newhdr;
                   1024:                             if ($maxnum > 2) {
                   1025:                                 for (my $i=0; $i<$maxnum-2; $i++) {
                   1026:                                     if ($env{'form.printfmthdr_del_'.$i}) {
                   1027:                                         $newhdr[$env{'form.printfmthdr_pos_'.$i}] = '';
                   1028:                                     } else {
                   1029:                                         my $hdr;
                   1030:                                         if ($env{'form.printfmthdr_sub_'.$i} =~ /^[nca]$/) {
                   1031:                                             $hdr = '%';
                   1032:                                             if ($env{'form.printfmthdr_limit_'.$i} =~ /^\d+$/) {
                   1033:                                                 $hdr .= $env{'form.printfmthdr_limit_'.$i};
                   1034:                                             }
                   1035:                                             $hdr .= $env{'form.printfmthdr_sub_'.$i};
1.28.2.2  raeburn  1036:                                         } elsif ($env{'form.printfmthdr_text_'.$i} ne '') {
                   1037:                                             $hdr = $env{'form.printfmthdr_text_'.$i};
1.3       raeburn  1038:                                         }
                   1039:                                         $newhdr[$env{'form.printfmthdr_pos_'.$i}] = $hdr;
                   1040:                                     }
                   1041:                                 }
                   1042:                             }
                   1043:                             my $newsub = $maxnum-2;
                   1044:                             if ($env{'form.printfmthdr_sub_'.$newsub} =~ /^[nca]$/) {
                   1045:                                 my $hdr = '%';
                   1046:                                 if ($env{'form.printfmthdr_limit_'.$newsub} =~ /^\d+$/) {
                   1047:                                     $hdr .= $env{'form.printfmthdr_limit_'.$newsub};
                   1048:                                 }
                   1049:                                 $hdr .= $env{'form.printfmthdr_sub_'.$newsub};
                   1050:                                 $newhdr[$env{'form.printfmthdr_pos_'.$newsub}] = $hdr;
                   1051:                             }
                   1052:                             my $newtext = $maxnum-1;
                   1053:                             $newhdr[$env{'form.printfmthdr_pos_'.$newtext}] = $env{'form.printfmthdr_text_'.$newtext};
                   1054:                             $newvalues{$entry} = join('',@newhdr);
                   1055:                         } elsif ($entry eq 'languages') {
                   1056:                             my $langstr;
                   1057:                             my $total = $env{'form.'.$entry.'_total'};
                   1058:                             if ($total) {
                   1059:                                 my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
                   1060:                                 for (my $i=0; $i<$total; $i++) {
                   1061:                                     unless (grep(/^$i$/,@deletes)) {
                   1062:                                        $langstr .= $env{'form.'.$entry.'_'.$i}.',';
                   1063:                                     }
                   1064:                                 }
                   1065:                             } else {
                   1066:                                 $total = 0;
                   1067:                             }
                   1068:                             if ($env{'form.'.$entry.'_'.$total} ne '') {
                   1069:                                 my $newlang = $env{'form.'.$entry.'_'.$total};
                   1070:                                 my %langchoices = &get_lang_choices();
                   1071:                                 if ($langchoices{$newlang}) {
                   1072:                                     $langstr .= $newlang;
                   1073:                                 } else {
                   1074:                                     $langstr =~ s/,$//;
                   1075:                                     $disallowed->{'localization'}{$entry} = $newlang;
                   1076:                                 }
                   1077:                             } else {
                   1078:                                 $langstr =~ s/,$//;
                   1079:                             }
                   1080:                             $newvalues{$entry} = $langstr;
                   1081:                         } else {
                   1082:                             $newvalues{$entry} = $env{'form.'.$entry};
                   1083:                         }
1.25      raeburn  1084:                         unless ($entry eq 'co-owners') {
                   1085:                             if ($newvalues{$entry} ne $values->{$entry}) {
                   1086:                                 $changes->{$entry} = $newvalues{$entry};
                   1087:                             }
1.3       raeburn  1088:                         }
                   1089:                     }
                   1090:                 }
                   1091:             }
                   1092:         }
                   1093:     }
                   1094:     return;
                   1095: }
                   1096: 
                   1097: sub get_sec_str {
                   1098:     my ($entry,$num) = @_;
                   1099:     my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$num);
                   1100:     my $secstr;
                   1101:     if (grep(/^\s*$/,@secs)) {
                   1102:         $secstr = '';
                   1103:     } elsif (@secs > 0) {
                   1104:         $secstr = join(';',@secs);
                   1105:     }
                   1106:     if ($secstr ne '') {
                   1107:         return '('.$secstr.')';
                   1108:     }
                   1109:     return;
                   1110: }
                   1111: 
                   1112: sub check_clone {
                   1113:     my ($clonedom,$disallowed,$clonename) = @_;
                   1114:     return if (ref($disallowed) ne 'HASH');
                   1115:     if ($clonedom !~ /^$match_domain$/) {
                   1116:         $disallowed->{'cloners'}{'format'} .= $clonedom.',';
                   1117:         return;
                   1118:     } elsif (!&Apache::lonnet::domain($clonedom)) {
                   1119:         $disallowed->{'cloners'}{'domain'} .= $clonedom.',';
                   1120:         return;
                   1121:     }
                   1122:     if ($clonename ne '') {
                   1123:         if ($clonename !~ /^$match_username$/) {
                   1124:             $disallowed->{'cloners'}{'format'} .= $clonename.':'.$clonedom.',';
                   1125:             return;
                   1126:         } else {
                   1127:             if (&Apache::lonnet::homeserver($clonename,$clonedom) eq 'no_host') {
                   1128:                 $disallowed->{'cloners'}{'newuser'} .= $clonename.':'.$clonedom.',';
                   1129:                 return;
                   1130:             }
                   1131:         }
                   1132:     }
                   1133:     return 'ok';
                   1134: }
                   1135: 
                   1136: sub store_changes {
1.9       raeburn  1137:     my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_;
1.3       raeburn  1138:     my ($chome,$output);
1.23      raeburn  1139:     my (%storehash,@delkeys,@need_env_update,@oldcloner);
1.3       raeburn  1140:     if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {
                   1141:         %storehash = %{$values};
                   1142:     } else {
1.9       raeburn  1143:         if ($crstype eq 'Community') {
                   1144:             $output = &mt('No changes made to community settings.');
                   1145:         } else {
                   1146:             $output = &mt('No changes made to course settings.');
                   1147:         }
                   1148:         return $output;
1.3       raeburn  1149:     }
                   1150:     my %yesno = (
                   1151:                  hidefromcat           => '1',
                   1152:                  problem_stream_switch => '1',
                   1153:                  suppress_tries        => '1',
                   1154:                  disableexampointprint => '1',
                   1155:                  hideemptyrows         => '1',
                   1156:                  suppress_embed_prompt => '1',
                   1157:                 );
                   1158:     foreach my $item (@{$prefs_order}) {
                   1159:         if (grep(/^\Q$item\E$/,@{$actions})) {
                   1160:             $output .= '<h3>'.&mt($prefs->{$item}{'text'}).'</h3>';
                   1161:             if (ref($changes->{$item}) eq 'HASH') {
                   1162:                 if (keys(%{$changes->{$item}}) > 0) {
1.22      wenzelju 1163:                     $output .= &mt('Changes made:').'<ul style="list-style:none;">';
1.3       raeburn  1164:                     if ($item eq 'other') {
                   1165:                         foreach my $key (sort(keys(%{$changes->{$item}}))) {
                   1166:                             $storehash{$key} = $changes->{$item}{$key};
                   1167:                             if ($changes->{$item}{$key} eq '') {
                   1168:                                 push(@delkeys,$key);
1.22      wenzelju 1169:                                 $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]','<i>'.$key.'</i>')).'</li>';
1.3       raeburn  1170:                             } else {
1.22      wenzelju 1171:                                 $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]','<i>'.$key.'</i>',
                   1172:                                            "'$storehash{$key}'")).'</li>';
1.3       raeburn  1173:                             }
                   1174:                         }
                   1175:                     } else {
                   1176:                         if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {
                   1177:                             my @settings = @{$prefs->{$item}->{'ordered'}};
                   1178:                             if ($item eq 'feedback') {
                   1179:                                 push(@settings,(map { $_.'.text'; } @settings));
                   1180:                             }
                   1181:                             foreach my $key (@settings) {
                   1182:                                 if ($key eq 'rolenames') {
                   1183:                                     my $displayname = $prefs->{$item}->{'itemtext'}{$key};
                   1184:                                     my $msg;
1.9       raeburn  1185:                                     my @roles;
                   1186:                                     if ($crstype eq 'Community') {
                   1187:                                         @roles = ('co');
                   1188:                                     } else {
                   1189:                                         @roles = ('cc');
                   1190:                                     }
                   1191:                                     push(@roles,('in','ta','ep','ad','st'));
                   1192:                                     foreach my $role (@roles) {
1.3       raeburn  1193:                                         next if (!exists($changes->{$item}{$key.'_'.$role}));
                   1194:                                         my $stdname = &Apache::lonnet::plaintext($role,$crstype,undef,1);
                   1195:                                         my $newname = $changes->{$item}{$key.'_'.$role};
                   1196:                                         $storehash{$role.'.plaintext'} = $newname;
                   1197:                                         if ($newname eq '') {
                   1198:                                             $newname = $stdname;
                   1199:                                         }
                   1200:                                         $msg .= '<li>'.&mt('[_1] set to [_2]','<i>'.$stdname.'</i>',
                   1201:                                                 "'<b>".$newname."</b>'").'</li>';
                   1202:                                     }
                   1203:                                     if ($msg ne '') {
1.22      wenzelju 1204:                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt($displayname)).'<ul class="LC_success">'.$msg.'</ul></li>';
1.3       raeburn  1205:                                     }
                   1206:                                 } else {
                   1207:                                     next if (!exists($changes->{$item}{$key}));
                   1208:                                     my ($displayname,$text);
                   1209:                                     $text = $prefs->{$item}->{'itemtext'}{$key};
1.25      raeburn  1210:                                     my $displayval;
                   1211:                                     unless ($key eq 'co-owners') {
                   1212:                                         $displayval = $changes->{$item}{$key};
                   1213:                                     }
1.3       raeburn  1214:                                     if ($item eq 'feedback') {
                   1215:                                         if ($key =~ /^(question|policy|comment)(\.email)\.text$/) {
                   1216:                                             $text = $prefs->{$item}->{'itemtext'}{$1.$2};
                   1217:                                             $displayname = &mt('Custom text for '.$text.' questions');
                   1218:                                         } else {
                   1219:                                             $displayname = &mt('Recipients of '.$text.' questions');
                   1220:                                         }
                   1221:                                     } elsif ($item eq 'discussion') {
                   1222:                                         if ($key =~ /^p(lc|ch)\.roles\.denied/) {
                   1223:                                             $displayname = &mt("$text (role-based)");
                   1224:                                             if ($displayval ne '') {
                   1225:                                                 my @roles = split(',',$displayval);
                   1226:                                                 @roles = map { &Apache::lonnet::plaintext($_); } @roles;
                   1227:                                                 $displayval = join(', ',@roles);
                   1228:                                             } 
                   1229:                                         } elsif ($key =~ /^p(lc|ch)\.users\.denied/) {
                   1230:                                             $displayname = &mt("$text (specific user(s))");
                   1231:                                         } else {
                   1232:                                             if ($key eq 'allow_discussion_post_editing') {
                   1233:                                                 if ($displayval ne '') {
                   1234:                                                     my @roles = split(',',$displayval);
                   1235:                                                     my @longroles;
                   1236:                                                     foreach my $role (@roles) {
                   1237:                                                         my ($trole,$sec) = split(':',$role);
                   1238:                                                         my $rolename = 
                   1239:                                                             &Apache::lonnet::plaintext($trole);
                   1240:                                                         if ($sec ne '') {
                   1241:                                                             $rolename .= ':'.$sec;
                   1242:                                                         }
                   1243:                                                         push(@longroles,$rolename);
                   1244:                                                     }
                   1245:                                                     $displayval = join(', ',@longroles);
                   1246:                                                 }
                   1247:                                             }
                   1248:                                             $displayname = &mt($text);
                   1249:                                         }
                   1250:                                     } elsif ($item eq 'spreadsheet') {
                   1251:                                         if ($key =~ /^spreadsheet_default_(studentcalc|assesscalc)$/x) {
                   1252:                                             my $sheettype = $1;
                   1253:                                             if ($sheettype eq 'studentcalc') {
                   1254:                                                 &Apache::lonnet::expirespread('','','studentcalc');
                   1255:                                             } else {
                   1256:                                                 &Apache::lonnet::expirespread('','','assesscalc');
                   1257:                                                 &Apache::lonnet::expirespread('','','studentcalc');
                   1258:                                             }
                   1259:                                         }
                   1260:                                         $displayname = &mt($text);
                   1261:                                     } else {
                   1262:                                         $displayname = &mt($text);
                   1263:                                     }
                   1264:                                     if (defined($yesno{$key})) {
1.14      raeburn  1265:                                         $displayval = &mt('No');
1.3       raeburn  1266:                                         if ($changes->{$item}{$key} eq 'yes') {
1.14      raeburn  1267:                                             $displayval = &mt('Yes');                          
1.3       raeburn  1268:                                         }
                   1269:                                     } elsif (($key =~ /^default_enrollment_(start|end)_date$/) && ($displayval)) {
                   1270:                                         $displayval = &Apache::lonlocal::locallocaltime($displayval);
                   1271:                                     } elsif ($key eq 'categories') {
                   1272:                                         $displayval = $env{'form.categories_display'};
1.14      raeburn  1273:                                     } elsif ($key eq 'canuse_pdfforms') {
                   1274:                                         if ($changes->{$item}{$key} eq '1') {
                   1275:                                             $displayval = &mt('Yes');
                   1276:                                         } elsif ($changes->{$item}{$key} eq '0') {
                   1277:                                             $displayval = &mt('No');
                   1278:                                         }
                   1279:                                     }
1.25      raeburn  1280:                                     if ($key eq 'co-owners') {
                   1281:                                         if (ref($changes->{$item}{$key}) eq 'HASH') {
                   1282:                                             if (ref($changes->{$item}{$key}{'changed'}) eq 'ARRAY') {
                   1283:                                                 foreach my $type ('co-owners','pendingco-owners') {
                   1284:                                                     next unless (grep(/^\Q$type\E$/,@{$changes->{$item}{$key}{'changed'}}));
                   1285:                                                     if ($type eq 'pendingco-owners') {
                   1286:                                                         if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
                   1287:                                                             $displayname = &mt('Invited as co-owners, pending acceptance');
                   1288:                                                         }
                   1289:                                                     }
                   1290:                                                     if ($changes->{$item}{$key}{$type} eq '') {
                   1291:                                                         push(@delkeys,'internal.'.$type);
                   1292:                                                         if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
                   1293:                                                             $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
                   1294:                                                             '<i>'.$displayname.'</i>')).'</li>';
                   1295:                                                         }
                   1296:                                                     } elsif (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
                   1297:                                                         $displayval = join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } split(',',$changes->{$item}{$key}{$type}));
                   1298:                                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
                   1299:                                                                    '<i>'.$displayname.'</i>',
                   1300:                                                                    "'<b>$displayval</b>'")).'</li>';
                   1301:                                                     }
                   1302:                                                 }
                   1303:                                             }
                   1304:                                             unless (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
                   1305:                                                 if ($env{'form.pending_coowoner'} eq 'accept') {
                   1306:                                                         $displayval = &mt('on');
                   1307:                                                 } elsif ($env{'form.pending_coowoner'} eq 'decline') {
                   1308:                                                         $displayval = '';
                   1309:                                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Invitation to be co-owner declined')).'</li>';
                   1310:                                                 } elsif ($env{'form.remove_coowoner'}) {
                   1311:                                                     $displayval = &mt('off');
                   1312:                                                 }
                   1313:                                                 if ($displayval) {
                   1314:                                                     $displayname = &mt('Your co-ownership status');
                   1315:                                                     $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
                   1316:                                                    '<i>'.$displayname.'</i>',
                   1317:                                                    "'<b>$displayval</b>'")).'</li>';
                   1318:                                                 }
                   1319:                                             }
                   1320:                                         }
                   1321:                                     } elsif ($changes->{$item}{$key} eq '') {
1.3       raeburn  1322:                                         push(@delkeys,$key);
1.22      wenzelju 1323:                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
                   1324:                                                    '<i>'.$displayname.'</i>')).'</li>';
1.3       raeburn  1325:                                     } else {
1.22      wenzelju 1326:                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
1.3       raeburn  1327:                                                    '<i>'.$displayname.'</i>',
1.22      wenzelju 1328:                                                    "'<b>$displayval</b>'"));
1.3       raeburn  1329:                                         if ($key eq 'url') {
                   1330:                                             my $bkuptime=time;
                   1331:                                             $output .= ('&nbsp;'x2).&mt('(Previous URL backed up)').': '.
1.28.2.4! raeburn  1332:                                             $storehash{'top level map backup '.$bkuptime} = $values->{$key};
1.3       raeburn  1333:                                         }
                   1334:                                         $output .= '</li>';
                   1335:                                     }
1.25      raeburn  1336:                                     if ($key eq 'co-owners') {
                   1337:                                         if (ref($changes->{$item}{$key}) eq 'HASH') {
                   1338:                                             if (ref($changes->{$item}{$key}{'changed'}) eq 'ARRAY') {
                   1339:                                                 foreach my $type ('co-owners','pendingco-owners') {
                   1340:                                                     next unless (grep(/^\Q$type\E$/,@{$changes->{$item}{$key}{'changed'}}));
                   1341:                                                     $storehash{'internal.'.$type} = $changes->{$item}{$key}{$type};
                   1342:                                                 }
                   1343:                                             }
                   1344:                                         }
                   1345:                                     } else {
                   1346:                                         $storehash{$key} = $changes->{$item}{$key};
                   1347:                                     }
1.3       raeburn  1348:                                 }
1.23      raeburn  1349:                                 if ($key eq 'cloners') {
                   1350:                                     # Get existing cloners
                   1351:                                     my %clonenames = 
                   1352:                                         &Apache::lonnet::dump('environment',$cdom,$cnum,'cloners');
                   1353:                                     if ($clonenames{'cloners'} =~ /,/) {
                   1354:                                         @oldcloner = split(/\s*\,\s*/,$clonenames{'cloners'});
                   1355:                                     } else {
                   1356:                                         $oldcloner[0] = $clonenames{'cloners'};
                   1357:                                     }
                   1358:                                 }
1.3       raeburn  1359:                                 if (($key eq 'description') || ($key eq 'cloners') ||
1.25      raeburn  1360:                                     ($key eq 'hidefromcat') || ($key eq 'categories') ||
                   1361:                                     ($key eq 'co-owners')) {
1.3       raeburn  1362:                                     push(@need_env_update,$key);
                   1363:                                 }
                   1364:                             }
                   1365:                         }
                   1366:                     }
                   1367:                     $output .= '</ul>';
                   1368:                 } else {
1.9       raeburn  1369:                     if ($crstype eq 'Community') {
                   1370:                         $output = &mt('No changes made to community settings.');
                   1371:                     } else {
                   1372:                         $output = &mt('No changes made to course settings.');
                   1373:                     }
1.3       raeburn  1374:                 }
                   1375:             }
                   1376:         }
                   1377:     }
                   1378:     if (&Apache::lonnet::put('environment',\%storehash,$cdom,$cnum) eq 'ok') {
1.23      raeburn  1379:         if (ref($changes) eq 'HASH') {
                   1380:             if (ref($changes->{'courseinfo'}) eq 'HASH') {
                   1381:                 if (exists($changes->{'courseinfo'}{'cloners'})) {
                   1382:                     &change_clone($cdom,$cnum,$changes->{'courseinfo'}{'cloners'},
                   1383:                                   \@oldcloner);
                   1384:                 }
                   1385:             }
                   1386:         }
1.3       raeburn  1387:         if (@delkeys) {
                   1388:             if (&Apache::lonnet::del('environment',\@delkeys,$cdom,$cnum) ne 'ok') {
1.9       raeburn  1389:                 $output .= '<br /><span class="LC_error">';
                   1390:                 if ($crstype eq 'Community') {
                   1391:                     $output .= &mt('An error occurred when removing community settings which are no longer in use.');
                   1392:                 } else {
                   1393:                     $output .= &mt('An error occurred when removing course settings which are no longer in use.');
                   1394:                 }
                   1395:                 $output .= '</span>';
1.14      raeburn  1396:             } else {
                   1397:                 foreach my $key (@delkeys) {
                   1398:                     &Apache::lonnet::delenv('course.'.$cdom.'_'.$cnum.'.'.$key);
                   1399:                 }
1.3       raeburn  1400:             }
                   1401:         }
                   1402:         if (@need_env_update) {
                   1403:             $chome = &Apache::lonnet::homeserver($cnum,$cdom);
                   1404:             &update_env($cnum,$cdom,$chome,\@need_env_update,\%storehash);
                   1405:         }
                   1406:         &Apache::lonnet::coursedescription($env{'request.course.id'},
                   1407:                                            {'freshen_cache' => 1});
                   1408:     } else {
1.9       raeburn  1409:         $output = '<span class="LC_error">';
                   1410:         if ($crstype eq 'Community') {
                   1411:             $output .= &mt('An error occurred when saving changes to community settings, which remain unchanged.');
                   1412:         } else {          
                   1413:             $output .= &mt('An error occurred when saving changes to course settings, which remain unchanged.');
                   1414:         }
                   1415:         $output .= '</span>';
1.3       raeburn  1416:     }
                   1417:     return $output;
                   1418: }
                   1419: 
                   1420: sub update_env {
                   1421:     my ($cnum,$cdom,$chome,$need_env_update,$storehash)  = @_;
                   1422:     my $count = 0;
                   1423:     if ((ref($need_env_update) eq 'ARRAY') && (ref($storehash) eq 'HASH')) {    
                   1424:         my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.');
                   1425:         if (ref($crsinfo{$env{'request.course.id'}}) eq 'HASH') {
                   1426:             foreach my $key (@{$need_env_update}) {
                   1427:                 if ($key eq 'description' && defined($storehash->{$key})) {
                   1428:                     &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.description' => $storehash->{$key}});
                   1429:                     $crsinfo{$env{'request.course.id'}}{'description'} = $storehash->{$key};
                   1430:                     $count ++;
                   1431:                 } elsif (($key eq 'cloners') || ($key eq 'hidefromcat') || ($key eq 'categories')) {
                   1432:                     &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash->{$key}});
                   1433:                     $crsinfo{$env{'request.course.id'}}{$key} = $storehash->{$key};
                   1434:                     $count ++;
1.25      raeburn  1435:                 } elsif ($key eq 'co-owners') {
                   1436:                     if ($storehash->{'internal.co-owners'} ne '') {
                   1437:                         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.co-owners' => $storehash->{'internal.co-owners'}});
                   1438:                     }
                   1439:                     if ($storehash->{'internal.pendingco-owners'} ne '') {
                   1440:                         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.pendingco-owners' => $storehash->{'internal.pendingco-owners'}});
                   1441:                     }
                   1442:                     my @coowners = split(',',$storehash->{'internal.'.$key});
                   1443:                     $crsinfo{$env{'request.course.id'}}{'co-owners'} = \@coowners;
                   1444:                     $count ++;
1.3       raeburn  1445:                 }
                   1446:             }
                   1447:             if ($count) {
                   1448:                 my $putresult = &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime');
                   1449:             }
                   1450:         }
                   1451:     }
                   1452:     return;
                   1453: }
                   1454: 
                   1455: sub display_disallowed {
1.9       raeburn  1456:     my ($item,$disallowed,$prefs,$crstype) = @_;
1.3       raeburn  1457:     my $output;
                   1458:     if ((ref($disallowed) eq 'HASH') && (ref($prefs) eq 'HASH')) {
                   1459:         if (keys(%{$disallowed})) {
                   1460:             if ($item eq 'cloners') {
                   1461:                 my @fails;
                   1462:                 my %lt = &Apache::lonlocal::texthash (
                   1463:                                  format  => 'Invalid format',
                   1464:                                  domain  => 'Domain does not exist',
                   1465:                                  newuser => 'LON-CAPA user(s) do(es) not exist.',
                   1466:                          );
                   1467:                 foreach my $error ('format','domain','newuser') {
                   1468:                     if (defined($disallowed->{$error})) {
                   1469:                         my $msg = '<b>'.$disallowed->{$error}.'</b>, '.&mt('reason').' - '.
                   1470:                                   $lt{$error}; 
                   1471:                         if ($error eq 'newuser') {
1.9       raeburn  1472:                             $msg .= '<br />'.&mt("Please [_1]add the user(s)[_2] before returning to the [_3]$crstype Configuration[_2] to add as potential cloners.",'<a href="/adm/createuser">','</a>','<a href="/adm/courseprefs">');
1.3       raeburn  1473:                         }
                   1474:                         push(@fails,$msg);
                   1475:                     }
                   1476:                 }
                   1477:                 if (@fails) {
                   1478:                     $output .= '<span class="LC_warning">'.&mt('Unable to add to allowed cloners: ').
                   1479:                                '</span>'.join(';&nbsp;&nbsp;',@fails).'.<br />';
                   1480:                 }
                   1481:             } elsif ($item eq 'rolenames') {
                   1482:                 my %lt = &Apache::lonlocal::texthash (
                   1483:                     replacements => 'Name already used to replace a different standard role name',
                   1484:                     regulars     => 'Name already used as a standard role name',
                   1485:                     customrole   => 'Name already used as the name of a custom role',
                   1486:                 );
                   1487:                 my @fails;
                   1488:                 foreach my $error ('replacements','regulars','customrole') {
                   1489:                     if (ref($disallowed->{$error}) eq 'ARRAY') {
                   1490:                         push(@fails,'<b>'.join(', ',@{$disallowed->{$error}}).
                   1491:                                     '</b>, '.&mt('reason').' - '.$lt{'error'});
                   1492:                     }
                   1493:                 }
                   1494:                 if (@fails) {
                   1495:                     $output .= '<span class="LC_warning">'.
                   1496:                                &mt('Unable to include amongst replacements for role names: ').
                   1497:                                '</span>'.join(';&nbsp;&nbsp;',@fails).'.<br />';
                   1498:                 }
                   1499: 
                   1500:             } elsif (($item eq 'feedback') || ($item eq 'discussion') || ($item eq 'localization')) {
                   1501:                 $output .= '<span class="LC_warning">';
                   1502:                 if ($item eq 'feedback') {
1.9       raeburn  1503:                     if ($crstype eq 'Community') {
                   1504:                         $output .= &mt('Unable to include as a recipient of community feedback for:');
                   1505:                     } else {
                   1506:                         $output .= &mt('Unable to include as a recipient of course feedback for:');
                   1507:                     }
1.3       raeburn  1508:                 } elsif ($item eq 'discussion') {
                   1509:                     $output .= &mt('Unable to include in user-based access control for:');
                   1510:                 } elsif ($item eq 'localization') {
1.9       raeburn  1511:                     if ($crstype eq 'Community') {
                   1512:                         $output .= &mt('Unable to include in community localization:');
                   1513:                     } else {
                   1514:                         $output .= &mt('Unable to include in course localization:');
                   1515:                     }
1.3       raeburn  1516:                 }
                   1517:                 $output .= '</span><ul>';
                   1518:                 foreach my $key (sort(keys(%{$disallowed}))) {
                   1519:                     my $itemtext = $prefs->{$item}{'itemtext'}{$key};
                   1520:                     $output .=  '<li><i>'.$itemtext.'</i> - ';
                   1521:                     if ($item eq 'localization') {
                   1522:                         $output .= &mt('reason - unsupported language: [_1]',
                   1523:                                        '<b>'.$disallowed->{$key}.'</b>');
                   1524:                     } else {
                   1525:                         $output .= &mt('reason - invalid user: [_1]',
                   1526:                                        '<b>'.$disallowed->{$key}.'</b>').'</li>';
                   1527:                     }
                   1528:                 }
                   1529:                 $output .= '</ul><br />';
                   1530:             }
                   1531:         }
1.1       raeburn  1532:     }
1.3       raeburn  1533:     return $output;
1.1       raeburn  1534: }
                   1535: 
                   1536: sub get_course {
                   1537:     my ($courseid) = @_;
                   1538:     if (!defined($courseid)) {
                   1539:         $courseid = $env{'request.course.id'};
                   1540:     }
                   1541:     my $cdom=$env{'course.'.$courseid.'.domain'};
                   1542:     my $cnum=$env{'course.'.$courseid.'.num'};
                   1543:     return ($cnum,$cdom);
                   1544: }
                   1545: 
                   1546: sub get_jscript {
1.12      raeburn  1547:     my ($cdom,$phase,$crstype) = @_;
                   1548:     my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
1.1       raeburn  1549:     my ($jscript,$categorize_js);
                   1550:     my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();
                   1551:     my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset');
1.3       raeburn  1552:     my $cloners_js = &cloners_javascript($phase);
1.1       raeburn  1553:     if ($can_categorize) {
                   1554:         $categorize_js = <<ENDSCRIPT;
                   1555: function catsbrowser() {
                   1556:     var catswin = null;
                   1557:     var url = '/adm/courseprefs?phase=categorizecourse';
                   1558:     if (!catswin || catswin.closed) {
                   1559:         catswin=window.open(url,'categorieswin','height=480,width=600,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
                   1560:     } else {
                   1561:         catswin.focus();
                   1562:     }
                   1563: }
                   1564: ENDSCRIPT
                   1565:     }
                   1566:     $jscript = '<script type="text/javascript" language="Javascript">'."\n".
1.3       raeburn  1567:                $browse_js."\n".$categorize_js."\n".$cloners_js."\n".'</script>'.
                   1568:                "\n".$stubrowse_js."\n";
1.1       raeburn  1569:     return $jscript;
                   1570: }
                   1571: 
1.3       raeburn  1572: sub cloners_javascript {
                   1573:     my ($formname) = @_;
                   1574:     return <<"ENDSCRIPT";
                   1575: 
                   1576: function update_cloners(caller,num) {
                   1577:     var delidx = getIndexByName('cloners_delete');
                   1578:     var actidx = getIndexByName('cloners_activate');
                   1579:     if (caller == 'cloners_all') {
                   1580:         var selall;
                   1581:         for (var i=0; i<document.$formname.cloners_all.length; i++) {
                   1582:             if (document.$formname.cloners_all[i].checked) {
                   1583:                 selall = document.$formname.cloners_all[i].value;
                   1584:             }
                   1585:         }
                   1586:         if (selall == 1) {
                   1587:             if (delidx != -1) {
                   1588:                 if (document.$formname.cloners_delete.length) {
                   1589:                     for (var j=0; j<document.$formname.cloners_delete.length; j++) {
                   1590:                         document.$formname.cloners_delete[j].checked = true;
                   1591:                     }
                   1592:                 } else {
                   1593:                     document.$formname.elements[delidx].checked = true;
                   1594:                 }
                   1595:             }
                   1596:             if (actidx != -1) {
                   1597:                 if (document.$formname.cloners_activate.length) {
                   1598:                     for (var i=0; i<document.$formname.cloners_activate.length; i++) {
                   1599:                         if (document.$formname.cloners_activate[i].value == '0') {
                   1600:                             document.$formname.cloners_activate[i].checked = false;
                   1601:                         }
                   1602:                         if (document.$formname.cloners_activate[i].value == '') {
                   1603:                             document.$formname.cloners_activate[i].checked = true;
                   1604:                         }
                   1605:                     }
                   1606:                 }
                   1607:             }
                   1608:             document.$formname.cloners_newdom.selectedIndex = 0;
                   1609:         }
                   1610:     }
                   1611:     if (caller == 'cloners_activate') {
                   1612:         if (document.$formname.cloners_activate.length) {
                   1613:             for (var j=0; j<document.$formname.cloners_activate.length; j++) {
                   1614:                 if (document.$formname.cloners_activate[j].value == num) {
                   1615:                     if (document.$formname.cloners_activate[j].checked) {
                   1616:                         for (var i=0; i<document.$formname.cloners_all.length; i++) {
                   1617:                             if (document.$formname.cloners_all[i].value == '1') {
                   1618:                                 document.$formname.cloners_all[i].checked = false;
                   1619:                             }
                   1620:                             if (document.$formname.cloners_all[i].value == '0') {
                   1621:                                 document.$formname.cloners_all[i].checked = true;
                   1622:                             }
                   1623:                         }
                   1624:                     }
                   1625:                 }
                   1626:             }
                   1627:         } else {
                   1628:             for (var i=0; i<document.$formname.cloners_all.length; i++) {
                   1629:                 if (document.$formname.cloners_all[i].value == '1') {
                   1630:                     document.$formname.cloners_all[i].checked = false;
                   1631:                 }
                   1632:                 if (document.$formname.cloners_all[i].value == '0') {
                   1633:                     document.$formname.cloners_all[i].checked = true;
                   1634:                 }
                   1635:             }
                   1636:         }
                   1637:     }
                   1638:     return;
                   1639: }
                   1640: 
                   1641: function getIndexByName(item) {
                   1642:     for (var i=0;i<document.$formname.elements.length;i++) {
                   1643:         if (document.$formname.elements[i].name == item) {
                   1644:             return i;
                   1645:         }
                   1646:     }
                   1647:     return -1;
                   1648: }
                   1649: 
                   1650: ENDSCRIPT
                   1651: }
                   1652: 
                   1653: 
1.1       raeburn  1654: sub print_courseinfo {
1.9       raeburn  1655:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3       raeburn  1656:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  1657:         return;
                   1658:     }
1.25      raeburn  1659:     my ($cathash,$categoriesform,$autocoowner);
1.1       raeburn  1660:     my %domconf = 
1.25      raeburn  1661:         &Apache::lonnet::get_dom('configuration',['coursecategories','autoenroll'],$cdom);
1.1       raeburn  1662:     if (ref($domconf{'coursecategories'}) eq 'HASH') {
                   1663:         $cathash = $domconf{'coursecategories'}{'cats'};
                   1664:         if (ref($cathash) eq 'HASH') {
                   1665:             $categoriesform = 
                   1666:                 &Apache::loncommon::assign_categories_table($cathash,
1.12      raeburn  1667:                                                 $settings->{'categories'},$crstype)."\n";
1.1       raeburn  1668:         }
                   1669:     }
1.25      raeburn  1670:     if (ref($domconf{'autoenroll'}) eq 'HASH') {
                   1671:         $autocoowner = $domconf{'autoenroll'}{'co-owners'};
                   1672:     }
1.1       raeburn  1673:     if (!defined($categoriesform)) {
1.15      raeburn  1674:         $categoriesform = &mt('No categories defined in this domain.');
1.1       raeburn  1675:     }
                   1676: 
1.12      raeburn  1677:     my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
1.1       raeburn  1678: 
1.9       raeburn  1679:     my $replace;
                   1680:     if ($crstype eq 'Community') {
                   1681:         $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank');
                   1682:     } else {
                   1683:         $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank');
                   1684:     }
1.1       raeburn  1685:     my %items = (
1.3       raeburn  1686:         'url' => {
                   1687:                    text => '<b>'.&mt($itemtext->{'url'}).'</b>'.('&nbsp;'x2).
1.1       raeburn  1688:                            '<a href="javascript:openbrowser'.
                   1689:                            "('display','url','sequence')\">".
                   1690:                            &mt('Select Map').'</a><br /><span class="LC_warning"> '.
                   1691:                            &mt('Modification may make assessment data inaccessible!').
                   1692:                            '</span>',
                   1693:                    input => 'textbox',
                   1694:                    size  => '40',
                   1695:                  },
                   1696:         'description'  => { 
1.3       raeburn  1697:                    text => '<b>'.&mt($itemtext->{'description'}).'</b>',
1.1       raeburn  1698:                    input => 'textbox',
                   1699:                    size  => '25',
                   1700:                           },
1.24      raeburn  1701:         'owner'        => {
                   1702:                    text => '<b>'.&mt($itemtext->{'owner'}).'</b>',
                   1703:                           },
1.25      raeburn  1704:         'co-owners'    => {
                   1705:                    text => '<b>'.&mt($itemtext->{'co-owners'}).'</b>',
                   1706:                           },
1.1       raeburn  1707:         'courseid'     => { 
1.3       raeburn  1708:                    text => '<b>'.&mt($itemtext->{'courseid'}).'</b><br />'.'('.
                   1709:                            &mt('internal, optional').')',
1.1       raeburn  1710:                    input => 'textbox',
                   1711:                    size  => '25',
                   1712:                           },
                   1713:         'cloners'      => { 
1.3       raeburn  1714:                    text => '<b>'.&mt($itemtext->{'cloners'}).'</b><br />'.
1.24      raeburn  1715:                            &mt('Owner and Coordinators included automatically'),
1.1       raeburn  1716:                    input => 'textbox',
                   1717:                    size  => '40',
                   1718:                          },
                   1719:         'rolenames'  => { 
1.3       raeburn  1720:                    text  => '<b>'.&mt($itemtext->{'rolenames'}).'</b><br />'.
1.9       raeburn  1721:                             '('.$replace.')',
1.1       raeburn  1722:                    input => 'textbox',
                   1723:                    size  => '20',
                   1724:                         },
                   1725:         'externalsyllabus' => {
1.3       raeburn  1726:                    text => '<b>'.&mt($itemtext->{'externalsyllabus'}).'</b><br />('.
                   1727:                            &mt('not using syllabus template)'),
1.1       raeburn  1728:                    input => 'textbox',
                   1729:                    size  => '40',
                   1730:                         },
                   1731:         'hidefromcat' => {
1.3       raeburn  1732:                    text => '<b>'.&mt($itemtext->{'hidefromcat'}).'</b><br />'.
1.1       raeburn  1733:                            ' ('.&mt('included by default if assigned institutional code, or categorized').')',
                   1734:                    input => 'radio',
                   1735:                          },
                   1736:         'categories' => {
1.3       raeburn  1737:                    text => '<b>'.&mt($itemtext->{'categories'}).'</b> <a href="javascript:catsbrowser()">'.
1.1       raeburn  1738:                            &mt('Display Categories').'</a>',
                   1739:                    input => 'textbox',
                   1740:                    size  => '25',
                   1741:                         },
                   1742:     );
                   1743:     my $datatable;
                   1744:     my $count = 0;
                   1745:     foreach my $item (@{$ordered}) {
                   1746:         if ($item eq 'hidefromcat') {
                   1747:             next if (!$can_toggle_cat);
                   1748:         } elsif ($item eq 'categories') {
                   1749:             next if (!$can_categorize);
                   1750:         }
                   1751:         $count ++;
1.28.2.1  raeburn  1752:         $datatable .= &item_table_row_start($items{$item}{text},$count);
1.1       raeburn  1753:         if ($items{$item}{input} eq 'radio') {
                   1754:             $datatable .= &yesno_radio($item,$settings);
                   1755:         } elsif ($item eq 'cloners') {
                   1756:             my $includeempty = 1;
                   1757:             my $num = 0;
                   1758:             $datatable .= &Apache::loncommon::start_data_table().
                   1759:                           &Apache::loncommon::start_data_table_row().
                   1760:                           '<td><span class="LC_nobreak"><label>'.
                   1761:                           &mt('Any user in any domain:').
                   1762:                           '&nbsp;<input type="radio" name="cloners_all" value="1" ';
                   1763:             if ($settings->{$item} eq '*') {
                   1764:                 $datatable .= ' checked="checked" ';
                   1765:             }
                   1766:             $datatable .= 'onchange="javascript:update_cloners('.
                   1767:                           "'cloners_all'".');" />'.&mt('Yes').'</label>'.
                   1768:                           ('&nbsp;'x2).'<input type="radio" name="cloners_all" value="0" ';
                   1769:             if ($settings->{$item} ne '*') {
                   1770:                 $datatable .= ' checked="checked" ';
                   1771:             }
                   1772:             $datatable .= ' onchange="javascript:update_cloners('.
                   1773:                           "'cloners_all'".');"/>'.&mt('No').'</label></td>'.
                   1774:                           &Apache::loncommon::end_data_table_row().
                   1775:                           &Apache::loncommon::end_data_table().
                   1776:                           '<table><tr><td align="left">'.&mt('Or').
                   1777:                           '</td></tr></table>'.
                   1778:                           &Apache::loncommon::start_data_table();
                   1779:             my @cloners;
                   1780:             if ($settings->{$item} eq '') {
                   1781:                 $datatable .= &new_cloners_dom_row($cdom,'0');
                   1782:             } elsif ($settings->{$item} ne '*') {
                   1783:                 my @entries = split(/,/,$settings->{$item});
                   1784:                 if (@entries > 0) {
                   1785:                     foreach my $entry (@entries) {
                   1786:                         my ($uname,$udom) = split(/:/,$entry);
1.23      raeburn  1787:                         if ($udom =~ /^$match_domain$/) {
                   1788:                             unless (&Apache::lonnet::domain($udom)) {
                   1789:                                 next;
                   1790:                             }
                   1791:                         } else {
                   1792:                             next;
                   1793:                         }
1.1       raeburn  1794:                         if ($uname eq '*') {
                   1795:                             $datatable .= 
                   1796:                                 &Apache::loncommon::start_data_table_row().
1.3       raeburn  1797:                                 '<td valign="top" align="left"><span class="LC_nobreak">'.
1.23      raeburn  1798:                                 &mt('Any user in domain:').'<b>&nbsp;'.$udom.
1.1       raeburn  1799:                                 '</b><input type="hidden" name="cloners_dom_'.$num.
                   1800:                                 '" value="'.$udom.'" /></span><br />'.
                   1801:                                 '<span class="LC_nobreak"><label><input type="checkbox" '.
1.3       raeburn  1802:                                 'name="cloners_delete" value="'.$num.'" onchange="javascript:update_cloners('."'cloners_delete','$num'".');" />'.
1.1       raeburn  1803:                                 &mt('Delete').'</label></span></td>'.
                   1804:                                 &Apache::loncommon::end_data_table_row();
                   1805:                             $num ++;
1.23      raeburn  1806:                         } elsif (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
                   1807:                             unless (grep(/^\Q$entry\E$/,@cloners)) {
                   1808:                                 push(@cloners,$entry);
                   1809:                             }
1.1       raeburn  1810:                         }
                   1811:                     }
                   1812:                 }
                   1813:             }
                   1814:             my $add_domtitle = &mt('Any user in additional domain:');
                   1815:             if ($settings->{$item} eq '*') {
                   1816:                 $add_domtitle = &mt('Any user in specific domain:');
                   1817:             } elsif ($settings->{$item} eq '') {
                   1818:                 $add_domtitle = &mt('Any user in other domain:');
                   1819:             }
                   1820:             my $cloners_str = join(',',@cloners);
                   1821:             $datatable .= &Apache::loncommon::start_data_table_row().
                   1822:                           '<td align="left"><span class="LC_nobreak">'.
                   1823:                           $add_domtitle.'</span><br />'.
                   1824:                           &Apache::loncommon::select_dom_form('','cloners_newdom',
                   1825:                                                               $includeempty).
                   1826:                           '<input type="hidden" name="cloners_total" value="'.$num.'" />'.
                   1827:                           '</td>'.&Apache::loncommon::end_data_table_row().
1.3       raeburn  1828:                           &Apache::loncommon::end_data_table().
                   1829:                           '<table><tr><td align="left">'.&mt('And').
                   1830:                           '</td></tr></table>'.
1.1       raeburn  1831:                           &Apache::loncommon::start_data_table().
                   1832:                           &Apache::loncommon::start_data_table_row().
                   1833:                           '<td align="left">'.
                   1834:                           &mt('Specific users').'&nbsp;(<tt>'.
                   1835:                           &mt('user:domain,user:domain').'</tt>)<br />'.
                   1836:                           &Apache::lonhtmlcommon::textbox($item,$cloners_str,
                   1837:                                                           $items{$item}{'size'}).
                   1838:                           '</td>'.&Apache::loncommon::end_data_table_row().
                   1839:                           &Apache::loncommon::end_data_table();
                   1840:         } elsif ($item eq 'rolenames') {
                   1841:             $datatable .= &Apache::loncommon::start_data_table();
1.9       raeburn  1842:             my @roles;
                   1843:             if ($crstype eq 'Community') {
                   1844:                 @roles = ('co');
                   1845:             } else {
                   1846:                 @roles = ('cc');
                   1847:             }
                   1848:             push (@roles,('in','ta','ep','ad','st'));
                   1849:             foreach my $role (@roles) {
1.1       raeburn  1850:                 $datatable .= &Apache::loncommon::start_data_table_row().
                   1851:                               '<td align="left"><span class="LC_nobreak">'.
                   1852:                               &Apache::lonnet::plaintext($role,$crstype,undef,1).
                   1853:                               '</span></td><td align="left">'.
                   1854:                               &Apache::lonhtmlcommon::textbox('rolenames_'.$role,
                   1855:                                                  $settings->{$role.'.plaintext'},
                   1856:                                                  $items{$item}{size}).'</td>'.
                   1857:                               &Apache::loncommon::end_data_table_row();
                   1858:             }
                   1859:             $datatable .= &Apache::loncommon::end_data_table().'</td>';
                   1860:         } elsif ($item eq 'categories') {
1.3       raeburn  1861:             my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";';
                   1862:             $datatable .= '<input type="hidden" name="categories" value="'.$settings->{$item}.'" />'.
                   1863:                           &Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item},
                   1864:                                                           $items{$item}{size},$launcher);
1.24      raeburn  1865:         } elsif ($item eq 'owner') {
                   1866:             my $owner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'};
                   1867:             if ($owner =~ /:/) {
                   1868:                 my ($ownername,$ownerdom) = split(':',$owner); 
                   1869:                 $owner = &Apache::loncommon::plainname($ownername,$ownerdom);
                   1870:             } elsif ($owner ne '') {
                   1871:                 $owner = &Apache::loncommon::plainname($owner,$cdom);
                   1872:             } else {
                   1873:                 $owner = &mt('None specified');
                   1874:             }
                   1875:             my $domdesc = &Apache::lonnet::domain($cdom,'description');
                   1876:             $datatable .= $owner;
1.25      raeburn  1877:         } elsif ($item eq 'co-owners') {
                   1878:             my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1879:             my $coowners = $env{'course.'.$env{'request.course.id'}.'.internal.co-owners'};
                   1880:             my @currcoown;
                   1881:             if ($coowners) {
                   1882:                 @currcoown = split(',',$coowners);
                   1883:             }
                   1884:             if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
                   1885:                 if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
                   1886:                     $datatable .= &show_autocoowners(@currcoown);
                   1887:                 } else {
                   1888:                     $datatable .= &coowner_invitations($cnum,$cdom,@currcoown);
                   1889:                 }
                   1890:             } else {
                   1891:                 if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
                   1892:                     $datatable .= &show_autocoowners(@currcoown);
                   1893:                 } else {
                   1894:                     $datatable .= &manage_coownership($cnum,$cdom,@currcoown);
                   1895:                 }
                   1896:             }
1.1       raeburn  1897:         } else {
                   1898:             $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size});
                   1899:         }
                   1900:         $datatable .= &item_table_row_end();
                   1901:     }
                   1902:     $$rowtotal += scalar(@{$ordered});
                   1903:     return $datatable;
                   1904: }
                   1905: 
                   1906: sub new_cloners_dom_row {
                   1907:     my ($newdom,$num) = @_;
                   1908:     my $output;
                   1909:     if ($newdom ne '') {
                   1910:         $output .= &Apache::loncommon::start_data_table_row().
                   1911:                    '<td valign="top"><span class="LC_nobreak">'.
                   1912:                    &mt('Any user in domain:').'&nbsp;<b>'.$newdom.'</b>'.
                   1913:                    ('&nbsp;'x2).'<label><input type="radio" '.
                   1914:                    'name="cloners_activate" value="'.$num.'" '.
1.3       raeburn  1915:                    'onchange="javascript:update_cloners('.
1.1       raeburn  1916:                    "'cloners_activate','$num'".');" />'.
                   1917:                    &mt('Yes').'</label>'.('&nbsp;'x2).
                   1918:                    '<label><input type="radio" '.
                   1919:                    'name="cloners_activate" value="" checked="checked" '.
1.3       raeburn  1920:                    'onchange="javascript:update_cloners('.
1.1       raeburn  1921:                    "'cloners_activate','$num'".');" />'.
1.3       raeburn  1922:                    &mt('No').'</label><input type="hidden" name="cloners_dom_'.
                   1923:                    $num.'" value="'.$newdom.'" /></span></td>'.
1.1       raeburn  1924:                    &Apache::loncommon::end_data_table_row();
                   1925:     }
                   1926:     return $output;
                   1927: }
                   1928: 
                   1929: sub can_modify_catsettings {
1.12      raeburn  1930:     my ($dom,$crstype) = @_;
1.1       raeburn  1931:     my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom);
                   1932:     my ($can_toggle_cat,$can_categorize);
                   1933:     if (ref($domconf{'coursecategories'}) eq 'HASH') {
1.12      raeburn  1934:         if ($crstype eq 'Community') {
                   1935:             if ($domconf{'coursecategories'}{'togglecatscomm'} eq 'comm') {
                   1936:                 $can_toggle_cat = 1;
                   1937:             }
                   1938:             if ($domconf{'coursecategories'}{'categorizecomm'} eq 'comm') {
                   1939:                 $can_categorize = 1;
                   1940:             }
                   1941:         } else {
                   1942:             if ($domconf{'coursecategories'}{'togglecats'} eq 'crs') {
                   1943:                 $can_toggle_cat = 1;
                   1944:             }
                   1945:             if ($domconf{'coursecategories'}{'categorize'} eq 'crs') {
                   1946:                 $can_categorize = 1;
                   1947:             }
1.1       raeburn  1948:         }
                   1949:     }
                   1950:     return ($can_toggle_cat,$can_categorize);
                   1951: }
                   1952: 
                   1953: sub assign_course_categories {
1.9       raeburn  1954:     my ($r,$crstype) = @_;
1.1       raeburn  1955:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1956:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1957:     my $hascats = 0;
                   1958:     my $cathash;
                   1959:     my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom);
                   1960:     if (ref($domconf{'coursecategories'}) eq 'HASH') {
                   1961:         $cathash = $domconf{'coursecategories'}{'cats'};
                   1962:         if (ref($cathash) eq 'HASH') {
1.12      raeburn  1963:             foreach my $cat (keys(%{$cathash})) {
                   1964:                 next if ($cat eq 'instcode::0');
                   1965:                 unless ($crstype eq 'Community') {
                   1966:                     next if ($cat eq 'communities::0');
                   1967:                 }
                   1968:                 $hascats ++; 
                   1969:             }
1.1       raeburn  1970:         }
                   1971:     }
                   1972:     my $catwin_js;
                   1973:     if ($hascats) {
1.9       raeburn  1974:         my $alert;
                   1975:         if ($crstype eq 'Community') {
                   1976:             $alert = &mt("Use 'Save' in the main window to save community categories");
                   1977:         } else {
                   1978:             $alert = &mt("Use 'Save' in the main window to save course categories");
                   1979:         }
1.1       raeburn  1980:         $catwin_js = <<ENDSCRIPT;
                   1981: <script type="text/javascript">
                   1982: 
                   1983: function updateCategories() {
                   1984:     var newcategories = '';
                   1985:     var unescapedcats = '';
                   1986:     if (document.chgcats.usecategory.length) {
                   1987:         for (var i=0; i<document.chgcats.usecategory.length; i++) {
                   1988:             if (document.chgcats.usecategory[i].checked == true) {
                   1989:                 newcategories = newcategories + document.chgcats.usecategory[i].value + '&';
                   1990:                 unescapedcats = unescapedcats + document.chgcats.catname[i].value + ' & ';
                   1991:             }
                   1992:         }
                   1993:         if (newcategories.length > 0) {
                   1994:             newcategories = newcategories.slice(0,-1);
                   1995:         }
                   1996:         if (unescapedcats.length > 0) {
                   1997:             unescapedcats = unescapedcats.slice(0,-3);
                   1998:         }
                   1999:     } else {
                   2000:          if (document.chgcats.usecategory.checked == true) {
                   2001:              newcategories = document.chgcats.usecategory.value;
                   2002:              unescapedcats = document.chgcats.catname.value;
                   2003:          }
                   2004:     }
                   2005:     opener.document.display.categories.value = newcategories;
                   2006:     opener.document.display.categories_display.value = unescapedcats;
                   2007:     alert("$alert");
                   2008:     self.close();
                   2009:     return;
                   2010: }
                   2011: 
                   2012: </script>
                   2013: ENDSCRIPT
                   2014:     } else {
                   2015:         my $onload;
                   2016:     }
1.9       raeburn  2017:     my ($crscat,$catcrs,$assign);
                   2018:     if ($crstype eq 'Community') {
                   2019:         $crscat = 'Community Categories';
                   2020:         $catcrs = &mt('Categorize Community');
                   2021:         $assign = &mt('Assign one or more categories to this community.')
                   2022:     } else {
                   2023:         $crscat = 'Course Categories';
                   2024:         $catcrs = &mt('Categorize Course');
                   2025:         $assign = &mt('Assign one or more categories to this course.')
                   2026:     }
1.1       raeburn  2027:     my $start_page =
1.9       raeburn  2028:         &Apache::loncommon::start_page($crscat,$catwin_js,
1.1       raeburn  2029:                                        {'only_body'      => 1,});
                   2030:     my $end_page = &Apache::loncommon::end_page();
1.9       raeburn  2031:     my $categoriesform = '<h3>'.$catcrs.'</h3>';
1.1       raeburn  2032:     if ($hascats) {
                   2033:         my %currsettings =
                   2034:             &Apache::lonnet::get('environment',['hidefromcat','categories'],$cdom,$cnum);
1.12      raeburn  2035:         my $cattable = &Apache::loncommon::assign_categories_table($cathash,
                   2036:                                        $currsettings{'categories'},$crstype);
                   2037:         if ($cattable eq '') {
                   2038:             $categoriesform .= &mt('No suitable categories defined for this course type in this domain.'); 
                   2039:         } else {
                   2040:             $categoriesform .= $assign.'<br /><br />'.
                   2041:                                '<form name="chgcats" action="/adm/courseprefs" method="post">'."\n".
                   2042:                                $cattable."\n".
                   2043:                                '<br /><input type="button" name="changes" value="'.
                   2044:                                &mt('Copy to main window').'" '.
                   2045:                                'onclick="javascript:updateCategories()" /></form><br />';
                   2046:         }
1.1       raeburn  2047:     } else {
1.12      raeburn  2048:         $categoriesform .= &mt('No categories defined in this domain.');
1.1       raeburn  2049:     }
                   2050:     $r->print($start_page.$categoriesform.$end_page);
                   2051:     return;
                   2052: }
                   2053: 
1.25      raeburn  2054: sub show_autocoowners {
                   2055:     my (@currcoown) = @_;
                   2056:     my $output = '<i>'.&mt('Co-ownership is set automatically when a Course Coordinator role is assigned to official course personnel (from institutional data).').'</i>';
                   2057:     if (@currcoown > 0) { 
                   2058:         $output .= '<br />'.&mt('Current co-owners are:').'&nbsp;'.
                   2059:                    join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));
                   2060:     } else {
                   2061:         $output .= '<br />'.&mt('Currently no co-owners.');
                   2062:     } 
                   2063:     return $output;
                   2064: }
                   2065: 
                   2066: sub coowner_invitations {
                   2067:     my ($cnum,$cdom,@currcoown) = @_;
                   2068:     my ($output,@pendingcoown,@othercoords);
                   2069:     my $pendingcoowners =
                   2070:         $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
                   2071:     if ($pendingcoowners) {
                   2072:         @pendingcoown = split(',',$pendingcoowners);
                   2073:     }
                   2074:     my $ccrole = 'cc';
                   2075:     my %ccroles = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,undef,[$ccrole]);
                   2076:     foreach my $key (sort(keys(%ccroles))) {
                   2077:         my ($ccname,$ccdom,$role) = split(':',$key);
                   2078:         next if ($key eq $env{'user.name'}.':'.$env{'user.domain'}.':'.$ccrole);
                   2079:         unless (grep(/^\Q$ccname\E:\Q$ccdom\E$/,@currcoown,@pendingcoown)) {
                   2080:             push(@othercoords,$ccname.':'.$ccdom);
                   2081:         }
                   2082:     }
                   2083:     my $coowner_rows = @currcoown + @pendingcoown + @othercoords;
                   2084:     if ($coowner_rows) {
                   2085:         $output .= &Apache::loncommon::start_data_table();
                   2086:         if (@currcoown) {
                   2087:             $output .= &Apache::loncommon::start_data_table_row().
                   2088:                           '<td><i>'.&mt('Current co-owners').'</i></td><td>';
                   2089:             foreach my $person (@currcoown) {
                   2090:                 my ($co_uname,$co_dom) = split(':',$person);
                   2091:                 $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="coowners" checked="checked" value="'.$person.'" />'.&Apache::loncommon::plainname($co_uname,$co_dom).'</label></span>'.('&nbsp;'x2).' ';
                   2092:             }
                   2093:             $output .= '</td>'.
                   2094:                           &Apache::loncommon::end_data_table_row();
                   2095:         }
                   2096:         if ($pendingcoowners) {
                   2097:             $output .= &Apache::loncommon::start_data_table_row().
                   2098:                           '<td><i>'.&mt('Invited as co-owners [_1](agreement pending)','<br />').'</i></td><td>';
                   2099:             foreach my $person (@pendingcoown) {
                   2100:                 my ($co_uname,$co_dom) = split(':',$person);
                   2101:                 $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="pendingcoowners" checked="checked" value="'.$person.'" />'.&Apache::loncommon::plainname($co_uname,$co_dom).'</label></span>'.('&nbsp;'x2).' ';
                   2102:             }
                   2103:             $output .= '</td>'.
                   2104:                        &Apache::loncommon::end_data_table_row();
                   2105:         }
                   2106:         if (@othercoords) {
                   2107:             $output .= &Apache::loncommon::start_data_table_row().
                   2108:                           '<td><i>'.&mt('Invite other Coordinators [_1]to become co-owners','<br />').'</i></td><td>';
                   2109:             foreach my $person (@othercoords) {
                   2110:                 my ($co_uname,$co_dom) = split(':',$person);
                   2111:                 $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="invitecoowners" value="'.$person.'" />'.&Apache::loncommon::plainname($co_uname,$co_dom).'</label></span>'.('&nbsp;'x2).' ';
                   2112:             }
                   2113:             $output .= '</td>'.
                   2114:                           &Apache::loncommon::end_data_table_row();
                   2115:         }
                   2116:         $output .= &Apache::loncommon::end_data_table();
                   2117:     } else {
                   2118:         $output = &mt('There are no coordinators to select as co-owners');
                   2119:     }
                   2120:     return $output;
                   2121: }
                   2122: 
                   2123: sub manage_coownership  {
                   2124:     my ($cnum,$cdom,@currcoown) = @_;
                   2125:     my (@pendingcoown);
                   2126:     my $pendingcoowners =
                   2127:         $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
                   2128:     if ($pendingcoowners) {
                   2129:         @pendingcoown = split(',',$pendingcoowners);
                   2130:     }
                   2131:     my ($is_coowner,$is_pending,$output);
                   2132:     my $uname = $env{'user.name'};
                   2133:     my $udom = $env{'user.domain'};
                   2134:     if (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {
                   2135:         $is_coowner = 1;
                   2136:     }
                   2137:     if (grep(/^\Q$uname\E:\Q$udom\E$/,@pendingcoown)) {
                   2138:         $is_pending = 1;
                   2139:     }
                   2140:     if (@currcoown && ($is_coowner || $is_pending)) {
                   2141:         $output = &Apache::loncommon::start_data_table();
                   2142:     }
                   2143:     if (@currcoown) {
                   2144:         if ($is_coowner || $is_pending) { 
                   2145:             $output .= &Apache::loncommon::start_data_table().
                   2146:                        &Apache::loncommon::start_data_table_row().'<td>';
                   2147:         }
                   2148:         $output .= &mt('Current co-owners are:').'&nbsp;'.
                   2149:                    join(', ', map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));  
                   2150:         if ($is_coowner || $is_pending) {
                   2151:             $output .= '</td>'.&Apache::loncommon::end_data_table_row(); 
                   2152:         }
                   2153:     }
                   2154:     if ($is_coowner || $is_pending) {
                   2155:         if (@currcoown) { 
                   2156:             $output .= &Apache::loncommon::start_data_table_row().'<td>';
                   2157:         }
                   2158:         $output .= '<span class="LC_nobreak">';
                   2159:         if ($is_coowner) {
                   2160:             $output .= &mt('You are currently a co-owner:').'&nbsp;<label><input type="checkbox" name="remove_coowoner" value="'.$uname.':'.$udom.'" />'.&mt('Discontinue?').'</label>';
                   2161:         } else {
                   2162:             $output .= &mt('The course owner has invited you to become a co-owner:').'&nbsp;<label><input type="radio" name="pending_coowoner" value="accept" />'.&mt('Accept?').'</label>'.('&nbsp;'x2).
                   2163:                        '<label><input type="radio" name=pending_coowoner" value="decline" />'.&mt('Decline?').'</label>';
                   2164:         }
                   2165:         $output .= '</span>';
                   2166:         if (@currcoown) {
                   2167:             $output .= '</td>'.&Apache::loncommon::end_data_table_row();
                   2168:         }
                   2169:     }
                   2170:     if (@currcoown && ($is_coowner || $is_pending)) {
                   2171:         $output .= &Apache::loncommon::end_data_table();
                   2172:     }
                   2173:     return $output;
                   2174: }
                   2175: 
1.1       raeburn  2176: sub print_localization {
1.3       raeburn  2177:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
                   2178:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2179:         return;
                   2180:     }
                   2181:     my %items = (
                   2182:         languages => {
1.17      faziophi 2183:                         text => '<b>'.&mt($itemtext->{'languages'}).'</b><br />'.
                   2184:                                 &mt("(overrides individual user preference)"),
1.1       raeburn  2185:                         input => 'selectbox',
                   2186:                      }, 
                   2187:         timezone => {
1.17      faziophi 2188:                         text  => '<b>'.&mt($itemtext->{'timezone'}).'</b>',
1.1       raeburn  2189:                         input => 'selectbox',
                   2190:                     },
                   2191:         datelocale  => { 
1.17      faziophi 2192:                          text => '<b>'.&mt($itemtext->{'datelocale'}).'</b>',
1.1       raeburn  2193:                          input => 'selectbox',
                   2194:                        },
                   2195:     );
                   2196:     my $datatable;
                   2197:     my $count = 0;
                   2198:     foreach my $item (@{$ordered}) {
                   2199:         $count ++;
                   2200:         $datatable .= &item_table_row_start($items{$item}{text},$count);
                   2201:         if ($item eq 'timezone') {
                   2202:             my $includeempty = 1;
                   2203:             my $timezone = &Apache::lonlocal::gettimezone();
                   2204:             $datatable .= 
                   2205:                 &Apache::loncommon::select_timezone($item,$timezone,undef,
                   2206:                                                     $includeempty);
                   2207:         } elsif ($item eq 'datelocale') {
                   2208:             my $includeempty = 1;
                   2209:             my $locale_obj = &Apache::lonlocal::getdatelocale();
                   2210:             my $currdatelocale;
                   2211:             if (ref($locale_obj)) {
                   2212:                 $currdatelocale = $locale_obj->id();
                   2213:             }
                   2214:             $datatable .= 
                   2215:                 &Apache::loncommon::select_datelocale($item,$currdatelocale,
                   2216:                                                       undef,$includeempty);
                   2217:         } else {
                   2218:             if ($settings->{$item} eq '') {
                   2219:                 $datatable .= 
1.3       raeburn  2220:                     &Apache::loncommon::select_language('languages_0','',1);
1.1       raeburn  2221:             } else {
                   2222:                 my $num = 0;
1.3       raeburn  2223:                 my @languages = split(/\s*[,;:]\s*/,$settings->{$item});
1.1       raeburn  2224:                 $datatable .= &Apache::loncommon::start_data_table();
                   2225:                 if (@languages > 0) {
1.3       raeburn  2226:                     my %langchoices = &get_lang_choices();
1.1       raeburn  2227:                     foreach my $lang (@languages) {
                   2228:                         my $showlang = $lang;
1.3       raeburn  2229:                         if (exists($langchoices{$lang})) {
                   2230:                             $showlang = $langchoices{$lang};
1.1       raeburn  2231:                         }
                   2232:                         $datatable .=
                   2233:                             &Apache::loncommon::start_data_table_row().
1.3       raeburn  2234:                             '<td align="left"><span class="LC_nobreak">'.
1.1       raeburn  2235:                             &mt('Language:').'<b>&nbsp;'.$showlang.
                   2236:                             '</b><input type="hidden" name="languages_'.$num.
                   2237:                             '" value="'.$lang.'" /></span><br />'.
                   2238:                             '<span class="LC_nobreak"><label><input type="checkbox" '.
                   2239:                             'name="languages_delete" value="'.$num.'" />'.
                   2240:                             &mt('Delete').'</label></span></td>'.
1.3       raeburn  2241:                             &Apache::loncommon::end_data_table_row();
1.1       raeburn  2242:                             $num ++;
                   2243:                     }
                   2244:                 }
                   2245:                 $datatable .= &Apache::loncommon::start_data_table_row().
1.3       raeburn  2246:                               '<td align="left"><span class="LC_nobreak">'.
                   2247:                               &mt('Additional language:'). '</span><br />'.
                   2248:                               &Apache::loncommon::select_language('languages_'.$num,'',1).
1.1       raeburn  2249:                               '<input type="hidden" name="languages_total" value="'.$num.'" />'.
                   2250:                               '</td>'.&Apache::loncommon::end_data_table_row().
                   2251:                               &Apache::loncommon::end_data_table();
                   2252:             }
                   2253:         }
                   2254:         $datatable .= &item_table_row_end();
                   2255:     }
                   2256:     $$rowtotal += scalar(@{$ordered});
                   2257:     return $datatable;
                   2258: }
                   2259: 
1.3       raeburn  2260: sub get_lang_choices {
                   2261:     my %langchoices;
                   2262:     foreach my $id (&Apache::loncommon::languageids()) {
                   2263:         my $code = &Apache::loncommon::supportedlanguagecode($id);
                   2264:         if ($code) {
                   2265:             $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id);
                   2266:         }
                   2267:     }
                   2268:     return %langchoices;
                   2269: }
                   2270: 
1.1       raeburn  2271: sub print_feedback {
1.3       raeburn  2272:     my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
                   2273:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2274:         return;
                   2275:     }
                   2276:     my %items = (
1.3       raeburn  2277:         'question.email' => {
                   2278:                    text => '<b>'.&mt($itemtext->{'question.email'}).'</b>',
1.1       raeburn  2279:                    input => 'textbox',
                   2280:                    size  => '50',
                   2281:                  },
                   2282: 
1.3       raeburn  2283:         'comment.email'  => {
                   2284:                    text => '<b>'.&mt($itemtext->{'comment.email'}).'</b>',
1.1       raeburn  2285:                    input => 'textbox',
                   2286:                    size  => '50',
                   2287:                  },
                   2288: 
1.3       raeburn  2289:         'policy.email'   => {
                   2290:                    text => '<b>'.&mt($itemtext->{'policy.email'}).'</b>',
1.1       raeburn  2291:                    input => 'textbox',
                   2292:                    size  => '50',
                   2293:                  },
                   2294:     );
                   2295:     my $datatable;
                   2296:     my $count = 0;
                   2297:     my ($cnum) = &get_course();
                   2298:     my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
                   2299:     my @sections = sort( { $a <=> $b } keys(%sections));
                   2300:     my %lt = &Apache::lonlocal::texthash (
1.21      raeburn  2301:                                            currone  => 'Current recipient:',
                   2302:                                            currmult => 'Current recipients:',
                   2303:                                            add      => 'Additional recipient:',
                   2304:                                            del      => 'Delete?',
                   2305:                                            sec      => 'Sections:',
1.1       raeburn  2306:                                          );
                   2307: 
                   2308:     foreach my $item (@{$ordered}) {
                   2309:         $count ++;
1.28.2.1  raeburn  2310:        	$datatable .= &item_table_row_start($items{$item}{text},$count);
1.1       raeburn  2311:         if ($position eq 'top') {
                   2312:             my $includeempty = 0;
                   2313:             $datatable .= &user_table($cdom,$item,\@sections,
1.3       raeburn  2314:                                       $settings->{$item},\%lt);
1.1       raeburn  2315:         } else {
1.3       raeburn  2316:             $datatable .= &Apache::lonhtmlcommon::textbox($item.'.text',
1.28.2.1  raeburn  2317:                               $settings->{$item.'.text'},$items{$item}{size});
1.1       raeburn  2318:         }
                   2319:         $datatable .= &item_table_row_end();
                   2320:     }
                   2321:     $$rowtotal += scalar(@{$ordered});
                   2322:     return $datatable;
                   2323: }
                   2324: 
                   2325: sub user_table {
                   2326:     my ($cdom,$item,$sections,$currvalue,$lt) = @_;
                   2327:     my $output;
                   2328:     if ($currvalue eq '') {
                   2329:         $output .= &select_recipient($item,'0',$cdom,$sections);
                   2330:     } else {
                   2331:         my $num = 0;
                   2332:         my @curr = split(/,/,$currvalue);
1.10      raeburn  2333:         $output .= '<table class="LC_nested_outer">';
1.1       raeburn  2334:         my ($currusers);
                   2335:         foreach my $val (@curr) {
                   2336:             next if ($val eq '');
                   2337:             my ($uname,$udom,$seclist) = ($val =~ /^($match_username):($match_domain)(\(?[^\)]*\)?)$/);
                   2338:             my @selsec;
                   2339:             if ($seclist) {
                   2340:                 $seclist =~ s/(^\(|\)$)//g;
                   2341:                 @selsec = split(/\s*;\s*/,$seclist);
                   2342:             }
                   2343:             $currusers .= '<tr>'.
                   2344:                         '<td valign="top"><span class="LC_nobreak">'.
                   2345:                         '<label><input type="checkbox" '.
                   2346:                         'name="'.$item.'_delete" value="'.$num.'" />'.
                   2347:                         $lt->{'del'}.'</label>'.
                   2348:                         '<input type="hidden" name="'.$item.'_user_'.
1.3       raeburn  2349:                         $num.'" value="'.$uname.':'.$udom.'" />'.('&nbsp;'x2).
1.1       raeburn  2350:                         &Apache::loncommon::aboutmewrapper(
                   2351:                             &Apache::loncommon::plainname($uname,$udom,'firstname'),
                   2352:                             $uname,$udom,'aboutuser');
                   2353:             if (ref($sections) eq 'ARRAY') {
                   2354:                 if (@{$sections}) {
                   2355:                     $currusers.= ('&nbsp;'x3).$lt->{'sec'}.'&nbsp;'.
                   2356:                                   &select_sections($item,$num,$sections,
                   2357:                                   \@selsec);
                   2358:                 }
                   2359:             }
                   2360:             $currusers .= '</span></td></tr>';
                   2361:             $num ++;
                   2362:         }
                   2363:         if ($num) {
1.10      raeburn  2364:             $output .= '<tr>'.
1.1       raeburn  2365:                        '<td align="left"><i>';
1.20      faziophi 2366:             if ($num == 1) {
1.1       raeburn  2367:                 $output .= $lt->{'currone'};
                   2368:             } else {
1.21      raeburn  2369:                 $output .= $lt->{'currmult'};
1.1       raeburn  2370:             }
                   2371:             $output .= '</i><br />'.
                   2372:                           '<table>'.$currusers.'</table></td>'.
1.10      raeburn  2373:                           '</tr>';
1.1       raeburn  2374:         }
1.10      raeburn  2375:         $output .= '<tr>'.
1.1       raeburn  2376:                   '<td align="left"><span class="LC_nobreak"><i>'.
                   2377:                   $lt->{'add'}.'</i></span><br />'.
                   2378:                   &select_recipient($item,$num,$cdom,$sections).
                   2379:                   '<input type="hidden" name="'.$item.'_total" value="'.$num.'" />'.
1.10      raeburn  2380:                   '</td></tr></table>';
1.1       raeburn  2381:     }
                   2382:     return $output;
                   2383: }
                   2384: 
                   2385: sub select_recipient {
                   2386:     my ($item,$num,$cdom,$sections,$selected,$includeempty) = @_;
                   2387:     my $domform = &Apache::loncommon::select_dom_form($cdom,$item.'_udom_'.$num,$includeempty);
                   2388:     my $selectlink =
                   2389:         &Apache::loncommon::selectstudent_link('display',$item.'_uname_'.$num,
                   2390:                                                $item.'_udom_'.$num,1);
                   2391:     my $output = 
1.10      raeburn  2392:         '<table><tr><td align="center">'.&mt('Username').'<br />'.
1.1       raeburn  2393:         '<input type="text" name="'.$item.'_uname_'.$num.'" value="" /></td>'.
                   2394:         '<td align="center">'.&mt('Domain').'<br />'.$domform.'</td>';
                   2395:     if (ref($sections) eq 'ARRAY') {
                   2396:         if (@{$sections}) {
                   2397:             $output .= '<td align="center">'.&mt('Sections').'<br />'.
                   2398:                        &select_sections($item,$num,$sections,$selected).'</td>'; 
                   2399:         }
                   2400:     }
                   2401:     $output .= '<td valign="top">'.
                   2402:                $selectlink.'</td></tr></table>';
                   2403:     return $output;
                   2404: }
                   2405: 
                   2406: sub select_sections {
                   2407:     my ($item,$num,$sections,$selected) = @_;
                   2408:     my ($output,@currsecs,$allsec);
                   2409:     if (ref($selected) eq 'ARRAY') {
                   2410:         @currsecs = @{$selected};
                   2411:     }
                   2412:     if (!@currsecs) {
                   2413:         $allsec = ' selected="selected"';
                   2414:     }
                   2415:     if (ref($sections) eq 'ARRAY') {
                   2416:         if (@{$sections}) {
                   2417:             my $mult;
                   2418:             if (@{$sections} > 1) {
                   2419:                 $mult = ' multiple="multiple"';
                   2420:                 if (@{$sections} > 3) {
                   2421:                     $mult .= ' size="4"';
                   2422:                 }
                   2423:             }
                   2424:             $output = '<select name="'.$item.'_sections_'.$num.'"'.$mult.'>'.
                   2425:                       ' <option value=""'.$allsec.'>'.&mt('All').'</option>';
                   2426:             foreach my $sec (@{$sections}) {
                   2427:                 my $is_sel;
                   2428:                 if ((@currsecs) && (grep(/^\Q$sec\E$/,@currsecs))) {
                   2429:                     $is_sel = 'selected="selected"';
                   2430:                 }
                   2431:                 $output .= '<option value="'.$sec.'"'.$is_sel.'>'.$sec.'</option>';
                   2432:             }
                   2433:             $output .= '</select>';
                   2434:         }
                   2435:     }
                   2436:     return $output;
                   2437: }
                   2438: 
                   2439: sub print_discussion {
1.3       raeburn  2440:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
                   2441:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2442:         return;
                   2443:     }
                   2444:     my %items = (
                   2445:         'plc.roles.denied' => {
1.10      raeburn  2446:                    text => '<span class="LC_nobreak"><b>'.&mt($itemtext->{'plc.roles.denied'}).'</b>'.
                   2447:                            &Apache::loncommon::help_open_topic("Course_Disable_Discussion").'</span><br />'.
1.5       raeburn  2448:                            &mt('(role-based)'),
1.1       raeburn  2449:                    input => 'checkbox',
                   2450:                  },
                   2451: 
                   2452:         'plc.users.denied'  => {
1.3       raeburn  2453:                    text => '<b>'.&mt($itemtext->{'plc.users.denied'}).'</b><br />'.
                   2454:                            &mt('(specific user(s))'),
1.1       raeburn  2455:                    input => 'checkbox',
                   2456:                  },
                   2457: 
                   2458:         'pch.roles.denied'   => {
1.10      raeburn  2459:                    text => '<span class="LC_nobreak"><b>'.&mt($itemtext->{'pch.roles.denied'}).'</b>'.
                   2460:                            &Apache::loncommon::help_open_topic("Course_Disable_Discussion").'</span><br />'.
1.3       raeburn  2461:                            &mt('(role-based)'),
1.1       raeburn  2462:                    input => 'checkbox',
                   2463:                  },
                   2464: 
                   2465:         'pch.users.denied'   => {
1.3       raeburn  2466:                    text => '<b>'.&mt($itemtext->{'pch.users.denied'}).'</b><br />'.
                   2467:                            &mt('(specific user(s))'),
1.1       raeburn  2468:                    input => 'checkbox',
                   2469:                  },
                   2470:         'allow_limited_html_in_feedback' => {
1.3       raeburn  2471:                    text => '<b>'.&mt($itemtext->{'allow_limited_html_in_feedback'}).'</b>',
1.1       raeburn  2472:                    input => 'radio',
                   2473:                  },
                   2474: 
                   2475:         'allow_discussion_post_editing' => {
1.3       raeburn  2476:                    text => '<b>'.&mt($itemtext->{'allow_discussion_post_editing'}).'</b>',
1.1       raeburn  2477:                    input => 'checkbox',
                   2478:                  },
                   2479:     );
                   2480:     my $datatable;
                   2481:     my $count;
                   2482:     my ($cnum) = &get_course();
                   2483:     my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
                   2484:     my @sections = sort( { $a <=> $b } keys(%sections));
                   2485:     my %lt = &Apache::lonlocal::texthash (
1.21      raeburn  2486:                                           currone  => 'Disallowed:',
                   2487:                                           currmult => 'Disallowed:',
                   2488:                                           add      => 'Disallow more:',
                   2489:                                           del      => 'Delete?',
                   2490:                                           sec      => 'Sections:',
1.1       raeburn  2491:                                          );
                   2492: 
                   2493:     foreach my $item (@{$ordered}) {
                   2494:         $count ++;
                   2495:         $datatable .= &item_table_row_start($items{$item}{text},$count);
                   2496:         if ($item eq 'plc.roles.denied') {
                   2497:             $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
                   2498:                           '</table>';
                   2499:         } elsif ($item eq 'plc.users.denied') {
                   2500:             $datatable .= &user_table($cdom,$item,undef,
                   2501:                                       $settings->{$item},\%lt);
                   2502:         } elsif ($item eq 'pch.roles.denied') {
                   2503:             $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
                   2504:                           '</table>';
                   2505:         } elsif ($item eq 'pch.users.denied') {
                   2506:             $datatable .= &user_table($cdom,$item,undef,
                   2507:                                       $settings->{$item},\%lt);
                   2508:         } elsif ($item eq 'allow_limited_html_in_feedback') {
                   2509:             $datatable .= &yesno_radio($item,$settings);
                   2510:         } elsif ($item eq 'allow_discussion_post_editing') {
                   2511:             $datatable .= &Apache::loncommon::start_data_table().
                   2512:                           &Apache::loncommon::start_data_table_row().
                   2513:                           '<th align="left">'.&mt('Role').'</th><th>'.
                   2514:                           &mt('Sections').'</th>'.
                   2515:                           &Apache::loncommon::end_data_table_row().
                   2516:                           &role_checkboxes($cdom,$cnum,$item,$settings,1).
                   2517:                           &Apache::loncommon::end_data_table();
                   2518:         }
                   2519:         $datatable .= &item_table_row_end();
                   2520:     }
                   2521:     $$rowtotal += scalar(@{$ordered});
                   2522:     return $datatable;
                   2523: }
                   2524: 
                   2525: sub role_checkboxes {
1.9       raeburn  2526:     my ($cdom,$cnum,$item,$settings,$showsections,$crstype) = @_;
                   2527:     my @roles = ('st','ad','ta','ep','in');
                   2528:     if ($crstype eq 'Community') {
                   2529:         push(@roles,'co');
                   2530:     } else {
                   2531:         push(@roles,'cc');
                   2532:     }
1.1       raeburn  2533:     my $output;
                   2534:     my (@current,@curr_roles,%currsec,@sections);
                   2535:     if ($showsections) {
                   2536:         my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
                   2537:         @sections = sort( { $a <=> $b } keys(%sections));
                   2538:     }
                   2539:     if (ref($settings) eq 'HASH') {
                   2540:         if ($settings->{$item}) {
                   2541:             @current = split(',',$settings->{$item});
                   2542:             if ($showsections) {
                   2543:                 foreach my $role (@current) {
                   2544:                     if ($role =~ /:/) {
                   2545:                         my ($trole,$sec) = split(':',$role);
                   2546:                         push(@curr_roles,$trole);
                   2547:                         if (ref($currsec{$trole}) eq 'ARRAY') {
                   2548:                             if (!grep(/^\Q$sec\E/,@{$currsec{$trole}})) {
                   2549:                                 push(@{$currsec{$trole}},$sec);
                   2550:                             }
1.3       raeburn  2551:                         } else {
                   2552:                             $currsec{$trole} = [$sec];
1.1       raeburn  2553:                         }
                   2554:                     } else {
                   2555:                         push(@curr_roles,$role);
                   2556:                     }
                   2557:                 }
                   2558:                 @current = @curr_roles;
                   2559:             }
                   2560:         }
                   2561:     }
                   2562:     my $numinrow = 3;
                   2563:     my $count = 0;
                   2564:     foreach my $role (@roles) {
                   2565:         my $checked = '';
                   2566:         if (grep(/^\Q$role\E$/,@current)) {
                   2567:             $checked = ' checked="checked" ';
                   2568:         }
1.9       raeburn  2569:         my $plrole=&Apache::lonnet::plaintext($role,$crstype);
1.1       raeburn  2570:         if ($showsections) {
                   2571:             $output .= &Apache::loncommon::start_data_table_row();
                   2572:         } else {
                   2573:             my $rem = $count%($numinrow);
                   2574:             if ($rem == 0) {
                   2575:                 if ($count > 0) {
                   2576:                     $output .= '</tr>';
                   2577:                 }
                   2578:                 $output .= '<tr>';
                   2579:             }
                   2580:         }
1.28.2.2  raeburn  2581:         $output .= '<td align="left"><span class="LC_nobreak"><label><input type="checkbox" name="'.
1.1       raeburn  2582:                    $item.'" value="'.$role.'"'.$checked.'/>&nbsp;'.
                   2583:                    $plrole.'</label></span></td>';
                   2584:         if ($showsections) {
                   2585:             $output .= '<td align="left">'.
                   2586:                        &select_sections($item,$role,\@sections,$currsec{$role}).
                   2587:                        '</td></tr>';
                   2588:         }
                   2589:         $count ++;
                   2590:     }
                   2591:     my %adv_roles =
                   2592:         &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
                   2593:     my $total = @roles;
                   2594:     foreach my $role (sort(keys(%adv_roles))) {
                   2595:         if ($role =~ m{^cr/($match_domain)/($match_name)/\w$}) {
                   2596:             my $rolename = $3;
                   2597:             my $value = 'cr_'.$1.'_'.$2.'_'.$rolename;
                   2598:             my $checked = '';
                   2599:             if (grep(/^\Q$value\E$/,@current)) {
                   2600:                 $checked = ' checked="checked" ';
                   2601:             }
                   2602:             if ($showsections) {
                   2603:                 $output .= &Apache::loncommon::start_data_table_row();
                   2604:             } else {
                   2605:                 my $rem = $count%($numinrow);
                   2606:                 if ($rem == 0) {
                   2607:                     if ($count > 0) {
                   2608:                         $output .= '</tr>';
                   2609:                     }
                   2610:                     $output .= '<tr>';
                   2611:                 }
                   2612:             }
1.28.2.2  raeburn  2613:             $output .= '<td><span class="LC_nobreak"><label><input type="checkbox" name="'.
1.1       raeburn  2614:                        $item.'" value="'.$value.'"'.$checked.' />&nbsp;'.$rolename.
                   2615:                        '</label></span></td>';
                   2616:             if ($showsections) {
                   2617:                 $output .= '<td>'.
                   2618:                            &select_sections($item,$role,\@sections,$currsec{$role}).
                   2619:                            '</td>'.&Apache::loncommon::end_data_table_row();
                   2620:             }
                   2621:             $total ++;
                   2622:             $count ++;
                   2623:         }
                   2624:     }
                   2625:     if (!$showsections) {
                   2626:         my $rem = $total%($numinrow);
                   2627:         my $colsleft = $numinrow - $rem;
                   2628:         if ($colsleft > 1 ) {
                   2629:             $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
                   2630:                        '&nbsp;</td>';
                   2631:         } elsif ($colsleft == 1) {
                   2632:             $output .= '<td class="LC_left_item">&nbsp;</td>';
                   2633:         }
                   2634:         $output .= '</tr>';
                   2635:     }
                   2636:     return $output;
                   2637: }
                   2638: 
                   2639: sub print_classlists {
1.9       raeburn  2640:     my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype) = @_;
1.1       raeburn  2641:     my @ordered;
                   2642:     if ($position eq 'top') {
                   2643:         @ordered = ('default_enrollment_start_date',
                   2644:                     'default_enrollment_end_date');
                   2645:     } elsif ($position eq 'middle') {
                   2646:         @ordered = ('nothideprivileged');
                   2647:     } else {
                   2648:         @ordered = ('student_classlist_view',
1.26      raeburn  2649:                     'student_classlist_opt_in',
                   2650:                      'student_classlist_portfiles');
1.1       raeburn  2651:     }
1.9       raeburn  2652:     my %lt;
                   2653: 
                   2654:     if ($crstype eq 'Community') {
                   2655:         %lt = &Apache::lonlocal::texthash (
                   2656:                  disabled => 'No viewable membership list',
                   2657:                  section  => "Membership of viewer's section",
                   2658:                  all      => 'List of all members',
                   2659:               );
                   2660:     } else {
                   2661:         %lt = &Apache::lonlocal::texthash (
                   2662:                  disabled => 'No viewable classlist',
                   2663:                  section  => "Classlist of viewer's section",
                   2664:                  all      => 'Classlist of all students',
                   2665:               );
                   2666:     }
                   2667: 
1.1       raeburn  2668:     my %items = (
                   2669:         'default_enrollment_start_date' => {
1.3       raeburn  2670:                    text => '<b>'.&mt($itemtext->{'default_enrollment_start_date'}).'</b>',
1.1       raeburn  2671:                    input => 'dates',
                   2672:                  },
                   2673:         'default_enrollment_end_date'  => {
1.3       raeburn  2674:                    text => '<b>'.&mt($itemtext->{'default_enrollment_end_date'}).'</b>',
1.1       raeburn  2675:                    input => 'dates',
                   2676:                  },
                   2677: 
                   2678:         'nothideprivileged'   => {
1.3       raeburn  2679:                    text => '<b>'.&mt($itemtext->{'nothideprivileged'}).'</b>',
1.1       raeburn  2680:                    input => 'checkbox',
                   2681:                  },
                   2682: 
                   2683:         'student_classlist_view'   => {
1.3       raeburn  2684:                    text => '<b>'.&mt($itemtext->{'student_classlist_view'}).'</b>',
1.1       raeburn  2685:                    input => 'selectbox',
1.9       raeburn  2686:                    options => \%lt,
1.1       raeburn  2687:                    order => ['disabled','all','section'],
                   2688:                  },
1.26      raeburn  2689:         'student_classlist_opt_in' => {
                   2690:                    text => '<b>'.&mt($itemtext->{'student_classlist_opt_in'}).'</b>',
1.1       raeburn  2691:                    input => 'radio',
                   2692:                  },
                   2693: 
                   2694:         'student_classlist_portfiles' => {
1.3       raeburn  2695:                    text => '<b>'.&mt($itemtext->{'student_classlist_portfiles'}).'</b>',
1.1       raeburn  2696:                    input => 'radio',
                   2697:                  },
                   2698:     );
                   2699:     unless (($settings->{'student_classlist_view'} eq 'all') || 
                   2700:             ($settings->{'student_classlist_view'} eq 'section')) { 
                   2701:         $settings->{'student_classlist_view'} = 'disabled';
                   2702:     }
1.9       raeburn  2703:     return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype);
1.1       raeburn  2704: }
                   2705: 
                   2706: sub print_appearance {
1.9       raeburn  2707:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3       raeburn  2708:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2709:         return;
                   2710:     }
1.9       raeburn  2711:     my $mathdef;
                   2712:     if ($crstype eq 'Community') {
                   2713:         $mathdef = &mt("None specified - use member's choice");
                   2714:     } else {
                   2715:         $mathdef = &mt("None specified - use student's choice");
                   2716:     }
1.1       raeburn  2717:     my %items = (
                   2718:         'default_xml_style' => {
1.3       raeburn  2719:                    text => '<b>'.&mt($itemtext->{'default_xml_style'}).'</b> '.
1.1       raeburn  2720:                            '<a href="javascript:openbrowser'.
                   2721:                            "('display','default_xml_style'".
                   2722:                            ",'sty')".'">'.&mt('Select Style File').'</a>',
                   2723:                    input => 'textbox',
                   2724:                    size => 35,
                   2725:                  },
                   2726: 
                   2727:         'pageseparators'  => {
1.3       raeburn  2728:                    text => '<b>'.&mt($itemtext->{'pageseparators'}).'</b>',
1.1       raeburn  2729:                    input => 'radio',
                   2730:                  },
                   2731:         'disable_receipt_display' => {
1.3       raeburn  2732:                    text => '<b>'.&mt($itemtext->{'disable_receipt_display'}).'</b>',
1.1       raeburn  2733:                    input => 'radio',
                   2734:                  },
                   2735:         'texengine'  => {
1.3       raeburn  2736:                    text => '<b>'.&mt($itemtext->{'texengine'}).'</b>',
1.1       raeburn  2737:                    input => 'selectbox',
                   2738:                    options => {
                   2739:                                 jsMath   => 'jsMath',
                   2740:                                 mimetex => &mt('Convert to Images'),
                   2741:                                 tth      => &mt('TeX to HTML'),
                   2742:                               },
                   2743:                    order  => ['jsMath','mimetex','tth'],
1.9       raeburn  2744:                    nullval => $mathdef,
1.1       raeburn  2745:                  },
                   2746:         'tthoptions' => {
1.3       raeburn  2747:                    text => '<b>'.&mt($itemtext->{'tthoptions'}).'</b>',
1.1       raeburn  2748:                    input => 'textbox',
                   2749:                    size => 40,
                   2750:                  },
                   2751:     );
1.9       raeburn  2752:     return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1       raeburn  2753: }
                   2754: 
                   2755: sub print_grading {
1.9       raeburn  2756:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3       raeburn  2757:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2758:         return;
                   2759:     }
                   2760:     my %items = (
                   2761:         'grading'  => {
1.3       raeburn  2762:                    text => '<b>'.&mt($itemtext->{'grading'}).'</b>'.
1.1       raeburn  2763:                            &Apache::loncommon::help_open_topic('GradingOptions'),
                   2764:                    input => 'selectbox',
                   2765:                    options => {
                   2766:                                 standard => &mt('Standard: shows points'),
1.11      www      2767:                                 external => &mt('External: shows number of completed parts and totals'),
                   2768:                                 externalnototals => &mt('External: shows only number of completed parts'),
1.1       raeburn  2769:                                 spreadsheet => &mt('Spreadsheet: (with link to detailed scores)'), 
                   2770:                               },
1.11      www      2771:                    order => ['standard','external','externalnototals','spreadsheet'],
1.1       raeburn  2772:                  },
                   2773:         'rndseed' => {
1.3       raeburn  2774:                    text => '<b>'.&mt($itemtext->{'rndseed'}).'</b>'.
1.17      faziophi 2775:                            '<span class="LC_warning">'.'<br />'.
1.1       raeburn  2776:                            &mt('Modifying this will make problems have different numbers and answers!').
                   2777:                            '</span>',
                   2778:                    input => 'selectbox',
                   2779:                    options => {
                   2780:                                 '32bit'  => '32bit',
                   2781:                                 '64bit'  => '64bit',
                   2782:                                 '64bit2' => '64bit2',
                   2783:                                 '64bit3' => '64bit3',
                   2784:                                 '64bit4' => '64bit4',
                   2785:                                 '64bit5' => '64bit5',
                   2786:                               },
                   2787:                    order => ['32bit','64bit','64bit2','64bit3','64bit4','64bit5'],
                   2788:                  },
                   2789:         'receiptalg'  => {
1.3       raeburn  2790:                    text => '<b>'.&mt($itemtext->{'receiptalg'}).'</b><br />'.
1.5       raeburn  2791:                            &mt('This controls how receipt numbers are generated'),
1.1       raeburn  2792:                    input => 'selectbox',
                   2793:                    options => {
                   2794:                                 receipt  => 'receipt',
                   2795:                                 receipt2 => 'receipt2',
                   2796:                                 receipt3 => 'receipt3',
                   2797:                               },
                   2798:                    order => ['receipt','receipt2','receipt3'],
                   2799:                  },
                   2800:         'disablesigfigs' => {
1.3       raeburn  2801:                    text => '<b>'.&mt($itemtext->{'disablesigfigs'}).'</b>',
1.1       raeburn  2802:                    input => 'radio',
                   2803:                  },
                   2804:     );
1.9       raeburn  2805:     return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1       raeburn  2806: }
                   2807: 
                   2808: sub print_printouts {
1.9       raeburn  2809:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3       raeburn  2810:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2811:         return;
                   2812:     }
                   2813:     my %items = (
                   2814:         problem_stream_switch => {
1.3       raeburn  2815:             text => '<b>'.&mt($itemtext->{'problem_stream_switch'}).'</b>',
1.1       raeburn  2816:             input => 'radio',
                   2817:                                  },
                   2818:         suppress_tries => {
1.3       raeburn  2819:             text => '<b>'.&mt($itemtext->{'suppress_tries'}).'</b>',
1.1       raeburn  2820:             input => 'radio',
                   2821:                           },
                   2822:         default_paper_size => {
1.3       raeburn  2823:             text => '<b>'.&mt($itemtext->{'default_paper_size'}).'</b>',
1.1       raeburn  2824:             input => 'selectbox',
                   2825:             options => {
                   2826:                          Letter    => &mt('Letter').' [8 1/2x11 in]',
                   2827:                          Legal     => &mt('Legal').' [8 1/2x14 in]',
                   2828:                          Tabloid   => &mt('Tabloid').' [11x17 in]',
                   2829:                          Executive => &mt('Executive').' [7 1/2x10 in]',
                   2830:                          A2        => &mt('A2').' [420x594 mm]',
                   2831:                          A3        => &mt('A3').' [297x420 mm]',
                   2832:                          A4        => &mt('A4').' [210x297 mm]',
                   2833:                          A5        => &mt('A5').' [148x210 mm]',
                   2834:                          A6        => &mt('A6').' [105x148 mm]',
                   2835:                        },
                   2836:             order => ['Letter','Legal','Tabloid','Executive','A2','A3','A4','A5','A6'],
                   2837:             nullval => 'None specified',
                   2838:                               },
                   2839:         print_header_format => {
1.3       raeburn  2840:             text => '<b>'.&mt($itemtext->{'print_header_format'}).'</b>',
1.1       raeburn  2841:             input => 'checkbox',
                   2842:                                },
                   2843:         disableexampointprint => {
1.3       raeburn  2844:             text => '<b>'.&mt($itemtext->{'disableexampointprint'}).'</b>',
1.1       raeburn  2845:             input => 'radio',
                   2846:                                  },
1.14      raeburn  2847:         canuse_pdfforms => {
                   2848:             text  => '<b>'.&mt($itemtext->{'canuse_pdfforms'}).'</b>',
                   2849:             input => 'selectbox',
                   2850:             options => {
                   2851:                          1    => &mt('Yes'),
                   2852:                          0    => &mt('No'),
                   2853:                        },
                   2854:             order => ['1','0'],
                   2855:             nullval => 'None specified - use domain default',
                   2856:                     }
1.1       raeburn  2857:     );
1.9       raeburn  2858:     return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1       raeburn  2859: }
                   2860: 
                   2861: sub print_spreadsheet {
1.9       raeburn  2862:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3       raeburn  2863:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2864:         return;
                   2865:     }
                   2866:     my $SelectSpreadsheetFile=&mt('Select Spreadsheet File');
                   2867:     my %items = (
                   2868:         spreadsheet_default_classcalc => {
1.3       raeburn  2869:             text => '<b>'.&mt($itemtext->{'spreadsheet_default_classcalc'}).'</b> '.
1.1       raeburn  2870:                     '<span class="LC_nobreak"><a href="javascript:openbrowser'.
                   2871:                     "('display','spreadsheet_default_classcalc'".
                   2872:                     ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
                   2873:             input => 'textbox',
                   2874:                                          },
                   2875:         spreadsheet_default_studentcalc => {
1.3       raeburn  2876:             text => '<b>'.&mt($itemtext->{'spreadsheet_default_studentcalc'}).'</b> '.
1.1       raeburn  2877:                     '<span class="LC_nobreak"><a href="javascript:openbrowser'.
                   2878:                     "('display','spreadsheet_default_calc'".
                   2879:                     ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
                   2880:             input => 'textbox',
                   2881:                                            },
                   2882:         spreadsheet_default_assesscalc => {
1.3       raeburn  2883:             text => '<b>'.&mt($itemtext->{'spreadsheet_default_assesscalc'}).'</b> '.
1.1       raeburn  2884:                     '<span class="LC_nobreak"><a href="javascript:openbrowser'.
                   2885:                     "('display','spreadsheet_default_assesscalc'".
                   2886:                     ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
                   2887:             input => 'textbox',
                   2888:                                           },
                   2889:         hideemptyrows => {
1.3       raeburn  2890:             text => '<b>'.&mt($itemtext->{'hideemptyrows'}).'</b>',
1.1       raeburn  2891:             input => 'radio',
                   2892:                          },
                   2893:                 );
1.9       raeburn  2894:     return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
                   2895: }
1.1       raeburn  2896: 
                   2897: sub print_bridgetasks {
1.9       raeburn  2898:     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3       raeburn  2899:     unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1       raeburn  2900:         return;
                   2901:     }
1.9       raeburn  2902:     my ($stumsg,$msgnote);
                   2903:     if ($crstype eq 'Community') {
                   2904:         $stumsg = &mt('Send message to member');
                   2905:         $msgnote = &mt('Message to member and add to user notes');
                   2906:     } else {
                   2907:         $stumsg = &mt('Send message to student');
                   2908:         $msgnote = &mt('Message to student and add to user notes');
                   2909:     }
1.1       raeburn  2910:     my %items = (
                   2911:          task_messages => {
1.3       raeburn  2912:               text => '<b>'.&mt($itemtext->{'task_messages'}).'</b>',
1.1       raeburn  2913:               input => 'selectbox',
                   2914:               options => {
1.9       raeburn  2915:                            only_student => $stumsg,
                   2916:                            student_and_user_notes_screen => $msgnote,
1.1       raeburn  2917:                          },
                   2918:               order   => ['only_student','student_and_user_notes_screen'],
                   2919:               nullval => &mt('No message or record in user notes'),
                   2920:                           },
                   2921:          task_grading => {
1.3       raeburn  2922:               text => '<b>'.&mt($itemtext->{'task_grading'}).'</b>',
1.1       raeburn  2923:               input => 'selectbox',
                   2924:               options => {
                   2925:                            any => &mt('Grade BTs in any section'),
                   2926:                            section => &mt('Grade BTs only in own section')
                   2927:                          },
                   2928:               order => ['any','section'],
                   2929:                          },
                   2930:          suppress_embed_prompt => {
1.3       raeburn  2931:              text => '<b>'.&mt($itemtext->{'suppress_embed_prompt'}).'</b><span class="LC_nobreak">'.
                   2932:                      '&nbsp;'.&mt('(applies when current role is student)').'</span>',
1.1       raeburn  2933:              input => 'radio',
                   2934:                                   },
                   2935:                 );
1.9       raeburn  2936:     return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1       raeburn  2937: }
                   2938: 
                   2939: sub print_other {
1.9       raeburn  2940:     my ($cdom,$settings,$allitems,$rowtotal,$crstype) = @_;
1.1       raeburn  2941:     unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
                   2942:         return;
                   2943:     }
1.3       raeburn  2944:     my @ordered = &get_other_items($cdom,$settings,$allitems);
                   2945:     my %items;
                   2946:     foreach my $parameter (@ordered) {
                   2947:         $items{$parameter} = {
                   2948:                                text  => '<b>'.$parameter.'</b>',
                   2949:                                input => 'textbox',
                   2950:                                size  => '15',
                   2951:                              },
                   2952:     }
                   2953:     push (@ordered,'newp_value');
                   2954:     $items{'newp_value'} = {
                   2955:                             text  => '<b>'.&mt('Create New Environment Variable').'</b><br />'.
                   2956:                                      '<input type="textbox" name="newp_name"'.
                   2957:                                      ' value="" size="30" />',
                   2958:                             input => 'textbox',
                   2959:                             size  => '30',
                   2960:                            };
1.9       raeburn  2961:     my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype);
1.3       raeburn  2962: }
                   2963: 
                   2964: sub get_other_items {
                   2965:     my ($cdom,$settings,$allitems) = @_;
                   2966:     unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
                   2967:         return;
                   2968:     }
1.1       raeburn  2969:     my @ordered;
                   2970:     if (ref($settings) eq 'HASH') {
                   2971:         foreach my $parameter (sort(keys(%{$settings}))) {
                   2972:             next if (grep/^\Q$parameter\E$/,@{$allitems});
1.3       raeburn  2973:             next if (($parameter eq 'course.helper.not.run') &&
                   2974:                      (!exists($env{'user.role.dc./'.$env{'request.role.domain'}.'/'})));
1.1       raeburn  2975:             unless (($parameter =~ m/^internal\./)||($parameter =~ m/^metadata\./) ||
                   2976:                     ($parameter =~ m/^selfenroll_/) || ($parameter =~ /_selfenroll$/)
                   2977:                     || ($parameter eq 'type') ||
1.9       raeburn  2978:                     ($parameter =~ m/^(cc|co|in|ta|ep|ad|st)\.plaintext$/)) {
1.1       raeburn  2979:                 push(@ordered,$parameter);
                   2980:             }
                   2981:         }
                   2982:     }
1.3       raeburn  2983:     return @ordered;
1.1       raeburn  2984: }
                   2985: 
                   2986: sub item_table_row_start {
1.19      faziophi 2987:     my ($text,$count,$add_class) = @_;
1.1       raeburn  2988:     my $output;
1.19      faziophi 2989: 	my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
                   2990: 	$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
                   2991: 	$output .= '<tr class="'.$css_class.'">'."\n";;
1.1       raeburn  2992:     $output .= '<td class="LC_left_item">'.$text.
1.19      faziophi 2993:                '</td><td class="LC_right_item">';
1.1       raeburn  2994:     return $output;
                   2995: }
                   2996: 
                   2997: sub item_table_row_end {
                   2998:     return '</td></tr>';
                   2999: }
                   3000: 
                   3001: sub yesno_radio {
                   3002:     my ($item,$settings) = @_;
                   3003:     my $itemon = ' ';
                   3004:     my $itemoff = ' checked="checked" ';
                   3005:     if (ref($settings) eq 'HASH') {
                   3006:         if ($settings->{$item} eq 'yes') {
                   3007:             $itemon = $itemoff;
                   3008:             $itemoff = ' ';
                   3009:         }
                   3010:     }
                   3011:     return '<span class="LC_nobreak"><label>'.
                   3012:            '<input type="radio" name="'.$item.'"'.
                   3013:            $itemon.' value="yes" />'.&mt('Yes').'</label>&nbsp;'.
                   3014:            '<label><input type="radio" name="'.$item.'"'.
                   3015:            $itemoff.' value="" />'.&mt('No').'</label></span>';
                   3016: }
                   3017: 
                   3018: sub select_from_options {
                   3019:     my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange) = @_;
                   3020:     my $output;
                   3021:     if ((ref($order) eq 'ARRAY') && (ref($options) eq 'HASH')) {
                   3022:         $output='<select name="'.$item.'" '.$onchange;
                   3023:         if ($multiple) {
                   3024:             $output .= ' multiple="multiple"';
                   3025:             my $num = @{$order};
                   3026:             $num ++ if ($nullval ne '');
                   3027:             if (($maxsize) && ($maxsize < $num)) {
                   3028:                 $output .= ' size="'.$maxsize.'"';
                   3029:             }
                   3030:         }
                   3031:         $output .= '>'."\n";
                   3032:         if ($nullval ne '') {
                   3033:             $output .= '<option value=""';
                   3034:             if (ref($curr) eq 'ARRAY') {
                   3035:                 if ((@{$curr} == 0) || (grep(/^$/,@{$curr}))) {
                   3036:                     $output .= ' selected="selected" ';
                   3037:                 }
                   3038:             } else {
                   3039:                 if ($curr eq '') {
                   3040:                     $output .= ' selected="selected" ';
                   3041:                 }
                   3042:             }
                   3043:             $output .= '>'.$nullval.'</option>';
                   3044:         }
                   3045:         foreach my $option (@{$order}) {
                   3046:             $output.= '<option value="'.$option.'"';
                   3047:             if (ref($curr) eq 'ARRAY') {
                   3048:                 if (grep(/^\Q$option\E$/,@{$curr})) {
                   3049:                     $output .= ' selected="selected" ';
                   3050:                 }
                   3051:             } else {
                   3052:                 if ($option eq $curr) {
                   3053:                     $output.=' selected="selected"';
                   3054:                 }
                   3055:             }
                   3056:             $output.=">$options->{$option}</option>\n";
                   3057:         }
                   3058:         $output.="</select>";
                   3059:     }
                   3060:     return $output;
                   3061: }
                   3062: 
                   3063: sub make_item_rows {
1.9       raeburn  3064:     my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype) = @_;
1.1       raeburn  3065:     my $datatable;
                   3066:     if ((ref($items) eq 'HASH') && (ref($ordered) eq 'ARRAY')) {
                   3067:         my $count = 0;
                   3068:         foreach my $item (@{$ordered}) {
                   3069:             $count ++;
                   3070:             $datatable .= &item_table_row_start($items->{$item}{text},$count);
                   3071:             if ($item eq 'nothideprivileged') {
1.9       raeburn  3072:                 $datatable .= &nothidepriv_row($cdom,$item,$settings,$crstype);
1.1       raeburn  3073:             } elsif ($item eq 'print_header_format') {
                   3074:                 $datatable .= &print_hdrfmt_row($item,$settings);
                   3075:             } elsif ($items->{$item}{input} eq 'dates') {
                   3076:                $datatable .=
                   3077:                    &Apache::lonhtmlcommon::date_setter('display',$item,
                   3078:                                                        $settings->{$item});
                   3079:             } elsif ($items->{$item}{input} eq 'radio') {
                   3080:                 $datatable .= &yesno_radio($item,$settings);
                   3081:             } elsif ($items->{$item}{input} eq 'selectbox') {
                   3082:                 my $curr = $settings->{$item};
                   3083:                 $datatable .=
                   3084:                     &select_from_options($item,$items->{$item}{'order'},
                   3085:                                          $items->{$item}{'options'},$curr,
                   3086:                                          $items->{$item}{'nullval'});
                   3087:             } elsif ($items->{$item}{input} eq 'textbox') {
                   3088:                 $datatable .= 
                   3089:                     &Apache::lonhtmlcommon::textbox($item,$settings->{$item},
                   3090:                                                     $items->{$item}{size});
                   3091:             }
                   3092:             $datatable .= &item_table_row_end();
                   3093:         }
                   3094:         if (ref($rowtotal)) {
                   3095:             $$rowtotal += scalar(@{$ordered});
                   3096:         }
                   3097:     }
                   3098:     return $datatable;
                   3099: }
                   3100: 
                   3101: sub nothidepriv_row {
1.9       raeburn  3102:     my ($cdom,$item,$settings,$crstype) = @_;
1.1       raeburn  3103:     my ($cnum) = &get_course();
                   3104:     my %nothide;
                   3105:     my $datatable;
                   3106:     if (ref($settings) eq 'HASH') {
                   3107:         if ($settings->{$item} ne '') {
                   3108:             foreach my $user (split(/\s*\,\s*/,$settings->{$item})) {
                   3109:                 if ($user !~ /:/) {
                   3110:                     $nothide{join(':',split(/[\@]/,$user))}=1;
                   3111:                 } else {
                   3112:                     $nothide{$user} = 1;
                   3113:                 }
                   3114:             }
                   3115:         }
                   3116:     }
                   3117:     my %coursepersonnel = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
                   3118:     my $now = time;
                   3119:     my @privusers;
1.3       raeburn  3120:     my %privileged;
1.1       raeburn  3121:     foreach my $person (keys(%coursepersonnel)) {
                   3122:         my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/);
                   3123:         $user =~ s/:$//;
                   3124:         my ($end,$start) = split(/:/,$coursepersonnel{$person});
                   3125:         if ($end == -1 || $start == -1) {
                   3126:             next;
                   3127:         }
                   3128:         my ($uname,$udom) = split(':',$user);
1.3       raeburn  3129:         unless (ref($privileged{$udom}) eq 'HASH') {
                   3130:             my %dompersonnel = &Apache::lonnet::get_domain_roles($udom,['dc'],undef,$now);
                   3131:             $privileged{$udom} = {};
                   3132:             if (keys(%dompersonnel)) {
                   3133:                 foreach my $server (keys(%dompersonnel)) {
                   3134:                     foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
                   3135:                         my ($trole,$uname,$udom) = split(/:/,$user); 
                   3136:                         $privileged{$udom}{$uname} = $trole;
                   3137:                     }
                   3138:                 }
                   3139:             }
                   3140:         }
                   3141:         if (exists($privileged{$udom}{$uname})) {
1.7       raeburn  3142:             unless (grep(/^\Q$user\E$/,@privusers)) {
                   3143:                 push(@privusers,$user);
                   3144:             }
1.1       raeburn  3145:         }
                   3146:     }
                   3147:     if (@privusers) {
                   3148:         $datatable .= '<table align="right">';
                   3149:         foreach my $user (sort(@privusers)) {
                   3150:             my $hideon = ' checked="checked" ';
                   3151:             my $hideoff = '';
                   3152:             if ($nothide{$user}) {
                   3153:                 $hideoff = $hideon;
                   3154:                 $hideon = '';
                   3155:             }
                   3156:             my ($uname,$udom) = split(':',$user);
                   3157:             $datatable .=  '<tr><td align="left">'.
                   3158:                            &Apache::loncommon::aboutmewrapper(
                   3159:                            &Apache::loncommon::plainname($uname,$udom,'firstname'),
                   3160:                            $uname,$udom,'aboutuser').
                   3161:                           '</td><td align="left">'.
                   3162:                           '<span class="LC_nobreak"><label>'.
                   3163:                           '<input type="radio" name="'.$item.'_'.$user.'"'.
1.7       raeburn  3164:                           $hideon.' value="" />'.&mt('Hidden').'</label>&nbsp;'.
                   3165:                           '<label><input type="radio" name="'.$item.'_'.$user.'"'.                          $hideoff.' value="yes" />'.&mt('Shown').'</label></span></td>'.
1.1       raeburn  3166:                           '</tr>';
                   3167:         }
                   3168:         $datatable .= '</table>';
                   3169:     } else {
1.9       raeburn  3170:         if ($crstype eq 'Community') {
                   3171:             $datatable .= &mt('No Domain Coordinators have community roles');
                   3172:         } else {
                   3173:             $datatable .= &mt('No Domain Coordinators have course roles');
                   3174:         }
1.1       raeburn  3175:     }
                   3176:     return $datatable;
                   3177: }
                   3178: 
                   3179: sub print_hdrfmt_row {
                   3180:     my ($item,$settings) = @_;
                   3181:     my @curr;
                   3182:     my $currnum = 0;
                   3183:     my $maxnum = 2;
                   3184:     my $currstr;
                   3185:     if ($settings->{$item} ne '') {
                   3186:         $currstr .= '<b>'.&mt('Current print header:').' <span class="LC_warning"><tt>'.
                   3187:                    $settings->{$item}.'</tt></span></b><br />';
                   3188:         my @current = split(/(%\d*[nca])/,$settings->{$item});
1.23      raeburn  3189:         foreach my $val (@current) {
                   3190:             unless ($val eq '') {
                   3191:                 push(@curr,$val);
1.1       raeburn  3192:             }
                   3193:         }
                   3194:         $currnum = @curr;
                   3195:         $maxnum += $currnum;
                   3196:     }
                   3197: 
                   3198:     my $output = <<ENDJS;
                   3199: 
                   3200: <script type="text/javascript" language="Javascript">
                   3201: 
                   3202: function reOrder(chgnum) {
                   3203:     var maxnum = $maxnum;
                   3204:     var oldidx = 'printfmthdr_oldpos_'+chgnum;
                   3205:     var newidx = 'printfmthdr_pos_'+chgnum;
                   3206:     oldidx = getIndexByName(oldidx);
                   3207:     newidx = getIndexByName(newidx);
                   3208:     var oldpos = document.display.elements[oldidx].value;
                   3209:     var newpos = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
                   3210:     document.display.elements[oldidx].value = newpos;
                   3211:     var chgtype = 'up';
                   3212:     if (newpos < oldpos) {
                   3213:         chgtype = 'down';
                   3214:     }
                   3215:     for (var j=0; j<maxnum; j++) {
                   3216:         if (j != chgnum) {
                   3217:             oldidx = 'printfmthdr_oldpos_'+j;
                   3218:             newidx = 'printfmthdr_pos_'+j;
                   3219:             oldidx = getIndexByName(oldidx);
                   3220:             newidx = getIndexByName(newidx);
                   3221:             var currpos = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
                   3222:             var currsel = document.display.elements[newidx].selectedIndex;
                   3223:             if (chgtype == 'up') {
                   3224:                 if ((currpos > oldpos) && (currpos <= newpos)) {
                   3225:                     document.display.elements[newidx].selectedIndex = currsel-1;
                   3226:                     document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
                   3227:                 }
                   3228:             } else {
                   3229:                 if ((currpos >= newpos) && (currpos < oldpos)) {
                   3230:                     document.display.elements[newidx].selectedIndex = currsel+1;
                   3231:                     document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
                   3232:                 }
                   3233:             }
                   3234:         }
                   3235:     }
                   3236:     return;
                   3237: }
                   3238: 
                   3239: function getIndexByName(item) {
                   3240:     for (var i=0;i<document.display.elements.length;i++) {
                   3241:         if (document.display.elements[i].name == item) {
                   3242:             return i;
                   3243:         }
                   3244:     }
                   3245:     return -1;
                   3246: }
                   3247: 
                   3248: </script>
                   3249: 
                   3250: ENDJS
1.10      raeburn  3251:     $output .= $currstr.'<table class="LC_nested_outer">';
1.1       raeburn  3252:     if (@curr > 0) {
                   3253:         for (my $i=0; $i<@curr; $i++) {
                   3254:             my $pos = $i+1;
1.10      raeburn  3255:             $output .= '<tr>'.
1.1       raeburn  3256:                        '<td align="left"><span class="LC_nobreak">'.
                   3257:                        &position_selector($pos,$i,$maxnum).&mt('Delete:').
                   3258:                        '<input type="checkbox" name="printfmthdr_del_'.$i.
                   3259:                        '" /></span></td>';
                   3260:             if ($curr[$i] =~ /^%\d*[nca]$/) {
                   3261:                 my ($limit,$subst) = ($curr[$i] =~ /^%(\d*)([nca])$/);
                   3262:                 $output .= '<td align="left">'.
                   3263:                            &substitution_selector($i,$subst,$limit).'</td>';
                   3264:             } else {
                   3265:                 $output .= '<td colspan="2" align="left">'.&mt('Text').'<br />'.
                   3266:                            '<input type="textbox" name="printfmthdr_text_'.$i.'"'.
                   3267:                            ' value="'.$curr[$i].'" size="25" /></td>';
                   3268:             }
1.10      raeburn  3269:             $output .= '</tr>';
1.1       raeburn  3270:         }
                   3271:     }
                   3272:     my $pos = $currnum+1; 
1.10      raeburn  3273:     $output .= '<tr>'.
1.1       raeburn  3274:                '<td align="left"><span class="LC_nobreak">'.
                   3275:                &position_selector($pos,$currnum,$maxnum).
                   3276:                '<b>'.&mt('New').'</b></span></td><td align="left">'.
                   3277:                &substitution_selector($currnum).'</td>'.
1.10      raeburn  3278:                '</tr>'; 
1.1       raeburn  3279:     $pos ++;
                   3280:     $currnum ++;
1.10      raeburn  3281:     $output .= '<tr>'.
1.1       raeburn  3282:                '<td align="left"><span class="LC_nobreak">'.
                   3283:                &position_selector($pos,$currnum,$maxnum).
                   3284:                '<b>'.&mt('New').'</b></span></td>'.
                   3285:                '<td colspan="2" align="left">'.&mt('Text').'<br />'.
                   3286:                '<input type="textbox" name="printfmthdr_text_'.$currnum.
1.3       raeburn  3287:                '" value="" size ="25" />'.
                   3288:                '<input type="hidden" name="printfmthdr_maxnum" value="'.
                   3289:                 $maxnum.'" /></td>'.
1.10      raeburn  3290:                '</tr>'.
                   3291:                '</table>'; 
1.1       raeburn  3292:     return $output;
                   3293: }
                   3294: 
                   3295: sub position_selector {
                   3296:     my ($pos,$num,$maxnum) = @_;
                   3297:     my $output = '<select name="printfmthdr_pos_'.$num.'" onchange="reOrder('."'$num'".');">';
                   3298:     for (my $j=1; $j<=$maxnum; $j++) {
                   3299:         my $sel = '';
                   3300:         if ($pos == $j) {
                   3301:             $sel = ' selected="selected"';
                   3302:         }
                   3303:         $output .= '<option value="'.$j.'"'.$sel.'">'.$j.'</option>';
                   3304:     }
                   3305:     $output .= '</select><input type="hidden" name="printfmthdr_oldpos_'.$num.
                   3306:                '" value="'.$pos.'" />';
                   3307:     return $output;
                   3308: }
                   3309: 
                   3310: sub substitution_selector {
1.9       raeburn  3311:     my ($num,$subst,$limit,$crstype) = @_;
                   3312:     my ($stunametxt,$crsidtxt);
                   3313:     if ($crstype eq 'Community') {
                   3314:         $stunametxt = 'member name';
                   3315:         $crsidtxt = 'community ID',
                   3316:     } else {
                   3317:         $stunametxt = 'student name';
                   3318:         $crsidtxt = 'course ID',
                   3319:     }
1.1       raeburn  3320:     my %lt = &Apache::lonlocal::texthash(
1.9       raeburn  3321:                     n => $stunametxt,
                   3322:                     c => $crsidtxt,
1.1       raeburn  3323:                     a => 'assignment note',
                   3324:              );
                   3325:     my $output .= &mt('Substitution').'<br />'.
1.28.2.2  raeburn  3326:                   '<select name="printfmthdr_sub_'.$num.'">';
1.1       raeburn  3327:     if ($subst eq '') {
                   3328:         $output .= '<option value="" selected="selected"> </option>';
                   3329:     }
                   3330:     foreach my $field ('n','c','a') {
                   3331:         my $sel ='';
                   3332:         if ($subst eq $field) {
                   3333:             $sel = ' selected="selected"';
                   3334:         }
                   3335:         $output .= '<option value="'.$field.'"'.$sel.'>'.
                   3336:                    $lt{$field}.'</option>';
                   3337:     }
                   3338:     $output .= '</select></td><td align="left">'.&mt('Size limit').'<br />'.
                   3339:                '<input type="textbox" name="printfmthdr_limit_'.$num.
                   3340:                '" value="'.$limit.'" size="5" /></span>';
                   3341:     return $output;
                   3342: }
                   3343: 
1.23      raeburn  3344: sub change_clone {
                   3345:     my ($cdom,$cnum,$clonelist,$oldcloner) = @_;
                   3346:     my $clone_crs = $cnum.':'.$cdom;
                   3347:     if ($cnum && $cdom) {
                   3348:         my $clone_crs = $cnum.':'.$cdom;
                   3349:         my @allowclone;
                   3350:         if ($clonelist =~ /,/) {
                   3351:             @allowclone = split(',',$clonelist);
                   3352:         } else {
                   3353:             $allowclone[0] = $clonelist;
                   3354:         }
                   3355:         foreach my $currclone (@allowclone) {
                   3356:             if (!grep(/^$currclone$/,@$oldcloner)) {
                   3357:                 if ($currclone ne '*') {
                   3358:                     my ($uname,$udom) = split(/:/,$currclone);
                   3359:                     if ($uname && $udom && $uname ne '*') {
                   3360:                         if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
                   3361:                             my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable');
                   3362:                             if ($currclonecrs{'cloneable'} !~ /\Q$clone_crs\E/) {
                   3363:                                 if ($currclonecrs{'cloneable'} eq '') {
                   3364:                                     $currclonecrs{'cloneable'} = $clone_crs;
                   3365:                                 } else {
                   3366:                                     $currclonecrs{'cloneable'} .= ','.$clone_crs;
                   3367:                                 }
                   3368:                                 &Apache::lonnet::put('environment',\%currclonecrs,$udom,$uname);
                   3369:                             }
                   3370:                         }
                   3371:                     }
                   3372:                 }
                   3373:             }
                   3374:         }
                   3375:         foreach my $oldclone (@$oldcloner) {
                   3376:             if (!grep(/^\Q$oldclone\E$/,@allowclone)) {
                   3377:                 if ($oldclone ne '*') {
                   3378:                     my ($uname,$udom) = split(/:/,$oldclone);
                   3379:                     if ($uname && $udom && $uname ne '*' ) {
                   3380:                         if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
                   3381:                             my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable');
                   3382:                             my %newclonecrs = ();
                   3383:                             if ($currclonecrs{'cloneable'} =~ /\Q$clone_crs\E/) {
                   3384:                                 if ($currclonecrs{'cloneable'} =~ /,/) {
                   3385:                                     my @currclonecrs = split/,/,$currclonecrs{'cloneable'};
                   3386:                                     foreach my $crs (@currclonecrs) {
                   3387:                                         if ($crs ne $clone_crs) {
                   3388:                                             $newclonecrs{'cloneable'} .= $crs.',';
                   3389:                                         }
                   3390:                                     }
                   3391:                                     $newclonecrs{'cloneable'} =~ s/,$//;
                   3392:                                 } else {
                   3393:                                     $newclonecrs{'cloneable'} = '';
                   3394:                                 }
                   3395:                                 &Apache::lonnet::put('environment',\%newclonecrs,$udom,$uname);
                   3396:                             }
                   3397:                         }
                   3398:                     }
                   3399:                 }
                   3400:             }
                   3401:         }
                   3402:     }
                   3403:     return;
                   3404: }
                   3405: 
1.1       raeburn  3406: 1;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.