--- loncom/interface/loncoursegroups.pm 2006/11/20 23:49:49 1.64 +++ loncom/interface/loncoursegroups.pm 2023/07/29 20:33:25 1.132 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: loncoursegroups.pm,v 1.64 2006/11/20 23:49:49 raeburn Exp $ +# $Id: loncoursegroups.pm,v 1.132 2023/07/29 20:33:25 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,11 +31,14 @@ 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::lonuserutils(); use Apache::Constants qw(:common :http); +use HTML::Entities; use LONCAPA::map(); use lib '/home/httpd/lib/perl/'; use LONCAPA; @@ -54,7 +57,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; } @@ -75,11 +78,11 @@ sub handler { my $crstype = &Apache::loncommon::course_type(); my %functions = ( - email => 'E-mail', - discussion => 'Discussion boards', - chat => 'Chat', - files => 'File repository', - roster => 'Membership roster', + email => 'Send Messages', + discussion => 'Discussion Boards', + chat => 'Chat Room', + files => 'Group Portfolio', + roster => 'Membership Roster', homepage => $ucgpterm.' home page', ); @@ -92,13 +95,13 @@ sub handler { my $action = $env{'form.action'}; my $state = $env{'form.state'}; - if ((!defined($action)) || ($action eq 'view') || ($action eq 'modify') || ($action eq 'delete')) { + if ((!defined($action)) || ($action eq 'view') || ($action eq 'modify') || ($action eq 'delete') || ($action eq 'reenable')) { if (!defined($state)) { $state = 'view'; } } if ($action eq 'create' || $action eq 'modify' || $action eq 'view' || - $action eq 'delete') { + $action eq 'delete' || $action eq 'reenable') { if ($view_permission || $manage_permission) { if ($state eq 'view') { &print_main_menu($r,$cdom,$cnum,\%functions,\%idx, @@ -111,8 +114,10 @@ sub handler { $crstype); } } else { - $r->print(&mt('You do not have [_1] administration '. - 'privileges in this [_2]',$gpterm,lc($crstype))); + $r->print('<div class="LC_warning">' + .&mt('You do not have '.$gpterm.' administration ' + .'privileges in this '.lc($crstype).'.') + .'</div>'); } } else { &print_main_menu($r,$cdom,$cnum,\%functions,\%idx,$view_permission, @@ -132,23 +137,27 @@ 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'); rosterbrowser.focus(); }\n|; - $r->print(&header('Groups',$jscript,$action,$state)); - if ($env{'form.refpage'} eq 'enrl') { + $r->print(&header('My Space',$jscript,$action,$state)); + if ($env{'form.refpage'} eq 'cusr') { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/dropadd", - text=>"Enrollment Manager"}); + ({href=>"/adm/createuser", + text=>"User Management"}); } &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/coursegroups", text=>"Groups"}); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Groups')); + my $helpitem; + if ($manage_permission) { + $helpitem = 'Creating_Groups'; + } + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Groups',$helpitem)); &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission, $manage_permission,$action,$state,$gpterm,$ucgpterm, $crstype); @@ -162,16 +171,19 @@ sub display_groups { my %curr_groups = (); my %grp_info = (); my %actionlinks = ( - modify => '<a href="/adm/coursegroups?action=modify&refpage='. - $env{'form.refpage'}.'&state=pick_task&groupname=', - view => '<a href="/adm/'.$cdom.'/'.$cnum.'/', - delete => '<a href="/adm/coursegroups?action=delete&refpage='. - $env{'form.refpage'}.'&state=verify&groupname=', + 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', view => 'View', delete => 'Delete', + reenable => 'Re-enable', act => 'Action', gname => 'Group Name', desc => 'Group Title', @@ -179,13 +191,14 @@ sub display_groups { crtd => 'Created', last => 'Last Modified', func => 'Collaborative Tools', - quot => 'Quota (Mb)', + quot => 'Quota (MB)', memb => 'Members', file => 'Files', dibd => 'Discussion Boards', dius => 'Disk Use (%)', nogr => 'No groups exist.', crng => 'Create a new group', + redg => 'Re-enable a deleted group', alth => 'Although your current role has privileges'. ' to view any existing groups in this '. lc($crstype).', you do not have privileges '. @@ -195,11 +208,36 @@ sub display_groups { if (!defined($action)) { $action = 'view'; } - my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum); + my ($status,$reenable_link); + if ($action eq 'reenable') { + $status = 'deleted_groups'; + } else { + if ($manage_permission) { + my %deleted_groups = + &Apache::longroup::coursegroups($cdom,$cnum,undef,'deleted_groups'); + if (keys(%deleted_groups) > 0) { + $reenable_link = ' <a href="/adm/coursegroups?action=reenable&refpage='.$env{'form.refpage'}.'">'.$lt{'redg'}.'</a>'; + } + } + } + my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,undef, + $status); + if (%curr_groups) { + my $navmap=Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $r->print('<div class="LC_error">'. + &mt('An error occurred retrieving information about resources in the course.').'<br />'. + &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this page.','<a href="/adm/roles?selectrole=1&newrole='.$env{'request.role'}.'&orgurl=%2fadm%2fcoursegroups">','</a>'). + '</div>'); + return; + } if ($manage_permission) { - if (!exists($env{'form.refpage'})) { - $r->print('<br /><a href="/adm/coursegroups?action=create">'.$lt{'crng'}.'</a>'); + if ($action ne 'reenable') { + $r->print('<br /><a href="/adm/coursegroups?action=create&refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>'); + } + if ($reenable_link) { + $r->print($reenable_link); } } $r->print('<br /><br />'); @@ -213,7 +251,7 @@ sub display_groups { <th><a href="javascript:changeSort('creator')">$lt{'crea'}</a></th> <th><a href="javascript:changeSort('creation')">$lt{'crtd'}</a></th> <th><a href="javascript:changeSort('modified')">$lt{'last'}</a></th> - <th>$lt{'func'}</b></td> + <th>$lt{'func'}</th> <th><a href="javascript:changeSort('quota')">$lt{'quot'}</a></th> <th><a href="javascript:changeSort('totalmembers')">$lt{'memb'}</a></th> <th><a href="javascript:changeSort('totalfiles')">$lt{'file'}</a></th> @@ -229,13 +267,13 @@ END my $members_result = &group_members($cdom,$cnum,$group, \%grp_info); my $port_path = '/userfiles/groups/'.$group.'/portfolio'; - my $port_dir = &Apache::loncommon::propath($cdom,$cnum).$port_path; my $totaldirs = 0; my $totalfiles = 0; - &group_files($group,$port_dir,\$totalfiles,\$totaldirs); + &group_files($group,$port_path,\$totalfiles,\$totaldirs); $grp_info{$group}{'totalfiles'} = $totalfiles; $grp_info{$group}{'totaldirs'} = $totaldirs; - my $diskuse = &Apache::lonnet::diskusage($cdom,$cnum,$port_dir); + my $getpropath = 1; + my $diskuse = &Apache::lonnet::diskusage($cdom,$cnum,$port_path, $getpropath); if ($grp_info{$group}{'quota'} > 0) { my $pct_use = 0.1 * $diskuse/$grp_info{$group}{'quota'}; $grp_info{$group}{'diskuse'} = sprintf("%.0f",$pct_use); @@ -292,23 +330,31 @@ END if (!$functionality) { $functionality = &mt('None available'); } - my $link = $actionlinks{$action}; - if ($action eq 'modify' || $action eq 'delete') { - $link .= $group; + my $link; + if ($action eq 'modify' || $action eq 'delete' || + $action eq 'reenable') { + $link = '<a href="'.&HTML::Entities::encode($actionlinks{$action}.$group,'<>&"'). + '">'.$lt{$action}.'</a>'; } 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 = '<a href="'.$link; + $link .= (($link=~/\?/)?'&':'?').'ref=grouplist'; + if (exists($env{'form.refpage'})) { + $link .= '&refpage='.$env{'form.refpage'}; + } + $link .= '">'.$lt{$action}.'</a>'; } } - $link .= '">'.$lt{$action}.'</a>'; if ($action eq 'view') { - if (($manage_permission) && - ($env{'form.refpage'} ne 'enrl')) { - $link .= ' '.$actionlinks{'modify'}. - $group.'">'.$lt{'modify'}.'</a>'. - ' '.$actionlinks{'delete'}. - $group.'">'.$lt{'delete'}.'</a>'; + if ($manage_permission) { + $link .= ' <a href="'. + &HTML::Entities::encode($actionlinks{'modify'}.$group,'<>&"'). + '">'.$lt{'modify'}.'</a> <a href="'. + &HTML::Entities::encode($actionlinks{'delete'}.$group,'<>&"'). + '">'.$lt{'delete'}.'</a>'; } } $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense'). @@ -321,7 +367,10 @@ END '<td>'.$functionality.'</td>'. '<td align="right">'.$quota.'</td>'. '<td align="right">'.$totalmembers.'</td>'. - '<td align="right"><nobr>'.&mt('Files: ').$totalfiles.'</nobr><br /><nobr>'.&mt('Folders: ').$totaldirs.'</nobr></td>'. + '<td align="right">'. + '<span class="LC_nobreak">'.&mt('Files: [_1]',$totalfiles).'</span><br />'. + '<span class="LC_nobreak">'.&mt('Folders: [_1]',$totaldirs).'</span>'. + '</td>'. '<td align="right">'.$boards.'</td>'. '<td align="right">'.$diskuse.'</td>'. &Apache::loncommon::end_data_table_row()); @@ -340,32 +389,73 @@ END } else { $r->print($lt{'nogr'}); if ($manage_permission) { - if (!exists($env{'form.refpage'})) { - $r->print('<br /><br /><a href="/adm/coursegroups?action=create">'.$lt{'crng'}.'</a>'); + $r->print('<br /><br /><a href="/adm/coursegroups?action=create&refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>'); + if ($action ne 'reenable') { + if ($reenable_link) { + $r->print($reenable_link); + } } } else { $r->print('<br /><br />'.$lt{'alth'}); - } } } else { my @coursegroups = split(/:/,$env{'request.course.groups'}); if (@coursegroups > 0) { + my $numlinks = 0; $r->print('<br /><br />'); my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum); if (%curr_groups) { + my $navmap=Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $r->print('<div class="LC_error">'. + &mt('An error occurred retrieving information about resources in the course.').'<br />'. + &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this page.','<a href="/adm/roles?selectrole=1&newrole='.$env{'request.role'}.'&orgurl=%2fadm%2fcoursegroups">','</a>'). + '</div>'); + return; + } foreach my $group (@coursegroups) { my %group_info = &Apache::longroup::get_group_settings( $curr_groups{$group}); my $description = &unescape( $group_info{description}); - $r->print('<font size="+1"><a href="/adm/'.$cdom.'/'.$cnum.'/'.$group.'/smppg?ref=grouplist">'.$group,'</a><font><br /><small>'.$description.'</small><br /><br />'); + my ($link,$hidden) = + &Apache::longroup::get_group_link($cdom,$cnum,$group,$navmap, + $view_permission); + if ($link) { + $link .= '&ref=grouplist'; + $r->print('<span style="font-size: larger"><a href="'.$link.'">'. + $description.'</a></span><br /><br />'); + $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('<span style="font-size: larger">'.$description.'</a></span>'. + '<br />'.$output.'<br /><br />'); + $numlinks ++; + } + } } } + if (!$numlinks) { + $r->print( + '<p class="LC_info">' + .&mt('You do not currently have access to any '.$gpterm.'s' + .' in this '.lc($crstype).'.') + .'</p>' + ); + } } else { - $r->print(&mt('You are not currently a member of any '. - 'active [_1]s in this [_2]',$gpterm, - lc($crstype))); + $r->print( + '<p class="LC_info">' + .&mt('You are not currently a member of any active '.$gpterm.'s' + .' in this '.lc($crstype).'.') + .'</p>' + ); } } return; @@ -379,7 +469,6 @@ sub group_administration { my @types = (); my @roles = (); my @sections = (); - my @buildsections = (); my %users = (); my %userdata = (); my @members = (); @@ -433,7 +522,7 @@ sub group_administration { $state = 'pick_task'; } } else { - %stored = &retrieve_settings($cdom,$cnum,$groupname); + %stored = &retrieve_settings($cdom,$cnum,$groupname,$action); if (ref($stored{'types'}) eq 'ARRAY') { @types = @{$stored{'types'}}; } @@ -508,7 +597,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'; } @@ -539,16 +628,11 @@ sub group_administration { } if (defined($env{'form.sectionpick'})) { @sections=&Apache::loncommon::get_env_multiple('form.sectionpick'); - if (grep/^all$/,@sections) { - @buildsections = sort {$a cmp $b} keys(%sectioncount); - } else { - @buildsections = @sections; - } } } if (($state eq 'pick_members') || ($state eq 'pick_privs') || ($state eq 'change_privs')) { - &build_members_list($cdom,$cnum,\@types,\@roles,\@buildsections,\%users, + &build_members_list($cdom,$cnum,\@types,\@roles,\@sections,\%users, \%userdata); } if ($state eq 'pick_members') { @@ -761,7 +845,7 @@ sub group_administration { } var maxposs = '.sprintf("%.2f",$maxposs).'; if (newquota > maxposs) { - alert("The file repository 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.'; @@ -780,7 +864,7 @@ sub group_administration { } } if (warn_zero == 1) { - alert("You have indicated that the file repository 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; } } @@ -812,6 +896,7 @@ function changeSort(caller) { @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result'); @{$states{'modify'}} = ('pick_task'); @{$states{'delete'}} = ('verify','result'); + @{$states{'reenable'}} = ('verify','result'); @{$branchstates{'noprivs'}} = ('result'); @{$branchstates{'settings'}} = ('change_settings','chgresult'); @{$branchstates{'members'}} = ('change_members','change_privs','memresult'); @@ -822,7 +907,7 @@ function changeSort(caller) { push (@{$states{$action}},@{$branchstates{$env{'form.branch'}}}); } - if (($action eq 'create') || ($action eq 'modify') || ($action eq 'delete')) { + if (($action eq 'create') || ($action eq 'modify') || ($action eq 'delete') || ($action eq 'reenable')) { my $done = 0; my $i=0; while ($i<@{$states{$action}} && !$done) { @@ -838,14 +923,14 @@ function changeSort(caller) { $r->print(&header("Groups Manager", $jscript,$action,$state,$page,$loaditems)); - if ($env{'form.refpage'} eq 'enrl') { + if ($env{'form.refpage'} eq 'cusr') { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/dropadd", - text=>"Enrollment Manager", + ({href=>"/adm/createuser", + text=>"User Management", faq=>9,bug=>'Instructor Interface',}); if ($action eq 'modify' || $action eq 'delete') { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/coursegroups?refpage=enrl&action=$action", + ({href=>"/adm/coursegroups?refpage=cusr&action=$action", text=>"Groups", faq=>9,bug=>'Instructor Interface',}); } @@ -857,7 +942,8 @@ function changeSort(caller) { if ($env{'form.refpage'} eq 'grouplist') { &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/$cdom/$cnum/$env{'form.groupname'}/smppg?ref=grouplist", - text=>"Group: $description",}); + text=>&mt('Group').": $description", + no_mt=>1}); } } @@ -885,15 +971,19 @@ function changeSort(caller) { verify => 'Verify deletion', result => 'Deletion Complete' ); + %{$trail{'reenable'}} = &Apache::lonlocal::texthash( + verify => 'Verify Re-enable', + result => 'Re-enabled' + ); my %navbuttons = &Apache::lonlocal::texthash( - gtns => 'Go to next step', - gtps => 'Go to previous step', + gtns => 'Next',#'Go to next step', + gtps => 'Back',#'Go to previous step', crgr => 'Create '.$gpterm, - mose => 'Modify settings', - gtpp => 'Go to previous page', + mose => 'Save',#'Modify settings', + gtpp => 'Back',#'Go to previous page', adme => 'Add members', ); - if ((($action eq 'create') || ($action eq 'modify') || ($action eq 'delete')) && + if ((($action eq 'create') || ($action eq 'modify') || ($action eq 'delete') || ($action eq 'reenable')) && ($manage_permission)) { for (my $i=0; $i<@{$states{$action}}; $i++) { if ($state eq $states{$action}[$i]) { @@ -938,8 +1028,16 @@ function changeSort(caller) { } sub retrieve_settings { - my ($cdom,$cnum,$groupname) = @_; - my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,$groupname); + my ($cdom,$cnum,$groupname,$action) = @_; + my %curr_groups; + my $namespace; + if ($action eq 'reenable') { + $namespace = 'deleted_groups'; + } else { + $namespace = 'coursegroups'; + } + %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,$groupname, + $namespace); return if (!%curr_groups); @@ -1049,7 +1147,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, @@ -1079,30 +1177,43 @@ sub display_control { $sectioncount,$stored,$gpterm,$ucgpterm,$crstype); } } elsif ($action eq 'delete') { - my %stored = &retrieve_settings($cdom,$cnum,$groupname); + 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,$crstype); + } elsif ($state eq 'result') { + &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 following group: ").'<i>'. - $stored->{'description'}.'</i>'. + $r->print(&mt('You have requested deletion of the group [_1].' + ,'<i>'.$stored->{'description'}.'</i>'). '<br /><br />'.&mt('When a group is deleted the following occurs:').'<ul>'. '<li>'.&mt('All group membership is terminated.').'</li>'. - '<li>'.&mt('The group ceases to be available either for viewing or for modification of group settings and membership.').'</li>'. - '<li>'.&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.').'</li>'. - '</ul>'.&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.')); + '<li>'.&mt('The group ceases to be available either for viewing or for modification of group settings and membership.').'</li>'); + if ($crstype eq 'Community') { + $r->print( '<li>'.&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.").'</li>'. + '</ul>'.&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( '<li>'.&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.").'</li>'. + '</ul>'.&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 'enrl') { + if ($env{'form.refpage'} eq 'cusr') { $prev = 'view'; } &display_navbuttons($r,$formname,$prev,$prevtext, @@ -1111,7 +1222,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; @@ -1121,16 +1232,18 @@ sub delete_group { 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}); + my($end,$start,$userprivs) = split(/:/,$membership{$key},3); if ($start != -1) { $num_users ++; - $usersettings{$groupname.':'.$user} = $now.':-1:'; + $usersettings{$groupname.':'.$user} = $now.':-1:'.$userprivs; if (&Apache::lonnet::modify_group_roles($cdom,$cnum, $groupname,$user, - $now,'-1','') + $now,'-1',$userprivs, + '',$context) eq 'ok') { $num_ok ++; push(@deleted,$user); @@ -1147,39 +1260,107 @@ sub delete_group { \%usersettings); } if ($num_fail > 0) { - $r->print(&mt('Group deletion failed because deletion of [_1] out of [_2] members failed',$num_fail,$num_users)); - + $r->print('<div class="LC_error">' + .&mt('Group deletion failed because deletion of [_1] out of [_2] members failed.' + ,$num_fail,$num_users) + .'</div>'); } else { my ($result,$message) = - &Apache::lonnet::delete_coursegroup($cdom,$cnum,$groupname); + &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 ([_1]) occurred when removing the group's folder from the 'Course Groups' folder.",$outcome)); + $r->print('<div class="LC_error">'); + 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('</div>'); } } 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 modify_folders { - my ($cdom,$cnum,$groupname) = @_; +sub reenable_folder { + my ($cdom,$cnum,$groupname,$description,$crstype) = @_; my $outcome; + my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/'; + my $allgrpsmap = $crspath.'group_allfolders.sequence'; + 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); + if ($fatal) { + $outcome='<div class="LC_error">' + .&mt('An error occurred when reading contents of parent folder to group:') + ."<br />($allgrpsmap): $errtext" + .'</div>'; + } 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,1); + if ($errtext) { + $outcome='<div class="LC_error">' + .&mt('An error occurred when saving updated parent folder to group:' + ,"<br />$allgrpsmap - $errtext") + .'</div>'; + } else { + my ($furl,$ferr) = + &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + } + } + return $outcome; +} + +sub modify_folders { + my ($cdom,$cnum,$groupname,$crstype) = @_; + my ($outcome,$groupmap,$groupmapres,$map,$id,$src); my $navmap = Apache::lonnavmaps::navmap->new(); - my $groupmap = '/uploaded/'.$cdom.'/'.$cnum.'/'.'group_folder_'. + if (!defined($navmap)) { + $outcome = '<div class="LC_error">'; + 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 .= '</div>'; + return $outcome; + } + $groupmap = '/uploaded/'.$cdom.'/'.$cnum.'/'.'group_folder_'. $groupname.'.sequence'; - my $groupmapres = $navmap->getResourceByUrl($groupmap); + $groupmapres = $navmap->getResourceByUrl($groupmap); if ($groupmapres) { - my ($map,$id,$src)=&Apache::lonnet::decode_symb($groupmapres->symb()); + ($map,$id,$src)=&Apache::lonnet::decode_symb($groupmapres->symb()); + } + undef($navmap); + if ($map) { $map = '/'.$map; my ($errtext,$fatal) = &LONCAPA::map::mapread($map); if ($fatal) { - $outcome=&mt('Error reading contents of parent folder to group'). - " ($map): $errtext".'<br />'; + $outcome='<div class="LC_error">' + .&mt('An error occurred when reading contents of parent folder to group:') + ."<br />($map): $errtext" + .'</div>'; } else { my $idx = 0; my $grpidx; @@ -1200,18 +1381,143 @@ sub modify_folders { $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1]; } $#LONCAPA::map::order--; - my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1); - if ($outtext) { - $outcome = &mt('Error storing updated parent folder to group'). " ($map): $errtext".'<br />'; - return; - } + my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1,1); + if ($errtext) { + $outcome='<div class="LC_error">' + .&mt('An error occurred when saving updated parent folder to group:') + ."<br />$map - $errtext" + .'</div>'; + } else { + my ($furl,$ferr) = + &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + } } } } - undef($navmap); return $outcome; } +sub verify_reenable { + 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].' + ,'<i>'.$stored->{'description'}.'</i>'). + '<br /><br />'.&mt('When a deleted group is re-enabled the following occurs:').'<ul>'. + '<li>'.&mt('Group settings and membership at the time the group was deleted are reinstated.').'</li><li>'); + 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('</li></ul>'); + 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,$crstype) = @_; + 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?','<i>'.$groupname.'</i>'),'<br />'); + 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('<div class="LC_success">' + .&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) + .'</div>'); + } + } else { + $r->print('<div class="LC_error">' + .&mt('A problem occurred when trying to reinstate [_1] of the [_2] members of the pre-existing group.',$num_fail,$num_users) + .'</div>'); + } + } else { + $r->print('<div class="LC_info">' + .&mt('There were no group members to reinstate, as none were removed when the group was deleted.') + .'</div>'); + } + my $outcome = &reenable_folder($cdom,$cnum,$groupname,$description,$crstype); + if ($outcome eq '') { + my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Group successfully re-enabled.')); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); + } else { + $r->print('<div class="LC_error">'); + 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('</div>'); + } + } else { + my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Re-enabling group failed.'),1); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); + } + return; +} + sub header { my ($bodytitle,$jscript,$action,$state,$page,$loaditems) = @_; my $start_page= @@ -1221,7 +1527,7 @@ sub header { {'add_entries' => $loaditems,}); my $output = <<"END"; $start_page -<form method="POST" name="$state"> +<form method="post" name="$state" action=""> END if ($action eq 'create' || $action eq 'modify') { @@ -1279,18 +1585,21 @@ 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); - 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; - $$numdirs ++; - &group_files($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 ++; + } } } } @@ -1312,7 +1621,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) { @@ -1340,11 +1649,11 @@ sub open_list_window { my ($group,$status,$count,$text) = @_; my $entry; if ($count > 0) { - $entry = '<nobr><a href="javascript:openGroupRoster('. + $entry = '<span class="LC_nobreak"><a href="javascript:openGroupRoster('. "'$group','$status'".')">'.$text.'</a> - '.$count. - '</nobr><br />'; + '</span><br />'; } else { - $entry = '<nobr>'.$text.' - '.$count.'</nobr><br />'; + $entry = '<span class="LC_nobreak">'.$text.' - '.$count.'</span><br />'; } return $entry; } @@ -1360,7 +1669,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 = (); @@ -1369,7 +1678,7 @@ sub general_settings_form { @{$tools} = sort(keys(%{$functions})); &privilege_specificity($r,$action,3,$tools,$stored,$toolprivs, $fixedprivs,\@available,$formname, - $gpterm,$ucgpterm); + $gpterm,$ucgpterm,$functions,$crstype); &mapping_options($r,$action,$formname,$page,$sectioncount, $states,$stored,$navbuttons,4,5, $gpterm,$ucgpterm,$crstype,$cdom,$cnum); @@ -1393,101 +1702,115 @@ sub groupsettings_options { 'lett' => 'Letters, numbers and underscore only', 'doyo' => 'Different subsets of the chosen collaborative tools '. 'for different group members?', + 'gran' => 'Granularity', + 'dquo' => 'Disk quota', ); my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,$stored); - &topic_bar($r,$image,$lt{'gnde'}); - $r->print(' - <table class="LC_descriptive_input"> - <tr> - <td class="LC_description">'.$lt{'gnam'}.':</td> - <td colspan="5"> -'); + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'gnde'})); + + # Group Name + $r->print(&Apache::lonhtmlcommon::start_pick_box() + .&Apache::lonhtmlcommon::row_title($lt{'gnam'}) + ); if ($action eq 'create') { - $r->print('<input type="text" name="groupname" size="25" /> ('. - $lt{'lett'}.')'); + $r->print('<input type="text" name="groupname" size="25" />' + .' <span class="LC_nobreak">(' + .$lt{'lett'}.')</span>' + ); } else { $r->print('<input type="hidden" name="groupname" value="'. $env{'form.groupname'}.'" />'.$env{'form.groupname'}); } - $r->print(<<"END"); - </td> - <tr> - <tr> - <td class="LC_description">$lt{'desc'}:</td> - <td colspan="5"><input type="text" name="description" size="40" - value="" /> - </td> - <tr> - <tr> - <td class="LC_description">$lt{'func'}:</td> -END + $r->print(&Apache::lonhtmlcommon::row_closure()); + + # Group Title + $r->print(&Apache::lonhtmlcommon::row_title($lt{'desc'}) + .'<input type="text" name="description" size="40" value="" />' + .&Apache::lonhtmlcommon::row_closure() + ); + + # Collaborative Tools my $numitems = keys(%{$functions}); my $halfnum = int($numitems/2); my $remnum = $numitems%2; if ($remnum) { $halfnum ++; } - my @allfunctions = sort(keys (%{$functions})); - for (my $i=0; $i<$halfnum; $i++) { - $r->print('<td><label><input type="checkbox" name="tool" value="'. - $allfunctions[$i].'" /> '. - $$functions{$allfunctions[$i]}.'</label></td> - <td> </td><td> </td>'); - } - $r->print('<td><input type="button" value="check all" '. - 'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'. - '</td></tr><tr><td> </td>'); - for (my $j=$halfnum; $j<@allfunctions; $j++) { - $r->print('<td><label><input type="checkbox" name="tool" value="'. - $allfunctions[$j].'" /> '. - $$functions{$allfunctions[$j]}.'</label></td> - <td> </td><td> </td>'); - } - if ($remnum) { - $r->print('<td> </td>'); + my @allfunctions = sort(keys(%{$functions})); + + $r->print(&Apache::lonhtmlcommon::row_title($lt{'func'}) + .'<div>' + .'<input type="button" value="'.&mt('check all').'"' + .' onclick="javascript:checkAll(document.'.$formname.'.tool)" />' + .' <input type="button" value="'.&mt('uncheck all').'"' + .' onclick="javascript:uncheckAll(document.'.$formname.'.tool)" />' + .'</div>' + .'<table cellpadding="5px"><tr>' # FIXME Get rid of inflexible table (-> float) + ); + for (my $i=0; $i<@allfunctions; $i++) { + $r->print('<td><label><span class="LC_nobreak">' + .'<input type="checkbox" name="tool" value="' + .$allfunctions[$i].'" /> ' + .&mt($$functions{$allfunctions[$i]}) + .'</span></label></td>' + ); + if ($i == $halfnum - 1) { + $r->print('</tr><tr>'); + } } - $r->print(' - <td> - <input type="button" value="uncheck all" - onclick="javascript:uncheckAll(document.'.$formname.'.tool)" /> - </td> - </tr> - <tr> - <td class="LC_description">'.&mt('Granularity:').'</td> - <td colspan="10">'.$lt{'doyo'}.' <label><input type="radio" name="granularity" value="Yes" />'.&mt('Yes').'</label> <label><input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No').'</label>'); + $r->print('</tr></table>' + .&Apache::lonhtmlcommon::row_closure() + ); + + # Granularity + $r->print(&Apache::lonhtmlcommon::row_title($lt{'gran'}) + .$lt{'doyo'}.'<br />' + .'<label>' + .'<input type="radio" name="granularity" value="Yes" />'.&mt('Yes') + .'</label> <label>' + .'<input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No') + .'</label>' + ); if ($action eq 'modify') { - $r->print(' ('.&mt('Currently set to "[_1]"', - $$stored{'granularity'}).')'); + $r->print(' <span class="LC_nobreak">(' + .&mt('Currently set to [_1].' + ,'"'.&mt($$stored{'granularity'}).'"') + .')</span>' + ); } - $r->print(' - </td> - </tr> - <tr> - <td class="LC_description">'.&mt('Disk quota: ').'</td><td colspan="10">'); + $r->print(&Apache::lonhtmlcommon::row_closure()); + + # Disk Quota + $r->print(&Apache::lonhtmlcommon::row_title($lt{'dquo'})); if ($action eq 'create') { - $r->print(&mt('If you enable the file repository for the [_1], allocate a disk quota.',$gpterm)); + $r->print('<span class="LC_info">' + .&mt('If you enable the group portfolio for the '.$gpterm + .', allocate a disk quota.') + .'</span>' + ); } else { - $r->print(&mt('Quota allocated to file repository:')); + $r->print(&mt('Quota allocated to group portfolio:')); } - $r->print(' <input type="text" name="quota" size="4" />Mb'); + $r->print(' '.&mt('[_1] MB','<input type="text" name="quota" size="4" />')); if ($action eq 'create') { - $r->print('<br />'. - &mt('A total of [_1] Mb can be divided amongst all [_2]s in the '. - '[_3], and [_4] Mb are currently unallocated.',$crsquota, - $gpterm,lc($crstype),sprintf("%.2f",$freespace))); + $r->print('<br />' + .&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('<br />'.&mt('The quota can be increased to [_1] Mb, '. - 'by adding all unallocated space for [_2]s in the [_3].', - sprintf("%.2f",$maxposs),$gpterm,lc($crstype))); + $r->print('<br />' + .&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(' - </td> - </tr> - </table> -'); + $r->print(&Apache::lonhtmlcommon::row_closure(1)); + + $r->print(&Apache::lonhtmlcommon::end_pick_box()); + return; } @@ -1496,7 +1819,24 @@ sub get_quota_constraints { my ($crsquota,$freespace,$maxposs); $crsquota = $env{'course.'.$env{'request.course.id'}.'.internal.coursequota'}; if ($crsquota eq '') { - $crsquota = 20; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $crstype = &Apache::loncommon::course_type(); + my %domdefs = &Apache::lonnet::get_domain_defaults($cdom); + my %coursehash = ( + 'internal.coursecode' => $env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}, + 'internal.textbook' => $env{'course.'.$env{'request.course.id'}.'.internal.textbook'}, + ); + my %staticdefaults = ( + coursequota => 20, + ); + my $quotatype = &Apache::lonuserutils::get_extended_type($cdom,$cnum,$crstype,\%coursehash); + if ($crsquota eq '') { + $crsquota = $domdefs{$quotatype.'coursequota'}; + if ($crsquota eq '') { + $crsquota = $staticdefaults{'coursequota'}; + } + } } $freespace = $crsquota - &Apache::longroup::sum_quotas(); if ($action eq 'create') { @@ -1508,39 +1848,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 <i>changes</i> 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.','<i>','</i>'); + $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.','<i>','</i>'); + } 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}); - &topic_bar($r,$image,$lt{'pipa'}); - $r->print(' - <b>'.$lt{'gmem'}.'</b><br />'.$lt{'picr'}); + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'pipa'}).' + <b>'.$lt{'gmem'}.'</b><br />'); if ($action eq 'create') { - $r->print($lt{'meof'}.'<br />'.$lt{'ifno'}.'<br />'.$lt{'asub'}); + $r->print($lt{'picr'}.'<br />'.$lt{'ifno'}.'<br />'.$lt{'asub'}); } else { - $r->print($lt{'admg'}); + $r->print($lt{'pica'}); } $r->print(' <br /> @@ -1585,7 +1933,7 @@ sub sections_selection { } } my $output = ' - <select name="'.$elementname.'" multiple="true" size="'.$numvisible.'"> + <select name="'.$elementname.'" multiple="multiple" size="'.$numvisible.'"> '.$section_sel.' </select>'; return $output; @@ -1593,9 +1941,7 @@ sub sections_selection { sub access_date_settings { my ($r,$action,$formname,$stored,$image,$gpterm,$ucgpterm) = @_; - my %lt = &Apache::lonlocal::texthash( - 'sten' => "Default start and end dates for $gpterm access", - ); + my $sten = &mt("Default start and end dates for $gpterm access"); my $starttime = time; my $endtime = time+(6*30*24*60*60); # 6 months from now, approx if ($action eq 'modify') { @@ -1605,8 +1951,7 @@ sub access_date_settings { } } my ($table) = &date_setting_table($starttime,$endtime,$formname); - &topic_bar($r,$image,$lt{'sten'}); - $r->print(' + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$sten).' '.$table.' '); return; @@ -1659,7 +2004,8 @@ sub choose_members_form { } } &privilege_specificity($r,$action,$specimg,$tools,$stored,$toolprivs, - $fixedprivs,\@available,$formname,$gpterm,$ucgpterm); + $fixedprivs,\@available,$formname,$gpterm,$ucgpterm, + $functions,$crstype); my $newusers = &pick_new_members($r,$action,$formname,\@available,$idx, $stored,$memimg,$users,$userdata, $granularity,\%origmembers,$gpterm, @@ -1722,10 +2068,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<br />for different members:', - stda => 'Start date', + stda => 'Start date:', enda => 'End date:', ); + $lt{'difn'} = &mt('Different collaborative tools[_1]for different members:','<br />'); my $showstart = &Apache::lonlocal::locallocaltime($startdate); my $showend; if ($enddate == 0) { @@ -1756,46 +2102,31 @@ sub print_current_settings { <td valign="top">'.$description.'</td> <td> '); + if (@{$available} > 0) { - $r->print(&mt('<b>Available for assignment to members:</b>'). - '<table class="LC_group_priv"><tr>'); - my $rowcell = int(@{$available}/2) + @{$available}%2; + $r->print('<b>'.&mt('Available for assignment to members:').'</b>'); + $r->print('<ul>'); for (my $i=0; $i<@{$available}; $i++) { - if (@{$available} > 3) { - if ($i==$rowcell) { - $r->print('</tr><tr>'); - } - } - $r->print('<td>'.$$functions{$$available[$i]}. - '</td><td> </td>'); - } - if ((@{$available} > 3) && (@{$available}%2)) { - $r->print('<td> </td><td> </td>'); + $r->print('<li>'.&mt($$functions{$$available[$i]}).'</li>'); } - $r->print('</tr></table><br />'); + $r->print('</ul>'); } + if (@{$unavailable} > 0) { - $r->print(&mt('<b>Unavailable for assignment:</b>'). - '<table class="LC_group_priv"><tr>'); - my $rowcell = int(@{$unavailable}/2) + @{$unavailable}%2; - for (my $j=0; $j<@{$unavailable}; $j++) { - if (@{$unavailable} > 3) { - if ($j==$rowcell) { - $r->print('</tr><tr>'); - } - } - $r->print('<td>'.$$functions{$$unavailable[$j]}. - '</td><td> </td>'); + $r->print('<b>'.&mt('Unavailable for assignment:').'</b>'); + $r->print('<ul>'); + for (my $i=0; $i<@{$unavailable}; $i++) { + $r->print('<li>'.&mt($$functions{$$unavailable[$i]}).'</li>'); } - if ((@{$unavailable} > 3) && (@{$unavailable}%2)) { - $r->print('<td> </td><td> </td>'); - } - $r->print('</tr></table>'); + $r->print('</ul>'); } + + my $quota_text=&mt('[_1] MB',$quota); + my $granu_text=&mt($granularity); $r->print(<<"END"); </td> - <td valign="top"><b>$lt{'difn'}</b> $granularity</td> - <td valign="top">$quota Mb</td> + <td valign="top"><b>$lt{'difn'}</b> $granu_text</td> + <td valign="top">$quota_text</td> <td valign="top"><b>$lt{'stda'}</b> $showstart<br /> <b>$lt{'enda'}</b> $showend </td> @@ -1818,9 +2149,9 @@ sub pick_new_members { 'nnew' => "There are no users to add as new members, as all users". " matching the specified type(s), role(s), and ". "section(s) are already affiliated with this group.", - 'yoma' => 'You may need to use the '."'".'modify existing, past or '. - 'future members'."'".' page if you need to re-enable '. - 'or activate access for previous or future members.', + 'yoma' => "You may need to use the 'modify existing, past or ". + "future members' page if you need to re-enable ". + "or activate access for previous or future members.", ); my %members; my $totalusers = 0; @@ -1844,7 +2175,7 @@ sub pick_new_members { $r->print(&check_uncheck_tools($r,$available)); } } - &topic_bar($r,$img,$lt{'gpme'}); + $r->print(&Apache::lonhtmlcommon::topic_bar($img,$lt{'gpme'})); if (keys(%members) > 0) { $r->print(' <table> @@ -1852,14 +2183,14 @@ sub pick_new_members { &check_uncheck_buttons($r,$formname,'member',$lt{'addm'}); if (@{$available} > 0 && $granularity eq 'Yes') { $r->print('<td> - <fieldset><legend><b>'.$lt{'setf'}.'</b></legend> - <nobr> - <input type="button" value="check all" + <fieldset><legend>'.$lt{'setf'}.'</legend> + <span class="LC_nobreak"> + <input type="button" value="'.&mt('check all').'" onclick="javascript:checkAllTools(document.'.$formname.')" /> - <input type="button" value="uncheck all" + <input type="button" value="'.&mt('uncheck all').'" onclick="javascript:uncheckAllTools(document.'.$formname.')" /> - </nobr> + </span> </fieldset></td>'); } $r->print('</tr></table> @@ -1882,13 +2213,13 @@ sub pick_new_members { if ($granularity eq 'Yes') { $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').' <td colspan="6"> </td> - <td align="center"><nobr><b>'.&mt('All:').'</b> '); + <td align="center"><span class="LC_nobreak"><b>'.&mt('All:').'</b> '); foreach my $tool (@{$available}) { $r->print('<label><input type="checkbox" name="togglefunc" '. 'onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'. ' value="'.$tool.'">'.'<b>'.$tool.'</b></label> '); } - $r->print('</nobr></td></tr>'); + $r->print('</span></td></tr>'); } } my %Sortby = (); @@ -1922,7 +2253,7 @@ sub pick_new_members { '<td>'.$id.'</td>'. '<td>'.$section.'</td>'); if (@{$available} > 0) { - $r->print('<td align="center"><nobr>'. + $r->print('<td align="center"><span class="LC_nobreak">'. ' '); foreach my $tool (@{$available}) { if ($granularity eq 'Yes') { @@ -1933,7 +2264,7 @@ sub pick_new_members { $tool.'" value="'.$user.'" />'.$tool.' '); } } - $r->print('</nobr></td>'); + $r->print('</span></td>'); } $r->print(&Apache::loncommon::end_data_table_row()."\n"); } @@ -1951,7 +2282,7 @@ sub pick_new_members { sub privilege_specificity { my ($r,$action,$img,$tools,$stored,$toolprivs,$fixedprivs,$available, - $formname,$gpterm,$ucgpterm) = @_; + $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, '. @@ -1980,11 +2311,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 <b>optional</b> 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.','<b>','</b>'); + 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}}))) { @@ -1993,7 +2328,7 @@ sub privilege_specificity { } } } - &topic_bar($r,$img,$lt{'uprv'}); + $r->print(&Apache::lonhtmlcommon::topic_bar($img,$lt{'uprv'})); if ((($action eq 'create') && (@{$available} > 0)) || (($action eq 'modify') && ($formname eq 'change_settings'))) { my %specific = ( @@ -2020,8 +2355,8 @@ sub privilege_specificity { if ($totaloptionalprivs) { $r->print(' <br /> -<label><nobr><input type="radio" name="specificity" value="No" '.$specific{'No'}.' /> '.$lt{'algm'}.'</nobr></label><br /> -<label><nobr><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' /> '.$lt{'smgp'}.'</nobr></label><br /><br />'); +<label><span class="LC_nobreak"><input type="radio" name="specificity" value="No" '.$specific{'No'}.' /> '.$lt{'algm'}.'</span></label><br /> +<label><span class="LC_nobreak"><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' /> '.$lt{'smgp'}.'</span></label><br /><br />'); } else { $r->print('<input type="hidden" name="specificity" value="No" />'); } @@ -2048,7 +2383,7 @@ sub privilege_specificity { $r->print($lt{'algm'}.'<br /><br />'); } &default_privileges($r,$action,$tools,$toolprivs,$fixedprivs, - $available); + $available,$functions); } else { if ($action eq 'create') { $r->print($lt{'asyo'}); @@ -2072,7 +2407,7 @@ sub privilege_specificity { } sub default_privileges { - my ($r,$action,$tools,$toolprivs,$fixedprivs,$available) = @_; + my ($r,$action,$tools,$toolprivs,$fixedprivs,$available,$functions) = @_; my %lt = &Apache::lonlocal::texthash( 'addp' => 'Additional privileges', 'fixp' => 'Fixed privileges', @@ -2081,8 +2416,12 @@ sub default_privileges { ); $r->print(&Apache::lonhtmlcommon::start_pick_box('LC_group_priv_box'). &Apache::lonhtmlcommon::row_title($lt{'func'},undef, - 'LC_groups_functionality')); - $r->print(join('</td><td class="LC_groups_functionality">',@{$tools})); + 'LC_groups_functionality')); + my @tableHeader; + if ((ref($functions) eq 'HASH') && (ref($tools) eq 'ARRAY')) { + @tableHeader = map { $functions->{$_}; } @{$tools}; + } + $r->print(join('</td><td class="LC_groups_functionality">', @tableHeader)); $r->print(&Apache::lonhtmlcommon::row_closure(1)); my $fixed = ''; my $dynamic = ''; @@ -2097,7 +2436,8 @@ sub default_privileges { if ($fixed ne '') { $fixed .= '</td><td class="LC_groups_fixed">'; } - $fixed .= '<input type="hidden" name="defpriv" value="'.$priv.'" /><nobr>'.$$toolprivs{$tool}{$priv}.' '; + $fixed .= '<input type="hidden" name="defpriv" value="'.$priv.'" />' + .'<span class="LC_nobreak">'.&mt($$toolprivs{$tool}{$priv}).' '; if ($action eq 'modify') { if (grep(/^$tool$/,@{$available})) { $fixed .= '<small>'.&mt('(on)').'<small> '; @@ -2105,18 +2445,18 @@ sub default_privileges { $fixed .= '<small>'.&mt('(off)').'<small> '; } } - $fixed .= '</nobr>'; + $fixed .= '</span>'; } else { $privcount++; if ($privcount == 3) { $dynamic .= '</tr> <tr>'."\n"; } - $dynamic .= '<td><nobr><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'</label></nobr></td>'."\n"; + $dynamic .= '<td><span class="LC_nobreak"><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.&mt($$toolprivs{$tool}{$priv}).'</label></span></td>'."\n"; } } if ($privcount == 0) { - $dynamic .= '<td>None</td>'."\n"; + $dynamic .= '<td>'.&mt('None').'</td>'."\n"; } if ($privcount < 3) { $dynamic .= '<td> </td>'."\n"; @@ -2234,11 +2574,11 @@ sub change_members_form { $r->print(' <br /> '); - &topic_bar($r,1,$lt{'grse'}); + $r->print(&Apache::lonhtmlcommon::topic_bar(1,$lt{'grse'})); &print_current_settings($r,$action,$functions,$startdate,$enddate, $groupname,$description,$granularity,$quota, \@available,\@unavailable,$gpterm,$ucgpterm); - &topic_bar($r,2,$lt{'mogm'}); + $r->print(&Apache::lonhtmlcommon::topic_bar(2,$lt{'mogm'})); my $numcurrent = ¤t_membership($r,$cdom,$cnum,$formname,$groupname, \@available,\@unavailable,$fixedprivs, $granularity,$specificity); @@ -2260,6 +2600,7 @@ sub current_membership { 'actn' => 'Action?', 'name' => 'Name', 'usnm' => 'Username', + 'stid' => 'ID', 'doma' => 'Domain', 'stda' => 'Start Date', 'enda' => 'End Date', @@ -2296,15 +2637,15 @@ sub current_membership { $r->print(&check_uncheck_tools($r,$available)); $r->print(' <td> - <nobr> - <fieldset><legend><b>'.$lt{'curf'}.'</b></legend> - <input type="button" value="check all" + <span class="LC_nobreak"> + <fieldset><legend>'.$lt{'curf'}.'</legend> + <input type="button" value="'.&mt('check all').'" onclick="javascript:checkAllTools(document.'.$formname.')" /> - <input type="button" value="uncheck all" + <input type="button" value="'.&mt('uncheck all').'" onclick="javascript:uncheckAllTools(document.'.$formname.')" /> </fieldset> - </nobr> + </span> </td> '); } @@ -2321,7 +2662,7 @@ END <th><a href="javascript:changeSort('fullname')">$lt{'name'}</a></th> <th><a href="javascript:changeSort('username')">$lt{'usnm'}</a></th> <th><a href="javascript:changeSort('domain')">$lt{'doma'}</a></th> - <th><a href="javascript:changeSort('id')">ID</a></th> + <th><a href="javascript:changeSort('id')">$lt{'ID'}</a></th> <th><a href="javascript:changeSort('start')">$lt{'stda'}</a></th> <th><a href="javascript:changeSort('end')">$lt{'enda'}</a></th> END @@ -2339,14 +2680,14 @@ END if ($granularity eq 'Yes') { $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').' <td colspan="7"> </td> - <td colspan="'.$colspan.'" align="center"><nobr><b>'.&mt('All:'). + <td colspan="'.$colspan.'" align="center"><span class="LC_nobreak"><b>'.&mt('All:'). '</b> '); foreach my $tool (@{$available}) { $r->print('<label><input type="checkbox" name="togglefunc"'. ' onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'. ' value="'.$tool.'" />'.'<b>'.$tool.'</b></label> '); } - $r->print('</nobr></td></tr>'); + $r->print('</span></td></tr>'); } } my %Sortby = (); @@ -2374,25 +2715,25 @@ END $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').' <td>'); if ($$current{$user}{changestate} eq 'reenable') { - $r->print('<nobr><label>'. + $r->print('<span class="LC_nobreak"><label>'. '<input type="checkbox" name="reenable" value="'.$user.'" />'. - $lt{'reen'}.'</label></nobr><br />'); + $lt{'reen'}.'</label></span><br />'); } elsif ($$current{$user}{changestate} eq 'expire') { - $r->print('<nobr><label>'. + $r->print('<span class="LC_nobreak"><label>'. '<input type="checkbox" name="expire" value="'.$user.'" />'. - $lt{'expi'}.'</label></nobr><br />'); + $lt{'expi'}.'</label></span><br />'); } elsif ($$current{$user}{changestate} eq 'activate') { - $r->print('<nobr><label>'. + $r->print('<span class="LC_nobreak"><label>'. '<input type="checkbox" name="activate" value="'.$user.'" />'. - $lt{'acti'}.'</label></nobr><br />'); + $lt{'acti'}.'</label></span><br />'); } - $r->print('<nobr><label>'. + $r->print('<span class="LC_nobreak"><label>'. '<input type="checkbox" name="deletion" value="'.$user.'" />'. - $lt{'dele'}.'</label></nobr>'); + $lt{'dele'}.'</label></span>'); if ($specificity eq 'Yes') { - $r->print('<br /><nobr><label>'. + $r->print('<br /><span class="LC_nobreak"><label>'. '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}. - '</label></nobr>'); + '</label></span>'); } $r->print(' </td>'. @@ -2403,7 +2744,7 @@ END '<td>'.$start.'</td>'. '<td>'.$end.'</td>'); if ($hastools) { - $r->print('<td align="left"><nobr>'. + $r->print('<td align="left"><span class="LC_nobreak">'. ' '); foreach my $tool (@{$$current{$user}{currtools}}) { if ($granularity eq 'Yes') { @@ -2419,23 +2760,23 @@ END } $r->print(' '); } - $r->print('</nobr></td>'); + $r->print('</span></td>'); } if ($addtools) { $r->print('<td align="left">'); if ($granularity eq 'Yes') { foreach my $tool (@{$$current{$user}{newtools}}) { - $r->print('<nobr><label><input type="checkbox" + $r->print('<span class="LC_nobreak"><label><input type="checkbox" name="user_'.$tool.'" value="'. $user.'" />'.$tool. - '</label></nobr> '); + '</label></span> '); } } else { foreach my $tool (@{$$current{$user}{newtools}}) { - $r->print('<nobr><input type="hidden" + $r->print('<span class="LC_nobreak"><input type="hidden" name="user_'. $tool.'" value="'. $user.'" />'.$tool. - '</nobr> '); + '</span> '); } } $r->print('</td>'); @@ -2445,7 +2786,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( + '<p class="LC_info">' + .&mt('There are no active, future or previous group members to modify.') + .'</p>'); } return $numcurrent; } @@ -2455,14 +2799,14 @@ sub check_uncheck_buttons { $r->print(' <td '.$colspan.'> <fieldset> - <legend><b>'.$title.'</b></legend> - <nobr> - <input type="button" value="check all" + <legend>'.$title.'</legend> + <span class="LC_nobreak"> + <input type="button" value="'.&mt('check all').'" onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" /> - <input type="button" value="uncheck all" + <input type="button" value="'.&mt('uncheck all').'" onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" /> - </nobr> + </span> </fieldset> </td> '); @@ -2488,7 +2832,7 @@ sub change_privs_form { } else { $nexttext = $$navbuttons{'mose'}; } - &topic_bar($r,3,&mt('Members to delete or expire')); + $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('Members to delete or expire'))); my $exp_or_del = 0; if (ref($$memchg{'deletion'}) eq 'ARRAY') { if (@{$$memchg{'deletion'}} > 0) { @@ -2513,10 +2857,10 @@ sub change_privs_form { } } if (!$exp_or_del) { - $r->print($lt{'nome'}.'<br />'); + $r->print('<p class="LC_info">'.$lt{'nome'}.'</p>'); } - &topic_bar($r,4,&mt('Setting optional privileges for specific group members')); + $r->print(&Apache::lonhtmlcommon::topic_bar(4,&mt('Setting optional privileges for specific group members'))); my $numchgs = &member_privileges_form($r,$action,$formname,$tools, $toolprivs,$fixedprivs,$userdata, @@ -2535,7 +2879,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(' <br />'); my @available = (); my @unavailable = (); @@ -2544,7 +2888,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, @@ -2573,7 +2917,7 @@ sub choose_privs_form { $nexttext = $$navbuttons{'adme'}; } - &topic_bar($r,6,&mt('Setting optional privileges for specific group members')); + $r->print(&Apache::lonhtmlcommon::topic_bar(6,&mt('Setting optional privileges for specific group members'))); &member_privileges_form($r,$action,$formname,$tools,$toolprivs, $fixedprivs,$userdata,$usertools,$idx,undef, @@ -2662,7 +3006,8 @@ sub member_privileges_form { 'members being added or modified, '. 'there are no optional privileges to set '. 'for specific members.', - 'algr' => 'All new group members will receive the same privileges.', 'ifex' => 'If previously expired members are being re-enabled, or '. + 'algr' => 'All new group members will receive the same privileges.', + 'ifex' => 'If previously expired members are being re-enabled, or '. 'if access for future members is being activated now, '. 'previously set privileges will be preserved.', 'asno' => 'As no group members are being added, '. @@ -2738,9 +3083,8 @@ sub member_privileges_form { foreach my $tool (@{$tools}) { if (@{$showboxes{$tool}} > 0) { $r->print('<td valign="top">'); - $r->print('<table class="thinborder"><tr>'. - '<th colspan="'.$colspan.'">'. - $tool.'</th></tr><tr>'); + $r->print('<fieldset><legend>'.&mt($tool).'</legend>'); + $r->print('<table><tr>'); my $privcount = 0; foreach my $priv (@{$showboxes{$tool}}) { $privcount ++; @@ -2754,15 +3098,16 @@ sub member_privileges_form { } else { $r->print('<td>'); } - $r->print(qq| - <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend> - <nobr> - <input type="button" value="check all" - onclick="javascript:checkAll(document.$formname.userpriv_$priv)" /> - - <input type="button" value="uncheck all" - onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" /> - </nobr></fieldset><br />|); + $r->print( + '<fieldset><legend>'.&mt($$toolprivs{$tool}{$priv}).'</legend>' +.'<span class="LC_nobreak">' +.' <input type="button" value="'.&mt('check all').'"' +.' onclick="javascript:checkAll(document.'.$formname.'.userpriv_'.$priv.')" />' +.' ' +.'<input type="button" value="'.&mt('uncheck all').'"' +.' onclick="javascript:uncheckAll(document.'.$formname.'.userpriv_'.$priv.')" />' +.'</span></fieldset><br />' + ); $r->print('</td>'); if ($privcount < @{$showboxes{$tool}}) { if (@{$showboxes{$tool}} > 2) { @@ -2774,7 +3119,7 @@ sub member_privileges_form { } } } - $r->print('</tr></table></td><td> </td>'); + $r->print('</tr></table></fieldset></td><td> </td>'); } } $r->print('</tr></table>'); @@ -2874,7 +3219,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; } @@ -2906,11 +3251,19 @@ sub write_group_data { } if ($quota !~ /^\d*\.?\d*$/) { $quota = 0; - $r->print(&mt('The value you entered for the quota for the file repository in this [_1] contained invalid characters, so it has been set to 0 Mb. You can change this by modifying the [_1] settings.<br />',$gpterm)); + $r->print('<div class="LC_warning">' + .&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' + .' modifying the '.$gpterm.' settings.') + .'</div>'); } if ($quota > $maxposs) { $quota = $maxposs; - $r->print(&mt('The value you entered for the quota for the file repository in this [_1] exceeded the maximum possible value, so it has been set to [_2] Mb (the maximum possible value).<br />',$gpterm,sprintf("%.2f",$maxposs))); + $r->print('<div class="LC_warning">' + .&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 ' + .'(the maximum possible value).',sprintf("%.2f",$maxposs)) + .'</div>'); } my %groupinfo = ( description => $esc_description, @@ -2975,10 +3328,17 @@ sub write_group_data { my $result = &add_group_folder($cdom,$cnum,$now,$groupname,$action, $description,$tools,\%groupinfo, $gpterm,$ucgpterm,$crstype); - if ($result ne 'ok') { - $r->print(&mt('A problem occurred when creating folders for the new [_1]. [_2].<br />',$gpterm,$result)); + if ($result eq 'ok') { + my $msg = &Apache::lonhtmlcommon::confirm_success(&mt($ucgpterm.' [_1] was created.','<i>'.$groupname.'</i>')); + $msg = &Apache::loncommon::confirmwrapper($msg); + $r->print($msg); + } else { + my $msg = &Apache::lonhtmlcommon::confirm_success(&mt('A problem occurred when creating folders for the new '.$gpterm.' [_1]:' + ,'<i>'.$groupname.'</i>') + .'<br />'.$result,1); + $msg = &Apache::loncommon::confirmwrapper($msg); + $r->print($msg); } - $r->print(&mt('[_1] [_2] was created.<br />',$ucgpterm,$groupname)); } elsif ($action eq 'modify') { my (@oldtools,@newtools); if (ref($$stored{'tool'}) eq 'ARRAY') { @@ -2992,35 +3352,65 @@ sub write_group_data { my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/'; my $boardsmap = $crspath.'group_boards_'.$groupname.'.sequence'; my $navmap = Apache::lonnavmaps::navmap->new(); - my $bbmapres = $navmap->getResourceByUrl($boardsmap); - undef($navmap); - if (!$bbmapres) { - my $grpmap = $crspath.'group_folder_'.$groupname.'.sequence'; - my $disctitle = &mt('Discussion Boards'); - my $outcome = &map_updater($cdom,$cnum,'group_boards_'. - $groupname.'.sequence','bbseq', - $disctitle,$grpmap); - my ($furl,$ferr) = - &Apache::lonuserstate::readmap($cdom.'/'.$cnum); - $navmap = Apache::lonnavmaps::navmap->new(); - # modify parameter - if ($outcome eq 'ok') { - my $parm_result = &parm_setter($navmap,$cdom,$boardsmap, - $groupname); - if ($parm_result) { - $r->print(&mt('Error while setting parameters '. - 'for Discussion Boards folder: '. - '[_1]<br />.',$parm_result)); + my ($bbmapres,$error); + if (defined($navmap)) { + $bbmapres = $navmap->getResourceByUrl($boardsmap); + undef($navmap); + if (!$bbmapres) { + my $grpmap = $crspath.'group_folder_'.$groupname.'.sequence'; + my $disctitle = &mt('Discussion Boards'); + my $outcome = &map_updater($cdom,$cnum,'group_boards_'. + $groupname.'.sequence','bbseq', + $disctitle,$grpmap); + my ($furl,$ferr) = + &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + # modify parameter + if ($outcome eq 'ok') { + $navmap = Apache::lonnavmaps::navmap->new(); + if (defined($navmap)) { + my $parm_result = &parm_setter($navmap,$cdom,$boardsmap, + $groupname); + if ($parm_result) { + $error = &mt('An error occurred while setting parameters ' + .'for Discussion Boards folder: ' + .'[_1]',$parm_result); + } else { + $r->print('<div class="LC_success">'. + &mt('Discussion Boards Folder created.') + .'</div>'); + } + undef($navmap); + } else { + if ($crstype eq 'Community') { + $error = &mt("An error occurred while setting parameters '. + 'for Discussion Boards folder: '. + '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(&mt('Discussion Boards Folder created.<br />')); + $r->print($outcome); } + } + } else { + $error = &mt("An error occurred while retrieving the contents of the group's folder.").'<br />'; + if ($crstype eq 'Community') { + $error .= &mt("You need to re-initialize the community."); + } else { - $r->print($outcome); + $error .= &mt("You need to re-initialize the course."); } - undef($navmap); + } + if ($error ne '') { + $r->print('<div class="LC_error">'.$error.'</div>'); } } - $r->print(&mt('[_1] [_2] was updated.<br />',$ucgpterm,$groupname)); + my $message = &Apache::lonhtmlcommon::confirm_success(&mt($ucgpterm.' [_1] was updated.','<i>'.$groupname.'</i>')); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); } } else { my %actiontype = ( @@ -3030,8 +3420,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 [_2]. '. - 'Please try again.',$actiontype{$action},$gpterm)); + $r->print('<p class="LC_error">' + .&mt('An error occurred when '.$actiontype{$action}.' the '.$gpterm.'. ' + .'Please try again.') + .'</p'); } return $result; } @@ -3039,7 +3431,7 @@ sub write_group_data { sub process_membership { my ($r,$cdom,$cnum,$action,$state,$groupname,$tools,$enddate,$startdate, $userdata,$idx,$toolprivs,$usertools,$specificity,$defprivs,$memchg, - $gpterm,$ucgpterm)=@_; + $gpterm,$ucgpterm,$crstype)=@_; my %usersettings = (); my %added= (); my %failed = (); @@ -3050,6 +3442,7 @@ sub process_membership { my %curr_start = (); my %curr_end = (); my %tooltype = (); + my $context = 'processgroupmembership'; foreach my $tool (@{$tools}) { foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) { @@ -3119,7 +3512,7 @@ sub process_membership { $curr_privs{$user}; if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname, $user,$now,$savestart, - $curr_privs{$user}) eq 'ok') { + $curr_privs{$user},'',$context) eq 'ok') { push(@{$added{'expired'}},$user); $num_ok ++; } else { @@ -3130,7 +3523,7 @@ sub process_membership { foreach my $user (@deletion) { $usersettings{$groupname.':'.$user} = $now.':-1:'; if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname, - $user,$now,'-1','') + $user,$now,'-1','','',$context) eq 'ok') { push(@{$added{'deleted'}},$user); $num_ok ++; @@ -3161,7 +3554,7 @@ sub process_membership { if (grep/^$user$/,@reenable) { $start = $startdate; $end = $enddate; - $type = 'reenabled'; + $type = 're-enabled'; } } if ($type eq '') { @@ -3184,7 +3577,7 @@ sub process_membership { $group_privs{$user}; if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname, $user,$end,$start, - $group_privs{$user}) eq 'ok') { + $group_privs{$user},'',$context) eq 'ok') { push(@{$added{$type}},$user); $num_ok ++; } else { @@ -3195,12 +3588,14 @@ sub process_membership { my $roster_result = &Apache::lonnet::modify_coursegroup_membership($cdom, $cnum,\%usersettings); if ($num_ok) { - foreach my $type (sort(keys(%added))) { - $r->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(':<br />'); + $message .= &mt($tmsg.':').'<br/>'; foreach my $user (@{$added{$type}}) { my $privlist = ''; if (!($type eq 'deleted' || $type eq 'expired')) { @@ -3216,32 +3611,58 @@ sub process_membership { } $privlist =~ s/, $//; } - $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.$privlist.'<br />'); + $message .= $$userdata{$user}[$$idx{fullname}].' - '.$user.$privlist.'<br />'; } - $r->print('<br />'); + $message .= '<br/>'; + $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))) { - $r->print(&mt('The following users could not be [_1], because an error occurred:<br />',$type)); + $r->print('<div class="LC_error">' + .&mt("The following users could not be $type, because an error occurred:") + .'</div>'); foreach my $user (@{$failed{$type}}) { $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />'); } } $r->print('<br />'); } - if (@unchanged > 0) { - $r->print(&mt('No change occurred for the following users:<br />')); - foreach my $user (sort(@unchanged)) { - $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />'); - } - $r->print('<br />'); - } +# Is that really needed? +# +# if (@unchanged > 0) { +# $r->print(&mt('No change occurred for the following users:').'<br />'); +# foreach my $user (sort(@unchanged)) { +# $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />'); +# } +# $r->print('<br />'); +# } if ($roster_result eq 'ok') { - $r->print('<br />'.&mt('[_1] membership list updated.',$ucgpterm)); - $r->print('<p>'.&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).'</p>'); + $r->print('<div class="LC_success">' + .&mt($ucgpterm.' membership list updated.') + .'</div>'); + $r->print('<p class="LC_info">'); + 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.' + ,'<i>'.$groupname.'</i>')); + + } 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.' + ,'<i>'.$groupname.'</i>')); + } + $r->print('</p>'); } else { - $r->print('<br />'.&mt('An error occurred while updating the [_1] membership list -',$gpterm).$roster_result.'<br />'); + $r->print('<div class="LC_error">' + .&mt("An error occurred while updating the $gpterm membership list:") + .'<br />'.$roster_result + .'</div>'); } return; } @@ -3257,7 +3678,6 @@ sub mapping_options { 'adds' => "If automatic $gpterm enrollment is enabled, when a user is newly assigned a ".lc($crstype)."-wide or section-specific role, he/she will automatically be added as a member of the $gpterm, with start and end access dates defined by the default dates set for the $gpterm, unless he/she is already a $gpterm member, with access dates that permit either current or future $gpterm access.", 'drops' => "If automatic $gpterm disenrollment is enabled, when a user's role is expired, access to the $gpterm will be terminated unless the user continues to have other ".lc($crstype)."-wide or section-specific active or future roles which receive automatic membership in the $gpterm.", 'pirs' => "Pick roles and sections for automatic $gpterm enrollment", - 'curr' => 'Currently set to', 'on' => 'on', 'off' => 'off', 'auad' => "Automatically enable $gpterm membership when roles are added?", @@ -3280,22 +3700,21 @@ sub automapping { if (exists($$stored{'autodrop'})) { $drop = $$stored{'autodrop'}; } - &topic_bar($r,$image,$$lt{'endi'}); - $r->print(' + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$$lt{'endi'}).' <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br /><br /> - <nobr>'.$$lt{'auad'}.': - <label><input type="radio" name="autoadd" value="on" />on </label><label><input type="radio" name="autoadd" value="off" checked="checked" />off</label>'); + <span class="LC_nobreak">'.$$lt{'auad'}.': + <label><input type="radio" name="autoadd" value="on" />'.&mt('on').' </label><label><input type="radio" name="autoadd" value="off" checked="checked" />'.&mt('off').'</label>'); if ($action eq 'modify') { - $r->print(' ('.$$lt{'curr'}.' <b>'.$$lt{$add}.'</b>)'); + $r->print(' ('.&mt('Currently set to [_1].','<b>'.$$lt{$add}.'</b>').')'); } $r->print(' - </nobr><br /> - <nobr>'.$$lt{'auex'}.': - <label><input type="radio" name="autodrop" value="on" />on </label><label><input type="radio" name="autodrop" value="off" checked="checked" />off</label>'); + </span><br /> + <span class="LC_nobreak">'.$$lt{'auex'}.': + <label><input type="radio" name="autodrop" value="on" />'.&mt('on').' </label><label><input type="radio" name="autodrop" value="off" checked="checked" />'.&mt('off').'</label>'); if ($action eq 'modify') { - $r->print(' ('.$$lt{'curr'}.' <b>'.$$lt{$drop}.'</b>)'); + $r->print(' ('.&mt('Currently set to [_1].','<b>'.$$lt{$drop}.'</b>').')'); } - $r->print('</nobr><br /><br />'.$$lt{'mapr'}); + $r->print('</span><br /><br />'.$$lt{'mapr'}); } sub mapping_settings { @@ -3308,8 +3727,8 @@ sub mapping_settings { } else { @sections = ('all','none'); } - &topic_bar($r,$image,$$lt{'pirs'}); - my @roles = &standard_roles(); + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$$lt{'pirs'})); + 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()); @@ -3352,10 +3771,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 = '<td align="right">'. &mt('all sections').'<input type="hidden" '. - 'name="sec_cc" value="all" /></td>'; + 'name="sec_'.$role.'" value="all" /></td>'; } else { $sections_sel='<td align="right">'. §ions_selection($sections,'sec_'.$role). @@ -3371,43 +3790,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 .= - '<p><font size="+1"><a href="/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state='.$menu_item->{'state'}.'&branch='.$menu_item->{'branch'}.'">'; - $menu_html.= &mt($menu_item->{'text'}).'</a></font>'; - if (exists($menu_item->{'help'})) { - $menu_html.= - &Apache::loncommon::help_open_topic($menu_item->{'help'}); - } - $menu_html.='</p>'.$/; - } - $r->print($menu_html); + }]} + ); + $r->print(&Apache::lonhtmlcommon::generate_menu(@menu)); return; } @@ -3455,16 +3876,16 @@ sub member_privs_entries { if ($privcount == 3) { $dynamic .= '</tr><tr>'; } - $dynamic .='<td><nobr><label><input type="checkbox" '. + $dynamic .='<td><span class="LC_nobreak"><label><input type="checkbox" '. 'name="userpriv_'.$priv.'" value="'.$user.'"'; if (grep/^\Q$priv\E$/,@{$defprivs}) { $dynamic .= ' checked="checked" '; } $dynamic .= ' />'.$$toolprivs{$tool}{$priv}. - '</label></nobr></td>'; + '</label></span></td>'; } } - $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>'); + $r->print('<tr><td colspan="2"><span class="LC_nobreak">'.$fixed.'</span></td></tr><tr>'.$dynamic.'</tr></table></td>'); } else { $r->print('<td valign="top"><table width="100%"><tr><th colspan="2">'.$tool.'</th></tr><tr><td> </td></tr><tr><td> </td></tr></table></td>'); } @@ -3490,17 +3911,19 @@ sub date_setting_table { 'startdate',$starttime); my $endform = &Apache::lonhtmlcommon::date_setter($formname, 'enddate',$endtime); - my $perpetual = - '<nobr><label><input type="checkbox" name="no_end_date" />'. - &mt('None').'</label></nobr>'; - my $table = "<table class=\"LC_descriptive_input\">\n". - '<tr><td class="LC_description">'.&mt('Start:').'</td>'. - '<td>'.$startform.'</td>'. - '<td> </td>'."</tr>\n". - '<tr><td class="LC_description">'.&mt('End:').'</td>'. - '<td>'.$endform.'</td>'. - '<td>'.$perpetual.'</td>'."</tr>\n". - "</table>\n"; + my $perpetual = ' <span class="LC_nobreak"><label>' + .'<input type="checkbox" name="no_end_date" />' + .&mt('No end date') + .'</label></span>'; + my $table = &Apache::lonhtmlcommon::start_pick_box() + .&Apache::lonhtmlcommon::row_title(&mt('Start Date')) + .$startform + .&Apache::lonhtmlcommon::row_closure() + .&Apache::lonhtmlcommon::row_title(&mt('End Date')) + .$endform + .$perpetual + .&Apache::lonhtmlcommon::row_closure(1) + .&Apache::lonhtmlcommon::end_pick_box(); return $table; } @@ -3508,40 +3931,61 @@ 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 = '<span class="LC_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 .= '</span>'; + return $error; } - my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage); - my $navmap = Apache::lonnavmaps::navmap->new(); + my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage,$warning); my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/'; $allgrpsmap = $crspath.'group_allfolders.sequence'; - my $topmap = $navmap->getResourceByUrl($allgrpsmap); - undef($navmap); if ($action eq 'create') { - # check if group_allfolders.sequence exists. - if (!$topmap) { - my $grpstitle = &mt('[_1] [_2]s',$crstype,$ucgpterm); - my $topmap_url = '/'.$env{'course.'.$env{'request.course.id'}.'.url'}; - $topmap_url =~ s|/+|/|g; - if ($topmap_url =~ m|^/uploaded|) { - $outcome = &map_updater($cdom,$cnum,'group_allfolders.sequence', - 'toplevelgroup',$grpstitle,$topmap_url); + if (&get_folder_lock($cdom,$cnum,'group_allfolders',$now) eq 'ok') { + # check if group_allfolders.sequence exists. + my $mapcontents = &Apache::lonnet::getfile($allgrpsmap); + if ($mapcontents eq '-1') { #file does not exist; + my $grpstitle = &mt("$crstype $ucgpterm".'s'); + my $topmap_url = '/'.$env{'course.'.$env{'request.course.id'}.'.url'}; + $topmap_url =~ s|/+|/|g; + if ($topmap_url =~ m|^/uploaded|) { + $outcome = &map_updater($cdom,$cnum,'group_allfolders.sequence', + 'toplevelgroup',$grpstitle,$topmap_url); + } else { + $outcome = '<span class="LC_warning">' + .&mt('Non-standard course - folder for all groups not added.') + .'</span>'; + } if ($outcome ne 'ok') { - return $outcome; + my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders'); + if ($delresult ne 'ok') { + $warning = $delresult; + } + return $outcome.$warning; } - } else { - $outcome = &mt('Non-standard course - folder for all groups not added.'); - return $outcome; } + my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders'); + if ($delresult ne 'ok') { + $warning = $delresult ; + } + } else { + $outcome = '<span class="LC_error">' + .&mt('Could not obtain exclusive lock to check status of the folder for all groups. No group folder added.') + .'</span>'; + return $outcome; } - my $grpfolder = &mt('[_1] Folder -',$ucgpterm,).$description; + my $grpfolder = &mt($ucgpterm.' Folder - [_1]',$description); $grppage='/adm/'.$cdom.'/'.$cnum.'/'.$groupname.'/smppg'; - my $grptitle = &mt('Group homepage').' - '.$description; + my $grptitle = &mt('Group homepage - [_1]',$description); my ($discussions,$disctitle); my $outcome = &map_updater($cdom,$cnum,'group_folder_'.$groupname.'.sequence', 'grpseq',$grpfolder,$allgrpsmap,$grppage, $grptitle); if ($outcome ne 'ok') { - return $outcome; + return $outcome.$warning; } my $pageout = &create_homepage($cdom,$cnum,$groupname,$groupinfo, $tools,$gpterm,$ucgpterm,$now); @@ -3552,7 +3996,7 @@ sub add_group_folder { my $outcome = &map_updater($cdom,$cnum,'group_boards_'.$groupname. '.sequence','bbseq',$disctitle,$grpmap); if ($outcome ne 'ok') { - return $outcome; + return $outcome.$warning; } $boardsmap = $crspath.'group_boards_'.$groupname.'.sequence'; } @@ -3560,7 +4004,19 @@ sub add_group_folder { #modify group folder if status of discussions tools is changed } my ($furl,$ferr)= &Apache::lonuserstate::readmap($cdom.'/'.$cnum); - $navmap = Apache::lonnavmaps::navmap->new(); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $warning .= '<span class="LC_error">'; + 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 .= '</span>'; + return $warning; + } # modify parameters my $parm_result; if ($action eq 'create') { @@ -3574,8 +4030,42 @@ sub add_group_folder { $parm_result .= &parm_setter($navmap,$cdom,$boardsmap,$groupname); } } + undef($navmap); if ($parm_result) { - return $parm_result; + return $warning.$parm_result; + } else { + return 'ok'; + } +} + +sub get_folder_lock { + my ($cdom,$cnum,$folder_name,$now) = @_; + # get lock for folder being edited. + my $lockhash = { + $folder_name."\0".'locked_folder' => $now.':'.$env{'user.name'}. + ':'.$env{'user.domain'}, + }; + my $tries = 0; + my $gotlock = &Apache::lonnet::newput('coursegroups',$lockhash,$cdom,$cnum); + + while (($gotlock ne 'ok') && $tries <3) { + $tries ++; + sleep(1); + $gotlock = &Apache::lonnet::newput('coursegroups',$lockhash,$cdom,$cnum); + } + return $gotlock; +} + +sub release_folder_lock { + my ($cdom,$cnum,$folder_name) = @_; + # remove lock + my @del_lock = ($folder_name."\0".'locked_folder'); + my $dellockoutcome=&Apache::lonnet::del('coursegroups',\@del_lock,$cdom,$cnum); + if ($dellockoutcome ne 'ok') { + return ('<div class="LC_error">' + .&mt('Warning: failed to release lock for folder: [_1].','<tt>'.$folder_name.'</tt>') + .'</div>' + ); } else { return 'ok'; } @@ -3590,21 +4080,27 @@ sub map_updater { my $newmapurl=&Apache::lonnet::finishuserfileupload($cnum,$cdom,$itemname, $newfile); if ($newmapurl !~ m|^/uploaded|) { - $outcome = &mt('Error uploading new folder.')." ($newfile): $newmapurl".'<br />'; + $outcome = '<div class="LC_error">' + .&mt('Error uploading new folder.')." ($newfile): $newmapurl" + .'</div>'; return $outcome; - } + } my ($errtext,$fatal)=&LONCAPA::map::mapread($parentmap); if ($fatal) { - $outcome = &mt('Error reading contents of parent folder')." ($parentmap): $errtext".'<br />'; + $outcome = '<div class="LC_error">' + .&mt('Error reading contents of parent folder.')." ($parentmap): $errtext" + .'</div>'; return $outcome; } else { my $newidx=&LONCAPA::map::getresidx($newmapurl); $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); - if ($outtext) { - $outcome = &mt('Error storing updated parent folder')." ($parentmap): $errtext".'<br />'; + my ($outtext,$errtext) = &LONCAPA::map::storemap($parentmap,1,1); + if ($errtext) { + $outcome = '<div class="LC_error">' + .&mt('Error saving updated parent folder.')." ($parentmap): $errtext" + .'</div>'; return $outcome; } } @@ -3624,8 +4120,19 @@ sub new_map { } sub parm_setter { - my ($navmap,$cdom,$url,$groupname) = @_; - my $allresults; + my ($navmap,$cdom,$url,$groupname,$crstype) = @_; + if (!defined($navmap)) { + 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 '<div class="LC_warning">'.$allresults.'</div>'; + } my %hide_settings = ( 'course' => { 'num' => 13, @@ -3638,18 +4145,30 @@ sub parm_setter { }, ); my $res = $navmap->getResourceByUrl($url); - my $symb = $res->symb(); - foreach my $level (keys(%hide_settings)) { - my $parmresult = &Apache::lonparmset::storeparm_by_symb($symb, + my $allresults; + if ($res) { + my $symb = $res->symb(); + foreach my $level (keys(%hide_settings)) { + my $parmresult = + &Apache::lonparmset::storeparm_by_symb($symb, '0_hiddenresource', $hide_settings{$level}{'num'}, $hide_settings{$level}{'set'}, 'string_yesno',undef,$cdom, undef,undef, $hide_settings{$level}{'extra'}); - if ($parmresult) { - $allresults .= $level.': '.$parmresult; + if ($parmresult) { + $allresults .= $level.': '.$parmresult; + } + } + } else { + $allresults = '<div class="LC_warning">'; + if ($crstype eq 'Community') { + $allresults .= &mt("Parameters not set for [_1] because the resource was not recognized as part of the community.",'<tt>'.$url.'</tt>'); + } else { + $allresults .= &mt('Parameters not set for [_1] because the resource was not recognized as part of the course.','<tt>'.$url.'</tt>'); } + $allresults .= '</div>'; } return $allresults; } @@ -3658,10 +4177,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/\<br\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", @@ -3713,67 +4231,53 @@ sub validate_groupname { my ($groupname,$action,$cdom,$cnum,$gpterm,$ucgpterm,$crstype) = @_; my %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum); my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum); - my %deleted_groups = &Apache::lonnet::get_deleted_groups($cdom,$cnum); + my %deleted_groups = &Apache::longroup::coursegroups($cdom,$cnum,undef, + 'deleted_groups'); if (my $tmp = &Apache::lonnet::error(%deleted_groups)) { undef(%deleted_groups); &Apache::lonnet::logthis('Error retrieving groups: '.$tmp.' in '.$cnum.':'.$cdom); } 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 = '<span class="LC_error">'.$lt{'igna'}.'</span><br /><br />'. - $lt{'tgne'}.' "'.$groupname.'" '; - my $dupmsg = $lt{'grna'}; - my $earlyout; + my $exitmsg = '<span class="LC_error">'.$lt{'igna'}.'</span><br /><br />'; + my $nameshown = &Apache::loncommon::cleanup_html($groupname); if (($groupname eq '') || ($groupname =~ /\W/)) { - $earlyout = $exitmsg.$lt{'isno'}.'<br />'.$lt{'gnmo'}; - return $earlyout; + return $exitmsg. + &mt("The $gpterm name entered '[_1]' is not a valid name.",$nameshown). + '<br />'.$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'}. - '<br />'.$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). + '<br />'.$lt{'grna'}; } if ($action eq 'create') { if (exists($curr_groups{$groupname})) { - return $exitmsg.$lt{'cnnb'}.&mt('an existing [_1]',$gpterm). - $lt{'inth'}.'.<br />'.$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). + '<br />'.$lt{'grna'}; } elsif (exists($deleted_groups{$groupname})) { - return $exitmsg.$lt{'cnnb'}.&mt('a [_1] which previously existed',$gpterm). - $lt{'inth'}.'.<br />'.$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). + '<br />'.$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; } -sub topic_bar { - my ($r,$imgnum,$title) = @_; - $r->print(' -<div class="LC_topic_bar"> - <img alt="'.&mt('Step [_1]',$imgnum). - '"src="/res/adm/pages/bl_step'.$imgnum.'.gif" /> - <span>'.$title.'</span> -</div> -'); - return; -} - sub check_changes { my ($member_changes,$memchg) = @_; my %exclusions; @@ -3813,3 +4317,4 @@ sub check_changes { } 1; +