[LON-CAPA-cvs] cvs: loncom /interface lonnavmaps.pm lonparmset.pm /lonnet/perl lonnet.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Tue, 22 Nov 2005 02:24:55 -0000


This is a MIME encoded message

--raeburn1132626295
Content-Type: text/plain

raeburn		Mon Nov 21 21:24:55 2005 EDT

  Modified files:              
    /loncom/interface	lonnavmaps.pm lonparmset.pm 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  Parameters can be set for resources, maps, and course by group.  Group-level settings trump section-level settings in the cascading parameter scheme. Spreadsheet changes to follow.    
  
  
--raeburn1132626295
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20051121212455.txt"

Index: loncom/interface/lonnavmaps.pm
diff -u loncom/interface/lonnavmaps.pm:1.349 loncom/interface/lonnavmaps.pm:1.350
--- loncom/interface/lonnavmaps.pm:1.349	Thu Nov 17 06:32:30 2005
+++ loncom/interface/lonnavmaps.pm	Mon Nov 21 21:24:50 2005
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Navigate Maps Handler
 #
-# $Id: lonnavmaps.pm,v 1.349 2005/11/17 11:32:30 foxr Exp $
+# $Id: lonnavmaps.pm,v 1.350 2005/11/22 02:24:50 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2475,6 +2475,12 @@
 
     my $cid=$env{'request.course.id'};
     my $csec=$env{'request.course.sec'};
+    my $cgroup='';
+    my @cgrps=split(/:/,$env{'request.course.groups'});
+    if (@cgrps > 0) {
+        @cgrps = sort(@cgrps);
+        $cgroup = $cgrps[0];
+    } 
     my $uname=$env{'user.name'};
     my $udom=$env{'user.domain'};
 
@@ -2492,6 +2498,10 @@
     my $mapparm=$mapname.'___(all).'.$what;
     my $usercourseprefix=$cid;
 
+    my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what;
+    my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm;
+    my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm;
+
     my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what;
     my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm;
     my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm;
@@ -2512,6 +2522,12 @@
     }
 
 # ------------------------------------------------------- second, check course
+    if ($cgroup ne '' and defined($courseopt)) {
+        if (defined($$courseopt{$grplevelr})) { return $$courseopt{$grplevelr}; }
+        if (defined($$courseopt{$grplevelm})) { return $$courseopt{$grplevelm}; }
+        if (defined($$courseopt{$grplevel})) { return $$courseopt{$grplevel}; }
+    }
+
     if ($csec and defined($courseopt)) {
         if (defined($$courseopt{$seclevelr})) { return $$courseopt{$seclevelr}; }
         if (defined($$courseopt{$seclevelm})) { return $$courseopt{$seclevelm}; }
Index: loncom/interface/lonparmset.pm
diff -u loncom/interface/lonparmset.pm:1.268 loncom/interface/lonparmset.pm:1.269
--- loncom/interface/lonparmset.pm:1.268	Mon Nov 21 17:00:11 2005
+++ loncom/interface/lonparmset.pm	Mon Nov 21 21:24:50 2005
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set parameters for assessments
 #
-# $Id: lonparmset.pm,v 1.268 2005/11/21 22:00:11 albertel Exp $
+# $Id: lonparmset.pm,v 1.269 2005/11/22 02:24:50 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -88,16 +88,19 @@
          $id   - a bighash Id number
          $def  - the resource's default value   'stupid emacs
 
-Returns:  A list, the first item is the index into the remaining list of items of parm valuse that is the active one, the list consists of parm values at the 11 possible levels
+Returns:  A list, the first item is the index into the remaining list of items of parm valuse that is the active one, the list consists of parm values at the 14 possible levels
 
-11 - General Course
-10 - Map or Folder level in course
-9- resource default
-8- map default
-7 - resource level in course
-6 - General for section
-5 - Map or Folder level for section
-4 - resource level in section
+14 - General Course
+13 - Map or Folder level in course
+12- resource default
+11- map default
+10 - resource level in course
+9 - General for section
+8 - Map or Folder level for section
+7 - resource level in section
+6 - General for group
+5 - Map or Folder level for group
+4 - resource level in group
 3 - General for specific student
 2 - Map or Folder level for specific student
 1 - resource level for specific student
@@ -106,12 +109,12 @@
 
 ##################################################
 sub parmval {
-    my ($what,$id,$def,$uname,$udom,$csec)=@_;
-    return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec);
+    my ($what,$id,$def,$uname,$udom,$csec,$cgroup)=@_;
+    return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,$cgroup);
 }
 
 sub parmval_by_symb {
-    my ($what,$symb,$def,$uname,$udom,$csec)=@_;
+    my ($what,$symb,$def,$uname,$udom,$csec,$cgroup)=@_;
 # load caches
 
     &cacheparmhash();
@@ -121,7 +124,6 @@
     my $useropt=&Apache::lonnet::get_userresdata($uname,$udom);
     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
 
-
     my $result='';
     my @outpar=();
 # ----------------------------------------------------- Cascading lookup scheme
@@ -130,6 +132,10 @@
     my $symbparm=$symb.'.'.$what;
     my $mapparm=$map.'___(all).'.$what;
 
+    my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
+    my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
+    my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
+
     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
@@ -139,49 +145,63 @@
     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
 
 
-
 # --------------------------------------------------------- first, check course
 
     if (defined($$courseopt{$courselevel})) {
-	$outpar[11]=$$courseopt{$courselevel};
-	$result=11;
+	$outpar[14]=$$courseopt{$courselevel};
+	$result=14;
     }
 
     if (defined($$courseopt{$courselevelm})) {
-	$outpar[10]=$$courseopt{$courselevelm};
-	$result=10;
+	$outpar[13]=$$courseopt{$courselevelm};
+	$result=13;
     }
 
 # ------------------------------------------------------- second, check default
 
-    if (defined($def)) { $outpar[9]=$def; $result=9; }
+    if (defined($def)) { $outpar[12]=$def; $result=12; }
 
 # ------------------------------------------------------ third, check map parms
 
     my $thisparm=$parmhash{$symbparm};
-    if (defined($thisparm)) { $outpar[8]=$thisparm; $result=8; }
+    if (defined($thisparm)) { $outpar[11]=$thisparm; $result=11; }
 
     if (defined($$courseopt{$courselevelr})) {
-	$outpar[7]=$$courseopt{$courselevelr};
-	$result=7;
+	$outpar[10]=$$courseopt{$courselevelr};
+	$result=10;
     }
 
 # ------------------------------------------------------ fourth, back to course
     if (defined($csec)) {
         if (defined($$courseopt{$seclevel})) {
-	    $outpar[6]=$$courseopt{$seclevel};
-	    $result=6;
+	    $outpar[9]=$$courseopt{$seclevel};
+	    $result=9;
 	}
         if (defined($$courseopt{$seclevelm})) {
-	    $outpar[5]=$$courseopt{$seclevelm};
-	    $result=5;
+	    $outpar[8]=$$courseopt{$seclevelm};
+	    $result=8;
 	}
 
         if (defined($$courseopt{$seclevelr})) {
-	    $outpar[4]=$$courseopt{$seclevelr};
-	    $result=4;
+	    $outpar[7]=$$courseopt{$seclevelr};
+	    $result=7;
 	}
     }
+# ------------------------------------------------------ fifth, check gourse group
+    if (defined($cgroup)) {
+        if (defined($$courseopt{$grplevel})) {
+            $outpar[6]=$$courseopt{$grplevel};
+            $result=6;
+        }
+        if (defined($$courseopt{$grplevelm})) {
+            $outpar[5]=$$courseopt{$grplevelm};
+            $result=5;
+        }
+        if (defined($$courseopt{$grplevelr})) {
+            $outpar[4]=$$courseopt{$grplevelr};
+            $result=4;
+        }
+    }
 
 # ---------------------------------------------------------- fifth, check user
 
@@ -289,8 +309,8 @@
 # - userdomain
 
 sub storeparm {
-    my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec)=@_;
-    &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec);
+    my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
+    &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
 }
 
 #
@@ -307,7 +327,7 @@
 
 my %recstack;
 sub storeparm_by_symb {
-    my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag)=@_;
+    my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup,$recflag)=@_;
     unless ($recflag) {
 # first time call
 	%recstack=();
@@ -315,7 +335,7 @@
     }
 # store parameter
     &storeparm_by_symb_inner
-	($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec);
+	($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
 # don't do anything if parameter was reset
     unless ($nval) { return; }
     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
@@ -350,7 +370,7 @@
 	   }
 	   if ($active) {
 	       &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
-				   $uname,$udom,$csec,$recflag);
+				   $uname,$udom,$csec,$cgroup,$recflag);
 	   }
        }
     }
