MOBILE-4270 sync: Improve sync result types

main
Pau Ferrer Ocaña 2023-03-13 14:29:40 +01:00
parent 89890a103d
commit b4bd42b928
31 changed files with 101 additions and 224 deletions

View File

@ -27,7 +27,7 @@ import {
import { AddonCalendarOffline } from './calendar-offline'; import { AddonCalendarOffline } from './calendar-offline';
import { AddonCalendarHelper } from './calendar-helper'; import { AddonCalendarHelper } from './calendar-helper';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import moment from 'moment-timezone'; import moment from 'moment-timezone';
@ -301,13 +301,11 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider<AddonCalenda
export const AddonCalendarSync = makeSingleton(AddonCalendarSyncProvider); export const AddonCalendarSync = makeSingleton(AddonCalendarSyncProvider);
export type AddonCalendarSyncEvents = { export type AddonCalendarSyncEvents = CoreSyncResult & {
warnings: string[];
events: AddonCalendarEvent[]; events: AddonCalendarEvent[];
offlineIdMap: Record<number, number>; // Map offline ID with online ID for created events. offlineIdMap: Record<number, number>; // Map offline ID with online ID for created events.
deleted: number[]; deleted: number[];
toinvalidate: AddonCalendarSyncInvalidateEvent[]; toinvalidate: AddonCalendarSyncInvalidateEvent[];
updated: boolean;
source?: string; // Added on pages. source?: string; // Added on pages.
moment?: moment.Moment; // Added on day page. moment?: moment.Moment; // Added on day page.
}; };

View File

@ -14,6 +14,7 @@
import { Component, Optional, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { Component, Optional, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Params } from '@angular/router'; import { Params } from '@angular/router';
import { CoreError } from '@classes/errors/error';
import { CoreSite } from '@classes/site'; import { CoreSite } from '@classes/site';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
@ -314,11 +315,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected hasSyncSucceed(result?: AddonModAssignSyncResult): boolean { protected hasSyncSucceed(result: AddonModAssignSyncResult): boolean {
if (!result) {
return false;
}
if (result.updated) { if (result.updated) {
this.submissionComponent?.invalidateAndRefresh(false); this.submissionComponent?.invalidateAndRefresh(false);
} }
@ -384,9 +381,9 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async sync(): Promise<AddonModAssignSyncResult | void> { protected async sync(): Promise<AddonModAssignSyncResult> {
if (!this.assign) { if (!this.assign) {
return; throw new CoreError('Cannot sync without a assign.');
} }
return AddonModAssignSync.syncAssign(this.assign.id); return AddonModAssignSync.syncAssign(this.assign.id);

View File

@ -32,7 +32,7 @@ import {
AddonModAssignSubmissionsDBRecordFormatted, AddonModAssignSubmissionsDBRecordFormatted,
AddonModAssignSubmissionsGradingDBRecordFormatted, AddonModAssignSubmissionsGradingDBRecordFormatted,
} from './assign-offline'; } from './assign-offline';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
@ -530,9 +530,7 @@ export const AddonModAssignSync = makeSingleton(AddonModAssignSyncProvider);
/** /**
* Data returned by a assign sync. * Data returned by a assign sync.
*/ */
export type AddonModAssignSyncResult = { export type AddonModAssignSyncResult = CoreSyncResult & {
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
courseId?: number; // Course the assign belongs to (if known). courseId?: number; // Course the assign belongs to (if known).
gradesBlocked: number[]; // Whether some grade couldn't be synced because it was blocked. UserId fields of the blocked grade. gradesBlocked: number[]; // Whether some grade couldn't be synced because it was blocked. UserId fields of the blocked grade.
}; };

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
import { Component, Optional, OnInit } from '@angular/core'; import { Component, Optional, OnInit } from '@angular/core';
import { CoreError } from '@classes/errors/error';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { IonContent } from '@ionic/angular'; import { IonContent } from '@ionic/angular';
@ -454,22 +455,14 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected sync(): Promise<AddonModChoiceSyncResult> { protected sync(): Promise<AddonModChoiceSyncResult> {
return AddonModChoiceSync.syncChoice(this.choice!.id, this.userId); if (!this.choice) {
throw new CoreError('Cannot sync without a choice.');
} }
/** return AddonModChoiceSync.syncChoice(this.choice.id, this.userId);
* Checks if sync has succeed from result sync data.
*
* @param result Data returned on the sync function.
* @returns Whether it succeed or not.
*/
protected hasSyncSucceed(result: AddonModChoiceSyncResult): boolean {
return result.updated;
} }
} }

View File

@ -15,6 +15,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync'; import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync';
import { CoreSyncResult } from '@services/sync';
import { CoreCourse } from '@features/course/services/course'; import { CoreCourse } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
@ -217,10 +218,7 @@ export const AddonModChoiceSync = makeSingleton(AddonModChoiceSyncProvider);
/** /**
* Data returned by a choice sync. * Data returned by a choice sync.
*/ */
export type AddonModChoiceSyncResult = { export type AddonModChoiceSyncResult = CoreSyncResult;
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
};
/** /**
* Data passed to AUTO_SYNCED event. * Data passed to AUTO_SYNCED event.

View File

@ -519,24 +519,12 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected sync(): Promise<AddonModDataSyncResult> { protected sync(): Promise<AddonModDataSyncResult> {
return AddonModDataPrefetchHandler.sync(this.module, this.courseId); return AddonModDataPrefetchHandler.sync(this.module, this.courseId);
} }
/**
* Checks if sync has succeed from result sync data.
*
* @param result Data returned on the sync function.
* @returns If suceed or not.
*/
protected hasSyncSucceed(result: AddonModDataSyncResult): boolean {
return result.updated;
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@ -24,7 +24,7 @@ import { CoreRatingSync } from '@features/rating/services/rating-sync';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreFileEntry } from '@services/file-helper'; import { CoreFileEntry } from '@services/file-helper';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { Translate, makeSingleton } from '@singletons'; import { Translate, makeSingleton } from '@singletons';
@ -477,10 +477,7 @@ export type AddonModDataSyncEntryResult = {
/** /**
* Data returned by a database sync. * Data returned by a database sync.
*/ */
export type AddonModDataSyncResult = { export type AddonModDataSyncResult = CoreSyncResult;
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
};
export type AddonModDataAutoSyncData = { export type AddonModDataAutoSyncData = {
dataId: number; dataId: number;

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
import { Component, Input, Optional, ViewChild, OnInit, OnDestroy } from '@angular/core'; import { Component, Input, Optional, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { CoreError } from '@classes/errors/error';
import { CoreTabsComponent } from '@components/tabs/tabs'; import { CoreTabsComponent } from '@components/tabs/tabs';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
@ -477,14 +478,11 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
* @inheritdoc * @inheritdoc
*/ */
protected sync(): Promise<AddonModFeedbackSyncResult> { protected sync(): Promise<AddonModFeedbackSyncResult> {
return AddonModFeedbackSync.syncFeedback(this.feedback!.id); if (!this.feedback) {
throw new CoreError('Cannot sync without a feedback.');
} }
/** return AddonModFeedbackSync.syncFeedback(this.feedback.id);
* @inheritdoc
*/
protected hasSyncSucceed(result: AddonModFeedbackSyncResult): boolean {
return result.updated;
} }
/** /**

View File

@ -20,7 +20,7 @@ import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/c
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
@ -292,10 +292,7 @@ export const AddonModFeedbackSync = makeSingleton(AddonModFeedbackSyncProvider);
/** /**
* Data returned by a feedback sync. * Data returned by a feedback sync.
*/ */
export type AddonModFeedbackSyncResult = { export type AddonModFeedbackSyncResult = CoreSyncResult;
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
};
/** /**
* Data passed to AUTO_SYNCED event. * Data passed to AUTO_SYNCED event.

View File

@ -500,24 +500,12 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected sync(): Promise<AddonModForumSyncResult> { protected sync(): Promise<AddonModForumSyncResult> {
return AddonModForumPrefetchHandler.sync(this.module, this.courseId); return AddonModForumPrefetchHandler.sync(this.module, this.courseId);
} }
/**
* Checks if sync has succeed from result sync data.
*
* @param result Data returned on the sync function.
* @returns Whether it succeed or not.
*/
protected hasSyncSucceed(result: AddonModForumSyncResult): boolean {
return result.updated;
}
/** /**
* Compares sync event data with current data to check if refresh content is needed. * Compares sync event data with current data to check if refresh content is needed.
* *

View File

@ -21,7 +21,7 @@ import { CoreRatingSync } from '@features/rating/services/rating-sync';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreGroups } from '@services/groups'; import { CoreGroups } from '@services/groups';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
@ -221,7 +221,7 @@ export class AddonModForumSyncProvider extends CoreCourseActivitySyncBaseProvide
}; };
// Sync offline logs. // Sync offline logs.
const syncDiscussions = async (): Promise<{ warnings: string[]; updated: boolean }> => { const syncDiscussions = async (): Promise<AddonModForumSyncResult> => {
await CoreUtils.ignoreErrors( await CoreUtils.ignoreErrors(
CoreCourseLogHelper.syncActivity(AddonModForumProvider.COMPONENT, forumId, siteId), CoreCourseLogHelper.syncActivity(AddonModForumProvider.COMPONENT, forumId, siteId),
); );
@ -643,10 +643,7 @@ export const AddonModForumSync = makeSingleton(AddonModForumSyncProvider);
/** /**
* Result of forum sync. * Result of forum sync.
*/ */
export type AddonModForumSyncResult = { export type AddonModForumSyncResult = CoreSyncResult;
updated: boolean;
warnings: string[];
};
/** /**
* Data passed to AUTO_SYNCED event. * Data passed to AUTO_SYNCED event.

View File

@ -22,7 +22,7 @@ import { CoreCourse, CoreCourseAnyModuleData, CoreCourseCommonModWSOptions } fro
import { CoreUser } from '@features/user/services/user'; import { CoreUser } from '@features/user/services/user';
import { CoreGroups, CoreGroupsProvider } from '@services/groups'; import { CoreGroups, CoreGroupsProvider } from '@services/groups';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { AddonModForumSync } from '../forum-sync'; import { AddonModForumSync, AddonModForumSyncResult } from '../forum-sync';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreCourses } from '@features/courses/services/courses'; import { CoreCourses } from '@features/courses/services/courses';
@ -341,11 +341,3 @@ export class AddonModForumPrefetchHandlerService extends CoreCourseActivityPrefe
} }
export const AddonModForumPrefetchHandler = makeSingleton(AddonModForumPrefetchHandlerService); export const AddonModForumPrefetchHandler = makeSingleton(AddonModForumPrefetchHandlerService);
/**
* Data returned by a forum sync.
*/
export type AddonModForumSyncResult = {
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
};

View File

@ -215,24 +215,12 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected sync(): Promise<AddonModGlossarySyncResult> { protected sync(): Promise<AddonModGlossarySyncResult> {
return AddonModGlossaryPrefetchHandler.sync(this.module, this.courseId); return AddonModGlossaryPrefetchHandler.sync(this.module, this.courseId);
} }
/**
* Checks if sync has succeed from result sync data.
*
* @param result Data returned on the sync function.
* @returns Whether it succeed or not.
*/
protected hasSyncSucceed(result: AddonModGlossarySyncResult): boolean {
return result.updated;
}
/** /**
* Compares sync event data with current data to check if refresh content is needed. * Compares sync event data with current data to check if refresh content is needed.
* *

View File

@ -21,7 +21,7 @@ import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreRatingSync } from '@features/rating/services/rating-sync'; import { CoreRatingSync } from '@features/rating/services/rating-sync';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
@ -344,10 +344,7 @@ export const AddonModGlossarySync = makeSingleton(AddonModGlossarySyncProvider);
/** /**
* Data returned by a glossary sync. * Data returned by a glossary sync.
*/ */
export type AddonModGlossarySyncResult = { export type AddonModGlossarySyncResult = CoreSyncResult;
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
};
/** /**
* Data passed to AUTO_SYNCED event. * Data passed to AUTO_SYNCED event.

View File

@ -16,6 +16,7 @@ import { Injectable } from '@angular/core';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync'; import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync';
import { CoreSyncResult } from '@services/sync';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreXAPIOffline } from '@features/xapi/services/offline'; import { CoreXAPIOffline } from '@features/xapi/services/offline';
import { CoreXAPI } from '@features/xapi/services/xapi'; import { CoreXAPI } from '@features/xapi/services/xapi';
@ -197,10 +198,7 @@ export const AddonModH5PActivitySync = makeSingleton(AddonModH5PActivitySyncProv
/** /**
* Sync result. * Sync result.
*/ */
export type AddonModH5PActivitySyncResult = { export type AddonModH5PActivitySyncResult = CoreSyncResult;
updated: boolean;
warnings: string[];
};
/** /**
* Data passed to AUTO_SYNC event. * Data passed to AUTO_SYNC event.

View File

@ -47,6 +47,7 @@ import {
} from '../../services/lesson-sync'; } from '../../services/lesson-sync';
import { AddonModLessonModuleHandlerService } from '../../services/handlers/module'; import { AddonModLessonModuleHandlerService } from '../../services/handlers/module';
import { CoreTime } from '@singletons/time'; import { CoreTime } from '@singletons/time';
import { CoreError } from '@classes/errors/error';
/** /**
* Component that displays a lesson entry page. * Component that displays a lesson entry page.
@ -270,10 +271,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Checks if sync has succeed from result sync data. * @inheritdoc
*
* @param result Data returned on the sync function.
* @returns If suceed or not.
*/ */
protected hasSyncSucceed(result: AddonModLessonSyncResult): boolean { protected hasSyncSucceed(result: AddonModLessonSyncResult): boolean {
if (result.updated || this.dataSent) { if (result.updated || this.dataSent) {
@ -637,12 +635,14 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected async sync(): Promise<AddonModLessonSyncResult> { protected async sync(): Promise<AddonModLessonSyncResult> {
const result = await AddonModLessonSync.syncLesson(this.lesson!.id, true); if (!this.lesson) {
throw new CoreError('Cannot sync without a lesson.');
}
const result = await AddonModLessonSync.syncLesson(this.lesson.id, true);
if (!result.updated && this.dataSent && this.isPrefetched()) { if (!result.updated && this.dataSent && this.isPrefetched()) {
// The user sent data to server, but not in the sync process. Check if we need to fetch data. // The user sent data to server, but not in the sync process. Check if we need to fetch data.

View File

@ -21,7 +21,7 @@ import { CoreCourse } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreTimeUtils } from '@services/utils/time'; import { CoreTimeUtils } from '@services/utils/time';
import { CoreUrlUtils } from '@services/utils/url'; import { CoreUrlUtils } from '@services/utils/url';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
@ -495,9 +495,7 @@ export const AddonModLessonSync = makeSingleton(AddonModLessonSyncProvider);
/** /**
* Data returned by a lesson sync. * Data returned by a lesson sync.
*/ */
export type AddonModLessonSyncResult = { export type AddonModLessonSyncResult = CoreSyncResult & {
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
courseId?: number; // Course the lesson belongs to (if known). courseId?: number; // Course the lesson belongs to (if known).
}; };

View File

@ -418,10 +418,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
} }
/** /**
* Checks if sync has succeed from result sync data. * @inheritdoc
*
* @param result Data returned on the sync function.
* @returns If suceed or not.
*/ */
protected hasSyncSucceed(result: AddonModQuizSyncResult): boolean { protected hasSyncSucceed(result: AddonModQuizSyncResult): boolean {
if (result.attemptFinished) { if (result.attemptFinished) {
@ -553,9 +550,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected async sync(): Promise<AddonModQuizSyncResult> { protected async sync(): Promise<AddonModQuizSyncResult> {
if (!this.candidateQuiz) { if (!this.candidateQuiz) {

View File

@ -13,7 +13,6 @@
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreError } from '@classes/errors/error';
import { CoreQuestionBehaviourDelegate, CoreQuestionQuestionWithAnswers } from '@features/question/services/behaviour-delegate'; import { CoreQuestionBehaviourDelegate, CoreQuestionQuestionWithAnswers } from '@features/question/services/behaviour-delegate';
import { CoreQuestionAnswerDBRecord } from '@features/question/services/database/question'; import { CoreQuestionAnswerDBRecord } from '@features/question/services/database/question';

View File

@ -23,7 +23,7 @@ import { CoreQuestion, CoreQuestionQuestionParsed } from '@features/question/ser
import { CoreQuestionDelegate } from '@features/question/services/question-delegate'; import { CoreQuestionDelegate } from '@features/question/services/question-delegate';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
@ -482,10 +482,8 @@ export const AddonModQuizSync = makeSingleton(AddonModQuizSyncProvider);
/** /**
* Data returned by a quiz sync. * Data returned by a quiz sync.
*/ */
export type AddonModQuizSyncResult = { export type AddonModQuizSyncResult = CoreSyncResult & {
warnings: string[]; // List of warnings.
attemptFinished: boolean; // Whether an attempt was finished in the site due to the sync. attemptFinished: boolean; // Whether an attempt was finished in the site due to the sync.
updated: boolean;
}; };
/** /**

View File

@ -14,6 +14,7 @@
import { CoreConstants } from '@/core/constants'; import { CoreConstants } from '@/core/constants';
import { Component, Input, OnInit, Optional } from '@angular/core'; import { Component, Input, OnInit, Optional } from '@angular/core';
import { CoreError } from '@classes/errors/error';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourse } from '@features/course/services/course'; import { CoreCourse } from '@features/course/services/course';
@ -364,10 +365,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
} }
/** /**
* Checks if sync has succeed from result sync data. * @inheritdoc
*
* @param result Data returned on the sync function.
* @returns If suceed or not.
*/ */
protected hasSyncSucceed(result: AddonModScormSyncResult): boolean { protected hasSyncSucceed(result: AddonModScormSyncResult): boolean {
if (result.updated || this.dataSent) { if (result.updated || this.dataSent) {
@ -377,7 +375,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
this.dataSent = false; this.dataSent = false;
return true; return result.updated;
} }
/** /**
@ -608,9 +606,9 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
* @param retries Number of retries done. * @param retries Number of retries done.
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
protected async sync(retries = 0): Promise<AddonModScormSyncResult | undefined> { protected async sync(retries = 0): Promise<AddonModScormSyncResult> {
if (!this.scorm) { if (!this.scorm) {
return; throw new CoreError('Cannot sync without a scorm.');
} }
if (CoreSync.isBlocked(AddonModScormProvider.COMPONENT, this.scorm.id) && retries < 5) { if (CoreSync.isBlocked(AddonModScormProvider.COMPONENT, this.scorm.id) && retries < 5) {

View File

@ -18,7 +18,7 @@ import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/act
import { CoreCourse } from '@features/course/services/course'; import { CoreCourse } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
@ -841,18 +841,14 @@ export const AddonModScormSync = makeSingleton(AddonModScormSyncProvider);
/** /**
* Data returned by a SCORM sync. * Data returned by a SCORM sync.
*/ */
export type AddonModScormSyncResult = { export type AddonModScormSyncResult = CoreSyncResult & {
warnings: string[]; // List of warnings.
attemptFinished: boolean; // Whether an attempt was finished in the site due to the sync, attemptFinished: boolean; // Whether an attempt was finished in the site due to the sync,
updated: boolean; // Whether some data was sent to the site.
}; };
/** /**
* Auto sync event data. * Auto sync event data.
*/ */
export type AddonModScormAutoSyncEventData = { export type AddonModScormAutoSyncEventData = CoreSyncResult & {
scormId: number; scormId: number;
attemptFinished: boolean; attemptFinished: boolean;
warnings: string[];
updated: boolean;
}; };

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
import { Component, OnInit, Optional } from '@angular/core'; import { Component, OnInit, Optional } from '@angular/core';
import { CoreError } from '@classes/errors/error';
import { CoreIonLoadingElement } from '@classes/ion-loading'; import { CoreIonLoadingElement } from '@classes/ion-loading';
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
@ -117,8 +118,8 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
if (sync) { if (sync) {
// Try to synchronize the survey. // Try to synchronize the survey.
const answersSent = await this.syncActivity(showErrors); const updated = await this.syncActivity(showErrors);
if (answersSent) { if (updated) {
// Answers were sent, update the survey. // Answers were sent, update the survey.
this.survey = await AddonModSurvey.getSurvey(this.courseId, this.module.id); this.survey = await AddonModSurvey.getSurvey(this.courseId, this.module.id);
} }
@ -236,26 +237,14 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected async sync(): Promise<AddonModSurveySyncResult | void> { protected async sync(): Promise<AddonModSurveySyncResult> {
if (!this.survey) { if (!this.survey) {
return; throw new CoreError('Cannot sync without a survey.');
} }
return AddonModSurveySync.syncSurvey(this.survey.id, this.currentUserId); return AddonModSurveySync.syncSurvey(this.survey.id, this.currentUserId);
} }
/**
* Checks if sync has succeed from result sync data.
*
* @param result Data returned on the sync function.
* @returns If suceed or not.
*/
protected hasSyncSucceed(result: AddonModSurveySyncResult): boolean {
return result.answersSent;
}
} }

View File

@ -15,6 +15,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync'; import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync';
import { CoreSyncResult } from '@services/sync';
import { CoreCourse } from '@features/course/services/course'; import { CoreCourse } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
@ -80,7 +81,7 @@ export class AddonModSurveySyncProvider extends CoreCourseActivitySyncBaseProvid
? this.syncSurvey(entry.surveyid, entry.userid, siteId) ? this.syncSurvey(entry.surveyid, entry.userid, siteId)
: this.syncSurveyIfNeeded(entry.surveyid, entry.userid, siteId)); : this.syncSurveyIfNeeded(entry.surveyid, entry.userid, siteId));
if (result && result.answersSent) { if (result && result.updated) {
// Sync successful, send event. // Sync successful, send event.
CoreEvents.trigger(AddonModSurveySyncProvider.AUTO_SYNCED, { CoreEvents.trigger(AddonModSurveySyncProvider.AUTO_SYNCED, {
surveyId: entry.surveyid, surveyId: entry.surveyid,
@ -150,7 +151,7 @@ export class AddonModSurveySyncProvider extends CoreCourseActivitySyncBaseProvid
protected async performSyncSurvey(surveyId: number, userId: number, siteId: string): Promise<AddonModSurveySyncResult> { protected async performSyncSurvey(surveyId: number, userId: number, siteId: string): Promise<AddonModSurveySyncResult> {
const result: AddonModSurveySyncResult = { const result: AddonModSurveySyncResult = {
warnings: [], warnings: [],
answersSent: false, updated: false,
}; };
// Sync offline logs. // Sync offline logs.
@ -179,7 +180,7 @@ export class AddonModSurveySyncProvider extends CoreCourseActivitySyncBaseProvid
try { try {
await AddonModSurvey.submitAnswersOnline(surveyId, data.answers, siteId); await AddonModSurvey.submitAnswersOnline(surveyId, data.answers, siteId);
result.answersSent = true; result.updated = true;
// Answers sent, delete them. // Answers sent, delete them.
await AddonModSurveyOffline.deleteSurveyAnswers(surveyId, siteId, userId); await AddonModSurveyOffline.deleteSurveyAnswers(surveyId, siteId, userId);
@ -190,7 +191,7 @@ export class AddonModSurveySyncProvider extends CoreCourseActivitySyncBaseProvid
} }
// The WebService has thrown an error, this means that answers cannot be submitted. Delete them. // The WebService has thrown an error, this means that answers cannot be submitted. Delete them.
result.answersSent = true; result.updated = true;
await AddonModSurveyOffline.deleteSurveyAnswers(surveyId, siteId, userId); await AddonModSurveyOffline.deleteSurveyAnswers(surveyId, siteId, userId);
@ -236,9 +237,7 @@ declare module '@singletons/events' {
/** /**
* Data returned by a assign sync. * Data returned by a assign sync.
*/ */
export type AddonModSurveySyncResult = { export type AddonModSurveySyncResult = CoreSyncResult & {
warnings: string[]; // List of warnings.
answersSent: boolean; // Whether some data was sent to the server or offline data was updated.
courseId?: number; // Course the survey belongs to (if known). courseId?: number; // Course the survey belongs to (if known).
}; };

View File

@ -707,12 +707,9 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} }
/** /**
* Checks if sync has succeed from result sync data. * @inheritdoc
*
* @param result Data returned on the sync function.
* @returns If suceed or not.
*/ */
protected hasSyncSucceed(result: AddonModWikiSyncWikiResult | undefined): boolean { protected hasSyncSucceed(result: AddonModWikiSyncWikiResult): boolean {
if (!result) { if (!result) {
return false; return false;
} }
@ -843,13 +840,11 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected async sync(): Promise<AddonModWikiSyncWikiResult | undefined> { protected async sync(): Promise<AddonModWikiSyncWikiResult> {
if (!this.wiki) { if (!this.wiki) {
return; throw new CoreError('Cannot sync without a wiki.');
} }
return AddonModWikiSync.syncWiki(this.wiki.id, this.courseId, this.wiki.coursemodule); return AddonModWikiSync.syncWiki(this.wiki.id, this.courseId, this.wiki.coursemodule);

View File

@ -19,7 +19,7 @@ import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreGroups } from '@services/groups'; import { CoreGroups } from '@services/groups';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
@ -345,9 +345,7 @@ export const AddonModWikiSync = makeSingleton(AddonModWikiSyncProvider);
/** /**
* Data returned by a subwiki sync. * Data returned by a subwiki sync.
*/ */
export type AddonModWikiSyncSubwikiResult = { export type AddonModWikiSyncSubwikiResult = CoreSyncResult & {
warnings: string[]; // List of warnings.
updated: boolean; // Whether data was updated in the site.
created: AddonModWikiCreatedPage[]; // List of created pages. created: AddonModWikiCreatedPage[]; // List of created pages.
discarded: AddonModWikiDiscardedPage[]; // List of discarded pages. discarded: AddonModWikiDiscardedPage[]; // List of discarded pages.
}; };
@ -355,9 +353,7 @@ export type AddonModWikiSyncSubwikiResult = {
/** /**
* Data returned by a wiki sync. * Data returned by a wiki sync.
*/ */
export type AddonModWikiSyncWikiResult = { export type AddonModWikiSyncWikiResult = CoreSyncResult & {
warnings: string[]; // List of warnings.
updated: boolean; // Whether data was updated in the site.
subwikis: { subwikis: {
[subwikiId: number]: { // List of subwikis. [subwikiId: number]: { // List of subwikis.
created: AddonModWikiCreatedPage[]; created: AddonModWikiCreatedPage[];

View File

@ -528,9 +528,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
} }
/** /**
* Performs the sync of the activity. * @inheritdoc
*
* @returns Promise resolved when done.
*/ */
protected sync(): Promise<AddonModWorkshopSyncResult> { protected sync(): Promise<AddonModWorkshopSyncResult> {
if (!this.workshop) { if (!this.workshop) {
@ -540,16 +538,6 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
return AddonModWorkshopSync.syncWorkshop(this.workshop.id); return AddonModWorkshopSync.syncWorkshop(this.workshop.id);
} }
/**
* Checks if sync has succeed from result sync data.
*
* @param result Data returned on the sync function.
* @returns If suceed or not.
*/
protected hasSyncSucceed(result: AddonModWorkshopSyncResult): boolean {
return result.updated;
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@ -20,7 +20,7 @@ import { CoreFileUploaderStoreFilesResult } from '@features/fileuploader/service
import { CoreNetwork } from '@services/network'; import { CoreNetwork } from '@services/network';
import { CoreFileEntry } from '@services/file-helper'; import { CoreFileEntry } from '@services/file-helper';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync, CoreSyncResult } from '@services/sync';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { Translate, makeSingleton } from '@singletons'; import { Translate, makeSingleton } from '@singletons';
@ -639,7 +639,4 @@ export type AddonModWorkshopAutoSyncData = {
warnings: string[]; warnings: string[];
}; };
export type AddonModWorkshopSyncResult = { export type AddonModWorkshopSyncResult = CoreSyncResult;
warnings: string[];
updated: boolean;
};

View File

@ -23,6 +23,7 @@ import { CoreNetwork } from '@services/network';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreCommentsDBRecord, CoreCommentsDeletedDBRecord } from './database/comments'; import { CoreCommentsDBRecord, CoreCommentsDeletedDBRecord } from './database/comments';
import { CoreSyncResult } from '@services/sync';
/** /**
* Service to sync omments. * Service to sync omments.
@ -318,10 +319,7 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider<CoreCommentsS
} }
export const CoreCommentsSync = makeSingleton(CoreCommentsSyncProvider); export const CoreCommentsSync = makeSingleton(CoreCommentsSyncProvider);
export type CoreCommentsSyncResult = { export type CoreCommentsSyncResult = CoreSyncResult;
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
};
/** /**
* Data passed to AUTO_SYNCED event. * Data passed to AUTO_SYNCED event.

View File

@ -20,9 +20,9 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreCourse } from '../services/course'; import { CoreCourse } from '../services/course';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreWSExternalWarning } from '@services/ws';
import { CoreCourseContentsPage } from '../pages/contents/contents'; import { CoreCourseContentsPage } from '../pages/contents/contents';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreSyncResult } from '@services/sync';
/** /**
* Template class to easily create CoreCourseModuleMainComponent of activities. * Template class to easily create CoreCourseModuleMainComponent of activities.
@ -188,32 +188,34 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
* *
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
protected async sync(): Promise<unknown> { protected async sync(): Promise<CoreSyncResult> {
return {}; return {
updated: false,
warnings: [],
};
} }
/** /**
* Checks if sync has succeed from result sync data. * Checks if sync has updated data on the server.
* *
* @param result Data returned on the sync function. * @param result Data returned on the sync function.
* @returns If suceed or not. * @returns If data has been updated or not.
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars protected hasSyncSucceed(result: CoreSyncResult): boolean {
protected hasSyncSucceed(result: unknown): boolean { return result.updated;
return true;
} }
/** /**
* Tries to synchronize the activity. * Tries to synchronize the activity.
* *
* @param showErrors If show errors to the user of hide them. * @param showErrors If show errors to the user of hide them.
* @returns Promise resolved with true if sync succeed, or false if failed. * @returns Promise resolved with true if sync hast updated data to the server, false otherwise.
*/ */
protected async syncActivity(showErrors: boolean = false): Promise<boolean> { protected async syncActivity(showErrors: boolean = false): Promise<boolean> {
try { try {
const result = <{warnings?: CoreWSExternalWarning[]}> await this.sync(); const result = await this.sync();
if (result?.warnings?.length) { if (result.warnings.length) {
CoreDomUtils.showErrorModal(result.warnings[0]); CoreDomUtils.showErrorModal(result.warnings[0]);
} }

View File

@ -183,3 +183,8 @@ export class CoreSyncProvider {
} }
export const CoreSync = makeSingleton(CoreSyncProvider); export const CoreSync = makeSingleton(CoreSyncProvider);
export type CoreSyncResult = {
warnings: string[]; // List of warnings.
updated: boolean; // Whether some data was sent to the server or offline data was updated.
};