MOBILE-3930 mod: Fix log view not called after PTR if fetch failed

main
Dani Palou 2022-03-08 07:42:09 +01:00
parent 5fba727114
commit 71f65cec07
37 changed files with 465 additions and 361 deletions

View File

@ -43,6 +43,7 @@ export class AddonBlogEntriesPage implements OnInit {
protected canLoadMoreEntries = false;
protected canLoadMoreUserEntries = true;
protected siteHomeId: number;
protected fetchSuccess = false;
loaded = false;
canLoadMore = false;
@ -123,8 +124,6 @@ export class AddonBlogEntriesPage implements OnInit {
deepLinkManager.treatLink();
await this.fetchEntries();
CoreUtils.ignoreErrors(AddonBlog.logView(this.filter));
}
/**
@ -176,13 +175,7 @@ export class AddonBlogEntriesPage implements OnInit {
entry.summary = CoreTextUtils.replacePluginfileUrls(entry.summary, entry.summaryfiles || []);
return CoreUser.getProfile(entry.userid, entry.courseid, true).then((user) => {
entry.user = user;
return;
}).catch(() => {
// Ignore errors.
});
entry.user = await CoreUtils.ignoreErrors(CoreUser.getProfile(entry.userid, entry.courseid, true));
});
if (refresh) {
@ -205,6 +198,11 @@ export class AddonBlogEntriesPage implements OnInit {
}
await Promise.all(promises);
if (!this.fetchSuccess) {
this.fetchSuccess = true;
CoreUtils.ignoreErrors(AddonBlog.logView(this.filter));
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'addon.blog.errorloadentries', true);
this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading.

View File

@ -58,6 +58,8 @@ export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
contextLevel?: string;
contextInstanceId?: number;
protected fetchSuccess = false;
constructor() {
try {
const planId = CoreNavigator.getRouteNumberParam('planId');
@ -117,33 +119,6 @@ export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
await source.reload();
await this.competencies.start();
await this.fetchCompetency();
if (!this.competency) {
return;
}
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,
),
);
}
} finally {
this.competencyLoaded = true;
}
@ -180,6 +155,32 @@ export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
evidence.description = Translate.instant(key, { $a: evidence.desca });
}
});
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,
),
);
}
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error getting competency data.');
}

View File

@ -36,6 +36,8 @@ export class AddonCompetencyCompetencySummaryPage implements OnInit {
contextLevel?: ContextLevel;
contextInstanceId?: number;
protected fetchSuccess = false; // Whether a fetch was finished successfully.
/**
* @inheritdoc
*/
@ -54,9 +56,6 @@ export class AddonCompetencyCompetencySummaryPage implements OnInit {
try {
await this.fetchCompetency();
const name = this.competency!.competency && this.competency!.competency.shortname;
CoreUtils.ignoreErrors(AddonCompetency.logCompetencyView(this.competencyId, name));
} finally {
this.competencyLoaded = true;
}
@ -73,10 +72,15 @@ export class AddonCompetencyCompetencySummaryPage implements OnInit {
if (!this.contextLevel || this.contextInstanceId === undefined) {
// Context not specified, use user context.
this.contextLevel = ContextLevel.USER;
this.contextInstanceId = result.usercompetency!.userid;
this.contextInstanceId = result.usercompetency?.userid;
}
this.competency = result.competency;
if (!this.fetchSuccess) {
this.fetchSuccess = true;
CoreUtils.ignoreErrors(AddonCompetency.logCompetencyView(this.competencyId, this.competency.competency.shortname));
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error getting competency summary data.');
}

View File

@ -17,7 +17,6 @@ import { Params } from '@angular/router';
import { CoreSite } from '@classes/site';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreGroupInfo, CoreGroups } from '@services/groups';
import { CoreNavigator } from '@services/navigator';
@ -121,7 +120,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
(data) => {
if (this.assign && data.assignmentId == this.assign.id && data.userId == this.currentUserId) {
// Assignment submitted, check completion.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
// Reload data since it can have offline data now.
this.showLoadingAndRefresh(true, false);
@ -138,25 +137,6 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
}, this.siteId);
await this.loadContent(false, true);
if (!this.assign) {
return;
}
try {
await AddonModAssign.logView(this.assign.id, this.assign.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors. Just don't check Module completion.
}
if (this.canViewAllSubmissions) {
// User can see all submissions, log grading view.
CoreUtils.ignoreErrors(AddonModAssign.logGradingView(this.assign.id, this.assign.name));
} 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));
}
}
/**
@ -232,6 +212,25 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
}
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.assign) {
return; // Shouldn't happen.
}
await AddonModAssign.logView(this.assign.id, this.assign.name);
if (this.canViewAllSubmissions) {
// User can see all submissions, log grading view.
CoreUtils.ignoreErrors(AddonModAssign.logGradingView(this.assign.id, this.assign.name));
} 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));
}
}
/**
* Set group to see the summary.
*

View File

@ -15,7 +15,6 @@
import { Component, OnInit, Optional } from '@angular/core';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreGroupInfo, CoreGroups } from '@services/groups';
import { CoreDomUtils } from '@services/utils/dom';
@ -54,18 +53,6 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
super.ngOnInit();
await this.loadContent();
if (!this.bbb) {
return;
}
try {
await AddonModBBB.logView(this.bbb.id, this.bbb.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
@ -82,7 +69,6 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
this.groupId = CoreGroups.validateGroupId(this.groupId, this.groupInfo);
await this.fetchMeetingInfo();
}
/**
@ -107,6 +93,17 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
}
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.bbb) {
return; // Shouldn't happen.
}
await AddonModBBB.logView(this.bbb.id, this.bbb.name);
}
/**
* Update meeting info.
*

View File

@ -18,7 +18,6 @@ import { AddonModBook, AddonModBookBookWSData, AddonModBookNumbering, AddonModBo
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { CoreNavigator } from '@services/navigator';
import { CoreUtils } from '@services/utils/utils';
/**
* Component that displays a book entry page.
@ -36,6 +35,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
hasStartedBook = false;
protected book?: AddonModBookBookWSData;
protected checkCompletionAfterLog = false;
constructor( @Optional() courseContentsPage?: CoreCourseContentsPage) {
super('AddonModBookIndexComponent', courseContentsPage);
@ -48,9 +48,6 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
super.ngOnInit();
this.loadContent();
// Log book viewed.
await CoreUtils.ignoreErrors(AddonModBook.logView(this.module.instance, undefined, this.module.name));
}
/**
@ -93,6 +90,13 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
this.chapters = AddonModBook.getTocList(contents);
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
AddonModBook.logView(this.module.instance, undefined, this.module.name);
}
/**
* Open the book in a certain chapter.
*

View File

@ -15,7 +15,6 @@
import { Component, OnInit, Optional } from '@angular/core';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreNavigator } from '@services/navigator';
import { CoreTimeUtils } from '@services/utils/time';
@ -53,18 +52,6 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
super.ngOnInit();
await this.loadContent();
if (!this.chat) {
return;
}
try {
await AddonModChat.logView(this.chat.id, this.chat.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
@ -89,6 +76,17 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
this.dataRetrieved.emit(this.chat);
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.chat) {
return; // Shouldn't happen.
}
await AddonModChat.logView(this.chat.id, this.chat.name);
}
/**
* Enter the chat.
*/

