[system] / trunk / webwork2 / lib / WeBWorK / ContentGenerator / Instructor / UserList.pm Repository:
ViewVC logotype

Annotation of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/UserList.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1603 - (view) (download) (as text)

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9