--- loncom/interface/courseprefs.pm 2010/08/21 04:04:54 1.29 +++ loncom/interface/courseprefs.pm 2017/02/07 15:44:23 1.84 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set configuration settings for a course # -# $Id: courseprefs.pm,v 1.29 2010/08/21 04:04:54 raeburn Exp $ +# $Id: courseprefs.pm,v 1.84 2017/02/07 15:44:23 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -137,7 +137,7 @@ whether Domain coordinators who are curr 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 +Inputs: $cdom,$item,$settings,$crstype,$noedit 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). @@ -215,9 +215,15 @@ use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonconfigsettings; +use Apache::lonrelrequtils; +use Apache::lonparmset; +use Apache::courseclassifier; use Apache::lonlocal; use LONCAPA qw(:DEFAULT :match); +my $registered_cleanup; +my $modified_courses; + sub handler { my $r=shift; if ($r->header_only) { @@ -227,11 +233,11 @@ sub handler { } my $context = 'course'; my $cid = $env{'request.course.id'}; - my ($cnum,$cdom) = &get_course($cid); + my ($cnum,$cdom,$chome) = &get_course($cid); my $crstype = &Apache::loncommon::course_type(); - my $parm_permission = &Apache::lonnet::allowed('opa',$cid); + my ($parm_permission,$allowed) = &get_permission($cid); my $navmap = Apache::lonnavmaps::navmap->new(); - if ($parm_permission && $navmap) { + if ($allowed && $navmap) { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; } else { @@ -256,6 +262,9 @@ sub handler { return HTTP_NOT_ACCEPTABLE; } + $registered_cleanup=0; + @{$modified_courses}=(); + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['phase','actions','origin']); &Apache::lonhtmlcommon::clear_breadcrumbs(); @@ -267,10 +276,11 @@ sub handler { my %lt; if ($crstype eq 'Community') { %lt = ( - conf => 'Community Configuration', - edit => 'Edit Community Configuration', + conf => 'Community Settings', + edit => 'Edit Community Settings', gens => 'General community settings', idnu => 'Community ID or number', + unco => 'Unique code', desc => 'Community Description', ownr => 'Community Owner', cown => 'Community Co-owners', @@ -286,19 +296,21 @@ sub handler { 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', + clas => 'Membership and facilitator listing', + prus => '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', + conf => 'Course Settings', + edit => 'Edit Course Settings', gens => 'General course settings', idnu => 'Course ID or number', + unco => 'Unique code', desc => 'Course Description', + cred => 'Student credits', ownr => 'Course Owner', cown => 'Course Co-owners', catg => 'Categorize course', @@ -313,13 +325,15 @@ sub handler { 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', + clas => 'Classlists and staff listing', + prus => 'Privileged users (Domain Coordinators) in staff listing', + prdo => "Domains to check for privileged users (besides course's domain)", defc => 'Default Course Spreadsheet', defs => 'Default Student Spreadsheet', seme => 'Send message to student when clicking Done on Tasks', ); } + $lt{'lcrv'} = 'Required LON-CAPA version'; &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs', text=>$lt{'conf'}}); my $breadcrumbs = @@ -330,11 +344,26 @@ sub handler { $phase = $env{'form.phase'}; } - if ($phase eq 'categorizecourse') { + if (($phase eq 'categorizecourse') && ($parm_permission->{'categorizecourse'})) { &assign_course_categories($r,$crstype); return OK; } + if (($phase eq 'releaseinfo') && ($parm_permission->{'releaseinfo'})) { + my $loncaparev = $env{'course.'.$cid.'.internal.releaserequired'}; + if ($loncaparev) { + if (&display_loncaparev_constraints($r,$navmap,$loncaparev,$crstype)) { + push(@{$modified_courses},[$cdom,$cnum,$chome,$crstype]); + unless ($registered_cleanup) { + my $handlers = $r->get_handlers('PerlCleanupHandler'); + $r->set_handlers('PerlCleanupHandler' => [\&update_releasereq,@{$handlers}]); + $registered_cleanup=1; + } + } + return OK; + } + } + my %values=&Apache::lonnet::dump('environment',$cdom,$cnum); my @prefs_order = ('courseinfo','localization','feedback','discussion', 'classlists','appearance','grading','printouts', @@ -343,26 +372,30 @@ sub handler { my %prefs = ( 'courseinfo' => { text => $lt{'gens'}, - help => 'Course_Environment', - ordered => ['owner','co-owners','description','courseid', - 'categories','hidefromcat','externalsyllabus', - 'cloners','url','rolenames'], + help => 'Course_Prefs_General', + ordered => ['owner','co-owners','loncaparev','description', + 'clonedfrom','courseid','uniquecode','categories', + 'hidefromcat','externalsyllabus','cloners','url', + 'rolenames'], itemtext => { 'owner' => $lt{'ownr'}, 'co-owners' => $lt{'cown'}, 'description' => $lt{'desc'}, 'courseid' => $lt{'idnu'}, + 'uniquecode' => $lt{'unco'}, 'categories' => $lt{'catg'}, 'hidefromcat' => $lt{'excc'}, 'cloners' => $lt{'clon'}, - 'externalsyllabus' => 'URL of Syllabus', + 'externalsyllabus' => 'Syllabus status', 'url' => 'Top Level Map', 'rolenames' => $lt{'rept'}, + 'loncaparev' => $lt{'lcrv'}, + 'clonedfrom' => 'Cloned from', }, }, 'localization' => - { text => 'Language and Time Localization', - help => 'Course_Environment', + { text => 'Language and time localization', + help => 'Course_Prefs_Language', ordered => ['languages','timezone','datelocale'], itemtext => { languages => 'Languages used', @@ -372,7 +405,7 @@ sub handler { }, 'feedback' => { text => 'Feedback messages', - help => 'Course_Environment', + help => 'Course_Prefs_Feedback', header => [{col1 => 'Questions about:', col2 => 'Recipients'}], ordered => ['question.email','comment.email','policy.email'], @@ -384,23 +417,28 @@ sub handler { }, 'discussion' => { text => 'Discussion and Chat', - help => 'Course_Environment', - ordered => ['plc.roles.denied','plc.users.denied', - 'pch.roles.denied','pch.users.denied', + help => 'Course_Prefs_Discussions', + ordered => ['pch.roles.denied','pch.users.denied', + 'pac.roles.denied','pac.users.denied', + 'plc.roles.denied','plc.users.denied', 'allow_limited_html_in_feedback', - 'allow_discussion_post_editing'], + 'allow_discussion_post_editing', + 'discussion_post_fonts'], itemtext => { - 'plc.roles.denied' => 'No Resource Discussion', - 'plc.users.denied' => 'No Resource Discussion', - 'pch.roles.denied' => 'No Chat room use', - 'pch.users.denied' => 'No Chat room use', + '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', + 'pac.roles.denied' => 'No Anonymous Resource Discussion', + 'pac.users.denied' => 'No Anonymous Resource Discussion', allow_limited_html_in_feedback => 'Allow limited HTML in discussion', allow_discussion_post_editing => 'Users can edit/delete own discussion posts', + discussion_post_fonts => 'Discussion post fonts based on likes/unlikes', }, }, 'classlists' => { text => $lt{'clas'}, - help => 'Course_Environment', + help => 'Course_Prefs_Classlists', header => [{col1 => 'Type', col2 => $lt{'defd'}}, {col1 => 'Setting', @@ -409,34 +447,40 @@ sub handler { col2 => $lt{'stuv'}}], ordered => ['default_enrollment_start_date', 'default_enrollment_end_date', - 'nothideprivileged','student_classlist_view', + 'defaultcredits', + 'nothideprivileged','checkforpriv', + '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'}, + nothideprivileged => $lt{'prus'}, + checkforpriv => $lt{'prdo'}, student_classlist_view => $lt{'stuv'}, student_classlist_opt_in => $lt{'stul'}, student_classlist_portfiles => 'Include link to accessible portfolio files', + defaultcredits => $lt{'cred'}, }, }, 'appearance' => { text => 'Display of resources ', - help => 'Course_Environment', + help => 'Course_Prefs_Display', ordered => ['default_xml_style','pageseparators', 'disable_receipt_display','texengine', - 'tthoptions'], + 'tthoptions','uselcmath','usejsme'], 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', + uselcmath => 'Student formula entry uses inline preview, not DragMath pop-up', + usejsme => 'Molecule editor uses JSME (HTML5) in place of JME (Java)', }, }, 'grading' => { text => 'Grading', - help => 'Course_Environment', + help => 'Course_Prefs_Grading', ordered => ['grading','rndseed', 'receiptalg','disablesigfigs'], itemtext => { @@ -449,7 +493,7 @@ sub handler { }, 'printouts' => { text => 'Printout generation', - help => 'Course_Environment', + help => 'Course_Prefs_Printouts', ordered => ['problem_stream_switch','suppress_tries', 'default_paper_size','print_header_format', 'disableexampointprint','canuse_pdfforms'], @@ -458,13 +502,13 @@ sub handler { 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', + disableexampointprint => 'Disable automatically printing point values on bubblesheet exams', canuse_pdfforms => 'Users can print problems as PDF forms and upload later for grading', }, }, 'spreadsheet' => { text => 'Spreadsheets', - help => 'Course_Environment', + help => 'Course_Prefs_Spreadsheet', ordered => ['spreadsheet_default_classcalc', 'spreadsheet_default_studentcalc', 'spreadsheet_default_assesscalc','hideemptyrows'], @@ -477,7 +521,7 @@ sub handler { }, 'bridgetasks' => { text => 'Bridge tasks', - help => 'Course_Environment', + help => 'Course_Prefs_Bridgetasks', ordered => ['task_messages','task_grading', 'suppress_embed_prompt'], itemtext => { @@ -488,29 +532,58 @@ sub handler { }, 'other' => { text => 'Other settings', - help => 'Course_Environment', + help => 'Course_Prefs_Other', header => [ {col1 => 'Item', col2 => 'Value', }], }, ); - if ($phase eq 'process') { + if (($phase eq 'process') && ($parm_permission->{'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); + $cnum,undef,\@allitems, + 'coursepref',$parm_permission); + } elsif (($phase eq 'display') && ($parm_permission->{'display'})) { + my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values); my @allitems = &get_allitems(%prefs); &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context, - \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype); + \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype, + 'coursepref',$parm_permission); } else { &Apache::lonconfigsettings::display_choices($r,$phase,$context, - \@prefs_order,\%prefs); + \@prefs_order,\%prefs, + 'coursepref',$parm_permission); } return OK; } +sub get_permission { + my ($cid) = @_; + my %permission; + my $allowed = 0; + return (\%permission,$allowed) unless ($cid); + if (&Apache::lonnet::allowed('opa',$cid)) { + %permission= ( + 'pickactions' => 1, + 'categorizecourse' => 1, + 'releaseinfo' => 1, + 'process' => 1, + 'display' => 1, + ); + } elsif (&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) { + %permission = ( + 'pickactions' => 1, + 'releaseinfo' => 1, + 'display' => 1, + ); + } + foreach my $perm (values(%permission)) { + if ($perm) { $allowed=1; last; } + } + return (\%permission,$allowed); +} + sub get_allitems { my (%prefs) = @_; my @allitems; @@ -528,92 +601,138 @@ sub get_allitems { } sub print_config_box { - my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype) = @_; + my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype,$parm_permission) = @_; my $ordered = $item->{'ordered'}; my $itemtext = $item->{'itemtext'}; + my $noedit; + if (ref($parm_permission) eq 'HASH') { + unless ($parm_permission->{'process'}) { + $noedit = 1; + } + } my $rowtotal = 0; my $output = - '

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

-
 '. - &Apache::loncommon::help_open_topic($item->{'help'}).''; + ' + + '."\n". + ''; if (($action eq 'feedback') || ($action eq 'classlists')) { $output .= ' + + + + + + + + '. + "'cloners_all'".');"'.$disabled.' />'.&mt('No').''. &Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(). - '
'. + &mt($item->{text}); + if ($item->{'help'}) { + $output .= ' '. + &Apache::loncommon::help_open_topic($item->{'help'}); + } + $output .= '
'; if (exists $item->{'header'}->[0]->{'col1'} || exists $item->{'header'}->[0]->{'col2'}) { $output .= ' - - + '; + if ($action eq 'feedback') { + $output .= ' + '; } $rowtotal ++; if ($action eq 'feedback') { - $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal); + $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit); } elsif ($action eq 'classlists') { - $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype); + $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit); } $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).''.&mt($item->{'header'}->[0]->{'col2'}).''.&mt($item->{'header'}->[0]->{'col1'}).''; + } else { + $output .= ' + '; + } + $output .= &mt($item->{'header'}->[0]->{'col2'}).'
+
'; - $output .= ' - + if ($action eq 'classlists') { + $output .= ' + '; if ($action eq 'classlists') { - $output .= &print_classlists('middle',$cdom,$settings,$itemtext,\$rowtotal,$crstype). + $output .= &print_classlists('middle',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit). '
'.&mt($item->{'header'}->[1]->{'col1'}).''.&mt($item->{'header'}->[1]->{'col2'}).''; + } else { + $output .= ' + '; + } + $output .= &mt($item->{'header'}->[1]->{'col2'}).'
+
'; - if (exists $item->{'header'}->[0]->{'col1'} || - exists $item->{'header'}->[0]->{'col2'}) { + if (exists $item->{'header'}->[2]->{'col1'} || + exists $item->{'header'}->[2]->{'col2'}) { $output .= ' - - + + '; } } } else { $output .= ' + + + +
'.&mt($item->{'header'}->[0]->{'col1'}).''.&mt($item->{'header'}->[0]->{'col2'}).''.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
'; if (exists $item->{'header'}->[0]->{'col1'} || exists $item->{'header'}->[0]->{'col2'}) { $output .= ' - - + '; + if (($action eq 'courseinfo') || ($action eq 'localization') || + ($action eq 'print_discussion')) { + $output .= ''; } } $rowtotal ++; if ($action eq 'courseinfo') { - $output .= &print_courseinfo($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); + $output .= &print_courseinfo($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'localization') { - $output .= &print_localization($cdom,$settings,$ordered,$itemtext,\$rowtotal); + $output .= &print_localization($cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit); } elsif ($action eq 'feedback') { - $output .= &print_feedback('bottom',$cdom,$settings,$ordered,$itemtext,\$rowtotal); + $output .= &print_feedback('bottom',$cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit); } 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); + $output .= &print_discussion($cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit); + } elsif (($action eq 'classlists') || ($action eq 'viewableroster')) { + $output .= &print_classlists('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'appearance') { - $output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); + $output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'grading') { - $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); + $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'printouts') { - $output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); + $output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'spreadsheet') { - $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); + $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'bridgetasks') { - $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype); + $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'other') { - $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype); + $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype,$noedit); } $output .= '
'.&mt($item->{'header'}->[0]->{'col1'}).''.&mt($item->{'header'}->[0]->{'col2'}).''.&mt($item->{'header'}->[0]->{'col1'}).''; + } else { + $output .= ''; + } + $output .= &mt($item->{'header'}->[0]->{'col2'}).'
-'; +

'; return ($output,$rowtotal); } @@ -637,7 +756,27 @@ sub process_changes { } } } elsif (ref($item->{'ordered'}) eq 'ARRAY') { - @ordered = @{$item->{'ordered'}}; + if ($action eq 'courseinfo') { + my ($can_toggle_cat,$can_categorize) = + &can_modify_catsettings($cdom,$crstype); + foreach my $entry (@{$item->{'ordered'}}) { + next if (($entry eq 'hidefromcat') && + (!$can_toggle_cat)); + next if (($entry eq 'categories') && + (!$can_categorize)); + next if (($entry eq 'loncaparev') || + ($entry eq 'owner') || + ($entry eq 'clonedfrom')); + push(@ordered,$entry); + } + } elsif ($action eq 'classlists') { + foreach my $entry (@{$item->{'ordered'}}) { + next if ($entry eq 'defaultcredits'); + push(@ordered,$entry); + } + } else { + @ordered = @{$item->{'ordered'}}; + } } if (@ordered > 0) { if ($action eq 'feedback') { @@ -686,9 +825,9 @@ sub process_changes { my @clonedoms; if (exists($env{'form.cloners_activate'})) { my $actnum = $env{'form.cloners_activate'}; - if ($actnum ne '') { - if ($env{'form.clonersdom_'.$actnum} ne '') { - my $clonedom = $env{'form.clonersdom_'.$actnum}; + if ($actnum ne '-1') { + 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}); @@ -704,7 +843,7 @@ sub process_changes { my $clonedom = $env{'form.cloners_dom_'.$i}; if (&check_clone($clonedom,$disallowed) eq 'ok') { if (!grep(/^\*:\Q$clonedom\E$/,@clonedoms)) { - push (@clonedoms,'*:'.$clonedom); + push(@clonedoms,'*:'.$clonedom); } } } @@ -750,6 +889,37 @@ sub process_changes { } } } + if (ref($values) eq 'HASH') { + my (@code_order,%codedefaults); + &Apache::lonnet::auto_instcode_defaults($cdom,\%codedefaults, + \@code_order); + my $clonebycode; + if ($env{'form.cloners_instcode'}) { + if (@code_order > 0) { + my @standardnames = &Apache::loncommon::get_standard_codeitems(); + my %local_to_standard; + for (my $i=0; $i<@code_order; $i++) { + $local_to_standard{$code_order[$i]} = $standardnames[$i]; + } + foreach my $item (@code_order) { + my $key = $local_to_standard{$item}; + if ($key ne '') { + if ($env{'form.'.$key}) { + $clonebycode .= $key.'='.&escape($env{'form.'.$key}).'&'; + } + } + } + $clonebycode =~ s/\&$//; + } + } + if ($clonebycode) { + if ($newvalues{$entry}) { + $newvalues{$entry} .= ','.$clonebycode; + } else { + $newvalues{$entry} = $clonebycode; + } + } + } } if (ref($disallowed) eq 'HASH') { if (ref($disallowed->{'cloners'}) eq 'HASH') { @@ -889,7 +1059,8 @@ sub process_changes { } } } - } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied')) { + } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied') || + ($entry eq 'pac.roles.denied')) { my @denied = &Apache::loncommon::get_env_multiple('form.'.$entry); @denied = sort(@denied); my $deniedstr = ''; @@ -897,7 +1068,8 @@ sub process_changes { $deniedstr = join(',',@denied); } $newvalues{$entry} = $deniedstr; - } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied')) { + } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied') || + ($entry eq 'pac.users.denied')) { my $total = $env{'form.'.$entry.'_total'}; my $userstr = ''; my @denied; @@ -945,6 +1117,35 @@ sub process_changes { } } $newvalues{$entry} =~ s/,$//; + } elsif ($entry eq 'discussion_post_fonts') { + my ($classorder,$classtitles) = &discussion_vote_classes(); + my $fontchange = 0; + foreach my $class (@{$classorder}) { + my $ext_entry = $entry.'_'.$class; + my $size = $env{'form.'.$ext_entry.'_size'}; + my $unit = $env{'form.'.$ext_entry.'_unit'}; + my $weight = $env{'form.'.$ext_entry.'_weight'}; + my $style = $env{'form.'.$ext_entry.'_style'}; + my $other = $env{'form.'.$ext_entry.'_other'}; + $size =~ s/,//g; + $unit =~ s/,//g; + $weight =~ s/,//g; + $style =~ s/,//g; + $other =~ s/[^\w;:\s\-\%.]//g; + $other =~ s/(^\s+|\s+$)//g; + $newvalues{$ext_entry} = join(',',($size.$unit,$weight,$style,$other)); + my $current = $values->{$ext_entry}; + if ($values->{$ext_entry} eq '') { + $current = ',,,'; + } + if ($newvalues{$ext_entry} ne $current) { + $changes->{$ext_entry} = $newvalues{$ext_entry}; + $fontchange ++; + } + } + if ($fontchange) { + $changes->{$entry} = 1; + } } elsif ($entry eq 'nothideprivileged') { my @curr_nothide; my @new_nothide; @@ -1019,36 +1220,47 @@ sub process_changes { 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; + } elsif (($entry eq 'languages') || + ($entry eq 'checkforpriv')) { + my $settings; 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}.','; + $settings .= $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; + my $new = $env{'form.'.$entry.'_'.$total}; + if ($entry eq 'languages') { + my %langchoices = &get_lang_choices(); + if ($langchoices{$new}) { + $settings .= $new; + } else { + $settings =~ s/,$//; + $disallowed->{'localization'}{$entry} = $new; + } } else { - $langstr =~ s/,$//; - $disallowed->{'localization'}{$entry} = $newlang; + my %domains=map { $_ => 1; } &Apache::lonnet::all_domains(); + if ($domains{$new}) { + $settings .= $new; + } else { + $settings =~ s/,$//; + $disallowed->{'classlists'}{$entry} = $new; + } } } else { - $langstr =~ s/,$//; + $settings =~ s/,$//; } - $newvalues{$entry} = $langstr; + $newvalues{$entry} = $settings; } else { $newvalues{$entry} = $env{'form.'.$entry}; } - unless ($entry eq 'co-owners') { + unless (($entry eq 'co-owners') || ($entry eq 'discussion_post_fonts')) { if ($newvalues{$entry} ne $values->{$entry}) { $changes->{$entry} = $newvalues{$entry}; } @@ -1175,7 +1387,7 @@ sub store_changes { my ($displayname,$text); $text = $prefs->{$item}->{'itemtext'}{$key}; my $displayval; - unless ($key eq 'co-owners') { + unless (($key eq 'co-owners') || ($key eq 'discussion_post_fonts')) { $displayval = $changes->{$item}{$key}; } if ($item eq 'feedback') { @@ -1211,6 +1423,36 @@ sub store_changes { } $displayval = join(', ',@longroles); } + } elsif ($key eq 'discussion_post_fonts') { + my ($classorder,$classtitles)=&discussion_vote_classes(); + my ($styleorder,$styleitems)=&discussion_vote_styles(); + my $count = 1; + my $total = scalar(keys(%{$changes->{$item}})); + foreach my $class (@{$classorder}) { + $count ++; + next unless ($changes->{$item}{$key.'_'.$class}); + my @vals = split(/,/,$changes->{$item}{$key.'_'.$class}); + my $showval = ''; + for (my $i=0; $i<@{$styleorder}; $i++) { + if ($vals[$i] ne '') { + $showval .= 'font-'.$styleorder->[$i].': '.$vals[$i].'; '; + } + } + if ($vals[3] ne '') { + $showval .= $vals[3]; + } + if ($showval ne '') { + $displayval .= $classtitles->{$class}.':{ '. + $showval.'}'; + $storehash{$key.'_'.$class} = $changes->{$item}{$key.'_'.$class}; + } else { + $displayval .= $classtitles->{$class}.': '.&mt('None'); + push(@delkeys,$key.'_'.$class); + } + unless ($count == $total) { + $displayval .= (' 'x2); + } + } } $displayname = &mt($text); } @@ -1237,7 +1479,7 @@ sub store_changes { $displayval = &Apache::lonlocal::locallocaltime($displayval); } elsif ($key eq 'categories') { $displayval = $env{'form.categories_display'}; - } elsif ($key eq 'canuse_pdfforms') { + } elsif (($key eq 'canuse_pdfforms') || ($key eq 'usejsme') || ($key eq 'uselcmath')) { if ($changes->{$item}{$key} eq '1') { $displayval = &mt('Yes'); } elsif ($changes->{$item}{$key} eq '0') { @@ -1296,7 +1538,7 @@ sub store_changes { if ($key eq 'url') { my $bkuptime=time; $output .= (' 'x2).&mt('(Previous URL backed up)').': '. - $storehash{'top level map backup '.$bkuptime} => $values->{$key}; + $storehash{'top level map backup '.$bkuptime} = $values->{$key}; } $output .= ''; } @@ -1310,7 +1552,9 @@ sub store_changes { } } } else { - $storehash{$key} = $changes->{$item}{$key}; + unless ($key eq 'discussion_post_fonts') { + $storehash{$key} = $changes->{$item}{$key}; + } } } if ($key eq 'cloners') { @@ -1334,9 +1578,9 @@ sub store_changes { $output .= ''; } else { if ($crstype eq 'Community') { - $output = &mt('No changes made to community settings.'); + $output .= &mt('No changes made to community settings.'); } else { - $output = &mt('No changes made to course settings.'); + $output .= &mt('No changes made to course settings.'); } } } @@ -1507,16 +1751,98 @@ sub get_course { } my $cdom=$env{'course.'.$courseid.'.domain'}; my $cnum=$env{'course.'.$courseid.'.num'}; - return ($cnum,$cdom); + my $chome=$env{'course.'.$courseid.'.home'}; + return ($cnum,$cdom,$chome); } sub get_jscript { - my ($cdom,$phase,$crstype) = @_; + my ($cid,$cdom,$phase,$crstype,$settings) = @_; my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype); - my ($jscript,$categorize_js); + my ($jscript,$categorize_js,$loncaparev_js,$instcode_js); my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript(); my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset'); my $cloners_js = &cloners_javascript($phase); + my @code_order; + if ($crstype ne 'Community') { + if (ref($settings) eq 'HASH') { + my %codedefaults; + &Apache::lonnet::auto_instcode_defaults($cdom,\%codedefaults, + \@code_order); + if (@code_order > 0) { + if ($phase eq 'display') { + my @actions = &Apache::loncommon::get_env_multiple('form.actions'); + if (grep(/^courseinfo$/,@actions)) { + if ($settings->{'cloners'} ne '') { + unless ($settings->{'cloners'} eq '*') { + my @cloners = split(/,/,$settings->{'cloners'}); + my @standardnames = &Apache::loncommon::get_standard_codeitems(); + my %local_to_standard; + for (my $i=0; $i<@code_order; $i++) { + $local_to_standard{$code_order[$i]} = $standardnames[$i]; + } + foreach my $cloner (@cloners) { + if (($cloner !~ /^\Q*:\E$match_domain$/) && + ($cloner !~ /^$match_username\:$match_domain$/)) { + foreach my $item (split(/\&/,$cloner)) { + my ($key,$val) = split(/\=/,$item); + $val = &unescape($val); + foreach my $code (@code_order) { + if ($key eq $local_to_standard{$code}) { + $env{'form.'.$key} = $val; + } + } + } + } + } + } + } + } + } + my @codetitles; + (undef,$instcode_js) = + &Apache::courseclassifier::instcode_selectors($cdom,'display',undef, + \@codetitles); + $instcode_js .= <'. - "\n".$stubrowse_js."\n"; + '// '."\n". + ''."\n".$stubrowse_js."\n"; return $jscript; } @@ -1566,7 +1921,7 @@ function update_cloners(caller,num) { if (document.$formname.cloners_activate[i].value == '0') { document.$formname.cloners_activate[i].checked = false; } - if (document.$formname.cloners_activate[i].value == '') { + if (document.$formname.cloners_activate[i].value == '-1') { document.$formname.cloners_activate[i].checked = true; } } @@ -1619,29 +1974,82 @@ ENDSCRIPT sub print_courseinfo { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } - my ($cathash,$categoriesform,$autocoowner); + my ($cathash,$categoriesform,$autocoowner,$clonedefaults,$disabled); + if ($noedit) { + $disabled = ' disabled="disabled"'; + } my %domconf = - &Apache::lonnet::get_dom('configuration',['coursecategories','autoenroll'],$cdom); + &Apache::lonnet::get_dom('configuration', + ['coursecategories','autoenroll','coursedefaults'],$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'},$crstype)."\n"; + $settings->{'categories'},$crstype,$disabled)."\n"; } } if (ref($domconf{'autoenroll'}) eq 'HASH') { $autocoowner = $domconf{'autoenroll'}{'co-owners'}; } + my ($currcanclone,@code_order,$cloner_instcode); + my %codedefaults; + &Apache::lonnet::auto_instcode_defaults($cdom,\%codedefaults, + \@code_order); + if ($settings->{'cloners'}) { + unless ($settings->{'cloners'} eq '*') { + my @currclone = split(/,/,$settings->{'cloners'}); + foreach my $item (@currclone) { + unless ($item eq '*') { + if (($item !~ /\:/) && ($item =~ /=/)) { + $cloner_instcode = 1; + } + } + } + } + } + if (ref($domconf{'coursedefaults'}) eq 'HASH') { + my $canclone = $domconf{'coursedefaults'}{'canclone'}; + if (ref($canclone) eq 'HASH') { + if (ref($canclone->{'instcode'}) eq 'ARRAY') { + if ($settings->{'internal.coursecode'}) { + my @posscodes; + if (@code_order > 0) { + $currcanclone = 'instcode'; + foreach my $item (@{$canclone->{'instcode'}}) { + if (grep(/^\Q$item\E$/,@code_order)) { + push(@posscodes,$item); + } + } + my $codestr = join(' + ',@posscodes); + $clonedefaults = &mt('Default for official courses is to also allow cloning if [_1] match in cloner and cloned.', + '"'.$codestr.'"').'
'; + } + } + } + } elsif ($canclone eq 'domain') { + $clonedefaults = &mt('Default is for any course requester in [_1] domain to be able to clone.', + ''.$cdom.'').'
'; + $currcanclone = 'domain'; + } + if ($clonedefaults) { + if ($settings->{'cloners'} ne '') { + $clonedefaults .= '
'.&mt('Default does [_1]not[_2] currently apply because values have been set in the course.','',''); + } else { + $clonedefaults .= &mt('Default is disregarded if [_1]any[_2] values are set here in the course.','',''); + } + $clonedefaults = '

'.$clonedefaults; + } + } if (!defined($categoriesform)) { $categoriesform = &mt('No categories defined in this domain.'); } - my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype); + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $replace; if ($crstype eq 'Community') { @@ -1649,22 +2057,28 @@ sub print_courseinfo { } else { $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank'); } + my ($editmap,$editsyllabus); + unless ($noedit) { + $editmap = (' 'x2). + '". + &mt('Select Map').'
'. + &mt('Modification may make assessment data inaccessible!'). + ''; + $editsyllabus = &mt('[_1]Edit[_2]','', + ''); + } my %items = ( 'url' => { - text => ''.&mt($itemtext->{'url'}).''.(' 'x2). - '". - &mt('Select Map').'
'. - &mt('Modification may make assessment data inaccessible!'). - '', + text => ''.&mt($itemtext->{'url'}).''.$editmap, input => 'textbox', - size => '40', + size => '55', advanced => 1 }, 'description' => { text => ''.&mt($itemtext->{'description'}).'', input => 'textbox', - size => '25', + size => '55', }, 'owner' => { text => ''.&mt($itemtext->{'owner'}).'', @@ -1672,18 +2086,24 @@ sub print_courseinfo { 'co-owners' => { text => ''.&mt($itemtext->{'co-owners'}).'', }, + 'clonedfrom' => { + text => ''.&mt($itemtext->{'clonedfrom'}).'', + }, 'courseid' => { text => ''.&mt($itemtext->{'courseid'}).'
'.'('. &mt('internal, optional').')', input => 'textbox', size => '25', }, + 'uniquecode' => { + text => ''.&mt($itemtext->{'uniquecode'}).'', + }, 'cloners' => { text => ''.&mt($itemtext->{'cloners'}).'
'. - &mt('Owner and Coordinators included automatically'), + &mt('Owner and Coordinators included automatically'). + $clonedefaults, input => 'textbox', - size => '40', - advanced => 1 + size => '40' }, 'rolenames' => { text => ''.&mt($itemtext->{'rolenames'}).'
'. @@ -1693,10 +2113,9 @@ sub print_courseinfo { advanced => 1 }, 'externalsyllabus' => { - text => ''.&mt($itemtext->{'externalsyllabus'}).'
('. - &mt('not using syllabus template)'), - input => 'textbox', - size => '40', + text => ''.&mt($itemtext->{'externalsyllabus'}).'
'. + &mt('(Syllabus type in use)').(' ' x2). + $editsyllabus, }, 'hidefromcat' => { text => ''.&mt($itemtext->{'hidefromcat'}).'
'. @@ -1709,27 +2128,40 @@ sub print_courseinfo { input => 'textbox', size => '25', }, + 'loncaparev' => { + text => ''.&mt($itemtext->{'loncaparev'}).'', + }, + 'defaultcredits' => { + text => ''.&mt($itemtext->{'defaultcredits'}).'', + }, ); my $datatable; my $count = 0; foreach my $item (@{$ordered}) { + my $colspan; if ($item eq 'hidefromcat') { next if (!$can_toggle_cat); } elsif ($item eq 'categories') { next if (!$can_categorize); + } elsif ($item eq 'uniquecode') { + next if (!$env{'course.'.$env{'request.course.id'}.'.internal.uniquecode'}); + } + unless (($item eq 'cloners') || ($item eq 'rolenames')) { + $colspan = 2; } $count ++; if (exists $items{$item}{advanced} && $items{$item}{advanced} == 1) { - $datatable .= &item_table_row_start($items{$item}{text},$count,"advanced"); + $datatable .= &item_table_row_start($items{$item}{text},$count,"advanced",$colspan); } else { - $datatable .= &item_table_row_start($items{$item}{text},$count); + $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan); } if ($items{$item}{input} eq 'radio') { - $datatable .= &yesno_radio($item,$settings); + $datatable .= &yesno_radio($item,$settings,undef,undef,undef,$noedit); } elsif ($item eq 'cloners') { my $includeempty = 1; my $num = 0; - $datatable .= &Apache::loncommon::start_data_table(). + $datatable .= '
'. + &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_row(). ''. - (' 'x2).''.&mt('Yes').''. + (' 'x2).'
'.&mt('Or'). - '
'. + '
'.&mt('Or'). + '
'. &Apache::loncommon::start_data_table(); my @cloners; if ($settings->{$item} eq '') { - $datatable .= &new_cloners_dom_row($cdom,'0'); + unless ($noedit) { + my $default; + if ($currcanclone eq 'domain') { + $default = '0'; + } + $datatable .= &new_cloners_dom_row($cdom,'0',$default); + } } elsif ($settings->{$item} ne '*') { my @entries = split(/,/,$settings->{$item}); if (@entries > 0) { @@ -1773,7 +2212,7 @@ sub print_courseinfo { '
'. ''. &Apache::loncommon::end_data_table_row(); $num ++; @@ -1796,23 +2235,56 @@ sub print_courseinfo { ''. $add_domtitle.'
'. &Apache::loncommon::select_dom_form('','cloners_newdom', - $includeempty). + $includeempty,undef,undef, + undef,undef,$noedit). ''. ''.&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(). - '
'.&mt('And'). - '
'. + '
'.&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'}). + $items{$item}{'size'},$disabled). ''.&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); + if (@code_order > 0) { + my (%cat_items,@codetitles,%cat_titles,%cat_order); + my ($jscript,$totcodes,$numtitles,$lasttitle) = + &Apache::courseclassifier::instcode_selectors_data($cdom,'display', + \%cat_items,\@codetitles, + \%cat_titles,\%cat_order); + my $showncodes = 'off'; + my $checkedoff = ' checked="checked"'; + my $checkedon = ''; + if ($cloner_instcode) { + $checkedon = $checkedoff; + $checkedoff = ''; + $showncodes = 'on'; + } + $datatable .= '
'.&mt('And'). + '
'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(). + ''. + &mt('Cloning by official course(s) based on course category').(' 'x2). + ''. + (' '). + ''. + &Apache::courseclassifier::build_instcode_selectors($numtitles, + $lasttitle,\%cat_items,\@codetitles,\%cat_titles,\%cat_order, + $showncodes,'LC_cloners_instcodes','LC_cloners_instcode',$noedit). + ''.&Apache::loncommon::end_data_table_row(). + &Apache::loncommon::end_data_table(); + } } elsif ($item eq 'rolenames') { - $datatable .= &Apache::loncommon::start_data_table(); + $datatable .= ''. + &Apache::loncommon::start_data_table(); my @roles; if ($crstype eq 'Community') { @roles = ('co'); @@ -1827,12 +2299,17 @@ sub print_courseinfo { ''. &Apache::lonhtmlcommon::textbox('rolenames_'.$role, $settings->{$role.'.plaintext'}, - $items{$item}{size}).''. + $items{$item}{size},$disabled).''. &Apache::loncommon::end_data_table_row(); } $datatable .= &Apache::loncommon::end_data_table().''; } elsif ($item eq 'categories') { - my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";'; + my $launcher; + if ($noedit) { + $launcher = $disabled; + } else { + $launcher = 'onfocus="this.blur();javascript:catsbrowser();"'; + } $datatable .= ''. &Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item}, $items{$item}{size},$launcher); @@ -1846,10 +2323,23 @@ sub print_courseinfo { } else { $owner = &mt('None specified'); } - my $domdesc = &Apache::lonnet::domain($cdom,'description'); $datatable .= $owner; + } elsif ($item eq 'clonedfrom') { + my $clonesrc = $env{'course.'.$env{'request.course.id'}.'.clonedfrom'}; + my $clonedfrom = &mt('None'); + if ($clonesrc =~ m{/$match_domain/$match_courseid}) { + my %clonesrcinfo = &Apache::lonnet::coursedescription($clonesrc); + if ($clonesrcinfo{'description'}) { + $clonedfrom = $clonesrcinfo{'description'}.' '.($clonesrc); + } + } + $datatable .= $clonedfrom; + } elsif ($item eq 'uniquecode') { + my $code = $env{'course.'.$env{'request.course.id'}.'.internal.uniquecode'}; + if ($code) { + $datatable .= $code; + } } 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) { @@ -1859,17 +2349,57 @@ sub print_courseinfo { if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) { $datatable .= &show_autocoowners(@currcoown); } else { - $datatable .= &coowner_invitations($cnum,$cdom,@currcoown); + $datatable .= &coowner_invitations($cnum,$cdom,\@currcoown,$noedit); } } 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); + $datatable .= &manage_coownership($cnum,$cdom,\@currcoown,$noedit); } } + } elsif ($item eq 'externalsyllabus') { + my $external = $env{'course.'.$env{'request.course.id'}.'.externalsyllabus'}; + my $uploaded = $env{'course.'.$env{'request.course.id'}.'.uploadedsyllabus'}; + my $minimal = $env{'course.'.$env{'request.course.id'}.'.minimalsyllabus'}; + if (($minimal =~/\w/) || ($uploaded =~/\w/)) { + if ($minimal =~/\w/) { + if ($external =~ m{\Q$minimal\E$}) { + undef($external); + } + } elsif ($uploaded =~/\w/) { + if ($external =~ m{\Q$uploaded\E$}) { + undef($external); + } + } + } elsif ($external!~/\w/) { + undef($external); + } + if ($external) { + $datatable .= &mt('External URL'); + } elsif ($minimal) { + $datatable .= &mt('Minimal template'); + } elsif ($uploaded) { + $datatable .= &mt('Uploaded file'); + } else { + $datatable .= &mt('Standard template'); + } + $datatable .= (' ' x 2). + &mt('[_1]View[_2]', + '', + ''); + } elsif ($item eq 'loncaparev') { + my $loncaparev = $env{'course.'.$env{'request.course.id'}.'.internal.releaserequired'}; + my $showreqd; + if ($loncaparev) { + $showreqd = &mt('[_1] or newer',$loncaparev).' '. + &mt('Details').''; + } else { + $showreqd = &mt('No specific version required'); + } + $datatable .= $showreqd; } else { - $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size}); + $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size},$disabled); } $datatable .= &item_table_row_end(); } @@ -1878,19 +2408,24 @@ sub print_courseinfo { } sub new_cloners_dom_row { - my ($newdom,$num) = @_; - my $output; + my ($newdom,$num,$default) = @_; + my ($output,$checkedon,$checkedoff); if ($newdom ne '') { + if ($num eq $default) { + $checkedon = 'checked="checked" '; + } else { + $checkedoff = 'checked="checked" '; + } $output .= &Apache::loncommon::start_data_table_row(). ''. &mt('Any user in domain:').' '.$newdom.''. (' 'x2).''.(' 'x2). ' @@ -2025,9 +2561,695 @@ ENDSCRIPT return; } +sub display_loncaparev_constraints { + my ($r,$navmap,$loncaparev,$crstype) = @_; + my ($reqdmajor,$reqdminor); + my $cid = $env{'request.course.id'}; + my $cdom = $env{'course.'.$cid.'.domain'}; + my $cnum = $env{'course.'.$cid.'.num'}; + my $output; + my %lt = &Apache::lonlocal::texthash ( + 'all' => 'all', + 'section/group' => 'section/group', + 'user' => 'user', + ); + &Apache::lonrelrequtils::init_global_hashes(); + if (defined($Apache::lonrelrequtils::checkcrstypes{$crstype})) { + ($reqdmajor,$reqdminor) = split(/\./,$Apache::lonrelrequtils::checkcrstypes{$crstype}); + $output .= '

'.&mt('Course type: [_1] requires [_2] or newer',$crstype, + $Apache::lonrelrequtils::checkcrstypes{$crstype}).'

'; + } + my (%fromparam,%rowspan,%bymap,%byresource,@scopeorder,%toshow,%allmaps, + %byresponsetype,%bysubmission,%fromblocks); + @scopeorder = ('all','section/group','user'); + my $now = time; + my $resourcedata = &Apache::lonparmset::readdata($cnum,$cdom); + if (ref($resourcedata) eq 'HASH') { + foreach my $key (keys(%{$resourcedata})) { + my %found; + foreach my $item (keys(%Apache::lonrelrequtils::checkparms)) { + if ($key =~ /(\Q$item\E)$/) { + if (ref($Apache::lonrelrequtils::checkparms{$item}) eq 'ARRAY') { + my $value = $resourcedata->{$key}; + if ($item eq 'examcode') { + if (&Apache::lonnet::validCODE($value)) { + $value = 'valid'; + } else { + $value = ''; + } + } elsif ($item eq 'printstartdate') { + if ($value =~ /^\d+$/) { + if ($value > $now) { + $value = 'future'; + } + } + } elsif ($item eq 'printenddate') { + if ($value =~ /^\d+$/) { + if ($value < $now) { + $value = 'past'; + } + } + } + if (grep(/^\Q$value\E$/,@{$Apache::lonrelrequtils::checkparms{$item}})) { + my $stdtype = &Apache::lonparmset::standard_parameter_types($item); + $found{$item}{'valname'} = &get_param_description($stdtype,$value); + $found{$item}{'rev'} = $Apache::lonnet::needsrelease{'parameter:'.$item.':'.$value.'::'}; + } + } + } + } + foreach my $item (keys(%Apache::lonrelrequtils::checkparmvalsmatch)) { + if (ref($Apache::lonrelrequtils::checkparmvalsmatch{$item}) eq 'ARRAY') { + my $value = $resourcedata->{$key}; + foreach my $valuematch (@{$Apache::lonrelrequtils::checkparmvalsmatch{$item}}) { + if ($value =~ /$valuematch/) { + my $stdtype = &Apache::lonparmset::standard_parameter_types($item); + $found{$item}{'valname'} = &get_param_description($stdtype,$value,1); + $found{$item}{'rev'} = + $Apache::lonnet::needsrelease{'parameter:'.$item.'::'.$valuematch.':'}; + last; + } + } + } + } + foreach my $item (keys(%Apache::lonrelrequtils::checkparmnamesmatch)) { + my $regexp; + if ($item eq 'maplevelrecurse') { + $regexp = '\.(?:sequence|page)___\(rec\)\.'; + } + if ($regexp ne '') { + if ($key =~ /$regexp.*\.(\w+)$/) { + my $name = $1; + my $value = $resourcedata->{$key}; + if ($name eq 'type') { + last unless (($value eq 'problem') || ($value eq 'practice') || ($value eq 'exam') || + ($value eq 'survey') || ($value eq 'surveycred') || ($value eq 'anonsurvey') || + ($value eq 'anonsurveycred') || ($value eq 'randomizetry') || ($value eq 'library')); + } + my $stdtype = &Apache::lonparmset::standard_parameter_types($name); + $found{$name}{'valname'} = &get_param_description($stdtype,$value); + $found{$name}{'extra'} = &mt('Recursive into sub-folders'); + $found{$name}{'rev'} = + $Apache::lonnet::needsrelease{'parameter::::'.$item}; + } + } + } + foreach my $item (keys(%found)) { + my $stdname = &Apache::lonparmset::standard_parameter_names($item); + my $rev = $found{$item}{'rev'}; + my $valname = $found{$item}{'valname'}; + my $extra = $found{$item}{'extra'}; + my ($middle,$scope,$which,$level,$map,$resource); + my $start = $cid.'.'; + if ($key =~ /^\Q$start\E(\[useropt\:($match_username\:$match_domain)\]\.)/) { + $middle = $1; + $which = $2; + $scope = 'user'; + } elsif ($key =~ /^\Q$start\E(\[(\w+)\]\.)/) { + $middle = $1; + $which = $2; + $scope = 'section/group'; + } else { + $scope = 'all'; + } + my $what="$stdname=$valname"; + if ($extra) { + $what .= "
$extra
"; + } + if ($key =~ /^\Q$start$middle\E\w+\.\Q$item\E$/) { + $level = 'general'; + if ($scope eq 'all') { + if (ref($fromparam{$rev}{$scope}) eq 'ARRAY') { + unless(grep(/^\Q$what\E$/,@{$fromparam{$rev}{$scope}})) { + push(@{$fromparam{$rev}{$scope}},$what); + } + } else { + push(@{$fromparam{$rev}{$scope}},$what); + } + } else { + if (ref($fromparam{$rev}{$scope}{$which}) eq 'ARRAY') { + unless (grep(/^\Q$what\E$/,@{$fromparam{$rev}{$scope}{$which}})) { + push(@{$fromparam{$rev}{$scope}{$which}},$what); + } + } else { + push(@{$fromparam{$rev}{$scope}{$which}},$what); + } + } + $rowspan{$rev} ++; + } elsif ($key =~ /^\Q$start$middle\E(.+)___\((all|rec)\).\w+\.\Q$item\E$/) { + $level = 'folder'; + $map = $1; + if ($scope eq 'all') { + if (ref($bymap{$map}{$rev}{$scope}) eq 'ARRAY') { + unless(grep(/^\Q$what\E$/,@{$bymap{$map}{$rev}{$scope}})) { + push(@{$bymap{$map}{$rev}{$scope}},$what); + } + } else { + push(@{$bymap{$map}{$rev}{$scope}},$what); + } + } else { + if (ref($bymap{$map}{$rev}{$scope}{$which}) eq 'ARRAY') { + unless(grep(/^\Q$what\E$/,@{$bymap{$map}{$rev}{$scope}{$which}})) { + push(@{$bymap{$map}{$rev}{$scope}{$which}},$what); + } + } else { + push(@{$bymap{$map}{$rev}{$scope}{$which}},$what); + } + } + } elsif ($key =~ /^\Q$start$middle\E(.+)\.\w+\.\Q$item\E$/) { + $level = 'resource'; + $resource = $1; + if ($scope eq 'all') { + if (ref($byresource{$resource}{$rev}{$scope}) eq 'ARRAY') { + unless(grep(/^\Q$what\E$/,@{$byresource{$resource}{$rev}{$scope}})) { + push(@{$byresource{$resource}{$rev}{$scope}},$what); + } + } else { + push(@{$byresource{$resource}{$rev}{$scope}},$what); + } + } else { + if (ref($byresource{$resource}{$rev}{$scope}{$which}) eq 'ARRAY') { + unless (grep(/^\Q$what\E$/,@{$byresource{$resource}{$rev}{$scope}{$which}})) { + push(@{$byresource{$resource}{$rev}{$scope}{$which}},$what); + } + } else { + push(@{$byresource{$resource}{$rev}{$scope}{$which}},$what); + } + } + } + } + } + if (keys(%fromparam)) { + $output .= '

'.&mt('Requirements from general settings').'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ''.&mt('Release').''.&mt('Scope').''. + ''.&mt('Extent').''.&mt('Setting').''. + &Apache::loncommon::end_data_table_header_row(); + foreach my $rev (keys(%fromparam)) { + my ($major,$minor) = split(/\./,$rev); + ($reqdmajor,$reqdminor) = + &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor); + $output .= &Apache::loncommon::start_data_table_row(). + ''.$rev.''; + my $newrow; + foreach my $scope (@scopeorder) { + if (ref($fromparam{$rev}{$scope}) eq 'HASH') { + if ($newrow) { + $output .= &Apache::loncommon::continue_data_table_row(); + } + $output .= ''.$lt{$scope}.''; + foreach my $which (sort(keys(%{$fromparam{$rev}{$scope}}))) { + $output .= ''.$which.''. + join('
',@{$fromparam{$rev}{$scope}{$which}}).''; + } + $output .= &Apache::loncommon::end_data_table_row(); + $newrow = 1; + } elsif (ref($fromparam{$rev}{$scope}) eq 'ARRAY') { + if ($newrow) { + $output .= &Apache::loncommon::continue_data_table_row(); + } + $output .= ''.$lt{$scope}.' '. + join('
',@{$fromparam{$rev}{$scope}}).''. + &Apache::loncommon::end_data_table_row(); + $newrow = 1; + } + } + } + $output .= &Apache::loncommon::end_data_table().'
'; + } + } + + my %comm_blocks = &Apache::lonnet::dump('comm_block',$cdom,$cnum); + my $now = time; + if (keys(%comm_blocks) > 0) { + foreach my $block (keys(%comm_blocks)) { + if ($block =~ /^firstaccess____(.+)$/) { + my $rev = $Apache::lonnet::needsrelease{'course:commblock:timer'}; + if (ref($comm_blocks{$block}) eq 'HASH') { + push(@{$fromblocks{'timer'}{$rev}},&unescape($comm_blocks{$block}{'event'}). + ' '.&mt('set by [_1]', + &Apache::loncommon::plainname(split(/:/,$comm_blocks{$block}{'setter'})))); + } + next; + } elsif ($block =~ /^(\d+)____(\d+)$/) { + my ($start,$end) = ($1,$2); + next if ($end < $now); + } + if (ref($comm_blocks{$block}) eq 'HASH') { + if (ref($comm_blocks{$block}{'blocks'}) eq 'HASH') { + if (ref($comm_blocks{$block}{'blocks'}{'docs'}) eq 'HASH') { + if (keys(%{$comm_blocks{$block}{'blocks'}{'docs'}}) > 0) { + my $rev = $Apache::lonnet::needsrelease{'course:commblock:docs'}; + push(@{$fromblocks{'docs'}{$rev}},&unescape($comm_blocks{$block}{'event'}). + ' '. + &mt('set by [_1]', + &Apache::loncommon::plainname(split(/:/,$comm_blocks{$block}{'setter'})))); + } + } elsif ($comm_blocks{$block}{'blocks'}{'printout'} eq 'on') { + my $rev = $Apache::lonnet::needsrelease{'course:commblock:printout'}; + push(@{$fromblocks{'printout'}{$rev}},&unescape($comm_blocks{$block}{'event'}). + ' '. + &mt('set by [_1]', + &Apache::loncommon::plainname(split(/:/,$comm_blocks{$block}{'setter'})))); + + } + } + } + } + if (keys(%fromblocks)) { + my %lt = ( + docs => 'Content blocking', + printout => 'Printout generation', + timer => 'Timed quiz trigger', + ); + $output .= '

'.&mt('Requirements from exam blocking').'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ''.&mt('Release').''.&mt('Setting').''. + ''.&mt('Event(s)').''. + &Apache::loncommon::end_data_table_header_row(); + foreach my $type ('docs','printout','timer') { + if (ref($fromblocks{$type}) eq 'HASH') { + foreach my $rev (keys(%{$fromblocks{$type}})) { + my ($major,$minor) = split(/\./,$rev); + ($reqdmajor,$reqdminor) = + &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor); + $output .= &Apache::loncommon::start_data_table_row(). + ''.$rev.''.$lt{$type}.''; + foreach my $event (sort(@{$fromblocks{$type}{$rev}})) { + $output .= $event.'
'; + } + $output =~ s{\Q
\E$}{}; + $output .= ''.&Apache::loncommon::end_data_table_row(); + } + } + } + $output .= &Apache::loncommon::end_data_table().'
'; + } + } + + if (defined($navmap)) { + my %anonsubms=&Apache::lonnet::dump('nohist_anonsurveys',$cdom,$cnum); + my $rev_anonsurv=$Apache::lonnet::needsrelease{'parameter:type:anonsurvey::'}; + my %randtrysubms=&Apache::lonnet::dump('nohist_randomizetry',$cdom,$cnum); + my $rev_randtry=$Apache::lonnet::needsrelease{'parameter:type:randomizetry::'}; + my $stdtype=&Apache::lonparmset::standard_parameter_types('type'); + my $stdname=&Apache::lonparmset::standard_parameter_names('type'); + my $valanon=&get_param_description($stdtype,'anonsurvey'); + my $valrandtry=&get_param_description($stdtype,'randomizetry'); + my %checkedrev; + foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_problem() },1,0)) { + my @parts = @{$res->parts()}; + my $symb = $res->symb(); + my $enclosing_map = &Apache::lonnet::declutter($res->enclosing_map_src()); + foreach my $part (@parts) { + if (exists($anonsubms{$symb."\0".$part})) { + my $rev = $rev_anonsurv; + my $what="$stdname=$valanon"; + if (ref($bysubmission{$symb}{$rev}) eq 'ARRAY') { + unless (grep(/^\Q$what\E/,@{$bysubmission{$symb}{$rev}})) { + push(@{$bysubmission{$symb}{$rev}},$what); + } + } else { + push(@{$bysubmission{$symb}{$rev}},$what); + } + $allmaps{$enclosing_map} = 1; + unless ($checkedrev{'anonsurvey'}) { + my ($major,$minor) = split(/\./,$rev); + ($reqdmajor,$reqdminor) = + &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor, + $reqdmajor,$reqdminor); + $checkedrev{'anonsurvey'} = 1; + } + } + if (exists($randtrysubms{$symb."\0".$part})) { + my $rev = $rev_randtry; + my $what="$stdname=$valrandtry"; + if (ref($bysubmission{$symb}{$rev}) eq 'ARRAY') { + unless (grep(/^\Q$what\E/,@{$bysubmission{$symb}{$rev}})) { + push(@{$bysubmission{$symb}{$rev}},$what); + } + } else { + push(@{$bysubmission{$symb}{$rev}},$what); + } + $allmaps{$enclosing_map} = 1; + unless ($checkedrev{'randomizetry'}) { + my ($major,$minor) = split(/\./,$rev); + ($reqdmajor,$reqdminor) = + &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor, + $reqdmajor,$reqdminor); + $checkedrev{'randomizetry'} = 1; + } + } + } + my %responses = $res->responseTypes(); + foreach my $key (keys(%responses)) { + if (exists($Apache::lonrelrequtils::checkresponsetypes{$key})) { + my $rev = $Apache::lonrelrequtils::checkresponsetypes{$key}; + unless ($checkedrev{$key}) { + my ($major,$minor) = split(/\./,$rev); + ($reqdmajor,$reqdminor) = + &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor, + $reqdmajor,$reqdminor); + $checkedrev{$key} = 1; + } + push(@{$byresponsetype{$symb}{$rev}},$key); + $allmaps{$enclosing_map} = 1; + } + } + } + if (keys(%byresource) > 0) { + foreach my $symb (keys(%byresource)) { + my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb); + $allmaps{$map} = 1; + } + } + if (keys(%bymap) > 0) { + foreach my $map (keys(%bymap)) { + $allmaps{$map} = 1; + } + } + foreach my $map (keys(%allmaps)) { + my $mapres = $navmap->getResourceByUrl($map); + if (ref($mapres)) { + my $mapsymb = $mapres->symb(); + $toshow{$mapsymb} = 1; + my $pcslist = $mapres->map_hierarchy(); + if ($pcslist ne '') { + foreach my $pc (split(/,/,$pcslist)) { + my $res = $navmap->getByMapPc($pc); + if (ref($res)) { + my $symb = $res->symb(); + unless ($symb eq '______') { + $toshow{$symb} = 1; + } + } + } + } + } + } + } + my $mapres_header = '

'. + &mt('Requirements for specific folders or resources'). + '

'; + if ((keys(%toshow) > 0) || (keys(%byresource) > 0) || + (keys(%bysubmission) > 0) || (keys(%byresponsetype))) { + $output .= $mapres_header; + } + my $top_header = '

'.&mt('LON-CAPA version dependencies').'

'; + my $title = 'Version Constraints'; + my $start_page = + &Apache::loncommon::start_page($title,undef,{'only_body' => 1,}); + $r->print($start_page.$top_header); + if ($output) { + $r->print($output); + if (defined($navmap)) { + &show_contents_view($r,$navmap,$cid,\%toshow,\%bymap,\%byresource,\%bysubmission, + \%byresponsetype,\@scopeorder,\%lt); + } + $r->print('

'); + } else { + $r->print('

'. + &mt('No version requirements from resource content or settings.'). + '

'); + } + $r->print(&Apache::loncommon::end_page()); + my ($currmajor,$currminor) = split(/\./,$loncaparev); + if (($currmajor != $reqdmajor) || ($currminor != $reqdminor)) { + return 1; + } + return; +} + +sub show_contents_view { + my ($r,$navmap,$cid,$toshow,$bymap,$byresource,$bysubmission,$byresponsetype, + $scopeorder,$lt) = @_; + if ((keys(%{$toshow}) > 0) || (keys(%{$byresource}) > 0) || + (keys(%{$bysubmission}) > 0) || (keys(%{$byresponsetype}) > 0)) { + my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons"); + my $whitespace = ''; + my $icon = ''; + my $topmap = $env{'course.'.$cid.'.url'}; + $r->print(&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ''.&mt('Location').''.&mt('Release').''. + ''.&mt('Attribute/Setting').''. + &Apache::loncommon::end_data_table_header_row(). + &Apache::loncommon::start_data_table_row(). + ' '.$icon.' '.&mt('Main Content').''); + &releases_by_map($r,$bymap,$topmap,$scopeorder,$lt); + $r->print(&Apache::loncommon::end_data_table_row()); + my $it=$navmap->getIterator(undef,undef,undef,1,1,undef); + my $curRes; + my $depth = 0; + my %parent = (); + my $startcount = 5; + my $lastcontainer = $startcount; + while ($curRes = $it->next()) { + if ($curRes == $it->BEGIN_MAP()) { + $depth++; + $parent{$depth}= $lastcontainer; + } + if ($curRes == $it->END_MAP()) { + $depth--; + $lastcontainer = $parent{$depth}; + } + my $indent; + for (my $i=0; $i<$depth; $i++) { + $indent.= $whitespace; + } + if (ref($curRes)) { + my $symb = $curRes->symb(); + my $ressymb = $symb; + my $srcf = $curRes->src(); + my $title = &Apache::lonnet::gettitle($srcf); + if (($curRes->is_sequence()) || ($curRes->is_page())) { + next unless($toshow->{$symb}); + my ($parent,$ind,$url) = &Apache::lonnet::decode_symb($symb); + $icon = ''; + if ($curRes->is_page()) { + $icon = ''; + } + my $rowspan = 1; + if (ref($bymap->{$url}) eq 'HASH') { + $rowspan = scalar(keys(%{$bymap->{$url}})); + } + $r->print(&Apache::loncommon::start_data_table_row(). + ''.$indent.$icon.' '.$title.''); + &releases_by_map($r,$bymap,$url,$scopeorder,$lt); + $r->print(&Apache::loncommon::end_data_table_row()); + } else { + my $rowspan; + if (ref($byresource->{$symb}) eq 'HASH') { + $rowspan += scalar(keys(%{$byresource->{$symb}})); + } + if (ref($bysubmission->{$symb}) eq 'HASH') { + $rowspan += scalar(keys(%{$bysubmission->{$symb}})); + } + if (ref($byresponsetype->{$symb}) eq 'HASH') { + $rowspan += scalar(keys(%{$byresponsetype->{$symb}})); + } + next if (!$rowspan); + $icon = ''.
+                            &mt('Problem').''; + $r->print(&Apache::loncommon::start_data_table_row(). + ''.$indent.$icon.' '.$title.''); + my $newrow; + if (ref($byresource->{$symb}) eq 'HASH') { + foreach my $rev (sort(keys(%{$byresource->{$symb}}))) { + if ($newrow) { + $r->print(&Apache::loncommon::continue_data_table_row()); + } + $r->print(''.$rev.''); + if (ref($byresource->{$symb}{$rev}) eq 'HASH') { + $r->print(''); + foreach my $scope (@{$scopeorder}) { + if (ref($byresource->{$symb}{$rev}{$scope}) eq 'HASH') { + $r->print(''); + foreach my $which (sort(keys(%{$byresource->{$symb}{$rev}{$scope}}))) { + $r->print(''); + } + $r->print(''); + } elsif (ref($byresource->{$symb}{$rev}{$scope}) eq 'ARRAY') { + $r->print(''. + ''); + } + } + $r->print('
'.&mt('Setting - scope: [_1]',$lt->{$scope}).''.$which.''. + join('
',@{$byresource->{$symb}{$rev}{$scope}{$which}}). + '
'.&mt('Setting - scope: [_1]',$lt->{$scope}).' '. + join('
',@{$byresource->{$symb}{$rev}{$scope}}).'
'); + } + $r->print(''); + $r->print(&Apache::loncommon::end_data_table_row()); + $newrow = 1; + } + } + if (ref($bysubmission->{$symb}) eq 'HASH') { + foreach my $rev (sort(keys(%{$bysubmission->{$symb}}))) { + if ($newrow) { + $r->print(&Apache::loncommon::continue_data_table_row()); + } + $r->print(''.$rev.''); + if (ref($bysubmission->{$symb}{$rev}) eq 'ARRAY') { + $r->print(&mt('Submissions to: ').' '. + join(', ',@{$bysubmission->{$symb}{$rev}})); + } + $r->print(''); + $r->print(&Apache::loncommon::end_data_table_row()); + $newrow = 1; + } + } + if (ref($byresponsetype->{$symb}) eq 'HASH') { + foreach my $rev (sort(keys(%{$byresponsetype->{$symb}}))) { + if ($newrow) { + $r->print(&Apache::loncommon::continue_data_table_row()); + } + $r->print(''.$rev.''); + if (ref($byresponsetype->{$symb}{$rev}) eq 'ARRAY') { + $r->print(&mt('Response Type(s): ').' '. + join('
',@{$byresponsetype->{$symb}{$rev}})); + } + $r->print(''); + } + $r->print(&Apache::loncommon::end_data_table_row()); + } + } + } + } + $r->print(&Apache::loncommon::end_data_table()); + } + return; +} + +sub releases_by_map { + my ($r,$bymap,$url,$scopeorder,$lt) = @_; + return unless ((ref($bymap) eq 'HASH') && (ref($scopeorder) eq 'ARRAY')); + my $newrow = 0; + if (ref($bymap->{$url}) eq 'HASH') { + foreach my $rev (sort(keys(%{$bymap->{$url}}))) { + if ($newrow) { + $r->print(&Apache::loncommon::end_data_table_row(). + &Apache::loncommon::continue_data_table_row()); + } + $r->print(''.$rev.''); + if (ref($bymap->{$url}{$rev}) eq 'HASH') { + $r->print(''); + foreach my $scope (@{$scopeorder}) { + if (ref($bymap->{$url}{$rev}{$scope}) eq 'HASH') { + $r->print(''); + foreach my $which (sort(keys(%{$bymap->{$url}{$rev}{$scope}}))) { + $r->print(''); + } + $r->print(''); + } elsif (ref($bymap->{$url}{$rev}{$scope}) eq 'ARRAY') { + $r->print(''); + } + } + $r->print('
'.&mt('Setting - scope: [_1]',$lt->{$scope}).''.$which.''. + join('
',@{$bymap->{$url}{$rev}{$scope}{$which}}). + '
'.&mt('Setting - scope: [_1]',$lt->{$scope}). + ' '. + join('
',@{$bymap->{$url}{$rev}{$scope}}).'
'); + } + $r->print(''); + $newrow = 1; + } + } else { + $r->print(' '); + } + return; +} + +sub get_param_description { + my ($stdtype,$value,$regexp) = @_; + my ($name,$parammatches,$paramstrings,@possibles); + if ($stdtype =~ /^string/) { + $paramstrings = &Apache::lonparmset::standard_string_options($stdtype); + } elsif ($stdtype eq 'date_interval') { + $paramstrings = &Apache::lonparmset::standard_interval_options($stdtype); + } + if ($regexp) { + if ($stdtype =~ /^string/) { + $parammatches = &Apache::lonparmset::standard_string_matches($stdtype); + } elsif ($stdtype eq 'date_interval') { + $parammatches = &Apache::lonparmset::standard_interval_matches($stdtype); + } + if (ref($parammatches) eq 'ARRAY') { + @possibles = @{$parammatches}; + } else { + undef($regexp); + $name = $value; + } + } + unless ($regexp) { + $name = $value; + if (ref($paramstrings) eq 'ARRAY') { + @possibles = @{$paramstrings}; + } else { + if (($stdtype eq 'date_start') || ($stdtype eq 'date_end')) { + if ($name == 0) { + $name = &mt('Never'); + } elsif (($name ne '') && ($name !~ /\D/)) { + $name = &Apache::lonlocal::locallocaltime($name); + } + } + return $name; + } + } + foreach my $possibilities (@possibles) { + next unless (ref($possibilities) eq 'ARRAY'); + my $gotregexmatch = ''; + if ($regexp) { + last if ($gotregexmatch); + my ($item,$pattern) = @{ $possibilities }; + if ($value =~ /$pattern/) { + if (ref($paramstrings) eq 'ARRAY') { + foreach my $possibles (@{$paramstrings}) { + next unless (ref($possibles) eq 'ARRAY'); + my ($thing,$description) = @{$possibles}; + if ($thing eq $item) { + $name = $description; + $gotregexmatch = 1; + last; + } + } + last if ($gotregexmatch); + } + } + } else { + my ($thing,$description) = @{ $possibilities }; + if ($thing eq $value) { + $name = $description; + last; + } + } + } + return $name; +} + +sub update_releasereq { + my $readmap = 1; + my $getrelreq = 1; + if (ref($modified_courses) eq 'ARRAY') { + foreach my $item (@{$modified_courses}) { + if (ref($item) eq 'ARRAY') { + my ($cdom,$cnum,$chome,$crstype) = @{$item}; + &Apache::lonrelrequtils::modify_course_relreq(undef,undef,$cnum,$cdom, + $chome,$crstype,$cdom.'_'.$cnum, + $readmap,$getrelreq); + } + } + $modified_courses = []; + } + undef($registered_cleanup); + 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).').''; + my $output = ''.&mt('Co-ownership is set automatically when a Course Coordinator role[_1] 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)); @@ -2038,13 +3260,20 @@ sub show_autocoowners { } sub coowner_invitations { - my ($cnum,$cdom,@currcoown) = @_; - my ($output,@pendingcoown,@othercoords); + my ($cnum,$cdom,$currcoownref,$noedit) = @_; + my ($output,@pendingcoown,@othercoords,@currcoown); my $pendingcoowners = $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'}; if ($pendingcoowners) { @pendingcoown = split(',',$pendingcoowners); } + if (ref($currcoownref) eq 'ARRAY') { + @currcoown == @{$currcoownref}; + } + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } my $ccrole = 'cc'; my %ccroles = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,undef,[$ccrole]); foreach my $key (sort(keys(%ccroles))) { @@ -2062,7 +3291,7 @@ sub coowner_invitations { ''.&mt('Current co-owners').''; foreach my $person (@currcoown) { my ($co_uname,$co_dom) = split(':',$person); - $output .= ''.(' 'x2).' '; + $output .= ''.(' 'x2).' '; } $output .= ''. &Apache::loncommon::end_data_table_row(); @@ -2072,7 +3301,7 @@ sub coowner_invitations { ''.&mt('Invited as co-owners [_1](agreement pending)','
').'
'; foreach my $person (@pendingcoown) { my ($co_uname,$co_dom) = split(':',$person); - $output .= ''.(' 'x2).' '; + $output .= ''.(' 'x2).' '; } $output .= ''. &Apache::loncommon::end_data_table_row(); @@ -2082,7 +3311,7 @@ sub coowner_invitations { ''.&mt('Invite other Coordinators [_1]to become co-owners','
').'
'; foreach my $person (@othercoords) { my ($co_uname,$co_dom) = split(':',$person); - $output .= ''.(' 'x2).' '; + $output .= ''.(' 'x2).' '; } $output .= ''. &Apache::loncommon::end_data_table_row(); @@ -2095,13 +3324,20 @@ sub coowner_invitations { } sub manage_coownership { - my ($cnum,$cdom,@currcoown) = @_; - my (@pendingcoown); + my ($cnum,$cdom,$currcoownref,$noedit) = @_; + my (@pendingcoown,@currcoown); my $pendingcoowners = $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'}; if ($pendingcoowners) { @pendingcoown = split(',',$pendingcoowners); } + if (ref($currcoownref) eq 'ARRAY') { + @currcoown == @{$currcoownref}; + } + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } my ($is_coowner,$is_pending,$output); my $uname = $env{'user.name'}; my $udom = $env{'user.domain'}; @@ -2133,8 +3369,8 @@ sub manage_coownership { 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 .= &mt('The course owner has invited you to become a co-owner:').' '.(' 'x2). + ''; } $output .= '
'; if (@currcoown) { @@ -2148,7 +3384,7 @@ sub manage_coownership { } sub print_localization { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2167,17 +3403,24 @@ sub print_localization { input => 'selectbox', }, ); - my $datatable; + my ($datatable,$disabled); my $count = 0; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } foreach my $item (@{$ordered}) { $count ++; - $datatable .= &item_table_row_start($items{$item}{text},$count); + my $colspan; + unless ($item eq 'languages') { + $colspan = 2; + } + $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan); if ($item eq 'timezone') { my $includeempty = 1; my $timezone = &Apache::lonlocal::gettimezone(); $datatable .= &Apache::loncommon::select_timezone($item,$timezone,undef, - $includeempty); + $includeempty,$disabled); } elsif ($item eq 'datelocale') { my $includeempty = 1; my $locale_obj = &Apache::lonlocal::getdatelocale(); @@ -2187,15 +3430,18 @@ sub print_localization { } $datatable .= &Apache::loncommon::select_datelocale($item,$currdatelocale, - undef,$includeempty); + undef,$includeempty,$disabled); } else { if ($settings->{$item} eq '') { - $datatable .= - &Apache::loncommon::select_language('languages_0','',1); + unless ($noedit) { + $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(); + $datatable .= '
'. + &Apache::loncommon::start_data_table(); if (@languages > 0) { my %langchoices = &get_lang_choices(); foreach my $lang (@languages) { @@ -2210,19 +3456,22 @@ sub print_localization { '
'. ''. &Apache::loncommon::end_data_table_row(); $num ++; } } - $datatable .= &Apache::loncommon::start_data_table_row(). + unless ($noedit) { + $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(); + ''.&Apache::loncommon::end_data_table_row(); + } + $datatable .= &Apache::loncommon::end_data_table().'
'; } } $datatable .= &item_table_row_end(); @@ -2243,7 +3492,7 @@ sub get_lang_choices { } sub print_feedback { - my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal) = @_; + my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2278,21 +3527,25 @@ sub print_feedback { del => 'Delete?', sec => 'Sections:', ); - + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } 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"); + $datatable .= &item_table_row_start($items{$item}{text}."
(Custom text)",$count, "advanced",2); } if ($position eq 'top') { my $includeempty = 0; - $datatable .= &user_table($cdom,$item,\@sections, - $settings->{$item},\%lt); + $datatable .= ''. + &user_table($cdom,$item,\@sections, + $settings->{$item},\%lt,$noedit); } else { $datatable .= &Apache::lonhtmlcommon::textbox($item.'.text', - $settings->{$item.'.text'},$items{$item}{size}); + $settings->{$item.'.text'},$items{$item}{size},$disabled); } $datatable .= &item_table_row_end(); } @@ -2301,15 +3554,21 @@ sub print_feedback { } sub user_table { - my ($cdom,$item,$sections,$currvalue,$lt) = @_; + my ($cdom,$item,$sections,$currvalue,$lt,$noedit) = @_; my $output; if ($currvalue eq '') { - $output .= &select_recipient($item,'0',$cdom,$sections); + unless ($noedit) { + $output .= &select_recipient($item,'0',$cdom,$sections); + } } else { my $num = 0; my @curr = split(/,/,$currvalue); - $output .= ''; + $output .= '
'; my ($currusers); + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } foreach my $val (@curr) { next if ($val eq ''); my ($uname,$udom,$seclist) = ($val =~ /^($match_username):($match_domain)(\(?[^\)]*\)?)$/); @@ -2321,7 +3580,7 @@ sub user_table { $currusers .= ''. ''; @@ -2350,12 +3609,16 @@ sub user_table { '
'. ''. ''.(' 'x2). @@ -2332,7 +3591,7 @@ sub user_table { if (@{$sections}) { $currusers.= (' 'x3).$lt->{'sec'}.' '. &select_sections($item,$num,$sections, - \@selsec); + \@selsec,$noedit); } } $currusers .= '
'.$currusers.'
'. ''; } - $output .= ''. + unless ($noedit) { + $output .= + ''. ''. $lt->{'add'}.'
'. &select_recipient($item,$num,$cdom,$sections). ''. - ''; + ''; + } + $output .= ''; } return $output; } @@ -2382,14 +3645,17 @@ sub select_recipient { } sub select_sections { - my ($item,$num,$sections,$selected) = @_; - my ($output,@currsecs,$allsec); + my ($item,$num,$sections,$selected,$noedit) = @_; + my ($output,@currsecs,$allsec,$disabled); if (ref($selected) eq 'ARRAY') { @currsecs = @{$selected}; } if (!@currsecs) { $allsec = ' selected="selected"'; } + if ($noedit) { + $disabled = ' disabled="disabled"'; + } if (ref($sections) eq 'ARRAY') { if (@{$sections}) { my $mult; @@ -2399,7 +3665,7 @@ sub select_sections { $mult .= ' size="4"'; } } - $output = ''. ' '; foreach my $sec (@{$sections}) { my $is_sel; @@ -2415,7 +3681,7 @@ sub select_sections { } sub print_discussion { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2445,6 +3711,20 @@ sub print_discussion { &mt('(specific user(s))'), input => 'checkbox', }, + + 'pac.roles.denied' => { + text => ''.&mt($itemtext->{'pac.roles.denied'}).''. + &Apache::loncommon::help_open_topic("Course_Disable_Anonymous_Discussion").'
'. + &mt('(role-based)'), + input => 'checkbox', + }, + + 'pac.users.denied' => { + text => ''.&mt($itemtext->{'pac.users.denied'}).'
'. + &mt('(specific user(s))'), + input => 'checkbox', + }, + 'allow_limited_html_in_feedback' => { text => ''.&mt($itemtext->{'allow_limited_html_in_feedback'}).'', input => 'radio', @@ -2454,6 +3734,11 @@ sub print_discussion { text => ''.&mt($itemtext->{'allow_discussion_post_editing'}).'', input => 'checkbox', }, + 'discussion_post_fonts' => { + text => ''.&mt($itemtext->{'discussion_post_fonts'}).'', + input => 'textbox', + size => '20', + }, ); my $datatable; my $count; @@ -2467,32 +3752,60 @@ sub print_discussion { del => 'Delete?', sec => 'Sections:', ); - foreach my $item (@{$ordered}) { $count ++; - $datatable .= &item_table_row_start($items{$item}{text},$count); + my $colspan; + if ($item eq 'allow_limited_html_in_feedback') { + $colspan = 2; + } + $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan); if ($item eq 'plc.roles.denied') { - $datatable .= ''.&role_checkboxes($cdom,$cnum,$item,$settings). + $datatable .= '
'. + ''.&role_checkboxes($cdom,$cnum,$item,$settings,undef,undef,$noedit). '
'; } elsif ($item eq 'plc.users.denied') { - $datatable .= &user_table($cdom,$item,undef, - $settings->{$item},\%lt); + $datatable .= '
'. + &user_table($cdom,$item,undef, + $settings->{$item},\%lt,$noedit); } elsif ($item eq 'pch.roles.denied') { - $datatable .= ''.&role_checkboxes($cdom,$cnum,$item,$settings). + $datatable .= ''. &Apache::loncommon::end_data_table_row(). - &role_checkboxes($cdom,$cnum,$item,$settings,1). - &Apache::loncommon::end_data_table(); + &role_checkboxes($cdom,$cnum,$item,$settings,1,undef,$noedit). + &Apache::loncommon::end_data_table().'
'; + } elsif ($item eq 'discussion_post_fonts') { + $datatable .= ''. + ''. + ''. + ''. + ''. + &Apache::loncommon::end_data_table_row(). + &set_discussion_fonts($cdom,$cnum,$item,$settings,$noedit). + &Apache::loncommon::end_data_table().'
'; } $datatable .= &item_table_row_end(); } @@ -2501,7 +3814,7 @@ sub print_discussion { } sub role_checkboxes { - my ($cdom,$cnum,$item,$settings,$showsections,$crstype) = @_; + my ($cdom,$cnum,$item,$settings,$showsections,$crstype,$noedit) = @_; my @roles = ('st','ad','ta','ep','in'); if ($crstype eq 'Community') { push(@roles,'co'); @@ -2539,6 +3852,10 @@ sub role_checkboxes { } my $numinrow = 3; my $count = 0; + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } foreach my $role (@roles) { my $checked = ''; if (grep(/^\Q$role\E$/,@current)) { @@ -2556,12 +3873,12 @@ sub role_checkboxes { $output .= ''; } } - $output .= ''; if ($showsections) { $output .= ''; } $count ++; @@ -2588,12 +3905,12 @@ sub role_checkboxes { $output .= ''; } } - $output .= ''; if ($showsections) { $output .= ''.&Apache::loncommon::end_data_table_row(); } $total ++; @@ -2614,14 +3931,90 @@ sub role_checkboxes { return $output; } +sub set_discussion_fonts { + my ($cdom,$cnum,$item,$settings,$noedit) = @_; + my ($classorder,$classtitles) = &discussion_vote_classes(); + my ($styleorder,$styleitems) = &discussion_vote_styles(); + my $output; + if (ref($classorder) eq 'ARRAY') { + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } + foreach my $cat (@{$classorder}) { + my %curr = (); + ($curr{'size'},$curr{'weight'},$curr{'style'},$curr{'other'}) = + split(/,/,$settings->{'discussion_post_fonts_'.$cat}); + $output .= &Apache::loncommon::start_data_table_row(). + ''; + if (ref($styleorder) eq 'ARRAY') { + foreach my $item (@{$styleorder}) { + $output .= ''; + } + $output .= &Apache::loncommon::end_data_table_row(); + } + return $output; +} + +sub discussion_vote_classes { + my $classorder = ['twoplus','oneplus','zero','oneminus','twominus']; + my %classtitles = &Apache::lonlocal::texthash( + 'twoplus' => 'Two sigma above mean', + 'oneplus' => 'One sigma above mean', + 'zero' => 'Within one sigma of mean', + 'oneminus' => 'One sigma below mean', + 'twominus' => 'Two sigma below mean', + ); + return ($classorder,\%classtitles); +} + +sub discussion_vote_styles { + my $styleorder = ['size','weight','style']; + my $styleitems = { + size => ['','px','%','xx-small','x-small','small','medium','large', + 'x-large','xx-large','smaller','larger'], + weight => ['','normal','bold','bolder','lighter','100','200','300','400', + '500','600','700','800','900'], + style => ['','normal','italic','oblique'], + }; + return ($styleorder,$styleitems); +} + sub print_classlists { - my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype) = @_; + my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype,$noedit) = @_; my @ordered; if ($position eq 'top') { @ordered = ('default_enrollment_start_date', 'default_enrollment_end_date'); + if ($crstype eq 'Course') { + push(@ordered,'defaultcredits'); + } } elsif ($position eq 'middle') { - @ordered = ('nothideprivileged'); + @ordered = ('nothideprivileged','checkforpriv'); } else { @ordered = ('student_classlist_view', 'student_classlist_opt_in', @@ -2652,12 +4045,20 @@ sub print_classlists { text => ''.&mt($itemtext->{'default_enrollment_end_date'}).'', input => 'dates', }, - + 'defaultcredits' => { + text => ''.&mt($itemtext->{'defaultcredits'}).'', + }, + 'nothideprivileged' => { text => ''.&mt($itemtext->{'nothideprivileged'}).'', input => 'checkbox', }, + 'checkforpriv' => { + text => ''.&mt($itemtext->{'checkforpriv'}).'', + input => 'selectbox', + }, + 'student_classlist_view' => { text => ''.&mt($itemtext->{'student_classlist_view'}).'', input => 'selectbox', @@ -2678,11 +4079,11 @@ sub print_classlists { ($settings->{'student_classlist_view'} eq 'section')) { $settings->{'student_classlist_view'} = 'disabled'; } - return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype); + return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'classlists',$noedit); } sub print_appearance { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2714,11 +4115,11 @@ sub print_appearance { text => ''.&mt($itemtext->{'texengine'}).'', input => 'selectbox', options => { - jsMath => 'jsMath', + MathJax => 'MathJax', mimetex => &mt('Convert to Images'), tth => &mt('TeX to HTML'), }, - order => ['jsMath','mimetex','tth'], + order => ['MathJax','mimetex','tth'], nullval => $mathdef, }, 'tthoptions' => { @@ -2726,12 +4127,20 @@ sub print_appearance { input => 'textbox', size => 40, }, + 'uselcmath' => { + text => ''.&mt($itemtext->{'uselcmath'}).'', + input => 'radio', + }, + 'usejsme' => { + text => ''.&mt($itemtext->{'usejsme'}).'', + input => 'radio', + }, ); - return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); + return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'appearance',$noedit); } sub print_grading { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2742,11 +4151,12 @@ sub print_grading { input => 'selectbox', options => { standard => &mt('Standard: shows points'), + categories => &mt('Categories: shows points according to categories'), 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'], + order => ['standard','categories','external','externalnototals','spreadsheet'], }, 'rndseed' => { text => ''.&mt($itemtext->{'rndseed'}).''. @@ -2763,6 +4173,7 @@ sub print_grading { '64bit5' => '64bit5', }, order => ['32bit','64bit','64bit2','64bit3','64bit4','64bit5'], + advanced => 1 }, 'receiptalg' => { text => ''.&mt($itemtext->{'receiptalg'}).'
'. @@ -2774,17 +4185,18 @@ sub print_grading { receipt3 => 'receipt3', }, order => ['receipt','receipt2','receipt3'], + advanced => 1 }, 'disablesigfigs' => { text => ''.&mt($itemtext->{'disablesigfigs'}).'', input => 'radio', }, ); - return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); + return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'grading',$noedit); } sub print_printouts { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2812,7 +4224,7 @@ sub print_printouts { A6 => &mt('A6').' [105x148 mm]', }, order => ['Letter','Legal','Tabloid','Executive','A2','A3','A4','A5','A6'], - nullval => 'None specified', + nullval => &mt('None specified'), }, print_header_format => { text => ''.&mt($itemtext->{'print_header_format'}).'', @@ -2830,14 +4242,14 @@ sub print_printouts { 0 => &mt('No'), }, order => ['1','0'], - nullval => 'None specified - use domain default', + nullval => &mt('None specified - use domain default'), } ); - return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); + return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'printouts',$noedit); } sub print_spreadsheet { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2869,11 +4281,11 @@ sub print_spreadsheet { input => 'radio', }, ); - return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); + return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'spreadsheet',$noedit); } sub print_bridgetasks { - my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -2911,11 +4323,11 @@ sub print_bridgetasks { input => 'radio', }, ); - return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype); + return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks',$noedit); } sub print_other { - my ($cdom,$settings,$allitems,$rowtotal,$crstype) = @_; + my ($cdom,$settings,$allitems,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) { return; } @@ -2936,7 +4348,7 @@ sub print_other { input => 'textbox', size => '30', }; - my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype); + my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'other',$noedit); } sub get_other_items { @@ -2953,7 +4365,10 @@ sub get_other_items { 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$/)) { + ($parameter =~ m/^(cc|co|in|ta|ep|ad|st)\.plaintext$/) + || ($parameter =~ m/^discussion_post_fonts/) || + ($parameter =~ m{^(minimal|updated|uploaded|external)syllabus$}) || + ($parameter eq 'clonedfrom')) { push(@ordered,$parameter); } } @@ -2962,13 +4377,18 @@ sub get_other_items { } sub item_table_row_start { - my ($text,$count,$add_class) = @_; + my ($text,$count,$add_class,$colspan) = @_; 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 .= ''."\n". + ''; + if ($colspan) { + $output .= ''. + &Apache::loncommon::end_data_table_row(); + $num ++; + unless (grep(/^\Q$currdom\E$/,@excdoms)) { + push(@excdoms,$currdom); + } + } + } + if ((scalar(keys(%domains)) - scalar(@excdoms)) > 0) { + $datatable .= + &Apache::loncommon::start_data_table_row(). + ''.&Apache::loncommon::end_data_table_row(); + } + $datatable .= &Apache::loncommon::end_data_table(). + ''. + '
'; + } + return $datatable; +} + sub print_hdrfmt_row { - my ($item,$settings) = @_; + my ($item,$settings,$noedit) = @_; my @curr; my $currnum = 0; my $maxnum = 2; @@ -3226,37 +4763,45 @@ function getIndexByName(item) { ENDJS - $output .= $currstr.'
'. + ''.&role_checkboxes($cdom,$cnum,$item,$settings,undef,undef,$noedit). '
'; } elsif ($item eq 'pch.users.denied') { - $datatable .= &user_table($cdom,$item,undef, - $settings->{$item},\%lt); + $datatable .= '
'. + &user_table($cdom,$item,undef, + $settings->{$item},\%lt,$noedit); + } elsif ($item eq 'pac.roles.denied') { + $datatable .= ''. + ''.&role_checkboxes($cdom,$cnum,$item,$settings,undef,undef,$noedit). + '
'; + } elsif ($item eq 'pac.users.denied') { + $datatable .= '
'. + &user_table($cdom,$item,undef, + $settings->{$item},\%lt,$noedit); } elsif ($item eq 'allow_limited_html_in_feedback') { - $datatable .= &yesno_radio($item,$settings); + $datatable .= &yesno_radio($item,$settings,undef,undef,undef,$noedit); } elsif ($item eq 'allow_discussion_post_editing') { - $datatable .= &Apache::loncommon::start_data_table(). + $datatable .= '
'. + &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_row(). '
'.&mt('Role').''. &mt('Sections').'
'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(). + '
'.&mt('Sum of likes/dislikes').''.&mt('font-size').''.&mt('font-weight').''.&mt('font-style').''.&mt('Other css').'
'. - &select_sections($item,$role,\@sections,$currsec{$role}). + &select_sections($item,$role,\@sections,$currsec{$role},$noedit). '
'. - &select_sections($item,$role,\@sections,$currsec{$role}). + &select_sections($item,$role,\@sections,$currsec{$role},$noedit). ''.$classtitles->{$cat}.''; + my $selitem = $item; + if ($item eq 'size') { + my ($currsize,$currunit); + if ($curr{'size'} =~ /^(\d+)(px|%)$/) { + ($currsize,$currunit) = ($1,$2); + $curr{'size'} = $currunit; + } + $output .= ''. + ' '; + $selitem = 'unit'; + } + if ((ref($styleitems) eq 'HASH') && (ref($styleitems->{$item}) eq 'ARRAY')) { + $output .= '
'.$text. - ''; + my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row'; + $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq ''); + $output .= '
'.$text. + ''; + } else { + $output .= ''; + } return $output; } @@ -2977,25 +4397,43 @@ sub item_table_row_end { } sub yesno_radio { - my ($item,$settings) = @_; + my ($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit) = @_; my $itemon = ' '; my $itemoff = ' checked="checked" '; + if (($valueyes eq '') && ($valueno eq '')) { + $valueyes = 'yes'; + $valueno = ''; + } if (ref($settings) eq 'HASH') { - if ($settings->{$item} eq 'yes') { + if ($settings->{$item} eq $valueyes) { $itemon = $itemoff; $itemoff = ' '; } + unless (exists($settings->{$item})) { + if ($unsetdefault eq $valueyes) { + $itemon = $itemoff; + $itemoff = ' '; + } + } + } + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; } return ' '. + $itemon.' value="'.$valueyes.'"'.$disabled.' />'.&mt('Yes').' '. ''; + $itemoff.' value="'.$valueno.'"'.$disabled.' />'.&mt('No').''; } sub select_from_options { - my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange) = @_; + my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit) = @_; my $output; + my $disabled; + if ($noedit) { + $disabled = ' disabled=disabled"'; + } if ((ref($order) eq 'ARRAY') && (ref($options) eq 'HASH')) { $output=''; foreach my $user (sort(@privusers)) { my $hideon = ' checked="checked" '; @@ -3139,8 +4611,9 @@ sub nothidepriv_row { ''. + $hideon.' value=""'.$disabled.' />'.&mt('Hidden').' '. + ''. ''; } $datatable .= '
'. ' '. - '
'; @@ -3154,8 +4627,72 @@ sub nothidepriv_row { return $datatable; } +sub checkforpriv_row { + my ($cdom,$item,$settings,$crstype,$noedit) = @_; + my $datatable; + my %domains=map { $_ => 1; } &Apache::lonnet::all_domains(); + if (keys(%domains) == 1) { + $datatable = '
'. + &mt("Course's domain is only domain"); + return $datatable; + } + my @excdoms = ($cdom); + my $num = 0; + if ($settings->{$item} eq '') { + $datatable = ''. + &Apache::loncommon::select_dom_form('','checkforpriv_'.$num, + 1,1,undef,undef,\@excdoms, + $noedit); + } else { + my @privdoms = split(/,/,$settings->{$item}); + my %domains=map { $_ => 1; } &Apache::lonnet::all_domains(); + $datatable = '
'. + &Apache::loncommon::start_data_table(); + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } + if (@privdoms > 0) { + foreach my $currdom (@privdoms) { + next unless ($domains{$currdom}); + my $domdesc = &Apache::lonnet::domain($currdom,'description'); + if ($domdesc eq '') { + $domdesc = $currdom; + } + $datatable .= + &Apache::loncommon::start_data_table_row(). + '
'. + &mt('Domain:').' '.$domdesc. + '
'. + '
'. + &mt('Additional domain:'). '
'. + &Apache::loncommon::select_dom_form('','checkforpriv_'.$num,1, + 1,undef,undef,\@excdoms,$noedit). + '
'; + $output .= ''; + } + $output .= '

'. + $currstr.''; + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; + } if (@curr > 0) { for (my $i=0; $i<@curr; $i++) { my $pos = $i+1; $output .= ''. ''; + '"'.$disabled.' />'; if ($curr[$i] =~ /^%\d*[nca]$/) { my ($limit,$subst) = ($curr[$i] =~ /^%(\d*)([nca])$/); $output .= ''; + &substitution_selector($i,$subst,$limit,$disabled).''; } else { $output .= ''; + ' value="'.$curr[$i].'" size="25"'.$disabled.' />'; } $output .= ''; } } - my $pos = $currnum+1; - $output .= ''. + my $pos = $currnum+1; + unless ($noedit) { + $output .= + ''. ''. ''; - $pos ++; - $currnum ++; - $output .= ''. + $pos ++; + $currnum ++; + $output .= + ''. ''. @@ -3265,14 +4810,15 @@ ENDJS '" value="" size ="25" />'. ''. - ''. - '
'. - &position_selector($pos,$i,$maxnum).&mt('Delete:'). + &position_selector($pos,$i,$maxnum,$disabled).&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').'
'; + '