View File

@ -15,7 +15,6 @@
import { Component, Optional, OnInit } from '@angular/core';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
@ -86,18 +85,6 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
this.userId = CoreSites.getCurrentSiteUserId();
await this.loadContent(false, true);
if (!this.choice) {
return;
}
try {
await AddonModChoice.logView(this.choice.id, this.choice.name);
await CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
@ -325,6 +312,17 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
this.canSeeResults = hasVotes || AddonModChoice.canStudentSeeResults(choice, this.hasAnsweredOnline);
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.choice) {
return; // Shouldn't happen.
}
await AddonModChoice.logView(this.choice.id, this.choice.name);
}
/**
* Check if a choice is open.
*
@ -384,7 +382,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
if (online) {
CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: this.moduleName });
// Check completion since it could be configured to complete once the user answers the choice.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
await this.dataUpdated(online);

View File

@ -18,7 +18,6 @@ import { Params } from '@angular/router';
import { CoreCommentsProvider } from '@features/comments/services/comments';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { CoreRatingProvider } from '@features/rating/services/rating';
import { CoreRatingSyncProvider } from '@features/rating/services/rating-sync';
import { IonContent } from '@ionic/angular';
@ -154,7 +153,6 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
});
await this.loadContent(false, true);
await this.logView(true);
}
/**
@ -410,7 +408,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
try {
await this.fetchEntriesData();
// Log activity view for coherence with Moodle web.
await this.logView();
await this.logActivity();
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
} finally {
@ -456,7 +454,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
await this.fetchEntriesData();
// Log activity view for coherence with Moodle web.
return this.logView();
return this.logActivity();
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
}
@ -522,24 +520,14 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
}
/**
* Log viewing the activity.
*
* @param checkCompletion Whether to check completion.
* @return Promise resolved when done.
* @inheritdoc
*/
protected async logView(checkCompletion = false): Promise<void> {
protected async logActivity(): Promise<void> {
if (!this.database || !this.database.id) {
return;
}
try {
await AddonModData.logView(this.database.id, this.database.name);
if (checkCompletion) {
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
}
} catch {
// Ignore errors, the user could be offline.
}
await AddonModData.logView(this.database.id, this.database.name);
}
/**

View File

@ -55,6 +55,7 @@ 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;
moduleId = 0;
courseId!: number;
@ -149,7 +150,6 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
this.commentsEnabled = !CoreComments.areCommentsDisabledInSite();
await this.fetchEntryData();
this.logView();
}
/**
@ -201,6 +201,11 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
title: this.title,
group: this.selectedGroup,
};
if (this.logAfterFetch) {
this.logAfterFetch = false;
this.logView();
}
} catch (error) {
if (!refresh) {
// Some call failed, retry without using cache since it might be a new activity.
@ -225,9 +230,9 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
this.entryId = undefined;
this.entry = undefined;
this.entryLoaded = false;
this.logAfterFetch = true;
await this.fetchEntryData();
this.logView();
}
/**
@ -286,9 +291,9 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
this.entry = undefined;
this.entryId = undefined;
this.entryLoaded = false;
this.logAfterFetch = true;
await this.fetchEntryData();
this.logView();
}
/**

View File

@ -82,6 +82,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
protected submitObserver: CoreEventObserver;
protected syncEventName = AddonModFeedbackSyncProvider.AUTO_SYNCED;
protected checkCompletionAfterLog = false;
constructor(
protected content?: IonContent,
@ -125,15 +126,22 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
try {
await this.loadContent(false, true);
if (this.feedback) {
CoreUtils.ignoreErrors(AddonModFeedback.logView(this.feedback.id, this.feedback.name));
}
} finally {
this.tabsReady = true;
}
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.feedback) {
return; // Shouldn't happen.
}
await AddonModFeedback.logView(this.feedback.id, this.feedback.name);
}
/**
* @inheritdoc
*/

View File

@ -62,13 +62,6 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
try {
await this.loadContent();
try {
await AddonModFolder.logView(this.module.instance, this.module.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
} finally {
this.showLoading = false;
}
@ -97,6 +90,13 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
this.contents = AddonModFolderHelper.formatContents(contents);
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
await AddonModFolder.logView(this.module.instance, this.module.name);
}
/**
* Navigate to a subfolder.
*

View File

@ -99,6 +99,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
protected ratingOfflineObserver?: CoreEventObserver;
protected ratingSyncObserver?: CoreEventObserver;
protected sourceUnsubscribe?: () => void;
protected checkCompletionAfterLog = false; // Use CoreListItemsManager log system instead.
constructor(
public route: ActivatedRoute,
@ -570,7 +571,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
});
// Check completion since it could be configured to complete once the user adds a new discussion or replies.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
}
@ -692,15 +693,13 @@ class AddonModForumDiscussionsManager extends CoreListItemsManager<AddonModForum
return;
}
CoreUtils.ignoreErrors(
AddonModForum.instance
.logView(forum.id, forum.name)
.then(async () => {
CoreCourse.checkModuleCompletion(this.page.courseId, this.page.module.completiondata);
try {
await AddonModForum.instance.logView(forum.id, forum.name);
return;
}),
);
CoreCourse.checkModuleCompletion(this.page.courseId, this.page.module.completiondata);
} catch {
// Ignore errors.
}
}
}

View File

@ -81,12 +81,13 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
protected sourceUnsubscribe?: () => void;
protected ratingOfflineObserver?: CoreEventObserver;
protected ratingSyncObserver?: CoreEventObserver;
protected checkCompletionAfterLog = false; // Use CoreListItemsManager log system instead.
getDivider?: (entry: AddonModGlossaryEntry) => string;
showDivider: (entry: AddonModGlossaryEntry, previous?: AddonModGlossaryEntry) => boolean = () => false;
constructor(
protected route: ActivatedRoute,
public route: ActivatedRoute,
protected content?: IonContent,
@Optional() protected courseContentsPage?: CoreCourseContentsPage,
) {
@ -124,10 +125,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
[this.courseId, this.module.id, this.courseContentsPage ? `${AddonModGlossaryModuleHandlerService.PAGE_NAME}/` : ''],
);
this.promisedEntries.resolve(new AddonModGlossaryEntriesManager(
source,
this.route.component,
));
this.promisedEntries.resolve(new AddonModGlossaryEntriesManager(source, this));
this.sourceUnsubscribe = source.addListener({
onItemsUpdated: items => this.hasOffline = !!items.find(item => source.isOfflineEntry(item)),
@ -139,7 +137,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
this.showLoadingAndRefresh(false);
// Check completion since it could be configured to complete once the user adds a new entry.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
});
@ -166,12 +164,6 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
await this.loadContent(false, true);
await entries.start(this.splitView);
try {
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch (error) {
// Ignore errors.
}
}
/**
@ -437,6 +429,14 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
*/
class AddonModGlossaryEntriesManager extends CoreListItemsManager<AddonModGlossaryEntryItem, AddonModGlossaryEntriesSource> {
page: AddonModGlossaryIndexComponent;
constructor(source: AddonModGlossaryEntriesSource, page: AddonModGlossaryIndexComponent) {
super(source, page.route.component);
this.page = page;
}
get offlineEntries(): AddonModGlossaryOfflineEntry[] {
return this.getSource().offlineEntries;
}
@ -463,7 +463,13 @@ class AddonModGlossaryEntriesManager extends CoreListItemsManager<AddonModGlossa
return;
}
await AddonModGlossary.logView(glossary.id, viewMode, glossary.name);
try {
await AddonModGlossary.logView(glossary.id, viewMode, glossary.name);
CoreCourse.checkModuleCompletion(this.page.courseId, this.page.module.completiondata);
} catch (error) {
// Ignore errors.
}
}
}

