diff --git a/assets/blocks/quiz/answer-blocks/index.js b/assets/blocks/quiz/answer-blocks/index.js index 38ccdace07..a33d7b6e35 100644 --- a/assets/blocks/quiz/answer-blocks/index.js +++ b/assets/blocks/quiz/answer-blocks/index.js @@ -42,6 +42,7 @@ const questionTypes = { view: MultipleChoiceAnswer.view, settings: [ QuestionMultipleChoiceSettings ], feedback: true, + hasContextualFeedback: true, validate: ( { answers = [] } = {} ) => { return { noAnswers: answers.filter( ( a ) => a.label ).length < 2, @@ -89,6 +90,7 @@ const questionTypes = { edit: TrueFalseAnswer, view: TrueFalseAnswer.view, feedback: true, + hasContextualFeedback: true, settings: [], }, 'gap-fill': { @@ -97,6 +99,7 @@ const questionTypes = { edit: GapFillAnswer, view: GapFillAnswer.view, feedback: true, + hasContextualFeedback: true, settings: [], validate: ( { before, after, gap } = {} ) => { return { @@ -130,6 +133,7 @@ const questionTypes = { 'Short answer to an open-ended question.', 'sensei-lms' ), + feedback: true, edit: SingleLineAnswer, view: SingleLineAnswer, settings: [ QuestionGradingNotesSettings ], @@ -140,6 +144,7 @@ const questionTypes = { 'Long answer to an open-ended question.', 'sensei-lms' ), + feedback: true, edit: MultiLineAnswer, view: MultiLineAnswer, settings: [ QuestionGradingNotesSettings ], diff --git a/assets/blocks/quiz/answer-feedback-block/answer-feedback.js b/assets/blocks/quiz/answer-feedback-block/answer-feedback.js index 95ba788cf2..c4ec7e0e3e 100644 --- a/assets/blocks/quiz/answer-feedback-block/answer-feedback.js +++ b/assets/blocks/quiz/answer-feedback-block/answer-feedback.js @@ -29,6 +29,13 @@ const config = { 'sensei-lms' ), }, + generic: { + title: __( 'Feedback', 'sensei-lms' ), + placeholder: __( + 'Show a message when the question has been answered', + 'sensei-lms' + ), + }, }; /** diff --git a/assets/blocks/quiz/answer-feedback-block/index.js b/assets/blocks/quiz/answer-feedback-block/index.js index 3649c8fb64..7d973dcf8a 100644 --- a/assets/blocks/quiz/answer-feedback-block/index.js +++ b/assets/blocks/quiz/answer-feedback-block/index.js @@ -23,6 +23,19 @@ const sharedMetadata = { }, }; +/** + * Generic Answer Feedback block definition. + */ +export const answerFeedbackGenericBlock = { + ...sharedMetadata, + name: 'sensei-lms/quiz-question-feedback-generic', + title: __( 'Generic Answer Feedback', 'sensei-lms' ), + icon, + description: __( 'Display generic answer feedback.', 'sensei-lms' ), + edit: ( props ) => edit( { ...props, type: 'generic' } ), + save: () => , +}; + /** * Correct Answer Feedback block definition. */ diff --git a/assets/blocks/quiz/index.js b/assets/blocks/quiz/index.js index d9cb04d003..7163d448df 100644 --- a/assets/blocks/quiz/index.js +++ b/assets/blocks/quiz/index.js @@ -6,6 +6,7 @@ import registerSenseiBlocks from '../register-sensei-blocks'; import { answerFeedbackCorrectBlock, answerFeedbackIncorrectBlock, + answerFeedbackGenericBlock, } from './answer-feedback-block'; import questionDescriptionBlock from './question-description-block'; import questionAnswersBlock from './question-answers-block'; @@ -21,6 +22,7 @@ const blocks = [ questionDescriptionBlock, answerFeedbackCorrectBlock, answerFeedbackIncorrectBlock, + answerFeedbackGenericBlock, questionAnswersBlock, ]; diff --git a/assets/blocks/quiz/question-answers-block/question-answers.js b/assets/blocks/quiz/question-answers-block/question-answers.js index 9cfcbc7a3b..f5f668b653 100644 --- a/assets/blocks/quiz/question-answers-block/question-answers.js +++ b/assets/blocks/quiz/question-answers-block/question-answers.js @@ -19,13 +19,9 @@ import { QuestionContext } from '../question-block/question-context'; * */ const QuestionAnswers = () => { - const { - answer, - setAttributes, - AnswerBlock, - hasSelected, - canHaveFeedback, - } = useContext( QuestionContext ); + const { answer, setAttributes, AnswerBlock, hasSelected } = useContext( + QuestionContext + ); return (
{ AnswerBlock?.edit && ( @@ -39,9 +35,7 @@ const QuestionAnswers = () => { } hasSelected={ hasSelected } /> - { canHaveFeedback && hasSelected && ( - - ) } + { hasSelected && } ) }
diff --git a/assets/blocks/quiz/question-block/question-block.editor.scss b/assets/blocks/quiz/question-block/question-block.editor.scss index 482b827c30..9b046c53ad 100644 --- a/assets/blocks/quiz/question-block/question-block.editor.scss +++ b/assets/blocks/quiz/question-block/question-block.editor.scss @@ -5,8 +5,8 @@ $block: '.sensei-lms-question-block'; @import '../../../shared/styles/wp-colors'; .sensei-lms-question-block { - - .editor-styles-wrapper .wp-block &__title, .editor-styles-wrapper .wp-block &__index { + .editor-styles-wrapper .wp-block &__title, + .editor-styles-wrapper .wp-block &__index { font-size: 24px; margin-top: 0; margin-bottom: 0; @@ -30,7 +30,7 @@ $block: '.sensei-lms-question-block'; white-space: nowrap; #{$block}.is-draft & { - opacity: .62; + opacity: 0.62; } .editor-styles-wrapper .wp-block & { @@ -47,7 +47,6 @@ $block: '.sensei-lms-question-block'; } &__type-selector { - &__popover .sensei-toolbar-dropdown__option { padding: 12px; } @@ -74,7 +73,8 @@ $block: '.sensei-lms-question-block'; } } - &__text-input-placeholder, &__file-input-placeholder { + &__text-input-placeholder, + &__file-input-placeholder { border: 2px solid currentColor; border-radius: 2px; padding: 5px; @@ -99,7 +99,9 @@ $block: '.sensei-lms-question-block'; &__input-label { } - &__answer--multiple-choice, &__answer--true-false, &__answer--gap-fill { + &__answer--multiple-choice, + &__answer--true-false, + &__answer--gap-fill { .editor-styles-wrapper & { margin: 28px 0; padding: 0; @@ -110,13 +112,13 @@ $block: '.sensei-lms-question-block'; } } - &__answer--multiple-choice, &__answer--true-false { + &__answer--multiple-choice, + &__answer--true-false { .editor-styles-wrapper & li { min-height: 35px; } &__toggle { - &__wrapper { flex-basis: 65px; margin-left: 12px; @@ -131,7 +133,7 @@ $block: '.sensei-lms-question-block'; background: #fff; border: 1px solid $gray-900; - &:not(:hover) { + &:not( :hover ) { color: $gray-900 !important; } } @@ -153,7 +155,6 @@ $block: '.sensei-lms-question-block'; &__control { margin-right: 12px; } - } .editor-styles-wrapper & li { @@ -161,7 +162,6 @@ $block: '.sensei-lms-question-block'; display: flex; align-items: baseline; } - } &__multiple-choice-answer-option { @@ -172,11 +172,9 @@ $block: '.sensei-lms-question-block'; &__input { flex: 1; } - } &__answer--gap-fill { - .components-form-token-field { &__input-container { margin: 0; @@ -192,7 +190,7 @@ $block: '.sensei-lms-question-block'; &__token { font-size: inherit; - background: var(--wp-admin-theme-color, #333); + background: var( --wp-admin-theme-color, #333 ); color: #fff; align-items: center; @@ -216,10 +214,9 @@ $block: '.sensei-lms-question-block'; } &__text { - border: 1px solid rgba(#ccc, 0.75); + border: 1px solid rgba( #ccc, 0.75 ); padding: 12px; border-radius: 2px; - } .editor-styles-wrapper &__right-answers { @@ -238,7 +235,7 @@ $block: '.sensei-lms-question-block'; &__token { font-size: inherit; - background: var(--wp-admin-theme-color, #333); + background: var( --wp-admin-theme-color, #333 ); color: #fff; padding: 6px; margin-right: 4px; @@ -256,7 +253,7 @@ $block: '.sensei-lms-question-block'; padding: 1px 4px; padding-left: 0; margin-top: 2px; - background: rgba(#ccc, 0.2); + background: rgba( #ccc, 0.2 ); position: absolute; cursor: default; user-select: none; @@ -284,29 +281,31 @@ $block: '.sensei-lms-question-block'; padding: 0; margin: 0; color: inherit; - &:hover, &:focus-visible { - color: var(--wp-admin-theme-color); + &:hover, + &:focus-visible { + color: var( --wp-admin-theme-color ); } } &__help { - opacity: .6; + opacity: 0.6; font-size: 12px; } &__icon { vertical-align: middle; margin-left: 6px; fill: currentColor; - .sensei-lms-question-block__answer-feedback-toggle:not(.is-visible) & { + .sensei-lms-question-block__answer-feedback-toggle:not( .is-visible ) + & { position: relative; top: -2px; } } - } - &:not(.show-answer-feedback) { - .wp-block[data-type="sensei-lms/quiz-question-feedback-correct"], - .wp-block[data-type="sensei-lms/quiz-question-feedback-incorrect"] { + &:not( .show-answer-feedback ) { + .wp-block[data-type='sensei-lms/quiz-question-feedback-correct'], + .wp-block[data-type='sensei-lms/quiz-question-feedback-incorrect'], + .wp-block[data-type='sensei-lms/quiz-question-feedback-generic'] { display: none; } } diff --git a/assets/blocks/quiz/question-block/question-edit.js b/assets/blocks/quiz/question-block/question-edit.js index e44bb002e0..f20f1769af 100644 --- a/assets/blocks/quiz/question-block/question-edit.js +++ b/assets/blocks/quiz/question-block/question-edit.js @@ -20,6 +20,7 @@ import { withBlockValidation } from '../../../shared/blocks/block-validation'; import { answerFeedbackCorrectBlock, answerFeedbackIncorrectBlock, + answerFeedbackGenericBlock, } from '../answer-feedback-block'; import questionDescriptionBlock from '../question-description-block'; import questionAnswersBlock from '../question-answers-block'; @@ -110,6 +111,7 @@ const QuestionEdit = ( props ) => { const AnswerBlock = type && types[ type ]; const canHaveFeedback = AnswerBlock?.feedback; + const canHaveContextualFeedback = AnswerBlock?.hasContextualFeedback; const hasSelected = useHasSelected( props ); const isSingle = context && ! ( 'sensei-lms/quizId' in context ); @@ -162,12 +164,16 @@ const QuestionEdit = ( props ) => { [ questionAnswersBlock.name, {} ], ...( canHaveFeedback ? [ - [ answerFeedbackCorrectBlock.name, {} ], - [ answerFeedbackIncorrectBlock.name, {} ], + ...( canHaveContextualFeedback + ? [ + [ answerFeedbackCorrectBlock.name, {} ], + [ answerFeedbackIncorrectBlock.name, {} ], + ] + : [ [ answerFeedbackGenericBlock.name, {} ] ] ), ] : [] ), ], - [ canHaveFeedback ] + [ canHaveFeedback, canHaveContextualFeedback ] ); if ( ! editable ) { diff --git a/includes/class-sensei-grading-user-quiz.php b/includes/class-sensei-grading-user-quiz.php index 7f70076cd3..35fd7b1e8a 100755 --- a/includes/class-sensei-grading-user-quiz.php +++ b/includes/class-sensei-grading-user-quiz.php @@ -138,9 +138,10 @@ public function display() { $custom_feedback = $custom_feedback[ $question_id ] ?? ''; $correct_feedback = Sensei_Quiz::get_correct_answer_feedback( $question_id ); $incorrect_feedback = Sensei_Quiz::get_incorrect_answer_feedback( $question_id ); + $generic_feedback = Sensei_Quiz::get_generic_answer_feedback( $question_id ); $question_answer_notes = Sensei()->quiz->get_user_question_feedback( $lesson_id, $question_id, $user_id ); - if ( ! $correct_feedback && ! $incorrect_feedback ) { + if ( ! $correct_feedback && ! $incorrect_feedback && ! $generic_feedback ) { $custom_feedback = $question_answer_notes; } @@ -355,6 +356,7 @@ public function display() {
+
diff --git a/includes/class-sensei-question.php b/includes/class-sensei-question.php index be35be1d89..47a9d884c5 100755 --- a/includes/class-sensei-question.php +++ b/includes/class-sensei-question.php @@ -799,24 +799,39 @@ public static function the_question_media( $question_id ) { * @return array CSS classes */ private static function get_answer_feedback_classes( $question_id, bool $answer_correct ): array { - if ( $answer_correct ) { - $feedback_block = Sensei_Quiz::get_correct_answer_feedback_block( $question_id ); + $generic_feedback = Sensei_Quiz::get_generic_answer_feedback( $question_id ); - return [ - 'sensei-lms-question__answer-feedback--correct', - isset( $feedback_block['attrs']['className'] ) ? $feedback_block['attrs']['className'] : '', - ]; + if($generic_feedback) { + $feedback_block = Sensei_Quiz::get_generic_answer_feedback_block( $question_id ); + + return [ + 'sensei-lms-question__answer-feedback--generic', + isset( $feedback_block['attrs']['className'] ) ? $feedback_block['attrs']['className'] : '', + ]; } else { - $feedback_block = Sensei_Quiz::get_incorrect_answer_feedback_block( $question_id ); - return [ - 'sensei-lms-question__answer-feedback--incorrect', - isset( $feedback_block['attrs']['className'] ) ? $feedback_block['attrs']['className'] : '', - ]; - } + if ( $answer_correct ) { + $feedback_block = Sensei_Quiz::get_correct_answer_feedback_block( $question_id ); + + + return [ + 'sensei-lms-question__answer-feedback--correct', + isset( $feedback_block['attrs']['className'] ) ? $feedback_block['attrs']['className'] : '', + ]; + + } else { + $feedback_block = Sensei_Quiz::get_incorrect_answer_feedback_block( $question_id ); + return [ + 'sensei-lms-question__answer-feedback--incorrect', + isset( $feedback_block['attrs']['className'] ) ? $feedback_block['attrs']['className'] : '', + + ]; + } + }; } + /** * Special kses processing for media output to allow 'source' video tag. * @@ -865,6 +880,9 @@ public static function the_question_hidden_fields( $question_id ) { */ public static function the_answer_feedback( $question_id ) { + $generic_feedback = Sensei_Quiz::get_generic_answer_feedback( $question_id ); + + $hide_answer_feedback = get_post_meta( $question_id, '_hide_answer_feedback', true ); if ( $hide_answer_feedback ) { return; @@ -918,14 +936,21 @@ public static function the_answer_feedback( $question_id ) { $answer_correct = $answer_grade > 0; $answer_notes_classnames = []; - $answer_feedback_title = ''; + $answer_feedback_title = 'Feedback'; - if ( $indicate_incorrect ) { + if ( $indicate_incorrect) { $answer_notes_classnames = self::get_answer_feedback_classes( $question_id, $answer_correct ); - if ( $answer_correct ) { - $answer_feedback_title = __( 'Correct', 'sensei-lms' ); + if($generic_feedback) { + + $answer_feedback_title = __( 'Feedback', 'sensei-lms' ); + } else { - $answer_feedback_title = __( 'Incorrect', 'sensei-lms' ); + + if ( $answer_correct ) { + $answer_feedback_title = __( 'Correct', 'sensei-lms' ); + } else { + $answer_feedback_title = __( 'Incorrect', 'sensei-lms' ); + } } } diff --git a/includes/class-sensei-quiz.php b/includes/class-sensei-quiz.php index 3cdc603028..b8ba2addae 100755 --- a/includes/class-sensei-quiz.php +++ b/includes/class-sensei-quiz.php @@ -1374,6 +1374,8 @@ public function get_user_question_feedback( $lesson_id, $question_id, $user_id = if ( $feedback_block ) { $feedback = $feedback_block; + } else { + $feedback = self::get_generic_answer_feedback( $question_id ); } } } else { @@ -1441,6 +1443,19 @@ public static function get_incorrect_answer_feedback( $question_id ) { return $block ? render_block( $block ) : ''; } + /** + * Get the contents for the generic answer feedback block. + * + * @access public + * @param int $question_id + * + * @return string + */ + public static function get_generic_answer_feedback( $question_id ) { + $block = self::get_generic_answer_feedback_block( $question_id ); + return $block ? render_block( $block ) : ''; + } + /** * Get the contents for the correct answer feedback block. @@ -1468,6 +1483,19 @@ public static function get_incorrect_answer_feedback_block( $question_id ) { return self::get_question_inner_block( $question_id, 'sensei-lms/quiz-question-feedback-incorrect' ); } + /** + * Get the contents for the generic answer feedback block. + * + * @since 4.6.0 + * @access public + * @param int $question_id Question Id. + * + * @return array + */ + public static function get_generic_answer_feedback_block( $question_id ) { + return self::get_question_inner_block( $question_id, 'sensei-lms/quiz-question-feedback-generic' ); + } + /** * Check if a quiz has no questions, and redirect back to lesson. *