| 1 | ################################################################################ |
1 | ################################################################################ |
| 2 | # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project |
2 | # WeBWorK Online Homework Delivery System |
| 3 | # $Id$ |
3 | # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/ |
|
|
4 | # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/Index.pm,v 1.37 2004/05/24 01:34:51 mschmitt Exp $ |
|
|
5 | # |
|
|
6 | # This program is free software; you can redistribute it and/or modify it under |
|
|
7 | # the terms of either: (a) the GNU General Public License as published by the |
|
|
8 | # Free Software Foundation; either version 2, or (at your option) any later |
|
|
9 | # version, or (b) the "Artistic License" which comes with this package. |
|
|
10 | # |
|
|
11 | # This program is distributed in the hope that it will be useful, but WITHOUT |
|
|
12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
|
13 | # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the |
|
|
14 | # Artistic License for more details. |
| 4 | ################################################################################ |
15 | ################################################################################ |
| 5 | |
16 | |
| 6 | package WeBWorK::ContentGenerator::Instructor::Index; |
17 | package WeBWorK::ContentGenerator::Instructor::Index; |
| 7 | use base qw(WeBWorK::ContentGenerator::Instructor); |
18 | use base qw(WeBWorK::ContentGenerator::Instructor); |
| 8 | |
19 | |
| 9 | =head1 NAME |
20 | =head1 NAME |
| 10 | |
21 | |
| 11 | WeBWorK::ContentGenerator::Instructor::Index - Menu interface to the Instructor pages |
22 | WeBWorK::ContentGenerator::Instructor::Index - Menu interface to the Instructor |
|
|
23 | pages |
| 12 | |
24 | |
| 13 | =cut |
25 | =cut |
| 14 | |
26 | |
| 15 | use strict; |
27 | use strict; |
| 16 | use warnings; |
28 | use warnings; |
|
|
29 | use Apache::Constants qw(:response); |
| 17 | use CGI qw(); |
30 | use CGI qw(); |
|
|
31 | use WeBWorK::HTML::ScrollingRecordList qw/scrollingRecordList/; |
|
|
32 | #use WeBWorK::Utils::FilterRecords qw/getFiltersForClass/; |
| 18 | |
33 | |
| 19 | sub title { |
34 | use constant E_NO_USERS => "Please do not select any users."; |
| 20 | my $self = shift; |
35 | use constant E_NO_SETS => "Please do not select any sets."; |
| 21 | return "Instructor tools for ".$self->{ce}->{courseName}; |
36 | use constant E_MAX_ONE_USER => "Please select at most one user."; |
|
|
37 | use constant E_MAX_ONE_SET => "Please select at most one set."; |
|
|
38 | use constant E_ONE_USER => "Please select exactly one user."; |
|
|
39 | use constant E_ONE_SET => "Please select exactly one set."; |
|
|
40 | use constant E_MIN_ONE_USER => "Please select at least one user."; |
|
|
41 | use constant E_MIN_ONE_SET => "Please select at least one set."; |
|
|
42 | |
|
|
43 | sub pre_header_initialize { |
|
|
44 | my ($self) = @_; |
|
|
45 | my $r = $self->r; |
|
|
46 | my $ce = $r->ce; |
|
|
47 | my $db = $r->db; |
|
|
48 | my $authz = $r->authz; |
|
|
49 | my $urlpath = $r->urlpath; |
|
|
50 | |
|
|
51 | my $courseID = $urlpath->arg("courseID"); |
|
|
52 | my $userID = $r->param("user"); |
|
|
53 | my $eUserID = $r->param("effectiveUser"); |
|
|
54 | |
|
|
55 | # Check permissions |
|
|
56 | return unless ($authz->hasPermissions($userID, "access_instructor_tools")); |
|
|
57 | |
|
|
58 | my @selectedUserIDs = $r->param("selected_users"); |
|
|
59 | my @selectedSetIDs = $r->param("selected_sets"); |
|
|
60 | |
|
|
61 | my $nusers = @selectedUserIDs; |
|
|
62 | my $nsets = @selectedSetIDs; |
|
|
63 | |
|
|
64 | my $firstUserID = $nusers ? $selectedUserIDs[0] : ""; |
|
|
65 | my $firstSetID = $nsets ? $selectedSetIDs[0] : ""; |
|
|
66 | |
|
|
67 | # these will be used to construct a new URL |
|
|
68 | my $module; |
|
|
69 | my %args = ( courseID => $courseID ); |
|
|
70 | my %params; |
|
|
71 | |
|
|
72 | my $pfx = "WeBWorK::ContentGenerator"; |
|
|
73 | my $ipfx = "WeBWorK::ContentGenerator::Instructor"; |
|
|
74 | |
|
|
75 | my @error; |
|
|
76 | |
|
|
77 | # depending on which button was pushed, fill values in for URL construction |
|
|
78 | |
|
|
79 | defined param $r "sets_assigned_to_user" and do { |
|
|
80 | if ($nusers == 1) { |
|
|
81 | $module = "${ipfx}::SetsAssignedToUser"; |
|
|
82 | $args{userID} = $firstUserID; |
|
|
83 | } else { |
|
|
84 | push @error, E_ONE_USER; |
|
|
85 | } |
|
|
86 | }; |
|
|
87 | |
|
|
88 | defined param $r "users_assigned_to_set" and do { |
|
|
89 | if ($nsets == 1) { |
|
|
90 | $module = "${ipfx}::UsersAssignedToSet"; |
|
|
91 | $args{setID} = $firstSetID; |
|
|
92 | } else { |
|
|
93 | push @error, E_ONE_SET; |
|
|
94 | } |
|
|
95 | }; |
|
|
96 | |
|
|
97 | defined param $r "edit_users" and do { |
|
|
98 | if ($nusers >= 1) { |
|
|
99 | $module = "${ipfx}::UserList"; |
|
|
100 | $params{visible_users} = \@selectedUserIDs; |
|
|
101 | $params{editMode} = 1; |
|
|
102 | } else { |
|
|
103 | push @error, E_MIN_ONE_USER; |
|
|
104 | } |
|
|
105 | }; |
|
|
106 | |
|
|
107 | defined param $r "edit_sets" and do { |
|
|
108 | if ($nsets == 1) { |
|
|
109 | $module = "${ipfx}::ProblemSetEditor"; |
|
|
110 | $args{setID} = $firstSetID; |
|
|
111 | } else { |
|
|
112 | push @error, E_ONE_SET; |
|
|
113 | |
|
|
114 | } |
|
|
115 | }; |
|
|
116 | |
|
|
117 | defined param $r "user_stats" and do { |
|
|
118 | if ($nusers == 1) { |
|
|
119 | $module = "${ipfx}::Stats"; |
|
|
120 | $args{statType} = "student"; # FIXME: fix URLPath -- i shouldn't have to type this! |
|
|
121 | $args{userID} = $firstUserID; |
|
|
122 | } else { |
|
|
123 | push @error, E_ONE_USER; |
|
|
124 | } |
|
|
125 | }; |
|
|
126 | |
|
|
127 | defined param $r "set_stats" and do { |
|
|
128 | if ($nsets == 1) { |
|
|
129 | $module = "${ipfx}::Stats"; |
|
|
130 | $args{statType} = "set"; # FIXME: fix URLPath -- i shouldn't have to type this! |
|
|
131 | $args{setID} = $firstSetID; |
|
|
132 | } else { |
|
|
133 | push @error, E_ONE_SET; |
|
|
134 | } |
|
|
135 | }; |
|
|
136 | |
|
|
137 | defined param $r "user_options" and do { |
|
|
138 | if ($nusers == 1) { |
|
|
139 | $module = "${pfx}::Options"; |
|
|
140 | $params{effectiveUser} = $firstUserID; |
|
|
141 | } else { |
|
|
142 | push @error, E_ONE_USER; |
|
|
143 | } |
|
|
144 | }; |
|
|
145 | |
|
|
146 | defined param $r "score_sets" and do { |
|
|
147 | if ($nsets >= 1) { |
|
|
148 | $module = "${ipfx}::Scoring"; |
|
|
149 | $params{selectedSet} = \@selectedSetIDs; |
|
|
150 | $params{scoreSelected} = 1; |
|
|
151 | } else { |
|
|
152 | push @error, E_MIN_ONE_SET; |
|
|
153 | } |
|
|
154 | }; |
|
|
155 | |
|
|
156 | defined param $r "act_as_user" and do { |
|
|
157 | if ($nusers == 1 and $nsets <= 1) { |
|
|
158 | if ($nsets) { |
|
|
159 | $module = "${pfx}::ProblemSet"; |
|
|
160 | $args{setID} = $firstSetID; |
|
|
161 | } else { |
|
|
162 | $module = "${pfx}::ProblemSets"; |
|
|
163 | } |
|
|
164 | $params{effectiveUser} = $firstUserID; |
|
|
165 | } else { |
|
|
166 | push @error, E_ONE_USER unless $nusers == 1; |
|
|
167 | push @error, E_MAX_ONE_SET unless $nsets <= 1; |
|
|
168 | } |
|
|
169 | }; |
|
|
170 | |
|
|
171 | defined param $r "edit_set_for_user" and do { |
|
|
172 | if ($nusers == 1 and $nsets == 1) { |
|
|
173 | $module = "${ipfx}::ProblemSetEditor"; |
|
|
174 | $args{setID} = $firstSetID; |
|
|
175 | $params{editForUser} = $firstUserID; |
|
|
176 | } else { |
|
|
177 | push @error, E_ONE_USER unless $nusers == 1; |
|
|
178 | push @error, E_ONE_SET unless $nsets == 1; |
|
|
179 | |
|
|
180 | } |
|
|
181 | }; |
|
|
182 | |
|
|
183 | push @error, "You are not allowed to act as a student." |
|
|
184 | if (defined param $r "act_as_user" and not $authz->hasPermissions($userID, "become_student")); |
|
|
185 | push @error, "You are not allowed to modify problem sets." |
|
|
186 | if ((defined param $r "edit_sets" or defined param $r "edit_set_for_user") and not $authz->hasPermissions($userID, "modify_problem_sets")); |
|
|
187 | push @error, "You are not allowed to assign problem sets." |
|
|
188 | if ((defined param $r "sets_assigned_to_user" or defined param $r "users_assigned_to_set") and not $authz->hasPermissions($userID, "assign_problem_sets")); |
|
|
189 | push @error, "You are not allowed to modify student data." |
|
|
190 | if ((defined param $r "edit_users" or defined param $r "user_options") and not $authz->hasPermissions($userID, "modify_student_data")); |
|
|
191 | push @error, "You are not allowed to score sets." |
|
|
192 | if (defined param $r "score_sets" and not $authz->hasPermissions($userID, "score_sets")); |
|
|
193 | |
|
|
194 | # handle errors, redirect to target page |
|
|
195 | if (@error) { |
|
|
196 | $self->addbadmessage( |
|
|
197 | CGI::p("Your request could not be fulfilled. Please correct the following errors and try again:") . |
|
|
198 | CGI::ul(CGI::li(\@error)), |
|
|
199 | ); |
|
|
200 | |
|
|
201 | } elsif ($module) { |
|
|
202 | my $page = $urlpath->newFromModule($module, %args); |
|
|
203 | my $url = $self->systemLink($page, params => \%params); |
|
|
204 | $self->reply_with_redirect($url); |
|
|
205 | } |
| 22 | } |
206 | } |
| 23 | |
207 | |
| 24 | sub body { |
208 | sub body { |
| 25 | my $self = shift; |
209 | my ($self) = @_; |
| 26 | my $r = $self->{r}; |
210 | my $r = $self->r; |
|
|
211 | my $db = $r->db; |
| 27 | my $ce = $self->{ce}; |
212 | my $ce = $r->ce; |
| 28 | my $courseName = $ce->{courseName}; |
213 | my $authz = $r->authz; |
| 29 | my $authen_args = $self->url_authen_args(); |
214 | |
|
|
215 | return CGI::div({class=>"ResultsWithError"}, "You are not authorized to access the Instructor tools.") |
|
|
216 | unless $authz->hasPermissions($r->param("user"), "access_instructor_tools"); |
|
|
217 | |
|
|
218 | print CGI::p("Use the interface below to quickly access commonly-used |
|
|
219 | instructor tools, or select a tool from the list to the left."); |
|
|
220 | |
|
|
221 | print CGI::p("Select user(s) and/or set(s) below and click the action button |
|
|
222 | of your choice."); |
|
|
223 | |
|
|
224 | my @userIDs = $db->listUsers; |
|
|
225 | my @Users = $db->getUsers(@userIDs); |
| 30 | |
226 | |
| 31 | my $prof_url = $ce->{webworkURLs}->{oldProf}; |
227 | ## Mark's Edits for filtering |
| 32 | my $full_url = "$prof_url?course=$courseName&$authen_args"; |
228 | my @myUsers; |
| 33 | my $userEditorURL = "users/?" . $self->url_args; |
229 | my $user = $r->param("user"); |
| 34 | my $problemSetEditorURL = "sets/?" . $self->url_args; |
230 | |
|
|
231 | my (@viewable_sections,@viewable_recitations); |
|
|
232 | |
|
|
233 | if (defined @{$ce->{viewable_sections}->{$user}}) |
|
|
234 | {@viewable_sections = @{$ce->{viewable_sections}->{$user}};} |
|
|
235 | if (defined @{$ce->{viewable_recitations}->{$user}}) |
|
|
236 | {@viewable_recitations = @{$ce->{viewable_recitations}->{$user}};} |
| 35 | |
237 | |
| 36 | return |
238 | if (@viewable_sections or @viewable_recitations){ |
| 37 | CGI::p("\n". |
239 | foreach my $student (@Users){ |
| 38 | CGI::a({href=>$userEditorURL}, "Users"). " - View and edit data and settings for users of $courseName" . CGI::br(). "\n". |
240 | my $keep = 0; |
| 39 | CGI::a({href=>$problemSetEditorURL}, "Problem Sets"). " - View and edit settings for problem sets in $courseName".CGI::br()."\n" |
241 | foreach my $sec (@viewable_sections){ |
| 40 | )."\n".CGI::hr()."\n". |
242 | if ($student->section() eq $sec){$keep = 1;} |
|
|
243 | } |
|
|
244 | foreach my $rec (@viewable_recitations){ |
|
|
245 | if ($student->recitation() eq $rec){$keep = 1;} |
|
|
246 | } |
|
|
247 | if ($keep) {push @myUsers, $student;} |
|
|
248 | } |
|
|
249 | @Users = @myUsers; |
|
|
250 | } |
|
|
251 | ## End Mark's Edits |
|
|
252 | |
|
|
253 | my @globalSetIDs = $db->listGlobalSets; |
|
|
254 | my @GlobalSets = $db->getGlobalSets(@globalSetIDs); |
|
|
255 | |
|
|
256 | my @selected_users = $r->param("selected_users"); |
|
|
257 | my @selected_sets = $r->param("selected_sets"); |
|
|
258 | |
|
|
259 | my $scrolling_user_list = scrollingRecordList({ |
|
|
260 | name => "selected_users", |
|
|
261 | request => $r, |
|
|
262 | default_sort => "lnfn", |
|
|
263 | default_format => "lnfn_uid", |
|
|
264 | default_filters => ["all"], |
|
|
265 | size => 10, |
|
|
266 | multiple => 1, |
|
|
267 | }, @Users); |
|
|
268 | |
|
|
269 | my $scrolling_set_list = scrollingRecordList({ |
|
|
270 | name => "selected_sets", |
|
|
271 | request => $r, |
|
|
272 | default_sort => "set_id", |
|
|
273 | default_format => "set_id", |
|
|
274 | default_filters => ["all"], |
|
|
275 | size => 10, |
|
|
276 | multiple => 1, |
|
|
277 | }, @GlobalSets); |
|
|
278 | |
|
|
279 | print CGI::start_form({method=>"get", action=>$r->uri()}); |
|
|
280 | print $self->hidden_authen_fields(); |
|
|
281 | |
|
|
282 | print CGI::table({class=>"FormLayout"}, |
| 41 | CGI::p( |
283 | CGI::Tr( |
| 42 | CGI::b("NOTE: ") . |
284 | CGI::th("Users"), |
| 43 | "The Instructor Tools in this preview release of WeBWorK |
285 | CGI::th("Sets"), |
| 44 | 2.0 are not stable or complete. If you need reliable and |
286 | ), |
| 45 | stable course editing features, than at this time you |
|
|
| 46 | will need to use the Professor tools from WeBWorK 1.8 |
|
|
| 47 | or earlier. Use the links below to go to the Professor |
|
|
| 48 | pages of your system's WeBWorK 1.x installation." |
|
|
| 49 | )."\n". |
|
|
| 50 | CGI::ul( |
287 | CGI::Tr( |
|
|
288 | CGI::td({style=>"width:50%"}, $scrolling_user_list), |
|
|
289 | CGI::td({style=>"width:50%"}, $scrolling_set_list), |
|
|
290 | ), |
|
|
291 | CGI::Tr({class=>"ButtonRow"}, [ |
| 51 | CGI::li( |
292 | CGI::td([ |
| 52 | CGI::a({-href=>$full_url}, "Go to Professor pages") |
293 | CGI::submit("sets_assigned_to_user", "View/edit")." all sets for one <b>user</b>", |
| 53 | ). |
294 | CGI::submit("users_assigned_to_set", "View/edit")." all users for one <b>set</b>", |
|
|
295 | ]), |
| 54 | CGI::li( |
296 | CGI::td([ |
| 55 | CGI::a({-href=>$full_url, -target=>"_new"}, "Open Professor pages in new window") |
297 | CGI::submit("edit_users", "Edit"). " selected <b>users</b>", |
|
|
298 | CGI::submit("edit_sets", "Edit"). " one <b>set</b>", |
|
|
299 | ]), |
|
|
300 | CGI::td([ |
|
|
301 | CGI::submit("user_stats", "View stats"). " for one <b>user</b>", |
|
|
302 | CGI::submit("set_stats", "View stats"). " for one <b>set</b>", |
|
|
303 | ]), |
|
|
304 | CGI::td([ |
|
|
305 | CGI::submit("user_options", "Change password")." for one <b>user</b>", |
|
|
306 | CGI::submit("score_sets", "Score"). " selected <b>sets</b>", |
|
|
307 | ]), |
|
|
308 | ]), |
|
|
309 | CGI::Tr({class=>"ButtonRowCenter"}, [ |
|
|
310 | CGI::td({colspan=>2,style=>'text-align:center'}, |
|
|
311 | CGI::submit("act_as_user", "Act as")." one <b>user</b> (on one <b>set</b>)", |
| 56 | ) |
312 | ), |
|
|
313 | CGI::td({colspan=>2,style=>'text-align:center'}, |
|
|
314 | CGI::submit("edit_set_for_user", "Edit"). " one <b>set</b> for one <b>user</b>", |
|
|
315 | ), |
|
|
316 | ]), |
| 57 | ); |
317 | ); |
|
|
318 | |
|
|
319 | print CGI::end_form(); |
|
|
320 | |
|
|
321 | return ""; |
| 58 | } |
322 | } |
| 59 | |
323 | |
| 60 | 1; |
324 | 1; |
| 61 | |
325 | |
| 62 | __END__ |
326 | __END__ |
| 63 | |
327 | |
| 64 | =head1 AUTHOR |
328 | =head1 AUTHOR |
| 65 | |
329 | |
| 66 | Written by Dennis Lambe Jr., malsyned (at) math.rochester.edu |
330 | Written by Dennis Lambe Jr., malsyned (at) math.rochester.edu. |
| 67 | |
331 | |
| 68 | =cut |
332 | =cut |