@@ -359,13 +379,17 @@
 
 sub storeparm_by_symb_inner {
 # ---------------------------------------------------------- Get symb, map, etc
-    my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec)=@_;
+    my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
 # ---------------------------------------------------------- Construct prefixes
     $spnam=~s/\_([^\_]+)$/\.$1/;
     my $map=(&Apache::lonnet::decode_symb($symb))[0];    
     my $symbparm=$symb.'.'.$spnam;
     my $mapparm=$map.'___(all).'.$spnam;
 
+    my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
+    my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
+    my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
+
     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
@@ -375,12 +399,16 @@
     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
     
     my $storeunder='';
-    if (($snum==11) || ($snum==3)) { $storeunder=$courselevel; }
-    if (($snum==10) || ($snum==2)) { $storeunder=$courselevelm; }
-    if (($snum==7) || ($snum==1)) { $storeunder=$courselevelr; }
-    if ($snum==6) { $storeunder=$seclevel; }
-    if ($snum==5) { $storeunder=$seclevelm; }
-    if ($snum==4) { $storeunder=$seclevelr; }
+    if (($snum==14) || ($snum==3)) { $storeunder=$courselevel; }
+    if (($snum==13) || ($snum==2)) { $storeunder=$courselevelm; }
+    if (($snum==10) || ($snum==1)) { $storeunder=$courselevelr; }
+    if ($snum==9) { $storeunder=$seclevel; }
+    if ($snum==8) { $storeunder=$seclevelm; }
+    if ($snum==7) { $storeunder=$seclevelr; }
+    if ($snum==6) { $storeunder=$grplevel; }
+    if ($snum==5) { $storeunder=$grplevelm; }
+    if ($snum==4) { $storeunder=$grplevelr; }
+
     
     my $delete;
     if ($nval eq '') { $delete=1;}
@@ -394,9 +422,9 @@
 	my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
 # Expire sheets
 	&Apache::lonnet::expirespread('','','studentcalc');
-	if (($snum==7) || ($snum==4)) {
+	if (($snum==10) || ($snum==7) || ($snum==4)) {
 	    &Apache::lonnet::expirespread('','','assesscalc',$symb);
-	} elsif (($snum==8) || ($snum==5)) {
+	} elsif (($snum==11) || ($snum==8) || ($snum==5)) {
 	    &Apache::lonnet::expirespread('','','assesscalc',$map);
 	} else {
 	    &Apache::lonnet::expirespread('','','assesscalc');
@@ -537,9 +565,9 @@
 
 sub startpage {
     my $r=shift;
-
+    my $loaditems = qq|onUnload="pclose()" onLoad="group_or_section('cgroup')"|;
     my $bodytag=&Apache::loncommon::bodytag('Set/Modify Course Parameters','',
-                                            'onUnload="pclose()"');
+                                            $loaditems);
     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(undef,'Table Mode Parameter Setting');
     my $selscript=&Apache::loncommon::studentbrowser_javascript();
     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
@@ -604,19 +632,19 @@
 
 sub print_row {
     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
-	$defbgtwo,$parmlev,$uname,$udom,$csec)=@_;
+	$defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup)=@_;
 # get the values for the parameter in cascading order
 # empty levels will remain empty
     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
-				  $rid,$$default{$which},$uname,$udom,$csec);
+				  $rid,$$default{$which},$uname,$udom,$csec,$cgroup);
 # get the type for the parameters
 # problem: these may not be set for all levels
     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
                                           $$name{$which}.'.type',
-				  $rid,$$defaulttype{$which},$uname,$udom,$csec);
+				  $rid,$$defaulttype{$which},$uname,$udom,$csec,$cgroup);
 # cascade down manually
     my $cascadetype=$$defaulttype{$which};
