Parent Directory
|
Revision Log
Revision 962 - (view) (download) (as text)
| 1 : | gage | 860 | package WeBWorK::ContentGenerator::Instructor::ProblemSetEditor; |
| 2 : | use base qw(WeBWorK::ContentGenerator::Instructor); | ||
| 3 : | malsyned | 935 | use WeBWorK::Utils qw(readFile formatDateTime parseDateTime); |
| 4 : | gage | 860 | |
| 5 : | =head1 NAME | ||
| 6 : | |||
| 7 : | WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list | ||
| 8 : | |||
| 9 : | =cut | ||
| 10 : | |||
| 11 : | use strict; | ||
| 12 : | use warnings; | ||
| 13 : | use CGI qw(); | ||
| 14 : | |||
| 15 : | gage | 869 | our $rowheight = 20; #controls the length of the popup menus. |
| 16 : | gage | 875 | our $libraryName; #library directory name |
| 17 : | malsyned | 935 | |
| 18 : | malsyned | 947 | use constant SET_FIELDS => [qw(open_date due_date answer_date set_header problem_header)]; |
| 19 : | malsyned | 957 | use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts)]; |
| 20 : | malsyned | 959 | use constant PROBLEM_USER_FIELDS => [qw(problem_seed status num_correct num_incorrect)]; |
| 21 : | malsyned | 947 | |
| 22 : | malsyned | 935 | sub getSetName { |
| 23 : | my ($self, $pathSetName) = @_; | ||
| 24 : | if (ref $pathSetName eq "HASH") { | ||
| 25 : | $pathSetName = undef; | ||
| 26 : | } | ||
| 27 : | return $pathSetName; | ||
| 28 : | } | ||
| 29 : | |||
| 30 : | gage | 860 | sub title { |
| 31 : | malsyned | 935 | my ($self, @components) = @_; |
| 32 : | return "Problem Set Editor - ".$self->{ce}->{courseName}." : ".$self->getSetName(@components); | ||
| 33 : | gage | 860 | } |
| 34 : | |||
| 35 : | malsyned | 960 | # Initialize does all of the form processing. It's extensive, and could probably be cleaned up and |
| 36 : | # consolidated with a little abstraction. | ||
| 37 : | malsyned | 935 | sub initialize { |
| 38 : | my ($self, @components) = @_; | ||
| 39 : | my $r = $self->{r}; | ||
| 40 : | my $db = $self->{db}; | ||
| 41 : | my $setName = $self->getSetName(@components); | ||
| 42 : | my $setRecord = $db->getGlobalSet($setName); | ||
| 43 : | malsyned | 957 | my @editForUser = $r->param('editForUser'); |
| 44 : | # some useful booleans | ||
| 45 : | my $forUsers = scalar(@editForUser); | ||
| 46 : | my $forOneUser = $forUsers == 1; | ||
| 47 : | malsyned | 935 | |
| 48 : | malsyned | 959 | my %overrides; |
| 49 : | # build a quick lookup table | ||
| 50 : | foreach my $param ($r->param('override')) { | ||
| 51 : | $overrides{$param} = "DUMMY"; | ||
| 52 : | } | ||
| 53 : | |||
| 54 : | # The set form was submitted | ||
| 55 : | malsyned | 936 | if (defined($r->param('submit_set_changes'))) { |
| 56 : | malsyned | 947 | foreach (@{SET_FIELDS()}) { |
| 57 : | malsyned | 935 | if (defined($r->param($_))) { |
| 58 : | if (m/_date$/) { | ||
| 59 : | $setRecord->$_(parseDateTime($r->param($_))); | ||
| 60 : | } else { | ||
| 61 : | $setRecord->$_($r->param($_)); | ||
| 62 : | } | ||
| 63 : | } | ||
| 64 : | } | ||
| 65 : | malsyned | 959 | $db->putGlobalSet($setRecord); |
| 66 : | malsyned | 957 | |
| 67 : | malsyned | 959 | if ($forOneUser) { |
| 68 : | |||
| 69 : | my $userSetRecord = $db->getUserSet($editForUser[0], $setName); | ||
| 70 : | foreach my $field (@{SET_FIELDS()}) { | ||
| 71 : | if (defined $r->param("${field}_override")) { | ||
| 72 : | if (exists $overrides{$field}) { | ||
| 73 : | if ($field =~ m/_date$/) { | ||
| 74 : | $userSetRecord->$field(parseDateTime($r->param("${field}_override"))); | ||
| 75 : | } else { | ||
| 76 : | $userSetRecord->$field($r->param("${field}_override")); | ||
| 77 : | } | ||
| 78 : | } else { | ||
| 79 : | $userSetRecord->$field(undef); | ||
| 80 : | } | ||
| 81 : | |||
| 82 : | $db->putUserSet($userSetRecord); | ||
| 83 : | } | ||
| 84 : | } | ||
| 85 : | } | ||
| 86 : | malsyned | 936 | } |
| 87 : | malsyned | 959 | # the Problem form was submitted |
| 88 : | malsyned | 936 | elsif (defined($r->param('submit_problem_changes'))) { |
| 89 : | my @problemList = $db->listGlobalProblems($setName); | ||
| 90 : | foreach my $problem (@problemList) { | ||
| 91 : | my $problemRecord = $db->getGlobalProblem($setName, $problem); | ||
| 92 : | malsyned | 959 | foreach my $field (@{PROBLEM_FIELDS()}) { |
| 93 : | my $paramName = "problem_${problem}_${field}"; | ||
| 94 : | malsyned | 936 | if (defined($r->param($paramName))) { |
| 95 : | malsyned | 959 | $problemRecord->$field($r->param($paramName)); |
| 96 : | malsyned | 936 | } |
| 97 : | } | ||
| 98 : | malsyned | 959 | $db->putGlobalProblem($problemRecord); |
| 99 : | |||
| 100 : | if ($forOneUser) { | ||
| 101 : | my $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem); | ||
| 102 : | foreach my $field (@{PROBLEM_USER_FIELDS()}) { | ||
| 103 : | my $paramName = "problem_${problem}_${field}"; | ||
| 104 : | if (defined($r->param($paramName))) { | ||
| 105 : | $userProblemRecord->$field($r->param($paramName)); | ||
| 106 : | } | ||
| 107 : | } | ||
| 108 : | malsyned | 960 | $userProblemRecord->attempted($userProblemRecord->num_correct + $userProblemRecord->num_incorrect); |
| 109 : | malsyned | 959 | foreach my $field (@{PROBLEM_FIELDS()}) { |
| 110 : | my $paramName = "problem_${problem}_${field}"; | ||
| 111 : | if (defined($r->param("${paramName}_override"))) { | ||
| 112 : | if (exists $overrides{$paramName}) { | ||
| 113 : | $userProblemRecord->$field($r->param("${paramName}_override")); | ||
| 114 : | } else { | ||
| 115 : | $userProblemRecord->$field(undef); | ||
| 116 : | } | ||
| 117 : | |||
| 118 : | $db->putUserProblem($userProblemRecord); | ||
| 119 : | } | ||
| 120 : | } | ||
| 121 : | |||
| 122 : | } | ||
| 123 : | malsyned | 935 | } |
| 124 : | } | ||
| 125 : | } | ||
| 126 : | |||
| 127 : | malsyned | 947 | # One wrinkle here: if $override is undefined, do the global thing, otherwise, it's truth value determines the checkbox. |
| 128 : | sub setRowHTML { | ||
| 129 : | my ($description, $fieldName, $fieldValue, $size, $override, $overrideValue) = @_; | ||
| 130 : | |||
| 131 : | my $attributeHash = {type=>"text", name=>$fieldName, value=>$fieldValue}; | ||
| 132 : | $attributeHash->{size} = $size if defined $size; | ||
| 133 : | |||
| 134 : | my $html = CGI::td({}, [$description, CGI::input($attributeHash)]); | ||
| 135 : | |||
| 136 : | if (defined $override) { | ||
| 137 : | $attributeHash->{name}="${fieldName}_override"; | ||
| 138 : | $attributeHash->{value}=($override ? $overrideValue : "" ); | ||
| 139 : | |||
| 140 : | $html .= CGI::td({}, [ | ||
| 141 : | CGI::checkbox({ | ||
| 142 : | type=>"checkbox", | ||
| 143 : | name=>"override", | ||
| 144 : | malsyned | 959 | label=>"override with:", |
| 145 : | malsyned | 947 | value=>$fieldName, |
| 146 : | checked=>($override ? 1 : 0) | ||
| 147 : | }), | ||
| 148 : | CGI::input($attributeHash) | ||
| 149 : | ]); | ||
| 150 : | } | ||
| 151 : | |||
| 152 : | return $html; | ||
| 153 : | |||
| 154 : | } | ||
| 155 : | |||
| 156 : | malsyned | 959 | sub hiddenUserFields { |
| 157 : | my @editForUser = @_; | ||
| 158 : | my $return = ""; | ||
| 159 : | foreach my $editUser (@editForUser) { | ||
| 160 : | $return .= CGI::input({type=>"hidden", name=>"editForUser", value=>$editUser}); | ||
| 161 : | } | ||
| 162 : | |||
| 163 : | return $return; | ||
| 164 : | } | ||
| 165 : | |||
| 166 : | malsyned | 947 | sub problemElementHTML { |
| 167 : | malsyned | 957 | my ($fieldName, $fieldValue, $size, $override, $overrideValue) = @_; |
| 168 : | malsyned | 947 | my $attributeHash = {type=>"text",name=>$fieldName,value=>$fieldValue}; |
| 169 : | $attributeHash->{size} = $size if defined $size; | ||
| 170 : | |||
| 171 : | malsyned | 957 | my $html = CGI::input($attributeHash); |
| 172 : | if (defined $override) { | ||
| 173 : | $attributeHash->{name} = "${fieldName}_override"; | ||
| 174 : | $attributeHash->{value} = ($override ? $overrideValue : ""); | ||
| 175 : | malsyned | 959 | $html = "default:".CGI::br().$html.CGI::br() |
| 176 : | malsyned | 957 | . CGI::checkbox({ |
| 177 : | type => "checkbox", | ||
| 178 : | name => "override", | ||
| 179 : | malsyned | 959 | label => "override:", |
| 180 : | malsyned | 957 | value => $fieldName, |
| 181 : | checked => ($override ? 1 : 0) | ||
| 182 : | }) | ||
| 183 : | malsyned | 959 | . CGI::br() |
| 184 : | malsyned | 957 | . CGI::input($attributeHash); |
| 185 : | } | ||
| 186 : | malsyned | 947 | |
| 187 : | malsyned | 957 | return $html; |
| 188 : | malsyned | 947 | } |
| 189 : | |||
| 190 : | gage | 860 | sub body { |
| 191 : | malsyned | 935 | my ($self, @components) = @_; |
| 192 : | my $r = $self->{r}; | ||
| 193 : | my $db = $self->{db}; | ||
| 194 : | malsyned | 962 | my $ce = $self->{ce}; |
| 195 : | my $courseName = $ce->{courseName}; | ||
| 196 : | malsyned | 935 | my $setName = $self->getSetName(@components); |
| 197 : | my $setRecord = $db->getGlobalSet($setName); | ||
| 198 : | malsyned | 936 | my @editForUser = $r->param('editForUser'); |
| 199 : | malsyned | 947 | # some useful booleans |
| 200 : | malsyned | 957 | my $forUsers = scalar(@editForUser); |
| 201 : | my $forOneUser = $forUsers == 1; | ||
| 202 : | malsyned | 935 | |
| 203 : | malsyned | 959 | ## Set Form ## |
| 204 : | malsyned | 947 | my $userSetRecord; |
| 205 : | my %overrideArgs; | ||
| 206 : | if ($forOneUser) { | ||
| 207 : | $userSetRecord = $db->getUserSet($editForUser[0], $setName); | ||
| 208 : | foreach my $field (@{SET_FIELDS()}) { | ||
| 209 : | malsyned | 959 | $overrideArgs{$field} = [defined $userSetRecord->$field, ($field =~ /_date$/ ? formatDateTime($userSetRecord->$field) : $userSetRecord->$field)]; |
| 210 : | malsyned | 947 | } |
| 211 : | } else { | ||
| 212 : | foreach my $field (@{SET_FIELDS()}) { | ||
| 213 : | $overrideArgs{$field} = [undef, undef]; | ||
| 214 : | } | ||
| 215 : | } | ||
| 216 : | |||
| 217 : | malsyned | 959 | print CGI::h2({}, "Set Data"), "\n"; |
| 218 : | print CGI::start_form({method=>"post", action=>$r->uri}), "\n"; | ||
| 219 : | malsyned | 935 | print CGI::table({}, |
| 220 : | CGI::Tr({}, [ | ||
| 221 : | malsyned | 959 | setRowHTML("Open Date:", "open_date", formatDateTime($setRecord->open_date), undef, @{$overrideArgs{open_date}})."\n", |
| 222 : | setRowHTML("Due Date:", "due_date", formatDateTime($setRecord->due_date), undef, @{$overrideArgs{due_date}})."\n", | ||
| 223 : | setRowHTML("Answer Date:", "answer_date", formatDateTime($setRecord->answer_date), undef, @{$overrideArgs{answer_date}})."\n", | ||
| 224 : | setRowHTML("Set Header:", "set_header", $setRecord->set_header, undef, @{$overrideArgs{set_header}})."\n", | ||
| 225 : | setRowHTML("Problem Header:", "problem_header", $setRecord->problem_header, undef, @{$overrideArgs{problem_header}})."\n" | ||
| 226 : | malsyned | 935 | ]) |
| 227 : | ); | ||
| 228 : | |||
| 229 : | malsyned | 959 | print hiddenUserFields(@editForUser); |
| 230 : | malsyned | 935 | print $self->hidden_authen_fields; |
| 231 : | malsyned | 936 | print CGI::input({type=>"submit", name=>"submit_set_changes", value=>"Save Set"}); |
| 232 : | malsyned | 935 | print CGI::end_form(); |
| 233 : | |||
| 234 : | malsyned | 959 | ## Problems Form ## |
| 235 : | malsyned | 935 | print CGI::h2({}, "Problems"); |
| 236 : | |||
| 237 : | my @problemList = $db->listGlobalProblems($setName); | ||
| 238 : | |||
| 239 : | malsyned | 936 | print CGI::start_form({method=>"POST", action=>$r->uri}); |
| 240 : | malsyned | 959 | print CGI::start_table({border=>1, cellpadding=>4}); |
| 241 : | malsyned | 957 | print CGI::Tr({}, CGI::th({}, [ |
| 242 : | "Problem", | ||
| 243 : | ($forUsers ? ("Status", "Problem Seed") : ()), | ||
| 244 : | "Source File", "Max. Attempts", "Weight", | ||
| 245 : | malsyned | 959 | ($forUsers ? ("Number Correct", "Number Incorrect") : ()) |
| 246 : | malsyned | 957 | ])); |
| 247 : | malsyned | 935 | foreach my $problem (sort {$a <=> $b} @problemList) { |
| 248 : | my $problemRecord = $db->getGlobalProblem($setName, $problem); | ||
| 249 : | my $problemID = $problemRecord->problem_id; | ||
| 250 : | malsyned | 957 | my $userProblemRecord; |
| 251 : | my %problemOverrideArgs; | ||
| 252 : | malsyned | 935 | |
| 253 : | malsyned | 957 | if ($forOneUser) { |
| 254 : | $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem); | ||
| 255 : | foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 256 : | $problemOverrideArgs{$field} = [defined $userProblemRecord->$field, $userProblemRecord->$field]; | ||
| 257 : | } | ||
| 258 : | # } elsif ($forUsers) { | ||
| 259 : | # foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 260 : | # $problemOverrideArgs{$field} = ["", ""]; | ||
| 261 : | # } | ||
| 262 : | } else { | ||
| 263 : | foreach my $field (@{PROBLEM_FIELDS()}) { | ||
| 264 : | $problemOverrideArgs{$field} = [undef, undef]; | ||
| 265 : | } | ||
| 266 : | } | ||
| 267 : | |||
| 268 : | malsyned | 935 | print CGI::Tr({}, |
| 269 : | malsyned | 959 | CGI::td({}, [ |
| 270 : | malsyned | 962 | CGI::a({href=>"/webwork/$courseName/instructor/pgProblemEditor/".$setName.'/'.$problemID.'?'.$self->url_authen_args}, $problemID), |
| 271 : | malsyned | 957 | ($forUsers ? ( |
| 272 : | problemElementHTML("problem_${problemID}_status", $userProblemRecord->status, "7"), | ||
| 273 : | problemElementHTML("problem_${problemID}_problem_seed", $userProblemRecord->problem_seed, "7"), | ||
| 274 : | ) : ()), | ||
| 275 : | problemElementHTML("problem_${problemID}_source_file", $problemRecord->source_file, "40", @{$problemOverrideArgs{source_file}}), | ||
| 276 : | problemElementHTML("problem_${problemID}_max_attempts",$problemRecord->max_attempts,"7", @{$problemOverrideArgs{max_attempts}}), | ||
| 277 : | problemElementHTML("problem_${problemID}_value",$problemRecord->value,"7", @{$problemOverrideArgs{value}}), | ||
| 278 : | ($forUsers ? ( | ||
| 279 : | problemElementHTML("problem_${problemID}_num_correct", $userProblemRecord->num_correct, "7"), | ||
| 280 : | problemElementHTML("problem_${problemID}_num_incorrect", $userProblemRecord->num_incorrect, "7") | ||
| 281 : | ) : ()) | ||
| 282 : | malsyned | 935 | ]) |
| 283 : | |||
| 284 : | ) | ||
| 285 : | } | ||
| 286 : | malsyned | 936 | print CGI::end_table(); |
| 287 : | malsyned | 959 | print hiddenUserFields(@editForUser); |
| 288 : | malsyned | 936 | print $self->hidden_authen_fields; |
| 289 : | print CGI::input({type=>"submit", name=>"submit_problem_changes", value=>"Save Problems"}); | ||
| 290 : | print CGI::end_form(); | ||
| 291 : | malsyned | 935 | |
| 292 : | return ""; | ||
| 293 : | } | ||
| 294 : | |||
| 295 : | sub mike_body { | ||
| 296 : | gage | 860 | my $self = shift; |
| 297 : | gage | 868 | |
| 298 : | # test area | ||
| 299 : | my $r = $self->{r}; | ||
| 300 : | my $db = $self->{db}; | ||
| 301 : | gage | 869 | |
| 302 : | gage | 868 | my $user = $r->param('user'); |
| 303 : | my $key = $db->getKey($user)->key(); | ||
| 304 : | |||
| 305 : | gage | 875 | |
| 306 : | ################ | ||
| 307 : | # Gathering info | ||
| 308 : | # What is needed | ||
| 309 : | # $setName -- formerly the name of the set definition file | ||
| 310 : | # $formURL -- the action URL for the form | ||
| 311 : | # $libraryName -- the name of the available library | ||
| 312 : | # $setDirectory -- the current library directory | ||
| 313 : | # $oldSetDirectory -- the previous library directory | ||
| 314 : | malsyned | 891 | # $problemName -- the name of the library problem (in the previous library directory) |
| 315 : | gage | 875 | # $problemList -- the contents of the textarea form |
| 316 : | # answer dates | ||
| 317 : | my ($setName,$formURL, | ||
| 318 : | $libraryName,$setDirectory,$oldSetDirectory, | ||
| 319 : | $problemName,$problemList, | ||
| 320 : | $openDate,$dueDate,$answerDate) = $self->gatherInfo(); | ||
| 321 : | |||
| 322 : | gage | 872 | ######################################################################### |
| 323 : | gage | 869 | # Determine a name for this set |
| 324 : | gage | 872 | ######################################################################### |
| 325 : | gage | 868 | # Determine the set number, if there is one. Otherwise make setName = "new set". |
| 326 : | malsyned | 888 | # FIXME: |
| 327 : | gage | 875 | # my ($path_info,@components) = $self->gatherInfo(); |
| 328 : | # my $setName = $components[0]; # get GET address for set name | ||
| 329 : | gage | 868 | |
| 330 : | # Override the setName if it is defined in a form. | ||
| 331 : | gage | 875 | # $setName = $r->param('setName') if defined($r->param('setName')); |
| 332 : | gage | 868 | |
| 333 : | gage | 875 | |
| 334 : | gage | 872 | ######################################################################### |
| 335 : | # determine the library set directory | ||
| 336 : | ######################################################################### | ||
| 337 : | gage | 875 | # $libraryName = $self->{ce}->{courseDirs}->{templates}; |
| 338 : | # my $setDirectory = $r->param('setDirectory'); | ||
| 339 : | # my $oldSetDirectory = $r->param('oldSetDirectory'); | ||
| 340 : | gage | 868 | |
| 341 : | malsyned | 888 | #FIXME: |
| 342 : | gage | 869 | # A user can select a new set AND a problem (in the old set) but the problem won't be in the new set! |
| 343 : | # In other words we must prevent the user from changing the problem and the set simultaneously. | ||
| 344 : | # We solve this by defining a hidden variable oldSetDirectory which matches the currently displayed problem list | ||
| 345 : | # the problem entry for the textarea element and the viewProblem url are | ||
| 346 : | # formed using this old version of setDefinition | ||
| 347 : | |||
| 348 : | |||
| 349 : | |||
| 350 : | gage | 868 | # Determine values for strings |
| 351 : | gage | 872 | ######################################################################### |
| 352 : | #text area region, adding problems to the list | ||
| 353 : | ######################################################################### | ||
| 354 : | gage | 868 | |
| 355 : | gage | 869 | my $textAreaString; |
| 356 : | malsyned | 888 | #FIXME: -- this does not handle multiple problem selections correctly. |
| 357 : | gage | 875 | # my $problemName = $r->param('pgProblem'); |
| 358 : | # my $problemList = $r->param('problemList'); | ||
| 359 : | gage | 872 | |
| 360 : | # Initialize the textarea string if it is empty or hasn't been defined. | ||
| 361 : | gage | 884 | $problemList = $self->gatherProblemList($setName) unless defined($problemList) and $problemList =~/\S/; |
| 362 : | |||
| 363 : | gage | 875 | my $problemEntry = $oldSetDirectory.'/'.$problemName.", 1, -1 \r\n"; |
| 364 : | gage | 872 | # add the new problem entry if the address is complete. (still buggy -- how do insure that oldSetDirectory is not empty? |
| 365 : | malsyned | 888 | $problemList .= $problemEntry unless $problemEntry =~ m|^/|; # don't print if oldSetDirectory name is empy (FIXME: -- more checks are needed?) |
| 366 : | gage | 872 | # format the complete textArea string |
| 367 : | malsyned | 891 | $textAreaString = CGI::textarea({"name"=>"problemList", "cols"=>"40", "rows"=>$rowheight, "default"=>$problemList}); |
| 368 : | gage | 868 | |
| 369 : | gage | 872 | #Determine the headline for the page |
| 370 : | |||
| 371 : | gage | 875 | |
| 372 : | malsyned | 888 | #FIXME: Debugging code |
| 373 : | gage | 875 | # my $header = "Choose problems from $libraryName directory" . |
| 374 : | gage | 869 | # "<p>This form is not yet operational. |
| 375 : | # <p>SetDirectory is $setDirectory. | ||
| 376 : | gage | 875 | # <p>formURL is $formURL |
| 377 : | gage | 869 | # <p>path_info is $path_info"; |
| 378 : | my $header = ''; | ||
| 379 : | gage | 868 | |
| 380 : | |||
| 381 : | gage | 872 | ######################################################################### |
| 382 : | # Define the popup strings used for selecting the library set directory, and the problem from that directory | ||
| 383 : | malsyned | 888 | #FIXME: |
| 384 : | gage | 869 | # he problem of multiple selections needs to be handled properly. |
| 385 : | gage | 872 | ######################################################################### |
| 386 : | gage | 868 | my $popUpSetDirectoryString = $self->fetchSetDirectories($setDirectory); #pass default choice as current directory |
| 387 : | my $popUpPGProblemString = $self->fetchPGproblems($setDirectory); | ||
| 388 : | |||
| 389 : | gage | 869 | |
| 390 : | gage | 872 | ######################################################################### |
| 391 : | gage | 869 | # Define a link to view the problem |
| 392 : | malsyned | 888 | #FIXME: |
| 393 : | gage | 869 | # Currently this link used the webwork problem library, which might be out of |
| 394 : | # sync with the local library | ||
| 395 : | gage | 872 | ######################################################################### |
| 396 : | gage | 869 | |
| 397 : | |||
| 398 : | my $viewProblemLink; | ||
| 399 : | gage | 875 | if ( (defined($oldSetDirectory) and defined($problemName)) ) { |
| 400 : | malsyned | 891 | $viewProblemLink = "View: " |
| 401 : | . CGI::a({ | ||
| 402 : | "href"=>"http://webhost.math.rochester.edu/webworkdocs/ww/pgView/$oldSetDirectory/$problemName", | ||
| 403 : | "target"=>"_probwindow" | ||
| 404 : | }, "$oldSetDirectory/$problemName"); | ||
| 405 : | gage | 869 | } else { |
| 406 : | $viewProblemLink = ''; | ||
| 407 : | |||
| 408 : | } | ||
| 409 : | gage | 872 | ######################################################################### |
| 410 : | # Format the page | ||
| 411 : | ######################################################################### | ||
| 412 : | malsyned | 891 | |
| 413 : | return CGI::p($header) | ||
| 414 : | gage | 868 | #CGI::start_form(-action=>"/webwork/mth143/instructor/problemSetEditor/"), |
| 415 : | malsyned | 891 | . CGI::start_form(-action=>$formURL) |
| 416 : | . CGI::table( {-border=>2}, | ||
| 417 : | gage | 860 | CGI::Tr({-align=>'CENTER',-valign=>'TOP'}, |
| 418 : | malsyned | 891 | CGI::th('Editing set : ') |
| 419 : | . CGI::td(CGI::textfield( -name=>'setName',-size=>'20',-value=>$setName,-override=>1)) | ||
| 420 : | . CGI::td(CGI::submit(-name=>'submitButton',-value=>'Save')) | ||
| 421 : | ) | ||
| 422 : | . CGI::Tr({-align=>'CENTER',-valign=>'TOP'}, | ||
| 423 : | CGI::td($textAreaString) | ||
| 424 : | . CGI::td($popUpSetDirectoryString) | ||
| 425 : | . CGI::td($popUpPGProblemString) | ||
| 426 : | |||
| 427 : | ) | ||
| 428 : | #(defined($viewProblemLink)) ? | ||
| 429 : | # CGI::Tr({"align"=>"center","valign"=>"top"}, CGI::th({"colspan"="3"}, $viewProblemLink)) | ||
| 430 : | # : '', | ||
| 431 : | . CGI::Tr( {-align=>'CENTER',-valign=>'TOP'}, | ||
| 432 : | CGI::th([$viewProblemLink, | ||
| 433 : | CGI::submit(-name=>'submitButton' , -value =>'Select set'), | ||
| 434 : | CGI::submit(-name=>'submitButton' , -value =>'Choose problem') | ||
| 435 : | ]) | ||
| 436 : | ) | ||
| 437 : | . CGI::Tr({-align=>'CENTER',-valign=>'TOP'}, | ||
| 438 : | CGI::th(["Open date","Due date", "Answer date"]) | ||
| 439 : | ) | ||
| 440 : | . CGI::Tr({-align=>'CENTER',-valign=>'TOP'}, | ||
| 441 : | CGI::td(CGI::textfield( -name=>'open_date', -size=>'20', -value=>$openDate)) | ||
| 442 : | . CGI::td(CGI::textfield(-name=>'due_date', -size=>'20', -value=>$dueDate)) | ||
| 443 : | . CGI::td(CGI::textfield(-name=>'answer_date', -size=>'20', -value=>$answerDate)) | ||
| 444 : | ) | ||
| 445 : | . CGI::Tr({"align"=>"center", "valign"=>"top"}, | ||
| 446 : | CGI::td({"colspan"=>"3"}, "View entire set (pdf format) -- not yet implemented") | ||
| 447 : | ) | ||
| 448 : | ) | ||
| 449 : | . $self->hidden_authen_fields | ||
| 450 : | . CGI::hidden(-name=>'oldSetDirectory', -value=>$setDirectory) | ||
| 451 : | . CGI::end_form() | ||
| 452 : | malsyned | 888 | # "<p> the parameters passed are " #FIXME: -- debugging code |
| 453 : | gage | 884 | # . join("<BR>", %{$r->param()}) . $self->gatherProblemList($setName)."setName is $setName"; |
| 454 : | gage | 860 | ; |
| 455 : | |||
| 456 : | } | ||
| 457 : | |||
| 458 : | gage | 868 | sub gatherInfo { |
| 459 : | malsyned | 887 | #FIXME: This is very much hacked together. In particular can we pass the key inside the post? |
| 460 : | gage | 875 | my $self = shift; |
| 461 : | my $ce = $self->{ce}; | ||
| 462 : | my $r = $self->{r}; | ||
| 463 : | my $path_info = $r->path_info || ""; | ||
| 464 : | |||
| 465 : | ## Determine the set name | ||
| 466 : | my $remaining_path = $path_info; | ||
| 467 : | gage | 868 | $remaining_path =~ s/^.*problemSetEditor//; |
| 468 : | gage | 875 | my($junk, $setName, @components) = split "/", $remaining_path; |
| 469 : | # Override the setName if it is defined in a form. | ||
| 470 : | $setName = $r->param('setName') if defined($r->param('setName')); | ||
| 471 : | malsyned | 888 | # FIXME:?? -- this insures backward compatibility with the old file naming convention. |
| 472 : | gage | 884 | $setName = "set$setName" unless $setName =~/^set/; |
| 473 : | gage | 868 | |
| 474 : | gage | 875 | # Find the URL for the form |
| 475 : | $path_info =~s|problemSetEditor.*$|problemSetEditor/|; # remove the setName, if any, from the path | ||
| 476 : | my $formURL = "/webwork$path_info"; # . $setName$self->url_authen_args(); | ||
| 477 : | |||
| 478 : | ######################################################################### | ||
| 479 : | # determine the library name and set directory | ||
| 480 : | ######################################################################### | ||
| 481 : | $libraryName = $ce->{courseDirs}->{templates}; | ||
| 482 : | my $setDirectory = $r->param('setDirectory'); | ||
| 483 : | my $oldSetDirectory = $r->param('oldSetDirectory'); | ||
| 484 : | |||
| 485 : | # Determine the problem name | ||
| 486 : | malsyned | 888 | #FIXME -- this does not handle multiple problem selections correctly. |
| 487 : | gage | 875 | my $problemName = $r->param('pgProblem'); |
| 488 : | # Determine the text area string (contents of set definition "file") | ||
| 489 : | my $problemList = $r->param('problemList'); | ||
| 490 : | |||
| 491 : | # get answer dates | ||
| 492 : | |||
| 493 : | my $openDate = $r->param('open_date'); | ||
| 494 : | $openDate = "" unless defined($openDate); | ||
| 495 : | my $dueDate = $r->param('due_date'); | ||
| 496 : | $dueDate = "" unless defined($dueDate); | ||
| 497 : | my $answerDate = $r->param('answer_date'); | ||
| 498 : | $answerDate = "" unless defined($answerDate); | ||
| 499 : | |||
| 500 : | ($setName,$formURL,$libraryName,$setDirectory,$oldSetDirectory,$problemName,$problemList,$openDate,$dueDate,$answerDate); | ||
| 501 : | gage | 868 | } |
| 502 : | gage | 884 | |
| 503 : | sub gatherProblemList { #workaround for obtaining the definition of a problem set (awaiting implementation of db function) | ||
| 504 : | my $self = shift; | ||
| 505 : | my $setName = shift; | ||
| 506 : | my $output = ""; | ||
| 507 : | if ( defined($setName) and $setName ne "" ) { | ||
| 508 : | my $templateDirectory = $self->{ce}->{courseDirs}->{templates}; | ||
| 509 : | my $fileName = "$templateDirectory/$setName.def"; | ||
| 510 : | my @output = split("\n",WeBWorK::Utils::readFile($fileName) ); | ||
| 511 : | @output = grep /\.pg/, @output; # only get the .pg files | ||
| 512 : | @output = grep !/Header/, @output; # eliminate header files | ||
| 513 : | $output = join("\n",@output); | ||
| 514 : | } else { | ||
| 515 : | $output = "No set name |$setName| is defined"; | ||
| 516 : | } | ||
| 517 : | |||
| 518 : | |||
| 519 : | return $output | ||
| 520 : | |||
| 521 : | |||
| 522 : | |||
| 523 : | |||
| 524 : | } | ||
| 525 : | gage | 860 | sub fetchSetDirectories { |
| 526 : | |||
| 527 : | my $self = shift; | ||
| 528 : | gage | 868 | my $defaultChoice = shift; |
| 529 : | gage | 860 | my $templateDirectory = $self->{ce}->{courseDirs}->{templates}; |
| 530 : | opendir SETDEFDIR, $templateDirectory | ||
| 531 : | or return "Can't open directory $templateDirectory"; | ||
| 532 : | |||
| 533 : | my @allFiles = grep !/^\./, readdir SETDEFDIR; | ||
| 534 : | closedir SETDEFDIR; | ||
| 535 : | |||
| 536 : | ## filter to find only the set directories | ||
| 537 : | ## -- it is assumed that these directories don't contain a period in their names | ||
| 538 : | ## and that all other files do. Directories names must also begin with "set". | ||
| 539 : | ## A better plan would be to read only the names of directories, not files. | ||
| 540 : | |||
| 541 : | ## sort the directories | ||
| 542 : | my @setDefFiles = grep /^set[^\.]*$/, @allFiles; | ||
| 543 : | my @sortedNames = sort @setDefFiles; | ||
| 544 : | |||
| 545 : | gage | 875 | return "$libraryName/" . CGI::br(). CGI::popup_menu(-name=>'setDirectory', -size=>$rowheight, |
| 546 : | gage | 869 | -values=>\@sortedNames, -default=>$defaultChoice ) .CGI::br() ; |
| 547 : | gage | 860 | } |
| 548 : | |||
| 549 : | sub fetchPGproblems { | ||
| 550 : | |||
| 551 : | my $self = shift; | ||
| 552 : | gage | 868 | my $setDirectory = shift; |
| 553 : | |||
| 554 : | # Handle default for setDirectory | ||
| 555 : | malsyned | 888 | # FIXME -- this is not bullet proof |
| 556 : | gage | 868 | $setDirectory = "set0" unless defined($setDirectory); |
| 557 : | gage | 860 | my $templateDirectory = $self->{ce}->{courseDirs}->{templates}; |
| 558 : | |||
| 559 : | ## | ||
| 560 : | opendir SETDEFDIR, "$templateDirectory/$setDirectory" | ||
| 561 : | or return "Can't open directory $templateDirectory/$setDirectory"; | ||
| 562 : | |||
| 563 : | my @allFiles = grep !/^\./, readdir SETDEFDIR; | ||
| 564 : | closedir SETDEFDIR; | ||
| 565 : | |||
| 566 : | ## filter to find only pg problems | ||
| 567 : | ## Some problems are themselves in directories (if they have auxiliary | ||
| 568 : | ## .png's for example. This eventuallity needs to be handled. | ||
| 569 : | |||
| 570 : | ## sort the directories | ||
| 571 : | my @pgFiles = grep /\.pg$/, @allFiles; | ||
| 572 : | my @sortedNames = sort @pgFiles; | ||
| 573 : | |||
| 574 : | gage | 869 | return "$setDirectory ". CGI::br() . |
| 575 : | gage | 875 | CGI::popup_menu(-name=>'pgProblem', -size=>$rowheight, -multiple=>undef, -values=>\@sortedNames, ) . |
| 576 : | gage | 869 | CGI::br() ; |
| 577 : | gage | 860 | } |
| 578 : | 1; |
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |