diff --git a/src/addons/badges/services/badges.ts b/src/addons/badges/services/badges.ts index d95e4f733..df39a9595 100644 --- a/src/addons/badges/services/badges.ts +++ b/src/addons/badges/services/badges.ts @@ -83,7 +83,7 @@ export class AddonBadgesProvider { badge.alignment = badge.alignment || badge.competencies; // Check that the alignment is valid, they were broken in 3.7. - if (badge.alignment && badge.alignment[0] && typeof badge.alignment[0].targetname == 'undefined') { + if (badge.alignment && badge.alignment[0] && badge.alignment[0].targetname === undefined) { // If any badge lacks targetname it means they are affected by the Moodle bug, don't display them. delete badge.alignment; } diff --git a/src/addons/badges/services/handlers/user.ts b/src/addons/badges/services/handlers/user.ts index 52e44fb69..5e3a5bc44 100644 --- a/src/addons/badges/services/handlers/user.ts +++ b/src/addons/badges/services/handlers/user.ts @@ -49,7 +49,7 @@ export class AddonBadgesUserHandlerService implements CoreUserProfileHandler { courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): Promise { - if (navOptions && typeof navOptions.badges != 'undefined') { + if (navOptions && navOptions.badges !== undefined) { return navOptions.badges; } diff --git a/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts b/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts index fdeb9a967..60db4a0c0 100644 --- a/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts +++ b/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts @@ -67,13 +67,13 @@ export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent i section.modules.forEach((mod) => { if (mod.uservisible === false || !CoreCourse.moduleHasView(mod) || - typeof modFullNames[mod.modname] != 'undefined') { + modFullNames[mod.modname] !== undefined) { // Ignore this module. return; } // Get the archetype of the module type. - if (typeof archetypes[mod.modname] == 'undefined') { + if (archetypes[mod.modname] === undefined) { archetypes[mod.modname] = CoreCourseModuleDelegate.supportsFeature( mod.modname, CoreConstants.FEATURE_MOD_ARCHETYPE, diff --git a/src/addons/blog/services/handlers/course-option.ts b/src/addons/blog/services/handlers/course-option.ts index c15f4b4de..c935a221d 100644 --- a/src/addons/blog/services/handlers/course-option.ts +++ b/src/addons/blog/services/handlers/course-option.ts @@ -62,7 +62,7 @@ export class AddonBlogCourseOptionHandlerService implements CoreCourseOptionsHan ): Promise { const enabled = await CoreCourseHelper.hasABlockNamed(courseId, 'blog_menu'); - if (enabled && navOptions && typeof navOptions.blogs != 'undefined') { + if (enabled && navOptions && navOptions.blogs !== undefined) { return navOptions.blogs; } diff --git a/src/addons/calendar/pages/day/day.page.ts b/src/addons/calendar/pages/day/day.page.ts index 984d5931b..b806ed84c 100644 --- a/src/addons/calendar/pages/day/day.page.ts +++ b/src/addons/calendar/pages/day/day.page.ts @@ -211,7 +211,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { this.filter.courseId = CoreNavigator.getRouteNumberParam('courseId'); this.filter.categoryId = CoreNavigator.getRouteNumberParam('categoryId'); - this.filter.filtered = typeof this.filter.courseId != 'undefined' || types.some((name) => !this.filter[name]); + this.filter.filtered = this.filter.courseId !== undefined || types.some((name) => !this.filter[name]); const month = CoreNavigator.getRouteNumberParam('month'); const source = new AddonCalendarDaySlidesItemsManagerSource(this, moment({ diff --git a/src/addons/calendar/services/calendar.ts b/src/addons/calendar/services/calendar.ts index 17c60c3bf..69473fb05 100644 --- a/src/addons/calendar/services/calendar.ts +++ b/src/addons/calendar/services/calendar.ts @@ -538,7 +538,7 @@ export class AddonCalendarProvider { // Ignore errors. } - if (typeof value == 'undefined' || value === null) { + if (value === undefined || value === null) { value = site.getStoredConfig('calendar_lookahead'); } diff --git a/src/addons/competency/pages/competencysummary/competencysummary.ts b/src/addons/competency/pages/competencysummary/competencysummary.ts index fa810bf2b..5119dd2c8 100644 --- a/src/addons/competency/pages/competencysummary/competencysummary.ts +++ b/src/addons/competency/pages/competencysummary/competencysummary.ts @@ -70,7 +70,7 @@ export class AddonCompetencyCompetencySummaryPage implements OnInit { protected async fetchCompetency(): Promise { try { const result = await AddonCompetency.getCompetencySummary(this.competencyId); - if (!this.contextLevel || typeof this.contextInstanceId == 'undefined') { + if (!this.contextLevel || this.contextInstanceId === undefined) { // Context not specified, use user context. this.contextLevel = ContextLevel.USER; this.contextInstanceId = result.usercompetency!.userid; diff --git a/src/addons/competency/services/handlers/course-option.ts b/src/addons/competency/services/handlers/course-option.ts index 7051064ff..d46c2d6fa 100644 --- a/src/addons/competency/services/handlers/course-option.ts +++ b/src/addons/competency/services/handlers/course-option.ts @@ -55,7 +55,7 @@ export class AddonCompetencyCourseOptionHandlerService implements CoreCourseOpti return false; // Not enabled for guests. } - if (navOptions && typeof navOptions.competencies != 'undefined') { + if (navOptions && navOptions.competencies !== undefined) { return navOptions.competencies; } @@ -83,7 +83,7 @@ export class AddonCompetencyCourseOptionHandlerService implements CoreCourseOpti * @inheritdoc */ async invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise { - if (navOptions && typeof navOptions.competencies != 'undefined') { + if (navOptions && navOptions.competencies !== undefined) { // No need to invalidate anything. return; } diff --git a/src/addons/coursecompletion/services/coursecompletion.ts b/src/addons/coursecompletion/services/coursecompletion.ts index 21898f3c6..0fa9d22ec 100644 --- a/src/addons/coursecompletion/services/coursecompletion.ts +++ b/src/addons/coursecompletion/services/coursecompletion.ts @@ -172,12 +172,12 @@ export class AddonCourseCompletionProvider { const course = await CoreCourses.getUserCourse(courseId, preferCache); if (course) { - if (typeof course.enablecompletion != 'undefined' && !course.enablecompletion) { + if (course.enablecompletion !== undefined && !course.enablecompletion) { // Completion not enabled for the course. return false; } - if (typeof course.completionhascriteria != 'undefined' && !course.completionhascriteria) { + if (course.completionhascriteria !== undefined && !course.completionhascriteria) { // No criteria, cannot view completion. return false; } @@ -206,7 +206,7 @@ export class AddonCourseCompletionProvider { // If the site is returning the completionhascriteria then the user can view his own completion. // We already checked the value in isPluginViewEnabledForCourse. - if (course && typeof course.completionhascriteria != 'undefined') { + if (course && course.completionhascriteria !== undefined) { return true; } } diff --git a/src/addons/filter/mathjaxloader/services/handlers/mathjaxloader.ts b/src/addons/filter/mathjaxloader/services/handlers/mathjaxloader.ts index a0aab60bf..2f9ae9056 100644 --- a/src/addons/filter/mathjaxloader/services/handlers/mathjaxloader.ts +++ b/src/addons/filter/mathjaxloader/services/handlers/mathjaxloader.ts @@ -86,7 +86,7 @@ export class AddonFilterMathJaxLoaderHandlerService extends CoreFilterDefaultHan // Update MathJax locale if app language changes. CoreEvents.on(CoreEvents.LANGUAGE_CHANGED, (lang: string) => { - if (typeof this.window.MathJax == 'undefined') { + if (this.window.MathJax === undefined) { return; } @@ -223,7 +223,7 @@ export class AddonFilterMathJaxLoaderHandlerService extends CoreFilterDefaultHan if (!this._configured) { const lang = this._lang; - if (typeof that.window.MathJax != 'undefined') { + if (that.window.MathJax !== undefined) { that.window.MathJax.Hub.Queue(() => { that.window.MathJax.Localization.setLocale(lang); }); @@ -238,7 +238,7 @@ export class AddonFilterMathJaxLoaderHandlerService extends CoreFilterDefaultHan this._setLocale(); } - if (typeof that.window.MathJax != 'undefined') { + if (that.window.MathJax !== undefined) { const processDelay = that.window.MathJax.Hub.processSectionDelay; // Set the process section delay to 0 when updating the formula. that.window.MathJax.Hub.processSectionDelay = 0; diff --git a/src/addons/messages/pages/discussion/discussion.page.ts b/src/addons/messages/pages/discussion/discussion.page.ts index ca9028029..7c4176af1 100644 --- a/src/addons/messages/pages/discussion/discussion.page.ts +++ b/src/addons/messages/pages/discussion/discussion.page.ts @@ -205,7 +205,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView message.useridfrom; let added = false; - if (typeof this.keepMessageMap[message.hash] === 'undefined') { + if (this.keepMessageMap[message.hash] === undefined) { // Message not added to the list. Add it now. this.messages.push(message); added = message.useridfrom != this.currentUserId; @@ -1277,7 +1277,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView }, }); - if (typeof userId != 'undefined') { + if (userId !== undefined) { const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/**/discussion'); // Open user conversation. diff --git a/src/addons/messages/pages/discussions-35/discussions.page.ts b/src/addons/messages/pages/discussions-35/discussions.page.ts index 5c904cbae..ad60b73e9 100644 --- a/src/addons/messages/pages/discussions-35/discussions.page.ts +++ b/src/addons/messages/pages/discussions-35/discussions.page.ts @@ -77,7 +77,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { if (data.userId && this.discussions) { const discussion = this.discussions.find((disc) => disc.message!.user == data.userId); - if (typeof discussion == 'undefined') { + if (discussion === undefined) { this.loaded = false; this.refreshData().finally(() => { this.loaded = true; @@ -99,7 +99,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { if (data.userId && this.discussions) { const discussion = this.discussions.find((disc) => disc.message!.user == data.userId); - if (typeof discussion != 'undefined') { + if (discussion !== undefined) { // A discussion has been read reset counter. discussion.unread = false; diff --git a/src/addons/messages/pages/group-conversations/group-conversations.page.ts b/src/addons/messages/pages/group-conversations/group-conversations.page.ts index f4d884458..47d6ba354 100644 --- a/src/addons/messages/pages/group-conversations/group-conversations.page.ts +++ b/src/addons/messages/pages/group-conversations/group-conversations.page.ts @@ -118,7 +118,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { // Search the conversation to update. const conversation = this.findConversation(data.conversationId, data.userId, expandedOption); - if (typeof conversation == 'undefined') { + if (conversation === undefined) { // Probably a new conversation, refresh the list. this.loaded = false; this.refreshData().finally(() => { @@ -152,7 +152,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { if (data.conversationId) { const conversation = this.findConversation(data.conversationId); - if (typeof conversation != 'undefined') { + if (conversation !== undefined) { // A conversation has been read reset counter. conversation.unreadcount = 0; @@ -318,7 +318,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { await Promise.all(promises); // The expanded status hasn't been initialized. Do it now. - if (typeof this.favourites.expanded == 'undefined' && (this.selectedConversationId || this.selectedUserId)) { + if (this.favourites.expanded === undefined && (this.selectedConversationId || this.selectedUserId)) { // A certain conversation should be opened. // We don't know which option it belongs to, so we need to fetch the data for all of them. const promises: Promise[] = []; @@ -355,7 +355,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { * @return Promise resolved when done. */ protected async fetchDataForExpandedOption(): Promise { - if (typeof this.favourites.expanded == 'undefined') { + if (this.favourites.expanded === undefined) { // Calculate which option should be expanded initially. this.favourites.expanded = this.favourites.count != 0 && !this.group.unread && !this.individual.unread; this.group.expanded = !this.favourites.expanded && this.group.count != 0 && !this.individual.unread; @@ -572,7 +572,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { if (conversation) { // Check if it's the last message. Offline messages are considered more recent than sent messages. - if (typeof conversation.lastmessage === 'undefined' || conversation.lastmessage === null || + if (conversation.lastmessage === undefined || conversation.lastmessage === null || !conversation.lastmessagepending || (conversation.lastmessagedate || 0) <= message.timecreated / 1000) { this.addLastOfflineMessage(conversation, message); diff --git a/src/addons/messages/services/handlers/discussion-link.ts b/src/addons/messages/services/handlers/discussion-link.ts index b0fae3fce..2eb03cdec 100644 --- a/src/addons/messages/services/handlers/discussion-link.ts +++ b/src/addons/messages/services/handlers/discussion-link.ts @@ -69,12 +69,12 @@ export class AddonMessagesDiscussionLinkHandlerService extends CoreContentLinksH return false; } - if (typeof params.id == 'undefined' && typeof params.user2 == 'undefined') { + if (params.id === undefined && params.user2 === undefined) { // Other user not defined, cannot treat the URL. return false; } - if (typeof params.user1 != 'undefined') { + if (params.user1 !== undefined) { // Check if user1 is the current user, since the app only supports current user. const site = await CoreSites.getSite(siteId); diff --git a/src/addons/messages/services/messages-sync.ts b/src/addons/messages/services/messages-sync.ts index cdcc4dd6c..64edaf6df 100644 --- a/src/addons/messages/services/messages-sync.ts +++ b/src/addons/messages/services/messages-sync.ts @@ -107,7 +107,7 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider { promises.push(this.syncDiscussion(conversationId, undefined, siteId).then((result) => { - if (typeof result == 'undefined') { + if (result === undefined) { return; } @@ -120,7 +120,7 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider { promises.push(this.syncDiscussion(undefined, userId, siteId).then((result) => { - if (typeof result == 'undefined') { + if (result === undefined) { return; } diff --git a/src/addons/messages/services/messages.ts b/src/addons/messages/services/messages.ts index 1498691b6..ba07393c5 100644 --- a/src/addons/messages/services/messages.ts +++ b/src/addons/messages/services/messages.ts @@ -317,7 +317,7 @@ export class AddonMessagesProvider { userid: userId, }; - if (typeof read != 'undefined') { + if (read !== undefined) { params.read = read; } @@ -1075,10 +1075,10 @@ export class AddonMessagesProvider { preSets.getFromCache = false; preSets.emergencyCache = false; } - if (typeof type != 'undefined' && type != null) { + if (type !== undefined && type != null) { params.type = type; } - if (typeof favourites != 'undefined' && favourites != null) { + if (favourites !== undefined && favourites != null) { params.favourites = !!favourites; } if (site.isVersionGreaterEqualThan('3.7') && type != AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP) { @@ -1244,7 +1244,7 @@ export class AddonMessagesProvider { userId: number, userFullname: string, ): void => { - if (typeof discussions[userId] === 'undefined') { + if (discussions[userId] === undefined) { discussions[userId] = { fullname: userFullname, profileimageurl: '', @@ -1259,7 +1259,7 @@ export class AddonMessagesProvider { // Extract the most recent message. Pending messages are considered more recent than messages already sent. const discMessage = discussions[userId].message; - if (typeof discMessage === 'undefined' || (!discMessage.pending && message.pending) || + if (discMessage === undefined || (!discMessage.pending && message.pending) || (discMessage.pending == message.pending && (discMessage.timecreated < message.timecreated || (discMessage.timecreated == message.timecreated && discMessage.id < messageId)))) { @@ -2646,7 +2646,7 @@ export class AddonMessagesProvider { conversationid: conversationId, messages: messages.map((message) => ({ text: message.text, - textformat: typeof message.textformat != 'undefined' ? message.textformat : 1, + textformat: message.textformat !== undefined ? message.textformat : 1, })), }; diff --git a/src/addons/mod/assign/classes/base-feedback-plugin-component.ts b/src/addons/mod/assign/classes/base-feedback-plugin-component.ts index b44226f47..2bc825f83 100644 --- a/src/addons/mod/assign/classes/base-feedback-plugin-component.ts +++ b/src/addons/mod/assign/classes/base-feedback-plugin-component.ts @@ -57,7 +57,7 @@ export class AddonModAssignFeedbackPluginBaseComponent { }, }); - if (typeof modalData == 'undefined') { + if (modalData === undefined) { throw new CoreCanceledError(); // User cancelled. } diff --git a/src/addons/mod/assign/components/index/index.ts b/src/addons/mod/assign/components/index/index.ts index 80a089d2b..0aa2a9a8e 100644 --- a/src/addons/mod/assign/components/index/index.ts +++ b/src/addons/mod/assign/components/index/index.ts @@ -304,7 +304,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo * @param hasSubmissions If the status has any submission. */ goToSubmissionList(status?: string, hasSubmissions = false): void { - if (typeof status != 'undefined' && !hasSubmissions) { + if (status !== undefined && !hasSubmissions) { return; } @@ -312,7 +312,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo groupId: this.group || 0, moduleName: this.moduleName, }; - if (typeof status != 'undefined') { + if (status !== undefined) { params.status = status; } diff --git a/src/addons/mod/assign/components/submission/submission.ts b/src/addons/mod/assign/components/submission/submission.ts index 4256c120a..5b7b69785 100644 --- a/src/addons/mod/assign/components/submission/submission.ts +++ b/src/addons/mod/assign/components/submission/submission.ts @@ -380,7 +380,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can for (const x in this.gradeInfo.outcomes) { const outcome = this.gradeInfo.outcomes[x]; - if (this.originalGrades.outcomes[outcome.id] == 'undefined' || + if (this.originalGrades.outcomes[outcome.id] === undefined || this.originalGrades.outcomes[outcome.id] != outcome.selectedId) { return true; } @@ -726,7 +726,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can if (submissionGrade.outcomes && Object.keys(submissionGrade.outcomes).length && this.gradeInfo?.outcomes) { this.gradeInfo.outcomes.forEach((outcome) => { - if (typeof submissionGrade.outcomes[outcome.itemNumber!] != 'undefined') { + if (submissionGrade.outcomes[outcome.itemNumber!] !== undefined) { // If outcome has been modified from gradebook, do not use offline. if (outcome.modified! < submissionGrade.timemodified) { outcome.selectedId = submissionGrade.outcomes[outcome.itemNumber!]; @@ -944,7 +944,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can // Check if grading method is simple or not. if (this.gradeInfo.advancedgrading && this.gradeInfo.advancedgrading[0] && - typeof this.gradeInfo.advancedgrading[0].method != 'undefined') { + this.gradeInfo.advancedgrading[0].method !== undefined) { this.grade.method = this.gradeInfo.advancedgrading[0].method || 'simple'; } else { this.grade.method = 'simple'; @@ -1039,7 +1039,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can } const submissionStatementMissing = !!this.assign!.requiresubmissionstatement && - typeof this.assign!.submissionstatement == 'undefined'; + this.assign!.submissionstatement === undefined; this.canSubmit = !this.isSubmittedForGrading && !this.submittedOffline && (submissionStatus.lastattempt.cansubmit || (this.hasOffline && AddonModAssign.canSubmitOffline(this.assign!, submissionStatus))); diff --git a/src/addons/mod/assign/feedback/comments/services/handler.ts b/src/addons/mod/assign/feedback/comments/services/handler.ts index 1b288988c..02a8bc342 100644 --- a/src/addons/mod/assign/feedback/comments/services/handler.ts +++ b/src/addons/mod/assign/feedback/comments/services/handler.ts @@ -69,7 +69,7 @@ export class AddonModAssignFeedbackCommentsHandlerService implements AddonModAss */ discardDraft(assignId: number, userId: number, siteId?: string): void { const id = this.getDraftId(assignId, userId, siteId); - if (typeof this.drafts[id] != 'undefined') { + if (this.drafts[id] !== undefined) { delete this.drafts[id]; } } @@ -95,7 +95,7 @@ export class AddonModAssignFeedbackCommentsHandlerService implements AddonModAss getDraft(assignId: number, userId: number, siteId?: string): AddonModAssignFeedbackCommentsDraftData | undefined { const id = this.getDraftId(assignId, userId, siteId); - if (typeof this.drafts[id] != 'undefined') { + if (this.drafts[id] !== undefined) { return this.drafts[id]; } } @@ -164,7 +164,7 @@ export class AddonModAssignFeedbackCommentsHandlerService implements AddonModAss const initialText = AddonModAssign.getSubmissionPluginText(plugin); const newText = AddonModAssignFeedbackCommentsHandler.getTextFromInputData(plugin, inputData); - if (typeof newText == 'undefined') { + if (newText === undefined) { return false; } diff --git a/src/addons/mod/assign/pages/submission-review/submission-review.ts b/src/addons/mod/assign/pages/submission-review/submission-review.ts index 20342ef15..a51cf4bc4 100644 --- a/src/addons/mod/assign/pages/submission-review/submission-review.ts +++ b/src/addons/mod/assign/pages/submission-review/submission-review.ts @@ -142,7 +142,7 @@ export class AddonModAssignSubmissionReviewPage implements OnInit, OnDestroy, Ca // Grades can be saved if simple grading. if (gradeInfo.advancedgrading && gradeInfo.advancedgrading[0] && - typeof gradeInfo.advancedgrading[0].method != 'undefined') { + gradeInfo.advancedgrading[0].method !== undefined) { const method = gradeInfo.advancedgrading[0].method || 'simple'; this.canSaveGrades = method == 'simple'; diff --git a/src/addons/mod/assign/services/assign-helper.ts b/src/addons/mod/assign/services/assign-helper.ts index 739c93d47..680bfbdaa 100644 --- a/src/addons/mod/assign/services/assign-helper.ts +++ b/src/addons/mod/assign/services/assign-helper.ts @@ -406,7 +406,7 @@ export class AddonModAssignHelperProvider { submissions.forEach((submission) => { submission.submitid = submission.userid && submission.userid > 0 ? submission.userid : submission.blindid; - if (typeof submission.submitid == 'undefined' || submission.submitid <= 0) { + if (submission.submitid === undefined || submission.submitid <= 0) { return; } diff --git a/src/addons/mod/assign/services/handlers/prefetch.ts b/src/addons/mod/assign/services/handlers/prefetch.ts index 1f7d6e533..bd504ca3b 100644 --- a/src/addons/mod/assign/services/handlers/prefetch.ts +++ b/src/addons/mod/assign/services/handlers/prefetch.ts @@ -28,7 +28,6 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/ import { CoreCourse, CoreCourseAnyModuleData, CoreCourseCommonModWSOptions } from '@features/course/services/course'; import { CoreWSFile } from '@services/ws'; import { AddonModAssignHelper, AddonModAssignSubmissionFormatted } from '../assign-helper'; -import { CoreCourseHelper } from '@features/course/services/course-helper'; import { CoreUtils } from '@services/utils/utils'; import { CoreFilepool } from '@services/filepool'; import { CoreGroups } from '@services/groups'; @@ -243,7 +242,7 @@ export class AddonModAssignPrefetchHandlerService extends CoreCourseActivityPref promises.push(this.prefetchSubmissions(assign, courseId, module.id, userId, siteId)); - promises.push(CoreCourseHelper.getModuleCourseIdByInstance(assign.id, 'assign', siteId)); + promises.push(CoreCourse.getModuleBasicInfoByInstance(assign.id, 'assign', { siteId })); // Get course data, needed to determine upload max size if it's configured to be course limit. promises.push(CoreUtils.ignoreErrors(CoreCourses.getCourseByField('id', courseId, siteId))); @@ -254,7 +253,6 @@ export class AddonModAssignPrefetchHandlerService extends CoreCourseActivityPref promises.push(CoreFilepool.addFilesToQueue(siteId, files, this.component, module.id)); await Promise.all(promises); - } /** @@ -515,7 +513,7 @@ export class AddonModAssignPrefetchHandlerService extends CoreCourseActivityPref * @return Promise resolved when done. */ sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { - return AddonModAssignSync.syncAssign(module.instance!, siteId); + return AddonModAssignSync.syncAssign(module.instance, siteId); } } diff --git a/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts b/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts index 85956b4ed..3cab8b60f 100644 --- a/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts +++ b/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts @@ -15,7 +15,7 @@ import { CoreConstants } from '@/core/constants'; import { Injectable, Type } from '@angular/core'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { CoreSitePluginsModuleHandler } from '@features/siteplugins/classes/handlers/module-handler'; import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; @@ -72,7 +72,7 @@ export class AddonModBBBModuleHandlerService extends CoreModuleHandlerBase imple * @inheritdoc */ async getData( - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, sectionId?: number, forCoursePage?: boolean, diff --git a/src/addons/mod/book/services/book.ts b/src/addons/mod/book/services/book.ts index 9cd689d84..1efa28d21 100644 --- a/src/addons/mod/book/services/book.ts +++ b/src/addons/mod/book/services/book.ts @@ -223,7 +223,7 @@ export class AddonModBookProvider { * @return The toc. */ getToc(contents: CoreCourseModuleContentFile[]): AddonModBookTocChapterParsed[] { - if (!contents || !contents.length || typeof contents[0].content == 'undefined') { + if (!contents || !contents.length || contents[0].content === undefined) { return []; } diff --git a/src/addons/mod/book/services/handlers/prefetch.ts b/src/addons/mod/book/services/handlers/prefetch.ts index 75dff4a32..c4c127821 100644 --- a/src/addons/mod/book/services/handlers/prefetch.ts +++ b/src/addons/mod/book/services/handlers/prefetch.ts @@ -14,7 +14,8 @@ import { Injectable } from '@angular/core'; import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler'; -import { CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course'; +import { CoreCourseAnyModuleData } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreUtils } from '@services/utils/utils'; import { CoreWSFile } from '@services/ws'; import { makeSingleton } from '@singletons'; @@ -39,7 +40,7 @@ export class AddonModBookPrefetchHandlerService extends CoreCourseResourcePrefet * @param prefetch True to prefetch, false to download right away. * @return Promise resolved when all content is downloaded. Data returned is not reliable. */ - async downloadOrPrefetch(module: CoreCourseWSModule, courseId: number, prefetch?: boolean): Promise { + async downloadOrPrefetch(module: CoreCourseModuleData, courseId: number, prefetch?: boolean): Promise { const promises: Promise[] = []; promises.push(super.downloadOrPrefetch(module, courseId, prefetch)); diff --git a/src/addons/mod/book/services/handlers/tag-area.ts b/src/addons/mod/book/services/handlers/tag-area.ts index dea35c442..4430bc4d5 100644 --- a/src/addons/mod/book/services/handlers/tag-area.ts +++ b/src/addons/mod/book/services/handlers/tag-area.ts @@ -17,6 +17,7 @@ import { CoreCourse } from '@features/course/services/course'; import { CoreTagFeedComponent } from '@features/tag/components/feed/feed'; import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate'; import { CoreTagFeedElement, CoreTagHelper } from '@features/tag/services/tag-helper'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreUrlUtils } from '@services/utils/url'; import { makeSingleton } from '@singletons'; import { AddonModBook } from '../book'; @@ -49,16 +50,17 @@ export class AddonModBookTagAreaHandlerService implements CoreTagAreaHandler { const items = CoreTagHelper.parseFeedContent(content); // Find module ids of the returned books, they are needed by the link delegate. - await Promise.all(items.map((item) => { + await Promise.all(items.map(async (item) => { const params = item.url ? CoreUrlUtils.extractUrlParams(item.url) : {}; if (params.b && !params.id) { const bookId = parseInt(params.b, 10); - return CoreCourse.getModuleBasicInfoByInstance(bookId, 'book').then((module) => { - item.url += '&id=' + module.id; - - return; - }); + const module = await CoreCourse.getModuleBasicInfoByInstance( + bookId, + 'book', + { readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); + item.url += '&id=' + module.id; } })); diff --git a/src/addons/mod/choice/services/choice-sync.ts b/src/addons/mod/choice/services/choice-sync.ts index ed2537467..44f78056a 100644 --- a/src/addons/mod/choice/services/choice-sync.ts +++ b/src/addons/mod/choice/services/choice-sync.ts @@ -197,7 +197,7 @@ export class AddonModChoiceSyncProvider extends CoreCourseActivitySyncBaseProvid // Data has been sent to server, prefetch choice if needed. try { - const module = await CoreCourse.getModuleBasicInfoByInstance(choiceId, 'choice', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance(choiceId, 'choice', { siteId }); await this.prefetchAfterUpdate(AddonModChoicePrefetchHandler.instance, module, courseId, undefined, siteId); } catch { diff --git a/src/addons/mod/choice/services/handlers/prefetch.ts b/src/addons/mod/choice/services/handlers/prefetch.ts index 0aa454612..5ae104e28 100644 --- a/src/addons/mod/choice/services/handlers/prefetch.ts +++ b/src/addons/mod/choice/services/handlers/prefetch.ts @@ -147,7 +147,7 @@ export class AddonModChoicePrefetchHandlerService extends CoreCourseActivityPref * @return Promise resolved when done. */ sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { - return AddonModChoiceSync.syncChoice(module.instance!, undefined, siteId); + return AddonModChoiceSync.syncChoice(module.instance, undefined, siteId); } } diff --git a/src/addons/mod/data/components/action/action.ts b/src/addons/mod/data/components/action/action.ts index b10d9fe6a..e77896781 100644 --- a/src/addons/mod/data/components/action/action.ts +++ b/src/addons/mod/data/components/action/action.ts @@ -14,7 +14,6 @@ import { Component, OnInit, Input } from '@angular/core'; import { Params } from '@angular/router'; -import { CoreCourseModule } from '@features/course/services/course-helper'; import { CoreTag } from '@features/tag/services/tag'; import { CoreUser } from '@features/user/services/user'; import { CoreNavigator } from '@services/navigator'; @@ -44,8 +43,8 @@ export class AddonModDataActionComponent implements OnInit { @Input() action!: AddonModDataAction; // The field to render. @Input() entry!: AddonModDataEntry; // The value of the field. @Input() database!: AddonModDataData; // Database object. - @Input() module!: CoreCourseModule; // Module object. - @Input() group = 0; // Module object. + @Input() title = ''; // Name of the module. + @Input() group = 0; // Module group. @Input() offset?: number; // Offset of the entry. siteId: string; @@ -92,13 +91,13 @@ export class AddonModDataActionComponent implements OnInit { * Go to the edit page of the entry. */ editEntry(): void { - const params = { - courseId: this.database.course, - module: this.module, + const params: Params = { + title: this.title, }; + const basePath = AddonModDataModuleHandlerService.PAGE_NAME; CoreNavigator.navigateToSitePath( - `${AddonModDataModuleHandlerService.PAGE_NAME}/${this.module.course}/${this.module.id}/edit/${this.entry.id}`, + `${basePath}/${this.database.course}/${this.database.coursemodule}/edit/${this.entry.id}`, { params }, ); } @@ -108,15 +107,14 @@ export class AddonModDataActionComponent implements OnInit { */ viewEntry(): void { const params: Params = { - courseId: this.database.course, - module: this.module, - entryId: this.entry.id, + title: this.title, group: this.group, offset: this.offset, }; + const basePath = AddonModDataModuleHandlerService.PAGE_NAME; CoreNavigator.navigateToSitePath( - `${AddonModDataModuleHandlerService.PAGE_NAME}/${this.module.course}/${this.module.id}/${this.entry.id}`, + `${basePath}/${this.database.course}/${this.database.coursemodule}/${this.entry.id}`, { params }, ); } diff --git a/src/addons/mod/data/components/index/index.ts b/src/addons/mod/data/components/index/index.ts index adec614b3..3386cbd82 100644 --- a/src/addons/mod/data/components/index/index.ts +++ b/src/addons/mod/data/components/index/index.ts @@ -17,7 +17,6 @@ import { Component, OnDestroy, OnInit, Optional, Type } from '@angular/core'; import { Params } from '@angular/router'; import { CoreCommentsProvider } from '@features/comments/services/comments'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; -import { CoreCourseModule } from '@features/course/course.module'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourse } from '@features/course/services/course'; import { CoreRatingProvider } from '@features/rating/services/rating'; @@ -95,7 +94,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp fields: Record; entries: Record; database: AddonModDataData; - module: CoreCourseModule; + title: string; group: number; gotoEntry: (a: number) => void; }; @@ -191,7 +190,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp * @return True if refresh is needed, false otherwise. */ protected isRefreshSyncNeeded(syncEventData: AddonModDataAutoSyncData): boolean { - if (this.database && syncEventData.dataId == this.database.id && typeof syncEventData.entryId == 'undefined') { + if (this.database && syncEventData.dataId == this.database.id && syncEventData.entryId === undefined) { this.loaded = false; // Refresh the data. this.content?.scrollToTop(); @@ -309,7 +308,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp this.entriesRendered = ''; - this.foundRecordsTranslationData = typeof entries.maxcount != 'undefined' + this.foundRecordsTranslationData = entries.maxcount !== undefined ? { num: entries.totalcount, max: entries.maxcount, @@ -371,7 +370,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp fields: this.fields, entries: entriesById, database: this.database!, - module: this.module, + title: this.module.name, group: this.selectedGroup, gotoEntry: this.gotoEntry.bind(this), }; @@ -474,8 +473,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp */ gotoAddEntries(): void { const params: Params = { - module: this.module, - courseId: this.courseId, + title: this.module.name, group: this.selectedGroup, }; @@ -492,8 +490,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp */ gotoEntry(entryId: number): void { const params: Params = { - module: this.module, - courseId: this.courseId, + title: this.module.name, group: this.selectedGroup, }; diff --git a/src/addons/mod/data/components/search/search.ts b/src/addons/mod/data/components/search/search.ts index 4221b769a..42fbd7e54 100644 --- a/src/addons/mod/data/components/search/search.ts +++ b/src/addons/mod/data/components/search/search.ts @@ -69,7 +69,7 @@ export class AddonModDataSearchComponent implements OnInit { ngOnInit(): void { this.advancedIndexed = {}; this.search.advanced?.forEach((field) => { - if (typeof field != 'undefined') { + if (field !== undefined) { this.advancedIndexed[field.name] = field.value ? CoreTextUtils.parseJSON(field.value, '') : ''; diff --git a/src/addons/mod/data/fields/latlong/component/latlong.ts b/src/addons/mod/data/fields/latlong/component/latlong.ts index a638544e4..87f1634d7 100644 --- a/src/addons/mod/data/fields/latlong/component/latlong.ts +++ b/src/addons/mod/data/fields/latlong/component/latlong.ts @@ -48,7 +48,7 @@ export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginCo * @return Readable Latitude and logitude. */ formatLatLong(north?: number, east?: number): string { - if (typeof north !== 'undefined' || typeof east !== 'undefined') { + if (north !== undefined || east !== undefined) { north = north || 0; east = east || 0; const northFixed = Math.abs(north).toFixed(4); @@ -69,7 +69,7 @@ export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginCo */ getLatLongLink(north?: number, east?: number): SafeUrl { let url = ''; - if (typeof north !== 'undefined' || typeof east !== 'undefined') { + if (north !== undefined || east !== undefined) { const northFixed = north ? north.toFixed(4) : '0.0000'; const eastFixed = east ? east.toFixed(4) : '0.0000'; diff --git a/src/addons/mod/data/fields/latlong/services/handler.ts b/src/addons/mod/data/fields/latlong/services/handler.ts index 4eed24cc1..03ab0a829 100644 --- a/src/addons/mod/data/fields/latlong/services/handler.ts +++ b/src/addons/mod/data/fields/latlong/services/handler.ts @@ -104,7 +104,7 @@ export class AddonModDataFieldLatlongHandlerService implements AddonModDataField // The lat long class has two values that need to be checked. inputData.forEach((value) => { - if (typeof value.value != 'undefined' && value.value != '') { + if (value.value !== undefined && value.value != '') { valueCount++; } }); diff --git a/src/addons/mod/data/fields/picture/services/handler.ts b/src/addons/mod/data/fields/picture/services/handler.ts index d0b503c13..d6e4dd4a5 100644 --- a/src/addons/mod/data/fields/picture/services/handler.ts +++ b/src/addons/mod/data/fields/picture/services/handler.ts @@ -135,7 +135,7 @@ export class AddonModDataFieldPictureHandlerService implements AddonModDataField } const found = inputData.some((input) => { - if (typeof input.subfield != 'undefined' && input.subfield == 'file') { + if (input.subfield !== undefined && input.subfield == 'file') { return !!input.value; } diff --git a/src/addons/mod/data/pages/edit/edit.html b/src/addons/mod/data/pages/edit/edit.html index 6ace095f7..0ee3b6e22 100644 --- a/src/addons/mod/data/pages/edit/edit.html +++ b/src/addons/mod/data/pages/edit/edit.html @@ -5,7 +5,7 @@

- +

diff --git a/src/addons/mod/data/pages/edit/edit.ts b/src/addons/mod/data/pages/edit/edit.ts index 5af31f6ed..dc307eaa2 100644 --- a/src/addons/mod/data/pages/edit/edit.ts +++ b/src/addons/mod/data/pages/edit/edit.ts @@ -15,7 +15,6 @@ import { Component, OnInit, ViewChild, ElementRef, Type } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { CoreError } from '@classes/errors/error'; -import { CoreCourseModule } from '@features/course/services/course-helper'; import { CoreFileUploader } from '@features/fileuploader/services/fileuploader'; import { CoreTag } from '@features/tag/services/tag'; import { IonContent } from '@ionic/angular'; @@ -66,7 +65,7 @@ export class AddonModDataEditPage implements OnInit { entry?: AddonModDataEntry; fields: Record = {}; courseId!: number; - module!: CoreCourseModule; + moduleId = 0; database?: AddonModDataData; title = ''; component = AddonModDataProvider.COMPONENT; @@ -97,9 +96,10 @@ export class AddonModDataEditPage implements OnInit { */ ngOnInit(): void { try { - this.module = CoreNavigator.getRequiredRouteParam('module'); - this.entryId = CoreNavigator.getRouteNumberParam('entryId') || undefined; + this.moduleId = CoreNavigator.getRequiredRouteNumberParam('cmId'); this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId'); + this.title = CoreNavigator.getRouteParam('title') || ''; + this.entryId = CoreNavigator.getRouteNumberParam('entryId') || undefined; this.selectedGroup = CoreNavigator.getRouteNumberParam('group') || 0; } catch (error) { CoreDomUtils.showErrorModal(error); @@ -110,9 +110,7 @@ export class AddonModDataEditPage implements OnInit { } // If entryId is lower than 0 or null, it is a new entry or an offline entry. - this.isEditing = typeof this.entryId != 'undefined' && this.entryId > 0; - - this.title = this.module.name; + this.isEditing = this.entryId !== undefined && this.entryId > 0; this.fetchEntryData(true); } @@ -134,7 +132,7 @@ export class AddonModDataEditPage implements OnInit { if (changed) { // Show confirmation if some data has been modified. - await CoreDomUtils.showConfirm(Translate.instant('coentryre.confirmcanceledit')); + await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit')); } // Delete the local files from the tmp folder. @@ -154,11 +152,11 @@ export class AddonModDataEditPage implements OnInit { */ protected async fetchEntryData(refresh = false): Promise { try { - this.database = await AddonModData.getDatabase(this.courseId, this.module.id); + this.database = await AddonModData.getDatabase(this.courseId, this.moduleId); this.title = this.database.name || this.title; this.cssClass = 'addon-data-entries-' + this.database.id; - this.fieldsArray = await AddonModData.getFields(this.database.id, { cmId: this.module.id }); + this.fieldsArray = await AddonModData.getFields(this.database.id, { cmId: this.moduleId }); this.fields = CoreUtils.arrayToObject(this.fieldsArray, 'id'); const entry = await AddonModDataHelper.fetchEntry(this.database, this.fieldsArray, this.entryId || 0); @@ -183,7 +181,7 @@ export class AddonModDataEditPage implements OnInit { await Promise.all(this.groupInfo.groups.map(async (group) => { const accessData = await AddonModData.getDatabaseAccessInformation(this.database!.id, { - cmId: this.module.id, groupId: group.id }); + cmId: this.moduleId, groupId: group.id }); canAddGroup[group.id] = accessData.canaddentry; })); @@ -196,7 +194,7 @@ export class AddonModDataEditPage implements OnInit { haveAccess = true; } } else { - const accessData = await AddonModData.getDatabaseAccessInformation(this.database.id, { cmId: this.module.id }); + const accessData = await AddonModData.getDatabaseAccessInformation(this.database.id, { cmId: this.moduleId }); haveAccess = accessData.canaddentry; } diff --git a/src/addons/mod/data/pages/entry/entry.html b/src/addons/mod/data/pages/entry/entry.html index 015b40c88..0bf31d990 100644 --- a/src/addons/mod/data/pages/entry/entry.html +++ b/src/addons/mod/data/pages/entry/entry.html @@ -5,7 +5,7 @@

- +

diff --git a/src/addons/mod/data/pages/entry/entry.ts b/src/addons/mod/data/pages/entry/entry.ts index 95e37b326..173242ed4 100644 --- a/src/addons/mod/data/pages/entry/entry.ts +++ b/src/addons/mod/data/pages/entry/entry.ts @@ -16,7 +16,6 @@ import { Component, OnDestroy, ViewChild, ChangeDetectorRef, OnInit, Type } from import { CoreCommentsCommentsComponent } from '@features/comments/components/comments/comments'; import { CoreComments } from '@features/comments/services/comments'; import { CoreCourse } from '@features/course/services/course'; -import { CoreCourseModule } from '@features/course/services/course-helper'; import { CoreRatingInfo } from '@features/rating/services/rating'; import { IonContent, IonRefresher } from '@ionic/angular'; import { CoreGroups, CoreGroupInfo } from '@services/groups'; @@ -57,7 +56,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { protected fields: Record = {}; protected fieldsArray: AddonModDataField[] = []; - module!: CoreCourseModule; + moduleId = 0; courseId!: number; offset?: number; title = ''; @@ -82,7 +81,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { fields: Record; entries: Record; database: AddonModDataData; - module: CoreCourseModule; + title: string; group: number; }; @@ -98,7 +97,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { // Refresh data if this discussion is synchronized automatically. this.syncObserver = CoreEvents.on(AddonModDataSyncProvider.AUTO_SYNCED, (data) => { - if (typeof data.entryId == 'undefined') { + if (data.entryId === undefined) { return; } @@ -133,9 +132,10 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { */ async ngOnInit(): Promise { try { - this.module = CoreNavigator.getRequiredRouteParam('module'); - this.entryId = CoreNavigator.getRouteNumberParam('entryId') || undefined; + this.moduleId = CoreNavigator.getRequiredRouteNumberParam('cmId'); this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId'); + this.entryId = CoreNavigator.getRouteNumberParam('entryId') || undefined; + this.title = CoreNavigator.getRouteParam('title') || ''; this.selectedGroup = CoreNavigator.getRouteNumberParam('group') || 0; this.offset = CoreNavigator.getRouteNumberParam('offset'); } catch (error) { @@ -146,8 +146,6 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { return; } - this.title = this.module.name; - this.commentsEnabled = !CoreComments.areCommentsDisabledInSite(); await this.fetchEntryData(); @@ -165,15 +163,15 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { this.isPullingToRefresh = isPtr; try { - this.database = await AddonModData.getDatabase(this.courseId, this.module.id); + this.database = await AddonModData.getDatabase(this.courseId, this.moduleId); this.title = this.database.name || this.title; - this.fieldsArray = await AddonModData.getFields(this.database.id, { cmId: this.module.id }); + this.fieldsArray = await AddonModData.getFields(this.database.id, { cmId: this.moduleId }); this.fields = CoreUtils.arrayToObject(this.fieldsArray, 'id'); await this.setEntryFromOffset(); - this.access = await AddonModData.getDatabaseAccessInformation(this.database.id, { cmId: this.module.id }); + this.access = await AddonModData.getDatabaseAccessInformation(this.database.id, { cmId: this.moduleId }); this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule); this.selectedGroup = CoreGroups.validateGroupId(this.selectedGroup, this.groupInfo); @@ -200,7 +198,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { fields: this.fields, entries: entries, database: this.database, - module: this.module, + title: this.title, group: this.selectedGroup, }; } catch (error) { @@ -299,7 +297,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { * @return Resolved when done. */ protected async setEntryFromOffset(): Promise { - if (typeof this.offset == 'undefined' && typeof this.entryId != 'undefined') { + if (this.offset === undefined && this.entryId !== undefined) { // Entry id passed as navigation parameter instead of the offset. // We don't display next/previous buttons in this case. this.hasNext = false; @@ -313,7 +311,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { } const perPage = AddonModDataProvider.PER_PAGE; - const page = typeof this.offset != 'undefined' && this.offset >= 0 + const page = this.offset !== undefined && this.offset >= 0 ? Math.floor(this.offset / perPage) : 0; @@ -329,7 +327,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { // Index of the entry when concatenating offline and online page entries. let pageIndex = 0; - if (typeof this.offset == 'undefined') { + if (this.offset === undefined) { // No offset passed, display the first entry. pageIndex = 0; } else if (this.offset > 0) { @@ -363,7 +361,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { if (this.entryId > 0) { // Online entry, we need to fetch the the rating info. - const entry = await AddonModData.getEntry(this.database!.id, this.entryId, { cmId: this.module.id }); + const entry = await AddonModData.getEntry(this.database!.id, this.entryId, { cmId: this.moduleId }); this.ratingInfo = entry.ratinginfo; } } diff --git a/src/addons/mod/data/services/data-helper.ts b/src/addons/mod/data/services/data-helper.ts index 869f2be38..64703aedb 100644 --- a/src/addons/mod/data/services/data-helper.ts +++ b/src/addons/mod/data/services/data-helper.ts @@ -18,7 +18,7 @@ import { CoreCourse } from '@features/course/services/course'; import { CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader'; import { CoreRatingOffline } from '@features/rating/services/rating-offline'; import { FileEntry } from '@ionic-native/file/ngx'; -import { CoreSites } from '@services/sites'; +import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreFormFields } from '@singletons/form'; import { CoreTextUtils } from '@services/utils/text'; @@ -86,7 +86,7 @@ export class AddonModDataHelperProvider { record.groupid = action.groupid; action.fields.forEach((offlineContent) => { - if (typeof offlineContents[offlineContent.fieldid] == 'undefined') { + if (offlineContents[offlineContent.fieldid] === undefined) { offlineContents[offlineContent.fieldid] = {}; } @@ -230,7 +230,7 @@ export class AddonModDataHelperProvider { render = Translate.instant('addon.mod_data.' + (entry.approved ? 'approved' : 'notapproved')); } else { render = ''; + '" [database]="database" [title]="title" [offset]="' + offset + '" [group]="group" >'; } template = template.replace(replaceRegex, render); } else { @@ -270,7 +270,7 @@ export class AddonModDataHelperProvider { result.hasOfflineActions = !!actions.length; actions.forEach((action) => { - if (typeof offlineActions[action.entryid] == 'undefined') { + if (offlineActions[action.entryid] === undefined) { offlineActions[action.entryid] = []; } offlineActions[action.entryid].push(action); @@ -437,7 +437,11 @@ export class AddonModDataHelperProvider { return courseId; } - const module = await CoreCourse.getModuleBasicInfoByInstance(dataId, 'data', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance( + dataId, + 'data', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); return module.course; } diff --git a/src/addons/mod/data/services/data-offline.ts b/src/addons/mod/data/services/data-offline.ts index 19d8638fe..67fdb5b78 100644 --- a/src/addons/mod/data/services/data-offline.ts +++ b/src/addons/mod/data/services/data-offline.ts @@ -262,7 +262,7 @@ export class AddonModDataOfflineProvider { const site = await CoreSites.getSite(siteId); timemodified = timemodified || new Date().getTime(); - entryId = typeof entryId == 'undefined' || entryId === null ? -timemodified : entryId; + entryId = entryId === undefined || entryId === null ? -timemodified : entryId; const entry: AddonModDataEntryDBRecord = { dataid: dataId, diff --git a/src/addons/mod/data/services/data-sync.ts b/src/addons/mod/data/services/data-sync.ts index 9a947ffcb..1549bf5f9 100644 --- a/src/addons/mod/data/services/data-sync.ts +++ b/src/addons/mod/data/services/data-sync.ts @@ -197,7 +197,7 @@ export class AddonModDataSyncProvider extends CoreCourseActivitySyncBaseProvider const offlineEntries: Record = {}; offlineActions.forEach((entry) => { - if (typeof offlineEntries[entry.entryid] == 'undefined') { + if (offlineEntries[entry.entryid] === undefined) { offlineEntries[entry.entryid] = []; } diff --git a/src/addons/mod/data/services/data.ts b/src/addons/mod/data/services/data.ts index 4dd6ce8e8..8c7e4e993 100644 --- a/src/addons/mod/data/services/data.ts +++ b/src/addons/mod/data/services/data.ts @@ -188,7 +188,7 @@ export class AddonModDataProvider { data, }; - if (typeof groupId !== 'undefined') { + if (groupId !== undefined) { params.groupid = groupId; } @@ -1004,16 +1004,16 @@ export class AddonModDataProvider { componentId: options.cmId, ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. }; - if (typeof options.sort != 'undefined') { + if (options.sort !== undefined) { params.sort = options.sort; } - if (typeof options.order !== 'undefined') { + if (options.order !== undefined) { params.order = options.order; } - if (typeof options.search !== 'undefined') { + if (options.search !== undefined) { params.search = options.search; } - if (typeof options.advSearch !== 'undefined') { + if (options.advSearch !== undefined) { params.advsearch = options.advSearch; } const response = await site.read('mod_data_search_entries', params, preSets); diff --git a/src/addons/mod/data/services/handlers/approve-link.ts b/src/addons/mod/data/services/handlers/approve-link.ts index 5d3072634..f6802bca2 100644 --- a/src/addons/mod/data/services/handlers/approve-link.ts +++ b/src/addons/mod/data/services/handlers/approve-link.ts @@ -50,7 +50,7 @@ export class AddonModDataApproveLinkHandlerService extends CoreContentLinksHandl * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Params): Promise { - if (typeof params.d == 'undefined' || (typeof params.approve == 'undefined' && typeof params.disapprove == 'undefined')) { + if (params.d === undefined || (params.approve === undefined && params.disapprove === undefined)) { // Required fields not defined. Cannot treat the URL. return false; } diff --git a/src/addons/mod/data/services/handlers/delete-link.ts b/src/addons/mod/data/services/handlers/delete-link.ts index e17e662b6..71b0d8125 100644 --- a/src/addons/mod/data/services/handlers/delete-link.ts +++ b/src/addons/mod/data/services/handlers/delete-link.ts @@ -48,7 +48,7 @@ export class AddonModDataDeleteLinkHandlerService extends CoreContentLinksHandle * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Params): Promise { - if (typeof params.d == 'undefined' || typeof params.delete == 'undefined') { + if (params.d === undefined || params.delete === undefined) { // Required fields not defined. Cannot treat the URL. return false; } diff --git a/src/addons/mod/data/services/handlers/edit-link.ts b/src/addons/mod/data/services/handlers/edit-link.ts index e759b20e2..bcabe86bd 100644 --- a/src/addons/mod/data/services/handlers/edit-link.ts +++ b/src/addons/mod/data/services/handlers/edit-link.ts @@ -18,6 +18,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModDataModuleHandlerService } from './module'; @@ -44,10 +45,13 @@ export class AddonModDataEditLinkHandlerService extends CoreContentLinksHandlerB const rId = params.rid || ''; try { - const module = await CoreCourse.getModuleBasicInfoByInstance(dataId, 'data', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance( + dataId, + 'data', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); const pageParams: Params = { - module, - courseId: module.course, + title: module.name, }; CoreNavigator.navigateToSitePath( @@ -66,7 +70,7 @@ export class AddonModDataEditLinkHandlerService extends CoreContentLinksHandlerB * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Params): Promise { - if (typeof params.d == 'undefined') { + if (params.d === undefined) { // Id not defined. Cannot treat the URL. return false; } diff --git a/src/addons/mod/data/services/handlers/prefetch.ts b/src/addons/mod/data/services/handlers/prefetch.ts index 4a7bf6b38..717b69b07 100644 --- a/src/addons/mod/data/services/handlers/prefetch.ts +++ b/src/addons/mod/data/services/handlers/prefetch.ts @@ -173,7 +173,7 @@ export class AddonModDataPrefetchHandlerService extends CoreCourseActivityPrefet async invalidateModule(module: CoreCourseAnyModuleData, courseId: number): Promise { const promises: Promise[] = []; promises.push(AddonModData.invalidateDatabaseData(courseId)); - promises.push(AddonModData.invalidateDatabaseAccessInformationData(module.instance!)); + promises.push(AddonModData.invalidateDatabaseAccessInformationData(module.instance)); await Promise.all(promises); } @@ -261,7 +261,7 @@ export class AddonModDataPrefetchHandlerService extends CoreCourseActivityPrefet }); // Add Basic Info to manage links. - promises.push(CoreCourse.getModuleBasicInfoByInstance(database.id, 'data', siteId)); + promises.push(CoreCourse.getModuleBasicInfoByInstance(database.id, 'data', { siteId })); // Get course data, needed to determine upload max size if it's configured to be course limit. promises.push(CoreUtils.ignoreErrors(CoreCourses.getCourseByField('id', courseId, siteId))); @@ -279,7 +279,7 @@ export class AddonModDataPrefetchHandlerService extends CoreCourseActivityPrefet */ async sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { const promises = [ - AddonModDataSync.syncDatabase(module.instance!, siteId), + AddonModDataSync.syncDatabase(module.instance, siteId), AddonModDataSync.syncRatings(module.id, true, siteId), ]; diff --git a/src/addons/mod/data/services/handlers/show-link.ts b/src/addons/mod/data/services/handlers/show-link.ts index f1279506a..f30535768 100644 --- a/src/addons/mod/data/services/handlers/show-link.ts +++ b/src/addons/mod/data/services/handlers/show-link.ts @@ -18,6 +18,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModDataModuleHandlerService } from './module'; @@ -47,10 +48,13 @@ export class AddonModDataShowLinkHandlerService extends CoreContentLinksHandlerB const page = parseInt(params.page, 10) || false; try { - const module = await CoreCourse.getModuleBasicInfoByInstance(dataId, 'data', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance( + dataId, + 'data', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); const pageParams: Params = { - module: module, - courseId: module.course, + title: module.name, }; if (group) { @@ -77,12 +81,12 @@ export class AddonModDataShowLinkHandlerService extends CoreContentLinksHandlerB * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Params): Promise { - if (typeof params.d == 'undefined') { + if (params.d === undefined) { // Id not defined. Cannot treat the URL. return false; } - if ((!params.mode || params.mode != 'single') && typeof params.rid == 'undefined') { + if ((!params.mode || params.mode != 'single') && params.rid === undefined) { return false; } diff --git a/src/addons/mod/feedback/components/index/index.ts b/src/addons/mod/feedback/components/index/index.ts index 3e77a7941..bfa04b763 100644 --- a/src/addons/mod/feedback/components/index/index.ts +++ b/src/addons/mod/feedback/components/index/index.ts @@ -299,7 +299,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity item.data = item.data.map((dataItem) => { const parsed = > CoreTextUtils.parseJSON(dataItem); - return typeof parsed.show != 'undefined' ? parsed.show : false; + return parsed.show !== undefined ? parsed.show : false; }).filter((dataItem) => dataItem); // Filter false entries. case 'textfield': @@ -312,7 +312,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity const parsedData = []> item.data.map((dataItem) => { const parsed = > CoreTextUtils.parseJSON(dataItem); - return typeof parsed.answertext != 'undefined' ? parsed : false; + return parsed.answertext !== undefined ? parsed : false; }).filter((dataItem) => dataItem); // Filter false entries. // Format labels. @@ -320,7 +320,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity dataItem.quotient = ( dataItem.quotient * 100).toFixed(2); let label = ''; - if (typeof dataItem.value != 'undefined') { + if (dataItem.value !== undefined) { label = '(' + dataItem.value + ') '; } label += dataItem.answertext; diff --git a/src/addons/mod/feedback/pages/form/form.ts b/src/addons/mod/feedback/pages/form/form.ts index 1a11ebb21..5807d7e3e 100644 --- a/src/addons/mod/feedback/pages/form/form.ts +++ b/src/addons/mod/feedback/pages/form/form.ts @@ -15,8 +15,8 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { CoreSite } from '@classes/site'; import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; -import { CoreCourse, CoreCourseCommonModWSOptions, CoreCourseWSModule } from '@features/course/services/course'; -import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { CoreCourse, CoreCourseCommonModWSOptions } from '@features/course/services/course'; +import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; import { CanLeave } from '@guards/can-leave'; import { IonContent } from '@ionic/angular'; import { CoreApp } from '@services/app'; @@ -51,7 +51,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { @ViewChild(IonContent) content?: IonContent; - protected module?: CoreCourseWSModule; + protected module?: CoreCourseModuleData; protected currentPage?: number; protected siteAfterSubmit?: string; protected onlineObserver: Subscription; diff --git a/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts b/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts index 12d312bc0..db568a32a 100644 --- a/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts +++ b/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts @@ -100,7 +100,7 @@ export class AddonModFeedbackNonRespondentsPage implements OnInit { protected async loadGroupUsers(groupId?: number): Promise { this.loadMoreError = false; - if (typeof groupId == 'undefined') { + if (groupId === undefined) { this.page++; } else { this.selectedGroup = groupId; diff --git a/src/addons/mod/feedback/pages/respondents/respondents.ts b/src/addons/mod/feedback/pages/respondents/respondents.ts index 3ef2266a7..73a95a75f 100644 --- a/src/addons/mod/feedback/pages/respondents/respondents.ts +++ b/src/addons/mod/feedback/pages/respondents/respondents.ts @@ -115,7 +115,7 @@ export class AddonModFeedbackRespondentsPage implements AfterViewInit { * @return Resolved with the attempts loaded. */ protected async loadGroupAttempts(groupId?: number): Promise { - if (typeof groupId == 'undefined') { + if (groupId === undefined) { this.page++; this.loadingMore = true; } else { diff --git a/src/addons/mod/feedback/services/feedback-helper.ts b/src/addons/mod/feedback/services/feedback-helper.ts index 05751c7f5..3c1a89ce9 100644 --- a/src/addons/mod/feedback/services/feedback-helper.ts +++ b/src/addons/mod/feedback/services/feedback-helper.ts @@ -176,9 +176,12 @@ export class AddonModFeedbackHelperProvider { const modal = await CoreDomUtils.showModalLoading(); try { - const module = await CoreCourse.getModuleBasicInfo(Number(params.id), siteId); + const module = await CoreCourse.getModuleBasicInfo( + Number(params.id), + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); - if (typeof params.showcompleted == 'undefined') { + if (params.showcompleted === undefined) { // Param showcompleted not defined. Show entry list. await CoreNavigator.navigateToSitePath( AddonModFeedbackModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/respondents`, @@ -269,7 +272,7 @@ export class AddonModFeedbackHelperProvider { if (type == MODE_COURSE || type == MODE_CATEGORY) { formItem.presentation = formItem.otherdata; - formItem.value = typeof formItem.rawValue != 'undefined' ? formItem.rawValue : formItem.otherdata; + formItem.value = formItem.rawValue !== undefined ? formItem.rawValue : formItem.otherdata; } else if (type == MODE_RESPONSETIME) { formItem.value = '__CURRENT__TIMESTAMP__'; @@ -298,7 +301,7 @@ export class AddonModFeedbackHelperProvider { const formItem: AddonModFeedbackNumericItem = Object.assign(item, { templateName: 'numeric', - value: typeof item.rawValue != 'undefined' ? Number(item.rawValue) : '', + value: item.rawValue !== undefined ? Number(item.rawValue) : '', rangefrom: typeof rangeFrom == 'number' && !isNaN(rangeFrom) ? range[0] : '', rangeto: typeof rangeTo == 'number' && !isNaN(rangeTo) ? rangeTo : '', hasTextInput: true, @@ -318,7 +321,7 @@ export class AddonModFeedbackHelperProvider { return Object.assign(item, { templateName: 'textfield', length: Number(item.presentation.split(AddonModFeedbackProvider.LINE_SEP)[1]) || 255, - value: typeof item.rawValue != 'undefined' ? item.rawValue : '', + value: item.rawValue !== undefined ? item.rawValue : '', hasTextInput: true, }); } @@ -332,7 +335,7 @@ export class AddonModFeedbackHelperProvider { protected getItemFormTextarea(item: AddonModFeedbackItem): AddonModFeedbackFormBasicItem { return Object.assign(item, { templateName: 'textarea', - value: typeof item.rawValue != 'undefined' ? item.rawValue : '', + value: item.rawValue !== undefined ? item.rawValue : '', hasTextInput: true, }); } @@ -373,12 +376,12 @@ export class AddonModFeedbackHelperProvider { if (formItem.subtype === 'r' && formItem.options.search(AddonModFeedbackProvider.MULTICHOICE_HIDENOSELECT) == -1) { formItem.choices.unshift({ value: 0, label: Translate.instant('addon.mod_feedback.not_selected') }); - formItem.value = typeof formItem.rawValue != 'undefined' ? Number(formItem.rawValue) : 0; + formItem.value = formItem.rawValue !== undefined ? Number(formItem.rawValue) : 0; } else if (formItem.subtype === 'd') { formItem.choices.unshift({ value: 0, label: '' }); - formItem.value = typeof formItem.rawValue != 'undefined' ? Number(formItem.rawValue) : 0; + formItem.value = formItem.rawValue !== undefined ? Number(formItem.rawValue) : 0; } else if (formItem.subtype === 'c') { - if (typeof formItem.rawValue != 'undefined') { + if (formItem.rawValue !== undefined) { formItem.rawValue = String(formItem.rawValue); const values = formItem.rawValue.split(AddonModFeedbackProvider.LINE_SEP); formItem.choices.forEach((choice) => { @@ -392,7 +395,7 @@ export class AddonModFeedbackHelperProvider { }); } } else { - formItem.value = typeof formItem.rawValue != 'undefined' ? Number(formItem.rawValue) : ''; + formItem.value = formItem.rawValue !== undefined ? Number(formItem.rawValue) : ''; } return formItem; diff --git a/src/addons/mod/feedback/services/feedback-sync.ts b/src/addons/mod/feedback/services/feedback-sync.ts index 8b6702b8a..c7042e15f 100644 --- a/src/addons/mod/feedback/services/feedback-sync.ts +++ b/src/addons/mod/feedback/services/feedback-sync.ts @@ -223,7 +223,7 @@ export class AddonModFeedbackSyncProvider extends CoreCourseActivitySyncBaseProv if (result.updated) { // Data has been sent to server, update data. try { - const module = await CoreCourse.getModuleBasicInfoByInstance(feedbackId, 'feedback', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance(feedbackId, 'feedback', { siteId }); await this.prefetchAfterUpdate(AddonModFeedbackPrefetchHandler.instance, module, courseId, undefined, siteId); } catch { diff --git a/src/addons/mod/feedback/services/feedback.ts b/src/addons/mod/feedback/services/feedback.ts index c1a254df3..814640e9f 100644 --- a/src/addons/mod/feedback/services/feedback.ts +++ b/src/addons/mod/feedback/services/feedback.ts @@ -87,7 +87,7 @@ export class AddonModFeedbackProvider { let values: AddonModFeedbackResponseValue[]; if (subtype === 'c') { - if (typeof item.rawValue == 'undefined') { + if (item.rawValue === undefined) { values = ['']; } else { item.rawValue = '' + item.rawValue; @@ -146,7 +146,7 @@ export class AddonModFeedbackProvider { }); filledItems.forEach((itemData) => { - if (itemData.hasvalue && typeof values[itemData.id] != 'undefined') { + if (itemData.hasvalue && values[itemData.id] !== undefined) { itemData.rawValue = values[itemData.id]; } }); @@ -182,7 +182,7 @@ export class AddonModFeedbackProvider { }); offlineValuesArray.forEach((value) => { - if (typeof offlineValues[value.item] == 'undefined') { + if (offlineValues[value.item] === undefined) { offlineValues[value.item] = []; } offlineValues[value.item].push(value.value); diff --git a/src/addons/mod/feedback/services/handlers/analysis-link.ts b/src/addons/mod/feedback/services/handlers/analysis-link.ts index 8081f4bee..f1b38c0dc 100644 --- a/src/addons/mod/feedback/services/handlers/analysis-link.ts +++ b/src/addons/mod/feedback/services/handlers/analysis-link.ts @@ -43,13 +43,11 @@ export class AddonModFeedbackAnalysisLinkHandlerService extends CoreContentLinks const moduleId = Number(params.id); try { - const moduleBasicInfo = await CoreCourse.getModuleBasicInfo(moduleId, siteId); - // Get the module. const module = await CoreCourse.getModule( moduleId, - moduleBasicInfo.course, - moduleBasicInfo.section, + undefined, + undefined, false, false, siteId, @@ -78,7 +76,7 @@ export class AddonModFeedbackAnalysisLinkHandlerService extends CoreContentLinks * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Record): Promise { - if (typeof params.id == 'undefined') { + if (params.id === undefined) { // Cannot treat the URL. return false; } diff --git a/src/addons/mod/feedback/services/handlers/complete-link.ts b/src/addons/mod/feedback/services/handlers/complete-link.ts index f0bc0ac94..7ae34e1a5 100644 --- a/src/addons/mod/feedback/services/handlers/complete-link.ts +++ b/src/addons/mod/feedback/services/handlers/complete-link.ts @@ -17,6 +17,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModFeedbackModuleHandlerService } from './module'; @@ -43,13 +44,16 @@ export class AddonModFeedbackCompleteLinkHandlerService extends CoreContentLinks const moduleId = Number(params.id); try { - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); CoreNavigator.navigateToSitePath( AddonModFeedbackModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/form`, { params: { - page: typeof params.gopage != 'undefined' ? Number(params.gopage) : undefined, + page: params.gopage !== undefined ? Number(params.gopage) : undefined, }, siteId, }, @@ -67,7 +71,7 @@ export class AddonModFeedbackCompleteLinkHandlerService extends CoreContentLinks * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Record): Promise { - if (typeof params.id == 'undefined') { + if (params.id === undefined) { return false; } diff --git a/src/addons/mod/feedback/services/handlers/prefetch.ts b/src/addons/mod/feedback/services/handlers/prefetch.ts index 3180321d9..b7f78b3b3 100644 --- a/src/addons/mod/feedback/services/handlers/prefetch.ts +++ b/src/addons/mod/feedback/services/handlers/prefetch.ts @@ -211,7 +211,7 @@ export class AddonModFeedbackPrefetchHandlerService extends CoreCourseActivityPr * @inheritdoc */ sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { - return AddonModFeedbackSync.syncFeedback(module.instance!, siteId); + return AddonModFeedbackSync.syncFeedback(module.instance, siteId); } } diff --git a/src/addons/mod/feedback/services/handlers/print-link.ts b/src/addons/mod/feedback/services/handlers/print-link.ts index 1a287d5ad..bb6d4d099 100644 --- a/src/addons/mod/feedback/services/handlers/print-link.ts +++ b/src/addons/mod/feedback/services/handlers/print-link.ts @@ -17,6 +17,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModFeedbackModuleHandlerService } from './module'; @@ -43,7 +44,10 @@ export class AddonModFeedbackPrintLinkHandlerService extends CoreContentLinksHan const moduleId = Number(params.id); try { - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); CoreNavigator.navigateToSitePath( AddonModFeedbackModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/form`, @@ -67,7 +71,7 @@ export class AddonModFeedbackPrintLinkHandlerService extends CoreContentLinksHan * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Record): Promise { - if (typeof params.id == 'undefined') { + if (params.id === undefined) { return false; } diff --git a/src/addons/mod/feedback/services/handlers/show-entries-link.ts b/src/addons/mod/feedback/services/handlers/show-entries-link.ts index 1d1f857d4..30f3b7c15 100644 --- a/src/addons/mod/feedback/services/handlers/show-entries-link.ts +++ b/src/addons/mod/feedback/services/handlers/show-entries-link.ts @@ -44,7 +44,7 @@ export class AddonModFeedbackShowEntriesLinkHandlerService extends CoreContentLi * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Record): Promise { - if (typeof params.id == 'undefined') { + if (params.id === undefined) { // Cannot treat the URL. return false; } diff --git a/src/addons/mod/feedback/services/handlers/show-non-respondents-link.ts b/src/addons/mod/feedback/services/handlers/show-non-respondents-link.ts index cccaadcad..ea6e054ef 100644 --- a/src/addons/mod/feedback/services/handlers/show-non-respondents-link.ts +++ b/src/addons/mod/feedback/services/handlers/show-non-respondents-link.ts @@ -17,6 +17,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModFeedbackModuleHandlerService } from './module'; @@ -42,7 +43,10 @@ export class AddonModFeedbackShowNonRespondentsLinkHandlerService extends CoreCo const moduleId = Number(params.id); try { - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); await CoreNavigator.navigateToSitePath( AddonModFeedbackModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/nonrespondents`, @@ -61,7 +65,7 @@ export class AddonModFeedbackShowNonRespondentsLinkHandlerService extends CoreCo * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Record): Promise { - if (typeof params.id == 'undefined') { + if (params.id === undefined) { // Cannot treat the URL. return false; } diff --git a/src/addons/mod/folder/components/index/index.ts b/src/addons/mod/folder/components/index/index.ts index 18f99216c..73cdb6271 100644 --- a/src/addons/mod/folder/components/index/index.ts +++ b/src/addons/mod/folder/components/index/index.ts @@ -66,7 +66,7 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo await this.loadContent(); try { - await AddonModFolder.logView(this.module.instance!, this.module.name); + await AddonModFolder.logView(this.module.instance, this.module.name); CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); } catch { // Ignore errors. @@ -96,7 +96,7 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo try { this.folderInstance = await AddonModFolder.getFolder(this.courseId, this.module.id); - const contents = await CoreCourse.getModuleContents(this.module, this.courseId, undefined, false, refresh); + const contents = await CoreCourse.getModuleContents(this.module, undefined, undefined, false, refresh); this.dataRetrieved.emit(this.folderInstance || this.module); diff --git a/src/addons/mod/folder/services/handlers/prefetch.ts b/src/addons/mod/folder/services/handlers/prefetch.ts index 5081cd5d5..33535bfb3 100644 --- a/src/addons/mod/folder/services/handlers/prefetch.ts +++ b/src/addons/mod/folder/services/handlers/prefetch.ts @@ -14,7 +14,8 @@ import { Injectable } from '@angular/core'; import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course'; +import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { makeSingleton } from '@singletons'; import { AddonModFolder, AddonModFolderProvider } from '../folder'; @@ -31,7 +32,7 @@ export class AddonModFolderPrefetchHandlerService extends CoreCourseResourcePref /** * @inheritdoc */ - async downloadOrPrefetch(module: CoreCourseWSModule, courseId: number, prefetch?: boolean): Promise { + async downloadOrPrefetch(module: CoreCourseModuleData, courseId: number, prefetch?: boolean): Promise { const promises: Promise[] = []; promises.push(super.downloadOrPrefetch(module, courseId, prefetch)); diff --git a/src/addons/mod/forum/classes/forum-discussions-source.ts b/src/addons/mod/forum/classes/forum-discussions-source.ts index 26bd22967..7ef18281f 100644 --- a/src/addons/mod/forum/classes/forum-discussions-source.ts +++ b/src/addons/mod/forum/classes/forum-discussions-source.ts @@ -128,7 +128,7 @@ export class AddonModForumDiscussionsSource extends CoreRoutedItemsManagerSource async loadForum(): Promise { this.forum = await AddonModForum.getForum(this.COURSE_ID, this.CM_ID); - if (typeof this.forum.istracked != 'undefined') { + if (this.forum.istracked !== undefined) { this.trackPosts = this.forum.istracked; } } @@ -192,7 +192,7 @@ export class AddonModForumDiscussionsSource extends CoreRoutedItemsManagerSource } // If any discussion has unread posts, the whole forum is being tracked. - if (typeof this.forum.istracked === 'undefined' && !this.trackPosts) { + if (this.forum.istracked === undefined && !this.trackPosts) { for (const discussion of discussions) { if (discussion.numunread > 0) { this.trackPosts = true; diff --git a/src/addons/mod/forum/components/index/index.ts b/src/addons/mod/forum/components/index/index.ts index 696f762da..9afeb028e 100644 --- a/src/addons/mod/forum/components/index/index.ts +++ b/src/addons/mod/forum/components/index/index.ts @@ -218,13 +218,13 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom ) as AddonModForumDiscussion; if (discussion) { - if (typeof data.locked != 'undefined') { + if (data.locked !== undefined) { discussion.locked = data.locked; } - if (typeof data.pinned != 'undefined') { + if (data.pinned !== undefined) { discussion.pinned = data.pinned; } - if (typeof data.starred != 'undefined') { + if (data.starred !== undefined) { discussion.starred = data.starred; } @@ -232,7 +232,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom } } - if (typeof data.deleted != 'undefined' && data.deleted) { + if (data.deleted !== undefined && data.deleted) { if (data.post?.parentid == 0 && CoreScreen.isTablet && !this.discussions.empty) { // Discussion deleted, clear details page. this.discussions.select(this.discussions[0]); diff --git a/src/addons/mod/forum/components/post-options-menu/post-options-menu.ts b/src/addons/mod/forum/components/post-options-menu/post-options-menu.ts index fd1662e5a..ad13a1e84 100644 --- a/src/addons/mod/forum/components/post-options-menu/post-options-menu.ts +++ b/src/addons/mod/forum/components/post-options-menu/post-options-menu.ts @@ -69,7 +69,7 @@ export class AddonModForumPostOptionsMenuComponent implements OnInit, OnDestroy return; } - if (typeof this.post.capabilities.delete == 'undefined') { + if (this.post.capabilities.delete === undefined) { if (this.forumId) { try { this.post = diff --git a/src/addons/mod/forum/pages/discussion/discussion.page.ts b/src/addons/mod/forum/pages/discussion/discussion.page.ts index 0b6428ae0..12bf5c553 100644 --- a/src/addons/mod/forum/pages/discussion/discussion.page.ts +++ b/src/addons/mod/forum/pages/discussion/discussion.page.ts @@ -254,17 +254,17 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes this.changeDiscObserver = CoreEvents.on(AddonModForumProvider.CHANGE_DISCUSSION_EVENT, data => { if (discussion && this.forumId && (this.forumId === data.forumId || data.cmId === this.cmId)) { AddonModForum.invalidateDiscussionsList(this.forumId).finally(() => { - if (typeof data.locked != 'undefined') { + if (data.locked !== undefined) { discussion.locked = data.locked; } - if (typeof data.pinned != 'undefined') { + if (data.pinned !== undefined) { discussion.pinned = data.pinned; } - if (typeof data.starred != 'undefined') { + if (data.starred !== undefined) { discussion.starred = data.starred; } - if (typeof data.deleted != 'undefined' && data.deleted) { + if (data.deleted !== undefined && data.deleted) { if (!data.post?.parentid) { this.goBack(); } else { @@ -469,7 +469,7 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes // Now try to get the forum. const forum = await this.fetchForum(); // "forum.istracked" is more reliable than "trackPosts". - if (typeof forum.istracked != 'undefined') { + if (forum.istracked !== undefined) { this.trackPosts = forum.istracked; } diff --git a/src/addons/mod/forum/services/forum-sync.ts b/src/addons/mod/forum/services/forum-sync.ts index 65925b3d7..f033e9d22 100644 --- a/src/addons/mod/forum/services/forum-sync.ts +++ b/src/addons/mod/forum/services/forum-sync.ts @@ -379,7 +379,7 @@ export class AddonModForumSyncProvider extends CoreCourseActivitySyncBaseProvide // Do not sync same discussion twice. replies.forEach((reply) => { - if (typeof promises[reply.discussionid] != 'undefined') { + if (promises[reply.discussionid] !== undefined) { return; } promises[reply.discussionid] = this.syncDiscussionReplies(reply.discussionid, userId, siteId); diff --git a/src/addons/mod/forum/services/forum.ts b/src/addons/mod/forum/services/forum.ts index 131706f96..fb1b53bbd 100644 --- a/src/addons/mod/forum/services/forum.ts +++ b/src/addons/mod/forum/services/forum.ts @@ -253,11 +253,11 @@ export class AddonModForumProvider { throw new Error('Invalid response calling mod_forum_can_add_discussion'); } - if (typeof result.canpindiscussions == 'undefined') { + if (result.canpindiscussions === undefined) { // WS doesn't support it yet, default it to false to prevent students from seeing the option. result.canpindiscussions = false; } - if (typeof result.cancreateattachment == 'undefined') { + if (result.cancreateattachment === undefined) { // WS doesn't support it yet, default it to true since usually the users will be able to create them. result.cancreateattachment = true; } @@ -816,7 +816,7 @@ export class AddonModForumProvider { discussions: [] as AddonModForumDiscussion[], error: false, }; - let numPages = typeof options.numPages == 'undefined' ? -1 : options.numPages; + let numPages = options.numPages === undefined ? -1 : options.numPages; if (!numPages) { return result; diff --git a/src/addons/mod/forum/services/handlers/module.ts b/src/addons/mod/forum/services/handlers/module.ts index 98b81258b..f4ad76e60 100644 --- a/src/addons/mod/forum/services/handlers/module.ts +++ b/src/addons/mod/forum/services/handlers/module.ts @@ -22,7 +22,7 @@ import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/ import { CoreConstants } from '@/core/constants'; import { AddonModForumIndexComponent } from '../../components/index'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; /** * Handler to support forum modules. @@ -53,7 +53,7 @@ export class AddonModForumModuleHandlerService extends CoreModuleHandlerBase imp /** * @inheritdoc */ - async getData(module: CoreCourseModule, courseId: number): Promise { + async getData(module: CoreCourseModuleData, courseId: number): Promise { const data = await super.getData(module, courseId); if ('afterlink' in module && !!module.afterlink) { diff --git a/src/addons/mod/forum/services/handlers/post-link.ts b/src/addons/mod/forum/services/handlers/post-link.ts index 7aa3042f3..4349b2aa9 100644 --- a/src/addons/mod/forum/services/handlers/post-link.ts +++ b/src/addons/mod/forum/services/handlers/post-link.ts @@ -18,6 +18,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModForumModuleHandlerService } from './module'; @@ -53,7 +54,11 @@ export class AddonModForumPostLinkHandlerService extends CoreContentLinksHandler const forumId = parseInt(params.forum, 10); try { - const module = await CoreCourse.getModuleBasicInfoByInstance(forumId, 'forum', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance( + forumId, + 'forum', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); await CoreNavigator.navigateToSitePath( `${AddonModForumModuleHandlerService.PAGE_NAME}/${module.course}/${module.id}/new/0`, @@ -78,7 +83,7 @@ export class AddonModForumPostLinkHandlerService extends CoreContentLinksHandler * @return Whether the handler is enabled for the URL and site. */ async isEnabled(siteId: string, url: string, params: Params): Promise { - return typeof params.forum != 'undefined'; + return params.forum !== undefined; } } diff --git a/src/addons/mod/forum/services/handlers/prefetch.ts b/src/addons/mod/forum/services/handlers/prefetch.ts index 41357fcf6..a460bc6e7 100644 --- a/src/addons/mod/forum/services/handlers/prefetch.ts +++ b/src/addons/mod/forum/services/handlers/prefetch.ts @@ -320,8 +320,8 @@ export class AddonModForumPrefetchHandlerService extends CoreCourseActivityPrefe ): Promise { const promises: Promise[] = []; - promises.push(AddonModForumSync.syncForumDiscussions(module.instance!, undefined, siteId)); - promises.push(AddonModForumSync.syncForumReplies(module.instance!, undefined, siteId)); + promises.push(AddonModForumSync.syncForumDiscussions(module.instance, undefined, siteId)); + promises.push(AddonModForumSync.syncForumReplies(module.instance, undefined, siteId)); promises.push(AddonModForumSync.syncRatings(module.id, undefined, true, siteId)); const results = await Promise.all(promises); diff --git a/src/addons/mod/glossary/services/glossary-helper.ts b/src/addons/mod/glossary/services/glossary-helper.ts index 1e25ddffd..ce1dcc587 100644 --- a/src/addons/mod/glossary/services/glossary-helper.ts +++ b/src/addons/mod/glossary/services/glossary-helper.ts @@ -71,7 +71,7 @@ export class AddonModGlossaryHelperProvider { files: CoreFileEntry[], original?: AddonModGlossaryNewEntryWithFiles, ): boolean { - if (!original || typeof original.concept == 'undefined') { + if (!original || original.concept === undefined) { // There is no original data. return !!(entry.definition || entry.concept || files.length > 0); } diff --git a/src/addons/mod/glossary/services/glossary.ts b/src/addons/mod/glossary/services/glossary.ts index 033adbe77..eeb8ec937 100644 --- a/src/addons/mod/glossary/services/glossary.ts +++ b/src/addons/mod/glossary/services/glossary.ts @@ -583,7 +583,7 @@ export class AddonModGlossaryProvider { try { const data = await this.getStoredDataForEntry(entryId, site.getId()); - if (typeof data.from != 'undefined') { + if (data.from !== undefined) { const response = await CoreUtils.ignoreErrors( this.getEntryFromList(data.glossaryId, entryId, data.from, false, options), ); diff --git a/src/addons/mod/glossary/services/handlers/edit-link.ts b/src/addons/mod/glossary/services/handlers/edit-link.ts index f72ea2667..8859a6d72 100644 --- a/src/addons/mod/glossary/services/handlers/edit-link.ts +++ b/src/addons/mod/glossary/services/handlers/edit-link.ts @@ -17,6 +17,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModGlossaryModuleHandlerService } from './module'; @@ -44,7 +45,10 @@ export class AddonModGlossaryEditLinkHandlerService extends CoreContentLinksHand const cmId = Number(params.cmid); try { - const module = await CoreCourse.getModuleBasicInfo(cmId, siteId); + const module = await CoreCourse.getModuleBasicInfo( + cmId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); await CoreNavigator.navigateToSitePath( AddonModGlossaryModuleHandlerService.PAGE_NAME + '/edit/0', @@ -70,7 +74,7 @@ export class AddonModGlossaryEditLinkHandlerService extends CoreContentLinksHand * @inheritdoc */ async isEnabled(siteId: string, url: string, params: Record): Promise { - return typeof params.cmid != 'undefined'; + return params.cmid !== undefined; } } diff --git a/src/addons/mod/glossary/services/handlers/entry-link.ts b/src/addons/mod/glossary/services/handlers/entry-link.ts index 9bf86e895..d58a0bac3 100644 --- a/src/addons/mod/glossary/services/handlers/entry-link.ts +++ b/src/addons/mod/glossary/services/handlers/entry-link.ts @@ -17,6 +17,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModGlossary } from '../glossary'; @@ -43,12 +44,15 @@ export class AddonModGlossaryEntryLinkHandlerService extends CoreContentLinksHan try { const entryId = params.mode == 'entry' ? Number(params.hook) : Number(params.eid); - const response = await AddonModGlossary.getEntry(entryId, { siteId }); + const response = await AddonModGlossary.getEntry( + entryId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); const module = await CoreCourse.getModuleBasicInfoByInstance( response.entry.glossaryid, 'glossary', - siteId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, ); await CoreNavigator.navigateToSitePath( diff --git a/src/addons/mod/glossary/services/handlers/prefetch.ts b/src/addons/mod/glossary/services/handlers/prefetch.ts index 58420e244..9945e4872 100644 --- a/src/addons/mod/glossary/services/handlers/prefetch.ts +++ b/src/addons/mod/glossary/services/handlers/prefetch.ts @@ -205,8 +205,8 @@ export class AddonModGlossaryPrefetchHandlerService extends CoreCourseActivityPr promises.push(AddonModGlossary.getAllCategories(glossary.id, options)); // Prefetch data for link handlers. - promises.push(CoreCourse.getModuleBasicInfo(module.id, siteId)); - promises.push(CoreCourse.getModuleBasicInfoByInstance(glossary.id, 'glossary', siteId)); + promises.push(CoreCourse.getModuleBasicInfo(module.id, { siteId })); + promises.push(CoreCourse.getModuleBasicInfoByInstance(glossary.id, 'glossary', { siteId })); // Get course data, needed to determine upload max size if it's configured to be course limit. promises.push(CoreUtils.ignoreErrors(CoreCourses.getCourseByField('id', courseId, siteId))); @@ -219,7 +219,7 @@ export class AddonModGlossaryPrefetchHandlerService extends CoreCourseActivityPr */ async sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { const results = await Promise.all([ - AddonModGlossarySync.syncGlossaryEntries(module.instance!, undefined, siteId), + AddonModGlossarySync.syncGlossaryEntries(module.instance, undefined, siteId), AddonModGlossarySync.syncRatings(module.id, undefined, siteId), ]); diff --git a/src/addons/mod/h5pactivity/services/handlers/report-link.ts b/src/addons/mod/h5pactivity/services/handlers/report-link.ts index ee6b8c9ab..f2f37c19c 100644 --- a/src/addons/mod/h5pactivity/services/handlers/report-link.ts +++ b/src/addons/mod/h5pactivity/services/handlers/report-link.ts @@ -18,7 +18,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; -import { CoreSites } from '@services/sites'; +import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModH5PActivity } from '../h5pactivity'; @@ -41,54 +41,36 @@ export class AddonModH5PActivityReportLinkHandlerService extends CoreContentLink siteIds: string[], url: string, params: Record, - courseId?: number, ): CoreContentLinksAction[] | Promise { - courseId = courseId || Number(params.courseid) || Number(params.cid); - return [{ action: async (siteId) => { + const modal = await CoreDomUtils.showModalLoading(); + try { const instanceId = Number(params.a); - if (!courseId) { - courseId = await this.getCourseId(instanceId, siteId); - } + const module = await CoreCourse.getModuleBasicInfoByInstance( + instanceId, + 'h5pactivity', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); - const module = await CoreCourse.getModuleBasicInfoByInstance(instanceId, 'h5pactivity', siteId); - - if (typeof params.attemptid != 'undefined') { - this.openAttemptResults(module.id, Number(params.attemptid), courseId, siteId); + if (params.attemptid !== undefined) { + this.openAttemptResults(module.id, Number(params.attemptid), module.course, siteId); } else { const userId = params.userid ? Number(params.userid) : undefined; - this.openUserAttempts(module.id, courseId, siteId, userId); + this.openUserAttempts(module.id, module.course, siteId, userId); } } catch (error) { CoreDomUtils.showErrorModalDefault(error, 'Error processing link.'); + } finally { + modal.dismiss(); } }, }]; } - /** - * Get course Id for an activity. - * - * @param id Activity ID. - * @param siteId Site ID. - * @return Promise resolved with course ID. - */ - protected async getCourseId(id: number, siteId: string): Promise { - const modal = await CoreDomUtils.showModalLoading(); - - try { - const module = await CoreCourse.getModuleBasicInfoByInstance(id, 'h5pactivity', siteId); - - return module.course; - } finally { - modal.dismiss(); - } - } - /** * @inheritdoc */ diff --git a/src/addons/mod/imscp/components/index/index.ts b/src/addons/mod/imscp/components/index/index.ts index 502478fab..0b6ae75a5 100644 --- a/src/addons/mod/imscp/components/index/index.ts +++ b/src/addons/mod/imscp/components/index/index.ts @@ -53,7 +53,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom await this.loadContent(); try { - await AddonModImscp.logView(this.module.instance!, this.module.name); + await AddonModImscp.logView(this.module.instance, this.module.name); CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); } catch { // Ignore errors. @@ -84,7 +84,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom this.dataRetrieved.emit(imscp); // Get contents. No need to refresh, it has been done in downloadResourceIfNeeded. - const contents = await CoreCourse.getModuleContents(this.module, this.courseId); + const contents = await CoreCourse.getModuleContents(this.module); this.items = AddonModImscp.createItemList(contents); diff --git a/src/addons/mod/imscp/services/handlers/prefetch.ts b/src/addons/mod/imscp/services/handlers/prefetch.ts index 4f8aca282..667603fed 100644 --- a/src/addons/mod/imscp/services/handlers/prefetch.ts +++ b/src/addons/mod/imscp/services/handlers/prefetch.ts @@ -18,8 +18,8 @@ import { CoreCourse, CoreCourseAnyModuleData, CoreCourseModuleContentFile, - CoreCourseWSModule, } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreFilepool } from '@services/filepool'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; @@ -40,7 +40,7 @@ export class AddonModImscpPrefetchHandlerService extends CoreCourseResourcePrefe /** * @inheritdoc */ - async downloadOrPrefetch(module: CoreCourseWSModule, courseId: number, prefetch?: boolean): Promise { + async downloadOrPrefetch(module: CoreCourseModuleData, courseId: number, prefetch?: boolean): Promise { const siteId = CoreSites.getCurrentSiteId(); const dirPath = await CoreFilepool.getPackageDirPathByUrl(siteId, module.url!); diff --git a/src/addons/mod/imscp/services/imscp.ts b/src/addons/mod/imscp/services/imscp.ts index 3783cf37d..88cae637e 100644 --- a/src/addons/mod/imscp/services/imscp.ts +++ b/src/addons/mod/imscp/services/imscp.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { CoreCourse, CoreCourseModuleContentFile } from '@features/course/services/course'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreApp } from '@services/app'; import { CoreFilepool } from '@services/filepool'; @@ -171,7 +171,7 @@ export class AddonModImscpProvider { * @param itemHref Href of item to get. If not defined, gets src of main item. * @return Promise resolved with the item src. */ - async getIframeSrc(module: CoreCourseModule, itemHref?: string): Promise { + async getIframeSrc(module: CoreCourseModuleData, itemHref?: string): Promise { const contents = await CoreCourse.getModuleContents(module); if (!itemHref) { diff --git a/src/addons/mod/label/services/handlers/module.ts b/src/addons/mod/label/services/handlers/module.ts index 495e9cd51..f7cc33d6a 100644 --- a/src/addons/mod/label/services/handlers/module.ts +++ b/src/addons/mod/label/services/handlers/module.ts @@ -15,7 +15,7 @@ import { CoreConstants } from '@/core/constants'; import { Injectable } from '@angular/core'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { makeSingleton } from '@singletons'; @@ -45,7 +45,7 @@ export class AddonModLabelModuleHandlerService extends CoreModuleHandlerBase imp /** * @inheritdoc */ - async getData(module: CoreCourseModule): Promise { + async getData(module: CoreCourseModuleData): Promise { // Remove the description from the module so it isn't rendered twice. const title = module.description || ''; module.description = ''; diff --git a/src/addons/mod/lesson/services/handlers/grade-link.ts b/src/addons/mod/lesson/services/handlers/grade-link.ts index 3bc46f80b..bc16a1ef5 100644 --- a/src/addons/mod/lesson/services/handlers/grade-link.ts +++ b/src/addons/mod/lesson/services/handlers/grade-link.ts @@ -18,6 +18,7 @@ import { CoreContentLinksModuleGradeHandler } from '@features/contentlinks/class import { CoreCourse } from '@features/course/services/course'; import { CoreCourseHelper } from '@features/course/services/course-helper'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModLesson } from '../lesson'; @@ -57,8 +58,10 @@ export class AddonModLessonGradeLinkHandlerService extends CoreContentLinksModul const modal = await CoreDomUtils.showModalLoading(); try { - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); - courseId = Number(module.course || courseId || params.courseid || params.cid); + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); // Check if the user can see the user reports in the lesson. const accessInfo = await AddonModLesson.getAccessInformation(module.instance, { cmId: module.id, siteId }); @@ -66,14 +69,14 @@ export class AddonModLessonGradeLinkHandlerService extends CoreContentLinksModul if (accessInfo.canviewreports) { // User can view reports, go to view the report. CoreNavigator.navigateToSitePath( - AddonModLessonModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/user-retake/${userId}`, + AddonModLessonModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/user-retake/${userId}`, { siteId, }, ); } else { // User cannot view the report, go to lesson index. - CoreCourseHelper.navigateToModule(moduleId, siteId, courseId, module.section); + CoreCourseHelper.navigateToModule(moduleId, siteId, module.course, module.section); } } catch (error) { CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true); diff --git a/src/addons/mod/lesson/services/handlers/index-link.ts b/src/addons/mod/lesson/services/handlers/index-link.ts index 98b647e8e..21be65658 100644 --- a/src/addons/mod/lesson/services/handlers/index-link.ts +++ b/src/addons/mod/lesson/services/handlers/index-link.ts @@ -18,6 +18,7 @@ import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/class import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton } from '@singletons'; @@ -85,14 +86,15 @@ export class AddonModLessonIndexLinkHandlerService extends CoreContentLinksModul try { // Get the module. - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); - - courseId = courseId || module.course; + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); // Store the password so it's automatically used. await CoreUtils.ignoreErrors(AddonModLesson.storePassword(module.instance, password, siteId)); - await CoreCourseHelper.navigateToModule(moduleId, siteId, courseId, module.section); + await CoreCourseHelper.navigateToModule(moduleId, siteId, module.course, module.section); } catch { // Error, go to index page. await CoreCourseHelper.navigateToModule(moduleId, siteId, courseId); diff --git a/src/addons/mod/lesson/services/handlers/prefetch.ts b/src/addons/mod/lesson/services/handlers/prefetch.ts index 2b550bf94..4d87bf1ce 100644 --- a/src/addons/mod/lesson/services/handlers/prefetch.ts +++ b/src/addons/mod/lesson/services/handlers/prefetch.ts @@ -537,7 +537,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref * @return Promise resolved when done. */ sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { - return AddonModLessonSync.syncLesson(module.instance!, false, false, siteId); + return AddonModLessonSync.syncLesson(module.instance, false, false, siteId); } } diff --git a/src/addons/mod/lesson/services/handlers/report-link.ts b/src/addons/mod/lesson/services/handlers/report-link.ts index 7a068134a..355476434 100644 --- a/src/addons/mod/lesson/services/handlers/report-link.ts +++ b/src/addons/mod/lesson/services/handlers/report-link.ts @@ -18,6 +18,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModLessonModuleHandlerService } from './module'; @@ -38,26 +39,20 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand * @param siteIds List of sites the URL belongs to. * @param url The URL to treat. * @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} - * @param courseId Course ID related to the URL. Optional but recommended. - * @param data Extra data to handle the URL. * @return List of (or promise resolved with list of) actions. */ getActions( siteIds: string[], url: string, params: Record, - courseId?: number, - data?: unknown, // eslint-disable-line @typescript-eslint/no-unused-vars ): CoreContentLinksAction[] | Promise { - courseId = Number(courseId || params.courseid || params.cid); - return [{ action: (siteId) => { if (!params.action || params.action == 'reportoverview') { // Go to overview. - this.openReportOverview(Number(params.id), courseId, Number(params.group), siteId); + this.openReportOverview(Number(params.id), Number(params.group), siteId); } else if (params.action == 'reportdetail') { - this.openUserRetake(Number(params.id), Number(params.userid), Number(params.try), siteId, courseId); + this.openUserRetake(Number(params.id), Number(params.userid), Number(params.try), siteId); } }, }]; @@ -70,11 +65,9 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand * @param siteId The site ID. * @param url The URL to treat. * @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} - * @param courseId Course ID related to the URL. Optional but recommended. * @return Whether the handler is enabled for the URL and site. */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - async isEnabled(siteId: string, url: string, params: Record, courseId?: number): Promise { + async isEnabled(siteId: string, url: string, params: Record): Promise { if (params.action == 'reportdetail' && !params.userid) { // Individual details are only available if the teacher is seeing a certain user. return false; @@ -87,29 +80,33 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand * Open report overview. * * @param moduleId Module ID. - * @param courseId Course ID. * @param groupId Group ID. * @param siteId Site ID. - * @param navCtrl The NavController to use to navigate. * @return Promise resolved when done. */ - protected async openReportOverview(moduleId: number, courseId?: number, groupId?: number, siteId?: string): Promise { + protected async openReportOverview(moduleId: number, groupId?: number, siteId?: string): Promise { const modal = await CoreDomUtils.showModalLoading(); try { // Get the module object. - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); + const module = await CoreCourse.getModule( + moduleId, + undefined, + undefined, + false, + false, + siteId, + ); - courseId = courseId || module.course; const params = { - module: module, + module, action: 'report', group: groupId === undefined || isNaN(groupId) ? null : groupId, }; CoreNavigator.navigateToSitePath( - `${AddonModLessonModuleHandlerService.PAGE_NAME}/${courseId}/${module.id}`, + `${AddonModLessonModuleHandlerService.PAGE_NAME}/${module.course}/${module.id}`, { params, siteId }, ); } catch (error) { @@ -126,7 +123,6 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand * @param userId User ID. * @param retake Retake to open. * @param siteId Site ID. - * @param courseId Course ID. * @return Promise resolved when done. */ protected async openUserRetake( @@ -134,22 +130,22 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand userId: number, retake: number, siteId: string, - courseId?: number, ): Promise { const modal = await CoreDomUtils.showModalLoading(); try { // Get the module object. - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); - - courseId = courseId || module.course; + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); const params = { retake: retake || 0, }; CoreNavigator.navigateToSitePath( - AddonModLessonModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/user-retake/${userId}`, + AddonModLessonModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/user-retake/${userId}`, { params, siteId }, ); } catch (error) { diff --git a/src/addons/mod/lesson/services/lesson-helper.ts b/src/addons/mod/lesson/services/lesson-helper.ts index cebbb9f88..669a9bd5b 100644 --- a/src/addons/mod/lesson/services/lesson-helper.ts +++ b/src/addons/mod/lesson/services/lesson-helper.ts @@ -416,7 +416,7 @@ export class AddonModLessonHelperProvider { // Treat each option. let controlAdded = false; options.forEach((option) => { - if (typeof option.value == 'undefined') { + if (option.value === undefined) { // Option not valid, ignore it. return; } diff --git a/src/addons/mod/lesson/services/lesson-sync.ts b/src/addons/mod/lesson/services/lesson-sync.ts index 55d5fa55f..9ad52a558 100644 --- a/src/addons/mod/lesson/services/lesson-sync.ts +++ b/src/addons/mod/lesson/services/lesson-sync.ts @@ -243,7 +243,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid if (result.updated && result.courseId) { try { // Data has been sent to server, update data. - const module = await CoreCourse.getModuleBasicInfoByInstance(lessonId, 'lesson', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance(lessonId, 'lesson', { siteId }); await this.prefetchAfterUpdate(AddonModLessonPrefetchHandler.instance, module, result.courseId, undefined, siteId); } catch { // Ignore errors. diff --git a/src/addons/mod/lesson/services/lesson.ts b/src/addons/mod/lesson/services/lesson.ts index a89470d6d..5f78849ec 100644 --- a/src/addons/mod/lesson/services/lesson.ts +++ b/src/addons/mod/lesson/services/lesson.ts @@ -418,11 +418,11 @@ export class AddonModLessonProvider { } // The name was changed to "answer_editor" in 3.7. Before it was just "answer". Support both cases. - if (typeof data['answer_editor[text]'] != 'undefined') { + if (data['answer_editor[text]'] !== undefined) { studentAnswer = data['answer_editor[text]']; } else if (typeof data.answer_editor == 'object') { studentAnswer = (<{text: string}> data.answer_editor).text; - } else if (typeof data['answer[text]'] != 'undefined') { + } else if (data['answer[text]'] !== undefined) { studentAnswer = data['answer[text]']; } else if (typeof data.answer == 'object') { studentAnswer = (<{text: string}> data.answer).text; @@ -505,7 +505,7 @@ export class AddonModLessonProvider { value = CoreTextUtils.decodeHTML(value); userResponse.push(value); - if (typeof answers[id] != 'undefined') { + if (answers[id] !== undefined) { const answer = answers[id]; result.studentanswer += '
' + answer.answer + ' = ' + value; @@ -606,7 +606,7 @@ export class AddonModLessonProvider { nHits++; } else { // Always use the first student wrong answer. - if (typeof wrongPageId == 'undefined') { + if (wrongPageId === undefined) { wrongPageId = answer.jumpto; } // Save the answer id for scoring. @@ -621,7 +621,7 @@ export class AddonModLessonProvider { nCorrect++; // Save the first jumpto. - if (typeof correctPageId == 'undefined') { + if (correctPageId === undefined) { correctPageId = answer.jumpto; } // Save the answer id for scoring. @@ -644,7 +644,7 @@ export class AddonModLessonProvider { } } else { // Only one answer allowed. - if (typeof data.answerid == 'undefined' || (!data.answerid && Number(data.answerid) !== 0)) { + if (data.answerid === undefined || (!data.answerid && Number(data.answerid) !== 0)) { result.noanswer = true; return; @@ -1501,7 +1501,7 @@ export class AddonModLessonProvider { const response = await site.read('mod_lesson_get_lesson', params, preSets); - if (typeof response.lesson.ongoing == 'undefined') { + if (response.lesson.ongoing === undefined) { // Basic data not received, password is wrong. Remove stored password. this.removeStoredPassword(lessonId, site.id); @@ -1788,7 +1788,7 @@ export class AddonModLessonProvider { const jumps: AddonModLessonPossibleJumps = {}; response.jumps.forEach((jump) => { - if (typeof jumps[jump.pageid] == 'undefined') { + if (jumps[jump.pageid] === undefined) { jumps[jump.pageid] = {}; } jumps[jump.pageid][jump.jumpto] = jump; @@ -2886,7 +2886,7 @@ export class AddonModLessonProvider { if (options.pageIndex[lastAttempt.pageid].qtype == AddonModLessonProvider.LESSON_PAGE_ESSAY) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const score: number | undefined = ( lastAttempt.useranswer)?.score; - if (typeof score != 'undefined') { + if (score !== undefined) { result.earned += score; } result.nmanual++; @@ -2917,7 +2917,7 @@ export class AddonModLessonProvider { for (const answerId in answers) { const answer = answers[answerId]; - if (typeof bestScores[answer.pageid] == 'undefined') { + if (bestScores[answer.pageid] === undefined) { bestScores[answer.pageid] = answer.score || 0; } else if (bestScores[answer.pageid] < (answer.score || 0)) { bestScores[answer.pageid] = answer.score || 0; @@ -3271,7 +3271,7 @@ export class AddonModLessonProvider { if (lesson.review && !result.correctanswer && !result.isessayquestion) { // Calculate the number of question attempt in the page if it isn't calculated already. - if (typeof nAttempts == 'undefined') { + if (nAttempts === undefined) { const result = await this.getQuestionsAttempts(lesson.id, retake, { cmId: lesson.coursemodule, pageId: pageData.page.id, diff --git a/src/addons/mod/lti/services/handlers/module.ts b/src/addons/mod/lti/services/handlers/module.ts index 1692ec173..7dcf9b6ee 100644 --- a/src/addons/mod/lti/services/handlers/module.ts +++ b/src/addons/mod/lti/services/handlers/module.ts @@ -16,7 +16,7 @@ import { Injectable, Type } from '@angular/core'; import { CoreConstants } from '@/core/constants'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { makeSingleton } from '@singletons'; import { AddonModLtiHelper } from '../lti-helper'; import { AddonModLtiIndexComponent } from '../../components/index'; @@ -49,7 +49,7 @@ export class AddonModLtiModuleHandlerService extends CoreModuleHandlerBase imple * @inheritdoc */ async getData( - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, sectionId?: number, forCoursePage?: boolean, @@ -63,7 +63,7 @@ export class AddonModLtiModuleHandlerService extends CoreModuleHandlerBase imple data.buttons = [{ icon: 'fas-external-link-alt', label: 'addon.mod_lti.launchactivity', - action: (event: Event, module: CoreCourseModule, courseId: number): void => { + action: (event: Event, module: CoreCourseModuleData, courseId: number): void => { // Launch the LTI. AddonModLtiHelper.getDataAndLaunch(courseId, module); }, diff --git a/src/addons/mod/lti/services/lti-helper.ts b/src/addons/mod/lti/services/lti-helper.ts index 1dbf19578..74d28a689 100644 --- a/src/addons/mod/lti/services/lti-helper.ts +++ b/src/addons/mod/lti/services/lti-helper.ts @@ -15,7 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreCourse } from '@features/course/services/course'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton, Platform } from '@singletons'; @@ -28,7 +28,7 @@ import { AddonModLti, AddonModLtiLti } from './lti'; @Injectable({ providedIn: 'root' }) export class AddonModLtiHelperProvider { - protected pendingCheckCompletion: {[moduleId: string]: {courseId: number; module: CoreCourseModule}} = {}; + protected pendingCheckCompletion: {[moduleId: string]: {courseId: number; module: CoreCourseModuleData}} = {}; constructor() { // Clear pending completion on logout. @@ -57,7 +57,7 @@ export class AddonModLtiHelperProvider { * @param siteId Site ID. If not defined, current site. * @return Promise resolved when done. */ - async getDataAndLaunch(courseId: number, module: CoreCourseModule, lti?: AddonModLtiLti, siteId?: string): Promise { + async getDataAndLaunch(courseId: number, module: CoreCourseModuleData, lti?: AddonModLtiLti, siteId?: string): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); const modal = await CoreDomUtils.showModalLoading(); @@ -108,7 +108,7 @@ export class AddonModLtiHelperProvider { */ async logViewAndCheckCompletion( courseId: number, - module: CoreCourseModule, + module: CoreCourseModuleData, ltiId: number, name?: string, siteId?: string, diff --git a/src/addons/mod/page/components/index/index.ts b/src/addons/mod/page/components/index/index.ts index 3017d9bf1..dfba12b29 100644 --- a/src/addons/mod/page/components/index/index.ts +++ b/src/addons/mod/page/components/index/index.ts @@ -54,7 +54,7 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp await this.loadContent(); try { - await AddonModPage.logView(this.module.instance!, this.module.name); + await AddonModPage.logView(this.module.instance, this.module.name); CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); } catch { // Ignore errors. @@ -82,7 +82,7 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp const downloadResult = await this.downloadResourceIfNeeded(refresh); // Get contents. No need to refresh, it has been done in downloadResourceIfNeeded. - const contents = await CoreCourse.getModuleContents(this.module, this.courseId); + const contents = await CoreCourse.getModuleContents(this.module); const results = await Promise.all([ this.loadPageData(), @@ -113,9 +113,9 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp const options: Record = CoreTextUtils.unserialize(this.page.displayoptions) || {}; - this.displayDescription = typeof options.printintro == 'undefined' || + this.displayDescription = options.printintro === undefined || CoreUtils.isTrueOrOne(options.printintro); - this.displayTimemodified = typeof options.printlastmodified == 'undefined' || + this.displayTimemodified = options.printlastmodified === undefined || CoreUtils.isTrueOrOne(options.printlastmodified); } else { this.displayDescription = true; diff --git a/src/addons/mod/page/services/handlers/prefetch.ts b/src/addons/mod/page/services/handlers/prefetch.ts index fdbb6f721..c7b6f3958 100644 --- a/src/addons/mod/page/services/handlers/prefetch.ts +++ b/src/addons/mod/page/services/handlers/prefetch.ts @@ -14,7 +14,8 @@ import { Injectable } from '@angular/core'; import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course'; +import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton } from '@singletons'; import { AddonModPage, AddonModPageProvider } from '../page'; @@ -38,7 +39,7 @@ export class AddonModPagePrefetchHandlerService extends CoreCourseResourcePrefet * @param prefetch True to prefetch, false to download right away. * @return Promise resolved when all content is downloaded. Data returned is not reliable. */ - async downloadOrPrefetch(module: CoreCourseWSModule, courseId: number, prefetch?: boolean): Promise { + async downloadOrPrefetch(module: CoreCourseModuleData, courseId: number, prefetch?: boolean): Promise { const promises: Promise[] = []; promises.push(super.downloadOrPrefetch(module, courseId, prefetch)); diff --git a/src/addons/mod/quiz/accessrules/password/services/handlers/password.ts b/src/addons/mod/quiz/accessrules/password/services/handlers/password.ts index 447b336b6..b61c24d84 100644 --- a/src/addons/mod/quiz/accessrules/password/services/handlers/password.ts +++ b/src/addons/mod/quiz/accessrules/password/services/handlers/password.ts @@ -48,7 +48,7 @@ export class AddonModQuizAccessPasswordHandlerService implements AddonModQuizAcc prefetch?: boolean, siteId?: string, ): Promise { - if (typeof preflightData.quizpassword != 'undefined') { + if (preflightData.quizpassword !== undefined) { return; } @@ -134,7 +134,7 @@ export class AddonModQuizAccessPasswordHandlerService implements AddonModQuizAcc siteId?: string, ): Promise { // The password is right, store it to use it automatically in following executions. - if (typeof preflightData.quizpassword != 'undefined') { + if (preflightData.quizpassword !== undefined) { return this.storePassword(quiz.id, preflightData.quizpassword, siteId); } } diff --git a/src/addons/mod/quiz/components/index/index.ts b/src/addons/mod/quiz/components/index/index.ts index 078c97054..92bdfd881 100644 --- a/src/addons/mod/quiz/components/index/index.ts +++ b/src/addons/mod/quiz/components/index/index.ts @@ -615,7 +615,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp await Promise.all(promises); - const grade = typeof this.gradebookData?.grade != 'undefined' ? this.gradebookData.grade : this.bestGrade?.grade; + const grade = this.gradebookData?.grade !== undefined ? this.gradebookData.grade : this.bestGrade?.grade; const quizGrade = AddonModQuiz.formatGrade(grade, quiz.decimalpoints); // Calculate data to construct the header of the attempts table. diff --git a/src/addons/mod/quiz/pages/attempt/attempt.page.ts b/src/addons/mod/quiz/pages/attempt/attempt.page.ts index 85481178d..8906d97f2 100644 --- a/src/addons/mod/quiz/pages/attempt/attempt.page.ts +++ b/src/addons/mod/quiz/pages/attempt/attempt.page.ts @@ -186,7 +186,7 @@ export class AddonModQuizAttemptPage implements OnInit { promises.push(AddonModQuiz.invalidateQuizAccessInformation(this.quiz.id)); promises.push(AddonModQuiz.invalidateCombinedReviewOptionsForUser(this.quiz.id)); - if (this.attempt && typeof this.feedback != 'undefined') { + if (this.attempt && this.feedback !== undefined) { promises.push(AddonModQuiz.invalidateFeedback(this.quiz.id)); } } diff --git a/src/addons/mod/quiz/pages/player/player.page.ts b/src/addons/mod/quiz/pages/player/player.page.ts index c2da33f1b..16e1a22de 100644 --- a/src/addons/mod/quiz/pages/player/player.page.ts +++ b/src/addons/mod/quiz/pages/player/player.page.ts @@ -261,7 +261,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave { if (page != -1 && (this.attempt.state == AddonModQuizProvider.ATTEMPT_OVERDUE || this.attempt.finishedOffline)) { // We can't load a page if overdue or the local attempt is finished. return; - } else if (page == this.attempt.currentpage && !this.showSummary && typeof slot != 'undefined') { + } else if (page == this.attempt.currentpage && !this.showSummary && slot !== undefined) { // Navigating to a question in the current page. this.scrollToQuestion(slot); @@ -317,7 +317,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave { } finally { this.loaded = true; - if (typeof slot != 'undefined') { + if (slot !== undefined) { // Scroll to the question. Give some time to the questions to render. setTimeout(() => { this.scrollToQuestion(slot); diff --git a/src/addons/mod/quiz/pages/review/review.page.ts b/src/addons/mod/quiz/pages/review/review.page.ts index 98d01d3da..07fb1c5cd 100644 --- a/src/addons/mod/quiz/pages/review/review.page.ts +++ b/src/addons/mod/quiz/pages/review/review.page.ts @@ -116,7 +116,7 @@ export class AddonModQuizReviewPage implements OnInit { * @param slot Slot of the question to scroll to. */ async changePage(page: number, fromModal?: boolean, slot?: number): Promise { - if (typeof slot != 'undefined' && (this.attempt!.currentpage == -1 || page == this.currentPage)) { + if (slot !== undefined && (this.attempt!.currentpage == -1 || page == this.currentPage)) { // Scrol to a certain question in the current page. this.scrollToQuestion(slot); @@ -136,7 +136,7 @@ export class AddonModQuizReviewPage implements OnInit { } finally { this.loaded = true; - if (typeof slot != 'undefined') { + if (slot !== undefined) { // Scroll to the question. Give some time to the questions to render. setTimeout(() => { this.scrollToQuestion(slot); @@ -286,7 +286,7 @@ export class AddonModQuizReviewPage implements OnInit { if (this.options!.someoptions.marks >= AddonModQuizProvider.QUESTION_OPTIONS_MARK_AND_MAX && AddonModQuiz.quizHasGrades(this.quiz)) { - if (data.grade === null || typeof data.grade == 'undefined') { + if (data.grade === null || data.grade === undefined) { this.readableGrade = AddonModQuiz.formatGrade(data.grade, this.quiz.decimalpoints); } else { // Show raw marks only if they are different from the grade (like on the entry page). diff --git a/src/addons/mod/quiz/services/handlers/prefetch.ts b/src/addons/mod/quiz/services/handlers/prefetch.ts index 47b61b959..dedc71db5 100644 --- a/src/addons/mod/quiz/services/handlers/prefetch.ts +++ b/src/addons/mod/quiz/services/handlers/prefetch.ts @@ -120,7 +120,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet } const attemptGrade = AddonModQuiz.rescaleGrade(attempt.sumgrades, quiz, false); - if (typeof attemptGrade == 'undefined') { + if (attemptGrade === undefined) { return; } @@ -208,7 +208,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet // Invalidate the calls required to check if a quiz is downloadable. await Promise.all([ AddonModQuiz.invalidateQuizData(courseId), - AddonModQuiz.invalidateUserAttemptsForUser(module.instance!), + AddonModQuiz.invalidateUserAttemptsForUser(module.instance), ]); } @@ -421,7 +421,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet if (AddonModQuiz.isAttemptFinished(attempt.state)) { // Attempt is finished, get feedback and review data. const attemptGrade = AddonModQuiz.rescaleGrade(attempt.sumgrades, quiz, false); - if (typeof attemptGrade != 'undefined') { + if (attemptGrade !== undefined) { promises.push(AddonModQuiz.getFeedbackForGrade(quiz.id, Number(attemptGrade), modOptions)); } diff --git a/src/addons/mod/quiz/services/handlers/push-click.ts b/src/addons/mod/quiz/services/handlers/push-click.ts index b326cc699..7144d7a03 100644 --- a/src/addons/mod/quiz/services/handlers/push-click.ts +++ b/src/addons/mod/quiz/services/handlers/push-click.ts @@ -62,7 +62,6 @@ export class AddonModQuizPushClickHandlerService implements CorePushNotification return AddonModQuizHelper.handleReviewLink( Number(contextUrlParams.attempt), Number(contextUrlParams.page), - courseId, Number(data.instance), notification.site, ); diff --git a/src/addons/mod/quiz/services/handlers/review-link.ts b/src/addons/mod/quiz/services/handlers/review-link.ts index 413aea88b..d2c7cdd3b 100644 --- a/src/addons/mod/quiz/services/handlers/review-link.ts +++ b/src/addons/mod/quiz/services/handlers/review-link.ts @@ -46,17 +46,13 @@ export class AddonModQuizReviewLinkHandlerService extends CoreContentLinksHandle courseId?: number, data?: Record, ): CoreContentLinksAction[] | Promise { - - courseId = Number(courseId || params.courseid || params.cid); - data = data || {}; + const quizId = data?.instance ? Number(data.instance) : undefined; return [{ action: (siteId): void => { const attemptId = parseInt(params.attempt, 10); const page = parseInt(params.page, 10); - const quizId = data!.instance ? Number(data!.instance) : undefined; - - AddonModQuizHelper.handleReviewLink(attemptId, page, courseId, quizId, siteId); + AddonModQuizHelper.handleReviewLink(attemptId, page, quizId, siteId); }, }]; } diff --git a/src/addons/mod/quiz/services/quiz-helper.ts b/src/addons/mod/quiz/services/quiz-helper.ts index d94ccba31..4eeb1755a 100644 --- a/src/addons/mod/quiz/services/quiz-helper.ts +++ b/src/addons/mod/quiz/services/quiz-helper.ts @@ -215,12 +215,11 @@ export class AddonModQuizHelperProvider { * * @param attemptId Attempt ID. * @param page Page to load, -1 to all questions in same page. - * @param courseId Course ID. * @param quizId Quiz ID. * @param siteId Site ID. If not defined, current site. * @return Promise resolved when done. */ - async handleReviewLink(attemptId: number, page?: number, courseId?: number, quizId?: number, siteId?: string): Promise { + async handleReviewLink(attemptId: number, page?: number, quizId?: number, siteId?: string): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); const modal = await CoreDomUtils.showModalLoading(); @@ -230,13 +229,15 @@ export class AddonModQuizHelperProvider { quizId = await this.getQuizIdByAttemptId(attemptId, { siteId }); } - const module = await CoreCourse.getModuleBasicInfoByInstance(quizId, 'quiz', siteId); - - courseId = courseId || module.course; + const module = await CoreCourse.getModuleBasicInfoByInstance( + quizId, + 'quiz', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); // Go to the review page. await CoreNavigator.navigateToSitePath( - `${AddonModQuizModuleHandlerService.PAGE_NAME}/${courseId}/${module.id}/review/${attemptId}`, + `${AddonModQuizModuleHandlerService.PAGE_NAME}/${module.course}/${module.id}/review/${attemptId}`, { params: { page: page == undefined || isNaN(page) ? -1 : page, diff --git a/src/addons/mod/quiz/services/quiz-sync.ts b/src/addons/mod/quiz/services/quiz-sync.ts index 6990384f1..4f4aed5d0 100644 --- a/src/addons/mod/quiz/services/quiz-sync.ts +++ b/src/addons/mod/quiz/services/quiz-sync.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync'; -import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course'; +import { CoreCourse, CoreCourseModuleBasicInfo } from '@features/course/services/course'; import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; import { CoreQuestion, CoreQuestionQuestionParsed } from '@features/question/services/question'; @@ -92,9 +92,9 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider if (options.updated) { try { // Data has been sent. Update prefetched data. - const module = await CoreCourse.getModuleBasicInfoByInstance(quiz.id, 'quiz', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance(quiz.id, 'quiz', { siteId }); - await this.prefetchAfterUpdateQuiz(module, quiz, courseId, undefined, siteId); + await this.prefetchAfterUpdateQuiz(module, quiz, courseId, siteId); } catch { // Ignore errors. } @@ -139,27 +139,25 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider * @param module Module. * @param quiz Quiz. * @param courseId Course ID. - * @param regex If regex matches, don't download the data. Defaults to check files. * @param siteId Site ID. If not defined, current site. * @return Promise resolved when done. */ - async prefetchAfterUpdateQuiz( - module: CoreCourseAnyModuleData, + protected async prefetchAfterUpdateQuiz( + module: CoreCourseModuleBasicInfo, quiz: AddonModQuizQuizWSData, courseId: number, - regex?: RegExp, siteId?: string, ): Promise { - regex = regex || /^.*files$/; - let shouldDownload = false; // Get the module updates to check if the data was updated or not. const result = await CoreCourseModulePrefetchDelegate.getModuleUpdates(module, courseId, true, siteId); if (result?.updates?.length) { + const regex = /^.*files$/; + // Only prefetch if files haven't changed. - shouldDownload = !result.updates.find((entry) => entry.name.match(regex!)); + shouldDownload = !result.updates.find((entry) => entry.name.match(regex)); if (shouldDownload) { await AddonModQuizPrefetchHandler.download(module, courseId, undefined, false, false); diff --git a/src/addons/mod/quiz/services/quiz.ts b/src/addons/mod/quiz/services/quiz.ts index c3cc895df..bc8793596 100644 --- a/src/addons/mod/quiz/services/quiz.ts +++ b/src/addons/mod/quiz/services/quiz.ts @@ -425,7 +425,7 @@ export class AddonModQuizProvider { attemptId: number, options: AddonModQuizGetAttemptReviewOptions = {}, ): Promise { - const page = typeof options.page == 'undefined' ? -1 : options.page; + const page = options.page === undefined ? -1 : options.page; const site = await CoreSites.getSite(options.siteId); @@ -620,7 +620,7 @@ export class AddonModQuizProvider { * @return Number of decimals. */ getGradeDecimals(quiz: AddonModQuizQuizWSData): number { - if (typeof quiz.questiondecimalpoints == 'undefined') { + if (quiz.questiondecimalpoints === undefined) { quiz.questiondecimalpoints = -1; } @@ -1029,7 +1029,7 @@ export class AddonModQuizProvider { ): Promise { const status = options.status || 'all'; - const includePreviews = typeof options.includePreviews == 'undefined' ? true : options.includePreviews; + const includePreviews = options.includePreviews === undefined ? true : options.includePreviews; const site = await CoreSites.getSite(options.siteId); diff --git a/src/addons/mod/resource/components/index/index.ts b/src/addons/mod/resource/components/index/index.ts index a3a29b038..3987378fc 100644 --- a/src/addons/mod/resource/components/index/index.ts +++ b/src/addons/mod/resource/components/index/index.ts @@ -82,7 +82,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource await this.loadContent(); try { - await AddonModResource.logView(this.module.instance!, this.module.name); + await AddonModResource.logView(this.module.instance, this.module.name); CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); } catch { // Ignore errors. @@ -101,7 +101,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource */ protected async fetchContent(refresh?: boolean): Promise { // Load module contents if needed. Passing refresh is needed to force reloading contents. - const contents = await CoreCourse.getModuleContents(this.module, this.courseId, undefined, false, refresh); + const contents = await CoreCourse.getModuleContents(this.module, undefined, undefined, false, refresh); if (!contents.length) { throw new CoreError(Translate.instant('core.filenotfound')); @@ -116,7 +116,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource resource.displayoptions ? CoreTextUtils.unserialize(resource.displayoptions) : {}; try { - this.displayDescription = typeof options.printintro == 'undefined' || !!options.printintro; + this.displayDescription = options.printintro === undefined || !!options.printintro; this.dataRetrieved.emit(resource); if (AddonModResourceHelper.isDisplayedInIframe(this.module)) { @@ -148,7 +148,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource this.mode = 'embedded'; this.warning = ''; - this.contentText = await AddonModResourceHelper.getEmbeddedHtml(this.module, this.courseId); + this.contentText = await AddonModResourceHelper.getEmbeddedHtml(this.module); this.mode = this.contentText.length > 0 ? 'embedded' : 'external'; } else { this.mode = 'external'; diff --git a/src/addons/mod/resource/services/handlers/module.ts b/src/addons/mod/resource/services/handlers/module.ts index 275ea61f7..205173fe6 100644 --- a/src/addons/mod/resource/services/handlers/module.ts +++ b/src/addons/mod/resource/services/handlers/module.ts @@ -15,8 +15,8 @@ import { CoreConstants } from '@/core/constants'; import { Injectable, Type } from '@angular/core'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; -import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourse } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; import { CoreFileHelper } from '@services/file-helper'; @@ -63,7 +63,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase * @inheritdoc */ async getData( - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, sectionId?: number, forCoursePage?: boolean, @@ -84,8 +84,8 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase hidden: true, icon: openWithPicker ? 'fas-share-square' : 'fas-file', label: module.name + ': ' + Translate.instant(openWithPicker ? 'core.openwith' : 'addon.mod_resource.openthefile'), - action: async (event: Event, module: CoreCourseModule, courseId: number): Promise => { - const hide = await this.hideOpenButton(module, courseId); + action: async (event: Event, module: CoreCourseModuleData, courseId: number): Promise => { + const hide = await this.hideOpenButton(module); if (!hide) { AddonModResourceHelper.openModuleFile(module, courseId); } @@ -109,15 +109,14 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase * Returns if contents are loaded to show open button. * * @param module The module object. - * @param courseId The course ID. * @return Resolved when done. */ - protected async hideOpenButton(module: CoreCourseModule, courseId: number): Promise { - if (!('contentsinfo' in module) || !module.contentsinfo) { - await CoreCourse.loadModuleContents(module, courseId, undefined, false, false, undefined, this.modName); + protected async hideOpenButton(module: CoreCourseModuleData): Promise { + if (!module.contentsinfo) { // Not informed before 3.7.6. + await CoreCourse.loadModuleContents(module, undefined, undefined, false, false, undefined, this.modName); } - const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(module, courseId); + const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(module, module.course); return status !== CoreConstants.DOWNLOADED || AddonModResourceHelper.isDisplayedInIframe(module); } @@ -130,7 +129,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase * @return Resource data. */ protected async getResourceData( - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, handlerData: CoreCourseModuleHandlerData, ): Promise { @@ -138,7 +137,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase let options: AddonModResourceCustomData = {}; // Check if the button needs to be shown or not. - promises.push(this.hideOpenButton(module, courseId).then((hideOpenButton) => { + promises.push(this.hideOpenButton(module).then((hideOpenButton) => { if (!handlerData.buttons) { return; } @@ -148,7 +147,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase return; })); - if ('customdata' in module && module.customdata !== undefined) { + if (module.customdata !== undefined) { options = CoreTextUtils.unserialize(CoreTextUtils.parseJSON(module.customdata)); } else { // Get the resource data. @@ -164,7 +163,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase let mimetypeIcon = ''; const extra: string[] = []; - if ('contentsinfo' in module && module.contentsinfo) { + if (module.contentsinfo) { // No need to use the list of files. const mimetype = module.contentsinfo.mimetypes[0]; if (mimetype) { @@ -229,13 +228,13 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase /** * @inheritdoc */ - async getIconSrc(module?: CoreCourseWSModule): Promise { + async getIconSrc(module?: CoreCourseModuleData): Promise { if (!module) { return; } let mimetypeIcon = ''; - if ('contentsinfo' in module && module.contentsinfo) { + if (module.contentsinfo) { // No need to use the list of files. const mimetype = module.contentsinfo.mimetypes[0]; if (mimetype) { diff --git a/src/addons/mod/resource/services/handlers/prefetch.ts b/src/addons/mod/resource/services/handlers/prefetch.ts index 696922b78..3342cc474 100644 --- a/src/addons/mod/resource/services/handlers/prefetch.ts +++ b/src/addons/mod/resource/services/handlers/prefetch.ts @@ -15,7 +15,8 @@ import { CoreConstants } from '@/core/constants'; import { Injectable } from '@angular/core'; import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course'; +import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreFilepool } from '@services/filepool'; import { CoreSites } from '@services/sites'; import { makeSingleton } from '@singletons'; @@ -57,7 +58,7 @@ export class AddonModResourcePrefetchHandlerService extends CoreCourseResourcePr /** * @inheritdoc */ - async downloadOrPrefetch(module: CoreCourseWSModule, courseId: number, prefetch?: boolean): Promise { + async downloadOrPrefetch(module: CoreCourseModuleData, courseId: number, prefetch?: boolean): Promise { let dirPath: string | undefined; if (AddonModResourceHelper.isDisplayedInIframe(module)) { diff --git a/src/addons/mod/resource/services/resource-helper.ts b/src/addons/mod/resource/services/resource-helper.ts index 4cb2ccad1..f0975eacf 100644 --- a/src/addons/mod/resource/services/resource-helper.ts +++ b/src/addons/mod/resource/services/resource-helper.ts @@ -15,8 +15,8 @@ import { CoreConstants } from '@/core/constants'; import { Injectable } from '@angular/core'; import { CoreError } from '@classes/errors/error'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course'; -import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course'; +import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreApp } from '@services/app'; import { CoreFile } from '@services/file'; import { CoreFileHelper } from '@services/file-helper'; @@ -39,15 +39,14 @@ export class AddonModResourceHelperProvider { * Get the HTML to display an embedded resource. * * @param module The module object. - * @param courseId The course ID. * @return Promise resolved with the HTML. */ - async getEmbeddedHtml(module: CoreCourseWSModule, courseId: number): Promise { - const contents = await CoreCourse.getModuleContents(module, courseId); + async getEmbeddedHtml(module: CoreCourseModuleData): Promise { + const contents = await CoreCourse.getModuleContents(module); const result = await CoreCourseHelper.downloadModuleWithMainFileIfNeeded( module, - courseId, + module.course, AddonModResourceProvider.COMPONENT, module.id, contents, @@ -62,7 +61,7 @@ export class AddonModResourceHelperProvider { * @param module The module object. * @return Promise resolved with the iframe src. */ - async getIframeSrc(module: CoreCourseWSModule): Promise { + async getIframeSrc(module: CoreCourseModuleData): Promise { if (!module.contents?.length) { throw new CoreError('No contents available in module'); } @@ -97,7 +96,7 @@ export class AddonModResourceHelperProvider { * @param display The display mode (if available). * @return Whether the resource should be displayed embeded. */ - isDisplayedEmbedded(module: CoreCourseWSModule, display: number): boolean { + isDisplayedEmbedded(module: CoreCourseModuleData, display: number): boolean { const currentSite = CoreSites.getCurrentSite(); if (!CoreFile.isAvailable() || @@ -124,14 +123,14 @@ export class AddonModResourceHelperProvider { * @param module The module object. * @return Whether the resource should be displayed in an iframe. */ - isDisplayedInIframe(module: CoreCourseAnyModuleData): boolean { + isDisplayedInIframe(module: CoreCourseModuleData): boolean { if (!CoreFile.isAvailable()) { return false; } let mimetype: string | undefined; - if ('contentsinfo' in module && module.contentsinfo) { + if (module.contentsinfo) { mimetype = module.contentsinfo.mimetypes[0]; } else if (module.contents) { const ext = CoreMimetypeUtils.getFileExtension(module.contents[0].filename); @@ -150,7 +149,7 @@ export class AddonModResourceHelperProvider { * @param siteId Site ID. If not defined, current site. * @return Promise resolved with boolean: whether main file is downloadable. */ - async isMainFileDownloadable(module: CoreCourseWSModule, siteId?: string): Promise { + async isMainFileDownloadable(module: CoreCourseModuleData, siteId?: string): Promise { const contents = await CoreCourse.getModuleContents(module); if (!contents.length) { throw new CoreError(Translate.instant('core.filenotfound')); @@ -186,7 +185,7 @@ export class AddonModResourceHelperProvider { * @param options Options to open the file. * @return Resolved when done. */ - async openModuleFile(module: CoreCourseWSModule, courseId: number, options: CoreUtilsOpenFileOptions = {}): Promise { + async openModuleFile(module: CoreCourseModuleData, courseId: number, options: CoreUtilsOpenFileOptions = {}): Promise { const modal = await CoreDomUtils.showModalLoading(); try { @@ -202,7 +201,7 @@ export class AddonModResourceHelperProvider { ); try { - await AddonModResource.logView(module.instance!, module.name); + await AddonModResource.logView(module.instance, module.name); CoreCourse.checkModuleCompletion(courseId, module.completiondata); } catch { // Ignore errors. diff --git a/src/addons/mod/scorm/components/index/index.ts b/src/addons/mod/scorm/components/index/index.ts index 945ba9112..44985f6d1 100644 --- a/src/addons/mod/scorm/components/index/index.ts +++ b/src/addons/mod/scorm/components/index/index.ts @@ -203,7 +203,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom this.accessInfo = accessInfo; // Check whether to launch the SCORM immediately. - if (typeof this.skip == 'undefined') { + if (this.skip === undefined) { this.skip = !this.hasOffline && !this.errorMessage && (!this.scorm.lastattemptlock || this.attemptsLeft > 0) && this.accessInfo.canskipview && !this.accessInfo.canviewreport && diff --git a/src/addons/mod/scorm/services/scorm-offline.ts b/src/addons/mod/scorm/services/scorm-offline.ts index 2971656e9..9f9874486 100644 --- a/src/addons/mod/scorm/services/scorm-offline.ts +++ b/src/addons/mod/scorm/services/scorm-offline.ts @@ -682,7 +682,7 @@ export class AddonModScormOfflineProvider { scoid: scoId, attempt, element: element, - value: typeof value == 'undefined' ? null : JSON.stringify(value), + value: value === undefined ? null : JSON.stringify(value), timemodified: CoreTimeUtils.timestamp(), synced: 0, }; @@ -937,7 +937,7 @@ export class AddonModScormOfflineProvider { param: string, ifEmpty: AddonModScormDataValue = '', ): AddonModScormDataValue { - if (typeof userData[param] != 'undefined') { + if (userData[param] !== undefined) { return userData[param]; } diff --git a/src/addons/mod/scorm/services/scorm-sync.ts b/src/addons/mod/scorm/services/scorm-sync.ts index 5c9e1f158..19d073614 100644 --- a/src/addons/mod/scorm/services/scorm-sync.ts +++ b/src/addons/mod/scorm/services/scorm-sync.ts @@ -198,7 +198,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide if (updated) { try { // Update downloaded data. - const module = await CoreCourse.getModule(scorm.coursemodule, scorm.course, undefined, false, false, siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance(scorm.id, 'scorm', { siteId }); await this.prefetchAfterUpdate(AddonModScormPrefetchHandler.instance, module, scorm.course, undefined, siteId); } catch { @@ -476,7 +476,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide await this.syncScorm(scorm, siteId) : await this.syncScormIfNeeded(scorm, siteId); - if (typeof data != 'undefined') { + if (data !== undefined) { // We tried to sync. Send event. CoreEvents.trigger(AddonModScormSyncProvider.AUTO_SYNCED, { scormId: scorm.id, diff --git a/src/addons/mod/scorm/services/scorm.ts b/src/addons/mod/scorm/services/scorm.ts index a5cd5ecb9..528e68c6a 100644 --- a/src/addons/mod/scorm/services/scorm.ts +++ b/src/addons/mod/scorm/services/scorm.ts @@ -331,7 +331,7 @@ export class AddonModScormProvider { set.forEach((setElement) => { setElement = setElement.trim(); - if (typeof trackData[setElement] != 'undefined' && + if (trackData[setElement] !== undefined && (trackData[setElement].status == 'completed' || trackData[setElement].status == 'passed')) { count++; } @@ -350,11 +350,11 @@ export class AddonModScormProvider { matches = element.match(reOther)!; element = matches[1].trim(); - if (typeof trackData[element] != 'undefined') { + if (trackData[element] !== undefined) { let value = matches[3].trim().replace(/('|")/gi, ''); let oper: string; - if (typeof STATUSES[value] != 'undefined') { + if (STATUSES[value] !== undefined) { value = STATUSES[value]; } @@ -370,7 +370,7 @@ export class AddonModScormProvider { } } else { // Everything else must be an element defined like S45 ... - if (typeof trackData[element] != 'undefined' && + if (trackData[element] !== undefined && (trackData[element].status == 'completed' || trackData[element].status == 'passed')) { element = 'true'; } else { @@ -395,7 +395,7 @@ export class AddonModScormProvider { * @return Grade to display. */ formatGrade(scorm: AddonModScormScorm, grade: number): string { - if (typeof grade == 'undefined' || grade == -1) { + if (grade === undefined || grade == -1) { return Translate.instant('core.none'); } @@ -607,8 +607,8 @@ export class AddonModScormProvider { attemptScore.scos++; } - if (userData.score_raw || (typeof scorm.scormtype != 'undefined' && - scorm.scormtype == 'sco' && typeof userData.score_raw != 'undefined')) { + if (userData.score_raw || (scorm.scormtype !== undefined && + scorm.scormtype == 'sco' && userData.score_raw !== undefined)) { const scoreRaw = parseFloat( userData.score_raw); attemptScore.values++; @@ -912,14 +912,14 @@ export class AddonModScormProvider { } // Check isvisible attribute. - sco.isvisible = typeof scoData.isvisible == 'undefined' || (!!scoData.isvisible && scoData.isvisible !== 'false'); + sco.isvisible = scoData.isvisible === undefined || (!!scoData.isvisible && scoData.isvisible !== 'false'); // Check pre-requisites status. - sco.prereq = typeof scoData.prerequisites == 'undefined' || + sco.prereq = scoData.prerequisites === undefined || this.evalPrerequisites( scoData.prerequisites, trackDataBySCO); // Add status. - sco.status = (typeof scoData.status == 'undefined' || scoData.status === '') ? 'notattempted' : scoData.status; + sco.status = (scoData.status === undefined || scoData.status === '') ? 'notattempted' : scoData.status; // Exit var. - sco.exitvar = typeof scoData.exitvar == 'undefined' ? 'cmi.core.exit' : scoData.exitvar; + sco.exitvar = scoData.exitvar === undefined ? 'cmi.core.exit' : scoData.exitvar; sco.exitvalue = scoData[sco.exitvar]; // Copy score. sco.scoreraw = scoData.score_raw; @@ -1109,7 +1109,7 @@ export class AddonModScormProvider { } // If the SCORM isn't available the WS returns a warning and it doesn't return timeopen and timeclosed. - if (typeof currentScorm.timeopen == 'undefined') { + if (currentScorm.timeopen === undefined) { const warning = response.warnings?.find(warning => warning.itemid === currentScorm.id); currentScorm.warningMessage = warning?.message; } @@ -1339,7 +1339,7 @@ export class AddonModScormProvider { * @return Whether the SCORM is downloadable. */ isScormDownloadable(scorm: AddonModScormScorm): boolean { - return typeof scorm.protectpackagedownloads != 'undefined' && scorm.protectpackagedownloads === false; + return scorm.protectpackagedownloads !== undefined && scorm.protectpackagedownloads === false; } /** @@ -1635,7 +1635,7 @@ export class AddonModScormProvider { const component = AddonModScormProvider.COMPONENT; - if (typeof isOutdated == 'undefined') { + if (isOutdated === undefined) { // Calculate if it's outdated. const data = await CoreUtils.ignoreErrors(CoreFilepool.getPackageData(siteId, component, scorm.coursemodule)); diff --git a/src/addons/mod/survey/services/handlers/prefetch.ts b/src/addons/mod/survey/services/handlers/prefetch.ts index fca2d7852..31ffcff48 100644 --- a/src/addons/mod/survey/services/handlers/prefetch.ts +++ b/src/addons/mod/survey/services/handlers/prefetch.ts @@ -107,7 +107,7 @@ export class AddonModSurveyPrefetchHandlerService extends CoreCourseActivityPref * @inheritdoc */ sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { - return AddonModSurveySync.syncSurvey(module.instance!, undefined, siteId); + return AddonModSurveySync.syncSurvey(module.instance, undefined, siteId); } } diff --git a/src/addons/mod/survey/services/survey-sync.ts b/src/addons/mod/survey/services/survey-sync.ts index e128b0b1e..4ed43f0dd 100644 --- a/src/addons/mod/survey/services/survey-sync.ts +++ b/src/addons/mod/survey/services/survey-sync.ts @@ -202,7 +202,7 @@ export class AddonModSurveySyncProvider extends CoreCourseActivitySyncBaseProvid await AddonModSurvey.invalidateSurveyData(result.courseId, siteId); // Data has been sent to server, update survey data. - const module = await CoreCourse.getModuleBasicInfoByInstance(surveyId, 'survey', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance(surveyId, 'survey', { siteId }); CoreUtils.ignoreErrors( this.prefetchAfterUpdate(AddonModSurveyPrefetchHandler.instance, module, result.courseId, undefined, siteId), diff --git a/src/addons/mod/url/components/index/index.ts b/src/addons/mod/url/components/index/index.ts index e92c6541e..b79ee6610 100644 --- a/src/addons/mod/url/components/index/index.ts +++ b/src/addons/mod/url/components/index/index.ts @@ -92,13 +92,13 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo if (url.displayoptions) { const unserialized = CoreTextUtils.unserialize(url.displayoptions); - this.displayDescription = typeof unserialized.printintro == 'undefined' || !!unserialized.printintro; + this.displayDescription = unserialized.printintro === undefined || !!unserialized.printintro; } // Try to get module contents, it's needed to get the URL with parameters. const contents = await CoreCourse.getModuleContents( this.module, - this.courseId, + undefined, undefined, false, refresh, @@ -169,7 +169,7 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo */ protected async logView(): Promise { try { - await AddonModUrl.logView(this.module.instance!, this.module.name); + await AddonModUrl.logView(this.module.instance, this.module.name); CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); } catch { // Ignore errors. diff --git a/src/addons/mod/url/services/handlers/module.ts b/src/addons/mod/url/services/handlers/module.ts index 69c7d2c4b..ed9e30713 100644 --- a/src/addons/mod/url/services/handlers/module.ts +++ b/src/addons/mod/url/services/handlers/module.ts @@ -17,7 +17,7 @@ import { Injectable, Type } from '@angular/core'; import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; import { CoreCourse } from '@features/course/services/course'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { CoreNavigationOptions } from '@services/navigator'; import { CoreDomUtils } from '@services/utils/dom'; @@ -54,7 +54,7 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple /** * @inheritdoc */ - async getData(module: CoreCourseModule, courseId: number): Promise { + async getData(module: CoreCourseModuleData): Promise { /** * Open the URL. @@ -62,17 +62,17 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple * @param module The module object. * @param courseId The course ID. */ - const openUrl = async (module: CoreCourseModule, courseId: number): Promise => { + const openUrl = async (module: CoreCourseModuleData): Promise => { try { if (module.instance) { await AddonModUrl.logView(module.instance, module.name); - CoreCourse.checkModuleCompletion(courseId, module.completiondata); + CoreCourse.checkModuleCompletion(module.course, module.completiondata); } } catch { // Ignore errors. } - const contents = await CoreCourse.getModuleContents(module, courseId); + const contents = await CoreCourse.getModuleContents(module); AddonModUrlHelper.open(contents[0].fileurl); }; @@ -81,16 +81,16 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple title: module.name, class: 'addon-mod_url-handler', showDownloadButton: false, - action: async (event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions) => { + action: async (event: Event, module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions) => { const modal = await CoreDomUtils.showModalLoading(); try { - const shouldOpen = await this.shouldOpenLink(module, courseId); + const shouldOpen = await this.shouldOpenLink(module); if (shouldOpen) { - openUrl(module, courseId); + openUrl(module); } else { - this.openActivityPage(module, courseId, options); + this.openActivityPage(module, module.course, options); } } finally { modal.dismiss(); @@ -100,13 +100,13 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple hidden: true, // Hide it until we calculate if it should be displayed or not. icon: 'fas-link', label: 'core.openmodinbrowser', - action: (event: Event, module: CoreCourseModule, courseId: number): void => { - openUrl(module, courseId); + action: (event: Event, module: CoreCourseModuleData): void => { + openUrl(module); }, }], }; - this.hideLinkButton(module, courseId).then(async (hideButton) => { + this.hideLinkButton(module).then(async (hideButton) => { if (!handlerData.buttons) { return; } @@ -135,9 +135,10 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple * @param courseId The course ID. * @return Resolved when done. */ - protected async hideLinkButton(module: CoreCourseModule, courseId: number): Promise { + protected async hideLinkButton(module: CoreCourseModuleData): Promise { try { - const contents = await CoreCourse.getModuleContents(module, courseId, undefined, false, false, undefined, this.modName); + const contents = + await CoreCourse.getModuleContents(module, undefined, undefined, false, false, undefined, this.modName); return !(contents[0] && contents[0].fileurl); } catch { @@ -157,22 +158,22 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple * Check whether the link should be opened directly. * * @param module Module. - * @param courseId Course ID. * @return Promise resolved with boolean. */ - protected async shouldOpenLink(module: CoreCourseModule, courseId?: number): Promise { + protected async shouldOpenLink(module: CoreCourseModuleData): Promise { try { - const contents = await CoreCourse.getModuleContents(module, courseId, undefined, false, false, undefined, this.modName); + const contents = + await CoreCourse.getModuleContents(module, undefined, undefined, false, false, undefined, this.modName); // Check if the URL can be handled by the app. If so, always open it directly. - const canHandle = await CoreContentLinksHelper.canHandleLink(contents[0].fileurl, courseId, undefined, true); + const canHandle = await CoreContentLinksHelper.canHandleLink(contents[0].fileurl, module.course, undefined, true); if (canHandle) { // URL handled by the app, open it directly. return true; } else { // Not handled by the app, check the display type. - const url = courseId ? await CoreUtils.ignoreErrors(AddonModUrl.getUrl(courseId, module.id)) : undefined; + const url = await CoreUtils.ignoreErrors(AddonModUrl.getUrl(module.course, module.id)); const displayType = AddonModUrl.getFinalDisplayType(url); return displayType == CoreConstants.RESOURCELIB_DISPLAY_OPEN || @@ -186,8 +187,8 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple /** * @inheritdoc */ - manualCompletionAlwaysShown(module: CoreCourseModule): Promise { - return this.shouldOpenLink(module, module.course); + manualCompletionAlwaysShown(module: CoreCourseModuleData): Promise { + return this.shouldOpenLink(module); } } diff --git a/src/addons/mod/wiki/components/index/index.ts b/src/addons/mod/wiki/components/index/index.ts index 1ae8303a8..45ea90277 100644 --- a/src/addons/mod/wiki/components/index/index.ts +++ b/src/addons/mod/wiki/components/index/index.ts @@ -959,28 +959,28 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp candidateSubwikiId = subwiki.id; } - if (typeof candidateSubwikiId != 'undefined') { + if (candidateSubwikiId !== undefined) { if (candidateSubwikiId > 0) { // Subwiki found and created, no need to keep looking. candidateFirstPage = Number(i); break; - } else if (typeof candidateNoFirstPage == 'undefined') { + } else if (candidateNoFirstPage === undefined) { candidateNoFirstPage = Number(i); } - } else if (typeof firstCanEdit == 'undefined') { + } else if (firstCanEdit === undefined) { firstCanEdit = Number(i); } } } let subWikiToTake: number; - if (typeof candidateFirstPage != 'undefined') { + if (candidateFirstPage !== undefined) { // Take the candidate that already has the first page created. subWikiToTake = candidateFirstPage; - } else if (typeof candidateNoFirstPage != 'undefined') { + } else if (candidateNoFirstPage !== undefined) { // No first page created, take the first candidate. subWikiToTake = candidateNoFirstPage; - } else if (typeof firstCanEdit != 'undefined') { + } else if (firstCanEdit !== undefined) { // None selected, take the first the user can edit. subWikiToTake = firstCanEdit; } else { @@ -989,7 +989,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp } const subwiki = subwikiList[subWikiToTake]; - if (typeof subwiki != 'undefined') { + if (subwiki !== undefined) { this.setSelectedWiki(subwiki.id, subwiki.userid, subwiki.groupid); } } @@ -1022,7 +1022,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp // As we loop over each subwiki, add it to the current group subwikiList.forEach((subwiki) => { // Add the subwiki to the currently active grouping. - if (typeof subwiki.canedit == 'undefined') { + if (subwiki.canedit === undefined) { noGrouping.subwikis.push(subwiki); } else if (subwiki.canedit) { myGroupsGrouping.subwikis.push(subwiki); diff --git a/src/addons/mod/wiki/pages/edit/edit.ts b/src/addons/mod/wiki/pages/edit/edit.ts index 3777fbb3b..48f2c2adf 100644 --- a/src/addons/mod/wiki/pages/edit/edit.ts +++ b/src/addons/mod/wiki/pages/edit/edit.ts @@ -18,7 +18,7 @@ import { CoreError } from '@classes/errors/error'; import { CoreCourse } from '@features/course/services/course'; import { CanLeave } from '@guards/can-leave'; import { CoreNavigator } from '@services/navigator'; -import { CoreSites } from '@services/sites'; +import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSync } from '@services/sync'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreTextUtils } from '@services/utils/text'; @@ -262,7 +262,11 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave { return; } - const module = await CoreCourse.getModuleBasicInfoByInstance(this.wikiId, 'wiki'); + const module = await CoreCourse.getModuleBasicInfoByInstance( + this.wikiId, + 'wiki', + { readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); this.cmId = module.id; this.courseId = module.course; diff --git a/src/addons/mod/wiki/services/handlers/create-link.ts b/src/addons/mod/wiki/services/handlers/create-link.ts index 90a3c5aaa..b78a3f632 100644 --- a/src/addons/mod/wiki/services/handlers/create-link.ts +++ b/src/addons/mod/wiki/services/handlers/create-link.ts @@ -115,7 +115,11 @@ export class AddonModWikiCreateLinkHandlerService extends CoreContentLinksHandle path = path + `/${route!.snapshot.params.courseId}/${route!.snapshot.params.cmId}/edit`; } else if (wikiId) { // The URL specifies which wiki it belongs to. Get the module. - const module = await CoreCourse.getModuleBasicInfoByInstance(wikiId, 'wiki', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance( + wikiId, + 'wiki', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); path = path + `/${module.course}/${module.id}/edit`; } else { diff --git a/src/addons/mod/wiki/services/handlers/edit-link.ts b/src/addons/mod/wiki/services/handlers/edit-link.ts index 6a164a954..68e3a5140 100644 --- a/src/addons/mod/wiki/services/handlers/edit-link.ts +++ b/src/addons/mod/wiki/services/handlers/edit-link.ts @@ -17,6 +17,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { AddonModWiki } from '../wiki'; @@ -39,7 +40,6 @@ export class AddonModWikiEditLinkHandlerService extends CoreContentLinksHandlerB siteIds: string[], url: string, params: Record, - courseId?: number, ): CoreContentLinksAction[] | Promise { return [{ @@ -51,17 +51,19 @@ export class AddonModWikiEditLinkHandlerService extends CoreContentLinksHandlerB const pageContents = await AddonModWiki.getPageContents(pageId, { siteId }); - const module = await CoreCourse.getModuleBasicInfoByInstance(pageContents.wikiid, 'wiki', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance( + pageContents.wikiid, + 'wiki', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); let section = ''; - if (typeof params.section != 'undefined') { + if (params.section !== undefined) { section = params.section.replace(/\+/g, ' '); } - courseId = module.course || courseId || Number(params.courseid || params.cid); - CoreNavigator.navigateToSitePath( - AddonModWikiModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/edit`, + AddonModWikiModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/edit`, { params: { section: section, diff --git a/src/addons/mod/wiki/services/handlers/page-or-map-link.ts b/src/addons/mod/wiki/services/handlers/page-or-map-link.ts index 78bf94f5f..9b995e3bd 100644 --- a/src/addons/mod/wiki/services/handlers/page-or-map-link.ts +++ b/src/addons/mod/wiki/services/handlers/page-or-map-link.ts @@ -17,6 +17,7 @@ import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourse } from '@features/course/services/course'; import { CoreNavigator } from '@services/navigator'; +import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { makeSingleton } from '@singletons'; import { Md5 } from 'ts-md5'; @@ -40,11 +41,8 @@ export class AddonModWikiPageOrMapLinkHandlerService extends CoreContentLinksHan siteIds: string[], url: string, params: Record, - courseId?: number, ): CoreContentLinksAction[] | Promise { - courseId = Number(courseId || params.courseid || params.cid); - return [{ action: async (siteId: string) => { const modal = await CoreDomUtils.showModalLoading(); @@ -55,7 +53,11 @@ export class AddonModWikiPageOrMapLinkHandlerService extends CoreContentLinksHan // Get the page data to obtain wikiId, subwikiId, etc. const page = await AddonModWiki.getPageContents(pageId, { siteId }); - const module = await CoreCourse.getModuleBasicInfoByInstance(page.wikiid, 'wiki', siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance( + page.wikiid, + 'wiki', + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); const hash = Md5.hashAsciiStr(JSON.stringify({ pageId: page.id, @@ -64,10 +66,9 @@ export class AddonModWikiPageOrMapLinkHandlerService extends CoreContentLinksHan action: action, timestamp: Date.now(), })); - courseId = courseId || module.course; CoreNavigator.navigateToSitePath( - AddonModWikiModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/page/${hash}`, + AddonModWikiModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/page/${hash}`, { params: { module, @@ -97,7 +98,7 @@ export class AddonModWikiPageOrMapLinkHandlerService extends CoreContentLinksHan if (params.id && !isMap) { // ID param is more prioritary than pageid in index page, it's a index URL. return false; - } else if (isMap && typeof params.option != 'undefined' && params.option != '5') { + } else if (isMap && params.option !== undefined && params.option != '5') { // Map link but the option isn't "Page list", not supported. return false; } diff --git a/src/addons/mod/wiki/services/handlers/prefetch.ts b/src/addons/mod/wiki/services/handlers/prefetch.ts index d6b3b4179..c804afecd 100644 --- a/src/addons/mod/wiki/services/handlers/prefetch.ts +++ b/src/addons/mod/wiki/services/handlers/prefetch.ts @@ -14,8 +14,7 @@ import { Injectable } from '@angular/core'; import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler'; -import { CoreCourseAnyModuleData } from '@features/course/services/course'; -import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course'; import { CoreFilepool } from '@services/filepool'; import { CoreGroups } from '@services/groups'; import { CoreFileSizeSum, CorePluginFileDelegate } from '@services/plugin-file-delegate'; @@ -190,7 +189,7 @@ export class AddonModWikiPrefetchHandlerService extends CoreCourseActivityPrefet // Fetch info to provide wiki links. promises.push(AddonModWiki.getWiki(courseId, module.id, { siteId }).then((wiki) => - CoreCourseHelper.getModuleCourseIdByInstance(wiki.id, 'wiki', siteId))); + CoreCourse.getModuleBasicInfoByInstance(wiki.id, 'wiki', { siteId }))); // Get related page files and fetch them. promises.push(this.getFiles(module, courseId, single, siteId).then((files) => @@ -203,7 +202,7 @@ export class AddonModWikiPrefetchHandlerService extends CoreCourseActivityPrefet * @inheritdoc */ sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { - return AddonModWikiSync.syncWiki(module.instance!, module.course, module.id, siteId); + return AddonModWikiSync.syncWiki(module.instance, module.course, module.id, siteId); } } diff --git a/src/addons/mod/wiki/services/wiki.ts b/src/addons/mod/wiki/services/wiki.ts index 580e9f20d..c237c7856 100644 --- a/src/addons/mod/wiki/services/wiki.ts +++ b/src/addons/mod/wiki/services/wiki.ts @@ -58,7 +58,7 @@ export class AddonModWikiProvider { * @param wikiId wiki Id, if not provided all will be cleared. */ clearSubwikiList(wikiId?: number): void { - if (typeof wikiId == 'undefined') { + if (wikiId === undefined) { this.subwikiListsCache = {}; } else { delete this.subwikiListsCache[wikiId]; diff --git a/src/addons/mod/workshop/components/assessment/assessment.ts b/src/addons/mod/workshop/components/assessment/assessment.ts index f165e0105..5ca172f55 100644 --- a/src/addons/mod/workshop/components/assessment/assessment.ts +++ b/src/addons/mod/workshop/components/assessment/assessment.ts @@ -14,7 +14,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { Params } from '@angular/router'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreUser, CoreUserProfile } from '@features/user/services/user'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; @@ -41,7 +41,7 @@ export class AddonModWorkshopAssessmentComponent implements OnInit { @Input() workshop!: AddonModWorkshopData; @Input() access!: AddonModWorkshopGetWorkshopAccessInformationWSResponse; @Input() submission!: AddonModWorkshopSubmissionDataWithOfflineData; - @Input() module!: CoreCourseModule; + @Input() module!: CoreCourseModuleData; canViewAssessment = false; canSelfAssess = false; diff --git a/src/addons/mod/workshop/components/index/index.ts b/src/addons/mod/workshop/components/index/index.ts index 91c8bba44..f3cd51e4d 100644 --- a/src/addons/mod/workshop/components/index/index.ts +++ b/src/addons/mod/workshop/components/index/index.ts @@ -322,7 +322,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity const offlineData = await AddonModWorkshopHelper.applyOfflineData(submission, this.offlineSubmissions); - if (typeof offlineData != 'undefined') { + if (offlineData !== undefined) { this.grades!.push(offlineData); } })); diff --git a/src/addons/mod/workshop/components/submission/submission.ts b/src/addons/mod/workshop/components/submission/submission.ts index ef3a0cf4d..fc05e97b3 100644 --- a/src/addons/mod/workshop/components/submission/submission.ts +++ b/src/addons/mod/workshop/components/submission/submission.ts @@ -14,7 +14,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { Params } from '@angular/router'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreUser, CoreUserProfile } from '@features/user/services/user'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; @@ -44,7 +44,7 @@ import { AddonModWorkshopOffline } from '../../services/workshop-offline'; export class AddonModWorkshopSubmissionComponent implements OnInit { @Input() submission!: AddonModWorkshopSubmissionDataWithOfflineData; - @Input() module!: CoreCourseModule; + @Input() module!: CoreCourseModuleData; @Input() workshop!: AddonModWorkshopData; @Input() access!: AddonModWorkshopGetWorkshopAccessInformationWSResponse; @Input() courseId!: number; diff --git a/src/addons/mod/workshop/pages/edit-submission/edit-submission.ts b/src/addons/mod/workshop/pages/edit-submission/edit-submission.ts index c91033454..aa215a1ce 100644 --- a/src/addons/mod/workshop/pages/edit-submission/edit-submission.ts +++ b/src/addons/mod/workshop/pages/edit-submission/edit-submission.ts @@ -15,7 +15,7 @@ import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { CoreError } from '@classes/errors/error'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader'; import { CanLeave } from '@guards/can-leave'; import { CoreFile } from '@services/file'; @@ -51,7 +51,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca @ViewChild('editFormEl') formElement!: ElementRef; - module!: CoreCourseModule; + module!: CoreCourseModuleData; courseId!: number; access!: AddonModWorkshopGetWorkshopAccessInformationWSResponse; submission?: AddonModWorkshopSubmissionDataWithOfflineData; @@ -100,7 +100,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca */ ngOnInit(): void { try { - this.module = CoreNavigator.getRequiredRouteParam('module'); + this.module = CoreNavigator.getRequiredRouteParam('module'); this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId'); this.access = CoreNavigator.getRequiredRouteParam('access'); this.submissionId = CoreNavigator.getRouteNumberParam('submissionId') || 0; @@ -116,7 +116,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca this.editorExtraParams.id = this.submissionId; } - this.workshopId = this.module.instance!; + this.workshopId = this.module.instance; this.componentId = this.module.id; if (!this.isDestroyed) { diff --git a/src/addons/mod/workshop/pages/submission/submission.ts b/src/addons/mod/workshop/pages/submission/submission.ts index dee18605e..a131065af 100644 --- a/src/addons/mod/workshop/pages/submission/submission.ts +++ b/src/addons/mod/workshop/pages/submission/submission.ts @@ -16,7 +16,7 @@ import { Component, OnInit, OnDestroy, Optional, ViewChild, ElementRef } from '@ import { FormGroup, FormBuilder } from '@angular/forms'; import { Params } from '@angular/router'; import { CoreCourse } from '@features/course/services/course'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreGradesHelper, CoreGradesMenuItem } from '@features/grades/services/grades-helper'; import { CoreUser, CoreUserProfile } from '@features/user/services/user'; import { CanLeave } from '@guards/can-leave'; @@ -61,7 +61,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea @ViewChild('feedbackFormEl') formElement?: ElementRef; - module!: CoreCourseModule; + module!: CoreCourseModuleData; workshop!: AddonModWorkshopData; access!: AddonModWorkshopGetWorkshopAccessInformationWSResponse; assessment?: AddonModWorkshopSubmissionAssessmentWithFormData; @@ -132,7 +132,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea async ngOnInit(): Promise { try { this.submissionId = CoreNavigator.getRequiredRouteNumberParam('submissionId'); - this.module = CoreNavigator.getRequiredRouteParam('module'); + this.module = CoreNavigator.getRequiredRouteParam('module'); this.workshop = CoreNavigator.getRequiredRouteParam('workshop'); this.access = CoreNavigator.getRequiredRouteParam('access'); this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId'); diff --git a/src/addons/mod/workshop/services/handlers/prefetch.ts b/src/addons/mod/workshop/services/handlers/prefetch.ts index ad986d253..789b57f9f 100644 --- a/src/addons/mod/workshop/services/handlers/prefetch.ts +++ b/src/addons/mod/workshop/services/handlers/prefetch.ts @@ -160,7 +160,7 @@ export class AddonModWorkshopPrefetchHandlerService extends CoreCourseActivityPr return { workshop, groups, - files: files.filter((file) => typeof file !== 'undefined'), + files: files.filter((file) => file !== undefined), }; } catch (error) { if (options.omitFail) { @@ -168,7 +168,7 @@ export class AddonModWorkshopPrefetchHandlerService extends CoreCourseActivityPr return { workshop, groups, - files: files.filter((file) => typeof file !== 'undefined'), + files: files.filter((file) => file !== undefined), }; } @@ -363,7 +363,7 @@ export class AddonModWorkshopPrefetchHandlerService extends CoreCourseActivityPr })); // Add Basic Info to manage links. - promises.push(CoreCourse.getModuleBasicInfoByInstance(workshop.id, 'workshop', siteId)); + promises.push(CoreCourse.getModuleBasicInfoByInstance(workshop.id, 'workshop', { siteId })); promises.push(CoreCourse.getModuleBasicGradeInfo(module.id, siteId)); // Get course data, needed to determine upload max size if it's configured to be course limit. @@ -379,7 +379,7 @@ export class AddonModWorkshopPrefetchHandlerService extends CoreCourseActivityPr * @inheritdoc */ async sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise { - return AddonModWorkshopSync.syncWorkshop(module.instance!, siteId); + return AddonModWorkshopSync.syncWorkshop(module.instance, siteId); } } diff --git a/src/addons/mod/workshop/services/workshop-helper.ts b/src/addons/mod/workshop/services/workshop-helper.ts index 7f355f5ac..94eb54851 100644 --- a/src/addons/mod/workshop/services/workshop-helper.ts +++ b/src/addons/mod/workshop/services/workshop-helper.ts @@ -460,7 +460,7 @@ export class AddonModWorkshopHelperProvider { return submission; } - if (typeof submission == 'undefined') { + if (submission === undefined) { submission = { id: 0, workshopid: 0, @@ -559,7 +559,7 @@ export class AddonModWorkshopHelperProvider { return value; } - if (value == null || typeof value == 'undefined') { + if (value == null || value === undefined) { return undefined; } @@ -602,7 +602,7 @@ export class AddonModWorkshopHelperProvider { * @return If grade should be shown or not. */ showGrade(grade?: number|string): boolean { - return typeof grade !== 'undefined' && grade !== null; + return grade !== undefined && grade !== null; } } diff --git a/src/addons/mod/workshop/services/workshop.ts b/src/addons/mod/workshop/services/workshop.ts index 53bc85119..59ab0c196 100644 --- a/src/addons/mod/workshop/services/workshop.ts +++ b/src/addons/mod/workshop/services/workshop.ts @@ -263,8 +263,8 @@ export class AddonModWorkshopProvider { } // Set submission types for Moodle 3.5. - if (typeof workshop.submissiontypetext == 'undefined') { - if (typeof workshop.nattachments != 'undefined' && workshop.nattachments > 0) { + if (workshop.submissiontypetext === undefined) { + if (workshop.nattachments !== undefined && workshop.nattachments > 0) { workshop.submissiontypetext = AddonModWorkshopSubmissionType.SUBMISSION_TYPE_AVAILABLE; workshop.submissiontypefile = AddonModWorkshopSubmissionType.SUBMISSION_TYPE_AVAILABLE; } else { diff --git a/src/addons/notes/pages/list/list.page.ts b/src/addons/notes/pages/list/list.page.ts index 4480fc250..be375f2dd 100644 --- a/src/addons/notes/pages/list/list.page.ts +++ b/src/addons/notes/pages/list/list.page.ts @@ -195,7 +195,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy { }, }); - if (typeof modalData != 'undefined') { + if (modalData !== undefined) { if (modalData.sent && modalData.type) { if (modalData.type != this.type) { diff --git a/src/addons/notes/services/handlers/course-option.ts b/src/addons/notes/services/handlers/course-option.ts index 80ae7da99..646af845c 100644 --- a/src/addons/notes/services/handlers/course-option.ts +++ b/src/addons/notes/services/handlers/course-option.ts @@ -52,7 +52,7 @@ export class AddonNotesCourseOptionHandlerService implements CoreCourseOptionsHa return false; // Not enabled for guests. } - if (navOptions && typeof navOptions.notes != 'undefined') { + if (navOptions && navOptions.notes !== undefined) { return navOptions.notes; } diff --git a/src/addons/notes/services/notes-sync.ts b/src/addons/notes/services/notes-sync.ts index 218b18418..ba85ee026 100644 --- a/src/addons/notes/services/notes-sync.ts +++ b/src/addons/notes/services/notes-sync.ts @@ -75,7 +75,7 @@ export class AddonNotesSyncProvider extends CoreSyncBaseProvider this.ddQuestion.initObjects.drops; } - if (typeof this.ddQuestion.initObjects.readonly != 'undefined') { + if (this.ddQuestion.initObjects.readonly !== undefined) { this.ddQuestion.readOnly = !!this.ddQuestion.initObjects.readonly; } } else if (this.ddQuestion.amdArgs) { // Moodle version >= 3.6. - if (typeof this.ddQuestion.amdArgs[1] != 'undefined') { + if (this.ddQuestion.amdArgs[1] !== undefined) { this.ddQuestion.readOnly = !!this.ddQuestion.amdArgs[1]; } - if (typeof this.ddQuestion.amdArgs[2] != 'undefined') { + if (this.ddQuestion.amdArgs[2] !== undefined) { this.drops = this.ddQuestion.amdArgs[2]; } } diff --git a/src/addons/qtype/ddmarker/classes/ddmarker.ts b/src/addons/qtype/ddmarker/classes/ddmarker.ts index a8fca0b21..1e747e0de 100644 --- a/src/addons/qtype/ddmarker/classes/ddmarker.ts +++ b/src/addons/qtype/ddmarker/classes/ddmarker.ts @@ -499,7 +499,7 @@ export class AddonQtypeDdMarkerQuestion { const dragging = !!this.doc.dragItemBeingDragged(choiceNo); const coords: number[][] = []; - if (fv !== '' && typeof fv != 'undefined' && fv !== null) { + if (fv !== '' && fv !== undefined && fv !== null) { // Get all the coordinates in the input and add them to the coords list. const coordsStrings = fv.split(';'); diff --git a/src/addons/qtype/ddmarker/component/ddmarker.ts b/src/addons/qtype/ddmarker/component/ddmarker.ts index 547773271..27bd8ca14 100644 --- a/src/addons/qtype/ddmarker/component/ddmarker.ts +++ b/src/addons/qtype/ddmarker/component/ddmarker.ts @@ -64,7 +64,7 @@ export class AddonQtypeDdMarkerComponent extends CoreQuestionBaseComponent imple const ddForm = element.querySelector('.ddform'); this.ddQuestion.text = CoreDomUtils.getContentsOfElement(element, '.qtext'); - if (!ddArea || !ddForm || typeof this.ddQuestion.text == 'undefined') { + if (!ddArea || !ddForm || this.ddQuestion.text === undefined) { this.logger.warn('Aborting because of an error parsing question.', this.ddQuestion.slot); return CoreQuestionHelper.showComponentError(this.onAbort); @@ -82,10 +82,10 @@ export class AddonQtypeDdMarkerComponent extends CoreQuestionBaseComponent imple if (this.ddQuestion.initObjects) { // Moodle version = 3.5. - if (typeof this.ddQuestion.initObjects.dropzones != 'undefined') { + if (this.ddQuestion.initObjects.dropzones !== undefined) { this.dropZones = this.ddQuestion.initObjects.dropzones; } - if (typeof this.ddQuestion.initObjects.readonly != 'undefined') { + if (this.ddQuestion.initObjects.readonly !== undefined) { this.ddQuestion.readOnly = !!this.ddQuestion.initObjects.readonly; } } else if (this.ddQuestion.amdArgs) { @@ -97,12 +97,12 @@ export class AddonQtypeDdMarkerComponent extends CoreQuestionBaseComponent imple nextIndex++; } - if (typeof this.ddQuestion.amdArgs[nextIndex] != 'undefined') { + if (this.ddQuestion.amdArgs[nextIndex] !== undefined) { this.ddQuestion.readOnly = !!this.ddQuestion.amdArgs[nextIndex]; } nextIndex++; - if (typeof this.ddQuestion.amdArgs[nextIndex] != 'undefined') { + if (this.ddQuestion.amdArgs[nextIndex] !== undefined) { this.dropZones = this.ddQuestion.amdArgs[nextIndex]; } } diff --git a/src/addons/qtype/ddwtos/component/ddwtos.ts b/src/addons/qtype/ddwtos/component/ddwtos.ts index bbafd79cc..befd2c3a3 100644 --- a/src/addons/qtype/ddwtos/component/ddwtos.ts +++ b/src/addons/qtype/ddwtos/component/ddwtos.ts @@ -74,7 +74,7 @@ export class AddonQtypeDdwtosComponent extends CoreQuestionBaseComponent impleme this.ddQuestion.answers = answerContainer.outerHTML; this.ddQuestion.text = CoreDomUtils.getContentsOfElement(element, '.qtext'); - if (typeof this.ddQuestion.text == 'undefined') { + if (this.ddQuestion.text === undefined) { this.logger.warn('Aborting because of an error parsing question.', this.ddQuestion.slot); return CoreQuestionHelper.showComponentError(this.onAbort); diff --git a/src/addons/qtype/essay/component/essay.ts b/src/addons/qtype/essay/component/essay.ts index 16e1c75d2..64df2a9fc 100644 --- a/src/addons/qtype/essay/component/essay.ts +++ b/src/addons/qtype/essay/component/essay.ts @@ -45,7 +45,7 @@ export class AddonQtypeEssayComponent extends CoreQuestionBaseComponent implemen * Component being initialized. */ ngOnInit(): void { - this.uploadFilesSupported = typeof this.question?.responsefileareas != 'undefined'; + this.uploadFilesSupported = this.question?.responsefileareas !== undefined; this.initEssayComponent(this.review); this.essayQuestion = this.question; diff --git a/src/addons/qtype/essay/services/handlers/essay.ts b/src/addons/qtype/essay/services/handlers/essay.ts index cb6c91646..707c9737e 100644 --- a/src/addons/qtype/essay/services/handlers/essay.ts +++ b/src/addons/qtype/essay/services/handlers/essay.ts @@ -143,7 +143,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { */ getPreventSubmitMessage(question: CoreQuestionQuestionParsed): string | undefined { const element = CoreDomUtils.convertToElement(question.html); - const uploadFilesSupported = typeof question.responsefileareas != 'undefined'; + const uploadFilesSupported = question.responsefileareas !== undefined; if (!uploadFilesSupported && element.querySelector('div[id*=filemanager]')) { // The question allows attachments. Since the app cannot attach files yet we will prevent submitting the question. @@ -229,7 +229,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { ): number { const hasTextAnswer = !!answers.answer; - const uploadFilesSupported = typeof question.responsefileareas != 'undefined'; + const uploadFilesSupported = question.responsefileareas !== undefined; const allowedOptions = this.getAllowedOptions(question); if (hasTextAnswer && this.checkInputWordCount(question, answers.answer, undefined)) { @@ -281,7 +281,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { component: string, componentId: string | number, ): number { - if (typeof question.responsefileareas == 'undefined') { + if (question.responsefileareas === undefined) { return -1; } @@ -309,7 +309,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { component: string, componentId: string | number, ): boolean { - const uploadFilesSupported = typeof question.responsefileareas != 'undefined'; + const uploadFilesSupported = question.responsefileareas !== undefined; const allowedOptions = this.getAllowedOptions(question); // First check the inline text. @@ -355,7 +355,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { // Search the textarea to get its name. const textarea = element.querySelector('textarea[name*=_answer]'); - if (textarea && typeof answers[textarea.name] != 'undefined') { + if (textarea && answers[textarea.name] !== undefined) { await this.prepareTextAnswer(question, answers, textarea, siteId); } diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.ts b/src/addons/storagemanager/pages/course-storage/course-storage.ts index e52ddb0e0..80e28b258 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.ts +++ b/src/addons/storagemanager/pages/course-storage/course-storage.ts @@ -15,7 +15,7 @@ import { CoreConstants } from '@/core/constants'; import { Component, OnInit } from '@angular/core'; import { CoreCourse } from '@features/course/services/course'; -import { CoreCourseHelper, CoreCourseModule, CoreCourseSection } from '@features/course/services/course-helper'; +import { CoreCourseHelper, CoreCourseModuleData, CoreCourseSection } from '@features/course/services/course-helper'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; import { CoreEnrolledCourseData } from '@features/courses/services/courses'; import { CoreNavigator } from '@services/navigator'; @@ -52,8 +52,8 @@ export class AddonStorageManagerCourseStoragePage implements OnInit { return; } - this.sections = await CoreCourse.getSections(this.course.id, false, true); - CoreCourseHelper.addHandlerDataForModules(this.sections, this.course.id); + const sections = await CoreCourse.getSections(this.course.id, false, true); + this.sections = CoreCourseHelper.addHandlerDataForModules(sections, this.course.id).sections; this.totalSize = 0; @@ -231,7 +231,7 @@ type AddonStorageManagerCourseSection = Omit & { modules: AddonStorageManagerModule[]; }; -type AddonStorageManagerModule = CoreCourseModule & { +type AddonStorageManagerModule = CoreCourseModuleData & { parentSection?: AddonStorageManagerCourseSection; totalSize?: number; }; diff --git a/src/addons/userprofilefield/checkbox/services/handlers/checkbox.ts b/src/addons/userprofilefield/checkbox/services/handlers/checkbox.ts index 887770465..643738a62 100644 --- a/src/addons/userprofilefield/checkbox/services/handlers/checkbox.ts +++ b/src/addons/userprofilefield/checkbox/services/handlers/checkbox.ts @@ -56,7 +56,7 @@ export class AddonUserProfileFieldCheckboxHandlerService implements CoreUserProf ): Promise { const name = 'profile_field_' + field.shortname; - if (typeof formValues[name] != 'undefined') { + if (formValues[name] !== undefined) { return { type: 'checkbox', name: name, diff --git a/src/core/classes/base-sync.ts b/src/core/classes/base-sync.ts index 8849ec24c..417b03ff6 100644 --- a/src/core/classes/base-sync.ts +++ b/src/core/classes/base-sync.ts @@ -244,7 +244,7 @@ export class CoreSyncBaseProvider { * @return Promise resolved when the time is set. */ async setSyncTime(id: string | number, siteId?: string, time?: number): Promise { - time = typeof time != 'undefined' ? time : Date.now(); + time = time !== undefined ? time : Date.now(); await CoreSync.insertOrUpdateSyncRecord(this.component, id, { time: time }, siteId); } diff --git a/src/core/classes/cache.ts b/src/core/classes/cache.ts index 833ecac56..325669148 100644 --- a/src/core/classes/cache.ts +++ b/src/core/classes/cache.ts @@ -58,7 +58,7 @@ export class CoreCache { getValue(id: string, name: string, ignoreInvalidate = false): T | undefined { const entry = this.getEntry(id); - if (entry[name] && typeof entry[name].value != 'undefined') { + if (entry[name] && entry[name].value !== undefined) { const now = Date.now(); // Invalidate after 5 minutes. if (ignoreInvalidate || entry[name].timemodified + 300000 >= now) { diff --git a/src/core/classes/delegate.ts b/src/core/classes/delegate.ts index 3e5e7aac3..588f0ce9f 100644 --- a/src/core/classes/delegate.ts +++ b/src/core/classes/delegate.ts @@ -199,7 +199,7 @@ export class CoreDelegate { * @return If the handler is registered or not. */ hasHandler(name: string, enabled: boolean = false): boolean { - return enabled ? typeof this.enabledHandlers[name] !== 'undefined' : typeof this.handlers[name] !== 'undefined'; + return enabled ? this.enabledHandlers[name] !== undefined : this.handlers[name] !== undefined; } /** @@ -226,7 +226,7 @@ export class CoreDelegate { registerHandler(handler: HandlerType): boolean { const key = handler[this.handlerNameProperty] || handler.name; - if (typeof this.handlers[key] !== 'undefined') { + if (this.handlers[key] !== undefined) { this.logger.log(`Handler '${handler[this.handlerNameProperty]}' already registered`); return false; @@ -293,7 +293,7 @@ export class CoreDelegate { * @return Whether is enabled or disabled in site. */ protected isFeatureDisabled(handler: HandlerType, site: CoreSite): boolean { - return typeof this.featurePrefix != 'undefined' && site.isFeatureDisabled(this.featurePrefix + handler.name); + return this.featurePrefix !== undefined && site.isFeatureDisabled(this.featurePrefix + handler.name); } /** diff --git a/src/core/classes/errors/ajaxwserror.ts b/src/core/classes/errors/ajaxwserror.ts index 338a0706a..b21eedd1b 100644 --- a/src/core/classes/errors/ajaxwserror.ts +++ b/src/core/classes/errors/ajaxwserror.ts @@ -41,7 +41,7 @@ export class CoreAjaxWSError extends CoreError { this.backtrace = error.backtrace; this.available = available; - if (typeof this.available == 'undefined') { + if (this.available === undefined) { if (this.errorcode) { this.available = this.errorcode == 'invalidrecord' ? -1 : 1; } else { diff --git a/src/core/classes/interceptor.ts b/src/core/classes/interceptor.ts index 34c8e4f4d..5ddbe7d11 100644 --- a/src/core/classes/interceptor.ts +++ b/src/core/classes/interceptor.ts @@ -53,7 +53,7 @@ export class CoreInterceptor implements HttpInterceptor { innerObj[fullSubName] = subValue; query += this.serialize(innerObj) + '&'; } - } else if (addNull || (typeof value != 'undefined' && value !== null)) { + } else if (addNull || (value !== undefined && value !== null)) { query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; } } diff --git a/src/core/classes/site.ts b/src/core/classes/site.ts index 201b23ba1..b6f17c472 100644 --- a/src/core/classes/site.ts +++ b/src/core/classes/site.ts @@ -355,7 +355,7 @@ export class CoreSite { * @return Whether the user authenticated in the site using an OAuth method. */ isOAuth(): boolean { - return this.oauthId != null && typeof this.oauthId != 'undefined'; + return this.oauthId != null && this.oauthId !== undefined; } /** @@ -366,7 +366,7 @@ export class CoreSite { canAccessMyFiles(): boolean { const info = this.getInfo(); - return !!(info && (typeof info.usercanmanageownfiles === 'undefined' || info.usercanmanageownfiles)); + return !!(info && (info.usercanmanageownfiles === undefined || info.usercanmanageownfiles)); } /** @@ -390,7 +390,7 @@ export class CoreSite { canUseAdvancedFeature(featureName: string, whenUndefined: boolean = true): boolean { const info = this.getInfo(); - if (typeof info?.advancedfeatures === 'undefined') { + if (info?.advancedfeatures === undefined) { return whenUndefined; } @@ -444,13 +444,13 @@ export class CoreSite { // eslint-disable-next-line @typescript-eslint/no-explicit-any read(method: string, data: any, preSets?: CoreSiteWSPreSets): Promise { preSets = preSets || {}; - if (typeof preSets.getFromCache == 'undefined') { + if (preSets.getFromCache === undefined) { preSets.getFromCache = true; } - if (typeof preSets.saveToCache == 'undefined') { + if (preSets.saveToCache === undefined) { preSets.saveToCache = true; } - if (typeof preSets.reusePending == 'undefined') { + if (preSets.reusePending === undefined) { preSets.reusePending = true; } @@ -468,13 +468,13 @@ export class CoreSite { // eslint-disable-next-line @typescript-eslint/no-explicit-any write(method: string, data: any, preSets?: CoreSiteWSPreSets): Promise { preSets = preSets || {}; - if (typeof preSets.getFromCache == 'undefined') { + if (preSets.getFromCache === undefined) { preSets.getFromCache = false; } - if (typeof preSets.saveToCache == 'undefined') { + if (preSets.saveToCache === undefined) { preSets.saveToCache = false; } - if (typeof preSets.emergencyCache == 'undefined') { + if (preSets.emergencyCache === undefined) { preSets.emergencyCache = false; } @@ -655,7 +655,7 @@ export class CoreSite { this.saveToCache(method, data, error, preSets); throw new CoreWSError(error); - } else if (typeof preSets.emergencyCache !== 'undefined' && !preSets.emergencyCache) { + } else if (preSets.emergencyCache !== undefined && !preSets.emergencyCache) { this.logger.debug(`WS call '${method}' failed. Emergency cache is forbidden, rejecting.`); throw new CoreWSError(error); @@ -681,7 +681,7 @@ export class CoreSite { // eslint-disable-next-line @typescript-eslint/no-explicit-any }).then((response: any) => { // Check if the response is an error, this happens if the error was stored in the cache. - if (response && (typeof response.exception != 'undefined' || typeof response.errorcode != 'undefined')) { + if (response && (response.exception !== undefined || response.errorcode !== undefined)) { throw new CoreWSError(response); } @@ -857,7 +857,7 @@ export class CoreSite { } else { let responseData = response.data ? CoreTextUtils.parseJSON(response.data) : {}; // Match the behaviour of CoreWSProvider.call when no response is expected. - const responseExpected = typeof wsPresets.responseExpected == 'undefined' || wsPresets.responseExpected; + const responseExpected = wsPresets.responseExpected === undefined || wsPresets.responseExpected; if (!responseExpected && (responseData == null || responseData === '')) { responseData = {}; } @@ -938,7 +938,7 @@ export class CoreSite { entry = await db.getRecord(CoreSite.WS_CACHE_TABLE, { id }); } - if (typeof entry == 'undefined') { + if (entry === undefined) { throw new CoreError('Cache entry not valid.'); } @@ -957,7 +957,7 @@ export class CoreSite { } } - if (typeof entry.data != 'undefined') { + if (entry.data !== undefined) { if (!expirationTime) { this.logger.info(`Cached element found, id: ${id}. Expiration time ignored.`); } else { @@ -1206,7 +1206,7 @@ export class CoreSite { * @return Fixed URL. */ fixPluginfileURL(url: string): string { - const accessKey = this.tokenPluginFileWorks || typeof this.tokenPluginFileWorks == 'undefined' ? + const accessKey = this.tokenPluginFileWorks || this.tokenPluginFileWorks === undefined ? this.infos && this.infos.userprivateaccesskey : undefined; return CoreUrlUtils.fixPluginfileURL(url, this.token || '', this.siteUrl, accessKey); @@ -1829,7 +1829,7 @@ export class CoreSite { return entry.value; } catch (error) { - if (typeof defaultValue != 'undefined') { + if (defaultValue !== undefined) { return defaultValue; } @@ -1876,7 +1876,7 @@ export class CoreSite { if (!CoreUrlUtils.canUseTokenPluginFile(url, this.siteUrl, this.infos && this.infos.userprivateaccesskey)) { // Cannot use tokenpluginfile. return Promise.resolve(false); - } else if (typeof this.tokenPluginFileWorks != 'undefined') { + } else if (this.tokenPluginFileWorks !== undefined) { // Already checked. return Promise.resolve(this.tokenPluginFileWorks); } else if (this.tokenPluginFileWorksPromise) { diff --git a/src/core/classes/sqlitedb.ts b/src/core/classes/sqlitedb.ts index 9455e4c6a..c84c52ccd 100644 --- a/src/core/classes/sqlitedb.ts +++ b/src/core/classes/sqlitedb.ts @@ -221,7 +221,7 @@ export class SQLiteDB { columnSql += ` CHECK (${column.check})`; } - if (typeof column.default != 'undefined') { + if (column.default !== undefined) { columnSql += ` DEFAULT ${column.default}`; } @@ -388,7 +388,7 @@ export class SQLiteDB { * @return Promise resolved with the number of affected rows. */ async deleteRecords(table: string, conditions?: SQLiteDBRecordValues): Promise { - if (conditions === null || typeof conditions == 'undefined') { + if (conditions === null || conditions === undefined) { // No conditions, delete the whole table. const result = await this.execute(`DELETE FROM ${table}`); @@ -485,7 +485,7 @@ export class SQLiteDB { // Remove undefined entries and convert null to "NULL". for (const name in data) { - if (typeof data[name] == 'undefined') { + if (data[name] === undefined) { delete data[name]; } } @@ -581,13 +581,13 @@ export class SQLiteDB { let params: SQLiteDBRecordValue[]; // Default behavior, return empty data on empty array. - if (Array.isArray(items) && !items.length && typeof onEmptyItems == 'undefined') { + if (Array.isArray(items) && !items.length && onEmptyItems === undefined) { return { sql: '', params: [] }; } // Handle onEmptyItems on empty array of items. if (Array.isArray(items) && !items.length) { - if (onEmptyItems === null || typeof onEmptyItems === 'undefined') { // Special case, NULL value. + if (onEmptyItems === null || onEmptyItems === undefined) { // Special case, NULL value. sql = equal ? ' IS NULL' : ' IS NOT NULL'; return { sql, params: [] }; @@ -1091,7 +1091,7 @@ export class SQLiteDB { for (const key in conditions) { const value = conditions[key]; - if (typeof value == 'undefined' || value === null) { + if (value === undefined || value === null) { where.push(key + ' IS NULL'); } else { where.push(key + ' = ?'); @@ -1124,7 +1124,7 @@ export class SQLiteDB { let sql = ''; values.forEach((value) => { - if (typeof value == 'undefined' || value === null) { + if (value === undefined || value === null) { sql = field + ' IS NULL'; } else { params.push(value); diff --git a/src/core/classes/tabs.ts b/src/core/classes/tabs.ts index b03b8f827..76527de07 100644 --- a/src/core/classes/tabs.ts +++ b/src/core/classes/tabs.ts @@ -427,7 +427,7 @@ export class CoreTabsBaseComponent implements OnInit, Aft this.slides!.slideTo(this.maxSlides); } else { const currentIndex = await this.slides!.getActiveIndex(); - if (typeof currentIndex !== 'undefined') { + if (currentIndex !== undefined) { const nextSlideIndex = currentIndex + this.maxSlides; this.isInTransition = true; if (nextSlideIndex < this.numTabsShown) { @@ -456,7 +456,7 @@ export class CoreTabsBaseComponent implements OnInit, Aft // Slide to the previous of the latest page. } else { const currentIndex = await this.slides!.getActiveIndex(); - if (typeof currentIndex !== 'undefined') { + if (currentIndex !== undefined) { const prevSlideIndex = currentIndex - this.maxSlides; this.isInTransition = true; if (prevSlideIndex >= 0) { diff --git a/src/core/components/chart/chart.ts b/src/core/components/chart/chart.ts index dbff890ca..cd792d859 100644 --- a/src/core/components/chart/chart.ts +++ b/src/core/components/chart/chart.ts @@ -64,7 +64,7 @@ export class CoreChartComponent implements OnDestroy, OnInit, OnChanges { */ async ngOnInit(): Promise { let legend: ChartLegendOptions = {}; - if (typeof this.legend == 'undefined') { + if (this.legend === undefined) { legend = { display: false, labels: { diff --git a/src/core/components/chrono/chrono.ts b/src/core/components/chrono/chrono.ts index 179ad69f8..b111a9b0e 100644 --- a/src/core/components/chrono/chrono.ts +++ b/src/core/components/chrono/chrono.ts @@ -102,7 +102,7 @@ export class CoreChronoComponent implements OnInit, OnChanges, OnDestroy { this.time += Date.now() - lastExecTime; lastExecTime = Date.now(); - if (typeof this.endTime != 'undefined' && this.time > this.endTime) { + if (this.endTime !== undefined && this.time > this.endTime) { // End time reached, stop the timer and call the end function. this.stop(); this.onEnd.emit(); diff --git a/src/core/components/progress-bar/progress-bar.ts b/src/core/components/progress-bar/progress-bar.ts index ec65e69bc..ae6f86fcc 100644 --- a/src/core/components/progress-bar/progress-bar.ts +++ b/src/core/components/progress-bar/progress-bar.ts @@ -44,7 +44,7 @@ export class CoreProgressBarComponent implements OnChanges { * Detect changes on input properties. */ ngOnChanges(changes: { [name: string]: SimpleChange }): void { - if (changes.text && typeof changes.text.currentValue != 'undefined') { + if (changes.text && changes.text.currentValue !== undefined) { // User provided a custom text, don't use default. this.textSupplied = true; } diff --git a/src/core/components/tabs-outlet/tabs-outlet.ts b/src/core/components/tabs-outlet/tabs-outlet.ts index 1783496b4..54da61022 100644 --- a/src/core/components/tabs-outlet/tabs-outlet.ts +++ b/src/core/components/tabs-outlet/tabs-outlet.ts @@ -80,7 +80,7 @@ export class CoreTabsOutletComponent extends CoreTabsBaseComponent forceOpenLinksIn setting > data-open-in HTML attribute. let openInApp = this.inApp; - if (typeof this.inApp == 'undefined') { + if (this.inApp === undefined) { if (CoreConstants.CONFIG.forceOpenLinksIn == 'browser') { openInApp = false; } else if (CoreConstants.CONFIG.forceOpenLinksIn == 'app' || openIn == 'app') { diff --git a/src/core/directives/supress-events.ts b/src/core/directives/supress-events.ts index 0ec7aab2e..559558129 100644 --- a/src/core/directives/supress-events.ts +++ b/src/core/directives/supress-events.ts @@ -63,7 +63,7 @@ export class CoreSupressEventsDirective implements OnInit { let events: string[]; - if (this.suppressEvents == 'all' || typeof this.suppressEvents == 'undefined' || this.suppressEvents === null) { + if (this.suppressEvents == 'all' || this.suppressEvents === undefined || this.suppressEvents === null) { // Suppress all events. events = ['click', 'mousedown', 'touchdown', 'touchmove', 'touchstart']; diff --git a/src/core/features/comments/components/comments/comments.ts b/src/core/features/comments/components/comments/comments.ts index 8e8683cac..04c45f389 100644 --- a/src/core/features/comments/components/comments/comments.ts +++ b/src/core/features/comments/components/comments/comments.ts @@ -211,7 +211,7 @@ export class CoreCommentsCommentsComponent implements OnInit, OnChanges, OnDestr * @return Whether it's undefined or equal. */ protected undefinedOrEqual(data: Record, name: string): boolean { - return typeof data[name] == 'undefined' || data[name] == this[name]; + return data[name] === undefined || data[name] == this[name]; } } diff --git a/src/core/features/comments/pages/viewer/viewer.page.ts b/src/core/features/comments/pages/viewer/viewer.page.ts index befbfd691..fba333730 100644 --- a/src/core/features/comments/pages/viewer/viewer.page.ts +++ b/src/core/features/comments/pages/viewer/viewer.page.ts @@ -163,7 +163,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { this.canAddComments = this.addDeleteCommentsAvailable && !!commentsResponse.canpost; let comments = commentsResponse.comments.sort((a, b) => a.timecreated - b.timecreated); - if (typeof commentsResponse.count != 'undefined') { + if (commentsResponse.count !== undefined) { this.canLoadMore = (this.comments.length + comments.length) < commentsResponse.count; } else { // Old style. diff --git a/src/core/features/comments/services/comments-sync.ts b/src/core/features/comments/services/comments-sync.ts index f402366f8..277c7e651 100644 --- a/src/core/features/comments/services/comments-sync.ts +++ b/src/core/features/comments/services/comments-sync.ts @@ -92,7 +92,7 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider CoreCommentsProvider.pageSize) { + if (response.count === undefined && response.comments.length > CoreCommentsProvider.pageSize) { CoreCommentsProvider.pageSize = response.comments.length; } @@ -434,7 +434,7 @@ export class CoreCommentsProvider { const response = await this.getComments(contextLevel, instanceId, component, itemId, area, page, siteId); // Count is only available in 3.8 onwards. - if (typeof response.count != 'undefined') { + if (response.count !== undefined) { trueCount = true; return response.count; diff --git a/src/core/features/contentlinks/classes/module-index-handler.ts b/src/core/features/contentlinks/classes/module-index-handler.ts index 3cd4da191..5efc4c83a 100644 --- a/src/core/features/contentlinks/classes/module-index-handler.ts +++ b/src/core/features/contentlinks/classes/module-index-handler.ts @@ -83,7 +83,7 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB courseId = Number(courseId || params.courseid || params.cid); const pageParams = this.getPageParams(url, params, courseId); - if (this.instanceIdParam && typeof params[this.instanceIdParam] != 'undefined') { + if (this.instanceIdParam && params[this.instanceIdParam] !== undefined) { const instanceId = parseInt(params[this.instanceIdParam], 10); return [{ diff --git a/src/core/features/contentlinks/services/contentlinks-delegate.ts b/src/core/features/contentlinks/services/contentlinks-delegate.ts index 8c40a4724..eeaab8bbc 100644 --- a/src/core/features/contentlinks/services/contentlinks-delegate.ts +++ b/src/core/features/contentlinks/services/contentlinks-delegate.ts @@ -278,7 +278,7 @@ export class CoreContentLinksDelegateService { * @return True if registered successfully, false otherwise. */ registerHandler(handler: CoreContentLinksHandler): boolean { - if (typeof this.handlers[handler.name] !== 'undefined') { + if (this.handlers[handler.name] !== undefined) { this.logger.log(`Addon '${handler.name}' already registered`); return false; diff --git a/src/core/features/course/classes/activity-prefetch-handler.ts b/src/core/features/course/classes/activity-prefetch-handler.ts index 1b8617b01..f25c46294 100644 --- a/src/core/features/course/classes/activity-prefetch-handler.ts +++ b/src/core/features/course/classes/activity-prefetch-handler.ts @@ -119,7 +119,7 @@ export class CoreCourseActivityPrefetchHandlerBase extends CoreCourseModulePrefe // Package marked as downloading, get module info to be able to handle links. Get module filters too. await Promise.all([ - CoreCourse.getModuleBasicInfo(module.id, siteId), + CoreCourse.getModuleBasicInfo(module.id, { siteId }), CoreCourse.getModule(module.id, courseId, undefined, false, true, siteId), CoreFilterHelper.getFilters('module', module.id, { courseId }), ]); diff --git a/src/core/features/course/classes/main-activity-page.ts b/src/core/features/course/classes/main-activity-page.ts index de7604457..6d0785f4a 100644 --- a/src/core/features/course/classes/main-activity-page.ts +++ b/src/core/features/course/classes/main-activity-page.ts @@ -15,7 +15,7 @@ import { Component, OnInit } from '@angular/core'; import { CoreNavigator } from '@services/navigator'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreCourseAnyModuleData } from '../services/course'; +import { CoreCourseModuleData } from '../services/course-helper'; import { CoreCourseModuleMainResourceComponent } from './main-resource-component'; /** @@ -29,7 +29,7 @@ export class CoreCourseModuleMainActivityPage('module'); + this.module = CoreNavigator.getRequiredRouteParam('module'); this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId'); } catch (error) { CoreDomUtils.showErrorModal(error); @@ -47,7 +47,7 @@ export class CoreCourseModuleMainActivityPage(); // Called to notify changes the index page from the main component. @@ -96,11 +96,10 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, this.description = this.module.description; this.componentId = this.module.id; this.externalUrl = this.module.url; - this.courseId = this.courseId || this.module.course!; + this.courseId = this.courseId || this.module.course; this.showCompletion = !!CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('3.11'); if (this.showCompletion) { - CoreCourseHelper.calculateModuleCompletionData(this.module, this.courseId); CoreCourseHelper.loadModuleOfflineCompletion(this.courseId, this.module); this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_MODULE_VIEWED, async (data) => { @@ -395,11 +394,11 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, const ignoreCache = refresh && CoreApp.isOnline(); try { - await CoreCourse.loadModuleContents(this.module, this.courseId, undefined, false, ignoreCache); + await CoreCourse.loadModuleContents(this.module, undefined, undefined, false, ignoreCache); } catch (error) { // Error loading contents. If we ignored cache, try to get the cached value. if (ignoreCache && !this.module.contents) { - await CoreCourse.loadModuleContents(this.module, this.courseId); + await CoreCourse.loadModuleContents(this.module); } else if (!this.module.contents) { // Not able to load contents, throw the error. throw error; @@ -428,8 +427,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, protected async fetchModule(): Promise { const module = await CoreCourse.getModule(this.module.id, this.courseId); - CoreCourseHelper.calculateModuleCompletionData(module, this.courseId); - await CoreCourseHelper.loadModuleOfflineCompletion(this.courseId, module); this.module = module; diff --git a/src/core/features/course/classes/module-base-handler.ts b/src/core/features/course/classes/module-base-handler.ts index 3d59a9d00..0950a8d2a 100644 --- a/src/core/features/course/classes/module-base-handler.ts +++ b/src/core/features/course/classes/module-base-handler.ts @@ -14,7 +14,7 @@ import { CoreNavigationOptions, CoreNavigator } from '@services/navigator'; import { CoreCourse } from '../services/course'; -import { CoreCourseModule } from '../services/course-helper'; +import { CoreCourseModuleData } from '../services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '../services/module-delegate'; /** @@ -35,7 +35,7 @@ export class CoreModuleHandlerBase implements Partial { * @inheritdoc */ async getData( - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, // eslint-disable-line @typescript-eslint/no-unused-vars sectionId?: number, // eslint-disable-line @typescript-eslint/no-unused-vars forCoursePage?: boolean, // eslint-disable-line @typescript-eslint/no-unused-vars @@ -47,7 +47,7 @@ export class CoreModuleHandlerBase implements Partial { showDownloadButton: true, action: async ( event: Event, - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions, ): Promise => { @@ -64,7 +64,7 @@ export class CoreModuleHandlerBase implements Partial { * @param options Options for the navigation. * @return Promise resolved when done. */ - async openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise { + async openActivityPage(module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions): Promise { if (!CoreCourse.moduleHasView(module)) { return; } diff --git a/src/core/features/course/classes/module-prefetch-handler.ts b/src/core/features/course/classes/module-prefetch-handler.ts index e68b13c68..ab9bf9fda 100644 --- a/src/core/features/course/classes/module-prefetch-handler.ts +++ b/src/core/features/course/classes/module-prefetch-handler.ts @@ -181,7 +181,7 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref */ getIntroFilesFromInstance(module: CoreCourseAnyModuleData, instance?: ModuleInstance): CoreWSFile[] { if (instance) { - if (typeof instance.introfiles != 'undefined') { + if (instance.introfiles !== undefined) { return instance.introfiles; } else if (instance.intro) { return CoreFilepool.extractDownloadableFilesFromHtmlAsFakeFileObjects(instance.intro); diff --git a/src/core/features/course/classes/resource-prefetch-handler.ts b/src/core/features/course/classes/resource-prefetch-handler.ts index a11108d27..c7549df91 100644 --- a/src/core/features/course/classes/resource-prefetch-handler.ts +++ b/src/core/features/course/classes/resource-prefetch-handler.ts @@ -18,7 +18,8 @@ import { CoreApp } from '@services/app'; import { CoreFilepool } from '@services/filepool'; import { CoreSites } from '@services/sites'; import { CoreWSFile } from '@services/ws'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from '../services/course'; +import { CoreCourse, CoreCourseAnyModuleData } from '../services/course'; +import { CoreCourseModuleData } from '../services/course-helper'; import { CoreCourseModulePrefetchHandlerBase } from './module-prefetch-handler'; /** @@ -40,7 +41,7 @@ export class CoreCourseResourcePrefetchHandlerBase extends CoreCourseModulePrefe * @param dirPath Path of the directory where to store all the content files. * @return Promise resolved when all content is downloaded. */ - download(module: CoreCourseWSModule, courseId: number, dirPath?: string): Promise { + download(module: CoreCourseModuleData, courseId: number, dirPath?: string): Promise { return this.downloadOrPrefetch(module, courseId, false, dirPath); } @@ -55,7 +56,7 @@ export class CoreCourseResourcePrefetchHandlerBase extends CoreCourseModulePrefe * in the filepool root folder. * @return Promise resolved when all content is downloaded. */ - async downloadOrPrefetch(module: CoreCourseWSModule, courseId: number, prefetch?: boolean, dirPath?: string): Promise { + async downloadOrPrefetch(module: CoreCourseModuleData, courseId: number, prefetch?: boolean, dirPath?: string): Promise { if (!CoreApp.isOnline()) { // Cannot download in offline. throw new CoreNetworkError(); @@ -85,13 +86,13 @@ export class CoreCourseResourcePrefetchHandlerBase extends CoreCourseModulePrefe */ protected async performDownloadOrPrefetch( siteId: string, - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, prefetch: boolean, dirPath?: string, ): Promise { // Get module info to be able to handle links. - await CoreCourse.getModuleBasicInfo(module.id, siteId); + await CoreCourse.getModuleBasicInfo(module.id, { siteId }); // Load module contents (ignore cache so we always have the latest data). await this.loadContents(module, courseId, true); @@ -143,7 +144,7 @@ export class CoreCourseResourcePrefetchHandlerBase extends CoreCourseModulePrefe * @return Promise resolved with the list of files. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - async getFiles(module: CoreCourseWSModule, courseId: number, single?: boolean): Promise { + async getFiles(module: CoreCourseModuleData, courseId: number, single?: boolean): Promise { // Load module contents if needed. await this.loadContents(module, courseId); @@ -190,7 +191,7 @@ export class CoreCourseResourcePrefetchHandlerBase extends CoreCourseModulePrefe * @param dirPath Path of the directory where to store all the content files. * @return Promise resolved when done. */ - prefetch(module: CoreCourseWSModule, courseId: number, single?: boolean, dirPath?: string): Promise { + prefetch(module: CoreCourseModuleData, courseId: number, single?: boolean, dirPath?: string): Promise { return this.downloadOrPrefetch(module, courseId, true, dirPath); } diff --git a/src/core/features/course/components/format/format.ts b/src/core/features/course/components/format/format.ts index 6e8ae36bc..683eb061e 100644 --- a/src/core/features/course/components/format/format.ts +++ b/src/core/features/course/components/format/format.ts @@ -33,11 +33,12 @@ import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-comp import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; import { CoreCourse, + CoreCourseModuleCompletionStatus, CoreCourseProvider, } from '@features/course/services/course'; import { CoreCourseHelper, - CoreCourseModule, + CoreCourseModuleData, CoreCourseModuleCompletionData, CoreCourseSection, CoreCourseSectionWithStatus, @@ -164,9 +165,9 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { let section: CoreCourseSection | undefined; - if (typeof data.sectionId != 'undefined' && this.sections) { + if (data.sectionId !== undefined && this.sections) { section = this.sections.find((section) => section.id == data.sectionId); - } else if (typeof data.sectionNumber != 'undefined' && this.sections) { + } else if (data.sectionNumber !== undefined && this.sections) { section = this.sections.find((section) => section.section == data.sectionNumber); } @@ -398,7 +399,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { } } - if (this.moduleId && typeof previousValue == 'undefined') { + if (this.moduleId && previousValue === undefined) { setTimeout(() => { CoreDomUtils.scrollToElementBySelector( this.elementRef.nativeElement, @@ -636,14 +637,14 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { } // If the completion value is not used, the page won't be reloaded, so update the progress bar. - const completionModules = ( []) + const completionModules = ( []) .concat(...this.sections!.map((section) => section.modules)) .map((module) => module.completion && module.completion > 0 ? 1 : module.completion) .reduce((accumulator, currentValue) => (accumulator || 0) + (currentValue || 0), 0); const moduleProgressPercent = 100 / (completionModules || 1); // Use min/max here to avoid floating point rounding errors over/under-flowing the progress bar. - if (completionData.state === CoreCourseProvider.COMPLETION_COMPLETE) { + if (completionData.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) { this.course.progress = Math.min(100, this.course.progress + moduleProgressPercent); } else { this.course.progress = Math.max(0, this.course.progress - moduleProgressPercent); diff --git a/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts b/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts index 8eca20fe0..1b9e0b453 100644 --- a/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts +++ b/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts @@ -15,7 +15,7 @@ import { Component } from '@angular/core'; import { CoreUser } from '@features/user/services/user'; -import { CoreCourseProvider } from '@features/course/services/course'; +import { CoreCourseModuleCompletionStatus, CoreCourseModuleCompletionTracking } from '@features/course/services/course'; import { CoreFilterHelper } from '@features/filter/services/filter-helper'; import { Translate } from '@singletons'; import { CoreCourseModuleCompletionBaseComponent } from '@features/course/classes/module-completion'; @@ -52,28 +52,28 @@ export class CoreCourseModuleCompletionLegacyComponent extends CoreCourseModuleC let langKey: string | undefined; let image: string | undefined; - if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_MANUAL && - this.completion.state === CoreCourseProvider.COMPLETION_INCOMPLETE) { + if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL && + this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) { image = 'completion-manual-n'; langKey = 'core.completion-alt-manual-n'; - } else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_MANUAL && - this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE) { + } else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL && + this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) { image = 'completion-manual-y'; langKey = 'core.completion-alt-manual-y'; - } else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC && - this.completion.state === CoreCourseProvider.COMPLETION_INCOMPLETE) { + } else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC && + this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) { image = 'completion-auto-n'; langKey = 'core.completion-alt-auto-n'; - } else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC && - this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE) { + } else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC && + this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) { image = 'completion-auto-y'; langKey = 'core.completion-alt-auto-y'; - } else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC && - this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE_PASS) { + } else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC && + this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS) { image = 'completion-auto-pass'; langKey = 'core.completion-alt-auto-pass'; - } else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC && - this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE_FAIL) { + } else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC && + this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL) { image = 'completion-auto-fail'; langKey = 'core.completion-alt-auto-fail'; } diff --git a/src/core/features/course/components/module-completion/module-completion.ts b/src/core/features/course/components/module-completion/module-completion.ts index 92fbb0b0e..33fab2dd5 100644 --- a/src/core/features/course/components/module-completion/module-completion.ts +++ b/src/core/features/course/components/module-completion/module-completion.ts @@ -15,7 +15,7 @@ import { Component, Input } from '@angular/core'; import { CoreCourseModuleCompletionBaseComponent } from '@features/course/classes/module-completion'; -import { CoreCourseModuleWSRuleDetails, CoreCourseProvider } from '@features/course/services/course'; +import { CoreCourseModuleCompletionStatus, CoreCourseModuleWSRuleDetails } from '@features/course/services/course'; import { CoreUser } from '@features/user/services/user'; import { Translate } from '@singletons'; @@ -51,10 +51,10 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet // Format rules. this.details = await Promise.all(this.completion.details.map(async (rule: CompletionRule) => { - rule.statuscomplete = rule.rulevalue.status == CoreCourseProvider.COMPLETION_COMPLETE || - rule.rulevalue.status == CoreCourseProvider.COMPLETION_COMPLETE_PASS; - rule.statuscompletefail = rule.rulevalue.status == CoreCourseProvider.COMPLETION_COMPLETE_FAIL; - rule.statusincomplete = rule.rulevalue.status == CoreCourseProvider.COMPLETION_INCOMPLETE; + rule.statuscomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE || + rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS; + rule.statuscompletefail = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL; + rule.statusincomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE; rule.accessibleDescription = null; if (this.completion!.overrideby) { diff --git a/src/core/features/course/components/module-info/module-info.ts b/src/core/features/course/components/module-info/module-info.ts index 2c958c99f..43fbe8ec4 100644 --- a/src/core/features/course/components/module-info/module-info.ts +++ b/src/core/features/course/components/module-info/module-info.ts @@ -14,7 +14,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { CoreCourse } from '@features/course/services/course'; -import { CoreCourseModule, CoreCourseModuleCompletionData } from '@features/course/services/course-helper'; +import { CoreCourseModuleData, CoreCourseModuleCompletionData } from '@features/course/services/course-helper'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; import { CoreSites } from '@services/sites'; @@ -35,7 +35,7 @@ import { CoreSites } from '@services/sites'; }) export class CoreCourseModuleInfoComponent implements OnInit { - @Input() module!: CoreCourseModule; // The module to render. + @Input() module!: CoreCourseModuleData; // The module to render. @Input() showManualCompletion = true; // Whether to show manual completion, true by default. @Input() courseId!: number; // The courseId the module belongs to. diff --git a/src/core/features/course/components/module-navigation/module-navigation.ts b/src/core/features/course/components/module-navigation/module-navigation.ts index c6cc18ae9..fa326b1c7 100644 --- a/src/core/features/course/components/module-navigation/module-navigation.ts +++ b/src/core/features/course/components/module-navigation/module-navigation.ts @@ -14,7 +14,7 @@ import { Component, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; import { CoreCourse, CoreCourseProvider, CoreCourseWSSection } from '@features/course/services/course'; -import { CoreCourseModule, CoreCourseSection } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; import { IonContent } from '@ionic/angular'; import { ScrollDetail } from '@ionic/core'; @@ -41,10 +41,10 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { @Input() courseId!: number; // Course ID. @Input() currentModuleId!: number; // Current module ID. - nextModule?: CoreCourseModule; - previousModule?: CoreCourseModule; - nextModuleSection?: CoreCourseSection; - previousModuleSection?: CoreCourseSection; + nextModule?: CoreCourseModuleData; + previousModule?: CoreCourseModuleData; + nextModuleSection?: CoreCourseWSSection; + previousModuleSection?: CoreCourseWSSection; loaded = false; protected element: HTMLElement; @@ -184,7 +184,7 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { return false; } - currentModuleIndex = section.modules.findIndex((module: CoreCourseModule) => module.id == this.currentModuleId); + currentModuleIndex = section.modules.findIndex((module: CoreCourseModuleData) => module.id == this.currentModuleId); return currentModuleIndex >= 0; }); @@ -250,7 +250,7 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { * @param module Module to check. * @return Wether the module is available to the user or not. */ - protected async isModuleAvailable(module: CoreCourseModule): Promise { + protected async isModuleAvailable(module: CoreCourseModuleData): Promise { return CoreCourse.instance.moduleHasView(module); } diff --git a/src/core/features/course/components/module/module.ts b/src/core/features/course/components/module/module.ts index b077bd66f..944eed73a 100644 --- a/src/core/features/course/components/module/module.ts +++ b/src/core/features/course/components/module/module.ts @@ -19,7 +19,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreCourseHelper, - CoreCourseModule, + CoreCourseModuleData, CoreCourseModuleCompletionData, CoreCourseSection, } from '@features/course/services/course-helper'; @@ -44,7 +44,7 @@ import { }) export class CoreCourseModuleComponent implements OnInit, OnDestroy { - @Input() module!: CoreCourseModule; // The module to render. + @Input() module!: CoreCourseModuleData; // The module to render. @Input() courseId?: number; // The course the module belongs to. @Input() section?: CoreCourseSection; // The section the module belongs to. @Input() showActivityDates = false; // Whether to show activity dates. @@ -106,7 +106,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { if (this.module.handlerData.showDownloadButton) { // Listen for changes on this module status, even if download isn't enabled. - this.prefetchHandler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(this.module); + this.prefetchHandler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(this.module.name); this.statusObserver = CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { if (!this.module || data.componentId != this.module.id || !this.prefetchHandler || @@ -180,14 +180,14 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { try { // Get download size to ask for confirm if it's high. - const size = await this.prefetchHandler.getDownloadSize(this.module, this.courseId!, true); + const size = await this.prefetchHandler.getDownloadSize(this.module, this.module.course, true); - await CoreCourseHelper.prefetchModule(this.prefetchHandler, this.module, size, this.courseId!, refresh); + await CoreCourseHelper.prefetchModule(this.prefetchHandler, this.module, size, this.module.course, refresh); const eventData = { sectionId: this.section?.id, moduleId: this.module.id, - courseId: this.courseId!, + courseId: this.module.course, }; this.statusChanged.emit(eventData); } catch (error) { diff --git a/src/core/features/course/components/section-selector/section-selector.ts b/src/core/features/course/components/section-selector/section-selector.ts index c2fdc2069..e71790478 100644 --- a/src/core/features/course/components/section-selector/section-selector.ts +++ b/src/core/features/course/components/section-selector/section-selector.ts @@ -15,7 +15,11 @@ import { Component, Input, OnInit } from '@angular/core'; import { CoreCourseSection } from '@features/course/services/course-helper'; -import { CoreCourseProvider } from '@features/course/services/course'; +import { + CoreCourseModuleCompletionStatus, + CoreCourseModuleCompletionTracking, + CoreCourseProvider, +} from '@features/course/services/course'; import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; import { CoreUtils } from '@services/utils/utils'; import { ModalController } from '@singletons'; @@ -56,14 +60,14 @@ export class CoreCourseSectionSelectorComponent implements OnInit { let complete = 0; let total = 0; section.modules.forEach((module) => { - if (!module.uservisible || module.completiondata === undefined || module.completiondata.tracking === undefined || - module.completiondata.tracking <= CoreCourseProvider.COMPLETION_TRACKING_NONE) { + if (!module.uservisible || module.completiondata === undefined || + module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE) { return; } total++; - if (module.completiondata.state == CoreCourseProvider.COMPLETION_COMPLETE || - module.completiondata.state == CoreCourseProvider.COMPLETION_COMPLETE_PASS) { + if (module.completiondata.state == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE || + module.completiondata.state == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS) { complete++; } }); diff --git a/src/core/features/course/components/unsupported-module/unsupported-module.ts b/src/core/features/course/components/unsupported-module/unsupported-module.ts index b8be27123..5df40ab8f 100644 --- a/src/core/features/course/components/unsupported-module/unsupported-module.ts +++ b/src/core/features/course/components/unsupported-module/unsupported-module.ts @@ -14,7 +14,8 @@ import { Component, Input, OnInit } from '@angular/core'; -import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course'; +import { CoreCourse } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; /** @@ -27,7 +28,7 @@ import { CoreCourseModuleDelegate } from '@features/course/services/module-deleg export class CoreCourseUnsupportedModuleComponent implements OnInit { @Input() courseId?: number; // The course to module belongs to. - @Input() module?: CoreCourseWSModule; // The module to render. + @Input() module?: CoreCourseModuleData; // The module to render. isDisabledInSite?: boolean; isSupportedByTheApp?: boolean; diff --git a/src/core/features/course/directives/download-module-main-file.ts b/src/core/features/course/directives/download-module-main-file.ts index 6f63da894..e004e3eb5 100644 --- a/src/core/features/course/directives/download-module-main-file.ts +++ b/src/core/features/course/directives/download-module-main-file.ts @@ -15,8 +15,8 @@ import { Directive, Input, OnInit, ElementRef } from '@angular/core'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreCourse, CoreCourseModuleContentFile, CoreCourseWSModule } from '@features/course/services/course'; -import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { CoreCourse, CoreCourseModuleContentFile } from '@features/course/services/course'; +import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreUtilsOpenFileOptions } from '@services/utils/utils'; /** @@ -31,7 +31,7 @@ import { CoreUtilsOpenFileOptions } from '@services/utils/utils'; }) export class CoreCourseDownloadModuleMainFileDirective implements OnInit { - @Input() module?: CoreCourseWSModule; // The module. + @Input() module?: CoreCourseModuleData; // The module. @Input() moduleId?: string | number; // The module ID. Required if module is not supplied. @Input() courseId?: string | number; // The course ID. @Input() component?: string; // Component to link the file to. @@ -71,7 +71,7 @@ export class CoreCourseDownloadModuleMainFileDirective implements OnInit { await CoreCourseHelper.downloadModuleAndOpenFile( this.module, - courseId ?? this.module.course!, + courseId ?? this.module.course, this.component, componentId, this.files, diff --git a/src/core/features/course/format/weeks/services/handlers/weeks-format.ts b/src/core/features/course/format/weeks/services/handlers/weeks-format.ts index 4e7682eee..10de07200 100644 --- a/src/core/features/course/format/weeks/services/handlers/weeks-format.ts +++ b/src/core/features/course/format/weeks/services/handlers/weeks-format.ts @@ -57,7 +57,7 @@ export class CoreCourseFormatWeeksHandlerService implements CoreCourseFormatHand for (let i = 0; i < sections.length; i++) { const section = sections[i]; - if (typeof section.section == 'undefined' || section.section < 1) { + if (section.section === undefined || section.section < 1) { continue; } diff --git a/src/core/features/course/pages/contents/contents.ts b/src/core/features/course/pages/contents/contents.ts index 1cad013f4..768cfc65f 100644 --- a/src/core/features/course/pages/contents/contents.ts +++ b/src/core/features/course/pages/contents/contents.ts @@ -256,7 +256,10 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { if (sync) { // Try to synchronize the course data. // For now we don't allow manual syncing, so ignore errors. - const result = await CoreUtils.ignoreErrors(CoreCourseSync.syncCourse(this.course.id)); + const result = await CoreUtils.ignoreErrors(CoreCourseSync.syncCourse( + this.course.id, + this.course.displayname || this.course.fullname, + )); if (result?.warnings?.length) { CoreDomUtils.showErrorModal(result.warnings[0]); } @@ -296,7 +299,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { if (this.course.enablecompletion !== false) { const sectionWithModules = sections.find((section) => section.modules.length > 0); - if (sectionWithModules && typeof sectionWithModules.modules[0].completion != 'undefined') { + if (sectionWithModules && sectionWithModules.modules[0].completion !== undefined) { // The module already has completion (3.6 onwards). Load the offline completion. this.modulesHaveCompletion = true; @@ -396,7 +399,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { * @return Promise resolved when done. */ async onCompletionChange(completionData: CoreCourseModuleCompletionData): Promise { - const shouldReload = typeof completionData.valueused == 'undefined' || completionData.valueused; + const shouldReload = completionData.valueused === undefined || completionData.valueused; if (!shouldReload) { // Invalidate the completion. diff --git a/src/core/features/course/pages/index/index.page.ts b/src/core/features/course/pages/index/index.page.ts index 98dd85dd1..68ae06832 100644 --- a/src/core/features/course/pages/index/index.page.ts +++ b/src/core/features/course/pages/index/index.page.ts @@ -20,8 +20,8 @@ import { CoreCourseFormatDelegate } from '../../services/format-delegate'; import { CoreCourseOptionsDelegate } from '../../services/course-options-delegate'; import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course'; -import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { CoreCourse } from '@features/course/services/course'; +import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreUtils } from '@services/utils/utils'; import { CoreTextUtils } from '@services/utils/text'; import { CoreNavigator } from '@services/navigator'; @@ -46,7 +46,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { protected currentPagePath = ''; protected selectTabObserver: CoreEventObserver; protected firstTabName?: string; - protected module?: CoreCourseWSModule; + protected module?: CoreCourseModuleData; protected modParams?: Params; protected isGuest?: boolean; protected contentsTab: CoreTabsOutletTab = { @@ -90,7 +90,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { // Get params. this.course = CoreNavigator.getRouteParam('course'); this.firstTabName = CoreNavigator.getRouteParam('selectedTab'); - this.module = CoreNavigator.getRouteParam('module'); + this.module = CoreNavigator.getRouteParam('module'); this.modParams = CoreNavigator.getRouteParam('modParams'); this.isGuest = CoreNavigator.getRouteBooleanParam('isGuest'); diff --git a/src/core/features/course/pages/list-mod-type/list-mod-type.page.ts b/src/core/features/course/pages/list-mod-type/list-mod-type.page.ts index f24a70c92..735cfc346 100644 --- a/src/core/features/course/pages/list-mod-type/list-mod-type.page.ts +++ b/src/core/features/course/pages/list-mod-type/list-mod-type.page.ts @@ -85,7 +85,7 @@ export class CoreCourseListModTypePage implements OnInit { if (this.modName === 'resources') { // Check that the module is a resource. - if (typeof this.archetypes[mod.modname] == 'undefined') { + if (this.archetypes[mod.modname] === undefined) { this.archetypes[mod.modname] = CoreCourseModuleDelegate.supportsFeature( mod.modname, CoreConstants.FEATURE_MOD_ARCHETYPE, diff --git a/src/core/features/course/pages/module-preview/module-preview.page.ts b/src/core/features/course/pages/module-preview/module-preview.page.ts index 51dc29b23..620b1f981 100644 --- a/src/core/features/course/pages/module-preview/module-preview.page.ts +++ b/src/core/features/course/pages/module-preview/module-preview.page.ts @@ -14,7 +14,7 @@ import { Component, OnInit } from '@angular/core'; import { CoreCourse } from '@features/course/services/course'; -import { CoreCourseHelper, CoreCourseModule, CoreCourseSection } from '@features/course/services/course-helper'; +import { CoreCourseHelper, CoreCourseModuleData, CoreCourseSection } from '@features/course/services/course-helper'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; import { IonRefresher } from '@ionic/angular'; import { CoreNavigator } from '@services/navigator'; @@ -31,7 +31,7 @@ import { CoreUtils } from '@services/utils/utils'; export class CoreCourseModulePreviewPage implements OnInit { title!: string; - module!: CoreCourseModule; + module!: CoreCourseModuleData; section?: CoreCourseSection; // The section the module belongs to. courseId!: number; loaded = false; @@ -45,7 +45,7 @@ export class CoreCourseModulePreviewPage implements OnInit { */ async ngOnInit(): Promise { try { - this.module = CoreNavigator.getRequiredRouteParam('module'); + this.module = CoreNavigator.getRequiredRouteParam('module'); this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId'); this.section = CoreNavigator.getRouteParam('section'); } catch (error) { @@ -73,8 +73,6 @@ export class CoreCourseModulePreviewPage implements OnInit { this.module = await CoreCourse.getModule(this.module.id, this.courseId); } - CoreCourseHelper.calculateModuleCompletionData(this.module, this.courseId); - await CoreCourseHelper.loadModuleOfflineCompletion(this.courseId, this.module); this.unsupported = !CoreCourseModuleDelegate.getHandlerName(this.module.modname); diff --git a/src/core/features/course/pages/preview/preview.page.ts b/src/core/features/course/pages/preview/preview.page.ts index b7a6aa5e2..65fd8e105 100644 --- a/src/core/features/course/pages/preview/preview.page.ts +++ b/src/core/features/course/pages/preview/preview.page.ts @@ -356,7 +356,7 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy { }, ); - if (typeof modalData != 'undefined') { + if (modalData !== undefined) { this.selfEnrolInCourse(modalData, instanceId); return; diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index 768470957..4162eb2b4 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -16,15 +16,17 @@ import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; import moment from 'moment'; -import { CoreSites } from '@services/sites'; +import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreCourse, CoreCourseCompletionActivityStatus, CoreCourseModuleWSCompletionData, CoreCourseModuleContentFile, - CoreCourseWSModule, CoreCourseProvider, CoreCourseWSSection, + CoreCourseModuleCompletionTracking, + CoreCourseModuleCompletionStatus, + CoreCourseGetContentsWSModule, } from './course'; import { CoreConstants } from '@/core/constants'; import { CoreLogger } from '@singletons/logger'; @@ -162,7 +164,7 @@ export class CoreCourseHelperProvider { * @param sections List of sections to treat modules. * @param courseId Course ID of the modules. * @param completionStatus List of completion status. - * @param courseName Course name. Recommended if completionStatus is supplied. + * @param courseName Not used since 4.0 * @param forCoursePage Whether the data will be used to render the course page. * @return Whether the sections have content. */ @@ -174,18 +176,16 @@ export class CoreCourseHelperProvider { forCoursePage = false, ): { hasContent: boolean; sections: CoreCourseSection[] } { - const formattedSections: CoreCourseSection[] = sections; let hasContent = false; - formattedSections.forEach((section) => { - if (!section || !section.modules) { - return; - } - - section.hasContent = this.sectionHasContent(section); + const formattedSections = sections.map((courseSection) => { + const section = { + ...courseSection, + hasContent: this.sectionHasContent(courseSection), + }; if (!section.hasContent) { - return; + return section; } hasContent = true; @@ -199,9 +199,7 @@ export class CoreCourseHelperProvider { forCoursePage, ); - if (module.completiondata) { - this.calculateModuleCompletionData(module, courseId, courseName); - } else if (completionStatus && typeof completionStatus[module.id] != 'undefined') { + if (!module.completiondata && completionStatus && completionStatus[module.id] !== undefined) { // Should not happen on > 3.6. Check if activity has completions and if it's marked. const activityStatus = completionStatus[module.id]; @@ -212,7 +210,6 @@ export class CoreCourseHelperProvider { valueused: activityStatus.valueused, tracking: activityStatus.tracking, courseId, - courseName, cmid: module.id, }; } @@ -220,6 +217,8 @@ export class CoreCourseHelperProvider { // Check if the module is stealth. module.isStealth = module.visibleoncoursepage === 0 || (!!module.visible && !section.visible); }); + + return section; }); return { hasContent, sections: formattedSections }; @@ -228,17 +227,15 @@ export class CoreCourseHelperProvider { /** * Calculate completion data of a module. * + * @deprecated since 4.0. * @param module Module. - * @param courseId Course ID of the module. - * @param courseName Course name. */ - calculateModuleCompletionData(module: CoreCourseModule, courseId: number, courseName?: string): void { + calculateModuleCompletionData(module: CoreCourseModuleData): void { if (!module.completiondata || !module.completion) { return; } - module.completiondata.courseId = courseId; - module.completiondata.courseName = courseName; + module.completiondata.courseId = module.course; module.completiondata.tracking = module.completion; module.completiondata.cmid = module.id; } @@ -495,7 +492,7 @@ export class CoreCourseHelperProvider { * @param done Function to call when done. It will close the context menu. * @return Promise resolved when done. */ - async confirmAndRemoveFiles(module: CoreCourseWSModule, courseId: number, done?: () => void): Promise { + async confirmAndRemoveFiles(module: CoreCourseModuleData, courseId: number, done?: () => void): Promise { let modal: CoreIonLoadingElement | undefined; try { @@ -584,7 +581,7 @@ export class CoreCourseHelperProvider { */ async contextMenuPrefetch( instance: ComponentWithContextMenu, - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, done?: () => void, ): Promise { @@ -716,7 +713,7 @@ export class CoreCourseHelperProvider { * @return Resolved on success. */ async downloadModuleAndOpenFile( - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, component?: string, componentId?: string | number, @@ -728,7 +725,7 @@ export class CoreCourseHelperProvider { if (!files || !files.length) { // Try to use module contents. - files = await CoreCourse.getModuleContents(module, courseId); + files = await CoreCourse.getModuleContents(module); } if (!files.length) { @@ -808,7 +805,7 @@ export class CoreCourseHelperProvider { protected async openModuleFileInBrowser( fileUrl: string, site: CoreSite, - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, component?: string, componentId?: string | number, @@ -859,7 +856,7 @@ export class CoreCourseHelperProvider { * @return Promise resolved when done. */ async downloadModuleWithMainFileIfNeeded( - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, component: string, componentId?: string | number, @@ -942,7 +939,7 @@ export class CoreCourseHelperProvider { * @return Promise resolved when done. */ protected async downloadModuleWithMainFile( - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, fixedUrl: string, files: CoreCourseModuleContentFile[], @@ -1007,7 +1004,7 @@ export class CoreCourseHelperProvider { * @return Promise resolved when done. */ async downloadModule( - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, component?: string, componentId?: string | number, @@ -1016,7 +1013,7 @@ export class CoreCourseHelperProvider { ): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); - const prefetchHandler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(module); + const prefetchHandler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(module.name); if (prefetchHandler) { // Use the prefetch handler to download the module. @@ -1045,7 +1042,7 @@ export class CoreCourseHelperProvider { */ async fillContextMenu( instance: ComponentWithContextMenu, - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, invalidateCache?: boolean, component?: string, @@ -1228,7 +1225,7 @@ export class CoreCourseHelperProvider { * @param siteId Site ID. If not defined, current site. * @return Promise resolved when done. */ - async loadOfflineCompletion(courseId: number, sections: CoreCourseSection[], siteId?: string): Promise { + async loadOfflineCompletion(courseId: number, sections: CoreCourseWSSection[], siteId?: string): Promise { const offlineCompletions = await CoreCourseOffline.getCourseManualCompletions(courseId, siteId); if (!offlineCompletions || !offlineCompletions.length) { @@ -1251,7 +1248,7 @@ export class CoreCourseHelperProvider { const module = section.modules[j]; const offlineCompletion = offlineCompletionsMap[module.id]; - if (offlineCompletion && typeof module.completiondata != 'undefined' && + if (offlineCompletion && module.completiondata !== undefined && offlineCompletion.timecompleted >= module.completiondata.timecompleted * 1000) { // The module has offline completion. Load it. module.completiondata.state = offlineCompletion.completed; @@ -1276,7 +1273,7 @@ export class CoreCourseHelperProvider { * @param siteId Site ID. If not defined, current site. * @return Promise resolved when done. */ - async loadModuleOfflineCompletion(courseId: number, module: CoreCourseModule, siteId?: string): Promise { + async loadModuleOfflineCompletion(courseId: number, module: CoreCourseModuleData, siteId?: string): Promise { if (!module.completiondata) { return; } @@ -1435,14 +1432,19 @@ export class CoreCourseHelperProvider { /** * Get the course ID from a module instance ID, showing an error message if it can't be retrieved. * - * @param id Instance ID. - * @param module Name of the module. E.g. 'glossary'. + * @deprecated since 4.0. + * @param instanceId Instance ID. + * @param moduleName Name of the module. E.g. 'glossary'. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the module's course ID. */ - async getModuleCourseIdByInstance(id: number, module: string, siteId?: string): Promise { + async getModuleCourseIdByInstance(instanceId: number, moduleName: string, siteId?: string): Promise { try { - const cm = await CoreCourse.getModuleBasicInfoByInstance(id, module, siteId); + const cm = await CoreCourse.getModuleBasicInfoByInstance( + instanceId, + moduleName, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); return cm.course; } catch (error) { @@ -1462,7 +1464,7 @@ export class CoreCourseHelperProvider { * @return Promise resolved with the info. */ async getModulePrefetchInfo( - module: CoreCourseWSModule, + module: CoreCourseModuleData, courseId: number, invalidateCache?: boolean, component?: string, @@ -1574,7 +1576,7 @@ export class CoreCourseHelperProvider { const modal = await CoreDomUtils.showModalLoading(); try { - const module = await CoreCourse.getModuleBasicInfoByInstance(instanceId, modName, siteId); + const module = await CoreCourse.getModuleBasicInfoByInstance(instanceId, modName, { siteId }); this.navigateToModule( module.id, @@ -1617,22 +1619,21 @@ export class CoreCourseHelperProvider { const modal = await CoreDomUtils.showModalLoading(); try { - if (!courseId) { - // We don't have courseId. - const module = await CoreCourse.getModuleBasicInfo(moduleId, siteId); + if (!courseId || !sectionId) { + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); courseId = module.course; sectionId = module.section; - } else if (!sectionId) { - // We don't have sectionId but we have courseId. - sectionId = await CoreCourse.getModuleSectionId(moduleId, siteId); } // Get the site. const site = await CoreSites.getSite(siteId); // Get the module. - const module = + const module = await CoreCourse.getModule(moduleId, courseId, sectionId, false, false, siteId, modName); if (CoreSites.getCurrentSiteId() == site.getId()) { @@ -1652,13 +1653,11 @@ export class CoreCourseHelperProvider { } } - this.logger.warn('navCtrl was not passed to navigateToModule by the link handler for ' + module.modname); - const params: Params = { course: { id: courseId }, - module: module, - sectionId: sectionId, - modParams: modParams, + module, + sectionId, + modParams, }; if (courseId == site.getSiteHomeId()) { @@ -1691,7 +1690,7 @@ export class CoreCourseHelperProvider { * @param modParams Params to pass to the module * @param True if module can be opened, false otherwise. */ - async openModule(module: CoreCourseModule, courseId: number, sectionId?: number, modParams?: Params): Promise { + async openModule(module: CoreCourseModuleData, courseId: number, sectionId?: number, modParams?: Params): Promise { if (!module.handlerData) { module.handlerData = await CoreCourseModuleDelegate.getModuleDataFor( module.modname, @@ -1747,7 +1746,7 @@ export class CoreCourseHelperProvider { const promises: Promise[] = []; // Prefetch all the sections. If the first section is "All sections", use it. Otherwise, use a fake "All sections". - let allSectionsSection: CoreCourseSection = sections[0]; + let allSectionsSection: CoreCourseWSSection = sections[0]; if (sections[0].id != CoreCourseProvider.ALL_SECTIONS_ID) { allSectionsSection = this.createAllSectionsSection(); } @@ -1769,7 +1768,7 @@ export class CoreCourseHelperProvider { promises.push(CoreCourses.getCoursesByField('id', course.id)); const sectionWithModules = sections.find((section) => section.modules && section.modules.length > 0); - if (!sectionWithModules || typeof sectionWithModules.modules[0].completion == 'undefined') { + if (!sectionWithModules || sectionWithModules.modules[0].completion === undefined) { promises.push(CoreCourse.getActivitiesCompletionStatus(course.id)); } @@ -1804,7 +1803,7 @@ export class CoreCourseHelperProvider { */ async prefetchModule( handler: CoreCourseModulePrefetchHandler, - module: CoreCourseWSModule, + module: CoreCourseModuleData, size: CoreFileSizeSum, courseId: number, refresh?: boolean, @@ -1982,11 +1981,15 @@ export class CoreCourseHelperProvider { * @return Whether the section has content. */ sectionHasContent(section: CoreCourseWSSection): boolean { + if (!section.modules) { + return false; + } + if (section.hiddenbynumsections) { return false; } - return (typeof section.availabilityinfo != 'undefined' && section.availabilityinfo != '') || + return (section.availabilityinfo !== undefined && section.availabilityinfo != '') || section.summary != '' || (section.modules && section.modules.length > 0); } @@ -2040,12 +2043,12 @@ export class CoreCourseHelperProvider { * @param courseId Course ID the module belongs to. * @return Promise resolved when done. */ - async removeModuleStoredData(module: CoreCourseWSModule, courseId: number): Promise { + async removeModuleStoredData(module: CoreCourseModuleData, courseId: number): Promise { const promises: Promise[] = []; promises.push(CoreCourseModulePrefetchDelegate.removeModuleFiles(module, courseId)); - const handler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(module); + const handler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(module.name); const site = CoreSites.getCurrentSite(); if (handler && site) { promises.push(site.deleteComponentFromCache(handler.component, module.id)); @@ -2069,7 +2072,8 @@ export class CoreCourseHelperProvider { return; } - if (typeof completion.cmid == 'undefined' || completion.tracking !== 1) { + if (completion.cmid === undefined || + completion.tracking !== CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL) { return; } @@ -2077,14 +2081,15 @@ export class CoreCourseHelperProvider { event?.stopPropagation(); const modal = await CoreDomUtils.showModalLoading(); - completion.state = completion.state === 1 ? 0 : 1; + completion.state = completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE + ? CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE + : CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE; try { const response = await CoreCourse.markCompletedManually( completion.cmid, - completion.state === 1, - completion.courseId!, - completion.courseName, + completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE, + completion.courseId, ); if (response.offline) { @@ -2093,7 +2098,11 @@ export class CoreCourseHelperProvider { return response; } catch (error) { - completion.state = completion.state === 1 ? 0 : 1; + // Restore previous state. + completion.state = completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE + ? CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE + : CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE; + CoreDomUtils.showErrorModalDefault(error, 'core.errorchangecompletion', true); } finally { modal.dismiss(); @@ -2107,9 +2116,8 @@ export const CoreCourseHelper = makeSingleton(CoreCourseHelperProvider); /** * Section with calculated data. */ -export type CoreCourseSection = Omit & { +export type CoreCourseSection = CoreCourseWSSection & { hasContent?: boolean; - modules: CoreCourseModule[]; }; /** @@ -2127,20 +2135,27 @@ export type CoreCourseSectionWithStatus = CoreCourseSection & { /** * Module with calculated data. */ -export type CoreCourseModule = Omit & { +export type CoreCourseModuleData = Omit & { + course: number; // The course id. isStealth?: boolean; handlerData?: CoreCourseModuleHandlerData; completiondata?: CoreCourseModuleCompletionData; }; +/** + * Module with calculated data. + * + * @deprecated since 4.0. Use CoreCourseModuleData instead. + */ +export type CoreCourseModule = CoreCourseModuleData; + /** * Module completion with calculated data. */ export type CoreCourseModuleCompletionData = CoreCourseModuleWSCompletionData & { - courseId?: number; - courseName?: string; - tracking?: number; - cmid?: number; + courseId: number; + tracking: CoreCourseModuleCompletionTracking; + cmid: number; offline?: boolean; }; diff --git a/src/core/features/course/services/course-offline.ts b/src/core/features/course/services/course-offline.ts index d6ae57611..033c9f551 100644 --- a/src/core/features/course/services/course-offline.ts +++ b/src/core/features/course/services/course-offline.ts @@ -81,7 +81,7 @@ export class CoreCourseOfflineProvider { * @param cmId The module ID to store the completion. * @param completed Whether the module is completed or not. * @param courseId Course ID the module belongs to. - * @param courseName Course name. Recommended, it is used to display a better warning message. + * @param courseName Not used since 4.0. * @param siteId Site ID. If not defined, current site. * @return Promise resolved when completion is successfully stored. */ @@ -99,7 +99,6 @@ export class CoreCourseOfflineProvider { cmid: cmId, completed: completed ? 1 : 0, courseid: courseId, - coursename: courseName || '', timecompleted: Date.now(), }; await site.getDb().insertRecord(MANUAL_COMPLETION_TABLE, entry); diff --git a/src/core/features/course/services/course-options-delegate.ts b/src/core/features/course/services/course-options-delegate.ts index 87765a546..038b5d51a 100644 --- a/src/core/features/course/services/course-options-delegate.ts +++ b/src/core/features/course/services/course-options-delegate.ts @@ -585,7 +585,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - if (typeof course.navOptions == 'undefined' || typeof course.admOptions == 'undefined' || refresh) { + if (course.navOptions === undefined || course.admOptions === undefined || refresh) { const options = await CoreCourses.getCoursesAdminAndNavOptions([course.id]); course.navOptions = options.navOptions[course.id]; diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts index 6d5b8ea86..cd482f5ca 100644 --- a/src/core/features/course/services/course.ts +++ b/src/core/features/course/services/course.ts @@ -18,7 +18,7 @@ import { Params } from '@angular/router'; import { CoreApp } from '@services/app'; import { CoreEvents } from '@singletons/events'; import { CoreLogger } from '@singletons/logger'; -import { CoreSitesCommonWSOptions, CoreSites } from '@services/sites'; +import { CoreSitesCommonWSOptions, CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; import { CoreSiteWSPreSets, CoreSite } from '@classes/site'; @@ -36,7 +36,7 @@ import { import { CoreDomUtils } from '@services/utils/dom'; import { CoreWSError } from '@classes/errors/wserror'; import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications'; -import { CoreCourseHelper, CoreCourseModuleCompletionData } from './course-helper'; +import { CoreCourseHelper, CoreCourseModuleData, CoreCourseModuleCompletionData } from './course-helper'; import { CoreCourseFormatDelegate } from './format-delegate'; import { CoreCronDelegate } from '@services/cron'; import { CoreCourseLogCronHandler } from './handlers/log-cron'; @@ -61,6 +61,25 @@ declare module '@singletons/events' { } +/** + * Completion status valid values. + */ +export enum CoreCourseModuleCompletionStatus { + COMPLETION_INCOMPLETE = 0, + COMPLETION_COMPLETE = 1, + COMPLETION_COMPLETE_PASS = 2, + COMPLETION_COMPLETE_FAIL = 3, +} + +/** + * Completion tracking valid values. + */ +export enum CoreCourseModuleCompletionTracking { + COMPLETION_TRACKING_NONE = 0, + COMPLETION_TRACKING_MANUAL = 1, + COMPLETION_TRACKING_AUTOMATIC = 2, +} + /** * Service that provides some features regarding a course. */ @@ -73,13 +92,34 @@ export class CoreCourseProvider { static readonly ACCESS_DEFAULT = 'courses_access_default'; static readonly ALL_COURSES_CLEARED = -1; + /** + * @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE instead. + */ static readonly COMPLETION_TRACKING_NONE = 0; + /** + * @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL instead. + */ static readonly COMPLETION_TRACKING_MANUAL = 1; + /** + * @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC instead. + */ static readonly COMPLETION_TRACKING_AUTOMATIC = 2; + /** + * @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE instead. + */ static readonly COMPLETION_INCOMPLETE = 0; + /** + * @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE instead. + */ static readonly COMPLETION_COMPLETE = 1; + /** + * @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS instead. + */ static readonly COMPLETION_COMPLETE_PASS = 2; + /** + * @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL instead. + */ static readonly COMPLETION_COMPLETE_FAIL = 3; static readonly COMPONENT = 'CoreCourse'; @@ -151,7 +191,8 @@ export class CoreCourseProvider { * @param completion Completion status of the module. */ checkModuleCompletion(courseId: number, completion?: CoreCourseModuleCompletionData): void { - if (completion && completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC && completion.state === 0) { + if (completion && completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC && + completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) { this.invalidateSections(courseId).finally(() => { CoreEvents.trigger(CoreEvents.COMPLETION_MODULE_VIEWED, { courseId: courseId, @@ -252,11 +293,11 @@ export class CoreCourseProvider { offlineCompletions.forEach((offlineCompletion) => { - if (offlineCompletion && typeof completionStatus[offlineCompletion.cmid] != 'undefined') { + if (offlineCompletion && completionStatus[offlineCompletion.cmid] !== undefined) { const onlineCompletion = completionStatus[offlineCompletion.cmid]; // If the activity uses manual completion, override the value with the offline one. - if (onlineCompletion.tracking === 1) { + if (onlineCompletion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL) { onlineCompletion.state = offlineCompletion.completed; onlineCompletion.offline = true; } @@ -390,19 +431,20 @@ export class CoreCourseProvider { ignoreCache: boolean = false, siteId?: string, modName?: string, - ): Promise { + ): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); // Helper function to do the WS request without processing the result. const doRequest = async ( site: CoreSite, + courseId: number, moduleId: number, modName: string | undefined, includeStealth: boolean, preferCache: boolean, - ): Promise => { + ): Promise => { const params: CoreCourseGetContentsParams = { - courseid: courseId!, + courseid: courseId, }; params.options = []; @@ -439,7 +481,7 @@ export class CoreCourseProvider { } try { - const sections = await site.read('core_course_get_contents', params, preSets); + const sections = await site.read('core_course_get_contents', params, preSets); return sections; } catch { @@ -447,10 +489,10 @@ export class CoreCourseProvider { if (!ignoreCache && !CoreApp.isOnline()) { if (includeStealth) { // Older versions didn't include the includestealthmodules option. - return doRequest(site, moduleId, modName, false, true); + return doRequest(site, courseId, moduleId, modName, false, true); } else if (modName) { // Falback to the request for the given moduleId only. - return doRequest(site, moduleId, undefined, this.canRequestStealthModules(site), true); + return doRequest(site, courseId, moduleId, undefined, this.canRequestStealthModules(site), true); } } @@ -460,17 +502,21 @@ export class CoreCourseProvider { if (!courseId) { // No courseId passed, try to retrieve it. - const module = await this.getModuleBasicInfo(moduleId, siteId); + const module = await this.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); courseId = module.course; + sectionId = module.section; } - let sections: CoreCourseWSSection[]; + let sections: CoreCourseGetContentsWSSection[]; try { const site = await CoreSites.getSite(siteId); // We have courseId, we can use core_course_get_contents for compatibility. this.logger.debug(`Getting module ${moduleId} in course ${courseId}`); - sections = await doRequest(site, moduleId, modName, this.canRequestStealthModules(site), preferCache); + sections = await doRequest(site, courseId, moduleId, modName, this.canRequestStealthModules(site), preferCache); } catch { // Error getting the module. Try to get all contents (without filtering by module). const preSets: CoreSiteWSPreSets = { @@ -485,12 +531,11 @@ export class CoreCourseProvider { sections = await this.getSections(courseId, false, false, preSets, siteId); } - let foundModule: CoreCourseWSModule | undefined; + let foundModule: CoreCourseGetContentsWSModule | undefined; const foundSection = sections.some((section) => { - if (sectionId != null && - !isNaN(sectionId) && - section.id != CoreCourseProvider.STEALTH_MODULES_SECTION_ID && + if (section.id != CoreCourseProvider.STEALTH_MODULES_SECTION_ID && + sectionId !== undefined && sectionId != section.id ) { return false; @@ -502,29 +547,59 @@ export class CoreCourseProvider { }); if (foundSection && foundModule) { - foundModule.course = courseId; - - return foundModule; + return this.addAdditionalModuleData(foundModule, courseId); } throw new CoreError(Translate.instant('core.course.modulenotfound')); } + /** + * Add some additional info to course module. + * + * @param module Module. + * @param courseId Course ID of the module. + * @return Module with additional info. + */ + protected addAdditionalModuleData( + module: CoreCourseGetContentsWSModule, + courseId: number, + ): CoreCourseModuleData { + let completionData: CoreCourseModuleCompletionData | undefined = undefined; + + if (module.completiondata && module.completion) { + completionData = { + ...module.completiondata, + tracking: module.completion, + cmid: module.id, + courseId, + }; + } + + const moduleWithCourse: CoreCourseModuleData = { + ...module, + course: courseId, + completiondata: completionData, + }; + + return moduleWithCourse; + } + /** * Gets a module basic info by module ID. * * @param moduleId Module ID. - * @param siteId Site ID. If not defined, current site. + * @param options Comon site WS options. * @return Promise resolved with the module's info. */ - async getModuleBasicInfo(moduleId: number, siteId?: string): Promise { - const site = await CoreSites.getSite(siteId); + async getModuleBasicInfo(moduleId: number, options: CoreSitesCommonWSOptions = {}): Promise { + const site = await CoreSites.getSite(options.siteId); const params: CoreCourseGetCourseModuleWSParams = { cmid: moduleId, }; const preSets: CoreSiteWSPreSets = { cacheKey: this.getModuleCacheKey(moduleId), updateFrequency: CoreSite.FREQUENCY_RARELY, + ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. }; const response = await site.read('core_course_get_course_module', params, preSets); @@ -543,23 +618,21 @@ export class CoreCourseProvider { * @return Promise resolved with the module's grade info. */ async getModuleBasicGradeInfo(moduleId: number, siteId?: string): Promise { - const info = await this.getModuleBasicInfo(moduleId, siteId); - - const grade: CoreCourseModuleGradeInfo = { - advancedgrading: info.advancedgrading, - grade: info.grade, - gradecat: info.gradecat, - gradepass: info.gradepass, - outcomes: info.outcomes, - scale: info.scale, - }; + const info = await this.getModuleBasicInfo(moduleId, { siteId }); if ( - typeof grade.grade != 'undefined' || - typeof grade.advancedgrading != 'undefined' || - typeof grade.outcomes != 'undefined' + info.grade !== undefined || + info.advancedgrading !== undefined || + info.outcomes !== undefined ) { - return grade; + return { + advancedgrading: info.advancedgrading, + grade: info.grade, + gradecat: info.gradecat, + gradepass: info.gradepass, + outcomes: info.outcomes, + scale: info.scale, + }; } } @@ -567,21 +640,29 @@ export class CoreCourseProvider { /** * Gets a module basic info by instance. * - * @param id Instance ID. - * @param module Name of the module. E.g. 'glossary'. - * @param siteId Site ID. If not defined, current site. + * @param instanceId Instance ID. + * @param moduleName Name of the module. E.g. 'glossary'. + * @param options Comon site WS options. * @return Promise resolved with the module's info. */ - async getModuleBasicInfoByInstance(id: number, module: string, siteId?: string): Promise { - const site = await CoreSites.getSite(siteId); + async getModuleBasicInfoByInstance( + instanceId: number, + moduleName: string, + options: CoreSitesCommonWSOptions = {}, + ): Promise { + const site = await CoreSites.getSite(options.siteId); + const params: CoreCourseGetCourseModuleByInstanceWSParams = { - instance: id, - module: module, + instance: instanceId, + module: moduleName, }; - const preSets = { - cacheKey: this.getModuleBasicInfoByInstanceCacheKey(id, module), + + const preSets: CoreSiteWSPreSets = { + cacheKey: this.getModuleBasicInfoByInstanceCacheKey(instanceId, moduleName), updateFrequency: CoreSite.FREQUENCY_RARELY, + ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. }; + const response: CoreCourseGetCourseModuleWSResponse = await site.read('core_course_get_course_module_by_instance', params, preSets); @@ -597,12 +678,12 @@ export class CoreCourseProvider { /** * Get cache key for get module by instance WS calls. * - * @param id Instance ID. - * @param module Name of the module. E.g. 'glossary'. + * @param instanceId Instance ID. + * @param moduleName Name of the module. E.g. 'glossary'. * @return Cache key. */ - protected getModuleBasicInfoByInstanceCacheKey(id: number, module: string): string { - return ROOT_CACHE_KEY + 'moduleByInstance:' + module + ':' + id; + protected getModuleBasicInfoByInstanceCacheKey(instanceId: number, moduleName: string): string { + return ROOT_CACHE_KEY + 'moduleByInstance:' + moduleName + ':' + instanceId; } /** @@ -652,13 +733,17 @@ export class CoreCourseProvider { /** * Get the section ID a module belongs to. * + * @deprecated since 4.0. * @param moduleId The module ID. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the section ID. */ async getModuleSectionId(moduleId: number, siteId?: string): Promise { // Try to get the section using getModuleBasicInfo. - const module = await this.getModuleBasicInfo(moduleId, siteId); + const module = await CoreCourse.getModuleBasicInfo( + moduleId, + { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); return module.section; } @@ -722,32 +807,33 @@ export class CoreCourseProvider { const params: CoreCourseGetContentsParams = { courseid: courseId, - options: [ - { - name: 'excludemodules', - value: excludeModules, - }, - { - name: 'excludecontents', - value: excludeContents, - }, - ], }; + params.options = [ + { + name: 'excludemodules', + value: excludeModules, + }, + { + name: 'excludecontents', + value: excludeContents, + }, + ]; + if (this.canRequestStealthModules(site)) { - params.options!.push({ + params.options.push({ name: 'includestealthmodules', value: includeStealthModules, }); } - let sections: CoreCourseWSSection[]; + let sections: CoreCourseGetContentsWSSection[]; try { sections = await site.read('core_course_get_contents', params, preSets); } catch { // Error getting the data, it could fail because we added a new parameter and the call isn't cached. // Retry without the new parameter and forcing cache. preSets.omitExpires = true; - params.options!.splice(-1, 1); + params.options.splice(-1, 1); sections = await site.read('core_course_get_contents', params, preSets); } @@ -755,15 +841,19 @@ export class CoreCourseProvider { let showSections = true; if (courseId == siteHomeId) { const storedNumSections = site.getStoredConfig('numsections'); - showSections = typeof storedNumSections != 'undefined' && !!storedNumSections; + showSections = storedNumSections !== undefined && !!storedNumSections; } - if (typeof showSections != 'undefined' && !showSections && sections.length > 0) { + if (showSections !== undefined && !showSections && sections.length > 0) { // Get only the last section (Main menu block section). sections.pop(); } - return sections; + // Add course to all modules. + return sections.map((section) => ({ + ...section, + modules: section.modules.map((module) => this.addAdditionalModuleData(module, courseId)), + })); } /** @@ -782,12 +872,12 @@ export class CoreCourseProvider { * @param sections Sections. * @return Modules. */ - getSectionsModules(sections: CoreCourseWSSection[]): CoreCourseWSModule[] { + getSectionsModules(sections: CoreCourseWSSection[]): CoreCourseModuleData[] { if (!sections || !sections.length) { return []; } - return sections.reduce((previous: CoreCourseWSModule[], section) => previous.concat(section.modules || []), []); + return sections.reduce((previous: CoreCourseModuleData[], section) => previous.concat(section.modules || []), []); } /** @@ -862,7 +952,7 @@ export class CoreCourseProvider { * Load module contents into module.contents if they aren't loaded already. * * @param module Module to load the contents. - * @param courseId The course ID. Recommended to speed up the process and minimize data usage. + * @param courseId Not used since 4.0. * @param sectionId The section ID. * @param preferCache True if shouldn't call WS if data is cached, false otherwise. * @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down). @@ -886,7 +976,7 @@ export class CoreCourseProvider { return; } - const mod = await this.getModule(module.id, courseId, sectionId, preferCache, ignoreCache, siteId, modName); + const mod = await this.getModule(module.id, module.course, sectionId, preferCache, ignoreCache, siteId, modName); if (!mod.contents) { throw new CoreError(Translate.instant('core.course.modulenotfound')); @@ -900,7 +990,7 @@ export class CoreCourseProvider { * It will throw an error if contents cannot be loaded. * * @param module Module to get its contents. - * @param courseId The course ID. Recommended to speed up the process and minimize data usage. + * @param courseId Not used since 4.0. * @param sectionId The section ID. * @param preferCache True if shouldn't call WS if data is cached, false otherwise. * @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down). @@ -910,7 +1000,7 @@ export class CoreCourseProvider { * @return Promise resolved when loaded. */ async getModuleContents( - module: CoreCourseAnyModuleData, + module: CoreCourseModuleData, courseId?: number, sectionId?: number, preferCache?: boolean, @@ -919,7 +1009,7 @@ export class CoreCourseProvider { modName?: string, ): Promise { // Make sure contents are loaded. - await this.loadModuleContents(module, courseId, sectionId, preferCache, ignoreCache, siteId, modName); + await this.loadModuleContents(module, undefined, sectionId, preferCache, ignoreCache, siteId, modName); if (!module.contents) { throw new CoreError(Translate.instant('core.course.modulenotfound')); @@ -943,7 +1033,7 @@ export class CoreCourseProvider { }; const wsName = 'core_course_view_course'; - if (typeof sectionNumber != 'undefined') { + if (sectionNumber !== undefined) { params.sectionnumber = sectionNumber; } @@ -967,7 +1057,7 @@ export class CoreCourseProvider { * @param cmId The module ID. * @param completed Whether the module is completed or not. * @param courseId Course ID the module belongs to. - * @param courseName Course name. Recommended, it is used to display a better warning message. + * @param courseName Not used since 4.0. * @param siteId Site ID. If not defined, current site. * @return Promise resolved when completion is successfully sent or stored. */ @@ -983,10 +1073,10 @@ export class CoreCourseProvider { // Convenience function to store a completion to be synchronized later. const storeOffline = (): Promise => - CoreCourseOffline.markCompletedManually(cmId, completed, courseId, courseName, siteId); + CoreCourseOffline.markCompletedManually(cmId, completed, courseId, undefined, siteId); // The offline function requires a courseId and it could be missing because it's a calculated field. - if (!CoreApp.isOnline() && courseId) { + if (!CoreApp.isOnline()) { // App is offline, store the action. return storeOffline(); } @@ -996,18 +1086,14 @@ export class CoreCourseProvider { const result = await this.markCompletedManuallyOnline(cmId, completed, siteId); // Data sent to server, if there is some offline data delete it now. - try { - await CoreCourseOffline.deleteManualCompletion(cmId, siteId); - } catch { - // Ignore errors, shouldn't happen. - } + await CoreUtils.ignoreErrors(CoreCourseOffline.deleteManualCompletion(cmId, siteId)); // Invalidate module now, completion has changed. await this.invalidateModule(cmId, siteId); return result; } catch (error) { - if (CoreUtils.isWebServiceError(error) || !courseId) { + if (CoreUtils.isWebServiceError(error)) { // The WebService has thrown an error, this means that responses cannot be submitted. throw error; } else { @@ -1058,7 +1144,7 @@ export class CoreCourseProvider { * @param module The module object. * @return Whether the module has a view page. */ - moduleHasView(module: CoreCourseModuleSummary | CoreCourseWSModule): boolean { + moduleHasView(module: CoreCourseModuleSummary | CoreCourseModuleData): boolean { if ('modname' in module) { // noviewlink was introduced in 3.8.5, use supports feature as a fallback. if (module.noviewlink || @@ -1090,7 +1176,7 @@ export class CoreCourseProvider { // Wait for site plugins to be fetched. await CoreUtils.ignoreErrors(CoreSitePlugins.waitFetchPlugins()); - if (!('format' in course) || typeof course.format == 'undefined') { + if (!('format' in course) || course.format === undefined) { const result = await CoreCourseHelper.getCourse(course.id); course = result.course; @@ -1210,7 +1296,7 @@ export class CoreCourseProvider { try { const entry = await this.getCourseStatusData(courseId, siteId); - if (typeof downloadTime == 'undefined') { + if (downloadTime === undefined) { // Keep previous download time. downloadTime = entry.downloadTime; previousDownloadTime = entry.previousDownloadTime; @@ -1346,7 +1432,7 @@ export type CoreCourseCompletionActivityStatus = { instance: number; // Instance ID. state: number; // Completion state value: 0 means incomplete, 1 complete, 2 complete pass, 3 complete fail. timecompleted: number; // Timestamp for completed activity. - tracking: number; // Type of tracking: 0 means none, 1 manual, 2 automatic. + tracking: CoreCourseModuleCompletionTracking; // Type of tracking: 0 means none, 1 manual, 2 automatic. overrideby?: number | null; // The user id who has overriden the status, or null. valueused?: boolean; // Whether the completion status affects the availability of another activity. hascompletion?: boolean; // @since 3.11. Whether this activity module has completion enabled. @@ -1437,7 +1523,12 @@ export type CoreCourseGetContentsParams = { /** * Data returned by core_course_get_contents WS. */ -export type CoreCourseWSSection = { +type CoreCourseGetContentsWSResponse = CoreCourseGetContentsWSSection[]; + +/** + * Section data returned by core_course_get_contents WS. + */ +type CoreCourseGetContentsWSSection = { id: number; // Section ID. name: string; // Section name. visible?: number; // Is the section visible. @@ -1447,7 +1538,54 @@ export type CoreCourseWSSection = { hiddenbynumsections?: number; // Whether is a section hidden in the course format. uservisible?: boolean; // Is the section visible for the user?. availabilityinfo?: string; // Availability information. - modules: CoreCourseWSModule[]; + modules: CoreCourseGetContentsWSModule[]; // List of module. +}; + +/** + * Module data returned by core_course_get_contents WS. + */ +export type CoreCourseGetContentsWSModule = { + id: number; // Activity id. + url?: string; // Activity url. + name: string; // Activity module name. + instance: number; // Instance id. Cannot be undefined. + contextid?: number; // @since 3.10. Activity context id. + description?: string; // Activity description. + visible: number; // Is the module visible. Cannot be undefined. + uservisible: boolean; // Is the module visible for the user?. Cannot be undefined. + availabilityinfo?: string; // Availability information. + visibleoncoursepage: number; // Is the module visible on course page. Cannot be undefined. + modicon: string; // Activity icon url. + modname: string; // Activity module type. + modplural: string; // Activity module plural name. + availability?: string; // Module availability settings. + indent: number; // Number of identation in the site. + onclick?: string; // Onclick action. + afterlink?: string; // After link info to be displayed. + customdata?: string; // Custom data (JSON encoded). + noviewlink?: boolean; // Whether the module has no view page. + completion?: CoreCourseModuleCompletionTracking; // Type of completion tracking: 0 means none, 1 manual, 2 automatic. + completiondata?: CoreCourseModuleWSCompletionData; // Module completion data. + contents?: CoreCourseModuleContentFile[]; + downloadcontent?: number; // @since 4.0 The download content value. + dates?: { + label: string; + timestamp: number; + }[]; // @since 3.11. Activity dates. + contentsinfo?: { // @since v3.7.6 Contents summary information. + filescount: number; // Total number of files. + filessize: number; // Total files size. + lastmodified: number; // Last time files were modified. + mimetypes: string[]; // Files mime types. + repositorytype?: string; // The repository type for the main file. + }; +}; + +/** + * Data returned by core_course_get_contents WS. + */ +export type CoreCourseWSSection = Omit & { + modules: CoreCourseModuleData[]; // List of module. }; /** @@ -1468,56 +1606,25 @@ type CoreCourseGetCourseModuleByInstanceWSParams = { /** * Data returned by core_course_get_course_module and core_course_get_course_module_by_instance WS. */ -export type CoreCourseGetCourseModuleWSResponse = { +type CoreCourseGetCourseModuleWSResponse = { cm: CoreCourseModuleBasicInfo; warnings?: CoreWSExternalWarning[]; }; /** - * Course module data returned by the WS. + * Course module data returned by the WS with course added. + * + * @deprecated since 4.0. Use CoreCourseModuleData instead. */ -export type CoreCourseWSModule = { - id: number; // Activity id. - course?: number; // The course id. - url?: string; // Activity url. - name: string; // Activity module name. - instance?: number; // Instance id. - contextid?: number; // Activity context id. - description?: string; // Activity description. - visible?: number; // Is the module visible. - uservisible?: boolean; // Is the module visible for the user?. - availabilityinfo?: string; // Availability information. - visibleoncoursepage?: number; // Is the module visible on course page. - modicon: string; // Activity icon url. - modname: string; // Activity module type. - modplural: string; // Activity module plural name. - availability?: string; // Module availability settings. - indent: number; // Number of identation in the site. - onclick?: string; // Onclick action. - afterlink?: string; // After link info to be displayed. - customdata?: string; // Custom data (JSON encoded). - noviewlink?: boolean; // Whether the module has no view page. - completion?: number; // Type of completion tracking: 0 means none, 1 manual, 2 automatic. - completiondata?: CoreCourseModuleWSCompletionData; // Module completion data. - contents?: CoreCourseModuleContentFile[]; - dates?: { - label: string; - timestamp: number; - }[]; // @since 3.11. Activity dates. - contentsinfo?: { // @since v3.7.6 Contents summary information. - filescount: number; // Total number of files. - filessize: number; // Total files size. - lastmodified: number; // Last time files were modified. - mimetypes: string[]; // Files mime types. - repositorytype?: string; // The repository type for the main file. - }; +export type CoreCourseWSModule = CoreCourseGetContentsWSModule & { + course: number; // The course id. }; /** * Module completion data. */ export type CoreCourseModuleWSCompletionData = { - state: number; // Completion state value: 0 means incomplete, 1 complete, 2 complete pass, 3 complete fail. + state: CoreCourseModuleCompletionStatus; // Completion state value. timecompleted: number; // Timestamp for completion status. overrideby: number | null; // The user id who has overriden the status. valueused?: boolean; // Whether the completion status affects the availability of another activity. @@ -1612,9 +1719,11 @@ export type CoreCourseModuleBasicInfo = CoreCourseModuleGradeInfo & { visibleoncoursepage?: number; // If visible on course page. visibleold?: number; // Visible old. completiongradeitemnumber?: number; // Completion grade item. + completionpassgrade?: number; // @since 4.0. Completion pass grade setting. completionview?: number; // Completion view setting. completionexpected?: number; // Completion time expected. showdescription?: number; // If the description is showed. + downloadcontent?: number; // @since 4.0. The download content value. availability?: string; // Availability settings. }; @@ -1637,6 +1746,6 @@ type CoreCompletionUpdateActivityCompletionStatusManuallyWSParams = { /** * Any of the possible module WS data. */ -export type CoreCourseAnyModuleData = CoreCourseWSModule | CoreCourseModuleBasicInfo & { +export type CoreCourseAnyModuleData = CoreCourseModuleData | CoreCourseModuleBasicInfo & { contents?: CoreCourseModuleContentFile[]; // If needed, calculated in the app in loadModuleContents. }; diff --git a/src/core/features/course/services/database/course.ts b/src/core/features/course/services/database/course.ts index db0305c68..7869b8a55 100644 --- a/src/core/features/course/services/database/course.ts +++ b/src/core/features/course/services/database/course.ts @@ -81,7 +81,7 @@ export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = { type: 'INTEGER', }, { - name: 'coursename', + name: 'coursename', // Not used since 4.0 it can be safely removed. type: 'TEXT', }, { @@ -106,6 +106,5 @@ export type CoreCourseManualCompletionDBRecord = { cmid: number; completed: number; courseid: number; - coursename: string; timecompleted: number; }; diff --git a/src/core/features/course/services/handlers/default-module.ts b/src/core/features/course/services/handlers/default-module.ts index 6e8cb25d6..13f40a844 100644 --- a/src/core/features/course/services/handlers/default-module.ts +++ b/src/core/features/course/services/handlers/default-module.ts @@ -17,7 +17,7 @@ import { Injectable, Type } from '@angular/core'; import { CoreSites } from '@services/sites'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '../module-delegate'; import { CoreCourse } from '../course'; -import { CoreCourseModule } from '../course-helper'; +import { CoreCourseModuleData } from '../course-helper'; import { CoreCourseUnsupportedModuleComponent } from '@features/course/components/unsupported-module/unsupported-module'; import { CoreNavigationOptions, CoreNavigator } from '@services/navigator'; @@ -42,14 +42,14 @@ export class CoreCourseModuleDefaultHandler implements CoreCourseModuleHandler { * @inheritdoc */ async getData( - module: CoreCourseModule, + module: CoreCourseModuleData, ): Promise { // Return the default data. const defaultData: CoreCourseModuleHandlerData = { icon: await CoreCourse.getModuleIconSrc(module.modname, module.modicon), title: module.name, class: 'core-course-default-handler core-course-module-' + module.modname + '-handler', - action: async (event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions) => { + action: async (event: Event, module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions) => { event.preventDefault(); event.stopPropagation(); @@ -92,7 +92,7 @@ export class CoreCourseModuleDefaultHandler implements CoreCourseModuleHandler { /** * @inheritdoc */ - async openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise { + async openActivityPage(module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions): Promise { options = options || {}; options.params = options.params || {}; Object.assign(options.params, { module }); diff --git a/src/core/features/course/services/module-delegate.ts b/src/core/features/course/services/module-delegate.ts index 2776043ff..d32c1be3e 100644 --- a/src/core/features/course/services/module-delegate.ts +++ b/src/core/features/course/services/module-delegate.ts @@ -20,10 +20,10 @@ import { CoreSite } from '@classes/site'; import { CoreCourseModuleDefaultHandler } from './handlers/default-module'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; -import { CoreCourse, CoreCourseWSModule } from './course'; +import { CoreCourse } from './course'; import { CoreSites } from '@services/sites'; import { makeSingleton } from '@singletons'; -import { CoreCourseModule } from './course-helper'; +import { CoreCourseModuleData } from './course-helper'; import { CoreNavigationOptions } from '@services/navigator'; /** @@ -52,7 +52,7 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler { * @return Data to render the module. */ getData( - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, sectionId?: number, forCoursePage?: boolean, @@ -67,7 +67,7 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler { * @param module The module object. * @return Promise resolved with component to use, undefined if not found. */ - getMainComponent(course: CoreCourseAnyCourseData, module: CoreCourseWSModule): Promise | undefined>; + getMainComponent(course: CoreCourseAnyCourseData, module: CoreCourseModuleData): Promise | undefined>; /** * Whether to display the course refresher in single activity course format. If it returns false, a refresher must be @@ -83,7 +83,7 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler { * @param module: Module to get the icon from. * @return The icon src. */ - getIconSrc?(module?: CoreCourseWSModule): Promise | string | undefined; + getIconSrc?(module?: CoreCourseModuleData): Promise | string | undefined; /** * Check if this type of module supports a certain feature. @@ -101,7 +101,7 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler { * @param module Module. * @return Promise resolved with boolean: whether the manual completion should always be displayed. */ - manualCompletionAlwaysShown?(module: CoreCourseModule): Promise; + manualCompletionAlwaysShown?(module: CoreCourseModuleData): Promise; /** * Opens the activity page. @@ -111,7 +111,7 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler { * @param options Options for the navigation. * @return Promise resolved when done. */ - openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise; + openActivityPage(module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions): Promise; } /** @@ -179,7 +179,7 @@ export interface CoreCourseModuleHandlerData { * @param options Options for the navigation. * @return Promise resolved when done. */ - action?(event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise | void; + action?(event: Event, module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions): Promise | void; /** * Updates the status of the module. @@ -250,7 +250,7 @@ export interface CoreCourseModuleHandlerButton { * @param options Options for the navigation. * @return Promise resolved when done. */ - action(event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise | void; + action(event: Event, module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions): Promise | void; } /** @@ -273,7 +273,7 @@ export class CoreCourseModuleDelegateService extends CoreDelegate | undefined> { + async getMainComponent(course: CoreCourseAnyCourseData, module: CoreCourseModuleData): Promise | undefined> { try { return await this.executeFunctionOnEnabled>(module.modname, 'getMainComponent', [course, module]); } catch (error) { @@ -293,7 +293,7 @@ export class CoreCourseModuleDelegateService extends CoreDelegate { @@ -381,7 +381,7 @@ export class CoreCourseModuleDelegateService extends CoreDelegate { + async getModuleIconSrc(modname: string, modicon?: string, module?: CoreCourseModuleData): Promise { const icon = await this.executeFunctionOnEnabled>(modname, 'getIconSrc', [module]); return icon || await CoreCourse.getModuleIconSrc(modname, modicon) || ''; @@ -419,7 +419,7 @@ export class CoreCourseModuleDelegateService extends CoreDelegate { + async manualCompletionAlwaysShown(module: CoreCourseModuleData): Promise { const result = await this.executeFunctionOnEnabled(module.modname, 'manualCompletionAlwaysShown', [module]); return !!result; diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index ff494e60a..a2998f6d7 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -22,7 +22,7 @@ import { CoreFilepool } from '@services/filepool'; import { CoreSites } from '@services/sites'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseModuleContentFile, CoreCourseWSModule } from './course'; +import { CoreCourse, CoreCourseAnyModuleData, CoreCourseModuleContentFile } from './course'; import { CoreCache } from '@classes/cache'; import { CoreSiteWSPreSets } from '@classes/site'; import { CoreConstants } from '@/core/constants'; @@ -33,6 +33,7 @@ import { CoreError } from '@classes/errors/error'; import { CoreWSFile, CoreWSExternalWarning } from '@services/ws'; import { CHECK_UPDATES_TIMES_TABLE, CoreCourseCheckUpdatesDBRecord } from './database/module-prefetch'; import { CoreFileSizeSum } from '@services/plugin-file-delegate'; +import { CoreCourseModuleData } from './course-helper'; const ROOT_CACHE_KEY = 'mmCourse:'; @@ -94,7 +95,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { // Module not supported, cannot use check updates. @@ -123,7 +124,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + protected async createToCheckList(modules: CoreCourseModuleData[], courseId: number): Promise { const result: ToCheckList = { toCheck: [], cannotUse: [], @@ -170,7 +171,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { // Check if the module has a prefetch handler. - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { return; @@ -221,12 +222,12 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + async getCourseUpdates(modules: CoreCourseModuleData[], courseId: number): Promise { // Check if there's already a getCourseUpdates in progress. const id = Md5.hashAsciiStr(courseId + '#' + JSON.stringify(modules)); const siteId = CoreSites.getCurrentSiteId(); - if (this.courseUpdatesPromises[siteId] && this.courseUpdatesPromises[siteId][id]) { + if (this.courseUpdatesPromises[siteId] && this.courseUpdatesPromises[siteId][id] !== undefined) { // There's already a get updates ongoing, return the promise. return this.courseUpdatesPromises[siteId][id]; } else if (!this.courseUpdatesPromises[siteId]) { @@ -253,7 +254,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { @@ -351,7 +352,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + async getDownloadSize(modules: CoreCourseModuleData[], courseId: number): Promise { // Get the status of each module. const data = await this.getModulesStatus(modules, courseId); @@ -380,7 +381,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { return { size: 0, total: false }; @@ -392,7 +393,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'downloadSize'); - if (typeof downloadSize != 'undefined') { + if (downloadSize !== undefined) { return downloadSize; } @@ -418,7 +419,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { return 0; } @@ -430,7 +431,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'downloadedSize'); - if (typeof downloadedSize != 'undefined') { + if (downloadedSize !== undefined) { return downloadedSize; } @@ -491,7 +492,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (handler?.getFiles) { // The handler defines a function to get files, use it. @@ -547,7 +548,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { // No handler found, module not downloadable. @@ -558,7 +559,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status'); - if (!refresh && typeof status != 'undefined') { + if (!refresh && status !== undefined) { this.storeCourseAndSection(packageId, courseId, sectionId); return this.determineModuleStatus(module, status); @@ -612,7 +613,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler || (onlyToDisplay && handler.skipListStatus)) { return; } @@ -729,7 +730,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status', true); - if (typeof cacheStatus == 'undefined') { + if (cacheStatus === undefined) { throw error; } @@ -757,7 +758,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); const siteId = CoreSites.getCurrentSiteId(); if (!handler) { @@ -769,7 +770,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status'); - if (typeof status != 'undefined' && !CoreFileHelper.isStateDownloaded(status)) { + if (status !== undefined && !CoreFileHelper.isStateDownloaded(status)) { // Module isn't downloaded, just return the status. return { status }; } @@ -862,11 +863,11 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + async invalidateModules(modules: CoreCourseModuleData[], courseId: number): Promise { const promises = modules.map(async (module) => { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { return; } @@ -918,7 +919,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'downloadable'); - if (typeof downloadable != 'undefined') { + if (downloadable !== undefined) { return downloadable; } @@ -999,7 +1000,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); const moduleUpdates = updates[module.id]; if (handler?.hasUpdates) { @@ -1032,7 +1033,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { return; } @@ -1049,7 +1050,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + syncModules(modules: CoreCourseModuleData[], courseId: number): Promise { return Promise.all(modules.map(async (module) => { await this.syncModule(module, courseId); @@ -1066,7 +1067,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(module: CoreCourseAnyModuleData, courseId: number): Promise { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler?.sync) { return; } @@ -1091,7 +1092,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { @@ -1123,7 +1124,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { // Check if the module has a prefetch handler. - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); if (!handler) { return; } @@ -1169,7 +1170,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - const handler = this.getPrefetchHandlerFor(module); + const handler = this.getPrefetchHandlerFor(module.name); const siteId = CoreSites.getCurrentSiteId(); if (handler?.removeFiles) { @@ -1512,7 +1513,7 @@ export interface CoreCourseModulePrefetchHandler extends CoreDelegateHandler { type ToCheckList = { toCheck: CheckUpdatesToCheckWSParam[]; - cannotUse: CoreCourseWSModule[]; + cannotUse: CoreCourseModuleData[]; }; /** @@ -1526,10 +1527,10 @@ type CourseUpdates = Record; export type CoreCourseModulesStatus = { total: number; // Number of modules. status: string; // Status of the list of modules. - [CoreConstants.NOT_DOWNLOADED]: CoreCourseWSModule[]; // Modules with state NOT_DOWNLOADED. - [CoreConstants.DOWNLOADED]: CoreCourseWSModule[]; // Modules with state DOWNLOADED. - [CoreConstants.DOWNLOADING]: CoreCourseWSModule[]; // Modules with state DOWNLOADING. - [CoreConstants.OUTDATED]: CoreCourseWSModule[]; // Modules with state OUTDATED. + [CoreConstants.NOT_DOWNLOADED]: CoreCourseModuleData[]; // Modules with state NOT_DOWNLOADED. + [CoreConstants.DOWNLOADED]: CoreCourseModuleData[]; // Modules with state DOWNLOADED. + [CoreConstants.DOWNLOADING]: CoreCourseModuleData[]; // Modules with state DOWNLOADING. + [CoreConstants.OUTDATED]: CoreCourseModuleData[]; // Modules with state OUTDATED. }; /** diff --git a/src/core/features/course/services/sync.ts b/src/core/features/course/services/sync.ts index 3b29dc151..9d3899dba 100644 --- a/src/core/features/course/services/sync.ts +++ b/src/core/features/course/services/sync.ts @@ -28,6 +28,7 @@ import { CoreCourseManualCompletionDBRecord } from './database/course'; import { CoreNetworkError } from '@classes/errors/network-error'; import { makeSingleton, Translate } from '@singletons'; import { CoreEvents } from '@singletons/events'; +import { CoreCourses } from '@features/courses/services/courses'; /** * Service to sync course offline data. This only syncs the offline data of the course itself, not the offline data of @@ -77,10 +78,18 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider { const completions = await CoreCourseOffline.getAllManualCompletions(siteId); + const courseNames: Record = {}; + // Sync all courses. await Promise.all(completions.map(async (completion) => { - const result = await (force ? this.syncCourse(completion.courseid, siteId) : - this.syncCourseIfNeeded(completion.courseid, siteId)); + if (courseNames[completion.courseid] === undefined) { + const course = await CoreUtils.ignoreErrors(CoreCourses.getUserCourse(completion.courseid, true, siteId)); + + courseNames[completion.courseid] = course?.displayname || course?.fullname; + } + + const result = await (force ? this.syncCourse(completion.courseid, courseNames[completion.courseid], siteId) : + this.syncCourseIfNeeded(completion.courseid, courseNames[completion.courseid], siteId)); if (!result || !result.updated) { return; @@ -98,23 +107,25 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider { + syncCourseIfNeeded(courseId: number, courseName?: string, siteId?: string): Promise { // Usually we call isSyncNeeded to check if a certain time has passed. // However, since we barely send data for now just sync the course. - return this.syncCourse(courseId, siteId); + return this.syncCourse(courseId, courseName, siteId); } /** * Synchronize a course. * * @param courseId Course ID to be synced. + * @param courseName Course Name to be synced. * @param siteId Site ID. If not defined, current site. * @return Promise resolved if sync is successful, rejected otherwise. */ - async syncCourse(courseId: number, siteId?: string): Promise { + async syncCourse(courseId: number, courseName?: string, siteId?: string): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); const currentSyncPromise = this.getOngoingSync(courseId, siteId); @@ -125,17 +136,18 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider { + protected async syncCourseCompletion(courseId: number, courseName?: string, siteId?: string): Promise { const result: CoreCourseSyncResult = { warnings: [], updated: false, @@ -182,7 +194,7 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider { diff --git a/src/core/features/courses/services/courses-helper.ts b/src/core/features/courses/services/courses-helper.ts index 62f98ed70..aa794077b 100644 --- a/src/core/features/courses/services/courses-helper.ts +++ b/src/core/features/courses/services/courses-helper.ts @@ -270,12 +270,12 @@ export class CoreCoursesHelperProvider { courses = slice > 0 ? courses.slice(0, slice) : courses; return Promise.all(courses.map(async (course) => { - if (typeof course.completed != 'undefined') { + if (course.completed !== undefined) { // The WebService already returns the completed status, no need to fetch it. return course; } - if (typeof course.enablecompletion != 'undefined' && !course.enablecompletion) { + if (course.enablecompletion !== undefined && !course.enablecompletion) { // Completion is disabled for this course, there is no need to fetch the completion status. return course; } diff --git a/src/core/features/courses/services/courses.ts b/src/core/features/courses/services/courses.ts index 002d3fc28..a724803f0 100644 --- a/src/core/features/courses/services/courses.ts +++ b/src/core/features/courses/services/courses.ts @@ -524,15 +524,15 @@ export class CoreCoursesProvider { // Courses will be sorted using sortorder if available. return response.courses.sort((a, b) => { - if (typeof a.sortorder == 'undefined' && typeof b.sortorder == 'undefined') { + if (a.sortorder === undefined && b.sortorder === undefined) { return b.id - a.id; } - if (typeof a.sortorder == 'undefined') { + if (a.sortorder === undefined) { return 1; } - if (typeof b.sortorder == 'undefined') { + if (b.sortorder === undefined) { return -1; } diff --git a/src/core/features/courses/services/handlers/course-link.ts b/src/core/features/courses/services/handlers/course-link.ts index dfe5426a7..5e1800ddb 100644 --- a/src/core/features/courses/services/handlers/course-link.ts +++ b/src/core/features/courses/services/handlers/course-link.ts @@ -65,7 +65,7 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler const pageParams: Params = { sectionId: sectionId || null, }; - let sectionNumber = typeof params.section != 'undefined' ? parseInt(params.section, 10) : NaN; + let sectionNumber = params.section !== undefined ? parseInt(params.section, 10) : NaN; if (!sectionId && !sectionNumber) { // Check if the URL has a hash to navigate to the section. @@ -294,7 +294,7 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler let body = ' '; // Empty message. const placeholder = Translate.instant('core.courses.password'); - if (typeof password != 'undefined') { + if (password !== undefined) { // The user attempted a password. Show an error message. body = CoreTextUtils.getErrorMessageFromError(error) || body; } diff --git a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts index 84c2931ef..2b82866d7 100644 --- a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts +++ b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts @@ -484,7 +484,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn }; let range = document.createRange(); - if (typeof chars === 'undefined') { + if (chars === undefined) { // Select all so it will go to the end. range.selectNode(parent); range.selectNodeContents(parent); @@ -601,7 +601,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn * @param value text */ protected isNullOrWhiteSpace(value: string | null): boolean { - if (value == null || typeof value == 'undefined') { + if (value == null || value === undefined) { return true; } @@ -926,10 +926,10 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn */ protected shouldAutoSaveDrafts(): boolean { return !!CoreSites.getCurrentSite() && - (typeof this.autoSave == 'undefined' || CoreUtils.isTrueOrOne(this.autoSave)) && - typeof this.contextLevel != 'undefined' && - typeof this.contextInstanceId != 'undefined' && - typeof this.elementId != 'undefined'; + (this.autoSave === undefined || CoreUtils.isTrueOrOne(this.autoSave)) && + this.contextLevel !== undefined && + this.contextInstanceId !== undefined && + this.elementId !== undefined; } /** @@ -948,7 +948,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn this.originalContent, ); - if (typeof entry == 'undefined') { + if (entry === undefined) { // No draft found. return; } diff --git a/src/core/features/emulator/services/capture-helper.ts b/src/core/features/emulator/services/capture-helper.ts index daee4b3d7..a65ebca93 100644 --- a/src/core/features/emulator/services/capture-helper.ts +++ b/src/core/features/emulator/services/capture-helper.ts @@ -192,7 +192,7 @@ export class CoreEmulatorCaptureHelperProvider { * @return Promise resolved when loaded. */ load(): Promise { - if (typeof window.MediaRecorder != 'undefined' && this.initGetUserMedia()) { + if (window.MediaRecorder !== undefined && this.initGetUserMedia()) { this.initMimeTypes(); } diff --git a/src/core/features/emulator/services/file.ts b/src/core/features/emulator/services/file.ts index bde3461bd..71eae6136 100644 --- a/src/core/features/emulator/services/file.ts +++ b/src/core/features/emulator/services/file.ts @@ -344,10 +344,10 @@ export class FileMock extends File { // eslint-disable-next-line @typescript-eslint/no-explicit-any const win = window; // Convert to to be able to use non-standard properties. - if (typeof win.requestFileSystem == 'undefined') { + if (win.requestFileSystem === undefined) { win.requestFileSystem = win.webkitRequestFileSystem; } - if (typeof win.resolveLocalFileSystemURL == 'undefined') { + if (win.resolveLocalFileSystemURL === undefined) { win.resolveLocalFileSystemURL = win.webkitResolveLocalFileSystemURL; } win.LocalFileSystem = { diff --git a/src/core/features/fileuploader/services/fileuploader-helper.ts b/src/core/features/fileuploader/services/fileuploader-helper.ts index b00769de3..33b70931d 100644 --- a/src/core/features/fileuploader/services/fileuploader-helper.ts +++ b/src/core/features/fileuploader/services/fileuploader-helper.ts @@ -123,8 +123,8 @@ export class CoreFileUploaderHelperProvider { throw new CoreError(Translate.instant('core.fileuploader.errormustbeonlinetoupload')); } - wifiThreshold = typeof wifiThreshold == 'undefined' ? CoreFileUploaderProvider.WIFI_SIZE_WARNING : wifiThreshold; - limitedThreshold = typeof limitedThreshold == 'undefined' ? + wifiThreshold = wifiThreshold === undefined ? CoreFileUploaderProvider.WIFI_SIZE_WARNING : wifiThreshold; + limitedThreshold = limitedThreshold === undefined ? CoreFileUploaderProvider.LIMITED_SIZE_WARNING : limitedThreshold; if (size < 0) { @@ -203,7 +203,7 @@ export class CoreFileUploaderHelperProvider { const fileName = options?.fileName || CoreFile.getFileAndDirectoryFromPath(path).name; // Check that size isn't too large. - if (typeof maxSize != 'undefined' && maxSize != -1) { + if (maxSize !== undefined && maxSize != -1) { try { const fileEntry = await CoreFile.getExternalFile(path); diff --git a/src/core/features/filter/services/filter.ts b/src/core/features/filter/services/filter.ts index 4b7dd89ca..e413084d5 100644 --- a/src/core/features/filter/services/filter.ts +++ b/src/core/features/filter/services/filter.ts @@ -205,11 +205,11 @@ export class CoreFilterProvider { // Clone object if needed so we can modify it. options = options ? Object.assign({}, options) : {}; - if (typeof options.clean == 'undefined') { + if (options.clean === undefined) { options.clean = false; } - if (typeof options.filter == 'undefined') { + if (options.filter === undefined) { options.filter = true; } diff --git a/src/core/features/grades/services/grades-helper.ts b/src/core/features/grades/services/grades-helper.ts index 319dc9313..b602a8df5 100644 --- a/src/core/features/grades/services/grades-helper.ts +++ b/src/core/features/grades/services/grades-helper.ts @@ -184,13 +184,13 @@ export class CoreGradesHelperProvider { let normalRow = formatted.rows.find( row => row.itemtype != 'leader' && - (typeof row.grade != 'undefined' || typeof row.percentage != 'undefined'), + (row.grade !== undefined || row.percentage !== undefined), ); // Decide if grades or percentage is being shown on phones. - if (normalRow && typeof normalRow.grade != 'undefined') { + if (normalRow && normalRow.grade !== undefined) { columns.grade = true; - } else if (normalRow && typeof normalRow.percentage != 'undefined') { + } else if (normalRow && normalRow.percentage !== undefined) { columns.percentage = true; } else { normalRow = formatted.rows.find((e) => e.itemtype != 'leader'); @@ -198,7 +198,7 @@ export class CoreGradesHelperProvider { } for (const colName in columns) { - if (normalRow && typeof normalRow[colName] != 'undefined') { + if (normalRow && normalRow[colName] !== undefined) { formatted.columns.push({ name: colName, colspan: colName == 'gradeitem' ? maxDepth : 1, @@ -562,7 +562,7 @@ export class CoreGradesHelperProvider { row.iconAlt = Translate.instant('core.grades.calculatedgrade'); } else if (text.indexOf('/mod/') > -1) { const module = text.match(/mod\/([^/]*)\//); - if (typeof module?.[1] != 'undefined') { + if (module?.[1] !== undefined) { row.itemtype = 'mod'; row.itemmodule = module[1]; row.iconAlt = CoreCourse.translateModuleName(row.itemmodule) || ''; @@ -613,7 +613,7 @@ export class CoreGradesHelperProvider { defaultValue: string | number = '', scale?: string, ): Promise { - if (typeof gradingType == 'undefined') { + if (gradingType === undefined) { return []; } diff --git a/src/core/features/grades/services/grades.ts b/src/core/features/grades/services/grades.ts index 00280957d..80b588e8a 100644 --- a/src/core/features/grades/services/grades.ts +++ b/src/core/features/grades/services/grades.ts @@ -318,7 +318,7 @@ export class CoreGradesProvider { const course = await CoreCourses.getUserCourse(courseId, true, siteId); - return !(course && typeof course.showgrades != 'undefined' && !course.showgrades); + return !(course && course.showgrades !== undefined && !course.showgrades); } /** diff --git a/src/core/features/grades/services/handlers/course-option.ts b/src/core/features/grades/services/handlers/course-option.ts index d3954b748..21fb0053b 100644 --- a/src/core/features/grades/services/handlers/course-option.ts +++ b/src/core/features/grades/services/handlers/course-option.ts @@ -41,7 +41,7 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa * @return Promise resolved when done. */ invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise { - if (navOptions && typeof navOptions.grades != 'undefined') { + if (navOptions && navOptions.grades !== undefined) { // No need to invalidate anything. return Promise.resolve(); } @@ -75,7 +75,7 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa return false; // Not enabled for guests. } - if (navOptions && typeof navOptions.grades != 'undefined') { + if (navOptions && navOptions.grades !== undefined) { return navOptions.grades; } diff --git a/src/core/features/h5p/classes/content-validator.ts b/src/core/features/h5p/classes/content-validator.ts index fb3468d5c..e3e916ba6 100644 --- a/src/core/features/h5p/classes/content-validator.ts +++ b/src/core/features/h5p/classes/content-validator.ts @@ -91,7 +91,7 @@ export class CoreH5PContentValidator { const group = CoreUtils.clone(metadata || {}); // Stop complaining about "invalid selected option in select" for old content without license chosen. - if (typeof group.license == 'undefined') { + if (group.license === undefined) { group.license = 'U'; } @@ -168,7 +168,7 @@ export class CoreH5PContentValidator { } // Check if string is within allowed length. - if (typeof semantics.maxLength != 'undefined') { + if (semantics.maxLength !== undefined) { text = text.substr(0, semantics.maxLength); } @@ -202,22 +202,22 @@ export class CoreH5PContentValidator { num = 0; } // Check if number is within valid bounds. Move within bounds if not. - if (typeof semantics.min != 'undefined' && num < semantics.min) { + if (semantics.min !== undefined && num < semantics.min) { num = semantics.min; } - if (typeof semantics.max != 'undefined' && num > semantics.max) { + if (semantics.max !== undefined && num > semantics.max) { num = semantics.max; } // Check if number is within allowed bounds even if step value is set. - if (typeof semantics.step != 'undefined') { - const testNumber = num - (typeof semantics.min != 'undefined' ? semantics.min : 0); + if (semantics.step !== undefined) { + const testNumber = num - (semantics.min !== undefined ? semantics.min : 0); const rest = testNumber % semantics.step; if (rest !== 0) { num -= rest; } } // Check if number has proper number of decimals. - if (typeof semantics.decimals != 'undefined') { + if (semantics.decimals !== undefined) { num = Number(num.toFixed(semantics.decimals)); } @@ -303,7 +303,7 @@ export class CoreH5PContentValidator { let keys = Object.keys(list); // Check that list is not longer than allowed length. - if (typeof semantics.max != 'undefined') { + if (semantics.max !== undefined) { keys = keys.slice(0, semantics.max); } @@ -392,8 +392,8 @@ export class CoreH5PContentValidator { file.bitrate = parseInt(file.bitrate, 10); } - if (typeof file.quality != 'undefined') { - if (file.quality === null || typeof file.quality.level == 'undefined' || typeof file.quality.label == 'undefined') { + if (file.quality !== undefined) { + if (file.quality === null || file.quality.level === undefined || file.quality.label === undefined) { delete file.quality; } else { this.filterParams(file.quality, ['level', 'label']); @@ -402,7 +402,7 @@ export class CoreH5PContentValidator { } } - if (typeof file.copyright != 'undefined') { + if (file.copyright !== undefined) { await this.validateGroup(file.copyright, this.getCopyrightSemantics()); } diff --git a/src/core/features/h5p/classes/core.ts b/src/core/features/h5p/classes/core.ts index 6ba4aeec8..ac6dddb45 100644 --- a/src/core/features/h5p/classes/core.ts +++ b/src/core/features/h5p/classes/core.ts @@ -241,7 +241,7 @@ export class CoreH5PCore { return content.filtered; } - if (typeof content.library == 'undefined' || typeof content.params == 'undefined') { + if (content.library === undefined || content.params === undefined) { return null; } diff --git a/src/core/features/h5p/classes/framework.ts b/src/core/features/h5p/classes/framework.ts index cfb77cac5..6386d853e 100644 --- a/src/core/features/h5p/classes/framework.ts +++ b/src/core/features/h5p/classes/framework.ts @@ -388,7 +388,7 @@ export class CoreH5PFramework { * @return Library parameter values separated by ', ' */ libraryParameterValuesToCsv(libraryData: CoreH5PLibraryBeingSaved, key: string, searchParam: string = 'path'): string { - if (typeof libraryData[key] != 'undefined') { + if (libraryData[key] !== undefined) { const parameterValues: string[] = []; libraryData[key].forEach((file) => { @@ -489,7 +489,7 @@ export class CoreH5PFramework { params.metadata.title = params.title; } content.metadata = params.metadata; - content.params = JSON.stringify(typeof params.params != 'undefined' && params.params != null ? params.params : params); + content.params = JSON.stringify(params.params !== undefined && params.params != null ? params.params : params); return content; } @@ -690,15 +690,15 @@ export class CoreH5PFramework { const preloadedCSS = this.libraryParameterValuesToCsv(libraryData, 'preloadedCss', 'path'); const dropLibraryCSS = this.libraryParameterValuesToCsv(libraryData, 'dropLibraryCss', 'machineName'); - if (typeof libraryData.semantics == 'undefined') { + if (libraryData.semantics === undefined) { libraryData.semantics = []; } - if (typeof libraryData.fullscreen == 'undefined') { + if (libraryData.fullscreen === undefined) { libraryData.fullscreen = 0; } let embedTypes = ''; - if (typeof libraryData.embedTypes != 'undefined') { + if (libraryData.embedTypes !== undefined) { embedTypes = libraryData.embedTypes.join(', '); } @@ -717,9 +717,9 @@ export class CoreH5PFramework { preloadedjs: preloadedJS, preloadedcss: preloadedCSS, droplibrarycss: dropLibraryCSS, - semantics: typeof libraryData.semantics != 'undefined' ? JSON.stringify(libraryData.semantics) : null, - addto: typeof libraryData.addTo != 'undefined' ? JSON.stringify(libraryData.addTo) : null, - metadatasettings: typeof libraryData.metadataSettings != 'undefined' ? + semantics: libraryData.semantics !== undefined ? JSON.stringify(libraryData.semantics) : null, + addto: libraryData.addTo !== undefined ? JSON.stringify(libraryData.addTo) : null, + metadatasettings: libraryData.metadataSettings !== undefined ? CoreH5PMetadata.boolifyAndEncodeSettings(libraryData.metadataSettings) : null, }; @@ -841,7 +841,7 @@ export class CoreH5PFramework { const db = await CoreSites.getSiteDb(siteId); // If the libraryid declared in the package is empty, get the latest version. - if (content.library && typeof content.library.libraryId == 'undefined') { + if (content.library && content.library.libraryId === undefined) { const mainLibrary = await this.getLatestLibraryVersion(content.library.machineName, siteId); content.library.libraryId = mainLibrary.id; @@ -867,7 +867,7 @@ export class CoreH5PFramework { }; let contentId: number | undefined; - if (typeof content.id != 'undefined') { + if (content.id !== undefined) { data.id = content.id; contentId = content.id; } else { diff --git a/src/core/features/h5p/classes/metadata.ts b/src/core/features/h5p/classes/metadata.ts index 359b0af26..b0639e57d 100644 --- a/src/core/features/h5p/classes/metadata.ts +++ b/src/core/features/h5p/classes/metadata.ts @@ -32,10 +32,10 @@ export class CoreH5PMetadata { } // Convert metadataSettings values to boolean. - if (typeof metadataSettings.disable != 'undefined') { + if (metadataSettings.disable !== undefined) { metadataSettings.disable = metadataSettings.disable === 1; } - if (typeof metadataSettings.disableExtraTitleField != 'undefined') { + if (metadataSettings.disableExtraTitleField !== undefined) { metadataSettings.disableExtraTitleField = metadataSettings.disableExtraTitleField === 1; } diff --git a/src/core/features/h5p/classes/storage.ts b/src/core/features/h5p/classes/storage.ts index c79bdd305..984dd022d 100644 --- a/src/core/features/h5p/classes/storage.ts +++ b/src/core/features/h5p/classes/storage.ts @@ -94,7 +94,7 @@ export class CoreH5PStorage { throw error; } - if (typeof libraryData.libraryId != 'undefined') { + if (libraryData.libraryId !== undefined) { const promises: Promise[] = []; // Remove all indexes of contents that use this library. @@ -127,17 +127,17 @@ export class CoreH5PStorage { // Insert the different new ones. const promises: Promise[] = []; - if (typeof libraryData.preloadedDependencies != 'undefined') { + if (libraryData.preloadedDependencies !== undefined) { promises.push(this.h5pFramework.saveLibraryDependencies( libraryData, libraryData.preloadedDependencies, 'preloaded', )); } - if (typeof libraryData.dynamicDependencies != 'undefined') { + if (libraryData.dynamicDependencies !== undefined) { promises.push(this.h5pFramework.saveLibraryDependencies(libraryData, libraryData.dynamicDependencies, 'dynamic')); } - if (typeof libraryData.editorDependencies != 'undefined') { + if (libraryData.editorDependencies !== undefined) { promises.push(this.h5pFramework.saveLibraryDependencies(libraryData, libraryData.editorDependencies, 'editor')); } diff --git a/src/core/features/h5p/classes/validator.ts b/src/core/features/h5p/classes/validator.ts index ac300f409..b95399f4b 100644 --- a/src/core/features/h5p/classes/validator.ts +++ b/src/core/features/h5p/classes/validator.ts @@ -65,13 +65,13 @@ export class CoreH5PValidator { const missing: Record = {}; Object.values(libraries).forEach((library) => { - if (typeof library.preloadedDependencies !== 'undefined') { + if (library.preloadedDependencies !== undefined) { Object.assign(missing, this.getMissingDependencies(library.preloadedDependencies, library, libraries)); } - if (typeof library.dynamicDependencies !== 'undefined') { + if (library.dynamicDependencies !== undefined) { Object.assign(missing, this.getMissingDependencies(library.dynamicDependencies, library, libraries)); } - if (typeof library.editorDependencies !== 'undefined') { + if (library.editorDependencies !== undefined) { Object.assign(missing, this.getMissingDependencies(library.editorDependencies, library, libraries)); } }); diff --git a/src/core/features/login/pages/email-signup/email-signup.ts b/src/core/features/login/pages/email-signup/email-signup.ts index 02812cc92..794e81e1d 100644 --- a/src/core/features/login/pages/email-signup/email-signup.ts +++ b/src/core/features/login/pages/email-signup/email-signup.ts @@ -165,7 +165,7 @@ export class CoreLoginEmailSignupPage implements OnInit { if (this.treatSiteConfig()) { // Check content verification. - if (typeof this.ageDigitalConsentVerification == 'undefined') { + if (this.ageDigitalConsentVerification === undefined) { const result = await CoreUtils.ignoreErrors( CoreWS.callAjax( diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index 627547671..ec3052968 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -323,7 +323,7 @@ export class CoreLoginHelperProvider { * @return OAuth ID. */ getOAuthIdFromParams(params?: CoreUrlParams): number | undefined { - return params && typeof params.oauthsso != 'undefined' ? Number(params.oauthsso) : undefined; + return params && params.oauthsso !== undefined ? Number(params.oauthsso) : undefined; } /** @@ -530,7 +530,7 @@ export class CoreLoginHelperProvider { * @return Whether email signup is disabled. */ isFeatureDisabled(feature: string, config?: CoreSitePublicConfigResponse, disabledFeatures?: string): boolean { - if (typeof disabledFeatures == 'undefined') { + if (disabledFeatures === undefined) { disabledFeatures = this.getDisabledFeatures(config); } @@ -978,7 +978,7 @@ export class CoreLoginHelperProvider { } const info = currentSite.getInfo(); - if (typeof info != 'undefined' && typeof info.username != 'undefined') { + if (info !== undefined && info.username !== undefined) { // If current page is already reconnect, stop. if (CoreNavigator.isCurrent('/login/reconnect')) { return; @@ -1249,7 +1249,7 @@ export class CoreLoginHelperProvider { * @return Whether the QR reader should be displayed in site screen. */ displayQRInSiteScreen(): boolean { - return CoreUtils.canScanQR() && (typeof CoreConstants.CONFIG.displayqronsitescreen == 'undefined' || + return CoreUtils.canScanQR() && (CoreConstants.CONFIG.displayqronsitescreen === undefined || !!CoreConstants.CONFIG.displayqronsitescreen); } diff --git a/src/core/features/mainmenu/pages/home/home.ts b/src/core/features/mainmenu/pages/home/home.ts index c7dfce575..a4d89d00e 100644 --- a/src/core/features/mainmenu/pages/home/home.ts +++ b/src/core/features/mainmenu/pages/home/home.ts @@ -109,7 +109,7 @@ export class CoreMainMenuHomePage implements OnInit { // Sort them by priority so new handlers are in the right position. newTabs.sort((a, b) => (handlersMap[b.title].priority || 0) - (handlersMap[a.title].priority || 0)); - if (typeof this.selectedTab == 'undefined' && newTabs.length > 0) { + if (this.selectedTab === undefined && newTabs.length > 0) { let maxPriority = 0; this.selectedTab = Object.entries(newTabs).reduce((maxIndex, [index, tab]) => { diff --git a/src/core/features/mainmenu/services/mainmenu.ts b/src/core/features/mainmenu/services/mainmenu.ts index d34ecde37..f1c09fef0 100644 --- a/src/core/features/mainmenu/services/mainmenu.ts +++ b/src/core/features/mainmenu/services/mainmenu.ts @@ -176,7 +176,7 @@ export class CoreMainMenuProvider { } // Remove undefined values. - return result.filter((entry) => typeof entry != 'undefined'); + return result.filter((entry) => entry !== undefined); } /** diff --git a/src/core/features/pushnotifications/services/push-delegate.ts b/src/core/features/pushnotifications/services/push-delegate.ts index 548301644..b897d0324 100644 --- a/src/core/features/pushnotifications/services/push-delegate.ts +++ b/src/core/features/pushnotifications/services/push-delegate.ts @@ -150,7 +150,7 @@ export class CorePushNotificationsDelegateService { * @return Observer to subscribe. */ on(eventName: string): Subject { - if (typeof this.observables[eventName] == 'undefined') { + if (this.observables[eventName] === undefined) { const eventNames = Object.keys(this.observables).join(', '); this.logger.warn(`'${eventName}' event name is not allowed. Use one of the following: '${eventNames}'.`); @@ -167,7 +167,7 @@ export class CorePushNotificationsDelegateService { * @return True if registered successfully, false otherwise. */ registerClickHandler(handler: CorePushNotificationsClickHandler): boolean { - if (typeof this.clickHandlers[handler.name] !== 'undefined') { + if (this.clickHandlers[handler.name] !== undefined) { this.logger.log(`Addon '${handler.name}' already registered`); return false; @@ -186,7 +186,7 @@ export class CorePushNotificationsDelegateService { * @param name Handler's name. */ registerCounterHandler(name: string): void { - if (typeof this.counterHandlers[name] == 'undefined') { + if (this.counterHandlers[name] === undefined) { this.logger.debug(`Registered handler '${name}' as badge counter handler.`); this.counterHandlers[name] = name; } else { @@ -201,7 +201,7 @@ export class CorePushNotificationsDelegateService { * @return If handler name is present. */ isCounterHandlerRegistered(name: string): boolean { - return typeof this.counterHandlers[name] != 'undefined'; + return this.counterHandlers[name] !== undefined; } /** diff --git a/src/core/features/question/classes/base-question-component.ts b/src/core/features/question/classes/base-question-component.ts index 630142130..7753c9d86 100644 --- a/src/core/features/question/classes/base-question-component.ts +++ b/src/core/features/question/classes/base-question-component.ts @@ -164,7 +164,7 @@ export class CoreQuestionBaseComponent { for (const i in options) { const optionEl = options[i]; - if (typeof optionEl.value == 'undefined') { + if (optionEl.value === undefined) { this.logger.warn('Aborting because couldn\'t find input.', this.question?.slot); CoreQuestionHelper.showComponentError(this.onAbort); @@ -225,7 +225,7 @@ export class CoreQuestionBaseComponent { // Extract question text. this.question.text = CoreDomUtils.getContentsOfElement(element, '.qtext'); - if (typeof this.question.text == 'undefined') { + if (this.question.text === undefined) { this.logger.warn('Aborting because of an error parsing question.', this.question.slot); return CoreQuestionHelper.showComponentError(this.onAbort); @@ -554,7 +554,7 @@ export class CoreQuestionBaseComponent { for (const j in options) { const optionEl = options[j]; - if (typeof optionEl.value == 'undefined') { + if (optionEl.value === undefined) { this.logger.warn('Aborting because couldn\'t find the value of an option.', question.slot); return CoreQuestionHelper.showComponentError(this.onAbort); diff --git a/src/core/features/question/services/question-helper.ts b/src/core/features/question/services/question-helper.ts index 6aacaca8a..b8ab02ad4 100644 --- a/src/core/features/question/services/question-helper.ts +++ b/src/core/features/question/services/question-helper.ts @@ -153,7 +153,7 @@ export class CoreQuestionHelperProvider { }); // If we have a certainty value stored in local we'll use that one. - if (question.localAnswers && typeof question.localAnswers['-certainty'] != 'undefined') { + if (question.localAnswers && question.localAnswers['-certainty'] !== undefined) { question.behaviourCertaintySelected = question.localAnswers['-certainty']; } diff --git a/src/core/features/rating/components/rate/rate.ts b/src/core/features/rating/components/rate/rate.ts index 55f489c7f..cf2c43639 100644 --- a/src/core/features/rating/components/rate/rate.ts +++ b/src/core/features/rating/components/rate/rate.ts @@ -142,7 +142,7 @@ export class CoreRatingRateComponent implements OnChanges, OnDestroy { this.aggregateMethod, ); - if (typeof response == 'undefined') { + if (response === undefined) { CoreDomUtils.showToast('core.datastoredoffline', true, 3000); } else { this.onUpdate.emit(); diff --git a/src/core/features/settings/services/settings-helper.ts b/src/core/features/settings/services/settings-helper.ts index 51e7a9c1f..3ca96984a 100644 --- a/src/core/features/settings/services/settings-helper.ts +++ b/src/core/features/settings/services/settings-helper.ts @@ -290,7 +290,7 @@ export class CoreSettingsHelperProvider { // Check old setting and update the new. try { const fontSize = await CoreConfig.get('CoreSettingsFontSize'); - if (typeof fontSize == 'undefined') { + if (fontSize === undefined) { // Already upgraded. return; } diff --git a/src/core/features/sitehome/pages/index/index.ts b/src/core/features/sitehome/pages/index/index.ts index eae6406f8..8e9a4d6e7 100644 --- a/src/core/features/sitehome/pages/index/index.ts +++ b/src/core/features/sitehome/pages/index/index.ts @@ -17,14 +17,14 @@ import { IonRefresher } from '@ionic/angular'; import { Params } from '@angular/router'; import { CoreSite, CoreSiteConfig } from '@classes/site'; -import { CoreCourse, CoreCourseWSModule, CoreCourseWSSection } from '@features/course/services/course'; +import { CoreCourse, CoreCourseWSSection } from '@features/course/services/course'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreSites } from '@services/sites'; import { CoreSiteHome } from '@features/sitehome/services/sitehome'; import { CoreCourses, CoreCoursesProvider } from '@features//courses/services/courses'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { CoreCourseHelper, CoreCourseModule } from '@features/course/services/course-helper'; -import { CoreCourseModuleDelegate, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; +import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; +import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate'; import { CoreNavigator } from '@services/navigator'; import { CoreBlockHelper } from '@features/block/services/block-helper'; @@ -52,7 +52,7 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy { searchEnabled = false; displayEnableDownload = false; downloadEnabled = false; - newsForumModule?: NewsForum; + newsForumModule?: CoreCourseModuleData; protected updateSiteObserver: CoreEventObserver; protected downloadEnabledObserver: CoreEventObserver; @@ -79,7 +79,7 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy { this.currentSite = CoreSites.getRequiredCurrentSite(); this.siteHomeId = CoreSites.getCurrentSiteHomeId(); - const module = CoreNavigator.getRouteParam('module'); + const module = CoreNavigator.getRouteParam('module'); if (module) { const modParams = CoreNavigator.getRouteParam('modParams'); CoreCourseHelper.openModule(module, this.siteHomeId, undefined, modParams); @@ -235,7 +235,3 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy { } } - -type NewsForum = CoreCourseWSModule & { - handlerData?: CoreCourseModuleHandlerData; -}; diff --git a/src/core/features/siteplugins/classes/call-ws-click-directive.ts b/src/core/features/siteplugins/classes/call-ws-click-directive.ts index 4e822ba1c..94c8b28f6 100644 --- a/src/core/features/siteplugins/classes/call-ws-click-directive.ts +++ b/src/core/features/siteplugins/classes/call-ws-click-directive.ts @@ -48,7 +48,7 @@ export class CoreSitePluginsCallWSOnClickBaseDirective extends CoreSitePluginsCa ev.preventDefault(); ev.stopPropagation(); - if (typeof this.confirmMessage != 'undefined') { + if (this.confirmMessage !== undefined) { // Ask for confirm. try { await CoreDomUtils.showConfirm(this.confirmMessage || Translate.instant('core.areyousure')); @@ -71,7 +71,7 @@ export class CoreSitePluginsCallWSOnClickBaseDirective extends CoreSitePluginsCa try { await super.callWS(); } catch (error) { - if (typeof this.showError == 'undefined' || CoreUtils.isTrueOrOne(this.showError)) { + if (this.showError === undefined || CoreUtils.isTrueOrOne(this.showError)) { CoreDomUtils.showErrorModalDefault(error, 'core.serverconnection', true); } } finally { diff --git a/src/core/features/siteplugins/classes/handlers/module-handler.ts b/src/core/features/siteplugins/classes/handlers/module-handler.ts index 847d2894b..846fd28f9 100644 --- a/src/core/features/siteplugins/classes/handlers/module-handler.ts +++ b/src/core/features/siteplugins/classes/handlers/module-handler.ts @@ -15,8 +15,8 @@ import { Type } from '@angular/core'; import { CoreConstants } from '@/core/constants'; -import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourse } from '@features/course/services/course'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { CoreSitePluginsModuleIndexComponent } from '@features/siteplugins/components/module-index/module-index'; import { @@ -64,12 +64,12 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp * @inheritdoc */ getData( - module: CoreCourseAnyModuleData, + module: CoreCourseModuleData, courseId: number, sectionId?: number, forCoursePage?: boolean, ): CoreCourseModuleHandlerData { - if ('description' in module && this.shouldOnlyDisplayDescription(module, forCoursePage)) { + if (this.shouldOnlyDisplayDescription(module, forCoursePage)) { const title = module.description; module.description = ''; @@ -87,14 +87,14 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp title: module.name, icon: this.getIconSrc(), class: this.handlerSchema.displaydata?.class, - showDownloadButton: typeof showDowloadButton != 'undefined' ? showDowloadButton : hasOffline, + showDownloadButton: showDowloadButton !== undefined ? showDowloadButton : hasOffline, }; if (this.handlerSchema.method) { // There is a method, add an action. handlerData.action = async ( event: Event, - module: CoreCourseModule, + module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions, ) => { @@ -128,7 +128,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp * @param forCoursePage Whether the data will be used to render the course page. * @return Bool. */ - protected shouldOnlyDisplayDescription(module: CoreCourseAnyModuleData, forCoursePage?: boolean): boolean { + protected shouldOnlyDisplayDescription(module: CoreCourseModuleData, forCoursePage?: boolean): boolean { if (forCoursePage && this.handlerSchema.coursepagemethod) { // The plugin defines a method for course page, don't display just the description. return false; @@ -167,7 +167,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp * @return Promise resolved when done. */ protected async loadCoursePageTemplate( - module: CoreCourseAnyModuleData, + module: CoreCourseModuleData, courseId: number, handlerData: CoreCourseModuleHandlerData, method: string, @@ -190,7 +190,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp // Use the html returned. handlerData.title = result.templates[0]?.html ?? ''; - ( module).description = ''; + ( module).description = ''; } catch (error) { this.logger.error('Error calling course page method:', error); } finally { @@ -215,7 +215,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp /** * @inheritdoc */ - async manualCompletionAlwaysShown(module: CoreCourseModule): Promise { + async manualCompletionAlwaysShown(module: CoreCourseModuleData): Promise { if (this.handlerSchema.manualcompletionalwaysshown !== undefined) { return this.handlerSchema.manualcompletionalwaysshown; } @@ -231,7 +231,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp /** * @inheritdoc */ - async openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise { + async openActivityPage(module: CoreCourseModuleData, courseId: number, options?: CoreNavigationOptions): Promise { if (!CoreCourse.moduleHasView(module)) { return; } diff --git a/src/core/features/siteplugins/components/module-index/module-index.ts b/src/core/features/siteplugins/components/module-index/module-index.ts index 499458d36..a4cab3943 100644 --- a/src/core/features/siteplugins/components/module-index/module-index.ts +++ b/src/core/features/siteplugins/components/module-index/module-index.ts @@ -16,7 +16,7 @@ import { CoreConstants } from '@/core/constants'; import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core'; import { CoreSiteWSPreSets } from '@classes/site'; -import { CoreCourseHelper, CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseModuleDelegate, CoreCourseModuleMainComponent, @@ -44,7 +44,7 @@ import { CoreSitePluginsPluginContentComponent } from '../plugin-content/plugin- }) export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, CoreCourseModuleMainComponent { - @Input() module!: CoreCourseModule; // The module. + @Input() module!: CoreCourseModuleData; // The module. @Input() courseId!: number; // Course ID the module belongs to. @Input() pageTitle?: string; // Current page title. It can be used by the "new-content" directives. @@ -145,7 +145,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C this.refreshIcon = CoreConstants.ICON_REFRESH; // Check if there is a prefetch handler for this type of module. - if (CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(this.module)) { + if (CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(this.module.name)) { CoreCourseHelper.fillContextMenu(this, this.module, this.courseId, refresh, this.component); } } diff --git a/src/core/features/siteplugins/directives/call-ws.ts b/src/core/features/siteplugins/directives/call-ws.ts index e2b2226a4..6c232973e 100644 --- a/src/core/features/siteplugins/directives/call-ws.ts +++ b/src/core/features/siteplugins/directives/call-ws.ts @@ -72,7 +72,7 @@ export class CoreSitePluginsCallWSDirective extends CoreSitePluginsCallWSOnClick this.parentContent.refreshContent(true); } - if (typeof this.successMessage != 'undefined') { + if (this.successMessage !== undefined) { // Display the success message. CoreDomUtils.showToast(this.successMessage || Translate.instant('core.success')); } diff --git a/src/core/features/siteplugins/pages/module-index/module-index.ts b/src/core/features/siteplugins/pages/module-index/module-index.ts index 5a8c07f4d..653d88a1e 100644 --- a/src/core/features/siteplugins/pages/module-index/module-index.ts +++ b/src/core/features/siteplugins/pages/module-index/module-index.ts @@ -15,7 +15,7 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { IonRefresher } from '@ionic/angular'; -import { CoreCourseModule } from '@features/course/services/course-helper'; +import { CoreCourseModuleData } from '@features/course/services/course-helper'; import { CanLeave } from '@guards/can-leave'; import { CoreNavigator } from '@services/navigator'; import { CoreSitePluginsModuleIndexComponent } from '../../components/module-index/module-index'; @@ -32,7 +32,7 @@ export class CoreSitePluginsModuleIndexPage implements OnInit, CanLeave { @ViewChild(CoreSitePluginsModuleIndexComponent) content?: CoreSitePluginsModuleIndexComponent; title?: string; // Page title. - module?: CoreCourseModule; + module?: CoreCourseModuleData; courseId?: number; /** diff --git a/src/core/features/siteplugins/services/siteplugins.ts b/src/core/features/siteplugins/services/siteplugins.ts index c03ffbe91..70e85ea13 100644 --- a/src/core/features/siteplugins/services/siteplugins.ts +++ b/src/core/features/siteplugins/services/siteplugins.ts @@ -403,7 +403,7 @@ export class CoreSitePluginsProvider { return false; } - if (restrictEnrolled || typeof restrictEnrolled == 'undefined') { + if (restrictEnrolled || restrictEnrolled === undefined) { // Only enabled for courses the user is enrolled to. Check if the user is enrolled in the course. try { await CoreCourses.getUserCourse(courseId, true); @@ -485,7 +485,7 @@ export class CoreSitePluginsProvider { otherData = otherData || {}; - if (typeof useOtherData == 'undefined') { + if (useOtherData === undefined) { // No need to add other data, return args as they are. return args; } else if (Array.isArray(useOtherData)) { @@ -560,12 +560,12 @@ export class CoreSitePluginsProvider { for (const i in paramsList) { const paramName = paramsList[i]; - if (typeof args[paramName] != 'undefined') { + if (args[paramName] !== undefined) { params[paramName] = args[paramName]; } else { // The param is not one of the default ones. Try to calculate the param to use. const value = this.getDownloadParam(component, paramName, courseId, module); - if (typeof value != 'undefined') { + if (value !== undefined) { params[paramName] = value; } } diff --git a/src/core/features/user/services/handlers/course-option.ts b/src/core/features/user/services/handlers/course-option.ts index 8d0484c9e..37de80356 100644 --- a/src/core/features/user/services/handlers/course-option.ts +++ b/src/core/features/user/services/handlers/course-option.ts @@ -42,7 +42,7 @@ export class CoreUserCourseOptionHandlerService implements CoreCourseOptionsHand * @return Promise resolved when done. */ invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise { - if (navOptions && typeof navOptions.participants != 'undefined') { + if (navOptions && navOptions.participants !== undefined) { // No need to invalidate anything. return Promise.resolve(); } @@ -76,7 +76,7 @@ export class CoreUserCourseOptionHandlerService implements CoreCourseOptionsHand return false; // Not enabled for guests. } - if (navOptions && typeof navOptions.participants != 'undefined') { + if (navOptions && navOptions.participants !== undefined) { return navOptions.participants; } diff --git a/src/core/features/user/services/user-delegate.ts b/src/core/features/user/services/user-delegate.ts index df503bc7d..6adebcf06 100644 --- a/src/core/features/user/services/user-delegate.ts +++ b/src/core/features/user/services/user-delegate.ts @@ -367,14 +367,14 @@ export class CoreUserDelegateService extends CoreDelegate { const site = await CoreSites.getSite(siteId); - if (typeof onlineValue == 'undefined') { + if (onlineValue === undefined) { const preference = await this.getPreference(name, site.id); onlineValue = preference.onlinevalue; diff --git a/src/core/features/user/services/user-profile-field-delegate.ts b/src/core/features/user/services/user-profile-field-delegate.ts index 93f893b5b..0432a8ea0 100644 --- a/src/core/features/user/services/user-profile-field-delegate.ts +++ b/src/core/features/user/services/user-profile-field-delegate.ts @@ -140,7 +140,7 @@ export class CoreUserProfileFieldDelegateService extends CoreDelegate { const name = (fileName.match(/^(?:\.\/)?(.+)\.ts$/) || [])[1]; - if (typeof name !== 'undefined' && name !== 'index') { + if (name !== undefined && name !== 'index') { providers.push({ provide: APP_INITIALIZER, useValue: context(fileName).default, diff --git a/src/core/pipes/format-date.ts b/src/core/pipes/format-date.ts index 960ec19c0..2e49d275a 100644 --- a/src/core/pipes/format-date.ts +++ b/src/core/pipes/format-date.ts @@ -59,7 +59,7 @@ export class CoreFormatDatePipe implements PipeTransform { format = 'core.' + format; } - if (typeof convert == 'undefined') { + if (convert === undefined) { // Initialize convert param. Set it to false if it's a core.df format, set it to true otherwise. convert = format.indexOf('core.df') != 0; } diff --git a/src/core/services/config.ts b/src/core/services/config.ts index 37c65708e..70d6982ef 100644 --- a/src/core/services/config.ts +++ b/src/core/services/config.ts @@ -73,7 +73,7 @@ export class CoreConfigProvider { return entry.value; } catch (error) { - if (typeof defaultValue != 'undefined') { + if (defaultValue !== undefined) { return defaultValue; } diff --git a/src/core/services/cron.ts b/src/core/services/cron.ts index 76a043947..a5b82dfa3 100644 --- a/src/core/services/cron.ts +++ b/src/core/services/cron.ts @@ -337,7 +337,7 @@ export class CoreCronDelegateService { // Invalid handler. return; } - if (typeof this.handlers[handler.name] != 'undefined') { + if (this.handlers[handler.name] !== undefined) { this.logger.debug(`The cron handler '${handler.name}' is already registered.`); return; diff --git a/src/core/services/db.ts b/src/core/services/db.ts index 1d1b2efea..a715625c8 100644 --- a/src/core/services/db.ts +++ b/src/core/services/db.ts @@ -36,7 +36,7 @@ export class CoreDbProvider { * @return DB. */ getDB(name: string, forceNew?: boolean): SQLiteDB { - if (typeof this.dbInstances[name] === 'undefined' || forceNew) { + if (this.dbInstances[name] === undefined || forceNew) { if (Platform.is('cordova')) { this.dbInstances[name] = new SQLiteDB(name); } else { @@ -54,7 +54,7 @@ export class CoreDbProvider { * @return Promise resolved when the DB is deleted. */ async deleteDB(name: string): Promise { - if (typeof this.dbInstances[name] != 'undefined') { + if (this.dbInstances[name] !== undefined) { // Close the database first. await this.dbInstances[name].close(); diff --git a/src/core/services/file-helper.ts b/src/core/services/file-helper.ts index 17b5f0d21..136d1291e 100644 --- a/src/core/services/file-helper.ts +++ b/src/core/services/file-helper.ts @@ -449,7 +449,7 @@ export class CoreFileHelperProvider { getFilenameFromPath(file: CoreFileEntry): string | undefined { const path = CoreUtils.isFileEntry(file) ? file.fullPath : file.filepath; - if (typeof path == 'undefined' || path.length == 0) { + if (path === undefined || path.length == 0) { return; } diff --git a/src/core/services/file.ts b/src/core/services/file.ts index 2316855b8..698cdac02 100644 --- a/src/core/services/file.ts +++ b/src/core/services/file.ts @@ -157,7 +157,7 @@ export class CoreFileProvider { * @return Whether the plugin is available. */ isAvailable(): boolean { - return typeof window.resolveLocalFileSystemURL !== 'undefined'; + return window.resolveLocalFileSystemURL !== undefined; } /** @@ -982,7 +982,7 @@ export class CoreFileProvider { async replaceInFile(path: string, search: string | RegExp, newValue: string): Promise { let content = await this.readFile(path); - if (typeof content == 'undefined' || content === null || !content.replace) { + if (content === undefined || content === null || !content.replace) { throw new CoreError(`Error reading file ${path}`); } @@ -1139,7 +1139,7 @@ export class CoreFileProvider { * @return Unique name. */ calculateUniqueName(usedNames: Record, name: string): string { - if (typeof usedNames[name.toLowerCase()] == 'undefined') { + if (usedNames[name.toLowerCase()] === undefined) { // No file with the same name. return name; } @@ -1153,7 +1153,7 @@ export class CoreFileProvider { do { name = nameWithoutExtension + '(' + num + ')' + extension; num++; - } while (typeof usedNames[name.toLowerCase()] != 'undefined'); + } while (usedNames[name.toLowerCase()] !== undefined); return name; } diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index 98efbef5f..d0c00aece 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -466,7 +466,7 @@ export class CoreFilepoolProvider { let size: number; - if (typeof this.sizeCache[fileUrl] != 'undefined') { + if (this.sizeCache[fileUrl] !== undefined) { size = this.sizeCache[fileUrl]; } else { if (!CoreApp.isOnline()) { @@ -594,7 +594,7 @@ export class CoreFilepoolProvider { * @return Link, null if nothing to link. */ protected createComponentLink(component?: string, componentId?: string | number): CoreFilepoolComponentLink | undefined { - if (typeof component != 'undefined' && component != null) { + if (component !== undefined && component != null) { return { component, componentId: this.fixComponentId(componentId) }; } } @@ -681,7 +681,7 @@ export class CoreFilepoolProvider { } const extension = CoreMimetypeUtils.guessExtensionFromUrl(fileUrl); - const addExtension = typeof filePath == 'undefined'; + const addExtension = filePath === undefined; const path = filePath || (await this.getFilePath(siteId, fileId, extension)); if (poolFileObject && poolFileObject.fileId !== fileId) { @@ -994,7 +994,7 @@ export class CoreFilepoolProvider { const links = this.createComponentLinks(component, componentId); const finishSuccessfulDownload = (url: string): string => { - if (typeof component != 'undefined') { + if (component !== undefined) { CoreUtils.ignoreErrors(this.addFileLink(siteId, fileId, component, componentId)); } @@ -1104,7 +1104,7 @@ export class CoreFilepoolProvider { * @return Promise resolved when done. */ protected async fillExtensionInFile(entry: CoreFilepoolFileEntry, siteId: string): Promise { - if (typeof entry.extension != 'undefined') { + if (entry.extension !== undefined) { // Already filled. return; } @@ -1149,7 +1149,7 @@ export class CoreFilepoolProvider { return componentId; } - if (typeof componentId == 'undefined' || componentId === null) { + if (componentId === undefined || componentId === null) { return -1; } @@ -1335,7 +1335,7 @@ export class CoreFilepoolProvider { protected async getFilePath(siteId: string, fileId: string, extension?: string): Promise { let path = this.getFilepoolFolderPath(siteId) + '/' + fileId; - if (typeof extension == 'undefined') { + if (extension === undefined) { // We need the extension to be able to open files properly. try { const entry = await this.hasFileInPool(siteId, fileId); @@ -1555,7 +1555,7 @@ export class CoreFilepoolProvider { try { const entry = await this.hasFileInPool(siteId, fileId); - if (typeof entry === 'undefined') { + if (entry === undefined) { throw new CoreError('File not downloaded.'); } @@ -1949,7 +1949,7 @@ export class CoreFilepoolProvider { } const matches = url.match(revisionRegex); - if (matches && typeof matches[1] != 'undefined') { + if (matches && matches[1] !== undefined) { return parseInt(matches[1], 10); } @@ -2131,7 +2131,7 @@ export class CoreFilepoolProvider { const db = await CoreSites.getSiteDb(siteId); const entry = await db.getRecord(FILES_TABLE_NAME, { fileId }); - if (typeof entry === 'undefined') { + if (entry === undefined) { throw new CoreError('File not found in filepool.'); } @@ -2149,7 +2149,7 @@ export class CoreFilepoolProvider { const db = await this.appDB; const entry = await db.getRecord(QUEUE_TABLE_NAME, { siteId, fileId }); - if (typeof entry === 'undefined') { + if (entry === undefined) { throw new CoreError('File not found in queue.'); } // Convert the links to an object. @@ -2872,7 +2872,7 @@ export class CoreFilepoolProvider { const entry = await site.getDb().getRecord(PACKAGES_TABLE_NAME, { id: packageId }); extra = extra ?? entry.extra; - if (typeof downloadTime == 'undefined') { + if (downloadTime === undefined) { // Keep previous download time. downloadTime = entry.downloadTime; previousDownloadTime = entry.previousDownloadTime; diff --git a/src/core/services/groups.ts b/src/core/services/groups.ts index b0d63b803..39320f09a 100644 --- a/src/core/services/groups.ts +++ b/src/core/services/groups.ts @@ -214,7 +214,7 @@ export class CoreGroupsProvider { const response: CoreGroupGetActivityGroupModeWSResponse = await site.read('core_group_get_activity_groupmode', params, preSets); - if (!response || typeof response.groupmode == 'undefined') { + if (!response || response.groupmode === undefined) { throw new CoreError('Activity group mode not found.'); } diff --git a/src/core/services/lang.ts b/src/core/services/lang.ts index f0430b64f..e8c09518c 100644 --- a/src/core/services/lang.ts +++ b/src/core/services/lang.ts @@ -223,7 +223,7 @@ export class CoreLangProvider { * @return Promise resolved with the current language. */ async getCurrentLanguage(): Promise { - if (typeof this.currentLanguage != 'undefined') { + if (this.currentLanguage !== undefined) { return this.currentLanguage; } @@ -254,13 +254,13 @@ export class CoreLangProvider { let preferredLanguage = navigator.language.toLowerCase(); if (preferredLanguage.indexOf('-') > -1) { // Language code defined by locale has a dash, like en-US or es-ES. Check if it's supported. - if (CoreConstants.CONFIG.languages && typeof CoreConstants.CONFIG.languages[preferredLanguage] == 'undefined') { + if (CoreConstants.CONFIG.languages && CoreConstants.CONFIG.languages[preferredLanguage] === undefined) { // Code is NOT supported. Fallback to language without dash. E.g. 'en-US' would fallback to 'en'. preferredLanguage = preferredLanguage.substr(0, preferredLanguage.indexOf('-')); } } - if (typeof CoreConstants.CONFIG.languages[preferredLanguage] == 'undefined') { + if (CoreConstants.CONFIG.languages[preferredLanguage] === undefined) { // Language not supported, use default language. return this.defaultLanguage; } @@ -349,7 +349,7 @@ export class CoreLangProvider { loadCustomStringsFromSite(currentSite: CoreSite): void { const customStrings = currentSite.getStoredConfig('tool_mobile_customlangstrings'); - if (typeof customStrings != 'undefined') { + if (customStrings !== undefined) { this.loadCustomStrings(customStrings); } } diff --git a/src/core/services/local-notifications.ts b/src/core/services/local-notifications.ts index 9b69435e0..f486e79e9 100644 --- a/src/core/services/local-notifications.ts +++ b/src/core/services/local-notifications.ts @@ -227,7 +227,7 @@ export class CoreLocalNotificationsProvider { const key = table + '#' + id; // Check if the code is already in memory. - if (typeof this.codes[key] != 'undefined') { + if (this.codes[key] !== undefined) { return this.codes[key]; } @@ -413,7 +413,7 @@ export class CoreLocalNotificationsProvider { protected async processNextRequest(): Promise { const nextKey = Object.keys(this.codeRequestsQueue)[0]; - if (typeof nextKey == 'undefined') { + if (nextKey === undefined) { // No more requests in queue, stop. return; } @@ -469,11 +469,11 @@ export class CoreLocalNotificationsProvider { ): CoreEventObserver { this.logger.debug(`Register observer '${component}' for event '${eventName}'.`); - if (typeof this.observables[eventName] == 'undefined') { + if (this.observables[eventName] === undefined) { this.observables[eventName] = {}; } - if (typeof this.observables[eventName][component] == 'undefined') { + if (this.observables[eventName][component] === undefined) { // No observable for this component, create a new one. this.observables[eventName][component] = new Subject(); } @@ -511,7 +511,7 @@ export class CoreLocalNotificationsProvider { const key = table + '#' + id; const isQueueEmpty = Object.keys(this.codeRequestsQueue).length == 0; - if (typeof this.codeRequestsQueue[key] != 'undefined') { + if (this.codeRequestsQueue[key] !== undefined) { // There's already a pending request for this store and ID, add the promise to it. this.codeRequestsQueue[key].deferreds.push(deferred); } else { diff --git a/src/core/services/plugin-file-delegate.ts b/src/core/services/plugin-file-delegate.ts index 9c566fec0..ef78e78ae 100644 --- a/src/core/services/plugin-file-delegate.ts +++ b/src/core/services/plugin-file-delegate.ts @@ -167,7 +167,7 @@ export class CorePluginFileDelegateService extends CoreDelegate { const size = await this.getFileSize(file, siteId); - if (typeof size == 'undefined') { + if (size === undefined) { // We don't have the file size, cannot calculate its total size. result.total = false; } else { diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index 116f125dd..f90b14ace 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -121,7 +121,7 @@ export class CoreSitesProvider { const demoSites = CoreConstants.CONFIG.demo_sites; name = name.toLowerCase(); - if (typeof demoSites != 'undefined' && typeof demoSites[name] != 'undefined') { + if (demoSites !== undefined && demoSites[name] !== undefined) { return demoSites[name]; } } @@ -364,13 +364,13 @@ export class CoreSitesProvider { throw new CoreError(Translate.instant('core.cannotconnecttrouble')); } - if (typeof data == 'undefined') { + if (data === undefined) { throw new CoreError(Translate.instant('core.cannotconnecttrouble')); } else { - if (typeof data.token != 'undefined') { + if (data.token !== undefined) { return { token: data.token, siteUrl, privateToken: data.privatetoken }; } else { - if (typeof data.error != 'undefined') { + if (data.error !== undefined) { // We only allow one retry (to avoid loops). if (!retry && data.errorcode == 'requirecorrectaccess') { siteUrl = CoreUrlUtils.addOrRemoveWWW(siteUrl); @@ -468,7 +468,7 @@ export class CoreSitesProvider { } } - if (typeof config != 'undefined') { + if (config !== undefined) { candidateSite.setConfig(config); } @@ -891,7 +891,7 @@ export class CoreSitesProvider { * @return Whether the user is logged in a site. */ isLoggedIn(): boolean { - return typeof this.currentSite != 'undefined' && typeof this.currentSite.token != 'undefined' && + return this.currentSite !== undefined && this.currentSite.token !== undefined && this.currentSite.token != ''; } @@ -904,7 +904,7 @@ export class CoreSitesProvider { async deleteSite(siteId: string): Promise { this.logger.debug(`Delete site ${siteId}`); - if (typeof this.currentSite != 'undefined' && this.currentSite.id == siteId) { + if (this.currentSite !== undefined && this.currentSite.id == siteId) { this.logout(); } @@ -956,7 +956,7 @@ export class CoreSitesProvider { throw new CoreError('No current site found.'); } else if (this.currentSite && this.currentSite.getId() == siteId) { return this.currentSite; - } else if (typeof this.sites[siteId] != 'undefined') { + } else if (this.sites[siteId] !== undefined) { return this.sites[siteId]; } else { // Retrieve and create the site. @@ -981,7 +981,7 @@ export class CoreSitesProvider { const db = await this.appDB; const data = await db.getRecord(SITES_TABLE_NAME, { siteUrl }); - if (typeof this.sites[data.id] != 'undefined') { + if (this.sites[data.id] !== undefined) { return this.sites[data.id]; } @@ -1326,7 +1326,7 @@ export class CoreSitesProvider { loggedOut: site.isLoggedOut() ? 1 : 0, }; - if (typeof config != 'undefined') { + if (config !== undefined) { site.setConfig(config); newValues.config = JSON.stringify(config); } diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index 9b22c544e..945871287 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -200,8 +200,8 @@ export class CoreDomUtilsProvider { const availableSpace = getAvailableSpace(availableBytes); - wifiThreshold = typeof wifiThreshold == 'undefined' ? CoreConstants.WIFI_DOWNLOAD_THRESHOLD : wifiThreshold; - limitedThreshold = typeof limitedThreshold == 'undefined' ? CoreConstants.DOWNLOAD_THRESHOLD : limitedThreshold; + wifiThreshold = wifiThreshold === undefined ? CoreConstants.WIFI_DOWNLOAD_THRESHOLD : wifiThreshold; + limitedThreshold = limitedThreshold === undefined ? CoreConstants.DOWNLOAD_THRESHOLD : limitedThreshold; let wifiPrefix = ''; if (CoreApp.isNetworkAccessLimited()) { @@ -948,7 +948,7 @@ export class CoreDomUtilsProvider { paths[CoreUrlUtils.removeUrlParams(CoreTextUtils.decodeURIComponent(currentSrc))] : undefined; - if (typeof newSrc != 'undefined') { + if (newSrc !== undefined) { media.setAttribute('src', newSrc); } @@ -956,7 +956,7 @@ export class CoreDomUtilsProvider { if (media.tagName == 'VIDEO' && media.getAttribute('poster')) { const currentPoster = media.getAttribute('poster'); const newPoster = paths[CoreTextUtils.decodeURIComponent(currentPoster!)]; - if (typeof newPoster !== 'undefined') { + if (newPoster !== undefined) { media.setAttribute('poster', newPoster); } } @@ -970,7 +970,7 @@ export class CoreDomUtilsProvider { paths[CoreUrlUtils.removeUrlParams(CoreTextUtils.decodeURIComponent(currentHref))] : undefined; - if (typeof newHref != 'undefined') { + if (newHref !== undefined) { anchor.setAttribute('href', newHref); if (typeof anchorFn == 'function') { @@ -1226,7 +1226,7 @@ export class CoreDomUtilsProvider { if (options.buttons) { // Execute dismiss function if any. const cancelButton = options.buttons.find( - (button) => typeof button != 'string' && typeof button.handler != 'undefined' && button.role == 'cancel', + (button) => typeof button != 'string' && button.handler !== undefined && button.role == 'cancel', ); cancelButton.handler?.(null); } diff --git a/src/core/services/utils/mimetype.ts b/src/core/services/utils/mimetype.ts index ddf65901d..98ab537a6 100644 --- a/src/core/services/utils/mimetype.ts +++ b/src/core/services/utils/mimetype.ts @@ -325,7 +325,7 @@ export class CoreMimetypeUtilsProvider { } // Check extension corresponds to a mimetype to know if it's valid. - if (extension && typeof this.getMimeType(extension) == 'undefined') { + if (extension && this.getMimeType(extension) === undefined) { this.logger.warn('Guess file extension: Not valid extension ' + extension); return; @@ -350,7 +350,7 @@ export class CoreMimetypeUtilsProvider { ext = this.cleanExtension(ext); // Check extension corresponds to a mimetype to know if it's valid. - if (typeof this.getMimeType(ext) == 'undefined') { + if (this.getMimeType(ext) === undefined) { this.logger.warn('Get file extension: Not valid extension ' + ext); return; @@ -370,7 +370,7 @@ export class CoreMimetypeUtilsProvider { getGroupMimeInfo(group: string): MimeTypeGroupInfo; getGroupMimeInfo(group: string, field: string): string[] | undefined; getGroupMimeInfo(group: string, field?: string): MimeTypeGroupInfo | string[] | undefined { - if (typeof this.groupsMimeInfo[group] == 'undefined') { + if (this.groupsMimeInfo[group] === undefined) { this.fillGroupMimeInfo(group); } @@ -590,7 +590,7 @@ export class CoreMimetypeUtilsProvider { if (position > -1) { // Check extension corresponds to a mimetype to know if it's valid. extension = path.substr(position + 1).toLowerCase(); - if (typeof this.getMimeType(extension) != 'undefined') { + if (this.getMimeType(extension) !== undefined) { return path.substr(0, position); // Remove extension. } } diff --git a/src/core/services/utils/text.ts b/src/core/services/utils/text.ts index 362298e18..c37c3f8a9 100644 --- a/src/core/services/utils/text.ts +++ b/src/core/services/utils/text.ts @@ -215,7 +215,7 @@ export class CoreTextUtilsProvider { * @return Size in human readable format. */ bytesToSize(bytes: number, precision: number = 2): string { - if (typeof bytes == 'undefined' || bytes === null || bytes < 0) { + if (bytes === undefined || bytes === null || bytes < 0) { return Translate.instant('core.notapplicable'); } @@ -347,7 +347,7 @@ export class CoreTextUtilsProvider { * @return Decoded text. */ decodeHTML(text: string | number): string { - if (typeof text == 'undefined' || text === null || (typeof text == 'number' && isNaN(text))) { + if (text === undefined || text === null || (typeof text == 'number' && isNaN(text))) { return ''; } else if (typeof text != 'string') { return '' + text; @@ -430,7 +430,7 @@ export class CoreTextUtilsProvider { * @return Escaped text. */ escapeHTML(text?: string | number | null, doubleEncode: boolean = true): string { - if (typeof text == 'undefined' || text === null || (typeof text == 'number' && isNaN(text))) { + if (text === undefined || text === null || (typeof text == 'number' && isNaN(text))) { return ''; } else if (typeof text != 'string') { return '' + text; @@ -673,7 +673,7 @@ export class CoreTextUtilsProvider { } // Error parsing, return the default value or the original value. - if (typeof defaultValue != 'undefined') { + if (defaultValue !== undefined) { return defaultValue; } diff --git a/src/core/services/utils/time.ts b/src/core/services/utils/time.ts index 684c741b0..60457d388 100644 --- a/src/core/services/utils/time.ts +++ b/src/core/services/utils/time.ts @@ -97,7 +97,7 @@ export class CoreTimeUtilsProvider { converted += ']'; } - converted += typeof CoreTimeUtilsProvider.FORMAT_REPLACEMENTS[char] != 'undefined' ? + converted += CoreTimeUtilsProvider.FORMAT_REPLACEMENTS[char] !== undefined ? CoreTimeUtilsProvider.FORMAT_REPLACEMENTS[char] : char; } else { // Not a PHP format. We need to escape them, otherwise the letters could be confused with Moment formats. @@ -338,7 +338,7 @@ export class CoreTimeUtilsProvider { convertToTimestamp(date: string, applyOffset?: boolean): number { const timestamp = moment(date).unix(); - if (typeof applyOffset !== 'undefined') { + if (applyOffset !== undefined) { return applyOffset ? timestamp - moment().utcOffset() * 60 : timestamp; } diff --git a/src/core/services/utils/url.ts b/src/core/services/utils/url.ts index 1fbf79211..15ed16dfc 100644 --- a/src/core/services/utils/url.ts +++ b/src/core/services/utils/url.ts @@ -146,7 +146,7 @@ export class CoreUrlUtilsProvider { } urlAndHash[0].replace(regex, (match: string, key: string, value: string): string => { - params[key] = typeof value != 'undefined' ? CoreTextUtils.decodeURIComponent(value) : ''; + params[key] = value !== undefined ? CoreTextUtils.decodeURIComponent(value) : ''; if (subParams) { params[key] = params[key].replace(subParamsPlaceholder, subParams); @@ -246,7 +246,7 @@ export class CoreUrlUtilsProvider { async getDocsUrl(release?: string, page: string = 'Mobile_app'): Promise { let docsUrl = 'https://docs.moodle.org/en/' + page; - if (typeof release != 'undefined') { + if (release !== undefined) { const version = CoreSites.getMajorReleaseNumber(release).replace('.', ''); // Check is a valid number. diff --git a/src/core/services/utils/utils.ts b/src/core/services/utils/utils.ts index 1ffe37ddf..e66e673fd 100644 --- a/src/core/services/utils/utils.ts +++ b/src/core/services/utils/utils.ts @@ -150,7 +150,7 @@ export class CoreUtilsProvider { ): Record { for (const entry of array) { const key = propertyName ? entry[propertyName] : entry; - if (typeof result[key] == 'undefined') { + if (result[key] === undefined) { result[key] = []; } @@ -202,7 +202,7 @@ export class CoreUtilsProvider { return equal; } else { if (undefinedIsNull && ( - (typeof itemA == 'undefined' && itemB === null) || (itemA === null && typeof itemB == 'undefined'))) { + (itemA === undefined && itemB === null) || (itemA === null && itemB === undefined))) { return true; } @@ -524,7 +524,7 @@ export class CoreUtilsProvider { * @return Locale float. */ formatFloat(float: unknown): string { - if (typeof float == 'undefined' || float === null || typeof float == 'boolean') { + if (float === undefined || float === null || typeof float == 'boolean') { return ''; } @@ -836,7 +836,7 @@ export class CoreUtilsProvider { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any isFalseOrZero(value: any): boolean { - return typeof value != 'undefined' && (value === false || value === 'false' || parseInt(value, 10) === 0); + return value !== undefined && (value === false || value === 'false' || parseInt(value, 10) === 0); } /** @@ -847,7 +847,7 @@ export class CoreUtilsProvider { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any isTrueOrOne(value: any): boolean { - return typeof value != 'undefined' && (value === true || value === 'true' || parseInt(value, 10) === 1); + return value !== undefined && (value === true || value === 'true' || parseInt(value, 10) === 1); } /** @@ -858,7 +858,7 @@ export class CoreUtilsProvider { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any isWebServiceError(error: any): boolean { - return error && (typeof error.warningcode != 'undefined' || (typeof error.errorcode != 'undefined' && + return error && (error.warningcode !== undefined || (error.errorcode !== undefined && error.errorcode != 'userdeleted' && error.errorcode != 'upgraderunning' && error.errorcode != 'forcepasswordchangenotice' && error.errorcode != 'usernotfullysetup' && error.errorcode != 'sitepolicynotagreed' && error.errorcode != 'sitemaintenance' && @@ -929,7 +929,7 @@ export class CoreUtilsProvider { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any notNullOrUndefined(value: any): boolean { - return typeof value != 'undefined' && value !== null; + return value !== undefined && value !== null; } /** @@ -1183,7 +1183,7 @@ export class CoreUtilsProvider { ): A[] { // Get the entries from an object or primitive value. const getEntries = (elKey: string, value: unknown): Record[] | unknown => { - if (typeof value == 'undefined' || value == null) { + if (value === undefined || value == null) { // Filter undefined and null values. return; } else if (this.isObject(value)) { @@ -1277,7 +1277,7 @@ export class CoreUtilsProvider { for (const name in flattened) { let value = flattened[name]; - if (removeEmpty && (value === null || typeof value == 'undefined')) { + if (removeEmpty && (value === null || value === undefined)) { continue; } @@ -1379,8 +1379,8 @@ export class CoreUtilsProvider { obj2: Record | unknown[], key: string, ): boolean { - let value1 = typeof obj1[key] != 'undefined' ? obj1[key] : ''; - let value2 = typeof obj2[key] != 'undefined' ? obj2[key] : ''; + let value1 = obj1[key] !== undefined ? obj1[key] : ''; + let value2 = obj2[key] !== undefined ? obj2[key] : ''; if (typeof value1 == 'number' || typeof value1 == 'boolean') { value1 = '' + value1; @@ -1484,7 +1484,7 @@ export class CoreUtilsProvider { // eslint-disable-next-line @typescript-eslint/no-explicit-any unformatFloat(localeFloat: any, strict?: boolean): false | '' | number { // Bad format on input type number. - if (typeof localeFloat == 'undefined') { + if (localeFloat === undefined) { return false; } @@ -1656,7 +1656,7 @@ export class CoreUtilsProvider { if (error) { this.qrScanData.deferred.reject(data); - } else if (typeof data != 'undefined') { + } else if (data !== undefined) { this.qrScanData.deferred.resolve(data as string); } else { this.qrScanData.deferred.reject(new CoreCanceledError()); diff --git a/src/core/services/ws.ts b/src/core/services/ws.ts index ff2d7e869..d1ab15a5e 100644 --- a/src/core/services/ws.ts +++ b/src/core/services/ws.ts @@ -100,7 +100,7 @@ export class CoreWSProvider { } preSets.typeExpected = preSets.typeExpected || 'object'; - if (typeof preSets.responseExpected == 'undefined') { + if (preSets.responseExpected === undefined) { preSets.responseExpected = true; } @@ -323,7 +323,7 @@ export class CoreWSProvider { */ protected getPromiseHttp(method: string, url: string, params?: Record): Promise | undefined { const queueItemId = this.getQueueItemId(method, url, params); - if (typeof this.ongoingCalls[queueItemId] != 'undefined') { + if (this.ongoingCalls[queueItemId] !== undefined) { return this.ongoingCalls[queueItemId]; } } @@ -414,13 +414,13 @@ export class CoreWSProvider { // eslint-disable-next-line @typescript-eslint/no-explicit-any let promise: Promise>; - if (typeof preSets.siteUrl == 'undefined') { + if (preSets.siteUrl === undefined) { throw new CoreAjaxError(Translate.instant('core.unexpectederror')); } else if (!CoreApp.isOnline()) { throw new CoreAjaxError(Translate.instant('core.networkerrormsg')); } - if (typeof preSets.responseExpected == 'undefined') { + if (preSets.responseExpected === undefined) { preSets.responseExpected = true; } @@ -655,7 +655,7 @@ export class CoreWSProvider { } } - if (typeof data.exception !== 'undefined') { + if (data.exception !== undefined) { // Special debugging for site plugins, otherwise it's hard to debug errors if the data is cached. if (method == 'tool_mobile_get_content') { this.logger.error('Error calling WS', method, data); @@ -664,7 +664,7 @@ export class CoreWSProvider { throw new CoreWSError(data); } - if (typeof data.debuginfo != 'undefined') { + if (data.debuginfo !== undefined) { throw new CoreError('Error. ' + data.message); } @@ -787,7 +787,7 @@ export class CoreWSProvider { } preSets.typeExpected = preSets.typeExpected || 'object'; - if (typeof preSets.responseExpected == 'undefined') { + if (preSets.responseExpected === undefined) { preSets.responseExpected = true; } @@ -838,7 +838,7 @@ export class CoreWSProvider { throw new CoreError(Translate.instant('core.errorinvalidresponse')); } - if (typeof data.exception != 'undefined' || typeof data.debuginfo != 'undefined') { + if (data.exception !== undefined || data.debuginfo !== undefined) { throw new CoreWSError(data); } @@ -907,14 +907,14 @@ export class CoreWSProvider { throw new CoreError(Translate.instant('core.errorinvalidresponse')); } - if (typeof data.exception !== 'undefined') { + if (data.exception !== undefined) { throw new CoreWSError(data); - } else if (typeof data.error !== 'undefined') { + } else if (data.error !== undefined) { throw new CoreWSError({ errorcode: data.errortype, message: data.error, }); - } else if (data[0] && typeof data[0].error !== 'undefined') { + } else if (data[0] && data[0].error !== undefined) { throw new CoreWSError({ errorcode: data[0].errortype, message: data[0].error, @@ -966,7 +966,7 @@ export class CoreWSProvider { async sendHTTPRequest(url: string, options: HttpRequestOptions): Promise> { // Set default values. options.responseType = options.responseType || 'json'; - options.timeout = typeof options.timeout == 'undefined' ? this.getRequestTimeout() : options.timeout; + options.timeout = options.timeout === undefined ? this.getRequestTimeout() : options.timeout; if (CoreApp.isMobile()) { // Use the cordova plugin. diff --git a/src/core/singletons/events.ts b/src/core/singletons/events.ts index a88ea0722..ecc3a9ad8 100644 --- a/src/core/singletons/events.ts +++ b/src/core/singletons/events.ts @@ -137,7 +137,7 @@ export class CoreEvents { this.logger.debug(`New observer listening to event '${eventName}'`); - if (typeof this.observables[eventName] == 'undefined') { + if (this.observables[eventName] === undefined) { // No observable for this event, create a new one. this.observables[eventName] = new Subject(); } diff --git a/upgrade.txt b/upgrade.txt index 4f36e38bc..75a4f115f 100644 --- a/upgrade.txt +++ b/upgrade.txt @@ -1,11 +1,13 @@ This files describes API changes in the Moodle Mobile app, information provided here is intended especially for developers. -=== 3.9.6 === +=== 4.0.0 === - The parameters of the functions confirmAndPrefetchCourse and confirmAndPrefetchCourses have changed, they now accept an object with options. - Component core-navigation-bar changed to add an slider inside. previous, previousTitle, next, nextTitle, info and title have been removed. Now you have to pass all items and 3 optional params have been added. +- CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor now admits module name instead of full module object. +- CoreCourse.getModuleBasicInfoByInstance and CoreCourse.getModuleBasicInfo have been modified to accept an "options" parameter instead of only siteId. === 3.9.5 ===