commit
						7c09d55ea8
					
				| @ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; | ||||
| import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Service to handle blog entries. | ||||
| @ -27,7 +28,8 @@ export class AddonBlogProvider { | ||||
|     protected ROOT_CACHE_KEY = 'addonBlog:'; | ||||
|     protected logger; | ||||
| 
 | ||||
|     constructor(logger: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider, protected utils: CoreUtilsProvider) { | ||||
|     constructor(logger: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider, protected utils: CoreUtilsProvider, | ||||
|             protected pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.logger = logger.getInstance('AddonBlogProvider'); | ||||
|     } | ||||
| 
 | ||||
| @ -102,6 +104,8 @@ export class AddonBlogProvider { | ||||
|      * @return {Promise<any>}         Promise to be resolved when done. | ||||
|      */ | ||||
|     logView(filter: any = {}, siteId?: string): Promise<any> { | ||||
|         this.pushNotificationsProvider.logViewListEvent('blog', 'core_blog_view_entries', filter, siteId); | ||||
| 
 | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             const data = { | ||||
|                 filters: this.utils.objectToArrayOfObjects(filter, 'name', 'value') | ||||
|  | ||||
| @ -55,13 +55,16 @@ export class AddonCompetencyCompetencyPage { | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.fetchCompetency().then(() => { | ||||
|             const name = this.competency && this.competency.competency && this.competency.competency.competency && | ||||
|                     this.competency.competency.competency.shortname; | ||||
| 
 | ||||
|             if (this.planId) { | ||||
|                 this.competencyProvider.logCompetencyInPlanView(this.planId, this.competencyId, this.planStatus, this.userId) | ||||
|                         .catch(() => { | ||||
|                 this.competencyProvider.logCompetencyInPlanView(this.planId, this.competencyId, this.planStatus, name, | ||||
|                         this.userId).catch(() => { | ||||
|                     // Ignore errors.
 | ||||
|                 }); | ||||
|             } else { | ||||
|                 this.competencyProvider.logCompetencyInCourseView(this.courseId, this.competencyId, this.userId).catch(() => { | ||||
|                 this.competencyProvider.logCompetencyInCourseView(this.courseId, this.competencyId, name, this.userId).catch(() => { | ||||
|                     // Ignore errors.
 | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
| @ -41,7 +41,10 @@ export class AddonCompetencyCompetencySummaryPage { | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.fetchCompetency().then(() => { | ||||
|             this.competencyProvider.logCompetencyView(this.competencyId).catch(() => { | ||||
|             const name = this.competency.competency && this.competency.competency.competency && | ||||
|                     this.competency.competency.competency.shortname; | ||||
| 
 | ||||
|             this.competencyProvider.logCompetencyView(this.competencyId, name).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
|         }).finally(() => { | ||||
|  | ||||
| @ -15,6 +15,7 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Service to handle caompetency learning plans. | ||||
| @ -38,7 +39,8 @@ export class AddonCompetencyProvider { | ||||
| 
 | ||||
|     protected logger; | ||||
| 
 | ||||
|     constructor(loggerProvider: CoreLoggerProvider, private sitesProvider: CoreSitesProvider) { | ||||
|     constructor(loggerProvider: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, | ||||
|             protected pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.logger = loggerProvider.getInstance('AddonCompetencyProvider'); | ||||
|     } | ||||
| 
 | ||||
| @ -471,13 +473,15 @@ export class AddonCompetencyProvider { | ||||
|      * @param  {number} planId    ID of the plan. | ||||
|      * @param  {number} competencyId  ID of the competency. | ||||
|      * @param  {number} planStatus    Current plan Status to decide what action should be logged. | ||||
|      * @param  {string} [name] Name of the competency. | ||||
|      * @param  {number} [userId] User ID. If not defined, current user. | ||||
|      * @param  {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logCompetencyInPlanView(planId: number, competencyId: number, planStatus: number, userId?: number, siteId?: string) | ||||
|             : Promise<any> { | ||||
|     logCompetencyInPlanView(planId: number, competencyId: number, planStatus: number, name?: string, userId?: number, | ||||
|             siteId?: string): Promise<any> { | ||||
|         if (planId && competencyId) { | ||||
| 
 | ||||
|             return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|                 userId = userId || site.getUserId(); | ||||
| 
 | ||||
| @ -488,13 +492,17 @@ export class AddonCompetencyProvider { | ||||
|                     }, | ||||
|                     preSets = { | ||||
|                         typeExpected: 'boolean' | ||||
|                     }; | ||||
|                     }, | ||||
|                     wsName = planStatus == AddonCompetencyProvider.STATUS_COMPLETE ? | ||||
|                                 'core_competency_user_competency_plan_viewed' : 'core_competency_user_competency_viewed_in_plan'; | ||||
| 
 | ||||
|                 if (planStatus == AddonCompetencyProvider.STATUS_COMPLETE) { | ||||
|                     return site.write('core_competency_user_competency_plan_viewed', params, preSets); | ||||
|                 } else { | ||||
|                     return site.write('core_competency_user_competency_viewed_in_plan', params, preSets); | ||||
|                 } | ||||
|                 this.pushNotificationsProvider.logViewEvent(competencyId, name, 'competency', wsName, { | ||||
|                     planid: planId, | ||||
|                     planstatus: planStatus, | ||||
|                     userid: userId | ||||
|                 }, siteId); | ||||
| 
 | ||||
|                 return site.write(wsName, params, preSets); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
| @ -506,11 +514,14 @@ export class AddonCompetencyProvider { | ||||
|      * | ||||
|      * @param  {number} courseId        ID of the course. | ||||
|      * @param  {number} competencyId    ID of the competency. | ||||
|      * @param  {string} [name] Name of the competency. | ||||
|      * @param  {number} [userId] User ID. If not defined, current user. | ||||
|      * @param  {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logCompetencyInCourseView(courseId: number, competencyId: number, userId?: number, siteId?: string): Promise<any> { | ||||
|     logCompetencyInCourseView(courseId: number, competencyId: number, name?: string, userId?: number, siteId?: string) | ||||
|             : Promise<any> { | ||||
| 
 | ||||
|         if (courseId && competencyId) { | ||||
|             return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|                 userId = userId || site.getUserId(); | ||||
| @ -523,8 +534,14 @@ export class AddonCompetencyProvider { | ||||
|                 const preSets = { | ||||
|                     typeExpected: 'boolean' | ||||
|                 }; | ||||
|                 const wsName = 'core_competency_user_competency_viewed_in_course'; | ||||
| 
 | ||||
|                 return site.write('core_competency_user_competency_viewed_in_course', params, preSets); | ||||
|                 this.pushNotificationsProvider.logViewEvent(competencyId, name, 'competency', wsName, { | ||||
|                     courseid: courseId, | ||||
|                     userid: userId | ||||
|                 }, siteId); | ||||
| 
 | ||||
|                 return site.write(wsName, params, preSets); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
| @ -535,10 +552,11 @@ export class AddonCompetencyProvider { | ||||
|      * Report the competency as being viewed. | ||||
|      * | ||||
|      * @param  {number} competencyId    ID of the competency. | ||||
|      * @param  {string} [name] Name of the competency. | ||||
|      * @param  {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logCompetencyView(competencyId: number, siteId?: string): Promise<any> { | ||||
|     logCompetencyView(competencyId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         if (competencyId) { | ||||
|             return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|                 const params = { | ||||
| @ -547,6 +565,9 @@ export class AddonCompetencyProvider { | ||||
|                 const preSets = { | ||||
|                     typeExpected: 'boolean' | ||||
|                 }; | ||||
|                 const wsName = 'core_competency_competency_viewed'; | ||||
| 
 | ||||
|                 this.pushNotificationsProvider.logViewEvent(competencyId, name, 'competency', wsName, {}, siteId); | ||||
| 
 | ||||
|                 return site.write('core_competency_competency_viewed', params, preSets); | ||||
|             }); | ||||
|  | ||||
| @ -80,7 +80,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo | ||||
|         this.userId = this.sitesProvider.getCurrentSiteUserId(); | ||||
| 
 | ||||
|         this.loadContent(false, true).then(() => { | ||||
|             this.assignProvider.logView(this.assign.id).then(() => { | ||||
|             this.assignProvider.logView(this.assign.id, this.assign.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
| @ -88,12 +88,12 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo | ||||
| 
 | ||||
|             if (this.canViewAllSubmissions) { | ||||
|                 // User can see all submissions, log grading view.
 | ||||
|                 this.assignProvider.logGradingView(this.assign.id).catch(() => { | ||||
|                 this.assignProvider.logGradingView(this.assign.id, this.assign.name).catch(() => { | ||||
|                     // Ignore errors.
 | ||||
|                 }); | ||||
|             } else if (this.canViewOwnSubmission) { | ||||
|                 // User can only see their own submission, log view the user submission.
 | ||||
|                 this.assignProvider.logSubmissionView(this.assign.id).catch(() => { | ||||
|                 this.assignProvider.logSubmissionView(this.assign.id, this.assign.name).catch(() => { | ||||
|                     // Ignore errors.
 | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
| @ -911,16 +911,19 @@ export class AddonModAssignProvider { | ||||
|      * Report an assignment submission as being viewed. | ||||
|      * | ||||
|      * @param {number} assignId Assignment ID. | ||||
|      * @param {string} [name] Name of the assign. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logSubmissionView(assignId: number, siteId?: string): Promise<any> { | ||||
|     logSubmissionView(assignId: number, name?: string, siteId?: string): Promise<any> { | ||||
| 
 | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             const params = { | ||||
|                 assignid: assignId | ||||
|             }; | ||||
| 
 | ||||
|             return site.write('mod_assign_view_submission_status', params); | ||||
|             return this.logHelper.logSingle('mod_assign_view_submission_status', params, AddonModAssignProvider.COMPONENT, | ||||
|                     assignId, name, 'assign', {}, siteId); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @ -928,30 +931,34 @@ export class AddonModAssignProvider { | ||||
|      * Report an assignment grading table is being viewed. | ||||
|      * | ||||
|      * @param {number} assignId Assignment ID. | ||||
|      * @param {string} [name] Name of the assign. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logGradingView(assignId: number, siteId?: string): Promise<any> { | ||||
|     logGradingView(assignId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             assignid: assignId | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_assign_view_grading_table', params, AddonModAssignProvider.COMPONENT, assignId, siteId); | ||||
|         return this.logHelper.logSingle('mod_assign_view_grading_table', params, AddonModAssignProvider.COMPONENT, assignId, | ||||
|                 name, 'assign', {}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Report an assign as being viewed. | ||||
|      * | ||||
|      * @param {number} assignId Assignment ID. | ||||
|      * @param {string} [name] Name of the assign. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(assignId: number, siteId?: string): Promise<any> { | ||||
|     logView(assignId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             assignid: assignId | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_assign_view_assign', params, AddonModAssignProvider.COMPONENT, assignId, siteId); | ||||
|         return this.logHelper.logSingle('mod_assign_view_assign', params, AddonModAssignProvider.COMPONENT, assignId, name, | ||||
|                 'assign', {}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -184,7 +184,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp | ||||
|             this.nextChapter = this.bookProvider.getNextChapter(this.chapters, chapterId); | ||||
| 
 | ||||
|             // Chapter loaded, log view. We don't return the promise because we don't want to block the user for this.
 | ||||
|             this.bookProvider.logView(this.module.instance, chapterId).then(() => { | ||||
|             this.bookProvider.logView(this.module.instance, chapterId, this.module.name).then(() => { | ||||
|                 // Module is completed when last chapter is viewed, so we only check completion if the last is reached.
 | ||||
|                 if (!this.nextChapter) { | ||||
|                     this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|  | ||||
| @ -380,15 +380,17 @@ export class AddonModBookProvider { | ||||
|      * | ||||
|      * @param {number} id Module ID. | ||||
|      * @param {string} chapterId Chapter ID. | ||||
|      * @param {string} [name] Name of the book. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, chapterId: string, siteId?: string): Promise<any> { | ||||
|     logView(id: number, chapterId: string, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             bookid: id, | ||||
|             chapterid: chapterId | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_book_view_book', params, AddonModBookProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_book_view_book', params, AddonModBookProvider.COMPONENT, id, name, 'book', | ||||
|                 {chapterid: chapterId}, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -47,7 +47,7 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|         super.ngOnInit(); | ||||
| 
 | ||||
|         this.loadContent().then(() => { | ||||
|             this.chatProvider.logView(this.chat.id).then(() => { | ||||
|             this.chatProvider.logView(this.chat.id, this.chat.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -87,15 +87,16 @@ export class AddonModChatProvider { | ||||
|      * Report a chat as being viewed. | ||||
|      * | ||||
|      * @param  {number} id Chat instance ID. | ||||
|      * @param {string} [name] Name of the chat. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             chatid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_chat_view_chat', params, AddonModChatProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_chat_view_chat', params, AddonModChatProvider.COMPONENT, id, name, 'chat', {}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -67,7 +67,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo | ||||
|             if (!this.choice) { | ||||
|                 return; | ||||
|             } | ||||
|             this.choiceProvider.logView(this.choice.id).then(() => { | ||||
|             this.choiceProvider.logView(this.choice.id, this.choice.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -371,15 +371,17 @@ export class AddonModChoiceProvider { | ||||
|      * Report the choice as being viewed. | ||||
|      * | ||||
|      * @param  {string} id Choice ID. | ||||
|      * @param {string} [name] Name of the choice. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             choiceid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_choice_view_choice', params, AddonModChoiceProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_choice_view_choice', params, AddonModChoiceProvider.COMPONENT, id, name, 'choice', | ||||
|                 {}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -129,7 +129,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             this.dataProvider.logView(this.data.id).then(() => { | ||||
|             this.dataProvider.logView(this.data.id, this.data.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -928,15 +928,17 @@ export class AddonModDataProvider { | ||||
|      * Report the database as being viewed. | ||||
|      * | ||||
|      * @param {number} id      Module ID. | ||||
|      * @param {string} [name] Name of the data. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             databaseid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_data_view_database', params, AddonModDataProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_data_view_database', params, AddonModDataProvider.COMPONENT, id, name, 'data', {}, | ||||
|                     siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -113,7 +113,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | ||||
|         super.ngOnInit(); | ||||
| 
 | ||||
|         this.loadContent(false, true).then(() => { | ||||
|             this.feedbackProvider.logView(this.feedback.id).catch(() => { | ||||
|             this.feedbackProvider.logView(this.feedback.id, this.feedback.name).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
|         }).finally(() => { | ||||
|  | ||||
| @ -95,7 +95,7 @@ export class AddonModFeedbackFormPage implements OnDestroy { | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.fetchData().then(() => { | ||||
|             this.feedbackProvider.logView(this.feedback.id, true).then(() => { | ||||
|             this.feedbackProvider.logView(this.feedback.id, this.feedback.name, true).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -1124,17 +1124,19 @@ export class AddonModFeedbackProvider { | ||||
|      * Report the feedback as being viewed. | ||||
|      * | ||||
|      * @param {number} id                   Module ID. | ||||
|      * @param {string} [name] Name of the feedback. | ||||
|      * @param  {boolean} [formViewed=false] True if form was viewed. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}               Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, formViewed: boolean = false, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, formViewed: boolean = false, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             feedbackid: id, | ||||
|             moduleviewed: formViewed ? 1 : 0 | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_feedback_view_feedback', params, AddonModFeedbackProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_feedback_view_feedback', params, AddonModFeedbackProvider.COMPONENT, id, name, | ||||
|                 'feedback', {moduleviewed: params.moduleviewed}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -55,7 +55,7 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo | ||||
|             this.refreshIcon = 'refresh'; | ||||
|         } else { | ||||
|             this.loadContent().then(() => { | ||||
|                 this.folderProvider.logView(this.module.instance).then(() => { | ||||
|                 this.folderProvider.logView(this.module.instance, this.module.name).then(() => { | ||||
|                     this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|                 }).catch(() => { | ||||
|                     // Ignore errors.
 | ||||
|  | ||||
| @ -133,14 +133,16 @@ export class AddonModFolderProvider { | ||||
|      * Report a folder as being viewed. | ||||
|      * | ||||
|      * @param {number} id Module ID. | ||||
|      * @param {string} [name] Name of the folder. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             folderid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_folder_view_folder', params, AddonModFolderProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_folder_view_folder', params, AddonModFolderProvider.COMPONENT, id, name, 'folder', | ||||
|                 {}, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -152,7 +152,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             this.forumProvider.logView(this.forum.id).then(() => { | ||||
|             this.forumProvider.logView(this.forum.id, this.forum.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -384,7 +384,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 || -1).catch(() => { | ||||
|                 this.forumProvider.logDiscussionView(this.discussionId, this.forumId || -1, this.forum.name).catch(() => { | ||||
|                     // Ignore errors.
 | ||||
|                 }).finally(() => { | ||||
|                     // Trigger mark read posts.
 | ||||
|  | ||||
| @ -771,15 +771,17 @@ export class AddonModForumProvider { | ||||
|      * Report a forum as being viewed. | ||||
|      * | ||||
|      * @param  {number} id    Module ID. | ||||
|      * @param {string} [name] Name of the forum. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             forumid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_forum_view_forum', params, AddonModForumProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_forum_view_forum', params, AddonModForumProvider.COMPONENT, id, name, 'forum', {}, | ||||
|                 siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -787,15 +789,17 @@ export class AddonModForumProvider { | ||||
|      * | ||||
|      * @param  {number} id    Discussion ID. | ||||
|      * @param  {number} forumId  Forum ID. | ||||
|      * @param {string} [name] Name of the forum. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logDiscussionView(id: number, forumId: number, siteId?: string): Promise<any> { | ||||
|     logDiscussionView(id: number, forumId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             discussionid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_forum_view_forum_discussion', params, AddonModForumProvider.COMPONENT, forumId, siteId); | ||||
|         return this.logHelper.logSingle('mod_forum_view_forum_discussion', params, AddonModForumProvider.COMPONENT, forumId, name, | ||||
|                 'forum', params, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -109,7 +109,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             this.glossaryProvider.logView(this.glossary.id, this.viewMode).then(() => { | ||||
|             this.glossaryProvider.logView(this.glossary.id, this.viewMode, this.glossary.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -51,7 +51,7 @@ export class AddonModGlossaryEntryPage { | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.fetchEntry().then(() => { | ||||
|             this.glossaryProvider.logEntryView(this.entry.id, this.componentId).catch(() => { | ||||
|             this.glossaryProvider.logEntryView(this.entry.id, this.componentId, this.glossary.name).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
|         }).finally(() => { | ||||
|  | ||||
| @ -867,16 +867,18 @@ export class AddonModGlossaryProvider { | ||||
|      * | ||||
|      * @param  {number} glossaryId Glossary ID. | ||||
|      * @param  {string} mode       The mode in which the glossary was viewed. | ||||
|      * @param {string} [name] Name of the glossary. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}      Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(glossaryId: number, mode: string, siteId?: string): Promise<any> { | ||||
|     logView(glossaryId: number, mode: string, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             id: glossaryId, | ||||
|             mode: mode | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_glossary_view_glossary', params, AddonModGlossaryProvider.COMPONENT, glossaryId, siteId); | ||||
|         return this.logHelper.logSingle('mod_glossary_view_glossary', params, AddonModGlossaryProvider.COMPONENT, glossaryId, name, | ||||
|                 'glossary', {mode: mode}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -884,14 +886,16 @@ export class AddonModGlossaryProvider { | ||||
|      * | ||||
|      * @param  {number} entryId Entry ID. | ||||
|      * @param  {number} glossaryId Glossary ID. | ||||
|      * @param {string} [name] Name of the glossary. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}   Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logEntryView(entryId: number, glossaryId: number, siteId?: string): Promise<any> { | ||||
|     logEntryView(entryId: number, glossaryId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             id: entryId | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_glossary_view_entry', params, AddonModGlossaryProvider.COMPONENT, glossaryId, siteId); | ||||
|         return this.logHelper.logSingle('mod_glossary_view_entry', params, AddonModGlossaryProvider.COMPONENT, glossaryId, name, | ||||
|                 'glossary', {entryid: entryId}, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -52,7 +52,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom | ||||
|         super.ngOnInit(); | ||||
| 
 | ||||
|         this.loadContent().then(() => { | ||||
|             this.imscpProvider.logView(this.module.instance).then(() => { | ||||
|             this.imscpProvider.logView(this.module.instance, this.module.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -309,14 +309,16 @@ export class AddonModImscpProvider { | ||||
|      * Report a IMSCP as being viewed. | ||||
|      * | ||||
|      * @param  {string} id Module ID. | ||||
|      * @param {string} [name] Name of the imscp. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             imscpid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_imscp_view_imscp', params, AddonModImscpProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_imscp_view_imscp', params, AddonModImscpProvider.COMPONENT, id, name, 'imscp', {}, | ||||
|                 siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -345,7 +345,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo | ||||
|      * Log viewing the lesson. | ||||
|      */ | ||||
|     protected logView(): void { | ||||
|         this.lessonProvider.logViewLesson(this.lesson.id, this.password).then(() => { | ||||
|         this.lessonProvider.logViewLesson(this.lesson.id, this.password, this.lesson.name).then(() => { | ||||
|             this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|         }).catch((error) => { | ||||
|             // Ignore errors.
 | ||||
|  | ||||
| @ -3017,10 +3017,11 @@ export class AddonModLessonProvider { | ||||
|      * | ||||
|      * @param {string} id Module ID. | ||||
|      * @param {string} [password] Lesson password (if any). | ||||
|      * @param {string} [name] Name of the assign. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logViewLesson(id: number, password?: string, siteId?: string): Promise<any> { | ||||
|     logViewLesson(id: number, password?: string, name?: string, siteId?: string): Promise<any> { | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             const params: any = { | ||||
|                 lessonid: id | ||||
| @ -3030,7 +3031,8 @@ export class AddonModLessonProvider { | ||||
|                 params.password = password; | ||||
|             } | ||||
| 
 | ||||
|             return this.logHelper.log('mod_lesson_view_lesson', params, AddonModLessonProvider.COMPONENT, id, siteId); | ||||
|             return this.logHelper.logSingle('mod_lesson_view_lesson', params, AddonModLessonProvider.COMPONENT, id, name, | ||||
|                     'lesson', {}, siteId); | ||||
|         }); | ||||
| 
 | ||||
|     } | ||||
|  | ||||
| @ -95,7 +95,7 @@ export class AddonModLtiIndexComponent extends CoreCourseModuleMainActivityCompo | ||||
|     launch(): void { | ||||
|         this.ltiProvider.getLtiLaunchData(this.lti.id).then((launchData) => { | ||||
|             // "View" LTI.
 | ||||
|             this.ltiProvider.logView(this.lti.id).then(() => { | ||||
|             this.ltiProvider.logView(this.lti.id, this.lti.name).then(() => { | ||||
|                 this.checkCompletion(); | ||||
|             }).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -213,14 +213,15 @@ export class AddonModLtiProvider { | ||||
|      * Report the LTI as being viewed. | ||||
|      * | ||||
|      * @param {string} id LTI id. | ||||
|      * @param {string} [name] Name of the lti. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params: any = { | ||||
|             ltiid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_lti_view_lti', params, AddonModLtiProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_lti_view_lti', params, AddonModLtiProvider.COMPONENT, id, name, 'lti', {}, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -91,7 +91,7 @@ export class AddonModLtiModuleHandler implements CoreCourseModuleHandler { | ||||
|                     this.ltiProvider.getLti(courseId, module.id).then((ltiData) => { | ||||
|                         return this.ltiProvider.getLtiLaunchData(ltiData.id).then((launchData) => { | ||||
|                             // "View" LTI.
 | ||||
|                             this.ltiProvider.logView(ltiData.id).then(() => { | ||||
|                             this.ltiProvider.logView(ltiData.id, ltiData.name).then(() => { | ||||
|                                 this.courseProvider.checkModuleCompletion(courseId, module.completiondata); | ||||
|                             }).catch(() => { | ||||
|                                 // Ignore errors.
 | ||||
|  | ||||
| @ -53,7 +53,7 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp | ||||
|         this.canGetPage = this.pageProvider.isGetPageWSAvailable(); | ||||
| 
 | ||||
|         this.loadContent().then(() => { | ||||
|             this.pageProvider.logView(this.module.instance).then(() => { | ||||
|             this.pageProvider.logView(this.module.instance, this.module.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -148,14 +148,15 @@ export class AddonModPageProvider { | ||||
|      * Report a page as being viewed. | ||||
|      * | ||||
|      * @param {number} id Module ID. | ||||
|      * @param {string} [name] Name of the page. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             pageid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_page_view_page', params, AddonModPageProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_page_view_page', params, AddonModPageProvider.COMPONENT, id, name, 'page', {}, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -85,7 +85,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             this.quizProvider.logViewQuiz(this.quizData.id).then(() => { | ||||
|             this.quizProvider.logViewQuiz(this.quizData.id, this.quizData.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -457,7 +457,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, page, this.preflightData, this.offline).catch((error) => { | ||||
|             this.quizProvider.logViewAttempt(this.attempt.id, page, this.preflightData, this.offline, this.quiz).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
| 
 | ||||
| @ -484,7 +484,8 @@ 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, this.quizId).catch((error) => { | ||||
|             this.quizProvider.logViewAttemptSummary(this.attempt.id, this.preflightData, this.quizId, this.quiz.name) | ||||
|                     .catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
| @ -81,7 +81,7 @@ export class AddonModQuizReviewPage implements OnInit { | ||||
|      */ | ||||
|     ngOnInit(): void { | ||||
|         this.fetchData().then(() => { | ||||
|             this.quizProvider.logViewAttemptReview(this.attemptId, this.quizId).catch((error) => { | ||||
|             this.quizProvider.logViewAttemptReview(this.attemptId, this.quizId, this.quiz.name).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
|         }).finally(() => { | ||||
|  | ||||
| @ -392,8 +392,9 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider | ||||
| 
 | ||||
|                         // Answers sent, now set the current page if the attempt isn't finished.
 | ||||
|                         if (!finish) { | ||||
|                             // Don't pass the quiz instance because we don't want to trigger a Firebase event in this case.
 | ||||
|                             return this.quizProvider.logViewAttempt(onlineAttempt.id, offlineAttempt.currentpage, preflightData, | ||||
|                                     false).catch(() => { | ||||
|                                     false, undefined, siteId).catch(() => { | ||||
|                                 // Ignore errors.
 | ||||
|                             }); | ||||
|                         } | ||||
|  | ||||
| @ -27,6 +27,7 @@ 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'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Service that provides some features for quiz. | ||||
| @ -63,7 +64,8 @@ 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 logHelper: CoreCourseLogHelperProvider) { | ||||
|             private domUtils: CoreDomUtilsProvider, private logHelper: CoreCourseLogHelperProvider, | ||||
|             protected pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.logger = logger.getInstance('AddonModQuizProvider'); | ||||
|     } | ||||
| 
 | ||||
| @ -1533,10 +1535,13 @@ 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 {string} [quiz] Quiz instance. If set, a Firebase event will be stored. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logViewAttempt(attemptId: number, page: number = 0, preflightData: any = {}, offline?: boolean, siteId?: string): Promise<any> { | ||||
|     logViewAttempt(attemptId: number, page: number = 0, preflightData: any = {}, offline?: boolean, quiz?: any, | ||||
|             siteId?: string): Promise<any> { | ||||
| 
 | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             const params = { | ||||
|                     attemptid: attemptId, | ||||
| @ -1549,6 +1554,10 @@ export class AddonModQuizProvider { | ||||
|             if (offline) { | ||||
|                 promises.push(this.quizOfflineProvider.setAttemptCurrentPage(attemptId, page, site.getId())); | ||||
|             } | ||||
|             if (quiz) { | ||||
|                 this.pushNotificationsProvider.logViewEvent(quiz.id, quiz.name, 'quiz', 'mod_quiz_view_attempt', | ||||
|                         {attemptid: attemptId, page: page}, siteId); | ||||
|             } | ||||
| 
 | ||||
|             return Promise.all(promises); | ||||
|         }); | ||||
| @ -1559,15 +1568,17 @@ export class AddonModQuizProvider { | ||||
|      * | ||||
|      * @param {number} attemptId Attempt ID. | ||||
|      * @param {number} quizId Quiz ID. | ||||
|      * @param {string} [name] Name of the quiz. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logViewAttemptReview(attemptId: number, quizId: number, siteId?: string): Promise<any> { | ||||
|     logViewAttemptReview(attemptId: number, quizId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             attemptid: attemptId | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_quiz_view_attempt_review', params, AddonModQuizProvider.COMPONENT, quizId, siteId); | ||||
|         return this.logHelper.logSingle('mod_quiz_view_attempt_review', params, AddonModQuizProvider.COMPONENT, quizId, name, | ||||
|                 'quiz', params, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -1576,31 +1587,35 @@ export class AddonModQuizProvider { | ||||
|      * @param {number} attemptId Attempt ID. | ||||
|      * @param {any} preflightData Preflight required data (like password). | ||||
|      * @param {number} quizId Quiz ID. | ||||
|      * @param {string} [name] Name of the quiz. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logViewAttemptSummary(attemptId: number, preflightData: any, quizId: number, siteId?: string): Promise<any> { | ||||
|     logViewAttemptSummary(attemptId: number, preflightData: any, quizId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             attemptid: attemptId, | ||||
|             preflightdata: this.utils.objectToArrayOfObjects(preflightData, 'name', 'value', true) | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_quiz_view_attempt_summary', params, AddonModQuizProvider.COMPONENT, quizId, siteId); | ||||
|         return this.logHelper.logSingle('mod_quiz_view_attempt_summary', params, AddonModQuizProvider.COMPONENT, quizId, name, | ||||
|                 'quiz', {attemptid: attemptId}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Report a quiz as being viewed. | ||||
|      * | ||||
|      * @param {number} id Module ID. | ||||
|      * @param {string} [name] Name of the quiz. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logViewQuiz(id: number, siteId?: string): Promise<any> { | ||||
|     logViewQuiz(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             quizid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_quiz_view_quiz', params, AddonModQuizProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_quiz_view_quiz', params, AddonModQuizProvider.COMPONENT, id, name, 'quiz', {}, | ||||
|                 siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -53,7 +53,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource | ||||
|         this.canGetResource = this.resourceProvider.isGetResourceWSAvailable(); | ||||
| 
 | ||||
|         this.loadContent().then(() => { | ||||
|             this.resourceProvider.logView(this.module.instance).then(() => { | ||||
|             this.resourceProvider.logView(this.module.instance, this.module.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -179,7 +179,7 @@ export class AddonModResourceHelperProvider { | ||||
|         // Download and open the file from the resource contents.
 | ||||
|         return this.courseHelper.downloadModuleAndOpenFile(module, courseId, AddonModResourceProvider.COMPONENT, module.id, | ||||
|                 module.contents).then(() => { | ||||
|             this.resourceProvider.logView(module.instance).then(() => { | ||||
|             this.resourceProvider.logView(module.instance, module.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(courseId, module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -150,14 +150,16 @@ export class AddonModResourceProvider { | ||||
|      * Report the resource as being viewed. | ||||
|      * | ||||
|      * @param {number} id Module ID. | ||||
|      * @param {string} [name] Name of the resource. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             resourceid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_resource_view_resource', params, AddonModResourceProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_resource_view_resource', params, AddonModResourceProvider.COMPONENT, id, name, | ||||
|                 'resource', {}, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -83,7 +83,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             this.scormProvider.logView(this.scorm.id).then(() => { | ||||
|             this.scormProvider.logView(this.scorm.id, this.scorm.name).then(() => { | ||||
|                 this.checkCompletion(); | ||||
|             }).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -370,7 +370,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | ||||
|         } | ||||
| 
 | ||||
|         // Trigger SCO launch event.
 | ||||
|         this.scormProvider.logLaunchSco(this.scorm.id, sco.id).catch(() => { | ||||
|         this.scormProvider.logLaunchSco(this.scorm.id, sco.id, this.scorm.name).catch(() => { | ||||
|             // Ignore errors.
 | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @ -1421,21 +1421,19 @@ export class AddonModScormProvider { | ||||
|      * | ||||
|      * @param {number} scormId SCORM ID. | ||||
|      * @param {number} scoId SCO ID. | ||||
|      * @param {string} [name] Name of the SCORM. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logLaunchSco(scormId: number, scoId: number, siteId?: string): Promise<any> { | ||||
|     logLaunchSco(scormId: number, scoId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             const params = { | ||||
|                 scormid: scormId, | ||||
|                 scoid: scoId | ||||
|             }; | ||||
| 
 | ||||
|             return site.write('mod_scorm_launch_sco', params).then((response) => { | ||||
|                 if (!response || !response.status) { | ||||
|                     return Promise.reject(null); | ||||
|                 } | ||||
|             }); | ||||
|             return this.logHelper.logSingle('mod_scorm_launch_sco', params, AddonModScormProvider.COMPONENT, scormId, name, | ||||
|                     'scorm', {scoid: scoId}, siteId); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @ -1443,15 +1441,17 @@ export class AddonModScormProvider { | ||||
|      * Report a SCORM as being viewed. | ||||
|      * | ||||
|      * @param {string} id Module ID. | ||||
|      * @param {string} [name] Name of the SCORM. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             scormid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_scorm_view_scorm', params, AddonModScormProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_scorm_view_scorm', params, AddonModScormProvider.COMPONENT, id, name, 'scorm', {}, | ||||
|                 siteId); | ||||
| } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -53,7 +53,7 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo | ||||
|         this.userId = this.sitesProvider.getCurrentSiteUserId(); | ||||
| 
 | ||||
|         this.loadContent(false, true).then(() => { | ||||
|             this.surveyProvider.logView(this.survey.id).then(() => { | ||||
|             this.surveyProvider.logView(this.survey.id, this.survey.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -213,15 +213,17 @@ export class AddonModSurveyProvider { | ||||
|      * Report the survey as being viewed. | ||||
|      * | ||||
|      * @param {number} id Module ID. | ||||
|      * @param {string} [name] Name of the assign. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             surveyid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_survey_view_survey', params, AddonModSurveyProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_survey_view_survey', params, AddonModSurveyProvider.COMPONENT, id, name, 'survey', | ||||
|                 {}, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -178,7 +178,7 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo | ||||
|      * @return {Promise<void>} Promise resolved when done. | ||||
|      */ | ||||
|     protected logView(): Promise<void> { | ||||
|         return this.urlProvider.logView(this.module.instance).then(() => { | ||||
|         return this.urlProvider.logView(this.module.instance, this.module.name).then(() => { | ||||
|             this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|         }).catch(() => { | ||||
|             // Ignore errors.
 | ||||
|  | ||||
| @ -173,7 +173,7 @@ export class AddonModUrlModuleHandler implements CoreCourseModuleHandler { | ||||
|      * @param {number} courseId The course ID. | ||||
|      */ | ||||
|     protected openUrl(module: any, courseId: number): void { | ||||
|         this.urlProvider.logView(module.instance).then(() => { | ||||
|         this.urlProvider.logView(module.instance, module.name).then(() => { | ||||
|             this.courseProvider.checkModuleCompletion(courseId, module.completiondata); | ||||
|         }).catch(() => { | ||||
|             // Ignore errors.
 | ||||
|  | ||||
| @ -217,14 +217,15 @@ export class AddonModUrlProvider { | ||||
|      * Report the url as being viewed. | ||||
|      * | ||||
|      * @param {number} id Module ID. | ||||
|      * @param {string} [name] Name of the assign. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}  Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             urlid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_url_view_url', params, AddonModUrlProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_url_view_url', params, AddonModUrlProvider.COMPONENT, id, name, 'url', {}, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -104,13 +104,13 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|             } | ||||
| 
 | ||||
|             if (this.isMainPage) { | ||||
|                 this.wikiProvider.logView(this.wiki.id).then(() => { | ||||
|                 this.wikiProvider.logView(this.wiki.id, this.wiki.name).then(() => { | ||||
|                     this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|                 }).catch((error) => { | ||||
|                     // Ignore errors.
 | ||||
|                 }); | ||||
|             } else { | ||||
|                 this.wikiProvider.logPageView(this.pageId, this.wiki.id).catch(() => { | ||||
|                 this.wikiProvider.logPageView(this.pageId, this.wiki.id, this.wiki.name).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.wiki.id).catch(() => { | ||||
|                                 this.wikiProvider.logPageView(this.currentPage, this.wiki.id, this.wiki.name).catch(() => { | ||||
|                                     // Ignore errors.
 | ||||
|                                 }); | ||||
|                             }); | ||||
|  | ||||
| @ -655,30 +655,34 @@ export class AddonModWikiProvider { | ||||
|      * | ||||
|      * @param {number} id Page ID. | ||||
|      * @param {number} wikiId Wiki ID. | ||||
|      * @param {string} [name] Name of the wiki. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logPageView(id: number, wikiId: number, siteId?: string): Promise<any> { | ||||
|     logPageView(id: number, wikiId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             pageid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_wiki_view_page', params, AddonModWikiProvider.COMPONENT, wikiId, siteId); | ||||
|         return this.logHelper.logSingle('mod_wiki_view_page', params, AddonModWikiProvider.COMPONENT, wikiId, name, 'wiki', | ||||
|                 params, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Report the wiki as being viewed. | ||||
|      * | ||||
|      * @param {number} id Wiki ID. | ||||
|      * @param {string} [name] Name of the wiki. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             wikiid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_wiki_view_wiki', params, AddonModWikiProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_wiki_view_wiki', params, AddonModWikiProvider.COMPONENT, id, name, 'wiki', {}, | ||||
|                 siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -107,7 +107,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             this.workshopProvider.logView(this.workshop.id).then(() => { | ||||
|             this.workshopProvider.logView(this.workshop.id, this.workshop.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch((error) => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -130,7 +130,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { | ||||
|      */ | ||||
|     ngOnInit(): void { | ||||
|         this.fetchSubmissionData().then(() => { | ||||
|             this.workshopProvider.logViewSubmission(this.submissionId, this.workshopId).then(() => { | ||||
|             this.workshopProvider.logViewSubmission(this.submissionId, this.workshopId, this.workshop.name).then(() => { | ||||
|                 this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|  | ||||
| @ -1362,15 +1362,17 @@ export class AddonModWorkshopProvider { | ||||
|      * Report the workshop as being viewed. | ||||
|      * | ||||
|      * @param  {number} id       Workshop ID. | ||||
|      * @param {string} [name] Name of the workshop. | ||||
|      * @param  {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}    Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(id: number, siteId?: string): Promise<any> { | ||||
|     logView(id: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             workshopid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_workshop_view_workshop', params, AddonModWorkshopProvider.COMPONENT, id, siteId); | ||||
|         return this.logHelper.logSingle('mod_workshop_view_workshop', params, AddonModWorkshopProvider.COMPONENT, id, name, | ||||
|                 'workshop', siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -1378,14 +1380,16 @@ export class AddonModWorkshopProvider { | ||||
|      * | ||||
|      * @param  {number} id          Submission ID. | ||||
|      * @param  {number} workshopId  Workshop ID. | ||||
|      * @param {string} [name] Name of the workshop. | ||||
|      * @param  {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>}    Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logViewSubmission(id: number, workshopId: number, siteId?: string): Promise<any> { | ||||
|     logViewSubmission(id: number, workshopId: number, name?: string, siteId?: string): Promise<any> { | ||||
|         const params = { | ||||
|             submissionid: id | ||||
|         }; | ||||
| 
 | ||||
|         return this.logHelper.log('mod_workshop_view_submission', params, AddonModWorkshopProvider.COMPONENT, workshopId, siteId); | ||||
|         return this.logHelper.logSingle('mod_workshop_view_submission', params, AddonModWorkshopProvider.COMPONENT, workshopId, | ||||
|                 name, 'workshop', params, siteId); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -21,6 +21,7 @@ import { CoreSiteWSPreSets } from '@classes/site'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { CoreUserProvider } from '@core/user/providers/user'; | ||||
| import { AddonNotesOfflineProvider } from './notes-offline'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Service to handle notes. | ||||
| @ -33,7 +34,7 @@ export class AddonNotesProvider { | ||||
| 
 | ||||
|     constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider, | ||||
|             private utils: CoreUtilsProvider, private translate: TranslateService, private userProvider: CoreUserProvider, | ||||
|             private notesOffline: AddonNotesOfflineProvider) { | ||||
|             private notesOffline: AddonNotesOfflineProvider, protected pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.logger = logger.getInstance('AddonNotesProvider'); | ||||
|     } | ||||
| 
 | ||||
| @ -318,6 +319,8 @@ export class AddonNotesProvider { | ||||
|                 userid: userId || 0 | ||||
|             }; | ||||
| 
 | ||||
|             this.pushNotificationsProvider.logViewListEvent('notes', 'core_notes_view_notes', params, site.getId()); | ||||
| 
 | ||||
|             return site.write('core_notes_view_notes', params); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @ -80,5 +80,6 @@ | ||||
|     "statusbarbgandroid": "#df7310", | ||||
|     "statusbarlighttextandroid": true, | ||||
|     "statusbarbgremotetheme": "#000000", | ||||
|     "statusbarlighttextremotetheme": true | ||||
|     "statusbarlighttextremotetheme": true, | ||||
|     "enableanalytics": false | ||||
| } | ||||
|  | ||||
| @ -213,7 +213,7 @@ export class CoreCourseSectionPage implements OnDestroy { | ||||
|                 let promise; | ||||
| 
 | ||||
|                 // Add log in Moodle.
 | ||||
|                 this.courseProvider.logView(this.course.id, this.sectionNumber).catch(() => { | ||||
|                 this.courseProvider.logView(this.course.id, this.sectionNumber, undefined, this.course.fullname).catch(() => { | ||||
|                     // Ignore errors.
 | ||||
|                 }); | ||||
| 
 | ||||
|  | ||||
| @ -27,6 +27,7 @@ import { CoreConstants } from '../../constants'; | ||||
| import { CoreCourseOfflineProvider } from './course-offline'; | ||||
| import { CoreSitePluginsProvider } from '@core/siteplugins/providers/siteplugins'; | ||||
| import { CoreCourseFormatDelegate } from './format-delegate'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Service that provides some features regarding a course. | ||||
| @ -102,7 +103,7 @@ export class CoreCourseProvider { | ||||
|             private utils: CoreUtilsProvider, private timeUtils: CoreTimeUtilsProvider, private translate: TranslateService, | ||||
|             private courseOffline: CoreCourseOfflineProvider, private appProvider: CoreAppProvider, | ||||
|             private courseFormatDelegate: CoreCourseFormatDelegate, private sitePluginsProvider: CoreSitePluginsProvider, | ||||
|             private domUtils: CoreDomUtilsProvider) { | ||||
|             private domUtils: CoreDomUtilsProvider, protected pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.logger = logger.getInstance('CoreCourseProvider'); | ||||
| 
 | ||||
|         this.sitesProvider.registerSiteSchema(this.siteSchema); | ||||
| @ -811,18 +812,22 @@ export class CoreCourseProvider { | ||||
|      * @param {number} courseId  Course ID. | ||||
|      * @param {number} [sectionNumber] Section number. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @param {string} [name] Name of the course. | ||||
|      * @return {Promise<void>} Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     logView(courseId: number, sectionNumber?: number, siteId?: string): Promise<void> { | ||||
|     logView(courseId: number, sectionNumber?: number, siteId?: string, name?: string): Promise<void> { | ||||
|         const params: any = { | ||||
|             courseid: courseId | ||||
|         }; | ||||
|                 courseid: courseId | ||||
|             }, | ||||
|             wsName = 'core_course_view_course'; | ||||
| 
 | ||||
|         if (typeof sectionNumber != 'undefined') { | ||||
|             params.sectionnumber = sectionNumber; | ||||
|         } | ||||
| 
 | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             this.pushNotificationsProvider.logViewEvent(courseId, name, 'course', wsName, {sectionnumber: sectionNumber}, siteId); | ||||
| 
 | ||||
|             return site.write('core_course_view_course', params).then((response) => { | ||||
|                 if (!response.status) { | ||||
|                     return Promise.reject(null); | ||||
|  | ||||
| @ -36,7 +36,7 @@ export class CoreCourseLogCronHandler implements CoreCronHandler { | ||||
|      */ | ||||
|     execute(siteId?: string, force?: boolean): Promise<any> { | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|            return this.courseProvider.logView(site.getSiteHomeId(), undefined, site.getId()); | ||||
|            return this.courseProvider.logView(site.getSiteHomeId(), undefined, site.getId(), site.getInfo().sitename); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -18,6 +18,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreTimeUtilsProvider } from '@providers/utils/time'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Helper to manage logging to Moodle. | ||||
| @ -62,7 +63,7 @@ export class CoreCourseLogHelperProvider { | ||||
| 
 | ||||
|     constructor(protected sitesProvider: CoreSitesProvider, protected timeUtils: CoreTimeUtilsProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, protected utils: CoreUtilsProvider, | ||||
|             protected appProvider: CoreAppProvider) { | ||||
|             protected appProvider: CoreAppProvider, protected pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.sitesProvider.registerSiteSchema(this.siteSchema); | ||||
|     } | ||||
| 
 | ||||
| @ -196,6 +197,47 @@ export class CoreCourseLogHelperProvider { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Perform log online. Data will be saved offline for syncing. | ||||
|      * It also triggers a Firebase view_item event. | ||||
|      * | ||||
|      * @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}         [name] Name of the viewed item. | ||||
|      * @param  {string}         [category] Category of the viewed item. | ||||
|      * @param  {string}         [eventData] Data to pass to the Firebase event. | ||||
|      * @param  {string}         [siteId]    Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when done. | ||||
|      */ | ||||
|     logSingle(ws: string, data: any, component: string, componentId: number, name?: string, category?: string, eventData?: any, | ||||
|             siteId?: string): Promise<any> { | ||||
|         this.pushNotificationsProvider.logViewEvent(componentId, name, category, ws, eventData, siteId); | ||||
| 
 | ||||
|         return this.log(ws, data, component, componentId, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Perform log online. Data will be saved offline for syncing. | ||||
|      * It also triggers a Firebase view_item_list event. | ||||
|      * | ||||
|      * @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}         category    Category of the viewed item. | ||||
|      * @param  {string}         [eventData] Data to pass to the Firebase event. | ||||
|      * @param  {string}         [siteId]    Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when done. | ||||
|      */ | ||||
|     logList(ws: string, data: any, component: string, componentId: number, category: string, eventData?: any, siteId?: string) | ||||
|             : Promise<any> { | ||||
|         this.pushNotificationsProvider.logViewListEvent(category, ws, eventData, siteId); | ||||
| 
 | ||||
|         return this.log(ws, data, component, componentId, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Save activity log for offline sync. | ||||
|      * | ||||
|  | ||||
| @ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; | ||||
| import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreCoursesProvider } from '@core/courses/providers/courses'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Service to provide grade functionalities. | ||||
| @ -33,7 +34,7 @@ export class CoreGradesProvider { | ||||
|     protected logger; | ||||
| 
 | ||||
|     constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, | ||||
|             private coursesProvider: CoreCoursesProvider) { | ||||
|             private coursesProvider: CoreCoursesProvider, protected pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.logger = logger.getInstance('CoreGradesProvider'); | ||||
|     } | ||||
| 
 | ||||
| @ -326,12 +327,25 @@ export class CoreGradesProvider { | ||||
|      * | ||||
|      * @param  {number}  courseId Course ID. | ||||
|      * @param  {number}  userId   User ID. | ||||
|      * @param  {string}  [name]   Course name. If not set, it will be calculated. | ||||
|      * @return {Promise<any>}     Promise resolved when done. | ||||
|      */ | ||||
|     logCourseGradesView(courseId: number, userId: number): Promise<any> { | ||||
|     logCourseGradesView(courseId: number, userId: number, name?: string): Promise<any> { | ||||
|         userId = userId || this.sitesProvider.getCurrentSiteUserId(); | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write('gradereport_user_view_grade_report', { | ||||
|         const wsName = 'gradereport_user_view_grade_report'; | ||||
| 
 | ||||
|         if (!name) { | ||||
|             this.coursesProvider.getUserCourse(courseId, true).catch(() => { | ||||
|                 return {}; | ||||
|             }).then((course) => { | ||||
|                 this.pushNotificationsProvider.logViewEvent(courseId, course.fullname || '', 'grades', wsName, {userid: userId}); | ||||
|             }); | ||||
|         } else { | ||||
|             this.pushNotificationsProvider.logViewEvent(courseId, name, 'grades', wsName, {userid: userId}); | ||||
|         } | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write(wsName, { | ||||
|             courseid: courseId, | ||||
|             userid: userId | ||||
|         }); | ||||
| @ -348,8 +362,12 @@ export class CoreGradesProvider { | ||||
|             courseId = this.sitesProvider.getCurrentSiteHomeId(); | ||||
|         } | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write('gradereport_overview_view_grade_report', { | ||||
|         const params = { | ||||
|             courseid: courseId | ||||
|         }); | ||||
|         }; | ||||
| 
 | ||||
|         this.pushNotificationsProvider.logViewListEvent('grades', 'gradereport_overview_view_grade_report', params); | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write('gradereport_overview_view_grade_report', params); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -292,6 +292,86 @@ export class CorePushNotificationsProvider { | ||||
|         return this.getAddonBadge(siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Log a firebase event. | ||||
|      * | ||||
|      * @param {string} name Name of the event. | ||||
|      * @param {any} data Data of the event. | ||||
|      * @param {boolean} [filter] Whether to filter the data. This is useful when logging a full notification. | ||||
|      * @return {Promise<any>} Promise resolved when done. This promise is never rejected. | ||||
|      */ | ||||
|     logEvent(name: string, data: any, filter?: boolean): Promise<any> { | ||||
|         const win = <any> window; // This feature is only present in our fork of the plugin.
 | ||||
| 
 | ||||
|         if (CoreConfigConstants.enableanalytics && win.PushNotification && win.PushNotification.logEvent) { | ||||
|             return new Promise((resolve, reject): void => { | ||||
|                 win.PushNotification.logEvent(resolve, (error) => { | ||||
|                     this.logger.error('Error logging firebase event', name, error); | ||||
|                     resolve(); | ||||
|                 }, name, data, !!filter); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         return Promise.resolve(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Log a firebase view_item event. | ||||
|      * | ||||
|      * @param {number|string} itemId The item ID. | ||||
|      * @param {string} itemName The item name. | ||||
|      * @param {string} itemCategory The item category. | ||||
|      * @param {string} wsName Name of the WS. | ||||
|      * @param {any} [data] Other data to pass to the event. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when done. This promise is never rejected. | ||||
|      */ | ||||
|     logViewEvent(itemId: number | string, itemName: string, itemCategory: string, wsName: string, data?: any, siteId?: string) | ||||
|             : Promise<any> { | ||||
|         data = data || {}; | ||||
| 
 | ||||
|         // Add "moodle" to the name of all extra params.
 | ||||
|         data = this.utils.prefixKeys(data, 'moodle'); | ||||
|         data['moodleaction'] = wsName; | ||||
|         data['moodlesiteid'] = siteId || this.sitesProvider.getCurrentSiteId(); | ||||
| 
 | ||||
|         if (itemId) { | ||||
|             data['item_id'] = itemId; | ||||
|         } | ||||
|         if (itemName) { | ||||
|             data['item_name'] = itemName; | ||||
|         } | ||||
|         if (itemCategory) { | ||||
|             data['item_category'] = itemCategory; | ||||
|         } | ||||
| 
 | ||||
|         return this.logEvent('view_item', data, false); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Log a firebase view_item_list event. | ||||
|      * | ||||
|      * @param {string} itemCategory The item category. | ||||
|      * @param {string} wsName Name of the WS. | ||||
|      * @param {any} [data] Other data to pass to the event. | ||||
|      * @param {string} [siteId] Site ID. If not defined, current site. | ||||
|      * @return {Promise<any>} Promise resolved when done. This promise is never rejected. | ||||
|      */ | ||||
|     logViewListEvent(itemCategory: string, wsName: string, data?: any, siteId?: string): Promise<any> { | ||||
|         data = data || {}; | ||||
| 
 | ||||
|         // Add "moodle" to the name of all extra params.
 | ||||
|         data = this.utils.prefixKeys(data, 'moodle'); | ||||
|         data['moodleaction'] = wsName; | ||||
|         data['moodlesiteid'] = siteId || this.sitesProvider.getCurrentSiteId(); | ||||
| 
 | ||||
|         if (itemCategory) { | ||||
|             data['item_category'] = itemCategory; | ||||
|         } | ||||
| 
 | ||||
|         return this.logEvent('view_item_list', data, false); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Function called when a push notification is clicked. Redirect the user to the right state. | ||||
|      * | ||||
|  | ||||
| @ -80,8 +80,18 @@ export class CorePushNotificationsModule { | ||||
|         }); | ||||
| 
 | ||||
|         // Listen for local notification clicks (generated by the app).
 | ||||
|         localNotificationsProvider.registerClick(CorePushNotificationsProvider.COMPONENT, | ||||
|             pushNotificationsProvider.notificationClicked.bind(pushNotificationsProvider)); | ||||
|         localNotificationsProvider.registerClick(CorePushNotificationsProvider.COMPONENT, (notification: any) => { | ||||
|             // Log notification open event.
 | ||||
|             pushNotificationsProvider.logEvent('moodle_notification_open', notification, true); | ||||
| 
 | ||||
|             pushNotificationsProvider.notificationClicked(notification); | ||||
|         }); | ||||
| 
 | ||||
|         // Listen for local notification dismissed events.
 | ||||
|         localNotificationsProvider.registerObserver('clear', CorePushNotificationsProvider.COMPONENT, (notification: any) => { | ||||
|             // Log notification dismissed event.
 | ||||
|             pushNotificationsProvider.logEvent('moodle_notification_dismiss', notification, true); | ||||
|         }); | ||||
| 
 | ||||
|         // Allow migrating the table from the old app to the new schema.
 | ||||
|         updateManager.registerAppTableMigration({ | ||||
|  | ||||
| @ -20,6 +20,7 @@ import { CoreCourseHelperProvider } from '@core/course/providers/helper'; | ||||
| import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; | ||||
| import { CoreBlockDelegate } from '@core/block/providers/delegate'; | ||||
| import { CoreBlockComponent } from '@core/block/components/block/block'; | ||||
| import { CoreSite } from '@classes/site'; | ||||
| 
 | ||||
| /** | ||||
|  * Component that displays site home index. | ||||
| @ -37,12 +38,14 @@ export class CoreSiteHomeIndexComponent implements OnInit { | ||||
|     hasSupportedBlock: boolean; | ||||
|     items: any[] = []; | ||||
|     siteHomeId: number; | ||||
|     currentSite: CoreSite; | ||||
|     blocks = []; | ||||
| 
 | ||||
|     constructor(private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider, | ||||
|     constructor(private domUtils: CoreDomUtilsProvider, sitesProvider: CoreSitesProvider, | ||||
|             private courseProvider: CoreCourseProvider, private courseHelper: CoreCourseHelperProvider, | ||||
|             private prefetchDelegate: CoreCourseModulePrefetchDelegate, private blockDelegate: CoreBlockDelegate) { | ||||
|         this.siteHomeId = sitesProvider.getCurrentSite().getSiteHomeId(); | ||||
|         this.currentSite = sitesProvider.getCurrentSite(); | ||||
|         this.siteHomeId = this.currentSite.getSiteHomeId(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -60,14 +63,13 @@ export class CoreSiteHomeIndexComponent implements OnInit { | ||||
|      * @param {any} refresher Refresher. | ||||
|      */ | ||||
|     doRefresh(refresher: any): void { | ||||
|         const promises = [], | ||||
|             currentSite = this.sitesProvider.getCurrentSite(); | ||||
|         const promises = []; | ||||
| 
 | ||||
|         promises.push(this.courseProvider.invalidateSections(this.siteHomeId)); | ||||
|         promises.push(currentSite.invalidateConfig().then(() => { | ||||
|         promises.push(this.currentSite.invalidateConfig().then(() => { | ||||
|             // Config invalidated, fetch it again.
 | ||||
|             return currentSite.getConfig().then((config) => { | ||||
|                 currentSite.setConfig(config); | ||||
|             return this.currentSite.getConfig().then((config) => { | ||||
|                 this.currentSite.setConfig(config); | ||||
|             }); | ||||
|         })); | ||||
| 
 | ||||
| @ -102,7 +104,7 @@ export class CoreSiteHomeIndexComponent implements OnInit { | ||||
|     protected loadContent(): Promise<any> { | ||||
|         this.hasContent = false; | ||||
| 
 | ||||
|         const config = this.sitesProvider.getCurrentSite().getStoredConfig() || { numsections: 1 }; | ||||
|         const config = this.currentSite.getStoredConfig() || { numsections: 1 }; | ||||
| 
 | ||||
|         if (config.frontpageloggedin) { | ||||
|             // Items with index 1 and 3 were removed on 2.5 and not being supported in the app.
 | ||||
| @ -142,7 +144,8 @@ export class CoreSiteHomeIndexComponent implements OnInit { | ||||
|             } | ||||
| 
 | ||||
|             // Add log in Moodle.
 | ||||
|             this.courseProvider.logView(this.siteHomeId).catch(() => { | ||||
|             this.courseProvider.logView(this.siteHomeId, undefined, undefined, | ||||
|                     this.currentSite && this.currentSite.getInfo().sitename).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
| 
 | ||||
|  | ||||
| @ -84,7 +84,7 @@ export class CoreUserProfilePage { | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.fetchUser().then(() => { | ||||
|             return this.userProvider.logView(this.userId, this.courseId).catch((error) => { | ||||
|             return this.userProvider.logView(this.userId, this.courseId, this.user.fullname).catch((error) => { | ||||
|                 this.isDeleted = error.errorcode === 'userdeleted'; | ||||
|                 this.isEnrolled = error.errorcode !== 'notenrolledprofile'; | ||||
|             }); | ||||
|  | ||||
| @ -20,6 +20,7 @@ import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreUserOfflineProvider } from './offline'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| /** | ||||
|  * Service to provide user functionalities. | ||||
| @ -63,7 +64,7 @@ export class CoreUserProvider { | ||||
| 
 | ||||
|     constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, | ||||
|             private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider, | ||||
|             private userOffline: CoreUserOfflineProvider) { | ||||
|             private userOffline: CoreUserOfflineProvider, private pushNotificationsProvider: CorePushNotificationsProvider) { | ||||
|         this.logger = logger.getInstance('CoreUserProvider'); | ||||
|         this.sitesProvider.registerSiteSchema(this.siteSchema); | ||||
|     } | ||||
| @ -432,18 +433,22 @@ export class CoreUserProvider { | ||||
|      * Log User Profile View in Moodle. | ||||
|      * @param  {number}       userId   User ID. | ||||
|      * @param  {number}       [courseId] Course ID. | ||||
|      * @param  {string}       [name] Name of the user. | ||||
|      * @return {Promise<any>}          Promise resolved when done. | ||||
|      */ | ||||
|     logView(userId: number, courseId?: number): Promise<any> { | ||||
|     logView(userId: number, courseId?: number, name?: string): Promise<any> { | ||||
|         const params = { | ||||
|             userid: userId | ||||
|         }; | ||||
|                 userid: userId | ||||
|             }, | ||||
|             wsName = 'core_user_view_user_profile'; | ||||
| 
 | ||||
|         if (courseId) { | ||||
|             params['courseid'] = courseId; | ||||
|         } | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write('core_user_view_user_profile', params); | ||||
|         this.pushNotificationsProvider.logViewEvent(userId, name, 'user', wsName, {courseid: courseId}); | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write(wsName, params); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -452,9 +457,13 @@ export class CoreUserProvider { | ||||
|      * @return {Promise<any>}          Promise resolved when done. | ||||
|      */ | ||||
|     logParticipantsView(courseId?: number): Promise<any> { | ||||
|         return this.sitesProvider.getCurrentSite().write('core_user_view_user_list', { | ||||
|         const params = { | ||||
|             courseid: courseId | ||||
|         }); | ||||
|         }; | ||||
| 
 | ||||
|         this.pushNotificationsProvider.logViewListEvent('user', 'core_user_view_user_list', params); | ||||
| 
 | ||||
|         return this.sitesProvider.getCurrentSite().write('core_user_view_user_list', params); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -102,6 +102,10 @@ export class CoreLocalNotificationsProvider { | ||||
|     }; | ||||
|     protected triggerSubscription: Subscription; | ||||
|     protected clickSubscription: Subscription; | ||||
|     protected clearSubscription: Subscription; | ||||
|     protected cancelSubscription: Subscription; | ||||
|     protected addSubscription: Subscription; | ||||
|     protected updateSubscription: Subscription; | ||||
| 
 | ||||
|     constructor(logger: CoreLoggerProvider, private localNotifications: LocalNotifications, private platform: Platform, | ||||
|             private appProvider: CoreAppProvider, private utils: CoreUtilsProvider, private configProvider: CoreConfigProvider, | ||||
| @ -113,16 +117,31 @@ export class CoreLocalNotificationsProvider { | ||||
|         this.appDB.createTablesFromSchema(this.tablesSchema); | ||||
| 
 | ||||
|         platform.ready().then(() => { | ||||
|             // Listen to events.
 | ||||
|             this.triggerSubscription = localNotifications.on('trigger').subscribe((notification: ILocalNotification) => { | ||||
|                 this.trigger(notification); | ||||
| 
 | ||||
|                 this.handleEvent('trigger', notification); | ||||
|             }); | ||||
| 
 | ||||
|             this.clickSubscription = localNotifications.on('click').subscribe((notification: ILocalNotification) => { | ||||
|                 if (notification && notification.data) { | ||||
|                     this.logger.debug('Notification clicked: ', notification.data); | ||||
|                 this.handleEvent('click', notification); | ||||
|             }); | ||||
| 
 | ||||
|                     this.notifyClick(notification.data); | ||||
|                 } | ||||
|             this.clearSubscription = localNotifications.on('clear').subscribe((notification: ILocalNotification) => { | ||||
|                 this.handleEvent('clear', notification); | ||||
|             }); | ||||
| 
 | ||||
|             this.cancelSubscription = localNotifications.on('cancel').subscribe((notification: ILocalNotification) => { | ||||
|                 this.handleEvent('cancel', notification); | ||||
|             }); | ||||
| 
 | ||||
|             this.addSubscription = localNotifications.on('add').subscribe((notification: ILocalNotification) => { | ||||
|                 this.handleEvent('add', notification); | ||||
|             }); | ||||
| 
 | ||||
|             this.updateSubscription = localNotifications.on('update').subscribe((notification: ILocalNotification) => { | ||||
|                 this.handleEvent('update', notification); | ||||
|             }); | ||||
| 
 | ||||
|             // Create the default channel for local notifications.
 | ||||
| @ -290,6 +309,20 @@ export class CoreLocalNotificationsProvider { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Handle an event triggered by the local notifications plugin. | ||||
|      * | ||||
|      * @param {string} eventName Name of the event. | ||||
|      * @param {any} notification Notification. | ||||
|      */ | ||||
|     protected handleEvent(eventName: string, notification: any): void { | ||||
|         if (notification && notification.data) { | ||||
|             this.logger.debug('Notification event: ' + eventName + '. Data:', notification.data); | ||||
| 
 | ||||
|             this.notifyEvent(eventName, notification.data); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns whether local notifications plugin is installed. | ||||
|      * | ||||
| @ -328,12 +361,22 @@ export class CoreLocalNotificationsProvider { | ||||
|      * @param {any} data Data received by the notification. | ||||
|      */ | ||||
|     notifyClick(data: any): void { | ||||
|         this.notifyEvent('click', data); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Notify a certain event to observers. Only the observers with the same component as the notification will be notified. | ||||
|      * | ||||
|      * @param {string} eventName Name of the event to notify. | ||||
|      * @param {any} data Data received by the notification. | ||||
|      */ | ||||
|     notifyEvent(eventName: string, data: any): void { | ||||
|         // Execute the code in the Angular zone, so change detection doesn't stop working.
 | ||||
|         this.zone.run(() => { | ||||
|             const component = data.component; | ||||
|             if (component) { | ||||
|                 if (this.observables[component]) { | ||||
|                     this.observables[component].next(data); | ||||
|                 if (this.observables[eventName] && this.observables[eventName][component]) { | ||||
|                     this.observables[eventName][component].next(data); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
| @ -385,18 +428,34 @@ export class CoreLocalNotificationsProvider { | ||||
|      * @return {any} Object with an "off" property to stop listening for clicks. | ||||
|      */ | ||||
|     registerClick(component: string, callback: Function): any { | ||||
|         this.logger.debug(`Register observer '${component}' for notification click.`); | ||||
|         return this.registerObserver('click', component, callback); | ||||
|     } | ||||
| 
 | ||||
|         if (typeof this.observables[component] == 'undefined') { | ||||
|             // No observable for this component, create a new one.
 | ||||
|             this.observables[component] = new Subject<any>(); | ||||
|     /** | ||||
|      * Register an observer to be notified when a certain event is fired for a notification belonging to a certain component. | ||||
|      * | ||||
|      * @param {string} eventName Name of the event to listen to. | ||||
|      * @param {string} component Component to listen notifications for. | ||||
|      * @param {Function} callback Function to call with the data received by the notification. | ||||
|      * @return {any} Object with an "off" property to stop listening for events. | ||||
|      */ | ||||
|     registerObserver(eventName: string, component: string, callback: Function): any { | ||||
|         this.logger.debug(`Register observer '${component}' for event '${eventName}'.`); | ||||
| 
 | ||||
|         if (typeof this.observables[eventName] == 'undefined') { | ||||
|             this.observables[eventName] = {}; | ||||
|         } | ||||
| 
 | ||||
|         this.observables[component].subscribe(callback); | ||||
|         if (typeof this.observables[eventName][component] == 'undefined') { | ||||
|             // No observable for this component, create a new one.
 | ||||
|             this.observables[eventName][component] = new Subject<any>(); | ||||
|         } | ||||
| 
 | ||||
|         this.observables[eventName][component].subscribe(callback); | ||||
| 
 | ||||
|         return { | ||||
|             off: (): void => { | ||||
|                 this.observables[component].unsubscribe(callback); | ||||
|                 this.observables[eventName][component].unsubscribe(callback); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| @ -1049,6 +1049,24 @@ export class CoreUtilsProvider { | ||||
|         return mapped; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Add a prefix to all the keys in an object. | ||||
|      * | ||||
|      * @param {any} data Object. | ||||
|      * @param {string} prefix Prefix to add. | ||||
|      * @return {any} Prefixed object. | ||||
|      */ | ||||
|     prefixKeys(data: any, prefix: string): any { | ||||
|         const newObj = {}, | ||||
|             keys = Object.keys(data); | ||||
| 
 | ||||
|         keys.forEach((key) => { | ||||
|             newObj[prefix + key] = data[key]; | ||||
|         }); | ||||
| 
 | ||||
|         return newObj; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Similar to AngularJS $q.defer(). | ||||
|      * | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user