'.&mt('When a group is deleted the following occurs:').'
'.
+ '
'.&mt('All group membership is terminated.').'
'.
+ '
'.&mt('The group ceases to be available either for viewing or for modification of group settings and membership.').'
'.
+ '
'.&mt('The group folder is removed from the folder containing it - normally this is the "Course Groups" folder which contains folders for all groups in the course.').'
'.
+ '
'.&mt('Although a deleted group is no longer accessible, the group name used for the group will be reserved, and will not be available for assignment to a new group in the same course in the future.'));
+ my $prevtext = &mt('Go back');
+ my $nexttext = &mt('Delete group');
+ my $prev;
+ if ($env{'form.refpage'} eq 'cusr') {
+ $prev = 'view';
+ }
+ &display_navbuttons($r,$formname,$prev,$prevtext,
+ $$states{$action}[$page+1],$nexttext);
+ return;
+}
+
+sub delete_group {
+ my ($r,$cdom,$cnum,$groupname) = @_;
+ my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
+ $groupname);
+ my $now = time;
+ my $num_users = 0;
+ my $num_fail = 0;
+ my $num_ok = 0;
+ my @deleted;
+ my @undeleted;
+ my %usersettings;
+ my $context = 'deletegroup';
+ foreach my $key (sort(keys(%membership))) {
+ if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
+ my $user = $1;
+ my($end,$start,$userprivs) = split(/:/,$membership{$key},3);
+ if ($start != -1) {
+ $num_users ++;
+ $usersettings{$groupname.':'.$user} = $now.':-1:'.$userprivs;
+ if (&Apache::lonnet::modify_group_roles($cdom,$cnum,
+ $groupname,$user,
+ $now,'-1',$userprivs,
+ '',$context)
+ eq 'ok') {
+ $num_ok ++;
+ push(@deleted,$user);
+ } else {
+ push(@undeleted,$user);
+ $num_fail ++;
+ }
+ }
+ }
+ }
+ if ($num_ok > 0) {
+ my $roster_result =
+ &Apache::lonnet::modify_coursegroup_membership($cdom,$cnum,
+ \%usersettings);
+ }
+ if ($num_fail > 0) {
+ $r->print('
'
+ .&mt('Group deletion failed because deletion of [_1] out of [_2] members failed.'
+ ,$num_fail,$num_users)
+ .'
');
+
+ } else {
+ my ($result,$message) =
+ &Apache::lonnet::toggle_coursegroup_status($cdom,$cnum,
+ $groupname,'delete');
+ if ($result eq 'ok') {
+ my $outcome = &modify_folders($cdom,$cnum,$groupname);
+ if ($outcome eq '') {
+ $r->print('
'
+ .&mt('Group successfully deleted.')
+ .'
');
+ } else {
+ $r->print('
'
+ .&mt("Although the group was deleted, an error occurred when removing"
+ ." the group's folder from the 'Course Groups' folder: [_1]",$outcome)
+ .'
');
+ }
+ } else {
+ $r->print('
'
+ .&mt('Group deletion failed.')
+ .'
');
+ }
+ }
+ return;
+}
+
+sub reenable_folder {
+ my ($cdom,$cnum,$groupname,$description) = @_;
+ my $outcome;
+ my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
+ my $allgrpsmap = $crspath.'group_allfolders.sequence';
+ my $foldertitle = &mt('Course Folder -[_1]',$description);
+ my $mapurl = $crspath.'group_folder_'.
+ $groupname.'.sequence';
+ my ($errtext,$fatal)=&LONCAPA::map::mapread($allgrpsmap);
+ if ($fatal) {
+ $outcome='
'
+ .&mt('An error occurred when reading contents of parent folder to group:')
+ ." ($allgrpsmap): $errtext"
+ .'
';
+ } else {
+ my $idx=&LONCAPA::map::getresidx($mapurl);
+ $LONCAPA::map::resources[$idx] = $foldertitle.':'.$mapurl.
+ ':false:normal:res';
+ $LONCAPA::map::order[1+$#LONCAPA::map::order]=$idx;
+ my ($outtext,$errtext) = &LONCAPA::map::storemap($allgrpsmap,1);
+ if ($errtext) {
+ $outcome='
'
+ .&mt('An error occurred when saving updated parent folder to group:'
+ ," $allgrpsmap - $errtext")
+ .'
';
+ } else {
+ my ($furl,$ferr) =
+ &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
+ }
+ }
+ return $outcome;
+}
+
+sub modify_folders {
+ my ($cdom,$cnum,$groupname) = @_;
+ my ($outcome,$groupmap,$groupmapres,$map,$id,$src);
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (!defined($navmap)) {
+ $outcome = '
'.
+ &mt('Error reading course contents.').' '.
+ &mt('You need to re-initialize the course.').
+ '
'
+ .&mt('An error occurred when reading contents of parent folder to group:')
+ ." ($map): $errtext"
+ .'
';
+ } else {
+ my $idx = 0;
+ my $grpidx;
+ foreach my $item (@LONCAPA::map::order) {
+ my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$item]);
+ $url=&LONCAPA::map::qtescape($url);
+ if ($url eq $groupmap) {
+ $grpidx = $idx;
+ last;
+ } else {
+ $idx++;
+ }
+ }
+
+ if ($grpidx ne '') {
+ &LONCAPA::map::makezombie($LONCAPA::map::order[$grpidx]);
+ for (my $i=$grpidx;$i<$#LONCAPA::map::order;$i++) {
+ $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1];
+ }
+ $#LONCAPA::map::order--;
+ my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1);
+ if ($errtext) {
+ $outcome='
'
+ .&mt('An error occurred when saving updated parent folder to group:')
+ ." $map - $errtext"
+ .'
';
+ } else {
+ my ($furl,$ferr) =
+ &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
+ }
+ }
+ }
+ }
+ return $outcome;
+}
+
+sub verify_reenable {
+ my ($r,$groupname,$formname,$action,$page,$states,$stored) = @_;
+ $r->print(&Apache::lonhtmlcommon::echo_form_input([]));
+ $r->print(&mt('You have requested enabling the previously deleted group [_1].'
+ ,''.$stored->{'description'}.'').
+ '
'.&mt('When a deleted group is re-enabled the following occurs:').'
'.
+ '
'.&mt('Group settings and membership at the time the group was deleted are reinstated.').'
'.
+ '
'.&mt('A group folder is added to the "Course Groups" folder which contains folders for all groups in the course.').'
');
+ my $prevtext = &mt('Go back');
+ my $nexttext = &mt('Reenable group');
+ my $prev;
+ if ($env{'form.refpage'} eq 'cusr') {
+ $prev = 'view';
+ }
+ &display_navbuttons($r,$formname,$prev,$prevtext,
+ $$states{$action}[$page+1],$nexttext);
+ return;
+}
+
+sub reenable_group {
+ my ($r,$cdom,$cnum,$groupname) = @_;
+ my %groups =
+ &Apache::longroup::coursegroups($cdom,$cnum,$groupname,
+ 'deleted_groups');
+ if (keys(%groups) == 0) {
+ $r->print(&mt('The group [_1] was not re-enabled, because it is not a deleted group.[_2]Perhaps it has already been re-enabled?',''.$groupname.''),' ');
+ return;
+ }
+ my %groupinfo =
+ &Apache::longroup::get_group_settings($groups{$groupname});
+ my $defstart = $groupinfo{'startdate'};
+ my $defend = $groupinfo{'enddate'};
+ my $showstart = &Apache::lonlocal::locallocaltime($defstart);
+ my $showend;
+ if ($defend == 0) {
+ $showend = &mt('No end date set');
+ } else {
+ $showend = &Apache::lonlocal::locallocaltime($defend);
+ }
+ my $description = &unescape($groupinfo{'description'});
+ my $num_users = 0;
+ my $num_ok = 0;
+ my $num_fail = 0;
+ my $context = 'reenablegroup';
+ my (%usersettings,@enabled,@unenabled);
+ my ($result,$message) =
+ &Apache::lonnet::toggle_coursegroup_status($cdom,$cnum,$groupname,
+ 'reenable');
+ if ($result eq 'ok') {
+ my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
+ $groupname);
+ foreach my $key (sort(keys(%membership))) {
+ if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
+ my $user = $1;
+ my($end,$start,$userprivs) = split(/:/,$membership{$key},3);
+ if (($start == -1) && ($end == $groupinfo{'modified'})) {
+ $num_users ++;
+ $usersettings{$groupname.':'.$user} = $defend.':'.
+ $defstart.':'.
+ $userprivs;
+ if (&Apache::lonnet::modify_group_roles($cdom,$cnum,
+ $groupname,$user,
+ $defend,$defstart,
+ $userprivs,'',
+$context) eq 'ok') {
+ $num_ok ++;
+ push(@enabled,$user);
+ } else {
+ push(@unenabled,$user);
+ $num_fail ++;
+ }
+ }
+ }
}
+ if ($num_users > 0) {
+ if ($num_ok > 0) {
+ my $roster_result =
+ &Apache::lonnet::modify_coursegroup_membership($cdom,$cnum,
+ \%usersettings);
+ if ($roster_result eq 'ok') {
+ $r->print('
'
+ .&mt('Membership reinstated for [quant,_1,user], each with start and end dates for group access set to defaults: [_2] and [_3]',$num_ok,$showstart,$showend)
+ .'
');
+ }
+ } else {
+ $r->print('
'
+ .&mt('A problem occurred when trying to reinstate [_1] of the [_2] members of the pre-existing group.',$num_fail,$num_users)
+ .'
');
+ }
+ } else {
+ $r->print('
'
+ .&mt('There were no group members to reinstate, as none were removed when the group was deleted.')
+ .'
');
+ }
+ my $outcome = &reenable_folder($cdom,$cnum,$groupname,$description);
+ if ($outcome eq '') {
+ $r->print('
'
+ .&mt('Group successfully re-enabled.')
+ .'
');
+ } else {
+ $r->print('
'
+ .&mt("Although the group was re-enabled, an error occurred when adding the group's folder to the 'Course Groups' folder: [_1]",$outcome)
+ .'
');
+ }
+ } else {
+ $r->print('
'
+ .&mt('Re-enabling group failed.')
+ .'
');
}
+ return;
}
sub header {
@@ -1092,8 +1467,7 @@ sub onload_action {
}
if (($action eq 'modify') &&
($state eq 'change_settings' || $state eq 'change_members' ||
- $state eq 'change_privs' || $state eq 'add_members' ||
- $state eq 'pick_members')) {
+ $state eq 'change_privs' || $state eq 'add_members')) {
$loaditems{'onload'} =
'javascript:setFormElements(document.'.$state.')';
}
@@ -1124,16 +1498,16 @@ sub build_members_list {
}
sub group_files {
- my ($group,$currdir,$numfiles,$numdirs) = @_;
+ my ($group,$portpath,$numfiles,$numdirs) = @_;
my $dirptr=16384;
- my @dir_list=&Apache::portfolio::get_dir_list($currdir,$group);
+ my @dir_list=&Apache::portfolio::get_dir_list($portpath,undef,$group);
foreach my $line (@dir_list) {
my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$line,16);
if (($filename !~ /^\.\.?$/) && ($filename !~ /\.meta$/ ) && ($filename !~ /(.*)\.(\d+)\.([^\.]*)$/) && ($filename ne 'no_such_dir')) {
if ($dirptr&$testdir) {
- $currdir .= '/'.$filename;
+ $portpath .= '/'.$filename;
$$numdirs ++;
- &group_files($numfiles,$numdirs)
+ &group_files($group,$portpath,$numfiles,$numdirs)
} else {
$$numfiles ++;
}
@@ -1146,60 +1520,78 @@ sub group_members {
my ($cdom,$cnum,$group,$group_info) = @_;
my %memberhash = &Apache::lonnet::get_group_membership($cdom,$cnum,$group);
my $now = time;
- my ($tmp)=keys(%memberhash);
- if ($tmp=~/^error:/) {
- $$group_info{'totalmembers'} = 'Unknown - an error occurred';
- return $tmp;
- }
+ my %lt = &Apache::lonlocal::texthash (
+ active => 'active',
+ previous => 'previous',
+ future => 'future',
+ );
+ my %membercounts = (
+ active => 0,
+ previous => 0,
+ future => 0,
+ );
my $totalmembers = 0;
- my $active = 0;
- my $previous = 0;
- my $future = 0;
foreach my $member (keys %memberhash) {
$totalmembers ++;
my ($end,$start) = split(/:/,$memberhash{$member});
unless ($start == -1) {
if (($end!=0) && ($end<$now)) {
- $previous ++;
+ $membercounts{previous} ++;
} elsif (($start!=0) && ($start>$now)) {
- $future ++;
+ $membercounts{future} ++;
} else {
- $active ++;
+ $membercounts{active} ++;
}
}
}
if ($totalmembers == 0) {
$$group_info{$group}{'totalmembers'} = 'None';
} else {
- $$group_info{$group}{'totalmembers'} = $active.' - active '.$previous.' -previous '.$future.' -future';
+ foreach my $type ('active','previous','future') {
+ $$group_info{$group}{'totalmembers'} .=
+ &open_list_window($group,$type,$membercounts{$type},$lt{$type});
+ }
}
return 'ok';
}
+sub open_list_window {
+ my ($group,$status,$count,$text) = @_;
+ my $entry;
+ if ($count > 0) {
+ $entry = ''.$text.' - '.$count.
+ ' ';
+ } else {
+ $entry = ''.$text.' - '.$count.' ';
+ }
+ return $entry;
+}
+
sub general_settings_form {
- my ($r,$cdom,$cnum,$action,$tabcol,$formname,$page,$functions,$tools,
+ my ($r,$cdom,$cnum,$action,$formname,$page,$functions,$tools,
$toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,
- $rowColor1,$rowColor2,$gpterm,$ucgpterm,$crstype) = @_;
+ $gpterm,$ucgpterm,$crstype) = @_;
my ($nexttext,$prevtext);
&groupsettings_options($r,$functions,$action,$formname,$stored,1,
$gpterm,$ucgpterm,$crstype);
&access_date_settings($r,$action,$formname,$stored,2,$gpterm,$ucgpterm);
if ($action eq 'create') {
- &membership_options($r,$action,$formname,$sectioncount,3,$gpterm,
- $ucgpterm);
+ &membership_options($r,$cdom,$cnum,$action,$formname,$sectioncount,3,
+ $gpterm,$ucgpterm);
$nexttext = $$navbuttons{'gtns'};
} else {
my @available = ();
my @unavailable = ();
&check_tools($functions,$tools,\@available,\@unavailable);
@{$tools} = sort(keys(%{$functions}));
- &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,
- 3,$tools,$stored,$toolprivs,$fixedprivs,
- \@available,$formname,$gpterm,$ucgpterm);
+ &privilege_specificity($r,$action,3,$tools,$stored,$toolprivs,
+ $fixedprivs,\@available,$formname,
+ $gpterm,$ucgpterm,$functions);
&mapping_options($r,$action,$formname,$page,$sectioncount,
$states,$stored,$navbuttons,4,5,
- $gpterm,$ucgpterm,$crstype);
+ $gpterm,$ucgpterm,$crstype,$cdom,$cnum);
$nexttext = $$navbuttons{'mose'};
}
$prevtext = $$navbuttons{'gtpp'};
@@ -1212,26 +1604,25 @@ sub groupsettings_options {
my ($r,$functions,$action,$formname,$stored,$image,$gpterm,
$ucgpterm,$crstype) = @_;
my %lt = &Apache::lonlocal::texthash(
- 'gdat' => "$ucgpterm open and close dates",
- 'sten' => "Set a start date/time and end date/time for the $gpterm",
- 'gfun' => "$ucgpterm functionality",
- 'gnde' => "$ucgpterm name, description and available functionality",
- 'desc' => 'Description',
- 'func' => 'Functionality',
- 'gnam' => "$ucgpterm Name",
- 'doyo' => "Do you want to assign different functionality ".
- "to different $gpterm members?",
+ 'gdat' => "Group access start and end dates",
+ 'gnde' => "Group name, title and available collaborative tools",
+ 'desc' => 'Group Title',
+ 'func' => 'Collaborative Tools',
+ 'gnam' => 'Group Name',
+ 'lett' => 'Letters, numbers and underscore only',
+ 'doyo' => 'Different subsets of the chosen collaborative tools '.
+ 'for different group members?',
);
my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,$stored);
- &topic_bar($r,$image,$lt{'gnde'});
- $r->print('
+ $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'gnde'}).'
'.$lt{'gnam'}.':
');
if ($action eq 'create') {
- $r->print('');
+ $r->print(' ('.
+ $lt{'lett'}.')');
} else {
$r->print(''.$env{'form.groupname'});
@@ -1258,16 +1649,16 @@ END
for (my $i=0; $i<$halfnum; $i++) {
$r->print('
+ &mt($$functions{$allfunctions[$i]}).'
');
}
- $r->print('
print('
'.
'
');
for (my $j=$halfnum; $j<@allfunctions; $j++) {
$r->print('
+ &mt($$functions{$allfunctions[$j]}).'
');
}
if ($remnum) {
@@ -1275,7 +1666,7 @@ END
}
$r->print('
-
@@ -1283,8 +1674,8 @@ END
'.&mt('Granularity:').'
'.$lt{'doyo'}.' ');
if ($action eq 'modify') {
- $r->print(' ('.&mt('Currently set to "[_1]"',
- $$stored{'granularity'}).')');
+ $r->print(' ('.&mt('Currently set to [_1].'
+ ,'"'.&mt($$stored{'granularity'}).'"').')');
}
$r->print('
@@ -1292,23 +1683,25 @@ END
'.&mt('Disk quota: ').'
');
if ($action eq 'create') {
- $r->print(&mt('If you enable the file repository for the [_1], allocate a disk quota.',$gpterm));
+ $r->print(&mt('If you enable the file repository for the '.$gpterm.', allocate a disk quota.'));
} else {
$r->print(&mt('Quota allocated to file repository:'));
}
- $r->print(' Mb');
+ $r->print(' '.&mt('[_1] Mb',''));
if ($action eq 'create') {
- $r->print(' '.
- &mt('A total of [_1] Mb is shared between all [_2]s in the '.
- '[_3], and [_4] Mb are currently unallocated.',$crsquota,
- $gpterm,lc($crstype),$freespace));
+ $r->print(' '
+ .&mt('A total of [_1] Mb can be divided amongst all '.$gpterm.'s in the '
+ .lc($crstype).', and [_2] Mb are currently unallocated.'
+ ,$crsquota,sprintf("%.2f",$freespace))
+ );
} else {
$r->print(' ('.&mt('The quota is currently [_1] Mb',
$$stored{'quota'}).').');
- $r->print(' '.&mt('The quota can be increased to [_1] Mb, '.
- 'by adding all unallocated space for [_2]s in the [_3].',
- $maxposs,$gpterm,lc($crstype)));
+ $r->print(' '
+ .&mt('The quota can be increased to [_1] Mb, '
+ .'by adding all unallocated space for '.$gpterm.'s in the '.lc($crstype).'.'
+ ,sprintf("%.2f",$maxposs)));
}
$r->print('
@@ -1335,18 +1728,18 @@ sub get_quota_constraints {
}
sub membership_options {
- my ($r,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm) = @_;
+ my ($r,$cdom,$cnum,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm)=@_;
my $crstype = &Apache::loncommon::course_type();
my %lt = &Apache::lonlocal::texthash(
- 'pipa' => 'Pick parameters to generate membership list',
- 'gmem' => "$ucgpterm membership options",
+ 'pipa' => 'Build a list of users for selection of group members',
+ 'gmem' => "Group membership selection list criteria:",
'picr' => 'Pick the criteria to use to build a list of '.
lc($crstype).' users from which you will select ',
- 'meof' => "members of the new $gpterm.",
- 'admg' => "additional members of the $gpterm.",
+ 'meof' => "members of the new group.",
+ 'admg' => "additional members of the group.",
'ifno' => "If you do not wish to add members when you first ".
- "create the $gpterm, do not make any selections.",
- 'asub' => "A subsequent step will also allow you to specify automatic adding/dropping of $gpterm members triggered by specified role and section changes.",
+ "create the group, there is no need to pick any criteria.",
+ 'asub' => "A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section changes in the course.",
'acty' => 'Access types',
'coro' => $crstype.' roles',
'cose' => $crstype.' sections',
@@ -1357,13 +1750,11 @@ sub membership_options {
future => &mt('Will have future access'),
);
- #FIXME need to plumb around for the various cr roles defined by the user
- my @roles = ('st','cc','in','ta','ep');
+ my @roles = ('st','cc','in','ta','ep','cr');
my @sections = keys(%{$sectioncount});
- &topic_bar($r,$image,$lt{'pipa'});
- $r->print('
+ $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'pipa'}).'
'.$lt{'gmem'}.' '.$lt{'picr'});
if ($action eq 'create') {
$r->print($lt{'meof'}.' '.$lt{'ifno'}.' '.$lt{'asub'});
@@ -1376,23 +1767,21 @@ sub membership_options {
');
- $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles));
+ $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles,undef,undef,1,$cdom,$cnum));
if (@sections > 0) {
@sections = sort {$a cmp $b} @sections;
unshift(@sections,'none'); # Put 'no sections' next
unshift(@sections,'all'); # Put 'all' at the front of the list
- $r->print('