--- loncom/interface/loncoursegroups.pm 2006/05/18 22:13:48 1.20 +++ loncom/interface/loncoursegroups.pm 2017/03/19 17:56:04 1.130 @@ -1,3 +1,6 @@ +# The LearningOnline Network with CAPA +# +# $Id: loncoursegroups.pm,v 1.130 2017/03/19 17:56:04 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,12 +29,18 @@ package Apache::loncoursegroups; use strict; use Apache::lonnet; -use Apache::loncommon; -use Apache::lonhtmlcommon; +use Apache::loncommon(); +use Apache::lonhtmlcommon(); +use Apache::lonhtmlgateway; use Apache::lonlocal; -use Apache::lonnavmaps; -use Apache::longroup; +use Apache::lonnavmaps(); +use Apache::longroup(); +use Apache::portfolio(); use Apache::Constants qw(:common :http); +use HTML::Entities; +use LONCAPA::map(); +use lib '/home/httpd/lib/perl/'; +use LONCAPA; sub handler { my ($r) = @_; @@ -47,30 +56,33 @@ 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; } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['action','refpage','state','groupname','branch']); - my $function = &Apache::loncommon::get_users_function(); - my $tabcol = &Apache::loncommon::designparm($function.'.tabbg'); my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $view_permission = - &Apache::lonnet::allowed('vcg',$env{'request.course.id'}); + &Apache::lonnet::allowed('vcg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')); my $manage_permission = - &Apache::lonnet::allowed('mdg',$env{'request.course.id'}); + &Apache::lonnet::allowed('mdg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')); &Apache::lonhtmlcommon::clear_breadcrumbs(); + my $gpterm = &Apache::loncommon::group_term(); + my $ucgpterm = $gpterm; + $ucgpterm =~ s/^(\w)/uc($1)/e; + my $crstype = &Apache::loncommon::course_type(); + my %functions = ( - email => 'E-mail', - discussion => 'Discussion boards', - chat => 'Chat', - files => 'File repository', - roster => 'Membership roster', - homepage => 'Group home page', + email => 'Send Messages', + discussion => 'Discussion Boards', + chat => 'Chat Room', + files => 'Group Portfolio', + roster => 'Membership Roster', + homepage => $ucgpterm.' home page', ); my %idx = (); @@ -78,108 +90,174 @@ sub handler { $idx{fullname} = &Apache::loncoursedata::CL_FULLNAME(); $idx{udom} = &Apache::loncoursedata::CL_SDOM(); $idx{uname} = &Apache::loncoursedata::CL_SNAME(); - - my $rowColor1 = "#dddddd"; - my $rowColor2 = "#eeeeee"; + $idx{section} = &Apache::loncoursedata::CL_SECTION(); my $action = $env{'form.action'}; - if ($action eq 'create' || $action eq 'modify' || $action eq 'view') { + my $state = $env{'form.state'}; + 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 'reenable') { if ($view_permission || $manage_permission) { - &group_administration($r,$action,$cdom,$cnum,$function,$tabcol, - \%functions,\%idx,$view_permission, - $manage_permission,$rowColor1,$rowColor2); + if ($state eq 'view') { + &print_main_menu($r,$cdom,$cnum,\%functions,\%idx, + $view_permission,$manage_permission, + $action,$state,$gpterm,$ucgpterm,$crstype); + } else { + &group_administration($r,$action,$state,$cdom,$cnum, + \%functions,\%idx,$view_permission, + $manage_permission,$gpterm,$ucgpterm, + $crstype); + } } else { - $r->print(&mt('You do not have group administration '. - 'privileges in this course')); + $r->print('
' + .&mt('You do not have '.$gpterm.' administration ' + .'privileges in this '.lc($crstype).'.') + .'
'); } } else { - &print_main_menu($r,$cdom,$cnum,$function,$tabcol,\%functions,\%idx, - $view_permission,$manage_permission,$action, - $rowColor1,$rowColor2); + &print_main_menu($r,$cdom,$cnum,\%functions,\%idx,$view_permission, + $manage_permission,$action,$state,$gpterm,$ucgpterm, + $crstype); } return OK; } sub print_main_menu { - my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission, - $manage_permission,$action,$rowColor1,$rowColor2) = @_; - $r->print(&header('Course Groups',undef,undef,undef,undef,$function)); + my ($r,$cdom,$cnum,$functions,$idx,$view_permission,$manage_permission, + $action,$state,$gpterm,$ucgpterm,$crstype) = @_; + my $jscript = qq| +function changeSort(caller) { + document.$state.sortby.value = caller; + document.$state.submit(); +} +function openGroupRoster(group,status) { + var url = '/adm/grouproster?'; + 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('My Space',$jscript,$action,$state)); + if ($env{'form.refpage'} eq 'cusr') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>"/adm/createuser", + text=>"User Management"}); + } &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/coursegroups", - text=>"Course Groups",}); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Groups')); - &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx, - $view_permission,$manage_permission,$action,$rowColor1, - $rowColor2); + text=>"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); $r->print(&footer()); return; } sub display_groups { - my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission, - $manage_permission,$action,$rowColor1,$rowColor2) = @_; + my ($r,$cdom,$cnum,$functions,$idx,$view_permission, + $manage_permission,$action,$state,$gpterm,$ucgpterm,$crstype) = @_; my %curr_groups = (); my %grp_info = (); - my %actionlinks = ( - modify => ' ''.$lt{'redg'}.''; + } + } + } + my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,undef, + $status); + if (%curr_groups) { + my $navmap=Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $r->print('
'. + &mt('An error occurred retrieving information about resources in the course.').'
'. + &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this page.','',''). + '
'); + return; + } + if ($manage_permission) { + if ($action ne 'reenable') { + $r->print('
'.$lt{'crng'}.''); + } + if ($reenable_link) { + $r->print($reenable_link); + } + } $r->print('

'); - $r->print(&Apache::lonhtmlcommon::start_pick_box()); + $r->print(&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row()); + $r->print(<<"END"); - - - - - - - - - - - - - - - + + + + + + + + + + + + END + $r->print(&Apache::loncommon::end_data_table_header_row()); my %Sortby = (); foreach my $group (sort(keys(%curr_groups))) { %{$grp_info{$group}} = @@ -187,12 +265,27 @@ END $curr_groups{$group}); my $members_result = &group_members($cdom,$cnum,$group, \%grp_info); - my $files_result = &group_files($group,\%grp_info); + my $port_path = '/userfiles/groups/'.$group.'/portfolio'; + my $totaldirs = 0; + my $totalfiles = 0; + &group_files($group,$port_path,\$totalfiles,\$totaldirs); + $grp_info{$group}{'totalfiles'} = $totalfiles; + $grp_info{$group}{'totaldirs'} = $totaldirs; + 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); + } else { + $grp_info{$group}{'diskuse'} = 'N/A'; + } + my ($groupboards,$boardshash)=&Apache::longroup::get_group_bbinfo( + $cdom,$cnum,$group); + $grp_info{$group}{'boards'} = scalar(@{$groupboards}); if ($env{'form.sortby'} eq 'groupname') { push(@{$Sortby{$group}},$group); } elsif ($env{'form.sortby'} eq 'description') { - push(@{$Sortby{$grp_info{$group}{'description'}}}, - $group); + push(@{$Sortby{$grp_info{$group}{'description'}}},$group); } elsif ($env{'form.sortby'} eq 'creator') { push(@{$Sortby{$grp_info{$group}{'creator'}}},$group); } elsif ($env{'form.sortby'} eq 'creation') { @@ -214,23 +307,17 @@ END push(@{$Sortby{$group}},$group); } } - my $rowNum = 0; - my $rowColor; foreach my $key (sort(keys(%Sortby))) { foreach my $group (@{$Sortby{$key}}) { - if ($rowNum %2 == 1) { - $rowColor = $rowColor1; - } else { - $rowColor = $rowColor2; - } my $description = - &Apache::lonnet::unescape($grp_info{$group}{'description'}); + &unescape($grp_info{$group}{'description'}); my $creator = $grp_info{$group}{'creator'}; my $creation = $grp_info{$group}{'creation'}; my $modified = $grp_info{$group}{'modified'}; my $quota = $grp_info{$group}{'quota'}; my $totalmembers = $grp_info{$group}{'totalmembers'}; my $totalfiles = $grp_info{$group}{'totalfiles'}; + my $totaldirs = $grp_info{$group}{'totaldirs'}; my $boards = $grp_info{$group}{'boards'}; my $diskuse = $grp_info{$group}{'diskuse'}; my $functionality; @@ -242,54 +329,140 @@ 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 = ''.$lt{$action}.''; } else { - $link .= $group.'/grppg'; + $link = + &Apache::longroup::get_group_link($cdom,$cnum,$group,$navmap, + $view_permission); + if ($link) { + $link = ''.$lt{$action}.''; + } + } + if ($action eq 'view') { + if ($manage_permission) { + $link .= '  '.$lt{'modify'}.'  '.$lt{'delete'}.''; + } } - $link .= '">'.$lt{$action}.''; - $r->print(''); - $rowNum ++; + $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense'). + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + &Apache::loncommon::end_data_table_row()); + } + } + $r->print(&Apache::loncommon::end_data_table()); + $r->print(''); + if ($action eq 'view') { + if (!defined($state)) { + $state = 'view'; } + $r->print(''); } - $r->print('
$lt{'act'}$lt{'gname'}$lt{'desc'}$lt{'crea'} - $lt{'crtd'} - $lt{'last'} - $lt{'func'} - $lt{'quot'}$lt{'memb'}$lt{'file'}$lt{'dibd'}$lt{'dius'}
$lt{'act'}$lt{'gname'}$lt{'desc'}$lt{'crea'}$lt{'crtd'}$lt{'last'}$lt{'func'}$lt{'quot'}$lt{'memb'}$lt{'file'}$lt{'dibd'}$lt{'dius'}
'.$link.''.$group.''.$description.''.$creator.''. &Apache::lonnavmaps::timeToHumanString($creation).''. &Apache::lonnavmaps::timeToHumanString($modified).''.$functionality.''.$quota.''.$totalmembers.''.$totalfiles.''.$boards.''.$diskuse.'
'.$link.''.$group.''.$description.''.$creator.''. &Apache::lonnavmaps::timeToHumanString($creation).''. &Apache::lonnavmaps::timeToHumanString($modified).''.$functionality.''.$quota.''.$totalmembers.''. + ''.&mt('Files: [_1]',$totalfiles).'
'. + ''.&mt('Folders: [_1]',$totaldirs).''. + '
'.$boards.''.$diskuse.'
'); - $r->print(&Apache::lonhtmlcommon::end_pick_box()); } else { $r->print($lt{'nogr'}); if ($manage_permission) { - $r->print('

'.$lt{'crng'}.''); + $r->print('

'.$lt{'crng'}.''); + if ($action ne 'reenable') { + if ($reenable_link) { + $r->print($reenable_link); + } + } } else { - $r->print('

'.$lt{'crng'}); - + $r->print('

'.$lt{'alth'}); } } } else { my @coursegroups = split(/:/,$env{'request.course.groups'}); if (@coursegroups > 0) { + my $numlinks = 0; $r->print('

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

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

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

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

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

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

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

' + ); } } return; } sub group_administration { - my ($r,$action,$cdom,$cnum,$function,$tabcol,$functions,$idx, - $view_permission,$manage_permission,$rowColor1,$rowColor2) = @_; + my ($r,$action,$state,$cdom,$cnum,$functions,$idx,$view_permission, + $manage_permission,$gpterm,$ucgpterm,$crstype) = @_; my %sectioncount = (); my @tools = (); my @types = (); @@ -303,8 +476,8 @@ sub group_administration { my %memchg; my @member_changes = ('deletion','expire','activate','reenable', 'changefunc','changepriv'); - my $state = $env{'form.state'}; - my ($groupname,$description,$startdate,$enddate,$granularity,$specificity); + my ($groupname,$description,$startdate,$enddate,$granularity,$specificity, + $quota,$validate_script); if (defined($env{'form.groupname'})) { $groupname = $env{'form.groupname'}; @@ -328,7 +501,9 @@ sub group_administration { if (defined($env{'form.specificity'})) { $specificity=$env{'form.specificity'}; } - + if (defined($env{'form.quota'})) { + $quota=$env{'form.quota'}; + } } if (($action eq 'create') || (($action eq 'modify') && (($state eq 'pick_privs') || ($state eq 'addresult')))) { @@ -342,9 +517,11 @@ sub group_administration { if ($action eq 'modify') { if ($state eq '') { - $state = 'pick_group'; + if (defined($env{'form.groupname'})) { + $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'}}; } @@ -363,92 +540,68 @@ sub group_administration { $description = $stored{'description'}; $granularity = $stored{'granularity'}; $specificity = $stored{'specificity'}; + $quota = $stored{'quota'}; } } } - my %toolprivs = (); - %{$toolprivs{'email'}} = ( - sgm => 'Send group mail', - sgb => 'Broadcast mail', - ); - %{$toolprivs{'discussion'}} = ( - cgb => 'Create boards', - pgd => 'Post', - pag => 'Anon. posts', - rgi => 'Get identities', - vgb => 'View boards', - ); - %{$toolprivs{'chat'}} = ( - pgc => 'Chat', - ); - %{$toolprivs{'files'}} = ( - rgf => 'Retrieve', - ugf => 'Upload', - dgf => 'Delete', - ); - %{$toolprivs{'roster'}} = ( - vgm => 'View', - ); - %{$toolprivs{'homepage'}} = ( - vgh => 'View page', - mgh => 'Modify page', - ); - my %fixedprivs = (); - %{$fixedprivs{'email'}} = ('sgm' => 1); - %{$fixedprivs{'discussion'}} = ('vgb' => 1); - %{$fixedprivs{'chat'}} = ('pgc' => 1); - %{$fixedprivs{'files'}} = ('rgf' => 1); - %{$fixedprivs{'roster'}} = ('vgm' => 1); - %{$fixedprivs{'homepage'}} = ('vgh' => 1); - - my %elements = (); - %{$elements{'create'}} = (); - %{$elements{'modify'}} = (); - %{$elements{'create'}{'pick_name'}} = ( - startdate_month => 'selectbox', - startdate_hour => 'selectbox', - enddate_month => 'selectbox', - enddate_hour => 'selectbox', - startdate_day => 'text', - startdate_year => 'text', - startdate_minute => 'text', - startdate_second => 'text', - enddate_day => 'text', - enddate_year => 'text', - enddate_minute => 'text', - enddate_second => 'text', - groupname => 'text', - description => 'text', - tool => 'checkbox', - granularity => 'radio', - no_end_date => 'checkbox', - ); - %{$elements{'modify'}{'change_settings'}} = ( - %{$elements{'create'}{'pick_name'}}, - specificity => 'radio', - defpriv => 'checkbox', - autorole => 'checkbox', - autoadd => 'radio', - autodrop => 'radio', - ); + my $toolprivs = &Apache::longroup::get_tool_privs($gpterm); + + my $fixedprivs = &Apache::longroup::get_fixed_privs(); + + my %elements = + ( + create => { + pick_name => { + startdate_month => 'selectbox', + startdate_hour => 'selectbox', + enddate_month => 'selectbox', + enddate_hour => 'selectbox', + startdate_day => 'text', + startdate_year => 'text', + startdate_minute => 'text', + startdate_second => 'text', + enddate_day => 'text', + enddate_year => 'text', + enddate_minute => 'text', + enddate_second => 'text', + groupname => 'text', + description => 'text', + quota => 'text', + tool => 'checkbox', + granularity => 'radio', + no_end_date => 'checkbox', + }, + pick_members => { + member => 'checkbox', + defpriv => 'checkbox', + }, + }, + ); + + $elements{'modify'} = { + change_settings => { + %{$elements{'create'}{'pick_name'}}, + specificity => 'radio', + defpriv => 'checkbox', + autorole => 'checkbox', + autoadd => 'radio', + autodrop => 'radio', + }, + add_members => { + types => 'selectbox', + roles => 'selectbox', + }, + }; + 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'; } } } - %{$elements{'create'}{'pick_members'}} = ( - member => 'checkbox', - defpriv => 'checkbox', - ); - - %{$elements{'modify'}{'add_members'}} = ( - types => 'selectbox', - roles => 'selectbox', - ); if (($action eq 'create') && ($state eq 'pick_name')) { $elements{'create'}{'pick_name'}{'types'} = 'selectbox'; @@ -459,11 +612,9 @@ sub group_administration { (($action eq 'modify') && (($state eq 'change_settings') || ($state eq 'add_members')))) { %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum); - if (%sectioncount) { - $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox'; - $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox'; - $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox'; - } + $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox'; + $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox'; + $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox'; } if (($action eq 'create') || @@ -476,9 +627,6 @@ sub group_administration { } if (defined($env{'form.sectionpick'})) { @sections=&Apache::loncommon::get_env_multiple('form.sectionpick'); - if (grep/^all$/,@sections) { - @sections = sort {$a cmp $b} keys(%sectioncount); - } } } @@ -519,7 +667,7 @@ sub group_administration { $num_reenable ++; next; } elsif (($start > $now)) { - $num_activate = 1; + $num_activate ++; next; } else { $num_expire ++; @@ -560,11 +708,17 @@ sub group_administration { } if (($state eq 'pick_privs') || ($state eq 'change_privs') || - (($specificity eq 'No') && - (($state eq 'addresult') || ($state eq 'memresult')))) { + (($specificity eq 'No') && + ($state eq 'memresult' || $state eq 'result' || $state eq 'addresult'))) { foreach my $tool (@tools) { my @values = &Apache::loncommon::get_env_multiple('form.user_'.$tool); foreach my $user (@values) { + if ($state eq 'pick_privs' || $state eq 'result' + || $state eq 'addresult') { + if (!grep(/^\Q$user\E$/,@members)) { + next; + } + } unless(exists($usertools{$user}{$tool})) { $usertools{$user}{$tool} = 1; } @@ -596,8 +750,8 @@ sub group_administration { } my @currtools = (); if (@userprivs > 0) { - foreach my $tool (sort(keys(%fixedprivs))) { - foreach my $priv (keys(%{$fixedprivs{$tool}})) { + foreach my $tool (sort(keys(%{$fixedprivs}))) { + foreach my $priv (keys(%{$$fixedprivs{$tool}})) { if (grep/^$priv$/,@userprivs) { push(@currtools,$tool); last; @@ -667,19 +821,59 @@ sub group_administration { && ($specificity eq 'Yes')) { foreach my $user (sort(keys(%usertools))) { foreach my $tool (keys(%{$usertools{$user}})) { - foreach my $priv (keys(%{$toolprivs{$tool}})) { - unless (exists($fixedprivs{$tool}{$priv})) { + foreach my $priv (keys(%{$$toolprivs{$tool}})) { + unless (exists($$fixedprivs{$tool}{$priv})) { $elements{$action}{$state}{'userpriv_'.$priv} = 'checkbox'; } } } } } - + + if (($action eq 'create' && $state eq 'pick_name') || + ($action eq 'modify' && $state eq 'change_settings')) { + my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,\%stored); + my $space_trim = '/^\s*|\s*\$/g,""'; + my $float_check = '/^([0-9]*\.?[0-9]*)$/'; + $validate_script = ' + var newquota = new String(document.'.$state.'.quota.value); + newquota.replace('.$space_trim.'); + if (newquota == "" ) { + document.'.$state.'.quota.value = 0; + newquota = "0"; + } + var maxposs = '.sprintf("%.2f",$maxposs).'; + if (newquota > maxposs) { + alert("The group portfolio quota you entered for this group ("+newquota+" MB) exceeds the maximum possible ("+maxposs+" MB). Please enter a smaller number."); + return; + } + var re_quota = '.$float_check.'; + var check_quota = newquota.match(re_quota); + if (check_quota == null) { + alert("The quota you entered contains invalid characters, the quota should only include numbers, with or without a decimal point."); + return; + } + if (newquota == 0) { + var warn_zero = 0; + for (var i=0; iprint(&header('Course Groups Manager', - $jscript,$action,$state,$page,$function,$loaditems)); + $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',}); - } else { + if ($action eq 'modify' || $action eq 'delete') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>"/adm/coursegroups?refpage=cusr&action=$action", + text=>"Groups", + faq=>9,bug=>'Instructor Interface',}); + } + } else { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/coursegroups", - text=>"Course Groups", - faq=>9,bug=>'Instructor Interface',}); + ({href=>"/adm/coursegroups", + text=>"Groups", + faq=>9,bug=>'Instructor Interface',}); + if ($env{'form.refpage'} eq 'grouplist') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>"/adm/$cdom/$cnum/$env{'form.groupname'}/smppg?ref=grouplist", + text=>"Group: $description",}); + } } my %trail = (); %{$trail{'create'}} = &Apache::lonlocal::texthash ( - pick_name => 'Group Settings', + pick_name => $ucgpterm.' Settings', pick_members => 'Select Members', pick_privs => 'Choose Privileges', result => 'Creation Complete', ); %{$trail{'modify'}} = &Apache::lonlocal::texthash( - pick_group => 'Groups', pick_task => 'Choose Task', - change_settings => 'Group Settings', + change_settings => "$ucgpterm Settings", change_members => 'Modify/Delete Members', change_privs => 'Change Privileges', change_mapping => 'Membership Mapping', @@ -759,59 +965,77 @@ function changeSort(caller) { memresult => 'Modifications Complete', addresult => 'Additions Complete', ); + %{$trail{'delete'}} = &Apache::lonlocal::texthash( + 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', - crgr => 'Create group', - mose => 'Modify settings', - gtpp => 'Go to previous page', + gtns => 'Next',#'Go to next step', + gtps => 'Back',#'Go to previous step', + crgr => 'Create '.$gpterm, + mose => 'Save',#'Modify settings', + gtpp => 'Back',#'Go to previous page', adme => 'Add members', ); - if ((($action eq 'create') || ($action eq 'modify')) && + 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]) { &Apache::lonhtmlcommon::add_breadcrumb( {text=>"$trail{$action}{$state}"}); $r->print(&Apache::lonhtmlcommon::breadcrumbs - ('Course Groups Manager')); - &display_control($r,$cdom,$cnum,$tabcol,$action,$state,$page, + ("Groups Manager","Creating_Groups")); + &display_control($r,$cdom,$cnum,$action,$state,$page, \%sectioncount,$groupname,$description,$functions, - \@tools,\%toolprivs,\%fixedprivs,$startdate,$enddate, + \@tools,$toolprivs,$fixedprivs,$startdate,$enddate, \%users,\%userdata,$idx,\%memchg,\%usertools, - $function,$view_permission,$manage_permission, - \%stored,$granularity,$specificity,\@types,\@roles, - \@sections,\%states,\%navbuttons,$rowColor1,$rowColor2); + $view_permission,$manage_permission, + \%stored,$granularity,$quota,$specificity,\@types,\@roles, + \@sections,\%states,\%navbuttons,$gpterm,$ucgpterm, + $crstype); last; } else { - if (($state eq 'result') && ($i > 0)) { - &Apache::lonhtmlcommon::add_breadcrumb( + if (($action eq 'create') || ($action eq 'modify')) { + if (($state eq 'result') && ($i > 0)) { + &Apache::lonhtmlcommon::add_breadcrumb( {href=>"javascript:backPage(document.$state,'$states{$action}[0]')", text=>"$trail{$action}{$states{$action}[$i]}"}); - } else { - &Apache::lonhtmlcommon::add_breadcrumb( + } else { + &Apache::lonhtmlcommon::add_breadcrumb( {href=>"javascript:backPage(document.$state,'$states{$action}[$i]')", text=>"$trail{$action}{$states{$action}[$i]}"}); + } } - } + } } } elsif (($action eq 'view') && ($view_permission)) { &Apache::lonhtmlcommon::add_breadcrumb( - {text=>"View groups"}); + {text=>"View $gpterm".'s'}); $r->print(&Apache::lonhtmlcommon::breadcrumbs - ('Course Groups Manager')); - &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx, - $view_permission,$manage_permission,$action, - $rowColor1,$rowColor2); - + ('Groups Manager')); + &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission, + $manage_permission,$action,$state,$gpterm,$ucgpterm, + $crstype); } $r->print(&footer()); return; } 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); @@ -821,7 +1045,7 @@ sub retrieve_settings { my %stored; $stored{'description'} = - &Apache::lonnet::unescape($groupinfo{'description'}); + &unescape($groupinfo{'description'}); $stored{'startdate'} = $groupinfo{'startdate'}; $stored{'enddate'} = $groupinfo{'enddate'}; if ($stored{'enddate'} == 0) { @@ -831,6 +1055,7 @@ sub retrieve_settings { $stored{'specificity'} = $groupinfo{'specificity'}; $stored{'creation'} = $groupinfo{'creation'}; $stored{'creator'} = $groupinfo{'creator'}; + $stored{'quota'} = $groupinfo{'quota'}; foreach my $tool (sort(keys(%{$groupinfo{'functions'}}))) { if ($groupinfo{functions}{$tool} eq 'on') { @@ -855,6 +1080,7 @@ sub retrieve_settings { foreach my $role (sort(keys(%{$groupinfo{'autosec'}}))) { if (ref($groupinfo{'autosec'}{$role}) eq 'ARRAY') { foreach my $section (@{$groupinfo{'autosec'}{$role}}) { + push (@{$stored{'sec_'.$role}},$section); } if (@{$groupinfo{'autosec'}{$role}} > 0) { @@ -867,104 +1093,439 @@ sub retrieve_settings { } sub display_control { - my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$sectioncount,$groupname, + my ($r,$cdom,$cnum,$action,$state,$page,$sectioncount,$groupname, $description,$functions,$tools,$toolprivs,$fixedprivs,$startdate, - $enddate,$users,$userdata,$idx,$memchg,$usertools,$function, - $view_permission,$manage_permission,$stored,$granularity,$specificity, - $types,$roles,$sections,$states,$navbuttons,$rowColor1,$rowColor2)=@_; + $enddate,$users,$userdata,$idx,$memchg,$usertools, + $view_permission,$manage_permission,$stored,$granularity,$quota, + $specificity,$types,$roles,$sections,$states,$navbuttons, + $gpterm,$ucgpterm,$crstype) = @_; if ($action eq 'create') { if ($state eq 'pick_name') { - &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page, + &general_settings_form($r,$cdom,$cnum,$action,$state,$page, $functions,$tools,$toolprivs,$fixedprivs, $sectioncount,$stored,$states,$navbuttons, - $rowColor1,$rowColor2); + $gpterm,$ucgpterm,$crstype); } elsif ($state eq 'pick_members') { - &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page, - $groupname,$description,$granularity, + &choose_members_form($r,$cdom,$cnum,$action,$state,$page, + $groupname,$description,$granularity,$quota, $startdate,$enddate,$tools,$fixedprivs, $toolprivs,$functions,$users,$userdata,$idx, - $stored,$states,$navbuttons,$rowColor1, - $rowColor2); + $stored,$states,$navbuttons,$gpterm,$ucgpterm, + $crstype); } elsif ($state eq 'pick_privs') { - &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page, + &choose_privs_form($r,$cdom,$cnum,$action,$state,$page, $startdate,$enddate,$tools,$functions, $toolprivs,$fixedprivs,$userdata,$usertools, $idx,$states,$stored,$sectioncount,$navbuttons, - $rowColor1,$rowColor2); + $gpterm,$ucgpterm,$crstype); } elsif ($state eq 'result') { - &process_request($r,$cdom,$cnum,$tabcol,$action,$state,$page, + &process_request($r,$cdom,$cnum,$action,$state,$page, $groupname,$description,$specificity,$userdata, $startdate,$enddate,$tools,$functions, $toolprivs,$usertools,$idx,$types,$roles, $sections,$states,$navbuttons,$memchg, - $sectioncount,$stored,$rowColor1,$rowColor2); + $sectioncount,$stored,$gpterm,$ucgpterm,$crstype); } } elsif ($action eq 'modify') { my $groupname = $env{'form.groupname'}; - if ($state eq 'pick_group') { - &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx, - $view_permission,$manage_permission,$action, - $rowColor1,$rowColor2); - } elsif ($state eq 'pick_task') { - &modify_menu($r,$groupname,$page); + if ($state eq 'pick_task') { + &modify_menu($r,$groupname,$page,$gpterm); } elsif ($state eq 'change_settings') { - &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page, + &general_settings_form($r,$cdom,$cnum,$action,$state,$page, $functions,$tools,$toolprivs,$fixedprivs, $sectioncount,$stored,$states,$navbuttons, - $rowColor1,$rowColor2); + $gpterm,$ucgpterm,$crstype); } elsif ($state eq 'change_members') { - &change_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page, + &change_members_form($r,$cdom,$cnum,$action,$state,$page, $groupname,$description,$startdate,$enddate, $tools,$fixedprivs,$functions,$users, - $userdata,$granularity,$specificity,$idx, - $states,$navbuttons,$rowColor1,$rowColor2); + $userdata,$granularity,$quota,$specificity, + $idx,$states,$navbuttons,$gpterm,$ucgpterm); } elsif ($state eq 'add_members') { - &add_members_form($r,$tabcol,$action,$state,$page,$startdate, + &add_members_form($r,$cdom,$cnum,$action,$state,$page,$startdate, $enddate,$groupname,$description,$granularity, - $sectioncount,$tools,$functions,$stored,$states, - $navbuttons,$rowColor1,$rowColor2); + $quota,$sectioncount,$tools,$functions,$stored, + $states,$navbuttons,$gpterm,$ucgpterm,$crstype); } elsif ($state eq 'pick_members') { - &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page, - $groupname,$description,$granularity, + &choose_members_form($r,$cdom,$cnum,$action,$state,$page, + $groupname,$description,$granularity,$quota, $startdate,$enddate,$tools,$fixedprivs, $toolprivs,$functions,$users,$userdata,$idx, - $stored,$states,$navbuttons,$rowColor1, - $rowColor2); + $stored,$states,$navbuttons,$gpterm,$ucgpterm, + $crstype); } elsif ($state eq 'pick_privs') { - &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page, + &choose_privs_form($r,$cdom,$cnum,$action,$state,$page, $startdate,$enddate,$tools,$functions, $toolprivs,$fixedprivs,$userdata,$usertools, $idx,$states,$stored,$sectioncount,$navbuttons, - $rowColor1,$rowColor2); + $gpterm,$ucgpterm,$crstype); } elsif ($state eq 'change_privs') { - &change_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page, + &change_privs_form($r,$cdom,$cnum,$action,$state,$page, $startdate,$enddate,$tools,$functions, $toolprivs,$fixedprivs,$userdata,$usertools, $memchg,$idx,$states,$stored,$sectioncount, - $navbuttons,$rowColor1,$rowColor2); + $navbuttons,$gpterm,$ucgpterm); } elsif ($state eq 'chgresult' || $state eq 'memresult' || $state eq 'addresult') { - &process_request($r,$cdom,$cnum,$tabcol,$action,$state,$page, + &process_request($r,$cdom,$cnum,$action,$state,$page, $groupname,$description,$specificity,$userdata, $startdate,$enddate,$tools,$functions, $toolprivs,$usertools,$idx,$types,$roles, $sections,$states,$navbuttons,$memchg, - $sectioncount,$stored,$rowColor1,$rowColor2); + $sectioncount,$stored,$gpterm,$ucgpterm,$crstype); + } + } elsif ($action eq 'delete') { + my %stored = &retrieve_settings($cdom,$cnum,$groupname,$action); + if ($state eq 'verify') { + &verify_delete($r,$groupname,$state,$action,$page,$states, + \%stored,$crstype); + } elsif ($state eq 'result') { + &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,$crstype) = @_; + $r->print(&Apache::lonhtmlcommon::echo_form_input([])); + $r->print(&mt('You have requested deletion of the group [_1].' + ,''.$stored->{'description'}.''). + '

'.&mt('When a group is deleted the following occurs:').'
    '. + '
  • '.&mt('All group membership is terminated.').'
  • '. + '
  • '.&mt('The group ceases to be available either for viewing or for modification of group settings and membership.').'
  • '); + if ($crstype eq 'Community') { + $r->print( '
  • '.&mt("The group folder is removed from the folder containing it - normally this is the 'Community Groups' folder which contains folders for all groups in the community.").'
  • '. + '
'.&mt("Although a deleted group is no longer accessible, the group name used for the group will be reserved, and will not be available for assignment to a new group in the same community in the future.")); + } else { + $r->print( '
  • '.&mt("The group folder is removed from the folder containing it - normally this is the 'Course Groups' folder which contains folders for all groups in the course.").'
  • '. + ''.&mt("Although a deleted group is no longer accessible, the group name used for the group will be reserved, and will not be available for assignment to a new group in the same course in the future.")); + } + my $prevtext = &mt('Go back'); + my $nexttext = &mt('Delete group'); + my $prev; + if ($env{'form.refpage'} eq 'cusr') { + $prev = 'view'; + } + &display_navbuttons($r,$formname,$prev,$prevtext, + $$states{$action}[$page+1],$nexttext); + return; +} + +sub delete_group { + my ($r,$cdom,$cnum,$groupname,$crstype) = @_; + my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum, + $groupname); + my $now = time; + my $num_users = 0; + my $num_fail = 0; + my $num_ok = 0; + my @deleted; + my @undeleted; + my %usersettings; + my $context = 'deletegroup'; + foreach my $key (sort(keys(%membership))) { + if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) { + my $user = $1; + my($end,$start,$userprivs) = split(/:/,$membership{$key},3); + if ($start != -1) { + $num_users ++; + $usersettings{$groupname.':'.$user} = $now.':-1:'.$userprivs; + if (&Apache::lonnet::modify_group_roles($cdom,$cnum, + $groupname,$user, + $now,'-1',$userprivs, + '',$context) + eq 'ok') { + $num_ok ++; + push(@deleted,$user); + } else { + push(@undeleted,$user); + $num_fail ++; + } + } + } + } + if ($num_ok > 0) { + my $roster_result = + &Apache::lonnet::modify_coursegroup_membership($cdom,$cnum, + \%usersettings); + } + if ($num_fail > 0) { + $r->print('
    ' + .&mt('Group deletion failed because deletion of [_1] out of [_2] members failed.' + ,$num_fail,$num_users) + .'
    '); + } else { + my ($result,$message) = + &Apache::lonnet::toggle_coursegroup_status($cdom,$cnum, + $groupname,'delete'); + if ($result eq 'ok') { + my $outcome = &modify_folders($cdom,$cnum,$groupname,$crstype); + if ($outcome eq '') { + my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Group successfully deleted.')); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); + } else { + $r->print('
    '); + if ($crstype eq 'Community') { + $r->print(&mt("Although the group was deleted, an error occurred when removing the group's folder from the 'Community Groups' folder: [_1]",$outcome)); + } else { + $r->print(&mt("Although the group was deleted, an error occurred when removing the group's folder from the 'Course Groups' folder: [_1]",$outcome)); + } + $r->print('
    '); + } + } else { + my $msg = &Apache::lonhtmlcommon::confirm_success(&mt('Group deletion failed.'),1); + $msg = &Apache::loncommon::confirmwrapper($msg); + $r->print($msg); + } + } + return; +} + +sub reenable_folder { + my ($cdom,$cnum,$groupname,$description,$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='
    ' + .&mt('An error occurred when reading contents of parent folder to group:') + ."
    ($allgrpsmap): $errtext" + .'
    '; + } else { + my $idx=&LONCAPA::map::getresidx($mapurl); + $LONCAPA::map::resources[$idx] = $foldertitle.':'.$mapurl. + ':false:normal:res'; + $LONCAPA::map::order[1+$#LONCAPA::map::order]=$idx; + my ($outtext,$errtext) = &LONCAPA::map::storemap($allgrpsmap,1,1); + if ($errtext) { + $outcome='
    ' + .&mt('An error occurred when saving updated parent folder to group:' + ,"
    $allgrpsmap - $errtext") + .'
    '; + } else { + my ($furl,$ferr) = + &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + } + } + return $outcome; +} + +sub modify_folders { + my ($cdom,$cnum,$groupname,$crstype) = @_; + my ($outcome,$groupmap,$groupmapres,$map,$id,$src); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $outcome = '
    '; + if ($crstype eq 'Community') { + $outcome .= &mt("Error reading community contents.").' '. + &mt("You need to re-initialize the community."); + } else { + $outcome .= &mt("Error reading course contents.").' '. + &mt("You need to re-initialize the course."); + } + $outcome .= '
    '; + return $outcome; + } + $groupmap = '/uploaded/'.$cdom.'/'.$cnum.'/'.'group_folder_'. + $groupname.'.sequence'; + $groupmapres = $navmap->getResourceByUrl($groupmap); + if ($groupmapres) { + ($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('An error occurred when reading contents of parent folder to group:') + ."
    ($map): $errtext" + .'
    '; + } else { + my $idx = 0; + my $grpidx; + foreach my $item (@LONCAPA::map::order) { + my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$item]); + $url=&LONCAPA::map::qtescape($url); + if ($url eq $groupmap) { + $grpidx = $idx; + last; + } else { + $idx++; + } + } + + if ($grpidx ne '') { + &LONCAPA::map::makezombie($LONCAPA::map::order[$grpidx]); + for (my $i=$grpidx;$i<$#LONCAPA::map::order;$i++) { + $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1]; + } + $#LONCAPA::map::order--; + my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1,1); + if ($errtext) { + $outcome='
    ' + .&mt('An error occurred when saving updated parent folder to group:') + ."
    $map - $errtext" + .'
    '; + } else { + my ($furl,$ferr) = + &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + } + } + } + } + return $outcome; +} + +sub verify_reenable { + my ($r,$groupname,$formname,$action,$page,$states,$stored,$crstype) = @_; + $r->print(&Apache::lonhtmlcommon::echo_form_input([])); + $r->print(&mt('You have requested enabling the previously deleted group [_1].' + ,''.$stored->{'description'}.''). + '

    '.&mt('When a deleted group is re-enabled the following occurs:').'
      '. + '
    • '.&mt('Group settings and membership at the time the group was deleted are reinstated.').'
    • '); + if ($crstype eq 'Community') { + $r->print(&mt("A group folder is added to the 'Community Groups' folder which contains folders for all groups in the community.")); + } else { + $r->print(&mt("A group folder is added to the 'Course Groups' folder which contains folders for all groups in the course.")); + } + $r->print('
    '); + my $prevtext = &mt('Go back'); + my $nexttext = &mt('Reenable group'); + my $prev; + 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?',''.$groupname.''),'
    '); + return; + } + my %groupinfo = + &Apache::longroup::get_group_settings($groups{$groupname}); + my $defstart = $groupinfo{'startdate'}; + my $defend = $groupinfo{'enddate'}; + my $showstart = &Apache::lonlocal::locallocaltime($defstart); + my $showend; + if ($defend == 0) { + $showend = &mt('No end date set'); + } else { + $showend = &Apache::lonlocal::locallocaltime($defend); + } + my $description = &unescape($groupinfo{'description'}); + my $num_users = 0; + my $num_ok = 0; + my $num_fail = 0; + my $context = 'reenablegroup'; + my (%usersettings,@enabled,@unenabled); + my ($result,$message) = + &Apache::lonnet::toggle_coursegroup_status($cdom,$cnum,$groupname, + 'reenable'); + if ($result eq 'ok') { + my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum, + $groupname); + foreach my $key (sort(keys(%membership))) { + if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) { + my $user = $1; + my($end,$start,$userprivs) = split(/:/,$membership{$key},3); + if (($start == -1) && ($end == $groupinfo{'modified'})) { + $num_users ++; + $usersettings{$groupname.':'.$user} = $defend.':'. + $defstart.':'. + $userprivs; + if (&Apache::lonnet::modify_group_roles($cdom,$cnum, + $groupname,$user, + $defend,$defstart, + $userprivs,'', +$context) eq 'ok') { + $num_ok ++; + push(@enabled,$user); + } else { + push(@unenabled,$user); + $num_fail ++; + } + } + } } + if ($num_users > 0) { + if ($num_ok > 0) { + my $roster_result = + &Apache::lonnet::modify_coursegroup_membership($cdom,$cnum, + \%usersettings); + if ($roster_result eq 'ok') { + $r->print('
    ' + .&mt('Membership reinstated for [quant,_1,user], each with start and end dates for group access set to defaults: [_2] and [_3]',$num_ok,$showstart,$showend) + .'
    '); + } + } else { + $r->print('
    ' + .&mt('A problem occurred when trying to reinstate [_1] of the [_2] members of the pre-existing group.',$num_fail,$num_users) + .'
    '); + } + } else { + $r->print('
    ' + .&mt('There were no group members to reinstate, as none were removed when the group was deleted.') + .'
    '); + } + my $outcome = &reenable_folder($cdom,$cnum,$groupname,$description,$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('
    '); + if ($crstype eq 'Community') { + $r->print(&mt("Although the group was re-enabled, an error occurred when adding the group's folder to the 'Community Groups' folder: [_1]",$outcome)); + } else { + $r->print(&mt("Although the group was re-enabled, an error occurred when adding the group's folder to the 'Course Groups' folder: [_1]",$outcome)); + } + $r->print('
    '); + } + } else { + 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,$function,$loaditems) = @_; + my ($bodytitle,$jscript,$action,$state,$page,$loaditems) = @_; my $start_page= &Apache::loncommon::start_page($bodytitle, '', - {'function' => $function, - 'add_entries' => $loaditems,}); + {'add_entries' => $loaditems,}); my $output = <<"END"; $start_page -
    + END if ($action eq 'create' || $action eq 'modify') { @@ -991,8 +1552,7 @@ sub onload_action { } if (($action eq 'modify') && ($state eq 'change_settings' || $state eq 'change_members' || - $state eq 'change_privs' || $state eq 'add_members' || - $state eq 'pick_members')) { + $state eq 'change_privs' || $state eq 'add_members')) { $loaditems{'onload'} = 'javascript:setFormElements(document.'.$state.')'; } @@ -1023,6 +1583,24 @@ sub build_members_list { } sub group_files { + my ($group,$portpath,$numfiles,$numdirs) = @_; + my $dirptr=16384; + 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 ++; + } + } + } + } return; } @@ -1030,240 +1608,292 @@ sub group_members { my ($cdom,$cnum,$group,$group_info) = @_; my %memberhash = &Apache::lonnet::get_group_membership($cdom,$cnum,$group); my $now = time; - my ($tmp)=keys(%memberhash); - if ($tmp=~/^error:/) { - $$group_info{'totalmembers'} = 'Unknown - an error occurred'; - return $tmp; - } - my $now = time; + my %lt = &Apache::lonlocal::texthash ( + active => 'active', + previous => 'previous', + future => 'future', + ); + my %membercounts = ( + active => 0, + previous => 0, + future => 0, + ); my $totalmembers = 0; - my $active = 0; - my $previous = 0; - my $future = 0; - foreach my $member (keys %memberhash) { + foreach my $member (keys(%memberhash)) { $totalmembers ++; my ($end,$start) = split(/:/,$memberhash{$member}); unless ($start == -1) { if (($end!=0) && ($end<$now)) { - $previous ++; + $membercounts{previous} ++; } elsif (($start!=0) && ($start>$now)) { - $future ++; + $membercounts{future} ++; } else { - $active ++; + $membercounts{active} ++; } } } if ($totalmembers == 0) { $$group_info{$group}{'totalmembers'} = 'None'; } else { - $$group_info{$group}{'totalmembers'} = $active.' - active
    '.$previous.' -previous
    '.$future.' -future'; + foreach my $type ('active','previous','future') { + $$group_info{$group}{'totalmembers'} .= + &open_list_window($group,$type,$membercounts{$type},$lt{$type}); + } } return 'ok'; } +sub open_list_window { + my ($group,$status,$count,$text) = @_; + my $entry; + if ($count > 0) { + $entry = ''.$text.' - '.$count. + '
    '; + } else { + $entry = ''.$text.' - '.$count.'
    '; + } + return $entry; +} + sub general_settings_form { - my ($r,$cdom,$cnum,$action,$tabcol,$formname,$page,$functions,$tools, + my ($r,$cdom,$cnum,$action,$formname,$page,$functions,$tools, $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons, - $rowColor1,$rowColor2) = @_; + $gpterm,$ucgpterm,$crstype) = @_; my ($nexttext,$prevtext); - $r->print('
    - -'); - &groupsettings_options($r,$tabcol,$functions,$action,$formname,$stored,1); - $r->print(' - - - '); - &access_date_settings($r,$tabcol,$action,$formname,$stored,2); - $r->print(' - - - '); + &groupsettings_options($r,$functions,$action,$formname,$stored,1, + $gpterm,$ucgpterm,$crstype); + &access_date_settings($r,$action,$formname,$stored,2,$gpterm,$ucgpterm); if ($action eq 'create') { - &membership_options($r,$action,$formname,$tabcol,$sectioncount,3); + &membership_options($r,$cdom,$cnum,$action,$formname,$sectioncount,3, + $gpterm,$ucgpterm,$crstype); $nexttext = $$navbuttons{'gtns'}; } else { my @available = (); my @unavailable = (); &check_tools($functions,$tools,\@available,\@unavailable); @{$tools} = sort(keys(%{$functions})); - &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action, - 3,$tools,$stored,$toolprivs,$fixedprivs, - \@available,$formname); - $r->print(' - - - '); - &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount, - $states,$stored,$navbuttons,4,5,$rowColor1, - $rowColor2); + &privilege_specificity($r,$action,3,$tools,$stored,$toolprivs, + $fixedprivs,\@available,$formname, + $gpterm,$ucgpterm,$functions,$crstype); + &mapping_options($r,$action,$formname,$page,$sectioncount, + $states,$stored,$navbuttons,4,5, + $gpterm,$ucgpterm,$crstype,$cdom,$cnum); $nexttext = $$navbuttons{'mose'}; } $prevtext = $$navbuttons{'gtpp'}; &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext, $$states{$action}[$page+1],$nexttext); - $r->print(' -
     
     
     
    '); return; } sub groupsettings_options { - my ($r,$tabcol,$functions,$action,$formname,$stored,$image) = @_; + my ($r,$functions,$action,$formname,$stored,$image,$gpterm, + $ucgpterm,$crstype) = @_; my %lt = &Apache::lonlocal::texthash( - 'gdat' => 'Group open and close dates', - 'sten' => 'Set a start date/time and end date/time for the group', - 'gfun' => 'Group functionality', - 'gnde' => 'Group name, description and available functionality', - 'desc' => 'Description', - 'func' => 'Functionality', + 'gdat' => "Group access start and end dates", + 'gnde' => "Group name, title and available collaborative tools", + 'desc' => 'Group Title', + 'func' => 'Collaborative Tools', 'gnam' => 'Group Name', - 'doyo' => 'Do you want to assign different functionality '. - 'to different group members?', + '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); + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'gnde'})); + + # Group Name + $r->print(&Apache::lonhtmlcommon::start_pick_box() + .&Apache::lonhtmlcommon::row_title($lt{'gnam'}) ); - &topic_bar($r,$tabcol,$image,$lt{'gnde'}); - $r->print(' - -   - - - - - - - - - - - - -END + $r->print(&Apache::lonhtmlcommon::row_closure()); + + # Group Title + $r->print(&Apache::lonhtmlcommon::row_title($lt{'desc'}) + .'' + .&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(' - '); - } - $r->print(''); - for (my $j=$halfnum; $j<@allfunctions; $j++) { - $r->print(' - '); - } - if ($remnum) { - $r->print(''); + my @allfunctions = sort(keys(%{$functions})); + + $r->print(&Apache::lonhtmlcommon::row_title($lt{'func'}) + .'
    ' + .'' + .' ' + .'
    ' + .'
    '.$lt{'gnam'}.': -'); if ($action eq 'create') { - $r->print(''); + $r->print('' + .' (' + .$lt{'lett'}.')' + ); } else { $r->print(''.$env{'form.groupname'}); } - $r->print(<<"END"); -
    $lt{'desc'}: -
    $lt{'func'}:  '. - '
        
    ' # FIXME Get rid of inflexible table (-> float) + ); + for (my $i=0; $i<@allfunctions; $i++) { + $r->print('' + ); + if ($i == $halfnum - 1) { + $r->print(''); + } } - $r->print(' - - - - -
    - -
    Granularity:'.$lt{'doyo'}.'  '); + $r->print('
    ' + .&Apache::lonhtmlcommon::row_closure() + ); + + # Granularity + $r->print(&Apache::lonhtmlcommon::row_title($lt{'gran'}) + .$lt{'doyo'}.'
    ' + .' ' + ); if ($action eq 'modify') { - $r->print('  ('.&mt('Currently set to "[_1]"', - $$stored{'granularity'}).')'); + $r->print(' (' + .&mt('Currently set to [_1].' + ,'"'.&mt($$stored{'granularity'}).'"') + .')' + ); } - $r->print(' - - - - - -'); + $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 group portfolio for the '.$gpterm + .', allocate a disk quota.') + .'' + ); + } else { + $r->print(&mt('Quota allocated to group portfolio:')); + } + $r->print(' '.&mt('[_1] MB','')); + if ($action eq 'create') { + $r->print('
    ' + .&mt('A total of [_1] MB can be divided amongst all '.$gpterm.'s in the ' + .lc($crstype).', and [_2] MB are currently unallocated.' + ,$crsquota,sprintf("%.2f",$freespace)) + ); + } else { + $r->print('  ('.&mt('The quota is currently [_1] MB', + $$stored{'quota'}).').'); + + $r->print('
    ' + .&mt('The quota can be increased to [_1] MB, ' + .'by adding all unallocated space for '.$gpterm.'s in the '.lc($crstype).'.' + ,sprintf("%.2f",$maxposs))); + } + $r->print(&Apache::lonhtmlcommon::row_closure(1)); + + $r->print(&Apache::lonhtmlcommon::end_pick_box()); + return; } +sub get_quota_constraints { + my ($action,$stored) = @_; + my ($crsquota,$freespace,$maxposs); + $crsquota = $env{'course.'.$env{'request.course.id'}.'.internal.coursequota'}; + if ($crsquota eq '') { + $crsquota = 20; + } + $freespace = $crsquota - &Apache::longroup::sum_quotas(); + if ($action eq 'create') { + $maxposs = $freespace; + } else { + $maxposs = $$stored{'quota'} + $freespace; + } + return ($crsquota,$freespace,$maxposs); +} + sub membership_options { - my ($r,$action,$state,$tabcol,$sectioncount,$image) = @_; + my ($r,$cdom,$cnum,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm,$crstype)=@_; my %lt = &Apache::lonlocal::texthash( - 'pipa' => 'Pick parameters to generate membership list', - 'gmem' => 'Group membership options', - 'picr' => 'Pick the criteria to use to build a list of '. - 'course 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, do not make any selections', + '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 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' => 'Course roles', 'cose' => 'Course sections', ); + if ($crstype eq 'Community') { + $lt{'picr'} = &mt('Pick the criteria to use to build a list of community participants from which you will select '); + $lt{'asub'} = &mt('A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section [_1]changes[_2] in the course.','',''); + $lt{'coro'} = &mt('Community roles'); + $lt{'cose'} = &mt('Community sections'); + } else { + $lt{'asub'} = &mt('A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section [_1]changes[_2] in the course.','',''); + } my %status_types = ( active => &mt('Currently has access'), previous => &mt('Previously had access'), future => &mt('Will have future access'), ); - my @roles = ('st','cc','in','ta','ep','cr'); + my @roles = ('st'); + if ($crstype eq 'Community') { + push(@roles,'co'); + } else { + push(@roles,'cc'); + } + push (@roles,('in','ta','ep','ad','cr')); my @sections = keys(%{$sectioncount}); - &topic_bar($r,$tabcol,$image,$lt{'pipa'}); - $r->print(' - -   - - '.$lt{'gmem'}.'
    '.$lt{'picr'}); + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'pipa'}).' + '.$lt{'gmem'}.'
    '); if ($action eq 'create') { - $r->print($lt{'meof'}.'
    '.$lt{'ifno'}); + $r->print($lt{'picr'}.'
    '.$lt{'ifno'}.'
    '.$lt{'asub'}); } else { - $r->print($lt{'admg'}); + $r->print($lt{'pica'}); } $r->print('

    - +
    - - - '); - if (@sections >0) { - $r->print(' - - - '); - } - $r->print(''); + + + + '); - $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles)); + $r->print(' - '); + unshift(@sections,'all'); # Put 'all' at the front of the list + } else { + @sections = ('all','none'); } - $r->print(' + $r->print(' -
    '.$lt{'acty'}.' '.$lt{'coro'}.' '.$lt{'cose'}.' 
    '.$lt{'acty'}.''.$lt{'coro'}.''.$lt{'cose'}.'
    '); $r->print(&Apache::lonhtmlcommon::status_select_row(\%status_types)); - $r->print(' '); + $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles,undef,undef,1,$cdom,$cnum)); if (@sections > 0) { @sections = sort {$a cmp $b} @sections; - unshift(@sections,'all'); # Put 'all' at the front of the list unshift(@sections,'none'); # Put 'no sections' next - $r->print(' '. - §ions_selection(\@sections,'sectionpick').''. + §ions_selection(\@sections,'sectionpick').'
    - - '); + '); return; } @@ -1276,25 +1906,23 @@ sub sections_selection { } foreach my $sec (@{$sections}) { if ($sec eq 'all') { - $section_sel .= ' '."\n"; } elsif ($sec eq 'none') { - $section_sel .= ' '."\n"; } else { - $section_sel .= ' \n"; } } my $output = ' - '.$section_sel.' '; return $output; } sub access_date_settings { - my ($r,$tabcol,$action,$formname,$stored,$image) = @_; - my %lt = &Apache::lonlocal::texthash( - 'sten' => 'Default start and end dates for group access', - ); + my ($r,$action,$formname,$stored,$image,$gpterm,$ucgpterm) = @_; + 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') { @@ -1303,47 +1931,30 @@ sub access_date_settings { $endtime = $$stored{'enddate'}; } } - my ($start_table,$end_table) = &date_setting_table - ($starttime,$endtime,$formname); - &topic_bar($r,$tabcol,$image,$lt{'sten'}); - $r->print(' - -   - '.$start_table.' - - -   - - -   - '.$end_table.' - '); + my ($table) = &date_setting_table($starttime,$endtime,$formname); + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$sten).' + '.$table.' + '); return; } sub choose_members_form { - my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description, - $granularity,$startdate,$enddate,$tools,$fixedprivs,$toolprivs, + my ($r,$cdom,$cnum,$action,$formname,$page,$groupname,$description, + $granularity,$quota,$startdate,$enddate,$tools,$fixedprivs,$toolprivs, $functions,$users,$userdata,$idx,$stored,$states,$navbuttons, - $rowColor1,$rowColor2) = @_; + $gpterm,$ucgpterm,$crstype) = @_; my @regexps = ('user_','userpriv_','sec_'); my %origmembers; $r->print(&Apache::lonhtmlcommon::echo_form_input( ['origin','action','state','page','member','specificity','branch', 'defpriv','autorole','autoadd','autodrop','sortby','togglefunc'], \@regexps)); - my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum); - $r->print(' - - - - '); + $r->print($earlyout); &display_navbuttons($r,$formname,$$states{$action}[$page-1], $$navbuttons{'gtps'}); - $r->print('
      -'); + my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm, + $ucgpterm,$crstype); if ($earlyout) { - $r->print($earlyout.'
    '); return; } my ($specimg,$memimg); @@ -1351,10 +1962,9 @@ sub choose_members_form { my @unavailable = (); &check_tools($functions,$tools,\@available,\@unavailable); if ($action eq 'create') { - &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2, - $functions,$startdate,$enddate,$groupname, - $description,$granularity,\@available, - \@unavailable); + &print_current_settings($r,$action,$functions,$startdate,$enddate, + $groupname,$description,$granularity,$quota, + \@available,\@unavailable,$gpterm,$ucgpterm); $specimg = 4; $memimg = 5; } else { @@ -1374,13 +1984,13 @@ sub choose_members_form { } } } - &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action, - $specimg,$tools,$stored,$toolprivs, - $fixedprivs,\@available,$formname); - my $newusers = &pick_new_members($r,$action,$formname,$tabcol,$rowColor1, - $rowColor2,\@available,$idx,$stored, - $memimg,$users,$userdata,$granularity, - \%origmembers); + &privilege_specificity($r,$action,$specimg,$tools,$stored,$toolprivs, + $fixedprivs,\@available,$formname,$gpterm,$ucgpterm, + $functions,$crstype); + my $newusers = &pick_new_members($r,$action,$formname,\@available,$idx, + $stored,$memimg,$users,$userdata, + $granularity,\%origmembers,$gpterm, + $ucgpterm); if ($newusers || $action eq 'create') { &display_navbuttons($r,$formname,$$states{$action}[$page-1], $$navbuttons{'gtps'},$$states{$action}[$page+1], @@ -1389,34 +1999,29 @@ sub choose_members_form { &display_navbuttons($r,$formname,$$states{$action}[$page-1], $$navbuttons{'gtps'}); } - $r->print(''); return; } sub display_navbuttons { my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_; - $r->print(' - -   - - -   - '); + $r->print('
    '); if ($prev) { $r->print('    '); + } elsif ($prevtext) { + $r->print(' + +    '); } if ($next) { $r->print(' '); } - $r->print(' - - -'); + $r->print('
    '); } sub check_tools { @@ -1432,21 +2037,22 @@ sub check_tools { } sub print_current_settings { - my ($r,$action,$tabcol,$rowColor1,$rowColor2,$functions,$startdate,$enddate, - $groupname,$description,$granularity,$available,$unavailable) =@_; + my ($r,$action,$functions,$startdate,$enddate,$groupname,$description, + $granularity,$quota,$available,$unavailable,$gpterm,$ucgpterm) = @_; my %lt = &Apache::lonlocal::texthash( grna => 'Group Name', - desc => 'Description', - grfn => 'Group Functions', + desc => 'Group Title', + grfn => "Collaborative Tools", gran => 'Granularity', + quot => 'File quota', dfac => 'Default access dates', - ygrs => 'Your group selections', - tfwa => 'The following settings will apply to the group:', - difn => 'Different functionality
    for different users:', - stda => 'Start date', + ygrs => "Your group selections - ", + tfwa => "The following settings will apply to the group:", + stda => 'Start date:', enda => 'End date:', ); + $lt{'difn'} = &mt('Different collaborative tools[_1]for different members:','
    '); my $showstart = &Apache::lonlocal::locallocaltime($startdate); my $showend; if ($enddate == 0) { @@ -1454,101 +2060,79 @@ sub print_current_settings { } else { $showend = &Apache::lonlocal::locallocaltime($enddate); } - $r->print(''); if ($action eq 'create') { $r->print(' - - -'); +'); } - $r->print(' - - END - $r->print(&Apache::lonhtmlcommon::end_pick_box()); - $r->print('
    '.$lt{'ygrs'}.' +
    '.$lt{'ygrs'}.'
    '.$lt{'tfwa'}.' -
    '); - $r->print(&Apache::lonhtmlcommon::start_pick_box()); + $r->print(&Apache::loncommon::start_data_table('LC_course_group_status'). + &Apache::loncommon::start_data_table_header_row()); $r->print(' -
    - - - - - - - - - - - + + + + + + +'); + $r->print(&Apache::loncommon::end_data_table_header_row(). + &Apache::loncommon::start_data_table_row('LC_data_table_dense')); + $r->print(' + + - + + - -
    '.$lt{'grna'}.''.$lt{'desc'}.''.$lt{'grfn'}.''.$lt{'gran'}.''.$lt{'dfac'}.'
    '.$groupname.''.$description.''.$lt{'grna'}.''.$lt{'desc'}.''.$lt{'grfn'}.''.$lt{'gran'}.''.$lt{'quot'}.''.$lt{'dfac'}.''.$groupname.''.$description.' '); + if (@{$available} > 0) { - $r->print('Available: - '); - my $rowcell = int(@{$available}/2) + @{$available}%2; + $r->print(''.&mt('Available for assignment to members:').''); + $r->print('
      '); for (my $i=0; $i<@{$available}; $i++) { - if (@{$available} > 3) { - if ($i==$rowcell) { - $r->print('
    '); - } - } - $r->print(''); - } - if ((@{$available} > 3) && (@{$available}%2)) { - $r->print(''); + $r->print('
  • '.&mt($$functions{$$available[$i]}).'
  • '); } - $r->print('
    '.$$functions{$$available[$i]}. - '   

    '); + $r->print(''); } + if (@{$unavailable} > 0) { - $r->print('Unavailable: - '); - my $rowcell = int(@{$unavailable}/2) + @{$unavailable}%2; - for (my $j=0; $j<@{$unavailable}; $j++) { - if (@{$unavailable} > 3) { - if ($j==$rowcell) { - $r->print(''); - } - } - $r->print(''); + $r->print(''.&mt('Unavailable for assignment:').''); + $r->print('
      '); + for (my $i=0; $i<@{$unavailable}; $i++) { + $r->print('
    • '.&mt($$functions{$$unavailable[$i]}).'
    • '); } - if ((@{$unavailable} > 3) && (@{$unavailable}%2)) { - $r->print('
    '); - } - $r->print('
    '.$$functions{$$unavailable[$j]}. - '   
    '); + $r->print(''); } + + my $quota_text=&mt('[_1] MB',$quota); + my $granu_text=&mt($granularity); $r->print(<<"END");
    $lt{'difn'} - $granularity - $lt{'stda'} $showstart
    - $lt{'enda'} $showend
    +
    $lt{'difn'} $granu_text$quota_text$lt{'stda'} $showstart
    + $lt{'enda'} $showend
    -

    '); + $r->print(&Apache::loncommon::end_data_table_row(). + &Apache::loncommon::end_data_table()); return; } sub pick_new_members { - my ($r,$action,$formname,$tabcol,$rowColor1,$rowColor2,$available,$idx, - $stored,$img,$users,$userdata,$granularity,$origmembers) = @_; + my ($r,$action,$formname,$available,$idx,$stored,$img,$users,$userdata, + $granularity,$origmembers,$gpterm,$ucgpterm) = @_; my %lt = &Apache::lonlocal::texthash( - 'gpme' => 'Group membership', + 'gpme' => "Group membership", 'addm' => 'Add members', - 'setf' => 'Set functionality', - 'func' => 'Functionality', - 'nome' => 'No members to add at this time.', - 'nnew' => 'There are no users to add as new members, as all users'. - ' matching the specified type(s), role(s), and/or '. - '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.', + 'setf' => 'Assign collaborative tools', + 'func' => 'Tools', + 'nome' => 'No members to add at this time, as there are no users '. + 'matching the specified type(s), role(s) and section(s).', + '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.", ); my %members; my $totalusers = 0; @@ -1572,61 +2156,51 @@ sub pick_new_members { $r->print(&check_uncheck_tools($r,$available)); } } - &topic_bar($r,$tabcol,$img,$lt{'gpme'}); + $r->print(&Apache::lonhtmlcommon::topic_bar($img,$lt{'gpme'})); if (keys(%members) > 0) { $r->print(' - -   - '); &check_uncheck_buttons($r,$formname,'member',$lt{'addm'}); if (@{$available} > 0 && $granularity eq 'Yes') { - $r->print(''); + + '); } $r->print('
    -
    '.$lt{'setf'}.' - print('
    +
    '.$lt{'setf'}.' + +    - -
    - - - -   - - -   - '); - $r->print(&Apache::lonhtmlcommon::start_pick_box()); + $r->print(&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row()); $r->print(' - - - - - - - + '); + $r->print(''); } - $r->print(''); + $r->print(&Apache::loncommon::end_data_table_header_row()); if (@{$available} > 0) { if ($granularity eq 'Yes') { - $r->print(' - - + '); + $r->print(''); } } my %Sortby = (); @@ -1639,29 +2213,28 @@ sub pick_new_members { push(@{$Sortby{$members{$user}[$$idx{udom}]}},$user); } elsif ($env{'form.sortby'} eq 'id') { push(@{$Sortby{$members{$user}[$$idx{id}]}},$user); + } elsif ($env{'form.sortby'} eq 'section') { + push(@{$Sortby{$members{$user}[$$idx{section}]}},$user); } else { push(@{$Sortby{$members{$user}[$$idx{fullname}]}},$user); } } - my $rowNum = 0; - my $rowColor; foreach my $key (sort(keys(%Sortby))) { foreach my $user (@{$Sortby{$key}}) { - if ($rowNum %2 == 1) { - $rowColor = $rowColor1; - } else { - $rowColor = $rowColor2; - } my $id = $members{$user}[$$idx{id}]; my $fullname = $members{$user}[$$idx{fullname}]; my $udom = $members{$user}[$$idx{udom}]; my $uname = $members{$user}[$$idx{uname}]; - $r->print(''); + my $section = $members{$user}[$$idx{section}]; + $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense'). + ''. + ''. + ''. + ''. + ''. + ''); if (@{$available} > 0) { - $r->print(''); + $r->print(''); } - $r->print(''."\n"); - $rowNum ++; + $r->print(&Apache::loncommon::end_data_table_row()."\n"); } } - $r->print(&Apache::lonhtmlcommon::end_pick_box()); - $r->print(' - - '); + $r->print(&Apache::loncommon::end_data_table()); } else { - $r->print(' - - - - '); } return $newusers; } sub privilege_specificity { - my ($r,$tabcol,$rowColor1,$rowColor2,$action,$img,$tools,$stored, - $toolprivs,$fixedprivs,$available,$formname) = @_; + my ($r,$action,$img,$tools,$stored,$toolprivs,$fixedprivs,$available, + $formname,$gpterm,$ucgpterm,$functions,$crstype) = @_; my %lt = &Apache::lonlocal::texthash ( - 'uprv' => 'User privileges', - 'frty' => 'For each type of functionality you have chosen to include, '. - 'there is a set of standard privileges which apply to all '. - 'of those for whom the functionality is enabled.', - 'thar' => 'There are also additional privileges which can be set for '. - 'some, or all, members. Please choose one of the following:', - 'fort' => 'For the types of functionality you have chosen to include '. - 'there are no additional privileges which can be set for some '. - 'or all members.', - 'eaty' => 'Each of the types of functionality includes standard '. - 'privileges which apply to members with access to that '. - 'functionality, and may also include additional privileges '. + 'uprv' => 'User privileges for collaborative tools', + 'frty' => 'For each collaborative tool you have chosen to include, '. + 'there is a set of core privileges which all group members '. + 'assigned use of the tool will receive.', + 'thar' => 'For some tools there are also additional optional '. + 'privileges which can be set.', + 'plch' => 'Choose one of the following:', + 'fort' => 'For the collaborative tools you have chosen to include '. + 'only core privileges are available, '. + 'so there are no optional privileges to assign.', + 'eaty' => 'Each collaborative tool includes core '. + 'privileges assigned to all members with access to the '. + 'tool. Some tools may also feature additional privileges '. 'which can be set for specific members.', 'cutg' => 'Currently the group is configured ', - 'sdif' => 'so different group members can receive different privileges.', - 'sall' => 'so all group members will receive the same privileges.', - 'algm' => 'All group members will receive the same privileges.', - 'smgp' => 'Some group members will receive different privileges from '. - 'others.', - 'thwi' => 'These will be the privileges all group members receive, '. + 'sdif' => 'so different members can receive different optional privileges for a particular tool.', + 'sall' => 'so all members will receive the same optional privileges for a particular tool.', + 'algm' => 'All group members will receive the same privileges for any tool assigned to them, including the default set of optional privileges.', + 'smgp' => 'Different group members may receive different privileges from '. + 'others for the tools they have been assigned.', + 'thwi' => 'These will be the privileges all group members receive for a particular assigned tool, '. 'if you selected the first option above.', - 'thes' => 'These will be the privileges given to members assigned '. - 'in the future, including via automatic group assignment '. - 'for specific sections/roles ', - 'asyo' => 'As you have chosen not to include any functionality in the '. - 'group, no default user privileges settings need to be set.', - 'plin' => 'Please indicate which optional privileges members '. - 'will receive by default.', + 'thes' => "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 course ", + 'asyo' => "As you have chosen not to include any collaborative tools ". + "in the group, no default optional privileges need to be set.", + 'will receive by default for a specific tool.', 'oppr' => 'Optional privileges', 'defp' => 'The default privileges new members will receive are:', ); + $lt{'plin'} = &mt('Indicate which [_1]optional[_2] privileges members '. + 'will receive by default for a specific tool.','',''); + if ($crstype eq 'Community') { + $lt{'thes'} = &mt('These will be the privileges given to members assigned in the future via automatic group assignment for users who receive specific sections/roles in the community '); + } my $totaloptionalprivs = 0; foreach my $tool (@{$tools}) { foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) { @@ -1743,14 +2309,9 @@ sub privilege_specificity { } } } - &topic_bar($r,$tabcol,$img,$lt{'uprv'}); - $r->print(' - - - - - - - '); +
    +
    +

    '); } else { $r->print(''); } if ($totaloptionalprivs) { - $r->print(' - - - - - - - - - - - - -'); return; } sub default_privileges { - my ($r,$action,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs, - $fixedprivs,$available) = @_; + my ($r,$action,$tools,$toolprivs,$fixedprivs,$available,$functions) = @_; my %lt = &Apache::lonlocal::texthash( 'addp' => 'Additional privileges', 'fixp' => 'Fixed privileges', 'oppr' => 'Optional privileges', - 'func' => 'Function', + 'func' => 'Collaborative Tool', ); - $r->print(&Apache::lonhtmlcommon::start_pick_box()); - $r->print(' - - '); + $r->print(&Apache::lonhtmlcommon::start_pick_box('LC_group_priv_box'). + &Apache::lonhtmlcommon::row_title($lt{'func'},undef, + 'LC_groups_functionality')); + my @tableHeader; + if ((ref($functions) eq 'HASH') && (ref($tools) eq 'ARRAY')) { + @tableHeader = map { $functions->{$_}; } @{$tools}; + } + $r->print(join(''."\n"); - $r->print(&Apache::lonhtmlcommon::end_pick_box()); + $r->print(&Apache::lonhtmlcommon::row_title($lt{'fixp'},undef, + 'LC_groups_fixed'). + $fixed. + &Apache::lonhtmlcommon::row_closure(1)); + $r->print(&Apache::lonhtmlcommon::row_title($lt{'oppr'},undef, + 'LC_groups_optional'). + $dynamic. + &Apache::lonhtmlcommon::end_pick_box()); $r->print('
    '); return; + } sub display_defprivs { - my ($r,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs,$defprivs) = @_; + my ($r,$tools,$toolprivs,$defprivs) = @_; + my $function = &Apache::loncommon::get_users_function(); + my $tabcol = &Apache::loncommon::designparm($function.'.tabbg'); + my $rowColor1 = "#dddddd"; + my $rowColor2 = "#eeeeee"; my %lt = &Apache::lonlocal::texthash( 'priv' => 'Privileges', - 'func' => 'Function', + 'func' => 'Collaborative Tool', ); $r->print(&Apache::lonhtmlcommon::start_pick_box()); $r->print(''); @@ -1936,7 +2477,7 @@ sub display_defprivs { @{$currprivs{$tool}} = (); foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) { if (ref($defprivs) eq 'ARRAY') { - if (grep/^\Q$priv\E$/,@{$defprivs}) { + if (grep(/^\Q$priv\E$/,@{$defprivs})) { push(@{$currprivs{$tool}},$priv); } } @@ -1992,13 +2533,13 @@ sub display_defprivs { sub change_members_form { - my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description, + my ($r,$cdom,$cnum,$action,$formname,$page,$groupname,$description, $startdate,$enddate,$tools,$fixedprivs,$functions,$users,$userdata, - $granularity,$specificity,$idx,$states,$navbuttons,$rowColor1, - $rowColor2) = @_; + $granularity,$quota,$specificity,$idx,$states,$navbuttons,$gpterm, + $ucgpterm) = @_; my %lt = &Apache::lonlocal::texthash( - grse => 'Group settings', - mogm => 'Modify group membership', + grse => "$ucgpterm settings", + mogm => "Modify $gpterm membership", ); my @regexps = ('user_','userpriv_'); $r->print(&Apache::lonhtmlcommon::echo_form_input( @@ -2013,44 +2554,34 @@ sub change_members_form { my $prevtext = $$navbuttons{'gtpp'}; $r->print('
    -
    '.&mt('Add?').''.&mt('Name').''.&mt('Username').' - '.&mt('Domain').'ID'.&mt('Add?').' + '.&mt('Name').' + '.&mt('Username').' + '.&mt('Domain').' + '.&mt('ID').' + '.&mt('Section').' '); if (@{$available} > 0) { - $r->print(''.$lt{'func'}.''.$lt{'func'}.'
     '.&mt('All:').' '); + $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').' +  '.&mt('All:').' '); foreach my $tool (@{$available}) { $r->print('   '); } - $r->print('
    - '. - $fullname.''.$uname.''. - $udom.''.$id.''.$fullname.''.$uname.''.$udom.''.$id.''.$section.''. + $r->print(''. '       '); foreach my $tool (@{$available}) { if ($granularity eq 'Yes') { @@ -1672,69 +2245,62 @@ sub pick_new_members { $tool.'" value="'.$user.'" />'.$tool.'   '); } } - $r->print('
      -'); if ($totalusers > 0) { $r->print($lt{'nnew'}.'

    '.$lt{'yoma'}); } else { $r->print($lt{'nome'}); } - $r->print(' -
      - '); + $r->print(&Apache::lonhtmlcommon::topic_bar($img,$lt{'uprv'})); if ((($action eq 'create') && (@{$available} > 0)) || - (($action eq 'modify') && ($formname eq 'change_settings'))) { + (($action eq 'modify') && ($formname eq 'change_settings'))) { my %specific = ( 'No' => 'checked="checked"', 'Yes' => '', @@ -1758,7 +2319,7 @@ sub privilege_specificity { if ($action eq 'create') { $r->print($lt{'frty'}.'
    '); if ($totaloptionalprivs) { - $r->print($lt{'thar'}); + $r->print($lt{'thar'}.'

    '.$lt{'plch'}); } else { $r->print($lt{'fort'}); } @@ -1774,23 +2335,16 @@ sub privilege_specificity { } if ($totaloptionalprivs) { $r->print(' -


    - -
     
     '.$lt{'plin'}); + $r->print($lt{'plin'}); if ($action eq 'create') { - $r->print(' '.$lt{'thwi'}); + $r->print('
    '.$lt{'thwi'}); } $r->print('
    '.$lt{'thes'}); if ($action eq 'create') { @@ -1799,30 +2353,22 @@ sub privilege_specificity { $r->print('('.&mt('if enabled below').').'); } $r->print('

    -
     '); +
    '); &check_uncheck_buttons($r,$formname,'defpriv',$lt{'oppr'}); $r->print('
    -
     
     
    '); } else { - $r->print('
     '.$lt{'algm'}.'

    '); + $r->print($lt{'algm'}.'

    '); } - &default_privileges($r,$action,$tabcol,$rowColor1,$rowColor2, - $tools,$toolprivs,$fixedprivs,$available); + &default_privileges($r,$action,$tools,$toolprivs,$fixedprivs, + $available,$functions); } else { if ($action eq 'create') { $r->print($lt{'asyo'}); + $r->print(''); } elsif ($action eq 'modify' && $formname eq 'pick_members') { my @defprivs; if (ref($$stored{'defpriv'}) eq 'ARRAY') { @@ -1835,98 +2381,93 @@ sub privilege_specificity { $r->print($lt{'sall'}); } $r->print(' '.$lt{'defp'}.'

    '); - &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools, - $toolprivs,\@defprivs); + &display_defprivs($r,$tools,$toolprivs,\@defprivs); } } - $r->print(' -
    - - - - - - - - - - -
    '.$lt{'func'}.'
    '.$lt{'fixp'}.'
    '.$lt{'oppr'}.'
    -
    ', @tableHeader)); + $r->print(&Apache::lonhtmlcommon::row_closure(1)); + my $fixed = ''; + my $dynamic = ''; foreach my $tool (@{$tools}) { - $r->print(' - - - - - '); my $privcount = 0; - my $fixed = ''; - my $dynamic = ''; + if ($dynamic ne '') { + $dynamic .= ' - '); + $dynamic .= '
    '.$tool.'
    '; + } + $dynamic .= ''; foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) { if (exists($$fixedprivs{$tool}{$priv})) { - $fixed .= ''.$$toolprivs{$tool}{$priv}.' '; + if ($fixed ne '') { + $fixed .= ' - '."\n"; + '."\n"; } - $dynamic .= ''."\n"; + $dynamic .= ''."\n"; } } - if ($dynamic eq '') { - $dynamic = ''."\n"; + if ($privcount == 0) { + $dynamic .= ''."\n"; } if ($privcount < 3) { - $dynamic .= ' - - '."\n"; + $dynamic .= ''."\n"; } elsif ($privcount%2) { $dynamic = ''."\n"; } - $r->print(' - - - '."\n".$dynamic.''."\n".'
    '; + } + $fixed .= '' + .''.&mt($$toolprivs{$tool}{$priv}).' '; if ($action eq 'modify') { - if (grep/^$tool$/,@{$available}) { + if (grep(/^$tool$/,@{$available})) { $fixed .= ''.&mt('(on)').' '; } else { $fixed .= ''.&mt('(off)').' '; } } + $fixed .= ''; } else { - $privcount ++; + $privcount++; if ($privcount == 3) { $dynamic .= '
    None'.&mt('None').'
       
    '.$fixed.'
    '."\n".'
    '; } - $r->print('
    '); - &topic_bar($r,$tabcol,1,$lt{'grse'}); - $r->print(' - - - '); - &topic_bar($r,$tabcol,2,$lt{'mogm'}); - $r->print(' - - - '); - &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext, - $$states{$action}[$page+1],$nexttext); - $r->print('
      -'); - &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2, - $functions,$startdate,$enddate,$groupname, - $description,$granularity,\@available,\@unavailable); -$r->print(' -
     
      -'); - ¤t_membership($r,$cdom,$cnum,$formname,$tabcol,$rowColor1, - $rowColor2,$groupname,\@available,\@unavailable, - $fixedprivs,$granularity,$specificity); - $r->print('
    '); + $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); + $r->print(&Apache::lonhtmlcommon::topic_bar(2,$lt{'mogm'})); + my $numcurrent = ¤t_membership($r,$cdom,$cnum,$formname,$groupname, + \@available,\@unavailable,$fixedprivs, + $granularity,$specificity); + if ($numcurrent > 0) { + &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext, + $$states{$action}[$page+1],$nexttext); + } else { + &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext); + } return; } sub current_membership { - my ($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,$rowColor2,$groupname, - $available,$unavailable,$fixedprivs,$granularity,$specificity) = @_; + my ($r,$cdom,$cnum,$formname,$groupname,$available,$unavailable, + $fixedprivs,$granularity,$specificity) = @_; my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum, $groupname); my %lt = &Apache::lonlocal::texthash( 'actn' => 'Action?', 'name' => 'Name', 'usnm' => 'Username', + 'stid' => 'ID', 'doma' => 'Domain', 'stda' => 'Start Date', 'enda' => 'End Date', @@ -2058,319 +2589,222 @@ sub current_membership { 'reen' => 'Re-enable', 'acti' => 'Activate', 'dele' => 'Delete', - 'curf' => 'Current Functionality', + 'curf' => 'Current Tool Set', 'chpr' => 'Change Privileges' ); - if (keys(%membership) > 0) { - my %current = (); - my %allnames = (); - my $hastools = 0; - my $addtools = 0; - my $num_reenable = 0; - my $num_activate = 0; - my $num_expire - 0; - foreach my $key (sort(keys(%membership))) { - if ($key =~ /^\Q$groupname\E:([^:]+):([^:]+)$/) { - my $uname = $1; - my $udom = $2; - my $user = $uname.':'.$udom; - my($end,$start,@userprivs) = split(/:/,$membership{$key}); - unless ($start == -1) { - $allnames{$udom}{$uname} = 1; - %{$current{$user}} = (); - $current{$user}{uname} = $uname; - $current{$user}{udom} = $udom; - $current{$user}{start} = - &Apache::lonlocal::locallocaltime($start); - if ($end == 0) { - $current{$user}{end} = 'No end date'; - } else { - $current{$user}{end} = - &Apache::lonlocal::locallocaltime($end); - } - my $now = time; - if (($end > 0) && ($end < $now)) { - $current{$user}{changestate} = 'reenable'; - $num_reenable++; - } elsif (($start > $now)) { - $current{$user}{changestate} = 'activate'; - $num_activate ++; - } else { - $current{$user}{changestate} = 'expire'; - $num_expire ++; - } - @{$current{$user}{currtools}} = (); - @{$current{$user}{newtools}} = (); - if (@userprivs > 0) { - foreach my $tool (sort(keys(%{$fixedprivs}))) { - foreach my $priv (keys(%{$$fixedprivs{$tool}})) { - if (grep/^$priv$/,@userprivs) { - push(@{$current{$user}{currtools}},$tool); - last; - } - } - } - $hastools = 1; - } - if (@{$available} > 0) { - if (@{$current{$user}{currtools}} > 0) { - if ("@{$available}" ne "@{$current{$user}{currtools}}") { - foreach my $tool (@{$available}) { - unless (grep/^$tool$/,@{$current{$user}{currtools}}) { - push(@{$current{$user}{newtools}},$tool); - } - } - } - } else { - @{$current{$user}{newtools}} = @{$available}; - } - if (@{$current{$user}{newtools}} > 0) { - $addtools = 1; - } - } - } - } - } - if (keys(%current) > 0) { - my %idhash; - foreach my $udom (keys(%allnames)) { - %{$idhash{$udom}} = &Apache::lonnet::idrget($udom, - keys(%{$allnames{$udom}})); - foreach my $uname (keys(%{$idhash{$udom}})) { - $current{$uname.':'.$udom}{'id'} = $idhash{$udom}{$uname}; - } - foreach my $uname (keys(%{$allnames{$udom}})) { - $current{$uname.':'.$udom}{'fullname'} = - &Apache::loncommon::plainname($uname,$udom, - 'lastname'); - } - } - $r->print(' - -   - + my ($current,$num_items,$hastools,$addtools) = + &Apache::longroup::group_memberlist($cdom,$cnum,$groupname,$fixedprivs, + $available); + my $numcurrent = scalar(keys(%{$current})); + if ($numcurrent > 0) { + $r->print(' '); - if ($num_expire) { - &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'}); - } - if ($num_reenable) { - &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'}); - } - if ($num_activate) { - &check_uncheck_buttons($r,$formname,'activate',$lt{'acti'}); + if ($num_items->{'active'}) { + &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'}); + } + if ($num_items->{'previous'}) { + &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'}); + } + if ($num_items->{'future'}) { + &check_uncheck_buttons($r,$formname,'activate',$lt{'acti'}); + } + &check_uncheck_buttons($r,$formname,'deletion',$lt{'dele'}); + if (@{$available} > 0) { + if ($specificity eq 'Yes') { + &check_uncheck_buttons($r,$formname,'changepriv',$lt{'chpr'}); } - &check_uncheck_buttons($r,$formname,'deletion',$lt{'dele'}); - if (@{$available} > 0) { - if ($specificity eq 'Yes') { - &check_uncheck_buttons($r,$formname,'changepriv',$lt{'chpr'}); - } - if ($granularity eq 'Yes') { - $r->print(&check_uncheck_tools($r,$available)); - $r->print(' + if ($granularity eq 'Yes') { + $r->print(&check_uncheck_tools($r,$available)); + $r->print(' '); - } } - $r->print(<<"END"); + } + $r->print(<<"END");
    - -
    '.$lt{'curf'}.' - +
    '.$lt{'curf'}.' +    -
    -
    +
    - -   - - -   - - -   - +
    END - $r->print(&Apache::lonhtmlcommon::start_pick_box()); - $r->print(<<"END"); - - - - - - - - - + $r->print(&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row()); + $r->print(<<"END"); + + + + + + + END - my $colspan = 0; - if ($hastools) { - $r->print(''); - $colspan ++; - } - if ($addtools) { - $r->print(''); - $colspan ++; - } - $r->print(''); - if ($colspan) { - if ($granularity eq 'Yes') { - $r->print(' + my $colspan = 0; + if ($hastools) { + $r->print(''); + $colspan++; + } + if ($addtools) { + $r->print(''); + $colspan++; + } + $r->print(&Apache::loncommon::end_data_table_header_row()); + if ($colspan) { + if ($granularity eq 'Yes') { + $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').' - '); + ' value="'.$tool.'" />'.''.$tool.'   '); } + $r->print(''); } - my %Sortby = (); - foreach my $user (sort(keys(%current))) { - if ($env{'form.sortby'} eq 'fullname') { - push(@{$Sortby{$current{$user}{fullname}}},$user); - } elsif ($env{'form.sortby'} eq 'username') { - push(@{$Sortby{$current{$user}{uname}}},$user); - } elsif ($env{'form.sortby'} eq 'domain') { - push(@{$Sortby{$current{$user}{udom}}},$user); - } elsif ($env{'form.sortby'} eq 'id') { - push(@{$Sortby{$current{$user}{id}}},$user); - } else { - push(@{$Sortby{$current{$user}{fullname}}},$user); - } + } + my %Sortby = (); + foreach my $user (sort(keys(%{$current}))) { + if ($env{'form.sortby'} eq 'fullname') { + push(@{$Sortby{$$current{$user}{fullname}}},$user); + } elsif ($env{'form.sortby'} eq 'username') { + push(@{$Sortby{$$current{$user}{uname}}},$user); + } elsif ($env{'form.sortby'} eq 'domain') { + push(@{$Sortby{$$current{$user}{udom}}},$user); + } elsif ($env{'form.sortby'} eq 'id') { + push(@{$Sortby{$$current{$user}{id}}},$user); + } else { + push(@{$Sortby{$$current{$user}{fullname}}},$user); } - my $rowNum = 0; - my $rowColor; - foreach my $key (sort(keys(%Sortby))) { - foreach my $user (@{$Sortby{$key}}) { - if ($rowNum %2 == 1) { - $rowColor = $rowColor1; - } else { - $rowColor = $rowColor2; - } - my $id = $current{$user}{id}; - my $fullname = $current{$user}{fullname}; - my $udom = $current{$user}{udom}; - my $uname = $current{$user}{uname}; - my $start = $current{$user}{start}; - my $end = $current{$user}{end}; - $r->print(' - - '); - if ($hastools) { - $r->print(''. + ''. + ''. + ''. + ''. + ''. + ''); + if ($hastools) { + $r->print(''); + } + $r->print('   '); } - if ($addtools) { - $r->print(''); + } + if ($addtools) { + $r->print(''); } - $r->print(''."\n"); - $rowNum ++; + $r->print(''); } + $r->print(&Apache::loncommon::end_data_table_row()."\n"); } - $r->print(&Apache::lonhtmlcommon::end_pick_box()); - $r->print(' - - '); } + $r->print(&Apache::loncommon::end_data_table()); + } else { + $r->print( + '

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

    '); } - return; + return $numcurrent; } sub check_uncheck_buttons { my ($r,$formname,$field,$title,$colspan) = @_; $r->print(' '); } sub change_privs_form { - my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate, - $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools, - $memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$rowColor1, - $rowColor2) = @_; + my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate, + $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools, + $memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$gpterm, + $ucgpterm) = @_; my @regexps = ('userpriv_'); my $nexttext; my %lt = &Apache::lonlocal::texthash( 'tode' => 'To be deleted', 'toex' => 'To be expired', - 'nome' => 'No members to be deleted or expired from the group.', + 'nome' => "No members to be deleted or expired from the $gpterm.", ); $r->print(&Apache::lonhtmlcommon::echo_form_input( ['origin','action','state','page','sortby'],\@regexps)); @@ -2379,43 +2813,40 @@ sub change_privs_form { } else { $nexttext = $$navbuttons{'mose'}; } - $r->print('
    $lt{'actn'}$lt{'name'}$lt{'usnm'} - $lt{'doma'}ID$lt{'stda'}$lt{'enda'}$lt{'actn'}$lt{'name'}$lt{'usnm'}$lt{'doma'}$lt{'ID'}$lt{'stda'}$lt{'enda'}'.$lt{'curf'}.'Additional Functionality
    '.$lt{'curf'}.''.&mt('Additional Tools').' '.&mt('All:'). + '.&mt('All:'). ' '); - foreach my $tool (@{$available}) { - $r->print('
    '); - if ($current{$user}{changestate} eq 'reenable') { - $r->print(''); + if ($$current{$user}{changestate} eq 'reenable') { + $r->print('
    '); - } elsif ($current{$user}{changestate} eq 'expire') { - $r->print('

    '); + } elsif ($$current{$user}{changestate} eq 'expire') { + $r->print('

    '); - } elsif ($current{$user}{changestate} eq 'activate') { - $r->print('
    '); + } elsif ($$current{$user}{changestate} eq 'activate') { + $r->print('

    '); - } - $r->print('
    '); + } + $r->print('
    '); - if ($specificity eq 'Yes') { - $r->print('
    '); + if ($specificity eq 'Yes') { + $r->print('
    '); - } - $r->print(' -
    '. - $fullname.''.$uname.''. - $udom.''.$id.''.$start. - ''.$end.''. + ''); + } + $r->print(' + '.$fullname.''.$uname.''. $udom.''.$id.''.$start.''.$end.''. '      '); - foreach my $tool (@{$current{$user}{currtools}}) { - if ($granularity eq 'Yes') { - $r->print(''); - if ($granularity eq 'Yes') { - foreach my $tool (@{$current{$user}{newtools}}) { - $r->print(''); + if ($granularity eq 'Yes') { + foreach my $tool (@{$$current{$user}{newtools}}) { + $r->print('   '); - } - } else { - foreach my $tool (@{$current{$user}{newtools}}) { - $r->print('   '); + } + } else { + foreach my $tool (@{$$current{$user}{newtools}}) { + $r->print(''.$tool. - '   '); - } + '   '); } - $r->print('
    -
    - '.$title.' - '.$title.' + +    - +
    -
    '); - &topic_bar($r,$tabcol,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) { - $r->print(''); + $r->print(''); $exp_or_del += @{$$memchg{'deletion'}}; } } if (ref($$memchg{'expire'}) eq 'ARRAY') { if (@{$$memchg{'expire'}} > 0) { - $r->print(''); + $r->print(''); $exp_or_del += @{$$memchg{'expire'}}; } } if (!$exp_or_del) { - $r->print(''); + $r->print('

    '.$lt{'nome'}.'

    '); } - &topic_bar($r,$tabcol,4,&mt('Group member privileges')); + $r->print(&Apache::lonhtmlcommon::topic_bar(4,&mt('Setting optional privileges for specific group members'))); - my $numchgs = &member_privileges_form($r,$tabcol,$action,$formname,$tools, + my $numchgs = &member_privileges_form($r,$action,$formname,$tools, $toolprivs,$fixedprivs,$userdata, $usertools,$idx,$memchg,$states, - $stored,$rowColor1,$rowColor2); - $r->print(''); + $stored,$gpterm); my $prevtext = $$navbuttons{'gtps'}; if ($numchgs || $exp_or_del) { &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext, @@ -2423,47 +2854,34 @@ sub change_privs_form { } else { &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext); } - $r->print('
     '.$lt{'tode'}.':
      '); + $r->print(''.$lt{'tode'}.':
        '); foreach my $user (@{$$memchg{'deletion'}}) { $r->print('
      • '.$$userdata{$user}[$$idx{fullname}]. ' ('.$user.')
      • '); } - $r->print('
     
     '.$lt{'toex'}.':
      '); + $r->print(''.$lt{'toex'}.':
        '); foreach my $user (@{$$memchg{'expire'}}) { $r->print('
      • '.$$userdata{$user}[$$idx{fullname}]. ' ('.$user.')
      • '); } - $r->print('
     
     '.$lt{'nome'}. - '
     
     
    '); return; } sub add_members_form { - my ($r,$tabcol,$action,$formname,$page,$startdate,$enddate,$groupname, - $description,$granularity,$sectioncount,$tools,$functions,$stored, - $states,$navbuttons,$rowColor1,$rowColor2) = @_; - $r->print('
    - - - - - - - - '); - - &membership_options($r,$action,$formname,$tabcol,$sectioncount,1); + &print_current_settings($r,$action,$functions,$startdate,$enddate, + $groupname,$description,$granularity,$quota, + \@available,\@unavailable,$gpterm,$ucgpterm); + &membership_options($r,$cdom,$cnum,$action,$formname,$sectioncount,1,$gpterm, + $ucgpterm,$crstype); my $nexttext = $$navbuttons{'gtns'}; my $prevtext = $$navbuttons{'gtpp'}; &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext, $$states{$action}[$page+1],$nexttext); - $r->print(' -
      -'); + my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,$groupname, + $description,$granularity,$quota,$sectioncount,$tools,$functions, + $stored,$states,$navbuttons,$gpterm,$ucgpterm,$crstype)=@_; + $r->print('
    '); my @available = (); my @unavailable = (); &check_tools($functions,$tools,\@available,\@unavailable); - &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2, - $functions,$startdate,$enddate,$groupname, - $description,$granularity,\@available,\@unavailable); - $r->print(' -
     
    '); return; } sub choose_privs_form { - my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate, - $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx, - $states,$stored,$sectioncount,$navbuttons,$rowColor1,$rowColor2) = @_; + my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate, + $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx, + $states,$stored,$sectioncount,$navbuttons,$gpterm,$ucgpterm, + $crstype) = @_; my @regexps = ('userpriv_'); my $nexttext; @@ -2480,27 +2898,22 @@ sub choose_privs_form { $nexttext = $$navbuttons{'adme'}; } - $r->print('
    '); - &topic_bar($r,$tabcol,6,&mt('Group member privileges')); + $r->print(&Apache::lonhtmlcommon::topic_bar(6,&mt('Setting optional privileges for specific group members'))); - &member_privileges_form($r,$tabcol,$action,$formname,$tools,$toolprivs, + &member_privileges_form($r,$action,$formname,$tools,$toolprivs, $fixedprivs,$userdata,$usertools,$idx,undef, - $states,$stored,$rowColor1,$rowColor2); + $states,$stored,$gpterm); - $r->print(''); if ($action eq 'create') { - if (keys(%{$sectioncount}) > 0) { - my $img1 = 7; - my $img2 = 8; - &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount, - $states,$stored,$navbuttons,$img1,$img2, - $rowColor1,$rowColor2); - } + my $img1 = 7; + my $img2 = 8; + &mapping_options($r,$action,$formname,$page,$sectioncount, + $states,$stored,$navbuttons,$img1,$img2, + $gpterm,$ucgpterm,$crstype,$cdom,$cnum); } my $prevtext = $$navbuttons{'gtps'}; &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext, $$states{$action}[$page+1],$nexttext); - $r->print('
     
    '); return; } @@ -2563,17 +2976,21 @@ function uncheckAllTools(formname) { } sub member_privileges_form { - my ($r,$tabcol,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata, - $usertools,$idx,$memchg,$states,$stored,$rowColor1,$rowColor2) = @_; + my ($r,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata, + $usertools,$idx,$memchg,$states,$stored,$gpterm) = @_; my %lt = &Apache::lonlocal::texthash( 'addp' => 'Additional privileges', - 'fixp' => 'Fixed privileges', + 'fixp' => 'Core privileges', 'oppr' => 'Optional privileges', - 'func' => 'Function', - 'forf' => 'For the functionality you have chosen to include '. - 'there are no optional privileges to set besides '. - 'the standard privileges.', - 'algr' => 'All group members will receive the same privileges.', + 'func' => 'Tool', + 'forf' => 'For the collaborative tools included for group '. + '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 '. + 'if access for future members is being activated now, '. + 'previously set privileges will be preserved.', 'asno' => 'As no group members are being added, '. 'there are no specific user privileges to set.', 'asng' => 'As no group tools will be made available to users, '. @@ -2581,7 +2998,7 @@ sub member_privileges_form { 'nogm' => 'No group member privileges to display or set, '. 'as you have not indicated that you will be activating,'. ' re-enabling, changing privileges, or adding/removing '. - 'functionality for any current members ', + 'tools for any current members.', 'full' => 'Fullname', 'user' => 'Username', 'doma' => 'Domain', @@ -2625,7 +3042,7 @@ sub member_privileges_form { } $numchgs = @currmembers; if (!$numchgs) { - $r->print(' '.$lt{'nogm'}); + $r->print($lt{'nogm'}); return $numchgs; } } @@ -2641,18 +3058,14 @@ sub member_privileges_form { my %total; if (keys(%{$usertools}) > 1) { $r->print(' - -   - - +
    '); foreach my $tool (@{$tools}) { if (@{$showboxes{$tool}} > 0) { $r->print(''); + $r->print('
    '); - $r->print(''); + $r->print('
    '.&mt($tool).''); + $r->print('
    '. - $tool.'
    '); my $privcount = 0; foreach my $priv (@{$showboxes{$tool}}) { $privcount ++; @@ -2666,15 +3079,16 @@ sub member_privileges_form { } else { $r->print(''); if ($privcount < @{$showboxes{$tool}}) { if (@{$showboxes{$tool}} > 2) { @@ -2686,66 +3100,53 @@ sub member_privileges_form { } } } - $r->print('
    '); } - $r->print(qq| -
    $$toolprivs{$tool}{$priv} - - -   - -

    |); + $r->print( + '
    '.&mt($$toolprivs{$tool}{$priv}).'' +.'' +.' ' +.' ' +.'' +.'

    ' + ); $r->print('
     
     '); } } - $r->print(''); - $r->print(' '); + $r->print(''); } - $r->print(' '); - $r->print(&Apache::lonhtmlcommon::start_pick_box()); + $r->print(&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row()); $r->print(<<"END"); - - $lt{'full'} - $lt{'user'} + $lt{'full'} + $lt{'user'} $lt{'doma'} $lt{'addp'} - END - &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2, - $usertools,$toolprivs,$fixedprivs, + $r->print(&Apache::loncommon::end_data_table_header_row()); + &member_privs_entries($r,$usertools,$toolprivs,$fixedprivs, $userdata,$idx,\@showtools,\@defprivs, \@excluded); - $r->print(''); - $r->print(&Apache::lonhtmlcommon::end_pick_box()); - $r->print(' - -   - -'); + $r->print(&Apache::loncommon::end_data_table()); } else { - $r->print(' '.$lt{'forf'}. - '
    '); - &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools, - $toolprivs,\@defprivs); + $r->print($lt{'forf'}.'
    '); + &display_defprivs($r,$tools,$toolprivs,\@defprivs); } } else { if (keys(%{$usertools}) > 0) { - $r->print(' '.$lt{'algr'}. - '

    '); - &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools, - $toolprivs,\@defprivs); + $r->print($lt{'algr'}.'
    '.$lt{'ifex'}.'

    '); + &display_defprivs($r,$tools,$toolprivs,\@defprivs); } else { - $r->print(' '.$lt{'asno'}. - '
    '); + $r->print($lt{'asno'}.'
    '); } } } else { - $r->print(' '.$lt{'asng'}); + $r->print($lt{'asng'}); } return $numchgs; } sub process_request { - my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$groupname,$description, + my ($r,$cdom,$cnum,$action,$state,$page,$groupname,$description, $specificity,$userdata,$startdate,$enddate,$tools,$functions,$toolprivs, $usertools,$idx,$types,$roles,$sections,$states,$navbuttons,$memchg, - $sectioncount,$stored,$rowColor1,$rowColor2) = @_; + $sectioncount,$stored,$gpterm,$ucgpterm,$crstype) = @_; $r->print(&Apache::lonhtmlcommon::echo_form_input( ['origin','action','state','page','sortby'])); - my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum); + my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm, + $ucgpterm,$crstype); if ($earlyout) { $r->print(' @@ -2791,13 +3192,15 @@ sub process_request { $description,$startdate,$enddate, $specificity,$functions,$tools, $sectioncount,$roles,$types,$sections, - \@defprivs,$stored); + \@defprivs,$stored,$gpterm,$ucgpterm, + $crstype); } if (($action eq 'create' && $outcome eq 'ok') || (($action eq 'modify') && (($state eq 'memresult') || ($state eq 'addresult')))) { &process_membership($r,$cdom,$cnum,$action,$state,$groupname,$tools, $enddate,$startdate,$userdata,$idx,$toolprivs, - $usertools,$specificity,\@defprivs,$memchg); + $usertools,$specificity,\@defprivs,$memchg,$gpterm, + $ucgpterm,$crstype); } return; } @@ -2805,7 +3208,7 @@ sub process_request { sub write_group_data { my ($r,$cdom,$cnum,$action,$state,$groupname,$description,$startdate, $enddate,$specificity,$functions,$tools,$sectioncount,$roles,$types, - $sections,$defprivs,$stored) = @_; + $sections,$defprivs,$stored,$gpterm,$ucgpterm,$crstype) = @_; my $now = time; my $creation = $now; my $creator = $env{'user.name'}.':'.$env{'user.domain'}; @@ -2813,12 +3216,36 @@ sub write_group_data { $creation = $$stored{'creation'}; $creator = $$stored{'creator'}; } - my $esc_description = &Apache::lonnet::escape($description); + my $esc_description = &escape($description); my @single_attributes = ('description','functions','startdate','enddate', 'creation','modified','creator','granularity', - 'specificity','autoadd','autodrop'); + 'specificity','autoadd','autodrop','quota'); my @mult_attributes = ('roles','types','sectionpick','defpriv'); + my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action, + $stored); + my $quota = $env{'form.quota'}; + + $quota =~ s/^\s*([^\s]*)\s*$/$1/; + if ($quota eq '') { + $quota = 0; + } + if ($quota !~ /^\d*\.?\d*$/) { + $quota = 0; + $r->print('
    ' + .&mt('The value you entered for the quota for the group portfolio in this '.$gpterm + .' contained invalid characters, so it has been set to 0 MB. You can change this by' + .' modifying the '.$gpterm.' settings.') + .'
    '); + } + if ($quota > $maxposs) { + $quota = $maxposs; + $r->print('
    ' + .&mt('The value you entered for the quota for the group portfolio in this '.$gpterm + .' exceeded the maximum possible value, so it has been set to [_1] MB ' + .'(the maximum possible value).',sprintf("%.2f",$maxposs)) + .'
    '); + } my %groupinfo = ( description => $esc_description, startdate => $startdate, @@ -2830,7 +3257,9 @@ sub write_group_data { specificity => $specificity, autoadd => $env{'form.autoadd'}, autodrop => $env{'form.autodrop'}, + quota => $quota, ); + foreach my $func (keys(%{$functions})) { my $status; if (grep(/^$func$/,@{$tools})) { @@ -2877,28 +3306,113 @@ sub write_group_data { if ($result eq 'ok') { if ($action eq 'create') { - my $put_result = &create_homepage($cdom,$cnum,$groupname, - \%groupinfo,$tools); - $r->print('Group '.$groupname.' was created.
    '); - } else { - $r->print('Group '.$groupname.' was updated.
    '); + my $result = &add_group_folder($cdom,$cnum,$now,$groupname,$action, + $description,$tools,\%groupinfo, + $gpterm,$ucgpterm,$crstype); + if ($result eq 'ok') { + my $msg = &Apache::lonhtmlcommon::confirm_success(&mt($ucgpterm.' [_1] was created.',''.$groupname.'')); + $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]:' + ,''.$groupname.'') + .'
    '.$result,1); + $msg = &Apache::loncommon::confirmwrapper($msg); + $r->print($msg); + } + } elsif ($action eq 'modify') { + my (@oldtools,@newtools); + if (ref($$stored{'tool'}) eq 'ARRAY') { + @oldtools = @{$$stored{'tool'}}; + } + if (ref($tools) eq 'ARRAY') { + @newtools = @{$tools}; + } + if (!grep(/^discussion$/,@oldtools) && + grep(/^discussion$/,@newtools)) { + my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/'; + my $boardsmap = $crspath.'group_boards_'.$groupname.'.sequence'; + my $navmap = Apache::lonnavmaps::navmap->new(); + 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('
    '. + &mt('Discussion Boards Folder created.') + .'
    '); + } + 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($outcome); + } + } + } else { + $error = &mt("An error occurred while retrieving the contents of the group's folder.").'
    '; + if ($crstype eq 'Community') { + $error .= &mt("You need to re-initialize the community."); + + } else { + $error .= &mt("You need to re-initialize the course."); + } + } + if ($error ne '') { + $r->print('
    '.$error.'
    '); + } + } + my $message = &Apache::lonhtmlcommon::confirm_success(&mt($ucgpterm.' [_1] was updated.',''.$groupname.'')); + $message = &Apache::loncommon::confirmwrapper($message); + $r->print($message); } } else { my %actiontype = ( 'create' => 'creating', 'modify' => 'modifying', ); - &Apache::lonnet::logthis('Failed to store group '.$groupname. - 'in course: '.$cnum.' in domain: '.$cdom); - $r->print(&mt('An error occurred when [_1] the new group. '. - 'Please try again.',$actiontype{$action})); + &Apache::lonnet::logthis("Failed to store $gpterm $groupname ". + 'in '.lc($crstype).': '.$cnum. + ' in domain: '.$cdom); + $r->print('

    ' + .&mt('An error occurred when '.$actiontype{$action}.' the '.$gpterm.'. ' + .'Please try again.') + .' 0) { - foreach my $priv (@{$defprivs}) { + if (grep/^\Q$priv\E$/,@{$defprivs}) { foreach my $user (sort(keys(%{$usertools}))) { if ($$usertools{$user}{$tool}) { $group_privs{$user} .= $priv.':'; @@ -2962,21 +3479,21 @@ sub process_membership { $groupname); foreach my $key (sort(keys(%membership))) { if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) { - (undef,undef,$curr_privs{$1})=split(/:/,$membership{$key},3); + ($curr_end{$1},$curr_start{$1},$curr_privs{$1}) = + split(/:/,$membership{$key},3); } } if (@expire + @deletion > 0) { foreach my $user (@expire) { - my ($currend,$currstart,$grp_privs) = - split(/:/,$membership{$groupname.':'.$user},3); - if ($currstart > $now) { - $currstart = $now; + my $savestart = $curr_start{$user}; + if ($savestart > $now) { + $savestart = $now; } - $usersettings{$groupname.':'.$user} = $now.':'.$currstart.':'. - $grp_privs; + $usersettings{$groupname.':'.$user} = $now.':'.$savestart.':'. + $curr_privs{$user}; if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname, - $user,$now,$currstart, - $grp_privs) eq 'ok') { + $user,$now,$savestart, + $curr_privs{$user},'',$context) eq 'ok') { push(@{$added{'expired'}},$user); $num_ok ++; } else { @@ -2987,7 +3504,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 ++; @@ -3007,22 +3524,33 @@ sub process_membership { my $start = $startdate; my $end = $enddate; if ($state eq 'memresult') { - if ($curr_privs{$user} eq $group_privs{$user}) { - push(@unchanged,$user); - next; - } - $type = 'modified'; if (@activate > 0) { if (grep/^$user$/,@activate) { $start = $now; + $end = $enddate; $type = 'activated'; } } if (@reenable > 0) { if (grep/^$user$/,@reenable) { - $type = 'reenabled'; + $start = $startdate; + $end = $enddate; + $type = 're-enabled'; } } + if ($type eq '') { + if ($curr_privs{$user} eq $group_privs{$user}) { + push(@unchanged,$user); + next; + } + if (exists($curr_start{$user})) { + $start = $curr_start{$user}; + } + if (exists($curr_end{$user})) { + $end = $curr_end{$user}; + } + $type = 'modified'; + } } else { $type = 'added'; } @@ -3030,7 +3558,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 { @@ -3041,12 +3569,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(':
    '); + $message .= &mt($tmsg.':').'
    '; foreach my $user (@{$added{$type}}) { my $privlist = ''; if (!($type eq 'deleted' || $type eq 'expired')) { @@ -3062,65 +3592,87 @@ sub process_membership { } $privlist =~ s/, $//; } - $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.$privlist.'
    '); + $message .= $$userdata{$user}[$$idx{fullname}].' - '.$user.$privlist.'
    '; } - $r->print('
    '); + $message .= '
    '; + $message = &Apache::lonhtmlcommon::confirm_success($message); + $msgall .= $message; } + $msgall = &Apache::loncommon::confirmwrapper($msgall); + $r->print($msgall); } if ($num_fail) { foreach my $type (sort(keys(%failed))) { - $r->print(&mt('The following users could not be [_1], because an error occurred:
    ',$type)); + $r->print('

    ' + .&mt("The following users could not be $type, because an error occurred:") + .'
    '); foreach my $user (@{$failed{$type}}) { $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'
    '); } } $r->print('
    '); } - if (@unchanged > 0) { - $r->print(&mt('No change occurred for the following users:
    ')); - foreach my $user (sort(@unchanged)) { - $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'
    '); - } - $r->print('
    '); - } +# Is that really needed? +# +# if (@unchanged > 0) { +# $r->print(&mt('No change occurred for the following users:').'
    '); +# foreach my $user (sort(@unchanged)) { +# $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'
    '); +# } +# $r->print('
    '); +# } if ($roster_result eq 'ok') { - $r->print('
    '.&mt('Group membership list updated.')); + $r->print('
    ' + .&mt($ucgpterm.' membership list updated.') + .'
    '); + $r->print('

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

    '); } else { - $r->print('
    '.&mt('An error occurred while updating the group membership list -').$roster_result.'
    '); + $r->print('
    ' + .&mt("An error occurred while updating the $gpterm membership list:") + .'
    '.$roster_result + .'
    '); } return; } sub mapping_options { - my ($r,$action,$formname,$page,$tabcol,$sectioncount,$states,$stored, - $navbuttons,$img1,$img2,$rowColor1,$rowColor2) = @_; + my ($r,$action,$formname,$page,$sectioncount,$states,$stored, + $navbuttons,$img1,$img2,$gpterm,$ucgpterm,$crstype,$cdom,$cnum) = @_; my %lt = &Apache::lonlocal::texthash( - 'auto' => 'Settings for automatic group enrollment', - 'gmma' => 'Group membership mapping to specific sections/roles', - 'endi' => 'Enable/disable automatic group enrollment for '. - 'users in specified roles and sections', - 'adds' => 'If automatic group enrollment is enabled, when a user is assigned a course-wide or section-specific role, he/she will automatically be added as a member of the group, with start and end access dates defined by the default dates set for the group, unless he/she is already a group member, with access dates that permit either current or future group access.', - 'drops' => "If automatic group disenrollment is enabled, when a user's role is expired, access to the group will be terminated unless the user continues to have other course-wide or section-specific active or future roles which receive automatic membership in the group.", - 'pirs' => 'Pick roles and sections for automatic group enrollment', - 'curr' => 'Currently set to', + 'auto' => "Settings for automatic $gpterm enrollment", + 'gmma' => "$ucgpterm membership mapping to specific sections/roles", + 'endi' => "Enable/disable automatic $gpterm enrollment for ". + "users in specified roles and sections", + '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", 'on' => 'on', 'off' => 'off', - 'auad' => 'Automatically enable group membership when roles are added?', - 'auex' => 'Automatically expire group membership when roles are removed?', - 'mapr' => 'Mapping of roles and sections affected by automatic group enrollment/disenrollment follows scheme chosen below.', + 'auad' => "Automatically enable $gpterm membership when roles are added?", + 'auex' => "Automatically expire $gpterm membership when roles are removed?", + 'mapr' => "Mapping of roles and sections affected by automatic $gpterm enrollment/disenrollment follows scheme chosen below.", ); - &automapping($r,$action,$tabcol,$stored,\%lt,$img1); - $r->print(' - - - '); - &mapping_settings($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,\%lt, - $stored,$img2); + &automapping($r,$action,$stored,\%lt,$img1); + &mapping_settings($r,$sectioncount,\%lt,$stored,$img2,$crstype,$cdom,$cnum, + $action); return; } sub automapping { - my ($r,$action,$tabcol,$stored,$lt,$image) = @_; + my ($r,$action,$stored,$lt,$image) = @_; my $add = 'off'; my $drop = 'off'; if (exists($$stored{'autoadd'})) { @@ -3129,178 +3681,141 @@ sub automapping { if (exists($$stored{'autodrop'})) { $drop = $$stored{'autodrop'}; } - &topic_bar($r,$tabcol,$image,$$lt{'endi'}); - $r->print(' - - - - - - - - - - - - - - - - - - - - - - -'); + $r->print('

    '.$$lt{'mapr'}); } sub mapping_settings { - my ($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,$lt,$stored,$image) = @_; + my ($r,$sectioncount,$lt,$stored,$image,$crstype,$cdom,$cnum,$action) = @_; my @sections = keys(%{$sectioncount}); if (@sections > 0) { @sections = sort {$a cmp $b} @sections; unshift(@sections,'none'); # Put 'no sections' next unshift(@sections,'all'); # Put 'all' at the front of the list + } else { + @sections = ('all','none'); } - &topic_bar($r,$tabcol,$image,$$lt{'pirs'}); - $r->print(' - - - '); if (@sections > 0) { - $r->print(''."\n"); + $r->print(''); } - my $rowNum = 0; - my $rowColor; + $r->print(&Apache::loncommon::end_data_table_header_row()."\n"); foreach my $role (@roles) { - my $plrole=&Apache::lonnet::plaintext($role); - my $sections_sel; - if (@sections > 0) { - if ($role eq 'cc') { - $sections_sel = ''; - } else { - $sections_sel=''; - } - } - if ($rowNum %2 == 1) { - $rowColor = $rowColor1; - } else { - $rowColor = $rowColor2; - } - $r->print(''.$sections_sel.''); - $rowNum ++; + my $roletitle=&Apache::lonnet::plaintext($role,$crstype); + $r->print(&print_autorole_item($role,$roletitle,\@sections)); } + my @customs; foreach my $role (sort(keys(%customroles))) { - my $sections_sel; - if (@sections > 0) { - $sections_sel = ''; - } - if ($rowNum %2 == 1) { - $rowColor = $rowColor1; - } else { - $rowColor = $rowColor2; - } - $r->print(''. - $sections_sel.''); - $rowNum ++; + my ($roletitle) = ($role =~ m|^cr/[^/]+/[^/]+/(.+)$|); + push (@customs,$role); + $r->print(&print_autorole_item($role,$roletitle,\@sections)); } - $r->print(&Apache::lonhtmlcommon::end_pick_box()); + if ($action eq 'modify') { + foreach my $role (@{$$stored{'autorole'}}) { + if ((!grep(/^\Q$role\E$/,@customs)) && + (!grep(/^\Q$role\E$/,@roles))) { + my $roletitle; + if ($role =~ /^cr/) { + ($roletitle) = ($role =~ m|_([^_]+)$|); + } else { + $roletitle = &Apache::lonnet::plaintext($role,$crstype); + } + $r->print(&print_autorole_item($role,$roletitle,\@sections)); + } + } + } + $r->print(&Apache::loncommon::end_data_table()); return; } -sub standard_roles { - my @roles = ('cc','in','ta','ep','st'); - return @roles; -} - -sub my_custom_roles { - my %returnhash=(); - my %rolehash=&Apache::lonnet::dump('roles'); - foreach (keys %rolehash) { - if ($_=~/^rolesdef\_(\w+)$/) { - $returnhash{$1}=$1; +sub print_autorole_item { + my ($role,$roletitle,$sections) = @_; + my $sections_sel; + if (@{$sections} > 0) { + if (($role eq 'cc') || ($role eq 'co')) { + $sections_sel = ''; + } else { + $sections_sel=''; } } - return %returnhash; + my $output = &Apache::loncommon::start_data_table_row(). + ''.$sections_sel. + &Apache::loncommon::end_data_table_row(); + return $output; +} + +sub standard_roles { + 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) = @_; + my ($r,$groupname,$page,$gpterm) = @_; my @menu = - ( - { text => 'Modify default group 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 group', + { linktext => "Add member(s) to the $gpterm", + url => '/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state=add_members&branch=adds', + icon => 'grp_add.png', + alttext => "Add member(s) to the $gpterm", + permission => '1', help => 'Course_Group_Add_Members', - state => 'add_members', - branch => 'adds', - }, - ); - my $menu_html = ''; - foreach my $menu_item (@menu) { - $menu_html .= - '

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

    '.$/; - } - $r->print($menu_html); + }]} + ); + $r->print(&Apache::lonhtmlcommon::generate_menu(@menu)); return; } sub member_privs_entries { - my ($r,$tabcol,$rowColor1,$rowColor2,$usertools,$toolprivs, - $fixedprivs,$userdata,$idx,$showtools,$defprivs,$excluded) = @_; - my $rowColor; - my $rowNum = 0; + my ($r,$usertools,$toolprivs,$fixedprivs,$userdata,$idx,$showtools, + $defprivs,$excluded) = @_; foreach my $user (sort(keys(%{$usertools}))) { if (defined($excluded)) { if (ref($excluded) eq 'ARRAY') { @@ -3310,19 +3825,27 @@ sub member_privs_entries { } } my ($uname,$udom) = split(/:/,$user); - if ($rowNum %2 == 1) { - $rowColor = $rowColor1; - } else { - $rowColor = $rowColor2; - } - $r->print(' + $r->print(&Apache::loncommon::start_data_table_row().' - '); + '); foreach my $tool (@{$showtools}) { if (exists($$usertools{$user}{$tool})) { - $r->print(''); } else { - $r->print(''); + $r->print(''); } } - $rowNum ++; + $r->print(&Apache::loncommon::end_data_table_row()); } } @@ -3369,40 +3892,282 @@ sub date_setting_table { 'startdate',$starttime); my $endform = &Apache::lonhtmlcommon::date_setter($formname, 'enddate',$endtime); - my $perpetual = ''; - my $start_table = ''; - $start_table .= "
     
      - '.$$lt{'gmma'}.':
    '.$$lt{'adds'}.'
    '.$$lt{'drops'}.'
    -
     
      - '.$$lt{'auad'}.':  - '); + $r->print(&Apache::lonhtmlcommon::topic_bar($image,$$lt{'endi'}).' + '.$$lt{'gmma'}.':
    '.$$lt{'adds'}.'
    '.$$lt{'drops'}.'

    + '.$$lt{'auad'}.':  + '); if ($action eq 'modify') { - $r->print('    ('.$$lt{'curr'}.' '.$$lt{$add}.')'); + $r->print('    ('.&mt('Currently set to [_1].',''.$$lt{$add}.'').')'); } $r->print(' -
    -
      - '.$$lt{'auex'}.':  - '); +
    + '.$$lt{'auex'}.':  + '); if ($action eq 'modify') { - $r->print('    ('.$$lt{'curr'}.' '.$$lt{$drop}.')'); + $r->print('    ('.&mt('Currently set to [_1].',''.$$lt{$drop}.'').')'); } - $r->print('
    -
     
     '.$$lt{'mapr'}.' -
      -'); - my @roles = &standard_roles(); - my %customroles = &my_custom_roles(); - $r->print(&Apache::lonhtmlcommon::start_pick_box()); + $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()); $r->print(' -
    '.&mt('Active?').' '.&mt('Role').''.&mt('Sections').'
    '.&mt('Sections').''. - &mt('all sections').''. - §ions_selection(\@sections,'sec_'.$role). - '
    '.$plrole. - '
    '.§ions_selection(\@sections,'sec_'.$role). - '
    '.$role.'
    '. + &mt('all sections').''. + §ions_selection($sections,'sec_'.$role). + ''. + ''.$roletitle.'
    '.$$userdata{$user}[$$idx{fullname}].' '.$uname.' '.$udom.'
    Function
    Fixed
    Optional
    + + + + + + + + + + +
    '. + &mt('Collaborative Tool').'
    '.&mt('Fixed').'
    '.&mt('Optional').'
    +
    '); + $r->print(''); + $r->print(''.$dynamic.'
    '.$tool.'
    '); my $privcount = 0; my $fixed = ''; my $dynamic = ''; @@ -3334,21 +3857,21 @@ sub member_privs_entries { if ($privcount == 3) { $dynamic .= ''; } - $dynamic .=''; + ''; } } - $r->print(''.$dynamic.'
    '.$tool.'
    '.$fixed.'
    '.$fixed.'
    '.$tool.'
     
     
    '.$tool.'
     
     
    \n"; - $start_table .= ''. - ''. - ''."\n"; - $start_table .= "
    Default starting date for - member access'.$startform.' 
    "; - my $end_table = ''; - $end_table .= "\n"; - $end_table .= ''. - ''. - ''."\n"; - $end_table .= "
    Default ending date for - member access'.$endform.''.$perpetual.'
    \n"; - return ($start_table, $end_table); + my $perpetual = ' '; + 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; +} + +sub add_group_folder { + my ($cdom,$cnum,$now,$groupname,$action,$description,$tools,$groupinfo, + $gpterm,$ucgpterm,$crstype) = @_; + if ($cdom eq '' || $cnum eq '') { + my $error = ''; + if ($crstype eq 'Community') { + $error .= &mt("Error: invalid community domain or number - group folder creation failed."); + } else { + $error .= &mt("Error: invalid course domain or number - group folder creation failed."); + } + $error .= ''; + return $error; + } + my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage,$warning); + my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/'; + $allgrpsmap = $crspath.'group_allfolders.sequence'; + if ($action eq 'create') { + 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 = '' + .&mt('Non-standard course - folder for all groups not added.') + .''; + } + if ($outcome ne 'ok') { + my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders'); + if ($delresult ne 'ok') { + $warning = $delresult; + } + return $outcome.$warning; + } + } + my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders'); + if ($delresult ne 'ok') { + $warning = $delresult ; + } + } else { + $outcome = '' + .&mt('Could not obtain exclusive lock to check status of the folder for all groups. No group folder added.') + .''; + return $outcome; + } + my $grpfolder = &mt($ucgpterm.' Folder - [_1]',$description); + $grppage='/adm/'.$cdom.'/'.$cnum.'/'.$groupname.'/smppg'; + 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.$warning; + } + my $pageout = &create_homepage($cdom,$cnum,$groupname,$groupinfo, + $tools,$gpterm,$ucgpterm,$now); + # Link to folder for bulletin boards + $grpmap = $crspath.'group_folder_'.$groupname.'.sequence'; + if (grep/^discussion$/,@{$tools}) { + $disctitle = &mt('Discussion Boards'); + my $outcome = &map_updater($cdom,$cnum,'group_boards_'.$groupname. + '.sequence','bbseq',$disctitle,$grpmap); + if ($outcome ne 'ok') { + return $outcome.$warning; + } + $boardsmap = $crspath.'group_boards_'.$groupname.'.sequence'; + } + } else { + #modify group folder if status of discussions tools is changed + } + my ($furl,$ferr)= &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $warning .= ''; + if ($crstype eq 'Community') { + $warning .= &mt("Error retrieving community contents"). + ' '.&mt("You need to re-initialize the community."); + } else { + $warning .= &mt("Error retrieving course contents"). + ' '.&mt("You need to re-initialize the course."); + } + $warning .= ''; + return $warning; + } + # modify parameters + my $parm_result; + if ($action eq 'create') { + if ($grpmap) { + $parm_result .= &parm_setter($navmap,$cdom,$grpmap,$groupname); + } + if ($grppage) { + $parm_result .= &parm_setter($navmap,$cdom,$grppage,$groupname); + } + if ($boardsmap) { + $parm_result .= &parm_setter($navmap,$cdom,$boardsmap,$groupname); + } + } + undef($navmap); + if ($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 ('
    ' + .&mt('Warning: failed to release lock for folder: [_1].',''.$folder_name.'') + .'
    ' + ); + } else { + return 'ok'; + } +} + +sub map_updater { + my ($cdom,$cnum,$newfile,$itemname,$itemtitle,$parentmap,$startsrc, + $starttitle,$endsrc,$endtitle) = @_; + my $outcome; + $env{'form.'.$itemname} = &new_map($startsrc,$starttitle,$endsrc, + $endtitle); + my $newmapurl=&Apache::lonnet::finishuserfileupload($cnum,$cdom,$itemname, + $newfile); + if ($newmapurl !~ m|^/uploaded|) { + $outcome = '
    ' + .&mt('Error uploading new folder.')." ($newfile): $newmapurl" + .'
    '; + return $outcome; + } + my ($errtext,$fatal)=&LONCAPA::map::mapread($parentmap); + if ($fatal) { + $outcome = '
    ' + .&mt('Error reading contents of parent folder.')." ($parentmap): $errtext" + .'
    '; + 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,1); + if ($errtext) { + $outcome = '
    ' + .&mt('Error saving updated parent folder.')." ($parentmap): $errtext" + .'
    '; + return $outcome; + } + } + return 'ok'; +} + +sub new_map { + my ($startsrc,$starttitle,$endsrc,$endtitle) = @_; + my $newmapstr = ' + + + + + +'; + return $newmapstr; +} + +sub parm_setter { + 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 '
    '.$allresults.'
    '; + } + my %hide_settings = ( + 'course' => { + 'num' => 13, + 'set' => 'yes', + }, + 'group' => { + 'num' => 5, + 'set' => 'no', + 'extra' => $groupname, + }, + ); + my $res = $navmap->getResourceByUrl($url); + 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; + } + } + } else { + $allresults = '
    '; + if ($crstype eq 'Community') { + $allresults .= &mt("Parameters not set for [_1] because the resource was not recognized as part of the community.",''.$url.''); + } else { + $allresults .= &mt('Parameters not set for [_1] because the resource was not recognized as part of the course.',''.$url.''); + } + $allresults .= '
    '; + } + return $allresults; } sub create_homepage { - my ($cdom,$cnum,$name,$groupinfo,$tools) = @_; + my ($cdom,$cnum,$name,$groupinfo,$tools,$gpterm,$ucgpterm,$now) = @_; my $functionality = join(',',@{$tools}); - my $content = &Apache::lonnet::unescape($$groupinfo{description}); - $content=~s/\s+$//s; - $content=~s/^\s+//s; - $content=~s/\$//s; - $content=&Apache::lonfeedback::clear_out_html($content,1); + my $content = &unescape($$groupinfo{description}); + chomp($content); + my $gateway = Apache::lonhtmlgateway->new(); + $content = $gateway->process_incoming_html($content,1); my %pageinfo = ( - 'aaa_title' => 'Group: '.$name, + 'aaa_title' => "$ucgpterm: $name", 'abb_links' => $functionality, 'bbb_content' => $content, 'ccc_webreferences' => '', - 'uploaded.lastmodified' => time, + 'uploaded.lastmodified' => $now, ); my $putresult = &Apache::lonnet::put('grppage_'.$name,\%pageinfo,$cdom,$cnum); return $putresult; @@ -3444,72 +4209,56 @@ function toggleTools(field,caller) { } sub validate_groupname { - my ($groupname,$action,$cdom,$cnum) = @_; + 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::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 group name', - tgne => 'The group name entered ', - grna => 'Group names and section names used in a course '. - 'must be unique.', - isno => 'is not a valid name.', - gnmo => 'Group names may only contain letters, numbers '. - 'or underscores.', - cnnb => 'can not be used as it is the name of ', - inth => ' in this course.', - thgr => '- does not correspond to the name of an existing'. - ' group ', + igna => "Invalid $gpterm name", + grna => "$ucgpterm names and section names used in a ". + "$crstype must be unique.", + gnmo => "$ucgpterm names may only contain letters, ". + "numbers or underscores.", ); - my $exitmsg = ''.$lt{'igna'}.'

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

    '; + my $nameshown = &Apache::loncommon::cleanup_html($groupname); if (($groupname eq '') || ($groupname =~ /\W/)) { - $earlyout = $exitmsg.$lt{'isno'}.'
    '.$lt{'gnmo'}; - return $earlyout; + return $exitmsg. + &mt("The $gpterm name entered '[_1]' is not a valid name.",$nameshown). + '
    '.$lt{'gnmo'}; + } elsif ($groupname eq 'syllabus') { + return $exitmsg. + &mt("The $gpterm name entered '[_1]' is reserved for use by LON-CAPA.",$nameshown); } if (exists($sectioncount{$groupname})) { - return $exitmsg.$lt{'cnnb'}.&mt('a section').$lt{'inth'}. - '
    '.$lt{'grna'}; - } - if ($action eq 'create' - && exists($curr_groups{$groupname})) { - - return $exitmsg.$lt{'cnnb'}.&mt('an existing group'). - $lt{'inth'}.'
    '.$lt{'grna'}; - + return $exitmsg. + &mt("The $gpterm name entered '[_1]' can not be used as it is the name of a section in this $crstype.",$nameshown). + '
    '.$lt{'grna'}; + } + if ($action eq 'create') { + if (exists($curr_groups{$groupname})) { + return $exitmsg. + &mt("The $gpterm name entered '[_1]' can not be used as it is the name of an existing $gpterm in this $crstype.",$nameshown). + '
    '.$lt{'grna'}; + } elsif (exists($deleted_groups{$groupname})) { + return $exitmsg. + &mt("The $gpterm name entered '[_1]' can not be used as it is the name of a $gpterm which previously existed in this $crstype.",$nameshown). + '
    '.$lt{'grna'}; + } } elsif ($action eq 'modify') { unless(exists($curr_groups{$groupname})) { - $earlyout = &mt('Group name:').' '.$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,$tabcol,$imgnum,$title) = @_; - $r->print(' - -   - - -   - - - '.$title.' - -   - - -   - -'); - return; -} - sub check_changes { my ($member_changes,$memchg) = @_; my %exclusions; @@ -3549,3 +4298,4 @@ sub check_changes { } 1; +