diff --git a/src/addon/mod/data/components/index/index.ts b/src/addon/mod/data/components/index/index.ts index ac4d95546..3236fbd37 100644 --- a/src/addon/mod/data/components/index/index.ts +++ b/src/addon/mod/data/components/index/index.ts @@ -20,11 +20,9 @@ import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups'; import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component'; import { CoreCommentsProvider } from '@core/comments/providers/comments'; import { CoreRatingProvider } from '@core/rating/providers/rating'; -import { CoreRatingOfflineProvider } from '@core/rating/providers/offline'; import { CoreRatingSyncProvider } from '@core/rating/providers/sync'; import { AddonModDataProvider } from '../../providers/data'; import { AddonModDataHelperProvider } from '../../providers/helper'; -import { AddonModDataOfflineProvider } from '../../providers/offline'; import { AddonModDataSyncProvider } from '../../providers/sync'; import { AddonModDataComponentsModule } from '../components.module'; import { AddonModDataPrefetchHandler } from '../../providers/prefetch-handler'; @@ -65,8 +63,6 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp advanced: [] }; hasNextPage = false; - offlineActions: any; - offlineEntries: any; entriesRendered = ''; extraImports = [AddonModDataComponentsModule]; jsData; @@ -81,12 +77,19 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp protected ratingOfflineObserver: any; protected ratingSyncObserver: any; - constructor(injector: Injector, private dataProvider: AddonModDataProvider, private dataHelper: AddonModDataHelperProvider, - private dataOffline: AddonModDataOfflineProvider, @Optional() content: Content, - private prefetchHandler: AddonModDataPrefetchHandler, private timeUtils: CoreTimeUtilsProvider, - private groupsProvider: CoreGroupsProvider, private commentsProvider: CoreCommentsProvider, - private modalCtrl: ModalController, private utils: CoreUtilsProvider, protected navCtrl: NavController, - private ratingOffline: CoreRatingOfflineProvider) { + constructor( + injector: Injector, + @Optional() content: Content, + private dataProvider: AddonModDataProvider, + private dataHelper: AddonModDataHelperProvider, + private prefetchHandler: AddonModDataPrefetchHandler, + private timeUtils: CoreTimeUtilsProvider, + private groupsProvider: CoreGroupsProvider, + private commentsProvider: CoreCommentsProvider, + private modalCtrl: ModalController, + private utils: CoreUtilsProvider, + protected navCtrl: NavController) { + super(injector, content); // Refresh entries on change. @@ -233,8 +236,6 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp this.selectedGroup = groupInfo.groups[0].id; } } - - return this.fetchOfflineEntries(); }); }).then(() => { return this.dataProvider.getFields(this.data.id).then((fields) => { @@ -270,21 +271,19 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp // Update values for current group. this.access.canaddentry = accessData.canaddentry; - if (this.search.searching) { - const text = this.search.searchingAdvanced ? undefined : this.search.text, - advanced = this.search.searchingAdvanced ? this.search.advanced : undefined; + const search = this.search.searching && !this.search.searchingAdvanced ? this.search.text : undefined; + const advSearch = this.search.searching && this.search.searchingAdvanced ? this.search.advanced : undefined; - return this.dataProvider.searchEntries(this.data.id, this.selectedGroup, text, advanced, this.search.sortBy, - this.search.sortDirection, this.search.page); - } else { - return this.dataProvider.getEntries(this.data.id, this.selectedGroup, this.search.sortBy, this.search.sortDirection, - this.search.page); - } + return this.dataHelper.fetchEntries(this.data, this.fieldsArray, this.selectedGroup, search, advSearch, + this.search.sortBy, this.search.sortDirection, this.search.page); }).then((entries) => { - const numEntries = (entries && entries.entries && entries.entries.length) || 0; - this.isEmpty = !numEntries && !Object.keys(this.offlineActions).length && !Object.keys(this.offlineEntries).length; + const numEntries = entries.entries.length; + const numOfflineEntries = entries.offlineEntries.length; + this.isEmpty = !numEntries && !entries.offlineEntries.length; this.hasNextPage = numEntries >= AddonModDataProvider.PER_PAGE && ((this.search.page + 1) * AddonModDataProvider.PER_PAGE) < entries.totalcount; + this.hasOffline = entries.hasOfflineActions; + this.hasOfflineRatings = entries.hasOfflineRatings; this.entriesRendered = ''; if (typeof entries.maxcount != 'undefined') { @@ -298,76 +297,40 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp } if (!this.isEmpty) { - const siteInfo = this.sitesProvider.getCurrentSite().getInfo(), - promises = []; + this.entries = entries.offlineEntries.concat(entries.entries); - this.utils.objectToArray(this.offlineEntries).forEach((offlineActions) => { - const offlineEntry = offlineActions.find((offlineEntry) => offlineEntry.action == 'add'); + let entriesHTML = this.data.listtemplateheader || ''; - if (offlineEntry) { - const entry = { - id: offlineEntry.entryid, - canmanageentry: true, - approved: !this.data.approval || this.data.manageapproved, - dataid: offlineEntry.dataid, - groupid: offlineEntry.groupid, - timecreated: -offlineEntry.entryid, - timemodified: -offlineEntry.entryid, - userid: siteInfo.userid, - fullname: siteInfo.fullname, - contents: {} - }; + // Get first entry from the whole list. + if (!this.search.searching || !this.firstEntry) { + this.firstEntry = this.entries[0].id; + } - if (offlineActions.length > 0) { - promises.push(this.dataHelper.applyOfflineActions(entry, offlineActions, this.fieldsArray)); - } else { - promises.push(Promise.resolve(entry)); - } - } + const template = this.data.listtemplate || this.dataHelper.getDefaultTemplate('list', this.fieldsArray); + + const entriesById = {}; + this.entries.forEach((entry, index) => { + entriesById[entry.id] = entry; + + const actions = this.dataHelper.getActions(this.data, this.access, entry); + const offset = this.search.searching ? undefined : + this.search.page * AddonModDataProvider.PER_PAGE + index - numOfflineEntries; + + entriesHTML += this.dataHelper.displayShowFields(template, this.fieldsArray, entry, offset, 'list', actions); }); + entriesHTML += this.data.listtemplatefooter || ''; - entries.entries.forEach((entry) => { - if (typeof this.offlineActions[entry.id] != 'undefined') { - promises.push(this.dataHelper.applyOfflineActions(entry, this.offlineActions[entry.id], this.fieldsArray)); - } else { - promises.push(Promise.resolve(entry)); - } - }); + this.entriesRendered = entriesHTML; - return Promise.all(promises).then((entries) => { - this.entries = entries; - - let entriesHTML = this.data.listtemplateheader || ''; - - // Get first entry from the whole list. - if (entries && entries[0] && (!this.search.searching || !this.firstEntry)) { - this.firstEntry = entries[0].id; - } - - const template = this.data.listtemplate || this.dataHelper.getDefaultTemplate('list', this.fieldsArray); - - const entriesById = {}; - entries.forEach((entry, index) => { - entriesById[entry.id] = entry; - - const actions = this.dataHelper.getActions(this.data, this.access, entry); - const offset = this.search.page * AddonModDataProvider.PER_PAGE + index; - - entriesHTML += this.dataHelper.displayShowFields(template, this.fieldsArray, entry, offset, 'list', - actions); - }); - entriesHTML += this.data.listtemplatefooter || ''; - - this.entriesRendered = entriesHTML; - - // Pass the input data to the component. - this.jsData = { - fields: this.fields, - entries: entriesById, - data: this.data, - gotoEntry: this.gotoEntry.bind(this) - }; - }); + // Pass the input data to the component. + this.jsData = { + fields: this.fields, + entries: entriesById, + data: this.data, + module: this.module, + group: this.selectedGroup, + gotoEntry: this.gotoEntry.bind(this) + }; } else if (!this.search.searching) { // Empty and no searching. this.canSearch = false; @@ -476,42 +439,6 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp this.navCtrl.push('AddonModDataEntryPage', params); } - /** - * Fetch offline entries. - * - * @return {Promise} Resolved then done. - */ - protected fetchOfflineEntries(): Promise { - // Check if there are entries stored in offline. - return this.dataOffline.getDatabaseEntries(this.data.id).then((offlineEntries) => { - this.hasOffline = !!offlineEntries.length; - - this.offlineActions = {}; - this.offlineEntries = {}; - - // Only show offline entries on first page. - if (this.search.page == 0 && this.hasOffline) { - offlineEntries.forEach((entry) => { - if (entry.entryid > 0) { - if (typeof this.offlineActions[entry.entryid] == 'undefined') { - this.offlineActions[entry.entryid] = []; - } - this.offlineActions[entry.entryid].push(entry); - } else { - if (typeof this.offlineActions[entry.entryid] == 'undefined') { - this.offlineEntries[entry.entryid] = []; - } - this.offlineEntries[entry.entryid].push(entry); - } - }); - } - }).then(() => { - return this.ratingOffline.hasRatings('mod_data', 'entry', 'module', this.data.coursemodule).then((hasRatings) => { - this.hasOfflineRatings = hasRatings; - }); - }); - } - /** * Performs the sync of the activity. * diff --git a/src/addon/mod/data/pages/edit/edit.ts b/src/addon/mod/data/pages/edit/edit.ts index ce8ccd06a..bed268873 100644 --- a/src/addon/mod/data/pages/edit/edit.ts +++ b/src/addon/mod/data/pages/edit/edit.ts @@ -45,7 +45,6 @@ export class AddonModDataEditPage { protected data: any; protected entryId: number; protected entry: any; - protected offlineActions = []; protected fields = {}; protected fieldsArray = []; protected siteId: string; @@ -145,28 +144,14 @@ export class AddonModDataEditPage { }); } }).then(() => { - return this.dataOffline.getEntryActions(this.data.id, this.entryId); - }).then((actions) => { - this.offlineActions = actions; - return this.dataProvider.getFields(this.data.id); }).then((fieldsData) => { this.fieldsArray = fieldsData; this.fields = this.utils.arrayToObject(fieldsData, 'id'); - return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions); + return this.dataHelper.fetchEntry(this.data, fieldsData, this.entryId); }).then((entry) => { - if (entry) { - entry = entry.entry; - } else { - entry = { - contents: {} - }; - } - - return this.dataHelper.applyOfflineActions(entry, this.offlineActions, this.fieldsArray); - }).then((entryData) => { - this.entry = entryData; + this.entry = entry.entry; this.editFormRender = this.displayEditFields(); }).catch((message) => { diff --git a/src/addon/mod/data/pages/entry/entry.html b/src/addon/mod/data/pages/entry/entry.html index aef6d0da0..20e8d31d0 100644 --- a/src/addon/mod/data/pages/entry/entry.html +++ b/src/addon/mod/data/pages/entry/entry.html @@ -9,7 +9,7 @@ -
+
{{ 'core.hasdatatosync' | translate: {$a: moduleName} }}
@@ -31,7 +31,7 @@ - + diff --git a/src/addon/mod/data/pages/entry/entry.ts b/src/addon/mod/data/pages/entry/entry.ts index 0ae32b2be..07b3ee48f 100644 --- a/src/addon/mod/data/pages/entry/entry.ts +++ b/src/addon/mod/data/pages/entry/entry.ts @@ -23,7 +23,6 @@ import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreRatingInfo } from '@core/rating/providers/rating'; import { AddonModDataProvider } from '../../providers/data'; import { AddonModDataHelperProvider } from '../../providers/helper'; -import { AddonModDataOfflineProvider } from '../../providers/offline'; import { AddonModDataSyncProvider } from '../../providers/sync'; import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate'; import { AddonModDataComponentsModule } from '../../components/components.module'; @@ -46,6 +45,7 @@ export class AddonModDataEntryPage implements OnDestroy { protected syncObserver: any; // It will observe the sync auto event. protected entryChangedObserver: any; // It will observe the changed entry event. protected fields = {}; + protected fieldsArray = []; title = ''; moduleName = 'data'; @@ -56,8 +56,6 @@ export class AddonModDataEntryPage implements OnDestroy { loadingRating = false; selectedGroup = 0; entry: any; - offlineActions = []; - hasOffline = false; previousOffset: number; nextOffset: number; access: any; @@ -74,7 +72,7 @@ export class AddonModDataEntryPage implements OnDestroy { constructor(params: NavParams, protected utils: CoreUtilsProvider, protected groupsProvider: CoreGroupsProvider, protected domUtils: CoreDomUtilsProvider, protected fieldsDelegate: AddonModDataFieldsDelegate, protected courseProvider: CoreCourseProvider, protected dataProvider: AddonModDataProvider, - protected dataOffline: AddonModDataOfflineProvider, protected dataHelper: AddonModDataHelperProvider, + protected dataHelper: AddonModDataHelperProvider, sitesProvider: CoreSitesProvider, protected navCtrl: NavController, protected eventsProvider: CoreEventsProvider, private cdr: ChangeDetectorRef) { this.module = params.get('module') || {}; @@ -131,8 +129,6 @@ export class AddonModDataEntryPage implements OnDestroy { * @return {Promise} Resolved when done. */ protected fetchEntryData(refresh?: boolean, isPtr?: boolean): Promise { - let fieldsArray; - this.isPullingToRefresh = isPtr; return this.dataProvider.getDatabase(this.courseId, this.module.id).then((data) => { @@ -155,32 +151,22 @@ export class AddonModDataEntryPage implements OnDestroy { this.selectedGroup = groupInfo.groups[0].id; } } - - return this.dataOffline.getEntryActions(this.data.id, this.entryId); }); - }).then((actions) => { - this.offlineActions = actions; - this.hasOffline = !!actions.length; - + }).then(() => { return this.dataProvider.getFields(this.data.id).then((fieldsData) => { this.fields = this.utils.arrayToObject(fieldsData, 'id'); + this.fieldsArray = fieldsData; - return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions); + return this.dataHelper.fetchEntry(this.data, fieldsData, this.entryId); }); }).then((entry) => { + this.entry = entry.entry; this.ratingInfo = entry.ratinginfo; - entry = entry.entry; - - fieldsArray = this.utils.objectToArray(this.fields); - - return this.dataHelper.applyOfflineActions(entry, this.offlineActions, fieldsArray); - }).then((entryData) => { - this.entry = entryData; const actions = this.dataHelper.getActions(this.data, this.access, this.entry); - const templte = this.data.singletemplate || this.dataHelper.getDefaultTemplate('single', fieldsArray); - this.entryHtml = this.dataHelper.displayShowFields(templte, fieldsArray, this.entry, this.offset, 'show', actions); + const templte = this.data.singletemplate || this.dataHelper.getDefaultTemplate('single', this.fieldsArray); + this.entryHtml = this.dataHelper.displayShowFields(templte, this.fieldsArray, this.entry, this.offset, 'show', actions); this.showComments = actions.comments; const entries = {}; diff --git a/src/addon/mod/data/providers/helper.ts b/src/addon/mod/data/providers/helper.ts index 930d63e15..c2428fabb 100644 --- a/src/addon/mod/data/providers/helper.ts +++ b/src/addon/mod/data/providers/helper.ts @@ -19,7 +19,9 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; import { AddonModDataFieldsDelegate } from './fields-delegate'; import { AddonModDataOfflineProvider, AddonModDataOfflineAction } from './offline'; -import { AddonModDataProvider, AddonModDataEntry, AddonModDataEntryFields } from './data'; +import { AddonModDataProvider, AddonModDataEntry, AddonModDataEntryFields, AddonModDataEntries } from './data'; +import { CoreRatingInfo } from '@core/rating/providers/rating'; +import { CoreRatingOfflineProvider } from '@core/rating/providers/offline'; /** * Service that provides helper functions for datas. @@ -30,7 +32,7 @@ export class AddonModDataHelperProvider { constructor(private sitesProvider: CoreSitesProvider, protected dataProvider: AddonModDataProvider, private translate: TranslateService, private fieldsDelegate: AddonModDataFieldsDelegate, private dataOffline: AddonModDataOfflineProvider, private fileUploaderProvider: CoreFileUploaderProvider, - private textUtils: CoreTextUtilsProvider) { } + private textUtils: CoreTextUtilsProvider, private ratingOffline: CoreRatingOfflineProvider) { } /** * Returns the record with the offline actions applied. @@ -156,6 +158,153 @@ export class AddonModDataHelperProvider { return template; } + /** + * Get online and offline entries, or search entries. + * + * @param {any} data Database object. + * @param {any[]} fields The fields that define the contents. + * @param {number} [groupId=0] Group ID. + * @param {string} [search] Search text. It will be used if advSearch is not defined. + * @param {any[]} [advSearch] Advanced search data. + * @param {string} [sort=0] Sort the records by this field id, reserved ids are: + * 0: timeadded + * -1: firstname + * -2: lastname + * -3: approved + * -4: timemodified. + * Empty for using the default database setting. + * @param {string} [order=DESC] The direction of the sorting: 'ASC' or 'DESC'. + * Empty for using the default database setting. + * @param {number} [page=0] Page of records to return. + * @param {number} [perPage=PER_PAGE] Records per page to return. Default on PER_PAGE. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the database is retrieved. + */ + fetchEntries(data: any, fields: any[], groupId: number = 0, search?: string, advSearch?: any[], sort: string = '0', + order: string = 'DESC', page: number = 0, perPage: number = AddonModDataProvider.PER_PAGE, siteId?: string): + Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + const offlineActions = {}; + const result: AddonModDataEntries = { + entries: [], + totalcount: 0, + offlineEntries: [] + }; + + const offlinePromise = this.dataOffline.getDatabaseEntries(data.id, site.id).then((actions) => { + result.hasOfflineActions = !!actions.length; + + actions.forEach((action) => { + if (typeof offlineActions[action.entryid] == 'undefined') { + offlineActions[action.entryid] = []; + } + offlineActions[action.entryid].push(action); + + // We only display new entries in the first page when not searching. + if (action.action == 'add' && page == 0 && !search && !advSearch && + (!action.groupid || !groupId || action.groupid == groupId)) { + result.offlineEntries.push({ + id: action.entryid, + canmanageentry: true, + approved: !data.approval || data.manageapproved, + dataid: data.id, + groupid: action.groupid, + timecreated: -action.entryid, + timemodified: -action.entryid, + userid: site.getUserId(), + fullname: site.getInfo().fullname, + contents: {} + }); + } + }); + + // Sort offline entries by creation time. + result.offlineEntries.sort((entry1, entry2) => entry2.timecreated - entry1.timecreated); + }); + + const ratingsPromise = this.ratingOffline.hasRatings('mod_data', 'entry', 'module', data.coursemodule) + .then((hasRatings) => { + result.hasOfflineRatings = hasRatings; + }); + + let fetchPromise: Promise; + if (search || advSearch) { + fetchPromise = this.dataProvider.searchEntries(data.id, groupId, search, advSearch, sort, order, page, perPage, + site.id).then((fetchResult) => { + result.entries = fetchResult.entries; + result.totalcount = fetchResult.totalcount; + result.maxcount = fetchResult.maxcount; + }); + } else { + fetchPromise = this.dataProvider.getEntries(data.id, groupId, sort, order, page, perPage, false, false, site.id) + .then((fetchResult) => { + result.entries = fetchResult.entries; + result.totalcount = fetchResult.totalcount; + }); + } + + return Promise.all([offlinePromise, ratingsPromise, fetchPromise]).then(() => { + // Apply offline actions to online and offline entries. + const promises = []; + result.entries.forEach((entry) => { + promises.push(this.applyOfflineActions(entry, offlineActions[entry.id] || [], fields)); + }); + result.offlineEntries.forEach((entry) => { + promises.push(this.applyOfflineActions(entry, offlineActions[entry.id] || [], fields)); + }); + + return Promise.all(promises); + }).then(() => { + return result; + }); + }); + } + + /** + * Fetch an online or offline entry. + * + * @param {any} data Database. + * @param {any[]} fields List of database fields. + * @param {number} entryId Entry ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise<{entry: AddonModDataEntry, ratinginfo?: CoreRatingInfo}>} Promise resolved with the entry. + */ + fetchEntry(data: any, fields: any[], entryId: number, siteId?: string): + Promise<{entry: AddonModDataEntry, ratinginfo?: CoreRatingInfo}> { + return this.sitesProvider.getSite(siteId).then((site) => { + return this.dataOffline.getEntryActions(data.id, entryId, site.id).then((offlineActions) => { + let promise: Promise<{entry: AddonModDataEntry, ratinginfo?: CoreRatingInfo}>; + + if (entryId > 0) { + // Online entry. + promise = this.dataProvider.getEntry(data.id, entryId, false, site.id); + } else { + // Offline entry or new entry. + promise = Promise.resolve({ + entry: { + id: entryId, + userid: site.getUserId(), + groupid: 0, + dataid: data.id, + timecreated: -entryId, + timemodified: -entryId, + approved: !data.approval || data.manageapproved, + canmanageentry: true, + fullname: site.getInfo().fullname, + contents: [], + } + }); + } + + return promise.then((response) => { + return this.applyOfflineActions(response.entry, offlineActions, fields).then(() => { + return response; + }); + }); + }); + }); + } + /** * Returns an object with all the actions that the user can do over the record. * @@ -352,45 +501,6 @@ export class AddonModDataHelperProvider { }); } - /** - * Get an online or offline entry. - * - * @param {any} data Database. - * @param {number} entryId Entry ID. - * @param {any} [offlineActions] Offline data with the actions done. Required for offline entries. - * @param {string} [siteId] Site ID. If not defined, current site. - * @return {Promise} Promise resolved with the entry. - */ - getEntry(data: any, entryId: number, offlineActions?: any, siteId?: string): Promise { - if (entryId > 0) { - // It's an online entry, get it from WS. - return this.dataProvider.getEntry(data.id, entryId, false, siteId); - } - - // It's an offline entry, search it in the offline actions. - return this.sitesProvider.getSite(siteId).then((site) => { - const offlineEntry = offlineActions.find((offlineAction) => offlineAction.action == 'add'); - - if (offlineEntry) { - const siteInfo = site.getInfo(); - - return {entry: { - id: offlineEntry.entryid, - canmanageentry: true, - approved: !data.approval || data.manageapproved, - dataid: offlineEntry.dataid, - groupid: offlineEntry.groupid, - timecreated: -offlineEntry.entryid, - timemodified: -offlineEntry.entryid, - userid: siteInfo.userid, - fullname: siteInfo.fullname, - contents: {} - } - }; - } - }); - } - /** * Get a list of stored attachment files for a new entry. See $mmaModDataHelper#storeFiles. * diff --git a/src/addon/mod/data/providers/offline.ts b/src/addon/mod/data/providers/offline.ts index 92e38cb25..2d6d6ca4a 100644 --- a/src/addon/mod/data/providers/offline.ts +++ b/src/addon/mod/data/providers/offline.ts @@ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; import { CoreLoggerProvider } from '@providers/logger'; import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites'; import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreFileProvider } from '@providers/file'; import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; import { SQLiteDB } from '@classes/sqlitedb'; @@ -101,7 +102,8 @@ export class AddonModDataOfflineProvider { }; constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider, - private fileProvider: CoreFileProvider, private fileUploaderProvider: CoreFileUploaderProvider) { + private fileProvider: CoreFileProvider, private fileUploaderProvider: CoreFileUploaderProvider, + private utils: CoreUtilsProvider) { this.logger = logger.getInstance('AddonModDataOfflineProvider'); this.sitesProvider.registerSiteSchema(this.siteSchema); } @@ -201,7 +203,7 @@ export class AddonModDataOfflineProvider { } /** - * Get all the stored entry data from a certain database. + * Get all the stored entry actions from a certain database, sorted by modification time. * * @param {number} dataId Database ID. * @param {string} [siteId] Site ID. If not defined, current site. @@ -209,7 +211,7 @@ export class AddonModDataOfflineProvider { */ getDatabaseEntries(dataId: number, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { - return site.getDb().getRecords(AddonModDataOfflineProvider.DATA_ENTRY_TABLE, {dataid: dataId}); + return site.getDb().getRecords(AddonModDataOfflineProvider.DATA_ENTRY_TABLE, {dataid: dataId}, 'timemodified'); }).then((entries) => { return entries.map(this.parseRecord.bind(this)); }); @@ -257,11 +259,10 @@ export class AddonModDataOfflineProvider { * @return {Promise} Promise resolved with boolean: true if has offline answers, false otherwise. */ hasOfflineData(dataId: number, siteId?: string): Promise { - return this.getDatabaseEntries(dataId, siteId).then((entries) => { - return !!entries.length; - }).catch(() => { - // No offline data found, return false. - return false; + return this.sitesProvider.getSite(siteId).then((site) => { + return this.utils.promiseWorks( + site.getDb().recordExists(AddonModDataOfflineProvider.DATA_ENTRY_TABLE, {dataid: dataId}) + ); }); }