MOBILE-2338 data: Fix during PR

main
Pau Ferrer Ocaña 2018-05-30 11:16:31 +02:00
parent 1bcc3c35b7
commit 518d1091ee
14 changed files with 54 additions and 77 deletions

View File

@ -99,6 +99,10 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
this.selectedGroup = this.group || 0; this.selectedGroup = this.group || 0;
this.loadContent(false, true).then(() => { this.loadContent(false, true).then(() => {
if (!this.data) {
return;
}
this.dataProvider.logView(this.data.id).then(() => { this.dataProvider.logView(this.data.id).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}); });
@ -216,10 +220,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
} }
this.search.advanced = []; this.search.advanced = [];
this.fields = {}; this.fields = this.utils.arrayToObject(fields, 'id');
fields.forEach((field) => {
this.fields[field.id] = field;
});
this.fieldsArray = this.utils.objectToArray(this.fields); this.fieldsArray = this.utils.objectToArray(this.fields);
return this.fetchEntriesData(); return this.fetchEntriesData();
@ -295,11 +296,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
entries.entries.forEach((entry) => { entries.entries.forEach((entry) => {
// Index contents by fieldid. // Index contents by fieldid.
const contents = {}; entry.contents = this.utils.arrayToObject(entry.contents, 'fieldid');
entry.contents.forEach((field) => {
contents[field.fieldid] = field;
});
entry.contents = contents;
if (typeof this.offlineActions[entry.id] != 'undefined') { if (typeof this.offlineActions[entry.id] != 'undefined') {
promises.push(this.dataHelper.applyOfflineActions(entry, this.offlineActions[entry.id], this.fieldsArray)); promises.push(this.dataHelper.applyOfflineActions(entry, this.offlineActions[entry.id], this.fieldsArray));
@ -391,7 +388,12 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
this.searchEntries(0); this.searchEntries(0);
} }
// Set group to see the database. /**
* Set group to see the database.
*
* @param {number} groupId Group ID.
* @return {Promise<any>} Resolved when new group is selected or rejected if not.
*/
setGroup(groupId: number): Promise<any> { setGroup(groupId: number): Promise<any> {
this.selectedGroup = groupId; this.selectedGroup = groupId;
@ -406,14 +408,13 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
* Opens add entries form. * Opens add entries form.
*/ */
gotoAddEntries(): void { gotoAddEntries(): void {
const stateParams = { const params = {
moduleId: this.module.id,
module: this.module, module: this.module,
courseId: this.courseId, courseId: this.courseId,
group: this.selectedGroup 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. * @param {number} entryId Entry ID.
*/ */
gotoEntry(entryId: number): void { gotoEntry(entryId: number): void {
const stateParams = { const params = {
module: this.module, module: this.module,
moduleId: this.module.id,
courseId: this.courseId, courseId: this.courseId,
entryId: entryId, entryId: entryId,
group: this.selectedGroup group: this.selectedGroup
}; };
this.navCtrl.push('AddonModDataEntryPage', stateParams); this.navCtrl.push('AddonModDataEntryPage', params);
} }
/** /**

View File

@ -2,8 +2,7 @@
<ion-input *ngIf="mode == 'search'" type="text" [placeholder]="field.name" [formControlName]="'f_'+field.id"></ion-input> <ion-input *ngIf="mode == 'search'" type="text" [placeholder]="field.name" [formControlName]="'f_'+field.id"></ion-input>
<span *ngIf="mode == 'edit'" [core-mark-required]="field.required" class="core-mark-required"></span> <span *ngIf="mode == 'edit'" [core-mark-required]="field.required" class="core-mark-required"></span>
<core-rich-text-editor *ngIf="mode == 'edit'" item-content [control]="form.controls['f_'+field.id]" [placeholder]="field.name" [formControlName]="'f_'+field.id"></core-rich-text-editor> <core-rich-text-editor *ngIf="mode == 'edit'" item-content [control]="form.controls['f_'+field.id]" [placeholder]="field.name" [formControlName]="'f_'+field.id" [component]="component" [componentId]="componentId"></core-rich-text-editor>
<!-- @todo: [component]="component" [componentId]="componentId" -->
<core-input-errors *ngIf="error && mode == 'edit'" [control]="form.controls['f_'+field.id]" [errorText]="error"></core-input-errors> <core-input-errors *ngIf="error && mode == 'edit'" [control]="form.controls['f_'+field.id]" [errorText]="error"></core-input-errors>
</span> </span>

View File

@ -154,12 +154,7 @@ export class AddonModDataEditPage {
return this.dataProvider.getFields(this.data.id); return this.dataProvider.getFields(this.data.id);
}).then((fieldsData) => { }).then((fieldsData) => {
this.fields = {}; this.fields = this.utils.arrayToObject(fieldsData, 'id');
fieldsData.forEach((field) => {
this.fields[field.id] = field;
});
this.fieldsArray = fieldsData;
return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions); return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions);
}).then((entry) => { }).then((entry) => {
@ -167,11 +162,7 @@ export class AddonModDataEditPage {
entry = entry.entry; entry = entry.entry;
// Index contents by fieldid. // Index contents by fieldid.
const contents = {}; entry.contents = this.utils.arrayToObject(entry.contents, 'fieldid');
entry.contents.forEach((field) => {
contents[field.fieldid] = field;
});
entry.contents = contents;
} else { } else {
entry = { entry = {
contents: {} contents: {}
@ -185,8 +176,6 @@ export class AddonModDataEditPage {
this.editFormRender = this.displayEditFields(); this.editFormRender = this.displayEditFields();
}).catch((message) => { }).catch((message) => {
this.domUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true); this.domUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true);
return Promise.reject(null);
}).finally(() => { }).finally(() => {
this.loaded = true; this.loaded = true;
}); });

View File

@ -126,6 +126,8 @@ export class AddonModDataEntryPage implements OnDestroy {
* @return {Promise<any>} Resolved when done. * @return {Promise<any>} Resolved when done.
*/ */
protected fetchEntryData(refresh?: boolean): Promise<any> { protected fetchEntryData(refresh?: boolean): Promise<any> {
let fieldsArray;
return this.dataProvider.getDatabase(this.courseId, this.module.id).then((data) => { return this.dataProvider.getDatabase(this.courseId, this.module.id).then((data) => {
this.title = data.name || this.title; this.title = data.name || this.title;
this.data = data; this.data = data;
@ -155,10 +157,7 @@ export class AddonModDataEntryPage implements OnDestroy {
this.hasOffline = !!actions.length; this.hasOffline = !!actions.length;
return this.dataProvider.getFields(this.data.id).then((fieldsData) => { return this.dataProvider.getFields(this.data.id).then((fieldsData) => {
this.fields = {}; this.fields = this.utils.arrayToObject(fieldsData, 'id');
fieldsData.forEach((field) => {
this.fields[field.id] = field;
});
return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions); 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); this.cssTemplate = this.dataHelper.prefixCSS(this.data.csstemplate, '.' + this.cssClass);
// Index contents by fieldid. // Index contents by fieldid.
const contents = {}; entry.contents = this.utils.arrayToObject(entry.contents, 'fieldid');
entry.contents.forEach((field) => {
contents[field.fieldid] = field;
});
entry.contents = contents;
const fieldsArray = this.utils.objectToArray(this.fields); fieldsArray = this.utils.objectToArray(this.fields);
return this.dataHelper.applyOfflineActions(entry, this.offlineActions, fieldsArray); return this.dataHelper.applyOfflineActions(entry, this.offlineActions, fieldsArray);
}).then((entryData) => { }).then((entryData) => {
this.entry = entryData; this.entry = entryData;
const actions = this.dataHelper.getActions(this.data, this.access, this.entry), const actions = this.dataHelper.getActions(this.data, this.access, this.entry);
fieldsArray = this.utils.objectToArray(this.fields);
this.entryRendered = this.dataHelper.displayShowFields(this.data.singletemplate, fieldsArray, this.entryRendered = this.dataHelper.displayShowFields(this.data.singletemplate, fieldsArray,
this.entry, 'show', actions); this.entry, 'show', actions);
@ -207,8 +201,6 @@ export class AddonModDataEntryPage implements OnDestroy {
} }
this.domUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true); this.domUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true);
return Promise.reject(null);
}).finally(() => { }).finally(() => {
this.content && this.content.scrollToTop(); this.content && this.content.scrollToTop();
this.entryLoaded = true; this.entryLoaded = true;

View File

@ -17,6 +17,7 @@ import { IonicPage, NavParams, ViewController } from 'ionic-angular';
import { FormBuilder, FormGroup } from '@angular/forms'; import { FormBuilder, FormGroup } from '@angular/forms';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreTextUtilsProvider } from '@providers/utils/text';
import { AddonModDataComponentsModule } from '../../components/components.module'; import { AddonModDataComponentsModule } from '../../components/components.module';
import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate'; import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
@ -39,14 +40,15 @@ export class AddonModDataSearchPage {
fieldsArray: any; fieldsArray: any;
constructor(params: NavParams, private viewCtrl: ViewController, fb: FormBuilder, protected utils: CoreUtilsProvider, 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.search = params.get('search');
this.fields = params.get('fields'); this.fields = params.get('fields');
this.data = params.get('data'); this.data = params.get('data');
const advanced = {}; const advanced = {};
this.search.advanced.forEach((field) => { 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; this.search.advanced = advanced;

View File

@ -76,7 +76,6 @@ export class AddonModDataApproveLinkHandler extends CoreContentLinksHandlerBase
// Approve/disapprove entry. // Approve/disapprove entry.
return this.dataProvider.approveEntry(dataId, entryId, approve, courseId, siteId).catch((message) => { return this.dataProvider.approveEntry(dataId, entryId, approve, courseId, siteId).catch((message) => {
modal.dismiss();
this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errorapproving', true); this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errorapproving', true);
return Promise.reject(null); return Promise.reject(null);
@ -90,11 +89,9 @@ export class AddonModDataApproveLinkHandler extends CoreContentLinksHandlerBase
}).then(() => { }).then(() => {
this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED, {dataId: dataId, entryId: entryId}, siteId); 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, this.domUtils.showToast(approve ? 'addon.mod_data.recordapproved' : 'addon.mod_data.recorddisapproved', true,
3000); 3000);
}).finally(() => { }).finally(() => {
// Just in case. In fact we need to dismiss the modal before showing a toast or error message.
modal.dismiss(); modal.dismiss();
}); });
} }

View File

@ -724,7 +724,7 @@ export class AddonModDataProvider {
/** /**
* Invalidate the prefetched content. * Invalidate the prefetched content.
* To invalidate files, use AddonDataProvider#invalidateFiles. * To invalidate files, use AddonModDataProvider#invalidateFiles.
* *
* @param {number} moduleId The module ID. * @param {number} moduleId The module ID.
* @param {number} courseId Course ID of the module. * @param {number} courseId Course ID of the module.

View File

@ -75,7 +75,6 @@ export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase {
// Delete entry. // Delete entry.
return this.dataProvider.deleteEntry(dataId, entryId, courseId, siteId).catch((message) => { return this.dataProvider.deleteEntry(dataId, entryId, courseId, siteId).catch((message) => {
modal.dismiss();
this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errordeleting', true); this.domUtils.showErrorModalDefault(message, 'addon.mod_data.errordeleting', true);
return Promise.reject(null); return Promise.reject(null);
@ -90,10 +89,8 @@ export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase {
this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED, {dataId: dataId, entryId: entryId, this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED, {dataId: dataId, entryId: entryId,
deleted: true}, siteId); deleted: true}, siteId);
modal.dismiss();
this.domUtils.showToast('addon.mod_data.recorddeleted', true, 3000); this.domUtils.showToast('addon.mod_data.recorddeleted', true, 3000);
}).finally(() => { }).finally(() => {
// Just in case. In fact we need to dismiss the modal before showing a toast or error message.
modal.dismiss(); modal.dismiss();
}); });
} }

View File

@ -53,17 +53,16 @@ export class AddonModDataEditLinkHandler extends CoreContentLinksHandlerBase {
rId = parseInt(params.rid, 10) || false; rId = parseInt(params.rid, 10) || false;
this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => { this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => {
const stateParams = { const pageParams = {
moduleId: module.id,
module: module, module: module,
courseId: module.course courseId: module.course
}; };
if (rId) { 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(() => { }).finally(() => {
// Just in case. In fact we need to dismiss the modal before showing a toast or error message. // Just in case. In fact we need to dismiss the modal before showing a toast or error message.
modal.dismiss(); modal.dismiss();

View File

@ -186,10 +186,6 @@ export class AddonModDataFieldsDelegate extends CoreDelegate {
* @return {Promise<void>} Promise rejected if has changed, resolved if no changes. * @return {Promise<void>} Promise rejected if has changed, resolved if no changes.
*/ */
hasFieldDataChanged(field: any, inputData: any, originalFieldData: any): Promise<void> { hasFieldDataChanged(field: any, inputData: any, originalFieldData: any): Promise<void> {
if (!this.hasFunction(field.type, 'hasFieldDataChanged')) {
return Promise.resolve();
}
return Promise.resolve(this.executeFunctionOnEnabled(field.type, 'hasFieldDataChanged', return Promise.resolve(this.executeFunctionOnEnabled(field.type, 'hasFieldDataChanged',
[field, inputData, originalFieldData])).then((result) => { [field, inputData, originalFieldData])).then((result) => {
return result ? Promise.reject(null) : Promise.resolve(); return result ? Promise.reject(null) : Promise.resolve();
@ -216,7 +212,7 @@ export class AddonModDataFieldsDelegate extends CoreDelegate {
* @return {any} Data overriden * @return {any} Data overriden
*/ */
overrideData(field: any, originalContent: any, offlineContent: any, offlineFiles?: any): any { overrideData(field: any, originalContent: any, offlineContent: any, offlineFiles?: any): any {
if (!offlineContent || !this.hasFunction(field.type, 'overrideData')) { if (!offlineContent) {
return originalContent; return originalContent;
} }

View File

@ -13,9 +13,10 @@
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreSitesProvider } from '@providers/sites';
import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
import { TranslateService } from '@ngx-translate/core'; 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 { AddonModDataFieldsDelegate } from './fields-delegate';
import { AddonModDataOfflineProvider } from './offline'; import { AddonModDataOfflineProvider } from './offline';
import { AddonModDataProvider } from './data'; import { AddonModDataProvider } from './data';
@ -28,7 +29,8 @@ export class AddonModDataHelperProvider {
constructor(private sitesProvider: CoreSitesProvider, protected dataProvider: AddonModDataProvider, constructor(private sitesProvider: CoreSitesProvider, protected dataProvider: AddonModDataProvider,
private translate: TranslateService, private fieldsDelegate: AddonModDataFieldsDelegate, 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. * Returns the record with the offline actions applied.
@ -62,9 +64,10 @@ export class AddonModDataHelperProvider {
} }
if (offlineContent.subfield) { if (offlineContent.subfield) {
offlineContents[offlineContent.fieldid][offlineContent.subfield] = JSON.parse(offlineContent.value); offlineContents[offlineContent.fieldid][offlineContent.subfield] =
this.textUtils.parseJSON(offlineContent.value);
} else { } else {
offlineContents[offlineContent.fieldid][''] = JSON.parse(offlineContent.value); offlineContents[offlineContent.fieldid][''] = this.textUtils.parseJSON(offlineContent.value);
} }
}); });

View File

@ -238,7 +238,11 @@ export class AddonModDataPrefetchHandler extends CoreCourseModulePrefetchHandler
* @return {Promise<any>} Promise resolved when invalidated. * @return {Promise<any>} Promise resolved when invalidated.
*/ */
invalidateModule(module: any, courseId: number): Promise<any> { invalidateModule(module: any, courseId: number): Promise<any> {
return this.dataProvider.invalidateDatabaseData(courseId); const promises = [];
promises.push(this.dataProvider.invalidateDatabaseData(courseId));
promises.push(this.dataProvider.invalidateDatabaseAccessInformationData(module.instance));
return Promise.all(promises);
} }
/** /**

View File

@ -55,23 +55,22 @@ export class AddonModDataShowLinkHandler extends CoreContentLinksHandlerBase {
page = parseInt(params.page, 10) || false; page = parseInt(params.page, 10) || false;
this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => { this.courseProvider.getModuleBasicInfoByInstance(dataId, 'data', siteId).then((module) => {
const stateParams = { const pageParams = {
moduleId: module.id,
module: module, module: module,
courseId: module.course courseId: module.course
}; };
if (group) { if (group) {
stateParams['group'] = group; pageParams['group'] = group;
} }
if (params.mode && params.mode == 'single') { if (params.mode && params.mode == 'single') {
stateParams['page'] = page || 1; pageParams['page'] = page || 1;
} else if (rId) { } 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(() => { }).finally(() => {
// Just in case. In fact we need to dismiss the modal before showing a toast or error message. // Just in case. In fact we need to dismiss the modal before showing a toast or error message.
modal.dismiss(); modal.dismiss();

View File

@ -251,7 +251,7 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider {
if (action.fields) { if (action.fields) {
action.fields.forEach((field) => { action.fields.forEach((field) => {
// Upload Files if asked. // Upload Files if asked.
const value = JSON.parse(field.value); const value = this.textUtils.parseJSON(field.value);
if (value.online || value.offline) { if (value.online || value.offline) {
let files = value.online || []; let files = value.online || [];
const fileProm = value.offline ? this.dataHelper.getStoredFiles(action.dataid, entryId, field.fieldid) : const fileProm = value.offline ? this.dataHelper.getStoredFiles(action.dataid, entryId, field.fieldid) :