-    for (my $i=11;$i>0;$i--) {
+    for (my $i=14;$i>0;$i--) {
 	 if ($typeoutpar[$i]) { 
             $cascadetype=$typeoutpar[$i];
 	} else {
@@ -645,34 +673,45 @@
 
         if ($uname) {
             &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+        } elsif ($cgroup) {
+            &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
         } elsif ($csec) {
-            &print_td($r,6,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display); 
+            &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display); 
         } else {
-            &print_td($r,11,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display); 
+            &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display); 
         }
     } elsif ($parmlev eq 'map') {
 
         if ($uname) {
             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+        } elsif ($cgroup) {
+            &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
         } elsif ($csec) {
-            &print_td($r,5,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+            &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
         } else {
-            &print_td($r,10,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+            &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
         }
     } else {
 
-        &print_td($r,11,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+        &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
 
+	&print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+	&print_td($r,12,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+	&print_td($r,11,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
 	&print_td($r,10,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
-	&print_td($r,9,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
-	&print_td($r,8,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
-	&print_td($r,7,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
 	
 	if ($csec) {
-	    &print_td($r,6,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
-	    &print_td($r,5,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
-	    &print_td($r,4,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+	    &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+	    &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+	    &print_td($r,7,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
 	}
+
+        if ($cgroup) {
+            &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+            &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+            &print_td($r,4,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
+        }
+
 	if ($uname) {
 	    &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
 	    &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display);
@@ -701,7 +740,7 @@
     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display)=@_;
     $r->print('<td bgcolor='.(($result==$which)?'"#AAFFAA"':$defbg).
               ' align="center">');
-    if ($which<8 || $which > 9) {
+    if ($which<11 || $which > 12) {
 	$r->print(&plink($$typeoutpar[$which],
 			 $$display{$value},$$outpar[$which],
 			 $mprefix."$which",'parmform.pres','psub'));
@@ -958,32 +997,84 @@
 }
 
 sub usermenu {
-    my ($r,$uname,$id,$udom,$csec)=@_;
+    my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev)=@_;
     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
         &Apache::loncommon::selectstudent_link('parmform','uname','udom');
     my $selscript=&Apache::loncommon::studentbrowser_javascript();
     my %lt=&Apache::lonlocal::texthash(
-		    'sg'    => "Section/Group",
+		    'se'    => "Section",
+                    'gr'    => "Group",
 		    'fu'    => "For User",
 		    'oi'    => "or ID",
 		    'ad'    => "at Domain"
 				       );
     my %sectionhash=();
     my $sections='';
-    if (&Apache::loncommon::get_sections(
+    my $numsec = &Apache::loncommon::get_sections(
                  $env{'course.'.$env{'request.course.id'}.'.domain'},
                  $env{'course.'.$env{'request.course.id'}.'.num'},
-					 \%sectionhash)) {
-        $sections=$lt{'sg'}.': <select name="csec">';
+					 \%sectionhash);
+    my $groups;
+    my %grouphash;
+    my $numgrp = &Apache::loncommon::coursegroups(
+                 \%grouphash,
+                 $env{'course.'.$env{'request.course.id'}.'.domain'},
+                 $env{'course.'.$env{'request.course.id'}.'.num'});
+    if ($numsec > 0) {
+        $sections=$lt{'se'}.': <select name="csec"';
+        if ($numsec && $numgrp && $parmlev ne 'full') {
+            $sections .= qq| onchange="group_or_section('csec')" |;
+        }
+        $sections .= '>';
 	foreach ('',sort keys %sectionhash) {
 	    $sections.='<option value="'.$_.'"'.
 		($_ eq $csec?'selected="selected"':'').'>'.$_.'</option>';
         }
         $sections.='</select>';
-     }
-     $r->print(<<ENDMENU);
+    }
+    if ($numsec && $numgrp && $parmlev ne 'full') {
+        $sections .= '&nbsp;or&nbsp;';
+        $sections .= qq|
+<script type="text/javascript">
+function group_or_section(caller) {
+   if (caller == "cgroup") {
+       if (document.parmform.cgroup.selectedIndex != 0) {
+           document.parmform.csec.selectedIndex = 0;
+       }
+   } else {
+       if (document.parmform.csec.selectedIndex != 0) {
+           document.parmform.cgroup.selectedIndex = 0;
+       }
+   }
+}
+</script>
+|;
+    } else {
+        $sections .= qq|
+<script type="text/javascript">
+function group_or_section(caller) {
+    return;
+}
+</script>
+|;
+    } 
+    if ($numgrp > 0) {
+        $groups=$lt{'gr'}.': <select name="cgroup"';
+        if ($numsec && $numgrp && $env{'form.action'} eq 'settable') {
+            $groups .= qq| onchange="group_or_section('cgroup')" |;
+        }
+        $groups .= '>';
+        foreach ('',sort keys %grouphash) {
+            $groups.='<option value="'.$_.'"'.
+                ($_ eq $cgroup?'selected="selected"':'').'>'.
+                                         $_.'</option>';
+        }
+        $groups.='</select>';
+    }
+    $r->print(<<ENDMENU);
 <b>
 $sections
+$groups
 <br />
 $lt{'fu'} 
 <input type="text" value="$uname" size="12" name="uname" />
@@ -1037,11 +1128,12 @@
 sub sectionmenu {
     my ($r,$selectedsections)=@_;
     my %sectionhash=();
-
-    if (&Apache::loncommon::get_sections(
+    my $sections='';
+    my $numsec = &Apache::loncommon::get_sections(
                  $env{'course.'.$env{'request.course.id'}.'.domain'},
                  $env{'course.'.$env{'request.course.id'}.'.num'},
-					 \%sectionhash)) {
+					 \%sectionhash);
+    if ($numsec) {
 	$r->print('<select name="Section" multiple="true" size="8" >');
 	foreach my $s ('all',sort keys %sectionhash) {
 	    $r->print('    <option value="'.$s.'"');
@@ -1053,10 +1145,34 @@
 	    }
 	    $r->print('>'.$s."</option>\n");
 	}
-	$r->print("</select>\n");
+        $r->print("</select>\n");
+   }
+}
+
+sub groupmenu {
+    my ($r,$selectedgroups)=@_;
+    my %grouphash;
+    my $numgrp = &Apache::loncommon::coursegroups(
+                 \%grouphash,
+                 $env{'course.'.$env{'request.course.id'}.'.domain'},
+                 $env{'course.'.$env{'request.course.id'}.'.num'});
+    if ($numgrp) {
+        $r->print('<select name="Group" multiple="true" size="8" >');
+        foreach my $group (sort(keys(%grouphash))) {
+            $r->print('    <option value="'.$group.'"');
+            foreach (@{$selectedgroups}) {
+                if ($group eq $_) {
+                    $r->print(' selected');
+                    last;
+                }
+            }
+            $r->print('>'.$group."</option>\n");
+        }
+        $r->print("</select>\n");
     }
 }
 
+
 sub keysplit {
     my $keyp=shift;
     return (split(/\,/,$keyp));
@@ -1177,6 +1293,7 @@
     my $udom;
     my $uhome;
     my $csec;
+    my $cgroup;
  
     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
 
@@ -1198,6 +1315,7 @@
     my $message='';
 
     $csec=$env{'form.csec'};
+    $cgroup=$env{'form.cgroup'};
 
     if      ($udom=$env{'form.udom'}) {
     } elsif ($udom=$env{'request.role.domain'}) {
@@ -1264,12 +1382,14 @@
         } else {
 	    $csec=&Apache::lonnet::getsection($udom,$uname,
 					      $env{'request.course.id'});
+            
 	    if ($csec eq '-1') {
 		$message="<font color=red>".
 		    &mt("User")." '$uname' ".&mt("at domain")." '$udom' ".
 		    &mt("not in this course")."</font>";
 		$uname='';
 		$csec=$env{'form.csec'};
+                $cgroup=$env{'form.cgroup'};
 	    } else {
 		my %name=&Apache::lonnet::userenvironment($udom,$uname,
 		      ('firstname','middlename','lastname','generation','id'));
@@ -1278,10 +1398,18 @@
 			.$name{'lastname'}.' '.$name{'generation'}.
 			    "<br>\n".&mt('ID').": ".$name{'id'}.'<p>';
 	    }
+            my $grouplist = &Apache::lonnet::get_users_groups(
+                                        $udom,$uname,$env{'request.course.id'});
+            if ($grouplist) {
+                my @groups = split(/:/,$grouplist);
+                @groups = sort(@groups);
+                $cgroup = $groups[0];
+            }
         }
     }
 
     unless ($csec) { $csec=''; }
+    unless ($cgroup) { $cgroup=''; }
 
 # --------------------------------------------------------- Get all assessments
     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps, 
@@ -1300,7 +1428,7 @@
 	    $message.=&storeparm(split(/\&/,$markers[$i]),
 				 $values[$i],
 				 $types[$i],
-				 $uname,$udom,$csec);
+				 $uname,$udom,$csec,$cgroup);
 	}
 # ---------------------------------------------------------------- Done storing
 	$message.='<h3>'.&mt('Changes can take up to 10 minutes before being active for all students.').&Apache::loncommon::help_open_topic('Caching').'</h3>';
@@ -1336,7 +1464,7 @@
 		  '<br /><label><b>'.&mt('Show all parts').': <input type="checkbox" name="psprt" value="all"'.
 		  ($env{'form.psprt'}?' checked="checked"':'').' /></b></label><br />');
     }
-    &usermenu($r,$uname,$id,$udom,$csec);    
+    &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev);    
 
     $r->print('<p>'.$message.'</p>');
 
@@ -1358,6 +1486,10 @@
 
         if ($parmlev eq 'full') {
            my $coursespan=$csec?8:5;
+           if ($cgroup ne '') {
+              $coursespan += 3;
+           } 
+      
            $r->print('<p><table border=2>');
            $r->print('<tr><td colspan=5></td>');
            $r->print('<th colspan='.($coursespan).'>'.&mt('Any User').'</th>');
@@ -1391,7 +1523,11 @@
 ENDTABLETWO
            if ($csec) {
                 $r->print("<th colspan=3>".
-			  &mt("in Section/Group")." $csec</th>");
+			  &mt("in Section")." $csec</th>");
+           }
+           if ($cgroup) {
+                $r->print("<th colspan=3>".
+                          &mt("in Group")." $cgroup</th>");
            }
            $r->print(<<ENDTABLEHEADFOUR);
 </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
@@ -1404,6 +1540,10 @@
                $r->print('<th>'.&mt('general').'</th><th>'.&mt('for Enclosing Map or Folder').'</th><th>'.&mt('for Resource').'</th>');
            }
 
+           if ($cgroup) {
+               $r->print('<th>'.&mt('general').'</th><th>'.&mt('for Enclosing Map or Folder').'</th><th>'.&mt('for Resource').'</th>');
+           }
+
            if ($uname) {
                $r->print('<th>'.&mt('general').'</th><th>'.&mt('for Enclosing Map or Folder').'</th><th>'.&mt('for Resource').'</th>');
            }
@@ -1412,6 +1552,7 @@
 
            my $defbgone='';
            my $defbgtwo='';
+           my $defbgthree = '';
 
            foreach (@ids) {
 
@@ -1433,6 +1574,12 @@
                     } else {
                         $defbgtwo='"#FFFF99"';
                     }
+                    if ($defbgthree eq '"#FFBB99"') {
+                        $defbgthree='"#FFBBDD"';
+                    } else {
+                        $defbgthree='"#FFBB99"';
+                    }
+
                     my $thistitle='';
                     my %name=   ();
                     undef %name;
@@ -1487,10 +1634,10 @@
                             } else {
                                 undef $firstrow;
                             }
-
                             &print_row($r,$_,\%part,\%name,\%symbp,$rid,\%default,
                                        \%type,\%display,$defbgone,$defbgtwo,
-                                       $parmlev,$uname,$udom,$csec);
+                                       $defbgthree,$parmlev,$uname,$udom,$csec,
+                                                                      $cgroup);
                         }
                     }
                 }
@@ -1502,6 +1649,7 @@
         if ($parmlev eq 'map') {
             my $defbgone = '"E0E099"';
             my $defbgtwo = '"FFFF99"';
+            my $defbgthree = '"FFBB99"';
 
             my %maplist;
 
@@ -1579,10 +1727,14 @@
                 } else {
                     $r->print("<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n");
                 }
-            
-                if ($csec) {$r->print(&mt("Section")." <font color=\"red\"><i>$csec</i></font> ".
-				      &mt('of')." \n")};
-
+                if ($cgroup) {
+                    $r->print(&mt("Group")." <font color=\"red\"><i>$cgroup".
+                              "</i></font> ".&mt('of')." \n");
+                    $csec = '';
+                } elsif ($csec) {
+                    $r->print(&mt("Section")." <font color=\"red\"><i>$csec".
+                              "</i></font> ".&mt('of')." \n");
+                }
                 $r->print("<font color=\"red\"><i>$coursename</i></font><br />");
                 $r->print("</h4>\n");
 #---------------------------------------------------------------- print table
@@ -1594,8 +1746,8 @@
 	        foreach (&keysinorder(\%name,\%keyorder)) {
                     $r->print('<tr>');
                     &print_row($r,$_,\%part,\%name,\%symbp,$mapid,\%default,
-                           \%type,\%display,$defbgone,$defbgtwo,
-                           $parmlev,$uname,$udom,$csec);
+                           \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
+                           $parmlev,$uname,$udom,$csec,$cgroup);
                 }
                 $r->print("</table></center>");
             } # end each map
@@ -1604,6 +1756,7 @@
         if ($parmlev eq 'general') {
             my $defbgone = '"E0E099"';
             my $defbgtwo = '"FFFF99"';
+            my $defbgthree = '"FFBB99"';
 
 #-------------------------------------------- for each map, gather information
             my $mapid="0.0";
@@ -1658,6 +1811,7 @@
             }
             
             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
+            if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$csec</i></font>\n")};
             $r->print("</h4>\n");
 #---------------------------------------------------------------- print table
             $r->print('<p><table border="2">');
@@ -1668,7 +1822,8 @@
 	    foreach (&keysinorder(\%name,\%keyorder)) {
                 $r->print('<tr>');
                 &print_row($r,$_,\%part,\%name,\%symbp,$mapid,\%default,
-                       \%type,\%display,$defbgone,$defbgtwo,$parmlev,$uname,$udom,$csec);
+                       \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
+                                   $parmlev,$uname,$udom,$csec,$cgroup);
             }
             $r->print("</table></center>");
         } # end of $parmlev eq general
