diff --git a/config.xml b/config.xml
index 5b9064b2c..8d93693b2 100644
--- a/config.xml
+++ b/config.xml
@@ -13,6 +13,10 @@
+
+
+
+
diff --git a/src/addon/mod/data/components/field-plugin/field-plugin.ts b/src/addon/mod/data/components/field-plugin/field-plugin.ts
index 819d43e2d..cbac94fa2 100644
--- a/src/addon/mod/data/components/field-plugin/field-plugin.ts
+++ b/src/addon/mod/data/components/field-plugin/field-plugin.ts
@@ -38,13 +38,13 @@ export class AddonModDataFieldPluginComponent implements OnInit {
fieldLoaded: boolean;
constructor(protected injector: Injector, protected dataDelegate: AddonModDataFieldsDelegate,
- protected dataProvider: AddonModDataProvider) { }
+ protected dataProvider: AddonModDataProvider) {
+ }
/**
* Component being initialized.
*/
ngOnInit(): void {
- console.error('HERE');
if (!this.field) {
this.fieldLoaded = true;
@@ -65,6 +65,7 @@ export class AddonModDataFieldPluginComponent implements OnInit {
error: this.error,
viewAction: this.viewAction
};
+
} else {
this.fieldLoaded = true;
}
diff --git a/src/addon/mod/data/components/index/index.html b/src/addon/mod/data/components/index/index.html
index e53c61d7a..2fe8fe250 100644
--- a/src/addon/mod/data/components/index/index.html
+++ b/src/addon/mod/data/components/index/index.html
@@ -63,7 +63,7 @@
{{ cssTemplate }}
-
+ 0 || hasNextPage">
diff --git a/src/addon/mod/data/components/index/index.scss b/src/addon/mod/data/components/index/index.scss
index 1a748d124..2c2a8e5a3 100644
--- a/src/addon/mod/data/components/index/index.scss
+++ b/src/addon/mod/data/components/index/index.scss
@@ -1,3 +1,28 @@
addon-mod-data-index {
+ .core-data-contents {
+ overflow: visible;
+ white-space: normal;
+ word-break: break-word;
+ padding: $content-padding;
+ background-color: white;
+ border-top-width: 1px;
+ border-bottom-width: 1px;
+ border-right-width: 0;
+ border-left-width: 0;
+ border-style: solid;
+ border-color: $list-border-color;
+ table, tbody {
+ display: block;
+ }
+
+ tr {
+ @extend .row;
+ padding: 0;
+ }
+
+ td, th {
+ @extend .col;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/addon/mod/data/components/index/index.ts b/src/addon/mod/data/components/index/index.ts
index 713731112..e2517fc62 100644
--- a/src/addon/mod/data/components/index/index.ts
+++ b/src/addon/mod/data/components/index/index.ts
@@ -23,6 +23,7 @@ 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 * as moment from 'moment';
/**
@@ -33,6 +34,7 @@ import * as moment from 'moment';
templateUrl: 'index.html',
})
export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComponent {
+
component = AddonModDataProvider.COMPONENT;
moduleName = 'data';
@@ -65,13 +67,16 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
offlineEntries: any;
entriesRendered = '';
cssTemplate = '';
+ extraImports = [AddonModDataComponentsModule];
+ jsData;
protected syncEventName = AddonModDataSyncProvider.AUTO_SYNCED;
protected entryChangedObserver: any;
protected hasComments = false;
+ protected fieldsArray: any;
constructor(injector: Injector, private dataProvider: AddonModDataProvider, private dataHelper: AddonModDataHelperProvider,
- private dataOffline: AddonModDataOfflineProvider, @Optional() private content: Content,
+ private dataOffline: AddonModDataOfflineProvider, @Optional() @Optional() content: Content,
private dataSync: AddonModDataSyncProvider, private timeUtils: CoreTimeUtilsProvider,
private groupsProvider: CoreGroupsProvider, private commentsProvider: CoreCommentsProvider,
private modalCtrl: ModalController, private utils: CoreUtilsProvider) {
@@ -216,8 +221,8 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
fields.forEach((field) => {
this.fields[field.id] = field;
});
- this.fields = this.utils.objectToArray(this.fields);
- this.advancedSearch = this.dataHelper.displayAdvancedSearchFields(this.data.asearchtemplate, this.fields);
+ this.fieldsArray = this.utils.objectToArray(this.fields);
+ this.advancedSearch = this.dataHelper.displayAdvancedSearchFields(this.data.asearchtemplate, this.fieldsArray);
return this.fetchEntriesData();
});
@@ -283,7 +288,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
};
if (offlineActions.length > 0) {
- promises.push(this.dataHelper.applyOfflineActions(entry, offlineActions, this.fields));
+ promises.push(this.dataHelper.applyOfflineActions(entry, offlineActions, this.fieldsArray));
} else {
promises.push(Promise.resolve(entry));
}
@@ -299,7 +304,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
entry.contents = contents;
if (typeof this.offlineActions[entry.id] != 'undefined') {
- promises.push(this.dataHelper.applyOfflineActions(entry, this.offlineActions[entry.id], this.fields));
+ promises.push(this.dataHelper.applyOfflineActions(entry, this.offlineActions[entry.id], this.fieldsArray));
} else {
promises.push(Promise.resolve(entry));
}
@@ -318,12 +323,19 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
const actions = this.dataHelper.getActions(this.data, this.access, entry);
- entriesHTML += this.dataHelper.displayShowFields(this.data.listtemplate, this.fields, entry, 'list',
+ entriesHTML += this.dataHelper.displayShowFields(this.data.listtemplate, this.fieldsArray, entry, 'list',
actions);
});
entriesHTML += this.data.listtemplatefooter || '';
this.entriesRendered = entriesHTML;
+
+ // Pass the input data to the component.
+ this.jsData = {
+ fields: this.fields,
+ entries: this.entries,
+ data: this.data
+ };
});
} else if (!this.search.searching) {
// Empty and no searching.
@@ -356,7 +368,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
if (this.search.searchingAdvanced) {
this.search.advanced = this.dataHelper.getSearchDataFromForm(document.forms['addon-mod_data-advanced-search-form'],
- this.fields);
+ this.fieldsArray);
this.search.searching = this.search.advanced.length > 0;
} else {
this.search.searching = this.search.text.length > 0;
diff --git a/src/addon/mod/data/fields/checkbox/component/checkbox.ts b/src/addon/mod/data/fields/checkbox/component/checkbox.ts
index 64f4db6e2..48404b1a8 100644
--- a/src/addon/mod/data/fields/checkbox/component/checkbox.ts
+++ b/src/addon/mod/data/fields/checkbox/component/checkbox.ts
@@ -32,7 +32,6 @@ export class AddonModDataFieldCheckboxComponent extends AddonModDataFieldPluginC
constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
element: ElementRef) {
-
super();
}
@@ -46,7 +45,7 @@ export class AddonModDataFieldCheckboxComponent extends AddonModDataFieldPluginC
protected render(): void {
if (this.mode == 'show') {
- this.value.content.split('##').join(' ');
+ this.value.content = this.value.content.split('##').join(' ');
return;
}
diff --git a/src/addon/mod/data/fields/checkbox/providers/handler.ts b/src/addon/mod/data/fields/checkbox/providers/handler.ts
index d49a0a3c0..14632ab59 100644
--- a/src/addon/mod/data/fields/checkbox/providers/handler.ts
+++ b/src/addon/mod/data/fields/checkbox/providers/handler.ts
@@ -35,7 +35,6 @@ export class AddonModDataFieldCheckboxHandler implements AddonModDataFieldHandle
* @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any): any | Promise {
- console.error(AddonModDataFieldCheckboxComponent);
return AddonModDataFieldCheckboxComponent;
}
diff --git a/src/addon/mod/data/fields/date/component/date.html b/src/addon/mod/data/fields/date/component/date.html
new file mode 100644
index 000000000..66a9c8de0
--- /dev/null
+++ b/src/addon/mod/data/fields/date/component/date.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ {{ 'addon.mod_data.usedate' | translate }}
+
+
+
+
+
+
diff --git a/src/addon/mod/data/fields/date/component/date.ts b/src/addon/mod/data/fields/date/component/date.ts
new file mode 100644
index 000000000..034669864
--- /dev/null
+++ b/src/addon/mod/data/fields/date/component/date.ts
@@ -0,0 +1,63 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data date field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-date',
+ templateUrl: 'date.html'
+})
+export class AddonModDataFieldDateComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ values = {};
+ enable: boolean;
+ val: any;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ return;
+ }
+
+ if (this.mode == 'edit' && this.value) {
+ this.enable = true;
+ } else {
+ this.value = {
+ content: Math.floor(Date.now() / 1000)
+ };
+ this.enable = false;
+ }
+
+ this.val = new Date(this.value.content * 1000);
+ }
+}
diff --git a/src/addon/mod/data/fields/date/date.module.ts b/src/addon/mod/data/fields/date/date.module.ts
new file mode 100644
index 000000000..faf696cf5
--- /dev/null
+++ b/src/addon/mod/data/fields/date/date.module.ts
@@ -0,0 +1,51 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldDateHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldDateComponent } from './component/date';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+import { CorePipesModule } from '@pipes/pipes.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldDateComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule,
+ CorePipesModule
+ ],
+ providers: [
+ AddonModDataFieldDateHandler
+ ],
+ exports: [
+ AddonModDataFieldDateComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldDateComponent
+ ]
+})
+export class AddonModDataFieldDateModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldDateHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/date/providers/handler.ts b/src/addon/mod/data/fields/date/providers/handler.ts
new file mode 100644
index 000000000..9bb37150b
--- /dev/null
+++ b/src/addon/mod/data/fields/date/providers/handler.ts
@@ -0,0 +1,180 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataFieldDateComponent } from '../component/date';
+
+/**
+ * Handler for date data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldDateHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldDateHandler';
+ type = 'date';
+
+ constructor(private translate: TranslateService) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldDateComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id,
+ enabledName = 'f_' + field.id + '_z';
+
+ if (inputData[enabledName]['1']) {
+ const values = [],
+ date = inputData[fieldName].split('-'),
+ year = date[0],
+ month = date[1],
+ day = date[2];
+ values.push({
+ name: fieldName + '_y',
+ value: year
+ });
+ values.push({
+ name: fieldName + '_m',
+ value: month
+ });
+ values.push({
+ name: fieldName + '_d',
+ value: day
+ });
+ values.push({
+ name: enabledName,
+ value: 1
+ });
+
+ return values;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ const values = [],
+ date = inputData[fieldName].split('-'),
+ year = date[0],
+ month = date[1],
+ day = date[2];
+ values.push({
+ fieldid: field.id,
+ subfield: 'year',
+ value: year
+ });
+ values.push({
+ fieldid: field.id,
+ subfield: 'month',
+ value: month
+ });
+ values.push({
+ fieldid: field.id,
+ subfield: 'day',
+ value: day
+ });
+
+ return values;
+ }
+
+ return false;
+ }
+
+ /**
+ * 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 = inputData[fieldName] || '';
+
+ originalFieldData = (originalFieldData && originalFieldData.content &&
+ new Date(originalFieldData.content * 1000).toISOString().substr(0, 10)) || '';
+
+ return input != originalFieldData;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required &&
+ (!inputData || inputData.length < 2 || !inputData[0].value || !inputData[1].value || !inputData[2].value)) {
+
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ let date = Date.UTC(offlineContent['year'] || '', offlineContent['month'] ? offlineContent['month'] - 1 : null,
+ offlineContent['day'] || null);
+ date = Math.floor(date / 1000);
+
+ originalContent.content = date || '';
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/field.module.ts b/src/addon/mod/data/fields/field.module.ts
index c38ed2f56..3bd3d9e3d 100644
--- a/src/addon/mod/data/fields/field.module.ts
+++ b/src/addon/mod/data/fields/field.module.ts
@@ -14,11 +14,33 @@
import { NgModule } from '@angular/core';
import { AddonModDataFieldCheckboxModule } from './checkbox/checkbox.module';
+import { AddonModDataFieldDateModule } from './date/date.module';
+import { AddonModDataFieldFileModule } from './file/file.module';
+import { AddonModDataFieldLatlongModule } from './latlong/latlong.module';
+import { AddonModDataFieldMenuModule } from './menu/menu.module';
+import { AddonModDataFieldMultimenuModule } from './multimenu/multimenu.module';
+import { AddonModDataFieldNumberModule } from './number/number.module';
+import { AddonModDataFieldPictureModule } from './picture/picture.module';
+import { AddonModDataFieldRadiobuttonModule } from './radiobutton/radiobutton.module';
+import { AddonModDataFieldTextModule } from './text/text.module';
+import { AddonModDataFieldTextareaModule } from './textarea/textarea.module';
+import { AddonModDataFieldUrlModule } from './url/url.module';
@NgModule({
declarations: [],
imports: [
- AddonModDataFieldCheckboxModule
+ AddonModDataFieldCheckboxModule,
+ AddonModDataFieldDateModule,
+ AddonModDataFieldFileModule,
+ AddonModDataFieldLatlongModule,
+ AddonModDataFieldMenuModule,
+ AddonModDataFieldMultimenuModule,
+ AddonModDataFieldNumberModule,
+ AddonModDataFieldPictureModule,
+ AddonModDataFieldRadiobuttonModule,
+ AddonModDataFieldTextModule,
+ AddonModDataFieldTextareaModule,
+ AddonModDataFieldUrlModule
],
providers: [
],
diff --git a/src/addon/mod/data/fields/file/component/file.html b/src/addon/mod/data/fields/file/component/file.html
new file mode 100644
index 000000000..1ed18a0f3
--- /dev/null
+++ b/src/addon/mod/data/fields/file/component/file.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/addon/mod/data/fields/file/component/file.ts b/src/addon/mod/data/fields/file/component/file.ts
new file mode 100644
index 000000000..773a3b7ed
--- /dev/null
+++ b/src/addon/mod/data/fields/file/component/file.ts
@@ -0,0 +1,81 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+import { CoreFileSessionProvider } from '@providers/file-session';
+import { AddonModDataProvider } from '../../../providers/data';
+
+/**
+ * Component to render data file field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-file',
+ templateUrl: 'file.html'
+})
+export class AddonModDataFieldFileComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ files = [];
+ component: string;
+ componentId: number;
+ maxSizeBytes: number;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef, private fileSessionprovider: CoreFileSessionProvider) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ /**
+ * Get the files from the input value.
+ *
+ * @param {any} value Input value.
+ * @return {any} List of files.
+ */
+ protected getFiles(value: any): any {
+ let files = (value && value.files) || [];
+
+ // Reduce to first element.
+ if (files.length > 0) {
+ files = [files[0]];
+ }
+
+ return files;
+ }
+
+ protected render(): void {
+ if (this.mode == 'show' || this.mode == 'edit') {
+ this.component = AddonModDataProvider.COMPONENT;
+ this.componentId = this.database.coursemodule;
+
+ this.files = this.getFiles(this.value);
+
+ if (this.mode != 'show') {
+ // Edit mode, the list shouldn't change so there is no need to watch it.
+ this.maxSizeBytes = parseInt(this.field.param3, 10);
+ this.fileSessionprovider.setFiles(this.component, this.database.id + '_' + this.field.id, this.files);
+ }
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/file/file.module.ts b/src/addon/mod/data/fields/file/file.module.ts
new file mode 100644
index 000000000..b2d240329
--- /dev/null
+++ b/src/addon/mod/data/fields/file/file.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldFileHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldFileComponent } from './component/file';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldFileComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule,
+ ],
+ providers: [
+ AddonModDataFieldFileHandler
+ ],
+ exports: [
+ AddonModDataFieldFileComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldFileComponent
+ ]
+})
+export class AddonModDataFieldFileModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldFileHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/file/providers/handler.ts b/src/addon/mod/data/fields/file/providers/handler.ts
new file mode 100644
index 000000000..38a58e7de
--- /dev/null
+++ b/src/addon/mod/data/fields/file/providers/handler.ts
@@ -0,0 +1,158 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { CoreFileSessionProvider } from '@providers/file-session';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataProvider } from '../../../providers/data';
+import { AddonModDataFieldFileComponent } from '../component/file';
+import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
+
+/**
+ * Handler for file data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldFileHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldFileHandler';
+ type = 'file';
+
+ constructor(private translate: TranslateService, private fileSessionprovider: CoreFileSessionProvider,
+ private fileUploaderProvider: CoreFileUploaderProvider) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldFileComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ name: fieldName,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const files = this.getFieldEditFiles(field);
+
+ if (files.length) {
+ return [{
+ fieldid: field.id,
+ subfield: 'file',
+ files: files
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit files in the input data.
+ *
+ * @param {any} field Defines the field..
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditFiles(field: any): any {
+ return this.fileSessionprovider.getFiles(AddonModDataProvider.COMPONENT, field.dataid + '_' + field.id);
+ }
+
+ /**
+ * 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 files = this.fileSessionprovider.getFiles(AddonModDataProvider.COMPONENT, field.dataid + '_' + field.id) || [];
+ let originalFiles = (originalFieldData && originalFieldData.files) || [];
+
+ if (originalFiles.length) {
+ originalFiles = [originalFiles[0]];
+ }
+
+ return this.fileUploaderProvider.areFileListDifferent(files, originalFiles);
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required && (!inputData || !inputData.length || !inputData[0].value)) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ if (offlineContent && offlineContent.file && offlineContent.file.offline > 0 && offlineFiles && offlineFiles.length > 0) {
+ originalContent.content = offlineFiles[0].filename;
+ originalContent.files = [offlineFiles[0]];
+ } else if (offlineContent && offlineContent.file && offlineContent.file.online && offlineContent.file.online.length > 0) {
+ originalContent.content = offlineContent.file.online[0].filename;
+ originalContent.files = [offlineContent.file.online[0]];
+ }
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/latlong/component/latlong.html b/src/addon/mod/data/fields/latlong/component/latlong.html
new file mode 100644
index 000000000..0b2ef6c9e
--- /dev/null
+++ b/src/addon/mod/data/fields/latlong/component/latlong.html
@@ -0,0 +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
new file mode 100644
index 000000000..2d4e555a8
--- /dev/null
+++ b/src/addon/mod/data/fields/latlong/component/latlong.ts
@@ -0,0 +1,90 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { Platform } from 'ionic-angular';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data latlong field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-latlong',
+ templateUrl: 'latlong.html'
+})
+export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ values = {};
+ north: number;
+ east: number;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef, private platform: Platform) {
+ super();
+ }
+
+ /**
+ * Format latitude and longitude in a simple text.
+ *
+ * @param {number} north Degrees north.
+ * @param {number} east Degrees East.
+ * @return {string} Readable Latitude and logitude.
+ */
+ formatLatLong(north: number, east: number): string {
+ if (north !== null || east !== null) {
+ const northFixed = north ? Math.abs(north).toFixed(4) : '0.0000',
+ eastFixed = east ? Math.abs(east).toFixed(4) : '0.0000';
+
+ return northFixed + (north < 0 ? '°S' : '°N') + ' ' + eastFixed + (east < 0 ? '°W' : '°E');
+ }
+ }
+
+ /**
+ * Get link to maps from latitude and longitude.
+ *
+ * @param {number} north Degrees north.
+ * @param {number} east Degrees East.
+ * @return {string} Link to maps depending on platform.
+ */
+ getLatLongLink(north: number, east: number): string {
+ if (north !== null || east !== null) {
+ const northFixed = north ? north.toFixed(4) : '0.0000',
+ eastFixed = east ? east.toFixed(4) : '0.0000';
+
+ if (this.platform.is('ios')) {
+ return 'http://maps.apple.com/?ll=' + northFixed + ',' + eastFixed + '&near=' + northFixed + ',' + eastFixed;
+ }
+
+ return 'geo:' + northFixed + ',' + eastFixed;
+ }
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.value) {
+ this.north = (this.value && parseFloat(this.value.content)) || null;
+ this.east = (this.value && parseFloat(this.value.content1)) || null;
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/latlong/latlong.module.ts b/src/addon/mod/data/fields/latlong/latlong.module.ts
new file mode 100644
index 000000000..5b9b4f11a
--- /dev/null
+++ b/src/addon/mod/data/fields/latlong/latlong.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldLatlongHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldLatlongComponent } from './component/latlong';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldLatlongComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldLatlongHandler
+ ],
+ exports: [
+ AddonModDataFieldLatlongComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldLatlongComponent
+ ]
+})
+export class AddonModDataFieldLatlongModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldLatlongHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/latlong/providers/handler.ts b/src/addon/mod/data/fields/latlong/providers/handler.ts
new file mode 100644
index 000000000..fb549c7c4
--- /dev/null
+++ b/src/addon/mod/data/fields/latlong/providers/handler.ts
@@ -0,0 +1,159 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataFieldLatlongComponent } from '../component/latlong';
+
+/**
+ * Handler for latlong data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldLatlongHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldLatlongHandler';
+ type = 'latlong';
+
+ constructor(private translate: TranslateService) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldLatlongComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ name: fieldName,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const fieldName = 'f_' + field.id,
+ values = [];
+
+ if (inputData[fieldName + '_0']) {
+ values.push({
+ fieldid: field.id,
+ subfield: '0',
+ value: inputData[fieldName + '_0']
+ });
+ }
+
+ if (inputData[fieldName + '_1']) {
+ values.push({
+ fieldid: field.id,
+ subfield: '1',
+ value: inputData[fieldName + '_1']
+ });
+ }
+
+ return values;
+ }
+
+ /**
+ * 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,
+ lat = inputData[fieldName + '_0'] || '',
+ long = inputData[fieldName + '_1'] || '',
+ originalLat = (originalFieldData && originalFieldData.content) || '',
+ originalLong = (originalFieldData && originalFieldData.content1) || '';
+
+ return lat != originalLat || long != originalLong;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ let valueCount = 0;
+
+ // The lat long class has two values that need to be checked.
+ inputData.forEach((value) => {
+ if (typeof value.value != 'undefined' && value.value != '') {
+ valueCount++;
+ }
+ });
+
+ // If we get here then only one field has been filled in.
+ if (valueCount == 1) {
+ return this.translate.instant('addon.mod_data.latlongboth');
+ } else if (field.required && valueCount == 0) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ originalContent.content = offlineContent[0] || '';
+ originalContent.content1 = offlineContent[1] || '';
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/menu/component/menu.html b/src/addon/mod/data/fields/menu/component/menu.html
new file mode 100644
index 000000000..12f41a13f
--- /dev/null
+++ b/src/addon/mod/data/fields/menu/component/menu.html
@@ -0,0 +1,9 @@
+
+
+
+
+ {{ 'addon.mod_data.menuchoose' | translate }}
+ {{option}}
+
+
+
\ 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
new file mode 100644
index 000000000..08628a556
--- /dev/null
+++ b/src/addon/mod/data/fields/menu/component/menu.ts
@@ -0,0 +1,57 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data menu field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-menu',
+ templateUrl: 'menu.html'
+})
+export class AddonModDataFieldMenuComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ val: string;
+ options = [];
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ return;
+ }
+
+ this.options = this.field.param1.split('\n');
+
+ if (this.mode == 'edit' && this.value) {
+ this.val = this.value.content;
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/menu/menu.module.ts b/src/addon/mod/data/fields/menu/menu.module.ts
new file mode 100644
index 000000000..2c4a16427
--- /dev/null
+++ b/src/addon/mod/data/fields/menu/menu.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldMenuHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldMenuComponent } from './component/menu';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldMenuComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldMenuHandler
+ ],
+ exports: [
+ AddonModDataFieldMenuComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldMenuComponent
+ ]
+})
+export class AddonModDataFieldMenuModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldMenuHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/menu/providers/handler.ts b/src/addon/mod/data/fields/menu/providers/handler.ts
new file mode 100644
index 000000000..4e6938c28
--- /dev/null
+++ b/src/addon/mod/data/fields/menu/providers/handler.ts
@@ -0,0 +1,134 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataFieldMenuComponent } from '../component/menu';
+
+/**
+ * Handler for menu data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldMenuHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldMenuHandler';
+ type = 'menu';
+
+ constructor(private translate: TranslateService) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldMenuComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ name: fieldName,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ fieldid: field.id,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * 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 = inputData[fieldName] || '';
+ originalFieldData = (originalFieldData && originalFieldData.content) || '';
+
+ return input != originalFieldData;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required && (!inputData || !inputData.length || !inputData[0].value)) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ originalContent.content = offlineContent[''] || '';
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/multimenu/component/multimenu.html b/src/addon/mod/data/fields/multimenu/component/multimenu.html
new file mode 100644
index 000000000..fbf41a7d7
--- /dev/null
+++ b/src/addon/mod/data/fields/multimenu/component/multimenu.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+')">
\ 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
new file mode 100644
index 000000000..c233c08c2
--- /dev/null
+++ b/src/addon/mod/data/fields/multimenu/component/multimenu.ts
@@ -0,0 +1,63 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data multimenu field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-multimenu',
+ templateUrl: 'multimenu.html'
+})
+export class AddonModDataFieldMultimenuComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ options = [];
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ return;
+ }
+
+ this.options = this.field.param1.split('\n').map((option) => {
+ return { key: option, value: option };
+ });
+
+ 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;
+ }
+ });
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/multimenu/multimenu.module.ts b/src/addon/mod/data/fields/multimenu/multimenu.module.ts
new file mode 100644
index 000000000..7b6b72d12
--- /dev/null
+++ b/src/addon/mod/data/fields/multimenu/multimenu.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldMultimenuHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldMultimenuComponent } from './component/multimenu';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldMultimenuComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldMultimenuHandler
+ ],
+ exports: [
+ AddonModDataFieldMultimenuComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldMultimenuComponent
+ ]
+})
+export class AddonModDataFieldMultimenuModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldMultimenuHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/multimenu/providers/handler.ts b/src/addon/mod/data/fields/multimenu/providers/handler.ts
new file mode 100644
index 000000000..9f65ee8bf
--- /dev/null
+++ b/src/addon/mod/data/fields/multimenu/providers/handler.ts
@@ -0,0 +1,152 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataFieldMultimenuComponent } from '../component/multimenu';
+
+/**
+ * Handler for multimenu data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldMultimenuHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldMultimenuHandler';
+ type = 'multimenu';
+
+ constructor(private translate: TranslateService) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldMultimenuComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id,
+ reqName = 'f_' + field.id + '_allreq';
+
+ if (inputData[fieldName].length > 0) {
+ const options = inputData[fieldName].split('###'),
+ values = [];
+
+ if (options.length > 0) {
+ values.push({
+ name: fieldName,
+ value: options
+ });
+
+ if (inputData[reqName]['1']) {
+ values.push({
+ name: reqName,
+ value: true
+ });
+ }
+
+ return values;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ 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 false;
+ }
+
+ /**
+ * 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 = inputData[fieldName] || '';
+ originalFieldData = (originalFieldData && originalFieldData.content) || '';
+
+ return input != originalFieldData;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required && (!inputData || !inputData.length || !inputData[0].value)) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ originalContent.content = (offlineContent[''] && offlineContent[''].join('###')) || '';
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/number/component/number.html b/src/addon/mod/data/fields/number/component/number.html
new file mode 100644
index 000000000..41bbe1fb0
--- /dev/null
+++ b/src/addon/mod/data/fields/number/component/number.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/addon/mod/data/fields/number/component/number.ts b/src/addon/mod/data/fields/number/component/number.ts
new file mode 100644
index 000000000..c463ea5e4
--- /dev/null
+++ b/src/addon/mod/data/fields/number/component/number.ts
@@ -0,0 +1,54 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data number field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-number',
+ templateUrl: 'number.html'
+})
+export class AddonModDataFieldNumberComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ val: number;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ return;
+ }
+
+ if (this.mode == 'edit' && this.value) {
+ this.val = this.value && parseFloat(this.value.content);
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/number/number.module.ts b/src/addon/mod/data/fields/number/number.module.ts
new file mode 100644
index 000000000..ce2acc789
--- /dev/null
+++ b/src/addon/mod/data/fields/number/number.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldNumberHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldNumberComponent } from './component/number';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldNumberComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldNumberHandler
+ ],
+ exports: [
+ AddonModDataFieldNumberComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldNumberComponent
+ ]
+})
+export class AddonModDataFieldNumberModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldNumberHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/number/providers/handler.ts b/src/addon/mod/data/fields/number/providers/handler.ts
new file mode 100644
index 000000000..654681d72
--- /dev/null
+++ b/src/addon/mod/data/fields/number/providers/handler.ts
@@ -0,0 +1,57 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldTextHandler } from '../../text/providers/handler';
+import { AddonModDataFieldNumberComponent } from '../component/number';
+
+/**
+ * Handler for number data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldNumberHandler extends AddonModDataFieldTextHandler {
+ name = 'AddonModDataFieldNumberHandler';
+ type = 'number';
+
+ constructor(protected translate: TranslateService) {
+ super(translate);
+ }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldNumberComponent;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required && (!inputData || !inputData.length || inputData[0].value == '')) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+}
diff --git a/src/addon/mod/data/fields/picture/component/picture.html b/src/addon/mod/data/fields/picture/component/picture.html
new file mode 100644
index 000000000..e435409f8
--- /dev/null
+++ b/src/addon/mod/data/fields/picture/component/picture.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+ {{ 'addon.mod_data.alttext' | translate }}
+
+ °N
+
+
+
+
+
\ 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
new file mode 100644
index 000000000..b4516a4a3
--- /dev/null
+++ b/src/addon/mod/data/fields/picture/component/picture.ts
@@ -0,0 +1,128 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+import { CoreFileSessionProvider } from '@providers/file-session';
+import { AddonModDataProvider } from '../../../providers/data';
+
+/**
+ * Component to render data picture field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-picture',
+ templateUrl: 'picture.html'
+})
+export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ files = [];
+ component: string;
+ componentId: number;
+ maxSizeBytes: number;
+
+ image: any;
+ entryId: number;
+ imageUrl: string;
+ title: string;
+ alttext: string;
+ width: string;
+ height: string;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef, private fileSessionprovider: CoreFileSessionProvider) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.render();
+ }
+
+ /**
+ * Get the files from the input value.
+ *
+ * @param {any} value Input value.
+ * @return {any} List of files.
+ */
+ protected getFiles(value: any): any {
+ let files = (value && value.files) || [];
+
+ // Reduce to first element.
+ if (files.length > 0) {
+ files = [files[0]];
+ }
+
+ return files;
+ }
+
+ /**
+ * Find file in a list.
+ *
+ * @param {any[]} files File list where to search.
+ * @param {string} filenameSeek Filename to search.
+ * @return {any} File found or false.
+ */
+ protected findFile(files: any[], filenameSeek: string): any {
+ return files.find((file) => file.filename == filenameSeek) || false;
+ }
+
+ protected render(): 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 = [];
+ }
+
+ 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 || '';
+ }
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/picture/picture.module.ts b/src/addon/mod/data/fields/picture/picture.module.ts
new file mode 100644
index 000000000..c666e1bad
--- /dev/null
+++ b/src/addon/mod/data/fields/picture/picture.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldPictureHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldPictureComponent } from './component/picture';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldPictureComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule,
+ ],
+ providers: [
+ AddonModDataFieldPictureHandler
+ ],
+ exports: [
+ AddonModDataFieldPictureComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldPictureComponent
+ ]
+})
+export class AddonModDataFieldPictureModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldPictureHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/picture/providers/handler.ts b/src/addon/mod/data/fields/picture/providers/handler.ts
new file mode 100644
index 000000000..a5eab43b0
--- /dev/null
+++ b/src/addon/mod/data/fields/picture/providers/handler.ts
@@ -0,0 +1,194 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { CoreFileSessionProvider } from '@providers/file-session';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataProvider } from '../../../providers/data';
+import { AddonModDataFieldPictureComponent } from '../component/picture';
+import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
+
+/**
+ * Handler for picture data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldPictureHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldPictureHandler';
+ type = 'picture';
+
+ constructor(private translate: TranslateService, private fileSessionprovider: CoreFileSessionProvider,
+ private fileUploaderProvider: CoreFileUploaderProvider) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldPictureComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ name: fieldName,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const files = this.getFieldEditFiles(field),
+ values = [],
+ fieldName = 'f_' + field.id + '_alttext';
+
+ if (files.length) {
+ values.push({
+ fieldid: field.id,
+ subfield: 'file',
+ files: files
+ });
+ }
+
+ if (inputData[fieldName]) {
+ values.push({
+ fieldid: field.id,
+ subfield: 'alttext',
+ value: inputData[fieldName]
+ });
+ }
+
+ return values;
+ }
+
+ /**
+ * Get field edit files in the input data.
+ *
+ * @param {any} field Defines the field..
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditFiles(field: any): any {
+ return this.fileSessionprovider.getFiles(AddonModDataProvider.COMPONENT, field.dataid + '_' + field.id);
+ }
+
+ /**
+ * 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 + '_alttext',
+ altText = inputData[fieldName] || '',
+ originalAltText = (originalFieldData && originalFieldData.content1) || '',
+ files = this.getFieldEditFiles(field) || [];
+ let originalFiles = (originalFieldData && originalFieldData.files) || [];
+
+ // Get image.
+ if (originalFiles.length > 0) {
+ const filenameSeek = (originalFieldData && originalFieldData.content) || '',
+ file = originalFiles.find((file) => file.filename == filenameSeek);
+ if (file) {
+ originalFiles = [file];
+ }
+ } else {
+ originalFiles = [];
+ }
+
+ return altText != originalAltText || this.fileUploaderProvider.areFileListDifferent(files, originalFiles);
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required) {
+ if (!inputData || !inputData.length) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ const found = inputData.some((input) => {
+ if (typeof input.subfield != 'undefined' && input.subfield == 'file') {
+ return !!input.value;
+ }
+
+ return false;
+ });
+
+ if (!found) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ if (offlineContent && offlineContent.file && offlineContent.file.offline > 0 && offlineFiles && offlineFiles.length > 0) {
+ originalContent.content = offlineFiles[0].filename;
+ originalContent.files = [offlineFiles[0]];
+ } else if (offlineContent && offlineContent.file && offlineContent.file.online && offlineContent.file.online.length > 0) {
+ originalContent.content = offlineContent.file.online[0].filename;
+ originalContent.files = [offlineContent.file.online[0]];
+ }
+
+ originalContent.content1 = offlineContent.alttext || '';
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/radiobutton/component/radiobutton.html b/src/addon/mod/data/fields/radiobutton/component/radiobutton.html
new file mode 100644
index 000000000..12f41a13f
--- /dev/null
+++ b/src/addon/mod/data/fields/radiobutton/component/radiobutton.html
@@ -0,0 +1,9 @@
+
+
+
+
+ {{ 'addon.mod_data.menuchoose' | translate }}
+ {{option}}
+
+
+
\ 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
new file mode 100644
index 000000000..208d5d2cb
--- /dev/null
+++ b/src/addon/mod/data/fields/radiobutton/component/radiobutton.ts
@@ -0,0 +1,57 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data radiobutton field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-radiobutton',
+ templateUrl: 'radiobutton.html'
+})
+export class AddonModDataFieldRadiobuttonComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ options: number;
+ val: number;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ return;
+ }
+
+ this.options = this.field.param1.split('\n');
+
+ if (this.mode == 'edit' && this.value) {
+ this.val = this.value.content;
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/radiobutton/providers/handler.ts b/src/addon/mod/data/fields/radiobutton/providers/handler.ts
new file mode 100644
index 000000000..6efbd744b
--- /dev/null
+++ b/src/addon/mod/data/fields/radiobutton/providers/handler.ts
@@ -0,0 +1,133 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataFieldRadiobuttonComponent } from '../component/radiobutton';
+
+/**
+ * Handler for checkbox data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldRadiobuttonHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldRadiobuttonHandler';
+ type = 'radiobutton';
+
+ constructor(private translate: TranslateService) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldRadiobuttonComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id;
+ if (inputData[fieldName]) {
+ return [{
+ name: fieldName,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ fieldid: field.id,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * 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 = inputData[fieldName] || '';
+ originalFieldData = (originalFieldData && originalFieldData.content) || '';
+
+ return input != originalFieldData;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required && (!inputData || !inputData.length || !inputData[0].value)) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ originalContent.content = offlineContent[''] || '';
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/radiobutton/radiobutton.module.ts b/src/addon/mod/data/fields/radiobutton/radiobutton.module.ts
new file mode 100644
index 000000000..d361bc934
--- /dev/null
+++ b/src/addon/mod/data/fields/radiobutton/radiobutton.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldRadiobuttonHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldRadiobuttonComponent } from './component/radiobutton';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldRadiobuttonComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldRadiobuttonHandler
+ ],
+ exports: [
+ AddonModDataFieldRadiobuttonComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldRadiobuttonComponent
+ ]
+})
+export class AddonModDataFieldRadiobuttonModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldRadiobuttonHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/text/component/text.html b/src/addon/mod/data/fields/text/component/text.html
new file mode 100644
index 000000000..d907c4a9c
--- /dev/null
+++ b/src/addon/mod/data/fields/text/component/text.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 000000000..174bc1cd2
--- /dev/null
+++ b/src/addon/mod/data/fields/text/component/text.ts
@@ -0,0 +1,54 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data text field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-text',
+ templateUrl: 'text.html'
+})
+export class AddonModDataFieldTextComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ val: number;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ return;
+ }
+
+ if (this.mode == 'edit' && this.value) {
+ this.val = this.value.content;
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/text/providers/handler.ts b/src/addon/mod/data/fields/text/providers/handler.ts
new file mode 100644
index 000000000..19d49b713
--- /dev/null
+++ b/src/addon/mod/data/fields/text/providers/handler.ts
@@ -0,0 +1,134 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldHandler } from '../../../providers/fields-delegate';
+import { AddonModDataFieldTextComponent } from '../component/text';
+
+/**
+ * Handler for number data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldTextHandler implements AddonModDataFieldHandler {
+ name = 'AddonModDataFieldTextHandler';
+ type = 'text';
+
+ constructor(protected translate: TranslateService) { }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldTextComponent;
+ }
+
+ /**
+ * Get field search data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the search form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldSearchData(field: any, inputData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ name: fieldName,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return [{
+ fieldid: field.id,
+ value: inputData[fieldName]
+ }];
+ }
+
+ return false;
+ }
+
+ /**
+ * 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 = inputData[fieldName] || '';
+ originalFieldData = (originalFieldData && originalFieldData.content) || '';
+
+ return input != originalFieldData;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required && (!inputData || !inputData.length || !inputData[0].value)) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ originalContent.content = offlineContent[''] || '';
+
+ return originalContent;
+ }
+
+ /**
+ * Whether or not the handler is enabled on a site level.
+ *
+ * @return {boolean|Promise} True or promise resolved with true if enabled.
+ */
+ isEnabled(): boolean | Promise {
+ return true;
+ }
+}
diff --git a/src/addon/mod/data/fields/text/text.module.ts b/src/addon/mod/data/fields/text/text.module.ts
new file mode 100644
index 000000000..a96ddf9de
--- /dev/null
+++ b/src/addon/mod/data/fields/text/text.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldTextHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldTextComponent } from './component/text';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldTextComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldTextHandler
+ ],
+ exports: [
+ AddonModDataFieldTextComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldTextComponent
+ ]
+})
+export class AddonModDataFieldTextModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldTextHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/textarea/component/textarea.html b/src/addon/mod/data/fields/textarea/component/textarea.html
new file mode 100644
index 000000000..5a625183b
--- /dev/null
+++ b/src/addon/mod/data/fields/textarea/component/textarea.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 000000000..83336cff7
--- /dev/null
+++ b/src/addon/mod/data/fields/textarea/component/textarea.ts
@@ -0,0 +1,69 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataProvider } from '../../../providers/data';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data number field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-textarea',
+ templateUrl: 'textarea.html'
+})
+export class AddonModDataFieldTextareaComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ component: string;
+ componentId: number;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ format(value: any): string {
+ const files = (value && value.files) || [];
+
+ return value ? this.textUtils.replacePluginfileUrls(value.content, files) : '';
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ this.component = AddonModDataProvider.COMPONENT;
+ this.componentId = this.database.coursemodule;
+
+ return;
+ }
+
+ // 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) : '';
+
+ this.control = this.fb.control(text);
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/textarea/providers/handler.ts b/src/addon/mod/data/fields/textarea/providers/handler.ts
new file mode 100644
index 000000000..0a5829698
--- /dev/null
+++ b/src/addon/mod/data/fields/textarea/providers/handler.ts
@@ -0,0 +1,145 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldTextHandler } from '../../text/providers/handler';
+import { AddonModDataFieldTextareaComponent } from '../component/textarea';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+
+/**
+ * Handler for textarea data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldTextareaHandler extends AddonModDataFieldTextHandler {
+ name = 'AddonModDataFieldTextareaHandler';
+ type = 'textarea';
+
+ constructor(protected translate: TranslateService, private textUtils: CoreTextUtilsProvider,
+ private domUtils: CoreDomUtilsProvider) {
+ super(translate);
+ }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldTextareaComponent;
+ }
+
+ /**
+ * Get field edit data in the input data.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditData(field: any, inputData: any, originalFieldData: any): any {
+ const fieldName = 'f_' + field.id;
+
+ if (inputData[fieldName]) {
+ return this.domUtils.isRichTextEditorEnabled().then((enabled) => {
+ const files = this.getFieldEditFiles(field, inputData, originalFieldData);
+ let text = this.textUtils.restorePluginfileUrls(inputData[fieldName], files);
+
+ if (!enabled) {
+ // Rich text editor not enabled, add some HTML to the text if needed.
+ text = this.textUtils.formatHtmlLines(text);
+ }
+
+ return [{
+ fieldid: field.id,
+ value: text
+ },
+ {
+ fieldid: field.id,
+ subfield: 'content1',
+ value: 1
+ },
+ {
+ fieldid: field.id,
+ subfield: 'itemid',
+ files: files
+ }
+ ];
+ });
+ }
+
+ return false;
+ }
+
+ /**
+ * Get field edit files in the input data.
+ *
+ * @param {any} field Defines the field..
+ * @param {any} inputData Data entered in the edit form.
+ * @param {any} originalFieldData Original field entered data.
+ * @return {any} With name and value of the data to be sent.
+ */
+ getFieldEditFiles(field: any, inputData: any, originalFieldData: any): any {
+ return (originalFieldData && originalFieldData.files) || [];
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required) {
+ if (!inputData || !inputData.length) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ const found = inputData.some((input) => {
+ if (!input.subfield) {
+ return !!input.value;
+ }
+
+ return false;
+ });
+
+ if (!found) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Override field content data with offline submission.
+ *
+ * @param {any} originalContent Original data to be overriden.
+ * @param {any} offlineContent Array with all the offline data to override.
+ * @param {any} [offlineFiles] Array with all the offline files in the field.
+ * @return {any} Data overriden
+ */
+ overrideData(originalContent: any, offlineContent: any, offlineFiles?: any): any {
+ originalContent.content = offlineContent[''] || '';
+ if (originalContent.content.length > 0 && originalContent.files && originalContent.files.length > 0) {
+ // Take the original files since we cannot edit them on the app.
+ originalContent.content = this.textUtils.replacePluginfileUrls(originalContent.content, originalContent.files);
+ }
+
+ return originalContent;
+ }
+}
diff --git a/src/addon/mod/data/fields/textarea/textarea.module.ts b/src/addon/mod/data/fields/textarea/textarea.module.ts
new file mode 100644
index 000000000..8c63d53f7
--- /dev/null
+++ b/src/addon/mod/data/fields/textarea/textarea.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldTextareaHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldTextareaComponent } from './component/textarea';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldTextareaComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldTextareaHandler
+ ],
+ exports: [
+ AddonModDataFieldTextareaComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldTextareaComponent
+ ]
+})
+export class AddonModDataFieldTextareaModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldTextareaHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/fields/url/component/url.html b/src/addon/mod/data/fields/url/component/url.html
new file mode 100644
index 000000000..ddd31d55f
--- /dev/null
+++ b/src/addon/mod/data/fields/url/component/url.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+{{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
new file mode 100644
index 000000000..15ac1f53f
--- /dev/null
+++ b/src/addon/mod/data/fields/url/component/url.ts
@@ -0,0 +1,54 @@
+// (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, OnInit, ElementRef } from '@angular/core';
+import { FormBuilder, FormControl } from '@angular/forms';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreTextUtilsProvider } from '@providers/utils/text';
+import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component';
+
+/**
+ * Component to render data url field.
+ */
+@Component({
+ selector: 'addon-mod-data-field-url',
+ templateUrl: 'url.html'
+})
+export class AddonModDataFieldUrlComponent extends AddonModDataFieldPluginComponent implements OnInit {
+
+ control: FormControl;
+ val: number;
+
+ constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider,
+ element: ElementRef) {
+ super();
+ }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.mode = this.mode == 'list' ? 'show' : this.mode;
+ this.render();
+ }
+
+ protected render(): void {
+ if (this.mode == 'show') {
+ return;
+ }
+
+ if (this.mode == 'edit' && this.value) {
+ this.val = this.value.content;
+ }
+ }
+}
diff --git a/src/addon/mod/data/fields/url/providers/handler.ts b/src/addon/mod/data/fields/url/providers/handler.ts
new file mode 100644
index 000000000..7e6ea803e
--- /dev/null
+++ b/src/addon/mod/data/fields/url/providers/handler.ts
@@ -0,0 +1,57 @@
+// (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 { Injector, Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AddonModDataFieldTextHandler } from '../../text/providers/handler';
+import { AddonModDataFieldUrlComponent } from '../component/url';
+
+/**
+ * Handler for url data field plugin.
+ */
+@Injectable()
+export class AddonModDataFieldUrlHandler extends AddonModDataFieldTextHandler {
+ name = 'AddonModDataFieldUrlHandler';
+ type = 'url';
+
+ constructor(protected translate: TranslateService) {
+ super(translate);
+ }
+
+ /**
+ * Return the Component to use to display the plugin data.
+ * It's recommended to return the class of the component, but you can also return an instance of the component.
+ *
+ * @param {Injector} injector Injector.
+ * @param {any} field The field object.
+ * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found.
+ */
+ getComponent(injector: Injector, plugin: any): any | Promise {
+ return AddonModDataFieldUrlComponent;
+ }
+
+ /**
+ * Check and get field requeriments.
+ *
+ * @param {any} field Defines the field to be rendered.
+ * @param {any} inputData Data entered in the edit form.
+ * @return {string | false} String with the notification or false.
+ */
+ getFieldsNotifications(field: any, inputData: any): string | false {
+ if (field.required && (!inputData || !inputData.length || !inputData[0].value)) {
+ return this.translate.instant('addon.mod_data.errormustsupplyvalue');
+ }
+
+ return false;
+ }
+}
diff --git a/src/addon/mod/data/fields/url/url.module.ts b/src/addon/mod/data/fields/url/url.module.ts
new file mode 100644
index 000000000..09cd8911e
--- /dev/null
+++ b/src/addon/mod/data/fields/url/url.module.ts
@@ -0,0 +1,49 @@
+// (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 { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddonModDataFieldUrlHandler } from './providers/handler';
+import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate';
+import { AddonModDataFieldUrlComponent } from './component/url';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+@NgModule({
+ declarations: [
+ AddonModDataFieldUrlComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ TranslateModule.forChild(),
+ CoreComponentsModule,
+ CoreDirectivesModule
+ ],
+ providers: [
+ AddonModDataFieldUrlHandler
+ ],
+ exports: [
+ AddonModDataFieldUrlComponent
+ ],
+ entryComponents: [
+ AddonModDataFieldUrlComponent
+ ]
+})
+export class AddonModDataFieldUrlModule {
+ constructor(fieldDelegate: AddonModDataFieldsDelegate, handler: AddonModDataFieldUrlHandler) {
+ fieldDelegate.registerHandler(handler);
+ }
+}
diff --git a/src/addon/mod/data/providers/helper.ts b/src/addon/mod/data/providers/helper.ts
index 43ffe33fe..8f929e8b0 100644
--- a/src/addon/mod/data/providers/helper.ts
+++ b/src/addon/mod/data/providers/helper.ts
@@ -113,7 +113,7 @@ export class AddonModDataHelperProvider {
replace = new RegExp(replace, 'gi');
// Replace field by a generic directive.
- const render = '';
template = template.replace(replace, render);
});
@@ -156,13 +156,13 @@ export class AddonModDataHelperProvider {
replace = new RegExp(replace, 'gi');
// Replace field by a generic directive.
- render = '';
template = template.replace(replace, render);
});
- for (const action in actions) {
+ /*for (const action in actions) {
replace = new RegExp('##' + action + '##', 'gi');
// Is enabled?
if (actions[action]) {
@@ -179,7 +179,7 @@ export class AddonModDataHelperProvider {
} else {
template = template.replace(replace, '');
}
- }
+ }*/
return template;
}
diff --git a/src/addon/mod/feedback/providers/helper.ts b/src/addon/mod/feedback/providers/helper.ts
index 7f5527623..cbd1ea4d5 100644
--- a/src/addon/mod/feedback/providers/helper.ts
+++ b/src/addon/mod/feedback/providers/helper.ts
@@ -47,7 +47,6 @@ export class AddonModFeedbackHelperProvider {
protected getActivityHistoryBackCounter(pageName: string, instance: number, paramName: string, prefix: string,
navCtrl: NavController): number {
let historyInstance, params,
- backTimes = 0,
view = navCtrl.getActive();
while (!view.isFirst()) {
@@ -60,9 +59,7 @@ export class AddonModFeedbackHelperProvider {
historyInstance = params.get(paramName) ? params.get(paramName) : params.get('module').instance;
// Check we are not changing to another activity.
- if (historyInstance && historyInstance == instance) {
- backTimes++;
- } else {
+ if (!historyInstance || historyInstance != instance) {
break;
}
diff --git a/src/core/compile/components/compile-html/compile-html.ts b/src/core/compile/components/compile-html/compile-html.ts
index c530b08f2..8b7a7a218 100644
--- a/src/core/compile/components/compile-html/compile-html.ts
+++ b/src/core/compile/components/compile-html/compile-html.ts
@@ -42,6 +42,8 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
@Input() text: string; // The HTML text to display.
@Input() javascript: string; // The Javascript to execute in the component.
@Input() jsData: any; // Data to pass to the fake component.
+ @Input() extraImports: any[] = []; // Extra import modules.
+ @Input() extraProviders: any[] = []; // Extra providers.
@Output() created: EventEmitter = new EventEmitter(); // Will emit an event when the component is instantiated.
// Get the container where to put the content.
@@ -61,7 +63,8 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
if ((changes.text || changes.javascript) && this.text) {
// Create a new component and a new module.
- this.compileProvider.createAndCompileComponent(this.text, this.getComponentClass()).then((factory) => {
+ this.compileProvider.createAndCompileComponent(this.text, this.getComponentClass(), this.extraImports)
+ .then((factory) => {
// Destroy previous components.
this.componentRef && this.componentRef.destroy();
@@ -95,7 +98,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
constructor() {
// If there is some javascript to run, prepare the instance.
if (compileInstance.javascript) {
- compileInstance.compileProvider.injectLibraries(this);
+ compileInstance.compileProvider.injectLibraries(this, compileInstance.extraProviders);
}
// Always add these elements, they could be needed on component init (componentObservable).
diff --git a/src/core/compile/providers/compile.ts b/src/core/compile/providers/compile.ts
index 828238d0f..411b62fee 100644
--- a/src/core/compile/providers/compile.ts
+++ b/src/core/compile/providers/compile.ts
@@ -112,17 +112,20 @@ export class CoreCompileProvider {
*
* @param {string} template The template of the component.
* @param {any} componentClass The JS class of the component.
+ * @param {any[]} [extraImports] Extra imported modules if needed and not imported by this class.
* @return {Promise>} Promise resolved with the factory to instantiate the component.
*/
- createAndCompileComponent(template: string, componentClass: any): Promise> {
+ createAndCompileComponent(template: string, componentClass: any, extraImports: any[] = []): Promise> {
// Create the component using the template and the class.
const component = Component({
template: template
})
(componentClass);
+ const imports = this.IMPORTS.concat(extraImports);
+
// Now create the module containing the component.
- const module = NgModule({imports: this.IMPORTS, declarations: [component]})(class {});
+ const module = NgModule({imports: imports, declarations: [component]})(class {});
// Compile the module and the component.
return this.compiler.compileModuleAndAllComponentsAsync(module).then((factories) => {
@@ -166,13 +169,14 @@ export class CoreCompileProvider {
* Inject all the core libraries in a certain object.
*
* @param {any} instance The instance where to inject the libraries.
+ * @param {any[]} [extraProviders] Extra imported providers if needed and not imported by this class.
*/
- injectLibraries(instance: any): void {
+ injectLibraries(instance: any, extraProviders: any[] = []): void {
const providers = ( CORE_PROVIDERS).concat(CORE_CONTENTLINKS_PROVIDERS).concat(CORE_COURSE_PROVIDERS)
.concat(CORE_COURSES_PROVIDERS).concat(CORE_FILEUPLOADER_PROVIDERS).concat(CORE_GRADES_PROVIDERS)
.concat(CORE_LOGIN_PROVIDERS).concat(CORE_MAINMENU_PROVIDERS).concat(CORE_SHAREDFILES_PROVIDERS)
.concat(CORE_SITEHOME_PROVIDERS).concat([CoreSitePluginsProvider]).concat(CORE_USER_PROVIDERS)
- .concat(CORE_QUESTION_PROVIDERS).concat(IONIC_NATIVE_PROVIDERS).concat(this.OTHER_PROVIDERS);
+ .concat(CORE_QUESTION_PROVIDERS).concat(IONIC_NATIVE_PROVIDERS).concat(this.OTHER_PROVIDERS).concat(extraProviders);
// We cannot inject anything to this constructor. Use the Injector to inject all the providers into the instance.
for (const i in providers) {