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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 : gage 860 package WeBWorK::ContentGenerator::Instructor::ProblemSetEditor;
2 :     use base qw(WeBWorK::ContentGenerator::Instructor);
3 :    
4 :     =head1 NAME
5 :    
6 :     WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list
7 :    
8 :     =cut
9 :    
10 :     use strict;
11 :     use warnings;
12 :     use CGI qw();
13 : malsyned 976 use WeBWorK::DB::Record::Problem;
14 :     use WeBWorK::Utils qw(readFile formatDateTime parseDateTime list2hash readDirectory max);
15 : gage 860
16 : gage 869 our $rowheight = 20; #controls the length of the popup menus.
17 : gage 875 our $libraryName; #library directory name
18 : malsyned 935
19 : malsyned 947 use constant SET_FIELDS => [qw(open_date due_date answer_date set_header problem_header)];
20 : malsyned 957 use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts)];
21 : malsyned 959 use constant PROBLEM_USER_FIELDS => [qw(problem_seed status num_correct num_incorrect)];
22 : malsyned 947
23 : malsyned 935 sub getSetName {
24 :     my ($self, $pathSetName) = @_;
25 :     if (ref $pathSetName eq "HASH") {
26 :     $pathSetName = undef;
27 :     }
28 :     return $pathSetName;
29 :     }
30 :    
31 : malsyned 967 # One wrinkle here: if $override is undefined, do the global thing, otherwise, it's truth value determines the checkbox.
32 :     sub setRowHTML {
33 :     my ($description, $fieldName, $fieldValue, $size, $override, $overrideValue) = @_;
34 :    
35 :     my $attributeHash = {type=>"text", name=>$fieldName, value=>$fieldValue};
36 :     $attributeHash->{size} = $size if defined $size;
37 :    
38 :     my $html = CGI::td({}, [$description, CGI::input($attributeHash)]);
39 :    
40 :     if (defined $override) {
41 :     $attributeHash->{name}="${fieldName}_override";
42 :     $attributeHash->{value}=($override ? $overrideValue : "" );
43 :    
44 :     $html .= CGI::td({}, [
45 :     CGI::checkbox({
46 :     type=>"checkbox",
47 :     name=>"override",
48 :     label=>"override with:",
49 :     value=>$fieldName,
50 :     checked=>($override ? 1 : 0)
51 :     }),
52 :     CGI::input($attributeHash)
53 :     ]);
54 :     }
55 :    
56 :     return $html;
57 :    
58 :     }
59 :    
60 :     sub hiddenEditForUserFields {
61 :     my @editForUser = @_;
62 :     my $return = "";
63 :     foreach my $editUser (@editForUser) {
64 :     $return .= CGI::input({type=>"hidden", name=>"editForUser", value=>$editUser});
65 :     }
66 :    
67 :     return $return;
68 :     }
69 :    
70 :     sub problemElementHTML {
71 :     my ($fieldName, $fieldValue, $size, $override, $overrideValue) = @_;
72 :     my $attributeHash = {type=>"text",name=>$fieldName,value=>$fieldValue};
73 :     $attributeHash->{size} = $size if defined $size;
74 :    
75 :     my $html = CGI::input($attributeHash);
76 :     if (defined $override) {
77 :     $attributeHash->{name} = "${fieldName}_override";
78 :     $attributeHash->{value} = ($override ? $overrideValue : "");
79 :     $html = "default:".CGI::br().$html.CGI::br()
80 :     . CGI::checkbox({
81 :     type => "checkbox",
82 :     name => "override",
83 :     label => "override:",
84 :     value => $fieldName,
85 :     checked => ($override ? 1 : 0)
86 :     })
87 :     . CGI::br()
88 :     . CGI::input($attributeHash);
89 :     }
90 :    
91 :     return $html;
92 :     }
93 :    
94 : malsyned 976
95 :     # pay no attention to the argument list. Here's what you pass:
96 :     # directoryListHTML($level, $selected, $libraryRoot, @path)
97 :     sub directoryListHTML {
98 :     my ($level, $selected, @path) = @_;
99 :     $selected = [$selected] unless ref $selected eq "ARRAY";
100 :     my $dirName = join "/", @path[0..$level];
101 :     my @contents = sort grep {m/\.pg$/ or -d $dirName.'/'.$_ and not m/^\.{1,2}$/} readDirectory($dirName);
102 : malsyned 979 my %contentsPretty = map {$_ => (-d $dirName.'/'.$_ ? $_.'/' : $_)} @contents;
103 : malsyned 976
104 :     my $html = ($level eq "0" ? "problem library" : $path[$level]) . CGI::br();
105 :     $html .= CGI::scrolling_list({
106 :     name=>"directory_level_$level",
107 :     values=>\@contents,
108 : malsyned 979 labels=>\%contentsPretty,
109 : malsyned 976 default=>$selected,
110 :     multiple=>'true',
111 :     size=>"20",
112 :     });
113 :     $html .= CGI::br()
114 :     . CGI::input({type=>"submit", name=>"open_add_$level", value=>"Open/Add"});
115 :     }
116 :    
117 : gage 860 sub title {
118 : malsyned 935 my ($self, @components) = @_;
119 :     return "Problem Set Editor - ".$self->{ce}->{courseName}." : ".$self->getSetName(@components);
120 : gage 860 }
121 :    
122 : malsyned 960 # Initialize does all of the form processing. It's extensive, and could probably be cleaned up and
123 :     # consolidated with a little abstraction.
124 : malsyned 935 sub initialize {
125 :     my ($self, @components) = @_;
126 :     my $r = $self->{r};
127 :     my $db = $self->{db};
128 : malsyned 976 my $ce = $self->{ce};
129 : malsyned 935 my $setName = $self->getSetName(@components);
130 :     my $setRecord = $db->getGlobalSet($setName);
131 : malsyned 957 my @editForUser = $r->param('editForUser');
132 :     # some useful booleans
133 :     my $forUsers = scalar(@editForUser);
134 :     my $forOneUser = $forUsers == 1;
135 : malsyned 935
136 : malsyned 967 my %overrides = list2hash $r->param('override');
137 : malsyned 959 # build a quick lookup table
138 :    
139 :     # The set form was submitted
140 : malsyned 936 if (defined($r->param('submit_set_changes'))) {
141 : malsyned 947 foreach (@{SET_FIELDS()}) {
142 : malsyned 935 if (defined($r->param($_))) {
143 :     if (m/_date$/) {
144 :     $setRecord->$_(parseDateTime($r->param($_)));
145 :     } else {
146 :     $setRecord->$_($r->param($_));
147 :     }
148 :     }
149 :     }
150 : malsyned 959 $db->putGlobalSet($setRecord);
151 : malsyned 957
152 : malsyned 959 if ($forOneUser) {
153 :    
154 :     my $userSetRecord = $db->getUserSet($editForUser[0], $setName);
155 :     foreach my $field (@{SET_FIELDS()}) {
156 :     if (defined $r->param("${field}_override")) {
157 :     if (exists $overrides{$field}) {
158 :     if ($field =~ m/_date$/) {
159 :     $userSetRecord->$field(parseDateTime($r->param("${field}_override")));
160 :     } else {
161 :     $userSetRecord->$field($r->param("${field}_override"));
162 :     }
163 :     } else {
164 :     $userSetRecord->$field(undef);
165 :     }
166 :    
167 :     $db->putUserSet($userSetRecord);
168 :     }
169 :     }
170 :     }
171 : malsyned 936 }
172 : malsyned 959 # the Problem form was submitted
173 : malsyned 936 elsif (defined($r->param('submit_problem_changes'))) {
174 : malsyned 967 foreach my $problem ($r->param('deleteProblem')) {
175 :     $db->deleteGlobalProblem($setName, $problem);
176 :     }
177 : malsyned 936 my @problemList = $db->listGlobalProblems($setName);
178 :     foreach my $problem (@problemList) {
179 :     my $problemRecord = $db->getGlobalProblem($setName, $problem);
180 : malsyned 959 foreach my $field (@{PROBLEM_FIELDS()}) {
181 :     my $paramName = "problem_${problem}_${field}";
182 : malsyned 936 if (defined($r->param($paramName))) {
183 : malsyned 959 $problemRecord->$field($r->param($paramName));
184 : malsyned 936 }
185 :     }
186 : malsyned 959 $db->putGlobalProblem($problemRecord);
187 :    
188 :     if ($forOneUser) {
189 :     my $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem);
190 :     foreach my $field (@{PROBLEM_USER_FIELDS()}) {
191 :     my $paramName = "problem_${problem}_${field}";
192 :     if (defined($r->param($paramName))) {
193 :     $userProblemRecord->$field($r->param($paramName));
194 :     }
195 :     }
196 : malsyned 960 $userProblemRecord->attempted($userProblemRecord->num_correct + $userProblemRecord->num_incorrect);
197 : malsyned 959 foreach my $field (@{PROBLEM_FIELDS()}) {
198 :     my $paramName = "problem_${problem}_${field}";
199 :     if (defined($r->param("${paramName}_override"))) {
200 :     if (exists $overrides{$paramName}) {
201 :     $userProblemRecord->$field($r->param("${paramName}_override"));
202 :     } else {
203 :     $userProblemRecord->$field(undef);
204 :     }
205 :    
206 :     $db->putUserProblem($userProblemRecord);
207 :     }
208 :     }
209 :    
210 :     }
211 : malsyned 935 }
212 : malsyned 976 } elsif (defined $r->param('fileBrowsing')) {
213 :     my $libraryRoot = $ce->{courseDirs}->{templates};
214 :     my $count = 0;
215 :     my $done = 0;
216 :     my @path = ();
217 :     my $freeProblemID = max($db->listGlobalProblems($setName)) + 1;
218 :     while (defined $r->param("directory_level_$count") and not $done) {
219 :     my @selected = $r->param("directory_level_$count");
220 :     my $dirFound = 0;
221 :     # If any directories are selected, "cd" into the first one and stop processing this level.
222 :     foreach my $selected (@selected) {
223 :     if (-d join "/", $libraryRoot, @path, $selected) {
224 :     push @path, $selected;
225 :     $dirFound = 1;
226 :     last;
227 :     }
228 :     }
229 :     # Otherwise, create a new global problem for each of the files selected
230 :     unless ($dirFound) {
231 :     foreach my $selected (@selected) {
232 :     my $file = join "/", @path, $selected;
233 :     my $problemRecord = new WeBWorK::DB::Record::Problem;
234 :     $problemRecord->problem_id($freeProblemID++);
235 :     $problemRecord->set_id($setName);
236 :     $problemRecord->source_file($file);
237 :     $problemRecord->value("1");
238 :     $problemRecord->max_attempts("-1");
239 :     $db->addGlobalProblem($problemRecord);
240 :     }
241 :     $done = 1;
242 :     }
243 :    
244 :     if (defined $r->param("open_add_$count")) {
245 :     $done = 1;
246 :     }
247 :     $count++;
248 :     }
249 :     $self->{path} = [@path];
250 : malsyned 968 }
251 : malsyned 935 }
252 :    
253 : malsyned 947
254 : gage 860 sub body {
255 : malsyned 935 my ($self, @components) = @_;
256 :     my $r = $self->{r};
257 :     my $db = $self->{db};
258 : malsyned 962 my $ce = $self->{ce};
259 :     my $courseName = $ce->{courseName};
260 : malsyned 935 my $setName = $self->getSetName(@components);
261 :     my $setRecord = $db->getGlobalSet($setName);
262 : malsyned 936 my @editForUser = $r->param('editForUser');
263 : malsyned 947 # some useful booleans
264 : malsyned 957 my $forUsers = scalar(@editForUser);
265 :     my $forOneUser = $forUsers == 1;
266 : malsyned 935
267 : malsyned 959 ## Set Form ##
268 : malsyned 947 my $userSetRecord;
269 :     my %overrideArgs;
270 :     if ($forOneUser) {
271 :     $userSetRecord = $db->getUserSet($editForUser[0], $setName);
272 :     foreach my $field (@{SET_FIELDS()}) {
273 : malsyned 959 $overrideArgs{$field} = [defined $userSetRecord->$field, ($field =~ /_date$/ ? formatDateTime($userSetRecord->$field) : $userSetRecord->$field)];
274 : malsyned 947 }
275 :     } else {
276 :     foreach my $field (@{SET_FIELDS()}) {
277 :     $overrideArgs{$field} = [undef, undef];
278 :     }
279 :     }
280 :    
281 : malsyned 959 print CGI::h2({}, "Set Data"), "\n";
282 :     print CGI::start_form({method=>"post", action=>$r->uri}), "\n";
283 : malsyned 935 print CGI::table({},
284 :     CGI::Tr({}, [
285 : malsyned 959 setRowHTML("Open Date:", "open_date", formatDateTime($setRecord->open_date), undef, @{$overrideArgs{open_date}})."\n",
286 :     setRowHTML("Due Date:", "due_date", formatDateTime($setRecord->due_date), undef, @{$overrideArgs{due_date}})."\n",
287 :     setRowHTML("Answer Date:", "answer_date", formatDateTime($setRecord->answer_date), undef, @{$overrideArgs{answer_date}})."\n",
288 :     setRowHTML("Set Header:", "set_header", $setRecord->set_header, undef, @{$overrideArgs{set_header}})."\n",
289 :     setRowHTML("Problem Header:", "problem_header", $setRecord->problem_header, undef, @{$overrideArgs{problem_header}})."\n"
290 : malsyned 935 ])
291 :     );
292 :    
293 : malsyned 967 print hiddenEditForUserFields(@editForUser);
294 : malsyned 935 print $self->hidden_authen_fields;
295 : malsyned 936 print CGI::input({type=>"submit", name=>"submit_set_changes", value=>"Save Set"});
296 : malsyned 935 print CGI::end_form();
297 :    
298 : malsyned 959 ## Problems Form ##
299 : malsyned 979 my @problemList = $db->listGlobalProblems($setName);
300 : malsyned 976 print CGI::a({name=>"problems"});
301 : malsyned 935 print CGI::h2({}, "Problems");
302 : malsyned 979 if (scalar(@problemList)) {
303 :     print CGI::start_form({method=>"POST", action=>$r->uri.'#problems'});
304 :     print CGI::start_table({border=>1, cellpadding=>4});
305 :     print CGI::Tr({}, CGI::th({}, [
306 :     ($forUsers ? () : ("Delete?")),
307 :     "Problem",
308 :     ($forUsers ? ("Status", "Problem Seed") : ()),
309 :     "Source File", "Max. Attempts", "Weight",
310 :     ($forUsers ? ("Number Correct", "Number Incorrect") : ())
311 :     ]));
312 :     foreach my $problem (sort {$a <=> $b} @problemList) {
313 :     my $problemRecord = $db->getGlobalProblem($setName, $problem);
314 :     my $problemID = $problemRecord->problem_id;
315 :     my $userProblemRecord;
316 :     my %problemOverrideArgs;
317 :    
318 :     if ($forOneUser) {
319 :     $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem);
320 :     foreach my $field (@{PROBLEM_FIELDS()}) {
321 :     $problemOverrideArgs{$field} = [defined $userProblemRecord->$field, $userProblemRecord->$field];
322 :     }
323 :     # } elsif ($forUsers) {
324 :     # foreach my $field (@{PROBLEM_FIELDS()}) {
325 :     # $problemOverrideArgs{$field} = ["", ""];
326 :     # }
327 :     } else {
328 :     foreach my $field (@{PROBLEM_FIELDS()}) {
329 :     $problemOverrideArgs{$field} = [undef, undef];
330 :     }
331 : malsyned 957 }
332 : malsyned 979
333 :     print CGI::Tr({},
334 :     CGI::td({}, [
335 :     ($forUsers ? () : (CGI::input({type=>"checkbox", name=>"deleteProblem", value=>$problemID}))),
336 :     CGI::a({href=>"/webwork/$courseName/instructor/pgProblemEditor/".$setName.'/'.$problemID.'?'.$self->url_authen_args}, $problemID),
337 :     ($forUsers ? (
338 :     problemElementHTML("problem_${problemID}_status", $userProblemRecord->status, "7"),
339 :     problemElementHTML("problem_${problemID}_problem_seed", $userProblemRecord->problem_seed, "7"),
340 :     ) : ()),
341 :     problemElementHTML("problem_${problemID}_source_file", $problemRecord->source_file, "40", @{$problemOverrideArgs{source_file}}),
342 :     problemElementHTML("problem_${problemID}_max_attempts",$problemRecord->max_attempts,"7", @{$problemOverrideArgs{max_attempts}}),
343 :     problemElementHTML("problem_${problemID}_value",$problemRecord->value,"7", @{$problemOverrideArgs{value}}),
344 :     ($forUsers ? (
345 :     problemElementHTML("problem_${problemID}_num_correct", $userProblemRecord->num_correct, "7"),
346 :     problemElementHTML("problem_${problemID}_num_incorrect", $userProblemRecord->num_incorrect, "7")
347 :     ) : ())
348 :     ])
349 :    
350 :     )
351 : malsyned 957 }
352 : malsyned 979 print CGI::end_table();
353 :     print hiddenEditForUserFields(@editForUser);
354 :     print $self->hidden_authen_fields;
355 : malsyned 982 print CGI::input({type=>"submit", name=>"submit_problem_changes", value=>"Save Problem Changes"});
356 : malsyned 979 print CGI::end_form();
357 :     } else {
358 :     print CGI::p("This set doesn't contain any problems yet.");
359 : malsyned 935 }
360 :    
361 : malsyned 968 unless ($forUsers) {
362 : malsyned 976 my $libraryRoot = $ce->{courseDirs}->{templates};
363 :     my @path = defined $self->{path} ? @{$self->{path}} : ();
364 :     unshift @path, $libraryRoot;
365 :     print CGI::a({name=>"addProblem"});
366 :     print CGI::h3({}, "Add Problem(s)");
367 :     print CGI::start_form({method=>"post", action=>$r->uri.'#addProblem'});
368 :     print CGI::input({type=>"hidden", name=>"fileBrowsing", value=>"Yes"});
369 :     print CGI::start_table();
370 : malsyned 982 my $columns = "";
371 : malsyned 976 for (my $counter = 0; $counter < scalar(@path); $counter++) {
372 : malsyned 982 $columns .= CGI::td(directoryListHTML ($counter, (exists $path[$counter+1] ? $path[$counter+1] : []), @path));
373 : malsyned 976 }
374 : malsyned 982 print CGI::Tr($columns);
375 : malsyned 976 print CGI::end_table();
376 : malsyned 968 print $self->hidden_authen_fields;
377 :     print CGI::end_form();
378 :     }
379 : malsyned 935 return "";
380 :     }
381 :    
382 : gage 860 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9