diff --git a/src/addon/mod/data/components/index/index.ts b/src/addon/mod/data/components/index/index.ts index e1d85cda6..409bf230f 100644 --- a/src/addon/mod/data/components/index/index.ts +++ b/src/addon/mod/data/components/index/index.ts @@ -99,6 +99,10 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp this.selectedGroup = this.group || 0; this.loadContent(false, true).then(() => { + if (!this.data) { + return; + } + this.dataProvider.logView(this.data.id).then(() => { this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); }); @@ -216,10 +220,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp } this.search.advanced = []; - this.fields = {}; - fields.forEach((field) => { - this.fields[field.id] = field; - }); + this.fields = this.utils.arrayToObject(fields, 'id'); this.fieldsArray = this.utils.objectToArray(this.fields); return this.fetchEntriesData(); @@ -295,11 +296,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp entries.entries.forEach((entry) => { // Index contents by fieldid. - const contents = {}; - entry.contents.forEach((field) => { - contents[field.fieldid] = field; - }); - entry.contents = contents; + entry.contents = this.utils.arrayToObject(entry.contents, 'fieldid'); if (typeof this.offlineActions[entry.id] != 'undefined') { promises.push(this.dataHelper.applyOfflineActions(entry, this.offlineActions[entry.id], this.fieldsArray)); @@ -391,7 +388,12 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp this.searchEntries(0); } - // Set group to see the database. + /** + * Set group to see the database. + * + * @param {number} groupId Group ID. + * @return {Promise} Resolved when new group is selected or rejected if not. + */ setGroup(groupId: number): Promise { this.selectedGroup = groupId; @@ -406,14 +408,13 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp * Opens add entries form. */ gotoAddEntries(): void { - const stateParams = { - moduleId: this.module.id, + const params = { module: this.module, courseId: this.courseId, group: this.selectedGroup }; - this.navCtrl.push('AddonModDataEditPage', stateParams); + this.navCtrl.push('AddonModDataEditPage', params); } /** @@ -422,15 +423,14 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp * @param {number} entryId Entry ID. */ gotoEntry(entryId: number): void { - const stateParams = { + const params = { module: this.module, - moduleId: this.module.id, courseId: this.courseId, entryId: entryId, group: this.selectedGroup }; - this.navCtrl.push('AddonModDataEntryPage', stateParams); + this.navCtrl.push('AddonModDataEntryPage', params); } /** diff --git a/src/addon/mod/data/fields/textarea/component/textarea.html b/src/addon/mod/data/fields/textarea/component/textarea.html index d07c54193..861d1edc9 100644 --- a/src/addon/mod/data/fields/textarea/component/textarea.html +++ b/src/addon/mod/data/fields/textarea/component/textarea.html @@ -2,9 +2,8 @@ - - - + + \ No newline at end of file diff --git a/src/addon/mod/data/pages/edit/edit.ts b/src/addon/mod/data/pages/edit/edit.ts index 2f6e44566..a4daffa6f 100644 --- a/src/addon/mod/data/pages/edit/edit.ts +++ b/src/addon/mod/data/pages/edit/edit.ts @@ -154,12 +154,7 @@ export class AddonModDataEditPage { return this.dataProvider.getFields(this.data.id); }).then((fieldsData) => { - this.fields = {}; - fieldsData.forEach((field) => { - this.fields[field.id] = field; - }); - - this.fieldsArray = fieldsData; + this.fields = this.utils.arrayToObject(fieldsData, 'id'); return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions); }).then((entry) => { @@ -167,11 +162,7 @@ export class AddonModDataEditPage { entry = entry.entry; // Index contents by fieldid. - const contents = {}; - entry.contents.forEach((field) => { - contents[field.fieldid] = field; - }); - entry.contents = contents; + entry.contents = this.utils.arrayToObject(entry.contents, 'fieldid'); } else { entry = { contents: {} @@ -185,8 +176,6 @@ export class AddonModDataEditPage { this.editFormRender = this.displayEditFields(); }).catch((message) => { this.domUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true); - - return Promise.reject(null); }).finally(() => { this.loaded = true; }); diff --git a/src/addon/mod/data/pages/entry/entry.ts b/src/addon/mod/data/pages/entry/entry.ts index c6e4c8cb5..b43816471 100644 --- a/src/addon/mod/data/pages/entry/entry.ts +++ b/src/addon/mod/data/pages/entry/entry.ts @@ -126,6 +126,8 @@ export class AddonModDataEntryPage implements OnDestroy { * @return {Promise} Resolved when done. */ protected fetchEntryData(refresh?: boolean): Promise { + let fieldsArray; + return this.dataProvider.getDatabase(this.courseId, this.module.id).then((data) => { this.title = data.name || this.title; this.data = data; @@ -155,10 +157,7 @@ export class AddonModDataEntryPage implements OnDestroy { this.hasOffline = !!actions.length; return this.dataProvider.getFields(this.data.id).then((fieldsData) => { - this.fields = {}; - fieldsData.forEach((field) => { - this.fields[field.id] = field; - }); + this.fields = this.utils.arrayToObject(fieldsData, 'id'); return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions); }); @@ -167,20 +166,15 @@ export class AddonModDataEntryPage implements OnDestroy { this.cssTemplate = this.dataHelper.prefixCSS(this.data.csstemplate, '.' + this.cssClass); // Index contents by fieldid. - const contents = {}; - entry.contents.forEach((field) => { - contents[field.fieldid] = field; - }); - entry.contents = contents; + entry.contents = this.utils.arrayToObject(entry.contents, 'fieldid'); - const fieldsArray = this.utils.objectToArray(this.fields); + 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), - fieldsArray = this.utils.objectToArray(this.fields); + const actions = this.dataHelper.getActions(this.data, this.access, this.entry); this.entryRendered = this.dataHelper.displayShowFields(this.data.singletemplate, fieldsArray, this.entry, 'show', actions); @@ -207,8 +201,6 @@ export class AddonModDataEntryPage implements OnDestroy { } this.domUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true); - - return Promise.reject(null); }).finally(() => { this.content && this.content.scrollToTop(); this.entryLoaded = true; diff --git a/src/addon/mod/data/pages/search/search.ts b/src/addon/mod/data/pages/search/search.ts index df40db75a..160f0ad59 100644 --- a/src/addon/mod/data/pages/search/search.ts +++ b/src/addon/mod/data/pages/search/search.ts @@ -17,6 +17,7 @@ import { IonicPage, NavParams, ViewController } from 'ionic-angular'; import { FormBuilder, FormGroup } from '@angular/forms'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreTextUtilsProvider } from '@providers/utils/text'; import { AddonModDataComponentsModule } from '../../components/components.module'; import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate'; @@ -39,14 +40,15 @@ export class AddonModDataSearchPage { fieldsArray: any; constructor(params: NavParams, private viewCtrl: ViewController, fb: FormBuilder, protected utils: CoreUtilsProvider, - protected domUtils: CoreDomUtilsProvider, protected fieldsDelegate: AddonModDataFieldsDelegate) { + protected domUtils: CoreDomUtilsProvider, protected fieldsDelegate: AddonModDataFieldsDelegate, + protected textUtils: CoreTextUtilsProvider) { this.search = params.get('search'); this.fields = params.get('fields'); this.data = params.get('data'); const advanced = {}; this.search.advanced.forEach((field) => { - advanced[field.name] = field.value ? JSON.parse(field.value) : ''; + advanced[field.name] = field.value ? this.textUtils.parseJSON(field.value) : ''; }); this.search.advanced = advanced; diff --git a/src/addon/mod/data/providers/approve-link-handler.ts b/src/addon/mod/data/providers/approve-link-handler.ts index bd3c9c71a..5e7a88a7d 100644 --- a/src/addon/mod/data/providers/approve-link-handler.ts +++ b/src/addon/mod/data/providers/approve-link-handler.ts @@ -76,7 +76,6 @@ export class AddonModDataApproveLinkHandler extends CoreContentLinksHandlerBase // Approve/disapprove entry. return this.dataProvider.approveEntry(dataId, entryId, approve, courseId, siteId).catch((message) => { - modal.dismiss(); this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errorapproving', true); return Promise.reject(null); @@ -90,11 +89,9 @@ export class AddonModDataApproveLinkHandler extends CoreContentLinksHandlerBase }).then(() => { this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED, {dataId: dataId, entryId: entryId}, siteId); - modal.dismiss(); this.domUtils.showToast(approve ? 'addon.mod_data.recordapproved' : 'addon.mod_data.recorddisapproved', true, 3000); }).finally(() => { - // Just in case. In fact we need to dismiss the modal before showing a toast or error message. modal.dismiss(); }); } diff --git a/src/addon/mod/data/providers/data.ts b/src/addon/mod/data/providers/data.ts index 5c665e605..4632f2f36 100644 --- a/src/addon/mod/data/providers/data.ts +++ b/src/addon/mod/data/providers/data.ts @@ -724,7 +724,7 @@ export class AddonModDataProvider { /** * Invalidate the prefetched content. - * To invalidate files, use AddonDataProvider#invalidateFiles. + * To invalidate files, use AddonModDataProvider#invalidateFiles. * * @param {number} moduleId The module ID. * @param {number} courseId Course ID of the module. diff --git a/src/addon/mod/data/providers/delete-link-handler.ts b/src/addon/mod/data/providers/delete-link-handler.ts index 43af7fb8a..9338d7817 100644 --- a/src/addon/mod/data/providers/delete-link-handler.ts +++ b/src/addon/mod/data/providers/delete-link-handler.ts @@ -75,7 +75,6 @@ export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase { // Delete entry. return this.dataProvider.deleteEntry(dataId, entryId, courseId, siteId).catch((message) => { - modal.dismiss(); this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errordeleting', true); return Promise.reject(null); @@ -90,10 +89,8 @@ export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase { this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED, {dataId: dataId, entryId: entryId, deleted: true}, siteId); - modal.dismiss(); this.domUtils.showToast('addon.mod_data.recorddeleted', true, 3000); }).finally(() => { - // Just in case. In fact we need to dismiss the modal before showing a toast or error message. modal.dismiss(); }); } diff --git a/src/addon/mod/data/providers/edit-link-handler.ts b/src/addon/mod/data/providers/edit-link-handler.ts index 448035aeb..b6857f3ab 100644 --- a/src/addon/mod/data/providers/edit-link-handler.ts +++ b/src/addon/mod/data/providers/edit-link-handler.ts @@ -53,17 +53,16 @@ export class AddonModDataEditLinkHandler extends CoreContentLinksHandlerBase { rId = parseInt(params.rid, 10) || false; this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => { - const stateParams = { - moduleId: module.id, + const pageParams = { module: module, courseId: module.course }; if (rId) { - stateParams['entryId'] = rId; + pageParams['entryId'] = rId; } - return this.linkHelper.goInSite(navCtrl, 'AddonModDataEditPage', stateParams, siteId); + return this.linkHelper.goInSite(navCtrl, 'AddonModDataEditPage', pageParams, siteId); }).finally(() => { // Just in case. In fact we need to dismiss the modal before showing a toast or error message. modal.dismiss(); diff --git a/src/addon/mod/data/providers/fields-delegate.ts b/src/addon/mod/data/providers/fields-delegate.ts index a72f0ad46..43f2895c5 100644 --- a/src/addon/mod/data/providers/fields-delegate.ts +++ b/src/addon/mod/data/providers/fields-delegate.ts @@ -186,10 +186,6 @@ export class AddonModDataFieldsDelegate extends CoreDelegate { * @return {Promise} Promise rejected if has changed, resolved if no changes. */ hasFieldDataChanged(field: any, inputData: any, originalFieldData: any): Promise { - if (!this.hasFunction(field.type, 'hasFieldDataChanged')) { - return Promise.resolve(); - } - return Promise.resolve(this.executeFunctionOnEnabled(field.type, 'hasFieldDataChanged', [field, inputData, originalFieldData])).then((result) => { return result ? Promise.reject(null) : Promise.resolve(); @@ -216,7 +212,7 @@ export class AddonModDataFieldsDelegate extends CoreDelegate { * @return {any} Data overriden */ overrideData(field: any, originalContent: any, offlineContent: any, offlineFiles?: any): any { - if (!offlineContent || !this.hasFunction(field.type, 'overrideData')) { + if (!offlineContent) { return originalContent; } diff --git a/src/addon/mod/data/providers/helper.ts b/src/addon/mod/data/providers/helper.ts index 96f049947..dd152ae51 100644 --- a/src/addon/mod/data/providers/helper.ts +++ b/src/addon/mod/data/providers/helper.ts @@ -13,9 +13,10 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreSitesProvider } from '@providers/sites'; -import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; import { TranslateService } from '@ngx-translate/core'; +import { CoreSitesProvider } from '@providers/sites'; +import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; import { AddonModDataFieldsDelegate } from './fields-delegate'; import { AddonModDataOfflineProvider } from './offline'; import { AddonModDataProvider } from './data'; @@ -28,7 +29,8 @@ export class AddonModDataHelperProvider { constructor(private sitesProvider: CoreSitesProvider, protected dataProvider: AddonModDataProvider, private translate: TranslateService, private fieldsDelegate: AddonModDataFieldsDelegate, - private dataOffline: AddonModDataOfflineProvider, private fileUploaderProvider: CoreFileUploaderProvider) { } + private dataOffline: AddonModDataOfflineProvider, private fileUploaderProvider: CoreFileUploaderProvider, + private textUtils: CoreTextUtilsProvider) { } /** * Returns the record with the offline actions applied. @@ -62,9 +64,10 @@ export class AddonModDataHelperProvider { } if (offlineContent.subfield) { - offlineContents[offlineContent.fieldid][offlineContent.subfield] = JSON.parse(offlineContent.value); + offlineContents[offlineContent.fieldid][offlineContent.subfield] = + this.textUtils.parseJSON(offlineContent.value); } else { - offlineContents[offlineContent.fieldid][''] = JSON.parse(offlineContent.value); + offlineContents[offlineContent.fieldid][''] = this.textUtils.parseJSON(offlineContent.value); } }); diff --git a/src/addon/mod/data/providers/prefetch-handler.ts b/src/addon/mod/data/providers/prefetch-handler.ts index fbd8921ce..81413449f 100644 --- a/src/addon/mod/data/providers/prefetch-handler.ts +++ b/src/addon/mod/data/providers/prefetch-handler.ts @@ -238,7 +238,11 @@ export class AddonModDataPrefetchHandler extends CoreCourseModulePrefetchHandler * @return {Promise} Promise resolved when invalidated. */ invalidateModule(module: any, courseId: number): Promise { - return this.dataProvider.invalidateDatabaseData(courseId); + const promises = []; + promises.push(this.dataProvider.invalidateDatabaseData(courseId)); + promises.push(this.dataProvider.invalidateDatabaseAccessInformationData(module.instance)); + + return Promise.all(promises); } /** diff --git a/src/addon/mod/data/providers/show-link-handler.ts b/src/addon/mod/data/providers/show-link-handler.ts index 702a03345..1d30f33ea 100644 --- a/src/addon/mod/data/providers/show-link-handler.ts +++ b/src/addon/mod/data/providers/show-link-handler.ts @@ -55,23 +55,22 @@ export class AddonModDataShowLinkHandler extends CoreContentLinksHandlerBase { page = parseInt(params.page, 10) || false; this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => { - const stateParams = { - moduleId: module.id, + const pageParams = { module: module, courseId: module.course }; if (group) { - stateParams['group'] = group; + pageParams['group'] = group; } if (params.mode && params.mode == 'single') { - stateParams['page'] = page || 1; + pageParams['page'] = page || 1; } else if (rId) { - stateParams['entryId'] = rId; + pageParams['entryId'] = rId; } - return this.linkHelper.goInSite(navCtrl, 'AddonModDataEntryPage', stateParams, siteId); + return this.linkHelper.goInSite(navCtrl, 'AddonModDataEntryPage', pageParams, siteId); }).finally(() => { // Just in case. In fact we need to dismiss the modal before showing a toast or error message. modal.dismiss(); diff --git a/src/addon/mod/data/providers/sync.ts b/src/addon/mod/data/providers/sync.ts index 3a7ccfb0f..e29f29ab6 100644 --- a/src/addon/mod/data/providers/sync.ts +++ b/src/addon/mod/data/providers/sync.ts @@ -251,7 +251,7 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider { if (action.fields) { action.fields.forEach((field) => { // Upload Files if asked. - const value = JSON.parse(field.value); + const value = this.textUtils.parseJSON(field.value); if (value.online || value.offline) { let files = value.online || []; const fileProm = value.offline ? this.dataHelper.getStoredFiles(action.dataid, entryId, field.fieldid) :