You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(53) |
Feb
(56) |
Mar
|
Apr
|
May
(30) |
Jun
(78) |
Jul
(121) |
Aug
(155) |
Sep
(77) |
Oct
(61) |
Nov
(45) |
Dec
(94) |
2006 |
Jan
(116) |
Feb
(33) |
Mar
(11) |
Apr
(23) |
May
(60) |
Jun
(89) |
Jul
(130) |
Aug
(109) |
Sep
(124) |
Oct
(63) |
Nov
(82) |
Dec
(45) |
2007 |
Jan
(31) |
Feb
(35) |
Mar
(123) |
Apr
(36) |
May
(18) |
Jun
(134) |
Jul
(133) |
Aug
(241) |
Sep
(126) |
Oct
(31) |
Nov
(15) |
Dec
(5) |
2008 |
Jan
(11) |
Feb
(6) |
Mar
(16) |
Apr
(29) |
May
(43) |
Jun
(149) |
Jul
(27) |
Aug
(29) |
Sep
(37) |
Oct
(20) |
Nov
(4) |
Dec
(6) |
2009 |
Jan
(34) |
Feb
(30) |
Mar
(16) |
Apr
(6) |
May
(1) |
Jun
(32) |
Jul
(22) |
Aug
(7) |
Sep
(18) |
Oct
(50) |
Nov
(22) |
Dec
(8) |
2010 |
Jan
(17) |
Feb
(15) |
Mar
(10) |
Apr
(9) |
May
(67) |
Jun
(30) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
|
From: Gavin L. v. a. <we...@ma...> - 2005-02-01 21:50:22
|
Log Message: ----------- StudentProgress.pm: clean up from previous commit to clear warning messages. Tags: ---- rel-2-1-a1 Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: StudentProgress.pm Revision Data ------------- Index: StudentProgress.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm,v retrieving revision 1.4.2.4 retrieving revision 1.4.2.5 diff -Llib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm -Llib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm -u -r1.4.2.4 -r1.4.2.5 --- lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm +++ lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm @@ -351,10 +351,6 @@ } else {@myUsers = @userRecords;} - # for versioned sets, if we're keeping track of only the high score - # then we need to know when we change student records - my $prevStuName = 'none'; - foreach my $studentRecord (@myUsers) { next unless ref($studentRecord); my $student = $studentRecord->user_id; @@ -603,22 +599,28 @@ # for versioned set viewing my @columnHdrs = (); # define this for use on all of the sorts - my @paramList = ( 'returning', $r->param('returning'), 'show_best_only', - $showBestOnly, 'show_index', $showColumns{'index'}, - 'show_date', $showColumns{'date'}, - 'show_problems', $showColumns{'problems'}, - 'show_section', $showColumns{'section'}, - 'show_recitation', $showColumns{'recit'}, - 'show_login', $showColumns{'login'} ); - push(@columnHdrs, ($sort_method_name ne 'name' && $sort_method_name ne '') ? CGI::a({'href'=>$self->systemLink($setStatsPage,params=>{sort=>'name', @paramList})},'Name') : 'Name') if ( $showColumns{'name'} ); - push(@columnHdrs, $sort_method_name ne 'score' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'score', @paramList})},'Score') : 'Score') if ( $showColumns{'score'} ); + my %paramList = (); + if ( $setIsVersioned ) { + my $rtng = (defined( $r->param('returning') )) ? + $r->param('returning') : 0; + %paramList = ( 'returning' => $rtng, + 'show_best_only' => $showBestOnly, + 'show_index' => $showColumns{'index'}, + 'show_date' => $showColumns{'date'}, + 'show_problems' => $showColumns{'problems'}, + 'show_section' => $showColumns{'section'}, + 'show_recitation' => $showColumns{'recit'}, + 'show_login' => $showColumns{'login'} ); + } + push(@columnHdrs, (! defined($sort_method_name) || ($sort_method_name ne 'name' && $sort_method_name ne '')) ? CGI::a({'href'=>$self->systemLink($setStatsPage,params=>{'sort'=>'name', %paramList})},'Name') : 'Name') if ( $showColumns{'name'} ); + push(@columnHdrs, (! defined($sort_method_name) || $sort_method_name ne 'score') ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{'sort'=>'score', %paramList})},'Score') : 'Score') if ( $showColumns{'score'} ); push(@columnHdrs, 'Out'.CGI::br().'Of') if ( $showColumns{'outof'} ); push(@columnHdrs, 'Date') if ( $showColumns{'date'} ); - push(@columnHdrs, $sort_method_name ne 'index' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'index', @paramList})},'Ind') : 'Ind') if ( $showColumns{'index'} ); + push(@columnHdrs, (! defined($sort_method_name) || $sort_method_name ne 'index') ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{'sort'=>'index', %paramList})},'Ind') : 'Ind') if ( $showColumns{'index'} ); push(@columnHdrs, 'Problems'.CGI::br().$problem_header) if ( $showColumns{'problems'} ); - push(@columnHdrs, $sort_method_name ne 'section' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'section', @paramList})},'Section') : 'Section') if ( $showColumns{'section'} ); - push(@columnHdrs, $sort_method_name ne 'recitation' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'recitation', @paramList})},'Recitation'):'Recitation') if ( $showColumns{'recit'} ); - push(@columnHdrs, $sort_method_name ne 'user_id' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'user_id', @paramList})},'Login Name'):'Login Name') if ( $showColumns{'login'} ); + push(@columnHdrs, (! defined($sort_method_name) || $sort_method_name ne 'section') ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{'sort'=>'section', %paramList})},'Section') : 'Section') if ( $showColumns{'section'} ); + push(@columnHdrs, (! defined($sort_method_name) || $sort_method_name ne 'recitation') ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{'sort'=>'recitation', %paramList})},'Recitation'):'Recitation') if ( $showColumns{'recit'} ); + push(@columnHdrs, (! defined($sort_method_name) || $sort_method_name ne 'user_id') ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{'sort'=>'user_id', %paramList})},'Login Name'):'Login Name') if ( $showColumns{'login'} ); print CGI::br(), |
From: Gavin L. v. a. <we...@ma...> - 2005-02-01 18:05:35
|
Log Message: ----------- Gateway update of StudentProgress.pm to allow selection of columns shown for versioned sets, and allow showing of only the version with the best score. Tags: ---- rel-2-1-a1 Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: StudentProgress.pm Revision Data ------------- Index: StudentProgress.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm,v retrieving revision 1.4.2.3 retrieving revision 1.4.2.4 diff -Llib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm -Llib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm -u -r1.4.2.3 -r1.4.2.4 --- lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm +++ lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm @@ -262,6 +262,16 @@ my $setStatsPage = $urlpath->newFromModule($urlpath->module,courseID=>$courseName,statType=>'sets',setID=>$setName); my $sort_method_name = $r->param('sort'); my @studentList = $db->listUsers; + +# another versioning/gateway change. in many cases we don't want or need +# all of the columns that are put in here by default, so we add a set of +# flags for which columns to show. for versioned sets we may also want to +# only see the best score, so we include that as an option also. +# defaults: + my %showColumns = ( 'name' => 1, 'score' => 1, 'outof' => 1, + 'date' => 0, 'index' => 1, 'problems' => 1, + 'section' => 1, 'recit' => 1, 'login' => 1 ); + my $showBestOnly = 0; my @index_list = (); # list of all student index my @score_list = (); # list of all student total percentage scores @@ -291,6 +301,20 @@ ( defined($GlobalSet->assignment_type()) && $GlobalSet->assignment_type() =~ /gateway/ ) ? 1 : 0; +# reset column view options based on whether the set is versioned and, if so, +# input parameters + if ( $setIsVersioned ) { + # the returning parameter lets us set defaults for versioned sets + my $ret = $r->param('returning'); + $showColumns{'date'} = $ret ? $r->param('show_date') : 1; + $showColumns{'index'} = $ret ? $r->param('show_index') : 0; + $showColumns{'problems'} = $ret ? $r->param('show_problems') : 0; + $showColumns{'section'} = $ret? $r->param('show_section') : 0; + $showColumns{'recit'} = $ret ? $r->param('show_recitation') : 0; + $showColumns{'login'} = $ret ? $r->param('show_login') : 0; + $showBestOnly = $ret ? $r->param('show_best_only') : 0; + } + ############################################################### # Print tables ############################################################### @@ -326,6 +350,11 @@ } } else {@myUsers = @userRecords;} + + # for versioned sets, if we're keeping track of only the high score + # then we need to know when we change student records + my $prevStuName = 'none'; + foreach my $studentRecord (@myUsers) { next unless ref($studentRecord); my $student = $studentRecord->user_id; @@ -344,6 +373,12 @@ @allSetNames = ( "$setName" ); } + # for versioned sets, we might be keeping only the high score + my $maxScore = -1; + my $max_hash = {}; + # make this global to the student loop + my $act_as_student_url = ''; + foreach my $sN ( @allSetNames ) { my $status = 0; @@ -386,7 +421,12 @@ $longStatus = 'C '; } else { - $longStatus = &threeSpaceFill($longStatus); + # change here to give a more reasonable output for gateways, + # and other versioned sets with only one attempt per version + # FIXME this isn't good in general, when versioned sets might + # FIXME allow multiple submissions + $longStatus = ($setIsVersioned)?'X ': + &threeSpaceFill($longStatus); } } else { @@ -418,13 +458,36 @@ } } + + # for versioned tests we might be displaying the test date + my $dateOfTest = ''; + # annoyingly, this is a set property, so get the set + if ( $setIsVersioned && $showColumns{'date'} ) { + my @userSet = + $db->getMergedVersionedSets( [ $studentRecord->user_id, $setName, $sN ] ); + if ( defined( $userSet[0] ) ) { # if this isn't defined, something's wrong + $dateOfTest = localtime( $userSet[0]->version_creation_time() ); + } else { + $dateOfTest = '???'; + } + } - - my $act_as_student_url = $self->systemLink($urlpath->new(type=>'set_list',args=>{courseID=>$courseName}), + $act_as_student_url = $self->systemLink($urlpath->new(type=>'set_list',args=>{courseID=>$courseName}), params=>{effectiveUser => $studentRecord->user_id} ); + # update for versioned sets +# if ( $setIsVersioned ) { +# $act_as_student_url =~ s/\/$courseName/\/$courseName\/quiz_mode/; +# } + my $email = $studentRecord->email_address; # FIXME this needs formatting + + # change to give better output for gateways + # FIXME this assumes that all versioned sets only allow one attempt + # FIXME per version, which is the case for gateways but probably not others + my $longtwo = ( $setIsVersioned ) ? $string : + "$string\n$twoString"; my $avg_num_attempts = ($num_of_problems) ? $num_of_attempts/$num_of_problems : 0; my $successIndicator = ($avg_num_attempts) ? ($totalRight/$total)**2/$avg_num_attempts : 0 ; @@ -436,19 +499,57 @@ index => $successIndicator, section => $studentRecord->section, recitation => $studentRecord->recitation, - problemString => "<pre>$string\n$twoString</pre>", + problemString => "<pre>$longtwo</pre>", act_as_student => $act_as_student_url, email_address => $studentRecord->email_address, problemData => {%h_problemData}, + date => $dateOfTest, }; + + # keep track of best score + if ( $totalRight > $maxScore ) { + $maxScore = $totalRight; + $max_hash = { %$temp_hash }; + } + + # if we're showing all records, add it in to the list + if ( ! $showBestOnly ) { # add this data to the list of total scores (out of 100) # add this data to the list of success indices. push( @index_list, $temp_hash->{index}); push( @score_list, ($temp_hash->{total}) ?$temp_hash->{score}/$temp_hash->{total} : 0 ) ; push( @augmentedUserRecords, $temp_hash ); - } - } + } + # if we're showing only the best score, add the best score now + if ( $showBestOnly ) { + if ( ! %$max_hash ) { # then we have no tests---e.g., for proctors + next; # if we could exclude proctors, etc., we + # might want to keep these: + $max_hash = { user_id => $studentRecord->user_id(), + last_name => $studentRecord->last_name(), + first_name => $studentRecord->first_name(), + score => 0, + total => 'n/a', + index => 0, + section => $studentRecord->section(), + recitation => $studentRecord->recitation(), + problemString => 'no attempt recorded', + act_as_student => $act_as_student_url, + email_address => $studentRecord->email_address(), + problemData => {}, + date => 'none', + } + } + push( @index_list, $max_hash->{index} ); + push( @score_list, + ($max_hash->{total} && $max_hash->{total} ne 'n/a') ? + $max_hash->{score}/$max_hash->{total} : 0 ); + push( @augmentedUserRecords, $max_hash ); + } + + } + $WeBWorK::timer->continue("end mainloop") if defined($WeBWorK::timer); @augmentedUserRecords = sort { &$sort_method($a,$b) @@ -458,7 +559,66 @@ ##################################################################################### # construct header my $problem_header = ''; - + +# changes for gateways/versioned sets here. in this case we allow instructors +# to modify the appearance of output, which we do with a form. so paste in the +# form header here, and make appropriate modifications + my $verSelectors = ''; + if ( $setIsVersioned ) { + print CGI::start_form({'method' => 'post', + 'action' => $self->systemLink($urlpath, + authen=>0), + 'name' => 'StudentProgress'}); + print $self->hidden_authen_fields(); + + $verSelectors = CGI::p({'style'=>'background-color:#eeeeee;color:black;'}, + "Display options: Show ", + CGI::hidden(-name=>'returning', -value=>'1'), + CGI::checkbox(-name=>'show_best_only', -value=>'1', + -checked=>$showBestOnly, + -label=>' only best scores; '), + CGI::checkbox(-name=>'show_index', -value=>'1', + -checked=>$showColumns{'index'}, + -label=>' success indicator; '), + CGI::checkbox(-name=>'show_date', -value=>'1', + -checked=>$showColumns{'date'}, + -label=>' test date; '), + CGI::checkbox(-name=>'show_problems', -value=>'1', + -checked=>$showColumns{'problems'}, + -label=>'problems;'), "\n", CGI::br(), "\n", + CGI::checkbox(-name=>'show_section', -value=>'1', + -checked=>$showColumns{'section'}, + -label=>' section #; '), + CGI::checkbox(-name=>'show_recitation', -value=>'1', + -checked=>$showColumns{'recit'}, + -label=>' recitation #; '), + CGI::checkbox(-name=>'show_login', -value=>'1', + -checked=>$showColumns{'login'}, + -label=>'login'), "\n", CGI::br(), "\n", + CGI::submit(-value=>'Update Display') + ); + } + +# set up a column header variable to allow us to drop certain columns +# for versioned set viewing + my @columnHdrs = (); +# define this for use on all of the sorts + my @paramList = ( 'returning', $r->param('returning'), 'show_best_only', + $showBestOnly, 'show_index', $showColumns{'index'}, + 'show_date', $showColumns{'date'}, + 'show_problems', $showColumns{'problems'}, + 'show_section', $showColumns{'section'}, + 'show_recitation', $showColumns{'recit'}, + 'show_login', $showColumns{'login'} ); + push(@columnHdrs, ($sort_method_name ne 'name' && $sort_method_name ne '') ? CGI::a({'href'=>$self->systemLink($setStatsPage,params=>{sort=>'name', @paramList})},'Name') : 'Name') if ( $showColumns{'name'} ); + push(@columnHdrs, $sort_method_name ne 'score' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'score', @paramList})},'Score') : 'Score') if ( $showColumns{'score'} ); + push(@columnHdrs, 'Out'.CGI::br().'Of') if ( $showColumns{'outof'} ); + push(@columnHdrs, 'Date') if ( $showColumns{'date'} ); + push(@columnHdrs, $sort_method_name ne 'index' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'index', @paramList})},'Ind') : 'Ind') if ( $showColumns{'index'} ); + push(@columnHdrs, 'Problems'.CGI::br().$problem_header) if ( $showColumns{'problems'} ); + push(@columnHdrs, $sort_method_name ne 'section' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'section', @paramList})},'Section') : 'Section') if ( $showColumns{'section'} ); + push(@columnHdrs, $sort_method_name ne 'recitation' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'recitation', @paramList})},'Recitation'):'Recitation') if ( $showColumns{'recit'} ); + push(@columnHdrs, $sort_method_name ne 'user_id' ? CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'user_id', @paramList})},'Login Name'):'Login Name') if ( $showColumns{'login'} ); print CGI::br(), @@ -476,21 +636,11 @@ "Click on student's name to see the student's version of the problem set; Click heading to sort table. ", CGI::br(), + $verSelectors, CGI::br(), defined($sort_method_name) ?" sort method is $sort_method_name":"", CGI::start_table({-border=>5,style=>'font-size:smaller'}), - CGI::Tr(CGI::td( {-align=>'left'}, - [CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'name' })},'Name'), - CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'score'})},'Score'), - 'Out'.CGI::br().'Of', - CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'index'})},'Ind'), - 'Problems'.CGI::br().$problem_header, - CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'section'})},'Section'), - CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'recitation'})},'Recitation'), - CGI::a({"href"=>$self->systemLink($setStatsPage,params=>{sort=>'user_id'})},'Login Name'), - ]) - - ); + CGI::Tr(CGI::td( {-align=>'left'}, [ @columnHdrs ])); my $prevFullName = ''; my $vNum = 1; @@ -503,25 +653,31 @@ my $nameEntry = ''; if ( $fullName eq $prevFullName ) { $vNum++; - $nameEntry = CGI::td({-align=>"right"}, "(v$vNum)"); + $nameEntry = CGI::span({-style=>"text-align:right;"}, + "(v$vNum)"); } else { - $nameEntry = CGI::td(CGI::a({-href=>$rec->{act_as_student}},$fullName), ($setIsVersioned ? ' (v1)' : ''), CGI::br(), CGI::a({-href=>"mailto:$email"},$email)); + $nameEntry = + CGI::a({-href=>$rec->{act_as_student}},$fullName) . + ($setIsVersioned && ! $showBestOnly ? ' (v1)' : ' ') . + CGI::br() . CGI::a({-href=>"mailto:$email"},$email); $vNum = 1; $prevFullName = $fullName; } + # build set of columns that we want + my @cols = (); + push(@cols, $nameEntry) if ($showColumns{'name'}); + push(@cols, sprintf("%0.2f",$rec->{score})) if ($showColumns{'score'}); + push(@cols, $rec->{total}) if ( $showColumns{'outof'} ); + push(@cols, $self->nbsp($rec->{date})) if ($showColumns{'date'}); + push(@cols, sprintf("%0.0f",100*($rec->{index}))) if ($showColumns{'index'}); + push(@cols, $rec->{problemString}) if ($showColumns{'problems'}); + push(@cols, $self->nbsp($rec->{section})) if ($showColumns{'section'}); + push(@cols, $self->nbsp($rec->{recitation})) if ($showColumns{'recit'}); + push(@cols, $rec->{user_id}) if ($showColumns{'login'}); - print CGI::Tr( + print CGI::Tr( CGI::td( [ @cols ] ) ); # CGI::td(CGI::a({-href=>$rec->{act_as_student}},$fullName), CGI::br(), CGI::a({-href=>"mailto:$email"},$email)), - $nameEntry, - CGI::td( sprintf("%0.2f",$rec->{score}) ), # score - CGI::td($rec->{total}), # out of - CGI::td(sprintf("%0.0f",100*($rec->{index}) )), # indicator - CGI::td($rec->{problemString}), # problems - CGI::td($self->nbsp($rec->{section})), - CGI::td($self->nbsp($rec->{recitation})), - CGI::td($rec->{user_id}), - - ); + } print CGI::end_table(); |
From: jj v. a. <we...@ma...> - 2005-01-29 01:45:56
|
Log Message: ----------- Removes starting and ending whitespace from most of the form field entries when adding users. Some instructors add students by doing copy/paste from elsewhere. This frequently picks up whitespace which causes the user id field to fail in checkKeyFields. Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: AddUsers.pm Revision Data ------------- Index: AddUsers.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/AddUsers.pm,v retrieving revision 1.16 retrieving revision 1.17 diff -Llib/WeBWorK/ContentGenerator/Instructor/AddUsers.pm -Llib/WeBWorK/ContentGenerator/Instructor/AddUsers.pm -u -r1.16 -r1.17 --- lib/WeBWorK/ContentGenerator/Instructor/AddUsers.pm +++ lib/WeBWorK/ContentGenerator/Instructor/AddUsers.pm @@ -47,7 +47,7 @@ my $numberOfStudents = $r->param('number_of_students'); warn "Internal error -- the number of students to be added has not been included" unless defined $numberOfStudents; foreach my $i (1..$numberOfStudents) { - my $new_user_id = $r->param("new_user_id_$i"); + my $new_user_id = trim_spaces($r->param("new_user_id_$i")); my $new_password = cryptPassword($r->param("student_id_$i")); next unless defined($new_user_id) and $new_user_id; push @userIDs, $new_user_id; @@ -59,13 +59,13 @@ $newPermissionLevel->user_id($new_user_id); $newPassword->user_id($new_user_id); $newPassword->password($new_password); - $newUser->last_name($r->param("last_name_$i")); - $newUser->first_name($r->param("first_name_$i")); - $newUser->student_id($r->param("student_id_$i")); - $newUser->email_address($r->param("email_address_$i")); - $newUser->section($r->param("section_$i")); - $newUser->recitation($r->param("recitation_$i")); - $newUser->comment($r->param("comment_$i")); + $newUser->last_name(trim_spaces($r->param("last_name_$i"))); + $newUser->first_name(trim_spaces($r->param("first_name_$i"))); + $newUser->student_id(trim_spaces($r->param("student_id_$i"))); + $newUser->email_address(trim_spaces($r->param("email_address_$i"))); + $newUser->section(trim_spaces($r->param("section_$i"))); + $newUser->recitation(trim_spaces($r->param("recitation_$i"))); + $newUser->comment(trim_spaces($r->param("comment_$i"))); $newUser->status('C'); $newPermissionLevel->permission(0); #FIXME handle errors if user exists already @@ -204,6 +204,14 @@ #or check individual users and click "save" at the bottom. </div> #Soon ( real soon -- honest!!! :-) ) you will also be able to assign sets to the students as they are entered from this page. } ); +} + + +## Utility function to trim whitespace off the start and end of its input +sub trim_spaces { + my $in = shift; + $in =~ s/^\s*(.*?)\s*$/$1/; + return($in); } 1; |
From: Mike G. v. a. <we...@ma...> - 2005-01-29 01:40:10
|
Log Message: ----------- Fixed problem with hardcopy editing. This case had simply not been handled in the code even though it's the same behavior for hardcopy headers as it is for screen headers. This fixes bug #763 Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: PGProblemEditor.pm Revision Data ------------- Index: PGProblemEditor.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v retrieving revision 1.51 retrieving revision 1.52 diff -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -u -r1.51 -r1.52 --- lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm +++ lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm @@ -294,7 +294,7 @@ # FIXME: even with an error we still open a new page because of the target specified in the form - # Some cases do not need a redirect revert, no fresh_edit + # Some cases do not need a redirect: revert, fresh_edit my $action = $self->{action}; return unless $action eq 'save' @@ -400,7 +400,7 @@ # redirect to ProblemSet.pm ###################################### - $file_type eq 'set_header' and do { + ($file_type eq 'set_header' or $file_type eq 'hardcopy_header' ) and do { if ($action eq 'save_as') { # redirect to myself my $sourceFilePath = $self->{problemPath}; # strip off template directory prefix @@ -485,9 +485,9 @@ my $tempFilePath = $self->{tempFilePath}; # path to the file currently being worked with (might be a .tmp file) my $inputFilePath = $self->{inputFilePath}; # path to the file for input, (might be a .tmp file) - my $protected_file = not -w $inputFilePath; + my $protected_file = (not -w $inputFilePath ) and -e $inputFilePath; #FIXME -- let's try to insure that the input file always exists, even for revert. $self->addbadmessage("Changes in this file have not yet been permanently saved.") if -r $tempFilePath; - $self->addbadmessage("This file protected! To edit this text you must first use 'Save As' to save it to another file.") if $protected_file; + $self->addbadmessage("This file |$inputFilePath| is protected! To edit this text you must first use 'Save As' to save it to another file.") if $protected_file; } @@ -951,7 +951,7 @@ ($action eq 'add_problem_to_set') and do { my $sourceFile = $editFilePath; my $targetSetName = $r->param('target_set'); - my $freeProblemID; + my $freeProblemID = WeBWorK::Utils::max($db->listGlobalProblems($setName)) + 1; $sourceFile =~ s|^$ce->{courseDirs}->{templates}/||; my $problemRecord = $self->addProblemToSet( setName => $targetSetName, |
From: Mike G. v. a. <we...@ma...> - 2005-01-29 01:37:32
|
Log Message: ----------- CourseID is now part of the subject line when feedback is sent. This allows you to filter out feedback by course, which is handy for those of use receiving lots of feedback emails. Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator: Feedback.pm Revision Data ------------- Index: Feedback.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Feedback.pm,v retrieving revision 1.24 retrieving revision 1.25 diff -Llib/WeBWorK/ContentGenerator/Feedback.pm -Llib/WeBWorK/ContentGenerator/Feedback.pm -u -r1.24 -r1.25 --- lib/WeBWorK/ContentGenerator/Feedback.pm +++ lib/WeBWorK/ContentGenerator/Feedback.pm @@ -76,6 +76,8 @@ my $showSolutions = $r->param("showSolutions"); my $from = $r->param("from"); my $feedback = $r->param("feedback"); + my $courseID = $r->urlpath->arg("courseID"); + my ($user, $set, $problem); $user = $db->getUser($userName) # checked @@ -198,7 +200,7 @@ # *** we might want to have a CE setting for # "additional recipients" smtp => $ce->{mail}->{smtpServer}, - subject => "WeBWorK feedback: ".$user->first_name." ".$user->last_name. + subject => "WeBWorK feedback from $courseID: ".$user->first_name." ".$user->last_name. ( ( defined($setName) && defined($problemNumber) ) ? " set$setName/prob$problemNumber" : "" ), |
From: Mike G. v. a. <we...@ma...> - 2005-01-29 01:36:09
|
Log Message: ----------- Better error message if there is a multiply defined user. Modified Files: -------------- webwork-modperl/lib/WeBWorK: ContentGenerator.pm Revision Data ------------- Index: ContentGenerator.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator.pm,v retrieving revision 1.132 retrieving revision 1.133 diff -Llib/WeBWorK/ContentGenerator.pm -Llib/WeBWorK/ContentGenerator.pm -u -r1.132 -r1.133 --- lib/WeBWorK/ContentGenerator.pm +++ lib/WeBWorK/ContentGenerator.pm @@ -1527,7 +1527,7 @@ } #FIXME -- evntually we'd like to catch where this happens if ($name eq 'user' and @values >1 ) { - warn "internal error -- user has been multiply defined!"; + warn "internal error -- user has been multiply defined! You may need to logout and log back in to correct this."; my $user = $r->param("user"); $r->param(user => $user); @values = ($user); |
From: Mike G. v. a. <we...@ma...> - 2005-01-29 01:34:48
|
Log Message: ----------- Adds checks to make sure that the multiple user problem is really gone. Modified Files: -------------- webwork-modperl/lib/WeBWorK: Authen.pm Revision Data ------------- Index: Authen.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/Authen.pm,v retrieving revision 1.37 retrieving revision 1.38 diff -Llib/WeBWorK/Authen.pm -Llib/WeBWorK/Authen.pm -u -r1.37 -r1.38 --- lib/WeBWorK/Authen.pm +++ lib/WeBWorK/Authen.pm @@ -196,7 +196,8 @@ my $force_passwd_authen = $r->param('force_passwd_authen'); my $login_practice_user = $r->param('login_practice_user'); my $send_cookie = $r->param("send_cookie"); - + my @temp_users = $r->param("user"); + warn "users start out as ", join(" ", @temp_users) if @temp_users >1; my $error; my $failWithoutError = 0; my $credentialSource = "params"; @@ -240,6 +241,7 @@ $user = $cookieUser; $key = $cookieKey; $r->param("user", $user); + #$r->args->{user} = $user; $r->param("key", $key); $credentialSource = "cookie"; } else { @@ -384,6 +386,18 @@ # neither a key or a password were supplied. $error = "You must enter a password." } + ############################################# + # Check for multiply defined users + ############################################ + my @test_users = $r->param("user"); + if (@test_users>1) { + warn "User has been multiply defined in Authen.pm ", join(" ", @test_users) ; + $r->param("user"=>$test_users[0]); + @test_users = $r->param("user"); + warn "New value of user is ", join(" ", @test_users); + } + ##### end check ###################### + if (defined $error) { # authentication failed, store the error message |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 21:40:49
|
Log Message: ----------- Added WWDBv3 and stylesheet settings from my local copy. Modified Files: -------------- webwork2/conf: global.conf.dist Revision Data ------------- Index: global.conf.dist =================================================================== RCS file: /webwork/cvs/system/webwork2/conf/global.conf.dist,v retrieving revision 1.115 retrieving revision 1.116 diff -Lconf/global.conf.dist -Lconf/global.conf.dist -u -r1.115 -r1.116 --- conf/global.conf.dist +++ conf/global.conf.dist @@ -28,7 +28,7 @@ ################################################################################ # Set these variables to correspond to your configuration and preferences. You -# will need to restart the webserver to reset the variables in this section +# will need to restart the webserver to reset the variables in this section. # URL of WeBWorK handler. $webwork_url = "/webwork2"; @@ -49,6 +49,7 @@ ################################################################################ $externalPrograms{mkdir} = "/bin/mkdir"; +$externalPrograms{mv} = "/bin/mv"; $externalPrograms{mysql} = "/usr/local/bin/mysql"; $externalPrograms{latex} = "/usr/local/bin/latex"; @@ -162,6 +163,9 @@ # URL of WeBWorK Bugzilla database. $webworkURLs{bugReporter} = "http://bugs.webwork.rochester.edu/"; +# Location of CSS +$webworkURLs{stylesheet} = "$webworkURLs{htdocs}/css/ur.css"; + # Location of jsMath script, used for the jsMath display mode. $webworkURLs{jsMath} = "$webworkURLs{htdocs}/jsMath/jsMath.js"; @@ -252,9 +256,9 @@ # The set header is displayed on the problem set page. It is a PG file. $webworkFiles{screenSnippets}{setHeader} = "$webworkDirs{conf}/snippets/setHeader.pg"; # screenSetHeader.pg" +# A PG template for creation of new problems. $webworkFiles{screenSnippets}{blankProblem} = "$webworkDirs{conf}/snippets/blankProblem.pg"; # screenSetHeader.pg" - ################################################################################ # Course-specific files ################################################################################ @@ -295,7 +299,22 @@ }; ################################################################################ -# Database options +# Database options (WWDBv3) +################################################################################ + +# The four arguments passed to the DBI::connect() method. See the DBI manual for +# more information. +$wwdbv3_settings{dsn} = "dbi:mysql:wwdbv3"; +$wwdbv3_settings{user} = "wwdbv3"; +$wwdbv3_settings{pass} = "xyzzy"; +$wwdbv3_settings{attr} = {}; + +# WWDBv3 needs a lock file to prevent concurrent database upgrades. The file +# will be locked with flock(). +$wwdbv3_settings{upgrade_lock} = "$webworkDirs{tmp}/wwdbv3_upgrade.lock"; + +################################################################################ +# Database options (WWDBv2) ################################################################################ # Several database are defined in the file conf/database.conf and stored in the |
From: Sam H. v. a. <act...@de...> - 2005-01-28 01:29:36
|
Log Message: ----------- HEAD backport: Changed some UI features. In particular the scrolling list is now used both for selecting students to send mail to AND for selecting the preview message (if multiple students are selected the first is used as the preview). The "command table" is now one line taller than it was, but it it now effectively narrower (just two columns) -- the last column has only the row and column options and is not used that much. (gage) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: SendMail.pm Revision Data ------------- Index: SendMail.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm,v retrieving revision 1.38 retrieving revision 1.38.2.1 diff -Llib/WeBWorK/ContentGenerator/Instructor/SendMail.pm -Llib/WeBWorK/ContentGenerator/Instructor/SendMail.pm -u -r1.38 -r1.38.2.1 --- lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm +++ lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm @@ -31,7 +31,8 @@ use WeBWorK::HTML::ScrollingRecordList qw/scrollingRecordList/; use WeBWorK::Utils::FilterRecords qw/filterRecords/; -my $REFRESH_RESIZE_BUTTON = "Set preview to: "; # handle submit value idiocy +#my $REFRESH_RESIZE_BUTTON = "Set preview to: "; # handle submit value idiocy +my $UPDATE_SETTINGS_BUTTON = "Update settings and refresh page"; # handle submit value idiocy sub initialize { my ($self) = @_; my $r = $self->r; @@ -79,8 +80,10 @@ $self->{default_msg_file} = $default_msg_file; $self->{old_default_msg_file} = $old_default_msg_file; $self->{merge_file} = (defined($r->param('merge_file' ))) ? $r->param('merge_file') : 'None'; - $self->{preview_user} = (defined($r->param('preview_user'))) ? $r->param('preview_user') : $user; - + #$self->{preview_user} = (defined($r->param('preview_user'))) ? $r->param('preview_user') : $user; + # an expermiment -- share the scrolling list for preivew and sendTo actions. + my @classList = (defined($r->param('classList'))) ? $r->param('classList') : ($user); + $self->{preview_user} = $classList[0] || $user; ############################################################################################# # gather database data @@ -303,8 +306,8 @@ my $script_action = ''; - if(not defined($action) or $action eq 'Open' or $action eq $REFRESH_RESIZE_BUTTON or $action eq 'Sort by' - or $action eq 'Set merge file to:' ){ + if(not defined($action) or $action eq 'Open' + or $action eq $UPDATE_SETTINGS_BUTTON ){ return ''; } @@ -509,7 +512,7 @@ my $permissionLevelTemplate = $db->newPermissionLevel; # This code will require changing if the permission and user tables ever have different keys. - my @users = @{ $self->{ra_users} }; + my @users = sort @{ $self->{ra_users} }; my $ra_user_records = $self->{ra_user_records}; my %classlistLabels = ();# %$hr_classlistLabels; foreach my $ur (@{ $ra_user_records }) { @@ -525,6 +528,7 @@ default_filters => ["all"], size => 5, multiple => 1, + refresh_button_name =>'Update settings and refresh page', }, @{$ra_user_records}); ############################################################################################################## @@ -563,17 +567,31 @@ # first column ############################################################################################# - CGI::td(CGI::strong("Message file: $input_file"),"\n",CGI::br(), + CGI::td(CGI::strong("Message file: "), $input_file,"\n",CGI::br(), CGI::submit(-name=>'action', -value=>'Open'), ' ',"\n", CGI::popup_menu(-name=>'openfilename', -values=>\@sorted_messages, -default=>$input_file - ), "\n",CGI::br(), - - "Save file to: $output_file","\n",CGI::br(), - "\n", 'From:',' ', CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1), - "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1), - "\n", CGI::br(),'Subject: ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>30, -override=>1), + ), + "\n",CGI::br(), + CGI::strong("Save file to: "), $output_file, + "\n",CGI::br(), + CGI::strong('Merge file: '), $merge_file, + CGI::br(), + CGI::popup_menu(-name=>'merge_file', + -values=>\@sorted_merge_files, + -default=>$merge_file, + ), "\n", + "\n", + #CGI::hr(), + CGI::div({style=>"background-color: #CCCCCC"}, + "\n", 'From:',' ', CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1), + "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1), + "\n", CGI::br(),'Subject: ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>30, -override=>1), + ), + #CGI::hr(), + CGI::submit(-name=>'action', -value=>$UPDATE_SETTINGS_BUTTON), + ), ############################################################################################# # second column @@ -591,7 +609,11 @@ CGI::radio_group(-name=>'radio', -values=>['all_students','studentID'], -labels=>{all_students=>'All students in course',studentID => 'Selected students'}, -default=>'studentID', -linebreak=>0), - CGI::br(),$scrolling_user_list), + CGI::br(),$scrolling_user_list, + CGI::i("Preview set to: "), $preview_record->last_name, + CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview message'),' ', + ), + ## Edit here to insert filtering ## be sure to fail GRACEFULLY! # @@ -620,28 +642,30 @@ # third column ############################################################################################# CGI::td({align=>'left'}, - "<b>Merge file:</b> $merge_file", CGI::br(), - CGI::submit(-name=>'action', -value=>'Set merge file to:'),CGI::br(), - CGI::popup_menu(-name=>'merge_file', - -values=>\@sorted_merge_files, - -default=>$merge_file, - ), "\n",CGI::hr(), - CGI::b("Viewing email for: "), "$preview_user",CGI::br(), - CGI::submit(-name=>'action', -value=>'resize', -label=>$REFRESH_RESIZE_BUTTON),' ', - CGI::popup_menu(-name=>'preview_user', - -values=>\@users, - #-labels=>\%classlistLabels, - -default=>$preview_user, - ), - CGI::br(), - CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview message'),' ', - - CGI::br(), - - CGI::hr(), +# "<b>Merge file:</b> $merge_file", CGI::br(), +# CGI::submit(-name=>'action', -value=>'Set merge file to:'),CGI::br(), +# CGI::popup_menu(-name=>'merge_file', +# -values=>\@sorted_merge_files, +# -default=>$merge_file, +# ), "\n", +# CGI::hr(), +# CGI::b("Viewing email for: "), "$preview_user",CGI::br(), +# CGI::submit(-name=>'action', -value=>'resize', -label=>$REFRESH_RESIZE_BUTTON),' ', +# CGI::popup_menu(-name=>'preview_user', +# -values=>\@users, +# #-labels=>\%classlistLabels, +# -default=>$preview_user, +# ), +# CGI::br(), +# CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview message'),' ', +# +# CGI::br(), +# +# CGI::hr(), " Rows: ", CGI::textfield(-name=>'rows', -size=>3, -value=>$rows), " Columns: ", CGI::textfield(-name=>'columns', -size=>3, -value=>$columns), - CGI::br(),CGI::i('Press any action button to update display'),CGI::br(), + CGI::br(), +# CGI::i('Press any action button to update display'),CGI::br(), #show available macros CGI::popup_menu( -name=>'dummyName', |
From: Mike G. v. a. <we...@ma...> - 2005-01-28 01:20:15
|
Log Message: ----------- I believe this will fix the bug which sometimes causes multiple users to appear in the parameters. The problem is that Login.pm filters out user, key, passwd values and then passes the remaining values to hidden_fields to be printed on the "relogin" page. Unfortunately if hidden_fields is passed an empty array then it prints ALL values in the parameter hash as hidden fields. So if only user and key are present they will be printed as hidden fields. If user, key and a non-filtered paramter value are present then only the non-filtered parameter value will be printed. The current fix is a conditional which doesn't call hidden_fields at all if there are no parameters left after the filtering operation. --Mike Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator: Login.pm Revision Data ------------- Index: Login.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Login.pm,v retrieving revision 1.23 retrieving revision 1.24 diff -Llib/WeBWorK/ContentGenerator/Login.pm -Llib/WeBWorK/ContentGenerator/Login.pm -u -r1.23 -r1.24 --- lib/WeBWorK/ContentGenerator/Login.pm +++ lib/WeBWorK/ContentGenerator/Login.pm @@ -106,12 +106,16 @@ print CGI::startform({-method=>"POST", -action=>$r->uri}); - # write out the form data posted to the requested URI - #print $self->print_form_data('<input type="hidden" name="','" value="',"\"/>\n",qr/^(user|passwd|key|force_passwd_authen)$/); # preserve the form data posted to the requested URI my @fields_to_print = grep { not m/^(user|passwd|key|force_passwd_authen)$/ } $r->param; - print $self->hidden_fields(@fields_to_print); + + #FIXME: This next line can be removed in time. MEG 1/27/2005 + warn "Error in filtering fields : |", join("|",@fields_to_print),"|" if grep {m/user/} @fields_to_print; + + # Important note. If hidden_fields is passed an empty array it prints ALL parameters as hidden fields. + # That is not what we want in this case, so we don't print at all if @fields_to_print is empty. + print $self->hidden_fields(@fields_to_print) if @fields_to_print > 0; print CGI::table({class=>"FormLayout"}, CGI::Tr([ |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 01:03:45
|
Log Message: ----------- HEAD backport: new regexp matching can now match on permission level too (toenail) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: UserList.pm Revision Data ------------- Index: UserList.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/UserList.pm,v retrieving revision 1.60.2.1 retrieving revision 1.60.2.2 diff -Llib/WeBWorK/ContentGenerator/Instructor/UserList.pm -Llib/WeBWorK/ContentGenerator/Instructor/UserList.pm -u -r1.60.2.1 -r1.60.2.2 --- lib/WeBWorK/ContentGenerator/Instructor/UserList.pm +++ lib/WeBWorK/ContentGenerator/Instructor/UserList.pm @@ -622,6 +622,12 @@ my @userIDs; foreach my $record (@userRecords) { next unless $record; + + # add permission level to user record hash so we can match it if necessary + if ($field eq "permission") { + my $permissionLevel = $db->getPermissionLevel($record->user_id); + $record->{permission} = $permissionLevel->permission; + } push @userIDs, $record->user_id if $record->{$field} =~ /^$regex/i; } $self->{visibleUserIDs} = \@userIDs; |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 01:02:27
|
Log Message: ----------- HEAD backport: Fixed a bug with the file editor that did not process the file name correctly in the top-level directory. Fixed a bug in uploading a file where the name was given a sequence number even when one was not needed. (dpvc) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: FileManager.pm Revision Data ------------- Index: FileManager.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm,v retrieving revision 1.5.2.1 retrieving revision 1.5.2.2 diff -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -u -r1.5.2.1 -r1.5.2.2 --- lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm +++ lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm @@ -373,7 +373,8 @@ my $pwd = $self->{pwd}; if ($filename) { $pwd = substr($filename,length($self->{courseRoot})+1); - $pwd =~ s!/([^/]*)$!!; $filename = $1; + $pwd =~ s!(/|^)([^/]*)$!!; $filename = $2; + $pwd = '.' if $pwd eq ''; } else { $filename = $self->getFile("save"); return unless $filename; } @@ -776,6 +777,7 @@ # sub uniqueName { my $dir = shift; my $name = shift; + return $name unless (-e "$dir/$name"); my $type = ""; my $n = -1; $type = $1 if ($name =~ s/(\.[^.]*)$//); $n = $1 if ($name =~ s/(\d+)$//); |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:59:10
|
Log Message: ----------- HEAD backport: Fixed index problem with matrix multiplciation (dpvc) Tags: ---- rel-2-1-patches Modified Files: -------------- pg/lib/Value: Matrix.pm Revision Data ------------- Index: Matrix.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Matrix.pm,v retrieving revision 1.12 retrieving revision 1.12.2.1 diff -Llib/Value/Matrix.pm -Llib/Value/Matrix.pm -u -r1.12 -r1.12.2.1 --- lib/Value/Matrix.pm +++ lib/Value/Matrix.pm @@ -233,9 +233,9 @@ # my @l = $l->value; my @r = $r->value; my @M = (); - foreach my $j (0..$dr[1]-1) { + foreach my $i (0..$dl[0]-1) { my @row = (); - foreach my $i (0..$dl[0]-1) { + foreach my $j (0..$dr[1]-1) { my $s = 0; foreach my $k (0..$dl[1]-1) {$s += $l[$i]->[$k] * $r[$k]->[$j]} push(@row,$s); |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:51:40
|
Log Message: ----------- HEAD backport: Catch multiply defined user warning (gage) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK: ContentGenerator.pm Revision Data ------------- Index: ContentGenerator.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator.pm,v retrieving revision 1.123.2.1 retrieving revision 1.123.2.2 diff -Llib/WeBWorK/ContentGenerator.pm -Llib/WeBWorK/ContentGenerator.pm -u -r1.123.2.1 -r1.123.2.2 --- lib/WeBWorK/ContentGenerator.pm +++ lib/WeBWorK/ContentGenerator.pm @@ -1378,7 +1378,8 @@ } elsif (defined $r->param($name)) { @values = $r->param($name); } - + #FIXME -- evntually we'd like to catch where this happens + croak "internal error -- user has been multiply defined!" if $name eq 'user' and @values >1; if (@values) { if ($first) { $url .= "?"; |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:48:00
|
Log Message: ----------- HEAD backport: Work around MSIE bug (dpvc) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: FileManager.pm Revision Data ------------- Index: FileManager.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm,v retrieving revision 1.5 retrieving revision 1.5.2.1 diff -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -u -r1.5 -r1.5.2.1 --- lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm +++ lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm @@ -224,7 +224,7 @@ print CGI::Tr({valign=>"middle"}, CGI::td(CGI::scrolling_list( -name => "files", id => "files", - -style => "font-family:monospace; width:30em; height:100%", + -style => "font-family:monospace; width:30em", -size => 15, -multiple => 1, -values => $files, |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:46:01
|
Log Message: ----------- HEAD backport: Fixed minor display problem where empty (not-overriden) date values were being displayed as 12/31/1969 (toenail) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: ProblemSetDetail.pm Revision Data ------------- Index: ProblemSetDetail.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm,v retrieving revision 1.13.2.1 retrieving revision 1.13.2.2 diff -Llib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm -Llib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm -u -r1.13.2.1 -r1.13.2.2 --- lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm +++ lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm @@ -85,7 +85,7 @@ size => "26", override => "any", labels => { - 0 => "None Specified", + #0 => "None Specified", "" => "None Specified", }, }, @@ -95,7 +95,7 @@ size => "26", override => "any", labels => { - 0 => "None Specified", + #0 => "None Specified", "" => "None Specified", }, }, @@ -105,7 +105,7 @@ size => "26", override => "any", labels => { - 0 => "None Specified", + #0 => "None Specified", "" => "None Specified", }, }, @@ -208,8 +208,8 @@ if ($forUsers) { $output .= CGI::Tr( CGI::th({colspan=>"2"}, " "), - CGI::th({colspan=>"1"}, "Individual set dates"), - CGI::th({}, "Class set dates"), + CGI::th({colspan=>"1"}, "User Values"), + CGI::th({}, "Class values"), ); } @@ -274,8 +274,8 @@ $userValue = (defined($userValue)) ? ($labels{$userValue || ""} || $userValue) : ""; if ($field =~ /_date/) { - $globalValue = $self->formatDateTime($globalValue) if $globalValue; - $userValue = $self->formatDateTime($userValue) if $userValue; + $globalValue = $self->formatDateTime($globalValue) if defined $globalValue && $globalValue ne $labels{""}; + $userValue = $self->formatDateTime($userValue) if defined $userValue && $userValue ne $labels{""}; } # check to make sure that a given value can be overridden @@ -319,7 +319,7 @@ name => "$recordType.$recordID.$field.override", label => "", value => $field, - checked => $r->param("$recordType.$recordID.$field.override") || ($userValue ne "" ? 1 : 0), + checked => $r->param("$recordType.$recordID.$field.override") || ($userValue ne ($labels{""} || "") ? 1 : 0), }) : "", $properties{name}, $inputType, @@ -518,15 +518,15 @@ my ($open_date, $due_date, $answer_date); my $error = 0; if (defined $r->param('submit_changes')) { + my @names = ("open_date", "due_date", "answer_date"); + + my %dates = map { $_ => $r->param("set.$setID.$_") } @names; + %dates = map { + my $unlabel = $undoLabels{$_}->{$dates{$_}}; + $_ => defined $unlabel ? $setRecord->$_ : $self->parseDateTime($dates{$_}) + } @names; - my $od_param = $r->param("set.$setID.open_date"); - my $dd_param = $r->param("set.$setID.due_date"); - my $ad_param = $r->param("set.$setID.answer_date"); - #my $setRecord = $db->getGlobalSet($setID); # already fetched above --sam - - $open_date = $od_param ? $self->parseDateTime($od_param) : $setRecord->open_date; - $due_date = $dd_param ? $self->parseDateTime($dd_param) : $setRecord->due_date; - $answer_date = $ad_param ? $self->parseDateTime($ad_param) : $setRecord->answer_date; + ($open_date, $due_date, $answer_date) = map { $dates{$_} } @names; if ($answer_date < $due_date || $answer_date < $open_date) { $self->addbadmessage("Answers cannot be made available until on or after the due date!"); @@ -557,20 +557,23 @@ foreach my $record (@userRecords) { foreach my $field ( @{ SET_FIELDS() } ) { next unless canChange($forUsers, $field); - my $override = $r->param("set.$setID.$field.override"); + if (defined $override && $override eq $field) { my $param = $r->param("set.$setID.$field"); $param = $properties{$field}->{default} || "" unless defined $param && $param ne ""; - $param = $undoLabels{$field}->{$param} || $param; + my $unlabel = $undoLabels{$field}->{$param}; + $param = $unlabel if defined $unlabel; +# $param = $undoLabels{$field}->{$param} || $param; if ($field =~ /_date/) { - $param = $self->parseDateTime($param); + $param = $self->parseDateTime($param) unless defined $unlabel; } $record->$field($param); } else { $record->$field(undef); } + } $db->putUserSet($record); } @@ -580,9 +583,10 @@ my $param = $r->param("set.$setID.$field"); $param = $properties{$field}->{default} || "" unless defined $param && $param ne ""; - $param = $undoLabels{$field}->{$param} || $param; + my $unlabel = $undoLabels{$field}->{$param}; + $param = $unlabel if defined $unlabel; if ($field =~ /_date/) { - $param = $self->parseDateTime($param); + $param = $self->parseDateTime($param) unless defined $unlabel; } $setRecord->$field($param); } @@ -619,7 +623,8 @@ my $param = $r->param("problem.$problemID.$field"); $param = $properties{$field}->{default} || "" unless defined $param && $param ne ""; - $param = $undoLabels{$field}->{$param} || $param; + my $unlabel = $undoLabels{$field}->{$param}; + $param = $unlabel if defined $unlabel; $changed ||= changed($record->$field, $param); $record->$field($param); } else { @@ -634,7 +639,8 @@ my $param = $r->param("problem.$problemID.$field"); $param = $properties{$field}->{default} || "" unless defined $param && $param ne ""; - $param = $undoLabels{$field}->{$param} || $param; + my $unlabel = $undoLabels{$field}->{$param}; + $param = $unlabel if defined $unlabel; $changed ||= changed($record->$field, $param); $record->$field($param); } @@ -652,7 +658,8 @@ my $param = $r->param("problem.$problemID.$field"); $param = $properties{$field}->{default} || "" unless defined $param && $param ne ""; - $param = $undoLabels{$field}->{$param} || $param; + my $unlabel = $undoLabels{$field}->{$param}; + $param = $unlabel if defined $unlabel; $changed ||= changed($problemRecord->$field, $param); $problemRecord->$field($param); } @@ -684,7 +691,8 @@ my $param = $r->param("problem.$problemID.$field"); $param = $properties{$field}->{default} || "" unless defined $param && $param ne ""; - $param = $undoLabels{$field}->{$param} || $param; + my $unlabel = $undoLabels{$field}->{$param}; + $param = $unlabel if defined $unlabel; $changed ||= changed($record->$field, $param); $record->$field($param); } @@ -709,7 +717,6 @@ my @userProblemIDs = map { [$_, $setID, $problemID] } ($forUsers ? @editForUser : $db->listProblemUsers($setID, $problemID)); my @userProblemRecords = $db->getUserProblems(@userProblemIDs); foreach my $record (@userProblemRecords) { -$self->addbadmessage($record->user_id); if (defined $record && ($record->status eq "" || $record->status < 1)) { $record->status(1); $record->attempted(1); |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:43:40
|
Log Message: ----------- HEAD backport: Added the following features: * Searching on any user data field * Sorting by any two fields * Reports duplicate names on classlist import. Closes #654, #664, and #684 (toenail) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: UserList.pm Revision Data ------------- Index: UserList.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/UserList.pm,v retrieving revision 1.60 retrieving revision 1.60.2.1 diff -Llib/WeBWorK/ContentGenerator/Instructor/UserList.pm -Llib/WeBWorK/ContentGenerator/Instructor/UserList.pm -u -r1.60 -r1.60.2.1 --- lib/WeBWorK/ContentGenerator/Instructor/UserList.pm +++ lib/WeBWorK/ContentGenerator/Instructor/UserList.pm @@ -68,7 +68,7 @@ use Apache::Constants qw(:common REDIRECT DONE); #FIXME -- this should be called higher up in the object tree. use constant HIDE_USERS_THRESHHOLD => 50; use constant EDIT_FORMS => [qw(cancelEdit saveEdit)]; -use constant VIEW_FORMS => [qw(filter edit import export add delete)]; +use constant VIEW_FORMS => [qw(filter sort edit import export add delete)]; # permissions needed to perform a given action use constant FORM_PERMS => { @@ -86,7 +86,7 @@ sets => "assign_problem_sets", }; -use constant STATE_PARAMS => [qw(user effectiveUser key visible_users no_visible_users prev_visible_users no_prev_visible_users editMode sortField)]; +use constant STATE_PARAMS => [qw(user effectiveUser key visible_users no_visible_users prev_visible_users no_prev_visible_users editMode primarySortField secondarySortField)]; use constant SORT_SUBS => { user_id => \&byUserID, @@ -295,6 +295,7 @@ "Perm. Level" ); + $self->{prettyFieldNames} = \%prettyFieldNames; ########## set initial values for state fields my @allUserIDs = $db->listUsers; @@ -327,7 +328,8 @@ if $self->{editMode} and not $authz->hasPermissions($user, "modify_student_data"); - $self->{sortField} = $r->param("sortField") || "last_name"; + $self->{primarySortField} = $r->param("primarySortField") || "last_name"; + $self->{secondarySortField} = $r->param("secondarySortField") || "first_name"; my @allUsers = $db->getUsers(@allUserIDs); my (%sections, %recitations); @@ -373,7 +375,8 @@ my @prevVisibleUserIDs = @{ $self->{prevVisibleUserIDs} }; my @selectedUserIDs = @{ $self->{selectedUserIDs} }; my $editMode = $self->{editMode}; - my $sortField = $self->{sortField}; + my $primarySortField = $self->{primarySortField}; + my $secondarySortField = $self->{secondarySortField}; #warn "visibleUserIDs=@visibleUserIDs\n"; #warn "prevVisibleUserIDs=@prevVisibleUserIDs\n"; @@ -383,12 +386,15 @@ ########## get required users my @Users = grep { defined $_ } @visibleUserIDs ? $db->getUsers(@visibleUserIDs) : (); - - # presort users + my %sortSubs = %{ SORT_SUBS() }; - my $sortSub = $sortSubs{$sortField}; - #@Users = sort $sortSub @Users; - @Users = sort byLnFnUid @Users; + my $primarySortSub = $sortSubs{$primarySortField}; + my $secondarySortSub = $sortSubs{$secondarySortField}; + + # don't forget to sort in opposite order of importance + @Users = sort $secondarySortSub @Users; + @Users = sort $primarySortSub @Users; + #@Users = sort byLnFnUid @Users; my @PermissionLevels; @@ -435,7 +441,8 @@ print CGI::hidden(-name=>"editMode", -value=>$editMode); - print CGI::hidden(-name=>"sortField", -value=>$sortField); + print CGI::hidden(-name=>"primarySortField", -value=>$primarySortField); + print CGI::hidden(-name=>"secondarySortField", -value=>$secondarySortField); print "\n<!-- state data here -->\n"; @@ -529,19 +536,23 @@ my ($self, $onChange, %actionParams) = @_; #return CGI::table({}, CGI::Tr({-valign=>"top"}, # CGI::td({}, + + my %prettyFieldNames = %{ $self->{prettyFieldNames} }; + return join("", "Show ", CGI::popup_menu( -name => "action.filter.scope", - -values => [qw(all none selected match_ids match_section match_recitation)], - -default => $actionParams{"action.filter.scope"}->[0] || "match_ids", + -values => [qw(all none selected match_regex)], + -default => $actionParams{"action.filter.scope"}->[0] || "match_regex", -labels => { all => "all users", none => "no users", selected => "users checked below", - match_ids => "users with matching user IDs:", - match_section => "users in selected section", - match_recitation => "users in selected recitation", +# match_ids => "users with matching user IDs:", + match_regex => "users who match:", +# match_section => "users in selected section", +# match_recitation => "users in selected recitation", }, -onchange => $onChange, ), @@ -552,22 +563,30 @@ -width => "50", -onchange => $onChange, ), - " (separate multiple IDs with commas)", - CGI::br(), - "sections: ", +# " (separate multiple IDs with commas)", +# CGI::br(), +# "sections: ", +# CGI::popup_menu( +# -name => "action.filter.section", +# -values => [ keys %{ $self->{sections} } ], +# -default => $actionParams{"action.filter.section"}->[0] || "", +# -labels => { $self->menuLabels($self->{sections}) }, +# -onchange => $onChange, +# ), +# " recitations: ", +# CGI::popup_menu( +# -name => "action.filter.recitation", +# -values => [ keys %{ $self->{recitations} } ], +# -default => $actionParams{"action.filter.recitation"}->[0] || "", +# -labels => { $self->menuLabels($self->{recitations}) }, +# -onchange => $onChange, +# ), + " in their ", CGI::popup_menu( - -name => "action.filter.section", - -values => [ keys %{ $self->{sections} } ], - -default => $actionParams{"action.filter.section"}->[0] || "", - -labels => { $self->menuLabels($self->{sections}) }, - -onchange => $onChange, - ), - " recitations: ", - CGI::popup_menu( - -name => "action.filter.recitation", - -values => [ keys %{ $self->{recitations} } ], - -default => $actionParams{"action.filter.recitation"}->[0] || "", - -labels => { $self->menuLabels($self->{recitations}) }, + -name => "action.filter.field", + -value => [ keys %{ FIELD_PROPERTIES() } ], + -default => $actionParams{"action.filter.field"}->[0] || "user_id", + -labels => \%prettyFieldNames, -onchange => $onChange, ), ); @@ -580,6 +599,9 @@ sub filter_handler { my ($self, $genericParams, $actionParams, $tableParams) = @_; + my $r = $self->r; + my $db = $r->db; + my $result; my $scope = $actionParams->{"action.filter.scope"}->[0]; @@ -592,6 +614,17 @@ } elsif ($scope eq "selected") { $result = "showing selected users"; $self->{visibleUserIDs} = $genericParams->{selected_users}; # an arrayref + } elsif ($scope eq "match_regex") { + $result = "showing matching users"; + my $regex = $actionParams->{"action.filter.user_ids"}->[0]; + my $field = $actionParams->{"action.filter.field"}->[0]; + my @userRecords = $db->getUsers(@{$self->{allUserIDs}}); + my @userIDs; + foreach my $record (@userRecords) { + next unless $record; + push @userIDs, $record->user_id if $record->{$field} =~ /^$regex/i; + } + $self->{visibleUserIDs} = \@userIDs; } elsif ($scope eq "match_ids") { my @userIDs = split /\s*,\s*/, $actionParams->{"action.filter.user_ids"}->[0]; $self->{visibleUserIDs} = \@userIDs; @@ -606,6 +639,76 @@ return $result; } +sub sort_form { + my ($self, $onChange, %actionParams) = @_; + return join ("", + "Primary sort: ", + CGI::popup_menu( + -name => "action.sort.primary", + -values => [qw(user_id first_name last_name email_address student_id status section recitation comment permission)], + -default => $actionParams{"action.sort.primary"}->[0] || "last_name", + -labels => { + user_id => "Login Name", + first_name => "First Name", + last_name => "Last Name", + email_address => "Email address", + student_id => "Student ID", + status => "Enrollment Status", + section => "Section", + recitation => "Recitation", + comment => "Comment", + permission => "Perm. Level" + }, + -onchange => $onChange, + ), + " Secondary sort: ", + CGI::popup_menu( + -name => "action.sort.secondary", + -values => [qw(user_id first_name last_name email_address student_id status section recitation comment permission)], + -default => $actionParams{"action.sort.secondary"}->[0] || "first_name", + -labels => { + user_id => "Login Name", + first_name => "First Name", + last_name => "Last Name", + email_address => "Email address", + student_id => "Student ID", + status => "Enrollment Status", + section => "Section", + recitation => "Recitation", + comment => "Comment", + permission => "Perm. Level" + }, + -onchange => $onChange, + ), + ".", + ); +} + +sub sort_handler { + my ($self, $genericParams, $actionParams, $tableParams) = @_; + + my $primary = $actionParams->{"action.sort.primary"}->[0]; + my $secondary = $actionParams->{"action.sort.secondary"}->[0]; + + $self->{primarySortField} = $primary; + $self->{secondarySortField} = $secondary; + + my %names = ( + user_id => "Login Name", + first_name => "First Name", + last_name => "Last Name", + email_address => "Email address", + student_id => "Student ID", + status => "Enrollment Status", + section => "Section", + recitation => "Recitation", + comment => "Comment", + permission => "Perm. Level" + ); + + return "Users sorted by $names{$primary} and then by $names{$secondary}."; +} + sub edit_form { my ($self, $onChange, %actionParams) = @_; @@ -791,7 +894,8 @@ return $numReplaced . " user" . ($numReplaced == 1 ? "" : "s") . " replaced, " . $numAdded . " user" . ($numAdded == 1 ? "" : "s") . " added, " - . $numSkipped . " user" . ($numSkipped == 1 ? "" : "s") . " skipped."; + . $numSkipped . " user" . ($numSkipped == 1 ? "" : "s") . " skipped" + . " (" . join (", ", @$skipped) . ") "; } sub export_form { @@ -934,8 +1038,8 @@ ################################################################################ sub byUserID { lc $a->user_id cmp lc $b->user_id } -sub byFirstName { (defined $a->first_name && defined $b->first_name) ? lc $a->first_name cmp lc $b->first_name : 0 } -sub byLastName { (defined $a->last_name && defined $b->last_name ) ? lc $a->last_name cmp lc $b->last_name : 0 } +sub byFirstName { (defined $a->first_name && defined $b->first_name) ? lc $a->first_name cmp lc $b->first_name : 0; } +sub byLastName { (defined $a->last_name && defined $b->last_name ) ? lc $a->last_name cmp lc $b->last_name : 0; } sub byEmailAddress { lc $a->email_address cmp lc $b->email_address } sub byStudentID { lc $a->student_id cmp lc $b->student_id } sub byStatus { lc $a->status cmp lc $b->status } |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:39:56
|
Log Message: ----------- HEAD backport: expansion of Mike's caching fixes. (sh002i) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib: WeBWorK.pm webwork2/lib/WeBWorK: Authz.pm Revision Data ------------- Index: WeBWorK.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK.pm,v retrieving revision 1.68.2.1 retrieving revision 1.68.2.2 diff -Llib/WeBWorK.pm -Llib/WeBWorK.pm -u -r1.68.2.1 -r1.68.2.2 --- lib/WeBWorK.pm +++ lib/WeBWorK.pm @@ -224,7 +224,7 @@ } debug("Create an authz object (Authen needs it to check login permission)...\n"); - $authz = new WeBWorK::Authz($r, $ce, $db); + $authz = new WeBWorK::Authz($r); debug("(here's the authz object: $authz)\n"); $r->authz($authz); @@ -234,6 +234,9 @@ if ($authenOK) { my $userID = $r->param("user"); debug("Hi, $userID, glad you made it.\n"); + + # tell authorizer to cache this user's permission level + $authz->setCachedUser($userID); debug("Now we deal with the effective user:\n"); my $eUserID = $r->param("effectiveUser") || $userID; Index: Authz.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/Authz.pm,v retrieving revision 1.17.2.1 retrieving revision 1.17.2.2 diff -Llib/WeBWorK/Authz.pm -Llib/WeBWorK/Authz.pm -u -r1.17.2.1 -r1.17.2.2 --- lib/WeBWorK/Authz.pm +++ lib/WeBWorK/Authz.pm @@ -20,52 +20,184 @@ WeBWorK::Authz - check user permissions. +=head1 SYNOPSIS + + # create new authorizer -- $r is a WeBWorK::Request object. + my $authz = new WeBWorK::Authz($r); + + # tell authorizer to cache permission level of user spammy. + $authz->setCachedUser("spammy"); + + # this call will use the cached data. + if ($authz->hasPermissions("spammy", "eat_breakfast")) { + eat_breakfast(); + } + + # this call will not use the cached data, and will cause a database lookup. + if ($authz->hasPermissions("hammy", "go_to_bed")) { + go_to_bed(); + } + +=head1 DESCRIPTION + +WeBWorK::Authen determines if a user is authorized to perform a specific +activity, based on the user's PermissionLevel record in the WeBWorK database and +the contents of the %permissionLevels hash in the course environment. + +=head2 Format of the %permissionLevels hash + +%permissionLevels maps text strings describing activities to numeric permission +levels. The definitive list of activities is contained in the default version of +%permissionLevels, in the file F<conf/global.conf.dist>. + +A user is able to engage in an activity if their permission level is greater +than or equal to the level associated with the activity. If the level associated +with an activity is undefiend, then no user is permitted to perform the +activity, regardless of their permission level. + =cut use strict; use warnings; +################################################################################ + +=head1 CONSTRUCTOR + +=over + +=item WeBWorK::Authz->new($r) + +Creates a new authorizer instance. $r is a WeBWorK::Request object. It must +already have its C<ce> and C<db> fields set. + +=cut sub new { - my ($invocant, $r, $ce, $db) = @_; + my ($invocant, $r) = @_; my $class = ref($invocant) || $invocant; my $self = { r => $r, }; - my $user = $r->param("user"); - return 0 unless defined($user); - my $Permission = $db->getPermissionLevel($user); # checked - return 0 unless defined $Permission; - my $permissionLevel = $Permission->permission(); - return 0 unless defined $permissionLevel and $permissionLevel ne ""; - - my $permissionLevels = $ce->{permissionLevels}; - $self->{permissionLevels} = $permissionLevels; - $self->{permissionLevel} = $permissionLevel; bless $self, $class; return $self; } -# This module assumes that neither the permissionLevels nor the permissionLevel -# changes between the time an authz module is created and the time it's used. +=back + +=cut + +################################################################################ + +=head1 METHODS + +=over + +=item setCachedUser($userID) + +Caches the PermissionLevel of the user $userID in an existing authorizer. If a +user's PermissionLevel is cached, it will be used whenever hasPermissions() is +called on the same user. Only one user can be cached at a time. This is used by +WeBWorK to cache the "real" user. + +=cut + +sub setCachedUser { + my ($self, $userID) = @_; + my $r = $self->{r}; + my $db = $r->db; + + delete $self->{userID}; + delete $self->{PermissionLevel}; + + if (defined $userID) { + $self->{userID} = $userID; + my $PermissionLevel = $db->getPermissionLevel($userID); # checked + if (defined $PermissionLevel) { + # store permission level record in database to avoid later database calls + $self->{PermissionLevel} = $PermissionLevel; + } + } else { + warn "setCachedUser() called with userID undefined.\n"; + } +} + +=item hasPermissions($userID, $activity) + +Checks the %permissionLevels hash in the course environment to determine if the +user $userID has permission to engage in the activity $activity. If the user's +permission level is greater than or equal to the level associated with $activty, +a true value is returned. Otherwise, a false value is returned. + +If $userID has been cached using the setCachedUser() call, the cached data is +used. Otherwise, the user's PermissionLevel is looked up in the WeBWorK +database. + +If the user does not have a PermissionLevel record, the permission level record +is empty, or the activity does not appear in %permissionLevels, hasPermissions() +assumes that the user does not have permission. + +=cut # This currently only uses two of it's arguments, but it accepts any number, in # case in the future calculating certain permissions requires more information. sub hasPermissions { - my ($self, $user, $activity) = @_; - my $permissionLevels = $self->{permissionLevels}; - my $permissionLevel = $self->{permissionLevel}; + my ($self, $userID, $activity) = @_; + my $r = $self->{r}; + my $ce = $r->ce; + my $db = $r->db; + + my $PermissionLevel; + + my $cachedUserID = $self->{userID}; + if (defined $cachedUserID and $cachedUserID ne "" and $cachedUserID eq $userID) { + # this is the same user -- we can skip the database call + $PermissionLevel = $self->{PermissionLevel}; + } else { + # a different user, or no user was defined before + my $prettyCachedUserID = defined $cachedUserID ? "'$cachedUserID'" : "undefined"; + #warn "hasPermissions called with user '$userID', but cached user is $prettyCachedUserID. Accessing database.\n"; + $PermissionLevel = $db->getPermissionLevel($userID); # checked + } + + my $permission_level; + + if (defined $PermissionLevel) { + $permission_level = $PermissionLevel->permission; + } else { + # uh, oh. this user has no permission level record! + warn "User '$userID' has no PermissionLevel record -- assuming no permission.\n"; + return 0; + } + + unless (defined $permission_level and $permission_level ne "") { + warn "User '$userID' has empty permission level -- assuming no permission.\n"; + return 0; + } + + my $permissionLevels = $ce->{permissionLevels}; if (exists $permissionLevels->{$activity}) { if (defined $permissionLevels->{$activity}) { - return $permissionLevel >= $permissionLevels->{$activity}; + return $permission_level >= $permissionLevels->{$activity}; } else { - return 0; + return 0; # nobody has permission to do this } } else { - die "Activity '$activity' not found in %permissionLevels. Can't continue.\n"; + warn "Activity '$activity' not found in %permissionLevels -- assuming no permission.\n"; + return 0; } - } + +=back + +=cut + +=head1 AUTHOR + +Written by Dennis Lambe, malsyned at math.rochester.edu. Modified by Sam +Hathaway, sh002i at math.rochester.edu. + +=cut 1; |
From: Gavin L. v. a. <act...@de...> - 2005-01-28 00:38:57
|
Log Message: ----------- Update ProblemSets listing to give more intelligible entries for gateway tests: add Score and Date columns, clean up status column, and change set names to be more logical for gateways. This works best when making the 'info' column in the template narrower (e.g., 15% instead of the default 30%), which might argue that a gateway template should be added to the available templates. Tags: ---- rel-2-1-a1 Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: ProblemSets.pm Revision Data ------------- Index: ProblemSets.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/ProblemSets.pm,v retrieving revision 1.50.2.4 retrieving revision 1.50.2.5 diff -Llib/WeBWorK/ContentGenerator/ProblemSets.pm -Llib/WeBWorK/ContentGenerator/ProblemSets.pm -u -r1.50.2.4 -r1.50.2.5 --- lib/WeBWorK/ContentGenerator/ProblemSets.pm +++ lib/WeBWorK/ContentGenerator/ProblemSets.pm @@ -105,37 +105,65 @@ print CGI::p({-align=>'center'},CGI::a({-href=>$instructorLink},'Instructor Tools')); } - $sort = "status" unless $sort eq "status" or $sort eq "name"; - my $nameHeader = $sort eq "name" - ? CGI::u("Name") - : CGI::a({href=>$self->systemLink($urlpath, params=>{sort=>"name"})}, "Name"); - my $statusHeader = $sort eq "status" - ? CGI::u("Status") - : CGI::a({href=>$self->systemLink($urlpath, params=>{sort=>"status"})}, "Status"); my $hardcopyPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Hardcopy", courseID => $courseName); my $actionURL = $self->systemLink($hardcopyPage, authen => 0); # no authen info for form action print CGI::startform(-method=>"POST", -action=>$actionURL); print $self->hidden_authen_fields; - print CGI::start_table(); - print CGI::Tr( - CGI::th("Sel."), - CGI::th($nameHeader), - CGI::th($statusHeader), - ); + # moved table header down after sets to allow inclusion of versioned set/ + # gateway columns my @setIDs = $db->listUserSets($effectiveUser); my @userSetIDs = map {[$effectiveUser, $_]} @setIDs; $WeBWorK::timer->continue("Begin collecting merged sets") if defined($WeBWorK::timer); my @sets = $db->getMergedSets( @userSetIDs ); + + $WeBWorK::timer->continue("Begin set-type check") if defined($WeBWorK::timer); +# check to see if we have gateways, in which case we want to include date +# taken and score columns in the output, and change the default sort order + my $existVersions = 0; + foreach ( @sets ) { + if ( defined( $_->assignment_type() ) && + $_->assignment_type() =~ /gateway/ ) { + $existVersions = 1; + last; + } + } +# change default sort order, if it wasn't declared earlier + $sort = 'name' if ( $existVersions && ! $r->param("sort") ); + $WeBWorK::timer->continue("Begin sorting merged sets") if defined($WeBWorK::timer); - @sets = sortByName("set_id", @sets) if $sort eq "name"; @sets = sort byUrgency @sets if $sort eq "status"; $WeBWorK::timer->continue("End preparing merged sets") if defined($WeBWorK::timer); - + + $sort = "status" unless $sort eq "status" or $sort eq "name"; + my $nameHeader = $sort eq "name" + ? CGI::u("Name") + : CGI::a({href=>$self->systemLink($urlpath, params=>{sort=>"name"})}, "Name"); + my $statusHeader = $sort eq "status" + ? CGI::u("Status") + : CGI::a({href=>$self->systemLink($urlpath, params=>{sort=>"status"})}, "Status"); + + print CGI::start_table(); + if ( ! $existVersions ) { + print CGI::Tr( + CGI::th("Sel."), + CGI::th($nameHeader), + CGI::th($statusHeader), + ); + } else { + print CGI::Tr( + CGI::th("Sel."), + CGI::th($nameHeader), + CGI::th("Score"), + CGI::th("Date"), + CGI::th($statusHeader), + ); + } + foreach my $set (@sets) { die "set $set not defined" unless $set; @@ -154,11 +182,8 @@ } warn "undefined published button".$set->set_id unless defined($set->published); if ($set->published || $authz->hasPermissions($user, "view_unpublished_sets")) { -# && $set->set_id() !~ /,v\d+$/ ) { -# should we exclude versions? we get new versions by clicking the global set -# but probably want to look at old ones too - print $self->setListRow($set, $authz->hasPermissions($user, "view_multiple_sets"), $authz->hasPermissions($user, "view_unopened_sets")); + print $self->setListRow($set, $authz->hasPermissions($user, "view_multiple_sets"), $authz->hasPermissions($user, "view_unopened_sets"),$existVersions,$db); } } @@ -193,7 +218,7 @@ } sub setListRow { - my ($self, $set, $multiSet, $preOpenSets) = @_; + my ($self, $set, $multiSet, $preOpenSets, $existVersions, $db) = @_; my $r = $self->r; my $ce = $r->ce; my $urlpath = $r->urlpath; @@ -244,12 +269,46 @@ } my $interactive = CGI::a({-href=>$interactiveURL}, "set $name"); - +# edit this a bit for gateways + if ( defined( $set->assignment_type() ) && + $set->assignment_type() =~ /gateway/ ) { + if ( $name =~ /,v\d+$/ ) { + my $sname = $name; + $sname =~ s/,v(\d+)$//; + $interactive = CGI::a({-href=>$interactiveURL}, + "$sname (test$1)"); + } else { # this is the case of a template URL + $interactive = CGI::a({-href=>$interactiveURL}, + "Take new $name test"); + } + } + +# for gateways, we aren't as verbose about open/closed status, because +# there's only one attempt and we default to showing answers once the +# test is done. my $status; - if (time < $set->open_date) { - $status = "will open on $openDate"; - $control = "" unless $preOpenSets; - $interactive = $name unless $preOpenSets; + if ( defined($set->assignment_type()) && + $set->assignment_type() =~ /gateway/ ) { + if ( $set->set_id() =~ /,v\d+$/ ) { + $status = ' '; # for g/w, we only give one attempt per version, + # so by the time we're here it's closed + } else { + my $t = time(); + if ( $t < $set->open_date() ) { + $status = "will open on $openDate"; + $control = "" unless $preOpenSets; + $interactive = $name unless $preOpenSets; + } elsif ( $t < $set->due_date() ) { + $status = "open, due $dueDate"; + } else { + $status = "closed"; + } + } +# old conditional + } elsif (time < $set->open_date) { + $status = "will open on $openDate"; + $control = "" unless $preOpenSets; + $interactive = $name unless $preOpenSets; } elsif (time < $set->due_date) { if ( $set->set_id() !~ /,v\d+$/ ) { $status = "now open, due $dueDate"; @@ -267,12 +326,48 @@ my $publishedClass = ($set->published) ? "Published" : "Unpublished"; $status = CGI::font({class=>$publishedClass}, $status) if $preOpenSets; - - return CGI::Tr(CGI::td([ - $control, - $interactive, - $status, - ])); + +# check to see if we need to return a score and a date column + if ( ! $existVersions ) { + return CGI::Tr(CGI::td([ + $control, + $interactive, + $status, + ])); + } else { + my ( $startTime, $score ); + + if ( defined( $set->assignment_type() ) && + $set->assignment_type() =~ /gateway/ && + $set->set_id() =~ /,v\d+$/ ) { + $startTime = localtime( $set->version_creation_time() ); + + # find score + my @problemRecords = $db->getAllUserProblems( $set->user_id(), + $set->set_id() ); + my $possible = 0; + $score = 0; + foreach my $pRec ( @problemRecords ) { + if ( defined( $pRec ) && $score ne 'undef' ) { + $score += $pRec->status() || 0; + } else { + $score = 'undef'; + } + $possible++; + } + $score = "$score/$possible"; + } else { + $startTime = ' '; + $score = $startTime; + } + return CGI::Tr(CGI::td([ + $control, + $interactive, + $score, + $startTime, + $status, + ])); + } } sub byname { $a->set_id cmp $b->set_id; } |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:36:27
|
Log Message: ----------- HEAD backport: Fixed double declaration of $user (gage) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: Assigner.pm Revision Data ------------- Index: Assigner.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/Assigner.pm,v retrieving revision 1.25.2.1 retrieving revision 1.25.2.2 diff -Llib/WeBWorK/ContentGenerator/Instructor/Assigner.pm -Llib/WeBWorK/ContentGenerator/Instructor/Assigner.pm -u -r1.25.2.1 -r1.25.2.2 --- lib/WeBWorK/ContentGenerator/Instructor/Assigner.pm +++ lib/WeBWorK/ContentGenerator/Instructor/Assigner.pm @@ -64,7 +64,7 @@ my @Users = $db->getUsers(@userIDs); ## Mark's Edits for filtering my @myUsers; - my $user = $r->param("user"); + my (@viewable_sections, @viewable_recitations); |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:30:02
|
Log Message: ----------- HEAD backport: Fixed small bug in the message passing facility Changed message passing when there is a duplicate administrator. (gage) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: CourseAdmin.pm Revision Data ------------- Index: CourseAdmin.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm,v retrieving revision 1.31 retrieving revision 1.31.2.1 diff -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -u -r1.31 -r1.31.2.1 --- lib/WeBWorK/ContentGenerator/CourseAdmin.pm +++ lib/WeBWorK/ContentGenerator/CourseAdmin.pm @@ -57,6 +57,10 @@ return; } + # get result and send to message + my $status_message = $r->param("status_message"); + $self->addmessage(CGI::p("$status_message")) if $status_message; + ## if the user is asking for the downloaded database... #if (defined $r->param("download_exported_database")) { # my $courseID = $r->param("export_courseID"); @@ -652,7 +656,7 @@ if ($add_admin_users ne "") { foreach my $userID ($db->listUsers) { if ($userID eq $add_initial_userID) { - warn "User '$userID' will not be copied from admin course as it is the initial instructor."; + $self->addbadmessage( "User '$userID' will not be copied from admin course as it is the initial instructor."); next; } my $User = $db->getUser($userID); |
From: Sam H. v. a. <we...@ma...> - 2005-01-28 00:27:32
|
Log Message: ----------- HEAD backport: The permission levels are now checked when the authz instance is created. (gage) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK: Authz.pm Revision Data ------------- Index: Authz.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/Authz.pm,v retrieving revision 1.17 retrieving revision 1.17.2.1 diff -Llib/WeBWorK/Authz.pm -Llib/WeBWorK/Authz.pm -u -r1.17 -r1.17.2.1 --- lib/WeBWorK/Authz.pm +++ lib/WeBWorK/Authz.pm @@ -25,30 +25,37 @@ use strict; use warnings; + sub new { - my ($invocant, $r) = @_; + my ($invocant, $r, $ce, $db) = @_; my $class = ref($invocant) || $invocant; my $self = { r => $r, }; + + my $user = $r->param("user"); + return 0 unless defined($user); + my $Permission = $db->getPermissionLevel($user); # checked + return 0 unless defined $Permission; + my $permissionLevel = $Permission->permission(); + return 0 unless defined $permissionLevel and $permissionLevel ne ""; + + my $permissionLevels = $ce->{permissionLevels}; + $self->{permissionLevels} = $permissionLevels; + $self->{permissionLevel} = $permissionLevel; bless $self, $class; return $self; } +# This module assumes that neither the permissionLevels nor the permissionLevel +# changes between the time an authz module is created and the time it's used. + # This currently only uses two of it's arguments, but it accepts any number, in # case in the future calculating certain permissions requires more information. sub hasPermissions { my ($self, $user, $activity) = @_; - my $r = $self->{r}; - my $ce = $r->ce; - my $db = $r->db; - - my $Permission = $db->getPermissionLevel($user); # checked - return 0 unless defined $Permission; - my $permissionLevel = $Permission->permission(); - return 0 unless defined $permissionLevel and $permissionLevel ne ""; - - my $permissionLevels = $ce->{permissionLevels}; + my $permissionLevels = $self->{permissionLevels}; + my $permissionLevel = $self->{permissionLevel}; if (exists $permissionLevels->{$activity}) { if (defined $permissionLevels->{$activity}) { return $permissionLevel >= $permissionLevels->{$activity}; @@ -58,6 +65,7 @@ } else { die "Activity '$activity' not found in %permissionLevels. Can't continue.\n"; } + } 1; |
From: Sam H. v. a. <act...@de...> - 2005-01-28 00:25:19
|
Log Message: ----------- HEAD backport: Added a line to check for empty records. The hope is that this fixes bug #733 (gage) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: Grades.pm Revision Data ------------- Index: Grades.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Grades.pm,v retrieving revision 1.9.2.1 retrieving revision 1.9.2.2 diff -Llib/WeBWorK/ContentGenerator/Grades.pm -Llib/WeBWorK/ContentGenerator/Grades.pm -u -r1.9.2.1 -r1.9.2.2 --- lib/WeBWorK/ContentGenerator/Grades.pm +++ lib/WeBWorK/ContentGenerator/Grades.pm @@ -75,7 +75,7 @@ $line.=$delimiter; # add 'A' to end of line so that # last field is never empty @lineArray = split(/\s*${delimiter}\s*/,$line); - $lineArray[0] =~s/^\s*//; # remove white space from first element + $lineArray[0] =~s/^\s*// if defined($lineArray[0]); # remove white space from first element @lineArray; } |
From: Sam H. v. a. <act...@de...> - 2005-01-28 00:21:54
|
Log Message: ----------- HEAD backport: Added an option to rename the "Change Display Settings" submit buttton. (gage) Tags: ---- rel-2-1-patches Modified Files: -------------- webwork2/lib/WeBWorK/HTML: ScrollingRecordList.pm Revision Data ------------- Index: ScrollingRecordList.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/HTML/ScrollingRecordList.pm,v retrieving revision 1.6 retrieving revision 1.6.2.1 diff -Llib/WeBWorK/HTML/ScrollingRecordList.pm -Llib/WeBWorK/HTML/ScrollingRecordList.pm -u -r1.6 -r1.6.2.1 --- lib/WeBWorK/HTML/ScrollingRecordList.pm +++ lib/WeBWorK/HTML/ScrollingRecordList.pm @@ -81,6 +81,8 @@ my @ids = (); my %labels = (); + my $refresh_button_name = defined($options{refresh_button_name}) ? $options{refresh_button_name}:"Change Display Settings"; + my @selected_records = $r->param("$name"); if (@Records) { @@ -166,7 +168,7 @@ CGI::td(CGI::scrolling_list(%filter_options)), ]), ), - CGI::submit("$name!refresh", "Change Display Settings"), CGI::br(), + CGI::submit("$name!refresh", $refresh_button_name), CGI::br(), CGI::scrolling_list(%list_options), ); } |
From: Robert V. D. v. a. <act...@de...> - 2005-01-28 00:07:40
|
Log Message: ----------- display mode was inadvertently reset with other problem/set elements that are safe to reset (rather than keep sticky) since they will be updated from the newly saved database record or thrown away as expected Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: ProblemSetDetail.pm Revision Data ------------- Index: ProblemSetDetail.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm,v retrieving revision 1.16 retrieving revision 1.17 diff -Llib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm -Llib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm -u -r1.16 -r1.17 --- lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm +++ lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm @@ -758,10 +758,9 @@ # if the current naming scheme is changed/broken, this could reek havoc # on all kinds of things foreach my $param ($r->param) { - $r->param($param, "") if $param =~ /^(set|problem|header)\./; + $r->param($param, "") if $param =~ /^(set|problem|header)\./ && $param !~ /displaymode/; } } - } # helper method for debugging |