You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(53) |
Feb
(56) |
Mar
|
Apr
|
May
(30) |
Jun
(78) |
Jul
(121) |
Aug
(155) |
Sep
(77) |
Oct
(61) |
Nov
(45) |
Dec
(94) |
2006 |
Jan
(116) |
Feb
(33) |
Mar
(11) |
Apr
(23) |
May
(60) |
Jun
(89) |
Jul
(130) |
Aug
(109) |
Sep
(124) |
Oct
(63) |
Nov
(82) |
Dec
(45) |
2007 |
Jan
(31) |
Feb
(35) |
Mar
(123) |
Apr
(36) |
May
(18) |
Jun
(134) |
Jul
(133) |
Aug
(241) |
Sep
(126) |
Oct
(31) |
Nov
(15) |
Dec
(5) |
2008 |
Jan
(11) |
Feb
(6) |
Mar
(16) |
Apr
(29) |
May
(43) |
Jun
(149) |
Jul
(27) |
Aug
(29) |
Sep
(37) |
Oct
(20) |
Nov
(4) |
Dec
(6) |
2009 |
Jan
(34) |
Feb
(30) |
Mar
(16) |
Apr
(6) |
May
(1) |
Jun
(32) |
Jul
(22) |
Aug
(7) |
Sep
(18) |
Oct
(50) |
Nov
(22) |
Dec
(8) |
2010 |
Jan
(17) |
Feb
(15) |
Mar
(10) |
Apr
(9) |
May
(67) |
Jun
(30) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
|
From: Mike G. v. a. <we...@ma...> - 2006-01-08 01:33:53
|
Log Message: ----------- Changed target for editing window Tags: ---- rel-2-2-dev Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator: Problem.pm Revision Data ------------- Index: Problem.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Problem.pm,v retrieving revision 1.191 retrieving revision 1.191.2.1 diff -Llib/WeBWorK/ContentGenerator/Problem.pm -Llib/WeBWorK/ContentGenerator/Problem.pm -u -r1.191 -r1.191.2.1 --- lib/WeBWorK/ContentGenerator/Problem.pm +++ lib/WeBWorK/ContentGenerator/Problem.pm @@ -831,7 +831,7 @@ my $editorPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", courseID => $courseName, setID => $set->set_id, problemID => $problem->problem_id); my $editorURL = $self->systemLink($editorPage, params=>$forced_field); - $editorLink = CGI::p(CGI::a({href=>$editorURL}, "Edit this problem")); + $editorLink = CGI::p(CGI::a({href=>$editorURL,target =>'WW_Editor'}, "Edit this problem")); } ##### translation errors? ##### |
From: Mike G. v. a. <we...@ma...> - 2006-01-08 01:33:07
|
Log Message: ----------- Changes to respond to bug report #936 Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: PGProblemEditor.pm Revision Data ------------- Index: PGProblemEditor.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v retrieving revision 1.67 retrieving revision 1.68 diff -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -u -r1.67 -r1.68 --- lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm +++ lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm @@ -75,10 +75,14 @@ # But it is used instead of set_header when producing a hardcopy of the problem set in the TeX format, instead of producing HTML # formatted version for use on the computer screen. # -# filte_type eq 'course_info +# file_type eq 'course_info # This allows editing of the course_info.txt file which gives general information about the course. It is called from the # ProblemSets.pm module. # +# file_type eq 'options_info +# This allows editing of the options_info.txt file which gives general information about the course. It is called from the +# Options.pm module. +# # file_type eq 'blank_problem' # This is a special call which allows one to create and edit a new PG problem. The "stationery" source for this problem is # stored in the conf/snippets directory and defined in global.conf by $webworkFiles{screenSnippets}{blankProblem} @@ -144,6 +148,7 @@ my $file_type = $r->param("file_type") || ''; my $setName = $self->{setID}; my $problemNumber = $self->{problemID}; + # Check permissions return unless ($authz->hasPermissions($user, "access_instructor_tools")); return unless ($authz->hasPermissions($user, "modify_problem_sets")); @@ -181,8 +186,9 @@ # # Problems "saved" or 'refreshed' are to be redirected to the Problem.pm module # Set headers which are "saved" are to be redirected to the ProblemSet.pm page - # Hardcopy headers which are "saved" are aso to be redirected to the ProblemSet.pm page + # Hardcopy headers which are "saved" are also to be redirected to the ProblemSet.pm page # Course_info files are redirected to the ProblemSets.pm page + # Options_info files are redirected to the Options.pm page ############################################################################## @@ -207,6 +213,7 @@ ###################################### if ( defined($r->param('sourceFilePath') and $r->param('sourceFilePath') =~/\S/) ) { $file_type ='source_path_for_problem_file'; + $file_type = 'set_header' if $r->param('sourceFilePath') =~ m!/headers/|Header\.pg$!; #FIXME this need to be cleaned up } elsif ( defined($problemNumber) ) { if ( $problemNumber =~/^\d+$/ and $problemNumber == 0 ) { # if problem number is numeric and zero $file_type = 'set_header' unless $file_type eq 'set_header' @@ -232,7 +239,7 @@ # $self->addgoodmessage("file type is $file_type"); #FIXME debug # warn "file type is $file_type\n parameter is ".$self->r->param("file_type"); ########################################## - # File type is one of: blank_problem course_info problem set_header hardcopy_header source_path_for_problem_file + # File type is one of: blank_problem course_info options_info problem set_header hardcopy_header source_path_for_problem_file ########################################## # # Determine the path to the file @@ -350,14 +357,18 @@ $self->addmessage($r->param('status_message') ||''); # record status messages carried over if this is a redirect $self->addbadmessage("Changes in this file have not yet been permanently saved.") if -r $tempFilePath; if ( not( -e $inputFilePath) ) { - $self->addbadmessage("This file: $inputFilePath, cannot be found."); +## $self->addbadmessage("This file: $inputFilePath, cannot be found."); + $self->addbadmessage("The file '".$self->shortPath($inputFilePath)."' cannot be found."); } elsif (not -w $inputFilePath ) { - $self->addbadmessage("This file '$inputFilePath' is protected! ".CGI::br()."To edit this text you must make a copy of this file using the 'make local editable copy at ...' or the - 'rename file path to ...' action below."); + + $self->addbadmessage("The file '".$self->shortPath($inputFilePath)."' is protected! ".CGI::br(). + "To edit this text you must make a copy of this file using the 'make local editable copy at ...'action below."); + } if ($inputFilePath =~/$BLANKPROBLEM$/) { - $self->addbadmessage("This file '$inputFilePath' is a blank problem! ".CGI::br()."To edit this text you must - use 'Save As' to save it to another file."); +# $self->addbadmessage("This file '$inputFilePath' is a blank problem! ".CGI::br()."To edit this text you must + $self->addbadmessage("The file '".$self->shortPath($inputFilePath)."' is a blank problem! ".CGI::br()."To edit this text you must + use 'Save as' to save it to another file."); } } @@ -392,7 +403,8 @@ my $file_type = $self->{'file_type'} || ''; return "Set Header" if ($file_type eq 'set_header'); return "Hardcopy Header" if ($file_type eq 'hardcopy_header'); - return "Course Information" if($file_type eq 'course_info'); + return "Course Information" if ($file_type eq 'course_info'); + return "Options Information" if ($file_type eq 'options_info'); return 'Problem ' . $r->{urlpath}->name; } @@ -475,7 +487,24 @@ } my $protected_file = not -w $inputFilePath; - my $header = CGI::i("Editing problem ".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath"); + +## +## DPVC +## my $header = CGI::i("Editing problem".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath"); + my $file_type = $self->{file_type}; + my %titles = ( + problem =>CGI::b("set $setName/problem $problemNumber"), + set_header => "header file", + hardcopy_header => "hardcopy header file", + course_info => "course information", + options_info => "options information", + '' => 'Unknown file type', + source_path_for_problem_file => " unassigned problem file: ".CGI::b("set $setName/problem $problemNumber"), + ); + my $header = CGI::i("Editing $titles{$file_type} in file '".$self->shortPath($inputFilePath)."'"); +## +## /DPVC +## $header = ($self->isTempEditFilePath($inputFilePath) ) ? CGI::div({class=>'temporaryFile'},$header) : $header; # use colors if temporary file ######################################################################### @@ -492,7 +521,7 @@ my $problemSeed = $self->{problemSeed}; my $uri = $r->uri; my $edit_level = $r->param('edit_level') || 0; - my $file_type = $self->{file_type}; +## my $file_type = $self->{file_type}; my $force_field = (defined($self->{sourceFilePath}) and $self->{sourceFilePath} ne "") ? CGI::hidden(-name=>'sourceFilePath', @@ -503,11 +532,28 @@ $allSetNames[$j] =~ s|^set||; $allSetNames[$j] =~ s|\.def||; } - my $target = "problem$edit_level"; # increasing edit_level gives you a new window with each edit. + my $target = 'WW_View'; #"problem$edit_level"; # increasing edit_level gives you a new window with each edit. + print CGI::script(<<EOF); + function setTarget(inWindow) { + document.getElementById("newWindow").checked = inWindow; + updateTarget(); + } + function updateTarget() { + var inWindow = document.getElementById("newWindow").checked; + document.getElementById("editor").target = (inWindow? "WW_View": ""); + } + function setRadio(i,nw) { + document.getElementById('action'+i).checked = true; + setTarget(nw); + } +EOF print CGI::p($header), - CGI::start_form({-method=>"POST", -name=>"editor", -action=>"$uri", -target=>$target, enctype=>"application/x-www-form-urlencoded"}), + +## CGI::start_form({method=>"POST", name=>"editor", action=>"$uri", target=>$target, enctype=>"application/x-www-form-urlencoded"}), + CGI::start_form({method=>"POST", id=>"editor", name=>"editor", action=>"$uri", enctype=>"application/x-www-form-urlencoded"}), + $self->hidden_authen_fields, $force_field, CGI::hidden(-name=>'file_type',-default=>$self->{file_type}), @@ -529,7 +575,8 @@ CGI::textarea( -name => 'problemContents', -default => $problemContents, -rows => $rows, -columns => $columns, -override => 1, - )," | ", +## )," | ", + ), ); @@ -546,11 +593,15 @@ # Check permissions #next if FORM_PERMS()->{$actionID} and not $authz->hasPermissions($user, FORM_PERMS()->{$actionID}); my $actionForm = "${actionID}_form"; - my $onChange = "document.userlist.action[$i].checked=true"; + my $newWindow = ($actionID =~ m/^(view|add_problem|save)$/)? 1: 0; ## DPVC + my $onChange = "setRadio($i,$newWindow)"; ## DPVC +## my $onChange = "document.userlist.action[$i].checked=true"; my %actionParams = $self->getActionParams($actionID); my $line_contents = $self->$actionForm($onChange, %actionParams); my $radio_params = {-type=>"radio", -name=>"action", -value=>$actionID}; $radio_params->{checked}=1 if ($actionID eq $default_choice) ; + $radio_params->{onclick} = "setTarget($newWindow)"; ## DPVC + $radio_params->{id} = "action$i"; ## DPVC print CGI::Tr({-valign=>"top"}, CGI::td({}, CGI::input($radio_params)), CGI::td({}, $line_contents) @@ -558,18 +609,44 @@ $i++; } - print CGI::Tr({}, CGI::td({-align=>"right"}, "Select above then:"), - CGI::td({-align=>"left"}, CGI::submit(-name=>'submit', -value=>"Take Action!")), +# print CGI::Tr({}, CGI::td({-align=>"right"}, "Select above then:"), +# CGI::td({-align=>"left"}, CGI::submit(-name=>'submit', -value=>"Take Action!")), + ## + ## DPVC + ## + my $checkbox = CGI::input({-type=>"checkbox", -id=>"newWindow", -checked=>"checked", + -onchange=>"updateTarget()"}); + $checkbox =~ s/\n//; # remove unwanted linebreak + print CGI::Tr({}, CGI::td({-colspan=>2}, "Select above then:", + CGI::submit(-name=>'submit', -value=>"Take Action!"), + CGI::script("document.write('$checkbox in another window')")) + ## + ## /DPVC + ## ); print CGI::end_table(); print CGI::end_form(); + + print CGI::script("updateTarget()"); return ""; } +# +# Convert long paths to [TMPL], etc. +# +sub shortPath { + my $self = shift; my $file = shift; + my $tmpl = $self->r->ce->{courseDirs}{templates}; + my $root = $self->r->ce->{courseDirs}{root}; + my $ww = $self->r->ce->{webworkDirs}{root}; + $file =~ s|^$tmpl|[TMPL]|; $file =~ s|^$root|[COURSE]|; $file =~ s|^$ww|[WW]|; + return $file; +} + ################################################################################ # Utilities ################################################################################ @@ -735,9 +812,17 @@ last CASE; }; + ($file_type eq 'options_info') and do { + # we are editing the options_info file + # value of courseFiles::options_info is relative to templates directory + $editFilePath .= '/' . $ce->{courseFiles}->{options_info}; + last CASE; + }; + ($file_type eq 'blank_problem') and do { $editFilePath = $ce->{webworkFiles}->{screenSnippets}->{blankProblem}; - $self->addbadmessage("$editFilePath is blank problem template file and can not be edited directly. " +## $self->addbadmessage("$editFilePath is blank problem template file and can not be edited directly. " + $self->addbadmessage("'".$self->shortPath($editFilePath)."' is blank problem template file and can not be edited directly. " ."First use 'Save as' to make a local copy, then add the file to the current problem set, then edit the file." ); last CASE; @@ -765,8 +850,11 @@ $editFilePath = $ce->{webworkFiles}->{screenSnippets}->{setHeader} if $file_type eq 'set_header'; $editFilePath = $ce->{webworkFiles}->{hardcopySnippets}->{setHeader} if $file_type eq 'hardcopy_header'; - $self->addbadmessage("$editFilePath is the default header file and cannot be edited directly."); - $self->addbadmessage("Any changes you make will have to be saved as another file."); + +## $self->addbadmessage("$editFilePath is the default header file and cannot be edited directly."); +# $self->addbadmessage("'".$self->shortPath($editFilePath)."' is the default header file and cannot be edited directly.".CGI::br()."Any changes you make will have to be saved as another file."); + #} + } last CASE; }; #end 'set_header, hardcopy_header' case @@ -808,13 +896,15 @@ # which is almost undoubtedly NOT desirable if (-d $editFilePath) { - my $msg = "The file $editFilePath is a directory!"; +## my $msg = "The file $editFilePath is a directory!"; + my $msg = "The file '".$self->shortPath($editFilePath)."' is a directory!"; $self->{failure} = 1; $self->addbadmessage($msg); } if (-e $editFilePath and not -r $editFilePath) { #it's ok if the file doesn't exist, perhaps we're going to create it # with save as - my $msg = "The file $editFilePath cannot be read!"; +## my $msg = "The file $editFilePath cannot be read!"; + my $msg = "The file '".$self->shortPath($editFilePath)."' cannot be read!"; $self->{failure} = 1; $self->addbadmessage($msg); } @@ -914,11 +1004,14 @@ if ( not -w $ce->{courseDirs}->{templates} ) { $errorMessage = "Write permissions have not been enabled in the templates directory. No changes can be made."; } elsif ( not -w $currentDirectory ) { - $errorMessage = "Write permissions have not been enabled in $currentDirectory. Changes must be saved to a different directory for viewing."; +## $errorMessage = "Write permissions have not been enabled in $currentDirectory. Changes must be saved to a different directory for viewing."; + $errorMessage = "Write permissions have not been enabled in '".$self->shortPath($currentDirectory)."'. Changes must be saved to a different directory for viewing."; } elsif ( -e $outputFilePath and not -w $outputFilePath ) { - $errorMessage = "Write permissions have not been enabled for $outputFilePath. Changes must be saved to another file for viewing."; +## $errorMessage = "Write permissions have not been enabled for $outputFilePath. Changes must be saved to another file for viewing."; + $errorMessage = "Write permissions have not been enabled for '".$self->shortPath($outputFilePath)."'. Changes must be saved to another file for viewing."; } else { - $errorMessage = "Unable to write to $outputFilePath: $writeFileErrors"; +## $errorMessage = "Unable to write to $outputFilePath: $writeFileErrors"; + $errorMessage = "Unable to write to '".$self->shortPath($outputFilePath)."': $writeFileErrors"; } $self->{failure} = 1; @@ -930,15 +1023,18 @@ ########################################################### unless( $writeFileErrors or $do_not_save) { # everything worked! unlink and announce success! # unlink the temporary file if there are no errors and the save button has been pushed - if ($action eq 'save' or $action eq 'save_as') { + if (($action eq 'save' or $action eq 'save_as') and (-w $self->{tempFilePath}) ) { - $self->addgoodmessage("Deleting temp file at " . $self->{tempFilePath}); + $self->addgoodmessage("Deleting temp file at " . $self->shortPath($self->{tempFilePath})); unlink($self->{tempFilePath}) ; } + if ( defined($outputFilePath) and ! $self->{failure} and not $self->isTempEditFilePath($outputFilePath) ) { # don't announce saving of temporary editing files - my $msg = "Saved to file: |$outputFilePath|"; + my $msg = "Saved to file '".$self->shortPath($outputFilePath)."'."; + $self->addgoodmessage($msg); + #$self->{inputFilePath} = $outputFilePath; ## DPVC -- avoid file-not-found message } } @@ -980,14 +1076,16 @@ sub view_form { my ($self, $onChange, %actionParams) = @_; my $output_string = "View"; - unless ($self->{file_type} eq 'course_info') { + unless ($self->{file_type} eq 'course_info' || $self->{file_type} eq 'options_info') { $output_string .= join(" ", - " problem using seed ", - CGI::textfield(-name=>'action.view.seed',-value=>$self->{problemSeed}), +## " problem using seed ", + " using seed ", + CGI::textfield(-name=>'action.view.seed',-value=>$self->{problemSeed},-onfocus=>$onChange), "and display mode ", CGI::popup_menu(-name=>'action.view.displayMode', -values=>$self->r->ce->{pg}->{displayModes}, - -default=>$self->{displayMode} - ), ".", + -default=>$self->{displayMode}, -onmousedown=>$onChange +## ), ".", + ) ); } @@ -1049,6 +1147,7 @@ $viewURL = $self->systemLink($problemPage, params => { + set_header => $tempFilePath, displayMode => $displayMode, problemSeed => $problemSeed, editMode => "temporaryFile", @@ -1059,11 +1158,23 @@ ); - } elsif ($file_type eq 'course_info') { # redirecto to ProblemSets.pm + } elsif ($file_type eq 'course_info') { # redirec to ProblemSets.pm my $problemSetsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets", courseID => $courseName); $viewURL = $self->systemLink($problemSetsPage, params => { + course_info => $tempFilePath, + editMode => "temporaryFile", + edit_level => $edit_level, + status_message => uri_escape($self->{status_message}) + } + ); + } elsif ($file_type eq 'options_info') { # redirec to Options.pm + my $optionsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Options", + courseID => $courseName); + $viewURL = $self->systemLink($optionsPage, + params => { + options_info => $tempFilePath, editMode => "temporaryFile", edit_level => $edit_level, status_message => uri_escape($self->{status_message}) @@ -1085,18 +1196,25 @@ $setName = defined($setName) ? $setName : ''; # we need this instead of using the || construction # to keep set 0 from being set to the # empty string. + my $filePath = $self->{inputFilePath}; $setName =~ s|^set||; my @allSetNames = sort $r->db->listGlobalSets; for (my $j=0; $j<scalar(@allSetNames); $j++) { $allSetNames[$j] =~ s|^set||; $allSetNames[$j] =~ s|\.def||; } - return "" if $self->{file_type} eq 'course_info'; + my $labels = { + problem => 'problem', + set_header => 'set header', + hardcopy_header => 'hardcopy header', + }; + return "" if $self->{file_type} eq 'course_info' || $self->{file_type} eq 'options_info'; return join(" ", - "Add problem to set " , - CGI::popup_menu(-name=>'action.add_problem.target_set', -values=>\@allSetNames, -default=>$setName), +## "Add problem to set " , + "Add to set " , + CGI::popup_menu({name=>'action.add_problem.target_set', values=>\@allSetNames, default=>$setName, onmousedown=>$onChange}), " as ", - CGI::popup_menu(-name=>'action.add_problem.file_type', -values=>['problem','set_header'], -default=>'problem'), + CGI::popup_menu({name=>'action.add_problem.file_type', values=>['problem','set_header', 'hardcopy_header'], labels=>$labels, default=>$self->{file_type}, onmousedown=>$onChange}), ); #FIXME add -lables to the pop up menu return ""; @@ -1162,9 +1280,11 @@ my $setRecord = $self->r->db->getGlobalSet($targetSetName); $setRecord->set_header($sourceFilePath); if( $self->r->db->putGlobalSet($setRecord) ) { - $self->addgoodmessage("Added $sourceFilePath to ". $targetSetName. " as new set header ") ; +## $self->addgoodmessage("Added $sourceFilePath to ". $targetSetName. " as new set header ") ; + $self->addgoodmessage("Added '".$self->shortPath($sourceFilePath)."' to ". $targetSetName. " as new set header ") ; } else { - $self->addbadmessage("Unable to make $sourceFilePath the set header for $targetSetName"); +## $self->addbadmessage("Unable to make $sourceFilePath the set header for $targetSetName"); + $self->addbadmessage("Unable to make '".$self->shortPath($sourceFilePath)."' the set header for $targetSetName"); } $self->{file_type} = 'set_header'; # change file type to set_header if it not already so ################################################# @@ -1192,13 +1312,13 @@ sub save_form { my ($self, $onChange, %actionParams) = @_; my $r => $self->r; + #return "" unless defined($self->{tempFilePath}) and -e $self->{tempFilePath}; if ($self->{editFilePath} =~ /$BLANKPROBLEM$/ ) { return ""; #Can't save blank problems without changing names } elsif (-w $self->{editFilePath}) { - my $sourceFilePath = $self->{editFilePath}; - my $templatesPath = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory - return "Save to: [TMPL]/$sourceFilePath"; + + return "Save to: ".$self->shortPath($self->{editFilePath})." and View"; + } else { return ""; #"Can't save -- No write permission"; } @@ -1237,7 +1357,7 @@ ######################################################## # construct redirect URL and redirect ######################################################## - if ($file_type eq 'problem' ) { # redirect to Problem.pm + if ($file_type eq 'problem' || $file_type eq 'source_path_for_problem_file') { # redirect to Problem.pm my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Problem", courseID => $courseName, setID => $setName, problemID => $problemNumber ); @@ -1280,6 +1400,16 @@ status_message => uri_escape($self->{status_message}) } ); + } elsif ($file_type eq 'options_info') { # redirect to Options.pm + my $optionsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Options", + courseID => $courseName); + $viewURL = $self->systemLink($optionsPage, + params => { + editMode => ("savedFile"), + edit_level => 0, + status_message => uri_escape($self->{status_message}) + } + ); } elsif ($file_type eq 'source_path_for_problem_file') { # redirect to ProblemSets.pm my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", courseID => $courseName, setID => $setName, problemID => $problemNumber @@ -1304,22 +1434,95 @@ $self->reply_with_redirect($viewURL); } -sub save_as_form { # calls either the save_as_handler or the rename_handler + +sub make_local_copy_form { + my ($self, $genericParams, $actionParams, $tableParams) = @_; + my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited + #warn "editFilePath $editFilePath inputFilePath",$self->{inputFilePath}; + return "" unless -e $editFilePath; + return "" if -w $editFilePath; + return "" unless $self->{file_type} eq 'problem' # need problem structure to make local copy in most cases + or $self->{file_type} eq 'set_header' # $editFilePath eq $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader} # special case to make copy of hardcopy header + or $self->{file_type} eq 'hardcopy_header'; # $editFilePath eq $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader} ; # special case to make copy of screen header + # or $self->{file_type} eq 'source_path_for_problem_file'; # need setID and problemID to make local copy -- can't be done in this case. + return join ("", + "Make local editable copy at: [TMPL]/".($self->determineLocalFilePath($editFilePath)), + CGI::hidden(-name=>'action.make_local_copy.target_file', -value=>$self->determineLocalFilePath($editFilePath) ), + CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$editFilePath ), + CGI::hidden(-name=>'action.make_local_copy.file_type',-value=>$self->{file_type}), + CGI::hidden(-name=>'action.make_local_copy.saveMode',-value=>'rename') + ); + +} + + + + + + + + + + +sub make_local_copy_handler { + my ($self, $genericParams, $actionParams, $tableParams) = @_; + foreach my $key (qw(target_file file_type saveMode source_file)) { + $actionParams->{"action.save_as.$key"}->[0] = $actionParams->{"action.make_local_copy.$key"}->[0]; + #warn "action.make_local_copy.$key", @{$actionParams->{"action.make_local_copy.$key"}} + } + save_as_handler($self, $genericParams, $actionParams, $tableParams); + +} +sub save_as_form { # calls the save_as_handler my ($self, $onChange, %actionParams) = @_; - my $sourceFilePath = $self->{editFilePath}; - my $templatesDir = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesDir/||; - $sourceFilePath = '' if $sourceFilePath =~ m|^/|; # if it is still an absolute path don't suggest that you save to it. + my $editFilePath = $self->{editFilePath}; + return "" unless -w $editFilePath; - return CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], - -default=>'rename',-labels=>{rename=>'Rename file path to ',save_a_copy=>'Create a copy of file at '} - ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$sourceFilePath),; - + my $shortFilePath = $editFilePath; + my $templatesDir = $self->r->ce->{courseDirs}->{templates}; + my $setID = $self->{setID}; + $shortFilePath =~ s|^$templatesDir/||; + $shortFilePath = '' if $shortFilePath =~ m|^/|; # if it is still an absolute path don't suggest that you save to it. + my $allowedActions = (defined($setID) && $setID =~/\S/ && $setID ne 'Undefined_Set') ? ['save_a_copy','rename' ] : ['save_a_copy']; +# return CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], +# -default=>'rename',-labels=>{rename=>'Rename file path to ',save_a_copy=>'Create a copy of file at '} +# ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath),; + +## +## DPVC +## + +# return "Save ". +# CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], +# -default=>'rename',-labels=>{rename=>' as ',save_a_copy=>'a copy to'} +# ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath),; + + return CGI::popup_menu( + -name=>'action.save_as.saveMode', -values=>$allowedActions, + -default=>'rename',-labels=>{save_a_copy=>'Create a copy of file at ', rename=>'Rename file path to'}, + -onmousedown=>$onChange + ). ": [TMPL]/". + CGI::textfield( + -name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath, + -onfocus=>$onChange + ). + CGI::hidden(-name=>'action.save_as.source_file', -value=>$editFilePath ). + CGI::hidden(-name=>'action.save_as.file_type',-value=>$self->{file_type}), + ; +# if $self->{setID} && $self->{setID} ne '' && $self->{setID} ne 'Undefined_Set'; +# FIXME -- this should eventually work for undefined sets as well. +# return CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['save_a_copy'], +# -default=>'save_a_copy',-labels=>{save_a_copy=>'Save as'}, -onmousedown=>$onChange +# ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath) +## +## /DPVC +## } sub save_as_handler { my ($self, $genericParams, $actionParams, $tableParams) = @_; #$self->addgoodmessage("save_as_handler called"); + $self->{status_message} = ''; ## DPVC -- remove bogus old messages my $courseName = $self->{courseID}; my $setName = $self->{setID}; my $problemNumber = $self->{problemID}; @@ -1327,15 +1530,17 @@ my $problemSeed = $self->{problemSeed}; my $do_not_save = 0; - my $saveMode = $actionParams->{'action.save_as.saveMode'}->[0] || ''; - my $new_file_name = $actionParams->{'action.save_as.target_file'}->[0] || ''; + my $saveMode = $actionParams->{'action.save_as.saveMode'}->[0] || ''; + my $new_file_name = $actionParams->{'action.save_as.target_file'}->[0] || ''; + my $sourceFilePath = $actionParams->{'action.save_as.source_file'}->[0] || ''; + my $file_type = $actionParams->{'action.save_as.file_type'}->[0] || ''; + $new_file_name =~ s/^\s*//; #remove initial and final white space $new_file_name =~ s/\s*$//; if ( $new_file_name !~ /\S/) { # need a non-blank file name # setting $self->{failure} stops saving and any redirects $do_not_save = 1; $self->addbadmessage(CGI::p("Please specify a file to save to.")); - last ACTION_CASES; #stop processing } ################################################# @@ -1344,14 +1549,14 @@ ################################################# my $problemContents = fixProblemContents($self->r->param('problemContents')); $self->{r_problemContents} = \$problemContents; - + warn "problem contents is empty" unless $problemContents; ################################################# # Rescue the user in case they forgot to end the file name with .pg ################################################# - my $file_type = $self->{file_type}; - if($self->{file_type} eq 'problem' - or $self->{file_type} eq 'blank_problem' - or $self->{file_type} eq 'set_header') { + + if($file_type eq 'problem' + or $file_type eq 'blank_problem' + or $file_type eq 'set_header') { $new_file_name =~ s/\.pg$//; # remove it if it is there $new_file_name .= '.pg'; # put it there @@ -1364,7 +1569,10 @@ if (defined $outputFilePath and -e $outputFilePath) { # setting $do_not_save stops saving and any redirects $do_not_save = 1; - $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); +## $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); + $self->addbadmessage(CGI::p("File '".$self->shortPath($outputFilePath)."' exists. + File not saved. No changes have been made. + You can change the file path for this problem manually from the 'Hmwk Sets Editor' page")); } else { $self->{editFilePath} = $outputFilePath; $self->{tempFilePath} = ''; # nothing needs to be unlinked. @@ -1373,24 +1581,52 @@ unless ($do_not_save ) { - $self->saveFileChanges($outputFilePath, \$problemContents); - my $sourceFilePath = $outputFilePath; - my $templatesPath = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory - - if ($saveMode eq 'rename') { #save to new file - my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); - $problemRecord->source_file($new_file_name); - if ( $self->r->db->putGlobalProblem($problemRecord) ) { - $self->addgoodmessage("The current source file for problem $problemNumber has been renamed to [TMPL]/$sourceFilePath.") ; + $self->saveFileChanges($outputFilePath); +## my $templatesPath = $self->r->ce->{courseDirs}->{templates}; +## $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory + + if ($saveMode eq 'rename' and -r $outputFilePath) { + ################################################# + # Modify source file in problem + ################################################# + if ($file_type eq 'set_header' ) { + my $setRecord = $self->r->db->getGlobalSet($setName); + $setRecord->set_header($new_file_name); + if ($self->r->db->putGlobalSet($setRecord)) { + $self->addgoodmessage("The set header for set $setName has been renamed to '".$self->shortPath($outputFilePath)."'.") ; + } else { + $self->addbadmessage("Unable to change the set header for set $setName. Unknown error."); + } + } elsif ($file_type eq 'hardcopy_header' ) { + my $setRecord = $self->r->db->getGlobalSet($setName); + $setRecord->hardcopy_header($new_file_name); + if ($self->r->db->putGlobalSet($setRecord)) { + $self->addgoodmessage("The hardcopy header for set $setName has been renamed to '".$self->shortPath($outputFilePath)."'.") ; + } else { + $self->addbadmessage("Unable to change the hardcopy header for set $setName. Unknown error."); + } } else { - $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); + my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); + $problemRecord->source_file($new_file_name); + if ( $self->r->db->putGlobalProblem($problemRecord) ) { + $self->addgoodmessage("The source file for 'set $setName / problem $problemNumber' has been changed from ". + $self->shortPath($sourceFilePath)." to '".$self->shortPath($outputFilePath)."'.") ; + } else { + $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); + } } } elsif ($saveMode eq 'save_a_copy') { - $self->addgoodmessage("A new local, editable, copy of this problem has been created at [TMPL]/$sourceFilePath.") ; + ################################################# + # Don't modify source file in problem -- just report + ################################################# + + #$self->{status_message} = ''; ## DPVC remove old messages + $self->addgoodmessage("A new file has been created at '".$self->shortPath($outputFilePath). + "' with the contents below. No changes have been made to set $setName."); } else { $self->addbadmessage("Don't recognize saveMode: |$saveMode|. Unknown error."); } + } my $edit_level = $self->r->param("edit_level") || 0; $edit_level++; @@ -1400,23 +1636,27 @@ # The redirect gives the server time to detect that the new file exists. ################################################# my $problemPage; + my $new_file_type; if ($saveMode eq 'save_a_copy' ) { $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", courseID => $courseName, setID => 'Undefined_Set', problemID => 'Undefined_Set' ); + $new_file_type = 'source_path_for_problem_file'; } elsif ($saveMode eq 'rename') { $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", courseID => $courseName, setID => $setName, problemID => $problemNumber ); - + $new_file_type = $file_type; } else { $self->addbadmessage("Don't recognize saveMode: |$saveMode|. Unknown error."); + die "Don't recognize saveMode: |$saveMode|. Unknown error." } + warn "save mode is $saveMode"; my $viewURL = $self->systemLink($problemPage, params=>{ sourceFilePath => $outputFilePath, #The path relative to the templates directory is required. edit_level => $edit_level, - file_type => 'source_path_for_problem_file', + file_type => $new_file_type, status_message => uri_escape($self->{status_message}) } @@ -1427,147 +1667,124 @@ } sub revert_form { my ($self, $onChange, %actionParams) = @_; - return "Revert" ; + my $editFilePath = $self->{editFilePath}; + return "Error: The original file $editFilePath cannot be read." unless -r $editFilePath; + return "" unless defined($self->{tempFilePath}) and -e $self->{tempFilePath} ; + return "Revert to ".$self->shortPath($editFilePath) ; } sub revert_handler { my ($self, $genericParams, $actionParams, $tableParams) = @_; - #$self->addgoodmessage("revert_handler called"); - - my $courseName = $self->{courseID}; - my $setName = $self->{setID}; - my $problemNumber = $self->{problemID}; - my $displayMode = $self->{displayMode}; - my $problemSeed = $self->{problemSeed}; - ################################################# - # Reset the problem paths - ################################################# - + #$self->addgoodmessage("revert_handler called"); my $editFilePath = $self->{editFilePath}; $self->{inputFilePath} = $editFilePath; # unlink the temp files; unlink($self->{tempFilePath}); - $self->addgoodmessage("Deleting temp file at " . $self->{tempFilePath}); + $self->addgoodmessage("Deleting temp file at " . $self->shortPath($self->{tempFilePath})); $self->{tempFilePath} = ''; my $problemContents =''; $self->{r_problemContents} = \$problemContents; - $self->addgoodmessage("Reverting to original file $editFilePath"); + $self->addgoodmessage("Reverting to original file '".$self->shortPath($editFilePath)."'"); # no redirect is needed } -sub make_local_copy_form { - my ($self, $genericParams, $actionParams, $tableParams) = @_; - my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited - return "" unless -e $editFilePath; - return "" if -w $editFilePath; - return "" unless $self->{file_type} eq 'problem' # need problem structure to make local copy in most cases - or $self->{file_type} eq 'set_header' # $editFilePath eq $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader} # special case to make copy of hardcopy header - or $self->{file_type} eq 'hardcopy_header'; # $editFilePath eq $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader} ; # special case to make copy of screen header - # or $self->{file_type} eq 'source_path_for_problem_file'; # need setID and problemID to make local copy -- can't be done in this case. - return join ("", - "Make local editable copy at: [TMPL]/".($self->determineLocalFilePath($editFilePath)), - CGI::hidden(-name=>'action.make_local_copy.target_file', -value=>$self->determineLocalFilePath($editFilePath) ), - CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$editFilePath ), - CGI::hidden(-name=>'action.make_local_copy.file_type',-value=>$self->{file_type}) - ); - -} -sub make_local_copy_handler { - my ($self, $genericParams, $actionParams, $tableParams) = @_; - #$self->addgoodmessage("make_local_copy_handler called"); - - my $courseName = $self->{courseID}; - my $setName = $self->{setID}; - my $problemNumber = $self->{problemID}; - my $displayMode = $self->{displayMode}; - my $problemSeed = $self->{problemSeed}; - - my $do_not_save = 0; #error flag - ################################################# - # Save the file locally - ################################################# - my $new_file_name = $actionParams->{'action.make_local_copy.target_file'}->[0] || ''; - my $sourceFilePath = $actionParams->{'action.make_local_copy.source_file'}->[0] || ''; - my $file_type = $actionParams->{'action.make_local_copy.file_type'}->[0] ||''; - - my $templatesPath = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory - - if ( $new_file_name !~ /\S/) { # need a non-blank file name - # setting $self->{failure} stops saving and any redirects - $do_not_save = 1; - warn "new file name is $new_file_name"; - $self->addbadmessage(CGI::p("Please specify a file to save to.")); - } - - ################################################# - # grab the problemContents from the form in order to save it to a new permanent file - # later we will unlink (delete) the current temporary file - ################################################# - - my $problemContents = fixProblemContents($self->r->param('problemContents')); - $self->{r_problemContents} = \$problemContents; - warn "problem contents is empty" unless $problemContents; - ################################################# - # Construct the output file path - ################################################# - my $outputFilePath = $self->r->ce->{courseDirs}->{templates} . '/' . - $new_file_name; - if (defined $outputFilePath and -e $outputFilePath) { - # setting $do_not_save stops saving and any redirects - $do_not_save = 1; - $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); - } else { - #$self->addgoodmessage("Saving to file $outputFilePath."); - } - unless ($do_not_save ) { - $self->saveFileChanges($outputFilePath); - } - ################################################# - # Modify source file in problem - ################################################# - if (-r $outputFilePath and !$do_not_save) { - if ($file_type eq 'problem') { - my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); - die "Unable to problem record for set $setName, problem $problemNumber"; - $problemRecord->source_file($new_file_name); - if ( $self->r->db->putGlobalProblem($problemRecord) ) { - $self->addgoodmessage("A local, editable, copy of [TMPL]/$sourceFilePath has been made for problem $problemNumber.") ; - } else { - $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); - } - } elsif ($file_type eq 'set_header' or $file_type eq 'hardcopy_header') { # we are dealing with a set header - - my $set_record = $self->r->db->getGlobalSet($setName); - $set_record->{$file_type} = $new_file_name; - if ( $self->r->db->putGlobalSet($set_record) ) { - $self->addgoodmessage("A local, editable, copy of [TMPL]/$sourceFilePath has been made for the $setName set header") ; - } else { - $self->addbadmessage("Unable to change the source file path for set $setName, set header. Unknown error."); - } - } - } - my $edit_level = $self->r->param("edit_level") || 0; - $edit_level++; - ################################################# - # Set up redirect - ################################################# - - my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", - courseID => $courseName, setID => $setName, problemID => $problemNumber - ); - my $viewURL = $self->systemLink($problemPage, - params=>{ - sourceFilePath => $new_file_name, - edit_level => $edit_level, - file_type => $self->{file_type}, - status_message => uri_escape($self->{status_message}) - - } - ); - $self->reply_with_redirect($viewURL); -} +# sub make_local_copy_handler { +# my ($self, $genericParams, $actionParams, $tableParams) = @_; +# #$self->addgoodmessage("make_local_copy_handler called"); +# +# my $courseName = $self->{courseID}; +# my $setName = $self->{setID}; +# my $problemNumber = $self->{problemID}; +# +# my $displayMode = $self->{displayMode}; +# my $problemSeed = $self->{problemSeed}; +# my $do_not_save = 0; #error flag +# +# my $new_file_name = $actionParams->{'action.make_local_copy.target_file'}->[0] || ''; +# my $sourceFilePath = $actionParams->{'action.make_local_copy.source_file'}->[0] || ''; +# my $file_type = $actionParams->{'action.make_local_copy.file_type'}->[0] ||''; +# +# my $templatesPath = $self->r->ce->{courseDirs}->{templates}; +# $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory +# +# if ( $new_file_name !~ /\S/) { # need a non-blank file name +# # setting $self->{failure} stops saving and any redirects +# $do_not_save = 1; +# #warn "new file name is $new_file_name"; +# $self->addbadmessage(CGI::p("Error: File to save to not specified.")); +# } +# +# ################################################# +# # grab the problemContents from the form in order to save it to a new permanent file +# # later we will unlink (delete) the current temporary file +# ################################################# +# +# my $problemContents = fixProblemContents($self->r->param('problemContents')); +# $self->{r_problemContents} = \$problemContents; +# warn "problem contents is empty" unless $problemContents; +# ################################################# +# # Construct the output file path +# ################################################# +# my $outputFilePath = $self->r->ce->{courseDirs}->{templates} . '/' . +# $new_file_name; +# if (defined $outputFilePath and -e $outputFilePath) { +# # setting $do_not_save stops saving and any redirects +# $do_not_save = 1; +# ## $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); +# $self->addbadmessage(CGI::p("File '".$self->shortPath($outputFilePath)."' exists. +# File not saved. No changes have been made. +# You can change the file path for this problem manually from the 'Hmwk Sets Editor' page")); +# } else { +# ## #$self->addgoodmessage("Saving to file $outputFilePath."); +# #$self->addgoodmessage("Saving to file '".$self->shortPath($outputFilePath)."'."); +# } +# +# unless ($do_not_save ) { +# $self->saveFileChanges($outputFilePath); +# ################################################# +# # Modify source file in problem +# ################################################# +# if ($file_type eq 'set_header') { +# my $setRecord = $self->r->db->getGlobalSet($setName); +# $setRecord->set_header($new_file_name); +# if ($self->r->db->putGlobalSet($setRecord)) { +# $self->addgoodmessage("The set header for set $setName has been renamed to '".$self->shortPath($outputFilePath)."'.") ; +# } else { +# $self->addbadmessage("Unable to change the header for set $setName. Unknown error."); +# } +# } else { +# my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); +# $problemRecord->source_file($new_file_name); +# if ( $self->r->db->putGlobalProblem($problemRecord) ) { +# ## $self->addgoodmessage("The current source file for set $setName problem $problemNumber has been renamed to [TMPL]/$outputFilePath.") ; +# $self->addgoodmessage("The current source file for problem $problemNumber has been renamed to '".$self->shortPath($outputFilePath)."'.") ; +# } else { +# $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); +# } +# } +# +# } +# my $edit_level = $self->r->param("edit_level") || 0; +# $edit_level++; +# ################################################# +# # Set up redirect +# ################################################# +# +# my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", +# courseID => $courseName, setID => $setName, problemID => $problemNumber +# ); +# my $viewURL = $self->systemLink($problemPage, +# params=>{ +# sourceFilePath => $new_file_name, +# edit_level => $edit_level, +# file_type => $self->{file_type}, +# status_message => uri_escape($self->{status_message}) +# +# } +# ); +# $self->reply_with_redirect($viewURL); +# } # sub rename_form { # see the save_as form # # my ($self, $onChange, %actionParams) = @_; @@ -1585,11 +1802,11 @@ # # } -sub rename_handler { - my ($self, $genericParams, $actionParams, $tableParams) = @_; - $actionParams->{'action.make_local_copy.target_file'}->[0] = $actionParams->{'action.rename.target_file'}->[0]; - make_local_copy_handler($self, $genericParams, $actionParams, $tableParams); -} +# sub rename_handler { +# my ($self, $genericParams, $actionParams, $tableParams) = @_; +# $actionParams->{'action.make_local_copy.target_file'}->[0] = $actionParams->{'action.rename.target_file'}->[0]; +# make_local_copy_handler($self, $genericParams, $actionParams, $tableParams); +# } 1; |
From: Mike G. v. a. <we...@ma...> - 2006-01-08 01:23:27
|
Log Message: ----------- Added many changes that address the weakness reported in bug report #936 This file has had significant testing but it still needs a workout. Tags: ---- rel-2-2-dev Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: PGProblemEditor.pm Revision Data ------------- Index: PGProblemEditor.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v retrieving revision 1.66 retrieving revision 1.66.2.1 diff -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -u -r1.66 -r1.66.2.1 --- lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm +++ lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm @@ -75,10 +75,14 @@ # But it is used instead of set_header when producing a hardcopy of the problem set in the TeX format, instead of producing HTML # formatted version for use on the computer screen. # -# filte_type eq 'course_info +# file_type eq 'course_info # This allows editing of the course_info.txt file which gives general information about the course. It is called from the # ProblemSets.pm module. # +# file_type eq 'options_info +# This allows editing of the options_info.txt file which gives general information about the course. It is called from the +# Options.pm module. +# # file_type eq 'blank_problem' # This is a special call which allows one to create and edit a new PG problem. The "stationery" source for this problem is # stored in the conf/snippets directory and defined in global.conf by $webworkFiles{screenSnippets}{blankProblem} @@ -182,8 +186,9 @@ # # Problems "saved" or 'refreshed' are to be redirected to the Problem.pm module # Set headers which are "saved" are to be redirected to the ProblemSet.pm page - # Hardcopy headers which are "saved" are aso to be redirected to the ProblemSet.pm page + # Hardcopy headers which are "saved" are also to be redirected to the ProblemSet.pm page # Course_info files are redirected to the ProblemSets.pm page + # Options_info files are redirected to the Options.pm page ############################################################################## @@ -197,6 +202,7 @@ # or regular problem if (defined($file_type) and ($file_type =~/\S/)) { #file_type is defined and is not blank # file type is already defined -- do nothing + #warn "file type already defined as $file_type" #FIXME debug } else { # if "sourceFilePath" is defined in the form, then we are getting the path directly. # if the problem number is defined and is 0 @@ -207,12 +213,14 @@ ###################################### if ( defined($r->param('sourceFilePath') and $r->param('sourceFilePath') =~/\S/) ) { $file_type ='source_path_for_problem_file'; + $file_type = 'set_header' if $r->param('sourceFilePath') =~ m!/headers/|Header\.pg$!; #FIXME this need to be cleaned up } elsif ( defined($problemNumber) ) { if ( $problemNumber =~/^\d+$/ and $problemNumber == 0 ) { # if problem number is numeric and zero - $file_type = 'set_header' unless $file_type eq 'set_header' + $file_type = 'set_header' unless $file_type eq 'set_header' or $file_type eq 'hardcopy_header'; } else { - $file_type = 'problem'; + $file_type = 'problem'; + #warn "setting file type to 'problem'\n"; #FIXME debug } } @@ -228,9 +236,10 @@ $self->{sourceFilePath} = $sourceFilePath; } $self->{file_type} = $file_type; - + # $self->addgoodmessage("file type is $file_type"); #FIXME debug + # warn "file type is $file_type\n parameter is ".$self->r->param("file_type"); ########################################## - # File type is one of: blank_problem course_info problem set_header hardcopy_header source_path_for_problem_file + # File type is one of: blank_problem course_info options_info problem set_header hardcopy_header source_path_for_problem_file ########################################## # # Determine the path to the file @@ -348,14 +357,18 @@ $self->addmessage($r->param('status_message') ||''); # record status messages carried over if this is a redirect $self->addbadmessage("Changes in this file have not yet been permanently saved.") if -r $tempFilePath; if ( not( -e $inputFilePath) ) { - $self->addbadmessage("This file: $inputFilePath, cannot be found."); +## $self->addbadmessage("This file: $inputFilePath, cannot be found."); + $self->addbadmessage("The file '".$self->shortPath($inputFilePath)."' cannot be found."); } elsif (not -w $inputFilePath ) { - $self->addbadmessage("This file '$inputFilePath' is protected! ".CGI::br()."To edit this text you must either 'Make a local copy' of this problem, or - use 'Save As' to save it to another file."); + + $self->addbadmessage("The file '".$self->shortPath($inputFilePath)."' is protected! ".CGI::br(). + "To edit this text you must make a copy of this file using the 'make local editable copy at ...'action below."); + } if ($inputFilePath =~/$BLANKPROBLEM$/) { - $self->addbadmessage("This file '$inputFilePath' is a blank problem! ".CGI::br()."To edit this text you must - use 'Save As' to save it to another file."); +# $self->addbadmessage("This file '$inputFilePath' is a blank problem! ".CGI::br()."To edit this text you must + $self->addbadmessage("The file '".$self->shortPath($inputFilePath)."' is a blank problem! ".CGI::br()."To edit this text you must + use 'Save as' to save it to another file."); } } @@ -390,7 +403,8 @@ my $file_type = $self->{'file_type'} || ''; return "Set Header" if ($file_type eq 'set_header'); return "Hardcopy Header" if ($file_type eq 'hardcopy_header'); - return "Course Information" if($file_type eq 'course_info'); + return "Course Information" if ($file_type eq 'course_info'); + return "Options Information" if ($file_type eq 'options_info'); return 'Problem ' . $r->{urlpath}->name; } @@ -473,8 +487,25 @@ } my $protected_file = not -w $inputFilePath; - my $header = CGI::i("Editing problem".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath"); - $header = ($self->isTempFilePath($inputFilePath) ) ? CGI::div({class=>'temporaryFile'},$header) : $header; # use colors if temporary file + +## +## DPVC +## my $header = CGI::i("Editing problem".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath"); + my $file_type = $self->{file_type}; + my %titles = ( + problem =>CGI::b("set $setName/problem $problemNumber"), + set_header => "header file", + hardcopy_header => "hardcopy header file", + course_info => "course information", + options_info => "options information", + '' => 'Unknown file type', + source_path_for_problem_file => " unassigned problem file: ".CGI::b("set $setName/problem $problemNumber"), + ); + my $header = CGI::i("Editing $titles{$file_type} in file '".$self->shortPath($inputFilePath)."'"); +## +## /DPVC +## + $header = ($self->isTempEditFilePath($inputFilePath) ) ? CGI::div({class=>'temporaryFile'},$header) : $header; # use colors if temporary file ######################################################################### # Format the page @@ -490,7 +521,7 @@ my $problemSeed = $self->{problemSeed}; my $uri = $r->uri; my $edit_level = $r->param('edit_level') || 0; - my $file_type = $self->{file_type}; +## my $file_type = $self->{file_type}; my $force_field = (defined($self->{sourceFilePath}) and $self->{sourceFilePath} ne "") ? CGI::hidden(-name=>'sourceFilePath', @@ -501,11 +532,28 @@ $allSetNames[$j] =~ s|^set||; $allSetNames[$j] =~ s|\.def||; } - my $target = "problem$edit_level"; # increasing edit_level gives you a new window with each edit. + my $target = 'WW_View'; #"problem$edit_level"; # increasing edit_level gives you a new window with each edit. + print CGI::script(<<EOF); + function setTarget(inWindow) { + document.getElementById("newWindow").checked = inWindow; + updateTarget(); + } + function updateTarget() { + var inWindow = document.getElementById("newWindow").checked; + document.getElementById("editor").target = (inWindow? "WW_View": ""); + } + function setRadio(i,nw) { + document.getElementById('action'+i).checked = true; + setTarget(nw); + } +EOF print CGI::p($header), - CGI::start_form({method=>"POST", name=>"editor", action=>"$uri", target=>$target, enctype=>"application/x-www-form-urlencoded"}), + +## CGI::start_form({method=>"POST", name=>"editor", action=>"$uri", target=>$target, enctype=>"application/x-www-form-urlencoded"}), + CGI::start_form({method=>"POST", id=>"editor", name=>"editor", action=>"$uri", enctype=>"application/x-www-form-urlencoded"}), + $self->hidden_authen_fields, $force_field, CGI::hidden(-name=>'file_type',-default=>$self->{file_type}), @@ -527,7 +575,8 @@ CGI::textarea( -name => 'problemContents', -default => $problemContents, -rows => $rows, -columns => $columns, -override => 1, - )," | ", +## )," | ", + ), ); @@ -544,11 +593,15 @@ # Check permissions #next if FORM_PERMS()->{$actionID} and not $authz->hasPermissions($user, FORM_PERMS()->{$actionID}); my $actionForm = "${actionID}_form"; - my $onChange = "document.userlist.action[$i].checked=true"; + my $newWindow = ($actionID =~ m/^(view|add_problem|save)$/)? 1: 0; ## DPVC + my $onChange = "setRadio($i,$newWindow)"; ## DPVC +## my $onChange = "document.userlist.action[$i].checked=true"; my %actionParams = $self->getActionParams($actionID); my $line_contents = $self->$actionForm($onChange, %actionParams); my $radio_params = {-type=>"radio", -name=>"action", -value=>$actionID}; $radio_params->{checked}=1 if ($actionID eq $default_choice) ; + $radio_params->{onclick} = "setTarget($newWindow)"; ## DPVC + $radio_params->{id} = "action$i"; ## DPVC print CGI::Tr({-valign=>"top"}, CGI::td({}, CGI::input($radio_params)), CGI::td({}, $line_contents) @@ -556,18 +609,44 @@ $i++; } - print CGI::Tr({}, CGI::td({-align=>"right"}, "Select above then:"), - CGI::td({-align=>"left"}, CGI::submit(-name=>'submit', -value=>"Take Action!")), +# print CGI::Tr({}, CGI::td({-align=>"right"}, "Select above then:"), +# CGI::td({-align=>"left"}, CGI::submit(-name=>'submit', -value=>"Take Action!")), + ## + ## DPVC + ## + my $checkbox = CGI::input({-type=>"checkbox", -id=>"newWindow", -checked=>"checked", + -onchange=>"updateTarget()"}); + $checkbox =~ s/\n//; # remove unwanted linebreak + print CGI::Tr({}, CGI::td({-colspan=>2}, "Select above then:", + CGI::submit(-name=>'submit', -value=>"Take Action!"), + CGI::script("document.write('$checkbox in another window')")) + ## + ## /DPVC + ## ); print CGI::end_table(); print CGI::end_form(); + + print CGI::script("updateTarget()"); return ""; } +# +# Convert long paths to [TMPL], etc. +# +sub shortPath { + my $self = shift; my $file = shift; + my $tmpl = $self->r->ce->{courseDirs}{templates}; + my $root = $self->r->ce->{courseDirs}{root}; + my $ww = $self->r->ce->{webworkDirs}{root}; + $file =~ s|^$tmpl|[TMPL]|; $file =~ s|^$root|[COURSE]|; $file =~ s|^$ww|[WW]|; + return $file; +} + ################################################################################ # Utilities ################################################################################ @@ -578,15 +657,16 @@ sub determineLocalFilePath { my $self= shift; die "determineLocalFilePath is a method" unless ref($self); my $path = shift; -# my $default_screen_header_path = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; -# my $default_hardcopy_header_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; - my $setID = $self->{setID} || int(rand(1000)); + my $default_screen_header_path = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; + my $default_hardcopy_header_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; + my $setID = $self->{setID}; + $setID = int(rand(1000)) unless $setID =~/\S/; # setID can be 0 if ($path =~ /Library/) { $path =~ s|^.*?Library/||; # truncate the url up to a segment such as ...rochesterLibrary/....... -# } elsif ($path eq $default_screen_header_path) { -# $path = "set$setID/setHeader.pg"; -# } elsif ($path eq $default_hardcopy_header_path) { -# $path = "set$setID/hardcopyHeader.tex"; + } elsif ($path eq $default_screen_header_path) { + $path = "set$setID/setHeader.pg"; + } elsif ($path eq $default_hardcopy_header_path) { + $path = "set$setID/hardcopyHeader.tex"; } else { # if its not in a library we'll just save it locally $path = "new_problem_".int(rand(1000)).".pg"; #l hope there aren't any collisions. } @@ -594,9 +674,10 @@ } -sub determineTempFilePath { # this does not create the path to the file - my $self = shift; die "determineTempFilePath is a method" unless ref($self); - my $path =shift; +sub determineTempEditFilePath { # this does not create the directories in the path to the file + # it returns an absolute path to the file + my $self = shift; die "determineTempEditFilePath is a method" unless ref($self); + my $path =shift; # this should be an absolute path to the file my $user = $self->r->param("user"); $user = int(rand(1000)) unless defined $user; my $setID = $self->{setID} || int(rand(1000)); @@ -604,32 +685,81 @@ ############### # Calculate the location of the temporary file ############### - my $templatesDirectory = $courseDirectory->{templates}; + my $templatesDirectory = $courseDirectory->{templates}; my $blank_file_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{blankProblem}; my $default_screen_header_path = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; my $default_hardcopy_header_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; - my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit"; - if ($path =~ /^$templatesDirectory/ ) { - $path =~ s|^$templatesDirectory||; - $path =~ s|^/||; # remove the initial slash if any - $path = "$tmpEditFileDirectory/$path.$user.tmp"; - } elsif ($path eq $blank_file_path) { - $path = "$tmpEditFileDirectory/blank.$setID.$user.tmp"; # handle the case of the blank problem - } elsif ($path eq $default_screen_header_path) { - $path = "$tmpEditFileDirectory/screenHeader.$setID.$user.tmp"; # handle the case of the screen header in snippets - } elsif ($path eq $default_hardcopy_header_path) { - $path = "$tmpEditFileDirectory/hardcopyHeader.$setID.$user.tmp"; # handle the case of the hardcopy header in snippets + my $tmpEditFileDirectory = $self->getTempEditFileDirectory(); + $self->addbadmessage("The path to the original file should be absolute") unless $path =~m|^/|; # debug + if ($path =~/^$tmpEditFileDirectory/) { + $self->addbadmessage("Error: This path is already in the temporary edit directory -- no new temporary file is created. path = $path"); + } else { - die "determineTempFilePath should only be used on paths within the templates directory, not on $path"; + if ($path =~ /^$templatesDirectory/ ) { + $path =~ s|^$templatesDirectory||; + $path =~ s|^/||; # remove the initial slash if any + $path = "$tmpEditFileDirectory/$path.$user.tmp"; + } elsif ($path eq $blank_file_path) { + $path = "$tmpEditFileDirectory/blank.$setID.$user.tmp"; # handle the case of the blank problem + } elsif ($path eq $default_screen_header_path) { + $path = "$tmpEditFileDirectory/screenHeader.$setID.$user.tmp"; # handle the case of the screen header in snippets + } elsif ($path eq $default_hardcopy_header_path) { + $path = "$tmpEditFileDirectory/hardcopyHeader.$setID.$user.tmp"; # handle the case of the hardcopy header in snippets + } else { + die "determineTempEditFilePath should only be used on paths within the templates directory, not on $path"; + } } $path; } -sub isTempFilePath { +sub determineOriginalEditFilePath { # determine the original path to a file corresponding to a temporary edit file + # returns path relative to the template directory my $self = shift; my $path = shift; - my $courseDirectory = $self->r->ce->{courseDirs}; - my $templatesDirectory = $courseDirectory->{templates}; - my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit"; + my $user = $self->r->param("user"); + $self->addbadmessage("Can't determine user of temporary edit file $path.") unless defined($user); + my $templatesDirectory = $self->r->ce->{courseDirs} ->{templates}; + my $tmpEditFileDirectory = $self->getTempEditFileDirectory(); + # unless path is absolute assume that it is relative to the template directory + my $newpath = $path; + unless ($path =~ m|^/| ) { + $newpath = "$templatesDirectory/$path"; + } + if ($self->isTempEditFilePath($newpath) ) { + $newpath =~ s|^$tmpEditFileDirectory/||; # delete temp edit directory + if ($newpath =~m|blank\.[^/]*$|) { # handle the case of the blank problem + $newpath = $self->r->ce->{webworkFiles}->{screenSnippets}->{blankProblem}; + } elsif (($newpath =~m|hardcopyHeader\.[^/]*$|)) { # handle the case of the hardcopy header in snippets + $newpath = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; + } elsif (($newpath =~m|screenHeader\.[^/]*$|)) { # handle the case of the screen header in snippets + $newpath = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; + } else { + $newpath =~ s|\.$user\.tmp$||; # delete suffix + + } + #$self->addgoodmessage("Original file path is $newpath"); #FIXME debug + } else { + $self->addbadmessage("This path |$newpath| is not the path to a temporary edit file."); + # returns original path + } + $newpath; +} + +sub getTempEditFileDirectory { + my $self = shift; + my $courseDirectory = $self->r->ce->{courseDirs}; + my $templatesDirectory = $courseDirectory->{templates}; + my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit"; + $tmpEditFileDirectory; +} +sub isTempEditFilePath { + my $self = shift; + my $path = shift; + my $templatesDirectory = $self->r->ce->{courseDirs} ->{templates}; + # unless path is absolute assume that it is relative to the template directory + unless ($path =~ m|^/| ) { + $path = "$templatesDirectory/$path"; + } + my $tmpEditFileDirectory = $self->getTempEditFileDirectory(); ($path =~/^$tmpEditFileDirectory/) ? 1: 0; } sub getFilePaths { @@ -645,7 +775,7 @@ $setName = '' unless defined $setName; $problemNumber = '' unless defined $problemNumber; die 'Internal error to PGProblemEditor -- file type is not defined' unless defined $file_type; - + #$self->addgoodmessage("file type is $file_type"); #FIXME remove ########################################################## # Determine path to the input file to be edited. # The permanent path of the input file == $editFilePath @@ -682,9 +812,17 @@ last CASE; }; + ($file_type eq 'options_info') and do { + # we are editing the options_info file + # value of courseFiles::options_info is relative to templates directory + $editFilePath .= '/' . $ce->{courseFiles}->{options_info}; + last CASE; + }; + ($file_type eq 'blank_problem') and do { $editFilePath = $ce->{webworkFiles}->{screenSnippets}->{blankProblem}; - $self->addbadmessage("$editFilePath is blank problem template file and can not be edited directly. " +## $self->addbadmessage("$editFilePath is blank problem template file and can not be edited directly. " + $self->addbadmessage("'".$self->shortPath($editFilePath)."' is blank problem template file and can not be edited directly. " ."First use 'Save as' to make a local copy, then add the file to the current problem set, then edit the file." ); last CASE; @@ -701,20 +839,22 @@ my $header_file = ""; $header_file = $set_record->{$file_type}; if ($header_file && $header_file ne "") { - $editFilePath .= '/' . $header_file; + if ( $header_file =~ m|^/| ) { # if absolute address + $editFilePath = $header_file; + } else { + $editFilePath .= '/' . $header_file; + } } else { - # if the set record doesn't specify the filename + # if the set record doesn't specify the filename for a header # then the set uses the default from snippets - # so we'll load that file, but change where it will be saved - # to and grey out the "Save" button - # FIXME why does the make_local_copy variable need to be checked? - # Isn't it automatic that a local copy has to be made? - #if ($r->param('make_local_copy')) { + $editFilePath = $ce->{webworkFiles}->{screenSnippets}->{setHeader} if $file_type eq 'set_header'; $editFilePath = $ce->{webworkFiles}->{hardcopySnippets}->{setHeader} if $file_type eq 'hardcopy_header'; - $self->addbadmessage("$editFilePath is the default header file and cannot be edited directly."); - $self->addbadmessage("Any changes you make will have to be saved as another file."); + +## $self->addbadmessage("$editFilePath is the default header file and cannot be edited directly."); +# $self->addbadmessage("'".$self->shortPath($editFilePath)."' is the default header file and cannot be edited directly.".CGI::br()."Any changes you make will have to be saved as another file."); #} + } last CASE; }; #end 'set_header, hardcopy_header' case @@ -736,7 +876,13 @@ ($file_type eq 'source_path_for_problem_file') and do { my $forcedSourceFile = $self->{sourceFilePath}; - # bail if no source path for the problem is found ; + # if the source file is in the temporary edit directory find the original source file + # the source file is relative to the templates directory. + if ($self->isTempEditFilePath($forcedSourceFile) ) { + $forcedSourceFile = $self->determineOriginalEditFilePath($forcedSourceFile); # original file path + $self->addgoodmessage("the original path to the file is $forcedSourceFile"); #FIXME debug + } + # bail if no source path for the problem is found ; die "Cannot find a file path to save to" unless( defined($forcedSourceFile) and ($forcedSourceFile =~ /\S/) ); $self->{problemSeed} = 1234; $editFilePath .= '/' . $forcedSourceFile; @@ -750,13 +896,15 @@ # which is almost undoubtedly NOT desirable if (-d $editFilePath) { - my $msg = "The file $editFilePath is a directory!"; +## my $msg = "The file $editFilePath is a directory!"; + my $msg = "The file '".$self->shortPath($editFilePath)."' is a directory!"; $self->{failure} = 1; $self->addbadmessage($msg); } if (-e $editFilePath and not -r $editFilePath) { #it's ok if the file doesn't exist, perhaps we're going to create it # with save as - my $msg = "The file $editFilePath cannot be read!"; +## my $msg = "The file $editFilePath cannot be read!"; + my $msg = "The file '".$self->shortPath($editFilePath)."' cannot be read!"; $self->{failure} = 1; $self->addbadmessage($msg); } @@ -765,16 +913,16 @@ # Whew!!! ################################################# - my $tempFilePath = $self->determineTempFilePath($editFilePath); #"$editFilePath.$TEMPFILESUFFIX"; + my $tempFilePath = $self->determineTempEditFilePath($editFilePath); #"$editFilePath.$TEMPFILESUFFIX"; $self->{editFilePath} = $editFilePath; $self->{tempFilePath} = $tempFilePath; $self->{inputFilePath} = (-r $tempFilePath) ? $tempFilePath : $editFilePath; #warn "editfile path is $editFilePath and tempFile is $tempFilePath and inputFilePath is ". $self->{inputFilePath}; } -sub new_saveFileChanges { +sub saveFileChanges { ################################################################################ -# new_saveFileChanges does most of the work. it is a separate method so that it can +# saveFileChanges does most of the work. it is a separate method so that it can # be called from either pre_header_initialize() or initilize(), depending on # whether a redirect is needed or not. # @@ -856,11 +1004,14 @@ if ( not -w $ce->{courseDirs}->{templates} ) { $errorMessage = "Write permissions have not been enabled in the templates directory. No changes can be made."; } elsif ( not -w $currentDirectory ) { - $errorMessage = "Write permissions have not been enabled in $currentDirectory. Changes must be saved to a different directory for viewing."; +## $errorMessage = "Write permissions have not been enabled in $currentDirectory. Changes must be saved to a different directory for viewing."; + $errorMessage = "Write permissions have not been enabled in '".$self->shortPath($currentDirectory)."'. Changes must be saved to a different directory for viewing."; } elsif ( -e $outputFilePath and not -w $outputFilePath ) { - $errorMessage = "Write permissions have not been enabled for $outputFilePath. Changes must be saved to another file for viewing."; +## $errorMessage = "Write permissions have not been enabled for $outputFilePath. Changes must be saved to another file for viewing."; + $errorMessage = "Write permissions have not been enabled for '".$self->shortPath($outputFilePath)."'. Changes must be saved to another file for viewing."; } else { - $errorMessage = "Unable to write to $outputFilePath: $writeFileErrors"; +## $errorMessage = "Unable to write to $outputFilePath: $writeFileErrors"; + $errorMessage = "Unable to write to '".$self->shortPath($outputFilePath)."': $writeFileErrors"; } $self->{failure} = 1; @@ -872,18 +1023,24 @@ ########################################################### unless( $writeFileErrors or $do_not_save) { # everything worked! unlink and announce success! # unlink the temporary file if there are no errors and the save button has been pushed - if ($action eq 'save' or $action eq 'save_as' or $action eq 'revert') { + if (($action eq 'save' or $action eq 'save_as') and (-w $self->{tempFilePath}) ) { + + $self->addgoodmessage("Deleting temp file at " . $self->shortPath($self->{tempFilePath})); unlink($self->{tempFilePath}) ; } - if ( defined($outputFilePath) and ! $self->{failure} ) { - my $msg = "Saved to file: |$outputFilePath|"; + + if ( defined($outputFilePath) and ! $self->{failure} and not $self->isTempEditFilePath($outputFilePath) ) { + # don't announce saving of temporary editing files + my $msg = "Saved to file '".$self->shortPath($outputFilePath)."'."; + $self->addgoodmessage($msg); + #$self->{inputFilePath} = $outputFilePath; ## DPVC -- avoid file-not-found message } } -} # end new_saveFileChanges +} # end saveFileChanges @@ -919,14 +1076,16 @@ sub view_form { my ($self, $onChange, %actionParams) = @_; my $output_string = "View"; - unless ($self->{file_type} eq 'course_info') { + unless ($self->{file_type} eq 'course_info' || $self->{file_type} eq 'options_info') { $output_string .= join(" ", - " problem using seed ", - CGI::textfield(-name=>'action.view.seed',-value=>$self->{problemSeed}), +## " problem using seed ", + " using seed ", + CGI::textfield(-name=>'action.view.seed',-value=>$self->{problemSeed},-onfocus=>$onChange), "and display mode ", CGI::popup_menu(-name=>'action.view.displayMode', -values=>$self->r->ce->{pg}->{displayModes}, - -default=>$self->{displayMode} - ), ".", + -default=>$self->{displayMode}, -onmousedown=>$onChange +## ), ".", + ) ); } @@ -956,7 +1115,7 @@ my $do_not_save = 0; my $file_type = $self->{file_type}; - $self->new_saveFileChanges($tempFilePath,); + $self->saveFileChanges($tempFilePath,); ######################################################## # construct redirect URL and redirect @@ -988,6 +1147,7 @@ $viewURL = $self->systemLink($problemPage, params => { + set_header => $tempFilePath, displayMode => $displayMode, problemSeed => $problemSeed, editMode => "temporaryFile", @@ -998,12 +1158,24 @@ ); - } elsif ($file_type eq 'course_info') { # redirecto to ProblemSets.pm + } elsif ($file_type eq 'course_info') { # redirec to ProblemSets.pm my $problemSetsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets", courseID => $courseName); $viewURL = $self->systemLink($problemSetsPage, params => { - editMode => ("temporaryFile"), + course_info => $tempFilePath, + editMode => "temporaryFile", + edit_level => $edit_level, + status_message => uri_escape($self->{status_message}) + } + ); + } elsif ($file_type eq 'options_info') { # redirec to Options.pm + my $optionsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Options", + courseID => $courseName); + $viewURL = $self->systemLink($optionsPage, + params => { + options_info => $tempFilePath, + editMode => "temporaryFile", edit_level => $edit_level, status_message => uri_escape($self->{status_message}) } @@ -1024,18 +1196,25 @@ $setName = defined($setName) ? $setName : ''; # we need this instead of using the || construction # to keep set 0 from being set to the # empty string. + my $filePath = $self->{inputFilePath}; $setName =~ s|^set||; my @allSetNames = sort $r->db->listGlobalSets; for (my $j=0; $j<scalar(@allSetNames); $j++) { $allSetNames[$j] =~ s|^set||; $allSetNames[$j] =~ s|\.def||; } - return "" if $self->{file_type} eq 'course_info'; + my $labels = { + problem => 'problem', + set_header => 'set header', + hardcopy_header => 'hardcopy header', + }; + return "" if $self->{file_type} eq 'course_info' || $self->{file_type} eq 'options_info'; return join(" ", - "Add problem to set " , - CGI::popup_menu(-name=>'action.add_problem.target_set', -values=>\@allSetNames, -default=>$setName), +## "Add problem to set " , + "Add to set " , + CGI::popup_menu({name=>'action.add_problem.target_set', values=>\@allSetNames, default=>$setName, onmousedown=>$onChange}), " as ", - CGI::popup_menu(-name=>'action.add_problem.file_type', -values=>['problem','set_header'], -default=>'problem'), + CGI::popup_menu({name=>'action.add_problem.file_type', values=>['problem','set_header', 'hardcopy_header'], labels=>$labels, default=>$self->{file_type}, onmousedown=>$onChange}), ); #FIXME add -lables to the pop up menu return ""; @@ -1101,9 +1280,11 @@ my $setRecord = $self->r->db->getGlobalSet($targetSetName); $setRecord->set_header($sourceFilePath); if( $self->r->db->putGlobalSet($setRecord) ) { - $self->addgoodmessage("Added $sourceFilePath to ". $targetSetName. " as new set header ") ; +## $self->addgoodmessage("Added $sourceFilePath to ". $targetSetName. " as new set header ") ; + $self->addgoodmessage("Added '".$self->shortPath($sourceFilePath)."' to ". $targetSetName. " as new set header ") ; } else { - $self->addbadmessage("Unable to make $sourceFilePath the set header for $targetSetName"); +## $self->addbadmessage("Unable to make $sourceFilePath the set header for $targetSetName"); + $self->addbadmessage("Unable to make '".$self->shortPath($sourceFilePath)."' the set header for $targetSetName"); } $self->{file_type} = 'set_header'; # change file type to set_header if it not already so ################################################# @@ -1131,10 +1312,13 @@ sub save_form { my ($self, $onChange, %actionParams) = @_; my $r => $self->r; + #return "" unless defined($self->{tempFilePath}) and -e $self->{tempFilePath}; if ($self->{editFilePath} =~ /$BLANKPROBLEM$/ ) { return ""; #Can't save blank problems without changing names } elsif (-w $self->{editFilePath}) { - return "Save"; + + return "Save to: ".$self->shortPath($self->{editFilePath})." and View"; + } else { return ""; #"Can't save -- No write permission"; } @@ -1165,7 +1349,7 @@ my $do_not_save = 0; my $file_type = $self->{file_type}; - $self->new_saveFileChanges($outputFilePath); + $self->saveFileChanges($outputFilePath); ################################################# # Set up redirect to Problem.pm ################################################# @@ -1173,7 +1357,7 @@ ######################################################## # construct redirect URL and redirect ######################################################## - if ($file_type eq 'problem' ) { # redirect to Problem.pm + if ($file_type eq 'problem' || $file_type eq 'source_path_for_problem_file') { # redirect to Problem.pm my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Problem", courseID => $courseName, setID => $setName, problemID => $problemNumber ); @@ -1216,6 +1400,16 @@ status_message => uri_escape($self->{status_message}) } ); + } elsif ($file_type eq 'options_info') { # redirect to Options.pm + my $optionsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Options", + courseID => $courseName); + $viewURL = $self->systemLink($optionsPage, + params => { + editMode => ("savedFile"), + edit_level => 0, + status_message => uri_escape($self->{status_message}) + } + ); } elsif ($file_type eq 'source_path_for_problem_file') { # redirect to ProblemSets.pm my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", courseID => $courseName, setID => $setName, problemID => $problemNumber @@ -1240,22 +1434,96 @@ $self->reply_with_redirect($viewURL); } -sub save_as_form { - my ($self, $onChange, %actionParams) = @_; - my $sourceFilePath = $self->{editFilePath}; - my $templatesPath = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory - - return "Save ". - CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], - -default=>'rename',-labels=>{rename=>' as ',save_a_copy=>'a copy to'} - ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$sourceFilePath),; + +sub make_local_copy_form { + my ($self, $genericParams, $actionParams, $tableParams) = @_; + my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited + #warn "editFilePath $editFilePath inputFilePath",$self->{inputFilePath}; + return "" unless -e $editFilePath; + return "" if -w $editFilePath; + return "" unless $self->{file_type} eq 'problem' # need problem structure to make local copy in most cases + or $self->{file_type} eq 'set_header' # $editFilePath eq $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader} # special case to make copy of hardcopy header + or $self->{file_type} eq 'hardcopy_header'; # $editFilePath eq $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader} ; # special case to make copy of screen header + # or $self->{file_type} eq 'source_path_for_problem_file'; # need setID and problemID to make local copy -- can't be done in this case. + return join ("", + "Make local editable copy at: [TMPL]/".($self->determineLocalFilePath($editFilePath)), + CGI::hidden(-name=>'action.make_local_copy.target_file', -value=>$self->determineLocalFilePath($editFilePath) ), + CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$editFilePath ), + CGI::hidden(-name=>'action.make_local_copy.file_type',-value=>$self->{file_type}), + CGI::hidden(-name=>'action.make_local_copy.saveMode',-value=>'rename') + ); } + + + + + + + + + +sub make_local_copy_handler { + my ($self, $genericParams, $actionParams, $tableParams) = @_; + foreach my $key (qw(target_file file_type saveMode source_file)) { + $actionParams->{"action.save_as.$key"}->[0] = $actionParams->{"action.make_local_copy.$key"}->[0]; + #warn "action.make_local_copy.$key", @{$actionParams->{"action.make_local_copy.$key"}} + } + save_as_handler($self, $genericParams, $actionParams, $tableParams); + + +} +sub save_as_form { # calls the save_as_handler + my ($self, $onChange, %actionParams) = @_; + my $editFilePath = $self->{editFilePath}; + return "" unless -w $editFilePath; + + my $shortFilePath = $editFilePath; + my $templatesDir = $self->r->ce->{courseDirs}->{templates}; + my $setID = $self->{setID}; + $shortFilePath =~ s|^$templatesDir/||; + $shortFilePath = '' if $shortFilePath =~ m|^/|; # if it is still an absolute path don't suggest that you save to it. + my $allowedActions = (defined($setID) && $setID =~/\S/ && $setID ne 'Undefined_Set') ? ['save_a_copy','rename' ] : ['save_a_copy']; +# return CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], +# -default=>'rename',-labels=>{rename=>'Rename file path to ',save_a_copy=>'Create a copy of file at '} +# ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath),; + +## +## DPVC +## + +# return "Save ". +# CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], +# -default=>'rename',-labels=>{rename=>' as ',save_a_copy=>'a copy to'} +# ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath),; + + return CGI::popup_menu( + -name=>'action.save_as.saveMode', -values=>$allowedActions, + -default=>'rename',-labels=>{save_a_copy=>'Create a copy of file at ', rename=>'Rename file path to'}, + -onmousedown=>$onChange + ). ": [TMPL]/". + CGI::textfield( + -name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath, + -onfocus=>$onChange + ). + CGI::hidden(-name=>'action.save_as.source_file', -value=>$editFilePath ). + CGI::hidden(-name=>'action.save_as.file_type',-value=>$self->{file_type}), + ; +# if $self->{setID} && $self->{setID} ne '' && $self->{setID} ne 'Undefined_Set'; +# FIXME -- this should eventually work for undefined sets as well. +# return CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['save_a_copy'], +# -default=>'save_a_copy',-labels=>{save_a_copy=>'Save as'}, -onmousedown=>$onChange +# ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$shortFilePath) +## +## /DPVC +## +} + sub save_as_handler { my ($self, $genericParams, $actionParams, $tableParams) = @_; #$self->addgoodmessage("save_as_handler called"); + $self->{status_message} = ''; ## DPVC -- remove bogus old messages my $courseName = $self->{courseID}; my $setName = $self->{setID}; my $problemNumber = $self->{problemID}; @@ -1263,15 +1531,17 @@ my $problemSeed = $self->{problemSeed}; my $do_not_save = 0; - my $saveMode = $actionParams->{'action.save_as.saveMode'}->[0] || ''; - my $new_file_name = $actionParams->{'action.save_as.target_file'}->[0] || ''; + my $saveMode = $actionParams->{'action.save_as.saveMode'}->[0] || ''; + my $new_file_name = $actionParams->{'action.save_as.target_file'}->[0] || ''; + my $sourceFilePath = $actionParams->{'action.save_as.source_file'}->[0] || ''; + my $file_type = $actionParams->{'action.save_as.file_type'}->[0] || ''; + $new_file_name =~ s/^\s*//; #remove initial and final white space $new_file_name =~ s/\s*$//; if ( $new_file_name !~ /\S/) { # need a non-blank file name # setting $self->{failure} stops saving and any redirects $do_not_save = 1; $self->addbadmessage(CGI::p("Please specify a file to save to.")); - last ACTION_CASES; #stop processing } ################################################# @@ -1280,14 +1550,14 @@ ################################################# my $problemContents = fixProblemContents($self->r->param('problemContents')); $self->{r_problemContents} = \$problemContents; - + warn "problem contents is empty" unless $problemContents; ################################################# # Rescue the user in case they forgot to end the file name with .pg ################################################# - my $file_type = $self->{file_type}; - if($self->{file_type} eq 'problem' - or $self->{file_type} eq 'blank_problem' - or $self->{file_type} eq 'set_header') { + + if($file_type eq 'problem' + or $file_type eq 'blank_problem' + or $file_type eq 'set_header') { $new_file_name =~ s/\.pg$//; # remove it if it is there $new_file_name .= '.pg'; # put it there @@ -1300,7 +1570,10 @@ if (defined $outputFilePath and -e $outputFilePath) { # setting $do_not_save stops saving and any redirects $do_not_save = 1; - $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); +## $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); + $self->addbadmessage(CGI::p("File '".$self->shortPath($outputFilePath)."' exists. + File not saved. No changes have been made. + You can change the file path for this problem manually from the 'Hmwk Sets Editor' page")); } else { $self->{editFilePath} = $outputFilePath; $self->{tempFilePath} = ''; # nothing needs to be unlinked. @@ -1309,24 +1582,52 @@ unless ($do_not_save ) { - $self->new_saveFileChanges($outputFilePath, \$problemContents); - my $sourceFilePath = $outputFilePath; - my $templatesPath = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory - - if ($saveMode eq 'rename') { #save to new file - my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); - $problemRecord->source_file($new_file_name); - if ( $self->r->db->putGlobalProblem($problemRecord) ) { - $self->addgoodmessage("The current source file for problem $problemNumber has been renamed to [TMPL]/$sourceFilePath.") ; + $self->saveFileChanges($outputFilePath); +## my $templatesPath = $self->r->ce->{courseDirs}->{templates}; +## $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory + + if ($saveMode eq 'rename' and -r $outputFilePath) { + ################################################# + # Modify source file in problem + ################################################# + if ($file_type eq 'set_header' ) { + my $setRecord = $self->r->db->getGlobalSet($setName); + $setRecord->set_header($new_file_name); + if ($self->r->db->putGlobalSet($setRecord)) { + $self->addgoodmessage("The set header for set $setName has been renamed to '".$self->shortPath($outputFilePath)."'.") ; + } else { + $self->addbadmessage("Unable to change the set header for set $setName. Unknown error."); + } + } elsif ($file_type eq 'hardcopy_header' ) { + my $setRecord = $self->r->db->getGlobalSet($setName); + $setRecord->hardcopy_header($new_file_name); + if ($self->r->db->putGlobalSet($setRecord)) { + $self->addgoodmessage("The hardcopy header for set $setName has been renamed to '".$self->shortPath($outputFilePath)."'.") ; + } else { + $self->addbadmessage("Unable to change the hardcopy header for set $setName. Unknown error."); + } } else { - $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); + my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); + $problemRecord->source_file($new_file_name); + if ( $self->r->db->putGlobalProblem($problemRecord) ) { + $self->addgoodmessage("The source file for 'set $setName / problem $problemNumber' has been changed from ". + $self->shortPath($sourceFilePath)." to '".$self->shortPath($outputFilePath)."'.") ; + } else { + $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); + } } } elsif ($saveMode eq 'save_a_copy') { - $self->addgoodmessage("A new local, editable, copy of this problem has been created at [TMPL]/$sourceFilePath.") ; + ################################################# + # Don't modify source file in problem -- just report + ################################################# + + #$self->{status_message} = ''; ## DPVC remove old messages + $self->addgoodmessage("A new file has been created at '".$self->shortPath($outputFilePath). + "' with the contents below. No changes have been made to set $setName."); } else { $self->addbadmessage("Don't recognize saveMode: |$saveMode|. Unknown error."); } + } my $edit_level = $self->r->param("edit_level") || 0; $edit_level++; @@ -1336,23 +1637,27 @@ # The redirect gives the server time to detect that the new file exists. ################################################# my $problemPage; + my $new_file_type; if ($saveMode eq 'save_a_copy' ) { $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", courseID => $courseName, setID => 'Undefined_Set', problemID => 'Undefined_Set' ); + $new_file_type = 'source_path_for_problem_file'; } elsif ($saveMode eq 'rename') { $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", courseID => $courseName, setID => $setName, problemID => $problemNumber ); - + $new_file_type = $file_type; } else { $self->addbadmessage("Don't recognize saveMode: |$saveMode|. Unknown error."); + die "Don't recognize saveMode: |$saveMode|. Unknown error." } + warn "save mode is $saveMode"; my $viewURL = $self->systemLink($problemPage, params=>{ sourceFilePath => $outputFilePath, #The path relative to the templates directory is required. edit_level => $edit_level, - file_type => 'source_path_for_problem_file', + file_type => $new_file_type, status_message => uri_escape($self->{status_message}) } @@ -1363,151 +1668,146 @@ } sub revert_form { my ($self, $onChange, %actionParams) = @_; - return "Revert" ; + my $editFilePath = $self->{editFilePath}; + return "Error: The original file $editFilePath cannot be read." unless -r $editFilePath; + return "" unless defined($self->{tempFilePath}) and -e $self->{tempFilePath} ; + return "Revert to ".$self->shortPath($editFilePath) ; } sub revert_handler { my ($self, $genericParams, $actionParams, $tableParams) = @_; - #$self->addgoodmessage("revert_handler called"); - - my $courseName = $self->{courseID}; - my $setName = $self->{setID}; - my $problemNumber = $self->{problemID}; - my $displayMode = $self->{displayMode}; - my $problemSeed = $self->{problemSeed}; - ################################################# - # Reset the problem paths - ################################################# - + #$self->addgoodmessage("revert_handler called"); my $editFilePath = $self->{editFilePath}; $self->{inputFilePath} = $editFilePath; - $self->{tempFilePath} = ''; # unlink the temp files; unlink($self->{tempFilePath}); + $self->addgoodmessage("Deleting temp file at " . $self->shortPath($self->{tempFilePath})); + $self->{tempFilePath} = ''; my $problemContents =''; $self->{r_problemContents} = \$problemContents; - $self->addgoodmessage("Reverting to original file $editFilePath"); + $self->addgoodmessage("Reverting to original file '".$self->shortPath($editFilePath)."'"); # no redirect is needed } -sub make_local_copy_form { - my ($self, $genericParams, $actionParams, $tableParams) = @_; - my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited - return "" unless -e $editFilePath; - return "" if -w $editFilePath; - return "" unless $self->{file_type} eq 'problem'; - # or $self->{file_type} eq 'set_header' ; # need problem structure to make local copy -- not available for header - # or $self->{file_type} eq 'source_path_for_problem_file'; # need setID and problemID to make local copy - return join ("", - "Make local copy at: [TMPL]/".($self->determineLocalFilePath($editFilePath)), - CGI::hidden(-name=>'action.make_local_copy.target_file', -value=>$self->determineLocalFilePath($editFilePath) ), - CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$editFilePath ), - ); - -} -sub make_local_copy_handler { - my ($self, $genericParams, $actionParams, $tableParams) = @_; - #$self->addgoodmessage("make_local_copy_handler called"); - my $courseName = $self->{courseID}; - my $setName = $self->{setID}; - my $problemNumber = $self->{problemID}; - - my $displayMode = $self->{displayMode}; - my $problemSeed = $self->{problemSeed}; - - my $do_not_save = 0; #error flag - ################################################# - # Save the file locally - ################################################# - my $new_file_name = $actionParams->{'action.make_local_copy.target_file'}->[0] || ''; - my $sourceFilePath = $actionParams->{'action.make_local_copy.source_file'}->[0] || ''; - my $templatesPath = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory - - if ( $new_file_name !~ /\S/) { # need a non-blank file name - # setting $self->{failure} stops saving and any redirects - $do_not_save = 1; - warn "new file name is $new_file_name"; - $self->addbadmessage(CGI::p("Please specify a file to save to.")); - } - - ################################################# - # grab the problemContents from the form in order to save it to a new permanent file - # later we will unlink (delete) the current temporary file - ################################################# - - my $problemContents = fixProblemContents($self->r->param('problemContents')); - $self->{r_problemContents} = \$problemContents; - warn "problem contents is empty" unless $problemContents; - ################################################# - # Construct the output file path - ################################################# - my $outputFilePath = $self->r->ce->{courseDirs}->{templates} . '/' . - $new_file_name; - if (defined $outputFilePath and -e $outputFilePath) { - # setting $do_not_save stops saving and any redirects - $do_not_save = 1; - $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); - } else { - #$self->addgoodmessage("Saving to file $outputFilePath."); - } - my $file_type = $self->{file_type}; - unless ($do_not_save ) { - $self->new_saveFileChanges($outputFilePath); - } - ################################################# - # Modify source file in problem - ################################################# - if (-r $outputFilePath and !$do_not_save) { - my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); - $problemRecord->source_file($new_file_name); - if ( $self->r->db->putGlobalProblem($problemRecord) ) { - $self->addgoodmessage("A local, editable, copy of [TMPL]/$sourceFilePath has been made for problem $problemNumber.") ; - } else { - $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); - } - } - my $edit_level = $self->r->param("edit_level") || 0; - $edit_level++; - ################################################# - # Set up redirect - ################################################# - - my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", - courseID => $courseName, setID => $setName, problemID => $problemNumber - ); - my $viewURL = $self->systemLink($problemPage, - params=>{ - sourceFilePath => $sourceFilePath, - edit_level => $edit_level, - file_type => 'problem', - status_message => uri_escape($self->{status_message}) - - } - ); - $self->reply_with_redirect($viewURL); -} - -sub rename_form { - my ($self, $onChange, %actionParams) = @_; - my $problemPath = $self->{editFilePath}; - my $templatesDir = $self->r->ce->{courseDirs}->{templates}; - #warn "problemPath $problemPath $templatesDir"; - $problemPath =~ s|^$templatesDir/||; - return join("", - "Rename problem file to : [TMPL]/".CGI::textfield(-name=>'action.rename.target_file', -size=>40, -value=>$problemPath), - CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$self->{editFilePath} ), - ); - - -} +# sub make_local_copy_handler { +# my ($self, $genericParams, $actionParams, $tableParams) = @_; +# #$self->addgoodmessage("make_local_copy_handler called"); +# +# my $courseName = $self->{courseID}; +# my $setName = $self->{setID}; +# my $problemNumber = $self->{problemID}; +# +# my $displayMode = $self->{displayMode}; +# my $problemSeed = $self->{problemSeed}; +# my $do_not_save = 0; #error flag +# +# my $new_file_name = $actionParams->{'action.make_local_copy.target_file'}->[0] || ''; +# my $sourceFilePath = $actionParams->{'action.make_local_copy.source_file'}->[0] || ''; +# my $file_type = $actionParams->{'action.make_local_copy.file_type'}->[0] ||''; +# +# my $templatesPath = $self->r->ce->{courseDirs}->{templates}; +# $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory +# +# if ( $new_file_name !~ /\S/) { # need a non-blank file name +# # setting $self->{failure} stops saving and any redirects +# $do_not_save = 1; +# #warn "new file name is $new_file_name"; +# $self->addbadmessage(CGI::p("Error: File to save to not specified.")); +# } +# +# ################################################# +# # grab the problemContents from the form in order to save it to a new permanent file +# # later we will unlink (delete) the current temporary file +# ################################################# +# +# my $problemContents = fixProblemContents($self->r->param('problemContents')); +# $self->{r_problemContents} = \$problemContents; +# warn "problem contents is empty" unless $problemContents; +# ################################################# +# # Construct the output file path +# ################################################# +# my $outputFilePath = $self->r->ce->{courseDirs}->{templates} . '/' . +# $new_file_name; +# if (defined $outputFilePath and -e $outputFilePath) { +# # setting $do_not_save stops saving and any redirects +# $do_not_save = 1; +# ## $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved.")); +# $self->addbadmessage(CGI::p("File '".$self->shortPath($outputFilePath)."' exists. +# File not saved. No changes have been made. +# You can change the file path for this problem manually from the 'Hmwk Sets Editor' page")); +# } else { +# ## #$self->addgoodmessage("Saving to file $outputFilePath."); +# #$self->addgoodmessage("Saving to file '".$self->shortPath($outputFilePath)."'."); +# } +# +# unless ($do_not_save ) { +# $self->saveFileChanges($outputFilePath); +# ################################################# +# # Modify source file in problem +# ################################################# +# if ($file_type eq 'set_header') { +# my $setRecord = $self->r->db->getGlobalSet($setName); +# $setRecord->set_header($new_file_name); +# if ($self->r->db->putGlobalSet($setRecord)) { +# $self->addgoodmessage("The set header for set $setName has been renamed to '".$self->shortPath($outputFilePath)."'.") ; +# } else { +# $self->addbadmessage("Unable to change the header for set $setName. Unknown error."); +# } +# } else { +# my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); +# $problemRecord->source_file($new_file_name); +# if ( $self->r->db->putGlobalProblem($problemRecord) ) { +# ## $self->addgoodmessage("The current source file for set $setName problem $problemNumber has been renamed to [TMPL]/$outputFilePath.") ; +# $self->addgoodmessage("The current source file for problem $problemNumber has been renamed to '".$self->shortPath($outputFilePath)."'.") ; +# } else { +# $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); +# } +# } +# +# } +# my $edit_level = $self->r->param("edit_level") || 0; +# $edit_level++; +# ################################################# +# # Set up redirect +# ################################################# +# +# my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor", +# courseID => $courseName, setID => $setName, problemID => $problemNumber +# ); +# my $viewURL = $self->systemLink($problemPage, +# params=>{ +# sourceFilePath => $new_file_name, +# edit_level => $edit_level, +# file_type => $self->{file_type}, +# status_message => uri_escape($self->{status_message}) +# +# } +# ); +# $self->reply_with_redirect($viewURL); +# } + +# sub rename_form { # see the save_as form +# # my ($self, $onChange, %actionParams) = @_; +# # my $problemPath = $self->{editFilePath}; +# # my $templatesDir = $self->r->ce->{courseDirs}->{templates}; +# # #warn "problemPath $problemPath $templatesDir"; +# # $problemPath =~ s|^$templatesDir/||; +# # $problemPath = '' if $problemPath =~ m|^/|; # if it is still an absolute path don't suggest that you save to it. +# # $self->addbadmessage("problem Path is $problemPath"); +# # return join("", +# # "Rename problem file to : [TMPL]/".CGI::textfield(-name=>'action.rename.target_file', -size=>40, -value=>$problemPath), +# # CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$self->{editFilePath} ), +# # ); +# +# +# } -sub rename_handler { - my ($self, $genericParams, $actionParams, $tableParams) = @_; - $actionParams->{'action.make_local_copy.target_file'}->[0] = $actionParams->{'action.rename.target_file'}->[0]; - make_local_copy_handler($self, $genericParams, $actionParams, $tableParams); -} +# sub rename_handler { +# my ($self, $genericParams, $actionParams, $tableParams) = @_; +# $actionParams->{'action.make_local_copy.target_file'}->[0] = $actionParams->{'action.rename.target_file'}->[0]; +# make_local_copy_handler($self, $genericParams, $actionParams, $tableParams); +# } 1; |
From: Mike G. v. a. <we...@ma...> - 2006-01-08 01:20:28
|
Log Message: ----------- Updated to conform to changes in PGProblemSetEditor.pm Tags: ---- rel-2-2-dev Modified Files: -------------- webwork-modperl/htdocs/helpFiles: InstructorPGProblemEditor.html Revision Data ------------- Index: InstructorPGProblemEditor.html =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/helpFiles/InstructorPGProblemEditor.html,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -Lhtdocs/helpFiles/InstructorPGProblemEditor.html -Lhtdocs/helpFiles/InstructorPGProblemEditor.html -u -r1.1.2.1 -r1.1.2.2 --- htdocs/helpFiles/InstructorPGProblemEditor.html +++ htdocs/helpFiles/InstructorPGProblemEditor.html @@ -33,7 +33,10 @@ as well as set headers and other files. </p> -<h4>Features:</h4> +<p> +<strong>Warning:</strong> New windows or refreshed windows may not always be brought to the front. This depends +on your browser. +</p> <dl> @@ -46,24 +49,26 @@ <h4>Action items:</h4> <i>(If an action cannot be executed it will not appear as an action item.) </i> </dl> - <dt> View problem</dt> + <dt> View ...</dt> <dd> Will bring up a window to show the results of your editing. It does not change the permanent file on the disk.</dd> - <dt> Add problem to set</dt> + <dt> Add to set ...</dt> <dd> Add this problem as the last problem in an existing set, either as a problem or as the set header (the text that appears on the home page of a homework set). You can rearrange the order of the problems later using the "Hmwk Sets Editor"</dd> <dt> Save to...</dt> <dd> Saves the changes to the file indicated.</dd> - <dt> Make local copy </dt> - <dd> Will make a local copy of an uneditable library problem so that you can edit it. It also changes the file path for the current problem to the new local copy. (It is much like "rename" but actually suggests the file name for you so that you can remember where the problem came from.</dd> - <dt> Rename ... </dt> - <dd> Saves the changes to a new file and changes the file path for the current problem to this new file</dd> + <dt> Make local editable copy ... </dt> + <dd> Will make a local copy of changes you have made to an uneditable library problem so that you can edit it. It also changes the file path for the current problem to the new local copy. (It is much like "rename" but actually suggests the file name for you so that you can remember where the problem came from.</dd> + <dt> Rename file path to ... </dt> + <dd> Saves the text to a new file and changes the file path for the current problem to this new file</dd> <dt> Create a copy ... </dt> <dd> Saves the changes to a new file but does not change the file path for the current problem</dd> - <dt> Revert</dt> + <dt> Revert to ...</dt> <dd> Reverts to the copy of the file saved on the disk -- all unsaved editing changes will be lost.</dd> <dt> Take action</dt> - <dd> Executes the</dd> action item selected above + <dd> Executes the action item selected above.</dd> </dl> + + </blockquote> </body> </html> |
From: Mike G. v. a. <we...@ma...> - 2006-01-07 02:15:06
|
Log Message: ----------- Adding help for PG Problem Editor Tags: ---- rel-2-2-dev Added Files: ----------- webwork-modperl/htdocs/helpFiles: InstructorPGProblemEditor.html Revision Data ------------- --- /dev/null +++ htdocs/helpFiles/InstructorPGProblemEditor.html @@ -0,0 +1,69 @@ + +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +=09 +<!-- +########################################################################= ######## +# WeBWorK Online Homework Delivery System +# Copyright =A9 2000-2003 The WeBWorK Project, http://openwebwork.sf.net= / +# $CVSHeader: webwork-modperl/htdocs/helpFiles/InstructorPGProblemEditor= .html,v 1.1.2.1 2006/01/07 02:11:16 gage Exp $ +#=20 +# This program is free software; you can redistribute it and/or modify i= t under +# the terms of either: (a) the GNU General Public License as published b= y the +# Free Software Foundation; either version 2, or (at your option) any la= ter +# version, or (b) the "Artistic License" which comes with this package. +#=20 +# This program is distributed in the hope that it will be useful, but WI= THOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or = FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License o= r the +# Artistic License for more details. +########################################################################= ######## +--> +<html xmlns=3D"http://www.w3.org/1999/xhtml" lang=3D"en-US"> +<head> +<title>PG Problem Editor Help Page</title> +</head> +<body> +=20 +<h3>PG Problem Editor Help Page</h3> +<blockquote> +<p> +This page allows to edit the contents of PG problem files (templates) +as well as set headers and other files. +</p> + +<h4>Features:</h4>=20 +<dl> + =09 + + <dt>| Manpages | macro list | pod docs | report problem bugs |</dt> + <dd>The first three links are to pages that give some information abou= t writing problems: "Manpages" is an (incomplete) list of the most common= ly used macros with a description of their parameters and how to use them= ; a complete list of macros is provided by the "macro list"; and details = for many macros can be obtained using the "pod docs" link which links to = documentation embedded in the macro files themselves. If you find an er= ror in a library problem please use the "Report problem bugs" link to not= ify us so that we can fix it. You will need to register with an email ad= dress the first time you use bugzilla, but after that you will not. </dd> + <dt> The large text window</dt> + <dd> This is where you edit the text of the problem template. Nothin= g happens until you pick an action (below) and click the "Take action!" b= utton.</dd> + </dl> + =09 +<h4>Action items:</h4> <i>(If an action cannot be executed it will not a= ppear as an action item.) +</i> +</dl> + <dt> View problem</dt> + <dd> Will bring up a window to show the results of your editing. It = does not change the permanent file on the disk.</dd> + <dt> Add problem to set</dt> + <dd> Add this problem as the last problem in an existing set, either= as a problem or as the set header (the text that appears on the home pag= e of a homework set). You can rearrange the order of the problems later u= sing the "Hmwk Sets Editor"</dd> + <dt> Save to...</dt> + <dd> Saves the changes to the file indicated.</dd> + <dt> Make local copy </dt> + <dd> Will make a local copy of an uneditable library problem so that = you can edit it. It also changes the file path for the current problem t= o the new local copy. (It is much like "rename" but actually suggests the= file name for you so that you can remember where the problem came from.<= /dd> + <dt> Rename ... </dt> + <dd> Saves the changes to a new file and changes the file path for th= e current problem to this new file</dd> + <dt> Create a copy ... </dt> + <dd> Saves the changes to a new file but does not change the file pat= h for the current problem</dd> + <dt> Revert</dt> + <dd> Reverts to the copy of the file saved on the disk -- all unsaved= editing changes will be lost.</dd> + <dt> Take action</dt> + <dd> Executes the</dd> action item selected above +</dl> + +</blockquote> +</body> +</html> |
From: Mike G. v. a. <we...@ma...> - 2006-01-07 02:12:41
|
Log Message: ----------- PG Problem Editor Help Page Added Files: ----------- webwork-modperl/htdocs/helpFiles: InstructorPGProblemEditor.html Revision Data ------------- --- /dev/null +++ htdocs/helpFiles/InstructorPGProblemEditor.html @@ -0,0 +1,69 @@ + +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +=09 +<!-- +########################################################################= ######## +# WeBWorK Online Homework Delivery System +# Copyright =A9 2000-2003 The WeBWorK Project, http://openwebwork.sf.net= / +# $CVSHeader: webwork-modperl/htdocs/helpFiles/InstructorPGProblemEditor= .html,v 1.1 2006/01/07 02:08:52 gage Exp $ +#=20 +# This program is free software; you can redistribute it and/or modify i= t under +# the terms of either: (a) the GNU General Public License as published b= y the +# Free Software Foundation; either version 2, or (at your option) any la= ter +# version, or (b) the "Artistic License" which comes with this package. +#=20 +# This program is distributed in the hope that it will be useful, but WI= THOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or = FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License o= r the +# Artistic License for more details. +########################################################################= ######## +--> +<html xmlns=3D"http://www.w3.org/1999/xhtml" lang=3D"en-US"> +<head> +<title>PG Problem Editor Help Page</title> +</head> +<body> + +<h3>PG Problem Editor Help Page</h3> +<blockquote> +<p> +This page allows to edit the contents of PG problem files (templates) +as well as set headers and other files. +</p> + +<h4>Features:</h4>=20 +<dl> + =09 + + <dt>| Manpages | macro list | pod docs | report problem bugs |</dt> + <dd>The first three links are to pages that give some information abou= t writing problems: "Manpages" is an (incomplete) list of the most common= ly used macros with a description of their parameters and how to use them= ; a complete list of macros is provided by the "macro list"; and details = for many macros can be obtained using the "pod docs" link which links to = documentation embedded in the macro files themselves. If you find an er= ror in a library problem please use the "Report problem bugs" link to not= ify us so that we can fix it. You will need to register with an email ad= dress the first time you use bugzilla, but after that you will not. </dd> + <dt> The large text window</dt> + <dd> This is where you edit the text of the problem template. Nothin= g happens until you pick an action (below) and click the "Take action!" b= utton.</dd> + </dl> + =09 +<h4>Action items:</h4> <i>(If an action cannot be executed it will not a= ppear as an action item.) +</i> +</dl> + <dt> View problem</dt> + <dd> Will bring up a window to show the results of your editing. It = does not change the permanent file on the disk.</dd> + <dt> Add problem to set</dt> + <dd> Add this problem as the last problem in an existing set, either= as a problem or as the set header (the text that appears on the home pag= e of a homework set). You can rearrange the order of the problems later u= sing the "Hmwk Sets Editor"</dd> + <dt> Save to...</dt> + <dd> Saves the changes to the file indicated.</dd> + <dt> Make local copy </dt> + <dd> Will make a local copy of an uneditable library problem so that = you can edit it. It also changes the file path for the current problem t= o the new local copy. (It is much like "rename" but actually suggests the= file name for you so that you can remember where the problem came from.<= /dd> + <dt> Rename ... </dt> + <dd> Saves the changes to a new file and changes the file path for th= e current problem to this new file</dd> + <dt> Create a copy ... </dt> + <dd> Saves the changes to a new file but does not change the file pat= h for the current problem</dd> + <dt> Revert</dt> + <dd> Reverts to the copy of the file saved on the disk -- all unsaved= editing changes will be lost.</dd> + <dt> Take action</dt> + <dd> Executes the</dd> action item selected above +</dl> + +</blockquote> +</body> +</html> |
From: Mike G. v. a. <we...@ma...> - 2006-01-07 02:11:16
|
Log Message: ----------- PG problem editor help Modified Files: -------------- webwork-modperl/htdocs/helpFiles: InstructorProblemSetDetail.html Revision Data ------------- Index: InstructorProblemSetDetail.html =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/helpFiles/InstructorProblemSetDetail.html,v retrieving revision 1.1 retrieving revision 1.2 diff -Lhtdocs/helpFiles/InstructorProblemSetDetail.html -Lhtdocs/helpFiles/InstructorProblemSetDetail.html -u -r1.1 -r1.2 --- htdocs/helpFiles/InstructorProblemSetDetail.html +++ htdocs/helpFiles/InstructorProblemSetDetail.html @@ -28,7 +28,7 @@ <h2>Set Detail Help Page</h2> - +<!-- <h3> Quick Links </h3> <ul> @@ -37,7 +37,7 @@ <li> My nose is leaking. </li> <li> How does this work? </li> </ul> - +--> <h3> "Modes" </h3> <p>The <strong>Set Detail</strong> page can be viewed in one of three distinct modes: |
From: Mike G. v. a. <we...@ma...> - 2006-01-07 01:18:44
|
Log Message: ----------- This fixes the bug specifically reported in bug report #935. There are still problems with saving local copies of set headers. Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: PGProblemEditor.pm Revision Data ------------- Index: PGProblemEditor.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v retrieving revision 1.66 retrieving revision 1.67 diff -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -Llib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm -u -r1.66 -r1.67 --- lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm +++ lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm @@ -144,7 +144,6 @@ my $file_type = $r->param("file_type") || ''; my $setName = $self->{setID}; my $problemNumber = $self->{problemID}; - # Check permissions return unless ($authz->hasPermissions($user, "access_instructor_tools")); return unless ($authz->hasPermissions($user, "modify_problem_sets")); @@ -197,6 +196,7 @@ # or regular problem if (defined($file_type) and ($file_type =~/\S/)) { #file_type is defined and is not blank # file type is already defined -- do nothing + #warn "file type already defined as $file_type" #FIXME debug } else { # if "sourceFilePath" is defined in the form, then we are getting the path directly. # if the problem number is defined and is 0 @@ -209,10 +209,11 @@ $file_type ='source_path_for_problem_file'; } elsif ( defined($problemNumber) ) { if ( $problemNumber =~/^\d+$/ and $problemNumber == 0 ) { # if problem number is numeric and zero - $file_type = 'set_header' unless $file_type eq 'set_header' + $file_type = 'set_header' unless $file_type eq 'set_header' or $file_type eq 'hardcopy_header'; } else { - $file_type = 'problem'; + $file_type = 'problem'; + #warn "setting file type to 'problem'\n"; #FIXME debug } } @@ -228,7 +229,8 @@ $self->{sourceFilePath} = $sourceFilePath; } $self->{file_type} = $file_type; - + # $self->addgoodmessage("file type is $file_type"); #FIXME debug + # warn "file type is $file_type\n parameter is ".$self->r->param("file_type"); ########################################## # File type is one of: blank_problem course_info problem set_header hardcopy_header source_path_for_problem_file ########################################## @@ -350,8 +352,8 @@ if ( not( -e $inputFilePath) ) { $self->addbadmessage("This file: $inputFilePath, cannot be found."); } elsif (not -w $inputFilePath ) { - $self->addbadmessage("This file '$inputFilePath' is protected! ".CGI::br()."To edit this text you must either 'Make a local copy' of this problem, or - use 'Save As' to save it to another file."); + $self->addbadmessage("This file '$inputFilePath' is protected! ".CGI::br()."To edit this text you must make a copy of this file using the 'make local editable copy at ...' or the + 'rename file path to ...' action below."); } if ($inputFilePath =~/$BLANKPROBLEM$/) { $self->addbadmessage("This file '$inputFilePath' is a blank problem! ".CGI::br()."To edit this text you must @@ -473,8 +475,8 @@ } my $protected_file = not -w $inputFilePath; - my $header = CGI::i("Editing problem".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath"); - $header = ($self->isTempFilePath($inputFilePath) ) ? CGI::div({class=>'temporaryFile'},$header) : $header; # use colors if temporary file + my $header = CGI::i("Editing problem ".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath"); + $header = ($self->isTempEditFilePath($inputFilePath) ) ? CGI::div({class=>'temporaryFile'},$header) : $header; # use colors if temporary file ######################################################################### # Format the page @@ -505,7 +507,7 @@ print CGI::p($header), - CGI::start_form({method=>"POST", name=>"editor", action=>"$uri", target=>$target, enctype=>"application/x-www-form-urlencoded"}), + CGI::start_form({-method=>"POST", -name=>"editor", -action=>"$uri", -target=>$target, enctype=>"application/x-www-form-urlencoded"}), $self->hidden_authen_fields, $force_field, CGI::hidden(-name=>'file_type',-default=>$self->{file_type}), @@ -578,15 +580,16 @@ sub determineLocalFilePath { my $self= shift; die "determineLocalFilePath is a method" unless ref($self); my $path = shift; -# my $default_screen_header_path = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; -# my $default_hardcopy_header_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; - my $setID = $self->{setID} || int(rand(1000)); + my $default_screen_header_path = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; + my $default_hardcopy_header_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; + my $setID = $self->{setID}; + $setID = int(rand(1000)) unless $setID =~/\S/; # setID can be 0 if ($path =~ /Library/) { $path =~ s|^.*?Library/||; # truncate the url up to a segment such as ...rochesterLibrary/....... -# } elsif ($path eq $default_screen_header_path) { -# $path = "set$setID/setHeader.pg"; -# } elsif ($path eq $default_hardcopy_header_path) { -# $path = "set$setID/hardcopyHeader.tex"; + } elsif ($path eq $default_screen_header_path) { + $path = "set$setID/setHeader.pg"; + } elsif ($path eq $default_hardcopy_header_path) { + $path = "set$setID/hardcopyHeader.tex"; } else { # if its not in a library we'll just save it locally $path = "new_problem_".int(rand(1000)).".pg"; #l hope there aren't any collisions. } @@ -594,9 +597,10 @@ } -sub determineTempFilePath { # this does not create the path to the file - my $self = shift; die "determineTempFilePath is a method" unless ref($self); - my $path =shift; +sub determineTempEditFilePath { # this does not create the directories in the path to the file + # it returns an absolute path to the file + my $self = shift; die "determineTempEditFilePath is a method" unless ref($self); + my $path =shift; # this should be an absolute path to the file my $user = $self->r->param("user"); $user = int(rand(1000)) unless defined $user; my $setID = $self->{setID} || int(rand(1000)); @@ -604,32 +608,81 @@ ############### # Calculate the location of the temporary file ############### - my $templatesDirectory = $courseDirectory->{templates}; + my $templatesDirectory = $courseDirectory->{templates}; my $blank_file_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{blankProblem}; my $default_screen_header_path = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; my $default_hardcopy_header_path = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; - my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit"; - if ($path =~ /^$templatesDirectory/ ) { - $path =~ s|^$templatesDirectory||; - $path =~ s|^/||; # remove the initial slash if any - $path = "$tmpEditFileDirectory/$path.$user.tmp"; - } elsif ($path eq $blank_file_path) { - $path = "$tmpEditFileDirectory/blank.$setID.$user.tmp"; # handle the case of the blank problem - } elsif ($path eq $default_screen_header_path) { - $path = "$tmpEditFileDirectory/screenHeader.$setID.$user.tmp"; # handle the case of the screen header in snippets - } elsif ($path eq $default_hardcopy_header_path) { - $path = "$tmpEditFileDirectory/hardcopyHeader.$setID.$user.tmp"; # handle the case of the hardcopy header in snippets + my $tmpEditFileDirectory = $self->getTempEditFileDirectory(); + $self->addbadmessage("The path to the original file should be absolute") unless $path =~m|^/|; # debug + if ($path =~/^$tmpEditFileDirectory/) { + $self->addbadmessage("Error: This path is already in the temporary edit directory -- no new temporary file is created. path = $path"); + } else { - die "determineTempFilePath should only be used on paths within the templates directory, not on $path"; + if ($path =~ /^$templatesDirectory/ ) { + $path =~ s|^$templatesDirectory||; + $path =~ s|^/||; # remove the initial slash if any + $path = "$tmpEditFileDirectory/$path.$user.tmp"; + } elsif ($path eq $blank_file_path) { + $path = "$tmpEditFileDirectory/blank.$setID.$user.tmp"; # handle the case of the blank problem + } elsif ($path eq $default_screen_header_path) { + $path = "$tmpEditFileDirectory/screenHeader.$setID.$user.tmp"; # handle the case of the screen header in snippets + } elsif ($path eq $default_hardcopy_header_path) { + $path = "$tmpEditFileDirectory/hardcopyHeader.$setID.$user.tmp"; # handle the case of the hardcopy header in snippets + } else { + die "determineTempEditFilePath should only be used on paths within the templates directory, not on $path"; + } } $path; } -sub isTempFilePath { +sub determineOriginalEditFilePath { # determine the original path to a file corresponding to a temporary edit file + # returns path relative to the template directory my $self = shift; my $path = shift; - my $courseDirectory = $self->r->ce->{courseDirs}; - my $templatesDirectory = $courseDirectory->{templates}; - my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit"; + my $user = $self->r->param("user"); + $self->addbadmessage("Can't determine user of temporary edit file $path.") unless defined($user); + my $templatesDirectory = $self->r->ce->{courseDirs} ->{templates}; + my $tmpEditFileDirectory = $self->getTempEditFileDirectory(); + # unless path is absolute assume that it is relative to the template directory + my $newpath = $path; + unless ($path =~ m|^/| ) { + $newpath = "$templatesDirectory/$path"; + } + if ($self->isTempEditFilePath($newpath) ) { + $newpath =~ s|^$tmpEditFileDirectory/||; # delete temp edit directory + if ($newpath =~m|blank\.[^/]*$|) { # handle the case of the blank problem + $newpath = $self->r->ce->{webworkFiles}->{screenSnippets}->{blankProblem}; + } elsif (($newpath =~m|hardcopyHeader\.[^/]*$|)) { # handle the case of the hardcopy header in snippets + $newpath = $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; + } elsif (($newpath =~m|screenHeader\.[^/]*$|)) { # handle the case of the screen header in snippets + $newpath = $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader}; + } else { + $newpath =~ s|\.$user\.tmp$||; # delete suffix + + } + #$self->addgoodmessage("Original file path is $newpath"); #FIXME debug + } else { + $self->addbadmessage("This path |$newpath| is not the path to a temporary edit file."); + # returns original path + } + $newpath; +} + +sub getTempEditFileDirectory { + my $self = shift; + my $courseDirectory = $self->r->ce->{courseDirs}; + my $templatesDirectory = $courseDirectory->{templates}; + my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit"; + $tmpEditFileDirectory; +} +sub isTempEditFilePath { + my $self = shift; + my $path = shift; + my $templatesDirectory = $self->r->ce->{courseDirs} ->{templates}; + # unless path is absolute assume that it is relative to the template directory + unless ($path =~ m|^/| ) { + $path = "$templatesDirectory/$path"; + } + my $tmpEditFileDirectory = $self->getTempEditFileDirectory(); ($path =~/^$tmpEditFileDirectory/) ? 1: 0; } sub getFilePaths { @@ -645,7 +698,7 @@ $setName = '' unless defined $setName; $problemNumber = '' unless defined $problemNumber; die 'Internal error to PGProblemEditor -- file type is not defined' unless defined $file_type; - + #$self->addgoodmessage("file type is $file_type"); #FIXME remove ########################################################## # Determine path to the input file to be edited. # The permanent path of the input file == $editFilePath @@ -701,20 +754,19 @@ my $header_file = ""; $header_file = $set_record->{$file_type}; if ($header_file && $header_file ne "") { - $editFilePath .= '/' . $header_file; + if ( $header_file =~ m|^/| ) { # if absolute address + $editFilePath = $header_file; + } else { + $editFilePath .= '/' . $header_file; + } } else { - # if the set record doesn't specify the filename + # if the set record doesn't specify the filename for a header # then the set uses the default from snippets - # so we'll load that file, but change where it will be saved - # to and grey out the "Save" button - # FIXME why does the make_local_copy variable need to be checked? - # Isn't it automatic that a local copy has to be made? - #if ($r->param('make_local_copy')) { + $editFilePath = $ce->{webworkFiles}->{screenSnippets}->{setHeader} if $file_type eq 'set_header'; $editFilePath = $ce->{webworkFiles}->{hardcopySnippets}->{setHeader} if $file_type eq 'hardcopy_header'; $self->addbadmessage("$editFilePath is the default header file and cannot be edited directly."); $self->addbadmessage("Any changes you make will have to be saved as another file."); - #} } last CASE; }; #end 'set_header, hardcopy_header' case @@ -736,7 +788,13 @@ ($file_type eq 'source_path_for_problem_file') and do { my $forcedSourceFile = $self->{sourceFilePath}; - # bail if no source path for the problem is found ; + # if the source file is in the temporary edit directory find the original source file + # the source file is relative to the templates directory. + if ($self->isTempEditFilePath($forcedSourceFile) ) { + $forcedSourceFile = $self->determineOriginalEditFilePath($forcedSourceFile); # original file path + $self->addgoodmessage("the original path to the file is $forcedSourceFile"); #FIXME debug + } + # bail if no source path for the problem is found ; die "Cannot find a file path to save to" unless( defined($forcedSourceFile) and ($forcedSourceFile =~ /\S/) ); $self->{problemSeed} = 1234; $editFilePath .= '/' . $forcedSourceFile; @@ -765,16 +823,16 @@ # Whew!!! ################################################# - my $tempFilePath = $self->determineTempFilePath($editFilePath); #"$editFilePath.$TEMPFILESUFFIX"; + my $tempFilePath = $self->determineTempEditFilePath($editFilePath); #"$editFilePath.$TEMPFILESUFFIX"; $self->{editFilePath} = $editFilePath; $self->{tempFilePath} = $tempFilePath; $self->{inputFilePath} = (-r $tempFilePath) ? $tempFilePath : $editFilePath; #warn "editfile path is $editFilePath and tempFile is $tempFilePath and inputFilePath is ". $self->{inputFilePath}; } -sub new_saveFileChanges { +sub saveFileChanges { ################################################################################ -# new_saveFileChanges does most of the work. it is a separate method so that it can +# saveFileChanges does most of the work. it is a separate method so that it can # be called from either pre_header_initialize() or initilize(), depending on # whether a redirect is needed or not. # @@ -872,10 +930,13 @@ ########################################################### unless( $writeFileErrors or $do_not_save) { # everything worked! unlink and announce success! # unlink the temporary file if there are no errors and the save button has been pushed - if ($action eq 'save' or $action eq 'save_as' or $action eq 'revert') { + if ($action eq 'save' or $action eq 'save_as') { + + $self->addgoodmessage("Deleting temp file at " . $self->{tempFilePath}); unlink($self->{tempFilePath}) ; } - if ( defined($outputFilePath) and ! $self->{failure} ) { + if ( defined($outputFilePath) and ! $self->{failure} and not $self->isTempEditFilePath($outputFilePath) ) { + # don't announce saving of temporary editing files my $msg = "Saved to file: |$outputFilePath|"; $self->addgoodmessage($msg); } @@ -883,7 +944,7 @@ } -} # end new_saveFileChanges +} # end saveFileChanges @@ -956,7 +1017,7 @@ my $do_not_save = 0; my $file_type = $self->{file_type}; - $self->new_saveFileChanges($tempFilePath,); + $self->saveFileChanges($tempFilePath,); ######################################################## # construct redirect URL and redirect @@ -1003,7 +1064,7 @@ courseID => $courseName); $viewURL = $self->systemLink($problemSetsPage, params => { - editMode => ("temporaryFile"), + editMode => "temporaryFile", edit_level => $edit_level, status_message => uri_escape($self->{status_message}) } @@ -1134,7 +1195,10 @@ if ($self->{editFilePath} =~ /$BLANKPROBLEM$/ ) { return ""; #Can't save blank problems without changing names } elsif (-w $self->{editFilePath}) { - return "Save"; + my $sourceFilePath = $self->{editFilePath}; + my $templatesPath = $self->r->ce->{courseDirs}->{templates}; + $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory + return "Save to: [TMPL]/$sourceFilePath"; } else { return ""; #"Can't save -- No write permission"; } @@ -1165,7 +1229,7 @@ my $do_not_save = 0; my $file_type = $self->{file_type}; - $self->new_saveFileChanges($outputFilePath); + $self->saveFileChanges($outputFilePath); ################################################# # Set up redirect to Problem.pm ################################################# @@ -1240,15 +1304,15 @@ $self->reply_with_redirect($viewURL); } -sub save_as_form { +sub save_as_form { # calls either the save_as_handler or the rename_handler my ($self, $onChange, %actionParams) = @_; my $sourceFilePath = $self->{editFilePath}; - my $templatesPath = $self->r->ce->{courseDirs}->{templates}; - $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory - - return "Save ". - CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], - -default=>'rename',-labels=>{rename=>' as ',save_a_copy=>'a copy to'} + my $templatesDir = $self->r->ce->{courseDirs}->{templates}; + $sourceFilePath =~ s|^$templatesDir/||; + $sourceFilePath = '' if $sourceFilePath =~ m|^/|; # if it is still an absolute path don't suggest that you save to it. + + return CGI::popup_menu(-name=>'action.save_as.saveMode', -values=>['rename','save_a_copy'], + -default=>'rename',-labels=>{rename=>'Rename file path to ',save_a_copy=>'Create a copy of file at '} ). ": [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>$sourceFilePath),; } @@ -1309,7 +1373,7 @@ unless ($do_not_save ) { - $self->new_saveFileChanges($outputFilePath, \$problemContents); + $self->saveFileChanges($outputFilePath, \$problemContents); my $sourceFilePath = $outputFilePath; my $templatesPath = $self->r->ce->{courseDirs}->{templates}; $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory @@ -1381,9 +1445,10 @@ my $editFilePath = $self->{editFilePath}; $self->{inputFilePath} = $editFilePath; - $self->{tempFilePath} = ''; # unlink the temp files; unlink($self->{tempFilePath}); + $self->addgoodmessage("Deleting temp file at " . $self->{tempFilePath}); + $self->{tempFilePath} = ''; my $problemContents =''; $self->{r_problemContents} = \$problemContents; $self->addgoodmessage("Reverting to original file $editFilePath"); @@ -1394,13 +1459,15 @@ my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited return "" unless -e $editFilePath; return "" if -w $editFilePath; - return "" unless $self->{file_type} eq 'problem'; - # or $self->{file_type} eq 'set_header' ; # need problem structure to make local copy -- not available for header - # or $self->{file_type} eq 'source_path_for_problem_file'; # need setID and problemID to make local copy + return "" unless $self->{file_type} eq 'problem' # need problem structure to make local copy in most cases + or $self->{file_type} eq 'set_header' # $editFilePath eq $self->r->ce->{webworkFiles}->{hardcopySnippets}->{setHeader} # special case to make copy of hardcopy header + or $self->{file_type} eq 'hardcopy_header'; # $editFilePath eq $self->r->ce->{webworkFiles}->{screenSnippets}->{setHeader} ; # special case to make copy of screen header + # or $self->{file_type} eq 'source_path_for_problem_file'; # need setID and problemID to make local copy -- can't be done in this case. return join ("", - "Make local copy at: [TMPL]/".($self->determineLocalFilePath($editFilePath)), + "Make local editable copy at: [TMPL]/".($self->determineLocalFilePath($editFilePath)), CGI::hidden(-name=>'action.make_local_copy.target_file', -value=>$self->determineLocalFilePath($editFilePath) ), CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$editFilePath ), + CGI::hidden(-name=>'action.make_local_copy.file_type',-value=>$self->{file_type}) ); } @@ -1422,6 +1489,8 @@ ################################################# my $new_file_name = $actionParams->{'action.make_local_copy.target_file'}->[0] || ''; my $sourceFilePath = $actionParams->{'action.make_local_copy.source_file'}->[0] || ''; + my $file_type = $actionParams->{'action.make_local_copy.file_type'}->[0] ||''; + my $templatesPath = $self->r->ce->{courseDirs}->{templates}; $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory @@ -1452,20 +1521,31 @@ } else { #$self->addgoodmessage("Saving to file $outputFilePath."); } - my $file_type = $self->{file_type}; unless ($do_not_save ) { - $self->new_saveFileChanges($outputFilePath); + $self->saveFileChanges($outputFilePath); } ################################################# # Modify source file in problem ################################################# if (-r $outputFilePath and !$do_not_save) { - my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); - $problemRecord->source_file($new_file_name); - if ( $self->r->db->putGlobalProblem($problemRecord) ) { - $self->addgoodmessage("A local, editable, copy of [TMPL]/$sourceFilePath has been made for problem $problemNumber.") ; - } else { - $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); + if ($file_type eq 'problem') { + my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber); + die "Unable to problem record for set $setName, problem $problemNumber"; + $problemRecord->source_file($new_file_name); + if ( $self->r->db->putGlobalProblem($problemRecord) ) { + $self->addgoodmessage("A local, editable, copy of [TMPL]/$sourceFilePath has been made for problem $problemNumber.") ; + } else { + $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error."); + } + } elsif ($file_type eq 'set_header' or $file_type eq 'hardcopy_header') { # we are dealing with a set header + + my $set_record = $self->r->db->getGlobalSet($setName); + $set_record->{$file_type} = $new_file_name; + if ( $self->r->db->putGlobalSet($set_record) ) { + $self->addgoodmessage("A local, editable, copy of [TMPL]/$sourceFilePath has been made for the $setName set header") ; + } else { + $self->addbadmessage("Unable to change the source file path for set $setName, set header. Unknown error."); + } } } my $edit_level = $self->r->param("edit_level") || 0; @@ -1479,9 +1559,9 @@ ); my $viewURL = $self->systemLink($problemPage, params=>{ - sourceFilePath => $sourceFilePath, + sourceFilePath => $new_file_name, edit_level => $edit_level, - file_type => 'problem', + file_type => $self->{file_type}, status_message => uri_escape($self->{status_message}) } @@ -1489,19 +1569,21 @@ $self->reply_with_redirect($viewURL); } -sub rename_form { - my ($self, $onChange, %actionParams) = @_; - my $problemPath = $self->{editFilePath}; - my $templatesDir = $self->r->ce->{courseDirs}->{templates}; - #warn "problemPath $problemPath $templatesDir"; - $problemPath =~ s|^$templatesDir/||; - return join("", - "Rename problem file to : [TMPL]/".CGI::textfield(-name=>'action.rename.target_file', -size=>40, -value=>$problemPath), - CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$self->{editFilePath} ), - ); - - -} +# sub rename_form { # see the save_as form +# # my ($self, $onChange, %actionParams) = @_; +# # my $problemPath = $self->{editFilePath}; +# # my $templatesDir = $self->r->ce->{courseDirs}->{templates}; +# # #warn "problemPath $problemPath $templatesDir"; +# # $problemPath =~ s|^$templatesDir/||; +# # $problemPath = '' if $problemPath =~ m|^/|; # if it is still an absolute path don't suggest that you save to it. +# # $self->addbadmessage("problem Path is $problemPath"); +# # return join("", +# # "Rename problem file to : [TMPL]/".CGI::textfield(-name=>'action.rename.target_file', -size=>40, -value=>$problemPath), +# # CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$self->{editFilePath} ), +# # ); +# +# +# } sub rename_handler { my ($self, $genericParams, $actionParams, $tableParams) = @_; |
From: Gavin L. v. a. <we...@ma...> - 2006-01-06 17:52:13
|
Log Message: ----------- Gateway bugfix: correct (or work around) missing score/values. Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: Scoring.pm Revision Data ------------- Index: Scoring.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/Scoring.pm,v retrieving revision 1.53 retrieving revision 1.54 diff -Llib/WeBWorK/ContentGenerator/Instructor/Scoring.pm -Llib/WeBWorK/ContentGenerator/Instructor/Scoring.pm -u -r1.53 -r1.54 --- lib/WeBWorK/ContentGenerator/Instructor/Scoring.pm +++ lib/WeBWorK/ContentGenerator/Instructor/Scoring.pm @@ -388,25 +388,35 @@ } else { # versioned sets; get the problems for the best version foreach my $userID (@sortedUserIDs) { - my %CurrUserProblems; + my $CurrUserProblems = {}; my $numVersions = $db->getUserSetVersionNumber( $userID, $setID ); my $bestScore = -1; - for ( my $i=1; $i<=$numVersions; $i++ ) { + if ( $numVersions ) { + for ( my $i=1; $i<=$numVersions; $i++ ) { my %versionUserProblems = map { $_->problem_id => $_ } $db->getAllUserProblems( $userID, "$setID,v$i" ); my $score = 0; foreach ( values ( %versionUserProblems ) ) { my $status = $_->status || 0; my $value = $_->value || 1; + # some of these are coming in null; I'm not + # why, or if this should be necessary + $_->status($status); + $_->value($value); $score += $status*$value; } if ( $score > $bestScore ) { - %CurrUserProblems = %versionUserProblems; + $CurrUserProblems = \%versionUserProblems; $bestScore = $score; } + } + } else { + my %cp = map { $_->problem_id => $_ } + $db->getAllMergedUserProblems($userID, $setID); + $CurrUserProblems = \%cp; } - $UserProblems{$userID} = \%CurrUserProblems; + $UserProblems{$userID} = { %{$CurrUserProblems} }; } } debug("done pre-fetching user problems for set $setID"); |
From: Gavin L. v. a. <we...@ma...> - 2006-01-02 23:28:33
|
Log Message: ----------- Gateway update: don't display gateway sets in siblings sidebar of ProblemSet list for all users, regardless of permissions. This may or may not be the desired behavior. I like it because it forces the user to go to a test from the ProblemSets page where we rewrite the link with the more intuitive (but longer) text "Take new [test name] test". Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: ProblemSet.pm Revision Data ------------- Index: ProblemSet.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/ProblemSet.pm,v retrieving revision 1.69 retrieving revision 1.70 diff -Llib/WeBWorK/ContentGenerator/ProblemSet.pm -Llib/WeBWorK/ContentGenerator/ProblemSet.pm -u -r1.69 -r1.70 --- lib/WeBWorK/ContentGenerator/ProblemSet.pm +++ lib/WeBWorK/ContentGenerator/ProblemSet.pm @@ -133,14 +133,19 @@ my @setIDs = sortByName(undef, $db->listUserSets($eUserID)); # do not show unpublished siblings unless user is allowed to view unpublished sets, and - # exclude gateway tests - unless ($authz->hasPermissions($user, "view_unpublished_sets") ) { + # exclude gateway tests in all cases + if ( $authz->hasPermissions($user, "view_unpublished_sets") ) { + @setIDs = grep {my $gs = $db->getGlobalSet( $_ ); + $gs->assignment_type() !~ /gateway/} @setIDs; + + } else { # @setIDs = grep {my $visible = $db->getGlobalSet( $_)->published; (defined($visible))? $visible : 1} @setIDs = grep {my $gs = $db->getGlobalSet( $_ ); - $gs->assignment_type() !~ /gateway/ && - ( defined($gs->published()) ? $gs->published() : 1 )} + $gs->assignment_type() !~ /gateway/ && + ( defined($gs->published()) ? $gs->published() : 1 )} @setIDs; } + #print CGI::start_ul({class=>"LinksMenu"}); #print CGI::start_li(); #print CGI::span({style=>"font-size:larger"}, "Homework Sets"); |
From: dpvc v. a. <we...@ma...> - 2005-12-31 16:35:23
|
Log Message: ----------- Added ability to supply a code reference (rather than a Value object) for the typeMatch and extra fields for the List answer checker (and the String answer checker). This makes these more useful in overriding the match for specific problems that want better error messages, for example. Modified Files: -------------- pg/lib/Value: AnswerChecker.pm Revision Data ------------- Index: AnswerChecker.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/AnswerChecker.pm,v retrieving revision 1.75 retrieving revision 1.76 diff -Llib/Value/AnswerChecker.pm -Llib/Value/AnswerChecker.pm -u -r1.75 -r1.76 --- lib/Value/AnswerChecker.pm +++ lib/Value/AnswerChecker.pm @@ -635,6 +635,7 @@ my $self = shift; my $other = shift; my $ans = shift; # return 0 if ref($other) && Value::isFormula($other); my $typeMatch = $ans->{typeMatch}; + return &$typeMatch($other,$ans) if ref($typeMatch) eq 'CODE'; return 1 if !Value::isValue($typeMatch) || $typeMatch->class eq 'String' || $self->type eq $other->type; return $typeMatch->typeMatch($other,$ans); @@ -1009,6 +1010,7 @@ entry_type => undef, list_type => undef, typeMatch => $element, + firstElement => $element, extra => undef, requireParenMatch => 1, removeParens => 1, @@ -1171,7 +1173,9 @@ my $ordered = $ans->{ordered}; my $showTypeWarnings = $ans->{showTypeWarnings} && !$ans->{isPreview}; my $typeMatch = $ans->{typeMatch}; - my $extra = $ans->{extra} || $typeMatch; + my $extra = $ans->{extra} || + (Value::isValue($typeMatch) ? $typeMatch: $ans->{firstElement}) || + "Value::List"; my $showHints = getOption($ans,'showHints') && !$ans->{isPreview}; my $error = $$Value::context->{error}; my $score = 0; my @errors; my $i = 0; @@ -1208,7 +1212,9 @@ if (scalar(@correct)) { if (shift(@correct)->cmp_compare($entry,$ans,$nth,$value)) {$score++; next ENTRY} } else { - $extra->cmp_compare($entry,$ans,$nth,$value); # do syntax check + # do syntax check + if (ref($extra) eq 'CODE') {&$extra($entry,$ans,$nth,$value)} + else {$extra->cmp_compare($entry,$ans,$nth,$value)} } if ($error->{flag} == $CMP_ERROR) {$self->cmp_error($ans); return} } else { @@ -1220,13 +1226,17 @@ if ($error->{flag} == $CMP_ERROR) {$self->cmp_error($ans); return} } $$Value::context->clearError; - $extra->cmp_compare($entry,$ans,$nth,$value); # do syntax check + # do syntax check + if (ref($extra) eq 'CODE') {&$extra($entry,$ans,$nth,$value)} + else {$extra->cmp_compare($entry,$ans,$nth,$value)} } # # Give messages about incorrect answers # - if ($showTypeWarnings && !$typeMatch->typeMatch($entry,$ans) && - !($ans->{ignoreStrings} && $entry->class eq 'String')) { + my $match = (ref($typeMatch) eq 'CODE')? &$typeMatch($entry,$ans) : + $typeMatch->typeMatch($entry,$ans); + if ($showTypeWarnings && !$match && + !($ans->{ignoreStrings} && $entry->class eq 'String')) { push(@errors,"Your$nth $answer isn't ".lc($class). " (it looks like ".lc($entry->showClass).")"); } elsif ($error->{flag} && $ans->{showEqualErrors}) { |
From: dpvc v. a. <we...@ma...> - 2005-12-31 16:33:05
|
Log Message: ----------- Avoid error when a CODE reference is checked to see if it is a Value object. Modified Files: -------------- pg/lib: Value.pm Revision Data ------------- Index: Value.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value.pm,v retrieving revision 1.50 retrieving revision 1.51 diff -Llib/Value.pm -Llib/Value.pm -u -r1.50 -r1.51 --- lib/Value.pm +++ lib/Value.pm @@ -136,10 +136,10 @@ return class($v) eq 'Formula' || (ref($v) && ref($v) ne 'ARRAY' && $v->{isFormula}); } -sub isValue { +sub isValue { my $v = shift; return (ref($v) || $v) =~ m/^Value::/ || - (ref($v) && ref($v) ne 'ARRAY' && $v->{isValue}); + (ref($v) && ref($v) ne 'ARRAY' && ref($v) ne 'CODE' && $v->{isValue}); } sub isNumber { |
From: dpvc v. a. <we...@ma...> - 2005-12-31 15:04:11
|
Log Message: ----------- Added ability to specify variables that are part of the union/list rather than requiring just constants. E.g., interval_cmp("(1,a),(2a-1,a)",unions=>'no',var=>'a'); or interval_cmp("(x,y),(2x,3y)",unions=>'no',vars=>['x','y']); Modified Files: -------------- pg/macros: extraAnswerEvaluators.pl Revision Data ------------- Index: extraAnswerEvaluators.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/extraAnswerEvaluators.pl,v retrieving revision 1.13 retrieving revision 1.14 diff -Lmacros/extraAnswerEvaluators.pl -Lmacros/extraAnswerEvaluators.pl -u -r1.13 -r1.14 --- macros/extraAnswerEvaluators.pl +++ macros/extraAnswerEvaluators.pl @@ -344,6 +344,17 @@ $ans_type = 'String' if $string eq uc($correct_ans); } } + # Add any variables + $opts{vars} = $opts{var} if ($opts{var}); + if ($opts{vars}) { + $context->variables->are(); # clear old vars + $opts{vars} = [$opts{vars}] unless ref($opts{vars}) eq 'ARRAY'; + foreach my $v (@{$opts{vars}}) { + $context->variables->add($v=>'Real') + unless $context->variables->get($v); + } + } + my $ans_eval; Context($context); if($ans_type eq 'List') { |
From: dpvc v. a. <we...@ma...> - 2005-12-31 15:01:22
|
Log Message: ----------- Added a new flag that controls how a list with a single entry that is a list is handled. In the past, the student could not specify such an item, but now the default is to form a list with a single entry that is a list, provided the student has used parens explicitly around his list. So "1,2" will be a list with two items and "(1,2)" will be a list with one item (a list). This improves the ability to use the list checker for lists of arbitrary pairs (like "(1,max)") especially when you want to check for lists of these (e.g., "(1,max),(2,min)"), since otherwise a single pair "(1,max)" entered by the student would become the list "1,max" rather than the list containing the single pair. If you really want "(1,max)" to become the list "1,max", use List("1,max")->cmp(implicitList=>0); to prevent single lists from forming a list of a single item. Modified Files: -------------- pg/lib/Value: AnswerChecker.pm Revision Data ------------- Index: AnswerChecker.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/AnswerChecker.pm,v retrieving revision 1.74 retrieving revision 1.75 diff -Llib/Value/AnswerChecker.pm -Llib/Value/AnswerChecker.pm -u -r1.74 -r1.75 --- lib/Value/AnswerChecker.pm +++ lib/Value/AnswerChecker.pm @@ -1012,6 +1012,7 @@ extra => undef, requireParenMatch => 1, removeParens => 1, + implicitList => 1, ); } @@ -1047,6 +1048,7 @@ my $showParenHints = getOption($ans,'showParenHints'); my $partialCredit = getOption($ans,'partialCredit'); my $requireParenMatch = $ans->{requireParenMatch}; + my $implicitList = $ans->{implicitList}; my $typeMatch = $ans->{typeMatch}; my $value = $ans->{entry_type}; my $ltype = $ans->{list_type} || lc($self->type); @@ -1074,11 +1076,19 @@ my $student = $ans->{student_value}; my @student = ($student); my ($sOpen,$sClose) = ('',''); if (Value::isFormula($student) && $student->type eq $self->type) { - @student = Value::List->splitFormula($student,$ans); - $sOpen = $student->{tree}{open}; $sClose = $student->{tree}{close}; + if ($implicitList && $student->{tree}{open} ne '') { + @student = ($student); + } else { + @student = Value::List->splitFormula($student,$ans); + $sOpen = $student->{tree}{open}; $sClose = $student->{tree}{close}; + } } elsif ($student->class ne 'Formula' && $student->class eq $self->type) { - @student = @{$student->{data}}; - $sOpen = $student->{open}; $sClose = $student->{close}; + if ($implicitList && $student->{open} ne '') { + @student = ($student); + } else { + @student = @{$student->{data}}; + $sOpen = $student->{open}; $sClose = $student->{close}; + } } return if $ans->{split_error}; # |
From: dpvc v. a. <we...@ma...> - 2005-12-31 02:46:18
|
Log Message: ----------- Now that the Parser allows multi-letter variable names, there is no need to handle C0 specially. Modified Files: -------------- pg/lib/Value: AnswerChecker.pm Revision Data ------------- Index: AnswerChecker.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/AnswerChecker.pm,v retrieving revision 1.73 retrieving revision 1.74 diff -Llib/Value/AnswerChecker.pm -Llib/Value/AnswerChecker.pm -u -r1.73 -r1.74 --- lib/Value/AnswerChecker.pm +++ lib/Value/AnswerChecker.pm @@ -1336,9 +1336,7 @@ my $current = Parser::Context->current(); my $context = $self->{context} = $self->{context}->copy; Parser::Context->current(undef,$context); - $context->{_variables}->{pattern} = $context->{_variables}->{namePattern} = - 'C0|' . $context->{_variables}->{pattern}; - $context->update; $context->variables->add('C0' => 'Parameter'); + $context->variables->add('C0' => 'Parameter'); my $f = Value::Formula->new('C0')+$self; for ('limits','test_points','test_values','num_points','granularity','resolution', 'checkUndefinedPoints','max_undefined') |
From: dpvc v. a. <we...@ma...> - 2005-12-31 02:44:52
|
Log Message: ----------- Now that the parser accepts multi-character variables, there is no need for the special treatment of dx. Also, allow the context to specify the default variable to use, and if not available, take the LAST varaible alphabetically, not the first. (x is more likely to be last, and the author might have added dx as a variable so that it will not cause an error if used in other answers in the problem, for example.) Modified Files: -------------- pg/macros: parserDifferenceQuotient.pl Revision Data ------------- Index: parserDifferenceQuotient.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/parserDifferenceQuotient.pl,v retrieving revision 1.4 retrieving revision 1.5 diff -Lmacros/parserDifferenceQuotient.pl -Lmacros/parserDifferenceQuotient.pl -u -r1.4 -r1.5 --- macros/parserDifferenceQuotient.pl +++ macros/parserDifferenceQuotient.pl @@ -13,7 +13,7 @@ # is not fully reduced. # # Use DifferenceQuotient(formula) to create a difference equation -# object. If the context has more than one variable, the first one +# object. If the context has more than one variable, the last one # alphabetically is used to form the dx. Otherwise, you can specify # the variable used for dx as the second argument to # DifferenceQuotient(). You could use a variable like h instead of @@ -40,20 +40,14 @@ sub new { my $self = shift; my $class = ref($self) || $self; - my $formula = shift; - my $dx = shift || 'd'.($$Value::context->variables->names)[0]; + my $formula = shift; my $current = $$Value::context; + my $dx = shift || $current->flag('diffQuotientVar') || 'd'.($current->variables->names)[-1]; # # Save the original context, and make a copy to which we # add a variable for 'dx' # - my $current = $$Value::context; my $context = main::Context($current->copy); - unless ($context->variables->get($dx)) { - $context->{_variables}->{pattern} = $context->{_variables}->{namePattern} = - $dx . '|' . $context->{_variables}->{pattern}; - $context->update; - $context->variables->add($dx=>'Real'); - } + $context->variables->add($dx=>'Real') unless ($context->variables->get($dx)); $q = bless $self->SUPER::new($formula), $class; $q->{isValue} = 1; $q->{isFormula} = 1; $q->{dx} = $dx; main::Context($current); # put back the original context; |
From: dpvc v. a. <we...@ma...> - 2005-12-31 01:43:31
|
Log Message: ----------- Allow multi-letter variable names and names like x1, x2, etc. Modified Files: -------------- pg/lib/Parser/Context: Variables.pm Revision Data ------------- Index: Variables.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Parser/Context/Variables.pm,v retrieving revision 1.9 retrieving revision 1.10 diff -Llib/Parser/Context/Variables.pm -Llib/Parser/Context/Variables.pm -u -r1.9 -r1.10 --- lib/Parser/Context/Variables.pm +++ lib/Parser/Context/Variables.pm @@ -27,7 +27,7 @@ $self->{dataName} = 'variables'; $self->{name} = 'variable'; $self->{Name} = 'Variable'; - $self->{namePattern} = '[a-zA-Z]'; + $self->{namePattern} = '[a-zA-Z][a-zA-Z0-9]*'; $self->{pattern} = $self->{namePattern}; } |
From: Arnie P. v. a. <we...@ma...> - 2005-12-30 20:49:31
|
Log Message: ----------- Put the phrase "Click the icon for page and item specific help" at the top since in most cases this is what people will want. If it's not there people may give up before they get to it at the bottom of the page. Also delete "(if it is available)" since it gives no useful information. Arnie Modified Files: -------------- webwork-modperl/htdocs/helpFiles: instructor_links.html Revision Data ------------- Index: instructor_links.html =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/helpFiles/instructor_links.html,v retrieving revision 1.3 retrieving revision 1.4 diff -Lhtdocs/helpFiles/instructor_links.html -Lhtdocs/helpFiles/instructor_links.html -u -r1.3 -r1.4 --- htdocs/helpFiles/instructor_links.html +++ htdocs/helpFiles/instructor_links.html @@ -24,7 +24,12 @@ <title>Instructor Links Help Page</title> </head> <body> + <h3>Instructor Links Help Page</h3> + +Click the icon <a href="instructor_links.html"><img src="/webwork2_files/images/question_mark.png"></a> for +page and item specific help. + <dl> <dt>Instructor Tools</dt> <dd>Quick access to many instructor tools, including @@ -66,7 +71,7 @@ </dl> Click the icon <a href="instructor_links.html"><img src="/webwork2_files/images/question_mark.png"></a> for -page and item specific help (if it is available). +page and item specific help. </body> </html> |
From: dpvc v. a. <we...@ma...> - 2005-12-30 19:10:11
|
Log Message: ----------- No longer needed. Removed Files: ------------- webwork-modperl/htdocs/jsMath: jsMath-mozilla.js Revision Data ------------- --- htdocs/jsMath/jsMath-mozilla.js +++ /dev/null @@ -1,212 +0,0 @@ -/* - * jsMath-mozilla.js - * - * Part of the jsMath package for mathematics on the web. - * - * This file makes changes needed for use with Mozilla-based - * browsers on any platform - * - * --------------------------------------------------------------------- - * - * jsMath is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * jsMath is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with jsMath; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - - -/******************************************************************** - * - * Mozilla has its own character mapping mechanism for accessing - * the TeX fonts, so we replace the values in our internal - * font map to point to these - */ - -jsMath.Update.TeXfontCodes({ - cmr10: [ - 'Γ', 'Δ', 'Θ', 'Λ', - 'Ξ', 'Π', 'Σ', 'Υ', - 'Φ', 'Ψ', 'Ω', 'ff', - 'fi', 'fl', 'ffi', 'ffl', - - 'ı', '', '̀', '́', - '̌', '̆', '̅', '̊', - '̧', 'ß', 'æ', 'œ', - 'ø', 'Æ', 'Œ', 'Ø', - - '̷', '!', '”', '#', - '$', '%', '&', ''', - '(', ')', '*', '+', - ',', '-', '.', '/', - - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ':', ';', '¡', '=', '¿', '?', - - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '“', ']', '̂', '̇', - - '‘', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', '–', '—', '̋', '̃', '̈' - ], - - cmmi10: [ - 'Γ', 'Δ', 'Θ', 'Λ', - 'Ξ', 'Π', 'Σ', 'Υ', - 'Φ', 'Ψ', 'Ω', 'α', - 'β', 'γ', 'δ', 'ε', - - 'ζ', 'η', 'θ', 'ι', - 'κ', 'λ', 'μ', 'ν', - 'ξ', 'π', 'ρ', 'σ', - 'τ', 'υ', 'φ', 'χ', - - 'ψ', 'ω', 'ɛ', 'ϑ', - 'ϖ', 'ϱ', 'ς', 'ϕ', - '↼', '↽', '⇀', '⇁', - '', '', '▹', '◃', - - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '.', ',', '<', '/', '>', '⋆', - - '∂', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '♭', '♮', '♯', '⌣', '⌢', - - 'ℓ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', 'ı', '', '℘', '⃗', '̑' - ], - - cmsy10: [ - '−', '·', '×', '⋆', - '÷', '⋄', '±', '∓', - '⊕', '⊖', '⊗', '⊘', - '⊙', '○', '∘', '∙', - - '≃', '≍', '⊆', '⊇', - '≤', '≥', '≼', '≽', - '∼', '≅', '⊂', '⊃', - '≪', '≫', '≺', '≻', - - '←', '→', '↑', '↓', - '↔', '↗', '↘', '≂', - '⇐', '⇒', '⇑', '⇓', - '⇔', '↖', '↙', '∝', - - '′', '∞', '∈', '∋', - '△', '▽', '̸', '', - '∀', '∃', '¬', '∅', - 'ℜ', 'ℑ', '⊤', '⊥', - - 'ℵ', '', 'ℬ', '', - '', 'ℰ', 'ℱ', '', - 'ℋ', 'ℐ', '', '', - 'ℒ', 'ℳ', '', '', - - '', '', 'ℛ', '', - '', '', '', '', - '', '', '', '∪', - '∩', '⊎', '∧', '∨', - - '⊢', '⊣', '⌊', '⌋', - '⌈', '⌉', '{', '}', - '〈', '〉', '∣', '∥', - '↕', '⇕', '∖', '≀', - - '√', '∐', '∇', '∫', - '⊔', '⊓', '⊑', '⊒', - '§', '†', '‡', '¶', - '♣', '♢', '♡', '♠' - ], - - cmex10: [ - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '', - - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '', - - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '', - - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '', - - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '', - - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '', - - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '', - - '', '', '', '', - '', '', '', '', - '', '', '', '', - '', '', '', '' - ] -}); - - -/* - * Adjust a few other characters as well - */ - -jsMath.Update.TeXfonts({ - cmr10: {'20': {c: 'ˇ', tclass: 'normal', w: .3}}, - cmmi10: { - '20': {c: '<I>&kappa</I>', tclass: 'normal'}, - '58': {c: '.', tclass: 'normal'}, - '59': {c: ',', tclass: 'normal'}, - '61': {c: '/', tclass: 'cmr10'} - }, - cmsy10: { - '3': {c: '*', tclass: 'normal'}, - '16': {c: '≍'}, - '17': {c: '≡', tclass: 'normal'}, - '25': {c: '≈', tclass: 'normal'}, - '39': {c: '≃'}, - '20': {c: '≤', tclass: 'normal'} - }, - cmex10: {'20': {c: '<SPAN STYLE="font-size: 80%"></SPAN>'}}, - cmti10: {'10': {c: '<I>Ω</I>', tclass: 'normal'}}, - cmbx10: {'10': {c: '<B>Ω</B>', tclass: 'normal'}} -}); - - - |
From: Mike G. v. a. <we...@ma...> - 2005-12-29 01:44:07
|
Log Message: ----------- Fixed error in POST url which caused user and key to become multiply defined. This may also cure some other anomolies such as the can't call method "psvn" without a package or object error because that error sometimes included a reference to the key. ??? Not sure about this part, but it definitely causes the multiple user and key definition. Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: ProblemSetDetail.pm Revision Data ------------- Index: ProblemSetDetail.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm,v retrieving revision 1.31 retrieving revision 1.32 diff -Llib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm -Llib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm -u -r1.31 -r1.32 --- lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm +++ lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm @@ -1067,7 +1067,7 @@ my $setDetailPage = $urlpath -> newFromModule($urlpath->module, courseID => $courseID, setID => $setID); - my $setDetailURL = $self->systemLink($setDetailPage); + my $setDetailURL = $self->systemLink($setDetailPage, authen=>0); my $userCountMessage = CGI::a({href=>$editUsersAssignedToSetURL}, $self->userCountMessage($setUserCount, $userCount)); @@ -1099,7 +1099,7 @@ CGI::td([ "Editing problem set ".CGI::strong($setID)." data for these individual students:".CGI::br(). CGI::strong(join CGI::br(), @userLinks), - CGI::a({href=>$setDetailURL },"Edit set ".CGI::strong($setID)." data for ALL students assigned to this set."), + CGI::a({href=>$self->systemLink($setDetailPage) },"Edit set ".CGI::strong($setID)." data for ALL students assigned to this set."), ]) ) |
From: Mike G. v. a. <we...@ma...> - 2005-12-28 02:37:28
|
Log Message: ----------- three more help files Added Files: ----------- webwork-modperl/htdocs/helpFiles: InstructorConfig.html InstructorIndex.html InstructorUserDetail.html Revision Data ------------- --- /dev/null +++ htdocs/helpFiles/InstructorIndex.html @@ -0,0 +1,52 @@ + +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +=09 +<!-- +########################################################################= ######## +# WeBWorK Online Homework Delivery System +# Copyright =A9 2000-2003 The WeBWorK Project, http://openwebwork.sf.net= / +# $CVSHeader: webwork-modperl/htdocs/helpFiles/InstructorIndex.html,v 1.= 1 2005/12/28 02:34:01 gage Exp $ +#=20 +# This program is free software; you can redistribute it and/or modify i= t under +# the terms of either: (a) the GNU General Public License as published b= y the +# Free Software Foundation; either version 2, or (at your option) any la= ter +# version, or (b) the "Artistic License" which comes with this package. +#=20 +# This program is distributed in the hope that it will be useful, but WI= THOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or = FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License o= r the +# Artistic License for more details. +########################################################################= ######## +--> +<html xmlns=3D"http://www.w3.org/1999/xhtml" lang=3D"en-US"> +<head> +<title>Instructor Tools Help Page</title> +</head> +<body> + +<h3>Instructor Tools Help Page</h3> +<blockquote> +<p> +This page allows quick access to an individual student's homework set, + a homework set for the entire class, or the class roster data for one o= r more + students. =20 +</p> + +<p> +It is a collection of short cut techniques which allow you to modify the= database with fewer +page clicks than are required when using the "Class List Editor" and "Hm= wk Sets Editor" pages. It is often more efficient because the set and the= student can both be selected at the same time. +</p> + +<p> +New users will probably find it easier to use those two pages until they= get used to the information required. +</p> +=20 +<p> +Importing and exporting class lists, and deleting students <strong>must<= /strong> be done +from the class list editor. +</p> +</blockquote> +</body> +</html> --- /dev/null +++ htdocs/helpFiles/InstructorUserDetail.html @@ -0,0 +1,49 @@ + +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +=09 +<!-- +########################################################################= ######## +# WeBWorK Online Homework Delivery System +# Copyright =A9 2000-2003 The WeBWorK Project, http://openwebwork.sf.net= / +# $CVSHeader: webwork-modperl/htdocs/helpFiles/InstructorUserDetail.html= ,v 1.1 2005/12/28 02:34:01 gage Exp $ +#=20 +# This program is free software; you can redistribute it and/or modify i= t under +# the terms of either: (a) the GNU General Public License as published b= y the +# Free Software Foundation; either version 2, or (at your option) any la= ter +# version, or (b) the "Artistic License" which comes with this package. +#=20 +# This program is distributed in the hope that it will be useful, but WI= THOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or = FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License o= r the +# Artistic License for more details. +########################################################################= ######## +--> +<html xmlns=3D"http://www.w3.org/1999/xhtml" lang=3D"en-US"> +<head> +<title>Instructor Tools Help Page</title> +</head> +<body> + +<h3>Sets assigned to student Help Page</h3> +<blockquote> +<p>A student must be assigned a homework set in order for it to appear o= n their WeBWorK home page. Check the box in the left column to assign a s= tudent to that homework set. Uncheck the box to unassign a student. If a= student is unassigned from a homework set, all of the student's data for= that homework set is deleted=20 +and cannot be recovered. Use this action cautiously! </p> + +<p> +Change the due dates for an individual +student on this page. Check the checkbox and enter the new date in orde= r +to override the date. (You can copy the date format from the date in the= right hand column which indicates the date when the homework set is due = for the whole class.) +</p> + +<p> +Click on the homework set links to edit change the grades for this indiv= idual student on the homework set. (The grade of each problem is called t= he "status".) +You can also change the number of allowed attempts and further modify th= e=20 +individual student's homework set.) You will also be able to change a st= udent's seed which determines the individual values used in the individua= l version of the student's problem and the weight (how much a problem cou= nts towards the grade.) +</p> + +</blockquote> +</body> +</html> + --- /dev/null +++ htdocs/helpFiles/InstructorConfig.html @@ -0,0 +1,48 @@ +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +=09 +<!-- +########################################################################= ######## +# WeBWorK Online Homework Delivery System +# Copyright =A9 2000-2003 The WeBWorK Project, http://openwebwork.sf.net= / +# $CVSHeader: webwork-modperl/htdocs/helpFiles/InstructorConfig.html,v 1= .1 2005/12/28 02:34:01 gage Exp $ +#=20 +# This program is free software; you can redistribute it and/or modify i= t under +# the terms of either: (a) the GNU General Public License as published b= y the +# Free Software Foundation; either version 2, or (at your option) any la= ter +# version, or (b) the "Artistic License" which comes with this package. +#=20 +# This program is distributed in the hope that it will be useful, but WI= THOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or = FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License o= r the +# Artistic License for more details. +########################################################################= ######## +--> +<html xmlns=3D"http://www.w3.org/1999/xhtml" lang=3D"en-US"> +<head> +<title>Course Configuration Help Page</title> +</head> +<body> +<blockquote> +<p> +This page allows you to configuration of certain parameters, such as=20 +<ul> + <li>permission levels, </li> + <li>display modes allowed </li> + <li>default display mode </li> + <li>and email feedback behavior, </li> +</ul> +on a course by course basis. +</p> + +<p> +Click on each of the tabs to view the configuration items. The question +mark icon provides access to information about the behavior of the confi= guration +settings. +</p> + + +</blockquote> +</body> +</html> |
From: Mike G. v. a. <we...@ma...> - 2005-12-27 00:38:26
|
Log Message: ----------- Fixed theme item in the Constants.pm file. Modified Files: -------------- webwork-modperl/lib/WeBWorK: Constants.pm Revision Data ------------- Index: Constants.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/Constants.pm,v retrieving revision 1.37 retrieving revision 1.38 diff -Llib/WeBWorK/Constants.pm -Llib/WeBWorK/Constants.pm -u -r1.37 -r1.38 --- lib/WeBWorK/Constants.pm +++ lib/WeBWorK/Constants.pm @@ -133,9 +133,10 @@ doc2 => 'The name of course information file (located in the templates directory). Its contents are displayed in the right panel next to the list of homework sets.', type => 'text'}, { var => 'defaultTheme', - doc => 'Theme. choices: (math, ur)', - doc2 => 'The name of course information file (located in the templates directory). Its contents are displayed in the right panel next to the list of homework sets.', - type => 'text'}, + doc => 'Theme (refresh page after saving changes to reveal new theme)', + doc2 => 'There are currently two themes (or skins) to choose from: ur and math. The theme specifies a unified look and feel for the WeBWorK course web pages.', + values => [qw(math ur)], + type => 'popuplist'}, { var => 'sessionKeyTimeout', doc => 'Inactivity time before a user is required to login again', doc2 => 'Length of time, in seconds, a user has to be inactive before he is required to login again.<p> This value should be entered as a number, so as 3600 instead of 60*60 for one hour', |
From: Mike G. v. a. <we...@ma...> - 2005-12-27 00:37:45
|
Log Message: ----------- Added popuplist widget to Config.pm. Modified Constants.pm to allow choice of theme from a pop up menu. Modified Files: -------------- webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor: Config.pm Revision Data ------------- Index: Config.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/Config.pm,v retrieving revision 1.5 retrieving revision 1.6 diff -Llib/WeBWorK/ContentGenerator/Instructor/Config.pm -Llib/WeBWorK/ContentGenerator/Instructor/Config.pm -u -r1.5 -r1.6 --- lib/WeBWorK/ContentGenerator/Instructor/Config.pm +++ lib/WeBWorK/ContentGenerator/Instructor/Config.pm @@ -343,6 +343,58 @@ ); } +########################### configpopuplist +package configpopuplist; +@configpopuplist::ISA = qw(configobject); + +sub display_value { + my ($self, $val) = @_; + $val = 'ur' if not defined($val); + return join(CGI::br(), $val); +} + +# here r->param() returns an array, so we need a custom +# version of convert_newval_source + +# sub convert_newval_source { +# my ($self, $newvalsource) = @_; +# my $inlinevarname = WeBWorK::ContentGenerator::Instructor::Config::inline_var($self->{var}); +# my @newvals; +# if($newvalsource =~ /widget/) { +# @newvals = $self->{Module}->{r}->param($newvalsource); +# } else { +# my $newval = eval('$self->{Module}->{r}->{ce}->'. $inlinevarname); +# @newvals = @$newval; +# } +# return(@newvals); +# } + +sub save_string { + my ($self, $oldval, $newvalsource) = @_; + my $varname = $self->{var}; + my $newval = $self->convert_newval_source($newvalsource); + my $displayoldval = $self->comparison_value($oldval); + return '' if($displayoldval eq $newval); + return('$'. $varname . " = " . "'$newval';\n"); +} + +# sub comparison_value { +# my ($self, $val) = @_; +# $val = 'ur' if not defined($val); +# my $str = join(',', @{$val}); +# return($str); +# } + +sub entry_widget { + my ($self, $name, $default) = @_; + return CGI::popup_menu( + -name => $name, + -value => $self->{values}, + -default => $default, + + ); +} + ########### Main Config Package starts here package WeBWorK::ContentGenerator::Instructor::Config; |
From: Mike G. v. a. <we...@ma...> - 2005-12-26 23:56:38
|
Log Message: ----------- Turn off debugging. Allow the theme to be edited for each course. (This is slightly dangerous since a misspelling of the theme could cause troubles.) It would be helpful to have a pop-up menu widget for Config.pm -- similar to the boolean or permission pop ups, but where the values can be specified. Modified Files: -------------- webwork-modperl/lib/WeBWorK: Constants.pm Revision Data ------------- Index: Constants.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/Constants.pm,v retrieving revision 1.36 retrieving revision 1.37 diff -Llib/WeBWorK/Constants.pm -Llib/WeBWorK/Constants.pm -u -r1.36 -r1.37 --- lib/WeBWorK/Constants.pm +++ lib/WeBWorK/Constants.pm @@ -31,7 +31,7 @@ # If true, WeBWorK::Debug will print debugging output. # -$WeBWorK::Debug::Enabled = 1; +$WeBWorK::Debug::Enabled = 0; # If non-empty, debugging output will be sent to the file named rather than STDERR. # @@ -51,7 +51,7 @@ # For example, this pattern allow only some function being worked on to log: # $WeBWorK::Debug::AllowSubroutineOutput = qr/^WeBWorK::SomePkg::myFunc$/; # -$WeBWorK::Debug::AllowSubroutineOutput = qr/^WeBWorK::ContentGenerator::Instructor::UserDetail::initialize$/; +$WeBWorK::Debug::AllowSubroutineOutput = undef; ################################################################################ # WeBWorK::ContentGenerator::Hardcopy @@ -132,6 +132,10 @@ doc => 'Name of course information file', doc2 => 'The name of course information file (located in the templates directory). Its contents are displayed in the right panel next to the list of homework sets.', type => 'text'}, + { var => 'defaultTheme', + doc => 'Theme. choices: (math, ur)', + doc2 => 'The name of course information file (located in the templates directory). Its contents are displayed in the right panel next to the list of homework sets.', + type => 'text'}, { var => 'sessionKeyTimeout', doc => 'Inactivity time before a user is required to login again', doc2 => 'Length of time, in seconds, a user has to be inactive before he is required to login again.<p> This value should be entered as a number, so as 3600 instead of 60*60 for one hour', |
From: Mike G. v. a. <we...@ma...> - 2005-12-26 22:10:05
|
Log Message: ----------- Modifications which replace SetsAssignedToUsers.pm by UserDetail.pm Added instructor help link to the links in the left margin. There is no specific student help link. Added some more configuration variables to Constants.pm Modified Files: -------------- webwork-modperl/lib/WeBWorK: Constants.pm ContentGenerator.pm URLPath.pm Revision Data ------------- Index: ContentGenerator.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/ContentGenerator.pm,v retrieving revision 1.161 retrieving revision 1.162 diff -Llib/WeBWorK/ContentGenerator.pm -Llib/WeBWorK/ContentGenerator.pm -u -r1.161 -r1.162 --- lib/WeBWorK/ContentGenerator.pm +++ lib/WeBWorK/ContentGenerator.pm @@ -700,7 +700,7 @@ if ($authz->hasPermissions($userID, "manage_course_files")) { print CGI::li(&$makelink("${pfx}Config", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)); } - + print CGI::li( $self->helpMacro('instructor_links','Help'),$self->help() ); print CGI::end_ul(); print CGI::end_li(); # end Instructor Tools } # /* access_instructor_tools */ @@ -715,13 +715,16 @@ print CGI::end_li(); # end Courses print CGI::end_ul(); + + print CGI::start_ul(); if (exists $ce->{webworkURLs}{bugReporter} and $ce->{webworkURLs}{bugReporter} ne "" - and $authz->hasPermissions($userID, "report_bugs")) { - print CGI::start_ul(); - print CGI::li(CGI::a({style=>"font-size:larger", href=>$ce->{webworkURLs}{bugReporter}}, "Report bugs")); - print CGI::end_ul(); + and $authz->hasPermissions($userID, "report_bugs")) { + print CGI::li(CGI::a({style=>'font-size:larger', href=>$ce->{webworkURLs}{bugReporter}}, "Report bugs")); } + print CGI::end_ul(); + + return ""; } @@ -1274,16 +1277,18 @@ sub helpMacro { my $self = shift; my $name = shift; + my $label = shift; #optional my $ce = $self->r->ce; my $basePath = $ce->{webworkDirs}->{local_help}; $name = 'no_help' unless -e "$basePath/$name.html"; my $path = "$basePath/$name.html"; my $url = $ce->{webworkURLs}->{local_help}."/$name.html"; my $imageURL = $ce->{webworkURLs}->{htdocs}."/images/question_mark.png"; + $label = CGI::img({src=>$imageURL, alt=>" ? "}) unless defined $label; return CGI::a({href => $url, target => 'ww_help', - onclick => "window.open(this.href,this.target,'width=550,height=350,scrollbars=yes,resizable=on')"}, - CGI::img({src=>$imageURL, alt=>" ? "})); + onclick => "window.open(this.href,this.target,'width=550,height=350,scrollbars=yes,resizable=yes')"}, + $label); } =item optionsMacro(options_to_show => \@options_to_show, extra_params => \@extra_params) Index: URLPath.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/URLPath.pm,v retrieving revision 1.28 retrieving revision 1.29 diff -Llib/WeBWorK/URLPath.pm -Llib/WeBWorK/URLPath.pm -u -r1.28 -r1.29 --- lib/WeBWorK/URLPath.pm +++ lib/WeBWorK/URLPath.pm @@ -262,7 +262,7 @@ display => 'WeBWorK::ContentGenerator::Instructor::UserList', }, instructor_user_detail => { - name => '$userID', + name => 'Sets assigned to $userID', parent => 'instructor_user_list', kids => [ qw/instructor_sets_assigned_to_user/ ], match => qr|^([^/]+)/|, Index: Constants.pm =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/lib/WeBWorK/Constants.pm,v retrieving revision 1.35 retrieving revision 1.36 diff -Llib/WeBWorK/Constants.pm -Llib/WeBWorK/Constants.pm -u -r1.35 -r1.36 --- lib/WeBWorK/Constants.pm +++ lib/WeBWorK/Constants.pm @@ -31,7 +31,7 @@ # If true, WeBWorK::Debug will print debugging output. # -$WeBWorK::Debug::Enabled = 0; +$WeBWorK::Debug::Enabled = 1; # If non-empty, debugging output will be sent to the file named rather than STDERR. # @@ -51,7 +51,7 @@ # For example, this pattern allow only some function being worked on to log: # $WeBWorK::Debug::AllowSubroutineOutput = qr/^WeBWorK::SomePkg::myFunc$/; # -$WeBWorK::Debug::AllowSubroutineOutput = undef; +$WeBWorK::Debug::AllowSubroutineOutput = qr/^WeBWorK::ContentGenerator::Instructor::UserDetail::initialize$/; ################################################################################ # WeBWorK::ContentGenerator::Hardcopy @@ -209,18 +209,28 @@ min => 1, values => ["plainText", "formattedText", "images", "jsMath", "asciimath"], type => 'checkboxlist'}, + + { var => 'pg{options}{displayMode} ', + doc => 'The default display mode', + doc2 => 'Enter one of the allowed display mode types above. See \'display modes entry\' for descriptions.', + min => 1, + type => 'text'}, + { var => 'pg{ansEvalDefaults}{useBaseTenLog}', doc => 'Use log base 10 instead of base <i>e</i>', doc2 => 'Set to true for log to mean base 10 log and false for log to mean natural logarithm', type => 'boolean'}, + { var => 'pg{ansEvalDefaults}{useOldAnswerMacros}', doc => 'Use older answer checkers', doc2 => 'During summer 2005, a newer version of the answer checkers was implemented for answers which are functions and numbers. The newer checkers allow more functions in student answers, and behave better in certain cases. Some problems are specifically coded to use new (or old) answer checkers. However, for the bulk of the problems, you can choose what the default will be here. <p>Choosing <i>false</i> here means that the newer answer checkers will be used by default, and choosing <i>true</i> means that the old answer checkers will be used by default.', type => 'boolean'}, + { var => 'pg{ansEvalDefaults}{defaultDisplayMatrixStyle}', doc => 'Control string for displaying matricies', doc2 => 'String of three characters for defining the defaults for displaying matricies. The first and last characters give the left and right delimiters of the matrix, so usually one of ([| for a left delimiter, and one of )]| for the right delimiter. It is also legal to specify "." for no delimiter. <p> The middle character indicates how to display vertical lines in a matrix (e.g., for an augmented matrix). This can be s for solid lines and d for dashed lines. While you can specify the defaults, individual problems may override these values.', type => 'text'}, + { var => 'pg{ansEvalDefaults}{numRelPercentTolDefault}', doc => 'Allowed error, as a percentage, for numerical comparisons', doc2 => "When numerical answers are checked, most test if the student's answer @@ -265,9 +275,14 @@ doc => 'E-mail addresses which can recieve e-mail from a pg problem', doc2 => 'List of e-mail addresses to which e-mail can be sent by a problem. Professors need to be added to this list if questionaires are used, or other WeBWorK problems which send e-mail as part of their answer mechanism.', type => 'list'}, + { var => 'permissionLevels{receive_feedback}', + doc => 'E-mail feedback from students automatically sent to this permission level and higher:', + doc2 => 'Users with this permssion level or greater will automatically be sent feedback from students (generated when they use the "Contact instructor" button on any problem page). In addition the feedback message will be sent to addresses listed below. To send ONLY to addresses listed below set permission level to "nobody".', + type => 'permission'}, + { var => 'mail{allowedFeedback}', - doc => 'Extra addresses for recieving feedback e-mail', - doc2 => 'By default, feeback is sent to all users who have permission to receive feedback. If this list is non-empty, feedback is also sent to the addresses specified here.', + doc => 'Additional addresses for receiving feedback e-mail.', + doc2 => 'By default, feeback is sent to all users above who have permission to receive feedback. Feedback is also sent to any addresses specified in this blank. (Separate email address entries by commas.', type => 'list'}, ] ]; |