diff --git a/src/addon/mod/data/fields/file/component/file.ts b/src/addon/mod/data/fields/file/component/file.ts
index b802d6f17..e39faafe5 100644
--- a/src/addon/mod/data/fields/file/component/file.ts
+++ b/src/addon/mod/data/fields/file/component/file.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
import { CoreFileSessionProvider } from '@providers/file-session';
@@ -24,7 +24,7 @@ import { AddonModDataProvider } from '../../../providers/data';
selector: 'addon-mod-data-field-file',
templateUrl: 'file.html'
})
-export class AddonModDataFieldFileComponent extends AddonModDataFieldPluginComponent implements OnInit {
+export class AddonModDataFieldFileComponent extends AddonModDataFieldPluginComponent {
files = [];
component: string;
@@ -35,14 +35,6 @@ export class AddonModDataFieldFileComponent extends AddonModDataFieldPluginCompo
super(fb);
}
- /**
- * Component being initialized.
- */
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
/**
* Get the files from the input value.
*
@@ -60,20 +52,32 @@ export class AddonModDataFieldFileComponent extends AddonModDataFieldPluginCompo
return files;
}
- protected render(): void {
- if (this.mode == 'show' || this.mode == 'edit') {
+ /**
+ * Initialize field.
+ */
+ protected init(): void {
+ if (this.mode != 'search') {
this.component = AddonModDataProvider.COMPONENT;
this.componentId = this.database.coursemodule;
- this.files = this.getFiles(this.value);
+ this.updateValue(this.value);
- if (this.mode != 'show') {
- // Edit mode, the list shouldn't change so there is no need to watch it.
+ if (this.mode == 'edit') {
this.maxSizeBytes = parseInt(this.field.param3, 10);
this.fileSessionprovider.setFiles(this.component, this.database.id + '_' + this.field.id, this.files);
}
+ } else {
+ this.addControl('f_' + this.field.id);
}
+ }
- this.addControl('f_' + this.field.id);
+ /**
+ * Update value being shown.
+ *
+ * @param {any} value New value to be set.
+ */
+ protected updateValue(value: any): void {
+ this.value = value;
+ this.files = this.getFiles(value);
}
}
diff --git a/src/addon/mod/data/fields/latlong/component/latlong.html b/src/addon/mod/data/fields/latlong/component/latlong.html
index 9303ec6d7..a219e554f 100644
--- a/src/addon/mod/data/fields/latlong/component/latlong.html
+++ b/src/addon/mod/data/fields/latlong/component/latlong.html
@@ -1,21 +1,19 @@
-
+
-
-
-
-
-
-
+
+
+
°N
-
-
-
+
+
+
°E
-
+
+
-
+
{{ formatLatLong(north, east) }}
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/latlong/component/latlong.ts b/src/addon/mod/data/fields/latlong/component/latlong.ts
index f9933bf6e..2b7fda2be 100644
--- a/src/addon/mod/data/fields/latlong/component/latlong.ts
+++ b/src/addon/mod/data/fields/latlong/component/latlong.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Platform } from 'ionic-angular';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
@@ -23,7 +23,7 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-latlong',
templateUrl: 'latlong.html'
})
-export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginComponent implements OnInit {
+export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginComponent {
north: number;
east: number;
@@ -69,17 +69,11 @@ export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginCo
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
+ protected init(): void {
if (this.value) {
- this.north = (this.value && parseFloat(this.value.content)) || null;
- this.east = (this.value && parseFloat(this.value.content1)) || null;
+ this.updateValue(this.value);
}
if (this.mode == 'edit') {
@@ -89,4 +83,15 @@ export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginCo
this.addControl('f_' + this.field.id);
}
}
+
+ /**
+ * Update value being shown.
+ *
+ * @param {any} value New value to be set.
+ */
+ protected updateValue(value: any): void {
+ this.value = value;
+ this.north = (value && parseFloat(value.content)) || null;
+ this.east = (value && parseFloat(value.content1)) || null;
+ }
}
diff --git a/src/addon/mod/data/fields/menu/component/menu.html b/src/addon/mod/data/fields/menu/component/menu.html
index c7e9e03c8..9a9357500 100644
--- a/src/addon/mod/data/fields/menu/component/menu.html
+++ b/src/addon/mod/data/fields/menu/component/menu.html
@@ -1,11 +1,10 @@
-
-
-
-
-
+
+
+
{{ 'addon.mod_data.menuchoose' | translate }}
{{option}}
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/menu/component/menu.ts b/src/addon/mod/data/fields/menu/component/menu.ts
index 7a7f867bf..e722375ef 100644
--- a/src/addon/mod/data/fields/menu/component/menu.ts
+++ b/src/addon/mod/data/fields/menu/component/menu.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
@@ -22,7 +22,7 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-menu',
templateUrl: 'menu.html'
})
-export class AddonModDataFieldMenuComponent extends AddonModDataFieldPluginComponent implements OnInit {
+export class AddonModDataFieldMenuComponent extends AddonModDataFieldPluginComponent {
options = [];
@@ -31,15 +31,10 @@ export class AddonModDataFieldMenuComponent extends AddonModDataFieldPluginCompo
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
- if (this.mode == 'show') {
+ protected init(): void {
+ if (this.isShowOrListMode()) {
return;
}
diff --git a/src/addon/mod/data/fields/menu/providers/handler.ts b/src/addon/mod/data/fields/menu/providers/handler.ts
index 4e6938c28..e8427cc66 100644
--- a/src/addon/mod/data/fields/menu/providers/handler.ts
+++ b/src/addon/mod/data/fields/menu/providers/handler.ts
@@ -47,7 +47,6 @@ export class AddonModDataFieldMenuHandler implements AddonModDataFieldHandler {
*/
getFieldSearchData(field: any, inputData: any): any {
const fieldName = 'f_' + field.id;
-
if (inputData[fieldName]) {
return [{
name: fieldName,
diff --git a/src/addon/mod/data/fields/multimenu/component/multimenu.html b/src/addon/mod/data/fields/multimenu/component/multimenu.html
index 6bd9c1bd6..e1d9081ba 100644
--- a/src/addon/mod/data/fields/multimenu/component/multimenu.html
+++ b/src/addon/mod/data/fields/multimenu/component/multimenu.html
@@ -1,10 +1,9 @@
-
-
-
-
-
+
+
+
{{option.key}}
+
@@ -14,4 +13,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/multimenu/component/multimenu.ts b/src/addon/mod/data/fields/multimenu/component/multimenu.ts
index 963b279f9..a93ee67d5 100644
--- a/src/addon/mod/data/fields/multimenu/component/multimenu.ts
+++ b/src/addon/mod/data/fields/multimenu/component/multimenu.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
@@ -22,7 +22,7 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-multimenu',
templateUrl: 'multimenu.html'
})
-export class AddonModDataFieldMultimenuComponent extends AddonModDataFieldPluginComponent implements OnInit {
+export class AddonModDataFieldMultimenuComponent extends AddonModDataFieldPluginComponent {
options = [];
@@ -31,16 +31,11 @@ export class AddonModDataFieldMultimenuComponent extends AddonModDataFieldPlugin
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
- if (this.mode == 'show') {
- this.value.content = this.value && this.value.content && this.value.content.split('##').join('
');
+ protected init(): void {
+ if (this.isShowOrListMode()) {
+ this.updateValue(this.value);
return;
}
@@ -49,11 +44,12 @@ export class AddonModDataFieldMultimenuComponent extends AddonModDataFieldPlugin
return { key: option, value: option };
});
+ const values = [];
if (this.mode == 'edit' && this.value && this.value.content) {
this.value.content.split('##').forEach((value) => {
const x = this.options.findIndex((option) => value == option.key);
if (x >= 0) {
- this.options[x].selected = true;
+ values.push(value);
}
});
}
@@ -62,6 +58,16 @@ export class AddonModDataFieldMultimenuComponent extends AddonModDataFieldPlugin
this.addControl('f_' + this.field.id + '_allreq');
}
- this.addControl('f_' + this.field.id);
+ this.addControl('f_' + this.field.id, values);
+ }
+
+ /**
+ * Update value being shown.
+ *
+ * @param {any} value New value to be set.
+ */
+ protected updateValue(value: any): void {
+ this.value = value;
+ this.value.content = value && value.content && value.content.split('##').join('
');
}
}
diff --git a/src/addon/mod/data/fields/multimenu/providers/handler.ts b/src/addon/mod/data/fields/multimenu/providers/handler.ts
index c5d5c5fcc..716da06bf 100644
--- a/src/addon/mod/data/fields/multimenu/providers/handler.ts
+++ b/src/addon/mod/data/fields/multimenu/providers/handler.ts
@@ -81,13 +81,10 @@ export class AddonModDataFieldMultimenuHandler implements AddonModDataFieldHandl
const fieldName = 'f_' + field.id;
if (inputData[fieldName] && inputData[fieldName].length > 0) {
- const options = inputData[fieldName].split('###');
- if (options.length > 0) {
- return [{
- fieldid: field.id,
- value: options
- }];
- }
+ return [{
+ fieldid: field.id,
+ value: inputData[fieldName]
+ }];
}
return false;
@@ -102,11 +99,11 @@ export class AddonModDataFieldMultimenuHandler implements AddonModDataFieldHandl
* @return {Promise | boolean} If the field has changes.
*/
hasFieldDataChanged(field: any, inputData: any, originalFieldData: any): Promise | boolean {
- const fieldName = 'f_' + field.id,
- input = inputData[fieldName] || '';
+ const fieldName = 'f_' + field.id;
+
originalFieldData = (originalFieldData && originalFieldData.content) || '';
- return input != originalFieldData;
+ return inputData[fieldName].join('##') != originalFieldData;
}
/**
diff --git a/src/addon/mod/data/fields/number/component/number.html b/src/addon/mod/data/fields/number/component/number.html
index 17a4a6423..aa71edc43 100644
--- a/src/addon/mod/data/fields/number/component/number.html
+++ b/src/addon/mod/data/fields/number/component/number.html
@@ -1,9 +1,7 @@
-
-
-
-
-
+
+
+
-
+
diff --git a/src/addon/mod/data/fields/number/component/number.ts b/src/addon/mod/data/fields/number/component/number.ts
index 9fe4d6472..c7dcb1127 100644
--- a/src/addon/mod/data/fields/number/component/number.ts
+++ b/src/addon/mod/data/fields/number/component/number.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
@@ -22,31 +22,26 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-number',
templateUrl: 'number.html'
})
-export class AddonModDataFieldNumberComponent extends AddonModDataFieldPluginComponent implements OnInit {
-
- val: number;
+export class AddonModDataFieldNumberComponent extends AddonModDataFieldPluginComponent{
constructor(protected fb: FormBuilder) {
super(fb);
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
- if (this.mode == 'show') {
+ protected init(): void {
+ if (this.isShowOrListMode()) {
return;
}
+ let value;
if (this.mode == 'edit' && this.value) {
- this.val = this.value && parseFloat(this.value.content);
+ const v = parseFloat(this.value.content);
+ value = isNaN(v) ? '' : v;
}
- this.addControl('f_' + this.field.id, this.val);
+ this.addControl('f_' + this.field.id, value);
}
}
diff --git a/src/addon/mod/data/fields/number/providers/handler.ts b/src/addon/mod/data/fields/number/providers/handler.ts
index 654681d72..40663e8f0 100644
--- a/src/addon/mod/data/fields/number/providers/handler.ts
+++ b/src/addon/mod/data/fields/number/providers/handler.ts
@@ -40,6 +40,24 @@ export class AddonModDataFieldNumberHandler extends AddonModDataFieldTextHandler
return AddonModDataFieldNumberComponent;
}
+ /**
+ * Get field data in changed.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @param {any} originalFieldData Original field entered data.
+ * @return {Promise | boolean} If the field has changes.
+ */
+ hasFieldDataChanged(field: any, inputData: any, originalFieldData: any): Promise | boolean {
+ const fieldName = 'f_' + field.id,
+ input = typeof inputData[fieldName] != 'undefined' ? parseFloat(inputData[fieldName]) : '';
+
+ originalFieldData = (originalFieldData && typeof originalFieldData.content != 'undefined') ?
+ parseFloat(originalFieldData.content) : '';
+
+ return input != originalFieldData;
+ }
+
/**
* Check and get field requeriments.
*
diff --git a/src/addon/mod/data/fields/picture/component/picture.html b/src/addon/mod/data/fields/picture/component/picture.html
index 7b24e5a3f..ee6cdcad0 100644
--- a/src/addon/mod/data/fields/picture/component/picture.html
+++ b/src/addon/mod/data/fields/picture/component/picture.html
@@ -1,15 +1,10 @@
-
+
+
+
-
-
-
-
-
- {{ 'addon.mod_data.alttext' | translate }}
-
- °N
-
+ {{ 'addon.mod_data.alttext' | translate }}
+
@@ -18,4 +13,4 @@
-
\ No newline at end of file
+
diff --git a/src/addon/mod/data/fields/picture/component/picture.ts b/src/addon/mod/data/fields/picture/component/picture.ts
index 810b63cc7..5c6796d90 100644
--- a/src/addon/mod/data/fields/picture/component/picture.ts
+++ b/src/addon/mod/data/fields/picture/component/picture.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
import { CoreFileSessionProvider } from '@providers/file-session';
@@ -24,7 +24,7 @@ import { AddonModDataProvider } from '../../../providers/data';
selector: 'addon-mod-data-field-picture',
templateUrl: 'picture.html'
})
-export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginComponent implements OnInit {
+export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginComponent {
files = [];
component: string;
@@ -35,7 +35,6 @@ export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginCo
entryId: number;
imageUrl: string;
title: string;
- alttext: string;
width: string;
height: string;
@@ -43,13 +42,6 @@ export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginCo
super(fb);
}
- /**
- * Component being initialized.
- */
- ngOnInit(): void {
- this.render();
- }
-
/**
* Get the files from the input value.
*
@@ -78,49 +70,67 @@ export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginCo
return files.find((file) => file.filename == filenameSeek) || false;
}
- protected render(): void {
+ /**
+ * Initialize field.
+ */
+ protected init(): void {
if (this.mode != 'search') {
this.component = AddonModDataProvider.COMPONENT;
this.componentId = this.database.coursemodule;
- // Edit mode, the list shouldn't change so there is no need to watch it.
- const files = this.value && this.value.files || [];
-
- // Get image or thumb.
- if (files.length > 0) {
- const filenameSeek = this.mode == 'list' ? 'thumb_' + this.value.content : this.value.content;
- this.image = this.findFile(files, filenameSeek);
-
- if (!this.image && this.mode == 'list') {
- this.image = this.findFile(files, this.value.content);
- }
-
- this.files = [this.image];
- } else {
- this.image = false;
- this.files = [];
- }
+ this.updateValue(this.value);
if (this.mode == 'edit') {
this.maxSizeBytes = parseInt(this.field.param3, 10);
this.fileSessionprovider.setFiles(this.component, this.database.id + '_' + this.field.id, this.files);
- this.alttext = (this.value && this.value.content1) || '';
- } else {
- this.entryId = (this.value && this.value.recordid) || null;
- this.title = (this.value && this.value.content1) || '';
- this.imageUrl = null;
- if (this.image) {
- if (this.image.offline) {
- this.imageUrl = (this.image && this.image.toURL()) || null;
- } else {
- this.imageUrl = (this.image && this.image.fileurl) || null;
- }
- }
- this.width = this.field.param1 || '';
- this.height = this.field.param2 || '';
+
+ const alttext = (this.value && this.value.content1) || '';
+ this.addControl('f_' + this.field.id + '_alttext', alttext);
}
+ } else {
+ this.addControl('f_' + this.field.id);
+ }
+ }
+
+ /**
+ * Update value being shown.
+ *
+ * @param {any} value New value to be set.
+ */
+ protected updateValue(value: any): void {
+ this.value = value;
+
+ // Edit mode, the list shouldn't change so there is no need to watch it.
+ const files = value && value.files || [];
+
+ // Get image or thumb.
+ if (files.length > 0) {
+ const filenameSeek = this.mode == 'list' ? 'thumb_' + value.content : value.content;
+ this.image = this.findFile(files, filenameSeek);
+
+ if (!this.image && this.mode == 'list') {
+ this.image = this.findFile(files, value.content);
+ }
+
+ this.files = [this.image];
+ } else {
+ this.image = false;
+ this.files = [];
}
- this.addControl('f_' + this.field.id);
+ if (this.mode != 'edit') {
+ this.entryId = (value && value.recordid) || null;
+ this.title = (value && value.content1) || '';
+ this.imageUrl = null;
+ if (this.image) {
+ if (this.image.offline) {
+ this.imageUrl = (this.image && this.image.toURL()) || null;
+ } else {
+ this.imageUrl = (this.image && this.image.fileurl) || null;
+ }
+ }
+ this.width = this.field.param1 || '';
+ this.height = this.field.param2 || '';
+ }
}
}
diff --git a/src/addon/mod/data/fields/radiobutton/component/radiobutton.html b/src/addon/mod/data/fields/radiobutton/component/radiobutton.html
index c7e9e03c8..9a9357500 100644
--- a/src/addon/mod/data/fields/radiobutton/component/radiobutton.html
+++ b/src/addon/mod/data/fields/radiobutton/component/radiobutton.html
@@ -1,11 +1,10 @@
-
-
-
-
-
+
+
+
{{ 'addon.mod_data.menuchoose' | translate }}
{{option}}
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/radiobutton/component/radiobutton.ts b/src/addon/mod/data/fields/radiobutton/component/radiobutton.ts
index 400d3aa78..e2b64425b 100644
--- a/src/addon/mod/data/fields/radiobutton/component/radiobutton.ts
+++ b/src/addon/mod/data/fields/radiobutton/component/radiobutton.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
@@ -22,7 +22,7 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-radiobutton',
templateUrl: 'radiobutton.html'
})
-export class AddonModDataFieldRadiobuttonComponent extends AddonModDataFieldPluginComponent implements OnInit {
+export class AddonModDataFieldRadiobuttonComponent extends AddonModDataFieldPluginComponent {
options = [];
@@ -31,15 +31,10 @@ export class AddonModDataFieldRadiobuttonComponent extends AddonModDataFieldPlug
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
- if (this.mode == 'show') {
+ protected init(): void {
+ if (this.isShowOrListMode()) {
return;
}
diff --git a/src/addon/mod/data/fields/text/component/text.html b/src/addon/mod/data/fields/text/component/text.html
index ad562369f..fa8846daf 100644
--- a/src/addon/mod/data/fields/text/component/text.html
+++ b/src/addon/mod/data/fields/text/component/text.html
@@ -1,9 +1,7 @@
-
-
-
-
-
-
+
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/text/component/text.ts b/src/addon/mod/data/fields/text/component/text.ts
index ce5f91649..1d9523d51 100644
--- a/src/addon/mod/data/fields/text/component/text.ts
+++ b/src/addon/mod/data/fields/text/component/text.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
@@ -22,31 +22,25 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-text',
templateUrl: 'text.html'
})
-export class AddonModDataFieldTextComponent extends AddonModDataFieldPluginComponent implements OnInit {
-
- val: number;
+export class AddonModDataFieldTextComponent extends AddonModDataFieldPluginComponent {
constructor(protected fb: FormBuilder) {
super(fb);
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
- if (this.mode == 'show') {
+ protected init(): void {
+ if (this.isShowOrListMode()) {
return;
}
+ let value;
if (this.mode == 'edit' && this.value) {
- this.val = this.value.content;
+ value = this.value.content;
}
- this.addControl('f_' + this.field.id, this.val);
+ this.addControl('f_' + this.field.id, value);
}
}
diff --git a/src/addon/mod/data/fields/textarea/component/textarea.html b/src/addon/mod/data/fields/textarea/component/textarea.html
index d7948298b..d07c54193 100644
--- a/src/addon/mod/data/fields/textarea/component/textarea.html
+++ b/src/addon/mod/data/fields/textarea/component/textarea.html
@@ -1,13 +1,10 @@
-
-
-
-
-
-
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/textarea/component/textarea.ts b/src/addon/mod/data/fields/textarea/component/textarea.ts
index 24bf5ecf9..532d762fa 100644
--- a/src/addon/mod/data/fields/textarea/component/textarea.ts
+++ b/src/addon/mod/data/fields/textarea/component/textarea.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { CoreTextUtilsProvider } from '@providers/utils/text';
import { AddonModDataProvider } from '../../../providers/data';
@@ -24,7 +24,7 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-textarea',
templateUrl: 'textarea.html'
})
-export class AddonModDataFieldTextareaComponent extends AddonModDataFieldPluginComponent implements OnInit {
+export class AddonModDataFieldTextareaComponent extends AddonModDataFieldPluginComponent {
component: string;
componentId: number;
@@ -33,6 +33,12 @@ export class AddonModDataFieldTextareaComponent extends AddonModDataFieldPluginC
super(fb);
}
+ /**
+ * Format value to be shown. Replacing plugin file Urls.
+ *
+ * @param {any} value Value to replace.
+ * @return {string} Replaced string to be rendered.
+ */
format(value: any): string {
const files = (value && value.files) || [];
@@ -40,27 +46,23 @@ export class AddonModDataFieldTextareaComponent extends AddonModDataFieldPluginC
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
- if (this.mode == 'show') {
+ protected init(): void {
+ if (this.isShowOrListMode()) {
this.component = AddonModDataProvider.COMPONENT;
this.componentId = this.database.coursemodule;
return;
}
+ let text;
// Check if rich text editor is enabled.
if (this.mode == 'edit') {
- const files = (this.value && this.value.files) || [],
- text = this.value ? this.textUtils.replacePluginfileUrls(this.value.content, files) : '';
+ const files = (this.value && this.value.files) || [];
+ text = this.value ? this.textUtils.replacePluginfileUrls(this.value.content, files) : '';
}
- this.addControl('f_' + this.field.id, '');
+ this.addControl('f_' + this.field.id, text);
}
}
diff --git a/src/addon/mod/data/fields/url/component/url.html b/src/addon/mod/data/fields/url/component/url.html
index e7ff179db..f1c018713 100644
--- a/src/addon/mod/data/fields/url/component/url.html
+++ b/src/addon/mod/data/fields/url/component/url.html
@@ -1,9 +1,7 @@
-
-
-
-
-
-
+
+
+
+
-{{field.name}}
\ No newline at end of file
+{{field.name}}
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/url/component/url.ts b/src/addon/mod/data/fields/url/component/url.ts
index e4395fb75..f6d2a8450 100644
--- a/src/addon/mod/data/fields/url/component/url.ts
+++ b/src/addon/mod/data/fields/url/component/url.ts
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
@@ -22,31 +22,25 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-
selector: 'addon-mod-data-field-url',
templateUrl: 'url.html'
})
-export class AddonModDataFieldUrlComponent extends AddonModDataFieldPluginComponent implements OnInit {
-
- val: number;
+export class AddonModDataFieldUrlComponent extends AddonModDataFieldPluginComponent {
constructor(protected fb: FormBuilder) {
super(fb);
}
/**
- * Component being initialized.
+ * Initialize field.
*/
- ngOnInit(): void {
- this.mode = this.mode == 'list' ? 'show' : this.mode;
- this.render();
- }
-
- protected render(): void {
- if (this.mode == 'show') {
+ protected init(): void {
+ if (this.isShowOrListMode()) {
return;
}
+ let value;
if (this.mode == 'edit' && this.value) {
- this.val = this.value.content;
+ value = this.value.content;
}
- this.addControl('f_' + this.field.id, this.val);
+ this.addControl('f_' + this.field.id, value);
}
}
diff --git a/src/addon/mod/data/pages/edit/edit.html b/src/addon/mod/data/pages/edit/edit.html
new file mode 100644
index 000000000..85b2fbcba
--- /dev/null
+++ b/src/addon/mod/data/pages/edit/edit.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ 'core.groupsseparate' | translate }}
+ {{ 'core.groupsvisible' | translate }}
+
+ {{groupOpt.name}}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/addon/mod/data/pages/edit/edit.module.ts b/src/addon/mod/data/pages/edit/edit.module.ts
new file mode 100644
index 000000000..fac3251a6
--- /dev/null
+++ b/src/addon/mod/data/pages/edit/edit.module.ts
@@ -0,0 +1,39 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { NgModule } from '@angular/core';
+import { IonicPageModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { CoreDirectivesModule } from '@directives/directives.module';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreCommentsComponentsModule } from '@core/comments/components/components.module';
+import { CoreCompileHtmlComponentModule } from '@core/compile/components/compile-html/compile-html.module';
+import { AddonModDataComponentsModule } from '../../components/components.module';
+import { AddonModDataEditPage } from './edit';
+
+@NgModule({
+ declarations: [
+ AddonModDataEditPage,
+ ],
+ imports: [
+ CoreDirectivesModule,
+ CoreComponentsModule,
+ AddonModDataComponentsModule,
+ CoreCompileHtmlComponentModule,
+ CoreCommentsComponentsModule,
+ IonicPageModule.forChild(AddonModDataEditPage),
+ TranslateModule.forChild()
+ ],
+})
+export class AddonModDataEditPageModule {}
diff --git a/src/addon/mod/data/pages/edit/edit.ts b/src/addon/mod/data/pages/edit/edit.ts
new file mode 100644
index 000000000..2f6e44566
--- /dev/null
+++ b/src/addon/mod/data/pages/edit/edit.ts
@@ -0,0 +1,373 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Component, ViewChild } from '@angular/core';
+import { Content, IonicPage, NavParams, NavController } from 'ionic-angular';
+import { TranslateService } from '@ngx-translate/core';
+import { FormGroup } from '@angular/forms';
+import { CoreUtilsProvider } from '@providers/utils/utils';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreSitesProvider } from '@providers/sites';
+import { CoreGroupsProvider } from '@providers/groups';
+import { CoreEventsProvider } from '@providers/events';
+import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
+import { CoreCourseProvider } from '@core/course/providers/course';
+import { AddonModDataProvider } from '../../providers/data';
+import { AddonModDataHelperProvider } from '../../providers/helper';
+import { AddonModDataOfflineProvider } from '../../providers/offline';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataComponentsModule } from '../../components/components.module';
+
+/**
+ * Page that displays the view edit page.
+ */
+@IonicPage({ segment: 'addon-mod-data-edit' })
+@Component({
+ selector: 'page-addon-mod-data-edit',
+ templateUrl: 'edit.html',
+})
+export class AddonModDataEditPage {
+ @ViewChild(Content) content: Content;
+
+ protected module: any;
+ protected courseId: number;
+ protected data: any;
+ protected entryId: number;
+ protected entry: any;
+ protected offlineActions = [];
+ protected fields = {};
+ protected fieldsArray = [];
+ protected siteId: string;
+ protected offline: boolean;
+ protected forceLeave = false; // To allow leaving the page without checking for changes.
+
+ title = '';
+ component = AddonModDataProvider.COMPONENT;
+ loaded = false;
+ selectedGroup = 0;
+ cssClass = '';
+ cssTemplate = '';
+ groupInfo: any;
+ editFormRender = '';
+ editForm: FormGroup;
+ extraImports = [AddonModDataComponentsModule];
+ jsData: any;
+ errors = {};
+
+ 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,
+ sitesProvider: CoreSitesProvider, protected navCtrl: NavController, protected translate: TranslateService,
+ protected eventsProvider: CoreEventsProvider, protected fileUploaderProvider: CoreFileUploaderProvider) {
+ this.module = params.get('module') || {};
+ this.entryId = params.get('entryId') || null;
+ this.courseId = params.get('courseId');
+ this.selectedGroup = params.get('group') || 0;
+
+ this.siteId = sitesProvider.getCurrentSiteId();
+
+ this.title = this.module.name;
+
+ this.editForm = new FormGroup({});
+ }
+
+ /**
+ * View loaded.
+ */
+ ionViewDidLoad(): void {
+ this.fetchEntryData();
+ }
+
+ /**
+ * Check if we can leave the page or not and ask to confirm the lost of data.
+ *
+ * @return {boolean | Promise} Resolved if we can leave it, rejected if not.
+ */
+ ionViewCanLeave(): boolean | Promise {
+ if (this.forceLeave) {
+ return true;
+ }
+
+ const inputData = this.editForm.value;
+
+ return this.dataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.data.id,
+ this.entry.contents).then((changed) => {
+ if (!changed) {
+ return Promise.resolve();
+ }
+
+ // Show confirmation if some data has been modified.
+ return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit'));
+ }).then(() => {
+ // Delete the local files from the tmp folder.
+ return this.dataHelper.getEditTmpFiles(inputData, this.fieldsArray, this.data.id,
+ this.entry.contents).then((files) => {
+ this.fileUploaderProvider.clearTmpFiles(files);
+ });
+ });
+ }
+
+ /**
+ * Fetch the entry data.
+ *
+ * @return {Promise} Resolved when done.
+ */
+ protected fetchEntryData(): Promise {
+ return this.dataProvider.getDatabase(this.courseId, this.module.id).then((data) => {
+ this.title = data.name || this.title;
+ this.data = data;
+ this.cssClass = 'addon-data-entries-' + data.id;
+
+ return this.dataProvider.getDatabaseAccessInformation(data.id);
+ }).then((accessData) => {
+ this.cssTemplate = this.dataHelper.prefixCSS(this.data.csstemplate, '.' + this.cssClass);
+
+ if (this.entryId) {
+ return this.groupsProvider.getActivityGroupInfo(this.data.coursemodule, accessData.canmanageentries)
+ .then((groupInfo) => {
+ this.groupInfo = groupInfo;
+
+ // Check selected group is accessible.
+ if (groupInfo && groupInfo.groups && groupInfo.groups.length > 0) {
+ if (!groupInfo.groups.some((group) => this.selectedGroup == group.id)) {
+ this.selectedGroup = groupInfo.groups[0].id;
+ }
+ }
+ });
+ }
+ }).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.fields = {};
+ fieldsData.forEach((field) => {
+ this.fields[field.id] = field;
+ });
+
+ this.fieldsArray = fieldsData;
+
+ return this.dataHelper.getEntry(this.data, this.entryId, this.offlineActions);
+ }).then((entry) => {
+ if (entry) {
+ entry = entry.entry;
+
+ // Index contents by fieldid.
+ const contents = {};
+ entry.contents.forEach((field) => {
+ contents[field.fieldid] = field;
+ });
+ entry.contents = contents;
+ } else {
+ entry = {
+ contents: {}
+ };
+ }
+
+ return this.dataHelper.applyOfflineActions(entry, this.offlineActions, this.fieldsArray);
+ }).then((entryData) => {
+ this.entry = entryData;
+
+ this.editFormRender = this.displayEditFields();
+ }).catch((message) => {
+ this.domUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true);
+
+ return Promise.reject(null);
+ }).finally(() => {
+ this.loaded = true;
+ });
+ }
+
+ /**
+ * Saves data.
+ *
+ * @return {Promise} Resolved when done.
+ */
+ save(): Promise {
+ const inputData = this.editForm.value;
+
+ return this.dataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.data.id,
+ this.entry.contents).then((changed) => {
+
+ if (!changed) {
+ if (this.entryId) {
+ return this.returnToEntryList();
+ }
+
+ // New entry, no changes means no field filled, warn the user.
+ return Promise.reject('addon.mod_data.emptyaddform');
+ }
+
+ const modal = this.domUtils.showModalLoading('core.sending', true);
+
+ // Create an ID to assign files.
+ const entryTemp = this.entryId ? this.entryId : - (new Date().getTime());
+
+ return this.dataHelper.getEditDataFromForm(inputData, this.fieldsArray, this.data.id, entryTemp, this.entry.contents,
+ this.offline).catch((e) => {
+ if (!this.offline) {
+ // Cannot submit in online, prepare for offline usage.
+ this.offline = true;
+
+ return this.dataHelper.getEditDataFromForm(inputData, this.fieldsArray, this.data.id, entryTemp,
+ this.entry.contents, this.offline);
+ }
+
+ return Promise.reject(e);
+ }).then((editData) => {
+ if (editData.length > 0) {
+ if (this.entryId) {
+ return this.dataProvider.editEntry(this.data.id, this.entryId, this.courseId, editData, this.fields,
+ undefined, this.offline);
+ }
+
+ return this.dataProvider.addEntry(this.data.id, entryTemp, this.courseId, editData, this.selectedGroup,
+ this.fields, undefined, this.offline);
+ }
+
+ return false;
+ }).then((result: any) => {
+ if (!result) {
+ // No field filled, warn the user.
+ return Promise.reject('addon.mod_data.emptyaddform');
+ }
+
+ // This is done if entry is updated when editing or creating if not.
+ if ((this.entryId && result.updated) || (!this.entryId && result.newentryid)) {
+ const promises = [];
+
+ this.entryId = this.entryId || result.newentryid;
+
+ promises.push(this.dataProvider.invalidateEntryData(this.data.id, this.entryId, this.siteId));
+ promises.push(this.dataProvider.invalidateEntriesData(this.data.id, this.siteId));
+
+ return Promise.all(promises).then(() => {
+ this.eventsProvider.trigger(AddonModDataProvider.ENTRY_CHANGED,
+ { dataId: this.data.id, entryId: this.entryId } , this.siteId);
+ }).finally(() => {
+ return this.returnToEntryList();
+ });
+ } else {
+ this.errors = {};
+ result.fieldnotifications.forEach((fieldNotif) => {
+ const field = this.fieldsArray.find((field) => field.name == fieldNotif.fieldname);
+ if (field) {
+ this.errors[field.id] = fieldNotif.notification;
+ }
+ });
+ this.jsData['errors'] = this.errors;
+
+ setTimeout(() => {
+ this.scrollToFirstError();
+ });
+ }
+ }).finally(() => {
+ modal.dismiss();
+ });
+ }).catch((error) => {
+ this.domUtils.showErrorModalDefault(error, 'Cannot edit entry', true);
+
+ return Promise.reject(null);
+ });
+
+ }
+
+ /**
+ * Set group to see the database.
+ *
+ * @param {number} groupId Group identifier to set.
+ * @return {Promise} Resolved when done.
+ */
+ setGroup(groupId: number): Promise {
+ this.selectedGroup = groupId;
+ this.loaded = false;
+
+ return this.fetchEntryData();
+ }
+
+ /**
+ * Displays Edit Search Fields.
+ *
+ * @return {string} Generated HTML.
+ */
+ protected displayEditFields(): string {
+ if (!this.data.addtemplate) {
+ return '';
+ }
+
+ this.jsData = {
+ fields: this.fields,
+ contents: this.entry.contents,
+ form: this.editForm,
+ data: this.data,
+ errors: this.errors
+ };
+
+ let replace,
+ render,
+ template = this.data.addtemplate;
+
+ // Replace the fields found on template.
+ this.fieldsArray.forEach((field) => {
+ replace = '[[' + field.name + ']]';
+ replace = replace.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
+ replace = new RegExp(replace, 'gi');
+
+ // Replace field by a generic directive.
+ render = '\
+ ';
+ template = template.replace(replace, render);
+
+ // Replace the field id tag.
+ replace = '[[' + field.name + '#id]]';
+ replace = replace.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
+ replace = new RegExp(replace, 'gi');
+
+ template = template.replace(replace, 'field_' + field.id);
+ });
+
+ return template;
+ }
+
+ /**
+ * Return to the entry list (previous page) discarding temp data.
+ *
+ * @return {Promise} Resolved when done.
+ */
+ protected returnToEntryList(): Promise {
+ const inputData = this.editForm.value;
+
+ return this.dataHelper.getEditTmpFiles(inputData, this.fieldsArray, this.data.id,
+ this.entry.contents).then((files) => {
+ this.fileUploaderProvider.clearTmpFiles(files);
+ }).finally(() => {
+ // Go back to entry list.
+ this.forceLeave = true;
+ this.navCtrl.pop();
+ });
+ }
+
+ /**
+ * Scroll to first error or to the top if not found.
+ */
+ protected scrollToFirstError(): void {
+ if (!this.domUtils.scrollToElementBySelector(this.content, '.addon-data-error')) {
+ this.content.scrollToTop();
+ }
+ }
+}
diff --git a/src/addon/mod/data/pages/entry/entry.ts b/src/addon/mod/data/pages/entry/entry.ts
index 2dce9294e..c6e4c8cb5 100644
--- a/src/addon/mod/data/pages/entry/entry.ts
+++ b/src/addon/mod/data/pages/entry/entry.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, ViewChild } from '@angular/core';
+import { Component, ViewChild, OnDestroy } from '@angular/core';
import { Content, IonicPage, NavParams, NavController } from 'ionic-angular';
import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
@@ -35,7 +35,7 @@ import { AddonModDataComponentsModule } from '../../components/components.module
selector: 'page-addon-mod-data-entry',
templateUrl: 'entry.html',
})
-export class AddonModDataEntryPage {
+export class AddonModDataEntryPage implements OnDestroy {
@ViewChild(Content) content: Content;
protected module: any;
@@ -107,7 +107,7 @@ export class AddonModDataEntryPage {
// Refresh entry on change.
this.entryChangedObserver = this.eventsProvider.on(AddonModDataProvider.ENTRY_CHANGED, (data) => {
- if (data.entryId == this.entryId && data.id == data.dataId) {
+ if (data.entryId == this.entryId && this.data.id == data.dataId) {
if (data.deleted) {
// If deleted, go back.
this.navCtrl.pop();
diff --git a/src/addon/mod/data/pages/search/search.html b/src/addon/mod/data/pages/search/search.html
index ad1be4d75..687e42605 100644
--- a/src/addon/mod/data/pages/search/search.html
+++ b/src/addon/mod/data/pages/search/search.html
@@ -19,7 +19,7 @@
- {{ 'core.sortby' | translate }}
+ {{ 'core.sortby' | translate }}