Parent Directory
|
Revision Log
This commit was manufactured by cvs2svn to create branch 'rel-2-3-dev'.
1 ################################################################################ 2 # WeBWorK Online Homework Delivery System 3 # Copyright © 2000-2006 The WeBWorK Project, http://openwebwork.sf.net/ 4 # $CVSHeader: 5 # 6 # This program is free software; you can redistribute it and/or modify it under 7 # the terms of either: (a) the GNU General Public License as published by the 8 # Free Software Foundation; either version 2, or (at your option) any later 9 # version, or (b) the "Artistic License" which comes with this package. 10 # 11 # This program is distributed in the hope that it will be useful, but WITHOUT 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the 14 # Artistic License for more details. 15 ################################################################################ 16 17 package WeBWorK::ContentGenerator::Instructor::UserDetail; 18 use base qw(WeBWorK::ContentGenerator::Instructor); 19 20 =head1 NAME 21 22 WeBWorK::ContentGenerator::Instructor::UserDetail - Detailed User specific information 23 24 =cut 25 26 use strict; 27 use warnings; 28 #use CGI qw(-nosticky ); 29 use WeBWorK::CGI; 30 use WeBWorK::Utils qw(sortByName); 31 use WeBWorK::Debug; 32 33 use constant DATE_FIELDS => { open_date => " Open: ", 34 due_date => " Due : ", 35 answer_date => " Ans : " 36 }; 37 use constant DATE_FIELDS_ORDER =>[qw(open_date due_date answer_date )]; 38 sub initialize { 39 my ($self) = @_; 40 my $r = $self->r; 41 my $urlpath = $r->urlpath; 42 my $db = $r->db; 43 my $authz = $r->authz; 44 my $userID = $r->param("user"); 45 my $editForUserID = $urlpath->arg("userID"); 46 47 return CGI::div({class => "ResultsWithError"}, "You are not authorized to edit user specific information.") 48 unless $authz->hasPermissions($userID, "access_instructor_tools"); 49 50 # templates for getting field names 51 my $userTemplate = $self->{userTemplate} = $db->newUser; 52 my $permissionLevelTemplate = $self->{permissionLevelTemplate} = $db->newPermissionLevel; 53 54 # first check to see if a save form has been submitted 55 return '' unless $r->param('save_button'); 56 57 # As it stands we need to check each set to see if it is still assigned 58 # the forms are not currently set up to simply transmit changes 59 60 #Get the list of sets and the global set records 61 my @setIDs = $db->listGlobalSets; 62 my @setRecords = grep { defined $_ } $db->getGlobalSets(@setIDs); 63 64 my @assignedSets = (); 65 foreach my $setID (@setIDs) { 66 push @assignedSets, $setID if defined($r->param("set.$setID.assignment")); 67 } 68 debug("assignedSets", join(" ", @assignedSets)); 69 my %selectedSets = map { $_ => 1 } @assignedSets; 70 #debug ########################## 71 #print STDERR ("aSsigned sets", join(" ",@assignedSets)); 72 #my @params = $r->param(); 73 #print STDERR " parameters ", join(" ", @params); 74 ############### 75 #Get the user(s) whose records are to be modified 76 # for now: $editForUserID 77 # check the user exists? Is this necessary? 78 my $editUserRecord = $db->getUser($editForUserID); 79 die "record not found for $editForUserID.\n" unless $editUserRecord; 80 81 82 #Perform the desired assignments or deletions 83 my %userSets = map { $_ => 1 } $db->listUserSets($editForUserID); 84 85 # go through each possible set 86 debug(" parameters ", join(" ", $r->param()) ); 87 foreach my $setRecord (@setRecords) { 88 my $setID = $setRecord->set_id; 89 # does the user want it to be assigned to the selected user 90 if (exists $selectedSets{$setID}) { 91 $self->assignSetToUser($editForUserID, $setRecord); 92 #override dates 93 94 95 my $userSetRecord = $db->getUserSet($editForUserID, $setID); 96 # get the dates 97 98 99 100 #do checks to see if new dates meet criteria 101 my $rh_dates = $self->checkDates($setRecord,$setID); 102 unless ( $rh_dates->{error} ) { #returns 1 if error 103 # if no error update database 104 foreach my $field (keys %{DATE_FIELDS()}) { 105 if (defined $r->param("set.$setID.$field.override")) { 106 $userSetRecord->$field($rh_dates->{$field}); 107 } else { 108 $userSetRecord->$field(undef); #stop override 109 } 110 } 111 $db->putUserSet($userSetRecord); 112 113 } 114 115 } else { 116 # user asked to NOT have the set assigned to the selected user 117 # debug("deleteUserSet($editForUserID, $setID)"); 118 $db->deleteUserSet($editForUserID, $setID); 119 # debug("done deleteUserSet($editForUserID, $setID)"); 120 } 121 } 122 123 return ''; 124 125 126 127 } 128 129 sub body { 130 my ($self) = @_; 131 my $r = $self->r; 132 my $urlpath = $r->urlpath; 133 my $db = $r->db; 134 my $ce = $r->ce; 135 my $authz = $r->authz; 136 my $courseID = $urlpath->arg("courseID"); 137 my $editForUserID = $urlpath->arg("userID"); 138 my $userID = $r->param("user"); 139 140 my @editForSets = $r->param("editForSets"); 141 142 return CGI::div({class => "ResultsWithError"}, "You are not authorized to edit user specific information.") 143 unless $authz->hasPermissions($userID, "access_instructor_tools"); 144 145 my $UserRecord = $db->getUser($editForUserID); 146 my $PermissionRecord = $db->getPermissionLevel($editForUserID); 147 my @UserSetIDs = $db->listUserSets($editForUserID); 148 149 my $userName = $UserRecord->first_name . " " . $UserRecord->last_name; 150 151 # templates for getting field names 152 my $userTemplate = $self->{userTemplate}; 153 my $permissionLevelTemplate = $self->{permissionLevelTemplate}; 154 155 # This table can be consulted when display-ready forms of field names are needed. 156 my %prettyFieldNames = map { $_ => $_ } 157 $userTemplate->FIELDS(); 158 159 # @prettyFieldNames{qw( 160 # #user_id 161 # first_name 162 # last_name 163 # email_address 164 # student_id 165 # status 166 # section 167 # recitation 168 # comment 169 # permission 170 # )} = ( 171 # #"Login Name", 172 # "First Name", 173 # "Last Name", 174 # "Email", 175 # "Student ID", 176 # "Status", 177 # "Section", 178 # "Recitation", 179 # "Comment", 180 # "Permission Level", 181 # ); 182 183 my @dateFields = @{DATE_FIELDS_ORDER()}; 184 my $rh_dateFieldLabels = DATE_FIELDS(); 185 186 187 # create a link to the SetsAssignedToUser page 188 # my $editSetsPath = $urlpath->newFromModule( 189 # "WeBWorK::ContentGenerator::Instructor::SetsAssignedToUser", 190 # courseID => $courseID, 191 # userID => $userID, 192 # ); 193 # my $editSetsAssignedToUserURL = $self->systemLink($editSetsPath); 194 195 # create a message about how many sets have been assigned to this user 196 my $setCount = $db->countUserSets($editForUserID); 197 # my $userCountMessage = CGI::a({href=>$editSetsAssignedToUserURL}, $setCount . " sets."); 198 # $userCountMessage = "The user " . CGI::b($userName . " ($editForUserID)") . " has been assigned " . $userCountMessage; 199 my $basicInfoPage = $urlpath->new(type =>'instructor_user_list', 200 args =>{ 201 courseID => $courseID, 202 } 203 ); 204 my $basicInfoUrl = $self->systemLink($basicInfoPage, 205 params =>{visible_users => $editForUserID, 206 editMode => 1, 207 } 208 ); 209 210 print CGI::h4({align=>'center'},"Edit ",CGI::a({href=>$basicInfoUrl},'class list data')," for $userName ($editForUserID) who has been assigned $setCount sets."); 211 212 #print CGI::h4("User Data"); 213 # print CGI::start_table({ align=>'center', border=>1,cellpadding=>5}); 214 # print CGI::Tr( 215 # CGI::th(CGI::checkbox({ type => 'checkbox', 216 # name => "edit.basic.info", 217 # label => '', 218 # checked => 0 219 # }),"Edit class list data for $editForUserID"), 220 # CGI::th(CGI::checkbox({ type => 'checkbox', 221 # name => "change.password", 222 # label => '', 223 # checked => 0 224 # }),"Change Password for $editForUserID")); 225 # 226 # print "<tr><td rowspan=\"2\">"; 227 # ######################################## 228 # # Basic student data 229 # ######################################## 230 # print CGI::start_table(); 231 # foreach ($userTemplate->FIELDS()) { 232 # next if $_ eq 'user_id'; # don't print login name 233 # print CGI::Tr( 234 # CGI::td([ 235 # $prettyFieldNames{$_}, 236 # CGI::input({ -value => $UserRecord->$_, -size => 25 }) 237 # ]) 238 # ); 239 # } 240 # foreach ($permissionLevelTemplate->FIELDS()) { 241 # print CGI::Tr( 242 # CGI::td([ 243 # $prettyFieldNames{$_}, 244 # CGI::input({ -value => $PermissionRecord->$_, -size => 25 }) 245 # ]) 246 # ); 247 # } 248 # print CGI::end_table(); 249 # 250 # #print CGI::br(); 251 # print "</td><td valign=\"top\">"; 252 # ######################################## 253 # # Change password section 254 # ######################################## 255 # my $profRecord = $db->getUser($userID); 256 # my $profName = $profRecord->first_name . " " . $profRecord->last_name; 257 # my $poss = "'s "; 258 # my $pass = " password "; 259 # 260 # print CGI::start_table(); 261 # print CGI::Tr(CGI::td(["<b>$profName</b>$poss$pass", CGI::input({ -type => "password", -name => "$userID.password"})])); 262 # print CGI::Tr(CGI::td(["<b>$userName</b>$poss new $pass", CGI::input({ -type => "password", -name => "$editForUserID.password.1"})])); 263 # print CGI::Tr(CGI::td(["Confirm <b>$userName</b>$poss new $pass", CGI::input({ -type => "password", -name => "$editForUserID.password.2"})])); 264 # print CGI::end_table(); 265 # print "</td></tr>"; 266 # print CGI::Tr(CGI::th( #FIXME enable this once it can be handled 267 # # CGI::checkbox({ type => 'checkbox', 268 # # name => "change.login", 269 # # label => '', 270 # # checked => 0 271 # # }), 272 # "Change login name $editForUserID to ", CGI::input({-name=>'new_login', -value=>'' ,-size=>25}) 273 # )); 274 # print CGI::end_table(); 275 276 print CGI::br(); 277 278 #print CGI::h4("Sets assigned to $userName"); 279 # construct url for the form 280 my $userDetailPage = $urlpath->new(type =>'instructor_user_detail', 281 args =>{ 282 courseID => $courseID, 283 userID => $editForUserID, #FIXME eventually this should be a list?? 284 } 285 ); 286 my $userDetailUrl = $self->systemLink($userDetailPage,authen=>0); 287 288 my %GlobalSetRecords = map { $_->set_id => $_ } $db->getGlobalSets($db->listGlobalSets()); 289 my @UserSetRefs = map { [$editForUserID, $_] } sortByName(undef, @UserSetIDs); 290 my %UserSetRecords = map { $_->set_id => $_ } $db->getUserSets(@UserSetRefs); 291 my @MergedSetRefs = map { [$editForUserID, $_] } sortByName(undef, @UserSetIDs); 292 my %MergedSetRecords = map { $_->set_id => $_ } $db->getMergedSets(@MergedSetRefs); 293 294 ######################################## 295 # Print warning 296 ######################################## 297 print CGI::div({-class=>'ResultsWithError'}, 298 "Do not uncheck a set unless you know what you are doing.", CGI::br(), 299 "There is NO undo for unassigning a set."); 300 301 print CGI::p("To change status (scores or grades) for this student for one 302 set, click on the individual set link."); 303 304 print CGI::div({-class=>'ResultsWithError'},"When you uncheck a homework set (and save the changes), you destroy all 305 of the data for that set for this student. If you 306 reassign the set, the student will receive a new version of each problem. 307 Make sure this is what you want to do before unchecking sets." 308 ); 309 ######################################## 310 # Assigned sets form 311 ######################################## 312 313 print CGI::start_form( {method=>'post',action=>$userDetailUrl, name=>'UserDetail'}),"\n"; 314 print $self->hidden_authen_fields(); 315 print CGI::p(CGI::submit(-name=>'save_button',-label=>'Save changes',)); 316 317 print CGI::start_table({ border=> 1,cellpadding=>5}),"\n"; 318 print CGI::Tr( 319 CGI::th({align=>'center',colspan=>3}, "Sets assigned to $userName ($editForUserID)") 320 ),"\n"; 321 print CGI::Tr( 322 CGI::th({ -align => "center"}, [ 323 "Assigned", 324 "Edit set for $editForUserID", 325 "Dates", 326 ]) 327 ),"\n"; 328 foreach my $setID (sortByName(undef, $db->listGlobalSets())) { 329 my $GlobalSetRecord = $GlobalSetRecords{$setID}; 330 my $UserSetRecord = $UserSetRecords{$setID}; 331 my $MergedSetRecord = $MergedSetRecords{$setID}; 332 my $setListPage = $urlpath->new(type =>'instructor_set_detail', 333 args =>{ 334 courseID => $courseID, 335 setID => $setID 336 } 337 ); 338 my $url = $self->systemLink($setListPage, 339 params =>{effectiveUser => $editForUserID, 340 editForUser => $editForUserID, 341 }); 342 343 print CGI::Tr( 344 CGI::td({ -align => "center" }, [ 345 CGI::checkbox({ type => 'checkbox', 346 name => "set.$setID.assignment", 347 label => '', 348 value => 'assigned', 349 checked => (defined $MergedSetRecord) 350 }), 351 defined($MergedSetRecord) ? CGI::b(CGI::a({href=>$url},$setID, ) ) : CGI::b($setID, ), 352 join "\n", $self->DBFieldTable($GlobalSetRecord, $UserSetRecord, $MergedSetRecord, "set", $setID, \@dateFields,$rh_dateFieldLabels), 353 ]) 354 ),"\n"; 355 } 356 print CGI::end_table(),"\n"; 357 print CGI::p(CGI::submit(-name=>'save_button',-label=>'Save changes',)); 358 print CGI::end_form(),"\n"; 359 ######################################## 360 # Print warning 361 ######################################## 362 363 CGI::div( {class=>'ResultsWithError'}, 364 "There is NO undo for this function. 365 Do not use it unless you know what you are doing! When you unassign 366 sets using this button, or by unchecking their set names, you destroy all 367 of the data for those sets for this student." 368 ); 369 370 371 # print CGI::start_table(); 372 # print CGI::Tr( 373 # CGI::th({ -align => "center"},[ 374 # "Assigned", 375 # "Set Name", 376 # "Opens", 377 # "Answers Due", 378 # "Answers Available", 379 # ]) 380 # ); 381 382 # foreach my $setID (sortByName(undef, @UserSetIDs)) { 383 # my $MergedSetRecord = $MergedSetRecords{$setID}; 384 # print CGI::Tr( 385 # CGI::td({ -align => "center" }, [ 386 # CGI::checkbox({checked => (defined $MergedSetRecord)}), 387 # $setID, 388 # CGI::checkbox() . 389 # CGI::input({ -value => $self->formatDateTime($MergedSetRecord->open_date), -size => 25}), 390 # CGI::checkbox() . 391 # CGI::input({ -value => $self->formatDateTime($MergedSetRecord->due_date), -size => 25}), 392 # CGI::checkbox() . 393 # CGI::input({ -value => $self->formatDateTime($MergedSetRecord->answer_date), -size => 25}), 394 # ]) 395 # ); 396 # } 397 return ''; 398 } 399 400 sub checkDates { 401 my $self = shift; 402 my $setRecord = shift; 403 my $setID = shift; 404 my $r = $self->r; 405 my %dates = (); 406 my $error_undefined_override = 0; 407 my $numerical_date=0; 408 my $error = 0; 409 foreach my $field (@{DATE_FIELDS_ORDER()}) { # check that override dates can be parsed and are not blank 410 $dates{$field} = $setRecord->$field; 411 if (defined $r->param("set.$setID.$field.override") ){ 412 eval{ $numerical_date = $self->parseDateTime($r->param("set.$setID.$field"))}; 413 unless( $@ ) { 414 $dates{$field}=$numerical_date; 415 } else { 416 $self->addbadmessage(" * Badly defined time for set $setID $field. No date changes made:<br/>$@"); 417 $error = 1; 418 } 419 } 420 421 422 } 423 return {%dates,error=>1} if $error; # no point in going on if the dates can't be parsed. 424 425 my ($open_date, $due_date, $answer_date) = map { $dates{$_} } @{DATE_FIELDS_ORDER()}; 426 427 if ($answer_date < $due_date || $answer_date < $open_date) { 428 $self->addbadmessage("Answers cannot be made available until on or after the due date in set $setID!"); 429 $error = 1; 430 } 431 432 if ($due_date < $open_date) { 433 $self->addbadmessage("Answers cannot be due until on or after the open date in set $setID!"); 434 $error = 1; 435 } 436 437 # make sure the dates are not more than 10 years in the future 438 my $curr_time = time; 439 my $seconds_per_year = 31_556_926; 440 my $cutoff = $curr_time + $seconds_per_year*10; 441 if ($open_date > $cutoff) { 442 $self->addbadmessage("Error: open date cannot be more than 10 years from now in set $setID"); 443 $error = 1; 444 } 445 if ($due_date > $cutoff) { 446 $self->addbadmessage("Error: due date cannot be more than 10 years from now in set $setID"); 447 $error = 1; 448 } 449 if ($answer_date > $cutoff) { 450 $self->addbadmessage("Error: answer date cannot be more than 10 years from now in set $setID"); 451 $error = 1; 452 } 453 454 455 if ($error) { 456 $self->addbadmessage("No date changes were saved!"); 457 } 458 return {%dates,error=>$error}; 459 } 460 461 sub DBFieldTable { 462 my ($self, $GlobalRecord, $UserRecord, $MergedRecord, $recordType, $recordID, $fieldsRef,$rh_fieldLabels) = @_; 463 464 return CGI::div({class => "ResultsWithError"}, "No record exists for $recordType $recordID") unless defined $GlobalRecord; 465 466 my $r = $self->r; 467 my @fields = @$fieldsRef; 468 my @results; 469 foreach my $field (@fields) { 470 my $globalValue = $GlobalRecord->$field; 471 my $userValue = defined $UserRecord ? $UserRecord->$field : $globalValue; 472 my $mergedValue = defined $MergedRecord ? $MergedRecord->$field : $globalValue; 473 push @results, 474 [$rh_fieldLabels->{$field}, 475 defined $UserRecord ? 476 CGI::checkbox({ 477 type => "checkbox", 478 name => "$recordType.$recordID.$field.override", 479 label => "", 480 value => $field, 481 checked => $r->param("$recordType.$recordID.$field.override") || ($mergedValue ne $globalValue ? 1 : 0) 482 }) : "", 483 defined $UserRecord ? 484 (CGI::input({ -name=>"$recordType.$recordID.$field", 485 -value => $userValue ? $self->formatDateTime($userValue) : "", 486 -size => 25}) 487 ) : "", 488 $self->formatDateTime($globalValue), 489 ] 490 491 } 492 493 my @table; 494 foreach my $row (@results) { 495 push @table, CGI::Tr(CGI::td({-align => "center"}, $row)); 496 } 497 498 return (CGI::start_table({border => 0}), @table, CGI::end_table()); 499 } 500 501 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |