From cee98a94faf2e30e306566751079344ea888853f Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 21 Dec 2018 16:35:37 +0100 Subject: [PATCH] MOBILE-2803 course: Prefetch course options --- src/addon/competency/providers/competency.ts | 32 +++++++++++++++---- .../providers/course-option-handler.ts | 26 +++++++++++++++ .../providers/course-option-handler.ts | 13 ++++++++ .../notes/providers/course-option-handler.ts | 10 ++++++ .../grades/providers/course-option-handler.ts | 28 +++++++++++++++- .../user/providers/course-option-handler.ts | 26 +++++++++++++++ src/core/user/providers/user.ts | 13 ++++++-- 7 files changed, 138 insertions(+), 10 deletions(-) diff --git a/src/addon/competency/providers/competency.ts b/src/addon/competency/providers/competency.ts index efbaa2034..28fae6304 100644 --- a/src/addon/competency/providers/competency.ts +++ b/src/addon/competency/providers/competency.ts @@ -220,9 +220,12 @@ export class AddonCompetencyProvider { * @param {number} competencyId ID of the competency. * @param {number} [userId] ID of the user. If not defined, current user. * @param {string} [siteId] Site ID. If not defined, current site. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @return {Promise} Promise to be resolved when the plans are retrieved. */ - getCompetencyInCourse(courseId: number, competencyId: number, userId?: number, siteId?: string): Promise { + getCompetencyInCourse(courseId: number, competencyId: number, userId?: number, siteId?: string, ignoreCache?: boolean) + : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { userId = userId || site.getUserId(); @@ -233,10 +236,15 @@ export class AddonCompetencyProvider { competencyid: competencyId, userid: userId }, - preSets = { + preSets: any = { cacheKey: this.getCompetencyInCourseCacheKey(courseId, competencyId, userId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('tool_lp_data_for_user_competency_summary_in_course', params, preSets).then((response) => { if (response.usercompetencysummary) { return response; @@ -253,9 +261,10 @@ export class AddonCompetencyProvider { * @param {number} competencyId ID of the competency. * @param {number} [userId] ID of the user. If not defined, current user. * @param {string} [siteId] Site ID. If not defined, current site. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @return {Promise} Promise to be resolved when the plans are retrieved. */ - getCompetencySummary(competencyId: number, userId?: number, siteId?: string): Promise { + getCompetencySummary(competencyId: number, userId?: number, siteId?: string, ignoreCache?: boolean): Promise { return this.sitesProvider.getSite(siteId).then((site) => { userId = userId || site.getUserId(); @@ -265,10 +274,15 @@ export class AddonCompetencyProvider { competencyid: competencyId, userid: userId }, - preSets = { + preSets: any = { cacheKey: this.getCompetencySummaryCacheKey(competencyId, userId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('tool_lp_data_for_user_competency_summary', params, preSets).then((response) => { if (response.competency) { return response.competency; @@ -285,9 +299,10 @@ export class AddonCompetencyProvider { * @param {number} courseId ID of the course. * @param {number} [userId] ID of the user. * @param {string} [siteId] Site ID. If not defined, current site. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @return {Promise} Promise to be resolved when the course competencies are retrieved. */ - getCourseCompetencies(courseId: number, userId?: number, siteId?: string): Promise { + getCourseCompetencies(courseId: number, userId?: number, siteId?: string, ignoreCache?: boolean): Promise { return this.sitesProvider.getSite(siteId).then((site) => { this.logger.debug('Get course competencies for course ' + courseId); @@ -295,10 +310,15 @@ export class AddonCompetencyProvider { const params = { courseid: courseId }, - preSets = { + preSets: any = { cacheKey: this.getCourseCompetenciesCacheKey(courseId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('tool_lp_data_for_course_competencies_page', params, preSets).then((response) => { if (response.competencies) { return response; diff --git a/src/addon/competency/providers/course-option-handler.ts b/src/addon/competency/providers/course-option-handler.ts index 6e7fbb562..f05219300 100644 --- a/src/addon/competency/providers/course-option-handler.ts +++ b/src/addon/competency/providers/course-option-handler.ts @@ -90,4 +90,30 @@ export class AddonCompetencyCourseOptionHandler implements CoreCourseOptionsHand return this.competencyProvider.invalidateCourseCompetencies(courseId); } + + /** + * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. + * + * @param {any} course The course. + * @return {Promise} Promise resolved when done. + */ + prefetch(course: any): Promise { + // Get the competencies in the course. + return this.competencyProvider.getCourseCompetencies(course.id, undefined, undefined, true).then((competencies) => { + const promises = []; + + // Prefetch all the competencies. + if (competencies && competencies.competencies) { + competencies.competencies.forEach((competency) => { + promises.push(this.competencyProvider.getCompetencyInCourse(course.id, competency.competency.id, undefined, + undefined, true)); + + promises.push(this.competencyProvider.getCompetencySummary(competency.competency.id, undefined, undefined, + true)); + }); + } + + return Promise.all(promises); + }); + } } diff --git a/src/addon/coursecompletion/providers/course-option-handler.ts b/src/addon/coursecompletion/providers/course-option-handler.ts index 0c61157fa..d6a08f6e9 100644 --- a/src/addon/coursecompletion/providers/course-option-handler.ts +++ b/src/addon/coursecompletion/providers/course-option-handler.ts @@ -86,4 +86,17 @@ export class AddonCourseCompletionCourseOptionHandler implements CoreCourseOptio invalidateEnabledForCourse(courseId: number, navOptions?: any, admOptions?: any): Promise { return this.courseCompletionProvider.invalidateCourseCompletion(courseId); } + + /** + * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. + * + * @param {any} course The course. + * @return {Promise} Promise resolved when done. + */ + prefetch(course: any): Promise { + return this.courseCompletionProvider.getCompletion(course.id, undefined, { + getFromCache: false, + emergencyCache: false + }); + } } diff --git a/src/addon/notes/providers/course-option-handler.ts b/src/addon/notes/providers/course-option-handler.ts index 34500726a..a1431a8c3 100644 --- a/src/addon/notes/providers/course-option-handler.ts +++ b/src/addon/notes/providers/course-option-handler.ts @@ -71,4 +71,14 @@ export class AddonNotesCourseOptionHandler implements CoreCourseOptionsHandler { component: AddonNotesListComponent, }; } + + /** + * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. + * + * @param {any} course The course. + * @return {Promise} Promise resolved when done. + */ + prefetch(course: any): Promise { + return this.notesProvider.getNotes(course.id, true); + } } diff --git a/src/core/grades/providers/course-option-handler.ts b/src/core/grades/providers/course-option-handler.ts index b4b062b93..7b253f723 100644 --- a/src/core/grades/providers/course-option-handler.ts +++ b/src/core/grades/providers/course-option-handler.ts @@ -16,6 +16,7 @@ import { Injectable, Injector } from '@angular/core'; import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '@core/course/providers/options-delegate'; import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreGradesProvider } from './grades'; +import { CoreGradesHelperProvider } from './helper'; import { CoreCoursesProvider } from '@core/courses/providers/courses'; import { CoreGradesCourseComponent } from '../components/course/course'; @@ -27,7 +28,8 @@ export class CoreGradesCourseOptionHandler implements CoreCourseOptionsHandler { name = 'CoreGrades'; priority = 400; - constructor(private gradesProvider: CoreGradesProvider, private coursesProvider: CoreCoursesProvider) {} + constructor(private gradesProvider: CoreGradesProvider, private coursesProvider: CoreCoursesProvider, + private gradesHelper: CoreGradesHelperProvider) {} /** * Should invalidate the data to determine if the handler is enabled for a certain course. @@ -90,4 +92,28 @@ export class CoreGradesCourseOptionHandler implements CoreCourseOptionsHandler { component: CoreGradesCourseComponent }; } + + /** + * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. + * + * @param {any} course The course. + * @return {Promise} Promise resolved when done. + */ + prefetch(course: any): Promise { + return this.gradesProvider.getCourseGradesTable(course.id, undefined, undefined, true).then((table) => { + const promises = []; + + table = this.gradesHelper.formatGradesTable(table); + + if (table && table.rows) { + table.rows.forEach((row) => { + if (row.itemtype != 'category') { + promises.push(this.gradesHelper.getGradeItem(course.id, row.id, undefined, undefined, true)); + } + }); + } + + return Promise.all(promises); + }); + } } diff --git a/src/core/user/providers/course-option-handler.ts b/src/core/user/providers/course-option-handler.ts index 9eb0230c9..4f91bb0ff 100644 --- a/src/core/user/providers/course-option-handler.ts +++ b/src/core/user/providers/course-option-handler.ts @@ -89,4 +89,30 @@ export class CoreUserParticipantsCourseOptionHandler implements CoreCourseOption component: CoreUserParticipantsComponent }; } + + /** + * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. + * + * @param {any} course The course. + * @return {Promise} Promise resolved when done. + */ + prefetch(course: any): Promise { + return this.getParticipantsPage(course.id, 0); + } + + /** + * Get a participant page and, if there are more participants, call the function again to get it too. + * + * @param {number} courseId Course ID. + * @param {number} limitFrom The number of participants already loaded. + * @return {Promise} Promise resolved when done. + */ + protected getParticipantsPage(courseId: number, limitFrom: number): Promise { + return this.userProvider.getParticipants(courseId, limitFrom, undefined, undefined, true).then((result) => { + if (result.canLoadMore) { + // There are more participants, load the next ones. + return this.getParticipantsPage(courseId, limitFrom + result.participants.length); + } + }); + } } diff --git a/src/core/user/providers/user.ts b/src/core/user/providers/user.ts index 45795a971..2a4d83d47 100644 --- a/src/core/user/providers/user.ts +++ b/src/core/user/providers/user.ts @@ -116,10 +116,12 @@ export class CoreUserProvider { * @param {number} limitFrom Position of the first participant to get. * @param {number} limitNumber Number of participants to get. * @param {string} [siteId] Site Id. If not defined, use current site. - * @return {Promise} Promise to be resolved when the participants are retrieved. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). + * @return {Promise<{participants: any[], canLoadMore: boolean}>} Promise resolved when the participants are retrieved. */ getParticipants(courseId: number, limitFrom: number = 0, limitNumber: number = CoreUserProvider.PARTICIPANTS_LIST_LIMIT, - siteId?: string): Promise { + siteId?: string, ignoreCache?: boolean): Promise<{participants: any[], canLoadMore: boolean}> { + return this.sitesProvider.getSite(siteId).then((site) => { this.logger.debug(`Get participants for course '${courseId}' starting at '${limitFrom}'`); @@ -139,10 +141,15 @@ export class CoreUserProvider { value: 'siteorder' } ] - }, preSets = { + }, preSets: any = { cacheKey: this.getParticipantsListCacheKey(courseId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('core_enrol_get_enrolled_users', data, preSets).then((users) => { const canLoadMore = users.length >= limitNumber; this.storeUsers(users, siteId);