Parent Directory
|
Revision Log
Revision 1324 -
(view)
(download)
(as text)
Original Path: trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/ProblemList.pm
| 1 : | gage | 1006 | ################################################################################ |
| 2 : | # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project | ||
| 3 : | # $Id$ | ||
| 4 : | ################################################################################ | ||
| 5 : | |||
| 6 : | package WeBWorK::ContentGenerator::Instructor::ProblemList; | ||
| 7 : | use base qw(WeBWorK::ContentGenerator::Instructor); | ||
| 8 : | |||
| 9 : | =head1 NAME | ||
| 10 : | |||
| 11 : | WeBWorK::ContentGenerator::Instructor::ProblemList - List and edit problems in a set | ||
| 12 : | |||
| 13 : | =cut | ||
| 14 : | |||
| 15 : | use strict; | ||
| 16 : | use warnings; | ||
| 17 : | use CGI qw(); | ||
| 18 : | use WeBWorK::Utils qw(readDirectory list2hash max); | ||
| 19 : | use WeBWorK::DB::Record::Set; | ||
| 20 : | |||
| 21 : | use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts)]; | ||
| 22 : | use constant PROBLEM_USER_FIELDS => [qw(problem_seed status num_correct num_incorrect)]; | ||
| 23 : | |||
| 24 : | sub problemElementHTML { | ||
| 25 : | my ($fieldName, $fieldValue, $size, $override, $overrideValue) = @_; | ||
| 26 : | my $attributeHash = {type=>"text",name=>$fieldName,value=>$fieldValue}; | ||
| 27 : | $attributeHash->{size} = $size if defined $size; | ||
| 28 : | |||
| 29 : | my $html = CGI::input($attributeHash); | ||
| 30 : | if (defined $override) { | ||
| 31 : | $attributeHash->{name} = "${fieldName}_override"; | ||
| 32 : | $attributeHash->{value} = ($override ? $overrideValue : ""); | ||
| 33 : | $html = "default:".CGI::br().$html.CGI::br() | ||
| 34 : | . CGI::checkbox({ | ||
| 35 : | type => "checkbox", | ||
| 36 : | name => "override", | ||
| 37 : | label => "override:", | ||
| 38 : | value => $fieldName, | ||
| 39 : | checked => ($override ? 1 : 0) | ||
| 40 : | }) | ||
| 41 : | . CGI::br() | ||
| 42 : | . CGI::input($attributeHash); | ||
| 43 : | } | ||
| 44 : | |||
| 45 : | return $html; | ||
| 46 : | } | ||
| 47 : | |||
| 48 : | # pay no attention to the argument list. Here's what you pass: | ||
| 49 : | # directoryListHTML($level, $selected, $libraryRoot, @path) | ||
| 50 : | sub directoryListHTML { | ||
| 51 : | my ($level, $selected, @path) = @_; | ||
| 52 : | $selected = [$selected] unless ref $selected eq "ARRAY"; | ||
| 53 : | my $dirName = join "/", @path[0..$level]; | ||
| 54 : | my @contents = sort grep {m/\.pg$/ or -d $dirName.'/'.$_ and not m/^\.{1,2}$/} readDirectory($dirName); | ||
| 55 : | my %contentsPretty = map {$_ => (-d $dirName.'/'.$_ ? $_.'/' : $_)} @contents; | ||
| 56 : | |||
| 57 : | my $html = ($level eq "0" ? "problem library" : $path[$level]) . CGI::br(); | ||
| 58 : | $html .= CGI::scrolling_list({ | ||
| 59 : | name=>"directory_level_$level", | ||
| 60 : | values=>\@contents, | ||
| 61 : | labels=>\%contentsPretty, | ||
| 62 : | default=>$selected, | ||
| 63 : | multiple=>'true', | ||
| 64 : | size=>"20", | ||
| 65 : | }); | ||
| 66 : | $html .= CGI::br() | ||
| 67 : | . CGI::input({type=>"submit", name=>"open_add_$level", value=>"Open/Add"}); | ||
| 68 : | } | ||
| 69 : | |||
| 70 : | sub initialize { | ||
| 71 : | my ($self, $setName) = @_; | ||
| 72 : | my $r = $self->{r}; | ||
| 73 : | my $db = $self->{db}; | ||
| 74 : | my $ce = $self->{ce}; | ||
| 75 : | malsyned | 1017 | my $authz = $self->{authz}; |
| 76 : | my $user = $r->param('user'); | ||
| 77 : | gage | 1006 | my $setRecord = $db->getGlobalSet($setName); |
| 78 : | gage | 1295 | $self->{set} = $setRecord; |
| 79 : | gage | 1006 | my @editForUser = $r->param('editForUser'); |
| 80 : | # some useful booleans | ||
| 81 : | my $forUsers = scalar(@editForUser); | ||
| 82 : | my $forOneUser = $forUsers == 1; | ||
| 83 : | |||
| 84 : | malsyned | 1017 | unless ($authz->hasPermissions($user, "modify_problem_sets")) { |
| 85 : | $self->{submitError} = "You are not authorized to modify problem sets"; | ||
| 86 : | return; | ||
| 87 : | } | ||
| 88 : | |||
| 89 : | gage | 1006 | # build a quick lookup table |
| 90 : | my %overrides = list2hash $r->param('override'); | ||
| 91 : | |||
| 92 : | # the Problem form was submitted | ||
| 93 : | if (defined($r->param('submit_problem_changes'))) { | ||
| 94 : | my @problemList = $db->listGlobalProblems($setName); | ||
| 95 : | foreach my $problem (@problemList) { | ||
| 96 : | my $problemRecord = $db->getGlobalProblem($setName, $problem); | ||
| 97 : | foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 98 : | malsyned | 1209 | my $paramName = "problem.${problem}.${field}"; |
| 99 : | gage | 1006 | if (defined($r->param($paramName))) { |
| 100 : | $problemRecord->$field($r->param($paramName)); | ||
| 101 : | } | ||
| 102 : | } | ||
| 103 : | $db->putGlobalProblem($problemRecord); | ||
| 104 : | |||
| 105 : | if ($forOneUser) { | ||
| 106 : | my $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem); | ||
| 107 : | foreach my $field (@{PROBLEM_USER_FIELDS()}) { | ||
| 108 : | malsyned | 1209 | my $paramName = "problem.${problem}.${field}"; |
| 109 : | gage | 1006 | if (defined($r->param($paramName))) { |
| 110 : | $userProblemRecord->$field($r->param($paramName)); | ||
| 111 : | } | ||
| 112 : | } | ||
| 113 : | foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 114 : | malsyned | 1209 | my $paramName = "problem.${problem}.${field}"; |
| 115 : | if (defined($r->param("${paramName}.override"))) { | ||
| 116 : | gage | 1006 | if (exists $overrides{$paramName}) { |
| 117 : | malsyned | 1209 | $userProblemRecord->$field($r->param("${paramName}.override")); |
| 118 : | gage | 1006 | } else { |
| 119 : | $userProblemRecord->$field(undef); | ||
| 120 : | } | ||
| 121 : | |||
| 122 : | } | ||
| 123 : | malsyned | 1323 | $db->putUserProblem($userProblemRecord); |
| 124 : | gage | 1006 | } |
| 125 : | |||
| 126 : | } | ||
| 127 : | } | ||
| 128 : | malsyned | 1209 | foreach my $problem ($r->param('deleteProblem')) { |
| 129 : | $db->deleteGlobalProblem($setName, $problem); | ||
| 130 : | } | ||
| 131 : | gage | 1006 | # The file list field was submitted |
| 132 : | } elsif (defined $r->param('fileBrowsing')) { | ||
| 133 : | my $libraryRoot = $ce->{courseDirs}->{templates}; | ||
| 134 : | my $count = 0; | ||
| 135 : | my $done = 0; | ||
| 136 : | my @path = (); | ||
| 137 : | my $freeProblemID = max($db->listGlobalProblems($setName)) + 1; | ||
| 138 : | while (defined $r->param("directory_level_$count") and not $done) { | ||
| 139 : | my @selected = $r->param("directory_level_$count"); | ||
| 140 : | my $dirFound = 0; | ||
| 141 : | # If any directories are selected, "cd" into the first one and stop processing this level. | ||
| 142 : | foreach my $selected (@selected) { | ||
| 143 : | if (-d join "/", $libraryRoot, @path, $selected) { | ||
| 144 : | push @path, $selected; | ||
| 145 : | $dirFound = 1; | ||
| 146 : | last; | ||
| 147 : | } | ||
| 148 : | } | ||
| 149 : | # Otherwise, create a new global problem for each of the files selected | ||
| 150 : | unless ($dirFound) { | ||
| 151 : | foreach my $selected (@selected) { | ||
| 152 : | my $file = join "/", @path, $selected; | ||
| 153 : | my $problemRecord = new WeBWorK::DB::Record::Problem; | ||
| 154 : | $problemRecord->problem_id($freeProblemID++); | ||
| 155 : | $problemRecord->set_id($setName); | ||
| 156 : | $problemRecord->source_file($file); | ||
| 157 : | $problemRecord->value("1"); | ||
| 158 : | $problemRecord->max_attempts("-1"); | ||
| 159 : | $db->addGlobalProblem($problemRecord); | ||
| 160 : | malsyned | 1106 | $self->assignProblemToAllSetUsers($problemRecord); |
| 161 : | gage | 1006 | } |
| 162 : | $done = 1; | ||
| 163 : | } | ||
| 164 : | |||
| 165 : | if (defined $r->param("open_add_$count")) { | ||
| 166 : | $done = 1; | ||
| 167 : | } | ||
| 168 : | $count++; | ||
| 169 : | } | ||
| 170 : | $self->{path} = [@path]; | ||
| 171 : | } | ||
| 172 : | |||
| 173 : | } | ||
| 174 : | |||
| 175 : | gage | 1295 | sub path { |
| 176 : | my $self = shift; | ||
| 177 : | my $args = $_[-1]; | ||
| 178 : | my $ce = $self->{ce}; | ||
| 179 : | my $root = $ce->{webworkURLs}->{root}; | ||
| 180 : | my $courseName = $ce->{courseName}; | ||
| 181 : | my $set_id = $self->{set}->set_id; | ||
| 182 : | return $self->pathMacro($args, | ||
| 183 : | "Home" => "$root", | ||
| 184 : | $courseName => "$root/$courseName", | ||
| 185 : | 'instructor' => "$root/$courseName/instructor", | ||
| 186 : | 'sets' => "$root/$courseName/instructor/sets/", | ||
| 187 : | "set $set_id" => "$root/$courseName/instructor/sets/$set_id", | ||
| 188 : | 'problems' => '', | ||
| 189 : | ); | ||
| 190 : | } | ||
| 191 : | |||
| 192 : | gage | 1006 | sub title { |
| 193 : | my ($self, $setName) = @_; | ||
| 194 : | return "Problems in ".$self->{ce}->{courseName}." : ".$setName; | ||
| 195 : | } | ||
| 196 : | |||
| 197 : | sub body { | ||
| 198 : | my ($self, $setName) = @_; | ||
| 199 : | my $r = $self->{r}; | ||
| 200 : | my $db = $self->{db}; | ||
| 201 : | my $ce = $self->{ce}; | ||
| 202 : | malsyned | 1017 | my $authz = $self->{authz}; |
| 203 : | my $user = $r->param('user'); | ||
| 204 : | gage | 1006 | my $courseName = $ce->{courseName}; |
| 205 : | my $setRecord = $db->getGlobalSet($setName); | ||
| 206 : | my @editForUser = $r->param('editForUser'); | ||
| 207 : | # some useful booleans | ||
| 208 : | my $forUsers = scalar(@editForUser); | ||
| 209 : | my $forOneUser = $forUsers == 1; | ||
| 210 : | |||
| 211 : | malsyned | 1017 | return CGI::em("You are not authorized to access the Instructor tools.") unless $authz->hasPermissions($user, "access_instructor_tools"); |
| 212 : | |||
| 213 : | gage | 1006 | ## Problems Form ## |
| 214 : | my @problemList = $db->listGlobalProblems($setName); | ||
| 215 : | print CGI::a({name=>"problems"}); | ||
| 216 : | print CGI::h2({}, "Problems"); | ||
| 217 : | if (scalar(@problemList)) { | ||
| 218 : | print CGI::start_form({method=>"POST", action=>$r->uri.'#problems'}); | ||
| 219 : | print CGI::start_table({border=>1, cellpadding=>4}); | ||
| 220 : | print CGI::Tr({}, CGI::th({}, [ | ||
| 221 : | ($forUsers ? () : ("Delete?")), | ||
| 222 : | "Problem", | ||
| 223 : | ($forUsers ? ("Status", "Problem Seed") : ()), | ||
| 224 : | "Source File", "Max. Attempts", "Weight", | ||
| 225 : | ($forUsers ? ("Number Correct", "Number Incorrect") : ()) | ||
| 226 : | ])); | ||
| 227 : | foreach my $problem (sort {$a <=> $b} @problemList) { | ||
| 228 : | my $problemRecord = $db->getGlobalProblem($setName, $problem); | ||
| 229 : | my $problemID = $problemRecord->problem_id; | ||
| 230 : | my $userProblemRecord; | ||
| 231 : | my %problemOverrideArgs; | ||
| 232 : | |||
| 233 : | if ($forOneUser) { | ||
| 234 : | $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem); | ||
| 235 : | foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 236 : | $problemOverrideArgs{$field} = [defined $userProblemRecord->$field, $userProblemRecord->$field]; | ||
| 237 : | } | ||
| 238 : | # } elsif ($forUsers) { | ||
| 239 : | # foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 240 : | # $problemOverrideArgs{$field} = ["", ""]; | ||
| 241 : | # } | ||
| 242 : | } else { | ||
| 243 : | foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 244 : | $problemOverrideArgs{$field} = [undef, undef]; | ||
| 245 : | } | ||
| 246 : | } | ||
| 247 : | |||
| 248 : | print CGI::Tr({}, | ||
| 249 : | CGI::td({}, [ | ||
| 250 : | ($forUsers ? () : (CGI::input({type=>"checkbox", name=>"deleteProblem", value=>$problemID}))), | ||
| 251 : | CGI::a({href=>$ce->{webworkURLs}->{root}."/$courseName/instructor/pgProblemEditor/".$setName.'/'.$problemID.'?'.$self->url_authen_args}, $problemID), | ||
| 252 : | ($forUsers ? ( | ||
| 253 : | malsyned | 1209 | problemElementHTML("problem.${problemID}.status", $userProblemRecord->status, "7"), |
| 254 : | problemElementHTML("problem.${problemID}.problem_seed", $userProblemRecord->problem_seed, "7"), | ||
| 255 : | gage | 1006 | ) : ()), |
| 256 : | malsyned | 1209 | problemElementHTML("problem.${problemID}.source_file", $problemRecord->source_file, "40", @{$problemOverrideArgs{source_file}}), |
| 257 : | problemElementHTML("problem.${problemID}.max_attempts",$problemRecord->max_attempts,"7", @{$problemOverrideArgs{max_attempts}}), | ||
| 258 : | problemElementHTML("problem.${problemID}.value",$problemRecord->value,"7", @{$problemOverrideArgs{value}}), | ||
| 259 : | gage | 1006 | ($forUsers ? ( |
| 260 : | malsyned | 1209 | problemElementHTML("problem.${problemID}.num_correct", $userProblemRecord->num_correct, "7"), |
| 261 : | problemElementHTML("problem.${problemID}.num_incorrect", $userProblemRecord->num_incorrect, "7") | ||
| 262 : | gage | 1006 | ) : ()) |
| 263 : | ]) | ||
| 264 : | |||
| 265 : | ) | ||
| 266 : | } | ||
| 267 : | print CGI::end_table(); | ||
| 268 : | print $self->hiddenEditForUserFields(@editForUser); | ||
| 269 : | print $self->hidden_authen_fields; | ||
| 270 : | print CGI::input({type=>"submit", name=>"submit_problem_changes", value=>"Save Problem Changes"}); | ||
| 271 : | print CGI::end_form(); | ||
| 272 : | } else { | ||
| 273 : | print CGI::p("This set doesn't contain any problems yet."); | ||
| 274 : | } | ||
| 275 : | |||
| 276 : | unless ($forUsers) { | ||
| 277 : | my $libraryRoot = $ce->{courseDirs}->{templates}; | ||
| 278 : | my @path = defined $self->{path} ? @{$self->{path}} : (); | ||
| 279 : | unshift @path, $libraryRoot; | ||
| 280 : | print CGI::a({name=>"addProblem"}); | ||
| 281 : | print CGI::h3({}, "Add Problem(s)"); | ||
| 282 : | print CGI::start_form({method=>"post", action=>$r->uri.'#addProblem'}); | ||
| 283 : | print CGI::input({type=>"hidden", name=>"fileBrowsing", value=>"Yes"}); | ||
| 284 : | print CGI::start_table(); | ||
| 285 : | my $columns = ""; | ||
| 286 : | for (my $counter = 0; $counter < scalar(@path); $counter++) { | ||
| 287 : | $columns .= CGI::td(directoryListHTML ($counter, (exists $path[$counter+1] ? $path[$counter+1] : []), @path)); | ||
| 288 : | } | ||
| 289 : | print CGI::Tr($columns); | ||
| 290 : | print CGI::end_table(); | ||
| 291 : | print $self->hidden_authen_fields; | ||
| 292 : | print CGI::end_form(); | ||
| 293 : | } | ||
| 294 : | |||
| 295 : | return ""; | ||
| 296 : | } | ||
| 297 : | |||
| 298 : | 1; |
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |