diff --git a/lib/WeBWorK/ContentGenerator/Instructor/Stats.pm b/lib/WeBWorK/ContentGenerator/Instructor/Stats.pm index d11cbb10a5..d71643e514 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/Stats.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/Stats.pm @@ -26,6 +26,7 @@ homework set (including sv graphs). use SVG; use WeBWorK::Utils qw(jitar_id_to_seq jitar_problem_adjusted_status format_set_name_display grade_set); +use WeBWorK::Utils::FilterRecords qw(getFiltersForClass filterRecords); sub initialize ($c) { my $db = $c->db; @@ -38,9 +39,9 @@ sub initialize ($c) { # Cache a list of all users except set level proctors and practice users, and restrict to the sections or # recitations that are allowed for the user if such restrictions are defined. This list is sorted by last_name, # then first_name, then user_id. This is used in multiple places in this module, and is guaranteed to be used at - # least once. So it is done here to prevent extra database access. + # least once. So it is done here to prevent extra database access. Filter out users not included in stats. $c->{student_records} = [ - $db->getUsersWhere( + grep { $ce->status_abbrev_has_behavior($_->status, 'include_in_stats') } $db->getUsersWhere( { user_id => [ -and => { not_like => 'set_id:%' }, { not_like => "$ce->{practiceUserPrefix}\%" } ], $ce->{viewable_sections}{$user} || $ce->{viewable_recitations}{$user} @@ -100,39 +101,18 @@ sub siblings ($c) { return $c->include('ContentGenerator/Instructor/Stats/siblings', header => $c->maketext('Statistics')); } -# Apply the currently selected filter to the the student records cached in initialize, and return a reference to the +# Apply the currently selected filter to the student records, and return a reference to the # list of students and a reference to a hash of section/recitation filters. sub filter_students ($c) { - my $ce = $c->ce; - my $db = $c->db; - my $user = $c->param('user'); + my $filter = $c->param('filter'); + my @students = $filter ? filterRecords($c, 0, [$filter], @{ $c->{student_records} }) : @{ $c->{student_records} }; - # Create a hash of sections and recitations, if there are any for the course. - # Filter out all records except for current/auditing students for stats. - # Filter out students not in selected section/recitation. - my $filter = $c->param('filter'); - my %filters; - my @outStudents; - for my $student (@{ $c->{student_records} }) { - # Only include current/auditing students in stats. - next - unless ($ce->status_abbrev_has_behavior($student->status, 'include_in_stats')); - - my $section = $student->section; - $filters{"section:$section"} = $c->maketext('Section [_1]', $section) - if $section && !$filters{"section:$section"}; - my $recitation = $student->recitation; - $filters{"recitation:$recitation"} = $c->maketext('Recitation [_1]', $recitation) - if $recitation && !$filters{"recitation:$recitation"}; - - # Only add users who match the selected section/recitation. - push(@outStudents, $student) - if (!$filter - || ($filter =~ /^section:(.*)$/ && $section eq $1) - || ($filter =~ /^recitation:(.*)$/ && $recitation eq $1)); - } + # convert the array from getFiltersForClass to a hash, after removing the first 'all' filter. + my $filters = getFiltersForClass($c, [ 'section', 'recitation' ], @{ $c->{student_records} }); + shift(@$filters); + $filters = { map { $_->[1] => $_->[0] } @$filters }; - return (\@outStudents, \%filters); + return (\@students, $filters); } sub set_stats ($c) { @@ -190,6 +170,7 @@ sub set_stats ($c) { # Only count top level problems for Jitar sets. my $num_problems = $isJitarSet ? scalar(keys %topLevelProblems) : scalar(@problems); + my $filter = $c->param('filter'); my ($students, $filters) = $c->filter_students; for my $studentRecord (@$students) { my $student = $studentRecord->user_id; @@ -381,6 +362,7 @@ sub problem_stats ($c) { my $db = $c->db; my $ce = $c->ce; my $user = $c->param('user'); + my $filter = $c->param('filter'); my $courseID = $c->stash('courseID'); my $problemID = $c->stash('problemID'); diff --git a/lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm b/lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm index 28fd8ec827..feaf6a5e93 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/StudentProgress.pm @@ -24,6 +24,7 @@ WeBWorK::ContentGenerator::Instructor::StudentProgress - Display Student Progres use WeBWorK::Utils qw(jitar_id_to_seq wwRound grade_set format_set_name_display); use WeBWorK::Utils::Grades qw(list_set_versions); +use WeBWorK::Utils::FilterRecords qw(getFiltersForClass filterRecords); sub initialize ($c) { my $db = $c->db; @@ -36,9 +37,9 @@ sub initialize ($c) { # Cache a list of all users except set level proctors and practice users, and restrict to the sections or # recitations that are allowed for the user if such restrictions are defined. This list is sorted by last_name, # then first_name, then user_id. This is used in multiple places in this module, and is guaranteed to be used at - # least once. So it is done here to prevent extra database access. + # least once. So it is done here to prevent extra database access. Filter out users not included in stats. $c->{student_records} = [ - $db->getUsersWhere( + grep { $ce->status_abbrev_has_behavior($_->status, 'include_in_stats') } $db->getUsersWhere( { user_id => [ -and => { not_like => 'set_id:%' }, { not_like => "$ce->{practiceUserPrefix}\%" } ], $ce->{viewable_sections}{$user} || $ce->{viewable_recitations}{$user} @@ -115,10 +116,19 @@ sub displaySets ($c) { : (date => 0, testtime => 0, timeleft => 0, problems => 1, section => 1, recit => 1, login => 1); my $showBestOnly = $setIsVersioned ? $c->param('show_best_only') : 0; + my $filter = $c->param('filter'); + my @student_records = + $filter ? filterRecords($c, 0, [$filter], @{ $c->{student_records} }) : @{ $c->{student_records} }; + + # convert the array from getFiltersForClass to a hash, after removing the first 'all' filter. + my $filters = getFiltersForClass($c, [ 'section', 'recitation' ], @{ $c->{student_records} }); + shift(@$filters); + $filters = { map { $_->[1] => $_->[0] } @$filters }; + my @score_list; my @user_set_list; - for my $studentRecord (@{ $c->{student_records} }) { + for my $studentRecord (@student_records) { next unless $ce->status_abbrev_has_behavior($studentRecord->status, 'include_in_stats'); my $studentName = $studentRecord->user_id; @@ -277,7 +287,9 @@ sub displaySets ($c) { secondary_sort_method => $secondary_sort_method, ternary_sort_method => $ternary_sort_method, problems => \@problems, - user_set_list => \@user_set_list + user_set_list => \@user_set_list, + filters => $filters, + filter => $filter, ); } diff --git a/templates/ContentGenerator/Instructor/Stats/problem_stats.html.ep b/templates/ContentGenerator/Instructor/Stats/problem_stats.html.ep index 7ff784594b..4767239499 100644 --- a/templates/ContentGenerator/Instructor/Stats/problem_stats.html.ep +++ b/templates/ContentGenerator/Instructor/Stats/problem_stats.html.ep @@ -6,7 +6,7 @@ %
<%= maketext('Showing statistics for:') =%> - <%= include 'ContentGenerator/Instructor/Stats/student_filter_menu', filters => $filters =%> + <%= include 'HTML/StudentFilterMenu/menu', filters => $filters, params => {} =%> <%= include 'ContentGenerator/Instructor/Stats/problem_menu', problems => $problems =%>
% diff --git a/templates/ContentGenerator/Instructor/Stats/set_stats.html.ep b/templates/ContentGenerator/Instructor/Stats/set_stats.html.ep index 6659417475..89c1c80b33 100644 --- a/templates/ContentGenerator/Instructor/Stats/set_stats.html.ep +++ b/templates/ContentGenerator/Instructor/Stats/set_stats.html.ep @@ -5,7 +5,7 @@ % # Filter and problem selectors.
<%= maketext('Showing statistics for:') =%> - <%= include 'ContentGenerator/Instructor/Stats/student_filter_menu', filters => $filters =%> + <%= include 'HTML/StudentFilterMenu/menu', filters => $filters, params => {} =%> <%= include 'ContentGenerator/Instructor/Stats/problem_menu', problems => $problems =%>
% # Set information diff --git a/templates/ContentGenerator/Instructor/StudentProgress/set_progress.html.ep b/templates/ContentGenerator/Instructor/StudentProgress/set_progress.html.ep index 0bf142219b..4fe3361435 100644 --- a/templates/ContentGenerator/Instructor/StudentProgress/set_progress.html.ep +++ b/templates/ContentGenerator/Instructor/StudentProgress/set_progress.html.ep @@ -1,5 +1,33 @@ <%= include 'ContentGenerator/Base/set_status', set => $c->{setRecord} =%> % +% my %params = ( + % defined $primary_sort_method ? (primary_sort => $primary_sort_method) : (), + % defined $secondary_sort_method ? (secondary_sort => $secondary_sort_method) : (), + % defined $ternary_sort_method ? (ternary_sort => $ternary_sort_method) : (), + % defined $filter ? (filter => $filter) : (), + % # Preserve display options when the sort headers are clicked for gateway quizzes. + % $setIsVersioned + % ? ( + % show_best_only => $showBestOnly, + % show_date => $showColumns->{date}, + % show_testtime => $showColumns->{testtime}, + % show_timeleft => $showColumns->{timeleft}, + % show_problems => $showColumns->{problems}, + % show_section => $showColumns->{section}, + % show_recitation => $showColumns->{recit}, + % show_login => $showColumns->{login}, + % ) + % : () +% ); +% +% # Filter selector. +% if (%$filters) { +
+ <%= maketext('Showing progress for:') =%> + <%= include 'HTML/StudentFilterMenu/menu', filters => $filters, params => \%params =%> +
+% } +% % # In the case of gateway tests, add a form with checkboxes that allow customization of what is included in the % # display. % if ($setIsVersioned) { @@ -60,6 +88,18 @@ + % if (param('filter')) { + <%= hidden_field filter => param('filter') =%> + % } + % if ($primary_sort_method) { + <%= hidden_field primary_sort => $primary_sort_method =%> + % } + % if ($secondary_sort_method) { + <%= hidden_field secondary_sort => $secondary_sort_method =%> + % } + % if ($ternary_sort_method) { + <%= hidden_field ternary_sort => $ternary_sort_method =%> + % } <%= submit_button maketext('Update Display'), class => 'btn btn-primary' =%> <% end =%> @@ -106,23 +146,11 @@ % } % -% my %params = ( +% my %sort_params = ( + % %params, % # Shift past sort methods down in priority. - % defined $primary_sort_method ? (secondary_sort => $primary_sort_method) : (), - % defined $secondary_sort_method ? (ternary_sort => $secondary_sort_method) : (), - % # Preserve display options when the sort headers are clicked for gateway quizzes. - % $setIsVersioned - % ? ( - % show_best_only => $showBestOnly, - % show_date => $showColumns->{date}, - % show_testtime => $showColumns->{testtime}, - % show_timeleft => $showColumns->{timeleft}, - % show_problems => $showColumns->{problems}, - % show_section => $showColumns->{section}, - % show_recitation => $showColumns->{recit}, - % show_login => $showColumns->{login}, - % ) - % : () + % defined $primary_sort_method ? (secondary_sort => $primary_sort_method) : (), + % defined $secondary_sort_method ? (ternary_sort => $secondary_sort_method) : (), % ); % % # Start table output @@ -135,17 +163,17 @@ <%= maketext('Name') %>
<%= link_to maketext('First') => - $c->systemLink(url_for, params => { primary_sort => 'first_name', %params }) =%> + $c->systemLink(url_for, params => { %sort_params, primary_sort => 'first_name' }) =%>     <%= link_to maketext('Last') => - $c->systemLink(url_for, params => { primary_sort => 'last_name', %params }) =%> + $c->systemLink(url_for, params => { %sort_params, primary_sort => 'last_name' }) =%>
<%= link_to maketext('Email') => - $c->systemLink(url_for, params => { primary_sort => 'email_address', %params }) =%> + $c->systemLink(url_for, params => { %sort_params, primary_sort => 'email_address' }) =%> > <%= link_to maketext('Score') => - $c->systemLink(url_for, params => { primary_sort => 'score', %params }) =%> + $c->systemLink(url_for, params => { %sort_params, primary_sort => 'score' }) =%> ><%= maketext('Out Of') %> % # Additional columns that may be shown depending on if showing a gateway quiz and user selection. @@ -176,19 +204,19 @@ % if ($showColumns->{section}) { > <%= link_to maketext('Section') => - $c->systemLink(url_for, params => { primary_sort => 'section', %params }) =%> + $c->systemLink(url_for, params => { %sort_params, primary_sort => 'section' }) =%> % } % if ($showColumns->{recit}) { > <%= link_to maketext('Recitation') => - $c->systemLink(url_for, params => { primary_sort => 'recitation', %params }) =%> + $c->systemLink(url_for, params => { %sort_params, primary_sort => 'recitation' }) =%> % } % if ($showColumns->{login}) { > <%= link_to maketext('Login Name') => - $c->systemLink(url_for, params => { primary_sort => 'user_id', %params }) =%> + $c->systemLink(url_for, params => { %sort_params, primary_sort => 'user_id' }) =%> % } diff --git a/templates/ContentGenerator/Instructor/Stats/student_filter_menu.html.ep b/templates/HTML/StudentFilterMenu/menu.html.ep similarity index 85% rename from templates/ContentGenerator/Instructor/Stats/student_filter_menu.html.ep rename to templates/HTML/StudentFilterMenu/menu.html.ep index a0fa3c0674..5dcecaf5e6 100644 --- a/templates/ContentGenerator/Instructor/Stats/student_filter_menu.html.ep +++ b/templates/HTML/StudentFilterMenu/menu.html.ep @@ -2,20 +2,20 @@ % % # Create a section/recitation "filter by" dropdown if there are sections or recitations.
- <%= link_to param('filter') ? $filters->{param('filter')} : maketext('All sections') => '#', + <%= link_to param('filter') ? $filters->{param('filter')} : maketext('All students') => '#', id => 'filter', class => 'btn btn-primary dropdown-toggle', role => 'button', 'aria-expanded' => 'false', data => { bs_toggle => 'dropdown' } =%> -
\ +