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

View of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/ProblemList.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1841 - (download) (as text) (annotate)
Thu Mar 4 21:05:58 2004 UTC (9 years, 2 months ago) by sh002i
File size: 12661 byte(s)
changed template escape handler functions to grab data from $r->urlpath
instead of @_ for compatability with dispatch_new.

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/ProblemList.pm,v 1.16 2003/12/18 03:02:19 sh002i Exp $
    5 #
    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
    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.
   10 #
   11 # This program is distributed in the hope that it will be useful, but WITHOUT
   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   14 # Artistic License for more details.
   15 ################################################################################
   16 
   17 package WeBWorK::ContentGenerator::Instructor::ProblemList;
   18 use base qw(WeBWorK::ContentGenerator::Instructor);
   19 
   20 =head1 NAME
   21 
   22 WeBWorK::ContentGenerator::Instructor::ProblemList - List and edit problems in a set
   23 
   24 =cut
   25 
   26 use strict;
   27 use warnings;
   28 use CGI qw();
   29 use WeBWorK::Utils qw(readDirectory list2hash max);
   30 use WeBWorK::DB::Record::Set;
   31 
   32 use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts)];
   33 use constant PROBLEM_USER_FIELDS => [qw(problem_seed status num_correct num_incorrect)];
   34 
   35 sub problemElementHTML {
   36   my ($fieldName, $fieldValue, $size, $override, $overrideValue) = @_;
   37   my $attributeHash = {type=>"text",name=>$fieldName,value=>$fieldValue};
   38   $attributeHash->{size} = $size if defined $size;
   39   my $html;
   40 # my $html = CGI::input($attributeHash);
   41 
   42   unless (defined $override) {
   43     $html = CGI::input($attributeHash);
   44   } else {
   45     $html = $fieldValue;
   46     $attributeHash->{name} = "${fieldName}.override";
   47     $attributeHash->{value} = ($override ? $overrideValue : "");
   48     $html = "default:".CGI::br().$html.CGI::br()
   49       . CGI::checkbox({
   50         type => "checkbox",
   51         name => "override",
   52         label => "override:",
   53         value => $fieldName,
   54         checked => ($override ? 1 : 0)
   55       })
   56       . CGI::br()
   57       . CGI::input($attributeHash);
   58   }
   59 
   60   return $html;
   61 }
   62 
   63 # pay no attention to the argument list.  Here's what you pass:
   64 # directoryListHTML($level, $selected, $libraryRoot, @path)
   65 sub directoryListHTML {
   66   my ($level, $selected, @path) = @_;
   67   $selected = [$selected] unless ref $selected eq "ARRAY";
   68   my $dirName = join "/", @path[0..$level];
   69   my $pathInLibrary = join "/", @path[1..$level];
   70   my @contents = sort grep {m/\.pg$/ or -d "$dirName/$_" and not m/^\.{1,2}$/} readDirectory($dirName);
   71   my %contentsPretty = map {$pathInLibrary . "/" . $_ => (-d "$dirName/$_" ? "$_/" : $_)} @contents;
   72   @contents = map {"$pathInLibrary/$_"} @contents; # Make the full path the actual values, so weird user behavior doesn't hurt.
   73   @$selected = map {"$pathInLibrary/$_"} @$selected;
   74 
   75   my $html = ($level eq "0" ? "problem library" : $path[$level]) . CGI::br();
   76   $html .= CGI::scrolling_list({
   77     name=>"directory_level_$level",
   78     values=>\@contents,
   79     labels=>\%contentsPretty,
   80     default=>$selected,
   81     multiple=>'true',
   82     size=>"20",
   83   });
   84   $html .= CGI::br()
   85     . CGI::input({type=>"submit", name=>"open_add_$level", value=>"Open/Add"});
   86 }
   87 
   88 sub initialize {
   89   my ($self) = @_;
   90   my $r = $self->{r};
   91   my $setName = $r->urlpath->arg("setID");
   92   my $db = $self->{db};
   93   my $ce = $self->{ce};
   94   my $authz = $self->{authz};
   95   my $user = $r->param('user');
   96   my $setRecord = $db->getGlobalSet($setName); # checked
   97   die "global set $setName  not found." unless $setRecord;
   98 
   99   $self->{set}  = $setRecord;
  100   my @editForUser = $r->param('editForUser');
  101   # some useful booleans
  102   my $forUsers = scalar(@editForUser);
  103   my $forOneUser = $forUsers == 1;
  104 
  105   unless ($authz->hasPermissions($user, "modify_problem_sets")) {
  106     $self->{submitError} = "You are not authorized to modify problem sets";
  107     return;
  108   }
  109 
  110   # build a quick lookup table
  111   my %overrides = list2hash $r->param('override');
  112 
  113   # the Problem form was submitted
  114   if (defined($r->param('submit_problem_changes'))) {
  115     my @problemList = $db->listGlobalProblems($setName);
  116     foreach my $problem (@problemList) {
  117       my $problemRecord = $db->getGlobalProblem($setName, $problem); # checked
  118       die "global $problem for set $setName not found." unless $problemRecord;
  119       foreach my $field (@{PROBLEM_FIELDS()}) {
  120         my $paramName = "problem.${problem}.${field}";
  121         if (defined($r->param($paramName))) {
  122           $problemRecord->$field($r->param($paramName));
  123         }
  124       }
  125       $db->putGlobalProblem($problemRecord);
  126 
  127       if ($forOneUser) {
  128         my $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem); # checked
  129         die " problem $problem for set $setName and effective user $editForUser[0] not found" unless $userProblemRecord;
  130         foreach my $field (@{PROBLEM_USER_FIELDS()}) {
  131           my $paramName = "problem.${problem}.${field}";
  132           if (defined($r->param($paramName))) {
  133             $userProblemRecord->$field($r->param($paramName));
  134           }
  135         }
  136         foreach my $field (@{PROBLEM_FIELDS()}) {
  137           my $paramName = "problem.${problem}.${field}";
  138           if (defined($r->param("${paramName}.override"))) {
  139             if (exists $overrides{$paramName}) {
  140               $userProblemRecord->$field($r->param("${paramName}.override"));
  141             } else {
  142               $userProblemRecord->$field(undef);
  143             }
  144 
  145           }
  146         }
  147         $db->putUserProblem($userProblemRecord);
  148 
  149       }
  150     }
  151     foreach my $problem ($r->param('deleteProblem')) {
  152       $db->deleteGlobalProblem($setName, $problem);
  153     }
  154   # The file list field was submitted
  155   } elsif (defined $r->param('fileBrowsing')) {
  156     my $libraryRoot = $ce->{courseDirs}->{templates};
  157     my $count = 0;
  158     my $done = 0;
  159     my @path = ();
  160     my $freeProblemID = max($db->listGlobalProblems($setName)) + 1;
  161 
  162     while (defined $r->param("directory_level_$count") and not $done) {
  163       if (defined $r->param("open_add_$count")) {
  164         $done = 1;
  165         my @selected = $r->param("directory_level_$count");
  166         my $dirFound = 0;
  167         foreach my $selected (@selected) {
  168           if (-d "$libraryRoot/$selected") {
  169             @path = split "/", $selected;
  170             shift @path if $path[0] eq ""; # remove the null element from the begining
  171             $dirFound = 1;
  172             last;
  173           }
  174         }
  175         # Otherwise, create a new global problem for each of the files selected
  176         unless ($dirFound) {
  177           foreach my $selected (@selected) {
  178             my $file = $selected;
  179             @path = split "/", $selected;
  180             pop @path; # Remove the file name from the path
  181             shift @path if $path[0] eq ""; # remove the null element from the begining
  182             my $problemRecord = $db->newGlobalProblem();
  183             $problemRecord->problem_id($freeProblemID++);
  184             $problemRecord->set_id($setName);
  185             $problemRecord->source_file($file);
  186             $problemRecord->value("1");
  187             $problemRecord->max_attempts("-1");
  188             $db->addGlobalProblem($problemRecord);
  189             $self->assignProblemToAllSetUsers($problemRecord);
  190           }
  191 
  192         }
  193       }
  194       $count++;
  195     }
  196     $self->{path} = [@path];
  197   }
  198 
  199 }
  200 
  201 sub path {
  202   my $self           = shift;
  203   my $args           = $_[-1];
  204   my $ce = $self->{ce};
  205   my $root = $ce->{webworkURLs}->{root};
  206   my $courseName = $ce->{courseName};
  207   my $set_id     = $self->{set}->set_id;
  208   return $self->pathMacro($args,
  209     "Home"          => "$root",
  210     $courseName     => "$root/$courseName",
  211     'instructor'    => "$root/$courseName/instructor",
  212     'sets'          => "$root/$courseName/instructor/sets/",
  213     "set $set_id"   => "$root/$courseName/instructor/sets/$set_id",
  214     'problems'  => '',
  215   );
  216 }
  217 
  218 sub title {
  219   my ($self) = @_;
  220   my $r = $self->{r};
  221   my $setName = $r->urlpath->arg("setID");
  222   return "Problems in ".$self->{ce}->{courseName}." : ".$setName;
  223 }
  224 
  225 sub body {
  226   my ($self) = @_;
  227   my $r = $self->{r};
  228   my $setName = $r->urlpath->arg("setID");
  229   my $db = $self->{db};
  230   my $ce = $self->{ce};
  231   my $authz = $self->{authz};
  232   my $user = $r->param('user');
  233   my $courseName = $ce->{courseName};
  234   my $setRecord = $db->getGlobalSet($setName); # checked
  235   die "Global set $setName not found." unless $setRecord;
  236   my @editForUser = $r->param('editForUser');
  237   # some useful booleans
  238   my $forUsers = scalar(@editForUser);
  239   my $forOneUser = $forUsers == 1;
  240 
  241         return CGI::em("You are not authorized to access the Instructor tools.") unless $authz->hasPermissions($user, "access_instructor_tools");
  242 
  243   my $userCount = $db->listUsers();
  244   my $setUserCount = $db->countSetUsers($setName);
  245   my $userCountMessage = "This set is assigned to " . $self->userCountMessage($setUserCount, $userCount) . ".";
  246 
  247   if (@editForUser) {
  248     print CGI::p("$userCountMessage  Editing user-specific overrides for ". CGI::b(join ", ", @editForUser));
  249   } else {
  250     print CGI::p($userCountMessage);
  251   }
  252 
  253   ## Problems Form ##
  254   my @problemList = $db->listGlobalProblems($setName);
  255   print CGI::a({name=>"problems"});
  256   print CGI::h2({}, "Problems");
  257   if (scalar(@problemList)) {
  258     print CGI::start_form({method=>"POST", action=>$r->uri.'#problems'});
  259     print CGI::start_table({border=>1, cellpadding=>4});
  260     print CGI::Tr({}, CGI::th({}, [
  261       ($forUsers ? () : ("Delete?")),
  262       "Problem",
  263       ($forUsers ? ("Status", "Problem Seed") : ()),
  264       "Source File", "Max. Attempts", "Weight",
  265       ($forUsers ? ("Number Correct", "Number Incorrect") : ())
  266     ]));
  267     foreach my $problem (sort {$a <=> $b} @problemList) {
  268       my $problemRecord = $db->getGlobalProblem($setName, $problem); # checked
  269       die "global problem $problem in set $setName not found." unless $problemRecord;
  270       my $problemID = $problemRecord->problem_id;
  271       my $userProblemRecord;
  272       my %problemOverrideArgs;
  273 
  274       if ($forOneUser) {
  275         $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem); # checked
  276         die "problem $problem for set $setName and user $editForUser[0] not found. " unless $userProblemRecord;
  277         foreach my $field (@{PROBLEM_FIELDS()}) {
  278           $problemOverrideArgs{$field} = [defined $userProblemRecord->$field, $userProblemRecord->$field];
  279         }
  280   #   } elsif ($forUsers) {
  281   #     foreach my $field (@{PROBLEM_FIELDS()}) {
  282   #       $problemOverrideArgs{$field} = ["", ""];
  283   #     }
  284       } else {
  285         foreach my $field (@{PROBLEM_FIELDS()}) {
  286           $problemOverrideArgs{$field} = [undef, undef];
  287         }
  288       }
  289 
  290       print CGI::Tr({},
  291         CGI::td({}, [
  292           ($forUsers ? () : (CGI::input({type=>"checkbox", name=>"deleteProblem", value=>$problemID}))),
  293           "$problemID "
  294             . CGI::a({href=>$ce->{webworkURLs}->{root}."/$courseName/".$setName.'/'.$problemID.'?'.$self->url_authen_args}, "view")
  295             . " "
  296             . CGI::a({href=>$ce->{webworkURLs}->{root}."/$courseName/instructor/pgProblemEditor/".$setName.'/'.$problemID.'?'.$self->url_authen_args}, "edit")
  297             ,
  298           ($forUsers ? (
  299             problemElementHTML("problem.${problemID}.status", $userProblemRecord->status, "7"),
  300             problemElementHTML("problem.${problemID}.problem_seed", $userProblemRecord->problem_seed, "7"),
  301           ) : ()),
  302           problemElementHTML("problem.${problemID}.source_file", $problemRecord->source_file, "40", @{$problemOverrideArgs{source_file}}),
  303           problemElementHTML("problem.${problemID}.max_attempts",$problemRecord->max_attempts,"7", @{$problemOverrideArgs{max_attempts}}),
  304           problemElementHTML("problem.${problemID}.value",$problemRecord->value,"7", @{$problemOverrideArgs{value}}),
  305           ($forUsers ? (
  306             problemElementHTML("problem.${problemID}.num_correct", $userProblemRecord->num_correct, "7"),
  307             problemElementHTML("problem.${problemID}.num_incorrect", $userProblemRecord->num_incorrect, "7")
  308           ) : ())
  309         ])
  310 
  311       )
  312     }
  313     print CGI::end_table();
  314     print $self->hiddenEditForUserFields(@editForUser);
  315     print $self->hidden_authen_fields;
  316     print CGI::input({type=>"submit", name=>"submit_problem_changes", value=>"Save Problem Changes"});
  317     print CGI::end_form();
  318   } else {
  319     print CGI::p("This set doesn't contain any problems yet.");
  320   }
  321 
  322   unless ($forUsers) {
  323     my $libraryRoot = $ce->{courseDirs}->{templates};
  324     my @path = defined $self->{path} ? @{$self->{path}} : ();
  325     unshift @path, $libraryRoot;
  326     print CGI::a({name=>"addProblem"});
  327     print CGI::h3({}, "Add Problem(s)");
  328     print CGI::start_form({method=>"post", action=>$r->uri.'#addProblem'});
  329     print CGI::input({type=>"hidden", name=>"fileBrowsing", value=>"Yes"});
  330     print CGI::start_table();
  331     my $columns = "";
  332     for (my $counter = 0; $counter < scalar(@path); $counter++) {
  333       $columns .= CGI::td(directoryListHTML ($counter, (exists $path[$counter+1] ? $path[$counter+1] : []), @path));
  334     }
  335     print CGI::Tr($columns);
  336     print CGI::end_table();
  337     print $self->hidden_authen_fields;
  338     print CGI::end_form();
  339   }
  340 
  341   return "";
  342 }
  343 
  344 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9