--- loncom/interface/lonmodifycourse.pm 2014/03/31 02:31:05 1.72
+++ loncom/interface/lonmodifycourse.pm 2016/07/24 14:34:59 1.84
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# handler for DC-only modifiable course settings
#
-# $Id: lonmodifycourse.pm,v 1.72 2014/03/31 02:31:05 raeburn Exp $
+# $Id: lonmodifycourse.pm,v 1.84 2016/07/24 14:34:59 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -55,7 +55,7 @@ sub get_dc_settable {
sub autoenroll_keys {
my $internals = ['coursecode','courseowner','authtype','autharg','defaultcredits',
'autoadds','autodrops','autostart','autoend','sectionnums',
- 'crosslistings','co-owners'];
+ 'crosslistings','co-owners','autodropfailsafe'];
my $accessdates = ['default_enrollment_start_date','default_enrollment_end_date'];
return ($internals,$accessdates);
}
@@ -71,6 +71,13 @@ sub catalog_settable {
if ($confhash->{'categorizecomm'} ne 'comm') {
push(@settable,'categorize');
}
+ } elsif ($type eq 'Placement') {
+ if ($confhash->{'togglecatsplace'} ne 'place') {
+ push(@settable,'togglecats');
+ }
+ if ($confhash->{'categorizeplace'} ne 'place') {
+ push(@settable,'categorize');
+ }
} else {
if ($confhash->{'togglecats'} ne 'crs') {
push(@settable,'togglecats');
@@ -117,14 +124,13 @@ sub get_enrollment_settings {
$enrollvar{$type} =~ s/,/, /g;
} elsif ($type eq "authtype"
|| $type eq "autharg" || $type eq "coursecode"
- || $type eq "crosslistings") {
+ || $type eq "crosslistings" || $type eq "selfenrollmgr"
+ || $type eq "autodropfailsafe") {
$enrollvar{$type} = $settings{$item};
} elsif ($type eq 'defaultcredits') {
if (&showcredits($cdom)) {
$enrollvar{$type} = $settings{$item};
}
- } elsif ($type eq 'selfenrollmgr') {
- $enrollvar{$type} = $settings{$item};
} elsif ($type eq 'courseowner') {
if ($settings{$item} =~ /^[^:]+:[^:]+$/) {
$enrollvar{$type} = $settings{$item};
@@ -167,6 +173,8 @@ sub print_course_search_page {
$r->print(&Apache::loncommon::js_changer());
if ($type eq 'Community') {
$r->print('
'.&mt('Search for a community in the [_1] domain',$domdesc).' ');
+ } elsif ($type eq 'Placement') {
+ $r->print(''.&mt('Search for a placement test in the [_1] domain',$domdesc).' ');
} else {
$r->print(''.&mt('Search for a course in the [_1] domain',$domdesc).' ');
}
@@ -178,6 +186,11 @@ sub print_course_search_page {
''.&mt('Enter the community with the role of [_1]',$cctitle).' '."\n".
''.&mt('View or modify community settings which only a [_1] may modify.',$dctitle).
' '."\n".'');
+ } elsif ($type eq 'Placement') {
+ $r->print(&mt('Actions available after searching for a placement test:').''.
+ ''.&mt('Enter the placement test with the role of [_1]',$cctitle).' '."\n".
+ ''.&mt('View or modify placement test settings which only a [_1] may modify.',$dctitle).
+ ' '."\n".' ');
} else {
$r->print(&mt('Actions available after searching for a course:').''.
''.&mt('Enter the course with the role of [_1]',$cctitle).' '."\n".
@@ -208,7 +221,7 @@ sub print_course_selection_page {
my %courses = &Apache::loncommon::search_courses($dom,$type,$filter,$numtitles,
undef,undef,undef,\@codetitles);
&Apache::lonpickcourse::display_matched_courses($r,$type,0,$action,undef,undef,undef,
- %courses);
+ undef,undef,%courses);
return;
}
@@ -254,14 +267,15 @@ sub print_modification_menu {
$categorytitle = 'View/Modify Course Settings';
$setquota_text = &mt('Total disk space allocated for storage of portfolio files in all groups in a course.');
$setuploadquota_text = &mt('Disk space allocated for storage of content uploaded directly to a course via Content Editor.');
- if (&showcredits($dom)) {
+ if (($type ne 'Placement') && (&showcredits($dom))) {
$setparams_text = 'View/Modify course owner, institutional code, default authentication, credits, and self-enrollment';
} else {
$setparams_text = 'View/Modify course owner, institutional code, default authentication, and self-enrollment';
}
$cat_text = 'View/Modify catalog settings for course';
}
- my $anon_text = 'Responder threshold required to display anonymous survey submissions';
+ my $anon_text = &mt('Responder threshold required to display anonymous survey submissions.');
+ my $postsubmit_text = &mt('Override defaults for submit button behavior post-submission for this specific course.');
my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom);
my @additional_params = &catalog_settable($domconf{'coursecategories'},$type);
@@ -319,7 +333,7 @@ sub print_modification_menu {
{
linktext => 'Display current settings for automated enrollment',
url => &phaseurl('viewparms'),
- permission => ($type ne 'Community'),
+ permission => (($type ne 'Community') && ($type ne 'Placement')),
#help => '',
icon => 'roles.png',
linktitle => ''
@@ -332,6 +346,14 @@ sub print_modification_menu {
permission => &manage_selfenrollment($cdom,$cnum,$type,$coursehash),
linktitle => 'Configure user self-enrollment.',
},
+ {
+ linktext => 'View/Modify submit button behavior, post-submission',
+ icon => 'emblem-readonly.png',
+ #help => '',
+ url => &phaseurl('setpostsubmit'),
+ permission => 1,
+ linktitle => '',
+ },
]
},
);
@@ -353,14 +375,15 @@ sub print_modification_menu {
} else {
$menu_html .= ''.&mt('Course owner (permitted to assign Course Coordinator roles in the course).').' '."\n".
''.&mt("Institutional code and default authentication (both required for auto-enrollment of students from institutional datafeeds).").' '."\n";
- if (&showcredits($dom)) {
+ if (($type ne 'Placement') && &showcredits($dom)) {
$menu_html .= ''.&mt('Default credits earned by student on course completion.').' '."\n";
}
$menu_html .= ' '.&mt('Override defaults for who configures self-enrollment for this specific course.').' '."\n";
}
$menu_html .= ''.$setquota_text.' '."\n".
''.$setuploadquota_text.' '."\n".
- ''.$anon_text.' '."\n";
+ ''.$anon_text.' '."\n".
+ ''.$postsubmit_text.' '."\n";
foreach my $item (@additional_params) {
if ($type eq 'Community') {
if ($item eq 'togglecats') {
@@ -555,6 +578,98 @@ ENDDOCUMENT
return;
}
+sub print_postsubmit_config {
+ my ($r,$cdom,$cnum,$cdesc,$type) = @_;
+ my %lt = &Apache::lonlocal::texthash (
+ 'conf' => 'Configure submit button behavior after student makes a submission',
+ 'disa' => 'Disable submit button/keypress following student submission',
+ 'nums' => 'Number of seconds submit is disabled',
+ 'modi' => 'Save',
+ 'back' => 'Pick another action',
+ 'yes' => 'Yes',
+ 'no' => 'No',
+ );
+ my %settings = &Apache::lonnet::get('environment',['internal.postsubmit','internal.postsubtimeout',
+ 'internal.coursecode','internal.textbook'],$cdom,$cnum);
+ my $postsubmit = $settings{'internal.postsubmit'};
+ if ($postsubmit eq '') {
+ my %domconfig =
+ &Apache::lonnet::get_dom('configuration',['coursedefaults'],$cdom);
+ $postsubmit = 1;
+ if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
+ if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
+ if ($domconfig{'coursedefaults'}{'postsubmit'}{'client'} eq 'off') {
+ $postsubmit = 0;
+ }
+ }
+ }
+ }
+ my ($checkedon,$checkedoff,$display);
+ if ($postsubmit) {
+ $checkedon = 'checked="checked"';
+ $display = 'block';
+ } else {
+ $checkedoff = 'checked="checked"';
+ $display = 'none';
+ }
+ my $postsubtimeout = $settings{'internal.postsubtimeout'};
+ my $default = &domain_postsubtimeout($cdom,$type,\%settings);
+ my $zero = &mt('(Enter 0 to disable until next page reload, or leave blank to use the domain default: [_1])',$default);
+ if ($postsubtimeout eq '') {
+ $postsubtimeout = $default;
+ }
+ &print_header($r,$type);
+ my $hidden_elements = &hidden_form_elements();
+ my $helpitem = &Apache::loncommon::help_open_topic('Modify_Postsubmit_Config');
+ $r->print(<
+$lt{'conf'} ($cdesc)
+
+$helpitem $lt{'disa'}:
+
+$lt{'yes'}
+
+$lt{'no'}
+
+$lt{'nums'}
+$zero
+
+
+
+$hidden_elements
+$lt{'back'}
+
+ENDDOCUMENT
+ return;
+}
+
+sub domain_postsubtimeout {
+ my ($cdom,$type,$settings) = @_;
+ return unless (ref($settings) eq 'HASH');
+ my $lctype = lc($type);
+ unless (($type eq 'Community') || ($type eq 'Placement')) {
+ $lctype = 'unofficial';
+ if ($settings->{'internal.coursecode'}) {
+ $lctype = 'official';
+ } elsif ($settings->{'internal.textbook'}) {
+ $lctype = 'textbook';
+ }
+ }
+ my %domconfig =
+ &Apache::lonnet::get_dom('configuration',['coursedefaults'],$cdom);
+ my $postsubtimeout = 60;
+ if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
+ if (ref($domconfig{'coursedefaults'}{'postsubmit'}) eq 'HASH') {
+ if (ref($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}) eq 'HASH') {
+ if ($domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}{$lctype} ne '') {
+ $postsubtimeout = $domconfig{'coursedefaults'}{'postsubmit'}{'timeout'}{$lctype};
+ }
+ }
+ }
+ }
+ return $postsubtimeout;
+}
+
sub print_catsettings {
my ($r,$cdom,$cnum,$cdesc,$type) = @_;
&print_header($r,$type);
@@ -591,6 +706,8 @@ sub print_catsettings {
' '.&mt('Yes').' '.&mt('No').'');
if ($type eq 'Community') {
$r->print(&mt("If a community has been categorized using at least one of the categories defined for communities in the domain, it will be listed in the domain's publicly accessible Course/Community Catalog, unless excluded."));
+ } elsif ($type eq 'Placement') {
+ $r->print(&mt("If a placement test has been categorized using at least one of the categories defined for placement tests in the domain, it will be listed in the domain's publicly accessible Course/Community Catalog, unless excluded."));
} else {
$r->print(&mt("Unless excluded, a course will be listed in the domain's publicly accessible Course/Community Catalog, if at least one of the following applies").':
'.
''.&mt('Auto-cataloging is enabled and the course is assigned an institutional code.').' '.
@@ -612,7 +729,7 @@ sub print_catsettings {
} else {
$r->print(&mt('No categories defined for this domain'));
}
- unless ($type eq 'Community') {
+ unless (($type eq 'Community') || ($type eq 'Placement')) {
$r->print(''.&mt('If auto-cataloging based on institutional code is enabled in the domain, a course will continue to be listed in the catalog of official courses, in addition to receiving a listing under any manually assigned categor(ies).').'
');
}
}
@@ -735,21 +852,21 @@ sub print_course_modification_page {
' '.&mt('Course Code'))."\n".
' '.
&Apache::lonhtmlcommon::row_closure());
- if (&showcredits($cdom)) {
+ if (($crstype eq 'Course') && (&showcredits($cdom))) {
$r->print(&Apache::lonhtmlcommon::row_title(
&Apache::loncommon::help_open_topic('Modify_Course_Credithours').
' '.&mt('Credits (students)'))."\n".
' '.
&Apache::lonhtmlcommon::row_closure());
- }
- $r->print(&Apache::lonhtmlcommon::row_title(
- &Apache::loncommon::help_open_topic('Modify_Course_Defaultauth').
- ' '.&mt('Default Authentication method'))."\n".
- $authenitems."\n".
- &Apache::lonhtmlcommon::row_closure().
- &Apache::lonhtmlcommon::row_title(
- &Apache::loncommon::help_open_topic('Modify_Course_Owner').
- ' '.&mt('Course Owner'))."\n");
+ }
+ $r->print(&Apache::lonhtmlcommon::row_title(
+ &Apache::loncommon::help_open_topic('Modify_Course_Defaultauth').
+ ' '.&mt('Default Authentication method'))."\n".
+ $authenitems."\n".
+ &Apache::lonhtmlcommon::row_closure().
+ &Apache::lonhtmlcommon::row_title(
+ &Apache::loncommon::help_open_topic('Modify_Course_Owner').
+ ' '.&mt('Course Owner'))."\n");
}
my ($cctitle,$rolename,$currmanages,$ccchecked,$dcchecked,$defaultchecked);
my ($selfenrollrows,$selfenrolltitles) = &Apache::lonuserutils::get_selfenroll_titles();
@@ -839,7 +956,7 @@ sub modify_selfenrollconfig {
$r->print(' ');
return;
}
@@ -862,6 +979,7 @@ sub get_selfenroll_settings {
selfenroll_end_access => $coursehash->{'internal.selfenroll_end_access'},
default_enrollment_start_date => $coursehash->{'default_enrollment_start_date'},
default_enrollment_end_date => $coursehash->{'default_enrollment_end_date'},
+ uniquecode => $coursehash->{'internal.uniquecode'},
);
}
return %currsettings;
@@ -923,7 +1041,7 @@ sub modify_course {
'internal.pendingco-owners','internal.selfenrollmgrdc',
'internal.selfenrollmgrcc');
my ($selfenrollrows,$selfenrolltitles) = &Apache::lonuserutils::get_selfenroll_titles();
- unless ($type eq 'Community') {
+ unless (($type eq 'Community') || ($type eq 'Placement')) {
push(@items,('internal.coursecode','internal.authtype','internal.autharg',
'internal.sectionnums','internal.crosslistings'));
if (&showcredits($cdom)) {
@@ -993,7 +1111,7 @@ sub modify_course {
}
}
- if (&showcredits($cdom) && exists($env{'form.defaultcredits'})) {
+ if (($type ne 'Placement') && (&showcredits($cdom) && exists($env{'form.defaultcredits'}))) {
$newattr{'defaultcredits'} =~ s/[^\d\.]//g;
$newattr{'defaultcredits'}=$env{'form.defaultcredits'};
}
@@ -1101,7 +1219,7 @@ sub modify_course {
$nochgresponse .= ''.&mt('[_1] still set to: [_2]',$longtype{$attr},$shown).' ';
}
}
- if (($type ne 'Community') && ($changed{'code'} || $changed{'owner'})) {
+ if (($type ne 'Community') && ($type ne 'Placement') && ($changed{'code'} || $changed{'owner'})) {
if ( $newattr{'courseowner'} eq '') {
push(@warnings,&mt('There is no owner associated with this LON-CAPA course.').
' '.&mt('If automated enrollment at your institution requires validation of course owners, automated enrollment will fail.'));
@@ -1542,7 +1660,83 @@ sub modify_anonsurvey_threshold {
}
$r->print(''.
''.
- &mt('Pick another action').' ');
+ &mt('Pick another action').'
');
+ $r->print(&hidden_form_elements().'');
+ return;
+}
+
+sub modify_postsubmit_config {
+ my ($r,$cdom,$cnum,$cdesc,$domdesc,$type) = @_;
+ &print_header($r,$type);
+ my %lt = &Apache::lonlocal::texthash(
+ subb => 'Submit button behavior after student makes a submission:',
+ unch => 'Post submission behavior of the Submit button is unchanged.',
+ erro => 'An error occurred when saving your proposed changes.',
+ inva => 'An invalid response was recorded.',
+ pick => 'Pick another action',
+ );
+ $r->print('');
return;
}
@@ -1722,6 +1916,8 @@ function hide_searching() {
} elsif ($phase eq 'setquota') {
my $invalid = &mt('The quota you entered contained invalid characters.');
my $alert = &mt('You must enter a number');
+ &js_escape(\$invalid);
+ &js_escape(\$alert);
my $regexp = '/^\s*(\d+\.?\d*|\.\d+)\s*$/';
$js .= <<"ENDSCRIPT";
@@ -1741,6 +1937,8 @@ ENDSCRIPT
} elsif ($phase eq 'setanon') {
my $invalid = &mt('The responder threshold you entered is invalid.');
my $alert = &mt('You must enter a positive integer.');
+ &js_escape(\$invalid);
+ &js_escape(\$alert);
my $regexp = ' /^\s*\d+\s*$/';
$js .= <<"ENDSCRIPT";
@@ -1762,8 +1960,86 @@ function verify_anon_threshold() {
}
ENDSCRIPT
+ } elsif ($phase eq 'setpostsubmit') {
+ my $invalid = &mt('The choice entered for disabling the submit button is invalid.');
+ my $invalidtimeout = &mt('The timeout you entered for disabling the submit button is invalid.');
+ my $alert = &mt('Enter one of: a positive integer, 0 (for no timeout), or leave blank to use domain default');
+ &js_escape(\$invalid);
+ &js_escape(\$invalidtimeout);
+ &js_escape(\$alert);
+ my $regexp = ' /^\s*\d+\s*$/';
+
+ $js .= <<"ENDSCRIPT";
+
+function verify_postsubmit() {
+ var optionsElement = document.setpostsubmit.postsubmit;
+ var verified = '';
+ if (optionsElement.length) {
+ var currval;
+ for (var i=0; i= 0) {
+ verified = 'ok';
+ } else {
+ alert("$invalidtimeout\\n$alert");
+ return false;
+ }
+ } else {
+ alert("$invalid\\n$alert");
+ return false;
+ }
+ }
+ } else {
+ if (currval == 0) {
+ verified = 'ok';
+ } else {
+ alert('$invalid');
+ return false;
+ }
+ }
+ if (verified == 'ok') {
+ changePage(document.setpostsubmit,'processpostsubmit');
+ return true;
+ }
+ }
+ return false;
+}
+
+function togglePostsubmit(caller) {
+ var optionsElement = document.setpostsubmit.postsubmit;
+ if (document.getElementById(caller)) {
+ var divitem = document.getElementById(caller);
+ var optionsElement = document.setpostsubmit.postsubmit;
+ if (optionsElement.length) {
+ var currval;
+ for (var i=0; i {'onload' => "hide_searching();"},
+ add_entries => {'onload' => "hide_searching(); courseSet(document.filterpicker.official, 'load');"},
};
}
$r->print(&Apache::loncommon::start_page('View/Modify Course/Community Settings',
@@ -1780,6 +2056,8 @@ ENDSCRIPT
my $bread_text = "View/Modify Courses/Communities";
if ($type eq 'Community') {
$bread_text = 'Community Settings';
+ } elsif ($type eq 'Placement') {
+ $bread_text = 'Placement Test Settings';
} else {
$bread_text = 'Course Settings';
}
@@ -1852,6 +2130,7 @@ sub course_settings_descrip {
'sectionnums' => 'Course section number:LON-CAPA section',
'crosslistings' => 'Crosslisted class:LON-CAPA section',
'defaultcredits' => 'Credits',
+ 'autodropfailsafe' => "Failsafe section enrollment count",
'selfenrollmgrdc' => "Course-specific self-enrollment configuration by Domain Coordinator",
'selfenrollmgrcc' => "Course-specific self-enrollment configuration by Course personnel",
@@ -1865,8 +2144,9 @@ sub hidden_form_elements {
&Apache::lonhtmlcommon::echo_form_input(['gosearch','updater','coursecode',
'prevphase','numlocalcc','courseowner','login','coursequota','intarg',
'locarg','krbarg','krbver','counter','hidefromcat','usecategory',
- 'threshold','defaultcredits','uploadquota','selfenrollmgrdc','selfenrollmgrcc',
- 'action','state','currsec_st','sections','newsec'],['^selfenrollmgr_'])."\n".
+ 'threshold','postsubmit','postsubtimeout','defaultcredits','uploadquota',
+ 'selfenrollmgrdc','selfenrollmgrcc','action','state','currsec_st',
+ 'sections','newsec'],['^selfenrollmgr_'])."\n".
' ';
return $hidden_elements;
}
@@ -1874,7 +2154,7 @@ sub hidden_form_elements {
sub showcredits {
my ($dom) = @_;
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
- if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbokcredits'}) {
+ if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) {
return 1;
}
}
@@ -1917,6 +2197,8 @@ sub handler {
}
if ($type eq 'Community') {
$choose_text = "Choose a community";
+ } elsif ($type eq 'Placement') {
+ $choose_text = "Choose a placement test";
} else {
$choose_text = "Choose a course";
}
@@ -1933,6 +2215,8 @@ sub handler {
my $enter_text;
if ($type eq 'Community') {
$enter_text = 'Enter community';
+ } elsif ($type eq 'Placement') {
+ $enter_text = 'Enter placement test';
} else {
$enter_text = 'Enter course';
}
@@ -1970,7 +2254,6 @@ sub handler {
({href=>"javascript:changePage(document.$phase,'$phase')",
text=>"Threshold for anonymous submissions display"});
&print_set_anonsurvey_threshold($r,$cdom,$cnum,$cdesc,$type);
-
} elsif ($phase eq 'processthreshold') {
&Apache::lonhtmlcommon::add_breadcrumb
({href=>"javascript:changePage(document.$phase,'setanon')",
@@ -1979,6 +2262,16 @@ sub handler {
({href=>"javascript:changePage(document.$phase,'$phase')",
text=>"Result"});
&modify_anonsurvey_threshold($r,$cdom,$cnum,$cdesc,$domdesc,$type);
+ } elsif ($phase eq 'setpostsubmit') {
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({href=>"javascript:changePage(document.$phase,'$phase')",
+ text=>"Configure submit button behavior post-submission"});
+ &print_postsubmit_config($r,$cdom,$cnum,$cdesc,$type);
+ } elsif ($phase eq 'processpostsubmit') {
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({href=>"javascript:changePage(document.$phase,'$phase')",
+ text=>"Result"});
+ &modify_postsubmit_config($r,$cdom,$cnum,$cdesc,$domdesc,$type);
} elsif ($phase eq 'viewparms') {
&Apache::lonhtmlcommon::add_breadcrumb
({href=>"javascript:changePage(document.$phase,'viewparms')",
@@ -2028,6 +2321,8 @@ sub handler {
$r->print('');
if ($type eq 'Community') {
$r->print(&mt('The community you selected is not a valid community in this domain'));
+ } elsif ($type eq 'Placement') {
+ $r->print(&mt('The course you selected is not a valid placement test in this domain'));
} else {
$r->print(&mt('The course you selected is not a valid course in this domain'));
}