MOBILE-4550 quiz: Move quiz service constants to constants file
parent
df3b328bac
commit
17bd64a5e0
|
@ -15,8 +15,9 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { AddonModQuizAccessRuleHandler } from '@addons/mod/quiz/services/access-rules-delegate';
|
import { AddonModQuizAccessRuleHandler } from '@addons/mod/quiz/services/access-rules-delegate';
|
||||||
import { AddonModQuizAttemptWSData, AddonModQuizProvider } from '@addons/mod/quiz/services/quiz';
|
import { AddonModQuizAttemptWSData } from '@addons/mod/quiz/services/quiz';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
|
import { ADDON_MOD_QUIZ_SHOW_TIME_BEFORE_DEADLINE } from '@addons/mod/quiz/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to support open/close date access rule.
|
* Handler to support open/close date access rule.
|
||||||
|
@ -50,8 +51,8 @@ export class AddonModQuizAccessOpenCloseDateHandlerService implements AddonModQu
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the time left only if it's less than QUIZ_SHOW_TIME_BEFORE_DEADLINE.
|
// Show the time left only if it's less than ADDON_MOD_QUIZ_SHOW_TIME_BEFORE_DEADLINE.
|
||||||
if (timeNow > endTime - AddonModQuizProvider.QUIZ_SHOW_TIME_BEFORE_DEADLINE) {
|
if (timeNow > endTime - ADDON_MOD_QUIZ_SHOW_TIME_BEFORE_DEADLINE) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ import {
|
||||||
AddonModQuizGetAttemptAccessInformationWSResponse,
|
AddonModQuizGetAttemptAccessInformationWSResponse,
|
||||||
AddonModQuizGetQuizAccessInformationWSResponse,
|
AddonModQuizGetQuizAccessInformationWSResponse,
|
||||||
AddonModQuizGetUserBestGradeWSResponse,
|
AddonModQuizGetUserBestGradeWSResponse,
|
||||||
AddonModQuizProvider,
|
|
||||||
} from '../../services/quiz';
|
} from '../../services/quiz';
|
||||||
import { AddonModQuizAttempt, AddonModQuizHelper, AddonModQuizQuizData } from '../../services/quiz-helper';
|
import { AddonModQuizAttempt, AddonModQuizHelper, AddonModQuizQuizData } from '../../services/quiz-helper';
|
||||||
import {
|
import {
|
||||||
|
@ -45,6 +44,8 @@ import {
|
||||||
AddonModQuizSyncProvider,
|
AddonModQuizSyncProvider,
|
||||||
AddonModQuizSyncResult,
|
AddonModQuizSyncResult,
|
||||||
} from '../../services/quiz-sync';
|
} from '../../services/quiz-sync';
|
||||||
|
import { ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT, ADDON_MOD_QUIZ_COMPONENT, AddonModQuizGradeMethods } from '../../constants';
|
||||||
|
import { QuestionDisplayOptionsMarks } from '@features/question/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a quiz entry page.
|
* Component that displays a quiz entry page.
|
||||||
|
@ -56,7 +57,7 @@ import {
|
||||||
})
|
})
|
||||||
export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit, OnDestroy {
|
export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
component = AddonModQuizProvider.COMPONENT;
|
component = ADDON_MOD_QUIZ_COMPONENT;
|
||||||
pluginName = 'quiz';
|
pluginName = 'quiz';
|
||||||
quiz?: AddonModQuizQuizData; // The quiz.
|
quiz?: AddonModQuizQuizData; // The quiz.
|
||||||
now?: number; // Current time.
|
now?: number; // Current time.
|
||||||
|
@ -110,7 +111,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
|
||||||
|
|
||||||
// Listen for attempt finished events.
|
// Listen for attempt finished events.
|
||||||
this.finishedObserver = CoreEvents.on(
|
this.finishedObserver = CoreEvents.on(
|
||||||
AddonModQuizProvider.ATTEMPT_FINISHED_EVENT,
|
ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT,
|
||||||
(data) => {
|
(data) => {
|
||||||
// Go to review attempt if an attempt in this quiz was finished and synced.
|
// Go to review attempt if an attempt in this quiz was finished and synced.
|
||||||
if (this.quiz && data.quizId == this.quiz.id) {
|
if (this.quiz && data.quizId == this.quiz.id) {
|
||||||
|
@ -609,12 +610,12 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
|
||||||
// Calculate data to construct the header of the attempts table.
|
// Calculate data to construct the header of the attempts table.
|
||||||
AddonModQuizHelper.setQuizCalculatedData(quiz, this.options);
|
AddonModQuizHelper.setQuizCalculatedData(quiz, this.options);
|
||||||
|
|
||||||
this.overallStats = !!lastFinished && this.options.alloptions.marks >= AddonModQuizProvider.QUESTION_OPTIONS_MARK_AND_MAX;
|
this.overallStats = !!lastFinished && this.options.alloptions.marks >= QuestionDisplayOptionsMarks.MARK_AND_MAX;
|
||||||
|
|
||||||
// Calculate data to show for each attempt.
|
// Calculate data to show for each attempt.
|
||||||
const formattedAttempts = await Promise.all(attempts.map((attempt, index) => {
|
const formattedAttempts = await Promise.all(attempts.map((attempt, index) => {
|
||||||
// Highlight the highest grade if appropriate.
|
// Highlight the highest grade if appropriate.
|
||||||
const shouldHighlight = this.overallStats && quiz.grademethod == AddonModQuizProvider.GRADEHIGHEST &&
|
const shouldHighlight = this.overallStats && quiz.grademethod === AddonModQuizGradeMethods.HIGHEST_GRADE &&
|
||||||
attempts.length > 1;
|
attempts.length > 1;
|
||||||
const isLast = index == attempts.length - 1;
|
const isLast = index == attempts.length - 1;
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,30 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
export const ADDON_MOD_QUIZ_COMPONENT = 'mmaModQuiz';
|
||||||
|
|
||||||
export const ADDON_MOD_QUIZ_FEATURE_NAME = 'CoreCourseModuleDelegate_AddonModQuiz';
|
export const ADDON_MOD_QUIZ_FEATURE_NAME = 'CoreCourseModuleDelegate_AddonModQuiz';
|
||||||
|
|
||||||
|
export const ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT = 'addon_mod_quiz_attempt_finished';
|
||||||
|
|
||||||
|
export const ADDON_MOD_QUIZ_SHOW_TIME_BEFORE_DEADLINE = 3600;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible grade methods for a quiz.
|
||||||
|
*/
|
||||||
|
export const enum AddonModQuizGradeMethods {
|
||||||
|
HIGHEST_GRADE = 1,
|
||||||
|
AVERAGE_GRADE = 2,
|
||||||
|
FIRST_ATTEMPT = 3,
|
||||||
|
LAST_ATTEMPT = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible states for an attempt.
|
||||||
|
*/
|
||||||
|
export const enum AddonModQuizAttemptStates {
|
||||||
|
IN_PROGRESS = 'inprogress',
|
||||||
|
OVERDUE = 'overdue',
|
||||||
|
FINISHED = 'finished',
|
||||||
|
ABANDONED = 'abandoned',
|
||||||
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ import {
|
||||||
AddonModQuiz,
|
AddonModQuiz,
|
||||||
AddonModQuizAttemptWSData,
|
AddonModQuizAttemptWSData,
|
||||||
AddonModQuizGetQuizAccessInformationWSResponse,
|
AddonModQuizGetQuizAccessInformationWSResponse,
|
||||||
AddonModQuizProvider,
|
|
||||||
} from '../../services/quiz';
|
} from '../../services/quiz';
|
||||||
import { AddonModQuizAttempt, AddonModQuizHelper, AddonModQuizQuizData } from '../../services/quiz-helper';
|
import { AddonModQuizAttempt, AddonModQuizHelper, AddonModQuizQuizData } from '../../services/quiz-helper';
|
||||||
|
import { ADDON_MOD_QUIZ_COMPONENT } from '../../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays some summary data about an attempt.
|
* Page that displays some summary data about an attempt.
|
||||||
|
@ -39,7 +39,7 @@ export class AddonModQuizAttemptPage implements OnInit {
|
||||||
courseId!: number; // The course ID the quiz belongs to.
|
courseId!: number; // The course ID the quiz belongs to.
|
||||||
quiz?: AddonModQuizQuizData; // The quiz the attempt belongs to.
|
quiz?: AddonModQuizQuizData; // The quiz the attempt belongs to.
|
||||||
attempt?: AddonModQuizAttempt; // The attempt to view.
|
attempt?: AddonModQuizAttempt; // The attempt to view.
|
||||||
component = AddonModQuizProvider.COMPONENT; // Component to link the files to.
|
component = ADDON_MOD_QUIZ_COMPONENT; // Component to link the files to.
|
||||||
componentId?: number; // Component ID to use in conjunction with the component.
|
componentId?: number; // Component ID to use in conjunction with the component.
|
||||||
loaded = false; // Whether data has been loaded.
|
loaded = false; // Whether data has been loaded.
|
||||||
feedback?: string; // Attempt feedback.
|
feedback?: string; // Attempt feedback.
|
||||||
|
|
|
@ -38,7 +38,6 @@ import {
|
||||||
AddonModQuizAttemptWSData,
|
AddonModQuizAttemptWSData,
|
||||||
AddonModQuizGetAttemptAccessInformationWSResponse,
|
AddonModQuizGetAttemptAccessInformationWSResponse,
|
||||||
AddonModQuizGetQuizAccessInformationWSResponse,
|
AddonModQuizGetQuizAccessInformationWSResponse,
|
||||||
AddonModQuizProvider,
|
|
||||||
AddonModQuizQuizWSData,
|
AddonModQuizQuizWSData,
|
||||||
} from '../../services/quiz';
|
} from '../../services/quiz';
|
||||||
import { AddonModQuizAttempt, AddonModQuizHelper } from '../../services/quiz-helper';
|
import { AddonModQuizAttempt, AddonModQuizHelper } from '../../services/quiz-helper';
|
||||||
|
@ -50,6 +49,7 @@ import { CoreTime } from '@singletons/time';
|
||||||
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
||||||
import { CoreWSError } from '@classes/errors/wserror';
|
import { CoreWSError } from '@classes/errors/wserror';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
|
import { ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT, AddonModQuizAttemptStates, ADDON_MOD_QUIZ_COMPONENT } from '../../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that allows attempting a quiz.
|
* Page that allows attempting a quiz.
|
||||||
|
@ -68,7 +68,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
quiz?: AddonModQuizQuizWSData; // The quiz the attempt belongs to.
|
quiz?: AddonModQuizQuizWSData; // The quiz the attempt belongs to.
|
||||||
attempt?: AddonModQuizAttempt; // The attempt being attempted.
|
attempt?: AddonModQuizAttempt; // The attempt being attempted.
|
||||||
moduleUrl?: string; // URL to the module in the site.
|
moduleUrl?: string; // URL to the module in the site.
|
||||||
component = AddonModQuizProvider.COMPONENT; // Component to link the files to.
|
component = ADDON_MOD_QUIZ_COMPONENT; // Component to link the files to.
|
||||||
loaded = false; // Whether data has been loaded.
|
loaded = false; // Whether data has been loaded.
|
||||||
quizAborted = false; // Whether the quiz was aborted due to an error.
|
quizAborted = false; // Whether the quiz was aborted due to an error.
|
||||||
offline = false; // Whether the quiz is being attempted in offline mode.
|
offline = false; // Whether the quiz is being attempted in offline mode.
|
||||||
|
@ -146,7 +146,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
|
|
||||||
if (this.quiz) {
|
if (this.quiz) {
|
||||||
// Unblock the quiz so it can be synced.
|
// Unblock the quiz so it can be synced.
|
||||||
CoreSync.unblockOperation(AddonModQuizProvider.COMPONENT, this.quiz.id);
|
CoreSync.unblockOperation(ADDON_MOD_QUIZ_COMPONENT, this.quiz.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page != -1 && (this.attempt.state == AddonModQuizProvider.ATTEMPT_OVERDUE || this.attempt.finishedOffline)) {
|
if (page != -1 && (this.attempt.state === AddonModQuizAttemptStates.OVERDUE || this.attempt.finishedOffline)) {
|
||||||
// We can't load a page if overdue or the local attempt is finished.
|
// We can't load a page if overdue or the local attempt is finished.
|
||||||
return;
|
return;
|
||||||
} else if (page == this.attempt.currentpage && !this.showSummary && slot !== undefined) {
|
} else if (page == this.attempt.currentpage && !this.showSummary && slot !== undefined) {
|
||||||
|
@ -341,7 +341,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
this.quiz = await AddonModQuiz.getQuiz(this.courseId, this.cmId);
|
this.quiz = await AddonModQuiz.getQuiz(this.courseId, this.cmId);
|
||||||
|
|
||||||
// Block the quiz so it cannot be synced.
|
// Block the quiz so it cannot be synced.
|
||||||
CoreSync.blockOperation(AddonModQuizProvider.COMPONENT, this.quiz.id);
|
CoreSync.blockOperation(ADDON_MOD_QUIZ_COMPONENT, this.quiz.id);
|
||||||
|
|
||||||
// Wait for any ongoing sync to finish. We won't sync a quiz while it's being played.
|
// Wait for any ongoing sync to finish. We won't sync a quiz while it's being played.
|
||||||
await AddonModQuizSync.waitForSync(this.quiz.id);
|
await AddonModQuizSync.waitForSync(this.quiz.id);
|
||||||
|
@ -408,7 +408,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Show confirm if the user clicked the finish button and the quiz is in progress.
|
// Show confirm if the user clicked the finish button and the quiz is in progress.
|
||||||
if (!timeUp && this.attempt.state == AddonModQuizProvider.ATTEMPT_IN_PROGRESS) {
|
if (!timeUp && this.attempt.state === AddonModQuizAttemptStates.IN_PROGRESS) {
|
||||||
let message = Translate.instant('addon.mod_quiz.confirmclose');
|
let message = Translate.instant('addon.mod_quiz.confirmclose');
|
||||||
|
|
||||||
const unansweredCount = this.summaryQuestions
|
const unansweredCount = this.summaryQuestions
|
||||||
|
@ -444,7 +444,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
await this.processAttempt(userFinish, timeUp);
|
await this.processAttempt(userFinish, timeUp);
|
||||||
|
|
||||||
// Trigger an event to notify the attempt was finished.
|
// Trigger an event to notify the attempt was finished.
|
||||||
CoreEvents.trigger(AddonModQuizProvider.ATTEMPT_FINISHED_EVENT, {
|
CoreEvents.trigger(ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT, {
|
||||||
quizId: this.quiz.id,
|
quizId: this.quiz.id,
|
||||||
attemptId: this.attempt.id,
|
attemptId: this.attempt.id,
|
||||||
synced: !this.offline,
|
synced: !this.offline,
|
||||||
|
@ -679,7 +679,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.showSummary = true;
|
this.showSummary = true;
|
||||||
this.canReturn = this.attempt.state == AddonModQuizProvider.ATTEMPT_IN_PROGRESS && !this.attempt.finishedOffline;
|
this.canReturn = this.attempt.state === AddonModQuizAttemptStates.IN_PROGRESS && !this.attempt.finishedOffline;
|
||||||
this.preventSubmitMessages = AddonModQuiz.getPreventSubmitMessages(this.summaryQuestions);
|
this.preventSubmitMessages = AddonModQuiz.getPreventSubmitMessages(this.summaryQuestions);
|
||||||
|
|
||||||
this.dueDateWarning = AddonModQuiz.getAttemptDueDateWarning(this.quiz, this.attempt);
|
this.dueDateWarning = AddonModQuiz.getAttemptDueDateWarning(this.quiz, this.attempt);
|
||||||
|
@ -904,7 +904,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
|
|
||||||
await this.loadNavigation();
|
await this.loadNavigation();
|
||||||
|
|
||||||
if (this.attempt.state != AddonModQuizProvider.ATTEMPT_OVERDUE && !this.attempt.finishedOffline) {
|
if (this.attempt.state !== AddonModQuizAttemptStates.OVERDUE && !this.attempt.finishedOffline) {
|
||||||
// Attempt not overdue and not finished in offline, load page.
|
// Attempt not overdue and not finished in offline, load page.
|
||||||
await this.loadPage(this.attempt.currentpage ?? 0);
|
await this.loadPage(this.attempt.currentpage ?? 0);
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,13 @@ import {
|
||||||
AddonModQuizAttemptWSData,
|
AddonModQuizAttemptWSData,
|
||||||
AddonModQuizCombinedReviewOptions,
|
AddonModQuizCombinedReviewOptions,
|
||||||
AddonModQuizGetAttemptReviewResponse,
|
AddonModQuizGetAttemptReviewResponse,
|
||||||
AddonModQuizProvider,
|
|
||||||
AddonModQuizQuizWSData,
|
AddonModQuizQuizWSData,
|
||||||
AddonModQuizWSAdditionalData,
|
AddonModQuizWSAdditionalData,
|
||||||
} from '../../services/quiz';
|
} from '../../services/quiz';
|
||||||
import { AddonModQuizHelper } from '../../services/quiz-helper';
|
import { AddonModQuizHelper } from '../../services/quiz-helper';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
|
import { AddonModQuizAttemptStates, ADDON_MOD_QUIZ_COMPONENT } from '../../constants';
|
||||||
|
import { QuestionDisplayOptionsMarks } from '@features/question/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that allows reviewing a quiz attempt.
|
* Page that allows reviewing a quiz attempt.
|
||||||
|
@ -52,7 +53,7 @@ export class AddonModQuizReviewPage implements OnInit {
|
||||||
@ViewChild(IonContent) content?: IonContent;
|
@ViewChild(IonContent) content?: IonContent;
|
||||||
|
|
||||||
attempt?: AddonModQuizAttemptWSData; // The attempt being reviewed.
|
attempt?: AddonModQuizAttemptWSData; // The attempt being reviewed.
|
||||||
component = AddonModQuizProvider.COMPONENT; // Component to link the files to.
|
component = ADDON_MOD_QUIZ_COMPONENT; // Component to link the files to.
|
||||||
showAll = false; // Whether to view all questions in the same page.
|
showAll = false; // Whether to view all questions in the same page.
|
||||||
numPages = 1; // Number of pages.
|
numPages = 1; // Number of pages.
|
||||||
showCompleted = false; // Whether to show completed time.
|
showCompleted = false; // Whether to show completed time.
|
||||||
|
@ -265,7 +266,7 @@ export class AddonModQuizReviewPage implements OnInit {
|
||||||
|
|
||||||
this.readableState = AddonModQuiz.getAttemptReadableStateName(this.attempt.state ?? '');
|
this.readableState = AddonModQuiz.getAttemptReadableStateName(this.attempt.state ?? '');
|
||||||
|
|
||||||
if (this.attempt.state != AddonModQuizProvider.ATTEMPT_FINISHED) {
|
if (this.attempt.state !== AddonModQuizAttemptStates.FINISHED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +300,7 @@ export class AddonModQuizReviewPage implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat grade.
|
// Treat grade.
|
||||||
if (this.options && this.options.someoptions.marks >= AddonModQuizProvider.QUESTION_OPTIONS_MARK_AND_MAX &&
|
if (this.options && this.options.someoptions.marks >= QuestionDisplayOptionsMarks.MARK_AND_MAX &&
|
||||||
AddonModQuiz.quizHasGrades(this.quiz)) {
|
AddonModQuiz.quizHasGrades(this.quiz)) {
|
||||||
|
|
||||||
if (data.grade === null || data.grade === undefined) {
|
if (data.grade === null || data.grade === undefined) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ import { AddonModQuizPrefetchHandler } from './services/handlers/prefetch';
|
||||||
import { AddonModQuizPushClickHandler } from './services/handlers/push-click';
|
import { AddonModQuizPushClickHandler } from './services/handlers/push-click';
|
||||||
import { AddonModQuizReviewLinkHandler } from './services/handlers/review-link';
|
import { AddonModQuizReviewLinkHandler } from './services/handlers/review-link';
|
||||||
import { AddonModQuizSyncCronHandler } from './services/handlers/sync-cron';
|
import { AddonModQuizSyncCronHandler } from './services/handlers/sync-cron';
|
||||||
import { AddonModQuizProvider } from './services/quiz';
|
import { ADDON_MOD_QUIZ_COMPONENT } from './constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get mod Quiz services.
|
* Get mod Quiz services.
|
||||||
|
@ -98,7 +98,7 @@ const routes: Routes = [
|
||||||
CorePushNotificationsDelegate.registerClickHandler(AddonModQuizPushClickHandler.instance);
|
CorePushNotificationsDelegate.registerClickHandler(AddonModQuizPushClickHandler.instance);
|
||||||
CoreCronDelegate.register(AddonModQuizSyncCronHandler.instance);
|
CoreCronDelegate.register(AddonModQuizSyncCronHandler.instance);
|
||||||
|
|
||||||
CoreCourseHelper.registerModuleReminderClick(AddonModQuizProvider.COMPONENT);
|
CoreCourseHelper.registerModuleReminderClick(ADDON_MOD_QUIZ_COMPONENT);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -32,11 +32,11 @@ import {
|
||||||
AddonModQuiz,
|
AddonModQuiz,
|
||||||
AddonModQuizAttemptWSData,
|
AddonModQuizAttemptWSData,
|
||||||
AddonModQuizGetQuizAccessInformationWSResponse,
|
AddonModQuizGetQuizAccessInformationWSResponse,
|
||||||
AddonModQuizProvider,
|
|
||||||
AddonModQuizQuizWSData,
|
AddonModQuizQuizWSData,
|
||||||
} from '../quiz';
|
} from '../quiz';
|
||||||
import { AddonModQuizHelper } from '../quiz-helper';
|
import { AddonModQuizHelper } from '../quiz-helper';
|
||||||
import { AddonModQuizSync, AddonModQuizSyncResult } from '../quiz-sync';
|
import { AddonModQuizSync, AddonModQuizSyncResult } from '../quiz-sync';
|
||||||
|
import { AddonModQuizAttemptStates, ADDON_MOD_QUIZ_COMPONENT } from '../../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to prefetch quizzes.
|
* Handler to prefetch quizzes.
|
||||||
|
@ -46,7 +46,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet
|
||||||
|
|
||||||
name = 'AddonModQuiz';
|
name = 'AddonModQuiz';
|
||||||
modName = 'quiz';
|
modName = 'quiz';
|
||||||
component = AddonModQuizProvider.COMPONENT;
|
component = ADDON_MOD_QUIZ_COMPONENT;
|
||||||
updatesNames = /^configuration$|^.*files$|^grades$|^gradeitems$|^questions$|^attempts$/;
|
updatesNames = /^configuration$|^.*files$|^grades$|^gradeitems$|^questions$|^attempts$/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -321,7 +321,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet
|
||||||
AddonModQuiz.getUserAttempts(quiz.id, modOptions),
|
AddonModQuiz.getUserAttempts(quiz.id, modOptions),
|
||||||
AddonModQuiz.getAttemptAccessInformation(quiz.id, 0, modOptions),
|
AddonModQuiz.getAttemptAccessInformation(quiz.id, 0, modOptions),
|
||||||
AddonModQuiz.getQuizRequiredQtypes(quiz.id, modOptions),
|
AddonModQuiz.getQuizRequiredQtypes(quiz.id, modOptions),
|
||||||
CoreFilepool.addFilesToQueue(siteId, introFiles, AddonModQuizProvider.COMPONENT, module.id),
|
CoreFilepool.addFilesToQueue(siteId, introFiles, ADDON_MOD_QUIZ_COMPONENT, module.id),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Check if we need to start a new attempt.
|
// Check if we need to start a new attempt.
|
||||||
|
@ -353,17 +353,17 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet
|
||||||
|
|
||||||
const attemptFiles = await this.getAttemptsFeedbackFiles(quiz, attempts, siteId);
|
const attemptFiles = await this.getAttemptsFeedbackFiles(quiz, attempts, siteId);
|
||||||
|
|
||||||
return CoreFilepool.addFilesToQueue(siteId, attemptFiles, AddonModQuizProvider.COMPONENT, module.id);
|
return CoreFilepool.addFilesToQueue(siteId, attemptFiles, ADDON_MOD_QUIZ_COMPONENT, module.id);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Update the download time to prevent detecting the new attempt as an update.
|
// Update the download time to prevent detecting the new attempt as an update.
|
||||||
promises.push(CoreUtils.ignoreErrors(
|
promises.push(CoreUtils.ignoreErrors(
|
||||||
CoreFilepool.updatePackageDownloadTime(siteId, AddonModQuizProvider.COMPONENT, module.id),
|
CoreFilepool.updatePackageDownloadTime(siteId, ADDON_MOD_QUIZ_COMPONENT, module.id),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
// Use the already fetched attempts.
|
// Use the already fetched attempts.
|
||||||
promises.push(this.getAttemptsFeedbackFiles(quiz, attempts, siteId).then((attemptFiles) =>
|
promises.push(this.getAttemptsFeedbackFiles(quiz, attempts, siteId).then((attemptFiles) =>
|
||||||
CoreFilepool.addFilesToQueue(siteId, attemptFiles, AddonModQuizProvider.COMPONENT, module.id)));
|
CoreFilepool.addFilesToQueue(siteId, attemptFiles, ADDON_MOD_QUIZ_COMPONENT, module.id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch attempt related data.
|
// Fetch attempt related data.
|
||||||
|
@ -444,7 +444,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet
|
||||||
promises.push(AddonModQuiz.getAttemptAccessInformation(quiz.id, attempt.id, modOptions));
|
promises.push(AddonModQuiz.getAttemptAccessInformation(quiz.id, attempt.id, modOptions));
|
||||||
promises.push(AddonModQuiz.getAttemptSummary(attempt.id, preflightData, modOptions));
|
promises.push(AddonModQuiz.getAttemptSummary(attempt.id, preflightData, modOptions));
|
||||||
|
|
||||||
if (attempt.state == AddonModQuizProvider.ATTEMPT_IN_PROGRESS) {
|
if (attempt.state === AddonModQuizAttemptStates.IN_PROGRESS) {
|
||||||
// Get data for each page.
|
// Get data for each page.
|
||||||
promises = promises.concat(pages.map(async (page) => {
|
promises = promises.concat(pages.map(async (page) => {
|
||||||
if (isSequential && typeof attempt.currentpage === 'number' && page < attempt.currentpage) {
|
if (isSequential && typeof attempt.currentpage === 'number' && page < attempt.currentpage) {
|
||||||
|
|
|
@ -30,10 +30,11 @@ import {
|
||||||
AddonModQuizAttemptWSData,
|
AddonModQuizAttemptWSData,
|
||||||
AddonModQuizCombinedReviewOptions,
|
AddonModQuizCombinedReviewOptions,
|
||||||
AddonModQuizGetQuizAccessInformationWSResponse,
|
AddonModQuizGetQuizAccessInformationWSResponse,
|
||||||
AddonModQuizProvider,
|
|
||||||
AddonModQuizQuizWSData,
|
AddonModQuizQuizWSData,
|
||||||
} from './quiz';
|
} from './quiz';
|
||||||
import { AddonModQuizOffline } from './quiz-offline';
|
import { AddonModQuizOffline } from './quiz-offline';
|
||||||
|
import { AddonModQuizAttemptStates } from '../constants';
|
||||||
|
import { QuestionDisplayOptionsMarks } from '@features/question/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper service that provides some features for quiz.
|
* Helper service that provides some features for quiz.
|
||||||
|
@ -291,7 +292,7 @@ export class AddonModQuizHelperProvider {
|
||||||
|
|
||||||
// Highlight the highest grade if appropriate.
|
// Highlight the highest grade if appropriate.
|
||||||
formattedAttempt.highlightGrade = !!(highlight && !attempt.preview &&
|
formattedAttempt.highlightGrade = !!(highlight && !attempt.preview &&
|
||||||
attempt.state == AddonModQuizProvider.ATTEMPT_FINISHED && formattedAttempt.readableGrade == bestGrade);
|
attempt.state === AddonModQuizAttemptStates.FINISHED && formattedAttempt.readableGrade == bestGrade);
|
||||||
} else {
|
} else {
|
||||||
formattedAttempt.readableGrade = '';
|
formattedAttempt.readableGrade = '';
|
||||||
}
|
}
|
||||||
|
@ -317,7 +318,7 @@ export class AddonModQuizHelperProvider {
|
||||||
formattedQuiz.gradeFormatted = AddonModQuiz.formatGrade(quiz.grade, quiz.decimalpoints);
|
formattedQuiz.gradeFormatted = AddonModQuiz.formatGrade(quiz.grade, quiz.decimalpoints);
|
||||||
|
|
||||||
formattedQuiz.showAttemptColumn = quiz.attempts != 1;
|
formattedQuiz.showAttemptColumn = quiz.attempts != 1;
|
||||||
formattedQuiz.showGradeColumn = options.someoptions.marks >= AddonModQuizProvider.QUESTION_OPTIONS_MARK_AND_MAX &&
|
formattedQuiz.showGradeColumn = options.someoptions.marks >= QuestionDisplayOptionsMarks.MARK_AND_MAX &&
|
||||||
AddonModQuiz.quizHasGrades(quiz);
|
AddonModQuiz.quizHasGrades(quiz);
|
||||||
formattedQuiz.showMarkColumn = formattedQuiz.showGradeColumn && quiz.grade != quiz.sumgrades;
|
formattedQuiz.showMarkColumn = formattedQuiz.showGradeColumn && quiz.grade != quiz.sumgrades;
|
||||||
formattedQuiz.showFeedbackColumn = !!quiz.hasfeedback && !!options.alloptions.overallfeedback;
|
formattedQuiz.showFeedbackColumn = !!quiz.hasfeedback && !!options.alloptions.overallfeedback;
|
||||||
|
@ -356,7 +357,7 @@ export class AddonModQuizHelperProvider {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (attempt) {
|
if (attempt) {
|
||||||
if (attempt.state != AddonModQuizProvider.ATTEMPT_OVERDUE && !attempt.finishedOffline) {
|
if (attempt.state !== AddonModQuizAttemptStates.OVERDUE && !attempt.finishedOffline) {
|
||||||
// We're continuing an attempt. Call getAttemptData to validate the preflight data.
|
// We're continuing an attempt. Call getAttemptData to validate the preflight data.
|
||||||
await AddonModQuiz.getAttemptData(attempt.id, attempt.currentpage ?? 0, preflightData, modOptions);
|
await AddonModQuiz.getAttemptData(attempt.id, attempt.currentpage ?? 0, preflightData, modOptions);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { AddonModQuizAttemptDBRecord, ATTEMPTS_TABLE_NAME } from './database/quiz';
|
import { AddonModQuizAttemptDBRecord, ATTEMPTS_TABLE_NAME } from './database/quiz';
|
||||||
import { AddonModQuizAttemptWSData, AddonModQuizProvider, AddonModQuizQuizWSData } from './quiz';
|
import { AddonModQuizAttemptWSData, AddonModQuizQuizWSData } from './quiz';
|
||||||
|
import { ADDON_MOD_QUIZ_COMPONENT } from '../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to handle offline quiz.
|
* Service to handle offline quiz.
|
||||||
|
@ -103,7 +104,7 @@ export class AddonModQuizOfflineProvider {
|
||||||
* @returns Promise resolved with the answers.
|
* @returns Promise resolved with the answers.
|
||||||
*/
|
*/
|
||||||
getAttemptAnswers(attemptId: number, siteId?: string): Promise<CoreQuestionAnswerDBRecord[]> {
|
getAttemptAnswers(attemptId: number, siteId?: string): Promise<CoreQuestionAnswerDBRecord[]> {
|
||||||
return CoreQuestion.getAttemptAnswers(AddonModQuizProvider.COMPONENT, attemptId, siteId);
|
return CoreQuestion.getAttemptAnswers(ADDON_MOD_QUIZ_COMPONENT, attemptId, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,7 +150,7 @@ export class AddonModQuizOfflineProvider {
|
||||||
|
|
||||||
await Promise.all(questions.map(async (question) => {
|
await Promise.all(questions.map(async (question) => {
|
||||||
const dbQuestion = await CoreUtils.ignoreErrors(
|
const dbQuestion = await CoreUtils.ignoreErrors(
|
||||||
CoreQuestion.getQuestion(AddonModQuizProvider.COMPONENT, attemptId, question.slot, siteId),
|
CoreQuestion.getQuestion(ADDON_MOD_QUIZ_COMPONENT, attemptId, question.slot, siteId),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!dbQuestion) {
|
if (!dbQuestion) {
|
||||||
|
@ -230,8 +231,8 @@ export class AddonModQuizOfflineProvider {
|
||||||
const db = await CoreSites.getSiteDb(siteId);
|
const db = await CoreSites.getSiteDb(siteId);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
CoreQuestion.removeAttemptAnswers(AddonModQuizProvider.COMPONENT, attemptId, siteId),
|
CoreQuestion.removeAttemptAnswers(ADDON_MOD_QUIZ_COMPONENT, attemptId, siteId),
|
||||||
CoreQuestion.removeAttemptQuestions(AddonModQuizProvider.COMPONENT, attemptId, siteId),
|
CoreQuestion.removeAttemptQuestions(ADDON_MOD_QUIZ_COMPONENT, attemptId, siteId),
|
||||||
db.deleteRecords(ATTEMPTS_TABLE_NAME, { id: attemptId }),
|
db.deleteRecords(ATTEMPTS_TABLE_NAME, { id: attemptId }),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -248,8 +249,8 @@ export class AddonModQuizOfflineProvider {
|
||||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
CoreQuestion.removeQuestion(AddonModQuizProvider.COMPONENT, attemptId, slot, siteId),
|
CoreQuestion.removeQuestion(ADDON_MOD_QUIZ_COMPONENT, attemptId, slot, siteId),
|
||||||
CoreQuestion.removeQuestionAnswers(AddonModQuizProvider.COMPONENT, attemptId, slot, siteId),
|
CoreQuestion.removeQuestionAnswers(ADDON_MOD_QUIZ_COMPONENT, attemptId, slot, siteId),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +300,7 @@ export class AddonModQuizOfflineProvider {
|
||||||
|
|
||||||
const state = await CoreQuestionBehaviourDelegate.determineNewState(
|
const state = await CoreQuestionBehaviourDelegate.determineNewState(
|
||||||
quiz.preferredbehaviour ?? '',
|
quiz.preferredbehaviour ?? '',
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
attempt.id,
|
attempt.id,
|
||||||
question,
|
question,
|
||||||
quiz.coursemodule,
|
quiz.coursemodule,
|
||||||
|
@ -312,12 +313,12 @@ export class AddonModQuizOfflineProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete previously stored answers for this question.
|
// Delete previously stored answers for this question.
|
||||||
await CoreQuestion.removeQuestionAnswers(AddonModQuizProvider.COMPONENT, attempt.id, question.slot, siteId);
|
await CoreQuestion.removeQuestionAnswers(ADDON_MOD_QUIZ_COMPONENT, attempt.id, question.slot, siteId);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Now save the answers.
|
// Now save the answers.
|
||||||
await CoreQuestion.saveAnswers(
|
await CoreQuestion.saveAnswers(
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
quiz.id,
|
quiz.id,
|
||||||
attempt.id,
|
attempt.id,
|
||||||
attempt.userid ?? CoreSites.getCurrentSiteUserId(),
|
attempt.userid ?? CoreSites.getCurrentSiteUserId(),
|
||||||
|
@ -332,7 +333,7 @@ export class AddonModQuizOfflineProvider {
|
||||||
const question = questionsWithAnswers[Number(slot)];
|
const question = questionsWithAnswers[Number(slot)];
|
||||||
|
|
||||||
await CoreQuestion.saveQuestion(
|
await CoreQuestion.saveQuestion(
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
quiz.id,
|
quiz.id,
|
||||||
attempt.id,
|
attempt.id,
|
||||||
attempt.userid ?? CoreSites.getCurrentSiteUserId(),
|
attempt.userid ?? CoreSites.getCurrentSiteUserId(),
|
||||||
|
|
|
@ -29,8 +29,9 @@ import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
import { AddonModQuizAttemptDBRecord } from './database/quiz';
|
import { AddonModQuizAttemptDBRecord } from './database/quiz';
|
||||||
import { AddonModQuizPrefetchHandler } from './handlers/prefetch';
|
import { AddonModQuizPrefetchHandler } from './handlers/prefetch';
|
||||||
import { AddonModQuiz, AddonModQuizAttemptWSData, AddonModQuizProvider, AddonModQuizQuizWSData } from './quiz';
|
import { AddonModQuiz, AddonModQuizAttemptWSData, AddonModQuizQuizWSData } from './quiz';
|
||||||
import { AddonModQuizOffline, AddonModQuizQuestionsWithAnswers } from './quiz-offline';
|
import { AddonModQuizOffline, AddonModQuizQuestionsWithAnswers } from './quiz-offline';
|
||||||
|
import { ADDON_MOD_QUIZ_COMPONENT } from '../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to sync quizzes.
|
* Service to sync quizzes.
|
||||||
|
@ -79,7 +80,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
|
||||||
for (const slot in options.onlineQuestions) {
|
for (const slot in options.onlineQuestions) {
|
||||||
promises.push(CoreQuestionDelegate.deleteOfflineData(
|
promises.push(CoreQuestionDelegate.deleteOfflineData(
|
||||||
options.onlineQuestions[slot],
|
options.onlineQuestions[slot],
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
quiz.coursemodule,
|
quiz.coursemodule,
|
||||||
siteId,
|
siteId,
|
||||||
));
|
));
|
||||||
|
@ -204,7 +205,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
|
||||||
}
|
}
|
||||||
quizIds[attempt.quizid] = true;
|
quizIds[attempt.quizid] = true;
|
||||||
|
|
||||||
if (CoreSync.isBlocked(AddonModQuizProvider.COMPONENT, attempt.quizid, siteId)) {
|
if (CoreSync.isBlocked(ADDON_MOD_QUIZ_COMPONENT, attempt.quizid, siteId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +269,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that quiz isn't blocked.
|
// Verify that quiz isn't blocked.
|
||||||
if (CoreSync.isBlocked(AddonModQuizProvider.COMPONENT, quiz.id, siteId)) {
|
if (CoreSync.isBlocked(ADDON_MOD_QUIZ_COMPONENT, quiz.id, siteId)) {
|
||||||
this.logger.debug('Cannot sync quiz ' + quiz.id + ' because it is blocked.');
|
this.logger.debug('Cannot sync quiz ' + quiz.id + ' because it is blocked.');
|
||||||
|
|
||||||
throw new CoreError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
|
throw new CoreError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
|
||||||
|
@ -300,7 +301,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
|
||||||
|
|
||||||
// Sync offline logs.
|
// Sync offline logs.
|
||||||
await CoreUtils.ignoreErrors(
|
await CoreUtils.ignoreErrors(
|
||||||
CoreCourseLogHelper.syncActivity(AddonModQuizProvider.COMPONENT, quiz.id, siteId),
|
CoreCourseLogHelper.syncActivity(ADDON_MOD_QUIZ_COMPONENT, quiz.id, siteId),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get all the offline attempts for the quiz. It should always be 0 or 1 attempt
|
// Get all the offline attempts for the quiz. It should always be 0 or 1 attempt
|
||||||
|
@ -381,7 +382,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
|
||||||
await CoreQuestionDelegate.prepareSyncData(
|
await CoreQuestionDelegate.prepareSyncData(
|
||||||
onlineQuestion,
|
onlineQuestion,
|
||||||
offlineQuestions[slot].answers,
|
offlineQuestions[slot].answers,
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
quiz.coursemodule,
|
quiz.coursemodule,
|
||||||
siteId,
|
siteId,
|
||||||
);
|
);
|
||||||
|
|
|
@ -42,8 +42,12 @@ import { AddonModQuizOffline, AddonModQuizQuestionsWithAnswers } from './quiz-of
|
||||||
import { AddonModQuizAutoSyncData, AddonModQuizSyncProvider } from './quiz-sync';
|
import { AddonModQuizAutoSyncData, AddonModQuizSyncProvider } from './quiz-sync';
|
||||||
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
||||||
import { QUESTION_INVALID_STATE_CLASSES, QUESTION_TODO_STATE_CLASSES } from '@features/question/constants';
|
import { QUESTION_INVALID_STATE_CLASSES, QUESTION_TODO_STATE_CLASSES } from '@features/question/constants';
|
||||||
|
import {
|
||||||
const ROOT_CACHE_KEY = 'mmaModQuiz:';
|
ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT,
|
||||||
|
AddonModQuizAttemptStates,
|
||||||
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
|
AddonModQuizGradeMethods,
|
||||||
|
} from '../constants';
|
||||||
|
|
||||||
declare module '@singletons/events' {
|
declare module '@singletons/events' {
|
||||||
|
|
||||||
|
@ -53,7 +57,7 @@ declare module '@singletons/events' {
|
||||||
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
|
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
|
||||||
*/
|
*/
|
||||||
export interface CoreEventsData {
|
export interface CoreEventsData {
|
||||||
[AddonModQuizProvider.ATTEMPT_FINISHED_EVENT]: AddonModQuizAttemptFinishedData;
|
[ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT]: AddonModQuizAttemptFinishedData;
|
||||||
[AddonModQuizSyncProvider.AUTO_SYNCED]: AddonModQuizAutoSyncData;
|
[AddonModQuizSyncProvider.AUTO_SYNCED]: AddonModQuizAutoSyncData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,27 +69,7 @@ declare module '@singletons/events' {
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class AddonModQuizProvider {
|
export class AddonModQuizProvider {
|
||||||
|
|
||||||
static readonly COMPONENT = 'mmaModQuiz';
|
protected static readonly ROOT_CACHE_KEY = 'mmaModQuiz:';
|
||||||
static readonly ATTEMPT_FINISHED_EVENT = 'addon_mod_quiz_attempt_finished';
|
|
||||||
|
|
||||||
// Grade methods.
|
|
||||||
static readonly GRADEHIGHEST = 1;
|
|
||||||
static readonly GRADEAVERAGE = 2;
|
|
||||||
static readonly ATTEMPTFIRST = 3;
|
|
||||||
static readonly ATTEMPTLAST = 4;
|
|
||||||
|
|
||||||
// Question options.
|
|
||||||
static readonly QUESTION_OPTIONS_MAX_ONLY = 1;
|
|
||||||
static readonly QUESTION_OPTIONS_MARK_AND_MAX = 2;
|
|
||||||
|
|
||||||
// Attempt state.
|
|
||||||
static readonly ATTEMPT_IN_PROGRESS = 'inprogress';
|
|
||||||
static readonly ATTEMPT_OVERDUE = 'overdue';
|
|
||||||
static readonly ATTEMPT_FINISHED = 'finished';
|
|
||||||
static readonly ATTEMPT_ABANDONED = 'abandoned';
|
|
||||||
|
|
||||||
// Show the countdown timer if there is less than this amount of time left before the the quiz close date.
|
|
||||||
static readonly QUIZ_SHOW_TIME_BEFORE_DEADLINE = 3600;
|
|
||||||
|
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
|
|
||||||
|
@ -164,7 +148,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getAttemptAccessInformationCommonCacheKey(quizId: number): string {
|
protected getAttemptAccessInformationCommonCacheKey(quizId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'attemptAccessInformation:' + quizId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'attemptAccessInformation:' + quizId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,7 +173,7 @@ export class AddonModQuizProvider {
|
||||||
};
|
};
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getAttemptAccessInformationCacheKey(quizId, attemptId),
|
cacheKey: this.getAttemptAccessInformationCacheKey(quizId, attemptId),
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -215,7 +199,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getAttemptDataCommonCacheKey(attemptId: number): string {
|
protected getAttemptDataCommonCacheKey(attemptId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'attemptData:' + attemptId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'attemptData:' + attemptId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,7 +232,7 @@ export class AddonModQuizProvider {
|
||||||
};
|
};
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getAttemptDataCacheKey(attemptId, page),
|
cacheKey: this.getAttemptDataCacheKey(attemptId, page),
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -288,10 +272,10 @@ export class AddonModQuizProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (attempt.state) {
|
switch (attempt.state) {
|
||||||
case AddonModQuizProvider.ATTEMPT_IN_PROGRESS:
|
case AddonModQuizAttemptStates.IN_PROGRESS:
|
||||||
return dueDate * 1000;
|
return dueDate * 1000;
|
||||||
|
|
||||||
case AddonModQuizProvider.ATTEMPT_OVERDUE:
|
case AddonModQuizAttemptStates.OVERDUE:
|
||||||
return (dueDate + (quiz.graceperiod ?? 0)) * 1000;
|
return (dueDate + (quiz.graceperiod ?? 0)) * 1000;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -311,7 +295,7 @@ export class AddonModQuizProvider {
|
||||||
getAttemptDueDateWarning(quiz: AddonModQuizQuizWSData, attempt: AddonModQuizAttemptWSData): string | undefined {
|
getAttemptDueDateWarning(quiz: AddonModQuizQuizWSData, attempt: AddonModQuizAttemptWSData): string | undefined {
|
||||||
const dueDate = this.getAttemptDueDate(quiz, attempt);
|
const dueDate = this.getAttemptDueDate(quiz, attempt);
|
||||||
|
|
||||||
if (attempt.state === AddonModQuizProvider.ATTEMPT_OVERDUE) {
|
if (attempt.state === AddonModQuizAttemptStates.OVERDUE) {
|
||||||
return Translate.instant(
|
return Translate.instant(
|
||||||
'addon.mod_quiz.overduemustbesubmittedby',
|
'addon.mod_quiz.overduemustbesubmittedby',
|
||||||
{ $a: CoreTimeUtils.userDate(dueDate) },
|
{ $a: CoreTimeUtils.userDate(dueDate) },
|
||||||
|
@ -334,10 +318,10 @@ export class AddonModQuizProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (attempt.state) {
|
switch (attempt.state) {
|
||||||
case AddonModQuizProvider.ATTEMPT_IN_PROGRESS:
|
case AddonModQuizAttemptStates.IN_PROGRESS:
|
||||||
return [Translate.instant('addon.mod_quiz.stateinprogress')];
|
return [Translate.instant('addon.mod_quiz.stateinprogress')];
|
||||||
|
|
||||||
case AddonModQuizProvider.ATTEMPT_OVERDUE: {
|
case AddonModQuizAttemptStates.OVERDUE: {
|
||||||
const sentences: string[] = [];
|
const sentences: string[] = [];
|
||||||
const dueDate = this.getAttemptDueDate(quiz, attempt);
|
const dueDate = this.getAttemptDueDate(quiz, attempt);
|
||||||
|
|
||||||
|
@ -353,7 +337,7 @@ export class AddonModQuizProvider {
|
||||||
return sentences;
|
return sentences;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AddonModQuizProvider.ATTEMPT_FINISHED:
|
case AddonModQuizAttemptStates.FINISHED:
|
||||||
return [
|
return [
|
||||||
Translate.instant('addon.mod_quiz.statefinished'),
|
Translate.instant('addon.mod_quiz.statefinished'),
|
||||||
Translate.instant(
|
Translate.instant(
|
||||||
|
@ -362,7 +346,7 @@ export class AddonModQuizProvider {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
case AddonModQuizProvider.ATTEMPT_ABANDONED:
|
case AddonModQuizAttemptStates.ABANDONED:
|
||||||
return [Translate.instant('addon.mod_quiz.stateabandoned')];
|
return [Translate.instant('addon.mod_quiz.stateabandoned')];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -378,16 +362,16 @@ export class AddonModQuizProvider {
|
||||||
*/
|
*/
|
||||||
getAttemptReadableStateName(state: string): string {
|
getAttemptReadableStateName(state: string): string {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AddonModQuizProvider.ATTEMPT_IN_PROGRESS:
|
case AddonModQuizAttemptStates.IN_PROGRESS:
|
||||||
return Translate.instant('addon.mod_quiz.stateinprogress');
|
return Translate.instant('addon.mod_quiz.stateinprogress');
|
||||||
|
|
||||||
case AddonModQuizProvider.ATTEMPT_OVERDUE:
|
case AddonModQuizAttemptStates.OVERDUE:
|
||||||
return Translate.instant('addon.mod_quiz.stateoverdue');
|
return Translate.instant('addon.mod_quiz.stateoverdue');
|
||||||
|
|
||||||
case AddonModQuizProvider.ATTEMPT_FINISHED:
|
case AddonModQuizAttemptStates.FINISHED:
|
||||||
return Translate.instant('addon.mod_quiz.statefinished');
|
return Translate.instant('addon.mod_quiz.statefinished');
|
||||||
|
|
||||||
case AddonModQuizProvider.ATTEMPT_ABANDONED:
|
case AddonModQuizAttemptStates.ABANDONED:
|
||||||
return Translate.instant('addon.mod_quiz.stateabandoned');
|
return Translate.instant('addon.mod_quiz.stateabandoned');
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -413,7 +397,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getAttemptReviewCommonCacheKey(attemptId: number): string {
|
protected getAttemptReviewCommonCacheKey(attemptId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'attemptReview:' + attemptId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'attemptReview:' + attemptId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -438,7 +422,7 @@ export class AddonModQuizProvider {
|
||||||
const preSets = {
|
const preSets = {
|
||||||
cacheKey: this.getAttemptReviewCacheKey(attemptId, page),
|
cacheKey: this.getAttemptReviewCacheKey(attemptId, page),
|
||||||
cacheErrors: ['noreview'],
|
cacheErrors: ['noreview'],
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -457,7 +441,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getAttemptSummaryCacheKey(attemptId: number): string {
|
protected getAttemptSummaryCacheKey(attemptId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'attemptSummary:' + attemptId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'attemptSummary:' + attemptId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -487,7 +471,7 @@ export class AddonModQuizProvider {
|
||||||
};
|
};
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getAttemptSummaryCacheKey(attemptId),
|
cacheKey: this.getAttemptSummaryCacheKey(attemptId),
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -521,7 +505,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCombinedReviewOptionsCommonCacheKey(quizId: number): string {
|
protected getCombinedReviewOptionsCommonCacheKey(quizId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'combinedReviewOptions:' + quizId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'combinedReviewOptions:' + quizId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -544,7 +528,7 @@ export class AddonModQuizProvider {
|
||||||
};
|
};
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getCombinedReviewOptionsCacheKey(quizId, userId),
|
cacheKey: this.getCombinedReviewOptionsCacheKey(quizId, userId),
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -581,7 +565,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getFeedbackForGradeCommonCacheKey(quizId: number): string {
|
protected getFeedbackForGradeCommonCacheKey(quizId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'feedbackForGrade:' + quizId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'feedbackForGrade:' + quizId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -606,7 +590,7 @@ export class AddonModQuizProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getFeedbackForGradeCacheKey(quizId, grade),
|
cacheKey: this.getFeedbackForGradeCacheKey(quizId, grade),
|
||||||
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -719,7 +703,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getQuizDataCacheKey(courseId: number): string {
|
protected getQuizDataCacheKey(courseId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'quiz:' + courseId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'quiz:' + courseId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -746,7 +730,7 @@ export class AddonModQuizProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getQuizDataCacheKey(courseId),
|
cacheKey: this.getQuizDataCacheKey(courseId),
|
||||||
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -797,7 +781,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getQuizAccessInformationCacheKey(quizId: number): string {
|
protected getQuizAccessInformationCacheKey(quizId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'quizAccessInformation:' + quizId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'quizAccessInformation:' + quizId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -818,7 +802,7 @@ export class AddonModQuizProvider {
|
||||||
};
|
};
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getQuizAccessInformationCacheKey(quizId),
|
cacheKey: this.getQuizAccessInformationCacheKey(quizId),
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -842,13 +826,13 @@ export class AddonModQuizProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case AddonModQuizProvider.GRADEHIGHEST:
|
case AddonModQuizGradeMethods.HIGHEST_GRADE:
|
||||||
return Translate.instant('addon.mod_quiz.gradehighest');
|
return Translate.instant('addon.mod_quiz.gradehighest');
|
||||||
case AddonModQuizProvider.GRADEAVERAGE:
|
case AddonModQuizGradeMethods.AVERAGE_GRADE:
|
||||||
return Translate.instant('addon.mod_quiz.gradeaverage');
|
return Translate.instant('addon.mod_quiz.gradeaverage');
|
||||||
case AddonModQuizProvider.ATTEMPTFIRST:
|
case AddonModQuizGradeMethods.FIRST_ATTEMPT:
|
||||||
return Translate.instant('addon.mod_quiz.attemptfirst');
|
return Translate.instant('addon.mod_quiz.attemptfirst');
|
||||||
case AddonModQuizProvider.ATTEMPTLAST:
|
case AddonModQuizGradeMethods.LAST_ATTEMPT:
|
||||||
return Translate.instant('addon.mod_quiz.attemptlast');
|
return Translate.instant('addon.mod_quiz.attemptlast');
|
||||||
default:
|
default:
|
||||||
return '';
|
return '';
|
||||||
|
@ -862,7 +846,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getQuizRequiredQtypesCacheKey(quizId: number): string {
|
protected getQuizRequiredQtypesCacheKey(quizId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'quizRequiredQtypes:' + quizId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'quizRequiredQtypes:' + quizId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -881,7 +865,7 @@ export class AddonModQuizProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getQuizRequiredQtypesCacheKey(quizId),
|
cacheKey: this.getQuizRequiredQtypesCacheKey(quizId),
|
||||||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
|
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -1015,7 +999,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getUserAttemptsCommonCacheKey(quizId: number): string {
|
protected getUserAttemptsCommonCacheKey(quizId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'userAttempts:' + quizId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'userAttempts:' + quizId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1045,7 +1029,7 @@ export class AddonModQuizProvider {
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getUserAttemptsCacheKey(quizId, userId),
|
cacheKey: this.getUserAttemptsCacheKey(quizId, userId),
|
||||||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
|
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -1073,7 +1057,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getUserBestGradeCommonCacheKey(quizId: number): string {
|
protected getUserBestGradeCommonCacheKey(quizId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'userBestGrade:' + quizId;
|
return AddonModQuizProvider.ROOT_CACHE_KEY + 'userBestGrade:' + quizId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1093,7 +1077,7 @@ export class AddonModQuizProvider {
|
||||||
};
|
};
|
||||||
const preSets: CoreSiteWSPreSets = {
|
const preSets: CoreSiteWSPreSets = {
|
||||||
cacheKey: this.getUserBestGradeCacheKey(quizId, userId),
|
cacheKey: this.getUserBestGradeCacheKey(quizId, userId),
|
||||||
component: AddonModQuizProvider.COMPONENT,
|
component: ADDON_MOD_QUIZ_COMPONENT,
|
||||||
componentId: options.cmId,
|
componentId: options.cmId,
|
||||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||||
};
|
};
|
||||||
|
@ -1430,7 +1414,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Whether it's finished.
|
* @returns Whether it's finished.
|
||||||
*/
|
*/
|
||||||
isAttemptFinished(state?: string): boolean {
|
isAttemptFinished(state?: string): boolean {
|
||||||
return state == AddonModQuizProvider.ATTEMPT_FINISHED || state == AddonModQuizProvider.ATTEMPT_ABANDONED;
|
return state === AddonModQuizAttemptStates.FINISHED || state === AddonModQuizAttemptStates.ABANDONED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1461,7 +1445,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Whether it's nearly over or over.
|
* @returns Whether it's nearly over or over.
|
||||||
*/
|
*/
|
||||||
isAttemptTimeNearlyOver(quiz: AddonModQuizQuizWSData, attempt: AddonModQuizAttemptWSData): boolean {
|
isAttemptTimeNearlyOver(quiz: AddonModQuizQuizWSData, attempt: AddonModQuizAttemptWSData): boolean {
|
||||||
if (attempt.state != AddonModQuizProvider.ATTEMPT_IN_PROGRESS) {
|
if (attempt.state !== AddonModQuizAttemptStates.IN_PROGRESS) {
|
||||||
// Attempt not in progress, return true.
|
// Attempt not in progress, return true.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1600,7 +1584,7 @@ export class AddonModQuizProvider {
|
||||||
return CoreCourseLogHelper.log(
|
return CoreCourseLogHelper.log(
|
||||||
'mod_quiz_view_attempt_review',
|
'mod_quiz_view_attempt_review',
|
||||||
params,
|
params,
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
quizId,
|
quizId,
|
||||||
siteId,
|
siteId,
|
||||||
);
|
);
|
||||||
|
@ -1633,7 +1617,7 @@ export class AddonModQuizProvider {
|
||||||
return CoreCourseLogHelper.log(
|
return CoreCourseLogHelper.log(
|
||||||
'mod_quiz_view_attempt_summary',
|
'mod_quiz_view_attempt_summary',
|
||||||
params,
|
params,
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
quizId,
|
quizId,
|
||||||
siteId,
|
siteId,
|
||||||
);
|
);
|
||||||
|
@ -1654,7 +1638,7 @@ export class AddonModQuizProvider {
|
||||||
return CoreCourseLogHelper.log(
|
return CoreCourseLogHelper.log(
|
||||||
'mod_quiz_view_quiz',
|
'mod_quiz_view_quiz',
|
||||||
params,
|
params,
|
||||||
AddonModQuizProvider.COMPONENT,
|
ADDON_MOD_QUIZ_COMPONENT,
|
||||||
id,
|
id,
|
||||||
siteId,
|
siteId,
|
||||||
);
|
);
|
||||||
|
@ -1897,7 +1881,7 @@ export class AddonModQuizProvider {
|
||||||
shouldShowTimeLeft(rules: string[], attempt: AddonModQuizAttemptWSData, endTime: number): boolean {
|
shouldShowTimeLeft(rules: string[], attempt: AddonModQuizAttemptWSData, endTime: number): boolean {
|
||||||
const timeNow = CoreTimeUtils.timestamp();
|
const timeNow = CoreTimeUtils.timestamp();
|
||||||
|
|
||||||
if (attempt.state != AddonModQuizProvider.ATTEMPT_IN_PROGRESS) {
|
if (attempt.state !== AddonModQuizAttemptStates.IN_PROGRESS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2392,7 +2376,7 @@ export type AddonModQuizViewQuizWSParams = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data passed to ATTEMPT_FINISHED_EVENT event.
|
* Data passed to ADDON_MOD_QUIZ_ATTEMPT_FINISHED_EVENT event.
|
||||||
*/
|
*/
|
||||||
export type AddonModQuizAttemptFinishedData = {
|
export type AddonModQuizAttemptFinishedData = {
|
||||||
quizId: number;
|
quizId: number;
|
||||||
|
|
|
@ -19,3 +19,8 @@ export const QUESTION_NEEDS_GRADING_STATE_CLASSES = ['requiresgrading', 'complet
|
||||||
export const QUESTION_FINISHED_STATE_CLASSES = ['complete'] as const;
|
export const QUESTION_FINISHED_STATE_CLASSES = ['complete'] as const;
|
||||||
export const QUESTION_GAVE_UP_STATE_CLASSES = ['notanswered'] as const;
|
export const QUESTION_GAVE_UP_STATE_CLASSES = ['notanswered'] as const;
|
||||||
export const QUESTION_GRADED_STATE_CLASSES = ['complete', 'incorrect', 'partiallycorrect', 'correct'] as const;
|
export const QUESTION_GRADED_STATE_CLASSES = ['complete', 'incorrect', 'partiallycorrect', 'correct'] as const;
|
||||||
|
|
||||||
|
export const enum QuestionDisplayOptionsMarks {
|
||||||
|
MAX_ONLY = 1,
|
||||||
|
MARK_AND_MAX = 2,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue