--- loncom/interface/loncoursegroups.pm 2010/01/25 22:19:55 1.101.4.1 +++ loncom/interface/loncoursegroups.pm 2019/08/05 19:16:50 1.127.2.2 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: loncoursegroups.pm,v 1.101.4.1 2010/01/25 22:19:55 raeburn Exp $ +# $Id: loncoursegroups.pm,v 1.127.2.2 2019/08/05 19:16:50 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,11 +31,13 @@ use strict; use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); +use Apache::lonhtmlgateway; use Apache::lonlocal; use Apache::lonnavmaps(); use Apache::longroup(); use Apache::portfolio(); use Apache::Constants qw(:common :http); +use HTML::Entities; use LONCAPA::map(); use lib '/home/httpd/lib/perl/'; use LONCAPA; @@ -54,7 +56,7 @@ sub handler { if (! ($env{'request.course.fn'})) { # Not in a course $env{'user.error.msg'}= - "/adm/coursegroups:mdg:0:0:Cannot edit or view course groups"; + "/adm/coursegroups:mdg:0:0:Cannot edit or view course/community groups"; return HTTP_NOT_ACCEPTABLE; } @@ -134,8 +136,8 @@ function changeSort(caller) { } function openGroupRoster(group,status) { var url = '/adm/grouproster?'; - url += 'group='+group+'&status='+status+'&ref=popup'; - var title = 'Group Membership'; + url += 'group='+group+'&status='+status+'&ref=popup'; + var title = 'Group_Membership'; var options = 'scrollbars=1,resizable=1,menubar=0'; options += ',width=700,height=600'; rosterbrowser = open(url,title,options,'1'); @@ -168,13 +170,13 @@ sub display_groups { my %curr_groups = (); my %grp_info = (); my %actionlinks = ( - modify => ' ' '/adm/coursegroups?action=modify&refpage='. + $env{'form.refpage'}.'&state=pick_task&groupname=', + view => '', + delete => '/adm/coursegroups?action=delete&refpage='. + $env{'form.refpage'}.'&state=verify&groupname=', + reenable => '/adm/coursegroups?action=reenable&refpage='. + $env{'form.refpage'}.'&state=verify&groupname=', ); my %lt = &Apache::lonlocal::texthash( modify => 'Modify', @@ -188,7 +190,7 @@ sub display_groups { crtd => 'Created', last => 'Last Modified', func => 'Collaborative Tools', - quot => 'Quota (Mb)', + quot => 'Quota (MB)', memb => 'Members', file => 'Files', dibd => 'Discussion Boards', @@ -221,6 +223,14 @@ sub display_groups { $status); if (%curr_groups) { + my $navmap=Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $r->print('
'. + &mt('An error occurred retrieving information about resources in the course.').'
'. + &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this page.','
',''). + '
'); + return; + } if ($manage_permission) { if ($action ne 'reenable') { $r->print('
'.$lt{'crng'}.''); @@ -240,7 +250,7 @@ sub display_groups { $lt{'crea'} $lt{'crtd'} $lt{'last'} - $lt{'func'} + $lt{'func'} $lt{'quot'} $lt{'memb'} $lt{'file'} @@ -319,23 +329,31 @@ END if (!$functionality) { $functionality = &mt('None available'); } - my $link = $actionlinks{$action}; + my $link; if ($action eq 'modify' || $action eq 'delete' || $action eq 'reenable') { - $link .= $group; + $link = ''.$lt{$action}.''; } else { - $link .= $group.'/smppg?ref=grouplist'; - if (exists($env{'form.refpage'})) { - $link .= '&refpage='.$env{'form.refpage'}; + $link = + &Apache::longroup::get_group_link($cdom,$cnum,$group,$navmap, + $view_permission); + if ($link) { + $link = ''.$lt{$action}.''; } } - $link .= '">'.$lt{$action}.''; if ($action eq 'view') { if ($manage_permission) { - $link .= '  '.$actionlinks{'modify'}. - $group.'">'.$lt{'modify'}.''. - '  '.$actionlinks{'delete'}. - $group.'">'.$lt{'delete'}.''; + $link .= '  '.$lt{'modify'}.'  '.$lt{'delete'}.''; } } $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense'). @@ -383,19 +401,60 @@ END } else { my @coursegroups = split(/:/,$env{'request.course.groups'}); if (@coursegroups > 0) { + my $numlinks = 0; $r->print('

'); my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum); if (%curr_groups) { + my $navmap=Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $r->print('
'. + &mt('An error occurred retrieving information about resources in the course.').'
'. + &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this page.','',''). + '
'); + return; + } foreach my $group (@coursegroups) { my %group_info = &Apache::longroup::get_group_settings( $curr_groups{$group}); my $description = &unescape( $group_info{description}); - $r->print(''.$group,'
'.$description.'

'); + my ($link,$hidden) = + &Apache::longroup::get_group_link($cdom,$cnum,$group,$navmap, + $view_permission); + if ($link) { + $link .= '&ref=grouplist'; + $r->print(''. + $description.'

'); + $numlinks ++; + } elsif ($hidden) { + my $numtools = 0; + my $refarg = '&ref=grouplist'; + my $output = + &Apache::longroup::display_group_links($r,$env{'form.grade_target'},$group,'view', + $refarg,\$numtools,$hidden,%group_info); + if ($numtools) { + $r->print(''.$description.''. + '
'.$output.'

