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