# The LearningOnline Network with CAPA # Handler to set configuration settings for a course # # $Id: courseprefs.pm,v 1.2 2009/04/26 00:43: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/ # # ############################################################### ############################################################## 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) { $env{'user.error.msg'}= "/adm/courseprefs:opa:0:0:Cannot modify course settings"; } else { $env{'user.error.msg'}= "/adm/courseprefs::0:1:Course environment gone, reinitialize the course"; } return HTTP_NOT_ACCEPTABLE; } &Apache::lonhtmlcommon::clear_breadcrumbs(); &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs', text=>"Course Configuration"}); my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Edit Course Configuration'); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['phase','actions']); my $phase = 'pickactions'; if ( exists($env{'form.phase'}) ) { $phase = $env{'form.phase'}; } if ($phase eq 'categorizecourse') { &assign_course_categories($r); 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 => 'General course settings', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value'}], ordered => ['description','courseid','categories', 'hidefromcat','cloners','externalsyllabus', 'url','rolenames'], }, 'localization' => { text => 'Language/TimeZone/Locale', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value',}], ordered => ['languages','timezone','datelocale'], }, 'feedback' => { text => 'Feedback messages', help => 'Course_Environment', header => [{col1 => 'Questions about:', col2 => 'Recipients'}, {col1 => 'Questions about:', col2 => 'Custom Text'}], ordered => ['question','comment','policy'], }, 'discussion' => { text => 'Discussion and Chat', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value',}], ordered => ['plc.roles.denied','plc.users.denied', 'pch.roles.denied','pch.users.denied', 'allow_limited_html_in_feedback', 'allow_discussion_post_editing'], }, 'classlists' => { text => 'Classlists and Staff Listing', help => 'Course_Environment', header => [{col1 => 'Type', col2 => 'Default dates for student access'}, {col1 => 'Setting', col2 => 'Privileged users (Domain Coordinators) in staff listing'}, {col1 => 'Setting', col2 => 'Student-viewable classlist options'}], ordered => ['default_enrollment_start_date', 'default_enrollment_end_date', 'nothideprivileged','student_classlist_view', 'student_opt_in','student_classlist_portfiles'], }, 'appearance' => { text => 'Display of resources ', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value'}], ordered => ['default_xml_style','pageseparators', 'disable_receipt_display','texengine', 'tthoptions'], }, 'grading' => { text => 'Grading', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value',}], ordered => ['grading','rndseed', 'receiptalg','disablesigfigs'], }, 'printouts' => { text => 'Printout generation', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value',}], ordered => ['problem_stream_switch','suppress_tries', 'default_paper_size','print_header_format', 'disableexampointprint'], }, 'spreadsheet' => { text => 'Spreadsheets', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value'}], ordered => ['spreadsheet_default_classcalc', 'spreadsheet_default_studentcalc', 'spreadsheet_default_assesscalc','hideemptyrows'], }, 'bridgetasks' => { text => 'Bridge tasks', help => 'Course_Environment', header => [{col1 => 'Setting', col2 => 'Value'}], ordered => ['task_messages','task_grading', 'suppress_embed_prompt'], }, 'other' => { text => 'Other settings', help => 'Course_Environment', header => [ {col1 => 'Item', col2 => 'Value', }], }, ); if ($phase eq 'process') { &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context, \@prefs_order,\%prefs,\%values); } elsif ($phase eq 'display') { my $jscript = &get_jscript($cdom); 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 { $_.'.email'; } @{$prefs{$item}{'ordered'}})); } } } } &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context, \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems); } else { &Apache::lonconfigsettings::display_choices($r,$phase,$context, \@prefs_order,\%prefs); } return OK; } sub print_config_box { my ($r,$cdom,$phase,$action,$item,$settings,$allitems) = @_; my $ordered = $item->{'ordered'}; my $rowtotal = 0; my $output = ''."\n". ''; if (($action eq 'feedback') || ($action eq 'classlists')) { $output .= ' '. &Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(). '
'. &mt($item->{text}).' '. &Apache::loncommon::help_open_topic($item->{'help'}).'
'; $rowtotal ++; if ($action eq 'feedback') { $output .= &print_feedback('top',$cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'classlists') { $output .= &print_classlists('top',$cdom,$settings,\$rowtotal); } $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).' '.&mt($item->{'header'}->[0]->{'col2'}).'
'; $output .= ' '; if ($action eq 'classlists') { $output .= &print_classlists('middle',$cdom,$settings,\$rowtotal). '
'.&mt($item->{'header'}->[1]->{'col1'}).''.&mt($item->{'header'}->[1]->{'col2'}).'
'; } } else { $output .= '
'.&mt($item->{'header'}->[2]->{'col1'}).' '.&mt($item->{'header'}->[2]->{'col2'}).'
'; } $rowtotal ++; if ($action eq 'courseinfo') { $output .= &print_courseinfo($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'localization') { $output .= &print_localization($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'feedback') { $output .= &print_feedback('bottom',$cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'discussion') { $output .= &print_discussion($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'classlists') { $output .= &print_classlists('bottom',$cdom,$settings,\$rowtotal); } elsif ($action eq 'appearance') { $output .= &print_appearance($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'grading') { $output .= &print_grading($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'printouts') { $output .= &print_printouts($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'spreadsheet') { $output .= &print_spreadsheet($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'bridgetasks') { $output .= &print_bridgetasks($cdom,$settings,$ordered,\$rowtotal); } elsif ($action eq 'other') { $output .= &print_other($cdom,$settings,$allitems,\$rowtotal); } $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).' '.&mt($item->{'header'}->[0]->{'col2'}).'

