--- loncom/interface/lonmodifycourse.pm 2009/11/23 21:45:18 1.49
+++ loncom/interface/lonmodifycourse.pm 2010/09/11 21:36:00 1.57.2.1
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# handler for DC-only modifiable course settings
#
-# $Id: lonmodifycourse.pm,v 1.49 2009/11/23 21:45:18 raeburn Exp $
+# $Id: lonmodifycourse.pm,v 1.57.2.1 2010/09/11 21:36:00 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -49,7 +49,8 @@ sub get_dc_settable {
sub autoenroll_keys {
my $internals = ['coursecode','courseowner','authtype','autharg','autoadds','autodrops',
- 'autostart','autoend','sectionnums','crosslistings'];
+ 'autostart','autoend','sectionnums','crosslistings',
+ 'co-owners'];
my $accessdates = ['default_enrollment_start_date','default_enrollment_end_date'];
return ($internals,$accessdates);
}
@@ -106,7 +107,7 @@ sub get_enrollment_settings {
} else {
$enrollvar{$type} = &Apache::lonlocal::locallocaltime($settings{$item});
}
- } elsif ($type eq "sectionnums") {
+ } elsif (($type eq 'sectionnums') || ($type eq 'co-owners')) {
$enrollvar{$type} = $settings{$item};
$enrollvar{$type} =~ s/,/, /g;
} elsif ($type eq "authtype"
@@ -198,7 +199,7 @@ sub print_course_selection_page {
undef,undef,\%filter,$action,\$numtitles));
$filter{'domainfilter'} = $dom;
my %courses = &Apache::lonpickcourse::search_courses($r,$type,0,
- \%filter,$numtitles);
+ \%filter,$numtitles));
&Apache::lonpickcourse::display_matched_courses($r,$type,0,$action,undef,undef,undef,
%courses);
return;
@@ -207,87 +208,122 @@ sub print_course_selection_page {
sub print_modification_menu {
my ($r,$cdesc,$domdesc,$dom,$type) = @_;
&print_header($r,$type);
- my ($ccrole,$setquota_text,$setparams_text,$cat_text);
+ my ($ccrole,$categorytitle,$setquota_text,$setparams_text,$cat_text);
if ($type eq 'Community') {
$ccrole = 'co';
} else {
$ccrole = 'cc';
}
- my $action = '/adm/modifycourse';
if ($type eq 'Community') {
+ $categorytitle = 'View/Modify Community Settings';
$setquota_text = &mt('Total disk space allocated for storage of portfolio files in all groups in a community.');
$setparams_text = 'View/Modify community owner';
$cat_text = 'View/Modify catalog settings for community';
} else {
+ $categorytitle = 'View/Modify Course Settings';
$setquota_text = &mt('Total disk space allocated for storage of portfolio files in all groups in a course.');
$setparams_text = 'View/Modify course owner, institutional code, and default authentication';
- $cat_text = 'View/Modify catalog settings for course';
+ $cat_text = 'View/Modify catalog settings for course';
}
- my @menu =
- (
- { text => $setparams_text,
- phase => 'setparms',
- },
- { text => 'View/Modify quota for group portfolio files',
- phase => 'setquota',
- }
- );
+ my $anon_text = 'Responder threshold required to display anonymous survey submissions';
+
my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom);
my @additional_params = &catalog_settable($domconf{'coursecategories'},$type);
- if (@additional_params > 0) {
- push (@menu, { text => $cat_text,
- phase => 'catsettings',
- });
+
+ sub phaseurl {
+ my $phase = shift;
+ return "javascript:changePage(document.menu,'$phase')"
}
- unless ($type eq 'Community') {
- push(@menu,
- { text => 'Display current settings for automated enrollment',
- phase => 'viewparms',
- }
+ my @menu =
+ ({ categorytitle => $categorytitle,
+ items => [
+ {
+ linktext => $setparams_text,
+ url => &phaseurl('setparms'),
+ permission => 1,
+ #help => '',
+ icon => 'crsconf.png',
+ linktitle => ''
+ },
+ {
+ linktext => 'View/Modify quota for group portfolio files',
+ url => &phaseurl('setquota'),
+ permission => 1,
+ #help => '',
+ icon => 'groupportfolioquota.png',
+ linktitle => ''
+ },
+ {
+ linktext => 'View/Modify responders threshold for anonymous survey submissions display',
+ url => &phaseurl('setanon'),
+ permission => 1,
+ #help => '',
+ icon => 'anonsurveythreshold.png',
+ linktitle => ''
+ },
+ {
+ linktext => $cat_text,
+ url => &phaseurl('catsettings'),
+ permission => (@additional_params > 0),
+ #help => '',
+ icon => 'ccatconf.png',
+ linktitle => ''
+ },
+ {
+ linktext => 'Display current settings for automated enrollment',
+ url => &phaseurl('viewparms'),
+ permission => ($type ne 'Community'),
+ #help => '',
+ icon => 'roles.png',
+ linktitle => ''
+ },
+ ]
+ },
);
- }
- my $menu_html = '
'.&mt('View/Modify settings for: ').
- ' '.$cdesc.' '."\n";
+
+ my $menu_html =
+ ''
+ .&mt('View/Modify settings for: [_1]',
+ ''.$cdesc.' ')
+ .' '."\n".'';
if ($type eq 'Community') {
$menu_html .= &mt('Although almost all community settings can be modified by a Coordinator, the following may only be set or modified by a Domain Coordinator:');
} else {
$menu_html .= &mt('Although almost all course settings can be modified by a Course Coordinator, the following may only be set or modified by a Domain Coordinator:');
}
- $menu_html .= '
';
+ $menu_html .= ''."\n".'';
if ($type eq 'Community') {
$menu_html .= ''.&mt('Community owner (permitted to assign Coordinator roles in the community).').' ';
} else {
$menu_html .= ''.&mt('Course owner (permitted to assign Course Coordinator roles in the course).').' '.
''.&mt("Institutional code and default authentication (both required for auto-enrollment of students from institutional datafeeds).").' ';
}
- $menu_html .= ''.$setquota_text.' '."\n";
+ $menu_html .= ''.$setquota_text.' '.
+ ''.$anon_text.' '."\n";
foreach my $item (@additional_params) {
if ($type eq 'Community') {
if ($item eq 'togglecats') {
- $menu_html .= ' '.&mt('Hiding/unhiding a community from the catalog (although can be [_1]configured[_2] to be modifiable by a Coordinator in community context).','',' ').' '."\n";
+ $menu_html .= ' '.&mt('Hiding/unhiding a community from the catalog (although can be [_1]configured[_2] to be modifiable by a Coordinator in community context).','',' ').' '."\n";
} elsif ($item eq 'categorize') {
- $menu_html .= ' '.&mt('Manual cataloging of a community (although can be [_1]configured[_2] to be modifiable by a Coordinator in community context).','',' ').' '."\n";
+ $menu_html .= ' '.&mt('Manual cataloging of a community (although can be [_1]configured[_2] to be modifiable by a Coordinator in community context).','',' ').' '."\n";
}
} else {
if ($item eq 'togglecats') {
- $menu_html .= ' '.&mt('Hiding/unhiding a course from the course catalog (although can be [_1]configured[_2] to be modifiable by a Course Coordinator in course context).','',' ').' '."\n";
+ $menu_html .= ' '.&mt('Hiding/unhiding a course from the course catalog (although can be [_1]configured[_2] to be modifiable by a Course Coordinator in course context).','',' ').' '."\n";
} elsif ($item eq 'categorize') {
- $menu_html .= ' '.&mt('Manual cataloging of a course (although can be [_1]configured[_2] to be modifiable by a Course Coordinator in course context).','',' ').' '."\n";
+ $menu_html .= ' '.&mt('Manual cataloging of a course (although can be [_1]configured[_2] to be modifiable by a Course Coordinator in course context).','',' ').' '."\n";
}
}
}
- $menu_html .= '
- '."\n".
- &hidden_form_elements();
- foreach my $menu_item (@menu) {
- $menu_html.='';
- }
+ $menu_html .=
+ ' '
+ .'');
return;
}
@@ -335,7 +371,7 @@ sub print_settings_display {
"$longtype{$item} \n".
"$enrollvar{$item} \n";
if (grep(/^\Q$item\E$/,@modifiable_params)) {
- $disp_table .= ''.&mt('Yes').' '."\n";
+ $disp_table .= ''.&mt('Yes').' '."\n";
} else {
$disp_table .= ''.&mt('No').' '."\n";
}
@@ -380,11 +416,11 @@ sub print_setquota {
my $hidden_elements = &hidden_form_elements();
my $helpitem = &Apache::loncommon::help_open_topic('Modify_Course_Quota');
$r->print(<
+
+ENDDOCUMENT
+ return;
+}
+
sub print_catsettings {
my ($r,$cdom,$cnum,$cdesc,$type) = @_;
&print_header($r,$type);
@@ -635,7 +710,8 @@ sub gather_authenitems {
sub modify_course {
my ($r,$cdom,$cnum,$cdesc,$domdesc,$type) = @_;
my %longtype = &course_settings_descrip($type);
- my @items = ('internal.courseowner','description');
+ my @items = ('internal.courseowner','description','internal.co-owners',
+ 'internal.pendingco-owners');
unless ($type eq 'Community') {
push(@items,('internal.coursecode','internal.authtype','internal.autharg',
'internal.sectionnums','internal.crosslistings'));
@@ -711,7 +787,7 @@ sub modify_course {
}
}
- if ($changed{'owner'} || $changed{'code'}) {
+ if ($changed{'owner'} || $changed{'code'}) {
my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,
undef,undef,'.');
if (ref($crsinfo{$env{'form.pickedcourse'}}) eq 'HASH') {
@@ -723,6 +799,9 @@ sub modify_course {
}
my $chome = &Apache::lonnet::homeserver($cnum,$cdom);
my $putres = &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime');
+ if ($putres eq 'ok') {
+ &update_coowners($cdom,$cnum,$chome,\%settings,\%newattr);
+ }
}
}
foreach my $param (@modifiable_params) {
@@ -774,10 +853,10 @@ sub modify_course {
my $outcome = &Apache::lonnet::auto_new_course($cnum,$cdom,$inst_course_id,$newattr{'courseowner'});
unless ($outcome eq 'ok') {
- push(@warnings,&mt('If automatic enrollment is enabled for "[_1]" automated enrollment may fail for "[_2]" - section: [_3], for the following reason: "[_4]"',$description,$newattr{'coursecode'},$instsec,$outcome).' ');
+ push(@warnings,&mt('If automatic enrollment is enabled for "[_1]", automated enrollment may fail for "[_2]" - section: [_3] for the following reason: "[_4]".',$description,$newattr{'coursecode'},$instsec,$outcome).' ');
}
} else {
- push(@warnings,&mt('If automatic enrollment is enabled for "[_1]" automated enrollment may fail for "[_2]" - section: [_3], for the following reason: "[_4]"',$description,$newattr{'coursecode'},$instsec,$course_check));
+ push(@warnings,&mt('If automatic enrollment is enabled for "[_1]", automated enrollment may fail for "[_2]" - section: [_3] for the following reason: "[_4]".',$description,$newattr{'coursecode'},$instsec,$course_check));
}
} else {
push(@warnings,&mt('If automatic enrollment is enabled for "[_1]", automated enrollment may fail for "[_2]" - section: [_3], because this is not a valid section entry.',$description,$newattr{'coursecode'},$sec));
@@ -790,15 +869,15 @@ sub modify_course {
my $inst_course_id = $newattr{'coursecode'}.$instsec;
my $outcome = &Apache::lonnet::auto_new_course($cnum,$cdom,$inst_course_id,$newattr{'courseowner'});
unless ($outcome eq 'ok') {
- push(@warnings,&mt('If automatic enrollment is enabled for "[_1]", automated enrollment may fail for "[_2]" - section [_3] for the following reason: "[_4]".',$description,$newattr{'coursecode'},$instsec,$outcome));
+ push(@warnings,&mt('If automatic enrollment is enabled for "[_1]", automated enrollment may fail for "[_2]" - section: [_3] for the following reason: "[_4]".',$description,$newattr{'coursecode'},$instsec,$outcome));
}
} else {
- push(@warnings,&mt('If automatic enrollment is enabled for "[_1]", automated enrollment may fail for "[_2]" - section [_3] because this is not a valid section entry.',$description,$newattr{'coursecode'},$sec));
+ push(@warnings,&mt('If automatic enrollment is enabled for "[_1]", automated enrollment may fail for "[_2]" - section: [_3], because this is not a valid section entry.',$description,$newattr{'coursecode'},$sec));
}
}
}
} else {
- push(@warnings,&mt('As no section numbers are currently listed for "[_1]" automated enrollment will not occur for any sections of institutional course code: "[_2]".',$description,$newattr{'coursecode'}));
+ push(@warnings,&mt('As no section numbers are currently listed for "[_1]", automated enrollment will not occur for any sections of institutional course code: "[_2]".',$description,$newattr{'coursecode'}));
}
if ( (@xlists > 0) && ($changed{'owner'}) ) {
foreach my $xlist (@xlists) {
@@ -861,6 +940,149 @@ sub modify_course {
return;
}
+sub update_coowners {
+ my ($cdom,$cnum,$chome,$settings,$newattr) = @_;
+ return unless ((ref($settings) eq 'HASH') && (ref($newattr) eq 'HASH'));
+ my %designhash = &Apache::loncommon::get_domainconf($cdom);
+ my (%cchash,$autocoowners);
+ if ($designhash{$cdom.'.autoassign.co-owners'}) {
+ $autocoowners = 1;
+ %cchash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,undef,['cc']);
+ }
+ if ($settings->{'internal.courseowner'} ne $newattr->{'courseowner'}) {
+ my $oldowner_to_coowner;
+ my @types = ('co-owners');
+ if (($newattr->{'coursecode'}) && ($autocoowners)) {
+ my $oldowner = $settings->{'internal.courseowner'};
+ if ($cchash{$oldowner.':cc'}) {
+ my ($result,$desc) = &Apache::lonnet::auto_validate_instcode($cnum,$cdom,$newattr->{'coursecode'},$oldowner);
+ if ($result eq 'valid') {
+ if ($settings->{'internal.co-owner'}) {
+ my @current = split(',',$settings->{'internal.co-owners'});
+ unless (grep(/^\Q$oldowner\E$/,@current)) {
+ $oldowner_to_coowner = 1;
+ }
+ } else {
+ $oldowner_to_coowner = 1;
+ }
+ }
+ }
+ } else {
+ push(@types,'pendingco-owners');
+ }
+ foreach my $type (@types) {
+ if ($settings->{'internal.'.$type}) {
+ my @current = split(',',$settings->{'internal.'.$type});
+ my $newowner = $newattr->{'courseowner'};
+ my @newvalues = ();
+ if (($newowner ne '') && (grep(/^\Q$newowner\E$/,@current))) {
+ foreach my $person (@current) {
+ unless ($person eq $newowner) {
+ push(@newvalues,$person);
+ }
+ }
+ } else {
+ @newvalues = @current;
+ }
+ if ($oldowner_to_coowner) {
+ push(@newvalues,$settings->{'internal.courseowner'});
+ @newvalues = sort(@newvalues);
+ }
+ my $newownstr = join(',',@newvalues);
+ if ($newownstr ne $settings->{'internal.'.$type}) {
+ if ($type eq 'co-owners') {
+ my $deleted = '';
+ unless (@newvalues) {
+ $deleted = 1;
+ }
+ &Apache::lonnet::store_coowners($cdom,$cnum,$chome,
+ $deleted,@newvalues);
+ } else {
+ my $pendingcoowners;
+ my $cid = $cdom.'_'.$cnum;
+ if (@newvalues) {
+ $pendingcoowners = join(',',@newvalues);
+ my %pendinghash = (
+ 'internal.pendingco-owners' => $pendingcoowners,
+ );
+ my $putresult = &Apache::lonnet::put('environment',\%pendinghash,$cdom,$cnum);
+ if ($putresult eq 'ok') {
+ if ($env{'course.'.$cid.'.num'} eq $cnum) {
+ &Apache::lonnet::appenv({'course.'.$cid.'.internal.pendingco-owners' => $pendingcoowners});
+ }
+ }
+ } else {
+ my $delresult = &Apache::lonnet::del('environment',['internal.pendingco-owners'],$cdom,$cnum);
+ if ($delresult eq 'ok') {
+ if ($env{'course.'.$cid.'.internal.pendingco-owners'}) {
+ &Apache::lonnet::delenv('course.'.$cid.'.internal.pendingco-owners');
+ }
+ }
+ }
+ }
+ } elsif ($oldowner_to_coowner) {
+ &Apache::lonnet::store_coowners($cdom,$cnum,$chome,'',
+ $settings->{'internal.courseowner'});
+
+ }
+ } elsif ($oldowner_to_coowner) {
+ &Apache::lonnet::store_coowners($cdom,$cnum,$chome,'',
+ $settings->{'internal.courseowner'});
+ }
+ }
+ }
+ if ($settings->{'internal.coursecode'} ne $newattr->{'coursecode'}) {
+ if ($newattr->{'coursecode'} ne '') {
+ my %designhash = &Apache::loncommon::get_domainconf($cdom);
+ if ($designhash{$cdom.'.autoassign.co-owners'}) {
+ my @newcoowners = ();
+ if ($settings->{'internal.co-owners'}) {
+ my @currcoown = split(',',$settings->{'internal.coowners'});
+ my ($updatecoowners,$delcoowners);
+ foreach my $person (@currcoown) {
+ my ($result,$desc) = &Apache::lonnet::auto_validate_instcode($cnum,$cdom,$newattr->{'coursecode'},$person);
+ if ($result eq 'valid') {
+ push(@newcoowners,$person);
+ }
+ }
+ foreach my $item (sort(keys(%cchash))) {
+ my ($uname,$udom,$urole) = split(':',$item);
+ next if ($uname.':'.$udom eq $newattr->{'courseowner'});
+ unless (grep(/^\Q$uname\E:\Q$udom\E$/,@newcoowners)) {
+ my ($result,$desc) = &Apache::lonnet::auto_validate_instcode($cnum,$cdom,$newattr->{'coursecode'},$uname.':'.$udom);
+ if ($result eq 'valid') {
+ push(@newcoowners,$uname.':'.$udom);
+ }
+ }
+ }
+ if (@newcoowners) {
+ my $coowners = join(',',sort(@newcoowners));
+ unless ($coowners eq $settings->{'internal.co-owners'}) {
+ $updatecoowners = 1;
+ }
+ } else {
+ $delcoowners = 1;
+ }
+ if ($updatecoowners || $delcoowners) {
+ &Apache::lonnet::store_coowners($cdom,$cnum,$chome,
+ $delcoowners,@newcoowners);
+ }
+ } else {
+ foreach my $item (sort(keys(%cchash))) {
+ my ($uname,$udom,$urole) = split(':',$item);
+ push(@newcoowners,$uname.':'.$udom);
+ }
+ if (@newcoowners) {
+ &Apache::lonnet::store_coowners($cdom,$cnum,$chome,'',
+ @newcoowners);
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
sub modify_quota {
my ($r,$cdom,$cnum,$cdesc,$domdesc,$type) = @_;
&print_header($r,$type);
@@ -891,7 +1113,7 @@ sub modify_quota {
} else {
if ($putreply eq 'ok') {
my %updatedsettings = &Apache::lonnet::get('environment',['internal.coursequota'],$cdom,$cnum);
- $r->print(&mt('The disk space allocated for group portfolio files is now: [_1] Mb.',$updatedsettings{'internal.coursequota'}));
+ $r->print(&mt('The disk space allocated for group portfolio files is now: [_1] Mb.',''.$updatedsettings{'internal.coursequota'}.' '));
my $usage = &Apache::longroup::sum_quotas($cdom.'_'.$cnum);
if ($usage >= $updatedsettings{'internal.coursequota'}) {
my $newoverquota;
@@ -925,6 +1147,62 @@ sub modify_quota {
return;
}
+sub modify_anonsurvey_threshold {
+ my ($r,$cdom,$cnum,$cdesc,$domdesc,$type) = @_;
+ &print_header($r,$type);
+ $r->print('');
+ return;
+}
+
sub modify_catsettings {
my ($r,$cdom,$cnum,$cdesc,$domdesc,$type) = @_;
&print_header($r,$type);
@@ -1088,17 +1366,45 @@ function gochoose(cname,cdom,cdesc) {
|;
} elsif ($phase eq 'setquota') {
- $js .= <<'ENDSCRIPT';
+ my $invalid = &mt('The quota you entered contained invalid characters.');
+ my $alert = &mt('You must enter a number');
+ my $regexp = '/^\s*(\d+\.?\d*|\.\d+)\s*$/';
+ $js .= <<"ENDSCRIPT";
+ENDSCRIPT
+ } elsif ($phase eq 'setanon') {
+ my $invalid = &mt('The responder threshold you entered is invalid.');
+ my $alert = &mt('You must enter a positive integer.');
+ my $regexp = ' /^\s*\d+\s*$/';
+ $js .= <<"ENDSCRIPT";
+
ENDSCRIPT
@@ -1168,8 +1474,8 @@ sub course_settings_descrip {
if ($type eq 'Community') {
%longtype = &Apache::lonlocal::texthash(
'courseowner' => "Username:domain of community owner",
+ 'co-owners' => "Username:domain of each co-owner",
);
-
} else {
%longtype = &Apache::lonlocal::texthash(
'authtype' => 'Default authentication method',
@@ -1182,6 +1488,7 @@ sub course_settings_descrip {
'default_enrollment_end_date' => 'Date of last student access',
'coursecode' => 'Official course code',
'courseowner' => "Username:domain of course owner",
+ 'co-owners' => "Username:domain of each co-owner",
'notifylist' => 'Course Coordinators to be notified of enrollment changes',
'sectionnums' => 'Course section number:LON-CAPA section',
'crosslistings' => 'Crosslisted class:LON-CAPA section',
@@ -1194,7 +1501,8 @@ sub hidden_form_elements {
my $hidden_elements =
&Apache::lonhtmlcommon::echo_form_input(['gosearch','updater','coursecode',
'prevphase','numlocalcc','courseowner','login','coursequota','intarg',
- 'locarg','krbarg','krbver','counter','hidefromcat','usecategory'])."\n".
+ 'locarg','krbarg','krbver','counter','hidefromcat','usecategory',
+ 'threshold'])."\n".
' ';
return $hidden_elements;
}
@@ -1282,7 +1590,21 @@ sub handler {
({href=>"javascript:changePage(document.$phase,'$phase')",
text=>"Result"});
&modify_quota($r,$cdom,$cnum,$cdesc,$domdesc,$type);
- } elsif ($phase eq 'viewparms') {
+ } elsif ($phase eq 'setanon') {
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({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')",
+ text=>"Threshold for anonymous submissions display"});
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({href=>"javascript:changePage(document.$phase,'$phase')",
+ text=>"Result"});
+ &modify_anonsurvey_threshold($r,$cdom,$cnum,$cdesc,$domdesc,$type);
+ } elsif ($phase eq 'viewparms') {
&Apache::lonhtmlcommon::add_breadcrumb
({href=>"javascript:changePage(document.$phase,'viewparms')",
text=>"Display settings"});