# The LearningOnline Network with CAPA # Handler to set configuration settings for a course # # $Id: courseprefs.pm,v 1.33 2010/11/19 14:56:14 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA# # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # # ############################################################### ############################################################## =pod =head1 NAME courseprefs- Handler to set/modify course configuration =head1 SYNOPSIS courseprefs provides an interface for setting general course configuration =head1 DESCRIPTION This module is used for configuration of a course =head1 INTERNAL SUBROUTINES =over =item get_allitems() =item print_config_box() =item process_changes() =item get_sec_str() =item check_clone() =item store_changes() =item update_env() =item display_disallowed() =item get_course() =item get_jscript() =item cloners_javascript() =item print_courseinfo() =item new_cloners_dom_row() =item can_modify_catsettings() =item assign_course_categories() =item print_localization() =item get_lang_choices() =item print_feedback() =item user_table() =item select_recipient() =item select_sections() =item print_discussion() =item role_checkboxes() =item print_classlists() =item print_appearance() =item print_grading() =item print_printouts() =item print_spreadsheet() =item print_bridgetasks() =item print_other() =item get_other_items() =item item_table_row_start() =item item_table_row_end() =item yes_no_radio() =item select_from_options() =item make_item_rows() Creates table used to display and set course configuration items. Inputs: $cdom,$items,$ordered,$settings,$rowtotal,$crstype where $cdom is course's domain, $items is HASH ref for current config item, $ordered is ARRAY ref of items to include in row in display order, $settings is HASH ref of current values forrow, $rowtotal is SCALAR ref used to accumulate row count, $crstype is course type. Returns: $datatable HTML mark-up of data table which accumulates individual rows. =item nothidepriv_row() Creates row containing form elements used to display and set whether Domain coordinators who are currently included in advanced course user .db file for a course are to be hidden (e.g., in syllabus, or from course user lists). Inputs: $cdom,$item,$settings,$crstype where $cdom is course domain, item is nothideprivileged, $settings is HASH ref of the current values for nothideprivileged, $crstype is course type (Course or Community). Return: $datatable HTML mark-up for Privileged users (Domain Coordinators) in staff listing. =item print_hdrfmt_row() Creates row containing form elements used to display and set substitution items and text to be used in the header included on printouts. Inputs: $item,$settings where $item is print_header_format, and $settings is a HASH ref of the current values stored for print_header_format. Returns: $output HTML mark-up containing Javascript functions: reOrder() and getIndexByName() used to dynamically update position selectboxes, and HTML table elements for the "Print header format" row. =item position_selector() Creates a select box which can be used to reorder substitutions and text included in a printout header. Inputs: $pos,$num,$maxnum where $pos is current position, $num is the unique identifier, and $maxnum is the total number of items (both substitutions and text in the printout header. Returns: $output HTML mark-up for the selectbox and a hidden form element containing the current position. =item substitution_selector() Creates a combination of select box for choosing an item (student name, course ID or assignment note) to substitute, and a corresponding size limit in the header used for printouts. Inputs: $num,$subst,$limit,$crstype where $num is the unique identifier, $subst is the current substitution (n,c or a, for name, course or note respectively, $limit is the current size limit (integer), and $crstype is course type - course or community. Returns: $output HTML mark-up for selectbox and textbox (separate table cells). =item change_clone() Modifies the list of courses a user can clone (stored in the user's environment.db file), called when a change is made to the list of users allowed to clone a course. Inputs: $action,$cloner where $action is add or drop, and $cloner is identity of user for whom cloning ability is to be changed in course. Returns: nothing =back =cut package Apache::courseprefs; use strict; use Apache::Constants qw(:common :http); use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonconfigsettings; use Apache::lonlocal; use LONCAPA qw(:DEFAULT :match); sub handler { my $r=shift; if ($r->header_only) { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK; } my $context = 'course'; my $cid = $env{'request.course.id'}; my ($cnum,$cdom) = &get_course($cid); my $crstype = &Apache::loncommon::course_type(); my $parm_permission = &Apache::lonnet::allowed('opa',$cid); my $navmap = Apache::lonnavmaps::navmap->new(); if ($parm_permission && $navmap) { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; } else { if ($navmap) { if ($crstype eq 'Community') { $env{'user.error.msg'}= "/adm/courseprefs:opa:0:0:Cannot modify community settings"; } else { $env{'user.error.msg'}= "/adm/courseprefs:opa:0:0:Cannot modify course settings"; } } else { if ($crstype eq 'Community') { $env{'user.error.msg'}= "/adm/courseprefs::0:1:Course environment gone, reinitialize the community"; } else { $env{'user.error.msg'}= "/adm/courseprefs::0:1:Course environment gone, reinitialize the course"; } } return HTTP_NOT_ACCEPTABLE; } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['phase','actions','origin']); &Apache::lonhtmlcommon::clear_breadcrumbs(); if ($env{'form.origin'} eq 'params') { &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset", text=>"Parameter Manager"}); } my ($brtext,$brtitle,$crsinfotext,$crsinfodesc,$crscateg,$crshide); my %lt; if ($crstype eq 'Community') { %lt = ( conf => 'Community Configuration', edit => 'Edit Community Configuration', gens => 'General community settings', idnu => 'Community ID or number', desc => 'Community Description', ownr => 'Community Owner', cown => 'Community Co-owners', catg => 'Categorize community', excc => 'Exclude from community catalog', clon => 'Users allowed to clone community', rept => 'Replacement titles for standard community roles', time => 'Timezone where the community is located', date => 'Locale used for community calendar', coco => 'Community Content', copo => 'Community Policy', priv => 'Domain Coordinators in community', defd => 'Default dates for member access', stuv => 'Member-viewable membership list options', stul => 'Member agreement needed to be listed', clas => 'Membership and Facilitator Listing', priv => 'Privileged users (Domain Coordinators) in facilitator listing', defc => 'Default Community Spreadsheet', defs => 'Default User Spreadsheet', seme => 'Send message to member when clicking Done on Tasks' ); } else { %lt = ( conf => 'Course Configuration', edit => 'Edit Course Configuration', gens => 'General course settings', idnu => 'Course ID or number', desc => 'Course Description', ownr => 'Course Owner', cown => 'Course Co-owners', catg => 'Categorize course', excc => 'Exclude from course catalog', clon => 'Users allowed to clone course', rept => 'Replacement titles for standard course roles', time => 'Timezone in which the course takes place', date => 'Locale used for course calendar', coco => 'Course Content', copo => 'Course Policy', priv => 'Domain Coordinators in course', defd => 'Default dates for student access', stuv => 'Student-viewable classlist options', stul => 'Student agreement needed to be listed', clas => 'Classlists and Staff Listing', priv => 'Privileged users (Domain Coordinators) in staff listing', defc => 'Default Course Spreadsheet', defs => 'Default Student Spreadsheet', seme => 'Send message to student when clicking Done on Tasks', ); } &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs', text=>$lt{'conf'}}); my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs($lt{'edit'}); my $phase = 'pickactions'; if ( exists($env{'form.phase'}) ) { $phase = $env{'form.phase'}; } if ($phase eq 'categorizecourse') { &assign_course_categories($r,$crstype); return OK; } my %values=&Apache::lonnet::dump('environment',$cdom,$cnum); my @prefs_order = ('courseinfo','localization','feedback','discussion', 'classlists','appearance','grading','printouts', 'spreadsheet','bridgetasks','other'); my %prefs = ( 'courseinfo' => { text => $lt{'gens'}, help => 'Course_Environment', ordered => ['owner','co-owners','description','courseid', 'categories','hidefromcat','externalsyllabus', 'cloners','url','rolenames'], itemtext => { 'owner' => $lt{'ownr'}, 'co-owners' => $lt{'cown'}, 'description' => $lt{'desc'}, 'courseid' => $lt{'idnu'}, 'categories' => $lt{'catg'}, 'hidefromcat' => $lt{'excc'}, 'cloners' => $lt{'clon'}, 'externalsyllabus' => 'URL of Syllabus', 'url' => 'Top Level Map', 'rolenames' => $lt{'rept'}, }, }, 'localization' => { text => 'Language and Time Localization', help => 'Course_Environment', ordered => ['languages','timezone','datelocale'], itemtext => { languages => 'Languages used', timezone => $lt{'time'}, datelocale => $lt{'date'}, }, }, 'feedback' => { text => 'Feedback messages', help => 'Course_Environment', header => [{col1 => 'Questions about:', col2 => 'Recipients'}], ordered => ['question.email','comment.email','policy.email'], itemtext => { 'question.email' => 'Resource Content', 'comment.email' => $lt{'coco'}, 'policy.email' => $lt{'copo'}, }, }, 'discussion' => { text => 'Discussion and Chat', help => 'Course_Environment', ordered => ['pch.roles.denied','pch.users.denied', 'plc.roles.denied','plc.users.denied', 'allow_limited_html_in_feedback', 'allow_discussion_post_editing'], itemtext => { 'pch.roles.denied' => 'No Resource Discussion', 'pch.users.denied' => 'No Resource Discussion', 'plc.roles.denied' => 'No Chat room use', 'plc.users.denied' => 'No Chat room use', allow_limited_html_in_feedback => 'Allow limited HTML in discussion', allow_discussion_post_editing => 'Users can edit/delete own discussion posts', }, }, 'classlists' => { text => $lt{'clas'}, help => 'Course_Environment', header => [{col1 => 'Type', col2 => $lt{'defd'}}, {col1 => 'Setting', col2 => $lt{'priv'}}, {col1 => 'Setting', col2 => $lt{'stuv'}}], ordered => ['default_enrollment_start_date', 'default_enrollment_end_date', 'nothideprivileged','student_classlist_view', 'student_classlist_opt_in','student_classlist_portfiles'], itemtext => { default_enrollment_start_date => 'Start date', default_enrollment_end_date => 'End date', nothideprivileged => $lt{'priv'}, student_classlist_view => $lt{'stuv'}, student_classlist_opt_in => $lt{'stul'}, student_classlist_portfiles => 'Include link to accessible portfolio files', }, }, 'appearance' => { text => 'Display of resources ', help => 'Course_Environment', ordered => ['default_xml_style','pageseparators', 'disable_receipt_display','texengine', 'tthoptions'], itemtext => { default_xml_style => 'Default XML style file', pageseparators => 'Visibly Separate Items on Pages', disable_receipt_display => 'Disable display of problem receipts', texengine => 'Force use of a specific math rendering engine', tthoptions => 'Default set of options to pass to tth/m when converting TeX', }, }, 'grading' => { text => 'Grading', help => 'Course_Environment', ordered => ['grading','rndseed', 'receiptalg','disablesigfigs'], itemtext => { grading => 'Grading', rndseed => 'Randomization algorithm used', receiptalg => 'Receipt algorithm used', disablesigfigs => 'Disable checking of Significant Figures', }, }, 'printouts' => { text => 'Printout generation', help => 'Course_Environment', ordered => ['problem_stream_switch','suppress_tries', 'default_paper_size','print_header_format', 'disableexampointprint','canuse_pdfforms'], itemtext => { problem_stream_switch => 'Allow problems to be split over pages', suppress_tries => 'Suppress number of tries in printing', default_paper_size => 'Default paper type', print_header_format => 'Print header format', disableexampointprint => 'Disable automatically printing point values on exams', canuse_pdfforms => 'Users can print problems as PDF forms and upload later for grading', }, }, 'spreadsheet' => { text => 'Spreadsheets', help => 'Course_Environment', ordered => ['spreadsheet_default_classcalc', 'spreadsheet_default_studentcalc', 'spreadsheet_default_assesscalc','hideemptyrows'], itemtext => { spreadsheet_default_classcalc => $lt{'defc'}, spreadsheet_default_studentcalc => $lt{'defs'}, spreadsheet_default_assesscalc => 'Default Assessment Spreadsheet', hideemptyrows => 'Hide Empty Rows in Spreadsheets', }, }, 'bridgetasks' => { text => 'Bridge tasks', help => 'Course_Environment', ordered => ['task_messages','task_grading', 'suppress_embed_prompt'], itemtext => { task_messages => $lt{'seme'}, task_grading => 'Bridge Task grading by instructors and TAs in sections' , suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio', }, }, 'other' => { text => 'Other settings', help => 'Course_Environment', header => [ {col1 => 'Item', col2 => 'Value', }], }, ); if ($phase eq 'process') { my @allitems = &get_allitems(%prefs); &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context, \@prefs_order,\%prefs,\%values, $cnum,undef,\@allitems); } elsif ($phase eq 'display') { my $jscript = &get_jscript($cdom,$phase,$crstype); my @allitems = &get_allitems(%prefs); &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context, \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype); } else { &Apache::lonconfigsettings::display_choices($r,$phase,$context, \@prefs_order,\%prefs); } return OK; } sub get_allitems { my (%prefs) = @_; my @allitems; foreach my $item (keys(%prefs)) { if (ref($prefs{$item}) eq 'HASH') { if (ref($prefs{$item}{'ordered'}) eq 'ARRAY') { push(@allitems,@{$prefs{$item}{'ordered'}}); if ($item eq 'feedback') { push(@allitems,(map { $_.'.text'; } @{$prefs{$item}{'ordered'}})); } } } } return @allitems; } sub print_config_box { my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype) = @_; my $ordered = $item->{'ordered'}; my $itemtext = $item->{'itemtext'}; my $rowtotal = 0; my $output = '

'.&mt($item->{text}).'

 '. &Apache::loncommon::help_open_topic($item->{'help'}).''; if (($action eq 'feedback') || ($action eq 'classlists')) { $output .= ' '; if (exists $item->{'header'}->[0]->{'col1'} || exists $item->{'header'}->[0]->{'col2'}) { $output .= ' '; } $rowtotal ++; if ($action eq 'feedback') { $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal); } elsif ($action eq 'classlists') { $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype); } $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).' '.&mt($item->{'header'}->[0]->{'col2'}).'
'; $output .= ' '; if ($action eq 'classlists') { $output .= &print_classlists('middle',$cdom,$settings,$itemtext,\$rowtotal,$crstype). '
'.&mt($item->{'header'}->[1]->{'col1'}).''.&mt($item->{'header'}->[1]->{'col2'}).'
'; if (exists $item->{'header'}->[0]->{'col1'} || exists $item->{'header'}->[0]->{'col2'}) { $output .= ' '; } } } else { $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).' '.&mt($item->{'header'}->[0]->{'col2'}).'
'; if (exists $item->{'header'}->[0]->{'col1'} || exists $item->{'header'}->[0]->{'col2'}) { $output .= ' '; } } $rowtotal ++; if ($action eq 'courseinfo') { $output .= &print_courseinfo($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); } elsif ($action eq 'localization') { $output .= &print_localization($cdom,$settings,$ordered,$itemtext,\$rowtotal); } elsif ($action eq 'feedback') { $output .= &print_feedback('bottom',$cdom,$settings,$ordered,$itemtext,\$rowtotal); } elsif ($action eq 'discussion') { $output .= &print_discussion($cdom,$settings,$ordered,$itemtext,\$rowtotal); } elsif ($action eq 'classlists') { $output .= &print_classlists('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype); } elsif ($action eq 'appearance') { $output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); } elsif ($action eq 'grading') { $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); } elsif ($action eq 'printouts') { $output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); } elsif ($action eq 'spreadsheet') { $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); } elsif ($action eq 'bridgetasks') { $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); } elsif ($action eq 'other') { $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype); } $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).' '.&mt($item->{'header'}->[0]->{'col2'}).'
'; return ($output,$rowtotal); } sub process_changes { my ($cdom,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_; my %newvalues; if (ref($item) eq 'HASH') { if (ref($changes) eq 'HASH') { my @ordered; if ($action eq 'other') { @ordered = &get_other_items($cdom,$values,$allitems); if ($env{'form.newp_name'} ne '') { my $newp = $env{'form.newp_name'}; if ($env{'form.newp_value'} ne '') { if (ref($allitems) eq 'ARRAY') { unless ((grep(/^\Q$newp\E$/,@ordered)) || (grep(/^\Q$newp\E$/,@{$allitems}))) { $changes->{$newp} = $env{'form.newp_value'}; } } } } } elsif (ref($item->{'ordered'}) eq 'ARRAY') { @ordered = @{$item->{'ordered'}}; } if (@ordered > 0) { if ($action eq 'feedback') { foreach my $entry (@ordered) { my $userstr = ''; my $total = $env{'form.'.$entry.'_total'}; if ($total) { my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete'); for (my $i=0; $i<$total; $i++) { unless (grep(/^$i$/,@deletes)) { $userstr .= $env{'form.'.$entry.'_user_'.$i}. &get_sec_str($entry,$i).','; } } } else { $total = 0; } if ($env{'form.'.$entry.'_uname_'.$total} ne '') { my $uname = $env{'form.'.$entry.'_uname_'.$total}; my $udom = $env{'form.'.$entry.'_udom_'.$total}; if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') { $userstr =~ s/,$//; $disallowed->{'feedback'}{$entry} = $uname.':'.$udom; } else { $userstr .= $uname.':'.$udom.&get_sec_str($entry,$total); } } else { $userstr =~ s/,$//; } $newvalues{$entry} = $userstr; if ($newvalues{$entry} ne $values->{$entry}) { $changes->{$entry} = $newvalues{$entry}; } my $ext_entry = $entry.'.text'; $newvalues{$ext_entry} = $env{'form.'.$ext_entry}; if ($newvalues{$ext_entry} ne $values->{$ext_entry}) { $changes->{$ext_entry} = $newvalues{$ext_entry}; } } } else { foreach my $entry (@ordered) { if ($entry eq 'cloners') { if ($env{'form.cloners_all'}) { $newvalues{$entry} = '*'; } else { my @clonedoms; if (exists($env{'form.cloners_activate'})) { my $actnum = $env{'form.cloners_activate'}; if ($actnum ne '') { if ($env{'form.cloners_dom_'.$actnum} ne '') { my $clonedom = $env{'form.cloners_dom_'.$actnum}; if (&check_clone($clonedom,$disallowed) eq 'ok') { $newvalues{$entry} = '*:'.$clonedom; push(@clonedoms,$newvalues{$entry}); } } } } else { my $num = $env{'form.cloners_total'}; my @deletes = &Apache::loncommon::get_env_multiple('form.cloners_delete'); for (my $i=0; $i<$num; $i++) { if (!grep(/^$i$/,@deletes)) { my $clonedom = $env{'form.cloners_dom_'.$i}; if (&check_clone($clonedom,$disallowed) eq 'ok') { if (!grep(/^\*:\Q$clonedom\E$/,@clonedoms)) { push (@clonedoms,'*:'.$clonedom); } } } } if (@clonedoms) { $newvalues{$entry}=join(',',@clonedoms); } } if ($env{'form.cloners_newdom'} ne '') { my $clonedom = $env{'form.cloners_newdom'}; if (&check_clone($clonedom,$disallowed) eq 'ok') { my $newdom = '*:'.$env{'form.cloners_newdom'}; if (@clonedoms) { if (!grep(/^\Q$newdom\E$/,@clonedoms)) { $newvalues{$entry} .= ','.$newdom; } } else { $newvalues{$entry} = $newdom; } } } if ($env{'form.'.$entry} ne '') { my @cloners = split(',',$env{'form.'.$entry}); my @okcloners; foreach my $cloner (@cloners) { $cloner =~ s/^\s+//; $cloner =~ s/\s+$//; unless ($cloner eq '') { my ($uname,$udom) = split(':',$cloner); if (&check_clone($udom,$disallowed,$uname) eq 'ok') { if (!grep(/^\Q$cloner\E$/,@okcloners)) { push(@okcloners,$cloner); } } } } if (@okcloners) { my $okclonestr = join(',',@okcloners); if ($newvalues{$entry} ne '') { $newvalues{$entry} .= ','.$okclonestr; } else { $newvalues{$entry} = $okclonestr; } } } } if (ref($disallowed) eq 'HASH') { if (ref($disallowed->{'cloners'}) eq 'HASH') { foreach my $key (keys(%{$disallowed->{'cloners'}})) { $disallowed->{'cloners'}{$key} =~ s/,$//; } } } } elsif ($entry eq 'co-owners') { my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $coowners = $values->{'internal.co-owners'}; my @currcoown; if ($coowners) { @currcoown = split(',',$coowners); } if (&Apache::lonnet::is_course_owner($cdom,$cnum)) { my $autocoowner; if (($crstype eq 'Course') && ($values->{'internal.coursecode'})) { my %domconf = &Apache::lonnet::get_dom('configuration',['autoenroll'],$cdom); if (ref($domconf{'autoenroll'}) eq 'HASH') { $autocoowner = $domconf{'autoenroll'}{'co-owners'}; } } unless ($autocoowner) { my @keepcoowners = &Apache::loncommon::get_env_multiple('form.coowners'); my @pendingcoowners = &Apache::loncommon::get_env_multiple('form.pendingcoowners'); my @invitecoowners = &Apache::loncommon::get_env_multiple('form.invitecoowners'); if (@invitecoowners) { push(@pendingcoowners,@invitecoowners); } $newvalues{'pendingco-owners'} = join(',',sort(@pendingcoowners)); $newvalues{'co-owners'} = join(',',sort(@keepcoowners)); if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) { $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'}; push(@{$changes->{$entry}{'changed'}},'co-owners'); } if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) { $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'}; push(@{$changes->{$entry}{'changed'}},'pendingco-owners'); } } } else { my (@newpending,@newcoown); my $uname = $env{'user.name'}; my $udom = $env{'user.domain'}; my $pendingcoowners = $values->{'internal.pendingco-owners'}; my @pendingcoown = split(',',$pendingcoowners); if ($env{'form.pending_coowoner'}) { foreach my $item (@pendingcoown) { unless ($item eq $uname.':'.$udom) { push(@newpending,$item); } } @newcoown = @currcoown; if ($env{'form.pending_coowoner'} eq 'accept') { unless (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) { push(@newcoown,$uname.':'.$udom); } } } elsif ($env{'form.remove_coowoner'}) { foreach my $item (@currcoown) { unless ($item eq $uname.':'.$udom) { push(@newcoown,$item); } } if ($pendingcoowners ne '') { @newpending = @pendingcoown; } } $newvalues{'pendingco-owners'} = join(',',sort(@newpending)); $newvalues{'co-owners'} = join(',',sort(@newcoown)); if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) { $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'}; push(@{$changes->{$entry}{'changed'}},'co-owners'); } if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) { $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'}; push(@{$changes->{$entry}{'changed'}},'pendingco-owners'); } } } elsif ($entry =~ /^default_enrollment_(start|end)_date$/) { $newvalues{$entry}=&Apache::lonhtmlcommon::get_date_from_form($entry); } elsif ($entry eq 'rolenames') { my %adv_roles = &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1); my @stds; if ($crstype eq 'Community') { @stds = ('co'); } else { @stds = ('cc'); } push(@stds,('in','ta','ep','ad','st')); my (@replacements,@regulars); foreach my $role (@stds) { if ($values->{$role.'.plaintext'} ne '') { push(@replacements,$role); } else { push(@regulars,$role); } } foreach my $stdrole (@stds) { my $ext_entry = $entry.'_'.$stdrole; my $stdname = &Apache::lonnet::plaintext($stdrole,$crstype, $env{'request.course.id'},1); if ($env{'form.'.$ext_entry} eq $stdname) { $newvalues{$ext_entry} = ''; } else { $newvalues{$ext_entry} = $env{'form.'.$ext_entry}; } if ($newvalues{$ext_entry} ne $values->{$stdrole.'.plaintext'}) { my $dupname = 0; if ($newvalues{$ext_entry} ne '') { if (grep(/^\Q$newvalues{$ext_entry}\E$/,@replacements)) { $dupname = 1; push(@{$disallowed->{'rolenames'}{'replacements'}},$newvalues{$ext_entry}); } if (!$dupname) { if (grep(/^\Q$newvalues{$ext_entry}\E$/,@regulars)) { $dupname = 1; push(@{$disallowed->{rolenames}{'regulars'}},$newvalues{$ext_entry}); } } if (!$dupname) { foreach my $role (keys(%adv_roles)) { if ($role =~ m{^cr/$match_domain/$match_name/\Q$newvalues{$ext_entry}\E$}) { $dupname = 1; push(@{$disallowed->{rolenames}{'customrole'}},$newvalues{$ext_entry}); last; } } } } if (!$dupname) { $changes->{$ext_entry} = $newvalues{$ext_entry}; } } } } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied')) { my @denied = &Apache::loncommon::get_env_multiple('form.'.$entry); @denied = sort(@denied); my $deniedstr = ''; if (@denied > 0) { $deniedstr = join(',',@denied); } $newvalues{$entry} = $deniedstr; } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied')) { my $total = $env{'form.'.$entry.'_total'}; my $userstr = ''; my @denied; if ($total > 0) { my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete'); for (my $i=0; $i<$total; $i++) { unless (grep(/^$i$/,@deletes)) { $userstr .= $env{'form.'.$entry.'_user_'.$i}.','; push(@denied,$env{'form.'.$entry.'_user_'.$i}); } } } else { $total = 0; } if ($env{'form.'.$entry.'_uname_'.$total} ne '') { my $uname = $env{'form.'.$entry.'_uname_'.$total}; my $udom = $env{'form.'.$entry.'_udom_'.$total}; if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') { $userstr =~ s/,$//; $disallowed->{'discussion'}{$entry} = $uname.':'.$udom; } else { my $newuser .= $uname.':'.$udom; if (grep(/^\Q$newuser\E$/,@denied)) { $userstr =~ s/,$//; } else { $userstr .= $newuser; } } } else { $userstr =~ s/,$//; } $newvalues{$entry} = $userstr; } elsif ($entry eq 'allow_discussion_post_editing') { my @canedit = &Apache::loncommon::get_env_multiple('form.'.$entry); @canedit = sort(@canedit); foreach my $role (@canedit) { my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$role); if ((grep(/^\s*$/,@secs)) || (@secs == 0)) { $newvalues{$entry} .= $role.','; } else { foreach my $sec (@secs) { $newvalues{$entry} .= $role.':'.$sec.','; } } } $newvalues{$entry} =~ s/,$//; } elsif ($entry eq 'nothideprivileged') { my @curr_nothide; my @new_nothide; if ($values->{$entry} ne '') { foreach my $user (split(/\s*\,\s*/,$values->{$entry})) { my $nothide; if ($user !~ /:/) { $nothide = join(':',split(/[\@]/,$user)); } else { $nothide = $user; } if ((defined($nothide)) && (!grep(/^\Q$nothide\E$/,@curr_nothide))) { push(@curr_nothide,$nothide); } } } foreach my $key (keys(%env)) { if ($key =~ /^form\.\Q$entry\E_($match_username:$match_domain)$/) { if ($env{$key}) { my $nothide = $1; if (!grep(/^\Q$nothide\E$/,@new_nothide)) { push(@new_nothide,$nothide); } } } } @new_nothide = sort(@new_nothide); my @differences = &Apache::loncommon::compare_arrays(\@curr_nothide, \@new_nothide); if (@differences > 0) { if (@new_nothide > 0) { $newvalues{$entry} = join(',',@new_nothide); } else { $newvalues{$entry} = ''; } } else { $newvalues{$entry} = $values->{$entry}; } } elsif ($entry eq 'print_header_format') { my $maxnum = $env{'form.printfmthdr_maxnum'}; my @newhdr; if ($maxnum > 2) { for (my $i=0; $i<$maxnum-2; $i++) { if ($env{'form.printfmthdr_del_'.$i}) { $newhdr[$env{'form.printfmthdr_pos_'.$i}] = ''; } else { my $hdr; if ($env{'form.printfmthdr_sub_'.$i} =~ /^[nca]$/) { $hdr = '%'; if ($env{'form.printfmthdr_limit_'.$i} =~ /^\d+$/) { $hdr .= $env{'form.printfmthdr_limit_'.$i}; } $hdr .= $env{'form.printfmthdr_sub_'.$i}; } elsif ($env{'form.printfmthdr_text_'.$i} ne '') { $hdr = $env{'form.printfmthdr_text_'.$i}; } $newhdr[$env{'form.printfmthdr_pos_'.$i}] = $hdr; } } } my $newsub = $maxnum-2; if ($env{'form.printfmthdr_sub_'.$newsub} =~ /^[nca]$/) { my $hdr = '%'; if ($env{'form.printfmthdr_limit_'.$newsub} =~ /^\d+$/) { $hdr .= $env{'form.printfmthdr_limit_'.$newsub}; } $hdr .= $env{'form.printfmthdr_sub_'.$newsub}; $newhdr[$env{'form.printfmthdr_pos_'.$newsub}] = $hdr; } my $newtext = $maxnum-1; $newhdr[$env{'form.printfmthdr_pos_'.$newtext}] = $env{'form.printfmthdr_text_'.$newtext}; $newvalues{$entry} = join('',@newhdr); } elsif ($entry eq 'languages') { my $langstr; my $total = $env{'form.'.$entry.'_total'}; if ($total) { my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete'); for (my $i=0; $i<$total; $i++) { unless (grep(/^$i$/,@deletes)) { $langstr .= $env{'form.'.$entry.'_'.$i}.','; } } } else { $total = 0; } if ($env{'form.'.$entry.'_'.$total} ne '') { my $newlang = $env{'form.'.$entry.'_'.$total}; my %langchoices = &get_lang_choices(); if ($langchoices{$newlang}) { $langstr .= $newlang; } else { $langstr =~ s/,$//; $disallowed->{'localization'}{$entry} = $newlang; } } else { $langstr =~ s/,$//; } $newvalues{$entry} = $langstr; } else { $newvalues{$entry} = $env{'form.'.$entry}; } unless ($entry eq 'co-owners') { if ($newvalues{$entry} ne $values->{$entry}) { $changes->{$entry} = $newvalues{$entry}; } } } } } } } return; } sub get_sec_str { my ($entry,$num) = @_; my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$num); my $secstr; if (grep(/^\s*$/,@secs)) { $secstr = ''; } elsif (@secs > 0) { $secstr = join(';',@secs); } if ($secstr ne '') { return '('.$secstr.')'; } return; } sub check_clone { my ($clonedom,$disallowed,$clonename) = @_; return if (ref($disallowed) ne 'HASH'); if ($clonedom !~ /^$match_domain$/) { $disallowed->{'cloners'}{'format'} .= $clonedom.','; return; } elsif (!&Apache::lonnet::domain($clonedom)) { $disallowed->{'cloners'}{'domain'} .= $clonedom.','; return; } if ($clonename ne '') { if ($clonename !~ /^$match_username$/) { $disallowed->{'cloners'}{'format'} .= $clonename.':'.$clonedom.','; return; } else { if (&Apache::lonnet::homeserver($clonename,$clonedom) eq 'no_host') { $disallowed->{'cloners'}{'newuser'} .= $clonename.':'.$clonedom.','; return; } } } return 'ok'; } sub store_changes { my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_; my ($chome,$output); my (%storehash,@delkeys,@need_env_update,@oldcloner); if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) { %storehash = %{$values}; } else { if ($crstype eq 'Community') { $output = &mt('No changes made to community settings.'); } else { $output = &mt('No changes made to course settings.'); } return $output; } my %yesno = ( hidefromcat => '1', problem_stream_switch => '1', suppress_tries => '1', disableexampointprint => '1', hideemptyrows => '1', suppress_embed_prompt => '1', ); foreach my $item (@{$prefs_order}) { if (grep(/^\Q$item\E$/,@{$actions})) { $output .= '

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

'; if (ref($changes->{$item}) eq 'HASH') { if (keys(%{$changes->{$item}}) > 0) { $output .= &mt('Changes made:').''; } else { if ($crstype eq 'Community') { $output = &mt('No changes made to community settings.'); } else { $output = &mt('No changes made to course settings.'); } } } } } if (&Apache::lonnet::put('environment',\%storehash,$cdom,$cnum) eq 'ok') { if (ref($changes) eq 'HASH') { if (ref($changes->{'courseinfo'}) eq 'HASH') { if (exists($changes->{'courseinfo'}{'cloners'})) { &change_clone($cdom,$cnum,$changes->{'courseinfo'}{'cloners'}, \@oldcloner); } } } if (@delkeys) { if (&Apache::lonnet::del('environment',\@delkeys,$cdom,$cnum) ne 'ok') { $output .= '
'; if ($crstype eq 'Community') { $output .= &mt('An error occurred when removing community settings which are no longer in use.'); } else { $output .= &mt('An error occurred when removing course settings which are no longer in use.'); } $output .= ''; } else { foreach my $key (@delkeys) { &Apache::lonnet::delenv('course.'.$cdom.'_'.$cnum.'.'.$key); } } } if (@need_env_update) { $chome = &Apache::lonnet::homeserver($cnum,$cdom); &update_env($cnum,$cdom,$chome,\@need_env_update,\%storehash); } &Apache::lonnet::coursedescription($env{'request.course.id'}, {'freshen_cache' => 1}); } else { $output = ''; if ($crstype eq 'Community') { $output .= &mt('An error occurred when saving changes to community settings, which remain unchanged.'); } else { $output .= &mt('An error occurred when saving changes to course settings, which remain unchanged.'); } $output .= ''; } return $output; } sub update_env { my ($cnum,$cdom,$chome,$need_env_update,$storehash) = @_; my $count = 0; if ((ref($need_env_update) eq 'ARRAY') && (ref($storehash) eq 'HASH')) { my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.'); if (ref($crsinfo{$env{'request.course.id'}}) eq 'HASH') { foreach my $key (@{$need_env_update}) { if ($key eq 'description' && defined($storehash->{$key})) { &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.description' => $storehash->{$key}}); $crsinfo{$env{'request.course.id'}}{'description'} = $storehash->{$key}; $count ++; } elsif (($key eq 'cloners') || ($key eq 'hidefromcat') || ($key eq 'categories')) { &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash->{$key}}); $crsinfo{$env{'request.course.id'}}{$key} = $storehash->{$key}; $count ++; } elsif ($key eq 'co-owners') { if ($storehash->{'internal.co-owners'} ne '') { &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.co-owners' => $storehash->{'internal.co-owners'}}); } if ($storehash->{'internal.pendingco-owners'} ne '') { &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.pendingco-owners' => $storehash->{'internal.pendingco-owners'}}); } my @coowners = split(',',$storehash->{'internal.'.$key}); $crsinfo{$env{'request.course.id'}}{'co-owners'} = \@coowners; $count ++; } } if ($count) { my $putresult = &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime'); } } } return; } sub display_disallowed { my ($item,$disallowed,$prefs,$crstype) = @_; my $output; if ((ref($disallowed) eq 'HASH') && (ref($prefs) eq 'HASH')) { if (keys(%{$disallowed})) { if ($item eq 'cloners') { my @fails; my %lt = &Apache::lonlocal::texthash ( format => 'Invalid format', domain => 'Domain does not exist', newuser => 'LON-CAPA user(s) do(es) not exist.', ); foreach my $error ('format','domain','newuser') { if (defined($disallowed->{$error})) { my $msg = ''.$disallowed->{$error}.', '.&mt('reason').' - '. $lt{$error}; if ($error eq 'newuser') { $msg .= '
'.&mt("Please [_1]add the user(s)[_2] before returning to the [_3]$crstype Configuration[_2] to add as potential cloners.",'','',''); } push(@fails,$msg); } } if (@fails) { $output .= ''.&mt('Unable to add to allowed cloners: '). ''.join(';  ',@fails).'.
'; } } elsif ($item eq 'rolenames') { my %lt = &Apache::lonlocal::texthash ( replacements => 'Name already used to replace a different standard role name', regulars => 'Name already used as a standard role name', customrole => 'Name already used as the name of a custom role', ); my @fails; foreach my $error ('replacements','regulars','customrole') { if (ref($disallowed->{$error}) eq 'ARRAY') { push(@fails,''.join(', ',@{$disallowed->{$error}}). ', '.&mt('reason').' - '.$lt{'error'}); } } if (@fails) { $output .= ''. &mt('Unable to include amongst replacements for role names: '). ''.join(';  ',@fails).'.
'; } } elsif (($item eq 'feedback') || ($item eq 'discussion') || ($item eq 'localization')) { $output .= ''; if ($item eq 'feedback') { if ($crstype eq 'Community') { $output .= &mt('Unable to include as a recipient of community feedback for:'); } else { $output .= &mt('Unable to include as a recipient of course feedback for:'); } } elsif ($item eq 'discussion') { $output .= &mt('Unable to include in user-based access control for:'); } elsif ($item eq 'localization') { if ($crstype eq 'Community') { $output .= &mt('Unable to include in community localization:'); } else { $output .= &mt('Unable to include in course localization:'); } } $output .= '
'; } } } return $output; } sub get_course { my ($courseid) = @_; if (!defined($courseid)) { $courseid = $env{'request.course.id'}; } my $cdom=$env{'course.'.$courseid.'.domain'}; my $cnum=$env{'course.'.$courseid.'.num'}; return ($cnum,$cdom); } sub get_jscript { my ($cdom,$phase,$crstype) = @_; my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype); my ($jscript,$categorize_js); my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript(); my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset'); my $cloners_js = &cloners_javascript($phase); if ($can_categorize) { $categorize_js = <'. "\n".$stubrowse_js."\n"; return $jscript; } sub cloners_javascript { my ($formname) = @_; return <<"ENDSCRIPT"; function update_cloners(caller,num) { var delidx = getIndexByName('cloners_delete'); var actidx = getIndexByName('cloners_activate'); if (caller == 'cloners_all') { var selall; for (var i=0; i{'categories'},$crstype)."\n"; } } if (ref($domconf{'autoenroll'}) eq 'HASH') { $autocoowner = $domconf{'autoenroll'}{'co-owners'}; } if (!defined($categoriesform)) { $categoriesform = &mt('No categories defined in this domain.'); } my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype); my $replace; if ($crstype eq 'Community') { $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank'); } else { $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank'); } my %items = ( 'url' => { text => ''.&mt($itemtext->{'url'}).''.(' 'x2). '
". &mt('Select Map').'
'. &mt('Modification may make assessment data inaccessible!'). '', input => 'textbox', size => '40', advanced => 1 }, 'description' => { text => ''.&mt($itemtext->{'description'}).'', input => 'textbox', size => '25', }, 'owner' => { text => ''.&mt($itemtext->{'owner'}).'', }, 'co-owners' => { text => ''.&mt($itemtext->{'co-owners'}).'', }, 'courseid' => { text => ''.&mt($itemtext->{'courseid'}).'
'.'('. &mt('internal, optional').')', input => 'textbox', size => '25', }, 'cloners' => { text => ''.&mt($itemtext->{'cloners'}).'
'. &mt('Owner and Coordinators included automatically'), input => 'textbox', size => '40', advanced => 1 }, 'rolenames' => { text => ''.&mt($itemtext->{'rolenames'}).'
'. '('.$replace.')', input => 'textbox', size => '20', advanced => 1 }, 'externalsyllabus' => { text => ''.&mt($itemtext->{'externalsyllabus'}).'
('. &mt('not using syllabus template)'), input => 'textbox', size => '40', }, 'hidefromcat' => { text => ''.&mt($itemtext->{'hidefromcat'}).'
'. ' ('.&mt('included by default if assigned institutional code, or categorized').')', input => 'radio', }, 'categories' => { text => ''.&mt($itemtext->{'categories'}).' '. &mt('Display Categories').'', input => 'textbox', size => '25', }, ); my $datatable; my $count = 0; foreach my $item (@{$ordered}) { if ($item eq 'hidefromcat') { next if (!$can_toggle_cat); } elsif ($item eq 'categories') { next if (!$can_categorize); } $count ++; if (exists $items{$item}{advanced} && $items{$item}{advanced} == 1) { $datatable .= &item_table_row_start($items{$item}{text},$count,"advanced"); } else { $datatable .= &item_table_row_start($items{$item}{text},$count); } if ($items{$item}{input} eq 'radio') { $datatable .= &yesno_radio($item,$settings); } elsif ($item eq 'cloners') { my $includeempty = 1; my $num = 0; $datatable .= &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_row(). ''. (' 'x2).'{$item} ne '*') { $datatable .= ' checked="checked" '; } $datatable .= ' onchange="javascript:update_cloners('. "'cloners_all'".');"/>'.&mt('No').''. &Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(). '
'.&mt('Or'). '
'. &Apache::loncommon::start_data_table(); my @cloners; if ($settings->{$item} eq '') { $datatable .= &new_cloners_dom_row($cdom,'0'); } elsif ($settings->{$item} ne '*') { my @entries = split(/,/,$settings->{$item}); if (@entries > 0) { foreach my $entry (@entries) { my ($uname,$udom) = split(/:/,$entry); if ($udom =~ /^$match_domain$/) { unless (&Apache::lonnet::domain($udom)) { next; } } else { next; } if ($uname eq '*') { $datatable .= &Apache::loncommon::start_data_table_row(). ''. &mt('Any user in domain:').' '.$udom. '
'. ''. &Apache::loncommon::end_data_table_row(); $num ++; } elsif (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') { unless (grep(/^\Q$entry\E$/,@cloners)) { push(@cloners,$entry); } } } } } my $add_domtitle = &mt('Any user in additional domain:'); if ($settings->{$item} eq '*') { $add_domtitle = &mt('Any user in specific domain:'); } elsif ($settings->{$item} eq '') { $add_domtitle = &mt('Any user in other domain:'); } my $cloners_str = join(',',@cloners); $datatable .= &Apache::loncommon::start_data_table_row(). ''. $add_domtitle.'
'. &Apache::loncommon::select_dom_form('','cloners_newdom', $includeempty). ''. ''.&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(). '
'.&mt('And'). '
'. &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_row(). ''. &mt('Specific users').' ('. &mt('user:domain,user:domain').')
'. &Apache::lonhtmlcommon::textbox($item,$cloners_str, $items{$item}{'size'}). ''.&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); } elsif ($item eq 'rolenames') { $datatable .= &Apache::loncommon::start_data_table(); my @roles; if ($crstype eq 'Community') { @roles = ('co'); } else { @roles = ('cc'); } push (@roles,('in','ta','ep','ad','st')); foreach my $role (@roles) { $datatable .= &Apache::loncommon::start_data_table_row(). ''. &Apache::lonnet::plaintext($role,$crstype,undef,1). ''. &Apache::lonhtmlcommon::textbox('rolenames_'.$role, $settings->{$role.'.plaintext'}, $items{$item}{size}).''. &Apache::loncommon::end_data_table_row(); } $datatable .= &Apache::loncommon::end_data_table().''; } elsif ($item eq 'categories') { my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";'; $datatable .= ''. &Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item}, $items{$item}{size},$launcher); } elsif ($item eq 'owner') { my $owner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'}; if ($owner =~ /:/) { my ($ownername,$ownerdom) = split(':',$owner); $owner = &Apache::loncommon::plainname($ownername,$ownerdom); } elsif ($owner ne '') { $owner = &Apache::loncommon::plainname($owner,$cdom); } else { $owner = &mt('None specified'); } my $domdesc = &Apache::lonnet::domain($cdom,'description'); $datatable .= $owner; } elsif ($item eq 'co-owners') { my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $coowners = $env{'course.'.$env{'request.course.id'}.'.internal.co-owners'}; my @currcoown; if ($coowners) { @currcoown = split(',',$coowners); } if (&Apache::lonnet::is_course_owner($cdom,$cnum)) { if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) { $datatable .= &show_autocoowners(@currcoown); } else { $datatable .= &coowner_invitations($cnum,$cdom,@currcoown); } } else { if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) { $datatable .= &show_autocoowners(@currcoown); } else { $datatable .= &manage_coownership($cnum,$cdom,@currcoown); } } } else { $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size}); } $datatable .= &item_table_row_end(); } $$rowtotal += scalar(@{$ordered}); return $datatable; } sub new_cloners_dom_row { my ($newdom,$num) = @_; my $output; if ($newdom ne '') { $output .= &Apache::loncommon::start_data_table_row(). ''. &mt('Any user in domain:').' '.$newdom.''. (' 'x2).''.(' 'x2). ''. &Apache::loncommon::end_data_table_row(); } return $output; } sub can_modify_catsettings { my ($dom,$crstype) = @_; my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom); my ($can_toggle_cat,$can_categorize); if (ref($domconf{'coursecategories'}) eq 'HASH') { if ($crstype eq 'Community') { if ($domconf{'coursecategories'}{'togglecatscomm'} eq 'comm') { $can_toggle_cat = 1; } if ($domconf{'coursecategories'}{'categorizecomm'} eq 'comm') { $can_categorize = 1; } } else { if ($domconf{'coursecategories'}{'togglecats'} eq 'crs') { $can_toggle_cat = 1; } if ($domconf{'coursecategories'}{'categorize'} eq 'crs') { $can_categorize = 1; } } } return ($can_toggle_cat,$can_categorize); } sub assign_course_categories { my ($r,$crstype) = @_; my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $hascats = 0; my $cathash; my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom); if (ref($domconf{'coursecategories'}) eq 'HASH') { $cathash = $domconf{'coursecategories'}{'cats'}; if (ref($cathash) eq 'HASH') { foreach my $cat (keys(%{$cathash})) { next if ($cat eq 'instcode::0'); unless ($crstype eq 'Community') { next if ($cat eq 'communities::0'); } $hascats ++; } } } my $catwin_js; if ($hascats) { my $alert; if ($crstype eq 'Community') { $alert = &mt("Use 'Save' in the main window to save community categories"); } else { $alert = &mt("Use 'Save' in the main window to save course categories"); } $catwin_js = < function updateCategories() { var newcategories = ''; var unescapedcats = ''; if (document.chgcats.usecategory.length) { for (var i=0; i 0) { newcategories = newcategories.slice(0,-1); } if (unescapedcats.length > 0) { unescapedcats = unescapedcats.slice(0,-3); } } else { if (document.chgcats.usecategory.checked == true) { newcategories = document.chgcats.usecategory.value; unescapedcats = document.chgcats.catname.value; } } opener.document.display.categories.value = newcategories; opener.document.display.categories_display.value = unescapedcats; alert("$alert"); self.close(); return; } ENDSCRIPT } else { my $onload; } my ($crscat,$catcrs,$assign); if ($crstype eq 'Community') { $crscat = 'Community Categories'; $catcrs = &mt('Categorize Community'); $assign = &mt('Assign one or more categories to this community.') } else { $crscat = 'Course Categories'; $catcrs = &mt('Categorize Course'); $assign = &mt('Assign one or more categories to this course.') } my $start_page = &Apache::loncommon::start_page($crscat,$catwin_js, {'only_body' => 1,}); my $end_page = &Apache::loncommon::end_page(); my $categoriesform = '

'.$catcrs.'

'; if ($hascats) { my %currsettings = &Apache::lonnet::get('environment',['hidefromcat','categories'],$cdom,$cnum); my $cattable = &Apache::loncommon::assign_categories_table($cathash, $currsettings{'categories'},$crstype); if ($cattable eq '') { $categoriesform .= &mt('No suitable categories defined for this course type in this domain.'); } else { $categoriesform .= $assign.'

'. '
'."\n". $cattable."\n". '

'; } } else { $categoriesform .= &mt('No categories defined in this domain.'); } $r->print($start_page.$categoriesform.$end_page); return; } sub show_autocoowners { my (@currcoown) = @_; my $output = ''.&mt('Co-ownership is set automatically when a Course Coordinator role is assigned to official course personnel (from institutional data).').''; if (@currcoown > 0) { $output .= '
'.&mt('Current co-owners are:').' '. join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown)); } else { $output .= '
'.&mt('Currently no co-owners.'); } return $output; } sub coowner_invitations { my ($cnum,$cdom,@currcoown) = @_; my ($output,@pendingcoown,@othercoords); my $pendingcoowners = $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'}; if ($pendingcoowners) { @pendingcoown = split(',',$pendingcoowners); } my $ccrole = 'cc'; my %ccroles = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,undef,[$ccrole]); foreach my $key (sort(keys(%ccroles))) { my ($ccname,$ccdom,$role) = split(':',$key); next if ($key eq $env{'user.name'}.':'.$env{'user.domain'}.':'.$ccrole); unless (grep(/^\Q$ccname\E:\Q$ccdom\E$/,@currcoown,@pendingcoown)) { push(@othercoords,$ccname.':'.$ccdom); } } my $coowner_rows = @currcoown + @pendingcoown + @othercoords; if ($coowner_rows) { $output .= &Apache::loncommon::start_data_table(); if (@currcoown) { $output .= &Apache::loncommon::start_data_table_row(). ''.&mt('Current co-owners').''; foreach my $person (@currcoown) { my ($co_uname,$co_dom) = split(':',$person); $output .= ''.(' 'x2).' '; } $output .= ''. &Apache::loncommon::end_data_table_row(); } if ($pendingcoowners) { $output .= &Apache::loncommon::start_data_table_row(). ''.&mt('Invited as co-owners [_1](agreement pending)','
').'
'; foreach my $person (@pendingcoown) { my ($co_uname,$co_dom) = split(':',$person); $output .= ''.(' 'x2).' '; } $output .= ''. &Apache::loncommon::end_data_table_row(); } if (@othercoords) { $output .= &Apache::loncommon::start_data_table_row(). ''.&mt('Invite other Coordinators [_1]to become co-owners','
').'
'; foreach my $person (@othercoords) { my ($co_uname,$co_dom) = split(':',$person); $output .= ''.(' 'x2).' '; } $output .= ''. &Apache::loncommon::end_data_table_row(); } $output .= &Apache::loncommon::end_data_table(); } else { $output = &mt('There are no coordinators to select as co-owners'); } return $output; } sub manage_coownership { my ($cnum,$cdom,@currcoown) = @_; my (@pendingcoown); my $pendingcoowners = $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'}; if ($pendingcoowners) { @pendingcoown = split(',',$pendingcoowners); } my ($is_coowner,$is_pending,$output); my $uname = $env{'user.name'}; my $udom = $env{'user.domain'}; if (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) { $is_coowner = 1; } if (grep(/^\Q$uname\E:\Q$udom\E$/,@pendingcoown)) { $is_pending = 1; } if (@currcoown && ($is_coowner || $is_pending)) { $output = &Apache::loncommon::start_data_table(); } if (@currcoown) { if ($is_coowner || $is_pending) { $output .= &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_row().''; } $output .= &mt('Current co-owners are:').' '. join(', ', map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown)); if ($is_coowner || $is_pending) { $output .= ''.&Apache::loncommon::end_data_table_row(); } } if ($is_coowner || $is_pending) { if (@currcoown) { $output .= &Apache::loncommon::start_data_table_row().''; } $output .= ''; if ($is_coowner) { $output .= &mt('You are currently a co-owner:').' '; } else { $output .= &mt('The course owner has invited you to become a co-owner:').' '.(' 'x2). ''; } $output .= ''; if (@currcoown) { $output .= ''.&Apache::loncommon::end_data_table_row(); } } if (@currcoown && ($is_coowner || $is_pending)) { $output .= &Apache::loncommon::end_data_table(); } return $output; } sub print_localization { my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my %items = ( languages => { text => ''.&mt($itemtext->{'languages'}).'
'. &mt("(overrides individual user preference)"), input => 'selectbox', }, timezone => { text => ''.&mt($itemtext->{'timezone'}).'', input => 'selectbox', }, datelocale => { text => ''.&mt($itemtext->{'datelocale'}).'', input => 'selectbox', }, ); my $datatable; my $count = 0; foreach my $item (@{$ordered}) { $count ++; $datatable .= &item_table_row_start($items{$item}{text},$count); if ($item eq 'timezone') { my $includeempty = 1; my $timezone = &Apache::lonlocal::gettimezone(); $datatable .= &Apache::loncommon::select_timezone($item,$timezone,undef, $includeempty); } elsif ($item eq 'datelocale') { my $includeempty = 1; my $locale_obj = &Apache::lonlocal::getdatelocale(); my $currdatelocale; if (ref($locale_obj)) { $currdatelocale = $locale_obj->id(); } $datatable .= &Apache::loncommon::select_datelocale($item,$currdatelocale, undef,$includeempty); } else { if ($settings->{$item} eq '') { $datatable .= &Apache::loncommon::select_language('languages_0','',1); } else { my $num = 0; my @languages = split(/\s*[,;:]\s*/,$settings->{$item}); $datatable .= &Apache::loncommon::start_data_table(); if (@languages > 0) { my %langchoices = &get_lang_choices(); foreach my $lang (@languages) { my $showlang = $lang; if (exists($langchoices{$lang})) { $showlang = $langchoices{$lang}; } $datatable .= &Apache::loncommon::start_data_table_row(). ''. &mt('Language:').' '.$showlang. '
'. ''. &Apache::loncommon::end_data_table_row(); $num ++; } } $datatable .= &Apache::loncommon::start_data_table_row(). ''. &mt('Additional language:'). '
'. &Apache::loncommon::select_language('languages_'.$num,'',1). ''. ''.&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); } } $datatable .= &item_table_row_end(); } $$rowtotal += scalar(@{$ordered}); return $datatable; } sub get_lang_choices { my %langchoices; foreach my $id (&Apache::loncommon::languageids()) { my $code = &Apache::loncommon::supportedlanguagecode($id); if ($code) { $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id); } } return %langchoices; } sub print_feedback { my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my %items = ( 'question.email' => { text => ''.&mt($itemtext->{'question.email'}).'', input => 'textbox', size => '50', }, 'comment.email' => { text => ''.&mt($itemtext->{'comment.email'}).'', input => 'textbox', size => '50', }, 'policy.email' => { text => ''.&mt($itemtext->{'policy.email'}).'', input => 'textbox', size => '50', }, ); my $datatable; my $count = 0; my ($cnum) = &get_course(); my %sections = &Apache::loncommon::get_sections($cdom,$cnum); my @sections = sort( { $a <=> $b } keys(%sections)); my %lt = &Apache::lonlocal::texthash ( currone => 'Current recipient:', currmult => 'Current recipients:', add => 'Additional recipient:', del => 'Delete?', sec => 'Sections:', ); foreach my $item (@{$ordered}) { $count ++; if ($position eq 'top') { $datatable .= &item_table_row_start($items{$item}{text},$count); } else { $datatable .= &item_table_row_start($items{$item}{text}."
(Custom text)",$count, "advanced"); } if ($position eq 'top') { my $includeempty = 0; $datatable .= &user_table($cdom,$item,\@sections, $settings->{$item},\%lt); } else { $datatable .= &Apache::lonhtmlcommon::textbox($item.'.text', $settings->{$item.'.text'},$items{$item}{size}); } $datatable .= &item_table_row_end(); } $$rowtotal += scalar(@{$ordered}); return $datatable; } sub user_table { my ($cdom,$item,$sections,$currvalue,$lt) = @_; my $output; if ($currvalue eq '') { $output .= &select_recipient($item,'0',$cdom,$sections); } else { my $num = 0; my @curr = split(/,/,$currvalue); $output .= ''; my ($currusers); foreach my $val (@curr) { next if ($val eq ''); my ($uname,$udom,$seclist) = ($val =~ /^($match_username):($match_domain)(\(?[^\)]*\)?)$/); my @selsec; if ($seclist) { $seclist =~ s/(^\(|\)$)//g; @selsec = split(/\s*;\s*/,$seclist); } $currusers .= ''. ''; $num ++; } if ($num) { $output .= ''. ''. ''; } $output .= ''. '
'. ''. ''.(' 'x2). &Apache::loncommon::aboutmewrapper( &Apache::loncommon::plainname($uname,$udom,'firstname'), $uname,$udom,'aboutuser'); if (ref($sections) eq 'ARRAY') { if (@{$sections}) { $currusers.= (' 'x3).$lt->{'sec'}.' '. &select_sections($item,$num,$sections, \@selsec); } } $currusers .= '
'; if ($num == 1) { $output .= $lt->{'currone'}; } else { $output .= $lt->{'currmult'}; } $output .= '
'. ''.$currusers.'
'. $lt->{'add'}.'
'. &select_recipient($item,$num,$cdom,$sections). ''. '
'; } return $output; } sub select_recipient { my ($item,$num,$cdom,$sections,$selected,$includeempty) = @_; my $domform = &Apache::loncommon::select_dom_form($cdom,$item.'_udom_'.$num,$includeempty); my $selectlink = &Apache::loncommon::selectstudent_link('display',$item.'_uname_'.$num, $item.'_udom_'.$num,1); my $output = ''. ''; if (ref($sections) eq 'ARRAY') { if (@{$sections}) { $output .= ''; } } $output .= '
'.&mt('Username').'
'. '
'.&mt('Domain').'
'.$domform.'
'.&mt('Sections').'
'. &select_sections($item,$num,$sections,$selected).'
'. $selectlink.'
'; return $output; } sub select_sections { my ($item,$num,$sections,$selected) = @_; my ($output,@currsecs,$allsec); if (ref($selected) eq 'ARRAY') { @currsecs = @{$selected}; } if (!@currsecs) { $allsec = ' selected="selected"'; } if (ref($sections) eq 'ARRAY') { if (@{$sections}) { my $mult; if (@{$sections} > 1) { $mult = ' multiple="multiple"'; if (@{$sections} > 3) { $mult .= ' size="4"'; } } $output = ''; } } return $output; } sub print_discussion { my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my %items = ( 'plc.roles.denied' => { text => ''.&mt($itemtext->{'plc.roles.denied'}).''. &Apache::loncommon::help_open_topic("Course_Disable_Discussion").'
'. &mt('(role-based)'), input => 'checkbox', }, 'plc.users.denied' => { text => ''.&mt($itemtext->{'plc.users.denied'}).'
'. &mt('(specific user(s))'), input => 'checkbox', }, 'pch.roles.denied' => { text => ''.&mt($itemtext->{'pch.roles.denied'}).''. &Apache::loncommon::help_open_topic("Course_Disable_Discussion").'
'. &mt('(role-based)'), input => 'checkbox', }, 'pch.users.denied' => { text => ''.&mt($itemtext->{'pch.users.denied'}).'
'. &mt('(specific user(s))'), input => 'checkbox', }, 'allow_limited_html_in_feedback' => { text => ''.&mt($itemtext->{'allow_limited_html_in_feedback'}).'', input => 'radio', }, 'allow_discussion_post_editing' => { text => ''.&mt($itemtext->{'allow_discussion_post_editing'}).'', input => 'checkbox', }, ); my $datatable; my $count; my ($cnum) = &get_course(); my %sections = &Apache::loncommon::get_sections($cdom,$cnum); my @sections = sort( { $a <=> $b } keys(%sections)); my %lt = &Apache::lonlocal::texthash ( currone => 'Disallowed:', currmult => 'Disallowed:', add => 'Disallow more:', del => 'Delete?', sec => 'Sections:', ); foreach my $item (@{$ordered}) { $count ++; $datatable .= &item_table_row_start($items{$item}{text},$count); if ($item eq 'plc.roles.denied') { $datatable .= ''.&role_checkboxes($cdom,$cnum,$item,$settings). '
'; } elsif ($item eq 'plc.users.denied') { $datatable .= &user_table($cdom,$item,undef, $settings->{$item},\%lt); } elsif ($item eq 'pch.roles.denied') { $datatable .= ''.&role_checkboxes($cdom,$cnum,$item,$settings). '
'; } elsif ($item eq 'pch.users.denied') { $datatable .= &user_table($cdom,$item,undef, $settings->{$item},\%lt); } elsif ($item eq 'allow_limited_html_in_feedback') { $datatable .= &yesno_radio($item,$settings); } elsif ($item eq 'allow_discussion_post_editing') { $datatable .= &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_row(). ''.&mt('Role').''. &mt('Sections').''. &Apache::loncommon::end_data_table_row(). &role_checkboxes($cdom,$cnum,$item,$settings,1). &Apache::loncommon::end_data_table(); } $datatable .= &item_table_row_end(); } $$rowtotal += scalar(@{$ordered}); return $datatable; } sub role_checkboxes { my ($cdom,$cnum,$item,$settings,$showsections,$crstype) = @_; my @roles = ('st','ad','ta','ep','in'); if ($crstype eq 'Community') { push(@roles,'co'); } else { push(@roles,'cc'); } my $output; my (@current,@curr_roles,%currsec,@sections); if ($showsections) { my %sections = &Apache::loncommon::get_sections($cdom,$cnum); @sections = sort( { $a <=> $b } keys(%sections)); } if (ref($settings) eq 'HASH') { if ($settings->{$item}) { @current = split(',',$settings->{$item}); if ($showsections) { foreach my $role (@current) { if ($role =~ /:/) { my ($trole,$sec) = split(':',$role); push(@curr_roles,$trole); if (ref($currsec{$trole}) eq 'ARRAY') { if (!grep(/^\Q$sec\E/,@{$currsec{$trole}})) { push(@{$currsec{$trole}},$sec); } } else { $currsec{$trole} = [$sec]; } } else { push(@curr_roles,$role); } } @current = @curr_roles; } } } my $numinrow = 3; my $count = 0; foreach my $role (@roles) { my $checked = ''; if (grep(/^\Q$role\E$/,@current)) { $checked = ' checked="checked" '; } my $plrole=&Apache::lonnet::plaintext($role,$crstype); if ($showsections) { $output .= &Apache::loncommon::start_data_table_row(); } else { my $rem = $count%($numinrow); if ($rem == 0) { if ($count > 0) { $output .= ''; } $output .= ''; } } $output .= ''; if ($showsections) { $output .= ''. &select_sections($item,$role,\@sections,$currsec{$role}). ''; } $count ++; } my %adv_roles = &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1); my $total = @roles; foreach my $role (sort(keys(%adv_roles))) { if ($role =~ m{^cr/($match_domain)/($match_name)/\w$}) { my $rolename = $3; my $value = 'cr_'.$1.'_'.$2.'_'.$rolename; my $checked = ''; if (grep(/^\Q$value\E$/,@current)) { $checked = ' checked="checked" '; } if ($showsections) { $output .= &Apache::loncommon::start_data_table_row(); } else { my $rem = $count%($numinrow); if ($rem == 0) { if ($count > 0) { $output .= ''; } $output .= ''; } } $output .= ''; if ($showsections) { $output .= ''. &select_sections($item,$role,\@sections,$currsec{$role}). ''.&Apache::loncommon::end_data_table_row(); } $total ++; $count ++; } } if (!$showsections) { my $rem = $total%($numinrow); my $colsleft = $numinrow - $rem; if ($colsleft > 1 ) { $output .= ''. ' '; } elsif ($colsleft == 1) { $output .= ' '; } $output .= ''; } return $output; } sub print_classlists { my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype) = @_; my @ordered; if ($position eq 'top') { @ordered = ('default_enrollment_start_date', 'default_enrollment_end_date'); } elsif ($position eq 'middle') { @ordered = ('nothideprivileged'); } else { @ordered = ('student_classlist_view', 'student_classlist_opt_in', 'student_classlist_portfiles'); } my %lt; if ($crstype eq 'Community') { %lt = &Apache::lonlocal::texthash ( disabled => 'No viewable membership list', section => "Membership of viewer's section", all => 'List of all members', ); } else { %lt = &Apache::lonlocal::texthash ( disabled => 'No viewable classlist', section => "Classlist of viewer's section", all => 'Classlist of all students', ); } my %items = ( 'default_enrollment_start_date' => { text => ''.&mt($itemtext->{'default_enrollment_start_date'}).'', input => 'dates', }, 'default_enrollment_end_date' => { text => ''.&mt($itemtext->{'default_enrollment_end_date'}).'', input => 'dates', }, 'nothideprivileged' => { text => ''.&mt($itemtext->{'nothideprivileged'}).'', input => 'checkbox', }, 'student_classlist_view' => { text => ''.&mt($itemtext->{'student_classlist_view'}).'', input => 'selectbox', options => \%lt, order => ['disabled','all','section'], }, 'student_classlist_opt_in' => { text => ''.&mt($itemtext->{'student_classlist_opt_in'}).'', input => 'radio', }, 'student_classlist_portfiles' => { text => ''.&mt($itemtext->{'student_classlist_portfiles'}).'', input => 'radio', }, ); unless (($settings->{'student_classlist_view'} eq 'all') || ($settings->{'student_classlist_view'} eq 'section')) { $settings->{'student_classlist_view'} = 'disabled'; } return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype); } sub print_appearance { my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my $mathdef; if ($crstype eq 'Community') { $mathdef = &mt("None specified - use member's choice"); } else { $mathdef = &mt("None specified - use student's choice"); } my %items = ( 'default_xml_style' => { text => ''.&mt($itemtext->{'default_xml_style'}).' '. ''.&mt('Select Style File').'', input => 'textbox', size => 35, }, 'pageseparators' => { text => ''.&mt($itemtext->{'pageseparators'}).'', input => 'radio', }, 'disable_receipt_display' => { text => ''.&mt($itemtext->{'disable_receipt_display'}).'', input => 'radio', }, 'texengine' => { text => ''.&mt($itemtext->{'texengine'}).'', input => 'selectbox', options => { jsMath => 'jsMath', mimetex => &mt('Convert to Images'), tth => &mt('TeX to HTML'), }, order => ['jsMath','mimetex','tth'], nullval => $mathdef, }, 'tthoptions' => { text => ''.&mt($itemtext->{'tthoptions'}).'', input => 'textbox', size => 40, }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); } sub print_grading { my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my %items = ( 'grading' => { text => ''.&mt($itemtext->{'grading'}).''. &Apache::loncommon::help_open_topic('GradingOptions'), input => 'selectbox', options => { standard => &mt('Standard: shows points'), external => &mt('External: shows number of completed parts and totals'), externalnototals => &mt('External: shows only number of completed parts'), spreadsheet => &mt('Spreadsheet: (with link to detailed scores)'), }, order => ['standard','external','externalnototals','spreadsheet'], }, 'rndseed' => { text => ''.&mt($itemtext->{'rndseed'}).''. ''.'
'. &mt('Modifying this will make problems have different numbers and answers!'). '
', input => 'selectbox', options => { '32bit' => '32bit', '64bit' => '64bit', '64bit2' => '64bit2', '64bit3' => '64bit3', '64bit4' => '64bit4', '64bit5' => '64bit5', }, order => ['32bit','64bit','64bit2','64bit3','64bit4','64bit5'], }, 'receiptalg' => { text => ''.&mt($itemtext->{'receiptalg'}).'
'. &mt('This controls how receipt numbers are generated'), input => 'selectbox', options => { receipt => 'receipt', receipt2 => 'receipt2', receipt3 => 'receipt3', }, order => ['receipt','receipt2','receipt3'], }, 'disablesigfigs' => { text => ''.&mt($itemtext->{'disablesigfigs'}).'', input => 'radio', }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); } sub print_printouts { my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my %items = ( problem_stream_switch => { text => ''.&mt($itemtext->{'problem_stream_switch'}).'', input => 'radio', }, suppress_tries => { text => ''.&mt($itemtext->{'suppress_tries'}).'', input => 'radio', }, default_paper_size => { text => ''.&mt($itemtext->{'default_paper_size'}).'', input => 'selectbox', options => { Letter => &mt('Letter').' [8 1/2x11 in]', Legal => &mt('Legal').' [8 1/2x14 in]', Tabloid => &mt('Tabloid').' [11x17 in]', Executive => &mt('Executive').' [7 1/2x10 in]', A2 => &mt('A2').' [420x594 mm]', A3 => &mt('A3').' [297x420 mm]', A4 => &mt('A4').' [210x297 mm]', A5 => &mt('A5').' [148x210 mm]', A6 => &mt('A6').' [105x148 mm]', }, order => ['Letter','Legal','Tabloid','Executive','A2','A3','A4','A5','A6'], nullval => 'None specified', }, print_header_format => { text => ''.&mt($itemtext->{'print_header_format'}).'', input => 'checkbox', }, disableexampointprint => { text => ''.&mt($itemtext->{'disableexampointprint'}).'', input => 'radio', }, canuse_pdfforms => { text => ''.&mt($itemtext->{'canuse_pdfforms'}).'', input => 'selectbox', options => { 1 => &mt('Yes'), 0 => &mt('No'), }, order => ['1','0'], nullval => 'None specified - use domain default', } ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); } sub print_spreadsheet { my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my $SelectSpreadsheetFile=&mt('Select Spreadsheet File'); my %items = ( spreadsheet_default_classcalc => { text => ''.&mt($itemtext->{'spreadsheet_default_classcalc'}).' '. ''.$SelectSpreadsheetFile.'', input => 'textbox', }, spreadsheet_default_studentcalc => { text => ''.&mt($itemtext->{'spreadsheet_default_studentcalc'}).' '. ''.$SelectSpreadsheetFile.'', input => 'textbox', }, spreadsheet_default_assesscalc => { text => ''.&mt($itemtext->{'spreadsheet_default_assesscalc'}).' '. ''.$SelectSpreadsheetFile.'', input => 'textbox', }, hideemptyrows => { text => ''.&mt($itemtext->{'hideemptyrows'}).'', input => 'radio', }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); } sub print_bridgetasks { my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } my ($stumsg,$msgnote); if ($crstype eq 'Community') { $stumsg = &mt('Send message to member'); $msgnote = &mt('Message to member and add to user notes'); } else { $stumsg = &mt('Send message to student'); $msgnote = &mt('Message to student and add to user notes'); } my %items = ( task_messages => { text => ''.&mt($itemtext->{'task_messages'}).'', input => 'selectbox', options => { only_student => $stumsg, student_and_user_notes_screen => $msgnote, }, order => ['only_student','student_and_user_notes_screen'], nullval => &mt('No message or record in user notes'), }, task_grading => { text => ''.&mt($itemtext->{'task_grading'}).'', input => 'selectbox', options => { any => &mt('Grade BTs in any section'), section => &mt('Grade BTs only in own section') }, order => ['any','section'], }, suppress_embed_prompt => { text => ''.&mt($itemtext->{'suppress_embed_prompt'}).''. ' '.&mt('(applies when current role is student)').'', input => 'radio', }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); } sub print_other { my ($cdom,$settings,$allitems,$rowtotal,$crstype) = @_; unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) { return; } my @ordered = &get_other_items($cdom,$settings,$allitems); my %items; foreach my $parameter (@ordered) { $items{$parameter} = { text => ''.$parameter.'', input => 'textbox', size => '15', }, } push (@ordered,'newp_value'); $items{'newp_value'} = { text => ''.&mt('Create New Environment Variable').'
'. '', input => 'textbox', size => '30', }; my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype); } sub get_other_items { my ($cdom,$settings,$allitems) = @_; unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) { return; } my @ordered; if (ref($settings) eq 'HASH') { foreach my $parameter (sort(keys(%{$settings}))) { next if (grep/^\Q$parameter\E$/,@{$allitems}); next if (($parameter eq 'course.helper.not.run') && (!exists($env{'user.role.dc./'.$env{'request.role.domain'}.'/'}))); unless (($parameter =~ m/^internal\./)||($parameter =~ m/^metadata\./) || ($parameter =~ m/^selfenroll_/) || ($parameter =~ /_selfenroll$/) || ($parameter eq 'type') || ($parameter =~ m/^(cc|co|in|ta|ep|ad|st)\.plaintext$/)) { push(@ordered,$parameter); } } } return @ordered; } sub item_table_row_start { my ($text,$count,$add_class) = @_; my $output; my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row'; $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq ''); $output .= ''."\n";; $output .= ''.$text. ''; return $output; } sub item_table_row_end { return ''; } sub yesno_radio { my ($item,$settings) = @_; my $itemon = ' '; my $itemoff = ' checked="checked" '; if (ref($settings) eq 'HASH') { if ($settings->{$item} eq 'yes') { $itemon = $itemoff; $itemoff = ' '; } } return ' '. ''; } sub select_from_options { my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange) = @_; my $output; if ((ref($order) eq 'ARRAY') && (ref($options) eq 'HASH')) { $output=''.&mt('Hidden').' '. '
'. ''; } $datatable .= ''; } else { if ($crstype eq 'Community') { $datatable .= &mt('No Domain Coordinators have community roles'); } else { $datatable .= &mt('No Domain Coordinators have course roles'); } } return $datatable; } sub print_hdrfmt_row { my ($item,$settings) = @_; my @curr; my $currnum = 0; my $maxnum = 2; my $currstr; if ($settings->{$item} ne '') { $currstr .= ''.&mt('Current print header:').' '. $settings->{$item}.'
'; my @current = split(/(%\d*[nca])/,$settings->{$item}); foreach my $val (@current) { unless ($val eq '') { push(@curr,$val); } } $currnum = @curr; $maxnum += $currnum; } my $output = < function reOrder(chgnum) { var maxnum = $maxnum; var oldidx = 'printfmthdr_oldpos_'+chgnum; var newidx = 'printfmthdr_pos_'+chgnum; oldidx = getIndexByName(oldidx); newidx = getIndexByName(newidx); var oldpos = document.display.elements[oldidx].value; var newpos = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value; document.display.elements[oldidx].value = newpos; var chgtype = 'up'; if (newpos < oldpos) { chgtype = 'down'; } for (var j=0; j oldpos) && (currpos <= newpos)) { document.display.elements[newidx].selectedIndex = currsel-1; document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value; } } else { if ((currpos >= newpos) && (currpos < oldpos)) { document.display.elements[newidx].selectedIndex = currsel+1; document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value; } } } } return; } function getIndexByName(item) { for (var i=0;i ENDJS $output .= $currstr.''; if (@curr > 0) { for (my $i=0; $i<@curr; $i++) { my $pos = $i+1; $output .= ''. ''; if ($curr[$i] =~ /^%\d*[nca]$/) { my ($limit,$subst) = ($curr[$i] =~ /^%(\d*)([nca])$/); $output .= ''; } else { $output .= ''; } $output .= ''; } } my $pos = $currnum+1; $output .= ''. ''. ''; $pos ++; $currnum ++; $output .= ''. ''. ''. ''. '
'. &position_selector($pos,$i,$maxnum).&mt('Delete:'). ''. &substitution_selector($i,$subst,$limit).''.&mt('Text').'
'. '
'. &position_selector($pos,$currnum,$maxnum). ''.&mt('New').''. &substitution_selector($currnum).'
'. &position_selector($pos,$currnum,$maxnum). ''.&mt('New').''.&mt('Text').'
'. ''. '
'; return $output; } sub position_selector { my ($pos,$num,$maxnum) = @_; my $output = ''; return $output; } sub substitution_selector { my ($num,$subst,$limit,$crstype) = @_; my ($stunametxt,$crsidtxt); if ($crstype eq 'Community') { $stunametxt = 'member name'; $crsidtxt = 'community ID', } else { $stunametxt = 'student name'; $crsidtxt = 'course ID', } my %lt = &Apache::lonlocal::texthash( n => $stunametxt, c => $crsidtxt, a => 'assignment note', ); my $output .= &mt('Substitution').'
'. ''.&mt('Size limit').'
'. ''; return $output; } sub change_clone { my ($cdom,$cnum,$clonelist,$oldcloner) = @_; my $clone_crs = $cnum.':'.$cdom; if ($cnum && $cdom) { my $clone_crs = $cnum.':'.$cdom; my @allowclone; if ($clonelist =~ /,/) { @allowclone = split(',',$clonelist); } else { $allowclone[0] = $clonelist; } foreach my $currclone (@allowclone) { if (!grep(/^$currclone$/,@$oldcloner)) { if ($currclone ne '*') { my ($uname,$udom) = split(/:/,$currclone); if ($uname && $udom && $uname ne '*') { if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') { my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable'); if ($currclonecrs{'cloneable'} !~ /\Q$clone_crs\E/) { if ($currclonecrs{'cloneable'} eq '') { $currclonecrs{'cloneable'} = $clone_crs; } else { $currclonecrs{'cloneable'} .= ','.$clone_crs; } &Apache::lonnet::put('environment',\%currclonecrs,$udom,$uname); } } } } } } foreach my $oldclone (@$oldcloner) { if (!grep(/^\Q$oldclone\E$/,@allowclone)) { if ($oldclone ne '*') { my ($uname,$udom) = split(/:/,$oldclone); if ($uname && $udom && $uname ne '*' ) { if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') { my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable'); my %newclonecrs = (); if ($currclonecrs{'cloneable'} =~ /\Q$clone_crs\E/) { if ($currclonecrs{'cloneable'} =~ /,/) { my @currclonecrs = split/,/,$currclonecrs{'cloneable'}; foreach my $crs (@currclonecrs) { if ($crs ne $clone_crs) { $newclonecrs{'cloneable'} .= $crs.','; } } $newclonecrs{'cloneable'} =~ s/,$//; } else { $newclonecrs{'cloneable'} = ''; } &Apache::lonnet::put('environment',\%newclonecrs,$udom,$uname); } } } } } } } return; } 1;