'; return ($output,$rowtotal); } sub process_changes { my ($r,$cdom,$action,$values) = @_; my %domconfig; if (ref($values) eq 'HASH') { %domconfig = %{$values}; } return &modify_crsenv($action,$cdom,%domconfig); } 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) = @_; my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom); my ($jscript,$categorize_js); my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript(); my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset'); if ($can_categorize) { $categorize_js = <'."\n".$stubrowse_js."\n"; return $jscript; } sub print_courseinfo { my ($cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my ($cathash,$categoriesform); my $crstype = &Apache::loncommon::course_type(); my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom); if (ref($domconf{'coursecategories'}) eq 'HASH') { $cathash = $domconf{'coursecategories'}{'cats'}; if (ref($cathash) eq 'HASH') { $categoriesform = &Apache::loncommon::assign_categories_table($cathash, $settings->{'categories'})."\n"; } } if (!defined($categoriesform)) { $categoriesform = &mt('No categories defined for this domain'); } my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom); my %items = ( 'url' => { text => ''.&mt('Top Level Map').''.(' 'x2). '". &mt('Select Map').'
'. &mt('Modification may make assessment data inaccessible!'). '', input => 'textbox', size => '40', }, 'description' => { text => ''.&mt('Course Description').'', input => 'textbox', size => '25', }, 'courseid' => { text => ''.&mt('Course ID or number'). '
'. '('.&mt('internal, optional').')', input => 'textbox', size => '25', }, 'cloners' => { text => ''.&mt('Users allowed to clone course').'
'. &mt('Course Coordinators included automatically'), input => 'textbox', size => '40', }, 'rolenames' => { text => ''.&mt('Replacement titles for standard course roles').'
'. '('.&mt('To replace the standard title for a course role, enter a title, otherwise leave blank').')', input => 'textbox', size => '20', }, 'externalsyllabus' => { text => ''.&mt('URL of Syllabus').'
('.&mt('not using internal handler)'), input => 'textbox', size => '40', }, 'hidefromcat' => { text => ''.&mt('Exclude from course catalog').'
'. ' ('.&mt('included by default if assigned institutional code, or categorized').')', input => 'radio', }, 'categories' => { text => ''.&mt('Categorize course').' '. &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 ++; $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').'
'.&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 ($uname eq '*') { $datatable .= &Apache::loncommon::start_data_table_row(). ''. &mt('Domain:').' '.$udom. '
'. ''. &Apache::loncommon::end_data_table_row(); $num ++; } else { 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().'
'. &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(); foreach my $role ('cc','in','ta','ep','ad','st') { $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') { $datatable .= ''.&Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item},$items{$item}{size}); } 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) = @_; my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom); my ($can_toggle_cat,$can_categorize); if (ref($domconf{'coursecategories'}) eq 'HASH') { 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) = @_; 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') { $hascats = 1; } } my $catwin_js; if ($hascats) { my $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 $start_page = &Apache::loncommon::start_page('Course Categories',$catwin_js, {'only_body' => 1,}); my $end_page = &Apache::loncommon::end_page(); my $categoriesform = '

'.&mt('Categorize Course').'

'; if ($hascats) { my %currsettings = &Apache::lonnet::get('environment',['hidefromcat','categories'],$cdom,$cnum); $categoriesform .= &mt('Assign one or more categories to this course.').'

'. '
'."\n". &Apache::loncommon::assign_categories_table($cathash, $currsettings{'categories'})."\n". '

