[system] / branches / rel-2-2-dev / webwork2 / lib / WeBWorK / ContentGenerator / Instructor / UserList.pm Repository:
ViewVC logotype

Annotation of /branches/rel-2-2-dev/webwork2/lib/WeBWorK/ContentGenerator/Instructor/UserList.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1640 - (view) (download) (as text)
Original Path: trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/UserList.pm

1 : sh002i 1567 ################################################################################
2 :     # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
3 :     # $Id$
4 :     ################################################################################
5 :    
6 : malsyned 832 package WeBWorK::ContentGenerator::Instructor::UserList;
7 :     use base qw(WeBWorK::ContentGenerator::Instructor);
8 :    
9 :     =head1 NAME
10 :    
11 : sh002i 1567 WeBWorK::ContentGenerator::Instructor::UserList - Entry point for User-specific
12 :     data editing
13 : malsyned 832
14 :     =cut
15 :    
16 : sh002i 1594 =for comment
17 :    
18 :     What do we want to be able to do here?
19 :    
20 :     Filter what users are shown:
21 :     - none, all, selected
22 :     - matching user_id, matching section, matching recitation
23 :     Switch from view mode to edit mode:
24 :     - showing visible users
25 :     - showing selected users
26 :     Switch from edit mode to view and save changes
27 :     Switch from edit mode to view and abandon changes
28 :     Delete users:
29 :     - visible
30 :     - selected
31 :     Import users:
32 :     - replace:
33 :     - any users
34 :     - visible users
35 :     - selected users
36 :     - no users
37 :     - add:
38 :     - any users
39 :     - no users
40 :     Export users:
41 :     - export:
42 :     - all
43 :     - visible
44 :     - selected
45 :     - to:
46 :     - existing file on server (overwrite): [ list of files ]
47 :     - new file on server (create): [ filename ]
48 :    
49 :     =cut
50 :    
51 : malsyned 832 use strict;
52 :     use warnings;
53 :     use CGI qw();
54 : sh002i 1594 use WeBWorK::Utils qw(readFile readDirectory);
55 : malsyned 832
56 : sh002i 1567 use constant HIDE_USERS_THRESHHOLD => 20;
57 : sh002i 1594 use constant EDIT_FORMS => [qw(cancelEdit saveEdit)];
58 :     use constant VIEW_FORMS => [qw(filter edit delete import export)];
59 :     use constant STATE_PARAMS => [qw(user effectiveUser key visible_users no_visible_users prev_visible_users no_prev_visible_users editMode sortField)];
60 : sh002i 1567
61 : sh002i 1594 use constant SORT_SUBS => {
62 :     user_id => \&byUserID,
63 :     first_name => \&byFirstName,
64 :     last_name => \&byLastName,
65 :     email_address => \&byEmailAddress,
66 :     student_id => \&byStudentID,
67 :     status => \&byStatus,
68 :     section => \&bySection,
69 :     recitation => \&byRecitation,
70 :     comment => \&byComment,
71 :     };
72 :    
73 :     use constant FIELD_PROPERTIES => {
74 :     user_id => {
75 :     type => "text",
76 :     size => 8,
77 :     access => "readonly",
78 :     },
79 :     first_name => {
80 :     type => "text",
81 :     size => 10,
82 :     access => "readwrite",
83 :     },
84 :     last_name => {
85 :     type => "text",
86 :     size => 10,
87 :     access => "readwrite",
88 :     },
89 :     email_address => {
90 :     type => "text",
91 :     size => 20,
92 :     access => "readwrite",
93 :     },
94 :     student_id => {
95 :     type => "text",
96 :     size => 11,
97 :     access => "readwrite",
98 :     },
99 :     status => {
100 :     type => "enumerable",
101 :     size => 4,
102 :     access => "readwrite",
103 :     items => {
104 :     "C" => "Enrolled",
105 :     "D" => "Drop",
106 :     "A" => "Audit",
107 :     },
108 :     synonyms => {
109 :     qr/^[ce]/i => "C",
110 :     qr/^[dw]/i => "D",
111 :     qr/^a/i => "A",
112 :     "*" => "C",
113 :     }
114 :     },
115 :     section => {
116 :     type => "text",
117 :     size => 4,
118 :     access => "readwrite",
119 :     },
120 :     recitation => {
121 :     type => "text",
122 :     size => 4,
123 :     access => "readwrite",
124 :     },
125 :     comment => {
126 :     type => "text",
127 :     size => 20,
128 :     access => "readwrite",
129 :     },
130 :     permission => {
131 :     type => "number",
132 :     size => 2,
133 :     access => "readwrite",
134 :     }
135 :     };
136 :    
137 : malsyned 1015 sub initialize {
138 : malsyned 1211 my ($self) = @_;
139 :     my $r = $self->{r};
140 :     my $db = $self->{db};
141 :     my $ce = $self->{ce};
142 :     my $authz = $self->{authz};
143 :     my $user = $r->param('user');
144 :    
145 :     unless ($authz->hasPermissions($user, "modify_student_data")) {
146 :     $self->{submitError} = "You are not authorized to modify student data";
147 :     return;
148 :     }
149 :    
150 : sh002i 1601 #if (defined($r->param('addStudent'))) {
151 :     # my $newUser = $db->newUser;
152 :     # my $newPermissionLevel = $db->newPermissionLevel;
153 :     # my $newPassword = $db->newPassword;
154 :     # $newUser->user_id($r->param('newUserID'));
155 :     # $newPermissionLevel->user_id($r->param('newUserID'));
156 :     # $newPassword->user_id($r->param('newUserID'));
157 :     # $newUser->status('C');
158 :     # $newPermissionLevel->permission(0);
159 :     # $db->addUser($newUser);
160 :     # $db->addPermissionLevel($newPermissionLevel);
161 :     # $db->addPassword($newPassword);
162 :     #}
163 : malsyned 1015 }
164 :    
165 : gage 1295 sub title {
166 :     my $self = shift;
167 : sh002i 1567 return "User List";
168 : gage 1295 }
169 :    
170 :     sub path {
171 : sh002i 1567 my $self = shift;
172 :     my $args = $_[-1];
173 : gage 1295 my $ce = $self->{ce};
174 :     my $root = $ce->{webworkURLs}->{root};
175 :     my $courseName = $ce->{courseName};
176 : sh002i 1567
177 : gage 1295 return $self->pathMacro($args,
178 : sh002i 1567 "Home" => "$root",
179 :     $courseName => "$root/$courseName",
180 :     "Instructor Tools" => "$root/$courseName/instructor",
181 : sh002i 1626 "Users" => "", # "$root/$courseName/instructor/users",
182 : gage 1295 );
183 :     }
184 :    
185 : malsyned 1014 sub body {
186 : malsyned 1015 my ($self, $setID) = @_;
187 : malsyned 1014 my $r = $self->{r};
188 : malsyned 1017 my $authz = $self->{authz};
189 :     my $user = $r->param('user');
190 : malsyned 1110 my $db = $self->{db};
191 : malsyned 1293 my $ce = $self->{ce};
192 :     my $root = $ce->{webworkURLs}->{root};
193 :     my $courseName = $ce->{courseName};
194 : sh002i 1584
195 : sh002i 1594 # templates for getting field names
196 :     my $userTemplate = $self->{userTemplate} = $db->newUser;
197 :     my $permissionLevelTemplate = $self->{permissionLevelTemplate} = $db->newPermissionLevel;
198 :    
199 : sh002i 1567 return CGI::em("You are not authorized to access the Instructor tools.")
200 :     unless $authz->hasPermissions($user, "access_instructor_tools");
201 : sh002i 1584
202 : malsyned 1214 # This table can be consulted when display-ready forms of field names are needed.
203 : sh002i 1594 my %prettyFieldNames = map { $_ => $_ }
204 :     $userTemplate->FIELDS(),
205 :     $permissionLevelTemplate->FIELDS();
206 : sh002i 1567
207 : malsyned 1214 @prettyFieldNames{qw(
208 :     user_id
209 :     first_name
210 :     last_name
211 :     email_address
212 :     student_id
213 :     status
214 :     section
215 :     recitation
216 :     comment
217 :     permission
218 :     )} = (
219 :     "User ID",
220 :     "First Name",
221 :     "Last Name",
222 :     "E-mail",
223 :     "Student ID",
224 :     "Status",
225 :     "Section",
226 :     "Recitation",
227 :     "Comment",
228 :     "Perm. Level"
229 :     );
230 : sh002i 1567
231 : sh002i 1594 ########## set initial values for state fields
232 :    
233 :     my @allUserIDs = $db->listUsers;
234 :     $self->{allUserIDs} = \@allUserIDs;
235 :    
236 :     if (defined $r->param("visible_users")) {
237 :     $self->{visibleUserIDs} = [ $r->param("visible_users") ];
238 :     } elsif (defined $r->param("no_visible_users")) {
239 :     $self->{visibleUserIDs} = [];
240 :     } else {
241 : sh002i 1597 if (@allUserIDs > HIDE_USERS_THRESHHOLD) {
242 :     $self->{visibleUserIDs} = [];
243 :     } else {
244 :     $self->{visibleUserIDs} = [ @allUserIDs ];
245 :     }
246 : sh002i 1594 }
247 :    
248 :     $self->{prevVisibleUserIDs} = $self->{visibleUserIDs};
249 :    
250 :     if (defined $r->param("selected_users")) {
251 :     $self->{selectedUserIDs} = [ $r->param("selected_users") ];
252 :     } else {
253 :     $self->{selectedUserIDs} = [];
254 :     }
255 :    
256 :     $self->{editMode} = $r->param("editMode") || 0;
257 :    
258 :     $self->{sortField} = $r->param("sortField") || "last_name";
259 :    
260 : sh002i 1601 my @allUsers = $db->getUsers(@allUserIDs);
261 :     my (%sections, %recitations);
262 :     foreach my $User (@allUsers) {
263 :     push @{$sections{$User->section}}, $User->user_id;
264 :     push @{$recitations{$User->recitation}}, $User->user_id;
265 :     }
266 :     $self->{sections} = \%sections;
267 :     $self->{recitations} = \%recitations;
268 :    
269 : sh002i 1594 ########## call action handler
270 :    
271 :     my $actionID = $r->param("action");
272 :     if ($actionID) {
273 :     unless (grep { $_ eq $actionID } @{ VIEW_FORMS() }, @{ EDIT_FORMS() }) {
274 :     die "Action $actionID not found";
275 :     }
276 :     my $actionHandler = "${actionID}_handler";
277 :     my %genericParams;
278 :     foreach my $param (qw(selected_users)) {
279 :     $genericParams{$param} = [ $r->param($param) ];
280 :     }
281 :     my %actionParams = $self->getActionParams($actionID);
282 :     my %tableParams = $self->getTableParams();
283 :     print CGI::p(
284 : sh002i 1597 "Result of last action performed: ",
285 : sh002i 1594 CGI::i($self->$actionHandler(\%genericParams, \%actionParams, \%tableParams))
286 :     );
287 :     }
288 :    
289 :     ########## retrieve possibly changed values for member fields
290 :    
291 :     #@allUserIDs = @{ $self->{allUserIDs} }; # do we need this one?
292 :     my @visibleUserIDs = @{ $self->{visibleUserIDs} };
293 :     my @prevVisibleUserIDs = @{ $self->{prevVisibleUserIDs} };
294 :     my @selectedUserIDs = @{ $self->{selectedUserIDs} };
295 :     my $editMode = $self->{editMode};
296 :     my $sortField = $self->{sortField};
297 :    
298 :     #warn "visibleUserIDs=@visibleUserIDs\n";
299 :     #warn "prevVisibleUserIDs=@prevVisibleUserIDs\n";
300 :     #warn "selectedUserIDs=@selectedUserIDs\n";
301 :     #warn "editMode=$editMode\n";
302 :    
303 :     ########## get required users
304 : sh002i 1601
305 :     my @Users = grep { defined $_ } @visibleUserIDs ? $db->getUsers(@visibleUserIDs) : ();
306 : sh002i 1594
307 :     # presort users
308 :     my %sortSubs = %{ SORT_SUBS() };
309 :     my $sortSub = $sortSubs{$sortField};
310 :     #@Users = sort $sortSub @Users;
311 :     @Users = sort byLnFnUid @Users;
312 :    
313 :     my @PermissionLevels;
314 :    
315 :     for (my $i = 0; $i < @Users; $i++) {
316 :     my $User = $Users[$i];
317 :     my $PermissionLevel = $db->getPermissionLevel($User->user_id);
318 :    
319 :     unless ($PermissionLevel) {
320 :     # uh oh! no permission level record found!
321 :     warn "added missing permission level for user ", $User->user_id, "\n";
322 :    
323 :     # create a new permission level record
324 :     $PermissionLevel = $db->newPermissionLevel;
325 :     $PermissionLevel->user_id($User->user_id);
326 :     $PermissionLevel->permission(0);
327 :    
328 :     # add it to the database
329 :     $db->addPermissionLevel($PermissionLevel);
330 :     }
331 :    
332 :     $PermissionLevels[$i] = $PermissionLevel;
333 :     }
334 :    
335 :     ########## print beginning of form
336 :    
337 :     print CGI::start_form({method=>"post", action=>$r->uri, name=>"userlist"});
338 :     print $self->hidden_authen_fields();
339 :    
340 :     ########## print state data
341 :    
342 :     print "\n<!-- state data here -->\n";
343 :    
344 :     if (@visibleUserIDs) {
345 :     print CGI::hidden(-name=>"visible_users", -value=>\@visibleUserIDs);
346 :     } else {
347 :     print CGI::hidden(-name=>"no_visible_users", -value=>"1");
348 :     }
349 :    
350 :     if (@prevVisibleUserIDs) {
351 :     print CGI::hidden(-name=>"prev_visible_users", -value=>\@prevVisibleUserIDs);
352 :     } else {
353 :     print CGI::hidden(-name=>"no_prev_visible_users", -value=>"1");
354 :     }
355 :    
356 :     print CGI::hidden(-name=>"editMode", -value=>$editMode);
357 :    
358 :     print CGI::hidden(-name=>"sortField", -value=>$sortField);
359 :    
360 :     print "\n<!-- state data here -->\n";
361 :    
362 :     ########## print action forms
363 :    
364 :     print CGI::start_table({});
365 :     print CGI::Tr({}, CGI::td({-colspan=>2}, "Select an action to perform:"));
366 :    
367 :     my @formsToShow;
368 :     if ($editMode) {
369 :     @formsToShow = @{ EDIT_FORMS() };
370 :     } else {
371 :     @formsToShow = @{ VIEW_FORMS() };
372 :     }
373 :    
374 :     my $i = 0;
375 :     foreach my $actionID (@formsToShow) {
376 :     my $actionForm = "${actionID}_form";
377 :     my $onChange = "document.userlist.action[$i].checked=true";
378 :     my %actionParams = $self->getActionParams($actionID);
379 :    
380 :     print CGI::Tr({-valign=>"top"},
381 :     CGI::td({}, CGI::input({-type=>"radio", -name=>"action", -value=>$actionID})),
382 :     CGI::td({}, $self->$actionForm($onChange, %actionParams))
383 :     );
384 :    
385 :     $i++;
386 :     }
387 :    
388 :     print CGI::Tr({}, CGI::td({-colspan=>2, -align=>"center"},
389 :     CGI::submit(-value=>"Take Action!"))
390 :     );
391 :     print CGI::end_table();
392 :    
393 : sh002i 1597 ########## print table
394 :    
395 :     print CGI::p("Showing ", scalar @visibleUserIDs, " out of ", scalar @allUserIDs, " users.");
396 :    
397 :     $self->printTableHTML(\@Users, \@PermissionLevels, \%prettyFieldNames,
398 :     editMode => $editMode,
399 :     selectedUserIDs => \@selectedUserIDs,
400 :     );
401 :    
402 :    
403 : sh002i 1594 ########## print end of form
404 :    
405 :     print CGI::end_form();
406 :    
407 :     return "";
408 :     }
409 :    
410 :     ################################################################################
411 :     # extract particular params and put them in a hash (values are ARRAYREFs!)
412 :     ################################################################################
413 :    
414 :     sub getActionParams {
415 :     my ($self, $actionID) = @_;
416 :     my $r = $self->{r};
417 :    
418 :     my %actionParams;
419 :     foreach my $param ($r->param) {
420 :     next unless $param =~ m/^action\.$actionID\./;
421 :     $actionParams{$param} = [ $r->param($param) ];
422 :     }
423 :     return %actionParams;
424 :     }
425 :    
426 :     sub getTableParams {
427 :     my ($self) = @_;
428 :     my $r = $self->{r};
429 :    
430 :     my %tableParams;
431 :     foreach my $param ($r->param) {
432 :     next unless $param =~ m/^(?:user|permission)\./;
433 :     $tableParams{$param} = [ $r->param($param) ];
434 :     }
435 :     return %tableParams;
436 :     }
437 :    
438 :     ################################################################################
439 :     # actions and action triggers
440 :     ################################################################################
441 :    
442 : sh002i 1597 # filter, edit, cancelEdit, and saveEdit should stay with the display module and
443 :     # not be real "actions". that way, all actions are shown in view mode and no
444 :     # actions are shown in edit mode.
445 :    
446 : sh002i 1594 sub filter_form {
447 :     my ($self, $onChange, %actionParams) = @_;
448 : sh002i 1601 #return CGI::table({}, CGI::Tr({-valign=>"top"},
449 :     # CGI::td({},
450 :     return join("",
451 :     "Show ",
452 :     CGI::popup_menu(
453 :     -name => "action.filter.scope",
454 :     -values => [qw(all none selected match_ids match_section match_recitation)],
455 :     -default => $actionParams{"action.filter.scope"}->[0] || "selected",
456 :     -labels => {
457 :     all => "all users",
458 :     none => "no users",
459 : sh002i 1605 selected => "users selected below",
460 : sh002i 1601 match_ids => "users with matching user IDs:",
461 :     match_section => "users in selected section",
462 :     match_recitation => "users in selected recitation",
463 :     },
464 :     -onchange => $onChange,
465 :     ),
466 :     " ",
467 :     CGI::textfield(
468 :     -name => "action.filter.user_ids",
469 :     -value => $actionParams{"action.filter.user_ids"}->[0] || "",,
470 :     -width => "50",
471 :     -onchange => $onChange,
472 :     ),
473 :     " (separate multiple IDs with commas)",
474 :     CGI::br(),
475 :     "sections: ",
476 :     CGI::popup_menu(
477 :     -name => "action.filter.section",
478 :     -values => [ keys %{ $self->{sections} } ],
479 :     -default => $actionParams{"action.filter.section"}->[0] || "",
480 :     -labels => { $self->menuLabels($self->{sections}) },
481 :     -onchange => $onChange,
482 :     ),
483 :     " recitations: ",
484 :     CGI::popup_menu(
485 :     -name => "action.filter.recitation",
486 :     -values => [ keys %{ $self->{recitations} } ],
487 :     -default => $actionParams{"action.filter.recitation"}->[0] || "",
488 :     -labels => { $self->menuLabels($self->{recitations}) },
489 :     -onchange => $onChange,
490 :     ),
491 : sh002i 1594 );
492 : sh002i 1601 # ),
493 :     #));
494 : sh002i 1594 }
495 :    
496 :     # this action handler modifies the "visibleUserIDs" field based on the contents
497 :     # of the "action.filter.scope" parameter and the "selected_users"
498 :     sub filter_handler {
499 :     my ($self, $genericParams, $actionParams, $tableParams) = @_;
500 :    
501 :     my $result;
502 :    
503 :     my $scope = $actionParams->{"action.filter.scope"}->[0];
504 :     if ($scope eq "all") {
505 :     $result = "showing all users";
506 :     $self->{visibleUserIDs} = $self->{allUserIDs};
507 :     } elsif ($scope eq "none") {
508 :     $result = "showing no users";
509 :     $self->{visibleUserIDs} = [];
510 :     } elsif ($scope eq "selected") {
511 :     $result = "showing selected users";
512 :     $self->{visibleUserIDs} = $genericParams->{selected_users}; # an arrayref
513 : sh002i 1601 } elsif ($scope eq "match_ids") {
514 :     my @userIDs = split /\s*,\s*/, $actionParams->{"action.filter.user_ids"}->[0];
515 :     $self->{visibleUserIDs} = \@userIDs;
516 :     } elsif ($scope eq "match_section") {
517 :     my $section = $actionParams->{"action.filter.section"}->[0];
518 : sh002i 1604 $self->{visibleUserIDs} = $self->{sections}->{$section}; # an arrayref
519 : sh002i 1601 } elsif ($scope eq "match_recitation") {
520 :     my $recitation = $actionParams->{"action.filter.recitation"}->[0];
521 : sh002i 1604 $self->{visibleUserIDs} = $self->{recitations}->{$recitation}; # an arrayref
522 : sh002i 1594 }
523 :    
524 :     return $result;
525 :     }
526 :    
527 :     sub edit_form {
528 :     my ($self, $onChange, %actionParams) = @_;
529 :     return join("",
530 :     "Edit ",
531 :     CGI::popup_menu(
532 :     -name => "action.edit.scope",
533 :     -values => [qw(all visible selected)],
534 : sh002i 1597 -default => $actionParams{"action.edit.scope"}->[0] || "visible",
535 : sh002i 1594 -labels => {
536 :     all => "all users",
537 :     visible => "visible users",
538 :     selected => "selected users"
539 :     },
540 :     -onchange => $onChange,
541 :     ),
542 :     );
543 :     }
544 :    
545 :     sub edit_handler {
546 :     my ($self, $genericParams, $actionParams, $tableParams) = @_;
547 :    
548 :     my $result;
549 :    
550 :     my $scope = $actionParams->{"action.edit.scope"}->[0];
551 :     if ($scope eq "all") {
552 :     $result = "editing all users";
553 :     $self->{visibleUserIDs} = $self->{allUserIDs};
554 :     } elsif ($scope eq "visible") {
555 :     $result = "editing visible users";
556 :     # leave visibleUserIDs alone
557 :     } elsif ($scope eq "selected") {
558 :     $result = "editing selected users";
559 :     $self->{visibleUserIDs} = $genericParams->{selected_users}; # an arrayref
560 :     }
561 :     $self->{editMode} = 1;
562 :    
563 :     return $result;
564 :     }
565 :    
566 :     sub delete_form {
567 :     my ($self, $onChange, %actionParams) = @_;
568 :     return join("",
569 :     "Delete ",
570 :     CGI::popup_menu(
571 :     -name => "action.delete.scope",
572 : sh002i 1597 -values => [qw(visible selected)],
573 : sh002i 1594 -default => $actionParams{"action.delete.scope"}->[0] || "selected",
574 :     -labels => {
575 :     visible => "visible users",
576 :     selected => "selected users"
577 :     },
578 :     -onchange => $onChange,
579 :     ),
580 : sh002i 1597 CGI::em(" Deletion destroys all user-related data and is not undoable!"),
581 : sh002i 1594 );
582 :     }
583 :    
584 :     sub delete_handler {
585 :     my ($self, $genericParams, $actionParams, $tableParams) = @_;
586 :     my $db = $self->{db};
587 :     my $scope = $actionParams->{"action.delete.scope"}->[0];
588 :    
589 :     my @userIDsToDelete;
590 : sh002i 1597 if ($scope eq "visible") {
591 : sh002i 1594 @userIDsToDelete = @{ $self->{visibleUserIDs} };
592 :     } elsif ($scope eq "selected") {
593 :     @userIDsToDelete = @{ $self->{selectedUserIDs} };
594 :     }
595 :    
596 :     my %allUserIDs = map { $_ => 1 } @{ $self->{allUserIDs} };
597 :     my %visibleUserIDs = map { $_ => 1 } @{ $self->{visibleUserIDs} };
598 :     my %selectedUserIDs = map { $_ => 1 } @{ $self->{selectedUserIDs} };
599 :    
600 :     foreach my $userID (@userIDsToDelete) {
601 :     delete $allUserIDs{$userID};
602 :     delete $visibleUserIDs{$userID};
603 :     delete $selectedUserIDs{$userID};
604 :     $db->deleteUser($userID);
605 :     }
606 :    
607 :     $self->{allUserIDs} = [ keys %allUserIDs ];
608 :     $self->{visibleUserIDs} = [ keys %visibleUserIDs ];
609 :     $self->{selectedUserIDs} = [ keys %selectedUserIDs ];
610 :    
611 :     my $num = @userIDsToDelete;
612 :     return "deleted $num user" . ($num == 1 ? "" : "s");
613 :     }
614 :    
615 :     sub import_form {
616 :     my ($self, $onChange, %actionParams) = @_;
617 :     return join(" ",
618 :     "Import users from file",
619 :     CGI::popup_menu(
620 :     -name => "action.import.source",
621 :     -values => [ "", $self->getCSVList() ],
622 :     -default => $actionParams{"action.import.source"}->[0] || "",
623 :     -onchange => $onChange,
624 : sh002i 1597 ),
625 : sh002i 1594 "replacing",
626 :     CGI::popup_menu(
627 :     -name => "action.import.replace",
628 :     -values => [qw(any visible selected none)],
629 :     -default => $actionParams{"action.import.replace"}->[0] || "none",
630 :     -labels => {
631 :     any => "any",
632 :     visible => "visible",
633 :     selected => "selected",
634 :     none => "no",
635 :     },
636 :     -onchange => $onChange,
637 :     ),
638 : sh002i 1597 "existing users and adding",
639 : sh002i 1594 CGI::popup_menu(
640 :     -name => "action.import.add",
641 :     -values => [qw(any none)],
642 :     -default => $actionParams{"action.import.add"}->[0] || "any",
643 :     -labels => {
644 :     any => "any",
645 :     none => "no",
646 :     },
647 :     -onchange => $onChange,
648 :     ),
649 :     "new users",
650 :     );
651 :     }
652 :    
653 :     sub import_handler {
654 :     my ($self, $genericParams, $actionParams, $tableParams) = @_;
655 :    
656 :     my $source = $actionParams->{"action.import.source"}->[0];
657 :     my $add = $actionParams->{"action.import.add"}->[0];
658 :     my $replace = $actionParams->{"action.import.replace"}->[0];
659 :    
660 :     my $fileName = $source;
661 :     my $createNew = $add eq "any";
662 :     my $replaceExisting;
663 :     my @replaceList;
664 :     if ($replace eq "any") {
665 :     $replaceExisting = "any";
666 :     } elsif ($replace eq "none") {
667 :     $replaceExisting = "none";
668 :     } elsif ($replace eq "visible") {
669 :     $replaceExisting = "listed";
670 :     @replaceList = @{ $self->{visibleUserIDs} };
671 :     } elsif ($replace eq "selected") {
672 :     $replaceExisting = "listed";
673 :     @replaceList = @{ $self->{selectedUserIDs} };
674 :     }
675 :    
676 :     my ($replaced, $added, $skipped)
677 :     = $self->importUsersFromCSV($fileName, $createNew, $replaceExisting, @replaceList);
678 :    
679 : sh002i 1597 # make new users visible... do we really want to do this? probably.
680 :     push @{ $self->{visibleUserIDs} }, @$added;
681 :    
682 : sh002i 1594 my $numReplaced = @$replaced;
683 :     my $numAdded = @$added;
684 :     my $numSkipped = @$skipped;
685 :    
686 :     return $numReplaced . " user" . ($numReplaced == 1 ? "" : "s") . " replaced, "
687 :     . $numAdded . " user" . ($numAdded == 1 ? "" : "s") . " added, "
688 :     . $numSkipped . " user" . ($numSkipped == 1 ? "" : "s") . " skipped.";
689 :     }
690 :    
691 :     sub export_form {
692 :     my ($self, $onChange, %actionParams) = @_;
693 : sh002i 1597 return join("",
694 :     "Export ",
695 : sh002i 1594 CGI::popup_menu(
696 :     -name => "action.export.scope",
697 :     -values => [qw(all visible selected)],
698 : sh002i 1597 -default => $actionParams{"action.export.scope"}->[0] || "visible",
699 : sh002i 1594 -labels => {
700 :     all => "all users",
701 :     visible => "visible users",
702 :     selected => "selected users"
703 :     },
704 :     -onchange => $onChange,
705 :     ),
706 : sh002i 1597 " to ",
707 : sh002i 1594 CGI::popup_menu(
708 : sh002i 1597 -name=>"action.export.target",
709 :     -values => [ "new", $self->getCSVList() ],
710 :     -labels => { new => "a new file named:" },
711 :     -default => $actionParams{"action.export.target"}->[0] || "",
712 : sh002i 1594 -onchange => $onChange,
713 : sh002i 1597 ),
714 :     #CGI::br(),
715 :     #"new file to create: ",
716 : sh002i 1594 CGI::textfield(
717 : sh002i 1597 -name => "action.export.new",
718 :     -value => $actionParams{"action.export.new"}->[0] || "",,
719 :     -width => "50",
720 :     -onchange => $onChange,
721 : sh002i 1594 ),
722 : sh002i 1597 CGI::tt(".lst"),
723 : sh002i 1594 );
724 :     }
725 :    
726 : sh002i 1597 sub export_handler {
727 :     my ($self, $genericParams, $actionParams, $tableParams) = @_;
728 :    
729 :     my $scope = $actionParams->{"action.export.scope"}->[0];
730 :     my $target = $actionParams->{"action.export.target"}->[0];
731 :     my $new = $actionParams->{"action.export.new"}->[0];
732 :    
733 :     my $fileName;
734 :     if ($target eq "new") {
735 :     $fileName = $new;
736 :     } else {
737 :     $fileName = $target;
738 :     }
739 :    
740 :     $fileName .= ".lst" unless $fileName =~ m/\.lst$/;
741 :    
742 :     my @userIDsToExport;
743 :     if ($scope eq "all") {
744 :     @userIDsToExport = @{ $self->{allUserIDs} };
745 :     } elsif ($scope eq "visible") {
746 :     @userIDsToExport = @{ $self->{visibleUserIDs} };
747 :     } elsif ($scope eq "selected") {
748 :     @userIDsToExport = @{ $self->{selectedUserIDs} };
749 :     }
750 :    
751 :     $self->exportUsersToCSV($fileName, @userIDsToExport);
752 :    
753 :     return scalar @userIDsToExport . " users exported";
754 :     }
755 :    
756 : sh002i 1594 sub cancelEdit_form {
757 :     my ($self, $onChange, %actionParams) = @_;
758 :     return "Abandon changes";
759 :     }
760 :    
761 :     sub cancelEdit_handler {
762 :     my ($self, $genericParams, $actionParams, $tableParams) = @_;
763 :     my $r = $self->{r};
764 :    
765 :     #$self->{selectedUserIDs} = $self->{visibleUserIDs};
766 :     # only do the above if we arrived here via "edit selected users"
767 :     if (defined $r->param("prev_visible_users")) {
768 :     $self->{visibleUserIDs} = [ $r->param("prev_visible_users") ];
769 :     } elsif (defined $r->param("no_prev_visible_users")) {
770 :     $self->{visibleUserIDs} = [];
771 :     } else {
772 :     # leave it alone
773 :     }
774 :     $self->{editMode} = 0;
775 :    
776 :     return "changes abandoned";
777 :     }
778 :    
779 :     sub saveEdit_form {
780 :     my ($self, $onChange, %actionParams) = @_;
781 :     return "Save changes";
782 :     }
783 :    
784 :     sub saveEdit_handler {
785 :     my ($self, $genericParams, $actionParams, $tableParams) = @_;
786 :     my $r = $self->{r};
787 :     my $db = $self->{db};
788 :    
789 :     my @visibleUserIDs = @{ $self->{visibleUserIDs} };
790 :     foreach my $userID (@visibleUserIDs) {
791 :     my $User = $db->getUser($userID);
792 :     my $PermissionLevel = $db->getPermissionLevel($userID);
793 :    
794 :     foreach my $field ($User->NONKEYFIELDS()) {
795 :     my $param = "user.${userID}.${field}";
796 :     if (defined $tableParams->{$param}->[0]) {
797 :     $User->$field($tableParams->{$param}->[0]);
798 : malsyned 1233 }
799 :     }
800 : sh002i 1594
801 :     foreach my $field ($PermissionLevel->NONKEYFIELDS()) {
802 :     my $param = "permission.${userID}.${field}";
803 :     if (defined $tableParams->{$param}->[0]) {
804 :     $PermissionLevel->$field($tableParams->{$param}->[0]);
805 :     }
806 :     }
807 :    
808 :     $db->putUser($User);
809 :     $db->putPermissionLevel($PermissionLevel);
810 :     }
811 :    
812 :     if (defined $r->param("prev_visible_users")) {
813 :     $self->{visibleUserIDs} = [ $r->param("prev_visible_users") ];
814 :     } elsif (defined $r->param("no_prev_visible_users")) {
815 :     $self->{visibleUserIDs} = [];
816 :     } else {
817 :     # leave it alone
818 :     }
819 :    
820 :     $self->{editMode} = 0;
821 :    
822 :     return "changes saved";
823 :     }
824 :    
825 :     ################################################################################
826 :     # sorts
827 :     ################################################################################
828 :    
829 :     sub byUserID { $a->user_id cmp $b->user_id }
830 :     sub byFirstName { $a->first_name cmp $b->first_name }
831 :     sub byLastName { $a->last_name cmp $b->last_name }
832 :     sub byEmailAddress { $a->email_address cmp $b->email_address }
833 :     sub byStudentID { $a->student_id cmp $b->student_id }
834 :     sub byStatus { $a->status cmp $b->status }
835 :     sub bySection { $a->section cmp $b->section }
836 :     sub byRecitation { $a->recitation cmp $b->recitation }
837 :     sub byComment { $a->comment cmp $b->comment }
838 :    
839 :     sub byLnFnUid { &byLastName || &byFirstName || &byUserID }
840 :    
841 :     ################################################################################
842 :     # utilities
843 :     ################################################################################
844 :    
845 :     # generate labels for section/recitation popup menus
846 :     sub menuLabels {
847 :     my ($self, $hashRef) = @_;
848 :     my %hash = %$hashRef;
849 :    
850 :     my %result;
851 :     foreach my $key (keys %hash) {
852 :     my $count = @{ $hash{$key} };
853 :     my $displayKey = $key || "<none>";
854 :     $result{$key} = "$displayKey ($count users)";
855 :     }
856 :     return %result;
857 :     }
858 :    
859 :     sub importUsersFromCSV {
860 :     my ($self, $fileName, $createNew, $replaceExisting, @replaceList) = @_;
861 :     my $ce = $self->{ce};
862 :     my $db = $self->{db};
863 :     my $dir = $ce->{courseDirs}->{templates};
864 :    
865 :     die "illegal character in input: \"/\"" if $fileName =~ m|/|;
866 :     die "won't be able to read from file $dir/$fileName: does it exist? is it readable?"
867 :     unless -r "$dir/$fileName";
868 :    
869 :     my %allUserIDs = map { $_ => 1 } @{ $self->{allUserIDs} };
870 :     my %replaceOK;
871 :     if ($replaceExisting eq "none") {
872 :     %replaceOK = ();
873 :     } elsif ($replaceExisting eq "listed") {
874 :     %replaceOK = map { $_ => 1 } @replaceList;
875 :     } elsif ($replaceExisting eq "any") {
876 :     %replaceOK = %allUserIDs;
877 :     }
878 :    
879 :     my (@replaced, @added, @skipped);
880 :    
881 :     my @contents = split /\n/, readFile("$dir/$fileName");
882 :     foreach my $string (@contents) {
883 :     $string =~ s/^\s+//;
884 :     $string =~ s/\s+$//;
885 :     my (
886 :     $student_id, $last_name, $first_name, $status, $comment,
887 :     $section, $recitation, $email_address, $user_id
888 :     ) = split /\s*,\s*/, $string;
889 :    
890 :     if (exists $allUserIDs{$user_id} and not exists $replaceOK{$user_id}) {
891 :     push @skipped, $user_id;
892 :     next;
893 :     }
894 :    
895 :     if (not exists $allUserIDs{$user_id} and not $createNew) {
896 :     push @skipped, $user_id;
897 :     next;
898 :     }
899 :    
900 :     my $User = $db->newUser;
901 :     $User->user_id($user_id);
902 :     $User->first_name($first_name);
903 :     $User->last_name($last_name);
904 :     $User->email_address($email_address);
905 :     $User->student_id($student_id);
906 :     $User->status($status);
907 :     $User->section($section);
908 :     $User->recitation($recitation);
909 :     $User->comment($comment);
910 :    
911 :     my $PermissionLevel = $db->newPermissionLevel;
912 :     $PermissionLevel->user_id($user_id);
913 :     $PermissionLevel->permission(0);
914 :    
915 :     my $Password = $db->newPassword;
916 :     $Password->user_id($user_id);
917 :     $Password->password($student_id);
918 :    
919 :     if (exists $allUserIDs{$user_id}) {
920 :     $db->putUser($User);
921 :     $db->putPermissionLevel($PermissionLevel);
922 :     $db->putPassword($Password);
923 :     push @replaced, $user_id;
924 :     } else {
925 :     $db->addUser($User);
926 :     $db->addPermissionLevel($PermissionLevel);
927 :     $db->addPassword($Password);
928 :     push @added, $user_id;
929 :     }
930 :     }
931 :    
932 :     return \@replaced, \@added, \@skipped;
933 :     }
934 :    
935 : sh002i 1597 sub exportUsersToCSV {
936 :     my ($self, $fileName, @userIDsToExport) = @_;
937 :     my $ce = $self->{ce};
938 :     my $db = $self->{db};
939 :     my $dir = $ce->{courseDirs}->{templates};
940 :    
941 :     die "illegal character in input: \"/\"" if $fileName =~ m|/|;
942 :    
943 :     open my $fh, ">", "$dir/$fileName"
944 :     or die "failed to open file $dir/$fileName for writing: $!\n";
945 :    
946 :     foreach my $userID (@userIDsToExport) {
947 :     my $User = $db->getUser($userID);
948 :     my @fields = (
949 :     $User->student_id,
950 :     $User->last_name,
951 :     $User->first_name,
952 :     $User->status,
953 :     $User->comment,
954 :     $User->section,
955 :     $User->recitation,
956 :     $User->email_address,
957 :     $User->user_id,
958 :     );
959 :     my $string = join ",", @fields;
960 :     print $fh "$string\n";
961 :     }
962 :    
963 :     close $fh;
964 :     }
965 :    
966 : sh002i 1594 ################################################################################
967 :     # "display" methods
968 :     ################################################################################
969 :    
970 :     sub fieldEditHTML {
971 :     my ($self, $fieldName, $value, $properties) = @_;
972 :     my $size = $properties->{size};
973 :     my $type = $properties->{type};
974 :     my $access = $properties->{access};
975 :     my $items = $properties->{items};
976 :     my $synonyms = $properties->{synonyms};
977 :    
978 :     if ($access eq "readonly") {
979 :     return $value;
980 :     }
981 :    
982 :     if ($type eq "number" or $type eq "text") {
983 :     return CGI::input({type=>"text", name=>$fieldName, value=>$value, size=>$size});
984 :     }
985 :    
986 :     if ($type eq "enumerable") {
987 :     my $matched = undef; # Whether a synonym match has occurred
988 :    
989 :     # Process synonyms for enumerable objects
990 :     foreach my $synonym (keys %$synonyms) {
991 :     if ($synonym ne "*" and $value =~ m/$synonym/) {
992 :     $value = $synonyms->{$synonym};
993 :     $matched = 1;
994 :     }
995 :     }
996 :    
997 :     if (!$matched and exists $synonyms->{"*"}) {
998 :     $value = $synonyms->{"*"};
999 :     }
1000 :    
1001 :     return CGI::popup_menu({
1002 :     name => $fieldName,
1003 :     values => [keys %$items],
1004 :     default => $value,
1005 :     labels => $items,
1006 :     });
1007 :     }
1008 :     }
1009 :    
1010 :     sub recordEditHTML {
1011 :     my ($self, $User, $PermissionLevel, %options) = @_;
1012 :     my $r = $self->{r};
1013 :     my $ce = $self->{ce};
1014 :     my $root = $ce->{webworkURLs}->{root};
1015 :     my $courseName = $ce->{courseName};
1016 :    
1017 :     my $editMode = $options{editMode};
1018 :     my $userSelected = $options{userSelected};
1019 :    
1020 :     my $changeEUserURL = "$root/$courseName?"
1021 :     . "user=" . $r->param("user")
1022 :     . "&effectiveUser=" . $User->user_id
1023 :     . "&key=" . $r->param("key");
1024 :    
1025 : sh002i 1640 my $setsAssignedToUserURL = "$root/$courseName/instructor/users/"
1026 :     . $User->user_id . "/sets/?"
1027 :     . "user=" . $r->param("user")
1028 :     . "&effectiveUser=" . $r->param("effectiveUser")
1029 :     . "&key=" . $r->param("key");
1030 :    
1031 : sh002i 1594 my @tableCells;
1032 :    
1033 :     # Select
1034 :     if ($editMode) {
1035 :     # column not there
1036 :     } else {
1037 :     # selection checkbox
1038 :     push @tableCells, CGI::checkbox(
1039 :     -name => "selected_users",
1040 :     -value => $User->user_id,
1041 :     -checked => $userSelected,
1042 :     -label => "",
1043 :     );
1044 :     }
1045 :    
1046 : sh002i 1640 # Act As
1047 :     if ($editMode) {
1048 :     # column not there
1049 :     } else {
1050 :     # selection checkbox
1051 :     push @tableCells, CGI::a({href=>$changeEUserURL}, "Act&nbsp;As");
1052 :     }
1053 :    
1054 : sh002i 1594 # User ID
1055 :     if ($editMode) {
1056 :     # straight user ID
1057 :     push @tableCells, $User->user_id;
1058 :     } else {
1059 : sh002i 1640 # "edit sets assigned to user" link
1060 :     push @tableCells, CGI::a({href=>$setsAssignedToUserURL}, $User->user_id);
1061 : sh002i 1594 }
1062 :    
1063 :     # User Fields
1064 :     foreach my $field ($User->NONKEYFIELDS) {
1065 :     my $fieldName = "user." . $User->user_id . "." . $field,
1066 :     my $fieldValue = $User->$field;
1067 :     my %properties = %{ FIELD_PROPERTIES()->{$field} };
1068 :     $properties{access} = "readonly" unless $editMode;
1069 :     push @tableCells, $self->fieldEditHTML($fieldName, $fieldValue, \%properties);
1070 :     }
1071 :    
1072 :     # PermissionLevel Fields
1073 :     foreach my $field ($PermissionLevel->NONKEYFIELDS) {
1074 :     my $fieldName = "permission." . $PermissionLevel->user_id . "." . $field,
1075 :     my $fieldValue = $PermissionLevel->$field;
1076 :     my %properties = %{ FIELD_PROPERTIES()->{$field} };
1077 :     $properties{access} = "readonly" unless $editMode;
1078 :     push @tableCells, $self->fieldEditHTML($fieldName, $fieldValue, \%properties);
1079 :     }
1080 :    
1081 :     return CGI::Tr({}, CGI::td({}, \@tableCells));
1082 :     }
1083 :    
1084 :     sub printTableHTML {
1085 :     my ($self, $UsersRef, $PermissionLevelsRef, $fieldNamesRef, %options) = @_;
1086 :     my $r = $self->{r};
1087 :     my $userTemplate = $self->{userTemplate};
1088 :     my $permissionLevelTemplate = $self->{permissionLevelTemplate};
1089 :     my @Users = @$UsersRef;
1090 :     my @PermissionLevels = @$PermissionLevelsRef;
1091 :     my %fieldNames = %$fieldNamesRef;
1092 :    
1093 :     my $editMode = $options{editMode};
1094 :     my %selectedUserIDs = map { $_ => 1 } @{ $options{selectedUserIDs} };
1095 :     my $currentSort = $options{currentSort};
1096 :    
1097 :     # names of headings:
1098 :     my @realFieldNames = (
1099 :     $userTemplate->KEYFIELDS,
1100 :     $userTemplate->NONKEYFIELDS,
1101 :     $permissionLevelTemplate->NONKEYFIELDS,
1102 : malsyned 1233 );
1103 :    
1104 : sh002i 1594 my %sortSubs = %{ SORT_SUBS() };
1105 :     #my @stateParams = @{ STATE_PARAMS() };
1106 :     #my $hrefPrefix = $r->uri . "?" . $self->url_args(@stateParams); # $self->url_authen_args
1107 :     my @tableHeadings;
1108 :     foreach my $field (@realFieldNames) {
1109 :     my $result;
1110 :     #if (exists $sortSubs{$field}) {
1111 :     # $result = CGI::a({-href=>"$hrefPrefix&sort=$field"}, $fieldNames{$field});
1112 :     #} else {
1113 :     $result = $fieldNames{$field};
1114 :     #}
1115 :     push @tableHeadings, $result;
1116 :     };
1117 :    
1118 :     # prepend selection checkbox? only if we're NOT editing!
1119 : sh002i 1640 unshift @tableHeadings, "Select", "Act As" unless $editMode;
1120 : sh002i 1594
1121 :     # print the table
1122 :     if ($editMode) {
1123 :     print CGI::start_table({});
1124 :     } else {
1125 :     print CGI::start_table({-border=>1});
1126 :     }
1127 :    
1128 :     print CGI::Tr({}, CGI::th({}, \@tableHeadings));
1129 :    
1130 :     for (my $i = 0; $i < @Users; $i++) {
1131 :     my $User = $Users[$i];
1132 :     my $PermissionLevel = $PermissionLevels[$i];
1133 :    
1134 :     print $self->recordEditHTML($User, $PermissionLevel,
1135 :     editMode => $editMode,
1136 :     userSelected => exists $selectedUserIDs{$User->user_id}
1137 :     );
1138 :     }
1139 :    
1140 :     print CGI::end_table();
1141 :     }
1142 :    
1143 :     1;
1144 :    
1145 :     __END__
1146 :    
1147 :     my $editMode = 0;
1148 :     if (defined $r->param("edit_selected") or defined $r->param("edit_visible")) {
1149 :     $editMode = 1;
1150 :     }
1151 :    
1152 : sh002i 1567 my @userIDs = $db->listUsers;
1153 :     my @userRecords = $db->getUsers(@userIDs);
1154 :    
1155 :     my (%sections, %recitations);
1156 :     foreach my $user (@userRecords) {
1157 :     push @{$sections{$user->section}}, $user;
1158 :     push @{$recitations{$user->recitation}}, $user;
1159 :     }
1160 :    
1161 :     my $filter_type = $r->param("filter_type")
1162 :     || (@userIDs > HIDE_USERS_THRESHHOLD ? "none" : "all");
1163 :     my $filter_user_id = $filter_type eq "filter_user_id"
1164 :     ? $r->param("filter_user_id") || ""
1165 :     : "";
1166 :     my $filter_section = $filter_type eq "filter_section"
1167 :     ? $r->param("filter_section") || ""
1168 :     : "";
1169 :     my $filter_recitation = $filter_type eq "filter_recitation"
1170 :     ? $r->param("filter_recitation") || ""
1171 :     : "";
1172 :    
1173 : sh002i 1584 # override filter selection if "Edit Selected Users" button is pressed
1174 :     if (defined $r->param("edit_selected")) {
1175 :     $filter_type = "filter_selected";
1176 :     }
1177 :    
1178 : sh002i 1567 if ($filter_type eq "none") {
1179 :     @userRecords = ();
1180 : sh002i 1584 } elsif ($filter_type eq "filter_selected") {
1181 :     @userRecords = ();
1182 :     my @userIDs = $r->param("selectUser");
1183 :     if (@userIDs) {
1184 :     @userRecords = $db->getUsers(@userIDs);
1185 :     }
1186 : sh002i 1567 } elsif ($filter_type eq "filter_user_id") {
1187 :     @userRecords = ();
1188 :     if ($filter_user_id ne "") {
1189 :     my $userRecord = $db->getUser($filter_user_id);
1190 :     @userRecords = ($userRecord) if $userRecord;
1191 :     }
1192 :     } elsif ($filter_type eq "filter_section") {
1193 :     @userRecords = ();
1194 :     @userRecords = @{$sections{$filter_section}}
1195 :     if exists $sections{$filter_section};
1196 :     } elsif ($filter_type eq "filter_recitation") {
1197 :     @userRecords = ();
1198 :     @userRecords = @{$recitations{$filter_recitation}}
1199 :     if exists $recitations{$filter_recitation};
1200 :     }
1201 :    
1202 :     @userRecords = sort {
1203 :     (lc $a->section cmp lc $b->section)
1204 :     || (lc $a->last_name cmp lc $b->last_name)
1205 :     || (lc $a->first_name cmp lc $b->first_name)
1206 :     || (lc $a->user_id cmp lc $b->user_id)
1207 :     } @userRecords;
1208 :    
1209 : malsyned 1211 print CGI::start_form({method=>"post", action=>$r->uri()});
1210 : sh002i 1567 print $self->hidden_authen_fields();
1211 :    
1212 : sh002i 1594 filter options
1213 : sh002i 1567 my %labels = (
1214 :     none => "No users",
1215 : sh002i 1584 all => "All " . scalar @userIDs . " users",
1216 :     filter_selected => "Users selected below",
1217 : sh002i 1567 filter_user_id => "User with ID " . CGI::input({
1218 :     type=>"text",
1219 :     name=>"filter_user_id",
1220 :     value=>$filter_user_id,
1221 :     size=>"20"
1222 :     }),
1223 :     filter_section => "Users in section " . CGI::popup_menu(
1224 :     -name=>"filter_section",
1225 :     -values=>[ keys %sections ],
1226 :     -labels=>{ $self->menuLabels(\%sections) },
1227 :     -default=>$filter_section,
1228 :     ),
1229 :     filter_recitation => "Users in recitation " . CGI::popup_menu(
1230 :     -name=>"filter_recitation",
1231 :     -values=>[ sort keys %recitations ],
1232 :     -labels=>{ $self->menuLabels(\%recitations) },
1233 :     -default=>$filter_recitation,
1234 :     ),
1235 :     );
1236 :    
1237 : sh002i 1584 if ($editMode) {
1238 :     print CGI::hidden(
1239 :     -name=>"filter_type",
1240 :     -value=>"filter_selected",
1241 :     );
1242 :     } else {
1243 :     my $cgi = new CGI;
1244 :     $cgi->autoEscape(0);
1245 :     print "Show:", CGI::br();
1246 :     print $cgi->radio_group(
1247 :     -name=>"filter_type",
1248 :     -values=>[ qw(none all filter_selected filter_user_id filter_section filter_recitation) ],
1249 :     -default=>$filter_type,
1250 :     -linebreak=>"true",
1251 :     -labels=>\%labels,
1252 :     -rows=>3,
1253 :     -columns=>2,
1254 :     );
1255 :     print CGI::submit({name=>"filter", value=>"Filter"});
1256 :     }
1257 :    
1258 : malsyned 1110 print CGI::start_table({});
1259 : malsyned 1214
1260 :     # Table headings, prettied-up
1261 : sh002i 1567 my @tableHeadings = (
1262 : sh002i 1584 ($editMode ? () : "Select"),
1263 : sh002i 1567 map {$prettyFieldNames{$_}} (
1264 :     $userTemplate->KEYFIELDS(),
1265 :     $userTemplate->NONKEYFIELDS(),
1266 :     $permissionLevelTemplate->NONKEYFIELDS(),
1267 :     ),
1268 :     );
1269 :    
1270 :     # now print them
1271 : malsyned 1110 print CGI::Tr({},
1272 : sh002i 1567 CGI::th({}, \@tableHeadings)
1273 : malsyned 1110 );
1274 : sh002i 1567
1275 : sh002i 1584 my @userIDsForHiddenSelectField;
1276 :    
1277 : gage 1473 # process user records
1278 :     foreach my $userRecord (@userRecords) {
1279 :     my $currentUser = $userRecord->user_id;
1280 : sh002i 1584 push @userIDsForHiddenSelectField, $currentUser;
1281 : malsyned 1110 my $permissionLevel = $db->getPermissionLevel($currentUser);
1282 : gage 1357 unless (defined $permissionLevel) {
1283 : sh002i 1567 warn "No permissionLevel record for user $currentUser -- added";
1284 : gage 1473 my $newPermissionLevel = $db->newPermissionLevel;
1285 :     $newPermissionLevel->user_id($currentUser);
1286 :     $newPermissionLevel->permission(0);
1287 :     $db->addPermissionLevel($newPermissionLevel);
1288 : sh002i 1567 $permissionLevel = $newPermissionLevel;
1289 : gage 1473 # permission set to minimum level
1290 : gage 1357 }
1291 : malsyned 1110
1292 : malsyned 1214 # A concise way of printing a row containing a cell for each field, editable unless it's a key
1293 : malsyned 1110 print CGI::Tr({},
1294 :     CGI::td({}, [
1295 : sh002i 1584 ($editMode
1296 :     ? () # don't show selection checkbox if we're in edit mode -- hidden field below
1297 :     #: CGI::input({type=>"checkbox", name=>"selectUser", value=>$currentUser})
1298 :     : CGI::checkbox(
1299 :     -name=>"selectUser",
1300 :     -value=>$currentUser,
1301 :     -checked=>($filter_type eq "filter_selected" and not defined $r->param("editingAllVisibleUsers")),
1302 :     -label=>""
1303 :     )
1304 :     ),
1305 :     ($editMode
1306 :     ? $currentUser
1307 :     : (map {
1308 :     my $changeEUserURL = "$root/$courseName?"
1309 :     . "user=" . $r->param("user")
1310 :     . "&effectiveUser=" . $userRecord->user_id
1311 :     . "&key=" . $r->param("key");
1312 :     CGI::a({href=>$changeEUserURL}, $userRecord->$_)
1313 :     } $userRecord->KEYFIELDS)
1314 :     ),
1315 : malsyned 1233 (map {
1316 : sh002i 1567 $self->fieldEditHTML(
1317 :     "user." . $userRecord->user_id . "." .$_,
1318 :     $userRecord->$_, $fieldProperties{$_});
1319 : malsyned 1233 } $userRecord->NONKEYFIELDS()),
1320 :     (map {
1321 : sh002i 1567 $self->fieldEditHTML(
1322 :     "permission." . $permissionLevel->user_id . "." . $_,
1323 :     $permissionLevel->$_, $fieldProperties{$_});
1324 : malsyned 1233 } $permissionLevel->NONKEYFIELDS()),
1325 : malsyned 1110 ])
1326 :     );
1327 :     }
1328 : malsyned 1214
1329 : sh002i 1567 unless (@userRecords) {
1330 :     print CGI::Tr({},
1331 :     CGI::td({-colspan=>scalar(@tableHeadings), -align=>"center"},
1332 :     "No users match the filter criteria above."
1333 :     ),
1334 :     );
1335 :     }
1336 :    
1337 : malsyned 1110 print CGI::end_table();
1338 : sh002i 1584
1339 :     if ($editMode) {
1340 :     print CGI::hidden(-name=>"selectUser", -value=>[ @userIDsForHiddenSelectField ]);
1341 :     if (defined $r->param("edit_visible")) {
1342 :     print CGI::hidden(-name=>"editingAllVisibleUsers", -value=>1);
1343 :     }
1344 :     }
1345 :    
1346 :     if ($editMode) {
1347 :     print CGI::submit({name=>"discard_chagnes", value=>"Discard Changes to Users"});
1348 :     print CGI::submit({name=>"save_classlist", value=>"Save Changes to Users"});
1349 :     } else {
1350 :     print CGI::submit({name=>"edit_visible", value=>"Edit Visible Users"});
1351 :     print CGI::submit({name=>"edit_selected", value=>"Edit Selected Users"});
1352 :     print CGI::submit({name=>"delete_selected", value=>"Delete Selected Users"});
1353 :     }
1354 :    
1355 : malsyned 1211 print CGI::end_form();
1356 : malsyned 1017
1357 : malsyned 1214 # Add a student form
1358 : sh002i 1584 unless ($editMode) {
1359 :     print CGI::start_form({method=>"post", action=>$r->uri()});
1360 :     print $self->hidden_authen_fields();
1361 :     print "User ID:";
1362 :     print CGI::input({type=>"text", name=>"newUserID", value=>"", size=>"20"});
1363 :     print CGI::submit({name=>"addStudent", value=>"Add User"});
1364 :     print CGI::end_form();
1365 :     }
1366 : malsyned 1214
1367 : malsyned 1014 return "";

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9