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

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

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

Revision 2021 Revision 2450
1################################################################################ 1################################################################################
2# WeBWorK Online Homework Delivery System 2# WeBWorK Online Homework Delivery System
3# Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/ 3# Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4# $CVSHeader: $ 4# $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm,v 1.21 2004/07/01 20:31:13 dpvc Exp $
5# 5#
6# This program is free software; you can redistribute it and/or modify it under 6# This program is free software; you can redistribute it and/or modify it under
7# the terms of either: (a) the GNU General Public License as published by the 7# the terms of either: (a) the GNU General Public License as published by the
8# Free Software Foundation; either version 2, or (at your option) any later 8# Free Software Foundation; either version 2, or (at your option) any later
9# version, or (b) the "Artistic License" which comes with this package. 9# version, or (b) the "Artistic License" which comes with this package.
32use WeBWorK::Utils qw(readDirectory max); 32use WeBWorK::Utils qw(readDirectory max);
33use WeBWorK::Utils::Tasks qw(renderProblems); 33use WeBWorK::Utils::Tasks qw(renderProblems);
34 34
35require WeBWorK::Utils::ListingDB; 35require WeBWorK::Utils::ListingDB;
36 36
37
38use constant MAX_SHOW => 20; 37use constant MAX_SHOW_DEFAULT => 20;
38use constant NO_LOCAL_SET_STRING => 'There are no local sets yet';
39use constant SELECT_SET_STRING => 'Select a Set for This Course';
40use constant SELECT_LOCAL_STRING => 'Select a Problem Collection';
41use constant MY_PROBLEMS => ' My Problems ';
42use constant MAIN_PROBLEMS => ' Main Problems ';
39 43
44## Flags for operations on files
45
46use constant ADDED => 1;
47use constant HIDDEN => (1 << 1);
48use constant SUCCESS => (1 << 2);
49
50## for additional problib buttons
51my %problib; ## filled in in global.conf
52my %ignoredir = ('.' => 1, '..' => 1, 'Library' => 1);
53
54## This is for searching the disk for directories containing pg files.
40## to make the recursion work, this returns an array where the first 55## to make the recursion work, this returns an array where the first
41## item is 1 or 0 depending on whether or not the current 56## item is 1 or 0 depending on whether or not the current
42## directory has any pg files. The second is a list of directories 57## directory has any pg files. The second is a list of directories
43## which contain pg files. 58## which contain pg files.
44sub get_library_sets { 59sub get_library_sets {
60 my $amtop = shift;
45 my $topdir = shift; 61 my $topdir = shift;
46 my @lis = readDirectory($topdir); 62 my @lis = readDirectory($topdir);
47 my @pgs = grep { m/\.pg$/ and (not m/Header\.pg/) and -f "$topdir/$_"} @lis; 63 my @pgs = grep { m/\.pg$/ and (not m/(Header|-text)\.pg/) and -f "$topdir/$_"} @lis;
48 my $havepg = scalar(@pgs)>0 ? 1 : 0; 64 my $havepg = scalar(@pgs)>0 ? 1 : 0;
49 my @mdirs = grep {$_ ne "." and $_ ne ".." and $_ ne "Library" 65 my @mdirs = grep {!defined($ignoredir{$_}) and -d "$topdir/$_"} @lis;
50 and -d "$topdir/$_"} @lis; 66 if ($amtop) {@mdirs = grep {!defined($problib{$_})} @mdirs}
51 my ($adir, @results, @thisresult); 67 my ($adir, @results, @thisresult);
52 for $adir (@mdirs) { 68 for $adir (@mdirs) {
53 @results = get_library_sets("$topdir/$adir"); 69 @results = get_library_sets(0, "$topdir/$adir");
54 my $isadirok = shift @results; 70 my $isadirok = shift @results;
55 @thisresult = (@thisresult, @results); 71 @thisresult = (@thisresult, @results);
56 if ($isadirok) { 72 if ($isadirok) {
57 @thisresult = ("$topdir/$adir", @thisresult); 73 @thisresult = ("$topdir/$adir", @thisresult);
58 } 74 }
64sub list_pg_files { 80sub list_pg_files {
65 my $templatedir = shift; 81 my $templatedir = shift;
66 my $topdir = shift; 82 my $topdir = shift;
67 83
68 my @lis = readDirectory("$templatedir/$topdir"); 84 my @lis = readDirectory("$templatedir/$topdir");
69 my @pgs = grep { m/\.pg$/ and (not m/Header\.pg/) and -f "$templatedir/$topdir/$_"} @lis; 85 my @pgs = grep { m/\.pg$/ and (not m/(Header|-text)\.pg/) and -f "$templatedir/$topdir/$_"} @lis;
70 @pgs = map { "$topdir/$_" } @pgs; 86 @pgs = map { "$topdir/$_" } @pgs;
71 return(@pgs); 87 return(@pgs);
72}
73
74## Maybe I should use this instead, returns a list
75sub get_global_set_defs {
76 my $db = shift;
77
78 my @globalSetIDs = $db->listGlobalSets;
79 return(@globalSetIDs);
80} 88}
81 89
82## go through past page getting a list of identifiers for the problems 90## go through past page getting a list of identifiers for the problems
83## and whether or not they are selected, and whether or not they should 91## and whether or not they are selected, and whether or not they should
84## be hidden 92## be hidden
86sub get_past_problem_files { 94sub get_past_problem_files {
87 my $r = shift; 95 my $r = shift;
88 my @found=(); 96 my @found=();
89 my $count =1; 97 my $count =1;
90 while (defined($r->param("filetrial$count"))) { 98 while (defined($r->param("filetrial$count"))) {
99 my $val = 0;
100 $val |= ADDED if($r->param("trial$count"));
101 $val |= HIDDEN if($r->param("hideme$count"));
91 push @found, [$r->param("filetrial$count"), 102 push @found, [$r->param("filetrial$count"), $val];
92 defined($r->param("trial$count")) ? $r->param("trial$count"):0,
93 defined($r->param("hideme$count")) ?$r->param("hideme$count"):0];
94 $count++; 103 $count++;
95 } 104 }
96 return(@found); 105 return(\@found);
97} 106}
98 107
99#### For adding new problems 108#### For adding new problems
100 109
101sub add_selected { 110sub add_selected {
102 my $self = shift; 111 my $self = shift;
103 my $db = shift; 112 my $db = shift;
104 my $setName = shift; 113 my $setName = shift;
114 my @past_problems = @{$self->{past_problems}};
105 my @selected = @_; 115 my @selected = @past_problems;
106 my (@path, $file, $selected, $freeProblemID); 116 my (@path, $file, $selected, $freeProblemID);
107 $freeProblemID = max($db->listGlobalProblems($setName)) + 1; 117 $freeProblemID = max($db->listGlobalProblems($setName)) + 1;
118 my $addedcount=0;
108 119
109 for $selected (@selected) { 120 for $selected (@selected) {
121 if($selected->[1] & ADDED) {
110 $file = $selected; 122 $file = $selected->[0];
111 @path = split "/", $selected; 123 my $problemRecord = $self->addProblemToSet(setName => $setName,
112 pop @path; # Remove the file name from the path 124 sourceFile => $file, problemID => $freeProblemID);
113 shift @path if $path[0] eq ""; # remove the null element from the begining 125 $freeProblemID++;
114 my $problemRecord = $db->newGlobalProblem();
115 $problemRecord->problem_id($freeProblemID++);
116 $problemRecord->set_id($setName);
117 $problemRecord->source_file($file);
118 $problemRecord->value("1");
119 $problemRecord->max_attempts("-1");
120 $db->addGlobalProblem($problemRecord);
121 $self->assignProblemToAllSetUsers($problemRecord); 126 $self->assignProblemToAllSetUsers($problemRecord);
127 $selected->[1] |= SUCCESS;
128 $addedcount++;
122 } 129 }
130 }
131 return($addedcount);
123} 132}
124 133
125 134
126############# List of library sets 135############# List of sets of problems in templates directory
127 136
128sub getalllibsets { 137sub get_problem_directories {
129 my $ce = shift; 138 my $ce = shift;
130 my @all_library_sets = get_library_sets($ce->{courseDirs}->{templates}); 139 my $lib = shift;
131 shift @all_library_sets; 140 my $source = $ce->{courseDirs}{templates};
141 my $main = MY_PROBLEMS; my $isTop = 1;
142 if ($lib) {$source .= "/$lib"; $main = MAIN_PROBLEMS; $isTop = 0}
143 my @all_problem_directories = get_library_sets($isTop, $source);
144 my $includetop = shift @all_problem_directories;
132 my $j; 145 my $j;
133 for ($j=0; $j<scalar(@all_library_sets); $j++) { 146 for ($j=0; $j<scalar(@all_problem_directories); $j++) {
134 $all_library_sets[$j] =~ s|^$ce->{courseDirs}->{templates}/?||; 147 $all_problem_directories[$j] =~ s|^$ce->{courseDirs}->{templates}/?||;
148 }
149 @all_problem_directories = sort @all_problem_directories;
150 unshift @all_problem_directories, $main if($includetop);
151 return (\@all_problem_directories);
152}
153
154############# Everyone has a view problems line. Abstract it
155sub view_problems_line {
156 my $internal_name = shift;
157 my $label = shift;
158 my $r = shift; # so we can get parameter values
159 my $result = CGI::submit(-name=>"$internal_name", -value=>$label);
160
161 my %display_modes = %{WeBWorK::PG::DISPLAY_MODES()};
162 my @active_modes = grep { exists $display_modes{$_} }
163 @{$r->ce->{pg}->{displayModes}};
164 push @active_modes, 'None';
165 # We have our own displayMode since its value may be None, which is illegal
166 # in other modules.
167 my $mydisplayMode = $r->param('mydisplayMode') || $r->ce->{pg}->{options}->{displayMode};
168 $result .= '&nbsp;Display&nbsp;Mode:&nbsp;'.CGI::popup_menu(-name=> 'mydisplayMode',
169 -values=>\@active_modes,
170 -default=> $mydisplayMode);
171 # Now we give a choice of the number of problems to show
172 my $defaultMax = $r->param('max_shown') || MAX_SHOW_DEFAULT;
173 $result .= '&nbsp;Max. Shown:&nbsp'.
174 CGI::popup_menu(-name=> 'max_shown',
175 -values=>[5,10,15,20,25,30,50,'All'],
176 -default=> $defaultMax);
135 } 177
136 @all_library_sets = sort @all_library_sets; 178 return($result);
137 return (\@all_library_sets);
138} 179}
180
139 181
140### The browsing panel has three versions 182### The browsing panel has three versions
141##### Version 1 is local problems 183##### Version 1 is local problems
142sub browse_local_panel { 184sub browse_local_panel {
143 my $self = shift; 185 my $self = shift;
144 my $library_selected = shift; 186 my $library_selected = shift;
187 my $lib = shift || ''; $lib =~ s/^browse_//;
188 my $name = ($lib eq '')? 'Local' : $problib{$lib};
145 189
146 my $list_of_sets= getalllibsets($self->r->ce); 190 my $list_of_prob_dirs= get_problem_directories($self->r->ce,$lib);
147 my $libstr = ""; 191 if(scalar(@$list_of_prob_dirs) == 0) {
148 my $default_value = "Select a Local Problem Collection"; 192 $library_selected = "Found no directories containing problems";
149 $libstr = CGI::br() . CGI::em($self->{libmsg}) if($self->{libmsg}); 193 unshift @{$list_of_prob_dirs}, $library_selected;
150 194 } else {
195 my $default_value = SELECT_LOCAL_STRING;
151 if (not $library_selected or $library_selected eq $default_value) { 196 if (not $library_selected or $library_selected eq $default_value) {
152 unshift @{$list_of_sets}, $default_value; 197 unshift @{$list_of_prob_dirs}, $default_value;
153 $library_selected = $default_value; 198 $library_selected = $default_value;
154 } 199 }
155
156 200 }
201 my $view_problem_line = view_problems_line('view_local_set', 'View Problems', $self->r);
157 print CGI::Tr(CGI::td({-class=>"InfoPanel"}, "Local Problems: ", 202 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "$name Problems: ",
158 CGI::popup_menu(-name=> 'library_sets', 203 CGI::popup_menu(-name=> 'library_sets',
159 -values=>$list_of_sets, 204 -values=>$list_of_prob_dirs,
160 -default=> $library_selected), 205 -default=> $library_selected),
161 CGI::br(), 206 CGI::br(),
162 CGI::submit(-name=>"view_local_set", -value=>"View Problems"), 207 $view_problem_line,
163 $libstr
164 )); 208 ));
165} 209}
166 210
167##### Version 2 is local problem sets 211##### Version 2 is local problem sets
168sub browse_mysets_panel { 212sub browse_mysets_panel {
169 my $self = shift; 213 my $self = shift;
170 my $library_selected = shift; 214 my $library_selected = shift;
171 my $list_of_local_sets = shift; 215 my $list_of_local_sets = shift;
172 my $default_value = "Select a Problem Set"; 216 my $default_value = "Select a Problem Set";
173 217
174 my $libstr = CGI::br() . CGI::em($self->{libmsg}) if($self->{libmsg}); 218 if(scalar(@$list_of_local_sets) == 0) {
175 219 $list_of_local_sets = [NO_LOCAL_SET_STRING];
176 if (not $library_selected or $library_selected eq $default_value) { 220 } elsif (not $library_selected or $library_selected eq $default_value) {
177 unshift @{$list_of_local_sets}, $default_value; 221 unshift @{$list_of_local_sets}, $default_value;
178 $library_selected = $default_value; 222 $library_selected = $default_value;
179 } 223 }
180 224
225 my $view_problem_line = view_problems_line('view_mysets_set', 'View Problems', $self->r);
181 print CGI::Tr(CGI::td({-class=>"InfoPanel"}, "Browse from: ", 226 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "Browse from: ",
182 CGI::popup_menu(-name=> 'library_sets', 227 CGI::popup_menu(-name=> 'library_sets',
183 -values=>$list_of_local_sets, 228 -values=>$list_of_local_sets,
184 -default=> $library_selected), 229 -default=> $library_selected),
185 CGI::br(), 230 CGI::br(),
186 CGI::submit(-name=>"view_mysets_set", -value=>"View This Set"), 231 $view_problem_line
187 $libstr
188 )); 232 ));
189} 233}
190 234
191##### Version 3 is the problem library 235##### Version 3 is the problem library
192 236
196# 240#
197# Incoming data - current chapter, current section 241# Incoming data - current chapter, current section
198sub browse_library_panel { 242sub browse_library_panel {
199 my $self = shift; 243 my $self = shift;
200 my $r = $self->r; 244 my $r = $self->r;
245 my $ce = $r->ce;
201 246
202 my $libraryRoot = $r->{ce}->{webworkDirs}->{libraryRoot}; 247 my $libraryRoot = $r->{ce}->{problemLibrary}->{root};
203 248
204 unless($libraryRoot) { 249 unless($libraryRoot) {
205 print CGI::Tr(CGI::td(CGI::div({class=>'ResultsWithError', align=>"center"}, 250 print CGI::Tr(CGI::td(CGI::div({class=>'ResultsWithError', align=>"center"},
206 "The problem library has not been installed."))); 251 "The problem library has not been installed.")));
207 return; 252 return;
208 } 253 }
254 # Test if the Library directory exists. If not, try to make it
255 unless(-d "$ce->{courseDirs}->{templates}/Library") {
256 unless(symlink($libraryRoot, "$ce->{courseDirs}->{templates}/Library")) {
257 my $msg = <<"HERE";
258You are missing the directory <code>templates/Library</code>, which is needed
259for the Problem Library to function. It should be a link pointing to
260<code>$libraryRoot</code>, which you set in <code>conf/global.conf</code>.
261I tried to make the link for you, but that failed. Check the permissions
262in your <code>templates</code> directory.
263HERE
264 $self->addbadmessage($msg);
265 }
266 }
209 267
210 my $default_chap = "All Chapters"; 268 my $default_chap = "All Chapters";
211 my $default_sect = "All Sections"; 269 my $default_sect = "All Sections";
212
213 my $libstr = CGI::br() . CGI::em($self->{libmsg}) if($self->{libmsg});
214 270
215 my @chaps = WeBWorK::Utils::ListingDB::getAllChapters($r->{ce}); 271 my @chaps = WeBWorK::Utils::ListingDB::getAllChapters($r->{ce});
216 unshift @chaps, $default_chap; 272 unshift @chaps, $default_chap;
217 my $chapter_selected = $r->param('library_chapters') || $default_chap; 273 my $chapter_selected = $r->param('library_chapters') || $default_chap;
218 274
223 279
224 my @textbooks = ('Textbook info not ready'); 280 my @textbooks = ('Textbook info not ready');
225 281
226 unshift @sects, $default_sect; 282 unshift @sects, $default_sect;
227 my $section_selected = $r->param('library_sections') || $default_sect; 283 my $section_selected = $r->param('library_sections') || $default_sect;
284 my $view_problem_line = view_problems_line('lib_view', 'View Problems', $self->r);
228 285
229 print CGI::Tr(CGI::td({-class=>"InfoPanel"}, 286 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"},
230 CGI::start_table(), 287 CGI::start_table(),
231 CGI::Tr( 288 CGI::Tr(
232 CGI::td(["Chapter:", 289 CGI::td(["Chapter:",
233 CGI::popup_menu(-name=> 'library_chapters', 290 CGI::popup_menu(-name=> 'library_chapters',
234 -values=>\@chaps, 291 -values=>\@chaps,
255# CGI::Tr( 312# CGI::Tr(
256# CGI::td("Keywords:"), 313# CGI::td("Keywords:"),
257# CGI::td({-colspan=>2}, CGI::textfield(-name=>"keywords", 314# CGI::td({-colspan=>2}, CGI::textfield(-name=>"keywords",
258# -default=>"Keywords not implemented yet", 315# -default=>"Keywords not implemented yet",
259# -override=>1, -size=>60))), 316# -override=>1, -size=>60))),
260 CGI::Tr(CGI::td({-colspan=>3},CGI::submit(-name=>"lib_view", -value=>"View Problems"))), 317 CGI::Tr(CGI::td({-colspan=>3},
318 $view_problem_line)),
261 CGI::end_table(), 319 CGI::end_table(),
262 $libstr
263 )); 320 ));
264} 321}
265 322
266sub make_top_row { 323sub make_top_row {
267 my $self = shift; 324 my $self = shift;
268 my $r = $self->r; 325 my $r = $self->r;
326 my $ce = $r->ce;
269 my %data = @_; 327 my %data = @_;
270 328
271 my $list_of_local_sets = $data{all_set_defs}; 329 my $list_of_local_sets = $data{all_set_defs};
330 my $have_local_sets = scalar(@$list_of_local_sets);
272 my $browse_which = $data{browse_which}; 331 my $browse_which = $data{browse_which};
273 my $library_selected = $r->param('library_sets'); 332 my $library_selected = $r->param('library_sets');
274 my $set_selected = $r->param('local_sets'); 333 my $set_selected = $r->param('local_sets');
275 334
276 my $list_of_sets;
277 my ($dis1, $dis2, $dis3) = ("","",""); 335 my ($dis1, $dis2, $dis3) = ("","","");
278 $dis1 = '-disabled' if($browse_which eq 'browse_library'); 336 $dis1 = '-disabled' if($browse_which eq 'browse_library');
279 $dis2 = '-disabled' if($browse_which eq 'browse_local'); 337 $dis2 = '-disabled' if($browse_which eq 'browse_local');
280 $dis3 = '-disabled' if($browse_which eq 'browse_mysets'); 338 $dis3 = '-disabled' if($browse_which eq 'browse_mysets');
281 339
282 my $locstr = ""; 340 ## Make buttons for additional problem libraries
283 $locstr = CGI::br() . CGI::em($self->{localmsg}) if($self->{localmsg}); 341 my $libs = '';
342 foreach my $lib (sort(keys(%problib))) {
343 $libs .= ' '. CGI::submit(-name=>"browse_$lib", -value=>$problib{$lib},
344 ($browse_which eq "browse_$lib")? '-disabled': '')
345 if (-d "$ce->{courseDirs}{templates}/$lib");
346 }
347 $libs = CGI::br()."or Problems from".$libs if $libs ne '';
284 348
285 my $these_widths = "width: 27ex"; 349 my $these_widths = "width: 20ex";
286 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"}, 350 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
351 "Browse ",
287 CGI::submit(-name=>"browse_library", -value=>"Browse Problem Library", -style=>$these_widths, $dis1), 352 CGI::submit(-name=>"browse_library", -value=>"Problem Library", -style=>$these_widths, $dis1),
288 CGI::submit(-name=>"browse_local", -value=>"Browse Local Problems", -style=>$these_widths, $dis2), 353 CGI::submit(-name=>"browse_local", -value=>"Local Problems", -style=>$these_widths, $dis2),
289 CGI::submit(-name=>"browse_mysets", -value=>"Browse From This Course", -style=>$these_widths, $dis3), 354 CGI::submit(-name=>"browse_mysets", -value=>"From This Course", -style=>$these_widths, $dis3),
355 $libs,
290 )); 356 ));
291 357
292 print CGI::Tr(CGI::td({-bgcolor=>"black"})); 358 print CGI::Tr(CGI::td({-bgcolor=>"black"}));
293 359
294 if ($browse_which eq 'browse_local') { 360 if ($browse_which eq 'browse_local') {
295 browse_local_panel($self, $library_selected); 361 $self->browse_local_panel($library_selected);
296 } elsif ($browse_which eq 'browse_mysets') { 362 } elsif ($browse_which eq 'browse_mysets') {
297 browse_mysets_panel($self, $library_selected, $list_of_local_sets); 363 $self->browse_mysets_panel($library_selected, $list_of_local_sets);
298 } else { 364 } elsif ($browse_which eq 'browse_library') {
299 browse_library_panel($self); 365 $self->browse_library_panel();
366 } else { ## handle other problem libraries
367 $self->browse_local_panel($library_selected,$browse_which);
300 } 368 }
301 369
302 print CGI::Tr(CGI::td({-bgcolor=>"black"})); 370 print CGI::Tr(CGI::td({-bgcolor=>"black"}));
303 371
304 if (not $set_selected or $set_selected eq "Select a Set for This Course") { 372 if($have_local_sets ==0) {
373 $list_of_local_sets = [NO_LOCAL_SET_STRING];
374 } elsif (not $set_selected or $set_selected eq SELECT_SET_STRING) {
305 if ($list_of_local_sets->[0] eq "Select a Problem Set") { 375 if ($list_of_local_sets->[0] eq "Select a Problem Set") {
306 shift @{$list_of_local_sets}; 376 shift @{$list_of_local_sets};
307 } 377 }
308 unshift @{$list_of_local_sets}, "Select a Set for This Course"; 378 unshift @{$list_of_local_sets}, SELECT_SET_STRING;
309 $set_selected = "Select a Set for This Course"; 379 $set_selected = SELECT_SET_STRING;
310 } 380 }
381 my $myjs = 'document.mainform.selfassign.value=confirm("Should I assign the new set to you now?\nUse OK for yes and Cancel for no.");true;';
311 382
312 print CGI::Tr(CGI::td({-class=>"InfoPanel"}, "Current Set: ", 383 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "Adding Problems to ",
384 CGI::b("Target Set: "),
313 CGI::popup_menu(-name=> 'local_sets', 385 CGI::popup_menu(-name=> 'local_sets',
314 -values=>$list_of_local_sets, 386 -values=>$list_of_local_sets,
315 -default=> $set_selected), 387 -default=> $set_selected),
316 CGI::submit(-name=>"edit_local", -value=>"Edit Current Set"), 388 CGI::submit(-name=>"edit_local", -value=>"Edit Target Set"),
389 CGI::hidden(-name=>"selfassign", -default=>[0]).
317 CGI::br(), 390 CGI::br(),
318 CGI::br(), 391 CGI::br(),
319 CGI::submit(-name=>"new_local_set", -value=>"Create New Local Set:"), 392 CGI::submit(-name=>"new_local_set", -value=>"Create a New Set in This Course:",
393 -onclick=>$myjs
394 ),
320 " ", 395 " ",
321 CGI::textfield(-name=>"new_set_name", 396 CGI::textfield(-name=>"new_set_name",
322 -default=>"Name for new set here", 397 -default=>"Name for new set here",
323 -override=>1, -size=>30), 398 -override=>1, -size=>30),
324 CGI::br(), 399 CGI::br(),
325 $locstr
326 )); 400 ));
327 401
328 print CGI::Tr(CGI::td({-bgcolor=>"black"})); 402 print CGI::Tr(CGI::td({-bgcolor=>"black"}));
329 403
330 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"}, 404 print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
405 CGI::start_table({-border=>"0"}),
406 CGI::Tr( CGI::td({ -align=>"center"},
407 CGI::submit(-name=>"select_all", -style=>$these_widths,
408 -value=>"Mark All For Adding"),
331 CGI::submit(-name=>"update", -style=>$these_widths, 409 CGI::submit(-name=>"select_none", -style=>$these_widths,
332 -value=>"Act on Marked Problems"), 410 -value=>"Clear All Marks"),
411 )),
412 CGI::Tr( CGI::td(
413 CGI::submit(-name=>"update", -style=>$these_widths. "; font-weight:bold",
414 -value=>"Update"),
333 CGI::submit(-name=>"rerandomize", 415 CGI::submit(-name=>"rerandomize",
334 -style=>$these_widths, 416 -style=>$these_widths,
335 -value=>"Rerandomize"), 417 -value=>"Rerandomize"),
336 CGI::submit(-name=>"cleardisplay", 418 CGI::submit(-name=>"cleardisplay",
337 -style=>$these_widths, 419 -style=>$these_widths,
338 -value=>"Clear Problem Display"))); 420 -value=>"Clear Problem Display")
421 )),
422 CGI::end_table()));
339 423
340} 424}
341 425
342sub make_data_row { 426sub make_data_row {
343 my $self = shift; 427 my $self = shift;
344 my $sourceFileName = shift; 428 my $sourceFileName = shift;
345 my $pg = shift; 429 my $pg = shift;
346 my $cnt = shift; 430 my $cnt = shift;
431 my $mark = shift || 0;
432
433 $sourceFileName =~ s|^./||; # clean up top ugliness
347 434
348 my $urlpath = $self->r->urlpath; 435 my $urlpath = $self->r->urlpath;
349 my $problem_output = $pg->{flags}->{error_flag} ? 436 my $problem_output = $pg->{flags}->{error_flag} ?
350 CGI::em("This problem produced an error") 437 CGI::div({class=>"ResultsWithError"}, CGI::em("This problem produced an error"))
351 : CGI::div({class=>"RenderSolo"}, $pg->{body_text}); 438 : CGI::div({class=>"RenderSolo"}, $pg->{body_text});
352 439
353 440
354 my $edit_link = CGI::a({href=>$self->systemLink( 441 my $edit_link = '';
355 $urlpath->new(type=>'instructor_problem_editor_withset_withproblem', 442 #if($self->{r}->param('browse_which') ne 'browse_library') {
443 if($sourceFileName !~ /^Library\//) {
444 $edit_link = CGI::a({href=>$self->systemLink($urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
356 args=>{courseID =>$urlpath->arg("courseID"), 445 courseID =>$urlpath->arg("courseID"),
357 setID=>"Undefined_Set", problemID=>"1" } 446 setID=>"Undefined_Set",
447 problemID=>"1"),
358 ), params=>{sourceFilePath => "$sourceFileName"} 448 params=>{sourceFilePath => "$sourceFileName"}
359 )}, "Edit it" ); 449 )}, "Edit it" );
450 }
360 451
361 my $try_link = CGI::a({href=>$self->systemLink( $urlpath->new(type=>'problem_detail', 452 my $try_link = CGI::a({href=>$self->systemLink($urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
362 args=>{courseID =>$urlpath->arg("courseID"), 453 courseID =>$urlpath->arg("courseID"),
363 setID=>"Undefined_Set", problemID=>"1"} 454 setID=>"Undefined_Set",
364 ), 455 problemID=>"1"),
365 params =>{effectiveUser => $self->r->param('user'), 456 params =>{effectiveUser => $self->r->param('user'),
366 editMode => "SetMaker", 457 editMode => "SetMaker",
367 sourceFilePath => "$sourceFileName"} )}, "Try it"); 458 sourceFilePath => "$sourceFileName"} )}, "Try it");
368 459
369 460 my %add_box_data = ( -name=>"trial$cnt",-value=>1,-label=>"Add me to the current set on the next update");
461 if($mark & SUCCESS) {
462 $add_box_data{ -label } .= " (just added this problem)";
463 } elsif($mark & ADDED) {
464 $add_box_data{ -checked } = 1;
465 }
370 466
371 print CGI::Tr({-align=>"left"}, CGI::td( 467 print CGI::Tr({-align=>"left"}, CGI::td(
372 468
373 CGI::div({-style=>"background-color: #DDDDDD"},"File name: $sourceFileName ", 469 CGI::div({-style=>"background-color: #DDDDDD; margin: 0px auto"},
374 #$edit_link, " ", 470CGI::span({-style=>"float:left ; text-align: left"},"File name: $sourceFileName "),
375 $try_link 471CGI::span({-style=>"float:right ; text-align: right"}, $edit_link, " ", $try_link)
376 ), 472 ), CGI::br(),
377 473
378 474
379 475
380 476
381 CGI::checkbox(-name=>"hideme$cnt",-value=>1,-label=>"Don't show me on the next update"), 477 CGI::checkbox(-name=>"hideme$cnt",-value=>1,-label=>"Don't show me on the next update"),
382 CGI::br(), 478 CGI::br(),
383 CGI::checkbox(-name=>"trial$cnt",-value=>1,-label=>"Add me to the current set on the next update"), 479 CGI::checkbox((%add_box_data)),
384 CGI::hidden(-name=>"filetrial$cnt", -default=>[$sourceFileName]). 480 CGI::hidden(-name=>"filetrial$cnt", -default=>[$sourceFileName]).
385 CGI::p($problem_output), 481 CGI::p($problem_output),
386 )); 482 ));
387} 483}
388 484
389sub title {
390 return "Problem Set Maker";
391}
392 485
393sub body { 486sub pre_header_initialize {
394 my ($self) = @_; 487 my ($self) = @_;
395
396 my $r = $self->r; 488 my $r = $self->r;
397 my $ce = $r->ce; # course environment 489 ## For all cases, lets set some things
490 $self->{error}=0;
491 my $ce = $r->ce;
398 my $db = $r->db; # database 492 my $db = $r->db;
399 my $j; # garden variety counter 493 my $maxShown = $r->param('max_shown') || MAX_SHOW_DEFAULT;
494 $maxShown = 10000000 if($maxShown eq 'All'); # let's hope there aren't more
495
496 ## These directories will have individual buttons
497 %problib = %{$ce->{courseFiles}{problibs}} if $ce->{courseFiles}{problibs};
400 498
401 my $userName = $r->param('user'); 499 my $userName = $r->param('user');
402
403 my $user = $db->getUser($userName); # checked 500 my $user = $db->getUser($userName); # checked
404 die "record for user $userName (real user) does not exist." 501 die "record for user $userName (real user) does not exist."
405 unless defined $user; 502 unless defined $user;
406
407 ### Check that this is a professor
408 my $authz = $r->authz; 503 my $authz = $r->authz;
409 unless ($authz->hasPermissions($userName, "modify_problem_sets")) { 504 unless ($authz->hasPermissions($userName, "modify_problem_sets")) {
410 print "User $userName returned " . 505 return(""); # Error message already produced in the body
411 $authz->hasPermissions($user, "modify_problem_sets") . 506 }
412 " for permission"; 507
413 return(CGI::em("You are not authorized to access the Instructor tools.")); 508 ## Now one action we have to deal with here
509 if ($r->param('edit_local')) {
510 my $urlpath = $r->urlpath;
511 my $db = $r->db;
512 my $checkset = $db->getGlobalSet($r->param('local_sets'));
513 if (not defined($checkset)) {
514 $self->{error} = 1;
515 $self->addbadmessage('You need to select a "Target Set" before you can edit it.');
516 } else {
517 my $page = $urlpath->newFromModule('WeBWorK::ContentGenerator::Instructor::ProblemSetEditor', setID=>$r->param('local_sets'), courseID=>$urlpath->arg("courseID"));
518 my $url = $self->systemLink($page);
519 $self->reply_with_redirect($url);
414 } 520 }
521 }
415 522
523 ## Next, lots of set up so that errors can be reported with message()
416 524
417 ############# List of problems we have already printed 525 ############# List of problems we have already printed
418 526
419 my @past_problems = get_past_problem_files($r); 527 $self->{past_problems} = get_past_problem_files($r);
420 my (@pg_files, @pg_html); 528 # if we don't end up reusing problems, this will be wiped out
529 # if we do redisplay the same problems, we must adjust this accordingly
530 my @past_marks = map {$_->[1]} @{$self->{past_problems}};
531 my $none_shown = scalar(@{$self->{past_problems}})==0;
532 my @pg_files=();
421 my $use_previous_problems = 1; 533 my $use_previous_problems = 1;
422 my $first_shown = $r->param('first_shown') || 0; 534 my $first_shown = $r->param('first_shown') || 0;
423 my $last_shown = $r->param('last_shown'); 535 my $last_shown = $r->param('last_shown');
424 if (not defined($last_shown)) { 536 if (not defined($last_shown)) {
425 $last_shown = -1; 537 $last_shown = -1;
426 } 538 }
427 my @all_past_list = (); # these are include requested, but not shown 539 my @all_past_list = (); # these are include requested, but not shown
428 $j = 0; 540 my $j = 0;
429 while (defined($r->param("all_past_list$j"))) { 541 while (defined($r->param("all_past_list$j"))) {
430 push @all_past_list, $r->param("all_past_list$j"); 542 push @all_past_list, $r->param("all_past_list$j");
431 $j++; 543 $j++;
432 } 544 }
433 545
434 ############# Default of which problem selector to display 546 ############# Default of which problem selector to display
435 547
436 my $browse_which = 'browse_local'; 548 my $browse_which = $r->param('browse_which') || 'browse_local';
437 $browse_which = $r->param('browse_which') if defined($r->param('browse_which'));
438 549
439 my $problem_seed = $r->param('problem_seed') || 0; 550 my $problem_seed = $r->param('problem_seed') || 0;
440 $r->param('problem_seed', $problem_seed); # if it wasn't defined before 551 $r->param('problem_seed', $problem_seed); # if it wasn't defined before
441 552
553 ## check for problem lib buttons
554 my $browse_lib = '';
555 foreach my $lib (keys %problib) {
556 if ($r->param("browse_$lib")) {
557 $browse_lib = "browse_$lib";
558 last;
559 }
560 }
561
442 ########### Start the logic through if elsif elsif ... 562 ########### Start the logic through if elsif elsif ...
443 563
444 ##### Asked to browse certain problems 564 ##### Asked to browse certain problems
565 if ($browse_lib ne '') {
566 $browse_which = $browse_lib;
567 $r->param('library_sets', "");
568 $use_previous_problems = 0; @pg_files = (); ## clear old problems
445 if ($r->param('browse_library')) { 569 } elsif ($r->param('browse_library')) {
446 $browse_which = 'browse_library'; 570 $browse_which = 'browse_library';
447 $r->param('library_sets', ""); 571 $r->param('library_sets', "");
572 $use_previous_problems = 0; @pg_files = (); ## clear old problems
448 } elsif ($r->param('browse_local')) { 573 } elsif ($r->param('browse_local')) {
449 $browse_which = 'browse_local'; 574 $browse_which = 'browse_local';
450 $r->param('library_sets', ""); 575 $r->param('library_sets', "");
576 $use_previous_problems = 0; @pg_files = (); ## clear old problems
451 } elsif ($r->param('browse_mysets')) { 577 } elsif ($r->param('browse_mysets')) {
452 $browse_which = 'browse_mysets'; 578 $browse_which = 'browse_mysets';
453 $r->param('library_sets', ""); 579 $r->param('library_sets', "");
580 $use_previous_problems = 0; @pg_files = (); ## clear old problems
454 581
455 ##### Change the seed value 582 ##### Change the seed value
456 583
457 } elsif ($r->param('rerandomize')) { 584 } elsif ($r->param('rerandomize')) {
458 $problem_seed++; 585 $problem_seed++;
459 $r->param('problem_seed', $problem_seed); 586 $r->param('problem_seed', $problem_seed);
587 $self->addbadmessage('Changing the problem seed for display, but there are no problems showing.') if $none_shown;
460 588
461 ##### Clear the display 589 ##### Clear the display
462 590
463 } elsif ($r->param('cleardisplay')) { 591 } elsif ($r->param('cleardisplay')) {
464 @pg_files = (); 592 @pg_files = ();
465 $use_previous_problems=0; 593 $use_previous_problems=0;
594 $self->addbadmessage('The display was already cleared.') if $none_shown;
466 595
467 ##### View problems selected from the local list 596 ##### View problems selected from the local list
468 597
469 } elsif ($r->param('view_local_set')) { 598 } elsif ($r->param('view_local_set')) {
470 599
471 my $set_to_display = $r->param('library_sets'); 600 my $set_to_display = $r->param('library_sets');
472 if (not defined($set_to_display) or $set_to_display eq "Select a Local Problem Collection") { 601 if (not defined($set_to_display) or $set_to_display eq SELECT_LOCAL_STRING or $set_to_display eq "Found no directories containing problems") {
473 $self->{libmsg} = "You need to select a set to view."; 602 $self->addbadmessage('You need to select a set to view.');
474 } else { 603 } else {
604 $set_to_display = '.' if $set_to_display eq MY_PROBLEMS;
605 $set_to_display = substr($browse_which,7) if $set_to_display eq MAIN_PROBLEMS;
475 @pg_files = list_pg_files($ce->{courseDirs}->{templates}, 606 @pg_files = list_pg_files($ce->{courseDirs}->{templates},
476 "$set_to_display"); 607 "$set_to_display");
477 $use_previous_problems=0; 608 $use_previous_problems=0;
478 } 609 }
479 610
480 ##### View problems selected from the a set in this course 611 ##### View problems selected from the a set in this course
481 612
482 } elsif ($r->param('view_mysets_set')) { 613 } elsif ($r->param('view_mysets_set')) {
483 614
484 my $set_to_display = $r->param('library_sets'); 615 my $set_to_display = $r->param('library_sets');
485 if (not defined($set_to_display) or $set_to_display eq "Select a Problem Set") { 616 if (not defined($set_to_display)
617 or $set_to_display eq "Select a Problem Set"
618 or $set_to_display eq NO_LOCAL_SET_STRING) {
486 $self->{libmsg} = "You need to select a set from this course to view."; 619 $self->addbadmessage("You need to select a set from this course to view.");
487 } else { 620 } else {
488 my @problemList = $db->listGlobalProblems($set_to_display); 621 my @problemList = $db->listGlobalProblems($set_to_display);
489 my $problem; 622 my $problem;
490 @pg_files=(); 623 @pg_files=();
491 for $problem (@problemList) { 624 for $problem (@problemList) {
499 } 632 }
500 633
501 ##### View whole chapter from the library 634 ##### View whole chapter from the library
502 ## This will change somewhat later 635 ## This will change somewhat later
503 636
504 } elsif ($r->param('lib_view')) { 637 } elsif ($r->param('lib_view')) {
505 638
506 @pg_files=(); 639 @pg_files=();
507 my $chap = $r->param('library_chapters') || ""; 640 my $chap = $r->param('library_chapters') || "";
508 $chap = "" if($chap eq "All Chapters"); 641 $chap = "" if($chap eq "All Chapters");
509 my $sect = $r->param('library_sections') || ""; 642 my $sect = $r->param('library_sections') || "";
519 $use_previous_problems=0; 652 $use_previous_problems=0;
520 653
521 ##### Edit the current local problem set 654 ##### Edit the current local problem set
522 655
523 } elsif ($r->param('edit_local')) { ## Jump to set edit page 656 } elsif ($r->param('edit_local')) { ## Jump to set edit page
524 # This is handled in pre_header_initialize -- it redirects 657
525 # If there is an error, so no redirect, we want to be ready 658 ; # already handled
526 # and do something here 659
527 660
528 ##### Make a new local problem set 661 ##### Make a new local problem set
529 662
530 } elsif ($r->param('new_local_set')) { 663 } elsif ($r->param('new_local_set')) {
531 if ($r->param('new_set_name') !~ /^[\w.-]*$/) { 664 if ($r->param('new_set_name') !~ /^[\w.-]*$/) {
532 $self->{localmsg} = "The name ".$r->param('new_set_name')." is not a valid set name. Use only letters, digits, -, _, and ."; 665 $self->addbadmessage("The name ".$r->param('new_set_name')." is not a valid set name. Use only letters, digits, -, _, and .");
533 } else { 666 } else {
534 my $newSetName = $r->param('new_set_name'); 667 my $newSetName = $r->param('new_set_name');
535 $newSetName =~ s/^set//; 668 $newSetName =~ s/^set//;
536 $newSetName =~ s/\.def$//; 669 $newSetName =~ s/\.def$//;
670 $r->param('local_sets',$newSetName);
537 my $newSetRecord = $db->getGlobalSet($newSetName); 671 my $newSetRecord = $db->getGlobalSet($newSetName);
538 if (defined($newSetRecord)) { 672 if (defined($newSetRecord)) {
539 $self->{localmsg} = "The set name $newSetName is already in use. Pick a different name if you would like to start a new set."; 673 $self->addbadmessage("The set name $newSetName is already in use. Pick a different name if you would like to start a new set.");
540 } else { # Do it! 674 } else { # Do it!
541 $newSetRecord = $db->{set}->{record}->new(); 675 $newSetRecord = $db->{set}->{record}->new();
542 $newSetRecord->set_id($newSetName); 676 $newSetRecord->set_id($newSetName);
543 $newSetRecord->set_header(""); 677 $newSetRecord->set_header("");
544 $newSetRecord->problem_header(""); 678 $newSetRecord->hardcopy_header("");
545 $newSetRecord->open_date(time()+60*60*24*7); # in one week 679 $newSetRecord->open_date(time()+60*60*24*7); # in one week
546 $newSetRecord->due_date(time()+60*60*24*7*2); # in two weeks 680 $newSetRecord->due_date(time()+60*60*24*7*2); # in two weeks
547 $newSetRecord->answer_date(time()+60*60*24*7*3); # in three weeks 681 $newSetRecord->answer_date(time()+60*60*24*7*3); # in three weeks
548 eval {$db->addGlobalSet($newSetRecord)}; 682 eval {$db->addGlobalSet($newSetRecord)};
683 $self->addgoodmessage("Set $newSetName has been created.");
684 my $selfassign = $r->param('selfassign') || "";
685 $selfassign = "" if($selfassign =~ /false/i); # deal with javascript false
686 if($selfassign) {
687 $self->assignSetToUser($userName, $newSetRecord);
688 $self->addgoodmessage("Set $newSetName was assigned to $userName.");
689 }
549 } 690 }
550 } 691 }
551 692
552 ##### Add selected problems to the current local set 693 ##### Add selected problems to the current local set
553 694
554 } elsif ($r->param('update')) { 695 } elsif ($r->param('update')) {
555 ## first handle problems to be added before we hide them 696 ## first handle problems to be added before we hide them
556 my($localSet, @selected); 697 my($localSet, @selected);
557 698
558 @pg_files = grep {$_->[1] != 0 } @past_problems; 699 @pg_files = grep {($_->[1] & ADDED) != 0 } @{$self->{past_problems}};
559 @selected = map {$_->[0]} @pg_files; 700 @selected = map {$_->[0]} @pg_files;
701
702 my @action_files = grep {$_->[1] > 0 } @{$self->{past_problems}};
703 # There are now good reasons to do an update without selecting anything.
704 #if(scalar(@action_files) == 0) {
705 # $self->addbadmessage('Update requested, but no problems were marked.');
706 #}
560 707
561 if (scalar(@selected)>0) { # if some are to be added, they need a place to go 708 if (scalar(@selected)>0) { # if some are to be added, they need a place to go
562 $localSet = $r->param('local_sets'); 709 $localSet = $r->param('local_sets');
563 if (not defined($localSet)) { 710 if (not defined($localSet) or
711 $localSet eq SELECT_SET_STRING or
712 $localSet eq NO_LOCAL_SET_STRING) {
564 $self->{localmsg} = "Trying to add problems to something, you did not select a current set name as a target."; 713 $self->addbadmessage('You are trying to add problems to something, but you did not select a "Target Set" name as a target.');
565 } else { 714 } else {
566 my $newSetRecord = $db->getGlobalSet($localSet); 715 my $newSetRecord = $db->getGlobalSet($localSet);
567 if (not defined($newSetRecord)) { 716 if (not defined($newSetRecord)) {
568 $self->{localmsg} = "You need to select a local problem set to add the problems to."; 717 $self->addbadmessage("You are trying to add problems to $localSet, but that set does not seem to exist! I bet you used your \"Back\" button.");
569 } else { 718 } else {
570 add_selected($self, $db, $localSet, @selected); 719 my $addcount = add_selected($self, $db, $localSet);
720 if($addcount > 0) {
721 $self->addgoodmessage("Added $addcount problem".(($addcount>1)?'s':'').
722 " to $localSet.");
723 }
571 } 724 }
572 } 725 }
573 } 726 }
574 ## now handle problems to be hidden 727 ## now handle problems to be hidden
575 728
729 ## only keep the ones which are not hidden
576 @pg_files = grep {$_->[2]==0 } @past_problems; 730 @pg_files = grep {($_->[1] & HIDDEN) ==0 } @{$self->{past_problems}};
731 @past_marks = map {$_->[1]} @pg_files;
577 @pg_files = map {$_->[0]} @pg_files; 732 @pg_files = map {$_->[0]} @pg_files;
578 @all_past_list = (@all_past_list[0..($first_shown-1)], 733 @all_past_list = (@all_past_list[0..($first_shown-1)],
579 @pg_files, 734 @pg_files,
580 @all_past_list[($last_shown+1)..(scalar(@all_past_list)-1)]); 735 @all_past_list[($last_shown+1)..(scalar(@all_past_list)-1)]);
581 $last_shown = $first_shown+MAX_SHOW -1; 736 $last_shown = $first_shown+$maxShown -1;
582 $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list)); 737 $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list));
583
584 ## FIXME: you should say something if no problems are selected
585 ## maybe the add button should be disabled if there are no problems
586 ## showing
587
588 738
589 } elsif ($r->param('next_page')) { 739 } elsif ($r->param('next_page')) {
590 $first_shown = $last_shown+1; 740 $first_shown = $last_shown+1;
591 $last_shown = $first_shown+MAX_SHOW-1; 741 $last_shown = $first_shown+$maxShown-1;
592 $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list)); 742 $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list));
743 @past_marks = ();
593 } elsif ($r->param('prev_page')) { 744 } elsif ($r->param('prev_page')) {
594 $last_shown = $first_shown-1; 745 $last_shown = $first_shown-1;
595 $first_shown = $last_shown - MAX_SHOW+1; 746 $first_shown = $last_shown - $maxShown+1;
596 747
597 $first_shown = 0 if($first_shown<0); 748 $first_shown = 0 if($first_shown<0);
749 @past_marks = ();
750
751 } elsif ($r->param('select_all')) {
752 @past_marks = map {1} @past_marks;
753 } elsif ($r->param('select_none')) {
754 @past_marks = ();
598 755
599 ##### No action requested, probably our first time here 756 ##### No action requested, probably our first time here
600 757
601 } else { 758 } else {
602 #my $c = $r->connection; 759 #my $c = $r->connection;
605 } ##### end of the if elsif ... 762 } ##### end of the if elsif ...
606 763
607 764
608 ############# List of local sets 765 ############# List of local sets
609 766
610 my @all_set_defs = get_global_set_defs($db); 767 my @all_set_defs = $db->listGlobalSets;
611 for ($j=0; $j<scalar(@all_set_defs); $j++) { 768 for ($j=0; $j<scalar(@all_set_defs); $j++) {
612 $all_set_defs[$j] =~ s|^set||; 769 $all_set_defs[$j] =~ s|^set||;
613 $all_set_defs[$j] =~ s|\.def||; 770 $all_set_defs[$j] =~ s|\.def||;
614 } 771 }
615 772
616 if ($use_previous_problems) { 773 if ($use_previous_problems) {
617 @pg_files = @all_past_list; 774 @pg_files = @all_past_list;
618 } else { 775 } else {
619 $first_shown = 0; 776 $first_shown = 0;
620 $last_shown = scalar(@pg_files)<MAX_SHOW ? scalar(@pg_files) : MAX_SHOW; 777 $last_shown = scalar(@pg_files)<$maxShown ? scalar(@pg_files) : $maxShown;
621 $last_shown--; # to make it an array index 778 $last_shown--; # to make it an array index
779 @past_marks = ();
622 } 780 }
781 ############# Now store data in self for retreival by body
782 $self->{first_shown} = $first_shown;
783 $self->{last_shown} = $last_shown;
784 $self->{browse_which} = $browse_which;
785 $self->{problem_seed} = $problem_seed;
786 $self->{pg_files} = \@pg_files;
787 $self->{past_marks} = \@past_marks;
788 $self->{all_set_defs} = \@all_set_defs;
623 789
790}
791
792
793sub title {
794 return "Problem Set Maker";
795}
796
797sub body {
798 my ($self) = @_;
799
800 my $r = $self->r;
801 my $ce = $r->ce; # course environment
802 my $db = $r->db; # database
803 my $j; # garden variety counter
804
805 my $userName = $r->param('user');
806
807 my $user = $db->getUser($userName); # checked
808 die "record for user $userName (real user) does not exist."
809 unless defined $user;
810
811 ### Check that this is a professor
812 my $authz = $r->authz;
813 unless ($authz->hasPermissions($userName, "modify_problem_sets")) {
814 print "User $userName returned " .
815 $authz->hasPermissions($user, "modify_problem_sets") .
816 " for permission";
817 return(CGI::div({class=>'ResultsWithError'},
818 CGI::em("You are not authorized to access the Instructor tools.")));
819 }
820
821 ########## Extract information computed in pre_header_initialize
822
823 my $first_shown = $self->{first_shown};
824 my $last_shown = $self->{last_shown};
825 my $browse_which = $self->{browse_which};
826 my $problem_seed = $self->{problem_seed};
827 my @pg_files = @{$self->{pg_files}};
828 my @all_set_defs = @{$self->{all_set_defs}};
829
624 @pg_html=($last_shown>=$first_shown) ? 830 my @pg_html=($last_shown>=$first_shown) ?
625 renderProblems($r,$user, @pg_files[$first_shown..$last_shown]) : (); 831 renderProblems(r=> $r,
832 user => $user,
833 problem_list => [@pg_files[$first_shown..$last_shown]],
834 displayMode => $r->param('mydisplayMode')) : ();
626 835
627 ########## Top part 836 ########## Top part
628 print CGI::startform({-method=>"POST", -action=>$r->uri}), 837 print CGI::startform({-method=>"POST", -action=>$r->uri, -name=>'mainform'}),
629 $self->hidden_authen_fields, 838 $self->hidden_authen_fields,
630 '<div align="center">', 839 '<div align="center">',
631 CGI::start_table({-border=>2}); 840 CGI::start_table({-border=>2});
632 make_top_row($self, 'all_set_defs'=>\@all_set_defs, 841 $self->make_top_row('all_set_defs'=>\@all_set_defs,
633 'browse_which'=> $browse_which); 842 'browse_which'=> $browse_which);
634 print CGI::hidden(-name=>'browse_which', -default=>[$browse_which]), 843 print CGI::hidden(-name=>'browse_which', -default=>[$browse_which]),
635 CGI::hidden(-name=>'problem_seed', -default=>[$problem_seed]); 844 CGI::hidden(-name=>'problem_seed', -default=>[$problem_seed]);
636 for ($j = 0 ; $j < scalar(@pg_files) ; $j++) { 845 for ($j = 0 ; $j < scalar(@pg_files) ; $j++) {
637 print CGI::hidden(-name=>"all_past_list$j", -default=>$pg_files[$j]); 846 print CGI::hidden(-name=>"all_past_list$j", -default=>$pg_files[$j]);
643 852
644 ########## Now print problems 853 ########## Now print problems
645 my $jj; 854 my $jj;
646 for ($jj=0; $jj<scalar(@pg_html); $jj++) { 855 for ($jj=0; $jj<scalar(@pg_html); $jj++) {
647 $pg_files[$jj] =~ s|^$ce->{courseDirs}->{templates}/?||; 856 $pg_files[$jj] =~ s|^$ce->{courseDirs}->{templates}/?||;
648 make_data_row($self, $pg_files[$jj+$first_shown], $pg_html[$jj], $jj+1); 857 $self->make_data_row($pg_files[$jj+$first_shown], $pg_html[$jj], $jj+1, $self->{past_marks}->[$jj]);
649 } 858 }
650 859
651 ########## Finish things off 860 ########## Finish things off
652 print CGI::end_table(); 861 print CGI::end_table();
653 print '</div>'; 862 print '</div>';
671 return ""; 880 return "";
672} 881}
673 882
674############################################## End of Body 883############################################## End of Body
675 884
676sub pre_header_initialize {
677 my ($self) = @_;
678 my $r = $self->r;
679 ## For all cases, lets set some things
680 $self->{error}=0;
681 $self->{libmsg}="";
682 $self->{localmsg}="";
683
684
685 ### Maybe FIXME: this needs to check permissions before doing anything
686
687 ## Now one action we have to deal with here
688 if ($r->param('edit_local')) {
689 my $urlpath = $r->urlpath;
690 my $db = $r->db;
691 my $checkset = $db->getGlobalSet($r->param('local_sets'));
692 if (not defined($checkset)) {
693 $self->{error} = 1;
694 $self->{localmsg} = "You need to select a local set before you can edit it.";
695 return();
696 }
697 my $page = $urlpath->newFromModule('WeBWorK::ContentGenerator::Instructor::ProblemSetEditor', setID=>$r->param('local_sets'), courseID=>$urlpath->arg("courseID"));
698 my $url = $self->systemLink($page);
699 $self->reply_with_redirect($url);
700 }
701}
702
703
704# SKEL: To emit your own HTTP header, uncomment this: 885# SKEL: To emit your own HTTP header, uncomment this:
705# 886#
706#sub header { 887#sub header {
707# my ($self) = @_; 888# my ($self) = @_;
708# 889#

Legend:
Removed from v.2021  
changed lines
  Added in v.2450

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9