'); + $numlinks ++; + } + } } } + if (!$numlinks) { + $r->print( + '

' + .&mt('You do not currently have access to any '.$gpterm.'s' + .' in this '.lc($crstype).'.') + .'

' + ); + } } else { - $r->print(&mt('You are not currently a member of any active '.$gpterm.'s in this '.lc($crstype).'.')); + $r->print( + '

' + .&mt('You are not currently a member of any active '.$gpterm.'s' + .' in this '.lc($crstype).'.') + .'

' + ); } } return; @@ -537,7 +596,7 @@ sub group_administration { if (ref($stored{'autorole'}) eq 'ARRAY') { foreach my $role (@{$stored{'autorole'}}) { - unless ($role eq 'cc') { + unless (($role eq 'cc') || ($role eq 'co')) { $elements{'modify'}{'change_settings'}{'sec_'.$role} = 'selectbox'; } @@ -785,7 +844,7 @@ sub group_administration { } var maxposs = '.sprintf("%.2f",$maxposs).'; if (newquota > maxposs) { - alert("The group portfolio quota you entered for this group ("+newquota+" Mb) exceeds the maximum possible ("+maxposs+" Mb). Please enter a smaller number."); + alert("The group portfolio quota you entered for this group ("+newquota+" MB) exceeds the maximum possible ("+maxposs+" MB). Please enter a smaller number."); return; } var re_quota = '.$float_check.'; @@ -804,7 +863,7 @@ sub group_administration { } } if (warn_zero == 1) { - alert("You have indicated that the group portfolio should be enabled, but you have set the respository quota to 0 Mb.\nThis will prevent any upload of files.\nPlease set a value or disable the repository feature."); + alert("You have indicated that the group portfolio should be enabled, but you have set the repository quota to 0 MB.\nThis will prevent any upload of files.\nPlease set a value or disable the repository feature."); return; } } @@ -870,7 +929,7 @@ function changeSort(caller) { faq=>9,bug=>'Instructor Interface',}); if ($action eq 'modify' || $action eq 'delete') { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/coursegroups?refpage=cusr&action=$action", + ({href=>"/adm/coursegroups?refpage=cusr&action=$action", text=>"Groups", faq=>9,bug=>'Instructor Interface',}); } @@ -1086,7 +1145,7 @@ sub display_control { &add_members_form($r,$cdom,$cnum,$action,$state,$page,$startdate, $enddate,$groupname,$description,$granularity, $quota,$sectioncount,$tools,$functions,$stored, - $states,$navbuttons,$gpterm,$ucgpterm); + $states,$navbuttons,$gpterm,$ucgpterm,$crstype); } elsif ($state eq 'pick_members') { &choose_members_form($r,$cdom,$cnum,$action,$state,$page, $groupname,$description,$granularity,$quota, @@ -1119,31 +1178,36 @@ sub display_control { my %stored = &retrieve_settings($cdom,$cnum,$groupname,$action); if ($state eq 'verify') { &verify_delete($r,$groupname,$state,$action,$page,$states, - \%stored); + \%stored,$crstype); } elsif ($state eq 'result') { - &delete_group($r,$cdom,$cnum,$groupname); + &delete_group($r,$cdom,$cnum,$groupname,$crstype); } } elsif ($action eq 'reenable') { my %stored = &retrieve_settings($cdom,$cnum,$groupname,$action); if ($state eq 'verify') { &verify_reenable($r,$groupname,$state,$action,$page,$states, - \%stored); + \%stored,$crstype); } elsif ($state eq 'result') { - &reenable_group($r,$cdom,$cnum,$groupname); + &reenable_group($r,$cdom,$cnum,$groupname,$crstype); } } } sub verify_delete { - my ($r,$groupname,$formname,$action,$page,$states,$stored) = @_; + my ($r,$groupname,$formname,$action,$page,$states,$stored,$crstype) = @_; $r->print(&Apache::lonhtmlcommon::echo_form_input([])); $r->print(&mt('You have requested deletion of the group [_1].' ,''.$stored->{'description'}.''). '

'.&mt('When a group is deleted the following occurs:').''.&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.')); + '
  • '.&mt('The group ceases to be available either for viewing or for modification of group settings and membership.').'
  • '); + if ($crstype eq 'Community') { + $r->print( '
  • '.&mt("The group folder is removed from the folder containing it - normally this is the 'Community Groups' folder which contains folders for all groups in the community.").'
  • '. + ''.&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 community in the future.")); + } else { + $r->print( '
  • '.&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; @@ -1156,7 +1220,7 @@ sub verify_delete { } sub delete_group { - my ($r,$cdom,$cnum,$groupname) = @_; + my ($r,$cdom,$cnum,$groupname,$crstype) = @_; my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum, $groupname); my $now = time; @@ -1198,38 +1262,45 @@ sub delete_group { .&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); + my $outcome = &modify_folders($cdom,$cnum,$groupname,$crstype); if ($outcome eq '') { - $r->print('
    ' - .&mt('Group successfully deleted.') - .'
    '); + my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Group successfully deleted.')); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); } 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) - .'
    '); + $r->print('
    '); + if ($crstype eq 'Community') { + $r->print(&mt("Although the group was deleted, an error occurred when removing the group's folder from the 'Community Groups' folder: [_1]",$outcome)); + } 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)); + } + $r->print('
    '); } } else { - $r->print('
    ' - .&mt('Group deletion failed.') - .'
    '); + my $msg = &Apache::lonhtmlcommon::confirm_success(&mt('Group deletion failed.'),1); + $msg = &Apache::loncommon::confirmwrapper($msg); + $r->print($msg); } } return; } sub reenable_folder { - my ($cdom,$cnum,$groupname,$description) = @_; + my ($cdom,$cnum,$groupname,$description,$crstype) = @_; my $outcome; my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/'; my $allgrpsmap = $crspath.'group_allfolders.sequence'; - my $foldertitle = &mt('Course Folder -[_1]',$description); + my $foldertitle; + if ($crstype eq 'Community') { + $foldertitle = &mt("Community Folder -[_1]",$description); + } else { + $foldertitle = &mt("Course Folder -[_1]",$description); + } my $mapurl = $crspath.'group_folder_'. $groupname.'.sequence'; my ($errtext,$fatal)=&LONCAPA::map::mapread($allgrpsmap); @@ -1243,7 +1314,7 @@ sub reenable_folder { $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); + my ($outtext,$errtext) = &LONCAPA::map::storemap($allgrpsmap,1,1); if ($errtext) { $outcome='
    ' .&mt('An error occurred when saving updated parent folder to group:' @@ -1258,14 +1329,19 @@ sub reenable_folder { } sub modify_folders { - my ($cdom,$cnum,$groupname) = @_; + my ($cdom,$cnum,$groupname,$crstype) = @_; 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.'). - '
    '; + $outcome = '
    '; + if ($crstype eq 'Community') { + $outcome .= &mt("Error reading community contents.").' '. + &mt("You need to re-initialize the community."); + } else { + $outcome .= &mt("Error reading course contents.").' '. + &mt("You need to re-initialize the course."); + } + $outcome .= '
    '; return $outcome; } $groupmap = '/uploaded/'.$cdom.'/'.$cnum.'/'.'group_folder_'. @@ -1303,7 +1379,7 @@ sub modify_folders { $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1]; } $#LONCAPA::map::order--; - my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1); + my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1,1); if ($errtext) { $outcome='
    ' .&mt('An error occurred when saving updated parent folder to group:') @@ -1320,13 +1396,18 @@ sub modify_folders { } sub verify_reenable { - my ($r,$groupname,$formname,$action,$page,$states,$stored) = @_; + my ($r,$groupname,$formname,$action,$page,$states,$stored,$crstype) = @_; $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.').'
    '); + '
  • '.&mt('Group settings and membership at the time the group was deleted are reinstated.').'
  • '); + if ($crstype eq 'Community') { + $r->print(&mt("A group folder is added to the 'Community Groups' folder which contains folders for all groups in the community.")); + } else { + $r->print(&mt("A group folder is added to the 'Course Groups' folder which contains folders for all groups in the course.")); + } + $r->print('
  • '); my $prevtext = &mt('Go back'); my $nexttext = &mt('Reenable group'); my $prev; @@ -1339,7 +1420,7 @@ sub verify_reenable { } sub reenable_group { - my ($r,$cdom,$cnum,$groupname) = @_; + my ($r,$cdom,$cnum,$groupname,$crstype) = @_; my %groups = &Apache::longroup::coursegroups($cdom,$cnum,$groupname, 'deleted_groups'); @@ -1413,20 +1494,24 @@ $context) eq 'ok') { .&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); + my $outcome = &reenable_folder($cdom,$cnum,$groupname,$description,$crstype); if ($outcome eq '') { - $r->print('
    ' - .&mt('Group successfully re-enabled.') - .'
    '); + my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Group successfully re-enabled.')); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); } 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) - .'
    '); + $r->print('
    '); + if ($crstype eq 'Community') { + $r->print(&mt("Although the group was re-enabled, an error occurred when adding the group's folder to the 'Community Groups' folder: [_1]",$outcome)); + } 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)); + } + $r->print('
    '); } } else { - $r->print('
    ' - .&mt('Re-enabling group failed.') - .'
    '); + my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Re-enabling group failed.'),1); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); } return; } @@ -1440,7 +1525,7 @@ sub header { {'add_entries' => $loaditems,}); my $output = <<"END"; $start_page -
    + END if ($action eq 'create' || $action eq 'modify') { @@ -1500,16 +1585,19 @@ sub build_members_list { sub group_files { my ($group,$portpath,$numfiles,$numdirs) = @_; my $dirptr=16384; - 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) { - $portpath .= '/'.$filename; - $$numdirs ++; - &group_files($group,$portpath,$numfiles,$numdirs) - } else { - $$numfiles ++; + my ($dirlistref,$listerror) = + &Apache::portfolio::get_dir_list($portpath,undef,$group); + if (ref($dirlistref) eq 'ARRAY') { + foreach my $line (@{$dirlistref}) { + 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) { + $portpath .= '/'.$filename; + $$numdirs ++; + &group_files($group,$portpath,$numfiles,$numdirs) + } else { + $$numfiles ++; + } } } } @@ -1531,7 +1619,7 @@ sub group_members { future => 0, ); my $totalmembers = 0; - foreach my $member (keys %memberhash) { + foreach my $member (keys(%memberhash)) { $totalmembers ++; my ($end,$start) = split(/:/,$memberhash{$member}); unless ($start == -1) { @@ -1579,7 +1667,7 @@ sub general_settings_form { &access_date_settings($r,$action,$formname,$stored,2,$gpterm,$ucgpterm); if ($action eq 'create') { &membership_options($r,$cdom,$cnum,$action,$formname,$sectioncount,3, - $gpterm,$ucgpterm); + $gpterm,$ucgpterm,$crstype); $nexttext = $$navbuttons{'gtns'}; } else { my @available = (); @@ -1588,7 +1676,7 @@ sub general_settings_form { @{$tools} = sort(keys(%{$functions})); &privilege_specificity($r,$action,3,$tools,$stored,$toolprivs, $fixedprivs,\@available,$formname, - $gpterm,$ucgpterm,$functions); + $gpterm,$ucgpterm,$functions,$crstype); &mapping_options($r,$action,$formname,$page,$sectioncount, $states,$stored,$navbuttons,4,5, $gpterm,$ucgpterm,$crstype,$cdom,$cnum); @@ -1646,7 +1734,7 @@ sub groupsettings_options { if ($remnum) { $halfnum ++; } - my @allfunctions = sort(keys (%{$functions})); + my @allfunctions = sort(keys(%{$functions})); $r->print(&Apache::lonhtmlcommon::row_title($lt{'func'}) .'
    ' @@ -1701,19 +1789,19 @@ sub groupsettings_options { } else { $r->print(&mt('Quota allocated to group portfolio:')); } - $r->print(' '.&mt('[_1] Mb','')); + $r->print(' '.&mt('[_1] MB','')); if ($action eq 'create') { $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.' + .&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', + $r->print('  ('.&mt('The quota is currently [_1] MB', $$stored{'quota'}).').'); $r->print('
    ' - .&mt('The quota can be increased to [_1] Mb, ' + .&mt('The quota can be increased to [_1] MB, ' .'by adding all unallocated space for '.$gpterm.'s in the '.lc($crstype).'.' ,sprintf("%.2f",$maxposs))); } @@ -1741,38 +1829,47 @@ sub get_quota_constraints { } sub membership_options { - my ($r,$cdom,$cnum,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm)=@_; - my $crstype = &Apache::loncommon::course_type(); + my ($r,$cdom,$cnum,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm,$crstype)=@_; my %lt = &Apache::lonlocal::texthash( '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 group.", - 'admg' => "additional members of the group.", - 'ifno' => "If you do not wish to add members when you first ". - "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.", + 'gmem' => 'Group membership selection list criteria:', + 'picr' => 'Pick the criteria to use to build a list of course users from which you will select members of the new group.', + 'pica' => 'Pick the criteria to use to build a list of course users from which you will select additional members of the group.', + 'ifno' => 'If you do not wish to add members when you first create the group, there is no need to pick any criteria.', 'acty' => 'Access types', - 'coro' => $crstype.' roles', - 'cose' => $crstype.' sections', + 'coro' => 'Course roles', + 'cose' => 'Course sections', ); + if ($crstype eq 'Community') { + $lt{'picr'} = &mt('Pick the criteria to use to build a list of community participants from which you will select '); + $lt{'asub'} = &mt('A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section [_1]changes[_2] in the course.','',''); + $lt{'coro'} = &mt('Community roles'); + $lt{'cose'} = &mt('Community sections'); + } else { + $lt{'asub'} = &mt('A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section [_1]changes[_2] in the course.','',''); + } my %status_types = ( active => &mt('Currently has access'), previous => &mt('Previously had access'), future => &mt('Will have future access'), ); - my @roles = ('st','cc','in','ta','ep','cr'); + my @roles = ('st'); + if ($crstype eq 'Community') { + push(@roles,'co'); + } else { + push(@roles,'cc'); + } + push (@roles,('in','ta','ep','ad','cr')); my @sections = keys(%{$sectioncount}); $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'pipa'}).' - '.$lt{'gmem'}.'
    '.$lt{'picr'}); + '.$lt{'gmem'}.'
    '); if ($action eq 'create') { - $r->print($lt{'meof'}.'
    '.$lt{'ifno'}.'
    '.$lt{'asub'}); + $r->print($lt{'picr'}.'
    '.$lt{'ifno'}.'
    '.$lt{'asub'}); } else { - $r->print($lt{'admg'}); + $r->print($lt{'pica'}); } $r->print('
    @@ -1889,7 +1986,7 @@ sub choose_members_form { } &privilege_specificity($r,$action,$specimg,$tools,$stored,$toolprivs, $fixedprivs,\@available,$formname,$gpterm,$ucgpterm, - $functions); + $functions,$crstype); my $newusers = &pick_new_members($r,$action,$formname,\@available,$idx, $stored,$memimg,$users,$userdata, $granularity,\%origmembers,$gpterm, @@ -1952,10 +2049,10 @@ sub print_current_settings { dfac => 'Default access dates', ygrs => "Your group selections - ", tfwa => "The following settings will apply to the group:", - difn => 'Different collaborative tools
    for different members:', stda => 'Start date:', enda => 'End date:', ); + $lt{'difn'} = &mt('Different collaborative tools[_1]for different members:','
    '); my $showstart = &Apache::lonlocal::locallocaltime($startdate); my $showend; if ($enddate == 0) { @@ -2005,7 +2102,7 @@ sub print_current_settings { $r->print(''); } - my $quota_text=&mt('[_1] Mb',$quota); + my $quota_text=&mt('[_1] MB',$quota); my $granu_text=&mt($granularity); $r->print(<<"END"); @@ -2067,7 +2164,7 @@ sub pick_new_members { &check_uncheck_buttons($r,$formname,'member',$lt{'addm'}); if (@{$available} > 0 && $granularity eq 'Yes') { $r->print(' -
    '.$lt{'setf'}.' +
    '.$lt{'setf'}.' @@ -2166,7 +2263,7 @@ sub pick_new_members { sub privilege_specificity { my ($r,$action,$img,$tools,$stored,$toolprivs,$fixedprivs,$available, - $formname,$gpterm,$ucgpterm,$functions) = @_; + $formname,$gpterm,$ucgpterm,$functions,$crstype) = @_; my %lt = &Apache::lonlocal::texthash ( 'uprv' => 'User privileges for collaborative tools', 'frty' => 'For each collaborative tool you have chosen to include, '. @@ -2195,11 +2292,15 @@ sub privilege_specificity { "for users who receive specific sections/roles in the course ", 'asyo' => "As you have chosen not to include any collaborative tools ". "in the group, no default optional privileges need to be set.", - 'plin' => 'Indicate which optional privileges members '. 'will receive by default for a specific tool.', 'oppr' => 'Optional privileges', 'defp' => 'The default privileges new members will receive are:', ); + $lt{'plin'} = &mt('Indicate which [_1]optional[_2] privileges members '. + 'will receive by default for a specific tool.','',''); + if ($crstype eq 'Community') { + $lt{'thes'} = &mt('These will be the privileges given to members assigned in the future via automatic group assignment for users who receive specific sections/roles in the community '); + } my $totaloptionalprivs = 0; foreach my $tool (@{$tools}) { foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) { @@ -2480,6 +2581,7 @@ sub current_membership { 'actn' => 'Action?', 'name' => 'Name', 'usnm' => 'Username', + 'stid' => 'ID', 'doma' => 'Domain', 'stda' => 'Start Date', 'enda' => 'End Date', @@ -2517,7 +2619,7 @@ sub current_membership { $r->print(' -
    '.$lt{'curf'}.' +
    '.$lt{'curf'}.'    @@ -2541,7 +2643,7 @@ END $lt{'name'} $lt{'usnm'} $lt{'doma'} - ID + $lt{'ID'} $lt{'stda'} $lt{'enda'} END @@ -2665,7 +2767,10 @@ END } $r->print(&Apache::loncommon::end_data_table()); } else { - $r->print(&mt('There are no active, future or previous group members to modify.')); + $r->print( + '

    ' + .&mt('There are no active, future or previous group members to modify.') + .'

    '); } return $numcurrent; } @@ -2675,7 +2780,7 @@ sub check_uncheck_buttons { $r->print('
    - '.$title.' + '.$title.' @@ -2733,7 +2838,7 @@ sub change_privs_form { } } if (!$exp_or_del) { - $r->print($lt{'nome'}.'
    '); + $r->print('

    '.$lt{'nome'}.'

    '); } $r->print(&Apache::lonhtmlcommon::topic_bar(4,&mt('Setting optional privileges for specific group members'))); @@ -2755,7 +2860,7 @@ sub change_privs_form { sub add_members_form { my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,$groupname, $description,$granularity,$quota,$sectioncount,$tools,$functions, - $stored,$states,$navbuttons,$gpterm,$ucgpterm)=@_; + $stored,$states,$navbuttons,$gpterm,$ucgpterm,$crstype)=@_; $r->print('
    '); my @available = (); my @unavailable = (); @@ -2764,7 +2869,7 @@ sub add_members_form { $groupname,$description,$granularity,$quota, \@available,\@unavailable,$gpterm,$ucgpterm); &membership_options($r,$cdom,$cnum,$action,$formname,$sectioncount,1,$gpterm, - $ucgpterm); + $ucgpterm,$crstype); my $nexttext = $$navbuttons{'gtns'}; my $prevtext = $$navbuttons{'gtpp'}; &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext, @@ -2975,7 +3080,7 @@ sub member_privileges_form { $r->print(''); } $r->print( - '
    '.&mt($$toolprivs{$tool}{$priv}).'' + '
    '.&mt($$toolprivs{$tool}{$priv}).'' .'' .' ' @@ -3095,7 +3200,7 @@ sub process_request { &process_membership($r,$cdom,$cnum,$action,$state,$groupname,$tools, $enddate,$startdate,$userdata,$idx,$toolprivs, $usertools,$specificity,\@defprivs,$memchg,$gpterm, - $ucgpterm); + $ucgpterm,$crstype); } return; } @@ -3129,7 +3234,7 @@ sub write_group_data { $quota = 0; $r->print('
    ' .&mt('The value you entered for the quota for the group portfolio in this '.$gpterm - .' contained invalid characters, so it has been set to 0 Mb. You can change this by' + .' contained invalid characters, so it has been set to 0 MB. You can change this by' .' modifying the '.$gpterm.' settings.') .'
    '); } @@ -3137,7 +3242,7 @@ sub write_group_data { $quota = $maxposs; $r->print('
    ' .&mt('The value you entered for the quota for the group portfolio in this '.$gpterm - .' exceeded the maximum possible value, so it has been set to [_1] Mb ' + .' exceeded the maximum possible value, so it has been set to [_1] MB ' .'(the maximum possible value).',sprintf("%.2f",$maxposs)) .'
    '); } @@ -3205,15 +3310,15 @@ sub write_group_data { $description,$tools,\%groupinfo, $gpterm,$ucgpterm,$crstype); if ($result eq 'ok') { - $r->print('
    ' - .&mt($ucgpterm.' [_1] was created.',''.$groupname.'') - .'
    '); + my $msg = &Apache::lonhtmlcommon::confirm_success(&mt($ucgpterm.' [_1] was created.',''.$groupname.'')); + $msg = &Apache::loncommon::confirmwrapper($msg); + $r->print($msg); } else { - $r->print('
    ' - .&mt('A problem occurred when creating folders for the new '.$gpterm.' [_1]:' - ,''.$groupname.'') - .'
    '.$result - .'
    '); + my $msg = &Apache::lonhtmlcommon::confirm_success(&mt('A problem occurred when creating folders for the new '.$gpterm.' [_1]:' + ,''.$groupname.'') + .'
    '.$result,1); + $msg = &Apache::loncommon::confirmwrapper($msg); + $r->print($msg); } } elsif ($action eq 'modify') { my (@oldtools,@newtools); @@ -3257,25 +3362,36 @@ sub write_group_data { } undef($navmap); } else { - $error = &mt('An error occurred while setting parameters '. + if ($crstype eq 'Community') { + $error = &mt("An error occurred while setting parameters '. 'for Discussion Boards folder: '. - 'Could not retrieve course information' ); + 'Could not retrieve community information"); + } else { + $error = &mt("An error occurred while setting parameters '. + 'for Discussion Boards folder: '. + 'Could not retrieve course information"); + } } } else { $r->print($outcome); } } } else { - $error = &mt("An error occurred while retrieving the contents of the group's folder.").'
    '. - &mt('You need to re-initialize the course.'); + $error = &mt("An error occurred while retrieving the contents of the group's folder.").'
    '; + if ($crstype eq 'Community') { + $error .= &mt("You need to re-initialize the community."); + + } else { + $error .= &mt("You need to re-initialize the course."); + } } if ($error ne '') { $r->print('
    '.$error.'
    '); } } - $r->print('
    ' - .&mt($ucgpterm.' [_1] was updated.',''.$groupname.'') - .'
    '); + my $message = &Apache::lonhtmlcommon::confirm_success(&mt($ucgpterm.' [_1] was updated.',''.$groupname.'')); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); } } else { my %actiontype = ( @@ -3285,10 +3401,10 @@ sub write_group_data { &Apache::lonnet::logthis("Failed to store $gpterm $groupname ". 'in '.lc($crstype).': '.$cnum. ' in domain: '.$cdom); - $r->print('
    ' - .&mt('An error occurred when [_1] the '.$gpterm.'. ' - .'Please try again.',$actiontype{$action}) - .'
    '); + $r->print('

    ' + .&mt('An error occurred when '.$actiontype{$action}.' the '.$gpterm.'. ' + .'Please try again.') + .'print(&mt('The following users were successfully [_1]',$type)); + my $msgall =''; + foreach my $type (sort(keys(%added))) { + my $message; + my $tmsg = "The following users were successfully $type"; if (!($type eq 'deleted' || $type eq 'expired')) { - $r->print(&mt(' with the following privileges')); + $tmsg .= ' with the following privileges'; } - $r->print(':
    '); + $message .= &mt($tmsg.':').'
    '; foreach my $user (@{$added{$type}}) { my $privlist = ''; if (!($type eq 'deleted' || $type eq 'expired')) { @@ -3474,10 +3592,14 @@ sub process_membership { } $privlist =~ s/, $//; } - $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.$privlist.'
    '); + $message .= $$userdata{$user}[$$idx{fullname}].' - '.$user.$privlist.'
    '; } - $r->print('
    '); + $message .= '
    '; + $message = &Apache::lonhtmlcommon::confirm_success($message); + $msgall .= $message; } + $msgall = &Apache::loncommon::confirmwrapper($msgall); + $r->print($msgall); } if ($num_fail) { foreach my $type (sort(keys(%failed))) { @@ -3490,24 +3612,33 @@ sub process_membership { } $r->print('
    '); } - if (@unchanged > 0) { - $r->print(&mt('No change occurred for the following users:').'
    '); - foreach my $user (sort(@unchanged)) { - $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'
    '); - } - $r->print('
    '); - } +# Is that really needed? +# +# if (@unchanged > 0) { +# $r->print(&mt('No change occurred for the following users:').'
    '); +# foreach my $user (sort(@unchanged)) { +# $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'
    '); +# } +# $r->print('
    '); +# } if ($roster_result eq 'ok') { $r->print('

    ' .&mt($ucgpterm.' membership list updated.') .'
    '); - $r->print('

    ' - .&mt('Any currently logged in course users affected by the changes you made' + $r->print('

    '); + if ($crstype eq 'Community') { + $r->print(&mt("Any currently logged in community users affected by the changes you made" .' to group membership or privileges for the [_1] group will need to log out' .' and log back in for their LON-CAPA sessions to reflect these changes.' - ,''.$groupname.'') - .'

    ' - ); + ,''.$groupname.'')); + + } else { + $r->print(&mt("Any currently logged in course users affected by the changes you made" + .' to group membership or privileges for the [_1] group will need to log out' + .' and log back in for their LON-CAPA sessions to reflect these changes.' + ,''.$groupname.'')); + } + $r->print('

    '); } else { $r->print('
    ' .&mt("An error occurred while updating the $gpterm membership list:") @@ -3578,7 +3709,7 @@ sub mapping_settings { @sections = ('all','none'); } $r->print(&Apache::lonhtmlcommon::topic_bar($image,$$lt{'pirs'})); - my @roles = &standard_roles(); + my @roles = &standard_roles($crstype); my %customroles = &Apache::lonhtmlcommon::course_custom_roles($cdom,$cnum); $r->print(&Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row()); @@ -3621,10 +3752,10 @@ sub print_autorole_item { my ($role,$roletitle,$sections) = @_; my $sections_sel; if (@{$sections} > 0) { - if ($role eq 'cc') { + if (($role eq 'cc') || ($role eq 'co')) { $sections_sel = ''. &mt('all sections').''; + 'name="sec_'.$role.'" value="all" />'; } else { $sections_sel=''. §ions_selection($sections,'sec_'.$role). @@ -3640,43 +3771,45 @@ sub print_autorole_item { } sub standard_roles { - my @roles = ('cc','in','ta','ep','st'); + my ($crstype) = @_; + my @roles = qw(in ta ep ad st); + if ($crstype eq 'Community') { + unshift(@roles,'co'); + } else { + unshift(@roles,'cc'); + } return @roles; } sub modify_menu { my ($r,$groupname,$page,$gpterm) = @_; my @menu = - ( - { text => "Modify default $gpterm settings", - help => 'Course_Modify_Group', - state => 'change_settings', - branch => 'settings', + ( { categorytitle =>'Group Actions', + items => [ + + { linktext => "Modify default $gpterm settings", + url => '/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state=change_settings&branch=settings', + icon => 'grp_settings.png', + alttext => "Modify default $gpterm settings", + permission => '1', + help => 'Course_Modify_Group', }, - { text => 'Modify access, tools and/or privileges for previous, '. - 'future, or current members', + { linktext => 'Modify access, tools and privileges for members', + url => '/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state=change_members&branch=members', + icon => 'grp_tools.png', + alttext => 'Modify access, tools and privileges for members', + permission => '1', help => 'Course_Modify_Group_Membership', - state => 'change_members', - branch => 'members', }, - { text => "Add member(s) to the $gpterm", + { linktext => "Add member(s) to the $gpterm", + url => '/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state=add_members&branch=adds', + icon => 'grp_add.png', + alttext => "Add member(s) to the $gpterm", + permission => '1', help => 'Course_Group_Add_Members', - state => 'add_members', - branch => 'adds', - }, - ); - my $menu_html = ''; - foreach my $menu_item (@menu) { - $menu_html .= - '

    '; - $menu_html.= &mt($menu_item->{'text'}).''; - if (exists($menu_item->{'help'})) { - $menu_html.= - &Apache::loncommon::help_open_topic($menu_item->{'help'}); - } - $menu_html.='

    '.$/; - } - $r->print($menu_html); + }]} + ); + $r->print(&Apache::lonhtmlcommon::generate_menu(@menu)); return; } @@ -3779,9 +3912,14 @@ sub add_group_folder { my ($cdom,$cnum,$now,$groupname,$action,$description,$tools,$groupinfo, $gpterm,$ucgpterm,$crstype) = @_; if ($cdom eq '' || $cnum eq '') { - return '' - .&mt('Error: invalid course domain or number - group folder creation failed.') - .''; + my $error = ''; + if ($crstype eq 'Community') { + $error .= &mt("Error: invalid community domain or number - group folder creation failed."); + } else { + $error .= &mt("Error: invalid course domain or number - group folder creation failed."); + } + $error .= ''; + return $error; } my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage,$warning); my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/'; @@ -3849,8 +3987,16 @@ sub add_group_folder { my ($furl,$ferr)= &Apache::lonuserstate::readmap($cdom.'/'.$cnum); my $navmap = Apache::lonnavmaps::navmap->new(); if (!defined($navmap)) { - return $warning.''.&mt('Error retrieving course contents'). - ' '.&mt('You need to re-initialize the course.').''; + $warning .= ''; + if ($crstype eq 'Community') { + $warning .= &mt("Error retrieving community contents"). + ' '.&mt("You need to re-initialize the community."); + } else { + $warning .= &mt("Error retrieving course contents"). + ' '.&mt("You need to re-initialize the course."); + } + $warning .= ''; + return $warning; } # modify parameters my $parm_result; @@ -3931,7 +4077,7 @@ sub map_updater { $LONCAPA::map::resources[$newidx] = $itemtitle.':'.$newmapurl. ':false:normal:res'; $LONCAPA::map::order[1+$#LONCAPA::map::order]=$newidx; - my ($outtext,$errtext) = &LONCAPA::map::storemap($parentmap,1); + my ($outtext,$errtext) = &LONCAPA::map::storemap($parentmap,1,1); if ($errtext) { $outcome = '
    ' .&mt('Error saving updated parent folder.')." ($parentmap): $errtext" @@ -3955,14 +4101,18 @@ sub new_map { } sub parm_setter { - my ($navmap,$cdom,$url,$groupname) = @_; - my $allresults; + my ($navmap,$cdom,$url,$groupname,$crstype) = @_; if (!defined($navmap)) { - $allresults = '
    '. - &mt('Parameters not set for [_1] because the contents of the course could not be retrieved.',$url).' '. - &mt('You need to reinitialize the course.'). - '
    '; - return $allresults; + my $allresults; + if ($crstype eq 'Community') { + $allresults = &mt("Parameters not set for [_1] because the contents of the community could not be retrieved.",$url).' '. + &mt("You need to reinitialize the community."); + } else { + $allresults = &mt("Parameters not set for [_1] because the contents of the course could not be retrieved.",$url).' '. + &mt("You need to reinitialize the course."); + + } + return '
    '.$allresults.'
    '; } my %hide_settings = ( 'course' => { @@ -3976,6 +4126,7 @@ sub parm_setter { }, ); my $res = $navmap->getResourceByUrl($url); + my $allresults; if ($res) { my $symb = $res->symb(); foreach my $level (keys(%hide_settings)) { @@ -3992,10 +4143,13 @@ sub parm_setter { } } } else { - $allresults = '
    ' - .&mt('Parameters not set for [_1] because the resource was not recognized' - .' as part of the course.',''.$url.'') - .'
    '; + $allresults = '
    '; + if ($crstype eq 'Community') { + $allresults .= &mt("Parameters not set for [_1] because the resource was not recognized as part of the community.",''.$url.''); + } else { + $allresults .= &mt('Parameters not set for [_1] because the resource was not recognized as part of the course.',''.$url.''); + } + $allresults .= '
    '; } return $allresults; } @@ -4004,10 +4158,9 @@ sub create_homepage { my ($cdom,$cnum,$name,$groupinfo,$tools,$gpterm,$ucgpterm,$now) = @_; my $functionality = join(',',@{$tools}); my $content = &unescape($$groupinfo{description}); - $content=~s/\s+$//s; - $content=~s/^\s+//s; - $content=~s/\$//s; - $content=&Apache::lonfeedback::clear_out_html($content,1); + chomp($content); + my $gateway = Apache::lonhtmlgateway->new(); + $content = $gateway->process_incoming_html($content,1); my %pageinfo = ( 'aaa_title' => "$ucgpterm: $name", @@ -4067,43 +4220,40 @@ sub validate_groupname { } my %lt = &Apache::lonlocal::texthash ( igna => "Invalid $gpterm name", - tgne => "The $gpterm name entered ", grna => "$ucgpterm names and section names used in a ". "$crstype must be unique.", - isno => "is not a valid name.", gnmo => "$ucgpterm names may only contain letters, ". "numbers or underscores.", - cnnb => "can not be used as it is the name of ", - inth => " in this $crstype", - thgr => "- does not correspond to the name of an ". - "existing $gpterm", ); - my $exitmsg = ''.$lt{'igna'}.'

    '. - $lt{'tgne'}.' "'.$groupname.'" '; - my $dupmsg = $lt{'grna'}; - my $earlyout; + my $exitmsg = ''.$lt{'igna'}.'

    '; + my $nameshown = &Apache::loncommon::cleanup_html($groupname); if (($groupname eq '') || ($groupname =~ /\W/)) { - $earlyout = $exitmsg.$lt{'isno'}.'
    '.$lt{'gnmo'}; - return $earlyout; + return $exitmsg. + &mt("The $gpterm name entered '[_1]' is not a valid name.",$nameshown). + '
    '.$lt{'gnmo'}; + } elsif ($groupname eq 'syllabus') { + return $exitmsg. + &mt("The $gpterm name entered '[_1]' is reserved for use by LON-CAPA.",$nameshown); } if (exists($sectioncount{$groupname})) { - return $exitmsg.$lt{'cnnb'}.&mt('a section').$lt{'inth'}. - '
    '.$lt{'grna'}; + return $exitmsg. + &mt("The $gpterm name entered '[_1]' can not be used as it is the name of a section in this $crstype.",$nameshown). + '
    '.$lt{'grna'}; } if ($action eq 'create') { if (exists($curr_groups{$groupname})) { - return $exitmsg.$lt{'cnnb'}.&mt('an existing [_1]',$gpterm). - $lt{'inth'}.'.
    '.$lt{'grna'}; + return $exitmsg. + &mt("The $gpterm name entered '[_1]' can not be used as it is the name of an existing $gpterm in this $crstype.",$nameshown). + '
    '.$lt{'grna'}; } elsif (exists($deleted_groups{$groupname})) { - return $exitmsg.$lt{'cnnb'}.&mt('a [_1] which previously existed',$gpterm). - $lt{'inth'}.'.
    '.$lt{'grna'}; + return $exitmsg. + &mt("The $gpterm name entered '[_1]' can not be used as it is the name of a $gpterm which previously existed in this $crstype.",$nameshown). + '
    '.$lt{'grna'}; } } elsif ($action eq 'modify') { unless(exists($curr_groups{$groupname})) { - $earlyout = &mt('[_1] name:',$ucgpterm).' '.$groupname.$lt{'thgr'}. - $lt{'inth'}; - return $earlyout; + return &mt("$ucgpterm name: [_1] does not correspond to the name of an existing $gpterm in this $crstype.",$nameshown); } } return; @@ -4148,3 +4298,4 @@ sub check_changes { } 1; + 500 Internal Server Error

    Internal Server Error

    The server encountered an internal error or misconfiguration and was unable to complete your request.

    Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

    More information about this error may be available in the server error log.