[system] / trunk / webwork-modperl / lib / WeBWorK / ContentGenerator / Instructor / ProblemSetDetail.pm Repository:
ViewVC logotype

Diff of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2817 Revision 2834
274 # $inputType contains either an input box or a popup_menu for changing a given db field 274 # $inputType contains either an input box or a popup_menu for changing a given db field
275 my $inputType = ""; 275 my $inputType = "";
276 if ($edit) { 276 if ($edit) {
277 $inputType = CGI::input({ 277 $inputType = CGI::input({
278 name => "$recordType.$recordID.$field", 278 name => "$recordType.$recordID.$field",
279 value => $forUsers ? $userValue : $globalValue, 279 value => $r->param("$recordType.$recordID.$field") || ($forUsers ? $userValue : $globalValue),
280 size => $properties{size} || 5, 280 size => $properties{size} || 5,
281 }); 281 });
282 } elsif ($choose) { 282 } elsif ($choose) {
283 # Note that in popup menus, you're almost guaranteed to have the choices hashed to labels in %properties 283 # Note that in popup menus, you're almost guaranteed to have the choices hashed to labels in %properties
284 # but $userValue and and $globalValue are the values in the hash not the keys 284 # but $userValue and and $globalValue are the values in the hash not the keys
285 # so we have to use the actual db record field values to select our default here. 285 # so we have to use the actual db record field values to select our default here.
286 $inputType = CGI::popup_menu({ 286 $inputType = CGI::popup_menu({
287 name => "$recordType.$recordID.$field", 287 name => "$recordType.$recordID.$field",
288 values => $properties{choices}, 288 values => $properties{choices},
289 labels => \%labels, 289 labels => \%labels,
290 default => $forUsers ? $userRecord->$field : $globalRecord->$field, 290 default => $r->param("$recordType.$recordID.$field") || ($forUsers ? $userRecord->$field : $globalRecord->$field),
291 }); 291 });
292 } 292 }
293 293
294 return (($forUsers && $edit && $check) ? CGI::checkbox({ 294 return (($forUsers && $edit && $check) ? CGI::checkbox({
295 type => "checkbox", 295 type => "checkbox",
296 name => "$recordType.$recordID.$field.override", 296 name => "$recordType.$recordID.$field.override",
297 label => "", 297 label => "",
298 value => $field, 298 value => $field,
299 checked => ($userValue ne "" ? 1 : 0), 299 checked => $r->param("$recordType.$recordID.$field.override") || ($userValue ne "" ? 1 : 0),
300 }) : "", 300 }) : "",
301 $properties{name}, 301 $properties{name},
302 $inputType, 302 $inputType,
303 $forUsers ? " $globalValue" : "", 303 $forUsers ? " $globalValue" : "",
304 ); 304 );
640 $db->putUserProblem($record) if $changed; 640 $db->putUserProblem($record) if $changed;
641 } 641 }
642 } 642 }
643 } 643 }
644 } 644 }
645 645
646 # Delete all problems marked for deletion 646 # Delete all problems marked for deletion
647 foreach my $problemID ($r->param('deleteProblem')) { 647 foreach my $problemID ($r->param('deleteProblem')) {
648 $db->deleteGlobalProblem($setID, $problemID); 648 $db->deleteGlobalProblem($setID, $problemID);
649 } 649 }
650 650
651 # "Deleting" a header means setting it to "" so that the default header is used instead. 651 # Sets the specified header to "" so that the default file will get used.
652 foreach my $header ($r->param('deleteHeader')) { 652 foreach my $header ($r->param('defaultHeader')) {
653 $setRecord->$header(""); 653 $setRecord->$header("");
654 } 654 }
655 655 } elsif (defined $r->param('undo_changes')) {
656
657 # reset all the parameters dealing with set/problem/header information
658 # if the current naming scheme is changed/broken, this could reek havoc
659 # on all kinds of things
660 foreach my $param ($r->param) {
661 $r->param($param, "") if $param =~ /^(set|problem|header)\./;
662 }
663 }
664
656# Leftover code from when there were up/down buttons 665# Leftover code from when there were up/down buttons
657 666
658# } else { 667# } else {
659# # Look for up and down buttons 668# # Look for up and down buttons
660# my $index = 2; 669# my $index = 2;
670# if (defined $r->param("move.down.$index.x")) { 679# if (defined $r->param("move.down.$index.x")) {
671# moveme($index, $db, $setID, @problemList); 680# moveme($index, $db, $setID, @problemList);
672# } 681# }
673# $index++; 682# $index++;
674# } 683# }
675 } 684# }
685
676 686
677 687
678 # handle renumbering of problems if necessary 688 # handle renumbering of problems if necessary
679 print CGI::a({name=>"problems"}); 689 print CGI::a({name=>"problems"});
680 690
704sub changed ($$) { 714sub changed ($$) {
705 my ($first, $second) = @_; 715 my ($first, $second) = @_;
706 716
707 return "def/undef" if defined $first and not defined $second; 717 return "def/undef" if defined $first and not defined $second;
708 return "undef/def" if not defined $first and defined $second; 718 return "undef/def" if not defined $first and defined $second;
709 return 0 if not defined $first and not defined $second; 719 return "" if not defined $first and not defined $second;
710 return "ne" if $first ne $second; 720 return "ne" if $first ne $second;
711 return 0; # if they're equal, there's no change 721 return ""; # if they're equal, there's no change
712} 722}
713 723
714# helper method that determines if a given 724# helper method that determines for how many users at a time a field can be changed
715# none means it can't be changed for anyone 725# none means it can't be changed for anyone
716# any means it can be changed for anyone 726# any means it can be changed for anyone
717# one means it can ONLY be changed for one at a time. (eg problem_seed) 727# one means it can ONLY be changed for one at a time. (eg problem_seed)
718# all means it can ONLY be changed for all at a time. (eg set_header) 728# all means it can ONLY be changed for all at a time. (eg set_header)
719sub canChange ($$) { 729sub canChange ($$) {
727 return 0 if $howManyCan eq "none"; 737 return 0 if $howManyCan eq "none";
728 return 1 if $howManyCan eq "any"; 738 return 1 if $howManyCan eq "any";
729 return 1 if $howManyCan eq "one" && $forOneUser; 739 return 1 if $howManyCan eq "one" && $forOneUser;
730 return 1 if $howManyCan eq "all" && !$forUsers; 740 return 1 if $howManyCan eq "all" && !$forUsers;
731 return 0; # FIXME: maybe it should default to 1? 741 return 0; # FIXME: maybe it should default to 1?
742}
743
744# helper method that determines if a file is valid and returns a pretty error message
745sub checkFile ($) {
746 my ($self, $file) = @_;
747
748 my $r = $self->r;
749 my $ce = $r->ce;
750
751 return "No source file specified" unless $file;
752 $file = $ce->{courseDirs}->{templates} . '/' . $file unless $file =~ m|^/|;
753
754 my $text = "This source file ";
755 my $fileError;
756 return "" if -e $file && -f $file && -r $file;
757 return $text . "is not readable!" if -e $file && -f $file;
758 return $text . "is a directory!" if -d $file;
759 return $text . "does not exist!" unless -e $file;
760 return $text . "is not a plain file!";
732} 761}
733 762
734# Creates two separate tables, first of the headers, and the of the problems in a given set 763# Creates two separate tables, first of the headers, and the of the problems in a given set
735# If one or more users are specified in the "editForUser" param, only the data for those users 764# If one or more users are specified in the "editForUser" param, only the data for those users
736# becomes editable, not all the data 765# becomes editable, not all the data
843 } else { 872 } else {
844 print CGI::p(CGI::b("Any changes made below will be reflected in the set for ALL students.")); 873 print CGI::p(CGI::b("Any changes made below will be reflected in the set for ALL students."));
845 } 874 }
846 875
847 print CGI::start_form({method=>"POST", action=>$setDetailURL}); 876 print CGI::start_form({method=>"POST", action=>$setDetailURL});
877 print $self->hiddenEditForUserFields(@editForUser);
878 print $self->hidden_authen_fields;
848 print CGI::input({type=>"submit", name=>"submit_changes", value=>"Save Changes"}); 879 print CGI::input({type=>"submit", name=>"submit_changes", value=>"Save Changes"});
849 880 print CGI::input({type=>"submit", name=>"undo_changes", value => "Reset Form"});
881
850 # spacing 882 # spacing
851 print CGI::p(); 883 print CGI::p();
852 884
853 ##################################################################### 885 #####################################################################
854 # Display general set information 886 # Display general set information
870 902
871 ##################################################################### 903 #####################################################################
872 # Display header information 904 # Display header information
873 ##################################################################### 905 #####################################################################
874 my @headers = @{ HEADER_ORDER() }; 906 my @headers = @{ HEADER_ORDER() };
875 my %headerModules = (set_header => 'problem_list', 'hardcopy_header' => 'hardcopy_preselect_set'); 907 my %headerModules = (set_header => 'problem_list', hardcopy_header => 'hardcopy_preselect_set');
908 my %headerDefaults = (set_header => $ce->{webworkFiles}->{screenSnippets}->{setHeader}, hardcopy_header => $ce->{webworkFiles}->{hardcopySnippets}->{setHeader});
876 my @headerFiles = map { $setRecord->{$_} } @headers; 909 my @headerFiles = map { $setRecord->{$_} } @headers;
877 if (scalar @headers and not $forUsers) { 910 if (scalar @headers and not $forUsers) {
878 911
879 print CGI::start_table({border=>1, cellpadding=>4}); 912 print CGI::start_table({border=>1, cellpadding=>4});
880 print CGI::Tr({}, CGI::th({}, [ 913 print CGI::Tr({}, CGI::th({}, [
885 CGI::input({type => "submit", name => "refresh", value => "Refresh"}), 918 CGI::input({type => "submit", name => "refresh", value => "Refresh"}),
886 ])); 919 ]));
887 920
888 my %header_html; 921 my %header_html;
889 922
923 my %error;
890 foreach my $header (@headers) { 924 foreach my $header (@headers) {
925 my $headerFile = $r->param("set.$setID.$header") || $setRecord->{$header} || $headerDefaults{$header};
926
927 $error{$header} = $self->checkFile($headerFile);
928 unless ($error{$header}) {
891 my @temp = renderProblems( r=> $r, 929 my @temp = renderProblems( r=> $r,
892 user => $db->getUser($userToShow), 930 user => $db->getUser($userToShow),
893 displayMode=> $default_header_mode, 931 displayMode=> $default_header_mode,
894 problem_number=> 0, 932 problem_number=> 0,
895 this_set => $db->getMergedSet($userToShow, $setID), 933 this_set => $db->getMergedSet($userToShow, $setID),
896 problem_list => [$setRecord->{$header}], 934 problem_list => [$headerFile],
897 ); 935 );
898 $header_html{$header} = $temp[0]; 936 $header_html{$header} = $temp[0];
937 }
899 } 938 }
900 939
901 foreach my $header (@headers) { 940 foreach my $header (@headers) {
902 941
903 my $editHeaderPage = $urlpath->new(type => 'instructor_problem_editor_withset_withproblem', args => { courseID => $courseID, setID => $setID, problemID => 0 }); 942 my $editHeaderPage = $urlpath->new(type => 'instructor_problem_editor_withset_withproblem', args => { courseID => $courseID, setID => $setID, problemID => 0 });
909 print CGI::Tr({}, CGI::td({}, [ 948 print CGI::Tr({}, CGI::td({}, [
910 CGI::start_table({border => 0, cellpadding => 0}) . 949 CGI::start_table({border => 0, cellpadding => 0}) .
911 CGI::Tr({}, CGI::td({}, $properties{$header}->{name})) . 950 CGI::Tr({}, CGI::td({}, $properties{$header}->{name})) .
912 CGI::Tr({}, CGI::td({}, CGI::a({href => $editHeaderLink}, "Edit it"))) . 951 CGI::Tr({}, CGI::td({}, CGI::a({href => $editHeaderLink}, "Edit it"))) .
913 CGI::Tr({}, CGI::td({}, CGI::a({href => $viewHeaderLink}, "View it"))) . 952 CGI::Tr({}, CGI::td({}, CGI::a({href => $viewHeaderLink}, "View it"))) .
914 CGI::Tr({}, CGI::td({}, CGI::checkbox({name => "defaultHeader", value => $header, label => "Use Default"}))) . 953# CGI::Tr({}, CGI::td({}, CGI::checkbox({name => "defaultHeader", value => $header, label => "Use Default"}))) .
915 CGI::end_table(), 954 CGI::end_table(),
916# "", 955# "",
917# CGI::input({ name => "set.$setID.$header", value => $setRecord->{$header}, size => 50}) . 956# CGI::input({ name => "set.$setID.$header", value => $setRecord->{$header}, size => 50}) .
918# join ("\n", $self->FieldHTML($userToShow, $setID, $problemID, "source_file")) . 957# join ("\n", $self->FieldHTML($userToShow, $setID, $problemID, "source_file")) .
919# CGI::br() . CGI::div({class=> "RenderSolo"}, $problem_html[0]->{body_text}), 958# CGI::br() . CGI::div({class=> "RenderSolo"}, $problem_html[0]->{body_text}),
920 959
921 comboBox({ 960 comboBox({
922 name => "set.$setID.$header", 961 name => "set.$setID.$header",
923 request => $r, 962 request => $r,
924 default => $setRecord->{$header}, 963 default => $r->param("set.$setID.$header") || $setRecord->{$header},
925 multiple => 0, 964 multiple => 0,
926 values => ["", @headerFileList], 965 values => ["", @headerFileList],
927 labels => { "" => "Use Default Header File" }, 966 labels => { "" => "Use Default Header File" },
928 }) . 967 }) .
968 ($error{$header} ?
969 CGI::div({class=>"ResultsWithError", style=>"font-weight: bold"}, $error{$header})
929 CGI::div({class=> "RenderSolo"}, $header_html{$header}->{body_text}), 970 : CGI::div({class=> "RenderSolo"}, $header_html{$header}->{body_text})
971 ),
930 ])); 972 ]));
931 } 973 }
932 974
933 print CGI::end_table(); 975 print CGI::end_table();
934 } else { 976 } else {
955 "Display Mode: " . 997 "Display Mode: " .
956 CGI::popup_menu(-name => "problem.displaymode", -values => \@active_modes, -default => $default_problem_mode) . ' '. 998 CGI::popup_menu(-name => "problem.displaymode", -values => \@active_modes, -default => $default_problem_mode) . ' '.
957 CGI::input({type => "submit", name => "refresh", value => "Refresh"}), 999 CGI::input({type => "submit", name => "refresh", value => "Refresh"}),
958 ])); 1000 ]));
959 1001
1002 my %shownYet;
1003 my $repeatFile;
960 foreach my $problemID (@problemIDList) { 1004 foreach my $problemID (@problemIDList) {
961 1005
962 my $problemRecord; 1006 my $problemRecord;
963 if ($forOneUser) { 1007 if ($forOneUser) {
964 $problemRecord = $db->getMergedProblem($editForUser[0], $setID, $problemID); 1008 $problemRecord = $db->getMergedProblem($editForUser[0], $setID, $problemID);
974 my $viewProblemLink = $self->systemLink($viewProblemPage, params => { effectiveUser => ($forOneUser ? $editForUser[0] : $userID)}); 1018 my $viewProblemLink = $self->systemLink($viewProblemPage, params => { effectiveUser => ($forOneUser ? $editForUser[0] : $userID)});
975 1019
976 my @fields = @{ PROBLEM_FIELDS() }; 1020 my @fields = @{ PROBLEM_FIELDS() };
977 push @fields, @{ USER_PROBLEM_FIELDS() } if $forOneUser; 1021 push @fields, @{ USER_PROBLEM_FIELDS() } if $forOneUser;
978 1022
1023 my $problemFile = $r->param("problem.$problemID.source_file") || $problemRecord->source_file;
1024
1025 # warn of repeat problems
1026 if (defined $shownYet{$problemFile}) {
1027 $repeatFile = "This problem uses the same source file as number " . $shownYet{$problemFile} . ".";
1028 } else {
1029 $shownYet{$problemFile} = $problemID;
1030 }
1031
1032 my $error = $self->checkFile($problemFile);
1033 my @problem_html;
1034 unless ($error) {
979 my @problem_html = renderProblems( r=> $r, 1035 @problem_html = renderProblems( r=> $r,
980 user => $db->getUser($userToShow), 1036 user => $db->getUser($userToShow),
981 displayMode=> $default_problem_mode, 1037 displayMode=> $default_problem_mode,
982 problem_number=> $problemID, 1038 problem_number=> $problemID,
983 this_set => $db->getMergedSet($userToShow, $setID), 1039 this_set => $db->getMergedSet($userToShow, $setID),
984 problem_seed => $forOneUser ? $problemRecord->problem_seed : 0, 1040 problem_seed => $forOneUser ? $problemRecord->problem_seed : 0,
985 problem_list => [$problemRecord->source_file], 1041 problem_list => [$problemRecord->source_file],
986 ); 1042 );
1043 }
987 1044
988 print CGI::Tr({}, CGI::td({}, [ 1045 print CGI::Tr({}, CGI::td({}, [
989 CGI::start_table({border => 0, cellpadding => 1}) . 1046 CGI::start_table({border => 0, cellpadding => 1}) .
990 CGI::Tr({}, CGI::td({}, problem_number_popup($problemID, $maxProblemNumber))) . 1047 CGI::Tr({}, CGI::td({}, problem_number_popup($problemID, $maxProblemNumber))) .
991 CGI::Tr({}, CGI::td({}, CGI::a({href => $editProblemLink}, "Edit it"))) . 1048 CGI::Tr({}, CGI::td({}, CGI::a({href => $editProblemLink}, "Edit it"))) .
1002# multiple => 0, 1059# multiple => 0,
1003# values => \@problemFileList, 1060# values => \@problemFileList,
1004# }) . 1061# }) .
1005 1062
1006 join ("\n", $self->FieldHTML($userToShow, $setID, $problemID, "source_file")) . 1063 join ("\n", $self->FieldHTML($userToShow, $setID, $problemID, "source_file")) .
1064 CGI::br() .
1065 ($error ?
1066 CGI::div({class=>"ResultsWithError", style=>"font-weight: bold"}, $error)
1007 CGI::br() . CGI::div({class=> "RenderSolo"}, $problem_html[0]->{body_text}), 1067 : CGI::div({class=> "RenderSolo"}, $problem_html[0]->{body_text})
1068 ) .
1069 ($repeatFile ? CGI::div({class=>"ResultsWithError", style=>"font-weight: bold"}, $repeatFile) : ''),
1008 ])); 1070 ]));
1009 } 1071 }
1010 1072
1011 print CGI::end_table(); 1073 print CGI::end_table();
1012 print $self->hiddenEditForUserFields(@editForUser);
1013 print $self->hidden_authen_fields;
1014 print CGI::checkbox({ 1074 print CGI::checkbox({
1015 label=> "Force problems to be numbered consecutively from one", 1075 label=> "Force problems to be numbered consecutively from one",
1016 name=>"force_renumber", value=>"1"}), 1076 name=>"force_renumber", value=>"1"}),
1017 1077
1018 CGI::br(); 1078 CGI::br();

Legend:
Removed from v.2817  
changed lines
  Added in v.2834

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9