@@ -2376,6 +2531,7 @@
     $alllevs{'Course Level'}='general';
 
     my $csec=$env{'form.csec'};
+    my $cgroup=$env{'form.cgroup'};
 
     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
     my $pschp=$env{'form.pschp'};
@@ -2390,6 +2546,8 @@
             @selected_sections = ('all');
         }
     }
+    my @selected_groups =
+        &Apache::loncommon::get_env_multiple('form.Group');
 
     my $pssymb='';
     my $parmlev='';
@@ -2417,11 +2575,15 @@
 
     $r->print('<table border="1"><tr><td>');  
     &parmmenu($r,\%allparms,\@pscat,\%keyorder);
-    $r->print('</td><td>');
+    $r->print('</td><td><table border="0" cellspacing="0" cellpadding="0">'.
+              '<tr><td>'.&mt('Parts').'</td><td></td><td>'.&mt('Section(s)').
+              '</td><td></td><td>'.&mt('Group(s)').'</td></tr><tr><td>');
     &partmenu($r,\%allparts,\@psprt);
-    $r->print('</td><td>');
+    $r->print('</td><td>&nbsp;</td><td>');
     &sectionmenu($r,\@selected_sections);
-
+    $r->print('</td><td>&nbsp;</td><td>');
+    &groupmenu($r,\@selected_groups);
+    $r->print('</td></tr></table>');
     $r->print('</td></tr></table>');
  
     my $sortorder=$env{'form.sortorder'};
@@ -2436,37 +2598,8 @@
     %{$listdata}=();
 
     foreach my $cat (@pscat) {
-	foreach my $section (@selected_sections) {
-	    foreach my $part (@psprt) {
-                my $rootparmkey=$env{'request.course.id'};
-                if (($section ne 'all') && ($section ne 'none') && ($section)) {
-		    $rootparmkey.='.['.$section.']';
-		}
-		if ($parmlev eq 'general') {
-# course-level parameter
-		    my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
-		    $$listdata{$newparmkey}=1;
-		    $$listdata{$newparmkey.'.type'}=$defkeytype{$cat};
-		} elsif ($parmlev eq 'map') {
-# map-level parameter
-		    foreach my $mapid (keys %allmaps) {
-			if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
-			my $newparmkey=$rootparmkey.'.'.$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
-                        $$listdata{$newparmkey}=1;
-                        $$listdata{$newparmkey.'.type'}=$defkeytype{$cat};
-		    }
-		} else {
-# resource-level parameter
-		    foreach my $rid (@ids) {
-			my ($map,$resid,$url)=&Apache::lonnet::decode_symb($symbp{$rid});
-			if (($pschp ne 'all') && ($allmaps{$pschp} ne $map)) { next; }
-			my $newparmkey=$rootparmkey.'.'.$symbp{$rid}.'.'.$part.'.'.$cat;
-                        $$listdata{$newparmkey}=1;
-                        $$listdata{$newparmkey.'.type'}=$defkeytype{$cat};
-		    }
-		}
-	    }
-	}
+        &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
+        &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
     }
 
     if (($env{'form.store'}) || ($env{'form.dis'})) {
@@ -2486,6 +2619,41 @@
 	      '</form></body></html>');
 }
 
