--- loncom/interface/courseprefs.pm 2010/01/07 20:33:22 1.18 +++ loncom/interface/courseprefs.pm 2012/05/27 01:36:09 1.49.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set configuration settings for a course # -# $Id: courseprefs.pm,v 1.18 2010/01/07 20:33:22 faziophi Exp $ +# $Id: courseprefs.pm,v 1.49.2.1 2012/05/27 01:36:09 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -28,6 +28,185 @@ ############################################################### ############################################################## +=pod + +=head1 NAME + +courseprefs- Handler to set/modify course configuration + +=head1 SYNOPSIS + +courseprefs provides an interface for setting general course configuration + +=head1 DESCRIPTION + +This module is used for configuration of a course + +=head1 INTERNAL SUBROUTINES + +=over + +=item get_allitems() + +=item print_config_box() + +=item process_changes() + +=item get_sec_str() + +=item check_clone() + +=item store_changes() + +=item update_env() + +=item display_disallowed() + +=item get_course() + +=item get_jscript() + +=item cloners_javascript() + +=item print_courseinfo() + +=item new_cloners_dom_row() + +=item can_modify_catsettings() + +=item assign_course_categories() + +=item print_localization() + +=item get_lang_choices() + +=item print_feedback() + +=item user_table() + +=item select_recipient() + +=item select_sections() + +=item print_discussion() + +=item role_checkboxes() + +=item print_classlists() + +=item print_appearance() + +=item print_grading() + +=item print_printouts() + +=item print_spreadsheet() + +=item print_bridgetasks() + +=item print_other() + +=item get_other_items() + +=item item_table_row_start() + +=item item_table_row_end() + +=item yes_no_radio() + +=item select_from_options() + +=item make_item_rows() + +Creates table used to display and set course configuration items. + +Inputs: $cdom,$items,$ordered,$settings,$rowtotal,$crstype +where $cdom is course's domain, $items is HASH ref for current config +item, $ordered is ARRAY ref of items to include in row in +display order, $settings is HASH ref of current values forrow, +$rowtotal is SCALAR ref used to accumulate row count, $crstype is +course type. + +Returns: $datatable +HTML mark-up of data table which accumulates individual rows. + +=item nothidepriv_row() + +Creates row containing form elements used to display and set +whether Domain coordinators who are currently included in +advanced course user .db file for a course are to be hidden (e.g., +in syllabus, or from course user lists). + +Inputs: $cdom,$item,$settings,$crstype +where $cdom is course domain, item is nothideprivileged, $settings is +HASH ref of the current values for nothideprivileged, $crstype is +course type (Course or Community). + +Return: $datatable +HTML mark-up for Privileged users (Domain Coordinators) in staff listing. + +=item print_hdrfmt_row() + +Creates row containing form elements used to display and set +substitution items and text to be used in the header included +on printouts. + +Inputs: $item,$settings +where $item is print_header_format, and $settings is a HASH ref +of the current values stored for print_header_format. + +Returns: $output +HTML mark-up containing Javascript functions: reOrder() and getIndexByName() +used to dynamically update position selectboxes, and HTML table elements +for the "Print header format" row. + +=item position_selector() + +Creates a select box which can be used to reorder substitutions +and text included in a printout header. + +Inputs: $pos,$num,$maxnum +where $pos is current position, $num is the unique identifier, +and $maxnum is the total number of items (both substitutions +and text in the printout header. + +Returns: $output +HTML mark-up for the selectbox and a hidden form element containing +the current position. + +=item substitution_selector() + +Creates a combination of select box for choosing an item +(student name, course ID or assignment note) to substitute, +and a corresponding size limit in the header used for printouts. + +Inputs: $num,$subst,$limit,$crstype +where $num is the unique identifier, $subst is the current +substitution (n,c or a, for name, course or note respectively, +$limit is the current size limit (integer), and $crstype is +course type - course or community. + +Returns: $output +HTML mark-up for selectbox and textbox (separate table cells). + +=item change_clone() + +Modifies the list of courses a user can clone (stored +in the user's environment.db file), called when a +change is made to the list of users allowed to clone +a course. + +Inputs: $action,$cloner +where $action is add or drop, and $cloner is identity of +user for whom cloning ability is to be changed in course. + +Returns: nothing + +=back + +=cut + + package Apache::courseprefs; use strict; @@ -36,6 +215,7 @@ use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonconfigsettings; +use Apache::lonparmset; use Apache::lonlocal; use LONCAPA qw(:DEFAULT :match); @@ -88,11 +268,13 @@ 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', desc => 'Community Description', + ownr => 'Community Owner', + cown => 'Community Co-owners', catg => 'Categorize community', excc => 'Exclude from community catalog', clon => 'Users allowed to clone community', @@ -105,7 +287,7 @@ 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', + clas => 'Membership and facilitator listing', priv => 'Privileged users (Domain Coordinators) in facilitator listing', defc => 'Default Community Spreadsheet', defs => 'Default User Spreadsheet', @@ -113,30 +295,33 @@ sub handler { ); } else { %lt = ( - conf => 'Course Configuration', - edit => 'Edit Course Configuration', - gens => 'General Settings', - idnu => 'ID/Number', - desc => 'Title', + conf => 'Course Settings', + edit => 'Edit Course Settings', + gens => 'General course settings', + idnu => 'Course ID or number', + desc => 'Course Description', + ownr => 'Course Owner', + cown => 'Course Co-owners', catg => 'Categorize course', excc => 'Exclude from course catalog', clon => 'Users allowed to clone course', rept => 'Replacement titles for standard course roles', - time => 'Timezone', - date => 'Calendar Locale', + time => 'Timezone in which the course takes place', + date => 'Locale used for course calendar', coco => 'Course Content', copo => 'Course Policy', priv => 'Domain Coordinators in course', defd => 'Default dates for student access', stuv => 'Student-viewable classlist options', stul => 'Student agreement needed to be listed', - clas => 'Classlists and Staff Listing', + clas => 'Classlists and staff listing', priv => 'Privileged users (Domain Coordinators) in staff listing', defc => 'Default Course Spreadsheet', defs => 'Default Student Spreadsheet', seme => 'Send message to student when clicking Done on Tasks', ); } + $lt{'lcrv'} = 'Required LON-CAPA version'; &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs', text=>$lt{'conf'}}); my $breadcrumbs = @@ -152,6 +337,14 @@ sub handler { return OK; } + if ($phase eq 'releaseinfo') { + my $loncaparev = $env{'course.'.$cid.'.internal.releaserequired'}; + if ($loncaparev) { + &display_loncaparev_constraints($r,$navmap,$loncaparev,$crstype); + return OK; + } + } + my %values=&Apache::lonnet::dump('environment',$cdom,$cnum); my @prefs_order = ('courseinfo','localization','feedback','discussion', 'classlists','appearance','grading','printouts', @@ -160,38 +353,39 @@ sub handler { my %prefs = ( 'courseinfo' => { text => $lt{'gens'}, - help => 'Course_Environment', - ordered => ['description','courseid','categories', - 'hidefromcat','externalsyllabus', - 'url','rolenames','cloners'], + help => 'Course_Prefs_General', + ordered => ['owner','co-owners','loncaparev','description', + 'courseid','categories','hidefromcat', + 'externalsyllabus','cloners','url','rolenames'], itemtext => { - description => $lt{'desc'}, - courseid => $lt{'idnu'}, - categories => $lt{'catg'}, - hidefromcat => $lt{'excc'}, - cloners => $lt{'clon'}, - externalsyllabus => 'External Syllabus URL', - url => 'Top Level Map', - rolenames => $lt{'rept'}, + 'owner' => $lt{'ownr'}, + 'co-owners' => $lt{'cown'}, + 'description' => $lt{'desc'}, + 'courseid' => $lt{'idnu'}, + 'categories' => $lt{'catg'}, + 'hidefromcat' => $lt{'excc'}, + 'cloners' => $lt{'clon'}, + 'externalsyllabus' => 'URL of Syllabus', + 'url' => 'Top Level Map', + 'rolenames' => $lt{'rept'}, + 'loncaparev' => $lt{'lcrv'}, }, }, 'localization' => - { text => 'Language & Time Localization', - help => 'Course_Environment', + { text => 'Language and time localization', + help => 'Course_Prefs_Language', ordered => ['languages','timezone','datelocale'], itemtext => { - languages => 'Language(s)', + languages => 'Languages used', timezone => $lt{'time'}, datelocale => $lt{'date'}, }, }, 'feedback' => - { text => 'Feedback Messages', - help => 'Course_Environment', + { text => 'Feedback messages', + help => 'Course_Prefs_Feedback', header => [{col1 => 'Questions about:', - col2 => 'Recipients'}, - {col1 => 'Questions about:', - col2 => 'Custom Text'}], + col2 => 'Recipients'}], ordered => ['question.email','comment.email','policy.email'], itemtext => { 'question.email' => 'Resource Content', @@ -201,23 +395,23 @@ 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', + 'plc.roles.denied','plc.users.denied', 'allow_limited_html_in_feedback', 'allow_discussion_post_editing'], itemtext => { - 'plc.roles.denied' => 'Disable resource discussion', - 'plc.users.denied' => 'Disable resource discussion', - 'pch.roles.denied' => 'Disable chat room', - 'pch.users.denied' => 'Disable chat room', - allow_limited_html_in_feedback => 'HTML in discussion', - allow_discussion_post_editing => 'Allow users to edit/delete own discussion posts', + 'pch.roles.denied' => 'No Resource Discussion', + 'pch.users.denied' => 'No Resource Discussion', + 'plc.roles.denied' => 'No Chat room use', + 'plc.users.denied' => 'No Chat room use', + allow_limited_html_in_feedback => 'Allow limited HTML in discussion', + allow_discussion_post_editing => 'Users can edit/delete own discussion posts', }, }, 'classlists' => { text => $lt{'clas'}, - help => 'Course_Environment', + help => 'Course_Prefs_Classlists', header => [{col1 => 'Type', col2 => $lt{'defd'}}, {col1 => 'Setting', @@ -227,49 +421,49 @@ sub handler { ordered => ['default_enrollment_start_date', 'default_enrollment_end_date', 'nothideprivileged','student_classlist_view', - 'student_opt_in','student_classlist_portfiles'], + 'student_classlist_opt_in','student_classlist_portfiles'], itemtext => { default_enrollment_start_date => 'Start date', default_enrollment_end_date => 'End date', nothideprivileged => $lt{'priv'}, student_classlist_view => $lt{'stuv'}, - student_opt_in => $lt{'stul'}, + student_classlist_opt_in => $lt{'stul'}, student_classlist_portfiles => 'Include link to accessible portfolio files', }, }, 'appearance' => - { text => 'Display of Resources ', - help => 'Course_Environment', + { text => 'Display of resources ', + help => 'Course_Prefs_Display', ordered => ['default_xml_style','pageseparators', 'disable_receipt_display','texengine', 'tthoptions'], itemtext => { default_xml_style => 'Default XML style file', - pageseparators => 'Separate items on composite pages', - disable_receipt_display => 'Disable problem receipts display', - texengine => 'Force specific math rendering engine', + pageseparators => 'Visibly Separate Items on Pages', + disable_receipt_display => 'Disable display of problem receipts', + texengine => 'Force use of a specific math rendering engine', tthoptions => 'Default set of options to pass to tth/m when converting TeX', }, }, 'grading' => { text => 'Grading', - help => 'Course_Environment', + help => 'Course_Prefs_Grading', ordered => ['grading','rndseed', 'receiptalg','disablesigfigs'], itemtext => { - grading => 'Grading Type', - rndseed => 'Randomization algorithm', - receiptalg => 'Receipt algorithm', - disablesigfigs => 'Disable significant figure checks', + grading => 'Grading', + rndseed => 'Randomization algorithm used', + receiptalg => 'Receipt algorithm used', + disablesigfigs => 'Disable checking of Significant Figures', }, }, 'printouts' => - { text => 'Printouts', - help => 'Course_Environment', + { text => 'Printout generation', + help => 'Course_Prefs_Printouts', ordered => ['problem_stream_switch','suppress_tries', 'default_paper_size','print_header_format', - 'disableexampointprint','canuse_pdfforms'], + 'disableexampointprint'], itemtext => { problem_stream_switch => 'Allow problems to be split over pages', suppress_tries => 'Suppress number of tries in printing', @@ -281,7 +475,7 @@ sub handler { }, 'spreadsheet' => { text => 'Spreadsheets', - help => 'Course_Environment', + help => 'Course_Prefs_Spreadsheet', ordered => ['spreadsheet_default_classcalc', 'spreadsheet_default_studentcalc', 'spreadsheet_default_assesscalc','hideemptyrows'], @@ -294,7 +488,7 @@ sub handler { }, 'bridgetasks' => { text => 'Bridge tasks', - help => 'Course_Environment', + help => 'Course_Prefs_Bridgetasks', ordered => ['task_messages','task_grading', 'suppress_embed_prompt'], itemtext => { @@ -305,7 +499,7 @@ sub handler { }, 'other' => { text => 'Other settings', - help => 'Course_Environment', + help => 'Course_Prefs_Other', header => [ {col1 => 'Item', col2 => 'Value', }], @@ -315,15 +509,15 @@ sub handler { my @allitems = &get_allitems(%prefs); &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context, \@prefs_order,\%prefs,\%values, - $cnum,undef,\@allitems); + $cnum,undef,\@allitems,'coursepref'); } elsif ($phase eq 'display') { - my $jscript = &get_jscript($cdom,$phase,$crstype); + my $jscript = &get_jscript($cid,$cdom,$phase,$crstype); 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'); } else { &Apache::lonconfigsettings::display_choices($r,$phase,$context, - \@prefs_order,\%prefs); + \@prefs_order,\%prefs,'coursepref'); } return OK; } @@ -350,11 +544,16 @@ sub print_config_box { my $itemtext = $item->{'itemtext'}; my $rowtotal = 0; my $output = - '
'. + &mt($item->{text}).' '. + &Apache::loncommon::help_open_topic($item->{'help'}).' | '."\n". + '|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'; return ($output,$rowtotal); } @@ -454,7 +665,21 @@ 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')); + push(@ordered,$entry); + } + } else { + @ordered = @{$item->{'ordered'}}; + } } if (@ordered > 0) { if ($action eq 'feedback') { @@ -504,8 +729,8 @@ sub process_changes { 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 ($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}); @@ -547,10 +772,14 @@ sub process_changes { my @cloners = split(',',$env{'form.'.$entry}); my @okcloners; foreach my $cloner (@cloners) { - my ($uname,$udom) = split(':',$cloner); - if (&check_clone($udom,$disallowed,$uname) eq 'ok') { - if (!grep(/^\Q$cloner\E$/,@okcloners)) { - push(@okcloners,$cloner); + $cloner =~ s/^\s+//; + $cloner =~ s/\s+$//; + unless ($cloner eq '') { + my ($uname,$udom) = split(':',$cloner); + if (&check_clone($udom,$disallowed,$uname) eq 'ok') { + if (!grep(/^\Q$cloner\E$/,@okcloners)) { + push(@okcloners,$cloner); + } } } } @@ -571,6 +800,80 @@ sub process_changes { } } } + } elsif ($entry eq 'co-owners') { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $coowners = $values->{'internal.co-owners'}; + my @currcoown; + if ($coowners) { + @currcoown = split(',',$coowners); + } + if (&Apache::lonnet::is_course_owner($cdom,$cnum)) { + my $autocoowner; + if (($crstype eq 'Course') && + ($values->{'internal.coursecode'})) { + my %domconf = + &Apache::lonnet::get_dom('configuration',['autoenroll'],$cdom); + if (ref($domconf{'autoenroll'}) eq 'HASH') { + $autocoowner = $domconf{'autoenroll'}{'co-owners'}; + } + } + unless ($autocoowner) { + my @keepcoowners = &Apache::loncommon::get_env_multiple('form.coowners'); + my @pendingcoowners = &Apache::loncommon::get_env_multiple('form.pendingcoowners'); + my @invitecoowners = &Apache::loncommon::get_env_multiple('form.invitecoowners'); + if (@invitecoowners) { + push(@pendingcoowners,@invitecoowners); + } + $newvalues{'pendingco-owners'} = join(',',sort(@pendingcoowners)); + $newvalues{'co-owners'} = join(',',sort(@keepcoowners)); + if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) { + $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'}; + push(@{$changes->{$entry}{'changed'}},'co-owners'); + } + if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) { + $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'}; + push(@{$changes->{$entry}{'changed'}},'pendingco-owners'); + } + } + } else { + my (@newpending,@newcoown); + my $uname = $env{'user.name'}; + my $udom = $env{'user.domain'}; + my $pendingcoowners = $values->{'internal.pendingco-owners'}; + my @pendingcoown = split(',',$pendingcoowners); + if ($env{'form.pending_coowoner'}) { + foreach my $item (@pendingcoown) { + unless ($item eq $uname.':'.$udom) { + push(@newpending,$item); + } + } + @newcoown = @currcoown; + if ($env{'form.pending_coowoner'} eq 'accept') { + unless (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) { + push(@newcoown,$uname.':'.$udom); + } + } + } elsif ($env{'form.remove_coowoner'}) { + foreach my $item (@currcoown) { + unless ($item eq $uname.':'.$udom) { + push(@newcoown,$item); + } + } + if ($pendingcoowners ne '') { + @newpending = @pendingcoown; + } + } + $newvalues{'pendingco-owners'} = join(',',sort(@newpending)); + $newvalues{'co-owners'} = join(',',sort(@newcoown)); + if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) { + $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'}; + push(@{$changes->{$entry}{'changed'}},'co-owners'); + } + if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) { + $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'}; + push(@{$changes->{$entry}{'changed'}},'pendingco-owners'); + } + } } elsif ($entry =~ /^default_enrollment_(start|end)_date$/) { $newvalues{$entry}=&Apache::lonhtmlcommon::get_date_from_form($entry); } elsif ($entry eq 'rolenames') { @@ -739,8 +1042,8 @@ sub process_changes { $hdr .= $env{'form.printfmthdr_limit_'.$i}; } $hdr .= $env{'form.printfmthdr_sub_'.$i}; - } elsif ($env{'form.printfmthdr_sub_'.$i} ne '') { - $hdr = $env{'form.printfmthdr_sub_'.$i}; + } elsif ($env{'form.printfmthdr_text_'.$i} ne '') { + $hdr = $env{'form.printfmthdr_text_'.$i}; } $newhdr[$env{'form.printfmthdr_pos_'.$i}] = $hdr; } @@ -787,8 +1090,10 @@ sub process_changes { } else { $newvalues{$entry} = $env{'form.'.$entry}; } - if ($newvalues{$entry} ne $values->{$entry}) { - $changes->{$entry} = $newvalues{$entry}; + unless ($entry eq 'co-owners') { + if ($newvalues{$entry} ne $values->{$entry}) { + $changes->{$entry} = $newvalues{$entry}; + } } } } @@ -840,7 +1145,7 @@ sub check_clone { sub store_changes { my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_; my ($chome,$output); - my (%storehash,@delkeys,@need_env_update); + my (%storehash,@delkeys,@need_env_update,@oldcloner); if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) { %storehash = %{$values}; } else { @@ -864,16 +1169,16 @@ sub store_changes { $output .= ' '.&mt($prefs->{$item}{'text'}).''; if (ref($changes->{$item}) eq 'HASH') { if (keys(%{$changes->{$item}}) > 0) { - $output .= &mt('Changes made:').'
'; @@ -1062,6 +1441,16 @@ sub update_env { &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash->{$key}}); $crsinfo{$env{'request.course.id'}}{$key} = $storehash->{$key}; $count ++; + } elsif ($key eq 'co-owners') { + if ($storehash->{'internal.co-owners'} ne '') { + &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.co-owners' => $storehash->{'internal.co-owners'}}); + } + if ($storehash->{'internal.pendingco-owners'} ne '') { + &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.pendingco-owners' => $storehash->{'internal.pendingco-owners'}}); + } + my @coowners = split(',',$storehash->{'internal.'.$key}); + $crsinfo{$env{'request.course.id'}}{'co-owners'} = \@coowners; + $count ++; } } if ($count) { @@ -1164,9 +1553,9 @@ sub get_course { } sub get_jscript { - my ($cdom,$phase,$crstype) = @_; + my ($cid,$cdom,$phase,$crstype) = @_; my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype); - my ($jscript,$categorize_js); + my ($jscript,$categorize_js,$loncaparev_js); my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript(); my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset'); my $cloners_js = &cloners_javascript($phase); @@ -1183,9 +1572,23 @@ function catsbrowser() { } ENDSCRIPT } + my $loncaparev = $env{'course.'.$cid.'.internal.releaserequired'}; + if ($loncaparev) { + $loncaparev_js = < '.'('. &mt('internal, optional').')', @@ -1323,15 +1736,16 @@ sub print_courseinfo { }, 'cloners' => { text => ''.&mt($itemtext->{'cloners'}).' '. - &mt('Coordinators included automatically'), + &mt('Owner and Coordinators included automatically'), input => 'textbox', - size => '40', + size => '40' }, 'rolenames' => { text => ''.&mt($itemtext->{'rolenames'}).' '. '('.$replace.')', input => 'textbox', size => '20', + advanced => 1 }, 'externalsyllabus' => { text => ''.&mt($itemtext->{'externalsyllabus'}).' ('. @@ -1350,6 +1764,9 @@ sub print_courseinfo { input => 'textbox', size => '25', }, + 'loncaparev' => { + text => ''.&mt($itemtext->{'loncaparev'}).'', + }, ); my $datatable; my $count = 0; @@ -1360,7 +1777,11 @@ sub print_courseinfo { next if (!$can_categorize); } $count ++; - $datatable .= &item_table_row_start($items{$item}{text},$count); + if (exists $items{$item}{advanced} && $items{$item}{advanced} == 1) { + $datatable .= &item_table_row_start($items{$item}{text},$count,"advanced"); + } else { + $datatable .= &item_table_row_start($items{$item}{text},$count); + } if ($items{$item}{input} eq 'radio') { $datatable .= &yesno_radio($item,$settings); } elsif ($item eq 'cloners') { @@ -1395,11 +1816,18 @@ sub print_courseinfo { if (@entries > 0) { foreach my $entry (@entries) { my ($uname,$udom) = split(/:/,$entry); + if ($udom =~ /^$match_domain$/) { + unless (&Apache::lonnet::domain($udom)) { + next; + } + } else { + next; + } if ($uname eq '*') { $datatable .= &Apache::loncommon::start_data_table_row(). ' '.
- &mt('Domain:').' '.$udom.
+ &mt('Any user in domain:').' '.$udom.
' | '.
&Apache::loncommon::end_data_table_row();
$num ++;
- } else {
- push(@cloners,$entry);
+ } elsif (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
+ unless (grep(/^\Q$entry\E$/,@cloners)) {
+ push(@cloners,$entry);
+ }
}
}
}
@@ -1464,6 +1894,47 @@ sub print_courseinfo {
$datatable .= ''.
&Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item},
$items{$item}{size},$launcher);
+ } elsif ($item eq 'owner') {
+ my $owner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'};
+ if ($owner =~ /:/) {
+ my ($ownername,$ownerdom) = split(':',$owner);
+ $owner = &Apache::loncommon::plainname($ownername,$ownerdom);
+ } elsif ($owner ne '') {
+ $owner = &Apache::loncommon::plainname($owner,$cdom);
+ } else {
+ $owner = &mt('None specified');
+ }
+ $datatable .= $owner;
+ } elsif ($item eq 'co-owners') {
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $coowners = $env{'course.'.$env{'request.course.id'}.'.internal.co-owners'};
+ my @currcoown;
+ if ($coowners) {
+ @currcoown = split(',',$coowners);
+ }
+ if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
+ if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
+ $datatable .= &show_autocoowners(@currcoown);
+ } else {
+ $datatable .= &coowner_invitations($cnum,$cdom,@currcoown);
+ }
+ } else {
+ if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
+ $datatable .= &show_autocoowners(@currcoown);
+ } else {
+ $datatable .= &manage_coownership($cnum,$cdom,@currcoown);
+ }
+ }
+ } 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});
}
@@ -1621,6 +2092,577 @@ ENDSCRIPT
return;
}
+sub display_loncaparev_constraints {
+ my ($r,$navmap,$loncaparev,$crstype) = @_;
+ 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',
+ );
+ my (%checkparms,%checkresponsetypes,%checkcrstypes,%anonsurvey,%randomizetry);
+ &Apache::loncommon::build_release_hashes(\%checkparms,\%checkresponsetypes,
+ \%checkcrstypes,\%anonsurvey,\%randomizetry);
+ if (defined($checkcrstypes{$crstype})) {
+ $output .= ''. ' '.&mt('Course type: [_1] requires [_2] or newer',$crstype, + $checkcrstypes{$crstype}).''; + } + my (%fromparam,%rowspan,%bymap,%byresource,@scopeorder,%toshow,%allmaps, + %byresponsetype,%bysubmission); + @scopeorder = ('all','section/group','user'); + my $resourcedata = &Apache::lonparmset::readdata($cnum,$cdom); + if (ref($resourcedata) eq 'HASH') { + foreach my $key (keys(%{$resourcedata})) { + foreach my $item (keys(%checkparms)) { + if ($key =~ /(\Q$item\E)$/) { + if (ref($checkparms{$item}) eq 'ARRAY') { + my $value = $resourcedata->{$key}; + my ($middle,$scope,$which,$level,$map,$resource); + if (grep(/^\Q$value\E$/,@{$checkparms{$item}})) { + my $stdtype = &Apache::lonparmset::standard_parameter_types($item); + my $stdname = &Apache::lonparmset::standard_parameter_names($item); + my $valname = &get_param_description($stdtype,$value); + my $rev = $Apache::lonnet::needsrelease{'parameter:'.$item.':'.$value}; + 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 ($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\).\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)) {
+ $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(' | ';
+ }
+ $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 .= '',@{$fromparam{$rev}{$scope}{$which}}).' '.$lt{$scope}.' | | '.
+ join(' | '.
+ &Apache::loncommon::end_data_table_row();
+ $newrow = 1;
+ }
+ }
+ }
+ $output .= &Apache::loncommon::end_data_table().'',@{$fromparam{$rev}{$scope}}).' '; + } + } + + 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'); + + 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; + } + 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; + } + } + my %responses = $res->responseTypes(); + foreach my $key (keys(%responses)) { + if (exists($checkresponsetypes{$key})) { + push(@{$byresponsetype{$symb}{$checkresponsetypes{$key}}},$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); + my $mapsymb = $mapres->symb(); + $toshow{$mapsymb} = 1; + if (ref($mapres)) { + 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()); + 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 = '![]() ![]() '.&mt('Location').' | '.&mt('Release').' | '.
+ ''.&mt('Attribute/Setting').' | '.
+ &Apache::loncommon::end_data_table_header_row().
+ &Apache::loncommon::start_data_table_row().
+ ' '.$icon.' '.&mt('Main Course Documents').' | ');
+ &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 = '![]() ![]() '.$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 = '![]() '.$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(' | ');
+ $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(' | ');
+ }
+ $r->print(&Apache::loncommon::end_data_table_row());
+ }
+ }
+ }
+ }
+ $r->print(&Apache::loncommon::end_data_table());
+ }
+}
+
+sub releases_by_map {
+ my ($r,$bymap,$url,$scopeorder,$lt) = @_;
+ return unless ((ref($bymap) eq 'HASH') && (ref($scopeorder) eq 'ARRAY'));
+ if (ref($bymap->{$url}) eq 'HASH') {
+ foreach my $rev (sort(keys(%{$bymap->{$url}}))) {
+ $r->print('',@{$byresponsetype->{$symb}{$rev}})); + } + $r->print(' '.$rev.' | ');
+ if (ref($bymap->{$url}{$rev}) eq 'HASH') {
+ $r->print(' | ');
+ }
+ } else {
+ $r->print('
| ');
+ }
+ return;
+}
+
+sub get_param_description {
+ my ($stdtype,$value) = @_;
+ my $name = $value;
+ my $paramstrings = &Apache::lonparmset::standard_string_options($stdtype);
+ unless (ref($paramstrings) eq 'ARRAY') {
+ return $name;
+ }
+ foreach my $possibilities (@{$paramstrings}) {
+ next unless (ref($possibilities) eq 'ARRAY');
+ my ($thing, $description) = @{ $possibilities };
+ if ($thing eq $value) {
+ $name = $description;
+ last;
+ }
+ }
+ return $name;
+}
+
+sub show_autocoowners {
+ my (@currcoown) = @_;
+ my $output = ''.&mt('Co-ownership is set automatically when a Course Coordinator role is assigned to official course personnel (from institutional data).').'';
+ if (@currcoown > 0) {
+ $output .= ''.&mt('Current co-owners are:').' '. + join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown)); + } else { + $output .= ' '.&mt('Currently no co-owners.'); + } + return $output; +} + +sub coowner_invitations { + my ($cnum,$cdom,@currcoown) = @_; + my ($output,@pendingcoown,@othercoords); + my $pendingcoowners = + $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'}; + if ($pendingcoowners) { + @pendingcoown = split(',',$pendingcoowners); + } + my $ccrole = 'cc'; + my %ccroles = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,undef,[$ccrole]); + foreach my $key (sort(keys(%ccroles))) { + my ($ccname,$ccdom,$role) = split(':',$key); + next if ($key eq $env{'user.name'}.':'.$env{'user.domain'}.':'.$ccrole); + unless (grep(/^\Q$ccname\E:\Q$ccdom\E$/,@currcoown,@pendingcoown)) { + push(@othercoords,$ccname.':'.$ccdom); + } + } + my $coowner_rows = @currcoown + @pendingcoown + @othercoords; + if ($coowner_rows) { + $output .= &Apache::loncommon::start_data_table(); + if (@currcoown) { + $output .= &Apache::loncommon::start_data_table_row(). + ' '.&mt('Current co-owners').' | ';
+ foreach my $person (@currcoown) {
+ my ($co_uname,$co_dom) = split(':',$person);
+ $output .= ''.(' 'x2).' ';
+ }
+ $output .= ' | '.
+ &Apache::loncommon::end_data_table_row();
+ }
+ if ($pendingcoowners) {
+ $output .= &Apache::loncommon::start_data_table_row().
+ ''.&mt('Invited as co-owners [_1](agreement pending)',' | ').' ';
+ foreach my $person (@pendingcoown) {
+ my ($co_uname,$co_dom) = split(':',$person);
+ $output .= ''.(' 'x2).' ';
+ }
+ $output .= ' | '.
+ &Apache::loncommon::end_data_table_row();
+ }
+ if (@othercoords) {
+ $output .= &Apache::loncommon::start_data_table_row().
+ ''.&mt('Invite other Coordinators [_1]to become co-owners',' | ').' ';
+ foreach my $person (@othercoords) {
+ my ($co_uname,$co_dom) = split(':',$person);
+ $output .= ''.(' 'x2).' ';
+ }
+ $output .= ' | '.
+ &Apache::loncommon::end_data_table_row();
+ }
+ $output .= &Apache::loncommon::end_data_table();
+ } else {
+ $output = &mt('There are no coordinators to select as co-owners');
+ }
+ return $output;
+}
+
+sub manage_coownership {
+ my ($cnum,$cdom,@currcoown) = @_;
+ my (@pendingcoown);
+ my $pendingcoowners =
+ $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
+ if ($pendingcoowners) {
+ @pendingcoown = split(',',$pendingcoowners);
+ }
+ my ($is_coowner,$is_pending,$output);
+ my $uname = $env{'user.name'};
+ my $udom = $env{'user.domain'};
+ if (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {
+ $is_coowner = 1;
+ }
+ if (grep(/^\Q$uname\E:\Q$udom\E$/,@pendingcoown)) {
+ $is_pending = 1;
+ }
+ if (@currcoown && ($is_coowner || $is_pending)) {
+ $output = &Apache::loncommon::start_data_table();
+ }
+ if (@currcoown) {
+ if ($is_coowner || $is_pending) {
+ $output .= &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_row().'';
+ }
+ $output .= &mt('Current co-owners are:').' '.
+ join(', ', map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));
+ if ($is_coowner || $is_pending) {
+ $output .= ' | '.&Apache::loncommon::end_data_table_row();
+ }
+ }
+ if ($is_coowner || $is_pending) {
+ if (@currcoown) {
+ $output .= &Apache::loncommon::start_data_table_row().'';
+ }
+ $output .= '';
+ if ($is_coowner) {
+ $output .= &mt('You are currently a co-owner:').' ';
+ } else {
+ $output .= &mt('The course owner has invited you to become a co-owner:').' '.(' 'x2).
+ '';
+ }
+ $output .= '';
+ if (@currcoown) {
+ $output .= ' | '.&Apache::loncommon::end_data_table_row();
+ }
+ }
+ if (@currcoown && ($is_coowner || $is_pending)) {
+ $output .= &Apache::loncommon::end_data_table();
+ }
+ return $output;
+}
+
sub print_localization {
my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
@@ -1746,16 +2788,20 @@ sub print_feedback {
my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
my @sections = sort( { $a <=> $b } keys(%sections));
my %lt = &Apache::lonlocal::texthash (
- currone => 'Current recipient:',
- curmult => 'Current recipients:',
- add => 'Additional recipient:',
- del => 'Delete?',
- sec => 'Sections:',
+ currone => 'Current recipient:',
+ currmult => 'Current recipients:',
+ add => 'Additional recipient:',
+ del => 'Delete?',
+ sec => 'Sections:',
);
foreach my $item (@{$ordered}) {
$count ++;
- $datatable .= &item_table_row_start($items{$item}{text},$count);
+ if ($position eq 'top') {
+ $datatable .= &item_table_row_start($items{$item}{text},$count);
+ } else {
+ $datatable .= &item_table_row_start($items{$item}{text}."(Custom text)",$count, "advanced"); + } if ($position eq 'top') { my $includeempty = 0; $datatable .= &user_table($cdom,$item,\@sections, @@ -1811,7 +2857,7 @@ sub user_table { if ($num) { $output .= ' ';
- if ($num > 1) {
+ if ($num == 1) {
$output .= $lt->{'currone'};
} else {
$output .= $lt->{'currmult'};
@@ -1931,11 +2977,11 @@ sub print_discussion {
my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
my @sections = sort( { $a <=> $b } keys(%sections));
my %lt = &Apache::lonlocal::texthash (
- currone => 'Disallowed:',
- curmult => 'Disallowed:',
- add => 'Disallow more:',
- del => 'Delete?',
- sec => 'Sections:',
+ currone => 'Disallowed:',
+ currmult => 'Disallowed:',
+ add => 'Disallow more:',
+ del => 'Delete?',
+ sec => 'Sections:',
);
foreach my $item (@{$ordered}) {
@@ -2026,7 +3072,7 @@ sub role_checkboxes {
$output .= ' | ';
if ($showsections) {
@@ -2058,7 +3104,7 @@ sub role_checkboxes {
$output .= ' | | ';
if ($showsections) {
@@ -2094,7 +3140,8 @@ sub print_classlists {
@ordered = ('nothideprivileged');
} else {
@ordered = ('student_classlist_view',
- 'student_opt_in','student_classlist_portfiles');
+ 'student_classlist_opt_in',
+ 'student_classlist_portfiles');
}
my %lt;
@@ -2133,8 +3180,8 @@ sub print_classlists {
options => \%lt,
order => ['disabled','all','section'],
},
- 'student_opt_in' => {
- text => ''.&mt($itemtext->{'student_opt_in'}).'',
+ 'student_classlist_opt_in' => {
+ text => ''.&mt($itemtext->{'student_classlist_opt_in'}).'',
input => 'radio',
},
@@ -2211,11 +3258,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'}).''.
@@ -2232,6 +3280,7 @@ sub print_grading {
'64bit5' => '64bit5',
},
order => ['32bit','64bit','64bit2','64bit3','64bit4','64bit5'],
+ advanced => 1
},
'receiptalg' => {
text => ''.&mt($itemtext->{'receiptalg'}).''. @@ -2243,6 +3292,7 @@ sub print_grading { receipt3 => 'receipt3', }, order => ['receipt','receipt2','receipt3'], + advanced => 1 }, 'disablesigfigs' => { text => ''.&mt($itemtext->{'disablesigfigs'}).'', @@ -2431,15 +3481,13 @@ sub get_other_items { } sub item_table_row_start { - my ($text,$count) = @_; + my ($text,$count,$add_class) = @_; my $output; - if ($count%2) { - $output .= ' '.$text.
- ' | ';
+ ' | ';
return $output;
}
@@ -2516,7 +3564,11 @@ sub make_item_rows {
my $count = 0;
foreach my $item (@{$ordered}) {
$count ++;
- $datatable .= &item_table_row_start($items->{$item}{text},$count);
+ if (exists $items->{$item}{advanced} && $items->{$item}{advanced} == 1) {
+ $datatable .= &item_table_row_start($items->{$item}{text},$count,"advanced");
+ } else {
+ $datatable .= &item_table_row_start($items->{$item}{text},$count);
+ }
if ($item eq 'nothideprivileged') {
$datatable .= ¬hidepriv_row($cdom,$item,$settings,$crstype);
} elsif ($item eq 'print_header_format') {
@@ -2635,9 +3687,9 @@ sub print_hdrfmt_row {
$currstr .= ''.&mt('Current print header:').' '.
$settings->{$item}.' | '; my @current = split(/(%\d*[nca])/,$settings->{$item}); - foreach my $item (@current) { - unless ($item eq '') { - push(@curr,$item); + foreach my $val (@current) { + unless ($val eq '') { + push(@curr,$val); } } $currnum = @curr; @@ -2772,7 +3824,7 @@ sub substitution_selector { a => 'assignment note', ); my $output .= &mt('Substitution').' '. - ' |