View File

@ -19,7 +19,6 @@ import { CoreConstants } from '@/core/constants';
import { CoreSite } from '@classes/site';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { CoreH5PDisplayOptions } from '@features/h5p/classes/core';
import { CoreH5PHelper } from '@features/h5p/classes/helper';
import { CoreH5P } from '@features/h5p/services/h5p';
@ -85,6 +84,7 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
protected site: CoreSite;
protected observer?: CoreEventObserver;
protected messageListenerFunction: (event: MessageEvent) => Promise<void>;
protected checkCompletionAfterLog = false; // It's called later, when the user plays the package.
constructor(
protected content?: IonContent,
@ -390,7 +390,7 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
// Mark the activity as viewed.
await AddonModH5PActivity.logView(this.h5pActivity.id, this.h5pActivity.name, this.siteId);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
/**
@ -464,7 +464,7 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
// Check if the H5P has ended. Final statements don't include a subContentId.
const hasEnded = data.statements.some(statement => !statement.object.id.includes('subContentId='));
if (hasEnded) {
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
}
} catch (error) {

View File

@ -45,6 +45,7 @@ export class AddonModH5PActivityAttemptResultsPage implements OnInit {
cmId!: number;
protected attemptId!: number;
protected fetchSuccess = false;
/**
* @inheritdoc
@ -62,17 +63,7 @@ export class AddonModH5PActivityAttemptResultsPage implements OnInit {
return;
}
try {
await this.fetchData();
if (this.h5pActivity) {
await AddonModH5PActivity.logViewReport(this.h5pActivity.id, this.h5pActivity.name, { attemptId: this.attemptId });
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempt.');
} finally {
this.loaded = true;
}
await this.fetchData();
}
/**
@ -92,13 +83,28 @@ export class AddonModH5PActivityAttemptResultsPage implements OnInit {
* @return Promise resolved when done.
*/
protected async fetchData(): Promise<void> {
this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.cmId);
try {
this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.cmId);
this.attempt = await AddonModH5PActivity.getAttemptResults(this.h5pActivity.id, this.attemptId, {
cmId: this.cmId,
});
this.attempt = await AddonModH5PActivity.getAttemptResults(this.h5pActivity.id, this.attemptId, {
cmId: this.cmId,
});
await this.fetchUserProfile();
await this.fetchUserProfile();
if (!this.fetchSuccess) {
this.fetchSuccess = true;
CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(
this.h5pActivity.id,
this.h5pActivity.name,
{ attemptId: this.attemptId },
));
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempt.');
} finally {
this.loaded = true;
}
}
/**

View File

@ -46,6 +46,7 @@ export class AddonModH5PActivityUserAttemptsPage implements OnInit {
isCurrentUser = false;
protected userId!: number;
protected fetchSuccess = false;
/**
* @inheritdoc
@ -65,17 +66,7 @@ export class AddonModH5PActivityUserAttemptsPage implements OnInit {
this.isCurrentUser = this.userId == CoreSites.getCurrentSiteUserId();
try {
await this.fetchData();
if (this.h5pActivity) {
await AddonModH5PActivity.logViewReport(this.h5pActivity.id, this.h5pActivity.name, { userId: this.userId });
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
} finally {
this.loaded = true;
}
await this.fetchData();
}
/**
@ -95,12 +86,27 @@ export class AddonModH5PActivityUserAttemptsPage implements OnInit {
* @return Promise resolved when done.
*/
protected async fetchData(): Promise<void> {
this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.cmId);
try {
this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.cmId);
await Promise.all([
this.fetchAttempts(),
this.fetchUserProfile(),
]);
await Promise.all([
this.fetchAttempts(),
this.fetchUserProfile(),
]);
if (!this.fetchSuccess) {
this.fetchSuccess = true;
CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(
this.h5pActivity.id,
this.h5pActivity.name,
{ userId: this.userId },
));
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
} finally {
this.loaded = true;
}
}
/**

View File

@ -44,6 +44,7 @@ export class AddonModH5PActivityUsersAttemptsPage implements OnInit {
canLoadMore = false;
protected page = 0;
protected fetchSuccess = false;
/**
* @inheritdoc
@ -60,17 +61,7 @@ export class AddonModH5PActivityUsersAttemptsPage implements OnInit {
return;
}
try {
await this.fetchData();
if (this.h5pActivity) {
await AddonModH5PActivity.logViewReport(this.h5pActivity.id, this.h5pActivity.name);
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
} finally {
this.loaded = true;
}
this.fetchData();
}
/**
@ -91,11 +82,22 @@ export class AddonModH5PActivityUsersAttemptsPage implements OnInit {
* @return Promise resolved when done.
*/
protected async fetchData(refresh?: boolean): Promise<void> {
this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.cmId);
try {
this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.cmId);
await Promise.all([
this.fetchUsers(refresh),
]);
await Promise.all([
this.fetchUsers(refresh),
]);
if (!this.fetchSuccess) {
this.fetchSuccess = true;
CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(this.h5pActivity.id, this.h5pActivity.name));
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
} finally {
this.loaded = true;
}
}
/**

View File

@ -45,13 +45,6 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
super.ngOnInit();
await this.loadContent();
try {
await AddonModImscp.logView(this.module.instance, this.module.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
@ -103,6 +96,13 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
this.items = AddonModImscp.createItemList(contents);
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
await AddonModImscp.logView(this.module.instance, this.module.name);
}
/**
* Open IMSCP book with a certain item.
*

View File

@ -18,7 +18,6 @@ import { Component, Input, ViewChild, ElementRef, OnInit, OnDestroy, Optional }
import { CoreTabsComponent } from '@components/tabs/tabs';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { CoreUser } from '@features/user/services/user';
import { IonContent, IonInput } from '@ionic/angular';
import { CoreGroupInfo, CoreGroups } from '@services/groups';
@ -108,12 +107,6 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
this.selectedTab = this.action == 'report' ? 1 : 0;
await this.loadContent(false, true);
if (!this.lesson || this.preventReasons.length) {
return;
}
this.logView();
}
/**
@ -285,7 +278,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
protected hasSyncSucceed(result: AddonModLessonSyncResult): boolean {
if (result.updated || this.dataSent) {
// Check completion status if something was sent.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
this.dataSent = false;
@ -373,20 +366,14 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
}
/**
* Log viewing the lesson.
*
* @return Promise resolved when done.
* @inheritdoc
*/
protected async logView(): Promise<void> {
if (!this.lesson) {
protected async logActivity(): Promise<void> {
if (!this.lesson || this.preventReasons.length) {
return;
}
await CoreUtils.ignoreErrors(
AddonModLesson.logViewLesson(this.lesson.id, this.password, this.lesson.name),
);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
await AddonModLesson.logViewLesson(this.lesson.id, this.password, this.lesson.name);
}
/**
@ -631,7 +618,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
this.preventReasons = preventReason ? [preventReason] : [];
// Log view now that we have the password.
this.logView();
this.logActivity();
} catch (error) {
CoreDomUtils.showErrorModal(error);
} finally {

View File

@ -52,13 +52,6 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
super.ngOnInit();
await this.loadContent();
try {
await AddonModPage.logView(this.module.instance, this.module.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
@ -118,4 +111,11 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
this.timemodified = 'timemodified' in this.page ? this.page.timemodified : undefined;
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
await AddonModPage.logView(this.module.instance, this.module.name);
}
}

View File

@ -17,7 +17,6 @@ import { Component, OnDestroy, OnInit, Optional } from '@angular/core';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { CoreQuestionBehaviourDelegate } from '@features/question/services/behaviour-delegate';
import { IonContent } from '@ionic/angular';
import { CoreNavigator } from '@services/navigator';
@ -121,18 +120,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
);
await this.loadContent(false, true);
if (!this.quiz) {
return;
}
try {
await AddonModQuiz.logViewQuiz(this.quiz.id, this.quiz.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
@ -387,6 +374,17 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
}
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.quiz) {
return; // Shouldn't happen.
}
await AddonModQuiz.logViewQuiz(this.quiz.id, this.quiz.name);
}
/**
* Go to review an attempt that has just been finished.
*
@ -398,7 +396,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
}
// If we go to auto review it means an attempt was finished. Check completion status.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
// Verify that user can see the review.
const attemptId = this.autoReview.attemptId;
@ -425,7 +423,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
protected hasSyncSucceed(result: AddonModQuizSyncResult): boolean {
if (result.attemptFinished) {
// An attempt was finished, check completion status.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
// If the sync call isn't rejected it means the sync was successful.
@ -508,7 +506,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
if (syncEventData.attemptFinished) {
// An attempt was finished, check completion status.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
if (this.quiz && syncEventData.quizId == this.quiz.id) {

View File

@ -73,6 +73,7 @@ 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;
constructor(
protected elementRef: ElementRef,
@ -99,10 +100,6 @@ export class AddonModQuizReviewPage implements OnInit {
try {
await this.fetchData();
CoreUtils.ignoreErrors(
AddonModQuiz.logViewAttemptReview(this.attemptId, this.quiz!.id, this.quiz!.name),
);
} finally {
this.loaded = true;
}
@ -160,6 +157,13 @@ 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),
);
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_quiz.errorgetquiz', true);
}

View File

@ -90,12 +90,6 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
});
await this.loadContent();
try {
await AddonModResource.logView(this.module.instance, this.module.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
@ -189,6 +183,13 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
}
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
await AddonModResource.logView(this.module.instance, this.module.name);
}
/**
* Opens a file.
*

View File

@ -16,7 +16,6 @@ import { CoreConstants } from '@/core/constants';
import { Component, OnInit, Optional } from '@angular/core';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreNavigator } from '@services/navigator';
import { CoreSync } from '@services/sync';
@ -114,21 +113,6 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
if (this.skip) {
this.open();
}
try {
await AddonModScorm.logView(this.scorm.id, this.scorm.name);
this.checkCompletion();
} catch {
// Ignore errors.
}
}
/**
* Check the completion.
*/
protected checkCompletion(): void {
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
}
/**
@ -357,6 +341,17 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
this.gradeFormatted = AddonModScorm.formatGrade(scorm, this.grade);
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.scorm) {
return; // Shouldn't happen.
}
await AddonModScorm.logView(this.scorm.id, this.scorm.name);
}
/**
* Checks if sync has succeed from result sync data.
*

View File

@ -16,7 +16,6 @@ import { Component, OnInit, Optional } from '@angular/core';
import { CoreIonLoadingElement } from '@classes/ion-loading';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
@ -75,13 +74,6 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
this.currentUserId = CoreSites.getCurrentSiteUserId();
await this.loadContent(false, true);
try {
await AddonModSurvey.logView(this.survey!.id, this.survey!.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors. Just don't check Module completion.
}
}
/**
@ -166,6 +158,17 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
});
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.survey) {
return; // Shouldn't happen.
}
await AddonModSurvey.logView(this.survey.id, this.survey.name);
}
/**
* Check if answers are valid to be submitted.
*

View File

@ -47,6 +47,8 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo
mimetype?: string;
displayDescription = true;
protected checkCompletionAfterLog = false;
constructor(@Optional() courseContentsPage?: CoreCourseContentsPage) {
super('AddonModUrlIndexComponent', courseContentsPage);
}
@ -58,12 +60,6 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo
super.ngOnInit();
await this.loadContent();
if ((this.shouldIframe ||
(this.shouldEmbed && this.isOther)) ||
(!this.shouldIframe && (!this.shouldEmbed || !this.isOther))) {
this.logView();
}
}
/**
@ -170,12 +166,24 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo
protected async logView(): Promise<void> {
try {
await AddonModUrl.logView(this.module.instance, this.module.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
} catch {
// Ignore errors.
}
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if ((this.shouldIframe ||
(this.shouldEmbed && this.isOther)) ||
(!this.shouldIframe && (!this.shouldEmbed || !this.isOther))) {
this.logView();
}
}
/**
* Opens a file.
*/

View File

@ -148,24 +148,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
this.openMap();
}
}
if (!this.wiki) {
CoreNavigator.back();
return;
}
if (!this.pageId) {
try {
await AddonModWiki.logView(this.wiki.id, this.wiki.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
} else {
CoreUtils.ignoreErrors(AddonModWiki.logPageView(this.pageId, this.wiki.id, this.wiki.name));
}
}
/**
@ -449,6 +431,22 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
}
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.wiki) {
return; // Shouldn't happen.
}
if (!this.pageId) {
await AddonModWiki.logView(this.wiki.id, this.wiki.name);
} else {
this.checkCompletionAfterLog = false;
CoreUtils.ignoreErrors(AddonModWiki.logPageView(this.pageId, this.wiki.id, this.wiki.name));
}
}
/**
* Get path to the wiki home view. If cannot determine or it's current view, return undefined.
*

View File

@ -16,7 +16,6 @@ import { Component, Input, OnDestroy, OnInit, Optional } from '@angular/core';
import { Params } from '@angular/router';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course';
import { IonContent } from '@ionic/angular';
import { CoreGroupInfo, CoreGroups } from '@services/groups';
import { CoreNavigator } from '@services/navigator';
@ -138,16 +137,6 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
super.ngOnInit();
await this.loadContent(false, true);
if (!this.workshop) {
return;
}
try {
await AddonModWorkshop.logView(this.workshop.id, this.workshop.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch (error) {
// Ignore errors.
}
}
/**
@ -164,7 +153,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
this.showLoadingAndRefresh(true);
// Check completion since it could be configured to complete once the user adds a new discussion or replies.
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
this.checkCompletion();
}
}
@ -257,6 +246,17 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
await this.setPhaseInfo();
}
/**
* @inheritdoc
*/
protected async logActivity(): Promise<void> {
if (!this.workshop) {
return; // Shouldn't happen.
}
await AddonModWorkshop.logView(this.workshop.id, this.workshop.name);
}
/**
* Retrieves and shows submissions grade page.
*

View File

@ -102,6 +102,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
protected obsAssessmentSaved: CoreEventObserver;
protected syncObserver: CoreEventObserver;
protected isDestroyed = false;
protected fetchSuccess = false;
constructor(
protected fb: FormBuilder,
@ -157,12 +158,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
await this.fetchSubmissionData();
try {
await AddonModWorkshop.logViewSubmission(this.submissionId, this.workshopId, this.workshop.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
this.logView();
}
/**
@ -447,6 +443,8 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
CoreEvents.trigger(AddonModWorkshopProvider.ASSESSMENT_INVALIDATED, null, this.siteId);
await this.fetchSubmissionData();
this.logView();
}
}
@ -596,6 +594,24 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
});
}
/**
* Log submission viewed.
*/
protected async logView(): Promise<void> {
if (this.fetchSuccess) {
return; // Already done.
}
this.fetchSuccess = true;
try {
await AddonModWorkshop.logViewSubmission(this.submissionId, this.workshopId, this.workshop.name);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
}
/**
* Component being destroyed.
*/

View File

@ -54,6 +54,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
currentUserId!: number;
protected syncObserver!: CoreEventObserver;
protected logAfterFetch = true;
constructor() {
try {
@ -91,8 +92,6 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
*/
async ngOnInit(): Promise<void> {
await this.fetchNotes(true);
CoreUtils.ignoreErrors(AddonNotes.logView(this.courseId, this.userId));
}
/**
@ -128,6 +127,11 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
} else {
this.notes = await AddonNotes.getNotesUserData(notesList);
}
if (this.logAfterFetch) {
this.logAfterFetch = false;
CoreUtils.ignoreErrors(AddonNotes.logView(this.courseId, this.userId));
}
} catch (error) {
CoreDomUtils.showErrorModal(error);
} finally {
@ -172,9 +176,9 @@ 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);
CoreUtils.ignoreErrors(AddonNotes.logView(this.courseId, this.userId));
}
/**

View File

@ -34,6 +34,7 @@ export class CoreListItemsManager<
protected pageRouteLocator?: unknown | ActivatedRoute;
protected splitView?: CoreSplitViewComponent;
protected splitViewOutletSubscription?: Subscription;
protected fetchSuccess = false; // Whether a fetch was finished successfully.
constructor(source: Source, pageRouteLocator: unknown | ActivatedRoute) {
super(source);
@ -71,9 +72,6 @@ export class CoreListItemsManager<
// Calculate current selected item.
this.updateSelectedItem();
// Log activity.
await CoreUtils.ignoreErrors(this.logActivity());
}
/**
@ -145,6 +143,8 @@ export class CoreListItemsManager<
*/
async reload(): Promise<void> {
await this.getSource().reload();
this.finishSuccessfulFetch();
}
/**
@ -152,6 +152,21 @@ export class CoreListItemsManager<
*/
async load(): Promise<void> {
await this.getSource().load();
this.finishSuccessfulFetch();
}
/**
* Finish a successful fetch.
*/
protected async finishSuccessfulFetch(): Promise<void> {
if (this.fetchSuccess) {
return; // Already treated.
}
// Log activity.
this.fetchSuccess = true;
await CoreUtils.ignoreErrors(this.logActivity());
}
/**

View File

@ -169,6 +169,8 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
}
await this.fetchContent(refresh, sync, showErrors);
this.finishSuccessfulFetch();
} catch (error) {
if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled() && this.isNotFoundError(error)) {
// Module not found, retry without using cache.

View File

@ -72,6 +72,8 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
protected showCompletion = false; // Whether to show completion inside the activity.
protected displayDescription = true; // Wether to show Module description on module page, and not on summary or the contrary.
protected isDestroyed = false; // Whether the component is destroyed.
protected fetchSuccess = false; // Whether a fetch was finished successfully.
protected checkCompletionAfterLog = true; // Whether to check if completion has changed after calling logActivity.
constructor(
@Optional() @Inject('') loggerName: string = 'CoreCourseModuleMainResourceComponent',
@ -191,6 +193,8 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
try {
await this.fetchContent(refresh);
this.finishSuccessfulFetch();
} catch (error) {
if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled() && this.isNotFoundError(error)) {
// Module not found, retry without using cache.
@ -427,6 +431,46 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
}
}
/**
* Finish a successful fetch.
*
* @return Promise resolved when done.
*/
protected async finishSuccessfulFetch(): Promise<void> {
if (this.fetchSuccess) {
return; // Already treated.
}
this.fetchSuccess = true;
// Log activity now.
try {
await this.logActivity();
if (this.checkCompletionAfterLog) {
this.checkCompletion();
}
} catch {
// Ignore errors.
}
}
/**
* Log activity.
*
* @return Promise resolved when done.
*/
protected async logActivity(): Promise<void> {
// To be overridden.
}
/**
* Check the module completion.
*/
protected checkCompletion(): void {
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
}
/**
* Component being destroyed.
*/

View File

@ -54,6 +54,8 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
totalColumnsSpan?: number;
withinSplitView?: boolean;
protected fetchSuccess = false;
constructor(
protected route: ActivatedRoute,
protected element: ElementRef<HTMLElement>,
@ -93,7 +95,6 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
await this.courses?.start();
await this.fetchInitialGrades();
await CoreGrades.logCourseGradesView(this.courseId, this.userId);
}
/**
@ -198,6 +199,11 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
this.columns = formattedTable.columns;
this.rows = formattedTable.rows;
this.totalColumnsSpan = formattedTable.columns.reduce((total, column) => total + column.colspan, 0);
if (!this.fetchSuccess) {
this.fetchSuccess = true;
await CoreGrades.logCourseGradesView(this.courseId, this.userId);
}
}
}

View File

@ -54,6 +54,7 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
newsForumModule?: CoreCourseModuleData;
protected updateSiteObserver: CoreEventObserver;
protected fetchSuccess = false;
constructor() {
// Refresh the enabled flags if site is updated.
@ -137,13 +138,15 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
this.hasContent = result.hasContent || this.hasContent;
}
// Add log in Moodle.
CoreUtils.ignoreErrors(CoreCourse.logView(
this.siteHomeId,
undefined,
undefined,
this.currentSite.getInfo()?.sitename,
));
if (!this.fetchSuccess) {
this.fetchSuccess = true;
CoreUtils.ignoreErrors(CoreCourse.logView(
this.siteHomeId,
undefined,
undefined,
this.currentSite.getInfo()?.sitename,
));
}
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'core.course.couldnotloadsectioncontent', true);
}

View File

@ -48,6 +48,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy {
protected site!: CoreSite;
protected obsProfileRefreshed: CoreEventObserver;
protected subscription?: Subscription;
protected fetchSuccess = false;
userLoaded = false;
isLoadingHandlers = false;
@ -106,18 +107,6 @@ export class CoreUserProfilePage implements OnInit, OnDestroy {
try {
await this.fetchUser();
if (!this.user) {
return;
}
try {
await CoreUser.logView(this.userId, this.courseId, this.user.fullname);
} catch (error) {
this.isDeleted = error?.errorcode === 'userdeleted' || error?.errorcode === 'wsaccessuserdeleted';
this.isSuspended = error?.errorcode === 'wsaccessusersuspended';
this.isEnrolled = error?.errorcode !== 'notenrolledprofile';
}
} finally {
this.userLoaded = true;
}
@ -162,6 +151,18 @@ export class CoreUserProfilePage implements OnInit, OnDestroy {
this.isLoadingHandlers = !CoreUserDelegate.areHandlersLoaded(user.id, context, this.courseId);
});
if (!this.fetchSuccess) {
this.fetchSuccess = true;
try {
await CoreUser.logView(this.userId, this.courseId, this.user.fullname);
} catch (error) {
this.isDeleted = error?.errorcode === 'userdeleted' || error?.errorcode === 'wsaccessuserdeleted';
this.isSuspended = error?.errorcode === 'wsaccessusersuspended';
this.isEnrolled = error?.errorcode !== 'notenrolledprofile';
}
}
} catch (error) {
// Error is null for deleted users, do not show the modal.
CoreDomUtils.showErrorModal(error);