+sub secgroup_lister {
+    my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
+    foreach my $item (@{$selections}) {
+        foreach my $part (@{$psprt}) {
+            my $rootparmkey=$env{'request.course.id'};
+            if (($item ne 'all') && ($item ne 'none') && ($item)) {
+                $rootparmkey.='.['.$item.']';
+            }
+            if ($parmlev eq 'general') {
+# course-level parameter
+                my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
+                $$listdata{$newparmkey}=1;
+                $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
+            } elsif ($parmlev eq 'map') {
+# map-level parameter
+                foreach my $mapid (keys %{$allmaps}) {
+                    if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
+                    my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
+                    $$listdata{$newparmkey}=1;
+                    $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
+                }
+            } else {
+# resource-level parameter
+                foreach my $rid (@{$ids}) {
+                    my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
+                    if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
+                    my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
+                    $$listdata{$newparmkey}=1;
+                    $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
+                }
+            }
+        }
+    }
+}
+
 sub overview {
     my $r=shift;
     my $bodytag=&Apache::loncommon::bodytag('Modify Parameters');
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.683 loncom/lonnet/perl/lonnet.pm:1.684
--- loncom/lonnet/perl/lonnet.pm:1.683	Mon Nov 21 19:01:53 2005
+++ loncom/lonnet/perl/lonnet.pm	Mon Nov 21 21:24:55 2005
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.683 2005/11/22 00:01:53 raeburn Exp $
+# $Id: lonnet.pm,v 1.684 2005/11/22 02:24:55 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -3718,6 +3718,10 @@
     my $role = 'gr/'.&escape($userprivs);
     my ($uname,$udom) = split(/:/,$user);
     my $result = &assignrole($udom,$uname,$url,$role,$end,$start);
+    if ($result eq 'ok') {
+        &devalidate_getgroups_cache($udom,$uname,$cdom,$cnum);
+    }
+
     return $result;
 }
 
