File:  [LON-CAPA] / loncom / interface / loncoursegroups.pm
Revision 1.3: download - view: text, annotated - select for diffs
Tue Nov 15 22:03:05 2005 UTC (18 years, 6 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
Course groups. Work still in progress. Creation of group, addition of members, assignment of member privileges etc.

    1: #
    2: # Copyright Michigan State University Board of Trustees
    3: #
    4: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    5: #
    6: # LON-CAPA is free software; you can redistribute it and/or modify
    7: # it under the terms of the GNU General Public License as published by
    8: # the Free Software Foundation; either version 2 of the License, or
    9: # (at your option) any later version.
   10: #
   11: # LON-CAPA is distributed in the hope that it will be useful,
   12: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   13: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14: # GNU General Public License for more details.
   15: #
   16: # You should have received a copy of the GNU General Public License
   17: # along with LON-CAPA; if not, write to the Free Software
   18: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19: #
   20: # /home/httpd/html/adm/gpl.txt
   21: #
   22: # http://www.lon-capa.org/
   23: #
   24: 
   25: package Apache::loncoursegroups;
   26: 
   27: use strict;
   28: use Apache::lonnet;
   29: use Apache::loncommon;
   30: use Apache::lonhtmlcommon;
   31: use Apache::lonlocal;
   32: use Apache::lonnavmaps;
   33: use Apache::Constants qw(:common :http);
   34: 
   35: sub handler {
   36:     my ($r) = @_;
   37: 
   38:     &Apache::loncommon::content_type($r,'text/html');
   39:     $r->send_http_header;
   40:                                                                                 
   41:     if ($r->header_only) {
   42:         return OK;
   43:     }
   44: 
   45:     #  Needs to be in a course
   46:     if (! ($env{'request.course.fn'})) {
   47:         # Not in a course
   48:         $env{'user.error.msg'}=
   49:      "/adm/coursegroups:mdg:0:0:Cannot edit or view course groups";
   50:         return HTTP_NOT_ACCEPTABLE;
   51:     }
   52: 
   53:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
   54:                                             ['action','refpage']);
   55:                                                                                       
   56:     my $function = &Apache::loncommon::get_users_function();
   57:     my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');
   58:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
   59:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
   60: 
   61:     my $view_permission =
   62:           &Apache::lonnet::allowed('vcg',$env{'request.course.id'});
   63:     my $manage_permission =
   64:           &Apache::lonnet::allowed('mdg',$env{'request.course.id'});
   65: 
   66:     &Apache::lonhtmlcommon::clear_breadcrumbs();
   67: 
   68:     my %functions = (
   69:                       email => 'E-mail',
   70:                       discussion => 'Discussion boards',
   71:                       chat => 'Chat',
   72:                       files => 'File repository',
   73:                       roster => 'Membership roster',
   74:                       homepage => 'Group home page',
   75:                     );
   76: 
   77:     my %idx = ();
   78:     $idx{id} = &Apache::loncoursedata::CL_ID();
   79:     $idx{fullname} = &Apache::loncoursedata::CL_FULLNAME();
   80:     $idx{udom} = &Apache::loncoursedata::CL_SDOM();
   81:     $idx{uname} = &Apache::loncoursedata::CL_SNAME();
   82: 
   83:     my $action = $env{'form.action'};
   84:     if ($action eq 'create' || $action eq 'modify' || $action eq 'view') { 
   85:         if ($view_permission || $manage_permission) {
   86:             &group_administration($r,$action,$cdom,$cnum,$function,$tabcol,
   87:                         \%functions,\%idx,$view_permission,$manage_permission);
   88:         } else {
   89:             $r->print('You do not have group administration '.
   90:                       'privileges in this course');
   91:         }
   92:     } else {
   93:         &print_main_menu($r,$cdom,$cnum,$function,$tabcol,\%functions,\%idx,
   94:                                           $view_permission,$manage_permission);
   95:     }
   96:     return OK;
   97: }
   98: 
   99: sub print_main_menu {
  100:     my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission,
  101:                                                           $manage_permission)
  102:                                                                           = @_;
  103:     $r->print(&header('Course Groups',&mt('LON-CAPA Course Groups'),
  104:                                                  undef,undef,undef,$function));
  105:     &Apache::lonhtmlcommon::add_breadcrumb
  106:         ({href=>"/adm/coursegroups",
  107:           text=>"Course Groups",});
  108:     $r->print(&Apache::lonhtmlcommon::breadcrumbs
  109:                 (undef,'Course Groups'));
  110:     &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
  111:                                           $view_permission,$manage_permission);
  112:     $r->print(&footer());
  113:     return;
  114: }
  115: 
  116: sub display_groups {
  117:     my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission,
  118:                                                           $manage_permission) = @_;
  119:     my %curr_groups = ();
  120:     my %grp_info = ();
  121:     my $rowColor1 = "#dddddd";
  122:     my $rowColor2 = "#eeeeee";
  123: 
  124:     $r->print('<br /><br />');
  125:     if ($view_permission) {
  126:         if (&Apache::lonnet::get_coursegroups($cdom,$cnum,\%curr_groups) > 0) {
  127:             $r->print(&Apache::lonhtmlcommon::start_pick_box());
  128:             if (keys(%curr_groups) > 0) {
  129:                 $r->print(<<"END");
  130:       <table border="0" cellpadding="4" cellspacing="1">
  131:        <tr bgcolor="$tabcol" align="center">
  132:         <td><b>Action</b></td>
  133:         <td><b><a href="javascript:changeSort('groupname')">Group Name</a></b></td>
  134:         <td><b><a href="javascript:changeSort('description')">Description</a></b></td>
  135:         <td><b><a href="javascript:changeSort('creator')">Creator</a></b>
  136:         </td>
  137:         <td><b><a href="javascript:changeSort('creation')">Created</a></b>
  138:         </td>
  139:         <td><b><a href="javascript:changeSort('modified')">Last Modified</a></b>
  140:         </td>
  141:         <td><b>Functionality</b>
  142:         </td>
  143:         <td><b><a href="javascript:changeSort('quota')">Quota (Mb)</a></b></td>
  144:         <td><b><a href="javascript:changeSort('totalmembers)">Members</a></b></td>
  145:         <td><b><a href="javascript:changeSort('totalfiles')">Files</a></b></td>
  146:         <td><b><a href="javascript:changeSort('boards')">Discussion boards</a></b></td>
  147:         <td><b><a href="javascript:changeSort('diskuse')">Disk use</a></b></td>
  148:        </tr>
  149: END
  150:                 my %Sortby = ();
  151:                 foreach my $group (sort(keys(%curr_groups))) {
  152:                     %{$grp_info{$group}} = 
  153:                                       &Apache::loncommon::get_group_settings(
  154:                                                          $curr_groups{$group});
  155:                     my $members_result = &group_members($group,\%grp_info);
  156:                     my $files_result = &group_files($group,\%grp_info); 
  157:                     if ($env{'form.sortby'} eq 'groupname') {
  158:                         push(@{$Sortby{$group}},$group);
  159:                     } elsif ($env{'form.sortby'} eq 'description') {
  160:                         push(@{$Sortby{$grp_info{$group}{'description'}}},
  161:                                                                      $group);
  162:                     } elsif ($env{'form.sortby'} eq 'creator') {
  163:                         push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);
  164:                     } elsif ($env{'form.sortby'} eq 'creation') {
  165:                         push(@{$Sortby{$grp_info{$group}{'creation'}}},$group);
  166:                     } elsif ($env{'form.sortby'} eq 'modified') {
  167:                         push(@{$Sortby{$grp_info{$group}{'modified'}}},$group);
  168:                     } elsif ($env{'form.sortby'} eq 'quota') {
  169:                         push(@{$Sortby{$grp_info{$group}{'quota'}}},$group);
  170:                     } elsif ($env{'form.sortby'} eq 'totalmembers') {
  171:                         push(@{$Sortby{$grp_info{$group}{'totalmembers'}}},
  172:                                                                        $group);
  173:                     } elsif ($env{'form.sortby'} eq 'totalfiles') {
  174:                         push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},
  175:                                                                        $group);
  176:                     } elsif ($env{'form.sortby'} eq 'boards') {
  177:                         push(@{$Sortby{$grp_info{$group}{'boards'}}},$group);
  178:                     } elsif ($env{'form.sortby'} eq 'diskuse') {
  179:                         push(@{$Sortby{$grp_info{$group}{'diskuse'}}},$group);
  180:                     } else {
  181:                         push(@{$Sortby{$group}},$group);
  182:                     }
  183:                 }
  184:                 my $rowNum = 0;
  185:                 my $rowColor;
  186:                 foreach my $key (sort(keys(%Sortby))) {
  187:                     foreach my $group (@{$Sortby{$key}}) {
  188:                         if ($rowNum %2 == 1) {
  189:                             $rowColor = $rowColor1;
  190:                         } else {
  191:                             $rowColor = $rowColor2;
  192:                         }
  193:                         my $description = 
  194:                    &Apache::lonnet::unescape($grp_info{$group}{'description'});
  195:                         my $creator = $grp_info{$group}{'creator'};
  196:                         my $creation = $grp_info{$group}{'creation'};
  197:                         my $modified = $grp_info{$group}{'modified'}; 
  198:                         my $quota = $grp_info{$group}{'quota'};
  199:                         my $totalmembers = $grp_info{$group}{'totalmembers'};
  200:                         my $totalfiles = $grp_info{$group}{'totalfiles'};
  201:                         my $boards = $grp_info{$group}{'boards'};
  202:                         my $diskuse = $grp_info{$group}{'diskuse'};
  203:                         my $functionality;
  204:                         foreach my $tool (sort keys(%{$functions})) {
  205:                             if (defined($grp_info{$group}{functions}{$tool})) {
  206:                                 $functionality .= ' '.$tool;
  207:                             }
  208:                         }
  209:                         if (!$functionality) {
  210:                             $functionality = 'None available';
  211:                         }
  212:                         $r->print('<tr bgcolor="'.$rowColor.'"><td align="right">
  213:    <a href="/adm/entergroup?group='.$group.'"/>View</a>&nbsp;<a href="/adm/coursegroups?action=modify&group='.$group.'">Modify</a></td><td><small>'.$group.'</small></td><td><small>'.$description.'</small></td><td><small>'.$creator.'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($creation).'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($modified).'</small></td><td><small>'.$functionality.'</small></td><td><small>'.$quota.'</small></td><td><small>'.$totalmembers.'</small></td><td><small>'.$totalfiles.'</small></td><td><small>'.$boards.'</small></td><td><small>'.$diskuse.'</small></td></tr>');
  214:                         $rowNum ++;
  215:                     }
  216:                 }
  217:                 $r->print('</table>');
  218:                 $r->print(&Apache::lonhtmlcommon::end_pick_box());
  219:             }               
  220:         } else {
  221:             $r->print('No groups exist');
  222:         }
  223:     } else {
  224:         $r->print('You do not have sufficient privileges to allow you to display course groups');
  225:     }
  226:     return;
  227: }
  228: 
  229: sub group_administration {
  230:     my ($r,$action,$cdom,$cnum,$function,$tabcol,$functions,$idx,
  231:                                      $view_permission,$manage_permission) = @_;
  232:     my %sectioncount = ();
  233:     my @tools = ();
  234:     my @types = ();
  235:     my @roles = ();
  236:     my @sections = ();
  237:     my %users = ();
  238:     my %userdata = ();
  239:     my @members = ();
  240:     my %usertools = ();
  241: 
  242:     my $state = $env{'form.state'};
  243:     my ($groupname,$description,$startdate,$enddate);
  244: 
  245:     if ($action eq 'create') {
  246:         if ($state eq '') {
  247:             $state = 'pick_name';
  248:         } else {
  249:             ($startdate,$enddate) = &get_dates_from_form();
  250:             if (defined($env{'form.groupname'})) {
  251:                 $groupname = $env{'form.groupname'};
  252:             }
  253:             if (defined($env{'form.description'})) {
  254:                 $description = $env{'form.description'};
  255:             }
  256:             if (defined($env{'form.tool'})) {
  257:                 @tools=&Apache::loncommon::get_env_multiple('form.tool');
  258:             }
  259:             if (defined($env{'form.member'})) {
  260:                 @members = &Apache::loncommon::get_env_multiple('form.member');
  261:                 foreach my $user (@members) {
  262:                     %{$usertools{$user}} = ();
  263:                 }
  264:             }
  265:         }
  266:     }
  267: 
  268:     my %toolprivs = ();
  269:     %{$toolprivs{'email'}} = (
  270:                                  sgm => 'Send group mail',
  271:                                  sgb => 'Broadcast mail',
  272:                              );
  273:     %{$toolprivs{'discussion'}} =  (
  274:                                      cgb => 'Create boards',
  275:                                      pgd => 'Post',
  276:                                      pag => 'Anon. posts',
  277:                                      rgi => 'Get identities', 
  278:                                      vgb => 'View boards',
  279:                                    );
  280:     %{$toolprivs{'chat'}} =  (
  281:                                 pgc => 'Chat',
  282:                              );
  283:     %{$toolprivs{'files'}} =  (
  284:                                  rgf => 'Retrieve',
  285:                                  ugf => 'Upload',
  286:                                  dgf => 'Delete',
  287:                               );
  288:     %{$toolprivs{'roster'}} = (
  289:                                  vgm => 'View',
  290:                               );
  291:     %{$toolprivs{'homepage'}} = (
  292:                                 vgh => 'View page',
  293:                                 mgh => 'Modify page',
  294:                               );
  295:     my %fixedprivs = ();
  296:     %{$fixedprivs{'email'}} = ('sgm' => 1);
  297:     %{$fixedprivs{'discussion'}} = ('vgb' => 1);
  298:     %{$fixedprivs{'chat'}} = ('pgc' => 1);
  299:     %{$fixedprivs{'files'}} = ('rgf' => 1);
  300:     %{$fixedprivs{'roster'}} = ('vgm' => 1);
  301:     %{$fixedprivs{'homepage'}} = ('vgh' => 1);
  302: 
  303:     my %elements = ();
  304:     %{$elements{'create'}} = ();
  305:     %{$elements{'modify'}} = ();
  306:     %{$elements{'create'}{'pick_name'}} = (
  307:         startdate_month => 'selectbox',
  308:         startdate_hour => 'selectbox',
  309:         enddate_month => 'selectbox',
  310:         enddate_hour => 'selectbox',
  311:         types => 'selectbox',
  312:         roles => 'selectbox',
  313:         startdate_day => 'text',
  314:         startdate_year => 'text',
  315:         startdate_minute => 'text',
  316:         startdate_second => 'text',
  317:         enddate_day => 'text',
  318:         enddate_year => 'text',
  319:         enddate_minute => 'text',
  320:         enddate_second => 'text',
  321:         groupname => 'text',
  322:         description => 'text',
  323:         tool => 'checkbox',
  324:         granularity => 'radio',
  325:         no_end_date => 'checkbox',
  326:     );
  327:     %{$elements{'create'}{'pick_members'}} = (
  328:         member => 'checkbox',
  329:     );
  330:     if (($action eq 'create') && ($state eq 'pick_name')) {
  331:         my $numsections = &Apache::loncommon::get_sections($cdom,$cnum,
  332:                            \%sectioncount);
  333:         if ($numsections > 0) {
  334:             $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';
  335:         }
  336:     }
  337:                                                                                       
  338:     if (($action eq 'create') && (($state eq 'pick_members') ||
  339:                                   ($state eq 'pick_privs'))) {
  340:         if (defined($env{'form.types'})) {
  341:             @types=&Apache::loncommon::get_env_multiple('form.types');
  342:         }
  343:         if (defined($env{'form.roles'})) {
  344:             @roles=&Apache::loncommon::get_env_multiple('form.roles');
  345:         }
  346:         if (defined($env{'form.sectionpick'})) {
  347:             @sections=&Apache::loncommon::get_env_multiple('form.sectionpick');
  348:             if (grep/^_all$/,@sections) {
  349:                 @sections = sort {$a cmp $b} keys(%sectioncount);
  350:             }
  351:         }
  352:         &build_members_list($cdom,$cnum,\@types,\@roles,
  353:                         \@sections,\%users,\%userdata);
  354:         if ((keys(%users) > 0) && (@tools > 0)) {
  355:             foreach my $tool (@tools) {
  356:                 if ($env{'form.granularity'} eq 'Yes') {
  357:                     $elements{'create'}{'pick_members'}{'user_'.$tool} = 'checkbox';
  358:                 }
  359:             }
  360:             $elements{'create'}{'pick_members'}{'specificity'} = 'radio';
  361:         }
  362:     }
  363: 
  364:     if (($action eq 'create') && (($state eq 'pick_privs') || (($state eq 'result') &&
  365:          ($env{'form.specificity'} eq 'No')))) {
  366:         foreach my $tool (@tools) {
  367:             my @values = &Apache::loncommon::get_env_multiple('form.user_'.$tool);
  368:             foreach my $user (@values) {
  369:                 unless(exists($usertools{$user}{$tool})) {
  370:                     $usertools{$user}{$tool} = 1;
  371:                 }
  372:             }
  373:         }
  374:         if (($state eq 'pick_privs') && ($env{'form.specificity'} eq 'Yes')) {
  375:             foreach my $member (@members) {
  376:                 foreach my $tool (keys(%{$usertools{$member}})) {
  377:                     foreach my $priv (keys(%{$toolprivs{$tool}})) {
  378:                         unless (exists($fixedprivs{$tool}{$priv})) {
  379:                             $elements{'create'}{'pick_privs'}{'userpriv_'.$priv} =
  380:                                                                    'checkbox';
  381:                         }
  382:                     }
  383:                 }
  384:             }
  385:         }
  386:     }
  387:  
  388:     my $jscript;
  389:     if ($env{'form.action'} eq 'create') {
  390:         $jscript = &Apache::loncommon::check_uncheck_jscript();
  391:     }
  392:     $jscript .= qq|
  393: function nextPage(formname,nextstate) {
  394:     formname.state.value= nextstate;
  395:     formname.submit();
  396: }
  397: function backPage(formname,prevstate) {
  398:     formname.state.value = prevstate;
  399:     formname.submit();
  400: }
  401:                                                                                       
  402: |;
  403:                                                                                       
  404:     $jscript .= &Apache::lonhtmlcommon::set_form_elements(
  405:                            \%{$elements{$action}{$state}});
  406: 
  407: 
  408:     my $loaditems =  &onload_action($action,$state);
  409:     $r->print(&header('Course Groups Manager',&mt('LON-CAPA Groups Manager'),
  410:                                $jscript,$action,$state,$function,$loaditems));
  411: 
  412:     if ($env{'form.refpage'} eq 'enrl') {
  413:         &Apache::lonhtmlcommon::add_breadcrumb
  414:         ({href=>"/adm/dropadd",
  415:           text=>"Enrollment Manager",
  416:           faq=>9,bug=>'Instructor Interface',});
  417:     } else {
  418:         &Apache::lonhtmlcommon::add_breadcrumb
  419:        ({href=>"/adm/coursegroups",
  420:           text=>"Course Groups",
  421:           faq=>9,bug=>'Instructor Interface',});
  422:     }
  423: 
  424:     my %states = ();
  425:     @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');
  426:     @{$states{'modify'}} = ();
  427:                                                                                       
  428:     my %trail = ();
  429:     %{$trail{'create'}} = (
  430:                             pick_name => 'Group Settings',
  431:                             pick_members => 'Select Members',
  432:                             pick_privs => 'Choose Privileges',
  433:                             result => 'Creation Complete',
  434:                           );
  435:     %{$trail{'modify'}} = ();
  436:                                                                                       
  437:     if ((($action eq 'create') || ($action eq 'modify')) &&
  438:               ($manage_permission)) {
  439:         for (my $i=0; $i<@{$states{$action}}; $i++) {
  440:             if ($state eq $states{$action}[$i]) {
  441:                 &Apache::lonhtmlcommon::add_breadcrumb(
  442:                    {text=>"$trail{$action}{$state}"});
  443:                 $r->print(&Apache::lonhtmlcommon::breadcrumbs
  444:                      (undef,'Course Groups Manager'));
  445:                 &display_control($r,$cdom,$cnum,$tabcol,$action,$state,
  446:                          \%sectioncount,$groupname,$description,$functions,
  447:                          \@tools,\%toolprivs,\%fixedprivs,$startdate,$enddate,
  448:                          \%users,\%userdata,$idx,\@members,\%usertools);
  449:                 last;
  450:             } else {
  451:                 if ($state eq 'result' && $i > 0) {
  452:                     &Apache::lonhtmlcommon::add_breadcrumb(
  453:     {href=>"javascript:backPage(document.$state,'$states{$action}[0]')",
  454:       text=>"$trail{$action}{$states{$action}[$i]}"});
  455:                 } else { 
  456:                     &Apache::lonhtmlcommon::add_breadcrumb(
  457:      {href=>"javascript:backPage(document.$state,'$states{$action}[$i]')",
  458:       text=>"$trail{$action}{$states{$action}[$i]}"});
  459:                 }
  460:             }
  461:         }
  462:     } elsif (($action eq 'view') && ($view_permission)) {
  463:                         &Apache::lonhtmlcommon::add_breadcrumb(
  464:                    {text=>"View groups"});
  465:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
  466:                      (undef,'Course Groups Manager'));
  467:         &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
  468:                                         $view_permission,$manage_permission);
  469: 
  470:     }
  471:     $r->print(&footer());
  472:     return;
  473: }
  474: 
  475: sub display_control {
  476:     my ($r,$cdom,$cnum,$tabcol,$action,$state,$sectioncount,$groupname,
  477:         $description,$functions,$tools,$toolprivs,$fixedprivs,$startdate,
  478:                       $enddate,$users,$userdata,$idx,$members,$usertools) = @_;
  479:     if ($action eq 'create') {
  480:         if ($state eq 'pick_name') {
  481:             &first_creation_form($r,$cdom,$cnum,$tabcol,$state,$functions,
  482:                                                                 $sectioncount);
  483:         } elsif ($state eq 'pick_members') {
  484:             &second_creation_form($r,$cdom,$cnum,$tabcol,$state,$groupname,
  485:                                   $description,$startdate,$enddate,$tools,
  486:                                              $functions,$users,$userdata,$idx);
  487:         } elsif ($state eq 'pick_privs') {
  488:             &third_creation_form($r,$cdom,$cnum,$tabcol,$state,$startdate,
  489:                            $enddate,$tools,$functions,$toolprivs,$fixedprivs,
  490:                                            $userdata,$members,$usertools,$idx);
  491:         } elsif ($state eq 'result') {
  492:             &completed_creation($r,$cdom,$cnum,$tabcol,$state,$groupname,
  493:                             $description,$userdata,$startdate,$enddate,$tools,
  494:                                $functions,$toolprivs,$members,$usertools,$idx);
  495:         }
  496:     }
  497: }
  498: 
  499: sub header {
  500:     my ($bodytitle,$title,$jscript,$action,$state,$function,$loaditems) = @_;
  501:     my $html=&Apache::lonxml::xmlbegin();
  502:     my $bodytag=&Apache::loncommon::bodytag($bodytitle,$function,$loaditems);
  503:     my $output = <<"END";
  504: $html
  505: <head>
  506: <title>$title</title>
  507: <script type="text/javascript">
  508: $jscript
  509: </script>
  510: </head>
  511: $bodytag
  512: <form method="post" name="$state">
  513: 
  514: END
  515:     if ($action eq 'create' || $action eq 'modify') {
  516:         $output .= <<"END";
  517:  <input type="hidden" name="action" value="$action" />
  518:  <input type="hidden" name="state" value="" />
  519:  <input type="hidden" name="origin" value="$state" />
  520: END
  521:     }
  522:     return $output;
  523: }
  524: 
  525: sub onload_action {
  526:     my ($action,$state) = @_;
  527:     my $loaditems;
  528:     if ((defined($env{'form.origin'})) && ($action eq 'create') &&
  529:                 ($state eq 'pick_name' || $state eq 'pick_members' || 
  530:                  $state eq 'pick_privs')) {
  531:         unless ($env{'form.origin'} eq '') {
  532:             $loaditems = 
  533:              'onload="javascript:setFormElements(document.'.$state.')"';
  534:         }
  535:     }
  536:     return $loaditems;
  537: }
  538: 
  539: sub footer {
  540:        return(<<ENDFOOT);
  541:   </form>
  542:  </body>
  543: </html>
  544: ENDFOOT
  545: }
  546: 
  547: sub build_members_list {
  548:     my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata) = @_;
  549:     my %access = ();
  550:     foreach my $role (@{$roles}) {
  551:         %{$$users{$role}} = ();
  552:     }
  553:     foreach my $type (@{$types}) {
  554:         $access{$type} = $type;
  555:     }
  556:     &Apache::loncommon::get_course_users($cdom,$cnum,\%access,$roles,
  557:                                           $sections,$users,$userdata);
  558:     return;
  559: }
  560: 
  561: sub group_files {
  562:     return;
  563: }
  564: 
  565: sub group_members {
  566:     return;
  567: }
  568: 
  569: 
  570: sub first_creation_form {
  571:     my ($r,$cdom,$cnum,$tabcol,$formname,$functions,$sectioncount) = @_;
  572:     my %lt = &Apache::lonlocal::texthash(
  573:         'gmem' => 'Group membership options',
  574:         'picr' => 'Pick the criteria to use to build a list of course users '.
  575:                   'from which you will select members of the new group',   
  576:         'gdat' => 'Group open and close dates',
  577:         'sten' => 'Set a start date/time and end date/time for the group',
  578:         'acty' => 'Access types',
  579:         'coro' => 'Course roles',
  580:         'cose' => 'Course sections',
  581:         'gfun' => 'Group functionality',
  582:     );
  583: 
  584:     my %status_types = (
  585:                    active => &mt('Currently has access'),
  586:                    previous => &mt('Previously had access'),
  587:                    future => &mt('Will have future access'),
  588:                    );
  589: 
  590:     my @roles = ('st','cc','in','ta','ep','cr');
  591: 
  592:     my $starttime = time;
  593:     my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
  594:     my ($start_table,$end_table) = &date_setting_table
  595:                                     ($starttime,$endtime,$formname);
  596: 
  597:     my @sections = ();
  598:     my $section_sel = '';
  599:     my $numvisible = 4;
  600: 
  601:     @sections = sort {$a cmp $b} keys(%{$sectioncount});
  602:     if (@sections > 0) {
  603:         unshift(@sections,'_all'); # Put 'all' at the front of the list
  604:         if (@sections < 4) {
  605:             $numvisible = @sections;
  606:         }
  607:         foreach (@sections) {
  608:             if ($_ eq '_all') {
  609:                 $section_sel .= '  <option value="'.$_.'" />all sections'."\n";
  610:             } else {
  611:                 $section_sel .= '  <option value="'.$_.'" />'.$_."\n";
  612:             }
  613:         }
  614:     }
  615: 
  616:     $r->print(<<"END");
  617:  <br />
  618:  <table width="100%" cellpadding="0" cellspacing="0" border="0">
  619:    <tr bgcolor="$tabcol">
  620:      <td>&nbsp;</td>
  621:      <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step1.gif" 
  622:          valign="bottom">&nbsp;&nbsp;</nobr>
  623:      </td>
  624:      <td align="left"><nobr>
  625:        <font face="arial,helvetica,sans-serif"><b>Group name, description
  626:          and available functionality</b></font></nobr> 
  627:      </td>
  628:      <td width="100%">&nbsp;</td>
  629:    </tr>
  630:    <tr>
  631:     <td colspan="4">&nbsp;</td>
  632:    </tr>
  633:    <tr>
  634:     <td>&nbsp;</td>
  635:     <td colspan="3">
  636:      <table border="0" cellpadding="2" cellspacing="2">
  637:       <tr>
  638:        <td><b>Group Name:</b></td>
  639:        <td colspan="5"><input type="text" name="groupname" size="25" />
  640:        </td>
  641:       <tr>
  642:       <tr>
  643:        <td><b>Description:</b></td>
  644:        <td colspan="5"><input type="text" name="description" size="40" />
  645:        </td>
  646:       <tr>
  647:       <tr>
  648:        <td><b>Functionality:</b></td>
  649: END
  650:     my $numitems = keys(%{$functions});
  651:     my $halfnum = int($numitems/2);
  652:     my $remnum = $numitems%2;
  653:     if ($remnum) {
  654:         $halfnum ++;
  655:     }
  656:     my @allfunctions = sort (keys (%{$functions}));
  657:     for (my $i=0; $i<$halfnum; $i++) {
  658:         $r->print('<td><input type="checkbox" name="tool" value="'.
  659:                   $allfunctions[$i].'" />&nbsp;'.
  660:                    $$functions{$allfunctions[$i]}.'</td>
  661:                    <td>&nbsp;</td><td>&nbsp;</td>');
  662:     }
  663:     $r->print('<td><input type="button" value="check all" '.
  664:               'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'.
  665:               '</td></tr><tr><td>&nbsp;</td>');
  666:     for (my $j=$halfnum; $j<@allfunctions; $j++) {
  667:         $r->print('<td><input type="checkbox" name="tool" value="'.
  668:                   $allfunctions[$j].'" />&nbsp;'.
  669:                   $$functions{$allfunctions[$j]}.'</td>
  670:                   <td>&nbsp;</td><td>&nbsp;</td>');
  671:     }
  672:     if ($remnum) {
  673:         $r->print('<td>&nbsp;</td>');
  674:     }
  675:     $r->print(<<"END"); 
  676:        <td>
  677:         <input type="button" value="uncheck all" 
  678:           onclick="javascript:uncheckAll(document.$formname.tool)" />
  679:        </td>
  680:       </tr>
  681:       <tr>
  682:        <td><b>Granularity:</b></td>
  683:        <td colspan="9">Do you want to assign different functionality to different group members?&nbsp;<input type="radio" name="granularity" value="Yes" />Yes&nbsp;<input type="radio" name="granularity" value="No" checked="checked" />No</td>
  684:       </tr> 
  685:      </table>
  686:     </td>
  687:    </tr>
  688:    <tr>
  689:     <td colspan="4">&nbsp;</td>
  690:    </tr>
  691:    <tr bgcolor="$tabcol">
  692:     <td>&nbsp;</td>
  693:     <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step2.gif" 
  694:         valign="bottom">&nbsp;&nbsp;</nobr>
  695:     </td>
  696:     <td align="left"><nobr>
  697:       <font face="arial,helvetica,sans-serif"><b>Start and end dates for group
  698:                                                   access</b></font></nobr>
  699:     </td>
  700:     <td width="100%">&nbsp;</td>
  701:    </tr>
  702:    <tr>
  703:     <td colspan="4">&nbsp;</td>
  704:    </tr>
  705:    <tr>
  706:     <td>&nbsp;</td>
  707:     <td colspan="3">$start_table</td>
  708:    <tr>
  709:    <tr>
  710:     <td colspan="4">&nbsp;</td>
  711:    </tr>
  712:    <tr>
  713:     <td>&nbsp;</td>
  714:     <td colspan="3">$end_table</td>
  715:    <tr>
  716:    <tr>
  717:     <td colspan="4">&nbsp;</td>
  718:    </tr>
  719:    <tr bgcolor="$tabcol">
  720:     <td>&nbsp;</td>
  721:     <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step3.gif" 
  722:         valign="bottom">&nbsp;&nbsp;</nobr>
  723:     </td>
  724:     <td align="left"><nobr>
  725:      <font face="arial,helvetica,sans-serif"><b>Pick parameters to generate 
  726:          membership list</b></nobr>
  727:      </font>
  728:     </td>
  729:     <td width="100%">&nbsp;</td>
  730:    </tr>
  731:    <tr>
  732:     <td colspan="4">&nbsp;</td>
  733:    </tr>
  734:    <tr>
  735:     <td>&nbsp;</td>
  736:     <td colspan="3">
  737:      <b>$lt{'gmem'}</b><br/> $lt{'picr'}
  738:      <br /><br />
  739:      <table border="0">
  740:       <tr>
  741:        <td><b>$lt{'acty'}</b></td>
  742:        <td>&nbsp;</td>
  743:        <td><b>$lt{'coro'}</b></td>
  744: END
  745:     if (@sections >0) {
  746:          $r->print('
  747:        <td>&nbsp;</td>
  748:        <td><b>'.$lt{'cose'}.'</b></td>
  749:        <td>&nbsp;</td>');
  750:     }
  751:     $r->print('</tr><tr>');
  752:     $r->print(&Apache::lonhtmlcommon::status_select_row(\%status_types));
  753:     $r->print('<td>&nbsp;</td>');
  754:     $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles));
  755:     if (@sections > 0) {
  756:         $r->print('
  757:        <td>&nbsp;</td>
  758:        <td colspan="3" align="center" valign="top">
  759:         <select name="sectionpick" multiple="true" size="'.$numvisible.'">
  760:           '.$section_sel.'
  761:         </select>
  762:        </td>');
  763:     }
  764:     $r->print('
  765:       </tr>
  766:      </table>
  767:     </td>
  768:    </tr>
  769:    <tr>
  770:     <td colspan="4">&nbsp;</td>
  771:    </tr>
  772:    <tr>
  773:     <td>&nbsp;</td>
  774:     <td colspan="3" align="left">
  775:      <input type="button" value="Go to next step"  
  776:      onclick="javascript:nextPage(document.'.$formname.','."'pick_members'".')>
  777:     </td>
  778:    </tr>
  779: </table>
  780: ');
  781:     return;
  782: }
  783: 
  784: sub second_creation_form {
  785:     my ($r,$cdom,$cnum,$tabcol,$formname,$groupname,$description,$startdate,
  786:                         $enddate,$tools,$functions,$users,$userdata,$idx) = @_;
  787:     my @regexps = ('user_','userpriv_');
  788:     $r->print(&Apache::lonhtmlcommon::echo_form_input(
  789:                 ['origin','action','state','member','specificity'],\@regexps));
  790:     my %sectioncount = ();
  791:     my $numsec = &Apache::loncommon::get_sections($cdom,$cnum,\%sectioncount);
  792:     my %curr_groups = ();
  793:     my $numgroups = &Apache::lonnet::get_coursegroups($cdom,$cnum,\%curr_groups);
  794:     my $earlyout = '';
  795:     my $exitmsg = '<b>Invalid group name</b><br /><br />The group name entered "'.
  796:                   $groupname.'" ';
  797:     my $dupmsg = 'Group names and section names used in a course must be unique.'; 
  798:     if ($groupname =~ /\W/) {
  799:         $earlyout = $exitmsg.'is not a valid name.<br />Group names may only contain letters, numbers or underscores';
  800:     }
  801:     if ($numsec) {
  802:         if (exists($sectioncount{$groupname})) {
  803:             $earlyout = $exitmsg.'can not be used as it is the name of a section 
  804:                                                 in this course.<br />'.$dupmsg;
  805:         }
  806:     }
  807:     if ($numgroups) {
  808:         if (exists($curr_groups{$groupname})) {
  809:             $earlyout = $exitmsg.'can not be used as it is the name of an 
  810:                                  existing group in this course.<br />'.$dupmsg;
  811:         }
  812:     }
  813:     if ($earlyout) {
  814:         $r->print('<table border="0" cellpadding="2" cellspacing="2">
  815:  <tr>
  816:   <td>&nbsp;</td>
  817:   <td>'.$earlyout.'</td>
  818:  </tr>
  819:  <tr>
  820:   <td colspan="2">&nbsp;</td>
  821:  </tr>
  822:  <tr>
  823:   <td>&nbsp;</td>
  824:   <td align="left">
  825:    <input type="button" name="previous" value = "Go to previous page"
  826:     onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>
  827:   </td>
  828:  </tr>
  829: </table>
  830:         ');
  831:         return;
  832:     }
  833:     my $rowColor1 = "#dddddd";
  834:     my $rowColor2 = "#eeeeee";
  835:     my $showstart = &Apache::lonlocal::locallocaltime($startdate);
  836:     my $showend = &Apache::lonlocal::locallocaltime($enddate);
  837:     $r->print('<table border="0" cellpadding="0" cellspacing="20">
  838: <tr>
  839:  <td><font face="arial,helvetica,sans-serif"><b>New group selections</b></font>
  840: <br />When you create the new group, the following settings will apply:
  841:  </td>
  842: </tr>
  843: <tr>
  844:  <td>');
  845:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
  846:     $r->print('
  847: <table cellspacing="1" cellpadding="4">
  848:  <tr bgcolor="'.$tabcol.'" align="center">
  849:   <td><b>Group Name</b></td>
  850:   <td><b>Description</b></td>
  851:   <td><b>Group Functionality</b></td>
  852:   <td><b>Default access dates</b></td>
  853:  </tr>
  854:  <tr bgcolor="'.$rowColor2.'">
  855:   <td valign="top"><small>'.$groupname.'</small></td>
  856:   <td valign="top"><small>'.$description.'</small></td>
  857:   <td>
  858: ');
  859:     my @available = ();
  860:     my @unavailable = ();
  861:     foreach my $item (sort(keys(%{$functions}))) {
  862:         if (grep/^$item$/,@{$tools}) {
  863:             push(@available,$item);
  864:         } else {
  865:             push(@unavailable,$item);
  866:         }
  867:     }
  868:     if (@available > 0) {
  869:         $r->print('<small><b>Available:</b></small>
  870:                     <table cellpadding="" cellspacing="1"><tr>');
  871:         my $rowcell = int(@available/2) + @available%2;
  872:         for (my $i=0; $i<@available; $i++) {
  873:             if (@available > 3) {
  874:                 if ($i==$rowcell) {
  875:                     $r->print('</tr><tr>');
  876:                 }
  877:             }
  878:             $r->print('<td><small>'.$$functions{$available[$i]}.
  879:                                           '</small></td><td>&nbsp;</td>');
  880:         }
  881:         if ((@available > 3) && (@available%2)) {
  882:             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
  883:         }
  884:         $r->print('</tr></table><br />');
  885:     }
  886:     if (@unavailable > 0) {
  887:         $r->print('<small><b>Unavailable:</b></small>
  888:                     <table cellpadding="0" cellspacing="1"  border="0"><tr>');
  889:         my $rowcell = int(@unavailable/2) + @unavailable%2;
  890:         for (my $j=0; $j<@unavailable; $j++) {
  891:             if (@unavailable > 3) {
  892:                 if ($j==$rowcell) {
  893:                     $r->print('</tr><tr>');
  894:                 }
  895:             }
  896:             $r->print('<td><small>'.$$functions{$unavailable[$j]}.
  897:                                               '</small></td><td>&nbsp;</td>');
  898:         }
  899:         if ((@unavailable > 3) && (@unavailable%2)) {
  900:             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
  901:         }
  902:         $r->print('</tr></table>');
  903:     }
  904:     $r->print(<<"END");
  905:   </td>
  906:   <td valign="top"><small><b>Start date:</b> $showstart<br />
  907:       <b>End date:</b> $showend</small>
  908:   </td>
  909:  </tr>
  910: </table>
  911: END
  912:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
  913:     my %members = ();
  914:     foreach my $role (keys(%{$users})) {
  915:         foreach my $user (keys(%{$$users{$role}})) {
  916:             unless (defined($members{$user})) {
  917:                 @{$members{$user}} = @{$$userdata{$user}};
  918:             }
  919:         }
  920:     }
  921:     $r->print('</td></tr></table><br />');
  922:     if (keys(%members) > 0) {
  923:         if ($env{'form.granularity'} eq 'Yes') {
  924:             $r->print('
  925: <script type="text/javascript">
  926: function checkAllTools(formname) {
  927: ');
  928:             foreach my $tool (@available) {
  929:                 $r->print('  checkAll(formname.user_'.$tool.');'."\n");
  930:             }
  931:             $r->print('
  932: }
  933: function uncheckAllTools(formname) {
  934: ');
  935:             foreach my $tool (@available) {
  936:                 $r->print('  uncheckAll(formname.user_'.$tool.');'."\n");
  937:             }
  938:             $r->print('
  939: }
  940: </script>
  941:             ');
  942:        }
  943:        $r->print(<<"END");
  944: <table width="100%" cellpadding="0" cellspacing="0" border="0">
  945:  <tr bgcolor="$tabcol">
  946:   <td>&nbsp;</td>
  947:   <td valign="top" align="left">
  948:    <nobr><img src="/res/adm/pages/bl_step4.gif" valign="middle">&nbsp;</nobr>
  949:   </td>
  950:   <td alin="left">
  951:    <nobr>
  952:    <font face="arial,helvetica,sans-serif">
  953:     <b>Select group members</b>
  954:    </font></nobr>
  955:   </td>
  956:   <td width="100%">&nbsp;</td>
  957:  </tr>
  958:  <tr>
  959:   <td colspan="4">&nbsp;</td>
  960:  </tr>
  961:  <tr>
  962:   <td>&nbsp;</td>
  963:   <td colspan="2">
  964:     <table>
  965:      <tr>
  966:       <td>
  967:    <nobr>
  968:     <fieldset><legend><b>Add members</b></legend>
  969:      <input type="button" value="check all" 
  970:        onclick="javascript:checkAll(document.$formname.member)" />
  971:       &nbsp;&nbsp;
  972:      <input type="button" value="uncheck all" 
  973:       onclick="javascript:uncheckAll(document.$formname.member)" />
  974:     </fieldset></nobr></td>
  975: END
  976:         if (@available > 0 && $env{'form.granularity'} eq 'Yes') {
  977:             $r->print('<td><nobr><fieldset><legend><b> 
  978:                                       Set functionality</b></legend>
  979:      <input type="button" value="check all" 
  980:        onclick="javascript:checkAllTools(document.'.$formname.')" />
  981:        &nbsp;&nbsp;
  982:      <input type="button" value="uncheck all" 
  983:         onclick="javascript:uncheckAllTools(document.'.$formname.')" />
  984:     </fieldset></nobr></td>');
  985:         }
  986:         $r->print('</tr></table>
  987:   </td>
  988:   <td width="100%">&nbsp;</td>
  989:  </tr>
  990:  <tr>
  991:   <td colspan="4">&nbsp;</td>
  992:  </tr>
  993:  <tr>
  994:   <td>&nbsp;</td>
  995:   <td colspan="3">
  996:         ');
  997:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
  998:         $r->print(<<"END");
  999:    <table border="0" cellpadding="4" cellspacing="1">
 1000:     <tr bgcolor="$tabcol" align="center">
 1001:      <td><b>Add?</b></td>
 1002:      <td><b><a href="javascript:changeSort('fullname')">Name</a></b></td>
 1003:      <td><b><a href="javascript:changeSort('username')">Username</a></b>
 1004:      </td>
 1005:      <td><b><a href="javascript:changeSort('domain')">Domain</a></b></td>
 1006:      <td><b><a href="javascript:changeSort('id')">ID</a></b></td>
 1007: END
 1008:         if (@available > 0) {
 1009:             $r->print('<td><b>Functionality</b></td>');
 1010:         }
 1011:         $r->print('</tr>');
 1012:         my %Sortby = ();
 1013:         foreach my $user (sort(keys(%members))) {
 1014:             if ($env{'form.sortby'} eq 'fullname') {
 1015:                 push(@{$Sortby{$members{$user}[$$idx{fullname}]}},$user);
 1016:             } elsif ($env{'form.sortby'} eq 'username') {
 1017:                 push(@{$Sortby{$members{$user}[$$idx{uname}]}},$user);
 1018:             } elsif ($env{'form.sortby'} eq 'domain') {
 1019:                 push(@{$Sortby{$members{$user}[$$idx{udom}]}},$user);
 1020:             } elsif ($env{'form.sortby'} eq 'id') {
 1021:                 push(@{$Sortby{$members{$user}[$$idx{id}]}},$user);
 1022:             } else {
 1023:                 push(@{$Sortby{$members{$user}[$$idx{fullname}]}},$user);
 1024:             }
 1025:         }
 1026:         my $rowNum = 0;
 1027:         my $rowColor;
 1028:         foreach my $key (sort(keys(%Sortby))) {
 1029:             foreach my $user (@{$Sortby{$key}}) {
 1030:                 if ($rowNum %2 == 1) {
 1031:                     $rowColor = $rowColor1;
 1032:                 } else {
 1033:                     $rowColor = $rowColor2;
 1034:                 }
 1035:                 my $id = $members{$user}[$$idx{id}];
 1036:                 my $fullname = $members{$user}[$$idx{fullname}];
 1037:                 my $udom = $members{$user}[$$idx{udom}];
 1038:                 my $uname = $members{$user}[$$idx{uname}];
 1039:                 $r->print('<tr bgcolor="'.$rowColor.'"><td align="right">
 1040:    <input type="checkbox" name="member" value="'.$user.'" /></td><td><small>'.
 1041:     $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.
 1042:     $udom.'</small></td><td><small>'.$id.'</small></td>');
 1043:                 if (@available > 0) {
 1044:                     $r->print('<td align="center"><small>'); 
 1045:                     foreach my $tool (@available) {
 1046:                         if ($env{'form.granularity'} eq 'Yes') {
 1047:                             $r->print('<input type="checkbox" name="user_'.
 1048:                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
 1049:                         } else {
 1050:                             $r->print('<input type="hidden" name="user_'.
 1051:                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
 1052:                         }
 1053:                     }
 1054:                     $r->print('</small></td>');
 1055:                 }
 1056:                 $r->print('</tr>'."\n");
 1057:                 $rowNum ++;
 1058:             }
 1059:         }
 1060:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
 1061:         $r->print('
 1062:   </td>
 1063:  </tr>
 1064:  <tr>
 1065:   <td colspan="4">&nbsp;</td>
 1066:  </tr>');
 1067:         if (@available > 0) {
 1068:             $r->print('
 1069:  <tr bgcolor="'.$tabcol.'">
 1070:   <td>&nbsp;</td>
 1071:   <td valign="middle" align="left">
 1072:    <nobr><img src="/res/adm/pages/bl_step5.gif" valign="middle">&nbsp;</nobr>
 1073:   </td>
 1074:   <td align="left"><nobr>
 1075:    <font face="arial,helvetica,sans-serif">
 1076:     <b>User privileges</b>
 1077:    </font></nobr>
 1078:   </td>
 1079:   <td width="100%">&nbsp;</td>
 1080:  </tr>
 1081:  <tr>
 1082:   <td>&nbsp;</td>
 1083:   <td colspan="3">
 1084:    <br />
 1085:    For each type of functionality you have chosen to include, there is a 
 1086: set of standard privileges which apply to all of those for whom the functionality is enabled.<br />There are also additional privileges which can be set for some, or all, members. Please choose one of the following:<br />
 1087: <br /><input type="radio" name="specificity" value="No" checked="checked" />&nbsp;All group members will receive the same privileges.<br/><input type="radio" name="specificity" value="Yes" />&nbsp;Some group members will receive different privileges from others.
 1088:   </td>
 1089:  </tr>
 1090:  <tr>
 1091:   <td colspan="4">&nbsp;</td>
 1092:  </tr>
 1093: ');
 1094:         }
 1095:         $r->print('    
 1096:  <tr>
 1097:   <td>&nbsp;</td>
 1098:   <td colspan="3">
 1099:    <input type="button" name="previous" value = "Go to previous page" 
 1100:     onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>
 1101:    &nbsp;&nbsp;&nbsp;
 1102:    <input type="button" name="next" value="Go to next page" 
 1103:  onclick="javascript:nextPage(document.'.$formname.','."'pick_privs'".')" />
 1104:   </td>
 1105:  </tr>
 1106:         ');
 1107:     } else {
 1108:         $r->print('No members to add');
 1109:     }
 1110:     $r->print('
 1111:    </table>
 1112:   </td>
 1113:  </tr>
 1114: </table>');
 1115:     return;
 1116: }
 1117: 
 1118: sub third_creation_form {
 1119:     my ($r,$cdom,$cnum,$tabcol,$formname,$startdate,$enddate,$tools,$functions,
 1120:                $toolprivs,$fixedprivs,$userdata,$members,$usertools,$idx) = @_;
 1121:     my @regexps = ('userpriv_','allpriv_');
 1122:     $r->print(&Apache::lonhtmlcommon::echo_form_input(
 1123:                              ['origin','action','state'],\@regexps));
 1124:     my %possibles = ();
 1125:     my %showboxes = ();
 1126:     my $totalboxes = 0;
 1127:     my $rowColor1 = "#dddddd";
 1128:     my $rowColor2 = "#eeeeee";
 1129:     my $numtools = 1 + @{$tools};
 1130:     foreach my $tool (@{$tools}) {
 1131:         @{$showboxes{$tool}} = ();
 1132:         foreach my $user (@{$members}) {
 1133:             if (exists($$usertools{$user}{$tool})) {
 1134:                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
 1135:                     unless (exists($$fixedprivs{$tool}{$priv})) {
 1136:                         push(@{$possibles{$user}},$priv);
 1137:                         unless(grep(/^$priv$/,@{$showboxes{$tool}})) {
 1138:                             push(@{$showboxes{$tool}},$priv);
 1139:                             $totalboxes ++;
 1140:                         }
 1141:                     }
 1142:                 }
 1143:             }
 1144:         }
 1145:     }
 1146:     if ($totalboxes > 0) {
 1147:         $r->print('
 1148: <script type="text/javascript">
 1149: function checkAllTools(formname) {
 1150: ');
 1151:         foreach my $tool (sort(keys(%showboxes))) {
 1152:             foreach my $priv (@{$showboxes{$tool}}) {
 1153:                 $r->print('  checkAll(formname.userpriv_'.$priv.');'."\n");
 1154:             }
 1155:         }
 1156:         $r->print('
 1157: }
 1158: function uncheckAllTools(formname) {
 1159: ');
 1160:         foreach my $tool (sort(keys(%showboxes))) {
 1161:             foreach my $priv (@{$showboxes{$tool}}) {
 1162:                 $r->print('  uncheckAll(formname.userpriv_'.$priv.');'."\n");
 1163:             }
 1164:         }
 1165:         $r->print('
 1166: }
 1167: </script>
 1168:        ');
 1169:    }
 1170:    $r->print(<<"END");
 1171: <br />
 1172: <table width="100%" cellpadding="0" cellspacing="0" border="0">
 1173:  <tr bgcolor="$tabcol">
 1174:   <td>&nbsp;</td>
 1175:   <td valign="middle" align="left">
 1176:    <nobr><img src="/res/adm/pages/bl_step6.gif" valign="middle">&nbsp;</nobr>
 1177:   </td>
 1178:   <th align="left"><nobr>
 1179:     Group member privileges
 1180:    </nobr>
 1181:   </th>
 1182:   <td width="100%">&nbsp;</td>
 1183:  </tr>
 1184:  <tr>
 1185:   <td colspan="4">&nbsp;</td>
 1186:  </tr>
 1187:  <tr>
 1188:   <td>&nbsp;</td>
 1189:   <td colspan="3">
 1190: END
 1191:     if ($env{'form.specificity'} eq 'Yes') {
 1192:         $r->print('
 1193:    <table border="0" cellspacing="2" cellpadding="2" border="0">
 1194:     <tr>
 1195:      <td valign="top">
 1196: ');
 1197:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
 1198:         $r->print(<<"END");
 1199:    <tr bgcolor="$tabcol">
 1200:     <th><b>Fullname</th>
 1201:     <th><b>Username</th>
 1202:     <th>Domain</th>
 1203:     <th colspan="$numtools">Additional Privileges</th>
 1204:   </tr>
 1205: END
 1206:     }
 1207:     if ($env{'form.specificity'} eq 'Yes') {
 1208:         &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,
 1209:                              $usertools,$toolprivs,$fixedprivs,$userdata,$idx);
 1210:     }
 1211:     if ($env{'form.specificity'} eq 'Yes') {
 1212:         $r->print('</td>');
 1213:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
 1214:         $r->print('<td>&nbsp;</td>
 1215:                <td>&nbsp;</td><td valign="top">');
 1216:         my @toolboxes = sort(keys(%showboxes));
 1217:         foreach my $tool (@{$tools}) {
 1218:             if (@{$showboxes{$tool}} > 0) { 
 1219:                 $r->print('<table class="thinborder"><tr bgcolor="'.$tabcol.
 1220:                       '"><th>'.$tool.'</th></tr>');
 1221:                 foreach my $priv (@{$showboxes{$tool}}) {
 1222:                     $r->print(qq|
 1223:        <tr><td>
 1224:        <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>
 1225:        <input type="button" value="check all"
 1226:          onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />
 1227:        &nbsp; 
 1228:        <input type="button" value="uncheck all"
 1229:         onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />
 1230:       </nobr></fieldset></td></tr>|);
 1231:                 }
 1232:                 $r->print('</table><br /><br />');
 1233:             }
 1234:         }
 1235:         $r->print('</td></tr></table>');
 1236:     } else {
 1237:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
 1238:         $r->print('<tr><td bgcolor="'.$tabcol.'" valign="top"><table cellspacing="0" cellpadding="1"><tr><td valign="top"><b>Function</b></td></tr><tr><td valign="top"><b>Fixed privileges</b>'.
 1239:                   '</td></tr><tr><td valign="top"><b>Optional privileges</b></td></tr></table></td>');
 1240:         foreach my $tool (@{$tools}) {
 1241:             $r->print('<td align="center" valign="top"><table cellspacing="0" cellpadding="1"><tr bgcolor="#cccccc">'.
 1242:                        '<td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');
 1243:             my $privcount = 0;
 1244:             my $fixed = '';
 1245:             my $dynamic = '';
 1246:             foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
 1247:                 if (exists($$fixedprivs{$tool}{$priv})) {
 1248:                     $fixed .= '<input type="hidden" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
 1249:                 } else {
 1250:                     $privcount ++;
 1251:                     if ($privcount == 3) {
 1252:                         $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'">';
 1253:                     }
 1254:                     $dynamic .= '<td><input type="checkbox" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'</td>';
 1255:                 }
 1256:             }
 1257:             if ($dynamic eq '') {
 1258:                 $dynamic = '<td>None</td>'; 
 1259:             }
 1260:             if ($privcount < 3) {
 1261:                 $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'"><td colspan="2">&nbsp;</td>';
 1262:             } elsif ($privcount%2) {
 1263:                 $dynamic = '<td>&nbsp;</td>';
 1264:             }
 1265:             $r->print('<tr bgcolor="'.$rowColor2.'"><td colspan="2" align="center"><nobr>'.$fixed.'</nobr></td></tr><tr bgcolor="'.$rowColor1.'">'.$dynamic.'</tr></table></td>');
 1266:         }
 1267:         $r->print('</tr>');
 1268:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
 1269:     }
 1270:     $r->print('</td></tr>
 1271:  <tr>
 1272:   <td colspan="4">&nbsp;</td>
 1273:  </tr>
 1274:  <tr>
 1275:   <td>&nbsp;</td>
 1276:   <td colspan="3">
 1277:    <input type="button" name="previous" value = "Go to previous page"
 1278:     onclick="javascript:backPage(document.'.$formname.','."'pick_members'".')"/>
 1279:    &nbsp;&nbsp;
 1280:    <input type="button" name="next" value="Create group"
 1281:  onclick="javascript:nextPage(document.'.$formname.','."'result'".')" />
 1282:   </td>
 1283:  </tr>
 1284:     ');
 1285:     $r->print('
 1286: </table>');
 1287: 
 1288:     return;
 1289: }
 1290: 
 1291: sub completed_creation {
 1292:     my ($r,$cdom,$cnum,$tabcol,$formname,$groupname,$description,$userdata,
 1293: $startdate,$enddate,$tools,$functions,$toolprivs,$members,$usertools,$idx) = @_;
 1294: 
 1295:     $r->print(&Apache::lonhtmlcommon::echo_form_input(
 1296:                                         ['origin','action','state']));
 1297:     my @added= ();
 1298:     my @failed = ();
 1299:     my $now = time;
 1300:     my %group_privs = ();
 1301:     my %tooltype = ();
 1302:     foreach my $tool (@{$tools}) {
 1303:         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
 1304:             $tooltype{$priv} = $tool;
 1305:             if ($env{'form.specificity'} eq 'Yes') {
 1306:                 my @users =
 1307:                   &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);
 1308:                 foreach my $user (@users) {
 1309:                     $group_privs{$user} .= $priv.':';
 1310:                 }
 1311:             } else {
 1312:                 if (defined($env{'form.allpriv_'.$priv})) {
 1313:                     foreach my $user (@{$members}) {
 1314:                         if ($$usertools{$user}{$tool}) {
 1315:                             $group_privs{$user} .= $priv.':';
 1316:                         }
 1317:                     }
 1318:                 }
 1319:             }
 1320:         }
 1321:     }
 1322:     foreach my $user (keys(%group_privs)) {
 1323:         $group_privs{$user} =~ s/:$//;
 1324:     }
 1325:     my $esc_description = &Apache::lonnet::escape($description);
 1326:     my @attributes = ('description','functions','startdate','enddate','creation','modified','creator');
 1327:         
 1328:     my %groupinfo = (
 1329:                       description => $esc_description,
 1330:                       startdate => $startdate,
 1331:                       enddate => $enddate,
 1332:                       creation => $now,
 1333:                       modified => $now,
 1334:                       creator => $env{'user.name'}.':'.$env{'user.domain'}, 
 1335:                     );
 1336:     foreach my $func (keys(%{$functions})) {
 1337:         my $status;
 1338:         if (grep(/^$func$/,@{$tools})) {
 1339:             $status = 'on';
 1340:         } else {
 1341:             $status = 'off';
 1342:         } 
 1343:         $groupinfo{'functions'} .=  qq|<name id="$func">$status</name>|;
 1344:     }
 1345: 
 1346:     my %curr_groups = ();
 1347:     my %groupsettings = ();
 1348:     my %usersettings = ();
 1349:     if (&Apache::lonnet::get_coursegroups($cdom,$cnum,\%curr_groups) > 0) {
 1350:         if (exists($curr_groups{$groupname})) {
 1351:             $r->print('Non-unique name -please choose another');
 1352:             return; 
 1353:         }
 1354:     }
 1355:     my $groupentry;
 1356:     foreach my $item (@attributes) {
 1357:         $groupsettings{$groupname} .= qq|<$item>$groupinfo{$item}</$item>|;
 1358:     }
 1359:     my $result = &Apache::lonnet::modify_coursegroup($cdom,$cnum,
 1360:                                                           \%groupsettings);
 1361:     if ($result eq 'ok') {
 1362:         my $put_result = &create_homepage($cdom,$cnum,$groupname,\%groupinfo,$tools);
 1363:         foreach my $user (sort(@{$members})) {
 1364:             $usersettings{$groupname.':'.$user} = $enddate.':'.$startdate.':'.$group_privs{$user};
 1365:             if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
 1366:                   $user,$enddate,$startdate,$group_privs{$user}) eq 'ok') {
 1367:                 push(@added,$user);
 1368:             } else {
 1369:                 push(@failed,$user);
 1370:             }
 1371:         }
 1372:         my $roster_result = &Apache::lonnet::modify_coursegroup_membership(
 1373:              $cdom,$cnum,\%usersettings);
 1374:         $r->print('
 1375: Group '.$groupname.' was created.<br />');
 1376:         if (@added > 0) {
 1377:             $r->print('Users were added with following privileges:<br />');
 1378:             foreach my $user (@added) {
 1379:                 my @privs = split(/:/,$group_privs{$user});
 1380:                 my $privlist= '';
 1381:                 my $curr_tool = '';
 1382:                 foreach my $priv (@privs) {
 1383:                     unless ($curr_tool eq $tooltype{$priv}) {
 1384:                         $curr_tool = $tooltype{$priv};
 1385:                         $privlist .= '<b>'.$curr_tool.'</b>: ';
 1386:                     }
 1387:                     $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';
 1388:                 }
 1389:                 $privlist =~ s/, $//;
 1390:                 $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.': '.$privlist.'<br />');
 1391:             }
 1392:         }
 1393:         if (@failed > 0) {
 1394:             $r->print('Addition of the following users was unsuccessful:<br />');
 1395:             foreach my $user (@failed) {
 1396:                 $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
 1397:             }
 1398:         }
 1399:         if ($roster_result eq 'ok') {
 1400:             $r->print('<br />Group membership list updated.');
 1401:         } else {
 1402:             $r->print('<br />An error occurred while updating the group membership list -'.$roster_result.'<br />');
 1403:         } 
 1404:     } else {
 1405:         &Apache::lonnet::logthis('Failed to create group '.$groupname. 
 1406:                                  'in course: '.$cnum.' in domain: '.$cdom);
 1407: 
 1408:         $r->print('An error occurred when creating the new group. '.
 1409:                                                       'Please try again.');
 1410:     }
 1411:     return;
 1412: }
 1413: 
 1414: sub member_privs_entries {
 1415:     my ($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,$usertools,$toolprivs,
 1416:                                               $fixedprivs,$userdata,$idx) = @_;
 1417:     my $rowColor;
 1418:     my $rowNum = 0;
 1419:     foreach my $member (@{$members}) {
 1420:         my ($uname,$udom) = split(/:/,$member);
 1421:         if ($rowNum %2 == 1) {
 1422:             $rowColor = $rowColor1;
 1423:         } else {
 1424:             $rowColor = $rowColor2;
 1425:         }
 1426:         $r->print('<tr bgcolor="'.$rowColor.'">
 1427:                 <td>'.$$userdata{$member}[$$idx{fullname}].'</td>
 1428:                 <td>'.$uname.'</td>
 1429:                 <td>'.$udom.'</td>
 1430:                 <td valign="top"><table><tr><td><b>Function</b></td></tr><tr><td><b>Fixed</b></td></tr><tr><td><b>Optional</b></td></tr></table></td>');
 1431:         foreach my $tool (@{$tools}) {
 1432:             if (exists($$usertools{$member}{$tool})) {
 1433:                 $r->print('<td valign="top"><table><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');
 1434:                 my $privcount = 0;
 1435:                 my $fixed = '';
 1436:                 my $dynamic = '';
 1437:                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
 1438:                     if (exists($$fixedprivs{$tool}{$priv})) {
 1439:                         $fixed .= '<input type="hidden" name="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
 1440:                     } else {
 1441:                         $privcount ++;
 1442:                         if ($privcount == 3) {
 1443:                             $dynamic .= '</tr><tr>';
 1444:                         }
 1445:                         $dynamic .= '<td><input type="checkbox" name="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'</td>';
 1446:                     }
 1447:                 }
 1448:                 $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');
 1449:             } else {
 1450:                 $r->print('<td>&nbsp;</td>');
 1451:             }
 1452:         }
 1453:         $rowNum ++;
 1454:     }
 1455: }
 1456: 
 1457: 
 1458: sub get_dates_from_form {
 1459:     my $startdate;
 1460:     my $enddate;
 1461:     $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate');
 1462:     $enddate   = &Apache::lonhtmlcommon::get_date_from_form('enddate');
 1463:     if ( exists ($env{'form.no_end_date'}) ) {
 1464:         $enddate = 0;
 1465:     }
 1466:     return ($startdate,$enddate);
 1467: }                                                                                     
 1468: sub date_setting_table {
 1469:     my ($starttime,$endtime,$formname) = @_;
 1470:     my $startform = &Apache::lonhtmlcommon::date_setter($formname,
 1471:                                                       'startdate',$starttime);
 1472:     my $endform = &Apache::lonhtmlcommon::date_setter($formname,
 1473:                                                       'enddate',$endtime);
 1474:     my $perpetual = '<nobr><input type="checkbox" name="no_end_date" />
 1475:                                                   no ending date</nobr>';
 1476:     my $start_table = '';
 1477:     $start_table .= "<table>\n";
 1478:     $start_table .= '<tr><td align="right">Default starting date for 
 1479:                                            member access</td>'.
 1480:         '<td>'.$startform.'</td>'.
 1481:         '<td>&nbsp;</td>'."</tr>\n";
 1482:     $start_table .= "</table>";
 1483:     my $end_table = '';
 1484:     $end_table .= "<table>\n";
 1485:     $end_table .= '<tr><td align="right">Default ending date for 
 1486:                                          member access</td>'.
 1487:         '<td>'.$endform.'</td>'.
 1488:         '<td>'.$perpetual.'</td>'."</tr>\n";
 1489:     $end_table .= "</table>\n";
 1490:     return ($start_table, $end_table);
 1491: }
 1492: 
 1493: sub create_homepage {
 1494:     my ($cdom,$cnum,$name,$groupinfo,$tools) = @_;
 1495:     my $functionality = join(',',@{$tools});
 1496:     my $content = &Apache::lonnet::unescape($$groupinfo{description});
 1497:     $content=~s/\s+$//s;
 1498:     $content=~s/^\s+//s;
 1499:     $content=~s/\<br\s*\/*\>$//s;
 1500:     $content=&Apache::lonfeedback::clear_out_html($content,1);
 1501: 
 1502:     my %pageinfo = (
 1503:                      'aaa_title' => 'Group: '.$name,
 1504:                      'abb_links' => $functionality,
 1505:                      'bbb_content' => $content,
 1506:                      'ccc_webreferences' => '',
 1507:                      'uploaded.lastmodified' => time,
 1508:                    );
 1509:    my $putresult = &Apache::lonnet::put('grppage_'.$name,\%pageinfo,$cdom,$cnum);
 1510:    return $putresult;
 1511: }
 1512: 
 1513: 
 1514: 1;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>