'; } else { $categoriesform .= &mt('No categories defined for this domain'); } $r->print($start_page.$categoriesform.$end_page); return; } sub print_localization { my ($cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my %items = ( languages => { text => &mt('Languages used').'
'.&mt("(will override user's preference)"), input => 'selectbox', }, timezone => { text => &mt('Timezone in which the course takes place'), input => 'selectbox', }, datelocale => { text => &mt('Locale used for course calendar'), 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('language_0','',1); } else { my $num = 0; my @languages = split(/\s*(\,|\;|\:)\s*/,$settings->{$item}); $datatable .= &Apache::loncommon::start_data_table(); if (@languages > 0) { foreach my $lang (@languages) { my $showlang = $lang; my $code = &Apache::loncommon::supportedlanguagecode($lang); if ($code) { $showlang = &plainlanguagedescription($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($item); ''. ''.&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); } } $datatable .= &item_table_row_end(); } $$rowtotal += scalar(@{$ordered}); return $datatable; } sub print_feedback { my ($position,$cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my %items = ( 'question' => { text => ''.&mt('Resource Content').'', input => 'textbox', size => '50', }, 'comment' => { text => ''.&mt('Course Content').'', input => 'textbox', size => '50', }, 'policy' => { text => ''.&mt('Course Policy').'', 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:', curmult => 'Current recipients:', add => 'Additional recipient:', del => 'Delete?', sec => 'Sections:', ); foreach my $item (@{$ordered}) { $count ++; $datatable .= &item_table_row_start($items{$item}{text},$count); if ($position eq 'top') { my $includeempty = 0; $datatable .= &user_table($cdom,$item,\@sections, $settings->{$item.'.email'},\%lt); } else { $datatable .= &Apache::lonhtmlcommon::textbox($item.'_text', $settings->{$item},$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 .= &Apache::loncommon::start_data_table(); 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 .= ''. ''. ''. ''.(' '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 .= ''; $num ++; } if ($num) { $output .= &Apache::loncommon::start_data_table_row(). ''; if ($num > 1) { $output .= $lt->{'currone'}; } else { $output .= $lt->{'currmult'}; } $output .= '
'. ''.$currusers.'
'. &Apache::loncommon::end_data_table_row(); } $output .= &Apache::loncommon::start_data_table_row(). ''. $lt->{'add'}.'
'. &select_recipient($item,$num,$cdom,$sections). ''. ''.&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); } 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,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my %items = ( 'plc.roles.denied' => { text => ''.&mt('No Chat room use').''. &Apache::loncommon::help_open_topic("Course_Disable_Discussion"), input => 'checkbox', }, 'plc.users.denied' => { text => ''.&mt('No Chat room use').'', input => 'checkbox', }, 'pch.roles.denied' => { text => ''.&mt('No Resource Discussion').''. &Apache::loncommon::help_open_topic("Course_Disable_Discussion"), input => 'checkbox', }, 'pch.users.denied' => { text => ''.&mt('No Resource Discussion').'', input => 'checkbox', }, 'allow_limited_html_in_feedback' => { text => ''.&mt('Allow limited HTML in discussion posts').'', input => 'radio', }, 'allow_discussion_post_editing' => { text => ''.&mt('Users can edit/delete own discussion posts').'', 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:', curmult => '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) = @_; my @roles = ('st','ad','ta','ep','in','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 { 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); 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,$rowtotal) = @_; 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_opt_in','student_classlist_portfiles'); } my %items = ( 'default_enrollment_start_date' => { text => ''.&mt('Start date').'', input => 'dates', }, 'default_enrollment_end_date' => { text => ''.&mt('End date').'', input => 'dates', }, 'nothideprivileged' => { text => ''.&mt('Domain Coodinators in course').'', input => 'checkbox', }, 'student_classlist_view' => { text => ''.&mt('Student-viewable classlist').'', input => 'selectbox', options => { disabled => &mt('No viewable classlist'), section => &mt("Classlist of viewer's section"), all => &mt('Classlist of all students'), }, order => ['disabled','all','section'], }, 'student_opt_in' => { text => ''.&mt('Student agreement needed to be listed').'', input => 'radio', }, 'student_classlist_portfiles' => { text => ''.&mt('Include link to accessible portfolio files').'', 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); } sub print_appearance { my ($cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my %items = ( 'default_xml_style' => { text => ''.&mt('Default XML Style File').' '. ''.&mt('Select Style File').'', input => 'textbox', size => 35, }, 'pageseparators' => { text => ''.&mt('Visibly Separate Items on Pages').'', input => 'radio', }, 'disable_receipt_display' => { text => ''.&mt('Disable display of problem receipts').'', input => 'radio', }, 'texengine' => { text => ''.&mt('Force use of a specific math rendering engine.').'', input => 'selectbox', options => { jsMath => 'jsMath', mimetex => &mt('Convert to Images'), tth => &mt('TeX to HTML'), }, order => ['jsMath','mimetex','tth'], nullval => &mt("None specified - use student's choice"), }, 'tthoptions' => { text => ''.&mt('Default set of options to pass to tth/m when converting TeX').'', input => 'textbox', size => 40, }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal); } sub print_grading { my ($cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my %items = ( 'grading' => { text => ''.&mt('Grading').''. &Apache::loncommon::help_open_topic('GradingOptions'), input => 'selectbox', options => { standard => &mt('Standard: shows points'), external => &mt('External: shows number of completed parts'), spreadsheet => &mt('Spreadsheet: (with link to detailed scores)'), }, order => ['standard','external','spreadsheet'], }, 'rndseed' => { text => ''.&mt('Randomization algorithm used').''. ''.'
'. &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('Receipt algorithm used').'
'. &mt('This controls how receipt numbers are generated.'), input => 'selectbox', options => { receipt => 'receipt', receipt2 => 'receipt2', receipt3 => 'receipt3', }, order => ['receipt','receipt2','receipt3'], }, 'disablesigfigs' => { text => ''.&mt('Disable checking of Significant Figures').'', input => 'radio', }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal); } sub print_printouts { my ($cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my %items = ( problem_stream_switch => { text => ''.&mt('Allow problems to be split over pages').'', input => 'radio', }, suppress_tries => { text => ''.&mt('Suppress number of tries in printing').'', input => 'radio', }, default_paper_size => { text => ''.&mt('Default paper type').'', 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('Print header format').'', input => 'checkbox', }, disableexampointprint => { text => ''.&mt('Disable automatically printing point values on exams').'', input => 'radio', }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal); } sub print_spreadsheet { my ($cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my $SelectSpreadsheetFile=&mt('Select Spreadsheet File'); my %items = ( spreadsheet_default_classcalc => { text => ''.&mt('Default Course Spreadsheet').' '. ''.$SelectSpreadsheetFile.'', input => 'textbox', }, spreadsheet_default_studentcalc => { text => ''.&mt('Default Student Spreadsheet').' '. ''.$SelectSpreadsheetFile.'', input => 'textbox', }, spreadsheet_default_assesscalc => { text => ''.&mt('Default Assessment Spreadsheet').' '. ''.$SelectSpreadsheetFile.'', input => 'textbox', }, hideemptyrows => { text => ''.&mt('Hide Empty Rows in Spreadsheets').'', input => 'radio', }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal); } sub print_bridgetasks { my ($cdom,$settings,$ordered,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { return; } my %items = ( task_messages => { text => ''.&mt('Send message to student when clicking Done on Tasks').'', input => 'selectbox', options => { only_student => &mt('Send message to student'), student_and_user_notes_screen => &mt('Message to student and add to user notes'), }, order => ['only_student','student_and_user_notes_screen'], nullval => &mt('No message or record in user notes'), }, task_grading => { text => ''.&mt('Bridge Task grading by instructors and TAs in sections').'', 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('Hi$de upload references prompt if uploading file to portfolio').' '. &mt('(applies when current role is student)').'', input => 'radio', }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal); } sub print_other { my ($cdom,$settings,$allitems,$rowtotal) = @_; unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) { return; } my @ordered; my %items; 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|in|ta|ep|ad|st)\.plaintext$/)) { push(@ordered,$parameter); $items{$parameter} = { text => $parameter, input => 'textbox', size => '15', }, } } } return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal); } sub item_table_row_start { my ($text,$count) = @_; my $output; if ($count%2) { $output .= ''; } else { $output .= ''; } $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 { $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 $item (@current) { unless ($item eq '') { push(@curr,$item); } } $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.&Apache::loncommon::start_data_table(); if (@curr > 0) { for (my $i=0; $i<@curr; $i++) { my $pos = $i+1; $output .= &Apache::loncommon::start_data_table_row(). ''. &position_selector($pos,$i,$maxnum).&mt('Delete:'). ''; if ($curr[$i] =~ /^%\d*[nca]$/) { my ($limit,$subst) = ($curr[$i] =~ /^%(\d*)([nca])$/); $output .= ''. &substitution_selector($i,$subst,$limit).''; } else { $output .= ''.&mt('Text').'
'. ''; } $output .= &Apache::loncommon::end_data_table_row(); } } my $pos = $currnum+1; $output .= &Apache::loncommon::start_data_table_row(). ''. &position_selector($pos,$currnum,$maxnum). ''.&mt('New').''. &substitution_selector($currnum).''. &Apache::loncommon::end_data_table_row(); $pos ++; $currnum ++; $output .= &Apache::loncommon::start_data_table_row(). ''. &position_selector($pos,$currnum,$maxnum). ''.&mt('New').''. ''.&mt('Text').'
'. ''. &Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); return $output; } sub position_selector { my ($pos,$num,$maxnum) = @_; my $output = ''; return $output; } sub substitution_selector { my ($num,$subst,$limit) = @_; my %lt = &Apache::lonlocal::texthash( n => 'student name', c => 'course ID', a => 'assignment note', ); my $output .= &mt('Substitution').'
'. ''.&mt('Size limit').'
'. ''; return $output; } sub modify_crsenv { my ($action,$cdom,%domconfig) = @_; return; } 1;