MOBILE-4550 quiz: Display when attempt can be reviewed
parent
e0b19ff20a
commit
cdb56d172e
|
@ -914,6 +914,8 @@
|
||||||
"addon.mod_quiz.mustbesubmittedby": "quiz",
|
"addon.mod_quiz.mustbesubmittedby": "quiz",
|
||||||
"addon.mod_quiz.noquestions": "quiz",
|
"addon.mod_quiz.noquestions": "quiz",
|
||||||
"addon.mod_quiz.noreviewattempt": "quiz",
|
"addon.mod_quiz.noreviewattempt": "quiz",
|
||||||
|
"addon.mod_quiz.noreviewuntil": "quiz",
|
||||||
|
"addon.mod_quiz.noreviewuntilshort": "quiz",
|
||||||
"addon.mod_quiz.notyetgraded": "quiz",
|
"addon.mod_quiz.notyetgraded": "quiz",
|
||||||
"addon.mod_quiz.opentoc": "local_moodlemobileapp",
|
"addon.mod_quiz.opentoc": "local_moodlemobileapp",
|
||||||
"addon.mod_quiz.outof": "quiz",
|
"addon.mod_quiz.outof": "quiz",
|
||||||
|
|
|
@ -82,14 +82,13 @@
|
||||||
<ion-icon name="fas-magnifying-glass" slot="start" aria-hidden="true" />
|
<ion-icon name="fas-magnifying-glass" slot="start" aria-hidden="true" />
|
||||||
{{ 'addon.mod_quiz.review' | translate }}
|
{{ 'addon.mod_quiz.review' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
} @else if (attempt.completed) {
|
} @else if (attempt.completed && attempt.cannotReviewMessage) {
|
||||||
<hr>
|
<hr>
|
||||||
<ion-item class="ion-text-wrap addon-mod_quiz-attempt-noreview">
|
<ion-item class="ion-text-wrap addon-mod_quiz-attempt-noreview">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>
|
<p>
|
||||||
<ion-icon name="fas-circle-info" color="info" slot="start" aria-hidden="true" />
|
<ion-icon name="fas-circle-info" color="info" slot="start" aria-hidden="true" />
|
||||||
{{ 'addon.mod_quiz.noreviewattempt' | translate }}
|
{{ attempt.cannotReviewMessage }}
|
||||||
<!-- TODO: Check if we can calculate the time when the attempt can be reviewed. -->
|
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -622,6 +622,9 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
|
||||||
]);
|
]);
|
||||||
|
|
||||||
formattedAttempt.canReview = canReview;
|
formattedAttempt.canReview = canReview;
|
||||||
|
if (!canReview) {
|
||||||
|
formattedAttempt.cannotReviewMessage = AddonModQuizHelper.getCannotReviewMessage(quiz, attempt, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (quiz.showFeedback && attempt.state === AddonModQuizAttemptStates.FINISHED &&
|
if (quiz.showFeedback && attempt.state === AddonModQuizAttemptStates.FINISHED &&
|
||||||
options.someoptions.overallfeedback && isSafeNumber(formattedAttempt.rescaledGrade)) {
|
options.someoptions.overallfeedback && isSafeNumber(formattedAttempt.rescaledGrade)) {
|
||||||
|
@ -698,5 +701,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
|
||||||
|
|
||||||
type QuizAttempt = AddonModQuizAttempt & {
|
type QuizAttempt = AddonModQuizAttempt & {
|
||||||
canReview?: boolean;
|
canReview?: boolean;
|
||||||
|
cannotReviewMessage?: string;
|
||||||
additionalData?: AddonModQuizWSAdditionalData[]; // Additional data to display for the attempt.
|
additionalData?: AddonModQuizWSAdditionalData[]; // Additional data to display for the attempt.
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
"mustbesubmittedby": "This attempt must be submitted by {{$a}}.",
|
"mustbesubmittedby": "This attempt must be submitted by {{$a}}.",
|
||||||
"noquestions": "No questions have been added yet",
|
"noquestions": "No questions have been added yet",
|
||||||
"noreviewattempt": "You are not allowed to review this attempt.",
|
"noreviewattempt": "You are not allowed to review this attempt.",
|
||||||
|
"noreviewuntil": "You are not allowed to review this quiz until {{$a}}",
|
||||||
|
"noreviewuntilshort": "Available {{$a}}",
|
||||||
"notyetgraded": "Not yet graded",
|
"notyetgraded": "Not yet graded",
|
||||||
"opentoc": "Open navigation popover",
|
"opentoc": "Open navigation popover",
|
||||||
"outof": "{{$a.grade}} out of {{$a.maxgrade}}",
|
"outof": "{{$a.grade}} out of {{$a.maxgrade}}",
|
||||||
|
|
|
@ -33,9 +33,14 @@ import {
|
||||||
AddonModQuizQuizWSData,
|
AddonModQuizQuizWSData,
|
||||||
} from './quiz';
|
} from './quiz';
|
||||||
import { AddonModQuizOffline } from './quiz-offline';
|
import { AddonModQuizOffline } from './quiz-offline';
|
||||||
import { AddonModQuizAttemptStates, AddonModQuizDisplayOptionsAttemptStates } from '../constants';
|
import {
|
||||||
|
ADDON_MOD_QUIZ_IMMEDIATELY_AFTER_PERIOD,
|
||||||
|
AddonModQuizAttemptStates,
|
||||||
|
AddonModQuizDisplayOptionsAttemptStates,
|
||||||
|
} from '../constants';
|
||||||
import { QuestionDisplayOptionsMarks } from '@features/question/constants';
|
import { QuestionDisplayOptionsMarks } from '@features/question/constants';
|
||||||
import { CoreGroups } from '@services/groups';
|
import { CoreGroups } from '@services/groups';
|
||||||
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper service that provides some features for quiz.
|
* Helper service that provides some features for quiz.
|
||||||
|
@ -121,6 +126,47 @@ export class AddonModQuizHelperProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cannot review message.
|
||||||
|
*
|
||||||
|
* @param quiz Quiz.
|
||||||
|
* @param attempt Attempt.
|
||||||
|
* @param short Whether to use a short message or not.
|
||||||
|
* @returns Cannot review message, or empty string if no message to display.
|
||||||
|
*/
|
||||||
|
getCannotReviewMessage(quiz: AddonModQuizQuizWSData, attempt: AddonModQuizAttemptWSData, short = false): string {
|
||||||
|
const displayOption = AddonModQuiz.getAttemptStateDisplayOption(quiz, attempt);
|
||||||
|
|
||||||
|
let reviewFrom = 0;
|
||||||
|
switch (displayOption) {
|
||||||
|
case AddonModQuizDisplayOptionsAttemptStates.DURING:
|
||||||
|
return '';
|
||||||
|
|
||||||
|
case AddonModQuizDisplayOptionsAttemptStates.IMMEDIATELY_AFTER:
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
if ((quiz.reviewattempt ?? 0) & AddonModQuizDisplayOptionsAttemptStates.LATER_WHILE_OPEN) {
|
||||||
|
reviewFrom = (attempt.timefinish ?? Date.now()) + ADDON_MOD_QUIZ_IMMEDIATELY_AFTER_PERIOD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Fall through.
|
||||||
|
|
||||||
|
case AddonModQuizDisplayOptionsAttemptStates.LATER_WHILE_OPEN:
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
if (quiz.timeclose && ((quiz.reviewattempt ?? 0) & AddonModQuizDisplayOptionsAttemptStates.AFTER_CLOSE)) {
|
||||||
|
reviewFrom = quiz.timeclose;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reviewFrom) {
|
||||||
|
return Translate.instant('addon.mod_quiz.noreviewuntil' + (short ? 'short' : ''), {
|
||||||
|
$a: CoreTimeUtils.userDate(reviewFrom * 1000, short ? 'core.strftimedatetimeshort': undefined),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Translate.instant('addon.mod_quiz.noreviewattempt');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate a preflight data or show a modal to input the preflight data if required.
|
* Validate a preflight data or show a modal to input the preflight data if required.
|
||||||
* It calls AddonModQuizProvider.startAttempt if a new attempt is needed.
|
* It calls AddonModQuizProvider.startAttempt if a new attempt is needed.
|
||||||
|
|
Loading…
Reference in New Issue