'; return $output; } sub position_selector { - my ($pos,$num,$maxnum) = @_; - my $output = ''; for (my $j=1; $j<=$maxnum; $j++) { my $sel = ''; if ($pos == $j) { @@ -3286,7 +4832,7 @@ sub position_selector { } sub substitution_selector { - my ($num,$subst,$limit,$crstype) = @_; + my ($num,$subst,$limit,$crstype,$disabled) = @_; my ($stunametxt,$crsidtxt); if ($crstype eq 'Community') { $stunametxt = 'member name'; @@ -3301,7 +4847,7 @@ sub substitution_selector { a => 'assignment note', ); my $output .= &mt('Substitution').'
'. - ''; if ($subst eq '') { $output .= ''; } @@ -3315,7 +4861,7 @@ sub substitution_selector { } $output .= '
'.&mt('Size limit').'
'. ''; + '" value="'.$limit.'" size="5"'.$disabled.' />'; return $output; } @@ -3333,17 +4879,19 @@ sub change_clone { 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; + if ($currclone =~ /:/) { + 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); } - &Apache::lonnet::put('environment',\%currclonecrs,$udom,$uname); } } } @@ -3353,24 +4901,26 @@ sub change_clone { 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.','; + if ($oldclone =~ /:/) { + 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'} = ''; } - $newclonecrs{'cloneable'} =~ s/,$//; - } else { - $newclonecrs{'cloneable'} = ''; + &Apache::lonnet::put('environment',\%newclonecrs,$udom,$uname); } - &Apache::lonnet::put('environment',\%newclonecrs,$udom,$uname); } } }