From 56eaafdedad96ccbcd4e2db21b92cd33def6f24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 4 Feb 2019 12:06:05 +0100 Subject: [PATCH 1/2] MOBILE-1979 course: Save offline log calls --- src/addon/mod/assign/providers/assign.ts | 24 +- src/addon/mod/book/providers/book.ts | 9 +- src/addon/mod/chat/providers/chat.ts | 15 +- src/addon/mod/choice/providers/choice.ts | 10 +- src/addon/mod/data/providers/data.ts | 9 +- src/addon/mod/feedback/providers/feedback.ts | 8 +- src/addon/mod/folder/providers/folder.ts | 8 +- .../mod/forum/pages/discussion/discussion.ts | 2 +- src/addon/mod/forum/providers/forum.ts | 17 +- src/addon/mod/glossary/pages/entry/entry.ts | 2 +- src/addon/mod/glossary/providers/glossary.ts | 15 +- src/addon/mod/imscp/providers/imscp.ts | 11 +- src/addon/mod/lesson/providers/lesson.ts | 12 +- src/addon/mod/lti/providers/lti.ts | 11 +- src/addon/mod/page/providers/page.ts | 9 +- src/addon/mod/quiz/pages/player/player.ts | 5 +- src/addon/mod/quiz/pages/review/review.ts | 2 +- src/addon/mod/quiz/providers/quiz-sync.ts | 4 +- src/addon/mod/quiz/providers/quiz.ts | 27 ++- src/addon/mod/resource/providers/resource.ts | 9 +- src/addon/mod/scorm/providers/scorm.ts | 19 +- src/addon/mod/survey/providers/survey.ts | 8 +- src/addon/mod/url/providers/url.ts | 9 +- src/addon/mod/wiki/components/index/index.ts | 4 +- src/addon/mod/wiki/providers/wiki.ts | 29 ++- .../workshop/pages/submission/submission.ts | 2 +- src/addon/mod/workshop/providers/workshop.ts | 31 ++- src/core/course/course.module.ts | 3 + src/core/course/providers/log-helper.ts | 225 ++++++++++++++++++ 29 files changed, 403 insertions(+), 136 deletions(-) create mode 100644 src/core/course/providers/log-helper.ts diff --git a/src/addon/mod/assign/providers/assign.ts b/src/addon/mod/assign/providers/assign.ts index c6c3bf8cf..69cce5081 100644 --- a/src/addon/mod/assign/providers/assign.ts +++ b/src/addon/mod/assign/providers/assign.ts @@ -23,6 +23,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCommentsProvider } from '@core/comments/providers/comments'; import { CoreUserProvider } from '@core/user/providers/user'; import { CoreGradesProvider } from '@core/grades/providers/grades'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModAssignSubmissionDelegate } from './submission-delegate'; import { AddonModAssignOfflineProvider } from './assign-offline'; import { CoreSiteWSPreSets } from '@classes/site'; @@ -68,7 +69,8 @@ export class AddonModAssignProvider { private timeUtils: CoreTimeUtilsProvider, private appProvider: CoreAppProvider, private utils: CoreUtilsProvider, private userProvider: CoreUserProvider, private submissionDelegate: AddonModAssignSubmissionDelegate, private gradesProvider: CoreGradesProvider, private filepoolProvider: CoreFilepoolProvider, - private assignOffline: AddonModAssignOfflineProvider, private commentsProvider: CoreCommentsProvider) { + private assignOffline: AddonModAssignOfflineProvider, private commentsProvider: CoreCommentsProvider, + private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModAssignProvider'); } @@ -976,13 +978,11 @@ export class AddonModAssignProvider { * @return {Promise} Promise resolved when the WS call is successful. */ logGradingView(assignId: number, siteId?: string): Promise { - return this.sitesProvider.getSite(siteId).then((site) => { - const params = { - assignid: assignId - }; + const params = { + assignid: assignId + }; - return site.write('mod_assign_view_grading_table', params); - }); + return this.logHelper.log('mod_assign_view_grading_table', params, AddonModAssignProvider.COMPONENT, assignId, siteId); } /** @@ -993,13 +993,11 @@ export class AddonModAssignProvider { * @return {Promise} Promise resolved when the WS call is successful. */ logView(assignId: number, siteId?: string): Promise { - return this.sitesProvider.getSite(siteId).then((site) => { - const params = { - assignid: assignId - }; + const params = { + assignid: assignId + }; - return site.write('mod_assign_view_assign', params); - }); + return this.logHelper.log('mod_assign_view_assign', params, AddonModAssignProvider.COMPONENT, assignId, siteId); } /** diff --git a/src/addon/mod/book/providers/book.ts b/src/addon/mod/book/providers/book.ts index 4f97a6e83..e322284c6 100644 --- a/src/addon/mod/book/providers/book.ts +++ b/src/addon/mod/book/providers/book.ts @@ -22,6 +22,7 @@ import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; /** * A book chapter inside the toc list. @@ -64,7 +65,8 @@ export class AddonModBookProvider { constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider, private fileProvider: CoreFileProvider, private filepoolProvider: CoreFilepoolProvider, private http: Http, - private utils: CoreUtilsProvider, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) { + private utils: CoreUtilsProvider, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModBookProvider'); } @@ -378,14 +380,15 @@ export class AddonModBookProvider { * * @param {number} id Module ID. * @param {string} chapterId Chapter ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number, chapterId: string): Promise { + logView(id: number, chapterId: string, siteId?: string): Promise { const params = { bookid: id, chapterid: chapterId }; - return this.sitesProvider.getCurrentSite().write('mod_book_view_book', params); + return this.logHelper.log('mod_book_view_book', params, AddonModBookProvider.COMPONENT, id, siteId); } } diff --git a/src/addon/mod/chat/providers/chat.ts b/src/addon/mod/chat/providers/chat.ts index d4f6e8f3e..1138502da 100644 --- a/src/addon/mod/chat/providers/chat.ts +++ b/src/addon/mod/chat/providers/chat.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUserProvider } from '@core/user/providers/user'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; /** * Service that provides some features for chats. @@ -24,7 +25,8 @@ export class AddonModChatProvider { static COMPONENT = 'mmaModChat'; static POLL_INTERVAL = 4000; - constructor(private sitesProvider: CoreSitesProvider, private userProvider: CoreUserProvider) {} + constructor(private sitesProvider: CoreSitesProvider, private userProvider: CoreUserProvider, + private logHelper: CoreCourseLogHelperProvider) {} /** * Get a chat. @@ -77,15 +79,16 @@ export class AddonModChatProvider { /** * Report a chat as being viewed. * - * @param {number} chatId Chat instance ID. - * @return {Promise} Promise resolved when the WS call is executed. + * @param {number} id Chat instance ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the WS call is successful. */ - logView(chatId: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { - chatid: chatId + chatid: id }; - return this.sitesProvider.getCurrentSite().write('mod_chat_view_chat', params); + return this.logHelper.log('mod_chat_view_chat', params, AddonModChatProvider.COMPONENT, id, siteId); } /** diff --git a/src/addon/mod/choice/providers/choice.ts b/src/addon/mod/choice/providers/choice.ts index b94fec312..8845aed49 100644 --- a/src/addon/mod/choice/providers/choice.ts +++ b/src/addon/mod/choice/providers/choice.ts @@ -17,6 +17,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModChoiceOfflineProvider } from './offline'; /** @@ -38,7 +39,7 @@ export class AddonModChoiceProvider { constructor(private sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider, private filepoolProvider: CoreFilepoolProvider, private utils: CoreUtilsProvider, - private choiceOffline: AddonModChoiceOfflineProvider) {} + private choiceOffline: AddonModChoiceOfflineProvider, private logHelper: CoreCourseLogHelperProvider) {} /** * Check if results can be seen by a student. The student can see the results if: @@ -346,14 +347,15 @@ export class AddonModChoiceProvider { * Report the choice as being viewed. * * @param {string} id Choice ID. - * @return {Promise} Promise resolved when the WS call is successful. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: string): Promise { + logView(id: number, siteId?: string): Promise { const params = { choiceid: id }; - return this.sitesProvider.getCurrentSite().write('mod_choice_view_choice', params); + return this.logHelper.log('mod_choice_view_choice', params, AddonModChoiceProvider.COMPONENT, id, siteId); } /** diff --git a/src/addon/mod/data/providers/data.ts b/src/addon/mod/data/providers/data.ts index ca9d5da62..8ab7f43e2 100644 --- a/src/addon/mod/data/providers/data.ts +++ b/src/addon/mod/data/providers/data.ts @@ -18,6 +18,7 @@ import { CoreLoggerProvider } from '@providers/logger'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreFilepoolProvider } from '@providers/filepool'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModDataOfflineProvider } from './offline'; import { AddonModDataFieldsDelegate } from './fields-delegate'; @@ -35,7 +36,8 @@ export class AddonModDataProvider { constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private filepoolProvider: CoreFilepoolProvider, private dataOffline: AddonModDataOfflineProvider, - private appProvider: CoreAppProvider, private fieldsDelegate: AddonModDataFieldsDelegate) { + private appProvider: CoreAppProvider, private fieldsDelegate: AddonModDataFieldsDelegate, + private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModDataProvider'); } @@ -846,14 +848,15 @@ export class AddonModDataProvider { * Report the database as being viewed. * * @param {number} id Module ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { databaseid: id }; - return this.sitesProvider.getCurrentSite().write('mod_data_view_database', params); + return this.logHelper.log('mod_data_view_database', params, AddonModDataProvider.COMPONENT, id, siteId); } /** diff --git a/src/addon/mod/feedback/providers/feedback.ts b/src/addon/mod/feedback/providers/feedback.ts index 3fcb0099e..a113791c5 100644 --- a/src/addon/mod/feedback/providers/feedback.ts +++ b/src/addon/mod/feedback/providers/feedback.ts @@ -18,6 +18,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreAppProvider } from '@providers/app'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModFeedbackOfflineProvider } from './offline'; /** @@ -38,7 +39,7 @@ export class AddonModFeedbackProvider { constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private filepoolProvider: CoreFilepoolProvider, private feedbackOffline: AddonModFeedbackOfflineProvider, - private appProvider: CoreAppProvider) { + private appProvider: CoreAppProvider, private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModFeedbackProvider'); } @@ -1071,15 +1072,16 @@ export class AddonModFeedbackProvider { * * @param {number} id Module ID. * @param {boolean} [formViewed=false] True if form was viewed. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number, formViewed: boolean = false): Promise { + logView(id: number, formViewed: boolean = false, siteId?: string): Promise { const params = { feedbackid: id, moduleviewed: formViewed ? 1 : 0 }; - return this.sitesProvider.getCurrentSite().write('mod_feedback_view_feedback', params); + return this.logHelper.log('mod_feedback_view_feedback', params, AddonModFeedbackProvider.COMPONENT, id, siteId); } /** diff --git a/src/addon/mod/folder/providers/folder.ts b/src/addon/mod/folder/providers/folder.ts index 63c5767bd..f26369af8 100644 --- a/src/addon/mod/folder/providers/folder.ts +++ b/src/addon/mod/folder/providers/folder.ts @@ -17,6 +17,7 @@ import { CoreLoggerProvider } from '@providers/logger'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; /** * Service that provides some features for folder. @@ -29,7 +30,7 @@ export class AddonModFolderProvider { protected logger; constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider, - private utils: CoreUtilsProvider) { + private utils: CoreUtilsProvider, private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModFolderProvider'); } @@ -132,13 +133,14 @@ export class AddonModFolderProvider { * Report a folder as being viewed. * * @param {number} id Module ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { folderid: id }; - return this.sitesProvider.getCurrentSite().write('mod_folder_view_folder', params); + return this.logHelper.log('mod_folder_view_folder', params, AddonModFolderProvider.COMPONENT, id, siteId); } } diff --git a/src/addon/mod/forum/pages/discussion/discussion.ts b/src/addon/mod/forum/pages/discussion/discussion.ts index 16d5537b2..7879e8470 100644 --- a/src/addon/mod/forum/pages/discussion/discussion.ts +++ b/src/addon/mod/forum/pages/discussion/discussion.ts @@ -299,7 +299,7 @@ export class AddonModForumDiscussionPage implements OnDestroy { if (forceMarkAsRead || (hasUnreadPosts && this.trackPosts)) { // // Add log in Moodle and mark unread posts as readed. - this.forumProvider.logDiscussionView(this.discussionId).catch(() => { + this.forumProvider.logDiscussionView(this.discussionId, this.forumId).catch(() => { // Ignore errors. }).finally(() => { // Trigger mark read posts. diff --git a/src/addon/mod/forum/providers/forum.ts b/src/addon/mod/forum/providers/forum.ts index f386ac855..a7eb0bbae 100644 --- a/src/addon/mod/forum/providers/forum.ts +++ b/src/addon/mod/forum/providers/forum.ts @@ -20,6 +20,7 @@ import { CoreGroupsProvider } from '@providers/groups'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUserProvider } from '@core/user/providers/user'; import { CoreUtilsProvider } from '@providers/utils/utils'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModForumOfflineProvider } from './offline'; /** @@ -43,7 +44,8 @@ export class AddonModForumProvider { private userProvider: CoreUserProvider, private translate: TranslateService, private utils: CoreUtilsProvider, - private forumOffline: AddonModForumOfflineProvider) {} + private forumOffline: AddonModForumOfflineProvider, + private logHelper: CoreCourseLogHelperProvider) {} /** * Get cache key for can add discussion WS calls. @@ -596,28 +598,31 @@ export class AddonModForumProvider { * Report a forum as being viewed. * * @param {number} id Module ID. - * @return {Promise} Promise resolved when the WS call is successful. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { forumid: id }; - return this.sitesProvider.getCurrentSite().write('mod_forum_view_forum', params); + return this.logHelper.log('mod_forum_view_forum', params, AddonModForumProvider.COMPONENT, id, siteId); } /** * Report a forum discussion as being viewed. * * @param {number} id Discussion ID. + * @param {number} forumId Forum ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logDiscussionView(id: number): Promise { + logDiscussionView(id: number, forumId: number, siteId?: string): Promise { const params = { discussionid: id }; - return this.sitesProvider.getCurrentSite().write('mod_forum_view_forum_discussion', params); + return this.logHelper.log('mod_forum_view_forum_discussion', params, AddonModForumProvider.COMPONENT, forumId, siteId); } /** diff --git a/src/addon/mod/glossary/pages/entry/entry.ts b/src/addon/mod/glossary/pages/entry/entry.ts index 0e2451be6..461f0350b 100644 --- a/src/addon/mod/glossary/pages/entry/entry.ts +++ b/src/addon/mod/glossary/pages/entry/entry.ts @@ -48,7 +48,7 @@ export class AddonModGlossaryEntryPage { */ ionViewDidLoad(): void { this.fetchEntry().then(() => { - this.glossaryProvider.logEntryView(this.entry.id).catch(() => { + this.glossaryProvider.logEntryView(this.entry.id, this.componentId).catch(() => { // Ignore errors. }); }).finally(() => { diff --git a/src/addon/mod/glossary/providers/glossary.ts b/src/addon/mod/glossary/providers/glossary.ts index 990f33cdd..da906180c 100644 --- a/src/addon/mod/glossary/providers/glossary.ts +++ b/src/addon/mod/glossary/providers/glossary.ts @@ -20,6 +20,7 @@ import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreSitesProvider } from '@providers/sites'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreUtilsProvider } from '@providers/utils/utils'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModGlossaryOfflineProvider } from './offline'; /** @@ -43,7 +44,8 @@ export class AddonModGlossaryProvider { private translate: TranslateService, private textUtils: CoreTextUtilsProvider, private utils: CoreUtilsProvider, - private glossaryOffline: AddonModGlossaryOfflineProvider) {} + private glossaryOffline: AddonModGlossaryOfflineProvider, + private logHelper: CoreCourseLogHelperProvider) {} /** * Get the course glossary cache key. @@ -860,28 +862,31 @@ export class AddonModGlossaryProvider { * * @param {number} glossaryId Glossary ID. * @param {string} mode The mode in which the glossary was viewed. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(glossaryId: number, mode: string): Promise { + logView(glossaryId: number, mode: string, siteId?: string): Promise { const params = { id: glossaryId, mode: mode }; - return this.sitesProvider.getCurrentSite().write('mod_glossary_view_glossary', params); + return this.logHelper.log('mod_glossary_view_glossary', params, AddonModGlossaryProvider.COMPONENT, glossaryId, siteId); } /** * Report a glossary entry as being viewed. * * @param {number} entryId Entry ID. + * @param {number} glossaryId Glossary ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logEntryView(entryId: number): Promise { + logEntryView(entryId: number, glossaryId: number, siteId?: string): Promise { const params = { id: entryId }; - return this.sitesProvider.getCurrentSite().write('mod_glossary_view_entry', params); + return this.logHelper.log('mod_glossary_view_entry', params, AddonModGlossaryProvider.COMPONENT, glossaryId, siteId); } } diff --git a/src/addon/mod/imscp/providers/imscp.ts b/src/addon/mod/imscp/providers/imscp.ts index cb66631a7..5cc7b9258 100644 --- a/src/addon/mod/imscp/providers/imscp.ts +++ b/src/addon/mod/imscp/providers/imscp.ts @@ -19,6 +19,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; /** * Service that provides some features for IMSCP. @@ -31,7 +32,8 @@ export class AddonModImscpProvider { constructor(private appProvider: CoreAppProvider, private courseProvider: CoreCourseProvider, private filepoolProvider: CoreFilepoolProvider, private sitesProvider: CoreSitesProvider, - private textUtils: CoreTextUtilsProvider, private utils: CoreUtilsProvider) {} + private textUtils: CoreTextUtilsProvider, private utils: CoreUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) {} /** * Get the IMSCP toc as an array. @@ -307,13 +309,14 @@ export class AddonModImscpProvider { * Report a IMSCP as being viewed. * * @param {string} id Module ID. - * @return {Promise} Promise resolved when the WS call is successful. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: string): Promise { + logView(id: number, siteId?: string): Promise { const params = { imscpid: id }; - return this.sitesProvider.getCurrentSite().write('mod_imscp_view_imscp', params); + return this.logHelper.log('mod_imscp_view_imscp', params, AddonModImscpProvider.COMPONENT, id, siteId); } } diff --git a/src/addon/mod/lesson/providers/lesson.ts b/src/addon/mod/lesson/providers/lesson.ts index 6af1f19d1..c996f0c6a 100644 --- a/src/addon/mod/lesson/providers/lesson.ts +++ b/src/addon/mod/lesson/providers/lesson.ts @@ -20,6 +20,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreGradesProvider } from '@core/grades/providers/grades'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreSiteWSPreSets } from '@classes/site'; import { AddonModLessonOfflineProvider } from './lesson-offline'; @@ -179,7 +180,7 @@ export class AddonModLessonProvider { constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private translate: TranslateService, private textUtils: CoreTextUtilsProvider, private domUtils: CoreDomUtilsProvider, - private lessonOfflineProvider: AddonModLessonOfflineProvider) { + private lessonOfflineProvider: AddonModLessonOfflineProvider, private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModLessonProvider'); this.sitesProvider.createTableFromSchema(this.tablesSchema); @@ -2960,14 +2961,9 @@ export class AddonModLessonProvider { params.password = password; } - return site.write('mod_lesson_view_lesson', params).then((result) => { - if (!result.status) { - return Promise.reject(null); - } - - return result; - }); + return this.logHelper.log('mod_lesson_view_lesson', params, AddonModLessonProvider.COMPONENT, id, siteId); }); + } /** diff --git a/src/addon/mod/lti/providers/lti.ts b/src/addon/mod/lti/providers/lti.ts index 64f6f6e6a..44163818a 100644 --- a/src/addon/mod/lti/providers/lti.ts +++ b/src/addon/mod/lti/providers/lti.ts @@ -20,6 +20,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUrlUtilsProvider } from '@providers/utils/url'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; export interface AddonModLtiParam { name: string; @@ -42,7 +43,8 @@ export class AddonModLtiProvider { private urlUtils: CoreUrlUtilsProvider, private utils: CoreUtilsProvider, private translate: TranslateService, - private appProvider: CoreAppProvider) {} + private appProvider: CoreAppProvider, + private logHelper: CoreCourseLogHelperProvider) {} /** * Delete launcher. @@ -211,13 +213,14 @@ export class AddonModLtiProvider { * Report the LTI as being viewed. * * @param {string} id LTI id. - * @return {Promise} Promise resolved when the WS call is successful. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: string): Promise { + logView(id: number, siteId?: string): Promise { const params: any = { ltiid: id }; - return this.sitesProvider.getCurrentSite().write('mod_lti_view_lti', params); + return this.logHelper.log('mod_lti_view_lti', params, AddonModLtiProvider.COMPONENT, id, siteId); } } diff --git a/src/addon/mod/page/providers/page.ts b/src/addon/mod/page/providers/page.ts index 11647e68b..cfdce8b11 100644 --- a/src/addon/mod/page/providers/page.ts +++ b/src/addon/mod/page/providers/page.ts @@ -17,6 +17,7 @@ import { CoreLoggerProvider } from '@providers/logger'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreFilepoolProvider } from '@providers/filepool'; /** @@ -30,7 +31,8 @@ export class AddonModPageProvider { protected logger; constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider, - private utils: CoreUtilsProvider, private filepoolProvider: CoreFilepoolProvider) { + private utils: CoreUtilsProvider, private filepoolProvider: CoreFilepoolProvider, + private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModPageProvider'); } @@ -146,13 +148,14 @@ export class AddonModPageProvider { * Report a page as being viewed. * * @param {number} id Module ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { pageid: id }; - return this.sitesProvider.getCurrentSite().write('mod_page_view_page', params); + return this.logHelper.log('mod_page_view_page', params, AddonModPageProvider.COMPONENT, id, siteId); } } diff --git a/src/addon/mod/quiz/pages/player/player.ts b/src/addon/mod/quiz/pages/player/player.ts index 5d91f73e6..feb27bb7f 100644 --- a/src/addon/mod/quiz/pages/player/player.ts +++ b/src/addon/mod/quiz/pages/player/player.ts @@ -428,7 +428,8 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy { }); // Mark the page as viewed. We'll ignore errors in this call. - this.quizProvider.logViewAttempt(this.attempt.id, page, this.preflightData, this.offline).catch((error) => { + this.quizProvider.logViewAttempt(this.attempt.id, this.quizId, page, this.preflightData, this.offline) + .catch((error) => { // Ignore errors. }); @@ -455,7 +456,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy { this.attempt.dueDateWarning = this.quizProvider.getAttemptDueDateWarning(this.quiz, this.attempt); // Log summary as viewed. - this.quizProvider.logViewAttemptSummary(this.attempt.id, this.preflightData).catch((error) => { + this.quizProvider.logViewAttemptSummary(this.attempt.id, this.preflightData, this.quizId).catch((error) => { // Ignore errors. }); }); diff --git a/src/addon/mod/quiz/pages/review/review.ts b/src/addon/mod/quiz/pages/review/review.ts index 805d9662b..03c894cf6 100644 --- a/src/addon/mod/quiz/pages/review/review.ts +++ b/src/addon/mod/quiz/pages/review/review.ts @@ -77,7 +77,7 @@ export class AddonModQuizReviewPage implements OnInit { */ ngOnInit(): void { this.fetchData().then(() => { - this.quizProvider.logViewAttemptReview(this.attemptId).catch((error) => { + this.quizProvider.logViewAttemptReview(this.attemptId, this.quizId).catch((error) => { // Ignore errors. }); }).finally(() => { diff --git a/src/addon/mod/quiz/providers/quiz-sync.ts b/src/addon/mod/quiz/providers/quiz-sync.ts index 9c27f22b5..4d00bf7fa 100644 --- a/src/addon/mod/quiz/providers/quiz-sync.ts +++ b/src/addon/mod/quiz/providers/quiz-sync.ts @@ -341,8 +341,8 @@ export class AddonModQuizSyncProvider extends CoreSyncBaseProvider { // Answers sent, now set the current page if the attempt isn't finished. if (!finish) { - return this.quizProvider.logViewAttempt(onlineAttempt.id, offlineAttempt.currentpage, preflightData, - false).catch(() => { + return this.quizProvider.logViewAttempt(onlineAttempt.id, quiz.id, offlineAttempt.currentpage, + preflightData, false).catch(() => { // Ignore errors. }); } diff --git a/src/addon/mod/quiz/providers/quiz.ts b/src/addon/mod/quiz/providers/quiz.ts index a3c8d87be..1777bafdf 100644 --- a/src/addon/mod/quiz/providers/quiz.ts +++ b/src/addon/mod/quiz/providers/quiz.ts @@ -24,6 +24,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreSiteWSPreSets } from '@classes/site'; import { CoreGradesHelperProvider } from '@core/grades/providers/helper'; import { CoreQuestionDelegate } from '@core/question/providers/delegate'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModQuizAccessRuleDelegate } from './access-rules-delegate'; import { AddonModQuizOfflineProvider } from './quiz-offline'; @@ -62,7 +63,7 @@ export class AddonModQuizProvider { private gradesHelper: CoreGradesHelperProvider, private questionDelegate: CoreQuestionDelegate, private filepoolProvider: CoreFilepoolProvider, private timeUtils: CoreTimeUtilsProvider, private accessRulesDelegate: AddonModQuizAccessRuleDelegate, private quizOfflineProvider: AddonModQuizOfflineProvider, - private domUtils: CoreDomUtilsProvider) { + private domUtils: CoreDomUtilsProvider, private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModQuizProvider'); } @@ -1523,9 +1524,12 @@ export class AddonModQuizProvider { * @param {number} [page=0] Page number. * @param {any} [preflightData] Preflight required data (like password). * @param {boolean} [offline] Whether attempt is offline. + * @param {number} quizId Quiz ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logViewAttempt(attemptId: number, page: number = 0, preflightData: any = {}, offline?: boolean): Promise { + logViewAttempt(attemptId: number, quizId: number, page: number = 0, preflightData: any = {}, offline?: boolean, + siteId?: string): Promise { const params = { attemptid: attemptId, page: page, @@ -1533,7 +1537,7 @@ export class AddonModQuizProvider { }, promises = []; - promises.push(this.sitesProvider.getCurrentSite().write('mod_quiz_view_attempt', params)); + promises.push(this.logHelper.log('mod_quiz_view_attempt', params, AddonModQuizProvider.COMPONENT, quizId, siteId)); if (offline) { promises.push(this.quizOfflineProvider.setAttemptCurrentPage(attemptId, page)); } @@ -1545,14 +1549,16 @@ export class AddonModQuizProvider { * Report an attempt's review as being viewed. * * @param {number} attemptId Attempt ID. + * @param {number} quizId Quiz ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logViewAttemptReview(attemptId: number): Promise { + logViewAttemptReview(attemptId: number, quizId: number, siteId?: string): Promise { const params = { attemptid: attemptId }; - return this.sitesProvider.getCurrentSite().write('mod_quiz_view_attempt_review', params); + return this.logHelper.log('mod_quiz_view_attempt_review', params, AddonModQuizProvider.COMPONENT, quizId, siteId); } /** @@ -1560,29 +1566,32 @@ export class AddonModQuizProvider { * * @param {number} attemptId Attempt ID. * @param {any} preflightData Preflight required data (like password). + * @param {number} quizId Quiz ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logViewAttemptSummary(attemptId: number, preflightData: any): Promise { + logViewAttemptSummary(attemptId: number, preflightData: any, quizId: number, siteId?: string): Promise { const params = { attemptid: attemptId, preflightdata: this.utils.objectToArrayOfObjects(preflightData, 'name', 'value', true) }; - return this.sitesProvider.getCurrentSite().write('mod_quiz_view_attempt_summary', params); + return this.logHelper.log('mod_quiz_view_attempt_summary', params, AddonModQuizProvider.COMPONENT, quizId, siteId); } /** * Report a quiz as being viewed. * * @param {number} id Module ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logViewQuiz(id: number): Promise { + logViewQuiz(id: number, siteId?: string): Promise { const params = { quizid: id }; - return this.sitesProvider.getCurrentSite().write('mod_quiz_view_quiz', params); + return this.logHelper.log('mod_quiz_view_quiz', params, AddonModQuizProvider.COMPONENT, id, siteId); } /** diff --git a/src/addon/mod/resource/providers/resource.ts b/src/addon/mod/resource/providers/resource.ts index cd09eabc6..725cbc473 100644 --- a/src/addon/mod/resource/providers/resource.ts +++ b/src/addon/mod/resource/providers/resource.ts @@ -17,6 +17,7 @@ import { CoreLoggerProvider } from '@providers/logger'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreFilepoolProvider } from '@providers/filepool'; /** @@ -30,7 +31,8 @@ export class AddonModResourceProvider { protected logger; constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider, - private filepoolProvider: CoreFilepoolProvider, private utils: CoreUtilsProvider) { + private filepoolProvider: CoreFilepoolProvider, private utils: CoreUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModResourceProvider'); } @@ -148,13 +150,14 @@ export class AddonModResourceProvider { * Report the resource as being viewed. * * @param {number} id Module ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { resourceid: id }; - return this.sitesProvider.getCurrentSite().write('mod_resource_view_resource', params); + return this.logHelper.log('mod_resource_view_resource', params, AddonModResourceProvider.COMPONENT, id, siteId); } } diff --git a/src/addon/mod/scorm/providers/scorm.ts b/src/addon/mod/scorm/providers/scorm.ts index 201bdeaee..0ee62a7f7 100644 --- a/src/addon/mod/scorm/providers/scorm.ts +++ b/src/addon/mod/scorm/providers/scorm.ts @@ -26,6 +26,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; import { AddonModScormOfflineProvider } from './scorm-offline'; import { CoreSiteWSPreSets } from '@classes/site'; import { CoreConstants } from '@core/constants'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; /** * Result of getAttemptCount. @@ -113,7 +114,7 @@ export class AddonModScormProvider { private wsProvider: CoreWSProvider, private textUtils: CoreTextUtilsProvider, private utils: CoreUtilsProvider, private filepoolProvider: CoreFilepoolProvider, private scormOfflineProvider: AddonModScormOfflineProvider, private timeUtils: CoreTimeUtilsProvider, private syncProvider: CoreSyncProvider, - private eventsProvider: CoreEventsProvider) { + private eventsProvider: CoreEventsProvider, private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModScormProvider'); } @@ -1446,18 +1447,12 @@ export class AddonModScormProvider { * @return {Promise} Promise resolved when the WS call is successful. */ logView(id: number, siteId?: string): Promise { - return this.sitesProvider.getSite(siteId).then((site) => { - const params = { - scormid: id - }; + const params = { + scormid: id + }; - return site.write('mod_scorm_view_scorm', params).then((response) => { - if (!response || !response.status) { - return Promise.reject(null); - } - }); - }); - } + return this.logHelper.log('mod_scorm_view_scorm', params, AddonModScormProvider.COMPONENT, id, siteId); +} /** * Saves a SCORM tracking record. diff --git a/src/addon/mod/survey/providers/survey.ts b/src/addon/mod/survey/providers/survey.ts index a7ae0337d..75bd970d0 100644 --- a/src/addon/mod/survey/providers/survey.ts +++ b/src/addon/mod/survey/providers/survey.ts @@ -18,6 +18,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModSurveyOfflineProvider } from './offline'; /** @@ -32,7 +33,7 @@ export class AddonModSurveyProvider { constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider, private filepoolProvider: CoreFilepoolProvider, private utils: CoreUtilsProvider, - private surveyOffline: AddonModSurveyOfflineProvider) { + private surveyOffline: AddonModSurveyOfflineProvider, private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModSurveyProvider'); } @@ -197,14 +198,15 @@ export class AddonModSurveyProvider { * Report the survey as being viewed. * * @param {number} id Module ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { surveyid: id }; - return this.sitesProvider.getCurrentSite().write('mod_survey_view_survey', params); + return this.logHelper.log('mod_survey_view_survey', params, AddonModSurveyProvider.COMPONENT, id, siteId); } /** diff --git a/src/addon/mod/url/providers/url.ts b/src/addon/mod/url/providers/url.ts index c1642b6ca..e7e02b85a 100644 --- a/src/addon/mod/url/providers/url.ts +++ b/src/addon/mod/url/providers/url.ts @@ -18,6 +18,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreConstants } from '@core/constants'; /** @@ -31,7 +32,8 @@ export class AddonModUrlProvider { protected logger; constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider, - private utils: CoreUtilsProvider, private mimeUtils: CoreMimetypeUtilsProvider) { + private utils: CoreUtilsProvider, private mimeUtils: CoreMimetypeUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModUrlProvider'); } @@ -215,13 +217,14 @@ export class AddonModUrlProvider { * Report the url as being viewed. * * @param {number} id Module ID. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logView(id: number): Promise { + logView(id: number, siteId?: string): Promise { const params = { urlid: id }; - return this.sitesProvider.getCurrentSite().write('mod_url_view_url', params); + return this.logHelper.log('mod_url_view_url', params, AddonModUrlProvider.COMPONENT, id, siteId); } } diff --git a/src/addon/mod/wiki/components/index/index.ts b/src/addon/mod/wiki/components/index/index.ts index b154c7f4e..ee4362456 100644 --- a/src/addon/mod/wiki/components/index/index.ts +++ b/src/addon/mod/wiki/components/index/index.ts @@ -110,7 +110,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp // Ignore errors. }); } else { - this.wikiProvider.logPageView(this.pageId).catch(() => { + this.wikiProvider.logPageView(this.pageId, this.wikiId).catch(() => { // Ignore errors. }); } @@ -341,7 +341,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp this.currentPage = data.pageId; this.showLoadingAndFetch(true, false).then(() => { - this.wikiProvider.logPageView(this.currentPage).catch(() => { + this.wikiProvider.logPageView(this.currentPage, this.wikiId).catch(() => { // Ignore errors. }); }); diff --git a/src/addon/mod/wiki/providers/wiki.ts b/src/addon/mod/wiki/providers/wiki.ts index ce98a5dff..42dcd8b1c 100644 --- a/src/addon/mod/wiki/providers/wiki.ts +++ b/src/addon/mod/wiki/providers/wiki.ts @@ -20,6 +20,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModWikiOfflineProvider } from './wiki-offline'; import { CoreSiteWSPreSets } from '@classes/site'; @@ -70,7 +71,8 @@ export class AddonModWikiProvider { constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider, private filepoolProvider: CoreFilepoolProvider, private utils: CoreUtilsProvider, private translate: TranslateService, - private wikiOffline: AddonModWikiOfflineProvider, eventsProvider: CoreEventsProvider) { + private wikiOffline: AddonModWikiOfflineProvider, eventsProvider: CoreEventsProvider, + private logHelper: CoreCourseLogHelperProvider) { this.logger = logger.getInstance('AddonModWikiProvider'); // Clear subwiki lists cache on logout. @@ -651,18 +653,17 @@ export class AddonModWikiProvider { /** * Report a wiki page as being viewed. * - * @param {string} id Page ID. + * @param {number} id Page ID. + * @param {number} wikiId Wiki ID. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logPageView(id: number, siteId?: string): Promise { - return this.sitesProvider.getSite(siteId).then((site) => { - const params = { - pageid: id - }; + logPageView(id: number, wikiId: number, siteId?: string): Promise { + const params = { + pageid: id + }; - return site.write('mod_wiki_view_page', params); - }); + return this.logHelper.log('mod_wiki_view_page', params, AddonModWikiProvider.COMPONENT, wikiId, siteId); } /** @@ -673,13 +674,11 @@ export class AddonModWikiProvider { * @return {Promise} Promise resolved when the WS call is successful. */ logView(id: number, siteId?: string): Promise { - return this.sitesProvider.getSite(siteId).then((site) => { - const params = { - wikiid: id - }; + const params = { + wikiid: id + }; - return site.write('mod_wiki_view_wiki', params); - }); + return this.logHelper.log('mod_wiki_view_wiki', params, AddonModWikiProvider.COMPONENT, id, siteId); } /** diff --git a/src/addon/mod/workshop/pages/submission/submission.ts b/src/addon/mod/workshop/pages/submission/submission.ts index b058e1d05..e4cb2cd5f 100644 --- a/src/addon/mod/workshop/pages/submission/submission.ts +++ b/src/addon/mod/workshop/pages/submission/submission.ts @@ -130,7 +130,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { */ ngOnInit(): void { this.fetchSubmissionData().then(() => { - this.workshopProvider.logViewSubmission(this.submissionId).then(() => { + this.workshopProvider.logViewSubmission(this.submissionId, this.workshopId).then(() => { this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); }).catch(() => { // Ignore errors. diff --git a/src/addon/mod/workshop/providers/workshop.ts b/src/addon/mod/workshop/providers/workshop.ts index 8c22710ef..5d0e3165e 100644 --- a/src/addon/mod/workshop/providers/workshop.ts +++ b/src/addon/mod/workshop/providers/workshop.ts @@ -17,6 +17,7 @@ import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModWorkshopOfflineProvider } from './offline'; /** @@ -49,7 +50,8 @@ export class AddonModWorkshopProvider { private filepoolProvider: CoreFilepoolProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, - private workshopOffline: AddonModWorkshopOfflineProvider) {} + private workshopOffline: AddonModWorkshopOfflineProvider, + private logHelper: CoreCourseLogHelperProvider) {} /** * Get cache key for workshop data WS calls. @@ -1359,34 +1361,31 @@ export class AddonModWorkshopProvider { /** * Report the workshop as being viewed. * - * @param {string} id Workshop ID. + * @param {number} id Workshop ID. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ logView(id: number, siteId?: string): Promise { - return this.sitesProvider.getSite(siteId).then((site) => { - const params = { - workshopid: id - }; + const params = { + workshopid: id + }; - return site.write('mod_workshop_view_workshop', params); - }); + return this.logHelper.log('mod_workshop_view_workshop', params, AddonModWorkshopProvider.COMPONENT, id, siteId); } /** * Report the workshop submission as being viewed. * - * @param {string} id Submission ID. + * @param {number} id Submission ID. + * @param {number} workshopId Workshop ID. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logViewSubmission(id: number, siteId?: string): Promise { - return this.sitesProvider.getSite(siteId).then((site) => { - const params = { - submissionid: id - }; + logViewSubmission(id: number, workshopId: number, siteId?: string): Promise { + const params = { + submissionid: id + }; - return site.write('mod_workshop_view_submission', params); - }); + return this.logHelper.log('mod_workshop_view_submission', params, AddonModWorkshopProvider.COMPONENT, workshopId, siteId); } } diff --git a/src/core/course/course.module.ts b/src/core/course/course.module.ts index e6e01a772..5293eda63 100644 --- a/src/core/course/course.module.ts +++ b/src/core/course/course.module.ts @@ -18,6 +18,7 @@ import { CoreCronDelegate } from '@providers/cron'; import { CoreEventsProvider } from '@providers/events'; import { CoreCourseProvider } from './providers/course'; import { CoreCourseHelperProvider } from './providers/helper'; +import { CoreCourseLogHelperProvider } from './providers/log-helper'; import { CoreCourseFormatDelegate } from './providers/format-delegate'; import { CoreCourseModuleDelegate } from './providers/module-delegate'; import { CoreCourseOfflineProvider } from './providers/course-offline'; @@ -37,6 +38,7 @@ import { CoreCourseLogCronHandler } from './providers/log-cron-handler'; export const CORE_COURSE_PROVIDERS: any[] = [ CoreCourseProvider, CoreCourseHelperProvider, + CoreCourseLogHelperProvider, CoreCourseFormatDelegate, CoreCourseModuleDelegate, CoreCourseModulePrefetchDelegate, @@ -56,6 +58,7 @@ export const CORE_COURSE_PROVIDERS: any[] = [ providers: [ CoreCourseProvider, CoreCourseHelperProvider, + CoreCourseLogHelperProvider, CoreCourseFormatDelegate, CoreCourseModuleDelegate, CoreCourseModulePrefetchDelegate, diff --git a/src/core/course/providers/log-helper.ts b/src/core/course/providers/log-helper.ts new file mode 100644 index 000000000..0b5a01f50 --- /dev/null +++ b/src/core/course/providers/log-helper.ts @@ -0,0 +1,225 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable } from '@angular/core'; +import { CoreSitesProvider } from '@providers/sites'; +import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { CoreTimeUtilsProvider } from '@providers/utils/time'; +import { CoreUtilsProvider } from '@providers/utils/utils'; +import { CoreAppProvider } from '@providers/app'; + +/** + * Helper to manage logging to Moodle. + */ +@Injectable() +export class CoreCourseLogHelperProvider { + + // Variables for database. + static ACTIVITY_LOG_TABLE = 'course_activity_log'; + protected tablesSchema = [ + { + name: CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE, + columns: [ + { + name: 'component', + type: 'TEXT' + }, + { + name: 'componentid', + type: 'INTEGER' + }, + { + name: 'ws', + type: 'TEXT' + }, + { + name: 'data', + type: 'TEXT' + }, + { + name: 'time', + type: 'INTEGER' + } + ], + primaryKeys: ['component', 'componentid', 'ws', 'time'] + } + ]; + + constructor(protected sitesProvider: CoreSitesProvider, protected timeUtils: CoreTimeUtilsProvider, + protected textUtils: CoreTextUtilsProvider, protected utils: CoreUtilsProvider, + protected appProvider: CoreAppProvider) { + this.sitesProvider.createTablesFromSchema(this.tablesSchema); + } + + /** + * Delete the offline saved activity logs. + * + * @param {string} component Component name. + * @param {number} componentId Component ID. + * @param {string} siteId Site ID. If not defined, current site. + * @return {Promise} Promise resolved when deleted, rejected if failure. + */ + protected deleteLogs(component: string, componentId: number, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + + return site.getDb().deleteRecords(CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE, + {component: component, componentid: componentId}); + }); + } + + /** + * Delete the offline saved activity logs using call data. + * + * @param {string} ws WS name. + * @param {any} data Data to send to the WS. + * @param {string} siteId Site ID. If not defined, current site. + * @return {Promise} Promise resolved when deleted, rejected if failure. + */ + protected deleteWSLogs(ws: string, data: any, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + + return site.getDb().deleteRecords(CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE, + {ws: ws, data: JSON.stringify(data)}); + }); + } + + /** + * Get the offline saved activity logs. + * + * @param {string} component Component name. + * @param {number} componentId Component ID. + * @param {string} siteId Site ID. If not defined, current site. + * @return {Promise} Promise resolved with the list of offline logs. + */ + protected getLogs(component: string, componentId: number, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + + return site.getDb().getRecords(CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE, + {component: component, componentid: componentId}); + }); + } + + /** + * Perform log online. Data will be saved offline for syncing. + * + * @param {string} ws WS name. + * @param {any} data Data to send to the WS. + * @param {string} component Component name. + * @param {number} componentId Component ID. + * @param {string} siteId Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + log(ws: string, data: any, component: string, componentId: number, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + if (!this.appProvider.isOnline()) { + // App is offline, store the action. + return this.storeOffline(ws, data, component, componentId, site.getId()); + } + + return this.logOnline(ws, data, site.getId()).catch((error) => { + if (this.utils.isWebServiceError(error)) { + // The WebService has thrown an error, this means that responses cannot be submitted. + return Promise.reject(error); + } + + // Couldn't connect to server, store in offline. + return this.storeOffline(ws, data, component, componentId, site.getId()); + }); + }); + } + + /** + * Perform the log online. + * + * @param {string} ws WS name. + * @param {any} data Data to send to the WS. + * @param {string} siteId Site ID. If not defined, current site. + * @return {Promise} Promise resolved when log is successfully submitted. Rejected with object containing + * the error message (if any) and a boolean indicating if the error was returned by WS. + */ + protected logOnline(ws: string, data: any, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + return site.write(ws, data).then((response) => { + if (!response.status) { + return Promise.reject(this.utils.createFakeWSError('')); + } + + // Remove all the logs performed. + // TODO: Remove this lines when time is accepted in logs. + return this.deleteWSLogs(ws, data); + }).catch((error) => { + return Promise.reject(this.utils.createFakeWSError(error)); + }); + }); + } + + /** + * Save activity log for offline sync. + * + * @param {string} ws WS name. + * @param {any} data Data to send to the WS. + * @param {string} component Component name. + * @param {number} componentId Component ID. + * @param {string} siteId Site ID. If not defined, current site. + * @return {Promise} Resolved with the inserted rowId field. + */ + protected storeOffline(ws: string, data: any, component: string, componentId: number, siteId?: string): + Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + const log = { + ws: ws, + data: JSON.stringify(data), + component: component, + componentid: componentId, + time: this.timeUtils.timestamp() + }; + + return site.getDb().insertRecord(CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE, log); + }); + } + + /** + * Sync the offline saved activity logs. + * + * @param {string} component Component name. + * @param {number} componentId Component ID. + * @param {string} siteId Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + syncIfNeeded(component: string, componentId: number, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + const siteId = site.getId(); + + return this.getLogs(component, componentId, siteId).then((logs) => { + const done = []; + + // TODO: When time is accepted on log, do not discard same logs. + return Promise.all(logs.map((log) => { + // Just perform unique syncs. + const found = done.find((doneLog) => { + return log.ws == doneLog.ws && log.data == doneLog.data; + }); + + if (found) { + return Promise.resolve(); + } + + done.push(log); + + return this.logOnline(log.ws, this.textUtils.parseJSON(log.data), siteId); + })); + }); + }); + } +} From 91435072844637ba7371ddc5ea12f937a91859e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 7 Feb 2019 10:12:54 +0100 Subject: [PATCH 2/2] MOBILE-1979 sync: Sync activity logs --- src/addon/mod/assign/providers/assign-sync.ts | 7 +- src/addon/mod/choice/providers/sync.ts | 14 ++- src/addon/mod/data/providers/sync.ts | 14 ++- src/addon/mod/feedback/providers/sync.ts | 15 ++- .../mod/forum/pages/discussion/discussion.ts | 2 +- src/addon/mod/forum/providers/sync.ts | 15 ++- src/addon/mod/glossary/providers/sync.ts | 15 ++- src/addon/mod/lesson/providers/lesson-sync.ts | 11 +- src/addon/mod/quiz/pages/player/player.ts | 3 +- src/addon/mod/quiz/providers/quiz-sync.ts | 14 ++- src/addon/mod/quiz/providers/quiz.ts | 30 ++--- src/addon/mod/scorm/providers/scorm-sync.ts | 11 +- src/addon/mod/survey/providers/sync.ts | 14 ++- src/addon/mod/wiki/components/index/index.ts | 4 +- src/addon/mod/wiki/providers/wiki-sync.ts | 13 +- src/addon/mod/workshop/providers/sync.ts | 7 +- src/core/course/providers/log-helper.ts | 118 ++++++++++++++---- .../course/providers/sync-cron-handler.ts | 12 +- 18 files changed, 228 insertions(+), 91 deletions(-) diff --git a/src/addon/mod/assign/providers/assign-sync.ts b/src/addon/mod/assign/providers/assign-sync.ts index 96627a1cc..6283bd878 100644 --- a/src/addon/mod/assign/providers/assign-sync.ts +++ b/src/addon/mod/assign/providers/assign-sync.ts @@ -23,6 +23,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreGradesHelperProvider } from '@core/grades/providers/helper'; import { CoreSyncBaseProvider } from '@classes/base-sync'; import { AddonModAssignProvider } from './assign'; @@ -61,7 +62,8 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider { private courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider, private assignProvider: AddonModAssignProvider, private assignOfflineProvider: AddonModAssignOfflineProvider, private utils: CoreUtilsProvider, private submissionDelegate: AddonModAssignSubmissionDelegate, - private gradesHelper: CoreGradesHelperProvider, timeUtils: CoreTimeUtilsProvider) { + private gradesHelper: CoreGradesHelperProvider, timeUtils: CoreTimeUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModAssignSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -202,6 +204,9 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider { return []; })); + // Sync offline logs. + promises.push(this.logHelper.syncIfNeeded(AddonModAssignProvider.COMPONENT, assignId, siteId)); + syncPromise = Promise.all(promises).then((results) => { const submissions = results[0], grades = results[1]; diff --git a/src/addon/mod/choice/providers/sync.ts b/src/addon/mod/choice/providers/sync.ts index 01635c5d4..b260f1ba7 100644 --- a/src/addon/mod/choice/providers/sync.ts +++ b/src/addon/mod/choice/providers/sync.ts @@ -25,6 +25,7 @@ import { AddonModChoiceProvider } from './choice'; import { CoreEventsProvider } from '@providers/events'; import { TranslateService } from '@ngx-translate/core'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreSyncProvider } from '@providers/sync'; /** @@ -40,7 +41,8 @@ export class AddonModChoiceSyncProvider extends CoreSyncBaseProvider { protected appProvider: CoreAppProvider, private choiceOffline: AddonModChoiceOfflineProvider, private eventsProvider: CoreEventsProvider, private choiceProvider: AddonModChoiceProvider, translate: TranslateService, private utils: CoreUtilsProvider, protected textUtils: CoreTextUtilsProvider, - courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider) { + courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModChoiceSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -137,10 +139,12 @@ export class AddonModChoiceSyncProvider extends CoreSyncBaseProvider { updated: false }; - // Get offline responses to be sent. - const syncPromise = this.choiceOffline.getResponse(choiceId, siteId, userId).catch(() => { - // No offline data found, return empty object. - return {}; + // Sync offline logs. + const syncPromise = this.logHelper.syncIfNeeded(AddonModChoiceProvider.COMPONENT, choiceId, siteId).finally(() => { + return this.choiceOffline.getResponse(choiceId, siteId, userId).catch(() => { + // No offline data found, return empty object. + return {}; + }); }).then((data) => { if (!data.choiceid) { // Nothing to sync. diff --git a/src/addon/mod/data/providers/sync.ts b/src/addon/mod/data/providers/sync.ts index 6e2a90128..22485fa93 100644 --- a/src/addon/mod/data/providers/sync.ts +++ b/src/addon/mod/data/providers/sync.ts @@ -26,6 +26,7 @@ import { AddonModDataHelperProvider } from './helper'; import { CoreEventsProvider } from '@providers/events'; import { TranslateService } from '@ngx-translate/core'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreSyncProvider } from '@providers/sync'; /** @@ -42,7 +43,7 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider { private eventsProvider: CoreEventsProvider, private dataProvider: AddonModDataProvider, protected translate: TranslateService, private utils: CoreUtilsProvider, courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, protected textUtils: CoreTextUtilsProvider, timeUtils: CoreTimeUtilsProvider, - private dataHelper: AddonModDataHelperProvider) { + private dataHelper: AddonModDataHelperProvider, private logHelper: CoreCourseLogHelperProvider) { super('AddonModDataSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -149,10 +150,13 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider { updated: false }; - // Get answers to be sent. - const syncPromise = this.dataOffline.getDatabaseEntries(dataId, siteId).catch(() => { - // No offline data found, return empty object. - return []; + // Sync offline logs. + const syncPromise = this.logHelper.syncIfNeeded(AddonModDataProvider.COMPONENT, dataId, siteId).finally(() => { + // Get answers to be sent. + return this.dataOffline.getDatabaseEntries(dataId, siteId).catch(() => { + // No offline data found, return empty object. + return []; + }); }).then((offlineActions) => { if (!offlineActions.length) { // Nothing to sync. diff --git a/src/addon/mod/feedback/providers/sync.ts b/src/addon/mod/feedback/providers/sync.ts index 4aca43570..e9154d724 100644 --- a/src/addon/mod/feedback/providers/sync.ts +++ b/src/addon/mod/feedback/providers/sync.ts @@ -26,6 +26,7 @@ import { CoreEventsProvider } from '@providers/events'; import { TranslateService } from '@ngx-translate/core'; import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreSyncProvider } from '@providers/sync'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; /** * Service to sync feedbacks. @@ -40,7 +41,8 @@ export class AddonModFeedbackSyncProvider extends CoreSyncBaseProvider { protected appProvider: CoreAppProvider, private feedbackOffline: AddonModFeedbackOfflineProvider, private eventsProvider: CoreEventsProvider, private feedbackProvider: AddonModFeedbackProvider, protected translate: TranslateService, private utils: CoreUtilsProvider, protected textUtils: CoreTextUtilsProvider, - courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider) { + courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModFeedbackSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -144,10 +146,13 @@ export class AddonModFeedbackSyncProvider extends CoreSyncBaseProvider { this.logger.debug(`Try to sync feedback '${feedbackId}' in site ${siteId}'`); - // Get offline responses to be sent. - const syncPromise = this.feedbackOffline.getFeedbackResponses(feedbackId, siteId).catch(() => { - // No offline data found, return empty array. - return []; + // Sync offline logs. + const syncPromise = this.logHelper.syncIfNeeded(AddonModFeedbackProvider.COMPONENT, feedbackId, siteId).finally(() => { + // Get offline responses to be sent. + return this.feedbackOffline.getFeedbackResponses(feedbackId, siteId).catch(() => { + // No offline data found, return empty array. + return []; + }); }).then((responses) => { if (!responses.length) { // Nothing to sync. diff --git a/src/addon/mod/forum/pages/discussion/discussion.ts b/src/addon/mod/forum/pages/discussion/discussion.ts index 7879e8470..ad3da6f2f 100644 --- a/src/addon/mod/forum/pages/discussion/discussion.ts +++ b/src/addon/mod/forum/pages/discussion/discussion.ts @@ -299,7 +299,7 @@ export class AddonModForumDiscussionPage implements OnDestroy { if (forceMarkAsRead || (hasUnreadPosts && this.trackPosts)) { // // Add log in Moodle and mark unread posts as readed. - this.forumProvider.logDiscussionView(this.discussionId, this.forumId).catch(() => { + this.forumProvider.logDiscussionView(this.discussionId, this.forumId || -1).catch(() => { // Ignore errors. }).finally(() => { // Trigger mark read posts. diff --git a/src/addon/mod/forum/providers/sync.ts b/src/addon/mod/forum/providers/sync.ts index 76fc0c4ae..ddb33ab61 100644 --- a/src/addon/mod/forum/providers/sync.ts +++ b/src/addon/mod/forum/providers/sync.ts @@ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreSyncBaseProvider } from '@classes/base-sync'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; import { CoreAppProvider } from '@providers/app'; import { CoreLoggerProvider } from '@providers/logger'; @@ -53,7 +54,8 @@ export class AddonModForumSyncProvider extends CoreSyncBaseProvider { private utils: CoreUtilsProvider, private forumProvider: AddonModForumProvider, private forumHelper: AddonModForumHelperProvider, - private forumOffline: AddonModForumOfflineProvider) { + private forumOffline: AddonModForumOfflineProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModForumSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -189,10 +191,13 @@ export class AddonModForumSyncProvider extends CoreSyncBaseProvider { updated: false }; - // Get offline responses to be sent. - const syncPromise = this.forumOffline.getNewDiscussions(forumId, siteId, userId).catch(() => { - // No offline data found, return empty object. - return []; + // Sync offline logs. + const syncPromise = this.logHelper.syncIfNeeded(AddonModForumProvider.COMPONENT, forumId, siteId).finally(() => { + // Get offline responses to be sent. + return this.forumOffline.getNewDiscussions(forumId, siteId, userId).catch(() => { + // No offline data found, return empty object. + return []; + }); }).then((discussions) => { if (!discussions.length) { // Nothing to sync. diff --git a/src/addon/mod/glossary/providers/sync.ts b/src/addon/mod/glossary/providers/sync.ts index ab748ab9d..af76e67d8 100644 --- a/src/addon/mod/glossary/providers/sync.ts +++ b/src/addon/mod/glossary/providers/sync.ts @@ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreSyncBaseProvider } from '@classes/base-sync'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; import { CoreAppProvider } from '@providers/app'; import { CoreLoggerProvider } from '@providers/logger'; @@ -52,7 +53,8 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider { private utils: CoreUtilsProvider, private glossaryProvider: AddonModGlossaryProvider, private glossaryHelper: AddonModGlossaryHelperProvider, - private glossaryOffline: AddonModGlossaryOfflineProvider) { + private glossaryOffline: AddonModGlossaryOfflineProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModGlossarySyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -160,10 +162,13 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider { updated: false }; - // Get offline responses to be sent. - const syncPromise = this.glossaryOffline.getGlossaryNewEntries(glossaryId, siteId, userId).catch(() => { - // No offline data found, return empty object. - return []; + // Sync offline logs. + const syncPromise = this.logHelper.syncIfNeeded(AddonModGlossaryProvider.COMPONENT, glossaryId, siteId).finally(() => { + // Get offline responses to be sent. + return this.glossaryOffline.getGlossaryNewEntries(glossaryId, siteId, userId).catch(() => { + // No offline data found, return empty object. + return []; + }); }).then((entries) => { if (!entries.length) { // Nothing to sync. diff --git a/src/addon/mod/lesson/providers/lesson-sync.ts b/src/addon/mod/lesson/providers/lesson-sync.ts index de7e2ef7c..69ce789f4 100644 --- a/src/addon/mod/lesson/providers/lesson-sync.ts +++ b/src/addon/mod/lesson/providers/lesson-sync.ts @@ -24,6 +24,7 @@ import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreSyncBaseProvider } from '@classes/base-sync'; import { AddonModLessonProvider } from './lesson'; import { AddonModLessonOfflineProvider } from './lesson-offline'; @@ -86,7 +87,8 @@ export class AddonModLessonSyncProvider extends CoreSyncBaseProvider { courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider, private lessonProvider: AddonModLessonProvider, private lessonOfflineProvider: AddonModLessonOfflineProvider, private prefetchHandler: AddonModLessonPrefetchHandler, timeUtils: CoreTimeUtilsProvider, - private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider) { + private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModLessonSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -263,8 +265,11 @@ export class AddonModLessonSyncProvider extends CoreSyncBaseProvider { this.logger.debug('Try to sync lesson ' + lessonId + ' in site ' + siteId); - // Try to synchronize the attempts first. - syncPromise = this.lessonOfflineProvider.getLessonAttempts(lessonId, siteId).then((attempts) => { + // Sync offline logs. + syncPromise = this.logHelper.syncIfNeeded(AddonModLessonProvider.COMPONENT, lessonId, siteId).finally(() => { + // Try to synchronize the attempts first. + return this.lessonOfflineProvider.getLessonAttempts(lessonId, siteId); + }).then((attempts) => { if (!attempts.length) { return; } else if (!this.appProvider.isOnline()) { diff --git a/src/addon/mod/quiz/pages/player/player.ts b/src/addon/mod/quiz/pages/player/player.ts index feb27bb7f..669445fbc 100644 --- a/src/addon/mod/quiz/pages/player/player.ts +++ b/src/addon/mod/quiz/pages/player/player.ts @@ -428,8 +428,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy { }); // Mark the page as viewed. We'll ignore errors in this call. - this.quizProvider.logViewAttempt(this.attempt.id, this.quizId, page, this.preflightData, this.offline) - .catch((error) => { + this.quizProvider.logViewAttempt(this.attempt.id, page, this.preflightData, this.offline).catch((error) => { // Ignore errors. }); diff --git a/src/addon/mod/quiz/providers/quiz-sync.ts b/src/addon/mod/quiz/providers/quiz-sync.ts index 4d00bf7fa..a7ebbdbec 100644 --- a/src/addon/mod/quiz/providers/quiz-sync.ts +++ b/src/addon/mod/quiz/providers/quiz-sync.ts @@ -22,6 +22,7 @@ import { CoreSyncProvider } from '@providers/sync'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreQuestionProvider } from '@core/question/providers/question'; import { CoreQuestionDelegate } from '@core/question/providers/delegate'; import { CoreSyncBaseProvider } from '@classes/base-sync'; @@ -61,7 +62,7 @@ export class AddonModQuizSyncProvider extends CoreSyncBaseProvider { courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider, timeUtils: CoreTimeUtilsProvider, private quizProvider: AddonModQuizProvider, private quizOfflineProvider: AddonModQuizOfflineProvider, private prefetchHandler: AddonModQuizPrefetchHandler, private questionProvider: CoreQuestionProvider, - private questionDelegate: CoreQuestionDelegate) { + private questionDelegate: CoreQuestionDelegate, private logHelper: CoreCourseLogHelperProvider) { super('AddonModQuizSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -259,8 +260,11 @@ export class AddonModQuizSyncProvider extends CoreSyncBaseProvider { this.logger.debug('Try to sync quiz ' + quiz.id + ' in site ' + siteId); - // Get all the offline attempts for the quiz. - syncPromise = this.quizOfflineProvider.getQuizAttempts(quiz.id, siteId).then((attempts) => { + // Sync offline logs. + syncPromise = this.logHelper.syncIfNeeded(AddonModQuizProvider.COMPONENT, quiz.id, siteId).finally(() => { + // Get all the offline attempts for the quiz. + return this.quizOfflineProvider.getQuizAttempts(quiz.id, siteId); + }).then((attempts) => { // Should return 0 or 1 attempt. if (!attempts.length) { return this.finishSync(siteId, quiz, courseId, warnings); @@ -341,8 +345,8 @@ export class AddonModQuizSyncProvider extends CoreSyncBaseProvider { // Answers sent, now set the current page if the attempt isn't finished. if (!finish) { - return this.quizProvider.logViewAttempt(onlineAttempt.id, quiz.id, offlineAttempt.currentpage, - preflightData, false).catch(() => { + return this.quizProvider.logViewAttempt(onlineAttempt.id, offlineAttempt.currentpage, preflightData, + false).catch(() => { // Ignore errors. }); } diff --git a/src/addon/mod/quiz/providers/quiz.ts b/src/addon/mod/quiz/providers/quiz.ts index 1777bafdf..551675b22 100644 --- a/src/addon/mod/quiz/providers/quiz.ts +++ b/src/addon/mod/quiz/providers/quiz.ts @@ -1518,31 +1518,31 @@ export class AddonModQuizProvider { } /** - * Report an attempt as being viewed. + * Report an attempt as being viewed. It did not store logs offline because order of the log is important. * * @param {number} attemptId Attempt ID. * @param {number} [page=0] Page number. * @param {any} [preflightData] Preflight required data (like password). * @param {boolean} [offline] Whether attempt is offline. - * @param {number} quizId Quiz ID. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the WS call is successful. */ - logViewAttempt(attemptId: number, quizId: number, page: number = 0, preflightData: any = {}, offline?: boolean, - siteId?: string): Promise { - const params = { - attemptid: attemptId, - page: page, - preflightdata: this.utils.objectToArrayOfObjects(preflightData, 'name', 'value', true) - }, - promises = []; + logViewAttempt(attemptId: number, page: number = 0, preflightData: any = {}, offline?: boolean, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + const params = { + attemptid: attemptId, + page: page, + preflightdata: this.utils.objectToArrayOfObjects(preflightData, 'name', 'value', true) + }, + promises = []; - promises.push(this.logHelper.log('mod_quiz_view_attempt', params, AddonModQuizProvider.COMPONENT, quizId, siteId)); - if (offline) { - promises.push(this.quizOfflineProvider.setAttemptCurrentPage(attemptId, page)); - } + promises.push(site.write('mod_quiz_view_attempt', params)); + if (offline) { + promises.push(this.quizOfflineProvider.setAttemptCurrentPage(attemptId, page, site.getId())); + } - return Promise.all(promises); + return Promise.all(promises); + }); } /** diff --git a/src/addon/mod/scorm/providers/scorm-sync.ts b/src/addon/mod/scorm/providers/scorm-sync.ts index e9b5014fb..1bf3ea4cb 100644 --- a/src/addon/mod/scorm/providers/scorm-sync.ts +++ b/src/addon/mod/scorm/providers/scorm-sync.ts @@ -23,6 +23,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; import { CoreSyncBaseProvider } from '@classes/base-sync'; import { AddonModScormProvider, AddonModScormAttemptCountResult } from './scorm'; @@ -67,7 +68,8 @@ export class AddonModScormSyncProvider extends CoreSyncBaseProvider { private eventsProvider: CoreEventsProvider, timeUtils: CoreTimeUtilsProvider, private scormProvider: AddonModScormProvider, private scormOfflineProvider: AddonModScormOfflineProvider, private prefetchHandler: AddonModScormPrefetchHandler, private utils: CoreUtilsProvider, - private prefetchDelegate: CoreCourseModulePrefetchDelegate, private courseProvider: CoreCourseProvider) { + private prefetchDelegate: CoreCourseModulePrefetchDelegate, private courseProvider: CoreCourseProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModScormSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -646,8 +648,11 @@ export class AddonModScormSyncProvider extends CoreSyncBaseProvider { this.logger.debug('Try to sync SCORM ' + scorm.id + ' in site ' + siteId); - // Get attempts data. We ignore cache for online attempts, so this call will fail if offline or server down. - syncPromise = this.scormProvider.getAttemptCount(scorm.id, false, true, siteId).then((attemptsData) => { + // Sync offline logs. + syncPromise = this.logHelper.syncIfNeeded(AddonModScormProvider.COMPONENT, scorm.id, siteId).finally(() => { + // Get attempts data. We ignore cache for online attempts, so this call will fail if offline or server down. + return this.scormProvider.getAttemptCount(scorm.id, false, true, siteId); + }).then((attemptsData) => { if (!attemptsData.offline || !attemptsData.offline.length) { // Nothing to sync. return this.finishSync(siteId, scorm, warnings, lastOnline, lastOnlineWasFinished); diff --git a/src/addon/mod/survey/providers/sync.ts b/src/addon/mod/survey/providers/sync.ts index 084e05eec..580c24da4 100644 --- a/src/addon/mod/survey/providers/sync.ts +++ b/src/addon/mod/survey/providers/sync.ts @@ -25,6 +25,7 @@ import { AddonModSurveyProvider } from './survey'; import { CoreEventsProvider } from '@providers/events'; import { TranslateService } from '@ngx-translate/core'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreSyncProvider } from '@providers/sync'; /** @@ -40,7 +41,7 @@ export class AddonModSurveySyncProvider extends CoreSyncBaseProvider { syncProvider: CoreSyncProvider, textUtils: CoreTextUtilsProvider, translate: TranslateService, courseProvider: CoreCourseProvider, private surveyOffline: AddonModSurveyOfflineProvider, private eventsProvider: CoreEventsProvider, private surveyProvider: AddonModSurveyProvider, - private utils: CoreUtilsProvider, timeUtils: CoreTimeUtilsProvider) { + private utils: CoreUtilsProvider, timeUtils: CoreTimeUtilsProvider, private logHelper: CoreCourseLogHelperProvider) { super('AddonModSurveySyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -141,10 +142,13 @@ export class AddonModSurveySyncProvider extends CoreSyncBaseProvider { answersSent: false }; - // Get answers to be sent. - const syncPromise = this.surveyOffline.getSurveyData(surveyId, siteId, userId).catch(() => { - // No offline data found, return empty object. - return {}; + // Sync offline logs. + const syncPromise = this.logHelper.syncIfNeeded(AddonModSurveyProvider.COMPONENT, surveyId, siteId).finally(() => { + // Get answers to be sent. + return this.surveyOffline.getSurveyData(surveyId, siteId, userId).catch(() => { + // No offline data found, return empty object. + return {}; + }); }).then((data) => { if (!data.answers || !data.answers.length) { // Nothing to sync. diff --git a/src/addon/mod/wiki/components/index/index.ts b/src/addon/mod/wiki/components/index/index.ts index ee4362456..25bc9af76 100644 --- a/src/addon/mod/wiki/components/index/index.ts +++ b/src/addon/mod/wiki/components/index/index.ts @@ -110,7 +110,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp // Ignore errors. }); } else { - this.wikiProvider.logPageView(this.pageId, this.wikiId).catch(() => { + this.wikiProvider.logPageView(this.pageId, this.wiki.id).catch(() => { // Ignore errors. }); } @@ -341,7 +341,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp this.currentPage = data.pageId; this.showLoadingAndFetch(true, false).then(() => { - this.wikiProvider.logPageView(this.currentPage, this.wikiId).catch(() => { + this.wikiProvider.logPageView(this.currentPage, this.wiki.id).catch(() => { // Ignore errors. }); }); diff --git a/src/addon/mod/wiki/providers/wiki-sync.ts b/src/addon/mod/wiki/providers/wiki-sync.ts index 5a2bdc441..cfd37e1a0 100644 --- a/src/addon/mod/wiki/providers/wiki-sync.ts +++ b/src/addon/mod/wiki/providers/wiki-sync.ts @@ -24,6 +24,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreSyncBaseProvider } from '@classes/base-sync'; import { AddonModWikiProvider } from './wiki'; import { AddonModWikiOfflineProvider } from './wiki-offline'; @@ -104,7 +105,8 @@ export class AddonModWikiSyncProvider extends CoreSyncBaseProvider { syncProvider: CoreSyncProvider, textUtils: CoreTextUtilsProvider, translate: TranslateService, courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider, private wikiProvider: AddonModWikiProvider, private wikiOfflineProvider: AddonModWikiOfflineProvider, - private utils: CoreUtilsProvider, private groupsProvider: CoreGroupsProvider, timeUtils: CoreTimeUtilsProvider) { + private utils: CoreUtilsProvider, private groupsProvider: CoreGroupsProvider, timeUtils: CoreTimeUtilsProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModWikiSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -336,8 +338,13 @@ export class AddonModWikiSyncProvider extends CoreSyncBaseProvider { syncWiki(wikiId: number, courseId?: number, cmId?: number, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); - // Sync is done at subwiki level, get all the subwikis. - return this.wikiProvider.getSubwikis(wikiId).then((subwikis) => { + // Sync offline logs. + return this.logHelper.syncIfNeeded(AddonModWikiProvider.COMPONENT, wikiId, siteId).catch(() => { + // Ignore errors. + }).then(() => { + // Sync is done at subwiki level, get all the subwikis. + return this.wikiProvider.getSubwikis(wikiId); + }).then((subwikis) => { const promises = [], result: AddonModWikiSyncWikiResult = { warnings: [], diff --git a/src/addon/mod/workshop/providers/sync.ts b/src/addon/mod/workshop/providers/sync.ts index 9b1fc1c02..74f7619cf 100644 --- a/src/addon/mod/workshop/providers/sync.ts +++ b/src/addon/mod/workshop/providers/sync.ts @@ -24,6 +24,7 @@ import { CoreSyncProvider } from '@providers/sync'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreUtilsProvider } from '@providers/utils/utils'; +import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { AddonModWorkshopProvider } from './workshop'; import { AddonModWorkshopHelperProvider } from './helper'; import { AddonModWorkshopOfflineProvider } from './offline'; @@ -51,7 +52,8 @@ export class AddonModWorkshopSyncProvider extends CoreSyncBaseProvider { private utils: CoreUtilsProvider, private workshopProvider: AddonModWorkshopProvider, private workshopHelper: AddonModWorkshopHelperProvider, - private workshopOffline: AddonModWorkshopOfflineProvider) { + private workshopOffline: AddonModWorkshopOfflineProvider, + private logHelper: CoreCourseLogHelperProvider) { super('AddonModWorkshopSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils); @@ -172,6 +174,9 @@ export class AddonModWorkshopSyncProvider extends CoreSyncBaseProvider { return []; })); + // Sync offline logs. + syncPromises.push(this.logHelper.syncIfNeeded(AddonModWorkshopProvider.COMPONENT, workshopId, siteId)); + const result = { warnings: [], updated: false diff --git a/src/core/course/providers/log-helper.ts b/src/core/course/providers/log-helper.ts index 0b5a01f50..24bde0ed5 100644 --- a/src/core/course/providers/log-helper.ts +++ b/src/core/course/providers/log-helper.ts @@ -67,7 +67,7 @@ export class CoreCourseLogHelperProvider { * * @param {string} component Component name. * @param {number} componentId Component ID. - * @param {string} siteId Site ID. If not defined, current site. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when deleted, rejected if failure. */ protected deleteLogs(component: string, componentId: number, siteId?: string): Promise { @@ -78,19 +78,49 @@ export class CoreCourseLogHelperProvider { }); } + /** + * Delete a WS based log. + * + * @param {string} component Component name. + * @param {number} componentId Component ID. + * @param {string} ws WS name. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when deleted, rejected if failure. + */ + protected deleteWSLogsByComponent(component: string, componentId: number, ws: string, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + + return site.getDb().deleteRecords(CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE, + {component: component, componentid: componentId, ws: ws}); + }); + } + /** * Delete the offline saved activity logs using call data. * * @param {string} ws WS name. * @param {any} data Data to send to the WS. - * @param {string} siteId Site ID. If not defined, current site. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when deleted, rejected if failure. */ protected deleteWSLogs(ws: string, data: any, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { return site.getDb().deleteRecords(CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE, - {ws: ws, data: JSON.stringify(data)}); + {ws: ws, data: this.utils.sortAndStringify(data)}); + }); + } + + /** + * Get all the offline saved activity logs. + * + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved with the list of offline logs. + */ + protected getAllLogs(siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + + return site.getDb().getAllRecords(CoreCourseLogHelperProvider.ACTIVITY_LOG_TABLE); }); } @@ -99,7 +129,7 @@ export class CoreCourseLogHelperProvider { * * @param {string} component Component name. * @param {number} componentId Component ID. - * @param {string} siteId Site ID. If not defined, current site. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved with the list of offline logs. */ protected getLogs(component: string, componentId: number, siteId?: string): Promise { @@ -117,7 +147,7 @@ export class CoreCourseLogHelperProvider { * @param {any} data Data to send to the WS. * @param {string} component Component name. * @param {number} componentId Component ID. - * @param {string} siteId Site ID. If not defined, current site. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when done. */ log(ws: string, data: any, component: string, componentId: number, siteId?: string): Promise { @@ -142,10 +172,10 @@ export class CoreCourseLogHelperProvider { /** * Perform the log online. * - * @param {string} ws WS name. - * @param {any} data Data to send to the WS. - * @param {string} siteId Site ID. If not defined, current site. - * @return {Promise} Promise resolved when log is successfully submitted. Rejected with object containing + * @param {string} ws WS name. + * @param {any} data Data to send to the WS. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when log is successfully submitted. Rejected with object containing * the error message (if any) and a boolean indicating if the error was returned by WS. */ protected logOnline(ws: string, data: any, siteId?: string): Promise { @@ -158,8 +188,6 @@ export class CoreCourseLogHelperProvider { // Remove all the logs performed. // TODO: Remove this lines when time is accepted in logs. return this.deleteWSLogs(ws, data); - }).catch((error) => { - return Promise.reject(this.utils.createFakeWSError(error)); }); }); } @@ -171,7 +199,7 @@ export class CoreCourseLogHelperProvider { * @param {any} data Data to send to the WS. * @param {string} component Component name. * @param {number} componentId Component ID. - * @param {string} siteId Site ID. If not defined, current site. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Resolved with the inserted rowId field. */ protected storeOffline(ws: string, data: any, component: string, componentId: number, siteId?: string): @@ -179,7 +207,7 @@ export class CoreCourseLogHelperProvider { return this.sitesProvider.getSite(siteId).then((site) => { const log = { ws: ws, - data: JSON.stringify(data), + data: this.utils.sortAndStringify(data), component: component, componentid: componentId, time: this.timeUtils.timestamp() @@ -189,12 +217,43 @@ export class CoreCourseLogHelperProvider { }); } + /** + * Sync all the offline saved activity logs. + * + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + syncAll(siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + const siteId = site.getId(); + + return this.getAllLogs(siteId).then((logs) => { + const unique = []; + + // TODO: When time is accepted on log, do not discard same logs. + logs.forEach((log) => { + // Just perform unique syncs. + const found = unique.find((doneLog) => { + return log.component == doneLog.component && log.componentid == doneLog.componentid && + log.ws == doneLog.ws && log.data == doneLog.data; + }); + + if (!found) { + unique.push(log); + } + }); + + return this.syncLogs(unique, siteId); + }); + }); + } + /** * Sync the offline saved activity logs. * * @param {string} component Component name. * @param {number} componentId Component ID. - * @param {string} siteId Site ID. If not defined, current site. + * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when done. */ syncIfNeeded(component: string, componentId: number, siteId?: string): Promise { @@ -202,24 +261,37 @@ export class CoreCourseLogHelperProvider { const siteId = site.getId(); return this.getLogs(component, componentId, siteId).then((logs) => { - const done = []; + const unique = []; // TODO: When time is accepted on log, do not discard same logs. - return Promise.all(logs.map((log) => { + logs.forEach((log) => { // Just perform unique syncs. - const found = done.find((doneLog) => { + const found = unique.find((doneLog) => { return log.ws == doneLog.ws && log.data == doneLog.data; }); - if (found) { - return Promise.resolve(); + if (!found) { + unique.push(log); } + }); - done.push(log); - - return this.logOnline(log.ws, this.textUtils.parseJSON(log.data), siteId); - })); + return this.syncLogs(unique, siteId); }); }); } + + /** + * Sync and delete given logs. + * + * @param {any[]} logs Array of log objects. + * @param {string} siteId Site Id. + * @return {Promise} Promise resolved when done. + */ + protected syncLogs(logs: any[], siteId: string): Promise { + return Promise.all(logs.map((log) => { + return this.logOnline(log.ws, this.textUtils.parseJSON(log.data), siteId).then(() => { + return this.deleteWSLogsByComponent(log.component, log.componentid, log.ws); + }); + })); + } } diff --git a/src/core/course/providers/sync-cron-handler.ts b/src/core/course/providers/sync-cron-handler.ts index f7bd6cdba..4e85dd398 100644 --- a/src/core/course/providers/sync-cron-handler.ts +++ b/src/core/course/providers/sync-cron-handler.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreCronHandler } from '@providers/cron'; import { CoreCourseSyncProvider } from './sync'; +import { CoreCourseLogHelperProvider } from './log-helper'; /** * Synchronization cron handler. @@ -23,7 +24,7 @@ import { CoreCourseSyncProvider } from './sync'; export class CoreCourseSyncCronHandler implements CoreCronHandler { name = 'CoreCourseSyncCronHandler'; - constructor(private courseSync: CoreCourseSyncProvider) {} + constructor(private courseSync: CoreCourseSyncProvider, private logHelper: CoreCourseLogHelperProvider) {} /** * Execute the process. @@ -33,7 +34,14 @@ export class CoreCourseSyncCronHandler implements CoreCronHandler { * @return {Promise} Promise resolved when done, rejected if failure. */ execute(siteId?: string): Promise { - return this.courseSync.syncAllCourses(siteId); + const promises = []; + // Sync activity logs even if the activity does not have sync handler. + // This will sync all the activity logs even if there's nothing else to sync and also recources. + promises.push(this.logHelper.syncAll(siteId)); + + promises.push(this.courseSync.syncAllCourses(siteId)); + + return Promise.all(promises); } /**