From 910ee50600eb64747aba16e550ceeb17fca0f166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Tue, 5 Mar 2019 17:09:07 +0100 Subject: [PATCH] MOBILE-2873 sync: Sync activities on course prefetch --- .../mod/assign/providers/prefetch-handler.ts | 15 ++++++- .../mod/choice/providers/prefetch-handler.ts | 22 +++++++++- src/addon/mod/choice/providers/sync.ts | 5 ++- src/addon/mod/data/components/index/index.ts | 15 ++----- .../mod/data/providers/prefetch-handler.ts | 24 ++++++++++- src/addon/mod/data/providers/sync.ts | 7 ++-- .../feedback/providers/prefetch-handler.ts | 23 ++++++++++- src/addon/mod/forum/components/index/index.ts | 13 +----- .../mod/forum/providers/prefetch-handler.ts | 26 +++++++++++- .../mod/glossary/components/index/index.ts | 15 ++----- .../glossary/providers/prefetch-handler.ts | 25 ++++++++++- src/addon/mod/glossary/providers/sync.ts | 7 ++-- .../mod/lesson/providers/prefetch-handler.ts | 22 +++++++++- .../mod/quiz/providers/prefetch-handler.ts | 15 +++++++ .../mod/scorm/providers/prefetch-handler.ts | 22 +++++++++- .../mod/survey/providers/prefetch-handler.ts | 22 +++++++++- src/addon/mod/survey/providers/sync.ts | 5 ++- .../mod/wiki/providers/prefetch-handler.ts | 15 ++++++- .../workshop/providers/prefetch-handler.ts | 15 ++++++- src/core/course/providers/helper.ts | 25 ++++++----- .../providers/module-prefetch-delegate.ts | 41 ++++++++++++++++++- 21 files changed, 306 insertions(+), 73 deletions(-) diff --git a/src/addon/mod/assign/providers/prefetch-handler.ts b/src/addon/mod/assign/providers/prefetch-handler.ts index cae9b6fec..1cc2a6faa 100644 --- a/src/addon/mod/assign/providers/prefetch-handler.ts +++ b/src/addon/mod/assign/providers/prefetch-handler.ts @@ -28,6 +28,7 @@ import { CoreGradesHelperProvider } from '@core/grades/providers/helper'; import { CoreUserProvider } from '@core/user/providers/user'; import { AddonModAssignProvider } from './assign'; import { AddonModAssignHelperProvider } from './helper'; +import { AddonModAssignSyncProvider } from './assign-sync'; import { AddonModAssignFeedbackDelegate } from './feedback-delegate'; import { AddonModAssignSubmissionDelegate } from './submission-delegate'; @@ -47,7 +48,8 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan protected textUtils: CoreTextUtilsProvider, protected feedbackDelegate: AddonModAssignFeedbackDelegate, protected submissionDelegate: AddonModAssignSubmissionDelegate, protected courseHelper: CoreCourseHelperProvider, protected groupsProvider: CoreGroupsProvider, protected gradesHelper: CoreGradesHelperProvider, - protected userProvider: CoreUserProvider, protected assignHelper: AddonModAssignHelperProvider) { + protected userProvider: CoreUserProvider, protected assignHelper: AddonModAssignHelperProvider, + protected syncProvider: AddonModAssignSyncProvider) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -454,4 +456,15 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan return Promise.all(promises); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + return this.syncProvider.syncAssign(module.instance, siteId); + } } diff --git a/src/addon/mod/choice/providers/prefetch-handler.ts b/src/addon/mod/choice/providers/prefetch-handler.ts index 0b2f74eba..c12bf6902 100644 --- a/src/addon/mod/choice/providers/prefetch-handler.ts +++ b/src/addon/mod/choice/providers/prefetch-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; @@ -22,6 +22,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { CoreUserProvider } from '@core/user/providers/user'; +import { AddonModChoiceSyncProvider } from './sync'; import { AddonModChoiceProvider } from './choice'; /** @@ -34,10 +35,12 @@ export class AddonModChoicePrefetchHandler extends CoreCourseActivityPrefetchHan component = AddonModChoiceProvider.COMPONENT; updatesNames = /^configuration$|^.*files$|^answers$/; + protected syncProvider: AddonModChoiceSyncProvider; // It will be injected later to prevent circular dependencies. + constructor(translate: TranslateService, appProvider: CoreAppProvider, utils: CoreUtilsProvider, courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider, domUtils: CoreDomUtilsProvider, protected choiceProvider: AddonModChoiceProvider, - protected userProvider: CoreUserProvider) { + protected userProvider: CoreUserProvider, protected injector: Injector) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -133,4 +136,19 @@ export class AddonModChoicePrefetchHandler extends CoreCourseActivityPrefetchHan invalidateModule(module: any, courseId: number): Promise { return this.choiceProvider.invalidateChoiceData(courseId); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + if (!this.syncProvider) { + this.syncProvider = this.injector.get(AddonModChoiceSyncProvider); + } + + return this.syncProvider.syncChoice(module.instance, undefined, siteId); + } } diff --git a/src/addon/mod/choice/providers/sync.ts b/src/addon/mod/choice/providers/sync.ts index bcdc0b848..5d7e82d7f 100644 --- a/src/addon/mod/choice/providers/sync.ts +++ b/src/addon/mod/choice/providers/sync.ts @@ -127,12 +127,13 @@ export class AddonModChoiceSyncProvider extends CoreCourseActivitySyncBaseProvid * Synchronize a choice. * * @param {number} choiceId Choice ID to be synced. - * @param {number} userId User the answers belong to. + * @param {number} [userId] User the answers belong to. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved if sync is successful, rejected otherwise. */ - syncChoice(choiceId: number, userId: number, siteId?: string): Promise { + syncChoice(choiceId: number, userId?: number, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); + userId = userId || this.sitesProvider.getCurrentSiteUserId(); const syncId = this.getSyncId(choiceId, userId); if (this.isSyncing(syncId, siteId)) { diff --git a/src/addon/mod/data/components/index/index.ts b/src/addon/mod/data/components/index/index.ts index ddd5975a9..caaae195f 100644 --- a/src/addon/mod/data/components/index/index.ts +++ b/src/addon/mod/data/components/index/index.ts @@ -27,6 +27,7 @@ import { AddonModDataHelperProvider } from '../../providers/helper'; import { AddonModDataOfflineProvider } from '../../providers/offline'; import { AddonModDataSyncProvider } from '../../providers/sync'; import { AddonModDataComponentsModule } from '../components.module'; +import { AddonModDataPrefetchHandler } from '../../providers/prefetch-handler'; /** * Component that displays a data index page. @@ -82,7 +83,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp constructor(injector: Injector, private dataProvider: AddonModDataProvider, private dataHelper: AddonModDataHelperProvider, private dataOffline: AddonModDataOfflineProvider, @Optional() content: Content, - private dataSync: AddonModDataSyncProvider, private timeUtils: CoreTimeUtilsProvider, + private prefetchHandler: AddonModDataPrefetchHandler, private timeUtils: CoreTimeUtilsProvider, private groupsProvider: CoreGroupsProvider, private commentsProvider: CoreCommentsProvider, private modalCtrl: ModalController, private utils: CoreUtilsProvider, protected navCtrl: NavController, private ratingOffline: CoreRatingOfflineProvider) { @@ -520,17 +521,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp * @return {Promise} Promise resolved when done. */ protected sync(): Promise { - const promises = [ - this.dataSync.syncDatabase(this.data.id), - this.dataSync.syncRatings(this.data.coursemodule) - ]; - - return Promise.all(promises).then((results) => { - return results.reduce((a, b) => ({ - updated: a.updated || b.updated, - warnings: (a.warnings || []).concat(b.warnings || []), - }), {updated: false}); - }); + return this.prefetchHandler.sync(this.module); } /** diff --git a/src/addon/mod/data/providers/prefetch-handler.ts b/src/addon/mod/data/providers/prefetch-handler.ts index 85c54d10e..8ac16c797 100644 --- a/src/addon/mod/data/providers/prefetch-handler.ts +++ b/src/addon/mod/data/providers/prefetch-handler.ts @@ -26,6 +26,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { CoreRatingProvider } from '@core/rating/providers/rating'; import { AddonModDataProvider } from './data'; +import { AddonModDataSyncProvider } from './sync'; import { AddonModDataHelperProvider } from './helper'; /** @@ -43,7 +44,7 @@ export class AddonModDataPrefetchHandler extends CoreCourseActivityPrefetchHandl domUtils: CoreDomUtilsProvider, protected dataProvider: AddonModDataProvider, protected timeUtils: CoreTimeUtilsProvider, protected dataHelper: AddonModDataHelperProvider, protected groupsProvider: CoreGroupsProvider, protected commentsProvider: CoreCommentsProvider, - private ratingProvider: CoreRatingProvider) { + private ratingProvider: CoreRatingProvider, protected syncProvider: AddonModDataSyncProvider) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -301,4 +302,25 @@ export class AddonModDataPrefetchHandler extends CoreCourseActivityPrefetchHandl return Promise.all(promises); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + const promises = [ + this.syncProvider.syncDatabase(module.instance, siteId), + this.syncProvider.syncRatings(module.id, true, siteId) + ]; + + return Promise.all(promises).then((results) => { + return results.reduce((a, b) => ({ + updated: a.updated || b.updated, + warnings: (a.warnings || []).concat(b.warnings || []), + }), {updated: false}); + }); + } } diff --git a/src/addon/mod/data/providers/sync.ts b/src/addon/mod/data/providers/sync.ts index 6b5768adf..cb1465820 100644 --- a/src/addon/mod/data/providers/sync.ts +++ b/src/addon/mod/data/providers/sync.ts @@ -114,7 +114,7 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider { return Promise.all(this.utils.objectToArray(promises)); })); - promises.push(this.syncRatings(undefined, siteId)); + promises.push(this.syncRatings(undefined, force, siteId)); return Promise.all(promises); } @@ -362,13 +362,14 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider { * Synchronize offline ratings. * * @param {number} [cmId] Course module to be synced. If not defined, sync all databases. + * @param {boolean} [force] Wether to force sync not depending on last execution. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved if sync is successful, rejected otherwise. */ - syncRatings(cmId?: number, siteId?: string): Promise { + syncRatings(cmId?: number, force?: boolean, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); - return this.ratingSync.syncRatings('mod_data', 'entry', 'module', cmId, 0, siteId).then((results) => { + return this.ratingSync.syncRatings('mod_data', 'entry', 'module', cmId, 0, force, siteId).then((results) => { let updated = false; const warnings = []; const promises = []; diff --git a/src/addon/mod/feedback/providers/prefetch-handler.ts b/src/addon/mod/feedback/providers/prefetch-handler.ts index ab9528fc7..2e6d0ed7a 100644 --- a/src/addon/mod/feedback/providers/prefetch-handler.ts +++ b/src/addon/mod/feedback/providers/prefetch-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; @@ -25,6 +25,7 @@ import { AddonModFeedbackProvider } from './feedback'; import { AddonModFeedbackHelperProvider } from './helper'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreGroupsProvider } from '@providers/groups'; +import { AddonModFeedbackSyncProvider } from './sync'; import { CoreUserProvider } from '@core/user/providers/user'; /** @@ -37,11 +38,14 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH component = AddonModFeedbackProvider.COMPONENT; updatesNames = /^configuration$|^.*files$|^attemptsfinished|^attemptsunfinished$/; + protected syncProvider: AddonModFeedbackSyncProvider; // It will be injected later to prevent circular dependencies. + constructor(translate: TranslateService, appProvider: CoreAppProvider, utils: CoreUtilsProvider, courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider, domUtils: CoreDomUtilsProvider, protected feedbackProvider: AddonModFeedbackProvider, protected userProvider: CoreUserProvider, protected feedbackHelper: AddonModFeedbackHelperProvider, - protected timeUtils: CoreTimeUtilsProvider, protected groupsProvider: CoreGroupsProvider) { + protected timeUtils: CoreTimeUtilsProvider, protected groupsProvider: CoreGroupsProvider, + protected injector: Injector) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -239,4 +243,19 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH }); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + if (!this.syncProvider) { + this.syncProvider = this.injector.get(AddonModFeedbackSyncProvider); + } + + return this.syncProvider.syncFeedback(module.instance, siteId); + } } diff --git a/src/addon/mod/forum/components/index/index.ts b/src/addon/mod/forum/components/index/index.ts index 036697410..38551d2ff 100644 --- a/src/addon/mod/forum/components/index/index.ts +++ b/src/addon/mod/forum/components/index/index.ts @@ -376,18 +376,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom * @return {Promise} Promise resolved when done. */ protected sync(): Promise { - const promises = []; - - promises.push(this.forumSync.syncForumDiscussions(this.forum.id)); - promises.push(this.forumSync.syncForumReplies(this.forum.id)); - promises.push(this.forumSync.syncRatings(this.forum.cmid)); - - return Promise.all(promises).then((results) => { - return results.reduce((a, b) => ({ - updated: a.updated || b.updated, - warnings: (a.warnings || []).concat(b.warnings || []), - }), {updated: false}); - }); + return this.prefetchHandler.sync(this.module); } /** diff --git a/src/addon/mod/forum/providers/prefetch-handler.ts b/src/addon/mod/forum/providers/prefetch-handler.ts index 03e60a6ba..1da5e7b71 100644 --- a/src/addon/mod/forum/providers/prefetch-handler.ts +++ b/src/addon/mod/forum/providers/prefetch-handler.ts @@ -24,6 +24,7 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/acti import { CoreGroupsProvider } from '@providers/groups'; import { CoreUserProvider } from '@core/user/providers/user'; import { AddonModForumProvider } from './forum'; +import { AddonModForumSyncProvider } from './sync'; import { CoreRatingProvider } from '@core/rating/providers/rating'; /** @@ -46,7 +47,8 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand private groupsProvider: CoreGroupsProvider, private userProvider: CoreUserProvider, private forumProvider: AddonModForumProvider, - private ratingProvider: CoreRatingProvider) { + private ratingProvider: CoreRatingProvider, + private syncProvider: AddonModForumSyncProvider) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -264,4 +266,26 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand } }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + const promises = []; + + promises.push(this.syncProvider.syncForumDiscussions(module.instance, undefined, siteId)); + promises.push(this.syncProvider.syncForumReplies(module.instance, undefined, siteId)); + promises.push(this.syncProvider.syncRatings(module.id, undefined, true, siteId)); + + return Promise.all(promises).then((results) => { + return results.reduce((a, b) => ({ + updated: a.updated || b.updated, + warnings: (a.warnings || []).concat(b.warnings || []), + }), {updated: false}); + }); + } } diff --git a/src/addon/mod/glossary/components/index/index.ts b/src/addon/mod/glossary/components/index/index.ts index e05699f71..f44df70c6 100644 --- a/src/addon/mod/glossary/components/index/index.ts +++ b/src/addon/mod/glossary/components/index/index.ts @@ -23,6 +23,7 @@ import { AddonModGlossaryProvider } from '../../providers/glossary'; import { AddonModGlossaryOfflineProvider } from '../../providers/offline'; import { AddonModGlossarySyncProvider } from '../../providers/sync'; import { AddonModGlossaryModePickerPopoverComponent } from '../mode-picker/mode-picker'; +import { AddonModGlossaryPrefetchHandler } from '../../providers/prefetch-handler'; type FetchMode = 'author_all' | 'cat_all' | 'newest_first' | 'recently_updated' | 'search' | 'letter_all'; @@ -68,7 +69,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity private popoverCtrl: PopoverController, private glossaryProvider: AddonModGlossaryProvider, private glossaryOffline: AddonModGlossaryOfflineProvider, - private glossarySync: AddonModGlossarySyncProvider, + private prefetchHandler: AddonModGlossaryPrefetchHandler, private ratingOffline: CoreRatingOfflineProvider) { super(injector); } @@ -219,17 +220,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity * @return {Promise} Promise resolved when done. */ protected sync(): Promise { - const promises = [ - this.glossarySync.syncGlossaryEntries(this.glossary.id), - this.glossarySync.syncRatings(this.glossary.coursemodule) - ]; - - return Promise.all(promises).then((results) => { - return results.reduce((a, b) => ({ - updated: a.updated || b.updated, - warnings: (a.warnings || []).concat(b.warnings || []), - }), {updated: false}); - }); + return this.prefetchHandler.sync(this.module); } /** diff --git a/src/addon/mod/glossary/providers/prefetch-handler.ts b/src/addon/mod/glossary/providers/prefetch-handler.ts index 024fece96..2436dd1b8 100644 --- a/src/addon/mod/glossary/providers/prefetch-handler.ts +++ b/src/addon/mod/glossary/providers/prefetch-handler.ts @@ -24,6 +24,7 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/acti import { CoreUserProvider } from '@core/user/providers/user'; import { AddonModGlossaryProvider } from './glossary'; import { CoreRatingProvider } from '@core/rating/providers/rating'; +import { AddonModGlossarySyncProvider } from './sync'; /** * Handler to prefetch forums. @@ -44,7 +45,8 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH domUtils: CoreDomUtilsProvider, private userProvider: CoreUserProvider, private ratingProvider: CoreRatingProvider, - private glossaryProvider: AddonModGlossaryProvider) { + private glossaryProvider: AddonModGlossaryProvider, + private syncProvider: AddonModGlossarySyncProvider) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -187,4 +189,25 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH return Promise.all(promises); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + const promises = [ + this.syncProvider.syncGlossaryEntries(module.instance, undefined, siteId), + this.syncProvider.syncRatings(module.id, undefined, siteId) + ]; + + return Promise.all(promises).then((results) => { + return results.reduce((a, b) => ({ + updated: a.updated || b.updated, + warnings: (a.warnings || []).concat(b.warnings || []), + }), {updated: false}); + }); + } } diff --git a/src/addon/mod/glossary/providers/sync.ts b/src/addon/mod/glossary/providers/sync.ts index c3eefdafd..746563f67 100644 --- a/src/addon/mod/glossary/providers/sync.ts +++ b/src/addon/mod/glossary/providers/sync.ts @@ -118,7 +118,7 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider { return Promise.all(this.utils.objectToArray(promises)); })); - promises.push(this.syncRatings(undefined, siteId)); + promises.push(this.syncRatings(undefined, force, siteId)); return Promise.all(promises); } @@ -259,13 +259,14 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider { * Synchronize offline ratings. * * @param {number} [cmId] Course module to be synced. If not defined, sync all glossaries. + * @param {boolean} [force] Wether to force sync not depending on last execution. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved if sync is successful, rejected otherwise. */ - syncRatings(cmId?: number, siteId?: string): Promise { + syncRatings(cmId?: number, force?: boolean, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); - return this.ratingSync.syncRatings('mod_glossary', 'entry', 'module', cmId, 0, siteId).then((results) => { + return this.ratingSync.syncRatings('mod_glossary', 'entry', 'module', cmId, 0, force, siteId).then((results) => { let updated = false; const warnings = []; const promises = []; diff --git a/src/addon/mod/lesson/providers/prefetch-handler.ts b/src/addon/mod/lesson/providers/prefetch-handler.ts index 3660a90cd..cdc03d516 100644 --- a/src/addon/mod/lesson/providers/prefetch-handler.ts +++ b/src/addon/mod/lesson/providers/prefetch-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { ModalController } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; @@ -24,6 +24,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreGroupsProvider } from '@providers/groups'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { AddonModLessonProvider } from './lesson'; +import { AddonModLessonSyncProvider } from './lesson-sync'; /** * Handler to prefetch lessons. @@ -36,10 +37,12 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan // Don't check timers to decrease positives. If a user performs some action it will be reflected in other items. updatesNames = /^configuration$|^.*files$|^grades$|^gradeitems$|^pages$|^answers$|^questionattempts$|^pagesviewed$/; + protected syncProvider: AddonModLessonSyncProvider; // It will be injected later to prevent circular dependencies. + constructor(translate: TranslateService, appProvider: CoreAppProvider, utils: CoreUtilsProvider, courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider, domUtils: CoreDomUtilsProvider, protected modalCtrl: ModalController, protected groupsProvider: CoreGroupsProvider, - protected lessonProvider: AddonModLessonProvider) { + protected lessonProvider: AddonModLessonProvider, protected injector: Injector) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -429,4 +432,19 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan }); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + if (!this.syncProvider) { + this.syncProvider = this.injector.get(AddonModLessonSyncProvider); + } + + return this.syncProvider.syncLesson(module.instance, false, false, siteId); + } } diff --git a/src/addon/mod/quiz/providers/prefetch-handler.ts b/src/addon/mod/quiz/providers/prefetch-handler.ts index d292dc958..7a4387058 100644 --- a/src/addon/mod/quiz/providers/prefetch-handler.ts +++ b/src/addon/mod/quiz/providers/prefetch-handler.ts @@ -554,4 +554,19 @@ export class AddonModQuizPrefetchHandler extends CoreCourseActivityPrefetchHandl } }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + if (!this.syncProvider) { + this.syncProvider = this.injector.get(AddonModQuizSyncProvider); + } + + return this.syncProvider.syncQuiz(module.instance, false, siteId); + } } diff --git a/src/addon/mod/scorm/providers/prefetch-handler.ts b/src/addon/mod/scorm/providers/prefetch-handler.ts index c6f19e138..161f3243c 100644 --- a/src/addon/mod/scorm/providers/prefetch-handler.ts +++ b/src/addon/mod/scorm/providers/prefetch-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; @@ -24,6 +24,7 @@ import { CoreFileProvider } from '@providers/file'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { AddonModScormProvider } from './scorm'; +import { AddonModScormSyncProvider } from './scorm-sync'; /** * Progress event used when downloading a SCORM. @@ -58,10 +59,12 @@ export class AddonModScormPrefetchHandler extends CoreCourseActivityPrefetchHand component = AddonModScormProvider.COMPONENT; updatesNames = /^configuration$|^.*files$|^tracks$/; + protected syncProvider: AddonModScormSyncProvider; // It will be injected later to prevent circular dependencies. + constructor(translate: TranslateService, appProvider: CoreAppProvider, utils: CoreUtilsProvider, courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider, domUtils: CoreDomUtilsProvider, protected fileProvider: CoreFileProvider, protected textUtils: CoreTextUtilsProvider, - protected scormProvider: AddonModScormProvider) { + protected scormProvider: AddonModScormProvider, protected injector: Injector) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -423,4 +426,19 @@ export class AddonModScormPrefetchHandler extends CoreCourseActivityPrefetchHand return Promise.all(promises); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + if (!this.syncProvider) { + this.syncProvider = this.injector.get(AddonModScormSyncProvider); + } + + return this.syncProvider.syncScorm(module.instance, siteId); + } } diff --git a/src/addon/mod/survey/providers/prefetch-handler.ts b/src/addon/mod/survey/providers/prefetch-handler.ts index e6b785486..c1ffba84a 100644 --- a/src/addon/mod/survey/providers/prefetch-handler.ts +++ b/src/addon/mod/survey/providers/prefetch-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; @@ -22,6 +22,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { AddonModSurveyProvider } from './survey'; +import { AddonModSurveySyncProvider } from './sync'; import { AddonModSurveyHelperProvider } from './helper'; /** @@ -34,10 +35,12 @@ export class AddonModSurveyPrefetchHandler extends CoreCourseActivityPrefetchHan component = AddonModSurveyProvider.COMPONENT; updatesNames = /^configuration$|^.*files$|^answers$/; + protected syncProvider: AddonModSurveySyncProvider; // It will be injected later to prevent circular dependencies. + constructor(translate: TranslateService, appProvider: CoreAppProvider, utils: CoreUtilsProvider, courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider, domUtils: CoreDomUtilsProvider, protected surveyProvider: AddonModSurveyProvider, - protected surveyHelper: AddonModSurveyHelperProvider) { + protected surveyHelper: AddonModSurveyHelperProvider, protected injector: Injector) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -126,4 +129,19 @@ export class AddonModSurveyPrefetchHandler extends CoreCourseActivityPrefetchHan return Promise.all(promises); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + if (!this.syncProvider) { + this.syncProvider = this.injector.get(AddonModSurveySyncProvider); + } + + return this.syncProvider.syncSurvey(module.instance, undefined, siteId); + } } diff --git a/src/addon/mod/survey/providers/sync.ts b/src/addon/mod/survey/providers/sync.ts index f9b070175..e2e459a18 100644 --- a/src/addon/mod/survey/providers/sync.ts +++ b/src/addon/mod/survey/providers/sync.ts @@ -130,12 +130,13 @@ export class AddonModSurveySyncProvider extends CoreCourseActivitySyncBaseProvid * Synchronize a survey. * * @param {number} surveyId Survey ID. - * @param {number} userId User the answers belong to. + * @param {number} [userId] User the answers belong to. If not defined, current user. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved if sync is successful, rejected otherwise. */ - syncSurvey(surveyId: number, userId: number, siteId?: string): Promise { + syncSurvey(surveyId: number, userId?: number, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); + userId = userId || this.sitesProvider.getCurrentSiteUserId(); const syncId = this.getSyncId(surveyId, userId); if (this.isSyncing(syncId, siteId)) { diff --git a/src/addon/mod/wiki/providers/prefetch-handler.ts b/src/addon/mod/wiki/providers/prefetch-handler.ts index a8848db0c..02762895c 100644 --- a/src/addon/mod/wiki/providers/prefetch-handler.ts +++ b/src/addon/mod/wiki/providers/prefetch-handler.ts @@ -27,6 +27,7 @@ import { CoreCourseHelperProvider } from '@core/course/providers/helper'; import { CoreGradesHelperProvider } from '@core/grades/providers/helper'; import { CoreUserProvider } from '@core/user/providers/user'; import { AddonModWikiProvider } from './wiki'; +import { AddonModWikiSyncProvider } from './wiki-sync'; /** * Handler to prefetch wikis. @@ -42,7 +43,8 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider, domUtils: CoreDomUtilsProvider, protected wikiProvider: AddonModWikiProvider, protected userProvider: CoreUserProvider, protected textUtils: CoreTextUtilsProvider, protected courseHelper: CoreCourseHelperProvider, - protected groupsProvider: CoreGroupsProvider, protected gradesHelper: CoreGradesHelperProvider) { + protected groupsProvider: CoreGroupsProvider, protected gradesHelper: CoreGradesHelperProvider, + protected syncProvider: AddonModWikiSyncProvider) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -210,4 +212,15 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl return Promise.all(promises); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + return this.syncProvider.syncWiki(module.instance, module.course, module.id, siteId); + } } diff --git a/src/addon/mod/workshop/providers/prefetch-handler.ts b/src/addon/mod/workshop/providers/prefetch-handler.ts index ccdb6c4d2..b6da65262 100644 --- a/src/addon/mod/workshop/providers/prefetch-handler.ts +++ b/src/addon/mod/workshop/providers/prefetch-handler.ts @@ -24,6 +24,7 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/acti import { CoreGroupsProvider } from '@providers/groups'; import { CoreUserProvider } from '@core/user/providers/user'; import { AddonModWorkshopProvider } from './workshop'; +import { AddonModWorkshopSyncProvider } from './sync'; import { AddonModWorkshopHelperProvider } from './helper'; /** @@ -47,7 +48,8 @@ export class AddonModWorkshopPrefetchHandler extends CoreCourseActivityPrefetchH private groupsProvider: CoreGroupsProvider, private userProvider: CoreUserProvider, private workshopProvider: AddonModWorkshopProvider, - private workshopHelper: AddonModWorkshopHelperProvider) { + private workshopHelper: AddonModWorkshopHelperProvider, + private syncProvider: AddonModWorkshopSyncProvider) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); } @@ -365,4 +367,15 @@ export class AddonModWorkshopPrefetchHandler extends CoreCourseActivityPrefetchH }); }); } + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync(module: any, siteId?: string): Promise { + return this.syncProvider.syncWorkshop(module.instance, siteId); + } } diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index a79546849..aca768b0d 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -294,6 +294,7 @@ export class CoreCourseHelperProvider { } return promise.then((sections) => { + // Confirm the download. return this.confirmDownloadSizeSection(course.id, undefined, sections, true).then(() => { // User confirmed, get the course handlers if needed. @@ -1317,18 +1318,22 @@ export class CoreCourseHelperProvider { section.isDownloading = true; - // Validate the section needs to be downloaded and calculate amount of modules that need to be downloaded. - promises.push(this.prefetchDelegate.getModulesStatus(section.modules, courseId, section.id).then((result) => { - if (result.status == CoreConstants.DOWNLOADED || result.status == CoreConstants.NOT_DOWNLOADABLE) { - // Section is downloaded or not downloadable, nothing to do. - return; - } + // Sync the modules first. + promises.push(this.prefetchDelegate.syncModules(section.modules).then(() => { + // Validate the section needs to be downloaded and calculate amount of modules that need to be downloaded. + return this.prefetchDelegate.getModulesStatus(section.modules, courseId, section.id).then((result) => { + if (result.status == CoreConstants.DOWNLOADED || result.status == CoreConstants.NOT_DOWNLOADABLE) { + // Section is downloaded or not downloadable, nothing to do. - return this.prefetchSingleSection(section, result, courseId); - }, (error) => { - section.isDownloading = false; + return ; + } - return Promise.reject(error); + return this.prefetchSingleSection(section, result, courseId); + }, (error) => { + section.isDownloading = false; + + return Promise.reject(error); + }); })); // Download the files in the section description. diff --git a/src/core/course/providers/module-prefetch-delegate.ts b/src/core/course/providers/module-prefetch-delegate.ts index 24ca8c933..7691f5276 100644 --- a/src/core/course/providers/module-prefetch-delegate.ts +++ b/src/core/course/providers/module-prefetch-delegate.ts @@ -206,6 +206,15 @@ export interface CoreCourseModulePrefetchHandler extends CoreDelegateHandler { * @return {Promise} Promise resolved when done. */ removeFiles?(module: any, courseId: number): Promise; + + /** + * Sync a module. + * + * @param {any} module Module. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + sync?(module: any, siteId?: any): Promise; } /** @@ -1139,12 +1148,42 @@ export class CoreCourseModulePrefetchDelegate extends CoreDelegate { // Check if the module has a prefetch handler. if (handler) { - return handler.prefetch(module, courseId, single); + return this.syncModule(module).then(() => { + return handler.prefetch(module, courseId, single); + }); } return Promise.resolve(); } + /** + * Sync a group of modules. + * + * @param {any[]} modules Array of modules to sync. + * @return {Promise} Promise resolved when finished. + */ + syncModules(modules: any[]): Promise { + return Promise.all(modules.map((module) => { + return this.syncModule(module); + })); + } + + /** + * Sync a module. + * + * @param {any} module Module to sync. + * @return {Promise} Promise resolved when finished. + */ + syncModule(module: any): Promise { + const handler = this.getPrefetchHandlerFor(module); + + const promise = handler && handler.sync ? handler.sync(module) : Promise.resolve(); + + return promise.catch(() => { + // Ignore errors. + }); + } + /** * Prefetches a list of modules using their prefetch handlers. * If a prefetch already exists for this site and id, returns the current promise.