MOBILE-4368 analytics: Apply new analytics system to all pages
parent
0598ec0062
commit
2d2cc2f5f9
|
@ -104,10 +104,12 @@
|
|||
"addon.calendar.currentmonth": "local_moodlemobileapp",
|
||||
"addon.calendar.daynext": "calendar",
|
||||
"addon.calendar.dayprev": "calendar",
|
||||
"addon.calendar.dayviewtitle": "calendar",
|
||||
"addon.calendar.defaultnotificationtime": "local_moodlemobileapp",
|
||||
"addon.calendar.deleteallevents": "calendar",
|
||||
"addon.calendar.deleteevent": "calendar",
|
||||
"addon.calendar.deleteoneevent": "calendar",
|
||||
"addon.calendar.detailedmonthviewtitle": "calendar",
|
||||
"addon.calendar.durationminutes": "calendar",
|
||||
"addon.calendar.durationnone": "calendar",
|
||||
"addon.calendar.durationuntil": "calendar",
|
||||
|
@ -369,6 +371,7 @@
|
|||
"addon.mod_assign.gradelocked": "assign",
|
||||
"addon.mod_assign.gradenotsynced": "local_moodlemobileapp",
|
||||
"addon.mod_assign.gradeoutof": "assign",
|
||||
"addon.mod_assign.grading": "assign",
|
||||
"addon.mod_assign.gradingstatus": "assign",
|
||||
"addon.mod_assign.groupsubmissionsettings": "assign",
|
||||
"addon.mod_assign.hiddenuser": "assign",
|
||||
|
@ -425,6 +428,7 @@
|
|||
"addon.mod_assign.submittedlate": "assign",
|
||||
"addon.mod_assign.submittedovertime": "assign",
|
||||
"addon.mod_assign.submittedundertime": "assign",
|
||||
"addon.mod_assign.subpagetitle": "assign",
|
||||
"addon.mod_assign.syncblockedusercomponent": "local_moodlemobileapp",
|
||||
"addon.mod_assign.timelimit": "assign",
|
||||
"addon.mod_assign.timemodified": "assign",
|
||||
|
@ -2235,6 +2239,7 @@
|
|||
"core.play": "local_moodlemobileapp",
|
||||
"core.previous": "moodle",
|
||||
"core.proceed": "moodle",
|
||||
"core.publicprofile": "moodle",
|
||||
"core.pulltorefresh": "local_moodlemobileapp",
|
||||
"core.qrscanner": "local_moodlemobileapp",
|
||||
"core.question.answer": "question",
|
||||
|
|
|
@ -26,6 +26,8 @@ import { ActivatedRoute } from '@angular/router';
|
|||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
||||
import { AddonBadgesUserBadgesSource } from '@addons/badges/classes/user-badges-source';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays the list of calendar events.
|
||||
|
@ -38,6 +40,7 @@ export class AddonBadgesIssuedBadgePage implements OnInit, OnDestroy {
|
|||
|
||||
protected badgeHash = '';
|
||||
protected userId!: number;
|
||||
protected logView: (badge: AddonBadgesUserBadge) => void;
|
||||
|
||||
courseId = 0;
|
||||
user?: CoreUserProfile;
|
||||
|
@ -58,6 +61,16 @@ export class AddonBadgesIssuedBadgePage implements OnInit, OnDestroy {
|
|||
);
|
||||
|
||||
this.badges = new CoreSwipeNavigationItemsManager(source);
|
||||
|
||||
this.logView = CoreTime.once((badge) => {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'core_badges_view_user_badges',
|
||||
name: badge.name,
|
||||
data: { id: badge.uniquehash, category: 'badges' },
|
||||
url: `/badges/badge.php?hash=${badge.uniquehash}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,6 +118,8 @@ export class AddonBadgesIssuedBadgePage implements OnInit, OnDestroy {
|
|||
this.course = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
this.logView(badge);
|
||||
} catch (message) {
|
||||
CoreDomUtils.showErrorModalDefault(message, 'Error getting badge data.');
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ import { CoreNavigator } from '@services/navigator';
|
|||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||
import { AddonBadgesUserBadgesSource } from '@addons/badges/classes/user-badges-source';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Page that displays the list of calendar events.
|
||||
|
@ -39,6 +42,8 @@ export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy {
|
|||
|
||||
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
||||
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
let courseId = CoreNavigator.getRouteNumberParam('courseId') ?? 0; // Use 0 for site badges.
|
||||
const userId = CoreNavigator.getRouteNumberParam('userId') ?? CoreSites.getCurrentSiteUserId();
|
||||
|
@ -52,6 +57,16 @@ export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy {
|
|||
CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(AddonBadgesUserBadgesSource, [courseId, userId]),
|
||||
AddonBadgesUserBadgesPage,
|
||||
);
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'core_badges_view_user_badges',
|
||||
name: Translate.instant('addon.badges.badges'),
|
||||
data: { courseId: this.badges.getSource().COURSE_ID, category: 'badges' },
|
||||
url: '/badges/mybadges.php',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,6 +110,8 @@ export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy {
|
|||
|
||||
try {
|
||||
await this.badges.reload();
|
||||
|
||||
this.logView();
|
||||
} catch (message) {
|
||||
CoreDomUtils.showErrorModalDefault(message, 'Error loading badges');
|
||||
|
||||
|
|
|
@ -20,11 +20,14 @@ import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-lin
|
|||
import { CoreTag } from '@features/tag/services/tag';
|
||||
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays the list of blog entries.
|
||||
|
@ -43,7 +46,7 @@ export class AddonBlogEntriesPage implements OnInit {
|
|||
protected canLoadMoreEntries = false;
|
||||
protected canLoadMoreUserEntries = true;
|
||||
protected siteHomeId: number;
|
||||
protected fetchSuccess = false;
|
||||
protected logView: () => void;
|
||||
|
||||
loaded = false;
|
||||
canLoadMore = false;
|
||||
|
@ -61,6 +64,25 @@ export class AddonBlogEntriesPage implements OnInit {
|
|||
constructor() {
|
||||
this.currentUserId = CoreSites.getCurrentSiteUserId();
|
||||
this.siteHomeId = CoreSites.getCurrentSiteHomeId();
|
||||
|
||||
this.logView = CoreTime.once(async () => {
|
||||
await CoreUtils.ignoreErrors(AddonBlog.logView(this.filter));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'core_blog_view_entries',
|
||||
name: this.title,
|
||||
data: {
|
||||
...this.filter,
|
||||
category: 'blog',
|
||||
},
|
||||
url: CoreUrlUtils.addParamsToUrl('/blog/index.php', {
|
||||
...this.filter,
|
||||
modid: this.filter.cmid,
|
||||
cmid: undefined,
|
||||
}),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,10 +222,7 @@ export class AddonBlogEntriesPage implements OnInit {
|
|||
|
||||
await Promise.all(promises);
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
CoreUtils.ignoreErrors(AddonBlog.logView(this.filter));
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.blog.errorloadentries', true);
|
||||
this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading.
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
||||
import { CoreTagItem } from '@features/tag/services/tag';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
@ -104,8 +103,6 @@ export class AddonBlogProvider {
|
|||
* @returns Promise to be resolved when done.
|
||||
*/
|
||||
async logView(filter: AddonBlogFilter = {}, siteId?: string): Promise<CoreStatusWithWarningsWSResponse> {
|
||||
CorePushNotifications.logViewListEvent('blog', 'core_blog_view_entries', filter, siteId);
|
||||
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
||||
const data: AddonBlogViewEntriesWSParams = {
|
||||
|
|
|
@ -49,6 +49,10 @@ import {
|
|||
} from '@classes/items-management/swipe-slides-dynamic-items-manager-source';
|
||||
import { CoreSwipeSlidesDynamicItemsManager } from '@classes/items-management/swipe-slides-dynamic-items-manager';
|
||||
import moment from 'moment-timezone';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Component that displays a calendar.
|
||||
|
@ -81,6 +85,7 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
|
|||
// Observers and listeners.
|
||||
protected undeleteEventObserver: CoreEventObserver;
|
||||
protected managerUnsubscribe?: () => void;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(differs: KeyValueDiffers) {
|
||||
this.currentSiteId = CoreSites.getCurrentSiteId();
|
||||
|
@ -107,6 +112,29 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
|
|||
|
||||
this.hiddenDiffer = this.hidden;
|
||||
this.filterDiffer = differs.find(this.filter ?? {}).create();
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
const month = this.manager?.getSelectedItem();
|
||||
if (!month) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = {
|
||||
course: this.filter?.courseId,
|
||||
time: month.moment.unix(),
|
||||
};
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'core_calendar_get_calendar_monthly_view',
|
||||
name: Translate.instant('addon.calendar.detailedmonthviewtitle', { $a: this.periodName }),
|
||||
data: {
|
||||
...params,
|
||||
category: 'calendar',
|
||||
},
|
||||
url: CoreUrlUtils.addParamsToUrl('/calendar/view.php?view=month', params),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@HostBinding('attr.hidden') get hiddenAttribute(): string | null {
|
||||
|
@ -124,7 +152,7 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
|
|||
const source = new AddonCalendarMonthSlidesItemsManagerSource(this, moment({
|
||||
year: this.initialYear,
|
||||
month: this.initialMonth ? this.initialMonth - 1 : undefined,
|
||||
}));
|
||||
}).startOf('month'));
|
||||
this.manager = new CoreSwipeSlidesDynamicItemsManager(source);
|
||||
this.managerUnsubscribe = this.manager.addListener({
|
||||
onSelectedItemUpdated: (item) => {
|
||||
|
@ -176,6 +204,8 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
|
|||
await this.manager?.getSource().fetchData();
|
||||
|
||||
await this.manager?.getSource().load(this.manager?.getSelectedItem());
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.calendar.errorloadevents', true);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ import { AddonCalendarHelper, AddonCalendarFilter } from '../../services/calenda
|
|||
import { AddonCalendarOffline } from '../../services/calendar-offline';
|
||||
import { CoreCategoryData, CoreCourses } from '@features/courses/services/courses';
|
||||
import { CoreConstants } from '@/core/constants';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Component that displays upcoming events.
|
||||
|
@ -54,6 +58,7 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, DoCheck, On
|
|||
protected lookAhead = 0;
|
||||
protected timeFormat?: string;
|
||||
protected differ: KeyValueDiffer<unknown, unknown>; // To detect changes in the data input.
|
||||
protected logView: () => void;
|
||||
|
||||
// Observers.
|
||||
protected undeleteEventObserver: CoreEventObserver;
|
||||
|
@ -84,6 +89,23 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, DoCheck, On
|
|||
);
|
||||
|
||||
this.differ = differs.find([]).create();
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
const params = {
|
||||
course: this.filter?.courseId,
|
||||
};
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'core_calendar_get_calendar_upcoming_view',
|
||||
name: Translate.instant('addon.calendar.upcomingevents'),
|
||||
data: {
|
||||
...params,
|
||||
category: 'calendar',
|
||||
},
|
||||
url: CoreUrlUtils.addParamsToUrl('/calendar/view.php?view=upcoming', params),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,8 +170,9 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, DoCheck, On
|
|||
try {
|
||||
await Promise.all(promises);
|
||||
|
||||
this.fetchEvents();
|
||||
await this.fetchEvents();
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.calendar.errorloadevents', true);
|
||||
}
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
"currentmonth": "Current Month",
|
||||
"daynext": "Next day",
|
||||
"dayprev": "Previous day",
|
||||
"dayviewtitle": "Day view: {{$a}}",
|
||||
"defaultnotificationtime": "Default notification time",
|
||||
"deleteallevents": "Delete all events",
|
||||
"deleteevent": "Delete event",
|
||||
"deleteoneevent": "Delete this event",
|
||||
"detailedmonthviewtitle": "Detailed month view: {{$a}}",
|
||||
"durationminutes": "Duration in minutes",
|
||||
"durationnone": "Without duration",
|
||||
"durationuntil": "Until",
|
||||
|
|
|
@ -33,7 +33,7 @@ import { CoreCategoryData, CoreCourses, CoreEnrolledCourseData } from '@features
|
|||
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||
import { AddonCalendarFilterComponent } from '../../components/filter/filter';
|
||||
import moment from 'moment-timezone';
|
||||
import { NgZone } from '@singletons';
|
||||
import { NgZone, Translate } from '@singletons';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { Params } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
@ -47,6 +47,9 @@ import {
|
|||
} from '@classes/items-management/swipe-slides-dynamic-items-manager-source';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { AddonCalendarEventsSource } from '@addons/calendar/classes/events-source';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays the calendar events for a certain day.
|
||||
|
@ -73,6 +76,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
protected onlineObserver: Subscription;
|
||||
protected filterChangedObserver: CoreEventObserver;
|
||||
protected managerUnsubscribe?: () => void;
|
||||
protected logView: () => void;
|
||||
|
||||
periodName?: string;
|
||||
manager?: CoreSwipeSlidesDynamicItemsManager<PreloadedDay, AddonCalendarDaySlidesItemsManagerSource>;
|
||||
|
@ -186,6 +190,28 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
this.isOnline = CoreNetwork.isOnline();
|
||||
});
|
||||
});
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
const day = this.manager?.getSelectedItem();
|
||||
if (!day) {
|
||||
return;
|
||||
}
|
||||
const params = {
|
||||
course: this.filter.courseId,
|
||||
time: day.moment.unix(),
|
||||
};
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'core_calendar_get_calendar_day_view',
|
||||
name: Translate.instant('addon.calendar.dayviewtitle', { $a: this.periodName }),
|
||||
data: {
|
||||
...params,
|
||||
category: 'calendar',
|
||||
},
|
||||
url: CoreUrlUtils.addParamsToUrl('/calendar/view.php?view=day', params),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,7 +235,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
year: CoreNavigator.getRouteNumberParam('year'),
|
||||
month: month ? month - 1 : undefined,
|
||||
date: CoreNavigator.getRouteNumberParam('day'),
|
||||
}));
|
||||
}).startOf('day'));
|
||||
this.manager = new CoreSwipeSlidesDynamicItemsManager(source);
|
||||
this.managerUnsubscribe = this.manager.addListener({
|
||||
onSelectedItemUpdated: (item) => {
|
||||
|
@ -246,6 +272,8 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
await this.manager?.getSource().fetchData(this.filter.courseId);
|
||||
|
||||
await this.manager?.getSource().load(this.manager?.getSelectedItem());
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.calendar.errorloadevents', true);
|
||||
}
|
||||
|
@ -500,6 +528,7 @@ class AddonCalendarDaySlidesItemsManagerSource extends CoreSwipeSlidesDynamicIte
|
|||
canCreate = false;
|
||||
|
||||
protected dayPage: AddonCalendarDayPage;
|
||||
protected sendLog = true;
|
||||
|
||||
constructor(page: AddonCalendarDayPage, initialMoment: moment.Moment) {
|
||||
super({ moment: initialMoment });
|
||||
|
@ -780,6 +809,7 @@ class AddonCalendarDaySlidesItemsManagerSource extends CoreSwipeSlidesDynamicIte
|
|||
promises.push(AddonCalendar.invalidateTimeFormat());
|
||||
|
||||
this.categories = undefined; // Get categories again.
|
||||
this.sendLog = true;
|
||||
|
||||
if (selectedDay) {
|
||||
selectedDay.dirty = true;
|
||||
|
|
|
@ -27,6 +27,9 @@ import { AddonCompetencyPlanCompetenciesSource } from '@addons/competency/classe
|
|||
import { AddonCompetencyCourseCompetenciesSource } from '@addons/competency/classes/competency-course-competencies-source';
|
||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays the list of competencies of a learning plan.
|
||||
|
@ -46,8 +49,11 @@ export class AddonCompetencyCompetenciesPage implements AfterViewInit, OnDestroy
|
|||
|
||||
title = '';
|
||||
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
const planId = CoreNavigator.getRouteNumberParam('planId');
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
|
||||
if (!planId) {
|
||||
const courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
||||
|
@ -96,6 +102,8 @@ export class AddonCompetencyCompetenciesPage implements AfterViewInit, OnDestroy
|
|||
} else {
|
||||
this.title = Translate.instant('addon.competency.coursecompetencies');
|
||||
}
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting competencies data.');
|
||||
}
|
||||
|
@ -122,4 +130,42 @@ export class AddonCompetencyCompetenciesPage implements AfterViewInit, OnDestroy
|
|||
this.competencies.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected performLogView(): void {
|
||||
const source = this.competencies.getSource();
|
||||
|
||||
if (source instanceof AddonCompetencyPlanCompetenciesSource) {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'tool_lp_data_for_plan_page',
|
||||
name: this.title,
|
||||
data: {
|
||||
category: 'competency',
|
||||
planid: source.PLAN_ID,
|
||||
},
|
||||
url: `/admin/tool/lp/plan.php?id=${source.PLAN_ID}`,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.USER_ID && source.USER_ID !== CoreSites.getCurrentSiteUserId()) {
|
||||
// Only log event when viewing own competencies. In LMS viewing students competencies uses a different view.
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'tool_lp_data_for_course_competencies_page',
|
||||
name: this.title,
|
||||
data: {
|
||||
category: 'competency',
|
||||
courseid: source.COURSE_ID,
|
||||
},
|
||||
url: `/admin/tool/lp/coursecompetencies.php?courseid=${source.COURSE_ID}`,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import {
|
|||
AddonCompetency,
|
||||
AddonCompetencyDataForPlanPageCompetency,
|
||||
AddonCompetencyDataForCourseCompetenciesPageCompetency,
|
||||
AddonCompetencyProvider,
|
||||
} from '@addons/competency/services/competency';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
|
@ -38,6 +39,9 @@ import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/
|
|||
import { AddonCompetencyPlanCompetenciesSource } from '@addons/competency/classes/competency-plan-competencies-source';
|
||||
import { ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { AddonCompetencyCourseCompetenciesSource } from '@addons/competency/classes/competency-course-competencies-source';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
|
||||
/**
|
||||
* Page that displays the competency information.
|
||||
|
@ -58,9 +62,11 @@ export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
|
|||
contextLevel?: string;
|
||||
contextInstanceId?: number;
|
||||
|
||||
protected fetchSuccess = false;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
|
||||
try {
|
||||
const planId = CoreNavigator.getRouteNumberParam('planId');
|
||||
|
||||
|
@ -156,31 +162,7 @@ export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
|
|||
}
|
||||
});
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
const name = this.competency.competency.competency.shortname;
|
||||
|
||||
if (source instanceof AddonCompetencyPlanCompetenciesSource) {
|
||||
this.planStatus && await CoreUtils.ignoreErrors(
|
||||
AddonCompetency.logCompetencyInPlanView(
|
||||
source.PLAN_ID,
|
||||
this.requireCompetencyId(),
|
||||
this.planStatus,
|
||||
name,
|
||||
source.user?.id,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
await CoreUtils.ignoreErrors(
|
||||
AddonCompetency.logCompetencyInCourseView(
|
||||
source.COURSE_ID,
|
||||
this.requireCompetencyId(),
|
||||
name,
|
||||
source.USER_ID,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting competency data.');
|
||||
}
|
||||
|
@ -288,6 +270,73 @@ export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
|
|||
return competency.usercompetencysummary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected async performLogView(): Promise<void> {
|
||||
if (!this.competency) {
|
||||
return;
|
||||
}
|
||||
|
||||
const source = this.competencies.getSource();
|
||||
const compId = this.requireCompetencyId();
|
||||
const name = this.competency.competency.competency.shortname;
|
||||
const userId = source.user?.id;
|
||||
|
||||
if (source instanceof AddonCompetencyPlanCompetenciesSource) {
|
||||
if (!this.planStatus) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(
|
||||
AddonCompetency.logCompetencyInPlanView(source.PLAN_ID, compId, this.planStatus, name, userId),
|
||||
);
|
||||
|
||||
const wsName = this.planStatus === AddonCompetencyProvider.STATUS_COMPLETE
|
||||
? 'core_competency_user_competency_plan_viewed'
|
||||
: 'core_competency_user_competency_viewed_in_plan';
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: wsName,
|
||||
name,
|
||||
data: {
|
||||
id: compId,
|
||||
category: 'competency',
|
||||
planid: source.PLAN_ID,
|
||||
planstatus: this.planStatus,
|
||||
userid: userId,
|
||||
},
|
||||
url: CoreUrlUtils.addParamsToUrl('/admin/tool/lp/user_competency_in_plan.php', {
|
||||
planid: source.PLAN_ID,
|
||||
userid: userId,
|
||||
competencyid: compId,
|
||||
}),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonCompetency.logCompetencyInCourseView(source.COURSE_ID, compId, name, source.USER_ID));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'core_competency_user_competency_viewed_in_course',
|
||||
name,
|
||||
data: {
|
||||
id: compId,
|
||||
category: 'competency',
|
||||
courseid: source.COURSE_ID,
|
||||
userid: userId,
|
||||
},
|
||||
url: CoreUrlUtils.addParamsToUrl('/admin/tool/lp/user_competency_in_course.php', {
|
||||
courseid: source.COURSE_ID,
|
||||
competencyid: compId,
|
||||
userid: userId,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,8 @@ import { CoreNavigator } from '@services/navigator';
|
|||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.module';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays the competency summary.
|
||||
|
@ -36,7 +38,30 @@ export class AddonCompetencyCompetencySummaryPage implements OnInit {
|
|||
contextLevel?: ContextLevel;
|
||||
contextInstanceId?: number;
|
||||
|
||||
protected fetchSuccess = false; // Whether a fetch was finished successfully.
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(async () => {
|
||||
if (!this.competency) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(
|
||||
AddonCompetency.logCompetencyView(this.competencyId, this.competency.competency.shortname),
|
||||
);
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'core_competency_competency_viewed',
|
||||
name: this.competency.competency.shortname,
|
||||
data: {
|
||||
competencyId: this.competencyId,
|
||||
category: 'competency',
|
||||
},
|
||||
url: `/admin/tool/lp/user_competency.php?id=${this.competencyId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -77,10 +102,7 @@ export class AddonCompetencyCompetencySummaryPage implements OnInit {
|
|||
|
||||
this.competency = result.competency;
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
CoreUtils.ignoreErrors(AddonCompetency.logCompetencyView(this.competencyId, this.competency.competency.shortname));
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting competency summary data.');
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@ import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.mod
|
|||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { AddonCompetencyCourseCompetenciesSource } from '@addons/competency/classes/competency-course-competencies-source';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Page that displays the list of competencies of a course.
|
||||
|
@ -41,7 +45,11 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit, OnDestroy
|
|||
AddonCompetencyCourseCompetenciesSource
|
||||
>;
|
||||
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
|
||||
try {
|
||||
const courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
||||
const userId = CoreNavigator.getRouteNumberParam('userId');
|
||||
|
@ -53,7 +61,6 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit, OnDestroy
|
|||
this.competencies = new CoreListItemsManager(source, AddonCompetencyCourseCompetenciesPage);
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
|
||||
CoreNavigator.back();
|
||||
|
||||
return;
|
||||
|
@ -112,6 +119,8 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit, OnDestroy
|
|||
protected async fetchCourseCompetencies(): Promise<void> {
|
||||
try {
|
||||
await this.competencies.getSource().reload();
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting course competencies data.');
|
||||
}
|
||||
|
@ -147,4 +156,26 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit, OnDestroy
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected performLogView(): void {
|
||||
const source = this.competencies.getSource();
|
||||
if (source.USER_ID && source.USER_ID !== CoreSites.getCurrentSiteUserId()) {
|
||||
// Only log event when viewing own competencies. In LMS viewing students competencies uses a different view.
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'tool_lp_data_for_course_competencies_page',
|
||||
name: Translate.instant('addon.competency.coursecompetencies'),
|
||||
data: {
|
||||
category: 'competency',
|
||||
courseid: source.COURSE_ID,
|
||||
},
|
||||
url: `/admin/tool/lp/coursecompetencies.php?courseid=${source.COURSE_ID}`,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/
|
|||
import { AddonCompetencyPlansSource } from '@addons/competency/classes/competency-plans-source';
|
||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||
import { AddonCompetencyPlanCompetenciesSource } from '@addons/competency/classes/competency-plan-competencies-source';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays a learning plan.
|
||||
|
@ -36,7 +38,11 @@ export class AddonCompetencyPlanPage implements OnInit, OnDestroy {
|
|||
plans!: CoreSwipeNavigationItemsManager;
|
||||
competencies!: CoreListItemsManager<AddonCompetencyDataForPlanPageCompetency, AddonCompetencyPlanCompetenciesSource>;
|
||||
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
|
||||
try {
|
||||
const planId = CoreNavigator.getRequiredRouteNumberParam('planId');
|
||||
const userId = CoreNavigator.getRouteNumberParam('userId');
|
||||
|
@ -93,6 +99,8 @@ export class AddonCompetencyPlanPage implements OnInit, OnDestroy {
|
|||
protected async fetchLearningPlan(): Promise<void> {
|
||||
try {
|
||||
await this.competencies.getSource().reload();
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting learning plan data.');
|
||||
}
|
||||
|
@ -111,4 +119,26 @@ export class AddonCompetencyPlanPage implements OnInit, OnDestroy {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected performLogView(): void {
|
||||
if (!this.plan) {
|
||||
return;
|
||||
}
|
||||
|
||||
const planId = this.competencies.getSource().PLAN_ID;
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'tool_lp_data_for_plan_page',
|
||||
name: this.plan.plan.name,
|
||||
data: {
|
||||
category: 'competency',
|
||||
planid: planId,
|
||||
},
|
||||
url: `/admin/tool/lp/coursecompetencies.php?id=${planId}`,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ import { CoreNavigator } from '@services/navigator';
|
|||
import { AddonCompetencyPlanFormatted, AddonCompetencyPlansSource } from '@addons/competency/classes/competency-plans-source';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Page that displays the list of learning plans.
|
||||
|
@ -34,11 +38,25 @@ export class AddonCompetencyPlanListPage implements AfterViewInit, OnDestroy {
|
|||
|
||||
plans: CoreListItemsManager<AddonCompetencyPlanFormatted, AddonCompetencyPlansSource>;
|
||||
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
const userId = CoreNavigator.getRouteNumberParam('userId');
|
||||
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(AddonCompetencyPlansSource, [userId]);
|
||||
|
||||
this.plans = new CoreListItemsManager(source, AddonCompetencyPlanListPage);
|
||||
|
||||
this.logView = CoreTime.once(async () => {
|
||||
const userId = source.USER_ID ?? CoreSites.getCurrentSiteId();
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'tool_lp_data_for_plans_page',
|
||||
name: Translate.instant('addon.competency.userplans'),
|
||||
data: { userid: userId },
|
||||
url: `/admin/tool/lp/plans.php?userid=${userId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +76,8 @@ export class AddonCompetencyPlanListPage implements AfterViewInit, OnDestroy {
|
|||
protected async fetchLearningPlans(): Promise<void> {
|
||||
try {
|
||||
await this.plans.load();
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting learning plans data.');
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||
import { CoreCommentsArea } from '@features/comments/services/comments';
|
||||
import { CoreCourseSummary, CoreCourseModuleSummary } from '@features/course/services/course';
|
||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
||||
import { CoreUserSummary } from '@features/user/services/user';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
@ -495,7 +494,7 @@ export class AddonCompetencyProvider {
|
|||
* @param planId ID of the plan.
|
||||
* @param competencyId ID of the competency.
|
||||
* @param planStatus Current plan Status to decide what action should be logged.
|
||||
* @param name Name of the competency.
|
||||
* @param name Deprecated, not used anymore.
|
||||
* @param userId User ID. If not defined, current user.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
|
@ -525,12 +524,6 @@ export class AddonCompetencyProvider {
|
|||
? 'core_competency_user_competency_plan_viewed'
|
||||
: 'core_competency_user_competency_viewed_in_plan';
|
||||
|
||||
CorePushNotifications.logViewEvent(competencyId, name, 'competency', wsName, {
|
||||
planid: planId,
|
||||
planstatus: planStatus,
|
||||
userid: userId,
|
||||
}, siteId);
|
||||
|
||||
await site.write(wsName, params, preSets);
|
||||
}
|
||||
|
||||
|
@ -539,7 +532,7 @@ export class AddonCompetencyProvider {
|
|||
*
|
||||
* @param courseId ID of the course.
|
||||
* @param competencyId ID of the competency.
|
||||
* @param name Name of the competency.
|
||||
* @param name Deprecated, not used anymore.
|
||||
* @param userId User ID. If not defined, current user.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
|
@ -564,14 +557,7 @@ export class AddonCompetencyProvider {
|
|||
typeExpected: 'boolean',
|
||||
};
|
||||
|
||||
const wsName = 'core_competency_user_competency_viewed_in_course';
|
||||
|
||||
CorePushNotifications.logViewEvent(competencyId, name, 'competency', 'wsName', {
|
||||
courseid: courseId,
|
||||
userid: userId,
|
||||
}, siteId);
|
||||
|
||||
await site.write(wsName, params, preSets);
|
||||
await site.write('core_competency_user_competency_viewed_in_course', params, preSets);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -593,10 +579,7 @@ export class AddonCompetencyProvider {
|
|||
typeExpected: 'boolean',
|
||||
};
|
||||
|
||||
const wsName = 'core_competency_competency_viewed';
|
||||
CorePushNotifications.logViewEvent(competencyId, name, 'competency', wsName, {}, siteId);
|
||||
|
||||
await site.write(wsName, params, preSets);
|
||||
await site.write('core_competency_competency_viewed', params, preSets);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,9 +19,12 @@ import {
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays the course completion report.
|
||||
|
@ -33,6 +36,7 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
export class AddonCourseCompletionReportPage implements OnInit {
|
||||
|
||||
protected userId!: number;
|
||||
protected logView: () => void;
|
||||
|
||||
courseId!: number;
|
||||
completionLoaded = false;
|
||||
|
@ -42,6 +46,21 @@ export class AddonCourseCompletionReportPage implements OnInit {
|
|||
statusText?: string;
|
||||
user?: CoreUserProfile;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'core_completion_get_course_completion_status',
|
||||
name: Translate.instant('addon.coursecompletion.coursecompletion'),
|
||||
data: {
|
||||
course: this.courseId,
|
||||
user: this.userId,
|
||||
},
|
||||
url: `/blocks/completionstatus/details.php?course=${this.courseId}&user=${this.userId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
@ -77,6 +96,7 @@ export class AddonCourseCompletionReportPage implements OnInit {
|
|||
this.showSelfComplete = AddonCourseCompletion.canMarkSelfCompleted(this.userId, this.completion);
|
||||
|
||||
this.tracked = true;
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
if (error && error.errorcode == 'notenroled') {
|
||||
// Not enrolled error, probably a teacher.
|
||||
|
|
|
@ -57,7 +57,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
@ViewChild(AddonModAssignSubmissionComponent) submissionComponent?: AddonModAssignSubmissionComponent;
|
||||
|
||||
component = AddonModAssignProvider.COMPONENT;
|
||||
moduleName = 'assign';
|
||||
pluginName = 'assign';
|
||||
|
||||
assign?: AddonModAssignAssign; // The assign object.
|
||||
canViewAllSubmissions = false; // Whether the user can view all submissions.
|
||||
|
@ -230,14 +230,20 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModAssign.logView(this.assign.id, this.assign.name);
|
||||
await CoreUtils.ignoreErrors(AddonModAssign.logView(this.assign.id));
|
||||
|
||||
this.analyticsLogEvent('mod_assign_view_assign');
|
||||
|
||||
if (this.canViewAllSubmissions) {
|
||||
// User can see all submissions, log grading view.
|
||||
CoreUtils.ignoreErrors(AddonModAssign.logGradingView(this.assign.id, this.assign.name));
|
||||
await CoreUtils.ignoreErrors(AddonModAssign.logGradingView(this.assign.id));
|
||||
|
||||
this.analyticsLogEvent('mod_assign_view_grading_table', { sendUrl: false });
|
||||
} else if (this.canViewOwnSubmission) {
|
||||
// User can only see their own submission, log view the user submission.
|
||||
CoreUtils.ignoreErrors(AddonModAssign.logSubmissionView(this.assign.id, this.assign.name));
|
||||
await CoreUtils.ignoreErrors(AddonModAssign.logSubmissionView(this.assign.id));
|
||||
|
||||
this.analyticsLogEvent('mod_assign_view_submission_status', { sendUrl: false });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
"gradelocked": "This grade is locked or overridden in the gradebook.",
|
||||
"gradenotsynced": "Grade not synced",
|
||||
"gradeoutof": "Grade out of {{$a}}",
|
||||
"grading": "Grading",
|
||||
"gradingstatus": "Grading status",
|
||||
"groupsubmissionsettings": "Group submission settings",
|
||||
"hiddenuser": "Participant",
|
||||
|
@ -101,6 +102,7 @@
|
|||
"submittedlate": "Assignment was submitted {{$a}} late",
|
||||
"submittedovertime": "Assignment was submitted {{$a}} over the time limit",
|
||||
"submittedundertime": "Assignment was submitted {{$a}} under the time limit",
|
||||
"subpagetitle": "{{$a.contextname}} - {{$a.subpage}}",
|
||||
"syncblockedusercomponent": "user grade",
|
||||
"timelimit": "Time limit",
|
||||
"timemodified": "Last modified",
|
||||
|
|
|
@ -39,6 +39,7 @@ import { AddonModAssignOffline } from '../../services/assign-offline';
|
|||
import { AddonModAssignSync } from '../../services/assign-sync';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWSExternalFile } from '@services/ws';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that allows adding or editing an assigment submission.
|
||||
|
@ -226,6 +227,17 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave {
|
|||
// No offline data found.
|
||||
this.hasOffline = false;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_assign_save_submission',
|
||||
name: Translate.instant('addon.mod_assign.subpagetitle', {
|
||||
contextname: this.assign.name,
|
||||
subpage: Translate.instant('addon.mod_assign.editsubmission'),
|
||||
}),
|
||||
data: { id: this.assign.id, category: 'assign' },
|
||||
url: `/mod/assign/view.php?action=editsubmission&id=${this.moduleId}`,
|
||||
});
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting assigment data.');
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import {
|
|||
AddonModAssignManualSyncData,
|
||||
AddonModAssignAutoSyncData,
|
||||
} from '../../services/assign-sync';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays a list of submissions of an assignment.
|
||||
|
@ -168,6 +169,21 @@ export class AddonModAssignSubmissionListPage implements AfterViewInit, OnDestro
|
|||
protected async fetchAssignment(sync = false): Promise<void> {
|
||||
try {
|
||||
await this.submissions.getSource().loadAssignment(sync);
|
||||
|
||||
if (!this.assign) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'mod_assign_get_submissions',
|
||||
name: Translate.instant('addon.mod_assign.subpagetitle', {
|
||||
contextname: this.assign.name,
|
||||
subpage: Translate.instant('addon.mod_assign.grading'),
|
||||
}),
|
||||
data: { assignid: this.assign.id, category: 'assign' },
|
||||
url: `/mod/assign/view.php?id=${this.assign.cmid}&action=grading`,
|
||||
});
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting assigment data.');
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { AddonModAssignListFilterName, AddonModAssignSubmissionsSource } from '../../classes/submissions-source';
|
||||
import { AddonModAssignSubmissionComponent } from '../../components/submission/submission';
|
||||
import { AddonModAssign, AddonModAssignAssign } from '../../services/assign';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Page that displays a submission.
|
||||
|
@ -49,8 +52,29 @@ export class AddonModAssignSubmissionReviewPage implements OnInit, OnDestroy, Ca
|
|||
protected assign?: AddonModAssignAssign; // The assignment the submission belongs to.
|
||||
protected blindMarking = false; // Whether it uses blind marking.
|
||||
protected forceLeave = false; // To allow leaving the page without checking for changes.
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(protected route: ActivatedRoute) { }
|
||||
constructor(protected route: ActivatedRoute) {
|
||||
this.logView = CoreTime.once(() => {
|
||||
if (!this.assign) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.blindMarking ? this.blindId : this.submitId;
|
||||
const paramName = this.blindMarking ? 'blindid' : 'userid';
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_assign_get_submission_status',
|
||||
name: Translate.instant('addon.mod_assign.subpagetitle', {
|
||||
contextname: this.assign.name,
|
||||
subpage: Translate.instant('addon.mod_assign.grading'),
|
||||
}),
|
||||
data: { id, assignid: this.assign.id, category: 'assign' },
|
||||
url: `/mod/assign/view.php?id=${this.assign.cmid}&action=grader&${paramName}=${id}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -84,6 +108,7 @@ export class AddonModAssignSubmissionReviewPage implements OnInit, OnDestroy, Ca
|
|||
}
|
||||
|
||||
this.fetchSubmission().finally(() => {
|
||||
this.logView();
|
||||
this.loaded = true;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -878,23 +878,19 @@ export class AddonModAssignProvider {
|
|||
* Report an assignment submission as being viewed.
|
||||
*
|
||||
* @param assignid Assignment ID.
|
||||
* @param name Name of the assign.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logSubmissionView(assignid: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logSubmissionView(assignid: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModAssignViewSubmissionStatusWSParams = {
|
||||
assignid,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_assign_view_submission_status',
|
||||
params,
|
||||
AddonModAssignProvider.COMPONENT,
|
||||
assignid,
|
||||
name,
|
||||
'assign',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -903,23 +899,19 @@ export class AddonModAssignProvider {
|
|||
* Report an assignment grading table is being viewed.
|
||||
*
|
||||
* @param assignid Assignment ID.
|
||||
* @param name Name of the assign.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logGradingView(assignid: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logGradingView(assignid: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModAssignViewGradingTableWSParams = {
|
||||
assignid,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_assign_view_grading_table',
|
||||
params,
|
||||
AddonModAssignProvider.COMPONENT,
|
||||
assignid,
|
||||
name,
|
||||
'assign',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -928,23 +920,19 @@ export class AddonModAssignProvider {
|
|||
* Report an assign as being viewed.
|
||||
*
|
||||
* @param assignid Assignment ID.
|
||||
* @param name Name of the assign.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(assignid: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(assignid: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModAssignViewAssignWSParams = {
|
||||
assignid,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_assign_view_assign',
|
||||
params,
|
||||
AddonModAssignProvider.COMPONENT,
|
||||
assignid,
|
||||
name,
|
||||
'assign',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ import {
|
|||
export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit {
|
||||
|
||||
component = AddonModBBBService.COMPONENT;
|
||||
moduleName = 'bigbluebuttonbn';
|
||||
pluginName = 'bigbluebuttonbn';
|
||||
bbb?: AddonModBBBData;
|
||||
groupInfo?: CoreGroupInfo;
|
||||
groupId = 0;
|
||||
|
@ -226,7 +226,9 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModBBB.logView(this.bbb.id, this.bbb.name);
|
||||
await CoreUtils.ignoreErrors(AddonModBBB.logView(this.bbb.id));
|
||||
|
||||
this.analyticsLogEvent('mod_bigbluebuttonbn_view_bigbluebuttonbn');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -276,23 +276,19 @@ export class AddonModBBBService {
|
|||
* Report a BBB as being viewed.
|
||||
*
|
||||
* @param id BBB instance ID.
|
||||
* @param name Name of the BBB.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModBBBViewBigBlueButtonBNWSParams = {
|
||||
bigbluebuttonbnid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_bigbluebuttonbn_view_bigbluebuttonbn',
|
||||
params,
|
||||
AddonModBBBService.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'bigbluebuttonbn',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import { CoreCourseContentsPage } from '@features/course/pages/contents/contents
|
|||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { AddonModBookModuleHandlerService } from '../../services/handlers/module';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Component that displays a book entry page.
|
||||
|
@ -29,6 +30,7 @@ import { AddonModBookModuleHandlerService } from '../../services/handlers/module
|
|||
})
|
||||
export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy {
|
||||
|
||||
pluginName = 'book';
|
||||
showNumbers = true;
|
||||
addPadding = true;
|
||||
showBullets = false;
|
||||
|
@ -102,7 +104,9 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
|
|||
* @inheritdoc
|
||||
*/
|
||||
protected async logActivity(): Promise<void> {
|
||||
AddonModBook.logView(this.module.instance, undefined, this.module.name);
|
||||
await CoreUtils.ignoreErrors(AddonModBook.logView(this.module.instance));
|
||||
|
||||
this.analyticsLogEvent('mod_book_view_book');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,8 @@ import {
|
|||
AddonModBookProvider,
|
||||
AddonModBookTocChapter,
|
||||
} from '../../services/book';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
|
||||
/**
|
||||
* Page that displays a book contents.
|
||||
|
@ -286,7 +288,15 @@ export class AddonModBookContentsPage implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
// Chapter loaded, log view.
|
||||
await CoreUtils.ignoreErrors(AddonModBook.logView(this.module.instance, chapterId, this.module.name));
|
||||
await CoreUtils.ignoreErrors(AddonModBook.logView(this.module.instance, chapterId));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_book_view_book',
|
||||
name: this.module.name,
|
||||
data: { id: this.module.instance, category: 'book', chapterid: chapterId },
|
||||
url: CoreUrlUtils.addParamsToUrl(`/mod/book/view.php?id=${this.module.id}`, { chapterid: chapterId }),
|
||||
});
|
||||
|
||||
const currentChapterIndex = this.chapters.findIndex((chapter) => chapter.id == chapterId);
|
||||
const isLastChapter = currentChapterIndex < 0 || this.chapters[currentChapterIndex + 1] === undefined;
|
||||
|
|
|
@ -359,24 +359,20 @@ export class AddonModBookProvider {
|
|||
*
|
||||
* @param id Module ID.
|
||||
* @param chapterId Chapter ID.
|
||||
* @param name Name of the book.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, chapterId?: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(id: number, chapterId?: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModBookViewBookWSParams = {
|
||||
bookid: id,
|
||||
chapterid: chapterId,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_book_view_book',
|
||||
params,
|
||||
AddonModBookProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'book',
|
||||
{ chapterid: chapterId },
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import { AddonModChatModuleHandlerService } from '../../services/handlers/module
|
|||
export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit {
|
||||
|
||||
component = AddonModChatProvider.COMPONENT;
|
||||
moduleName = 'chat';
|
||||
pluginName = 'chat';
|
||||
chat?: AddonModChatChat;
|
||||
chatInfo?: {
|
||||
date: string;
|
||||
|
@ -85,7 +85,9 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModChat.logView(this.chat.id, this.chat.name);
|
||||
await AddonModChat.logView(this.chat.id);
|
||||
|
||||
this.analyticsLogEvent('mod_chat_view_chat');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,8 @@ import { Subscription } from 'rxjs';
|
|||
import { AddonModChatUsersModalComponent, AddonModChatUsersModalResult } from '../../components/users-modal/users-modal';
|
||||
import { AddonModChat, AddonModChatProvider, AddonModChatUser } from '../../services/chat';
|
||||
import { AddonModChatFormattedMessage, AddonModChatHelper } from '../../services/chat-helper';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays a chat session.
|
||||
|
@ -61,6 +63,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
|||
protected viewDestroyed = false;
|
||||
protected pollingRunning = false;
|
||||
protected users: AddonModChatUser[] = [];
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.currentUserId = CoreSites.getCurrentSiteUserId();
|
||||
|
@ -71,6 +74,16 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
|||
this.isOnline = CoreNetwork.isOnline();
|
||||
});
|
||||
});
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'mod_chat_get_chat_latest_messages',
|
||||
name: this.title,
|
||||
data: { chatid: this.chatId, category: 'chat' },
|
||||
url: `/mod/chat/gui_ajax/index.php?id=${this.chatId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,6 +101,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
|||
await this.fetchMessages();
|
||||
|
||||
this.startPolling();
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_chat.errorwhileconnecting', true);
|
||||
CoreNavigator.back();
|
||||
|
|
|
@ -21,6 +21,9 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { AddonModChat } from '../../services/chat';
|
||||
import { AddonModChatFormattedSessionMessage, AddonModChatHelper } from '../../services/chat-helper';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays list of chat session messages.
|
||||
|
@ -42,6 +45,19 @@ export class AddonModChatSessionMessagesPage implements OnInit {
|
|||
protected sessionStart!: number;
|
||||
protected sessionEnd!: number;
|
||||
protected groupId!: number;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'mod_chat_view_sessions',
|
||||
name: Translate.instant('addon.mod_chat.messages'),
|
||||
data: { chatid: this.chatId, category: 'chat' },
|
||||
url: `/mod/chat/report.php?id=${this.cmId}&start=${this.sessionStart}&end=${this.sessionEnd}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
|
@ -21,6 +21,9 @@ import { CoreGroupInfo } from '@services/groups';
|
|||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { AddonModChatSessionFormatted, AddonModChatSessionsSource } from '../../classes/chat-sessions-source';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Page that displays list of chat sessions.
|
||||
|
@ -29,14 +32,32 @@ import { AddonModChatSessionFormatted, AddonModChatSessionsSource } from '../../
|
|||
selector: 'page-addon-mod-chat-sessions',
|
||||
templateUrl: 'sessions.html',
|
||||
})
|
||||
export class AddonModChatSessionsPage implements AfterViewInit, OnDestroy {
|
||||
export class AddonModChatSessionsPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
||||
|
||||
sessions!: CoreListItemsManager<AddonModChatSessionFormatted, AddonModChatSessionsSource>;
|
||||
courseId?: number;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => {
|
||||
const source = this.sessions.getSource();
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'mod_chat_view_sessions',
|
||||
name: Translate.instant('addon.mod_chat.chatreport'),
|
||||
data: { chatid: source.CHAT_ID, category: 'chat' },
|
||||
url: `/mod/chat/report.php?id=${source.CM_ID}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
try {
|
||||
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
||||
const chatId = CoreNavigator.getRequiredRouteNumberParam('chatId');
|
||||
|
@ -91,6 +112,8 @@ export class AddonModChatSessionsPage implements AfterViewInit, OnDestroy {
|
|||
async fetchSessions(): Promise<void> {
|
||||
try {
|
||||
await this.sessions.load();
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true);
|
||||
}
|
||||
|
|
|
@ -87,23 +87,19 @@ export class AddonModChatProvider {
|
|||
* Report a chat as being viewed.
|
||||
*
|
||||
* @param id Chat instance ID.
|
||||
* @param name Name of the chat.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModChatViewChatWSParams = {
|
||||
chatid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_chat_view_chat',
|
||||
params,
|
||||
AddonModChatProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'chat',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ import { AddonModChoicePrefetchHandler } from '../../services/handlers/prefetch'
|
|||
export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit {
|
||||
|
||||
component = AddonModChoiceProvider.COMPONENT;
|
||||
moduleName = 'choice';
|
||||
pluginName = 'choice';
|
||||
|
||||
choice?: AddonModChoiceChoice;
|
||||
options: AddonModChoiceOption[] = [];
|
||||
|
@ -321,7 +321,9 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModChoice.logView(this.choice.id, this.choice.name);
|
||||
await AddonModChoice.logView(this.choice.id);
|
||||
|
||||
this.analyticsLogEvent('mod_choice_view_choice');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -386,6 +388,8 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
this.checkCompletion();
|
||||
}
|
||||
|
||||
this.analyticsLogEvent('mod_choice_view_choice', { data: { notify: 'choicesaved' } });
|
||||
|
||||
await this.dataUpdated(online);
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_choice.cannotsubmit', true);
|
||||
|
@ -412,6 +416,8 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
|
||||
this.content?.scrollToTop();
|
||||
|
||||
this.analyticsLogEvent('mod_choice_view_choice', { data: { action: 'delchoice' } });
|
||||
|
||||
// Refresh the data. Don't call dataUpdated because deleting an answer doesn't mark the choice as outdated.
|
||||
await this.refreshContent(false);
|
||||
} catch (error) {
|
||||
|
|
|
@ -365,23 +365,19 @@ export class AddonModChoiceProvider {
|
|||
* Report the choice as being viewed.
|
||||
*
|
||||
* @param id Choice ID.
|
||||
* @param name Name of the choice.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModChoiceViewChoiceWSParams = {
|
||||
choiceid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_choice_view_choice',
|
||||
params,
|
||||
AddonModChoiceProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'choice',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ const contentToken = '<!-- CORE-DATABASE-CONTENT-GOES-HERE -->';
|
|||
export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit, OnDestroy {
|
||||
|
||||
component = AddonModDataProvider.COMPONENT;
|
||||
moduleName = 'data';
|
||||
pluginName = 'data';
|
||||
|
||||
access?: AddonModDataGetDataAccessInformationWSResponse;
|
||||
database?: AddonModDataData;
|
||||
|
@ -420,8 +420,6 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
|
||||
try {
|
||||
await this.fetchEntriesData();
|
||||
// Log activity view for coherence with Moodle web.
|
||||
await this.logActivity();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
|
||||
} finally {
|
||||
|
@ -470,9 +468,6 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
|
||||
try {
|
||||
await this.fetchEntriesData();
|
||||
|
||||
// Log activity view for coherence with Moodle web.
|
||||
return this.logActivity();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
|
||||
}
|
||||
|
@ -535,7 +530,9 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
return;
|
||||
}
|
||||
|
||||
await AddonModData.logView(this.database.id, this.database.name);
|
||||
await AddonModData.logView(this.database.id);
|
||||
|
||||
this.analyticsLogEvent('mod_data_view_database');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,6 +43,8 @@ import { AddonModDataHelper } from '../../services/data-helper';
|
|||
import { CoreDom } from '@singletons/dom';
|
||||
import { AddonModDataEntryFieldInitialized } from '../../classes/base-field-plugin-component';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays the view edit page.
|
||||
|
@ -65,6 +67,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
protected initialSelectedGroup?: number;
|
||||
protected isEditing = false;
|
||||
protected originalData: AddonModDataEntryFields = {};
|
||||
protected logView: () => void;
|
||||
|
||||
entry?: AddonModDataEntry;
|
||||
fields: Record<number, AddonModDataField> = {};
|
||||
|
@ -94,6 +97,20 @@ export class AddonModDataEditPage implements OnInit {
|
|||
constructor() {
|
||||
this.siteId = CoreSites.getCurrentSiteId();
|
||||
this.editForm = new FormGroup({});
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
if (!this.database) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: this.isEditing ? 'mod_data_update_entry' : 'mod_data_add_entry',
|
||||
name: this.title,
|
||||
data: { databaseid: this.database.id, category: 'data' },
|
||||
url: '/mod/data/edit.php?' + (this.isEditing ? `d=${this.database.id}&rid=${this.entryId}` : `id=${this.moduleId}`),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,6 +247,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
}
|
||||
|
||||
this.editFormRender = this.displayEditFields();
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ import { AddonModDataProvider,
|
|||
} from '../../services/data';
|
||||
import { AddonModDataHelper } from '../../services/data-helper';
|
||||
import { AddonModDataSyncProvider } from '../../services/data-sync';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays the view entry page.
|
||||
|
@ -55,9 +57,9 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
|
|||
protected entryChangedObserver: CoreEventObserver; // It will observe the changed entry event.
|
||||
protected fields: Record<number, AddonModDataField> = {};
|
||||
protected fieldsArray: AddonModDataField[] = [];
|
||||
protected logAfterFetch = true;
|
||||
protected sortBy = 0;
|
||||
protected sortDirection = 'DESC';
|
||||
protected logView: () => void;
|
||||
|
||||
moduleId = 0;
|
||||
courseId!: number;
|
||||
|
@ -129,6 +131,8 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
}, this.siteId);
|
||||
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,13 +223,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
|
|||
access: this.access,
|
||||
};
|
||||
|
||||
if (this.logAfterFetch) {
|
||||
this.logAfterFetch = false;
|
||||
await CoreUtils.ignoreErrors(AddonModData.logView(this.database.id, this.database.name));
|
||||
|
||||
// Store module viewed because this page also updates recent accessed items block.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.moduleId);
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
if (!refresh) {
|
||||
// Some call failed, retry without using cache since it might be a new activity.
|
||||
|
@ -250,7 +248,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
|
|||
this.entryId = undefined;
|
||||
this.entry = undefined;
|
||||
this.entryLoaded = false;
|
||||
this.logAfterFetch = true;
|
||||
this.logView = CoreTime.once(() => this.performLogView()); // Log again after loading data.
|
||||
|
||||
await this.fetchEntryData();
|
||||
}
|
||||
|
@ -310,7 +308,6 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
|
|||
this.entry = undefined;
|
||||
this.entryId = undefined;
|
||||
this.entryLoaded = false;
|
||||
this.logAfterFetch = true;
|
||||
|
||||
await this.fetchEntryData();
|
||||
}
|
||||
|
@ -422,6 +419,28 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
|
|||
AddonModData.invalidateEntryData(this.database!.id, this.entryId!);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected async performLogView(): Promise<void> {
|
||||
if (!this.database) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModData.logView(this.database.id));
|
||||
|
||||
// Store module viewed because this page also updates recent accessed items block.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.moduleId);
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_data_view_database',
|
||||
name: this.database.name,
|
||||
data: { id: this.entryId, databaseid: this.database.id, category: 'data' },
|
||||
url: `/mod/data/view.php?d=${this.database.id}&rid=${this.entryId}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
|
|
@ -955,23 +955,19 @@ export class AddonModDataProvider {
|
|||
* Report the database as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the data.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModDataViewDatabaseWSParams = {
|
||||
databaseid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_data_view_database',
|
||||
params,
|
||||
AddonModDataProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'data',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -37,8 +37,7 @@ export class AddonModFeedbackAttemptsSource extends CoreRoutedItemsManagerSource
|
|||
anonymous?: AddonModFeedbackWSAnonAttempt[];
|
||||
anonymousTotal?: number;
|
||||
groupInfo?: CoreGroupInfo;
|
||||
|
||||
protected feedback?: AddonModFeedbackWSFeedback;
|
||||
feedback?: AddonModFeedbackWSFeedback;
|
||||
|
||||
constructor(courseId: number, cmId: number) {
|
||||
super();
|
||||
|
|
|
@ -56,7 +56,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
|
|||
@Input() group = 0;
|
||||
|
||||
component = AddonModFeedbackProvider.COMPONENT;
|
||||
moduleName = 'feedback';
|
||||
pluginName = 'feedback';
|
||||
feedback?: AddonModFeedbackWSFeedback;
|
||||
goPage?: number;
|
||||
items: AddonModFeedbackItem[] = [];
|
||||
|
@ -140,7 +140,18 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModFeedback.logView(this.feedback.id, this.feedback.name);
|
||||
await AddonModFeedback.logView(this.feedback.id);
|
||||
|
||||
this.callAnalyticsLogEvent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call analytics.
|
||||
*/
|
||||
protected callAnalyticsLogEvent(): void {
|
||||
this.analyticsLogEvent('mod_feedback_view_feedback', {
|
||||
url: this.tab === 'analysis' ? `/mod/feedback/analysis.php?id=${this.module.id}` : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -429,11 +440,16 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
|
|||
* @param tabName New tab name.
|
||||
*/
|
||||
tabChanged(tabName: string): void {
|
||||
const tabHasChanged = this.tab !== undefined && this.tab !== tabName;
|
||||
this.tab = tabName;
|
||||
|
||||
if (!this.tabsLoaded[this.tab]) {
|
||||
this.loadContent(false, false, true);
|
||||
}
|
||||
|
||||
if (tabHasChanged) {
|
||||
this.callAnalyticsLogEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,8 @@ import {
|
|||
AddonModFeedbackWSFeedback,
|
||||
} from '../../services/feedback';
|
||||
import { AddonModFeedbackAttempt, AddonModFeedbackFormItem, AddonModFeedbackHelper } from '../../services/feedback-helper';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays a feedback attempt review.
|
||||
|
@ -48,6 +50,7 @@ export class AddonModFeedbackAttemptPage implements OnInit, OnDestroy {
|
|||
loaded = false;
|
||||
|
||||
protected attemptId: number;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
|
||||
|
@ -60,6 +63,21 @@ export class AddonModFeedbackAttemptPage implements OnInit, OnDestroy {
|
|||
);
|
||||
|
||||
this.attempts = new AddonModFeedbackAttemptsSwipeManager(source);
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
if (!this.feedback) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_feedback_get_responses_analysis',
|
||||
name: this.feedback.name,
|
||||
data: { id: this.attemptId, feedbackid: this.feedback.id, category: 'feedback' },
|
||||
url: `/mod/feedback/show_entries.php?id=${this.cmId}` +
|
||||
(this.attempt ? `userid=${this.attempt.userid}` : '' ) + `&showcompleted=${this.attemptId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,6 +147,8 @@ export class AddonModFeedbackAttemptPage implements OnInit, OnDestroy {
|
|||
|
||||
return attemptItem;
|
||||
}).filter((itemData) => itemData); // Filter items with errors.
|
||||
|
||||
this.logView();
|
||||
} catch (message) {
|
||||
// Some call failed on fetch, go back.
|
||||
CoreDomUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true);
|
||||
|
|
|
@ -25,6 +25,8 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { AddonModFeedbackAttemptItem, AddonModFeedbackAttemptsSource } from '../../classes/feedback-attempts-source';
|
||||
import { AddonModFeedbackWSAnonAttempt, AddonModFeedbackWSAttempt } from '../../services/feedback';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays feedback attempts.
|
||||
|
@ -41,8 +43,25 @@ export class AddonModFeedbackAttemptsPage implements AfterViewInit, OnDestroy {
|
|||
fetchFailed = false;
|
||||
courseId?: number;
|
||||
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(protected route: ActivatedRoute) {
|
||||
this.promisedAttempts = new CorePromisedValue();
|
||||
|
||||
this.logView = CoreTime.once(() => {
|
||||
const source = this.attempts?.getSource();
|
||||
if (!source || !source.feedback) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'mod_feedback_get_responses_analysis',
|
||||
name: source.feedback.name,
|
||||
data: { feedbackid: source.feedback.id, category: 'feedback' },
|
||||
url: `/mod/feedback/show_entries.php?id=${source.CM_ID}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get attempts(): AddonModFeedbackAttemptsManager | null {
|
||||
|
@ -112,6 +131,8 @@ export class AddonModFeedbackAttemptsPage implements AfterViewInit, OnDestroy {
|
|||
|
||||
await attempts.getSource().loadFeedback();
|
||||
await attempts.load();
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
this.fetchFailed = true;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import {
|
|||
import { AddonModFeedbackFormItem, AddonModFeedbackHelper } from '../../services/feedback-helper';
|
||||
import { AddonModFeedbackSync } from '../../services/feedback-sync';
|
||||
import { AddonModFeedbackModuleHandlerService } from '../../services/handlers/module';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays feedback form.
|
||||
|
@ -122,7 +123,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
|
|||
}
|
||||
|
||||
try {
|
||||
await AddonModFeedback.logView(this.feedback.id, this.feedback.name, true);
|
||||
await AddonModFeedback.logView(this.feedback.id, true);
|
||||
|
||||
CoreCourse.checkModuleCompletion(this.courseId, this.module!.completiondata);
|
||||
} catch {
|
||||
|
@ -263,6 +264,8 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
|
|||
const itemsCopy = CoreUtils.clone(this.items); // Copy the array to avoid modifications.
|
||||
this.originalData = AddonModFeedbackHelper.getPageItemsResponses(itemsCopy);
|
||||
}
|
||||
|
||||
this.analyticsLogEvent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -435,6 +438,40 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log event in analytics.
|
||||
*/
|
||||
protected analyticsLogEvent(): void {
|
||||
if (!this.feedback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.preview) {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_feedback_get_items',
|
||||
name: this.feedback.name,
|
||||
data: { id: this.feedback.id, category: 'feedback' },
|
||||
url: `/mod/feedback/print.php?id=${this.cmId}&courseid=${this.courseId}`,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let url = '/mod/feedback/complete.php';
|
||||
if (!this.completed) {
|
||||
url += `?id=${this.cmId}` + (this.currentPage ? `&gopage=${this.currentPage}` : '') + `&courseid=${this.courseId}`;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: this.completed ? 'mod_feedback_get_feedback_access_information' : 'mod_feedback_get_page_items',
|
||||
name: this.feedback.name,
|
||||
data: { id: this.feedback.id, category: 'feedback', page: this.currentPage },
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
|
|
@ -20,6 +20,8 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { AddonModFeedback, AddonModFeedbackWSFeedback } from '../../services/feedback';
|
||||
import { AddonModFeedbackHelper, AddonModFeedbackNonRespondent } from '../../services/feedback-helper';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays feedback non respondents.
|
||||
|
@ -33,6 +35,7 @@ export class AddonModFeedbackNonRespondentsPage implements OnInit {
|
|||
protected cmId!: number;
|
||||
protected feedback?: AddonModFeedbackWSFeedback;
|
||||
protected page = 0;
|
||||
protected logView: () => void;
|
||||
|
||||
courseId!: number;
|
||||
selectedGroup!: number;
|
||||
|
@ -43,6 +46,22 @@ export class AddonModFeedbackNonRespondentsPage implements OnInit {
|
|||
loaded = false;
|
||||
loadMoreError = false;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => {
|
||||
if (!this.feedback) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'mod_feedback_get_non_respondents',
|
||||
name: this.feedback.name,
|
||||
data: { feedbackid: this.feedback.id, category: 'feedback' },
|
||||
url: `/mod/feedback/show_nonrespondents.php?id=${this.cmId}&courseid=${this.courseId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
@ -81,6 +100,8 @@ export class AddonModFeedbackNonRespondentsPage implements OnInit {
|
|||
this.selectedGroup = CoreGroups.validateGroupId(this.selectedGroup, this.groupInfo);
|
||||
|
||||
await this.loadGroupUsers(this.selectedGroup);
|
||||
|
||||
this.logView();
|
||||
} catch (message) {
|
||||
CoreDomUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true);
|
||||
|
||||
|
|
|
@ -1093,25 +1093,21 @@ export class AddonModFeedbackProvider {
|
|||
* Report the feedback as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the feedback.
|
||||
* @param formViewed True if form was viewed.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, name?: string, formViewed: boolean = false, siteId?: string): Promise<void> {
|
||||
async logView(id: number, formViewed: boolean = false, siteId?: string): Promise<void> {
|
||||
const params: AddonModFeedbackViewFeedbackWSParams = {
|
||||
feedbackid: id,
|
||||
moduleviewed: formViewed,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_feedback_view_feedback',
|
||||
params,
|
||||
AddonModFeedbackProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'feedback',
|
||||
{ moduleviewed: params.moduleviewed },
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import { Md5 } from 'ts-md5';
|
|||
import { AddonModFolder, AddonModFolderFolder, AddonModFolderProvider } from '../../services/folder';
|
||||
import { AddonModFolderFolderFormattedData, AddonModFolderHelper } from '../../services/folder-helper';
|
||||
import { AddonModFolderModuleHandlerService } from '../../services/handlers/module';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Component that displays a folder.
|
||||
|
@ -39,6 +40,7 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
|
|||
@Input() subfolder?: AddonModFolderFolderFormattedData; // Subfolder to show.
|
||||
|
||||
component = AddonModFolderProvider.COMPONENT;
|
||||
pluginName = 'folder';
|
||||
contents?: AddonModFolderFolderFormattedData;
|
||||
|
||||
constructor(@Optional() courseContentsPage?: CoreCourseContentsPage) {
|
||||
|
@ -119,7 +121,9 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
|
|||
* @inheritdoc
|
||||
*/
|
||||
protected async logActivity(): Promise<void> {
|
||||
await AddonModFolder.logView(this.module.instance, this.module.name);
|
||||
await CoreUtils.ignoreErrors(AddonModFolder.logView(this.module.instance));
|
||||
|
||||
this.analyticsLogEvent('mod_folder_view_folder');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -126,23 +126,19 @@ export class AddonModFolderProvider {
|
|||
* Report a folder as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the folder.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModFolderViewFolderWSParams = {
|
||||
folderid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_folder_view_folder',
|
||||
params,
|
||||
AddonModFolderProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'folder',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
||||
|
||||
component = AddonModForumProvider.COMPONENT;
|
||||
moduleName = 'forum';
|
||||
pluginName = 'forum';
|
||||
descriptionNote?: string;
|
||||
promisedDiscussions: CorePromisedValue<AddonModForumDiscussionsManager>;
|
||||
discussionsItems: AddonModForumDiscussionItem[] = [];
|
||||
|
@ -708,12 +708,14 @@ class AddonModForumDiscussionsManager extends CoreListItemsManager<AddonModForum
|
|||
}
|
||||
|
||||
try {
|
||||
await AddonModForum.logView(forum.id, forum.name);
|
||||
await AddonModForum.logView(forum.id);
|
||||
|
||||
CoreCourse.checkModuleCompletion(this.page.courseId, this.page.module.completiondata);
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
this.page.analyticsLogEvent('mod_forum_view_forum');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,6 +52,7 @@ import { CoreForms } from '@singletons/form';
|
|||
import { CoreFileEntry } from '@services/file-helper';
|
||||
import { AddonModForumSharedPostFormData } from '../../pages/discussion/discussion';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Components that shows a discussion post, its attachments and the action buttons allowed (reply, etc.).
|
||||
|
@ -141,6 +142,9 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
* Deletes an online post.
|
||||
*/
|
||||
async deletePost(): Promise<void> {
|
||||
// Log analytics even if the user cancels for consistency with LMS.
|
||||
this.analyticsLogEvent('mod_forum_delete_post', `/mod/forum/post.php?delete=${this.post.id}`);
|
||||
|
||||
try {
|
||||
await CoreDomUtils.showDeleteConfirm('addon.mod_forum.deletesure');
|
||||
|
||||
|
@ -290,6 +294,8 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
}
|
||||
|
||||
this.scrollToForm();
|
||||
|
||||
this.analyticsLogEvent('mod_forum_add_discussion_post', `/mod/forum/post.php?reply=${this.post.id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -314,6 +320,8 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
);
|
||||
|
||||
this.scrollToForm();
|
||||
|
||||
this.analyticsLogEvent('mod_forum_update_discussion_post', `/mod/forum/post.php?edit=${this.post.id}`);
|
||||
} catch {
|
||||
// Cancelled.
|
||||
}
|
||||
|
@ -554,4 +562,24 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log analytics event.
|
||||
*
|
||||
* @param wsName WS name.
|
||||
* @param url URL.
|
||||
*/
|
||||
protected analyticsLogEvent(wsName: string, url: string): void {
|
||||
if (this.post.id <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: wsName,
|
||||
name: this.post.subject,
|
||||
data: { id: this.post.id, forumid: this.forum.id, category: 'forum' },
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import {
|
|||
import { AddonModForumHelper } from '../../services/forum-helper';
|
||||
import { AddonModForumOffline } from '../../services/forum-offline';
|
||||
import { AddonModForumSync, AddonModForumSyncProvider } from '../../services/forum-sync';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
type SortType = 'flat-newest' | 'flat-oldest' | 'nested';
|
||||
|
||||
|
@ -562,19 +563,7 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes
|
|||
|
||||
if (forceMarkAsRead || (hasUnreadPosts && this.trackPosts)) {
|
||||
// Add log in Moodle and mark unread posts as readed.
|
||||
AddonModForum.logDiscussionView(this.discussionId, this.forumId || -1, this.forum.name).catch(() => {
|
||||
// Ignore errors.
|
||||
}).finally(() => {
|
||||
if (!this.courseId || !this.cmId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger mark read posts.
|
||||
CoreEvents.trigger(AddonModForumProvider.MARK_READ_EVENT, {
|
||||
courseId: this.courseId,
|
||||
moduleId: this.cmId,
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
});
|
||||
this.logDiscussionView(forceMarkAsRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -854,6 +843,35 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes
|
|||
return posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log discussion as viewed. This will also mark the posts as read.
|
||||
*
|
||||
* @param logAnalytics Whether to log analytics too or not.
|
||||
*/
|
||||
protected async logDiscussionView(logAnalytics = false): Promise<void> {
|
||||
await CoreUtils.ignoreErrors(AddonModForum.logDiscussionView(this.discussionId, this.forumId || -1));
|
||||
|
||||
if (logAnalytics) {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_forum_view_forum_discussion',
|
||||
name: this.startingPost?.subject ?? this.forum.name ?? '',
|
||||
data: { id: this.discussionId, forumid: this.forumId, category: 'forum' },
|
||||
url: `/mod/forum/discuss.php?d=${this.discussionId}` + (this.postId ? `#p${this.postId}` : ''),
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.courseId || !this.cmId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger mark read posts.
|
||||
CoreEvents.trigger(AddonModForumProvider.MARK_READ_EVENT, {
|
||||
courseId: this.courseId,
|
||||
moduleId: this.cmId,
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,6 +44,8 @@ import { AddonModForumDiscussionsSwipeManager } from '../../classes/forum-discus
|
|||
import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { AddonModForumDiscussionsSource } from '../../classes/forum-discussions-source';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
type NewDiscussionData = {
|
||||
subject: string;
|
||||
|
@ -105,8 +107,19 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea
|
|||
protected originalData?: Partial<NewDiscussionData>;
|
||||
protected forceLeave = false;
|
||||
protected initialGroupId?: number;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(protected route: ActivatedRoute, @Optional() protected splitView: CoreSplitViewComponent) {}
|
||||
constructor(protected route: ActivatedRoute, @Optional() protected splitView: CoreSplitViewComponent) {
|
||||
this.logView = CoreTime.once(() => {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_forum_add_discussion',
|
||||
name: Translate.instant('addon.mod_forum.addanewdiscussion'),
|
||||
data: { id: this.forumId, category: 'forum' },
|
||||
url: '/mod/forum/post.php',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -309,6 +322,8 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea
|
|||
}
|
||||
|
||||
this.showForm = true;
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_forum.errorgetgroups', true);
|
||||
|
||||
|
|
|
@ -996,23 +996,19 @@ export class AddonModForumProvider {
|
|||
* Report a forum as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the forum.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
logView(id: number, siteId?: string): Promise<void> {
|
||||
const params = {
|
||||
forumid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_forum_view_forum',
|
||||
params,
|
||||
AddonModForumProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'forum',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -1022,23 +1018,19 @@ export class AddonModForumProvider {
|
|||
*
|
||||
* @param id Discussion ID.
|
||||
* @param forumId Forum ID.
|
||||
* @param name Name of the forum.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logDiscussionView(id: number, forumId: number, name?: string, siteId?: string): Promise<void> {
|
||||
logDiscussionView(id: number, forumId: number, siteId?: string): Promise<void> {
|
||||
const params = {
|
||||
discussionid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_forum_view_forum_discussion',
|
||||
params,
|
||||
AddonModForumProvider.COMPONENT,
|
||||
forumId,
|
||||
name,
|
||||
'forum',
|
||||
params,
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
|||
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
||||
|
||||
component = AddonModGlossaryProvider.COMPONENT;
|
||||
moduleName = 'glossary';
|
||||
pluginName = 'glossary';
|
||||
|
||||
canAdd = false;
|
||||
loadMoreError = false;
|
||||
|
@ -482,12 +482,14 @@ class AddonModGlossaryEntriesManager extends CoreListItemsManager<AddonModGlossa
|
|||
}
|
||||
|
||||
try {
|
||||
await AddonModGlossary.logView(glossary.id, viewMode, glossary.name);
|
||||
await AddonModGlossary.logView(glossary.id, viewMode);
|
||||
|
||||
CoreCourse.checkModuleCompletion(this.page.courseId, this.page.module.completiondata);
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
this.page.analyticsLogEvent('mod_glossary_view_glossary', { data: { mode: viewMode } });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,7 @@ import {
|
|||
} from '../../services/glossary';
|
||||
import { AddonModGlossaryHelper } from '../../services/glossary-helper';
|
||||
import { AddonModGlossaryOffline } from '../../services/glossary-offline';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays the edit form.
|
||||
|
@ -76,6 +77,7 @@ export class AddonModGlossaryEditPage implements OnInit, CanLeave {
|
|||
|
||||
originalData?: AddonModGlossaryFormData;
|
||||
|
||||
protected entry?: AddonModGlossaryEntry;
|
||||
protected syncId?: string;
|
||||
protected syncObserver?: CoreEventObserver;
|
||||
protected isDestroyed = false;
|
||||
|
@ -99,6 +101,7 @@ export class AddonModGlossaryEditPage implements OnInit, CanLeave {
|
|||
} else if (entrySlug) {
|
||||
const { entry } = await AddonModGlossary.getEntry(Number(entrySlug));
|
||||
|
||||
this.entry = entry;
|
||||
this.editorExtraParams.timecreated = entry.timecreated;
|
||||
this.handler = new AddonModGlossaryOnlineFormHandler(this, entry);
|
||||
} else {
|
||||
|
@ -127,6 +130,18 @@ export class AddonModGlossaryEditPage implements OnInit, CanLeave {
|
|||
await this.handler.loadData(this.glossary);
|
||||
|
||||
this.loaded = true;
|
||||
|
||||
if (this.handler instanceof AddonModGlossaryOfflineFormHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_glossary_get_glossaries_by_courses',
|
||||
name: this.glossary.name,
|
||||
data: { id: this.glossary.id, category: 'glossary' },
|
||||
url: '/mod/glossary/edit.php' + (this.entry ? `?cmid=${this.cmId}&id=${this.entry.id}` : ''),
|
||||
});
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_glossary.errorloadingglossary', true);
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ import {
|
|||
AddonModGlossaryProvider,
|
||||
GLOSSARY_ENTRY_UPDATED,
|
||||
} from '../../services/glossary';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays a glossary entry.
|
||||
|
@ -70,7 +72,19 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
|||
courseId!: number;
|
||||
cmId!: number;
|
||||
|
||||
constructor(@Optional() protected splitView: CoreSplitViewComponent, protected route: ActivatedRoute) {}
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(@Optional() protected splitView: CoreSplitViewComponent, protected route: ActivatedRoute) {
|
||||
this.logView = CoreTime.once(async () => {
|
||||
if (!this.onlineEntry || !this.glossary || !this.componentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModGlossary.logEntryView(this.onlineEntry.id, this.componentId));
|
||||
|
||||
this.analyticsLogEvent('mod_glossary_get_entry_by_id', `/mod/glossary/showentry.php?eid=${this.onlineEntry.id}`);
|
||||
});
|
||||
}
|
||||
|
||||
get entry(): AddonModGlossaryEntry | AddonModGlossaryOfflineEntry | undefined {
|
||||
return this.onlineEntry ?? this.offlineEntry;
|
||||
|
@ -128,12 +142,6 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
|||
try {
|
||||
if (onlineEntryId) {
|
||||
await this.loadOnlineEntry(onlineEntryId);
|
||||
|
||||
if (!this.glossary || !this.componentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModGlossary.logEntryView(onlineEntryId, this.componentId, this.glossary?.name));
|
||||
} else if (offlineEntryTimeCreated) {
|
||||
await this.loadOfflineEntry(offlineEntryTimeCreated);
|
||||
}
|
||||
|
@ -161,6 +169,12 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
|||
* Delete entry.
|
||||
*/
|
||||
async deleteEntry(): Promise<void> {
|
||||
// Log analytics even if the user cancels for consistency with LMS.
|
||||
this.analyticsLogEvent(
|
||||
'mod_glossary_delete_entry',
|
||||
`/mod/glossary/deleteentry.php?id=${this.glossary?.id}&mode=delete&entry=${this.onlineEntry?.id}`,
|
||||
);
|
||||
|
||||
const glossaryId = this.glossary?.id;
|
||||
const cancelled = await CoreUtils.promiseFails(
|
||||
CoreDomUtils.showConfirm(Translate.instant('addon.mod_glossary.areyousuredelete')),
|
||||
|
@ -250,6 +264,8 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
|||
this.canEdit = canUpdateEntries && !!result.permissions?.canupdate;
|
||||
|
||||
await this.loadGlossary();
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_glossary.errorloadingentry', true);
|
||||
}
|
||||
|
@ -321,6 +337,26 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
|||
AddonModGlossary.invalidateEntry(this.onlineEntry.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log analytics event.
|
||||
*
|
||||
* @param wsName WS name.
|
||||
* @param url URL.
|
||||
*/
|
||||
protected analyticsLogEvent(wsName: string, url: string): void {
|
||||
if (!this.onlineEntry || !this.glossary) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: wsName,
|
||||
name: this.onlineEntry.concept,
|
||||
data: { id: this.onlineEntry.id, glossaryid: this.glossary.id, category: 'glossary' },
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1020,23 +1020,19 @@ export class AddonModGlossaryProvider {
|
|||
*
|
||||
* @param glossaryId Glossary ID.
|
||||
* @param mode The mode in which the glossary was viewed.
|
||||
* @param name Name of the glossary.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
*/
|
||||
async logView(glossaryId: number, mode: string, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(glossaryId: number, mode: string, siteId?: string): Promise<void> {
|
||||
const params: AddonModGlossaryViewGlossaryWSParams = {
|
||||
id: glossaryId,
|
||||
mode: mode,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_glossary_view_glossary',
|
||||
params,
|
||||
AddonModGlossaryProvider.COMPONENT,
|
||||
glossaryId,
|
||||
name,
|
||||
'glossary',
|
||||
{ mode },
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -1046,22 +1042,18 @@ export class AddonModGlossaryProvider {
|
|||
*
|
||||
* @param entryId Entry ID.
|
||||
* @param glossaryId Glossary ID.
|
||||
* @param name Name of the glossary.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
*/
|
||||
async logEntryView(entryId: number, glossaryId: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logEntryView(entryId: number, glossaryId: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModGlossaryViewEntryWSParams = {
|
||||
id: entryId,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_glossary_view_entry',
|
||||
params,
|
||||
AddonModGlossaryProvider.COMPONENT,
|
||||
glossaryId,
|
||||
name,
|
||||
'glossary',
|
||||
{ entryid: entryId },
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
|
|||
@Output() onActivityFinish = new EventEmitter<boolean>();
|
||||
|
||||
component = AddonModH5PActivityProvider.COMPONENT;
|
||||
moduleName = 'h5pactivity';
|
||||
pluginName = 'h5pactivity';
|
||||
|
||||
h5pActivity?: AddonModH5PActivityData; // The H5P activity object.
|
||||
accessInfo?: AddonModH5PActivityAccessInfo; // Info about the user capabilities.
|
||||
|
@ -441,9 +441,11 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
|
|||
this.playing = true;
|
||||
|
||||
// Mark the activity as viewed.
|
||||
await AddonModH5PActivity.logView(this.h5pActivity.id, this.h5pActivity.name, this.siteId);
|
||||
await AddonModH5PActivity.logView(this.h5pActivity.id, this.siteId);
|
||||
|
||||
this.checkCompletion();
|
||||
|
||||
this.analyticsLogEvent('mod_h5pactivity_view_h5pactivity');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,8 @@ import {
|
|||
AddonModH5PActivityData,
|
||||
AddonModH5PActivityAttemptResults,
|
||||
} from '../../services/h5pactivity';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays results of an attempt.
|
||||
|
@ -45,7 +47,28 @@ export class AddonModH5PActivityAttemptResultsPage implements OnInit {
|
|||
cmId!: number;
|
||||
|
||||
protected attemptId!: number;
|
||||
protected fetchSuccess = false;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(async () => {
|
||||
if (!this.h5pActivity) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(
|
||||
this.h5pActivity.id,
|
||||
{ attemptId: this.attemptId },
|
||||
));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_h5pactivity_log_report_viewed',
|
||||
name: this.h5pActivity.name,
|
||||
data: { id: this.h5pActivity.id, attemptid: this.attemptId, category: 'h5pactivity' },
|
||||
url: `/mod/h5pactivity/report.php?a=${this.h5pActivity.id}&attemptid=${this.attemptId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -92,14 +115,7 @@ export class AddonModH5PActivityAttemptResultsPage implements OnInit {
|
|||
|
||||
await this.fetchUserProfile();
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(
|
||||
this.h5pActivity.id,
|
||||
this.h5pActivity.name,
|
||||
{ attemptId: this.attemptId },
|
||||
));
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempt.');
|
||||
} finally {
|
||||
|
|
|
@ -26,6 +26,8 @@ import {
|
|||
AddonModH5PActivityData,
|
||||
AddonModH5PActivityUserAttempts,
|
||||
} from '../../services/h5pactivity';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays user attempts of a certain user.
|
||||
|
@ -46,7 +48,28 @@ export class AddonModH5PActivityUserAttemptsPage implements OnInit {
|
|||
isCurrentUser = false;
|
||||
|
||||
protected userId!: number;
|
||||
protected fetchSuccess = false;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(async () => {
|
||||
if (!this.h5pActivity) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(
|
||||
this.h5pActivity.id,
|
||||
{ userId: this.userId },
|
||||
));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_h5pactivity_log_report_viewed',
|
||||
name: this.h5pActivity.name,
|
||||
data: { id: this.h5pActivity.id, userid: this.userId, category: 'h5pactivity' },
|
||||
url: `/mod/h5pactivity/report.php?a=${this.h5pActivity.id}&userid=${this.userId}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -94,14 +117,7 @@ export class AddonModH5PActivityUserAttemptsPage implements OnInit {
|
|||
this.fetchUserProfile(),
|
||||
]);
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(
|
||||
this.h5pActivity.id,
|
||||
this.h5pActivity.name,
|
||||
{ userId: this.userId },
|
||||
));
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
|
||||
} finally {
|
||||
|
|
|
@ -25,6 +25,8 @@ import {
|
|||
AddonModH5PActivityProvider,
|
||||
AddonModH5PActivityUserAttempts,
|
||||
} from '../../services/h5pactivity';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays all users that can attempt an H5P activity.
|
||||
|
@ -45,7 +47,25 @@ export class AddonModH5PActivityUsersAttemptsPage implements OnInit {
|
|||
canLoadMore = false;
|
||||
|
||||
protected page = 0;
|
||||
protected fetchSuccess = false;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(async () => {
|
||||
if (!this.h5pActivity) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(this.h5pActivity.id));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'mod_h5pactivity_log_report_viewed',
|
||||
name: this.h5pActivity.name,
|
||||
data: { id: this.h5pActivity.id, category: 'h5pactivity' },
|
||||
url: `/mod/h5pactivity/report.php?a=${this.h5pActivity.id}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -90,10 +110,7 @@ export class AddonModH5PActivityUsersAttemptsPage implements OnInit {
|
|||
this.fetchUsers(refresh),
|
||||
]);
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(this.h5pActivity.id, this.h5pActivity.name));
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
|
||||
} finally {
|
||||
|
|
|
@ -776,23 +776,19 @@ export class AddonModH5PActivityProvider {
|
|||
* Report an H5P activity as being viewed.
|
||||
*
|
||||
* @param id H5P activity ID.
|
||||
* @param name Name of the activity.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModH5PActivityViewH5pactivityWSParams = {
|
||||
h5pactivityid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_h5pactivity_view_h5pactivity',
|
||||
params,
|
||||
AddonModH5PActivityProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'h5pactivity',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -801,11 +797,10 @@ export class AddonModH5PActivityProvider {
|
|||
* Report an H5P activity report as being viewed.
|
||||
*
|
||||
* @param id H5P activity ID.
|
||||
* @param name Name of the activity.
|
||||
* @param options Options.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logViewReport(id: number, name?: string, options: AddonModH5PActivityViewReportOptions = {}): Promise<void> {
|
||||
async logViewReport(id: number, options: AddonModH5PActivityViewReportOptions = {}): Promise<void> {
|
||||
const site = await CoreSites.getSite(options.siteId);
|
||||
|
||||
if (!site.wsAvailable('mod_h5pactivity_log_report_viewed')) {
|
||||
|
@ -819,14 +814,11 @@ export class AddonModH5PActivityProvider {
|
|||
attemptid: options.attemptId,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_h5pactivity_log_report_viewed',
|
||||
params,
|
||||
AddonModH5PActivityProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'h5pactivity',
|
||||
{},
|
||||
site.getId(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import { CoreCourseContentsPage } from '@features/course/pages/contents/contents
|
|||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { AddonModImscpProvider, AddonModImscp, AddonModImscpTocItem } from '../../services/imscp';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Component that displays a IMSCP.
|
||||
|
@ -30,6 +31,7 @@ import { AddonModImscpProvider, AddonModImscp, AddonModImscpTocItem } from '../.
|
|||
export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceComponent implements OnInit {
|
||||
|
||||
component = AddonModImscpProvider.COMPONENT;
|
||||
pluginName = 'imscp';
|
||||
|
||||
items: AddonModImscpTocItem[] = [];
|
||||
hasStarted = false;
|
||||
|
@ -100,7 +102,9 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
|
|||
* @inheritdoc
|
||||
*/
|
||||
protected async logActivity(): Promise<void> {
|
||||
await AddonModImscp.logView(this.module.instance, this.module.name);
|
||||
await CoreUtils.ignoreErrors(AddonModImscp.logView(this.module.instance));
|
||||
|
||||
this.analyticsLogEvent('mod_imscp_view_imscp');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -271,7 +271,6 @@ export class AddonModImscpProvider {
|
|||
* Report a IMSCP as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the imscp.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
|
@ -280,14 +279,11 @@ export class AddonModImscpProvider {
|
|||
imscpid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_imscp_view_imscp',
|
||||
params,
|
||||
AddonModImscpProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'imscp',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
@Input() action?: string; // The "action" to display first.
|
||||
|
||||
component = AddonModLessonProvider.COMPONENT;
|
||||
moduleName = 'lesson';
|
||||
pluginName = 'lesson';
|
||||
|
||||
lesson?: AddonModLessonLessonWSData; // The lesson.
|
||||
selectedTab?: number; // The initial selected tab.
|
||||
|
@ -372,7 +372,16 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
return;
|
||||
}
|
||||
|
||||
await AddonModLesson.logViewLesson(this.lesson.id, this.password, this.lesson.name);
|
||||
await CoreUtils.ignoreErrors(AddonModLesson.logViewLesson(this.lesson.id, this.password));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call analytics.
|
||||
*/
|
||||
protected callAnalyticsLogEvent(): void {
|
||||
this.analyticsLogEvent('mod_lesson_view_lesson', {
|
||||
url: this.selectedTab === 1 ? `/mod/lesson/report.php?id=${this.module.id}&action=reportoverview` : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -435,13 +444,19 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
* First tab selected.
|
||||
*/
|
||||
indexSelected(): void {
|
||||
const tabHasChanged = this.selectedTab !== 0;
|
||||
this.selectedTab = 0;
|
||||
|
||||
if (tabHasChanged) {
|
||||
this.callAnalyticsLogEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports tab selected.
|
||||
*/
|
||||
reportsSelected(): void {
|
||||
const tabHasChanged = this.selectedTab !== 1;
|
||||
this.selectedTab = 1;
|
||||
|
||||
if (!this.groupInfo) {
|
||||
|
@ -449,6 +464,10 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
CoreDomUtils.showErrorModalDefault(error, 'Error getting report.');
|
||||
});
|
||||
}
|
||||
|
||||
if (tabHasChanged) {
|
||||
this.callAnalyticsLogEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,6 +54,7 @@ import {
|
|||
import { AddonModLessonOffline } from '../../services/lesson-offline';
|
||||
import { AddonModLessonSync } from '../../services/lesson-sync';
|
||||
import { CoreFormFields, CoreForms } from '@singletons/form';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that allows attempting and reviewing a lesson.
|
||||
|
@ -446,6 +447,8 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
|
|||
this.reviewPageId = Number(params.pageid);
|
||||
}
|
||||
}
|
||||
|
||||
this.logPageLoaded(AddonModLessonProvider.LESSON_EOL, Translate.instant('addon.mod_lesson.congratulations'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -615,6 +618,44 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
|
|||
} else {
|
||||
this.showRetake = false;
|
||||
}
|
||||
|
||||
this.logPageLoaded(pageId, data.page?.title ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log page loaded.
|
||||
*
|
||||
* @param pageId Page ID.
|
||||
*/
|
||||
protected logPageLoaded(pageId: number, title: string): void {
|
||||
if (!this.lesson) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_lesson_get_page_data',
|
||||
name: this.lesson.name + ': ' + title,
|
||||
data: { id: this.lesson.id, pageid: pageId, category: 'lesson' },
|
||||
url: `/mod/lesson/view.php?id=${this.lesson.id}&pageid=${pageId}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log continue page.
|
||||
*/
|
||||
protected logContinuePageLoaded(): void {
|
||||
if (!this.lesson) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_lesson_process_page',
|
||||
name: this.lesson.name + ': ' + Translate.instant('addon.mod_lesson.continue'),
|
||||
data: { id: this.lesson.id, category: 'lesson' },
|
||||
url: '/mod/lesson/continue.php',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -715,6 +756,8 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
|
|||
pageId: result.newpageid,
|
||||
});
|
||||
}
|
||||
|
||||
this.logContinuePageLoaded();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error processing page');
|
||||
} finally {
|
||||
|
|
|
@ -35,6 +35,7 @@ import {
|
|||
} from '../../services/lesson';
|
||||
import { AddonModLessonAnswerData, AddonModLessonHelper } from '../../services/lesson-helper';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays a retake made by a certain user.
|
||||
|
@ -59,6 +60,11 @@ export class AddonModLessonUserRetakePage implements OnInit {
|
|||
protected userId?: number; // User ID to see the retakes.
|
||||
protected retakeNumber?: number; // Number of the initial retake to see.
|
||||
protected previousSelectedRetake?: number; // To be able to detect the previous selected retake when it has changed.
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -93,6 +99,8 @@ export class AddonModLessonUserRetakePage implements OnInit {
|
|||
|
||||
try {
|
||||
await this.setRetake(retakeNumber);
|
||||
|
||||
this.performLogView();
|
||||
} catch (error) {
|
||||
this.selectedRetake = this.previousSelectedRetake ?? this.selectedRetake;
|
||||
CoreDomUtils.showErrorModal(CoreUtils.addDataNotDownloadedError(error, 'Error getting attempt.'));
|
||||
|
@ -160,6 +168,8 @@ export class AddonModLessonUserRetakePage implements OnInit {
|
|||
this.student.profileimageurl = user?.profileimageurl;
|
||||
|
||||
await this.setRetake(this.selectedRetake);
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting data.', true);
|
||||
}
|
||||
|
@ -243,6 +253,23 @@ export class AddonModLessonUserRetakePage implements OnInit {
|
|||
return formattedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected performLogView(): void {
|
||||
if (!this.lesson) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_lesson_get_user_attempt',
|
||||
name: this.lesson.name + ': ' + Translate.instant('addon.mod_lesson.detailedstats'),
|
||||
data: { id: this.lesson.id, userid: this.userId, try: this.selectedRetake, category: 'lesson' },
|
||||
url: `/mod/lesson/report.php?id=${this.cmId}&action=reportdetail&userid=${this.userId}&try=${this.selectedRetake}`,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2951,11 +2951,10 @@ export class AddonModLessonProvider {
|
|||
*
|
||||
* @param id Module ID.
|
||||
* @param password Lesson password (if any).
|
||||
* @param name Name of the assign.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logViewLesson(id: number, password?: string, name?: string, siteId?: string): Promise<void> {
|
||||
async logViewLesson(id: number, password?: string, siteId?: string): Promise<void> {
|
||||
const params: AddonModLessonViewLessonWSParams = {
|
||||
lessonid: id,
|
||||
};
|
||||
|
@ -2964,14 +2963,11 @@ export class AddonModLessonProvider {
|
|||
params.password = password;
|
||||
}
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_lesson_view_lesson',
|
||||
params,
|
||||
AddonModLessonProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'lesson',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import { AddonModLtiHelper } from '../../services/lti-helper';
|
|||
export class AddonModLtiIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit {
|
||||
|
||||
component = AddonModLtiProvider.COMPONENT;
|
||||
moduleName = 'lti';
|
||||
pluginName = 'lti';
|
||||
displayDescription = false;
|
||||
|
||||
lti?: AddonModLtiLti; // The LTI object.
|
||||
|
|
|
@ -22,6 +22,7 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { makeSingleton } from '@singletons';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { AddonModLti, AddonModLtiLti } from './lti';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Service that provides some helper functions for LTI.
|
||||
|
@ -86,7 +87,7 @@ export class AddonModLtiHelperProvider {
|
|||
const launchData = await AddonModLti.getLtiLaunchData(lti.id);
|
||||
|
||||
// "View" LTI without blocking the UI.
|
||||
this.logViewAndCheckCompletion(courseId, module, lti.id, lti.name, siteId);
|
||||
this.logViewAndCheckCompletion(courseId, module, lti.id, siteId);
|
||||
|
||||
// Launch LTI.
|
||||
return AddonModLti.launch(launchData.endpoint, launchData.parameters);
|
||||
|
@ -111,16 +112,23 @@ export class AddonModLtiHelperProvider {
|
|||
courseId: number,
|
||||
module: CoreCourseModuleData,
|
||||
ltiId: number,
|
||||
name?: string,
|
||||
siteId?: string,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await AddonModLti.logView(ltiId, name, siteId);
|
||||
await AddonModLti.logView(ltiId,siteId);
|
||||
|
||||
CoreCourse.checkModuleCompletion(courseId, module.completiondata);
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_lti_view_lti',
|
||||
name: module.name,
|
||||
data: { id: module.instance, category: 'lti' },
|
||||
url: `/mod/lti/view.php?id=${module.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -272,14 +272,11 @@ export class AddonModLtiProvider {
|
|||
ltiid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_lti_view_lti',
|
||||
params,
|
||||
AddonModLtiProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'lti',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import { AddonModPageHelper } from '../../services/page-helper';
|
|||
export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComponent implements OnInit {
|
||||
|
||||
component = AddonModPageProvider.COMPONENT;
|
||||
pluginName = 'page';
|
||||
contents?: string;
|
||||
displayDescription = false;
|
||||
displayTimemodified = true;
|
||||
|
@ -114,7 +115,9 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
|
|||
* @inheritdoc
|
||||
*/
|
||||
protected async logActivity(): Promise<void> {
|
||||
await AddonModPage.logView(this.module.instance, this.module.name);
|
||||
await CoreUtils.ignoreErrors(AddonModPage.logView(this.module.instance));
|
||||
|
||||
this.analyticsLogEvent('mod_page_view_page');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -141,23 +141,19 @@ export class AddonModPageProvider {
|
|||
* Report a page as being viewed.
|
||||
*
|
||||
* @param pageid Module ID.
|
||||
* @param name Name of the page.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(pageid: number, name?: string, siteId?: string): Promise<void> {
|
||||
logView(pageid: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModPageViewPageWSParams = {
|
||||
pageid,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_page_view_page',
|
||||
params,
|
||||
AddonModPageProvider.COMPONENT,
|
||||
pageid,
|
||||
name,
|
||||
'page',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ import {
|
|||
export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit, OnDestroy {
|
||||
|
||||
component = AddonModQuizProvider.COMPONENT;
|
||||
moduleName = 'quiz';
|
||||
pluginName = 'quiz';
|
||||
quiz?: AddonModQuizQuizData; // The quiz.
|
||||
now?: number; // Current time.
|
||||
syncTime?: string; // Last synchronization time.
|
||||
|
@ -386,7 +386,9 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModQuiz.logViewQuiz(this.quiz.id, this.quiz.name);
|
||||
await CoreUtils.ignoreErrors(AddonModQuiz.logViewQuiz(this.quiz.id));
|
||||
|
||||
this.analyticsLogEvent('mod_quiz_view_quiz');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,7 @@ import { CoreDom } from '@singletons/dom';
|
|||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
||||
import { CoreWSError } from '@classes/errors/wserror';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that allows attempting a quiz.
|
||||
|
@ -534,9 +535,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
|||
// @todo MOBILE-4350: This is called before getting the attempt data in sequential quizzes as a workaround for a bug
|
||||
// in the LMS. Once the bug has been fixed, this should be reverted.
|
||||
if (this.isSequential) {
|
||||
await CoreUtils.ignoreErrors(
|
||||
AddonModQuiz.logViewAttempt(this.attempt.id, page, this.preflightData, this.offline, this.quiz),
|
||||
);
|
||||
await this.logViewPage(page);
|
||||
}
|
||||
|
||||
const data = await AddonModQuiz.getAttemptData(this.attempt.id, page, this.preflightData, {
|
||||
|
@ -569,15 +568,55 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
|||
// Mark the page as viewed.
|
||||
if (!this.isSequential) {
|
||||
// @todo MOBILE-4350: Undo workaround.
|
||||
CoreUtils.ignoreErrors(
|
||||
AddonModQuiz.logViewAttempt(this.attempt.id, page, this.preflightData, this.offline, this.quiz),
|
||||
);
|
||||
await this.logViewPage(page);
|
||||
}
|
||||
|
||||
// Start looking for changes.
|
||||
this.autoSave.startCheckChangesProcess(this.quiz, this.attempt, this.preflightData, this.offline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view a page.
|
||||
*
|
||||
* @param page Page viewed.
|
||||
*/
|
||||
protected async logViewPage(page: number): Promise<void> {
|
||||
if (!this.quiz || !this.attempt) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModQuiz.logViewAttempt(this.attempt.id, page, this.preflightData, this.offline));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_quiz_view_attempt',
|
||||
name: this.quiz.name,
|
||||
data: { id: this.attempt.id, quizid: this.quiz.id, page, category: 'quiz' },
|
||||
url: `/mod/quiz/attempt.php?attempt=${this.attempt.id}&cmid=${this.cmId}` + (page > 0 ? `&page=${page}` : ''),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view summary.
|
||||
*/
|
||||
protected async logViewSummary(): Promise<void> {
|
||||
if (!this.quiz || !this.attempt) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(
|
||||
AddonModQuiz.logViewAttemptSummary(this.attempt.id, this.preflightData, this.quiz.id),
|
||||
);
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_quiz_view_attempt_summary',
|
||||
name: this.quiz.name,
|
||||
data: { id: this.attempt.id, quizid: this.quiz.id, category: 'quiz' },
|
||||
url: `/mod/quiz/summary.php?attempt=${this.attempt.id}&cmid=${this.cmId}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh attempt data.
|
||||
*/
|
||||
|
@ -618,10 +657,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
|||
|
||||
this.dueDateWarning = AddonModQuiz.getAttemptDueDateWarning(this.quiz, this.attempt);
|
||||
|
||||
// Log summary as viewed.
|
||||
CoreUtils.ignoreErrors(
|
||||
AddonModQuiz.logViewAttemptSummary(this.attempt.id, this.preflightData, this.quiz.id, this.quiz.name),
|
||||
);
|
||||
this.logViewSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,7 @@ import {
|
|||
AddonModQuizWSAdditionalData,
|
||||
} from '../../services/quiz';
|
||||
import { AddonModQuizHelper } from '../../services/quiz-helper';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that allows reviewing a quiz attempt.
|
||||
|
@ -73,11 +74,15 @@ export class AddonModQuizReviewPage implements OnInit {
|
|||
protected attemptId!: number; // The attempt being reviewed.
|
||||
protected currentPage!: number; // The current page being reviewed.
|
||||
protected options?: AddonModQuizCombinedReviewOptions; // Review options.
|
||||
protected fetchSuccess = false;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(
|
||||
protected elementRef: ElementRef,
|
||||
) {
|
||||
this.logView = CoreTime.once(() => this.performLogView(true, {
|
||||
showAllDisabled: !this.showAll,
|
||||
page: this.currentPage,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,6 +132,8 @@ export class AddonModQuizReviewPage implements OnInit {
|
|||
|
||||
try {
|
||||
await this.loadPage(page);
|
||||
|
||||
this.performLogView(false, { page });
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_quiz.errorgetquestions', true);
|
||||
} finally {
|
||||
|
@ -156,12 +163,7 @@ export class AddonModQuizReviewPage implements OnInit {
|
|||
// Load questions.
|
||||
await this.loadPage(this.currentPage);
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
CoreUtils.ignoreErrors(
|
||||
AddonModQuiz.logViewAttemptReview(this.attemptId, this.quiz.id, this.quiz.name),
|
||||
);
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_quiz.errorgetquiz', true);
|
||||
}
|
||||
|
@ -325,11 +327,13 @@ export class AddonModQuizReviewPage implements OnInit {
|
|||
/**
|
||||
* Switch mode: all questions in same page OR one page at a time.
|
||||
*/
|
||||
switchMode(): void {
|
||||
async switchMode(): Promise<void> {
|
||||
this.showAll = !this.showAll;
|
||||
|
||||
// Load all questions or first page, depending on the mode.
|
||||
this.loadPage(this.showAll ? -1 : 0);
|
||||
await this.loadPage(this.showAll ? -1 : 0);
|
||||
|
||||
this.performLogView(false, { showAllDisabled: !this.showAll });
|
||||
}
|
||||
|
||||
async openNavigation(): Promise<void> {
|
||||
|
@ -351,6 +355,37 @@ export class AddonModQuizReviewPage implements OnInit {
|
|||
this.changePage(modalData.page, modalData.slot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform log view.
|
||||
*
|
||||
* @param logInLMS Whether to log in LMS too or only in analytics.
|
||||
* @param options Other options.
|
||||
*/
|
||||
protected async performLogView(logInLMS = false, options: LogViewOptions = {}): Promise<void> {
|
||||
if (!this.quiz) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (logInLMS) {
|
||||
await CoreUtils.ignoreErrors(AddonModQuiz.logViewAttemptReview(this.attemptId, this.quiz.id));
|
||||
}
|
||||
|
||||
let url = `/mod/quiz/review.php?attempt=${this.attemptId}&cmid=${this.cmId}`;
|
||||
if (options.showAllDisabled) {
|
||||
url += '&showall=0';
|
||||
} else if (options.page && options.page > 0) {
|
||||
url += `&page=${ options.page}`;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_quiz_view_attempt_review',
|
||||
name: this.quiz.name,
|
||||
data: { id: this.attemptId, quizid: this.quiz.id, page: options.page, category: 'quiz' },
|
||||
url: url,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -359,3 +394,8 @@ export class AddonModQuizReviewPage implements OnInit {
|
|||
type QuizQuestion = CoreQuestionQuestionParsed & {
|
||||
readableMark?: string;
|
||||
};
|
||||
|
||||
type LogViewOptions = {
|
||||
page?: number; // Page being viewed (if viewing pages);
|
||||
showAllDisabled?: boolean; // Whether the showAll option has just been disabled.
|
||||
};
|
||||
|
|
|
@ -404,13 +404,11 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
|
|||
|
||||
if (!finish) {
|
||||
// Answers sent, now set the current page.
|
||||
// Don't pass the quiz instance because we don't want to trigger a Firebase event in this case.
|
||||
await CoreUtils.ignoreErrors(AddonModQuiz.logViewAttempt(
|
||||
onlineAttempt.id,
|
||||
offlineAttempt.currentpage,
|
||||
preflightData,
|
||||
false,
|
||||
undefined,
|
||||
siteId,
|
||||
));
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
|||
import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
|
||||
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
|
||||
import { CoreGradesFormattedItem, CoreGradesHelper } from '@features/grades/services/grades-helper';
|
||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
||||
import {
|
||||
CoreQuestion,
|
||||
CoreQuestionQuestionParsed,
|
||||
|
@ -1535,7 +1534,6 @@ export class AddonModQuizProvider {
|
|||
* @param page Page number.
|
||||
* @param preflightData Preflight required data (like password).
|
||||
* @param offline Whether attempt is offline.
|
||||
* @param quiz Quiz instance. If set, a Firebase event will be stored.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
|
@ -1544,7 +1542,6 @@ export class AddonModQuizProvider {
|
|||
page: number = 0,
|
||||
preflightData: Record<string, string> = {},
|
||||
offline?: boolean,
|
||||
quiz?: AddonModQuizQuizWSData,
|
||||
siteId?: string,
|
||||
): Promise<void> {
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
@ -1564,16 +1561,6 @@ export class AddonModQuizProvider {
|
|||
if (offline) {
|
||||
promises.push(AddonModQuizOffline.setAttemptCurrentPage(attemptId, page, site.getId()));
|
||||
}
|
||||
if (quiz) {
|
||||
CorePushNotifications.logViewEvent(
|
||||
quiz.id,
|
||||
quiz.name,
|
||||
'quiz',
|
||||
'mod_quiz_view_attempt',
|
||||
{ attemptid: attemptId, page },
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
@ -1583,23 +1570,19 @@ export class AddonModQuizProvider {
|
|||
*
|
||||
* @param attemptId Attempt ID.
|
||||
* @param quizId Quiz ID.
|
||||
* @param name Name of the quiz.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logViewAttemptReview(attemptId: number, quizId: number, name?: string, siteId?: string): Promise<void> {
|
||||
logViewAttemptReview(attemptId: number, quizId: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModQuizViewAttemptReviewWSParams = {
|
||||
attemptid: attemptId,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_quiz_view_attempt_review',
|
||||
params,
|
||||
AddonModQuizProvider.COMPONENT,
|
||||
quizId,
|
||||
name,
|
||||
'quiz',
|
||||
params,
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -1610,7 +1593,6 @@ export class AddonModQuizProvider {
|
|||
* @param attemptId Attempt ID.
|
||||
* @param preflightData Preflight required data (like password).
|
||||
* @param quizId Quiz ID.
|
||||
* @param name Name of the quiz.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
|
@ -1618,7 +1600,6 @@ export class AddonModQuizProvider {
|
|||
attemptId: number,
|
||||
preflightData: Record<string, string>,
|
||||
quizId: number,
|
||||
name?: string,
|
||||
siteId?: string,
|
||||
): Promise<void> {
|
||||
const params: AddonModQuizViewAttemptSummaryWSParams = {
|
||||
|
@ -1630,14 +1611,11 @@ export class AddonModQuizProvider {
|
|||
),
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_quiz_view_attempt_summary',
|
||||
params,
|
||||
AddonModQuizProvider.COMPONENT,
|
||||
quizId,
|
||||
name,
|
||||
'quiz',
|
||||
{ attemptid: attemptId },
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -1646,23 +1624,19 @@ export class AddonModQuizProvider {
|
|||
* Report a quiz as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the quiz.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logViewQuiz(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
logViewQuiz(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModQuizViewQuizWSParams = {
|
||||
quizid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_quiz_view_quiz',
|
||||
params,
|
||||
AddonModQuizProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'quiz',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import { CorePlatform } from '@services/platform';
|
|||
export class AddonModResourceIndexComponent extends CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy {
|
||||
|
||||
component = AddonModResourceProvider.COMPONENT;
|
||||
pluginName = 'resource';
|
||||
|
||||
mode = '';
|
||||
src = '';
|
||||
|
@ -188,7 +189,9 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
|
|||
* @inheritdoc
|
||||
*/
|
||||
protected async logActivity(): Promise<void> {
|
||||
await AddonModResource.logView(this.module.instance, this.module.name);
|
||||
await CoreUtils.ignoreErrors(AddonModResource.logView(this.module.instance));
|
||||
|
||||
this.analyticsLogEvent('mod_resource_view_resource');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,7 @@ import { CoreUtilsOpenFileOptions } from '@services/utils/utils';
|
|||
import { makeSingleton, Translate } from '@singletons';
|
||||
import { CorePath } from '@singletons/path';
|
||||
import { AddonModResource, AddonModResourceProvider } from './resource';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Service that provides helper functions for resources.
|
||||
|
@ -206,6 +207,14 @@ export class AddonModResourceHelperProvider {
|
|||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_resource_view_resource',
|
||||
name: module.name,
|
||||
data: { id: module.instance, category: 'resource' },
|
||||
url: `/mod/resource/view.php?id=${module.id}`,
|
||||
});
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_resource.errorwhileloadingthecontent', true);
|
||||
} finally {
|
||||
|
|
|
@ -146,23 +146,19 @@ export class AddonModResourceProvider {
|
|||
* Report the resource as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the resource.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModResourceViewResourceWSParams = {
|
||||
resourceid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_resource_view_resource',
|
||||
params,
|
||||
AddonModResourceProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'resource',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
@Input() autoPlayData?: AddonModScormAutoPlayData; // Data to use to play the SCORM automatically.
|
||||
|
||||
component = AddonModScormProvider.COMPONENT;
|
||||
moduleName = 'scorm';
|
||||
pluginName = 'scorm';
|
||||
|
||||
scorm?: AddonModScormScorm; // The SCORM object.
|
||||
currentOrganization: Partial<AddonModScormOrganization> & { identifier: string} = {
|
||||
|
@ -361,7 +361,9 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModScorm.logView(this.scorm.id, this.scorm.name);
|
||||
await CoreUtils.ignoreErrors(AddonModScorm.logView(this.scorm.id));
|
||||
|
||||
this.analyticsLogEvent('mod_scorm_view_scorm');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,6 +35,7 @@ import {
|
|||
} from '../../services/scorm';
|
||||
import { AddonModScormHelper, AddonModScormTOCScoWithIcon } from '../../services/scorm-helper';
|
||||
import { AddonModScormSync } from '../../services/scorm-sync';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that allows playing a SCORM.
|
||||
|
@ -442,8 +443,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
|
|||
this.markCompleted(sco);
|
||||
}
|
||||
|
||||
// Trigger SCO launch event.
|
||||
CoreUtils.ignoreErrors(AddonModScorm.logLaunchSco(this.scorm.id, sco.id, this.scorm.name));
|
||||
this.logEvent(sco.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -581,6 +581,27 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
|
|||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log event.
|
||||
*/
|
||||
protected async logEvent(scoId: number): Promise<void> {
|
||||
await CoreUtils.ignoreErrors(AddonModScorm.logLaunchSco(this.scorm.id, scoId));
|
||||
|
||||
let url = '/mod/scorm/player.php';
|
||||
if (this.scorm.popup) {
|
||||
url += `?a=${this.scorm.id}¤torg=${this.organizationId}&scoid=${scoId}` +
|
||||
`&display=popup&mode=${this.mode}`;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_scorm_get_scorm_user_data',
|
||||
name: this.scorm.name,
|
||||
data: { id: this.scorm.id, scoid: scoId, organization: this.organizationId, category: 'scorm' },
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
|
|
@ -1420,24 +1420,20 @@ export class AddonModScormProvider {
|
|||
*
|
||||
* @param scormId SCORM ID.
|
||||
* @param scoId SCO ID.
|
||||
* @param name Name of the SCORM.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logLaunchSco(scormId: number, scoId: number, name?: string, siteId?: string): Promise<void> {
|
||||
logLaunchSco(scormId: number, scoId: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModScormLaunchScoWSParams = {
|
||||
scormid: scormId,
|
||||
scoid: scoId,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_scorm_launch_sco',
|
||||
params,
|
||||
AddonModScormProvider.COMPONENT,
|
||||
scormId,
|
||||
name,
|
||||
'scorm',
|
||||
{ scoid: scoId },
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -1446,23 +1442,19 @@ export class AddonModScormProvider {
|
|||
* Report a SCORM as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the SCORM.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModScormViewScormWSParams = {
|
||||
scormid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_scorm_view_scorm',
|
||||
params,
|
||||
AddonModScormProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'scorm',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import {
|
|||
AddonModSurveySyncProvider,
|
||||
AddonModSurveySyncResult,
|
||||
} from '../../services/survey-sync';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Component that displays a survey.
|
||||
|
@ -50,7 +51,7 @@ import {
|
|||
export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit {
|
||||
|
||||
component = AddonModSurveyProvider.COMPONENT;
|
||||
moduleName = 'survey';
|
||||
pluginName = 'survey';
|
||||
|
||||
survey?: AddonModSurveySurvey;
|
||||
questions: AddonModSurveyQuestionFormatted[] = [];
|
||||
|
@ -168,7 +169,9 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModSurvey.logView(this.survey.id, this.survey.name);
|
||||
await CoreUtils.ignoreErrors(AddonModSurvey.logView(this.survey.id));
|
||||
|
||||
this.analyticsLogEvent('mod_survey_view_survey');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -208,7 +208,6 @@ export class AddonModSurveyProvider {
|
|||
* Report the survey as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the assign.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
|
@ -217,14 +216,11 @@ export class AddonModSurveyProvider {
|
|||
surveyid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_survey_view_survey',
|
||||
params,
|
||||
AddonModSurveyProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'survey',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import { AddonModUrlHelper } from '../../services/url-helper';
|
|||
export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceComponent implements OnInit {
|
||||
|
||||
component = AddonModUrlProvider.COMPONENT;
|
||||
pluginName = 'url';
|
||||
|
||||
url?: string;
|
||||
name?: string;
|
||||
|
@ -153,12 +154,14 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo
|
|||
*/
|
||||
protected async logView(): Promise<void> {
|
||||
try {
|
||||
await AddonModUrl.logView(this.module.instance, this.module.name);
|
||||
await AddonModUrl.logView(this.module.instance);
|
||||
|
||||
this.checkCompletion();
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
this.analyticsLogEvent('mod_url_view_url');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,6 +26,7 @@ import { makeSingleton } from '@singletons';
|
|||
import { AddonModUrlIndexComponent } from '../../components/index/index';
|
||||
import { AddonModUrl } from '../url';
|
||||
import { AddonModUrlHelper } from '../url-helper';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Handler to support url modules.
|
||||
|
@ -64,14 +65,7 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple
|
|||
* @param courseId The course ID.
|
||||
*/
|
||||
const openUrl = async (module: CoreCourseModuleData, courseId: number): Promise<void> => {
|
||||
try {
|
||||
if (module.instance) {
|
||||
await AddonModUrl.logView(module.instance, module.name);
|
||||
CoreCourse.checkModuleCompletion(module.course, module.completiondata);
|
||||
}
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
await this.logView(module);
|
||||
|
||||
CoreCourse.storeModuleViewed(courseId, module.id);
|
||||
|
||||
|
@ -196,5 +190,27 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple
|
|||
return !iconUrl?.startsWith('assets/img/files/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log module viewed.
|
||||
*/
|
||||
protected async logView(module: CoreCourseModuleData): Promise<void> {
|
||||
try {
|
||||
if (module.instance) {
|
||||
await AddonModUrl.logView(module.instance);
|
||||
CoreCourse.checkModuleCompletion(module.course, module.completiondata);
|
||||
}
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_url_view_url',
|
||||
name: module.name,
|
||||
data: { id: module.instance, category: 'url' },
|
||||
url: `/mod/url/view.php?id=${module.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
export const AddonModUrlModuleHandler = makeSingleton(AddonModUrlModuleHandlerService);
|
||||
|
|
|
@ -210,23 +210,19 @@ export class AddonModUrlProvider {
|
|||
* Report the url as being viewed.
|
||||
*
|
||||
* @param id Module ID.
|
||||
* @param name Name of the assign.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModUrlViewUrlWSParams = {
|
||||
urlid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_url_view_url',
|
||||
params,
|
||||
AddonModUrlProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'url',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
|
||||
component = AddonModWikiProvider.COMPONENT;
|
||||
componentId?: number;
|
||||
moduleName = 'wiki';
|
||||
pluginName = 'wiki';
|
||||
groupWiki = false;
|
||||
|
||||
isOnline = false;
|
||||
|
@ -327,9 +327,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
|
||||
await this.showLoadingAndFetch(true, false);
|
||||
|
||||
if (this.currentPage && this.wiki) {
|
||||
CoreUtils.ignoreErrors(AddonModWiki.logPageView(this.currentPage, this.wiki.id, this.wiki.name));
|
||||
}
|
||||
this.currentPage && this.logPageViewed(this.currentPage);
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
}
|
||||
|
||||
|
@ -443,12 +441,60 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
if (!this.pageId) {
|
||||
await AddonModWiki.logView(this.wiki.id, this.wiki.name);
|
||||
} else {
|
||||
if (this.pageId) {
|
||||
// View page.
|
||||
this.checkCompletionAfterLog = false;
|
||||
CoreUtils.ignoreErrors(AddonModWiki.logPageView(this.pageId, this.wiki.id, this.wiki.name));
|
||||
await this.logPageViewed(this.pageId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await AddonModWiki.logView(this.wiki.id);
|
||||
|
||||
if (this.groupId === undefined && this.userId === undefined) {
|
||||
// View initial page.
|
||||
this.analyticsLogEvent('mod_wiki_view_wiki', { name: this.currentPageObj?.title });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Viewing a different subwiki.
|
||||
const hasPersonalSubwikis = this.loadedSubwikis.some(subwiki => subwiki.userid > 0);
|
||||
const hasGroupSubwikis = this.loadedSubwikis.some(subwiki => subwiki.groupid > 0);
|
||||
|
||||
let url = `/mod/wiki/view.php?wid=${this.wiki.id}&title=${this.wiki.firstpagetitle}`;
|
||||
if (hasPersonalSubwikis && hasGroupSubwikis) {
|
||||
url += `&groupanduser=${this.groupId}-${this.userId}`;
|
||||
} else if (hasPersonalSubwikis) {
|
||||
url += `&uid=${this.userId}`;
|
||||
} else {
|
||||
url += `&group=${this.groupId}`;
|
||||
}
|
||||
|
||||
this.analyticsLogEvent('mod_wiki_view_wiki', {
|
||||
name: this.currentPageObj?.title,
|
||||
data: { subwiki: this.subwikiId, userid: this.userId, groupid: this.groupId },
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log page viewed.
|
||||
*
|
||||
* @param pageId Page ID.
|
||||
*/
|
||||
protected async logPageViewed(pageId: number): Promise<void> {
|
||||
if (!this.wiki) {
|
||||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(AddonModWiki.logPageView(pageId, this.wiki.id));
|
||||
|
||||
this.analyticsLogEvent('mod_wiki_view_page', {
|
||||
name: this.currentPageObj?.title,
|
||||
data: { pageid: this.pageId },
|
||||
url: `/mod/wiki/view.php?page=${this.pageId}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -619,7 +665,9 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
homeView: this.getWikiHomeView(),
|
||||
moduleId: this.module.id,
|
||||
courseId: this.courseId,
|
||||
selectedId: this.currentPage,
|
||||
selectedTitle: this.currentPageObj && this.currentPageObj.title,
|
||||
wiki: this.wiki,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { ModalController } from '@singletons';
|
||||
import { AddonModWikiPageDBRecord } from '../../services/database/wiki';
|
||||
import { AddonModWikiSubwikiPage } from '../../services/wiki';
|
||||
import { AddonModWikiSubwikiPage, AddonModWikiWiki } from '../../services/wiki';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Modal to display the map of a Wiki.
|
||||
|
@ -27,6 +28,8 @@ import { AddonModWikiSubwikiPage } from '../../services/wiki';
|
|||
export class AddonModWikiMapModalComponent implements OnInit {
|
||||
|
||||
@Input() pages: (AddonModWikiSubwikiPage | AddonModWikiPageDBRecord)[] = [];
|
||||
@Input() wiki?: AddonModWikiWiki;
|
||||
@Input() selectedId?: number;
|
||||
@Input() selectedTitle?: string;
|
||||
@Input() moduleId?: number;
|
||||
@Input() courseId?: number;
|
||||
|
@ -39,6 +42,16 @@ export class AddonModWikiMapModalComponent implements OnInit {
|
|||
*/
|
||||
ngOnInit(): void {
|
||||
this.constructMap();
|
||||
|
||||
if (this.selectedId && this.wiki) {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_wiki_get_subwiki_pages',
|
||||
name: this.selectedTitle || this.wiki.name,
|
||||
data: { id: this.wiki.id, pageid: this.selectedId, category: 'wiki' },
|
||||
url: `/mod/wiki/map.php?pageid=${this.selectedId}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,6 +30,7 @@ import { CoreForms } from '@singletons/form';
|
|||
import { AddonModWiki, AddonModWikiProvider } from '../../services/wiki';
|
||||
import { AddonModWikiOffline } from '../../services/wiki-offline';
|
||||
import { AddonModWikiSync } from '../../services/wiki-sync';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that allows adding or editing a wiki page.
|
||||
|
@ -64,6 +65,7 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave {
|
|||
protected editOffline = false; // Whether the user is editing an offline page.
|
||||
protected subwikiFiles: CoreWSFile[] = []; // List of files of the subwiki.
|
||||
protected originalContent?: string; // The original page content.
|
||||
protected originalTitle?: string; // The original page title.
|
||||
protected version?: number; // Page version.
|
||||
protected renewLockInterval?: number; // An interval to renew the lock every certain time.
|
||||
protected forceLeave = false; // To allow leaving the page without checking for changes.
|
||||
|
@ -89,17 +91,17 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave {
|
|||
this.groupId = CoreNavigator.getRouteNumberParam('groupId');
|
||||
this.userId = CoreNavigator.getRouteNumberParam('userId');
|
||||
|
||||
let pageTitle = CoreNavigator.getRouteParam<string>('pageTitle');
|
||||
pageTitle = pageTitle ? CoreTextUtils.cleanTags(pageTitle.replace(/\+/g, ' '), { singleLine: true }) : '';
|
||||
const pageTitle = CoreNavigator.getRouteParam<string>('pageTitle');
|
||||
this.originalTitle = pageTitle ? CoreTextUtils.cleanTags(pageTitle.replace(/\+/g, ' '), { singleLine: true }) : '';
|
||||
|
||||
this.canEditTitle = !pageTitle;
|
||||
this.title = pageTitle ?
|
||||
Translate.instant('addon.mod_wiki.editingpage', { $a: pageTitle }) :
|
||||
this.canEditTitle = !this.originalTitle;
|
||||
this.title = this.originalTitle ?
|
||||
Translate.instant('addon.mod_wiki.editingpage', { $a: this.originalTitle }) :
|
||||
Translate.instant('addon.mod_wiki.newpagehdr');
|
||||
this.blockId = AddonModWikiSync.getSubwikiBlockId(this.subwikiId, this.wikiId, this.userId, this.groupId);
|
||||
|
||||
// Create the form group and its controls.
|
||||
this.pageForm.addControl('title', this.formBuilder.control(pageTitle));
|
||||
this.pageForm.addControl('title', this.formBuilder.control(this.originalTitle));
|
||||
this.pageForm.addControl('text', this.contentControl);
|
||||
|
||||
// Block the wiki so it cannot be synced.
|
||||
|
@ -111,8 +113,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave {
|
|||
if (this.section) {
|
||||
this.editorExtraParams.section = this.section;
|
||||
}
|
||||
} else if (pageTitle) {
|
||||
this.editorExtraParams.pagetitle = pageTitle;
|
||||
} else if (this.originalTitle) {
|
||||
this.editorExtraParams.pagetitle = this.originalTitle;
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -126,6 +128,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave {
|
|||
this.blockId = newBlockId;
|
||||
CoreSync.blockOperation(this.component, this.blockId);
|
||||
}
|
||||
|
||||
this.logView();
|
||||
}
|
||||
} finally {
|
||||
this.loaded = true;
|
||||
|
@ -158,6 +162,7 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave {
|
|||
this.wikiId = pageContents.wikiid;
|
||||
this.subwikiId = pageContents.subwikiid;
|
||||
this.title = Translate.instant('addon.mod_wiki.editingpage', { $a: pageContents.title });
|
||||
this.originalTitle = pageContents.title;
|
||||
this.groupId = pageContents.groupid;
|
||||
this.userId = pageContents.userid;
|
||||
canEdit = pageContents.caneditpage;
|
||||
|
@ -466,6 +471,34 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected logView(): void {
|
||||
let url: string;
|
||||
if (this.pageId) {
|
||||
url = `/mod/wiki/edit.php?pageid=${this.pageId}` +
|
||||
(this.section ? `§ion=${this.section.replace(/ /g, '+')}` : '');
|
||||
} else if (this.originalTitle) {
|
||||
const title = this.originalTitle.replace(/ /g, '+');
|
||||
if (this.subwikiId) {
|
||||
url = `/mod/wiki/create.php?swid=${this.subwikiId}&title=${title}&action=new`;
|
||||
} else {
|
||||
url = `/mod/wiki/create.php?wid=${this.wikiId}&group=${this.groupId ?? 0}&uid=${this.userId ?? 0}&title=${title}`;
|
||||
}
|
||||
} else {
|
||||
url = `/mod/wiki/create.php?action=new&wid=${this.wikiId}&swid=${this.subwikiId}`;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: this.pageId ? 'mod_wiki_edit_page' : 'mod_wiki_new_page',
|
||||
name: this.originalTitle ?? Translate.instant('addon.mod_wiki.newpagehdr'),
|
||||
data: { id: this.wikiId, subwiki: this.subwikiId, category: 'wiki' },
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
|
|
@ -621,23 +621,19 @@ export class AddonModWikiProvider {
|
|||
*
|
||||
* @param id Page ID.
|
||||
* @param wikiId Wiki ID.
|
||||
* @param name Name of the wiki.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logPageView(id: number, wikiId: number, name?: string, siteId?: string): Promise<void> {
|
||||
logPageView(id: number, wikiId: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModWikiViewPageWSParams = {
|
||||
pageid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_wiki_view_page',
|
||||
params,
|
||||
AddonModWikiProvider.COMPONENT,
|
||||
wikiId,
|
||||
name,
|
||||
'wiki',
|
||||
params,
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -646,23 +642,19 @@ export class AddonModWikiProvider {
|
|||
* Report the wiki as being viewed.
|
||||
*
|
||||
* @param id Wiki ID.
|
||||
* @param name Name of the wiki.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModWikiViewWikiWSParams = {
|
||||
wikiid: id,
|
||||
};
|
||||
|
||||
return CoreCourseLogHelper.logSingle(
|
||||
return CoreCourseLogHelper.log(
|
||||
'mod_wiki_view_wiki',
|
||||
params,
|
||||
AddonModWikiProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'wiki',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
|
|||
@Input() group = 0;
|
||||
|
||||
component = AddonModWorkshopProvider.COMPONENT;
|
||||
moduleName = 'workshop';
|
||||
pluginName = 'workshop';
|
||||
|
||||
workshop?: AddonModWorkshopData;
|
||||
page = 0;
|
||||
|
@ -255,7 +255,9 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
|
|||
return; // Shouldn't happen.
|
||||
}
|
||||
|
||||
await AddonModWorkshop.logView(this.workshop.id, this.workshop.name);
|
||||
await CoreUtils.ignoreErrors(AddonModWorkshop.logView(this.workshop.id));
|
||||
|
||||
this.analyticsLogEvent('mod_workshop_view_workshop');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,8 @@ import {
|
|||
import { AddonModWorkshopHelper, AddonModWorkshopSubmissionAssessmentWithFormData } from '../../services/workshop-helper';
|
||||
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||
import { AddonModWorkshopSyncProvider } from '../../services/workshop-sync';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays a workshop assessment.
|
||||
|
@ -89,6 +91,7 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy, CanLea
|
|||
protected siteId: string;
|
||||
protected currentUserId: number;
|
||||
protected forceLeave = false;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(
|
||||
protected fb: FormBuilder,
|
||||
|
@ -111,6 +114,20 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy, CanLea
|
|||
this.refreshAllData();
|
||||
}
|
||||
}, this.siteId);
|
||||
|
||||
this.logView = CoreTime.once(async () => {
|
||||
if (!this.workshop) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_workshop_get_assessment',
|
||||
name: this.workshop.name,
|
||||
data: { id: this.workshop.id, assessmentid: this.assessment.id, category: 'workshop' },
|
||||
url: `/mod/workshop/assessment.php?asid=${this.assessment.id}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,7 @@ import {
|
|||
} from '../../services/workshop';
|
||||
import { AddonModWorkshopHelper, AddonModWorkshopSubmissionDataWithOfflineData } from '../../services/workshop-helper';
|
||||
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
||||
/**
|
||||
* Page that displays the workshop edit submission.
|
||||
|
@ -224,6 +225,8 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
|
|||
}
|
||||
|
||||
this.loaded = true;
|
||||
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
this.loaded = false;
|
||||
|
||||
|
@ -233,6 +236,23 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected logView(): void {
|
||||
if (!this.workshop) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: this.editing ? 'mod_workshop_update_submission' : 'mod_workshop_add_submission',
|
||||
name: this.workshop.name,
|
||||
data: { id: this.workshop.id, submissionid: this.submissionId, category: 'workshop' },
|
||||
url: `/mod/workshop/submission.php?cmid=${this.module.id}&id=${this.submissionId}&edit=on`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Force leaving the page, without checking for changes.
|
||||
*/
|
||||
|
|
|
@ -47,6 +47,8 @@ import {
|
|||
} from '../../services/workshop-helper';
|
||||
import { AddonModWorkshopOffline } from '../../services/workshop-offline';
|
||||
import { AddonModWorkshopSyncProvider, AddonModWorkshopAutoSyncData } from '../../services/workshop-sync';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays a workshop submission.
|
||||
|
@ -102,7 +104,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
|
|||
protected obsAssessmentSaved: CoreEventObserver;
|
||||
protected syncObserver: CoreEventObserver;
|
||||
protected isDestroyed = false;
|
||||
protected fetchSuccess = false;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor(
|
||||
protected fb: FormBuilder,
|
||||
|
@ -125,6 +127,8 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
|
|||
// Update just when all database is synced.
|
||||
this.eventReceived(data);
|
||||
}, this.siteId);
|
||||
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -599,19 +603,21 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
|
|||
/**
|
||||
* Log submission viewed.
|
||||
*/
|
||||
protected async logView(): Promise<void> {
|
||||
if (this.fetchSuccess) {
|
||||
return; // Already done.
|
||||
}
|
||||
|
||||
this.fetchSuccess = true;
|
||||
|
||||
protected async performLogView(): Promise<void> {
|
||||
try {
|
||||
await AddonModWorkshop.logViewSubmission(this.submissionId, this.workshopId, this.workshop.name);
|
||||
await AddonModWorkshop.logViewSubmission(this.submissionId, this.workshopId);
|
||||
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'mod_workshop_view_submission',
|
||||
name: this.workshop.name,
|
||||
data: { id: this.workshop.id, submissionid: this.submissionId, category: 'workshop' },
|
||||
url: `/mod/workshop/submission.php?cmid=${this.module.id}&id=${this.submissionId}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1443,23 +1443,19 @@ export class AddonModWorkshopProvider {
|
|||
* Report the workshop as being viewed.
|
||||
*
|
||||
* @param id Workshop ID.
|
||||
* @param name Name of the workshop.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logView(id: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logView(id: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModWorkshopViewWorkshopWSParams = {
|
||||
workshopid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_workshop_view_workshop',
|
||||
params,
|
||||
AddonModWorkshopProvider.COMPONENT,
|
||||
id,
|
||||
name,
|
||||
'workshop',
|
||||
{},
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
@ -1469,23 +1465,19 @@ export class AddonModWorkshopProvider {
|
|||
*
|
||||
* @param id Submission ID.
|
||||
* @param workshopId Workshop ID.
|
||||
* @param name Name of the workshop.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved when the WS call is successful.
|
||||
*/
|
||||
async logViewSubmission(id: number, workshopId: number, name?: string, siteId?: string): Promise<void> {
|
||||
async logViewSubmission(id: number, workshopId: number, siteId?: string): Promise<void> {
|
||||
const params: AddonModWorkshopViewSubmissionWSParams = {
|
||||
submissionid: id,
|
||||
};
|
||||
|
||||
await CoreCourseLogHelper.logSingle(
|
||||
await CoreCourseLogHelper.log(
|
||||
'mod_workshop_view_submission',
|
||||
params,
|
||||
AddonModWorkshopProvider.COMPONENT,
|
||||
workshopId,
|
||||
name,
|
||||
'workshop',
|
||||
params,
|
||||
siteId,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -21,12 +21,16 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
|||
import { CoreAnimations } from '@components/animations';
|
||||
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||
import { IonContent, IonRefresher } from '@ionic/angular';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils, ToastDuration } from '@services/utils/dom';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreUrlUtils } from '@services/utils/url';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
* Page that displays a list of notes.
|
||||
|
@ -54,9 +58,11 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
|
|||
currentUserId!: number;
|
||||
|
||||
protected syncObserver!: CoreEventObserver;
|
||||
protected logAfterFetch = true;
|
||||
protected logView: () => void;
|
||||
|
||||
constructor() {
|
||||
this.logView = CoreTime.once(() => this.performLogView());
|
||||
|
||||
try {
|
||||
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
||||
this.userId = CoreNavigator.getRouteNumberParam('userId');
|
||||
|
@ -128,10 +134,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
|
|||
this.notes = await AddonNotes.getNotesUserData(notesList);
|
||||
}
|
||||
|
||||
if (this.logAfterFetch) {
|
||||
this.logAfterFetch = false;
|
||||
CoreUtils.ignoreErrors(AddonNotes.logView(this.courseId, this.userId));
|
||||
}
|
||||
this.logView();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
} finally {
|
||||
|
@ -176,7 +179,6 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
|
|||
this.notesLoaded = false;
|
||||
this.refreshIcon = CoreConstants.ICON_LOADING;
|
||||
this.syncIcon = CoreConstants.ICON_LOADING;
|
||||
this.logAfterFetch = true;
|
||||
|
||||
await this.fetchNotes(true);
|
||||
}
|
||||
|
@ -190,6 +192,8 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.logViewAdd();
|
||||
|
||||
const modalData = await CoreDomUtils.openModal<AddonNotesAddModalReturn>({
|
||||
component: AddonNotesAddComponent,
|
||||
componentProps: {
|
||||
|
@ -225,6 +229,8 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
|
|||
e.stopPropagation();
|
||||
|
||||
try {
|
||||
this.logViewDelete(note);
|
||||
|
||||
await CoreDomUtils.showDeleteConfirm('addon.notes.deleteconfirm');
|
||||
try {
|
||||
await AddonNotes.deleteNote(note, this.courseId);
|
||||
|
@ -294,6 +300,58 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected async performLogView(): Promise<void> {
|
||||
await CoreUtils.ignoreErrors(AddonNotes.logView(this.courseId, this.userId));
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM_LIST,
|
||||
ws: 'core_notes_view_notes',
|
||||
name: Translate.instant('addon.notes.notes'),
|
||||
data: { courseid: this.courseId, userid: this.userId || 0, category: 'notes' },
|
||||
url: CoreUrlUtils.addParamsToUrl('/notes/index.php', {
|
||||
user: this.userId,
|
||||
course: this.courseId !== CoreSites.getCurrentSiteHomeId() ? this.courseId : undefined,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected async logViewAdd(): Promise<void> {
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'core_notes_create_notes',
|
||||
name: Translate.instant('addon.notes.notes'),
|
||||
data: { courseid: this.courseId, userid: this.userId || 0, category: 'notes' },
|
||||
url: CoreUrlUtils.addParamsToUrl('/notes/edit.php', {
|
||||
courseid: this.courseId,
|
||||
userid: this.userId,
|
||||
publishstate: this.type === 'personal' ? 'draft' : (this.type === 'course' ? 'public' : 'site'),
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log view.
|
||||
*/
|
||||
protected async logViewDelete(note: AddonNotesNoteFormatted): Promise<void> {
|
||||
if (!note.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreAnalytics.logEvent({
|
||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||
ws: 'core_notes_delete_notes',
|
||||
name: Translate.instant('addon.notes.notes'),
|
||||
data: { id: note.id, category: 'notes' },
|
||||
url: `/notes/delete.php?id=${note.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Page destroyed.
|
||||
*/
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { CoreWSError } from '@classes/errors/wserror';
|
||||
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { CoreNetwork } from '@services/network';
|
||||
import { CoreSites } from '@services/sites';
|
||||
|
@ -414,8 +413,6 @@ export class AddonNotesProvider {
|
|||
userid: userId || 0,
|
||||
};
|
||||
|
||||
CorePushNotifications.logViewListEvent('notes', 'core_notes_view_notes', params, site.getId());
|
||||
|
||||
await site.write('core_notes_view_notes', params);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue