From fa9830524930ada6608af71745c0ebc6e9b5eb37 Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Mon, 18 Sep 2023 08:35:23 -0500 Subject: [PATCH 1/2] Remove the attempts table. It is now provided by PG. PG also generates the results summary so the AttemptsTable module is not needed at all. Without the attempts table the problem page top matter looked too spaced out, so the styles were tweaked to improve spacing. --- htdocs/js/RenderProblem/renderproblem.js | 2 +- htdocs/themes/math4/math4.js | 5 - htdocs/themes/math4/math4.scss | 34 +- lib/FormatRenderedProblem.pm | 63 ++- lib/WeBWorK/ContentGenerator/GatewayQuiz.pm | 86 +--- lib/WeBWorK/ContentGenerator/Problem.pm | 117 ++--- lib/WeBWorK/ContentGenerator/ShowMeAnother.pm | 12 +- lib/WeBWorK/HTML/AttemptsTable.pm | 466 ------------------ lib/WeBWorK/Utils/Rendering.pm | 11 +- lib/WebworkWebservice/RenderProblem.pm | 10 +- .../ContentGenerator/GatewayQuiz.html.ep | 18 +- templates/RPCRenderFormats/default.html.ep | 4 +- templates/RPCRenderFormats/default.json.ep | 4 +- 13 files changed, 143 insertions(+), 689 deletions(-) delete mode 100644 lib/WeBWorK/HTML/AttemptsTable.pm diff --git a/htdocs/js/RenderProblem/renderproblem.js b/htdocs/js/RenderProblem/renderproblem.js index 726ff789a7..3041912cf1 100644 --- a/htdocs/js/RenderProblem/renderproblem.js +++ b/htdocs/js/RenderProblem/renderproblem.js @@ -28,7 +28,7 @@ send_pg_flags: 1, extra_header_text: '', ...renderOptions }; diff --git a/htdocs/themes/math4/math4.js b/htdocs/themes/math4/math4.js index 7787fd155e..4a29c2ac2a 100644 --- a/htdocs/themes/math4/math4.js +++ b/htdocs/themes/math4/math4.js @@ -80,11 +80,6 @@ (el) => new bootstrap.Tooltip(el, {trigger: 'hover', fallbackPlacements: []}) ); - // Set up popovers in the attemptResults table. - document.querySelectorAll('table.attemptResults td div.answer-preview').forEach((popover) => { - if (popover.dataset.bsContent) new bootstrap.Popover(popover, {trigger: 'click', html: true, sanitize: false}); - }); - // Sets up problems to rescale the image accoring to attr height width and not native height width. const rescaleImage = (_index, element) => { if (element.height != element.naturalHeight || element.width != element.naturalWidth) { diff --git a/htdocs/themes/math4/math4.scss b/htdocs/themes/math4/math4.scss index 87494e47b8..07844b815b 100644 --- a/htdocs/themes/math4/math4.scss +++ b/htdocs/themes/math4/math4.scss @@ -687,14 +687,6 @@ ul.courses-list { } } -div.AuthorComment { - background-color: #00e0e0; - color: black; - padding: 0.25rem; - border: 1px solid transparent; - border-radius: 0.25rem; -} - /* Footer */ #footer { font-size: 0.8em; @@ -901,22 +893,22 @@ input.changed[type=text] { /* orange */ min-width: 2.5em; text-align: center; } -} -span { - &.correct { - color: inherit; /* green */ - background-color: #8f8; - } + span { + &.correct { + color: inherit; + background-color: #8f8; + } - &.incorrect { - color: #bf5454; /* red */ - background-color: inherit; - } + &.incorrect { + color: #bf5454; /* red */ + background-color: inherit; + } - &.unattempted { - color: inherit; - background-color: #88ecff; + &.unattempted { + color: inherit; + background-color: #88ecff; + } } } diff --git a/lib/FormatRenderedProblem.pm b/lib/FormatRenderedProblem.pm index 8e128d1bc6..db96efad8e 100644 --- a/lib/FormatRenderedProblem.pm +++ b/lib/FormatRenderedProblem.pm @@ -29,7 +29,6 @@ use Digest::SHA qw(sha1_base64); use Mojo::Util qw(xml_escape); use Mojo::DOM; -use WeBWorK::HTML::AttemptsTable; use WeBWorK::Utils qw(getAssetURL); use WeBWorK::Utils::LanguageAndDirection; @@ -145,33 +144,30 @@ sub formatRenderedProblem { my $showCorrectMode = defined($ws->{inputs_ref}{WWcorrectAns}) || 0; # A problemUUID should be added to the request as a parameter. It is used by PG to create a proper UUID for use in # aliases for resources. It should be unique for a course, user, set, problem, and version. - my $problemUUID = $ws->{inputs_ref}{problemUUID} // ''; - my $problemResult = $rh_result->{problem_result} // {}; - my $showSummary = $ws->{inputs_ref}{showSummary} // 1; - my $showAnswerNumbers = $ws->{inputs_ref}{showAnswerNumbers} // 1; - - # Attempts table - my $answerTemplate = ''; - - # Do not produce an AttemptsTable when we had a rendering error. - if (!$renderErrorOccurred) { - my $tbl = WeBWorK::HTML::AttemptsTable->new( - $rh_result->{answers} // {}, $ws->c, - answersSubmitted => $ws->{inputs_ref}{answersSubmitted} // 0, - answerOrder => $rh_result->{flags}{ANSWER_ENTRY_ORDER} // [], - displayMode => $displayMode, - showAnswerNumbers => $showAnswerNumbers, - ce => $ce, - showAttemptPreviews => $previewMode || $submitMode || $showCorrectMode, - showAttemptResults => $submitMode || $showCorrectMode, - showCorrectAnswers => $showCorrectMode, - showMessages => $previewMode || $submitMode || $showCorrectMode, - showSummary => (($showSummary && ($submitMode || $showCorrectMode)) // 0) ? 1 : 0, - maketext => WeBWorK::Localize::getLoc($formLanguage), - summary => $problemResult->{summary} // '', # can be set by problem grader - ); - $answerTemplate = $tbl->answerTemplate; - $tbl->imgGen->render(refresh => 1) if $tbl->displayMode eq 'images'; + my $problemUUID = $ws->{inputs_ref}{problemUUID} // ''; + my $problemResult = $rh_result->{problem_result} // {}; + my $showSummary = $ws->{inputs_ref}{showSummary} // 1; + + # Result summary + my $resultSummary = ''; + + my $lh = WeBWorK::Localize::getLangHandle($formLanguage); + + # Do not produce a result summary when we had a rendering error. + if (!$renderErrorOccurred + && $showSummary + && !$previewMode + && ($submitMode || $showCorrectMode) + && $problemResult->{summary}) + { + $resultSummary = $ws->c->c( + $ws->c->tag( + 'h2', + class => 'fs-3 mb-2', + $ws->c->maketext('Results for this submission') + ) + . $ws->c->tag('div', role => 'alert', $ws->c->b($problemResult->{summary})) + )->join(''); } # Answer hash in XML format used by the PTX format. @@ -214,7 +210,7 @@ sub formatRenderedProblem { $output->{input} = $ws->{input}; # The following could be constructed from the above, but this is a convenience - $output->{answerTemplate} = $answerTemplate->to_string if $answerTemplate; + $output->{resultSummary} = $resultSummary->to_string if $resultSummary; $output->{lang} = $PROBLEM_LANG_AND_DIR{lang}; $output->{dir} = $PROBLEM_LANG_AND_DIR{dir}; $output->{extra_css_files} = \@extra_css_files; @@ -242,7 +238,7 @@ sub formatRenderedProblem { formatName => $formatName, ws => $ws, ce => $ce, - lh => WeBWorK::Localize::getLangHandle($ws->{inputs_ref}{language} // 'en'), + lh => $lh, rh_result => $rh_result, SITE_URL => $SITE_URL, FORM_ACTION_URL => $SITE_URL . $ws->c->webwork_url . '/render_rpc', @@ -263,7 +259,7 @@ sub formatRenderedProblem { extra_js_files => \@extra_js_files, problemText => $problemText, extra_header_text => $ws->{inputs_ref}{extra_header_text} // '', - answerTemplate => $answerTemplate, + resultSummary => $resultSummary, showScoreSummary => $submitMode && !$renderErrorOccurred && $problemResult, answerhashXML => $answerhashXML, LTIGradeMessage => $LTIGradeMessage, @@ -275,9 +271,8 @@ sub formatRenderedProblem { isInstructor => $ws->{inputs_ref}{isInstructor} // '', forceScaffoldsOpen => $ws->{inputs_ref}{forceScaffoldsOpen} // '', showSummary => $showSummary, - showHints => $ws->{inputs_ref}{showHints} // '', - showSolutions => $ws->{inputs_ref}{showSolutions} // '', - showAnswerNumbers => $showAnswerNumbers, + showHints => $ws->{inputs_ref}{showHints} // '', + showSolutions => $ws->{inputs_ref}{showSolutions} // '', showPreviewButton => $ws->{inputs_ref}{showPreviewButton} // '', showCheckAnswersButton => $ws->{inputs_ref}{showCheckAnswersButton} // '', showCorrectAnswersButton => $ws->{inputs_ref}{showCorrectAnswersButton} // '', diff --git a/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm b/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm index bf49e59896..f30e552205 100644 --- a/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm +++ b/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm @@ -38,7 +38,6 @@ use WeBWorK::Utils::Tasks qw(fake_set fake_set_version fake_problem); use WeBWorK::Debug; use WeBWorK::Authen::LTIAdvanced::SubmitGrade; use WeBWorK::Authen::LTIAdvantage::SubmitGrade; -use WeBWorK::HTML::AttemptsTable; use PGrandom; use Caliper::Sensor; use Caliper::Entity; @@ -238,42 +237,10 @@ sub can_useMathQuill ($c) { } # Output utility -sub attemptResults ($c, $pg, $showCorrectAnswers, $showAttemptResults, $showSummary) { - my $ce = $c->ce; - - # Create AttemptsTable object - my $tbl = WeBWorK::HTML::AttemptsTable->new( - $pg->{answers}, - $c, - answersSubmitted => 1, - answerOrder => $pg->{flags}{ANSWER_ENTRY_ORDER}, - displayMode => $c->{displayMode}, - showHeadline => 0, - showAnswerNumbers => 0, - showAttemptAnswers => $ce->{pg}{options}{showEvaluatedAnswers}, - showAttemptPreviews => 1, - showAttemptResults => $showAttemptResults, - showCorrectAnswers => $showCorrectAnswers, - showMessages => 1, - showSummary => $showSummary, - imgGen => WeBWorK::PG::ImageGenerator->new( - tempDir => $ce->{webworkDirs}{tmp}, - latex => $ce->{externalPrograms}{latex}, - dvipng => $ce->{externalPrograms}{dvipng}, - useCache => 1, - cacheDir => $ce->{webworkDirs}{equationCache}, - cacheURL => $ce->{webworkURLs}{equationCache}, - cacheDB => $ce->{webworkFiles}{equationCacheDB}, - useMarkers => 1, - dvipng_align => $ce->{pg}{displayModeOptions}{images}{dvipng_align}, - dvipng_depth_db => $ce->{pg}{displayModeOptions}{images}{dvipng_depth_db}, - ), - ); - - my $answerTemplate = $tbl->answerTemplate; - $tbl->imgGen->render(body_text => $answerTemplate) if $tbl->displayMode eq 'images'; - - return $answerTemplate; +sub attemptResults ($c, $pg) { + return ($c->{can}{showProblemScores} && $pg->{result}{summary}) + ? $c->tag('div', role => 'alert', $c->b($pg->{result}{summary})) + : ''; } sub get_instructor_comment ($c, $problem) { @@ -1482,18 +1449,6 @@ sub warningMessage ($c) { # hash of parameters from the input form that need to be passed to the translator, and $mergedProblem # is what we'd expect. async sub getProblemHTML ($c, $effectiveUser, $set, $formFields, $mergedProblem) { - my $setID = $set->set_id; - my $setVersionNumber = $set->version_id; - - # Figure out solutions are allowed and call renderPG accordingly. - my $showCorrectAnswers = $c->{will}{showCorrectAnswers}; - my $showHints = $c->{will}{showHints}; - my $showSolutions = $c->{will}{showSolutions}; - my $processAnswers = $c->{will}{checkAnswers}; - - # FIXME: I'm not sure that problem_id is what we want here. - my $problemNumber = $mergedProblem->problem_id; - my $pg = await renderPG( $c, $effectiveUser, @@ -1502,17 +1457,26 @@ async sub getProblemHTML ($c, $effectiveUser, $set, $formFields, $mergedProblem) $set->psvn, $formFields, { - displayMode => $c->{displayMode}, - showHints => $showHints, - showSolutions => $showSolutions, - refreshMath2img => $showHints || $showSolutions, - processAnswers => 1, - QUIZ_PREFIX => 'Q' . sprintf('%04d', $problemNumber) . '_', - useMathQuill => $c->{will}{useMathQuill}, - useMathView => $c->{will}{useMathView}, - forceScaffoldsOpen => 1, - isInstructor => $c->authz->hasPermissions($c->{userID}, 'view_answers'), - debuggingOptions => getTranslatorDebuggingOptions($c->authz, $c->{userID}) + displayMode => $c->{displayMode}, + showHints => $c->{will}{showHints}, + showSolutions => $c->{will}{showSolutions}, + refreshMath2img => $c->{will}{showHints} || $c->{will}{showSolutions}, + processAnswers => 1, + QUIZ_PREFIX => 'Q' . sprintf('%04d', $mergedProblem->problem_id) . '_', + useMathQuill => $c->{will}{useMathQuill}, + useMathView => $c->{will}{useMathView}, + forceScaffoldsOpen => 1, + isInstructor => $c->authz->hasPermissions($c->{userID}, 'view_answers'), + showFeedback => $c->{submitAnswers} || $c->{previewAnswers} || $c->{will}{checkAnswers}, + showAttemptAnswers => $c->ce->{pg}{options}{showEvaluatedAnswers}, + showAttemptPreviews => 1, + showAttemptResults => !$c->{previewAnswers} && $c->{can}{showProblemScores}, + forceShowAttemptResults => $c->{will}{showProblemGrader}, + showMessages => 1, + showCorrectAnswers => ($c->{submitAnswers} || $c->{will}{checkAnswers} || $c->{will}{showProblemGrader}) + ? $c->{will}{showCorrectAnswers} + : 0, + debuggingOptions => getTranslatorDebuggingOptions($c->authz, $c->{userID}) }, ); @@ -1523,7 +1487,7 @@ async sub getProblemHTML ($c, $effectiveUser, $set, $formFields, $mergedProblem) if ($pg->{flags}{error_flag}) { push @{ $c->{errors} }, { - set => "$setID,v$setVersionNumber", + set => $set->set_id . ',v' . $set->version_id, problem => $mergedProblem->problem_id, message => $pg->{errors}, context => $pg->{body_text}, diff --git a/lib/WeBWorK/ContentGenerator/Problem.pm b/lib/WeBWorK/ContentGenerator/Problem.pm index 3cbf75816b..9fe1a03f02 100644 --- a/lib/WeBWorK/ContentGenerator/Problem.pm +++ b/lib/WeBWorK/ContentGenerator/Problem.pm @@ -36,7 +36,6 @@ use WeBWorK::Localize; use WeBWorK::Utils::Tasks qw(fake_set fake_problem); use WeBWorK::Utils::LanguageAndDirection qw(get_problem_lang_and_dir); use WeBWorK::AchievementEvaluator; -use WeBWorK::HTML::AttemptsTable; # GET/POST Parameters for this module # @@ -246,42 +245,11 @@ sub can_showMeAnother ($c, $user, $effectiveUser, $set, $problem, $submitAnswers return 0; } -sub attemptResults ($c, $pg, $showCorrectAnswers, $showAttemptResults, $showSummary) { - my $ce = $c->ce; - - # Create AttemptsTable object - my $tbl = WeBWorK::HTML::AttemptsTable->new( - $pg->{answers}, - $c, - answersSubmitted => 1, - answerOrder => $pg->{flags}{ANSWER_ENTRY_ORDER}, - displayMode => $c->{displayMode}, - showAnswerNumbers => 0, - showAttemptAnswers => $ce->{pg}{options}{showEvaluatedAnswers}, - showAttemptPreviews => 1, - showAttemptResults => $showAttemptResults, - showCorrectAnswers => $showCorrectAnswers, - showMessages => 1, - showSummary => $showSummary, - imgGen => WeBWorK::PG::ImageGenerator->new( - tempDir => $ce->{webworkDirs}{tmp}, - latex => $ce->{externalPrograms}{latex}, - dvipng => $ce->{externalPrograms}{dvipng}, - useCache => 1, - cacheDir => $ce->{webworkDirs}{equationCache}, - cacheURL => $ce->{webworkURLs}{equationCache}, - cacheDB => $ce->{webworkFiles}{equationCacheDB}, - useMarkers => 1, - dvipng_align => $ce->{pg}{displayModeOptions}{images}{dvipng_align}, - dvipng_depth_db => $ce->{pg}{displayModeOptions}{images}{dvipng_depth_db}, - ), - ); - - # Render equation images - my $answerTemplate = $tbl->answerTemplate; - $tbl->imgGen->render(body_text => \$answerTemplate) if $tbl->displayMode eq 'images'; - - return $answerTemplate; +sub attemptResults ($c, $pg) { + return $pg->{result}{summary} + ? $c->c($c->tag('h2', class => 'fs-3 mb-2', $c->maketext('Results for this submission')) + . $c->tag('div', role => 'alert', $c->b($pg->{result}{summary})))->join('') + : ''; } async sub pre_header_initialize ($c) { @@ -407,8 +375,8 @@ async sub pre_header_initialize ($c) { } $c->addmessage($c->{set}->visible - ? $c->tag('p', class => 'font-visible', $c->maketext('This set is visible to students.')) - : $c->tag('p', class => 'font-hidden', $c->maketext('This set is hidden from students.'))); + ? $c->tag('p', class => 'font-visible m-0', $c->maketext('This set is visible to students.')) + : $c->tag('p', class => 'font-hidden m-0', $c->maketext('This set is hidden from students.'))); } else { # Test for additional problem validity if it's not already invalid. @@ -451,6 +419,7 @@ async sub pre_header_initialize ($c) { { $c->{submitAnswers} = 0; $c->{resubmitDetected} = 1; + delete $formFields->{submitAnswers}; } $c->{displayMode} = $displayMode; @@ -581,6 +550,24 @@ async sub pre_header_initialize ($c) { # Final values for options my %will = map { $_ => $can{$_} && ($want{$_} || $must{$_}) } keys %must; + if ($prEnabled && $problem->{prCount} >= $rerandomizePeriod && !after($c->{set}->due_date, $c->submitTime)) { + $showMeAnother{active} = 0; + $must{requestNewSeed} = 1; + $can{requestNewSeed} = 1; + $want{requestNewSeed} = 1; + $will{requestNewSeed} = 1; + $c->{showCorrectOnRandomize} = $ce->{pg}{options}{showCorrectOnRandomize}; + # If this happens, it means that the page was refreshed. So prevent the answers from + # being recorded and the number of attempts from being increased. + if ($problem->{prCount} > $rerandomizePeriod) { + $c->{resubmitDetected} = 1; + $must{recordAnswers} = 0; + $can{recordAnswers} = 0; + $want{recordAnswers} = 0; + $will{recordAnswers} = 0; + } + } + # Sticky answers if (!($c->{submitAnswers} || $previewAnswers || $checkAnswers) && $will{showOldAnswers}) { my %oldAnswers = decodeAnswers($problem->last_answer); @@ -615,7 +602,16 @@ async sub pre_header_initialize ($c) { useMathView => $will{useMathView}, forceScaffoldsOpen => 0, isInstructor => $authz->hasPermissions($userID, 'view_answers'), - debuggingOptions => getTranslatorDebuggingOptions($authz, $userID) + showFeedback => $c->{submitAnswers} || $c->{previewAnswers}, + showAttemptAnswers => $ce->{pg}{options}{showEvaluatedAnswers}, + showAttemptPreviews => 1, + showAttemptResults => $c->{submitAnswers}, + forceShowAttemptResults => $will{checkAnswers} || $will{showProblemGrader}, + showMessages => 1, + showCorrectAnswers => $c->{submitAnswers} ? ($c->{showCorrectOnRandomize} // $will{showCorrectAnswers}) + : $will{checkAnswers} || $will{showProblemGrader} ? $will{showCorrectAnswers} + : 0, + debuggingOptions => getTranslatorDebuggingOptions($authz, $userID) } ); @@ -630,24 +626,6 @@ async sub pre_header_initialize ($c) { id => 'num_attempts' ); - if ($prEnabled && $problem->{prCount} >= $rerandomizePeriod && !after($c->{set}->due_date, $c->submitTime)) { - $showMeAnother{active} = 0; - $must{requestNewSeed} = 1; - $can{requestNewSeed} = 1; - $want{requestNewSeed} = 1; - $will{requestNewSeed} = 1; - $c->{showCorrectOnRandomize} = $ce->{pg}{options}{showCorrectOnRandomize}; - # If this happens, it means that the page was refreshed. So prevent the answers from - # being recorded and the number of attempts from being increased. - if ($problem->{prCount} > $rerandomizePeriod) { - $c->{resubmitDetected} = 1; - $must{recordAnswers} = 0; - $can{recordAnswers} = 0; - $want{recordAnswers} = 0; - $will{recordAnswers} = 0; - } - } - # Update and fix hint/solution options after PG processing $can{showHints} &&= $pg->{flags}{hintExists}; $can{showSolutions} &&= $pg->{flags}{solutionExists}; @@ -1484,37 +1462,26 @@ sub output_summary ($c) { my $output = $c->c; # Attempt summary - if (defined $pg->{flags}{showPartialCorrectAnswers} - && $pg->{flags}{showPartialCorrectAnswers} >= 0 - && $c->{submitAnswers}) - { - push( - @$output, - $c->attemptResults( - $pg, - $c->{showCorrectOnRandomize} // $will{showCorrectAnswers}, - $pg->{flags}{showPartialCorrectAnswers}, 1 - ) - ); + if ($c->{submitAnswers}) { + push(@$output, $c->attemptResults($pg)); } elsif ($will{checkAnswers} || $c->{will}{showProblemGrader}) { push( @$output, $c->tag( 'div', - class => 'ResultsWithError d-inline-block mb-3', + class => 'ResultsWithError d-inline-block mb-2', $c->maketext('ANSWERS ONLY CHECKED -- ANSWERS NOT RECORDED') ), - $c->attemptResults($pg, $will{showCorrectAnswers}, 1, 1) + $c->attemptResults($pg) ); } elsif ($c->{previewAnswers}) { push( @$output, $c->tag( 'div', - class => 'ResultsWithError d-inline-block mb-3', + class => 'ResultsWithError d-inline-block mb-2', $c->maketext('PREVIEW ONLY -- ANSWERS NOT RECORDED') ), - $c->attemptResults($pg, 0, 0, 0) ); } @@ -1522,7 +1489,7 @@ sub output_summary ($c) { @$output, $c->tag( 'div', - class => 'ResultsWithError d-inline-block mb-3', + class => 'ResultsWithError d-inline-block mb-2', $c->maketext( 'ATTEMPT NOT ACCEPTED -- Please submit answers again (or request new version if neccessary).') ) diff --git a/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm b/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm index a18e87dd09..0c172c181f 100644 --- a/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm +++ b/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm @@ -299,12 +299,18 @@ async sub pre_header_initialize ($c) { processAnswers => 1, permissionLevel => $db->getPermissionLevel($userName)->permission, effectivePermissionLevel => $db->getPermissionLevel($effectiveUserName)->permission, - useMathQuill => $c->{will}{useMathQuill}, - useMathView => $c->{will}{useMathView}, + useMathQuill => $will->{useMathQuill}, + useMathView => $will->{useMathView}, forceScaffoldsOpen => 0, isInstructor => $authz->hasPermissions($userName, 'view_answers'), + showFeedback => $c->{checkAnswers} || $c->{previewAnswers}, + showAttemptAnswers => $ce->{pg}{options}{showEvaluatedAnswers}, + showAttemptPreviews => 1, + showAttemptResults => $c->{checkAnswers}, + showMessages => 1, + showCorrectAnswers => $will->{checkAnswers} ? $will->{showCorrectAnswers} : 0, debuggingOptions => getTranslatorDebuggingOptions($authz, $userName) - }, + } ); # Warnings in the renderPG subprocess will not be caught by the global warning handler of this process. diff --git a/lib/WeBWorK/HTML/AttemptsTable.pm b/lib/WeBWorK/HTML/AttemptsTable.pm deleted file mode 100644 index 15103e0638..0000000000 --- a/lib/WeBWorK/HTML/AttemptsTable.pm +++ /dev/null @@ -1,466 +0,0 @@ -################################################################################ -# WeBWorK Online Homework Delivery System -# Copyright © 2000-2023 The WeBWorK Project, https://github.com/openwebwork -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of either: (a) the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any later -# version, or (b) the "Artistic License" which comes with this package. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the -# Artistic License for more details. -################################################################################ - -=head1 NAME - - AttemptsTable - -=head1 SYNPOSIS - - my $tbl = WeBWorK::HTML::AttemptsTable->new( - $answers, - answersSubmitted => 1, - answerOrder => $pg->{flags}{ANSWER_ENTRY_ORDER}, - displayMode => 'MathJax', - showAnswerNumbers => 0, - showAttemptAnswers => $showAttemptAnswers && $showEvaluatedAnswers, - showAttemptPreviews => $showAttemptPreview, - showAttemptResults => $showAttemptResults, - showCorrectAnswers => $showCorrectAnswers, - showMessages => $showAttemptAnswers, # internally checks for messages - showSummary => $showSummary, - imgGen => $imgGen, # not needed if ce is present , - ce => '', # not needed if $imgGen is present - maketext => WeBWorK::Localize::getLoc("en"), - ); - $tbl->{imgGen}->render(refresh => 1) if $tbl->displayMode eq 'images'; - my $answerTemplate = $tbl->answerTemplate; - - -=head1 DESCRIPTION - -This module handles the formatting of the table which presents the results of analyzing a student's -answer to a WeBWorK problem. It is used in Problem.pm, OpaqueServer.pm, standAlonePGproblemRender - -=head2 new - - my $tbl = WeBWorK::HTML::AttemptsTable->new( - $answers, - answersSubmitted => 1, - answerOrder => $pg->{flags}{ANSWER_ENTRY_ORDER}, - displayMode => 'MathJax', - showHeadline => 1, - showAnswerNumbers => 0, - showAttemptAnswers => $showAttemptAnswers && $showEvaluatedAnswers, - showAttemptPreviews => $showAttemptPreview, - showAttemptResults => $showAttemptResults, - showCorrectAnswers => $showCorrectAnswers, - showMessages => $showAttemptAnswers, # internally checks for messages - showSummary => $showSummary, - imgGen => $imgGen, # not needed if ce is present , - ce => '', # not needed if $imgGen is present - maketext => WeBWorK::Localize::getLoc("en"), - summary =>'', - ); - - $answers -- a hash of student answers e.g. $pg->{answers} - answersSubmitted if 0 then then the attemptsTable is not displayed (???) - answerOrder -- an array indicating the order the answers appear on the page. - displayMode 'MathJax' and 'images' are the most common - - showHeadline Show the header line 'Results for this submission' - - showAnswerNumbers, showAttemptAnswers, showAttemptPreviews,showAttemptResults, - showCorrectAnswers and showMessages control the display of each column in the table. - - attemptAnswers the student's typed in answer (possibly simplified numerically) - attemptPreview the student's answer after typesetting - attemptResults "correct", "_% correct", "incorrect" or "ungraded"- links to the answer blank - correctAnswers typeset version (untypeset versions are available via popups) - messages warns of formatting typos in the answer, or - more detailed messages about a wrong answer - summary is obtained from $pg->{result}{summary}. - If this is empty then a (localized) - version of "all answers are correct" - or "at least one answer is not coorrect" - imgGen points to a prebuilt image generator objectfor "images" mode - ce points to the CourseEnvironment -- it is needed if AttemptsTable - is required to build its own imgGen object - maketext points to a localization subroutine - -=head2 Methods - -=over 4 - -=item answerTemplate - -Returns HTML which formats the analysis of the student's answers to the problem. - -=back - -=head2 Read/Write Properties - -=over 4 - -=item showMessages, - -This can be switched on or off before exporting the answerTemplate, perhaps -under instructions from the PG problem. - -=item summary - -The contents of the summary can be defined when the attemptsTable object is created. - -The summary can be defined by the PG problem grader usually returned as -$pg->{result}{summary}. - -If the summary is not explicitly defined then (localized) versions -of the default summaries are created: - - "The answer above is correct.", - "Some answers will be graded later.", - "All of the [gradeable] answers above are correct.", - "[N] of the questions remain unanswered.", - "At least one of the answers above is NOT [fully] correct.', - -Note that if this is set after initialization, you must ensure that it is a -Mojo::ByteStream object if it contains html or characters that need escaping. - -=back - -=cut - -package WeBWorK::HTML::AttemptsTable; -use Mojo::Base 'Class::Accessor', -signatures; - -use Scalar::Util 'blessed'; -use WeBWorK::Utils 'wwRound'; - -# %options may contain: displayMode, submitted, imgGen, ce -# At least one of imgGen or ce must be provided if displayMode is 'images'. -sub new ($class, $rh_answers, $c, %options) { - $class = ref $class || $class; - ref($rh_answers) =~ /HASH/ or die 'The first entry to AttemptsTable must be a hash of answers'; - $c->isa('WeBWorK::Controller') or die 'The second entry to AttemptsTable must be a WeBWorK::Controller'; - my $self = bless { - answers => $rh_answers, - c => $c, - answerOrder => $options{answerOrder} // [], - answersSubmitted => $options{answersSubmitted} // 0, - summary => undef, # summary provided by problem grader (set in _init) - displayMode => $options{displayMode} || 'MathJax', - showHeadline => $options{showHeadline} // 1, - showAnswerNumbers => $options{showAnswerNumbers} // 1, - showAttemptAnswers => $options{showAttemptAnswers} // 1, # show student answer as entered and parsed - showAttemptPreviews => $options{showAttemptPreviews} // 1, # show preview of student answer - showAttemptResults => $options{showAttemptResults} // 1, # show results of grading student answer - showMessages => $options{showMessages} // 1, # show messages generated by evaluation - showCorrectAnswers => $options{showCorrectAnswers} // 0, # show the correct answers - showSummary => $options{showSummary} // 1, # show result summary - imgGen => undef, # set or created in _init method - }, $class; - - # Create accessors/mutators - $self->mk_ro_accessors(qw(answers c answerOrder answersSubmitted displayMode imgGen showAnswerNumbers - showAttemptAnswers showHeadline showAttemptPreviews showAttemptResults showCorrectAnswers showSummary)); - $self->mk_accessors(qw(showMessages summary)); - - # Sanity check and initialize imgGenerator. - $self->_init(%options); - - return $self; -} - -# Verify the display mode, and build imgGen if it is not supplied. -sub _init ($self, %options) { - $self->{submitted} = $options{submitted} // 0; - $self->{displayMode} = $options{displayMode} || 'MathJax'; - - # Only show message column if there is at least one message. - my @reallyShowMessages = grep { $self->answers->{$_}{ans_message} } @{ $self->answerOrder }; - $self->showMessages($self->showMessages && !!@reallyShowMessages); - - # Only used internally. Accessors are not needed. - $self->{numCorrect} = 0; - $self->{numBlanks} = 0; - $self->{numEssay} = 0; - - if ($self->displayMode eq 'images') { - if (blessed($options{imgGen}) && $options{imgGen}->isa('WeBWorK::PG::ImageGenerator')) { - $self->{imgGen} = $options{imgGen}; - } elsif (blessed($options{ce}) && $options{ce}->isa('WeBWorK::CourseEnvironment')) { - my $ce = $options{ce}; - - $self->{imgGen} = WeBWorK::PG::ImageGenerator->new( - tempDir => $ce->{webworkDirs}{tmp}, - latex => $ce->{externalPrograms}{latex}, - dvipng => $ce->{externalPrograms}{dvipng}, - useCache => 1, - cacheDir => $ce->{webworkDirs}{equationCache}, - cacheURL => $ce->{server_root_url} . $ce->{webworkURLs}{equationCache}, - cacheDB => $ce->{webworkFiles}{equationCacheDB}, - dvipng_align => $ce->{pg}{displayModeOptions}{images}{dvipng_align}, - dvipng_depth_db => $ce->{pg}{displayModeOptions}{images}{dvipng_depth_db}, - ); - } else { - warn 'Must provide image Generator (imgGen) or a course environment (ce) to build attempts table.'; - } - } - - # Make sure that the provided summary is a Mojo::ByteStream object. - $self->summary(blessed($options{summary}) - && $options{summary}->isa('Mojo::ByteStream') ? $options{summary} : $self->c->b($options{summary} // '')); - - return; -} - -sub formatAnswerRow ($self, $rh_answer, $ans_id, $answerNumber) { - my $c = $self->c; - - my $answerString = $rh_answer->{student_ans} // ''; - my $answerPreview = $self->previewAnswer($rh_answer) // ' '; - my $correctAnswer = $rh_answer->{correct_ans} // ''; - my $correctAnswerPreview = $self->previewCorrectAnswer($rh_answer) // ' '; - - my $answerMessage = $rh_answer->{ans_message} // ''; - $answerMessage =~ s/\n/
/g; - my $answerScore = $rh_answer->{score} // 0; - $self->{numCorrect} += $answerScore >= 1; - $self->{numEssay} += ($rh_answer->{type} // '') eq 'essay'; - $self->{numBlanks}++ unless $answerString =~ /\S/ || $answerScore >= 1; - - my $feedbackMessageClass = ($answerMessage eq '') ? '' : $c->maketext('FeedbackMessage'); - - my $resultString; - my $resultStringClass; - if ($answerScore >= 1) { - $resultString = $c->maketext('correct'); - $resultStringClass = 'ResultsWithoutError'; - } elsif (($rh_answer->{type} // '') eq 'essay') { - $resultString = $c->maketext('Ungraded'); - $self->{essayFlag} = 1; - } elsif ($answerScore == 0) { - $resultStringClass = 'ResultsWithError'; - $resultString = $c->maketext('incorrect'); - } else { - $resultString = $c->maketext('[_1]% correct', wwRound(0, $answerScore * 100)); - } - my $attemptResults = $c->tag( - 'td', - class => $resultStringClass, - $c->tag('a', href => '#', data => { answer_id => $ans_id }, $self->nbsp($resultString)) - ); - - return $c->c( - $self->showAnswerNumbers ? $c->tag('td', $answerNumber) : '', - $self->showAttemptAnswers ? $c->tag('td', dir => 'auto', $self->nbsp($answerString)) : '', - $self->showAttemptPreviews - ? (((defined $answerPreview && $answerPreview ne '') || $self->showAttemptAnswers) - ? $self->formatToolTip($answerString, $answerPreview) - : $c->tag('td', dir => 'auto', $self->nbsp($answerString))) - : '', - $self->showAttemptResults ? $attemptResults : '', - $self->showCorrectAnswers ? $self->formatToolTip($correctAnswer, $correctAnswerPreview) : '', - $self->showMessages ? $c->tag('td', class => $feedbackMessageClass, $self->nbsp($answerMessage)) : '' - )->join(''); -} - -# Determine whether any answers were submitted and create answer template if they have been. -sub answerTemplate ($self) { - my $c = $self->c; - - return '' unless $self->answersSubmitted; # Only print if there is at least one non-blank answer - - my $tableRows = $c->c; - - push( - @$tableRows, - $c->tag( - 'tr', - $c->c( - $self->showAnswerNumbers ? $c->tag('th', '#') : '', - $self->showAttemptAnswers ? $c->tag('th', $c->maketext('Entered')) : '', - $self->showAttemptPreviews ? $c->tag('th', $c->maketext('Answer Preview')) : '', - $self->showAttemptResults ? $c->tag('th', $c->maketext('Result')) : '', - $self->showCorrectAnswers ? $c->tag('th', $c->maketext('Correct Answer')) : '', - $self->showMessages ? $c->tag('th', $c->maketext('Message')) : '' - )->join('') - ) - ); - - my $answerNumber = 0; - for (@{ $self->answerOrder() }) { - push @$tableRows, $c->tag('tr', $self->formatAnswerRow($self->{answers}{$_}, $_, ++$answerNumber)); - } - - return $c->c( - $self->showHeadline - ? $c->tag('h2', class => 'attemptResultsHeader', $c->maketext('Results for this submission')) - : '', - $c->tag( - 'div', - class => 'table-responsive', - $c->tag('table', class => 'attemptResults table table-sm table-bordered', $tableRows->join('')) - ), - $self->showSummary ? $self->createSummary : '' - )->join(''); -} - -sub previewAnswer ($self, $answerResult) { - my $displayMode = $self->displayMode; - my $imgGen = $self->imgGen; - - my $tex = $answerResult->{preview_latex_string}; - - return '' unless defined $tex and $tex ne ''; - - return $tex if $answerResult->{non_tex_preview}; - - if ($displayMode eq 'plainText') { - return $tex; - } elsif (($answerResult->{type} // '') eq 'essay') { - return $tex; - } elsif ($displayMode eq 'images') { - return $imgGen->add($tex); - } elsif ($displayMode eq 'MathJax') { - return $self->c->tag('script', type => 'math/tex; mode=display', $self->c->b($tex)); - } -} - -sub previewCorrectAnswer ($self, $answerResult) { - my $displayMode = $self->displayMode; - my $imgGen = $self->imgGen; - - my $tex = $answerResult->{correct_ans_latex_string}; - - # Some answers don't have latex strings defined return the raw correct answer - # unless defined $tex and $tex contains non whitespace characters; - return $answerResult->{correct_ans} - unless defined $tex and $tex =~ /\S/; - - return $tex if $answerResult->{non_tex_preview}; - - if ($displayMode eq 'plainText') { - return $tex; - } elsif ($displayMode eq 'images') { - return $imgGen->add($tex); - } elsif ($displayMode eq 'MathJax') { - return $self->c->tag('script', type => 'math/tex; mode=display', $self->c->b($tex)); - } -} - -# Create summary -sub createSummary ($self) { - my $c = $self->c; - - my $numCorrect = $self->{numCorrect}; - my $numBlanks = $self->{numBlanks}; - my $numEssay = $self->{numEssay}; - - my $summary; - - unless (defined($self->summary) and $self->summary =~ /\S/) { - # Default messages - $summary = $c->c; - my @answerNames = @{ $self->answerOrder() }; - if (scalar @answerNames == 1) { - if ($numCorrect == scalar @answerNames) { - push( - @$summary, - $c->tag( - 'div', - class => 'ResultsWithoutError mb-2', - $c->maketext('The answer above is correct.') - ) - ); - } elsif ($self->{essayFlag}) { - push(@$summary, $c->tag('div', $c->maketext('Some answers will be graded later.'))); - } else { - push( - @$summary, - $c->tag( - 'div', - class => 'ResultsWithError mb-2', - $c->maketext('The answer above is NOT correct.') - ) - ); - } - } else { - if ($numCorrect + $numEssay == scalar @answerNames) { - if ($numEssay) { - push( - @$summary, - $c->tag( - 'div', - class => 'ResultsWithoutError mb-2', - $c->maketext('All of the gradeable answers above are correct.') - ) - ); - } else { - push( - @$summary, - $c->tag( - 'div', - class => 'ResultsWithoutError mb-2', - $c->maketext('All of the answers above are correct.') - ) - ); - } - } elsif ($numBlanks + $numEssay != scalar(@answerNames)) { - push( - @$summary, - $c->tag( - 'div', - class => 'ResultsWithError mb-2', - $c->maketext('At least one of the answers above is NOT correct.') - ) - ); - } - if ($numBlanks > $numEssay) { - my $s = ($numBlanks > 1) ? '' : 's'; - push( - @$summary, - $c->tag( - 'div', - class => 'ResultsAlert mb-2', - $c->maketext( - '[quant,_1,of the questions remains,of the questions remain] unanswered.', $numBlanks - ) - ) - ); - } - } - $summary = $summary->join(''); - } else { - $summary = $self->summary; # Summary defined by grader - } - $summary = $c->tag('div', role => 'alert', class => 'attemptResultsSummary', $summary); - $self->summary($summary); - return $summary; -} - -# Utility subroutine that prevents unwanted line breaks, and ensures that the return value is a Mojo::ByteStream object. -sub nbsp ($self, $str) { - return $self->c->b(defined $str && $str =~ /\S/ ? $str : ' '); -} - -# Note that formatToolTip output includes the wrapper. -sub formatToolTip ($self, $answer, $formattedAnswer) { - return $self->c->tag( - 'td', - $self->c->tag( - 'div', - class => 'answer-preview', - data => { - bs_toggle => 'popover', - bs_content => $answer, - bs_placement => 'bottom', - }, - $self->nbsp($formattedAnswer) - ) - ); -} - -1; diff --git a/lib/WeBWorK/Utils/Rendering.pm b/lib/WeBWorK/Utils/Rendering.pm index 1bb7fa2d76..f10e27641c 100644 --- a/lib/WeBWorK/Utils/Rendering.pm +++ b/lib/WeBWorK/Utils/Rendering.pm @@ -151,6 +151,15 @@ sub constructPGOptions ($ce, $user, $set, $problem, $psvn, $formFields, $transla $options{inputs_ref} = $formFields; $options{processAnswers} = $translationOptions->{processAnswers}; + # Attempt Results + $options{showFeedback} = $translationOptions->{showFeedback}; + $options{showAttemptAnswers} = $translationOptions->{showAttemptAnswers}; + $options{showAttemptPreviews} = $translationOptions->{showAttemptPreviews}; + $options{forceShowAttemptResults} = $translationOptions->{forceShowAttemptResults}; + $options{showAttemptResults} = $translationOptions->{showAttemptResults}; + $options{showMessages} = $translationOptions->{showMessages}; + $options{showCorrectAnswers} = $translationOptions->{showCorrectAnswers}; + # External Data $options{external_data} = decode_json($set->{external_data} || '{}'); @@ -244,7 +253,7 @@ sub renderPG ($c, $effectiveUser, $set, $problem, $psvn, $formFields, $translati flags => $pg->{flags}, }; - if (ref $pg->{pgcore}) { + if (ref($pg->{pgcore}) eq 'PGcore') { $ret->{internal_debug_messages} = $pg->{pgcore}->get_internal_debug_messages; $ret->{warning_messages} = $pg->{pgcore}->get_warning_messages(); $ret->{debug_messages} = $pg->{pgcore}->get_debug_messages(); diff --git a/lib/WebworkWebservice/RenderProblem.pm b/lib/WebworkWebservice/RenderProblem.pm index ac2f5ef6ab..f039322613 100644 --- a/lib/WebworkWebservice/RenderProblem.pm +++ b/lib/WebworkWebservice/RenderProblem.pm @@ -228,7 +228,15 @@ async sub renderProblem { isInstructor => $rh->{isInstructor} // 0, forceScaffoldsOpen => $rh->{forceScaffoldsOpen} // 0, QUIZ_PREFIX => $rh->{answerPrefix}, - debuggingOptions => { + showFeedback => $rh->{preview} || $rh->{WWsubmit} || $rh->{WWcorrectAns}, + showAttemptAnswers => $rh->{showAttemptAnswers} // 1, + showAttemptPreviews => $rh->{showAttemptPreviews} + // ($rh->{preview} || $rh->{WWsubmit} || $rh->{WWcorrectAns}), + showAttemptResults => $rh->{showAttemptResults} // ($rh->{WWsubmit} || $rh->{WWcorrectAns}), + forceShowAttemptResults => $rh->{forceShowAttemptResults}, + showMessages => $rh->{showMessages} // ($rh->{preview} || $rh->{WWsubmit} || $rh->{WWcorrectAns}), + showCorrectAnswers => $rh->{showCorrectAnswers} // $rh->{WWcorrectAns}, + debuggingOptions => { show_resource_info => $rh->{show_resource_info} // 0, view_problem_debugging_info => $rh->{view_problem_debugging_info} // 0, show_pg_info => $rh->{show_pg_info} // 0, diff --git a/templates/ContentGenerator/GatewayQuiz.html.ep b/templates/ContentGenerator/GatewayQuiz.html.ep index f85113404c..9751ee722a 100644 --- a/templates/ContentGenerator/GatewayQuiz.html.ep +++ b/templates/ContentGenerator/GatewayQuiz.html.ep @@ -490,7 +490,6 @@ <%= $jumpLinks->() =%> % % # Print out problems and attempt results, as appropriate. - % # Note: Usage is $c->attemptResults($pg, $showCorrectAnswers, $showAttemptResults, $showSummary) % for my $i (0 .. $#$pg_results) { % my $pg = $pg_results->[ $probOrder->[$i] ]; % @@ -498,34 +497,23 @@ % my $recordMessage = ''; % my $resultsTable = ''; % - % if ($pg->{flags}{showPartialCorrectAnswers} >= 0 && $c->{submitAnswers}) { + % if ($c->{submitAnswers}) { % if ($c->{scoreRecordedMessage}[ $probOrder->[$i] ] ne 'recorded') { % $recordMessage = tag('div', class => 'ResultsWithError d-inline-block mb-2', % maketext('ANSWERS NOT RECORDED -- [_1]', $c->{scoreRecordedMessage}[ $probOrder->[$i] ]) % ); % } - % $resultsTable = $c->attemptResults( - % $pg, - % $c->{will}{showCorrectAnswers}, - % $pg->{flags}{showPartialCorrectAnswers} && $c->{can}{showProblemScores}, - % $c->{can}{showProblemScores} - % ); + % $resultsTable = $c->attemptResults($pg); % } elsif ($c->{will}{checkAnswers} || $c->{will}{showProblemGrader}) { % $recordMessage = tag('div', class => 'ResultsWithError d-inline-block mb-2', % maketext('ANSWERS ONLY CHECKED -- ANSWERS NOT RECORDED') % ); % - % $resultsTable = $c->attemptResults( - % $pg, - % $c->{will}{showCorrectAnswers}, - % $pg->{flags}{showPartialCorrectAnswers} && $c->{can}{showProblemScores}, - % $c->{can}{showProblemScores} - % ); + % $resultsTable = $c->attemptResults($pg); % } elsif ($c->{previewAnswers}) { % $recordMessage = tag('div', class => 'ResultsWithError d-inline-block mb-2', % maketext('PREVIEW ONLY -- ANSWERS NOT RECORDED') % ); - % $resultsTable = $c->attemptResults($pg, 0, 0, 0); % } %
diff --git a/templates/RPCRenderFormats/default.html.ep b/templates/RPCRenderFormats/default.html.ep index fbccee5544..71e4f68543 100644 --- a/templates/RPCRenderFormats/default.html.ep +++ b/templates/RPCRenderFormats/default.html.ep @@ -37,7 +37,7 @@
- %== $answerTemplate + %== $resultSummary <%= form_for $FORM_ACTION_URL, id => 'problemMainForm', class => 'problem-main-form', name => 'problemMainForm', method => 'POST', begin %>
> @@ -66,7 +66,6 @@ % } %== $LTIGradeMessage % - %= hidden_field answersSubmitted => 1 %= hidden_field sourceFilePath => $sourceFilePath %= hidden_field problemSource => $problemSource %= hidden_field uriEncodedProblemSource => $uriEncodedProblemSource @@ -87,7 +86,6 @@ %= hidden_field showSummary => $showSummary %= hidden_field showHints => $showHints %= hidden_field showSolutions => $showSolutions - %= hidden_field showAnswerNumbers => $showAnswerNumbers %= hidden_field showPreviewButton => $showPreviewButton %= hidden_field showCheckAnswersButton => $showCheckAnswersButton %= hidden_field showCorrectAnswersButton => $showCorrectAnswersButton diff --git a/templates/RPCRenderFormats/default.json.ep b/templates/RPCRenderFormats/default.json.ep index 38a8c504d9..c25764aadd 100644 --- a/templates/RPCRenderFormats/default.json.ep +++ b/templates/RPCRenderFormats/default.json.ep @@ -19,7 +19,7 @@ % % body_part001 => '', % body_part100 => '
', - % body_part300 => $answerTemplate, + % body_part300 => $resultSummary, % body_part500 => '
', % body_part530 => qq{
}, @@ -46,7 +46,6 @@ % . '}', % % hidden_input_field => { - % answersSubmitted => '1', % sourceFilePath => $sourceFilePath, % problemSource => $problemSource, % problemSeed => $problemSeed, @@ -64,7 +63,6 @@ % showSummary => $showSummary, % showHints => $showHints, % showSolutions => $showSolutions, - % showAnswerNumbers => $showAnswerNumbers, % showPreviewButton => $showPreviewButton, % showCheckAnswersButton => $showCheckAnswersButton, % showCorrectAnswersButton => $showCorrectAnswersButton, From 1a34fc30d97b30b2f3279d8ab1192463e5085671 Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Wed, 4 Oct 2023 16:36:38 -0500 Subject: [PATCH 2/2] Switch to using bootstrap alerts for problem messages. Dispense with the ResultsWithError and ResultsWithoutError classes, and instead use bootstrap alerts with the alert-danger and alert-sucess classes. Also remove the unused `$pg{options}{correct_answer}` and `$pg{options}{incorrect_answer}` variables from defaults.config. --- conf/defaults.config | 6 ------ lib/WeBWorK/ContentGenerator/Problem.pm | 6 +++--- lib/WeBWorK/ContentGenerator/ShowMeAnother.pm | 8 ++++---- templates/ContentGenerator/GatewayQuiz.html.ep | 16 ++++++++-------- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/conf/defaults.config b/conf/defaults.config index 9ca7323842..96dbe4b120 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -1045,12 +1045,6 @@ $pg{options}{showEvaluatedAnswers} = 1; # propogate to the main process. So this really should never be set to 0. $pg{options}{catchWarnings} = 1; -# decorations for correct input blanks -- apparently you can't define and name attribute collections in a .css file -$pg{options}{correct_answer} = "{border-width:2;border-style:solid;border-color:#8F8}"; #matches resultsWithOutError class in math2.css - -# decorations for incorrect input blanks -$pg{options}{incorrect_answer} = "{border-width:2;border-style:solid;border-color:#F55}"; #matches resultsWithError class in math2.css - ##### Settings for various display modes # "images" mode has several settings: diff --git a/lib/WeBWorK/ContentGenerator/Problem.pm b/lib/WeBWorK/ContentGenerator/Problem.pm index 9fe1a03f02..ce5451a027 100644 --- a/lib/WeBWorK/ContentGenerator/Problem.pm +++ b/lib/WeBWorK/ContentGenerator/Problem.pm @@ -1469,7 +1469,7 @@ sub output_summary ($c) { @$output, $c->tag( 'div', - class => 'ResultsWithError d-inline-block mb-2', + class => 'alert alert-danger d-inline-block mb-2 p-1', $c->maketext('ANSWERS ONLY CHECKED -- ANSWERS NOT RECORDED') ), $c->attemptResults($pg) @@ -1479,7 +1479,7 @@ sub output_summary ($c) { @$output, $c->tag( 'div', - class => 'ResultsWithError d-inline-block mb-2', + class => 'alert alert-danger d-inline-block mb-2 p-1', $c->maketext('PREVIEW ONLY -- ANSWERS NOT RECORDED') ), ); @@ -1489,7 +1489,7 @@ sub output_summary ($c) { @$output, $c->tag( 'div', - class => 'ResultsWithError d-inline-block mb-2', + class => 'alert alert-danger d-inline-block mb-2 p-1', $c->maketext( 'ATTEMPT NOT ACCEPTED -- Please submit answers again (or request new version if neccessary).') ) diff --git a/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm b/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm index 0c172c181f..d0bd45f011 100644 --- a/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm +++ b/lib/WeBWorK/ContentGenerator/ShowMeAnother.pm @@ -518,7 +518,7 @@ sub output_summary ($c) { ), $c->tag( 'div', - class => 'ResultsAlert', + class => 'alert alert-warning mb-2 p-1', $c->maketext(q{Remember to return to your original problem when you're finished here!}) ) ); @@ -532,7 +532,7 @@ sub output_summary ($c) { @$output, $c->tag( 'div', - class => 'ResultsAlert', + class => 'alert alert-warning mb-2 p-1', $c->maketext( 'You are only allowed to click on Show Me Another [quant,_1,time,times] per problem. ' . '[_2] Close this tab, and return to the original problem.', @@ -546,7 +546,7 @@ sub output_summary ($c) { @$output, $c->tag( 'div', - class => 'ResultsAlert', + class => 'alert alert-warning mb-2 p-1', $c->maketext( 'You must attempt this problem [quant,_1,time,times] before Show Me Another is available.', $showMeAnother{TriesNeeded} @@ -561,7 +561,7 @@ sub output_summary ($c) { @$output, $c->tag( 'div', - class => 'ResultsAlert', + class => 'alert alert-warning mb-2 p-1', $c->maketext( 'WeBWorK was unable to generate a different version of this problem. ' . 'Close this tab, and return to the original problem.' diff --git a/templates/ContentGenerator/GatewayQuiz.html.ep b/templates/ContentGenerator/GatewayQuiz.html.ep index 9751ee722a..0934437597 100644 --- a/templates/ContentGenerator/GatewayQuiz.html.ep +++ b/templates/ContentGenerator/GatewayQuiz.html.ep @@ -115,17 +115,17 @@ % my $numProbPerPage = $c->{set}->problems_per_page; % % if ($c->{will}{recordAnswers}) { - % my $divClass = 'ResultsWithoutError'; + % my $divClass = 'alert-success'; % my $recdMsg = ''; % for (@{ $c->{scoreRecordedMessage} }) { % if ($_ ne 'recorded') { % $recdMsg = $_; - % $divClass = 'ResultsWithError'; + % $divClass = 'alert-danger'; % last; % } % } % -
+
"> % # A handy noun for when referring to a test. % my $testNoun = ($c->{set}->attempts_per_version || 0) > 1 ? maketext('submission') : maketext('test'); % my $testNounNum = @@ -256,11 +256,11 @@ % } % % if ($timeLeft < 60 && $timeLeft > 0 && !$authz->hasPermissions($userID, 'record_answers_when_acting_as_student')) { -
+
<%= maketext('You have less than 1 minute to complete this test.') %>
% } elsif ($timeLeft <= 0 && !$authz->hasPermissions($userID, 'record_answers_when_acting_as_student')) { -
+
<%= maketext('You are out of time!') . ( @@ -499,19 +499,19 @@ % % if ($c->{submitAnswers}) { % if ($c->{scoreRecordedMessage}[ $probOrder->[$i] ] ne 'recorded') { - % $recordMessage = tag('div', class => 'ResultsWithError d-inline-block mb-2', + % $recordMessage = tag('div', class => 'alert alert-dangeer d-inline-block mb-2 p-1', % maketext('ANSWERS NOT RECORDED -- [_1]', $c->{scoreRecordedMessage}[ $probOrder->[$i] ]) % ); % } % $resultsTable = $c->attemptResults($pg); % } elsif ($c->{will}{checkAnswers} || $c->{will}{showProblemGrader}) { - % $recordMessage = tag('div', class => 'ResultsWithError d-inline-block mb-2', + % $recordMessage = tag('div', class => 'alert alert-danger d-inline-block mb-2 p-1', % maketext('ANSWERS ONLY CHECKED -- ANSWERS NOT RECORDED') % ); % % $resultsTable = $c->attemptResults($pg); % } elsif ($c->{previewAnswers}) { - % $recordMessage = tag('div', class => 'ResultsWithError d-inline-block mb-2', + % $recordMessage = tag('div', class => 'alert alert-danger d-inline-block mb-2 p-1', % maketext('PREVIEW ONLY -- ANSWERS NOT RECORDED') % ); % }