@@ -4801,7 +4805,8 @@
         return $env{'course.'.$courseid.'.'.$spacequalifierrest};
     } elsif ($realm eq 'resource') {
 
-	my $section;
+	my ($section,$group);
+        my @groups = ();
 	if (defined($courseid) && $courseid eq $env{'request.course.id'}) {
 	    if (!$symbparm) { $symbparm=&symbread(); }
 	}
@@ -4821,14 +4826,29 @@
 	    if (($env{'user.name'} eq $uname) &&
 		($env{'user.domain'} eq $udom)) {
 		$section=$env{'request.course.sec'};
+                @groups=split(/:/,$env{'request.course.groups'});
+                if (@groups > 0) {
+                    @groups = sort(@groups);
+                    $group = $groups[0];
+                }
 	    } else {
 		if (! defined($usection)) {
 		    $section=&getsection($udom,$uname,$courseid);
 		} else {
 		    $section = $usection;
 		}
+                my $grouplist = &get_users_groups($udom,$uname,$courseid);
+                if ($grouplist) {
+                    @groups = split(/:/,$grouplist);
+                    @groups = sort(@groups);
+                    $group = $groups[0];
+                }
 	    }
 
+            my $grplevel=$courseid.'.['.$group.'].'.$spacequalifierrest;
+            my $grplevelr=$courseid.'.['.$group.'].'.$symbparm;
+            my $grplevelm=$courseid.'.['.$group.'].'.$mapparm;
+
 	    my $seclevel=$courseid.'.['.$section.'].'.$spacequalifierrest;
 	    my $seclevelr=$courseid.'.['.$section.'].'.$symbparm;
 	    my $seclevelm=$courseid.'.['.$section.'].'.$mapparm;
@@ -4846,8 +4866,17 @@
 	    if (defined($userreply)) { return $userreply; }
 
 # ------------------------------------------------ second, check some of course
+            my $coursereply;
+            if (defined($group)) {
+                $coursereply = &resdata($env{'course.'.$courseid.'.num'},
+                                     $env{'course.'.$courseid.'.domain'},
+                                     'course',
+                                     ($grplevelr,$grplevelm,$grplevel,
+                                      $courselevelr));
+                if (defined($coursereply)) { return $coursereply; }
+            }
 
-	    my $coursereply=&resdata($env{'course.'.$courseid.'.num'},
+	    $coursereply=&resdata($env{'course.'.$courseid.'.num'},
 				     $env{'course.'.$courseid.'.domain'},
 				     'course',
 				     ($seclevelr,$seclevelm,$seclevel,

--raeburn1132626295--