forked from EVOgeek/Vmeda.Online
		
	MOBILE-3323 editor: Delete draft when form is submitted
This commit is contained in:
		
							parent
							
								
									5a79151b01
								
							
						
					
					
						commit
						7fa8e6fe05
					
				@ -9,7 +9,7 @@
 | 
				
			|||||||
    </ion-refresher>
 | 
					    </ion-refresher>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <core-loading [hideUntil]="loaded">
 | 
					    <core-loading [hideUntil]="loaded">
 | 
				
			||||||
        <form ion-list [formGroup]="eventForm" *ngIf="!error">
 | 
					        <form ion-list [formGroup]="eventForm" *ngIf="!error" #editEventForm>
 | 
				
			||||||
            <!-- Event name. -->
 | 
					            <!-- Event name. -->
 | 
				
			||||||
            <ion-item text-wrap>
 | 
					            <ion-item text-wrap>
 | 
				
			||||||
                <ion-label stacked><h2 [core-mark-required]="true">{{ 'addon.calendar.eventname' | translate }}</h2></ion-label>
 | 
					                <ion-label stacked><h2 [core-mark-required]="true">{{ 'addon.calendar.eventname' | translate }}</h2></ion-label>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy, Optional, ViewChild } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, Optional, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
 | 
					import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
 | 
				
			||||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
@ -44,6 +44,7 @@ import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
 | 
				
			|||||||
export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
 | 
					export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChild(CoreEditorRichTextEditorComponent) descriptionEditor: CoreEditorRichTextEditorComponent;
 | 
					    @ViewChild(CoreEditorRichTextEditorComponent) descriptionEditor: CoreEditorRichTextEditorComponent;
 | 
				
			||||||
 | 
					    @ViewChild('editEventForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    title: string;
 | 
					    title: string;
 | 
				
			||||||
    dateFormat: string;
 | 
					    dateFormat: string;
 | 
				
			||||||
@ -496,6 +497,11 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        this.calendarProvider.submitEvent(this.eventId, data).then((result) => {
 | 
					        this.calendarProvider.submitEvent(this.eventId, data).then((result) => {
 | 
				
			||||||
            event = result.event;
 | 
					            event = result.event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: result.sent,
 | 
				
			||||||
 | 
					            }, this.currentSite.getId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (result.sent) {
 | 
					            if (result.sent) {
 | 
				
			||||||
                // Event created or edited, invalidate right days & months.
 | 
					                // Event created or edited, invalidate right days & months.
 | 
				
			||||||
                const numberOfRepetitions = formData.repeat ? formData.repeats :
 | 
					                const numberOfRepetitions = formData.repeat ? formData.repeats :
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@
 | 
				
			|||||||
    </ion-navbar>
 | 
					    </ion-navbar>
 | 
				
			||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <form name="addon-mod_assign-edit-feedback-form" *ngIf="userId && plugin">
 | 
					    <form name="addon-mod_assign-edit-feedback-form" *ngIf="userId && plugin" #editFeedbackForm>
 | 
				
			||||||
        <addon-mod-assign-feedback-plugin [assign]="assign" [submission]="submission" [userId]="userId" [plugin]="plugin" [edit]="true"></addon-mod-assign-feedback-plugin>
 | 
					        <addon-mod-assign-feedback-plugin [assign]="assign" [submission]="submission" [userId]="userId" [plugin]="plugin" [edit]="true"></addon-mod-assign-feedback-plugin>
 | 
				
			||||||
        <button ion-button block (click)="done($event)">{{ 'core.done' | translate }}</button>
 | 
					        <button ion-button block (click)="done($event)">{{ 'core.done' | translate }}</button>
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,11 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Input } from '@angular/core';
 | 
					import { Component, Input, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, ViewController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, ViewController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate';
 | 
					import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -36,10 +38,17 @@ export class AddonModAssignEditFeedbackModalPage {
 | 
				
			|||||||
    @Input() plugin: AddonModAssignPlugin; // The plugin object.
 | 
					    @Input() plugin: AddonModAssignPlugin; // The plugin object.
 | 
				
			||||||
    @Input() userId: number; // The user ID of the submission.
 | 
					    @Input() userId: number; // The user ID of the submission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('editFeedbackForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected forceLeave = false; // To allow leaving the page without checking for changes.
 | 
					    protected forceLeave = false; // To allow leaving the page without checking for changes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(params: NavParams, protected viewCtrl: ViewController, protected domUtils: CoreDomUtilsProvider,
 | 
					    constructor(params: NavParams,
 | 
				
			||||||
            protected translate: TranslateService, protected feedbackDelegate: AddonModAssignFeedbackDelegate) {
 | 
					            protected viewCtrl: ViewController,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected translate: TranslateService,
 | 
				
			||||||
 | 
					            protected feedbackDelegate: AddonModAssignFeedbackDelegate,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.assign = params.get('assign');
 | 
					        this.assign = params.get('assign');
 | 
				
			||||||
        this.submission = params.get('submission');
 | 
					        this.submission = params.get('submission');
 | 
				
			||||||
@ -82,6 +91,11 @@ export class AddonModAssignEditFeedbackModalPage {
 | 
				
			|||||||
        e.preventDefault();
 | 
					        e.preventDefault();
 | 
				
			||||||
        e.stopPropagation();
 | 
					        e.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					            form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					            online: false,
 | 
				
			||||||
 | 
					        }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Close the modal, sending the input data.
 | 
					        // Close the modal, sending the input data.
 | 
				
			||||||
        this.forceLeave = true;
 | 
					        this.forceLeave = true;
 | 
				
			||||||
        this.closeModal(this.getInputData());
 | 
					        this.closeModal(this.getInputData());
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
    <core-loading [hideUntil]="loaded">
 | 
					    <core-loading [hideUntil]="loaded">
 | 
				
			||||||
        <ion-list>
 | 
					        <ion-list>
 | 
				
			||||||
            <!-- @todo: plagiarism_print_disclosure -->
 | 
					            <!-- @todo: plagiarism_print_disclosure -->
 | 
				
			||||||
            <form name="addon-mod_assign-edit-form" *ngIf="userSubmission && userSubmission.plugins && userSubmission.plugins.length">
 | 
					            <form name="addon-mod_assign-edit-form" *ngIf="userSubmission && userSubmission.plugins && userSubmission.plugins.length" #editSubmissionForm>
 | 
				
			||||||
                <!-- Submission statement. -->
 | 
					                <!-- Submission statement. -->
 | 
				
			||||||
                <ion-item text-wrap *ngIf="submissionStatement">
 | 
					                <ion-item text-wrap *ngIf="submissionStatement">
 | 
				
			||||||
                    <ion-label><core-format-text [text]="submissionStatement" [filter]="false"></core-format-text></ion-label>
 | 
					                    <ion-label><core-format-text [text]="submissionStatement" [filter]="false"></core-format-text></ion-label>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { CoreEventsProvider } from '@providers/events';
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
@ -34,6 +34,9 @@ import { AddonModAssignHelperProvider } from '../../providers/helper';
 | 
				
			|||||||
    templateUrl: 'edit.html',
 | 
					    templateUrl: 'edit.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModAssignEditPage implements OnInit, OnDestroy {
 | 
					export class AddonModAssignEditPage implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('editSubmissionForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    title: string; // Title to display.
 | 
					    title: string; // Title to display.
 | 
				
			||||||
    assign: AddonModAssignAssign; // Assignment.
 | 
					    assign: AddonModAssignAssign; // Assignment.
 | 
				
			||||||
    courseId: number; // Course ID the assignment belongs to.
 | 
					    courseId: number; // Course ID the assignment belongs to.
 | 
				
			||||||
@ -265,50 +268,60 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Promise resolved when done.
 | 
					     * @return Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected saveSubmission(): Promise<any> {
 | 
					    protected async saveSubmission(): Promise<void> {
 | 
				
			||||||
        const inputData = this.getInputData();
 | 
					        const inputData = this.getInputData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.submissionStatement && (!inputData.submissionstatement || inputData.submissionstatement === 'false')) {
 | 
					        if (this.submissionStatement && (!inputData.submissionstatement || inputData.submissionstatement === 'false')) {
 | 
				
			||||||
            return Promise.reject(this.translate.instant('addon.mod_assign.acceptsubmissionstatement'));
 | 
					            throw this.translate.instant('addon.mod_assign.acceptsubmissionstatement');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let modal = this.domUtils.showModalLoading();
 | 
					        let modal = this.domUtils.showModalLoading();
 | 
				
			||||||
 | 
					        let size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get size to ask for confirmation.
 | 
					        // Get size to ask for confirmation.
 | 
				
			||||||
        return this.assignHelper.getSubmissionSizeForEdit(this.assign, this.userSubmission, inputData).catch(() => {
 | 
					        try {
 | 
				
			||||||
 | 
					            size = await this.assignHelper.getSubmissionSizeForEdit(this.assign, this.userSubmission, inputData);
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
            // Error calculating size, return -1.
 | 
					            // Error calculating size, return -1.
 | 
				
			||||||
            return -1;
 | 
					            size = -1;
 | 
				
			||||||
        }).then((size) => {
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        modal.dismiss();
 | 
					        modal.dismiss();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
            // Confirm action.
 | 
					            // Confirm action.
 | 
				
			||||||
            return this.fileUploaderHelper.confirmUploadFile(size, true, this.allowOffline);
 | 
					            await this.fileUploaderHelper.confirmUploadFile(size, true, this.allowOffline);
 | 
				
			||||||
        }).then(() => {
 | 
					
 | 
				
			||||||
            modal = this.domUtils.showModalLoading('core.sending', true);
 | 
					            modal = this.domUtils.showModalLoading('core.sending', true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return this.prepareSubmissionData(inputData).then((pluginData) => {
 | 
					            const pluginData = await this.prepareSubmissionData(inputData);
 | 
				
			||||||
            if (!Object.keys(pluginData).length) {
 | 
					            if (!Object.keys(pluginData).length) {
 | 
				
			||||||
                // Nothing to save.
 | 
					                // Nothing to save.
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let promise;
 | 
					            let sent: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.saveOffline) {
 | 
					            if (this.saveOffline) {
 | 
				
			||||||
                // Save submission in offline.
 | 
					                // Save submission in offline.
 | 
				
			||||||
                    promise = this.assignOfflineProvider.saveSubmission(this.assign.id, this.courseId, pluginData,
 | 
					                sent = false;
 | 
				
			||||||
 | 
					                await this.assignOfflineProvider.saveSubmission(this.assign.id, this.courseId, pluginData,
 | 
				
			||||||
                        this.userSubmission.timemodified, !this.assign.submissiondrafts, this.userId);
 | 
					                        this.userSubmission.timemodified, !this.assign.submissiondrafts, this.userId);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // Try to send it to server.
 | 
					                // Try to send it to server.
 | 
				
			||||||
                    promise = this.assignProvider.saveSubmission(this.assign.id, this.courseId, pluginData, this.allowOffline,
 | 
					                sent = await this.assignProvider.saveSubmission(this.assign.id, this.courseId, pluginData, this.allowOffline,
 | 
				
			||||||
                        this.userSubmission.timemodified, !!this.assign.submissiondrafts, this.userId);
 | 
					                        this.userSubmission.timemodified, !!this.assign.submissiondrafts, this.userId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return promise.then(() => {
 | 
					 | 
				
			||||||
            // Clear temporary data from plugins.
 | 
					            // Clear temporary data from plugins.
 | 
				
			||||||
                    return this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, inputData);
 | 
					            await this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, inputData);
 | 
				
			||||||
                }).then(() => {
 | 
					
 | 
				
			||||||
                    // Submission saved, trigger event.
 | 
					            // Submission saved, trigger events.
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: sent,
 | 
				
			||||||
 | 
					            }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const params = {
 | 
					            const params = {
 | 
				
			||||||
                assignmentId: this.assign.id,
 | 
					                assignmentId: this.assign.id,
 | 
				
			||||||
                submissionId: this.userSubmission.id,
 | 
					                submissionId: this.userSubmission.id,
 | 
				
			||||||
@ -323,11 +336,9 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy {
 | 
				
			|||||||
                this.eventsProvider.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, params,
 | 
					                this.eventsProvider.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, params,
 | 
				
			||||||
                        this.sitesProvider.getCurrentSiteId());
 | 
					                        this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                });
 | 
					        } finally {
 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }).finally(() => {
 | 
					 | 
				
			||||||
            modal.dismiss();
 | 
					            modal.dismiss();
 | 
				
			||||||
        });
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@
 | 
				
			|||||||
        <div class="addon-data-contents addon-data-entries-{{data.id}}" *ngIf="data">
 | 
					        <div class="addon-data-contents addon-data-entries-{{data.id}}" *ngIf="data">
 | 
				
			||||||
            <core-style [css]="data.csstemplate" prefix=".addon-data-entries-{{data.id}}"></core-style>
 | 
					            <core-style [css]="data.csstemplate" prefix=".addon-data-entries-{{data.id}}"></core-style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <form (ngSubmit)="save($event)" [formGroup]="editForm">
 | 
					            <form (ngSubmit)="save($event)" [formGroup]="editForm" #editFormEl>
 | 
				
			||||||
                <core-compile-html [text]="editFormRender" [jsData]="jsData" [extraImports]="extraImports"></core-compile-html>
 | 
					                <core-compile-html [text]="editFormRender" [jsData]="jsData" [extraImports]="extraImports"></core-compile-html>
 | 
				
			||||||
            </form>
 | 
					            </form>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, ViewChild } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { Content, IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
					import { Content, IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { FormGroup } from '@angular/forms';
 | 
					import { FormGroup } from '@angular/forms';
 | 
				
			||||||
@ -40,6 +40,7 @@ import { CoreTagProvider } from '@core/tag/providers/tag';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModDataEditPage {
 | 
					export class AddonModDataEditPage {
 | 
				
			||||||
    @ViewChild(Content) content: Content;
 | 
					    @ViewChild(Content) content: Content;
 | 
				
			||||||
 | 
					    @ViewChild('editFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected module: any;
 | 
					    protected module: any;
 | 
				
			||||||
    protected courseId: number;
 | 
					    protected courseId: number;
 | 
				
			||||||
@ -216,6 +217,12 @@ export class AddonModDataEditPage {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // This is done if entry is updated when editing or creating if not.
 | 
					                // This is done if entry is updated when editing or creating if not.
 | 
				
			||||||
                if ((this.entryId && result.updated) || (!this.entryId && result.newentryid)) {
 | 
					                if ((this.entryId && result.updated) || (!this.entryId && result.newentryid)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                        form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                        online: result.sent,
 | 
				
			||||||
 | 
					                    }, this.siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    const promises = [];
 | 
					                    const promises = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    this.entryId = this.entryId || result.newentryid;
 | 
					                    this.entryId = this.entryId || result.newentryid;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <a class="tab-slide" [attr.aria-selected]="!search.searchingAdvanced" (click)="changeAdvanced(false)">{{ 'addon.mod_data.search' | translate}}</a>
 | 
					        <a class="tab-slide" [attr.aria-selected]="!search.searchingAdvanced" (click)="changeAdvanced(false)">{{ 'addon.mod_data.search' | translate}}</a>
 | 
				
			||||||
        <a class="tab-slide" [attr.aria-selected]="search.searchingAdvanced" (click)="changeAdvanced(true)">{{ 'addon.mod_data.advancedsearch' | translate }}</a>
 | 
					        <a class="tab-slide" [attr.aria-selected]="search.searchingAdvanced" (click)="changeAdvanced(true)">{{ 'addon.mod_data.advancedsearch' | translate }}</a>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <form (ngSubmit)="searchEntries($event)" [formGroup]="searchForm">
 | 
					    <form (ngSubmit)="searchEntries($event)" [formGroup]="searchForm" #searchFormEl>
 | 
				
			||||||
        <ion-list no-margin>
 | 
					        <ion-list no-margin>
 | 
				
			||||||
            <ion-item [hidden]="search.searchingAdvanced">
 | 
					            <ion-item [hidden]="search.searchingAdvanced">
 | 
				
			||||||
                <ion-input type="text" placeholder="{{ 'addon.mod_data.search' | translate}}" [(ngModel)]="search.text" name="text" formControlName="text"></ion-input>
 | 
					                <ion-input type="text" placeholder="{{ 'addon.mod_data.search' | translate}}" [(ngModel)]="search.text" name="text" formControlName="text"></ion-input>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,11 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavParams, ViewController } from 'ionic-angular';
 | 
					import { IonicPage, NavParams, ViewController } from 'ionic-angular';
 | 
				
			||||||
import { FormBuilder, FormGroup } from '@angular/forms';
 | 
					import { FormBuilder, FormGroup } from '@angular/forms';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
 | 
					import { CoreUtilsProvider } from '@providers/utils/utils';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
 | 
					import { CoreTextUtilsProvider } from '@providers/utils/text';
 | 
				
			||||||
@ -32,6 +34,8 @@ import { CoreTagProvider } from '@core/tag/providers/tag';
 | 
				
			|||||||
    templateUrl: 'search.html',
 | 
					    templateUrl: 'search.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModDataSearchPage {
 | 
					export class AddonModDataSearchPage {
 | 
				
			||||||
 | 
					    @ViewChild('searchFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    search: any;
 | 
					    search: any;
 | 
				
			||||||
    fields: any;
 | 
					    fields: any;
 | 
				
			||||||
    data: any;
 | 
					    data: any;
 | 
				
			||||||
@ -41,10 +45,17 @@ export class AddonModDataSearchPage {
 | 
				
			|||||||
    jsData: any;
 | 
					    jsData: any;
 | 
				
			||||||
    fieldsArray: any;
 | 
					    fieldsArray: any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(params: NavParams, private viewCtrl: ViewController, fb: FormBuilder, protected utils: CoreUtilsProvider,
 | 
					    constructor(params: NavParams,
 | 
				
			||||||
            protected domUtils: CoreDomUtilsProvider, protected fieldsDelegate: AddonModDataFieldsDelegate,
 | 
					            protected viewCtrl: ViewController,
 | 
				
			||||||
            protected textUtils: CoreTextUtilsProvider, protected dataHelper: AddonModDataHelperProvider,
 | 
					            fb: FormBuilder,
 | 
				
			||||||
            private tagProvider: CoreTagProvider) {
 | 
					            protected utils: CoreUtilsProvider,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected fieldsDelegate: AddonModDataFieldsDelegate,
 | 
				
			||||||
 | 
					            protected textUtils: CoreTextUtilsProvider,
 | 
				
			||||||
 | 
					            protected dataHelper: AddonModDataHelperProvider,
 | 
				
			||||||
 | 
					            protected tagProvider: CoreTagProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) {
 | 
				
			||||||
        this.search = params.get('search');
 | 
					        this.search = params.get('search');
 | 
				
			||||||
        this.fields = params.get('fields');
 | 
					        this.fields = params.get('fields');
 | 
				
			||||||
        this.data = params.get('data');
 | 
					        this.data = params.get('data');
 | 
				
			||||||
@ -209,6 +220,11 @@ export class AddonModDataSearchPage {
 | 
				
			|||||||
        this.search.sortBy = searchedData.sortBy;
 | 
					        this.search.sortBy = searchedData.sortBy;
 | 
				
			||||||
        this.search.sortDirection = searchedData.sortDirection;
 | 
					        this.search.sortDirection = searchedData.sortDirection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					            form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					            online: false,
 | 
				
			||||||
 | 
					        }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.closeModal(this.search);
 | 
					        this.closeModal(this.search);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -126,7 +126,8 @@ export class AddonModDataProvider {
 | 
				
			|||||||
                    .then((entry) => {
 | 
					                    .then((entry) => {
 | 
				
			||||||
                return {
 | 
					                return {
 | 
				
			||||||
                    // Return provissional entry Id.
 | 
					                    // Return provissional entry Id.
 | 
				
			||||||
                    newentryid: entry
 | 
					                    newentryid: entry,
 | 
				
			||||||
 | 
					                    sent: false,
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
@ -142,7 +143,11 @@ export class AddonModDataProvider {
 | 
				
			|||||||
            return storeOffline();
 | 
					            return storeOffline();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.addEntryOnline(dataId, contents, groupId, siteId).catch((error) => {
 | 
					        return this.addEntryOnline(dataId, contents, groupId, siteId).then((result) => {
 | 
				
			||||||
 | 
					            result.sent = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        }).catch((error) => {
 | 
				
			||||||
            if (this.utils.isWebServiceError(error)) {
 | 
					            if (this.utils.isWebServiceError(error)) {
 | 
				
			||||||
                // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
					                // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
				
			||||||
                return Promise.reject(error);
 | 
					                return Promise.reject(error);
 | 
				
			||||||
@ -194,7 +199,12 @@ export class AddonModDataProvider {
 | 
				
			|||||||
        const storeOffline = (): Promise<any> => {
 | 
					        const storeOffline = (): Promise<any> => {
 | 
				
			||||||
            const action = approve ? 'approve' : 'disapprove';
 | 
					            const action = approve ? 'approve' : 'disapprove';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return this.dataOffline.saveEntry(dataId, entryId, action, courseId, undefined, undefined, undefined, siteId);
 | 
					            return this.dataOffline.saveEntry(dataId, entryId, action, courseId, undefined, undefined, undefined, siteId)
 | 
				
			||||||
 | 
					                    .then(() => {
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    sent: false,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get if the opposite action is not synced.
 | 
					        // Get if the opposite action is not synced.
 | 
				
			||||||
@ -210,7 +220,11 @@ export class AddonModDataProvider {
 | 
				
			|||||||
                return storeOffline();
 | 
					                return storeOffline();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return this.approveEntryOnline(entryId, approve, siteId).catch((error) => {
 | 
					            return this.approveEntryOnline(entryId, approve, siteId).then(() => {
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    sent: true,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            }).catch((error) => {
 | 
				
			||||||
                if (this.utils.isWebServiceError(error)) {
 | 
					                if (this.utils.isWebServiceError(error)) {
 | 
				
			||||||
                    // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
					                    // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
				
			||||||
                    return Promise.reject(error);
 | 
					                    return Promise.reject(error);
 | 
				
			||||||
@ -288,7 +302,12 @@ export class AddonModDataProvider {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Convenience function to store a data to be synchronized later.
 | 
					        // Convenience function to store a data to be synchronized later.
 | 
				
			||||||
        const storeOffline = (): Promise<any> => {
 | 
					        const storeOffline = (): Promise<any> => {
 | 
				
			||||||
            return this.dataOffline.saveEntry(dataId, entryId, 'delete', courseId, undefined, undefined, undefined, siteId);
 | 
					            return this.dataOffline.saveEntry(dataId, entryId, 'delete', courseId, undefined, undefined, undefined, siteId)
 | 
				
			||||||
 | 
					                    .then(() => {
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    sent: false,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let justAdded = false;
 | 
					        let justAdded = false;
 | 
				
			||||||
@ -318,7 +337,11 @@ export class AddonModDataProvider {
 | 
				
			|||||||
                return storeOffline();
 | 
					                return storeOffline();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return this.deleteEntryOnline(entryId, siteId).catch((error) => {
 | 
					            return this.deleteEntryOnline(entryId, siteId).then(() => {
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    sent: true,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            }).catch((error) => {
 | 
				
			||||||
                if (this.utils.isWebServiceError(error)) {
 | 
					                if (this.utils.isWebServiceError(error)) {
 | 
				
			||||||
                    // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
					                    // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
				
			||||||
                    return Promise.reject(error);
 | 
					                    return Promise.reject(error);
 | 
				
			||||||
@ -368,7 +391,8 @@ export class AddonModDataProvider {
 | 
				
			|||||||
            return this.dataOffline.saveEntry(dataId, entryId, 'edit', courseId, undefined, contents, undefined, siteId)
 | 
					            return this.dataOffline.saveEntry(dataId, entryId, 'edit', courseId, undefined, contents, undefined, siteId)
 | 
				
			||||||
                    .then(() => {
 | 
					                    .then(() => {
 | 
				
			||||||
                return {
 | 
					                return {
 | 
				
			||||||
                    updated: true
 | 
					                    updated: true,
 | 
				
			||||||
 | 
					                    sent: false,
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
@ -408,6 +432,7 @@ export class AddonModDataProvider {
 | 
				
			|||||||
                return this.addEntry(dataId, entryId, courseId, contents, groupId, fields, siteId, forceOffline)
 | 
					                return this.addEntry(dataId, entryId, courseId, contents, groupId, fields, siteId, forceOffline)
 | 
				
			||||||
                        .then((result) => {
 | 
					                        .then((result) => {
 | 
				
			||||||
                    result.updated = true;
 | 
					                    result.updated = true;
 | 
				
			||||||
 | 
					                    result.sent = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return result;
 | 
					                    return result;
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
@ -418,7 +443,11 @@ export class AddonModDataProvider {
 | 
				
			|||||||
                return storeOffline();
 | 
					                return storeOffline();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return this.editEntryOnline(entryId, contents, siteId).catch((error) => {
 | 
					            return this.editEntryOnline(entryId, contents, siteId).then((result) => {
 | 
				
			||||||
 | 
					                result.sent = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return result;
 | 
				
			||||||
 | 
					            }).catch((error) => {
 | 
				
			||||||
                if (this.utils.isWebServiceError(error)) {
 | 
					                if (this.utils.isWebServiceError(error)) {
 | 
				
			||||||
                    // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
					                    // The WebService has thrown an error, this means that responses cannot be submitted.
 | 
				
			||||||
                    return Promise.reject(error);
 | 
					                    return Promise.reject(error);
 | 
				
			||||||
 | 
				
			|||||||
@ -34,7 +34,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                <!-- Input password for protected lessons. -->
 | 
					                <!-- Input password for protected lessons. -->
 | 
				
			||||||
                <ion-card *ngIf="askPassword">
 | 
					                <ion-card *ngIf="askPassword">
 | 
				
			||||||
                    <form ion-list (ngSubmit)="submitPassword($event, passwordinput)">
 | 
					                    <form ion-list (ngSubmit)="submitPassword($event, passwordinput)" #passwordForm>
 | 
				
			||||||
                        <ion-item text-wrap>
 | 
					                        <ion-item text-wrap>
 | 
				
			||||||
                            <ion-label stacked>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>
 | 
					                            <ion-label stacked>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>
 | 
				
			||||||
                            <core-show-password item-content [name]="'password'">
 | 
					                            <core-show-password item-content [name]="'password'">
 | 
				
			||||||
 | 
				
			|||||||
@ -12,8 +12,9 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Optional, Injector, Input, ViewChild } from '@angular/core';
 | 
					import { Component, Optional, Injector, Input, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { Content, NavController } from 'ionic-angular';
 | 
					import { Content, NavController } from 'ionic-angular';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups';
 | 
					import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups';
 | 
				
			||||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
 | 
					import { CoreTimeUtilsProvider } from '@providers/utils/time';
 | 
				
			||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
 | 
					import { CoreUtilsProvider } from '@providers/utils/utils';
 | 
				
			||||||
@ -35,6 +36,7 @@ import { CoreTabsComponent } from '@components/tabs/tabs';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityComponent {
 | 
					export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityComponent {
 | 
				
			||||||
    @ViewChild(CoreTabsComponent) tabsComponent: CoreTabsComponent;
 | 
					    @ViewChild(CoreTabsComponent) tabsComponent: CoreTabsComponent;
 | 
				
			||||||
 | 
					    @ViewChild('passwordForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Input() group: number; // The group to display.
 | 
					    @Input() group: number; // The group to display.
 | 
				
			||||||
    @Input() action: string; // The "action" to display first.
 | 
					    @Input() action: string; // The "action" to display first.
 | 
				
			||||||
@ -584,6 +586,11 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
 | 
				
			|||||||
            this.loaded = true;
 | 
					            this.loaded = true;
 | 
				
			||||||
            this.refreshIcon = 'refresh';
 | 
					            this.refreshIcon = 'refresh';
 | 
				
			||||||
            this.syncIcon = 'sync';
 | 
					            this.syncIcon = 'sync';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: true,
 | 
				
			||||||
 | 
					            }, this.siteId);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@
 | 
				
			|||||||
    </ion-navbar>
 | 
					    </ion-navbar>
 | 
				
			||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content padding class="addon-mod_lesson-password-modal">
 | 
					<ion-content padding class="addon-mod_lesson-password-modal">
 | 
				
			||||||
    <form ion-list (ngSubmit)="submitPassword($event, passwordinput)">
 | 
					    <form ion-list (ngSubmit)="submitPassword($event, passwordinput)" #passwordForm>
 | 
				
			||||||
        <ion-item>
 | 
					        <ion-item>
 | 
				
			||||||
            <core-show-password item-content [name]="'password'">
 | 
					            <core-show-password item-content [name]="'password'">
 | 
				
			||||||
                <ion-label>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>
 | 
					                <ion-label>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,8 +12,10 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, ViewController } from 'ionic-angular';
 | 
					import { IonicPage, ViewController } from 'ionic-angular';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Modal that asks the password for a lesson.
 | 
					 * Modal that asks the password for a lesson.
 | 
				
			||||||
@ -24,8 +26,11 @@ import { IonicPage, ViewController } from 'ionic-angular';
 | 
				
			|||||||
    templateUrl: 'password-modal.html',
 | 
					    templateUrl: 'password-modal.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModLessonPasswordModalPage {
 | 
					export class AddonModLessonPasswordModalPage {
 | 
				
			||||||
 | 
					    @ViewChild('passwordForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(protected viewCtrl: ViewController) { }
 | 
					    constructor(protected viewCtrl: ViewController,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Send the password back.
 | 
					     * Send the password back.
 | 
				
			||||||
@ -37,6 +42,11 @@ export class AddonModLessonPasswordModalPage {
 | 
				
			|||||||
        e.preventDefault();
 | 
					        e.preventDefault();
 | 
				
			||||||
        e.stopPropagation();
 | 
					        e.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					            form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					            online: false,
 | 
				
			||||||
 | 
					        }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.viewCtrl.dismiss(password.value);
 | 
					        this.viewCtrl.dismiss(password.value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                <!-- Question page. -->
 | 
					                <!-- Question page. -->
 | 
				
			||||||
                <!-- We need to set ngIf loaded to make formGroup directive restart every time a page changes, see MOBILE-2540. -->
 | 
					                <!-- We need to set ngIf loaded to make formGroup directive restart every time a page changes, see MOBILE-2540. -->
 | 
				
			||||||
                <form *ngIf="question && loaded" ion-list [formGroup]="questionForm">
 | 
					                <form *ngIf="question && loaded" ion-list [formGroup]="questionForm" #questionFormEl>
 | 
				
			||||||
                    <ion-item-divider text-wrap *ngIf="pageContent">
 | 
					                    <ion-item-divider text-wrap *ngIf="pageContent">
 | 
				
			||||||
                        <core-format-text [component]="component" [componentId]="lesson.coursemodule" [text]="pageContent" contextLevel="module" [contextInstanceId]="lesson.coursemodule" [courseId]="courseId"></core-format-text>
 | 
					                        <core-format-text [component]="component" [componentId]="lesson.coursemodule" [text]="pageContent" contextLevel="module" [contextInstanceId]="lesson.coursemodule" [courseId]="courseId"></core-format-text>
 | 
				
			||||||
                    </ion-item-divider>
 | 
					                    </ion-item-divider>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef, ElementRef } from '@angular/core';
 | 
				
			||||||
import { FormBuilder, FormGroup } from '@angular/forms';
 | 
					import { FormBuilder, FormGroup } from '@angular/forms';
 | 
				
			||||||
import { IonicPage, NavParams, Content, PopoverController, ModalController, Modal, NavController } from 'ionic-angular';
 | 
					import { IonicPage, NavParams, Content, PopoverController, ModalController, Modal, NavController } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
@ -41,6 +41,7 @@ import { AddonModLessonHelperProvider } from '../../providers/helper';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
 | 
					export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
 | 
				
			||||||
    @ViewChild(Content) content: Content;
 | 
					    @ViewChild(Content) content: Content;
 | 
				
			||||||
 | 
					    @ViewChild('questionFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    component = AddonModLessonProvider.COMPONENT;
 | 
					    component = AddonModLessonProvider.COMPONENT;
 | 
				
			||||||
    LESSON_EOL = AddonModLessonProvider.LESSON_EOL;
 | 
					    LESSON_EOL = AddonModLessonProvider.LESSON_EOL;
 | 
				
			||||||
@ -540,15 +541,23 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
 | 
				
			|||||||
     * Process a page, sending some data.
 | 
					     * Process a page, sending some data.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param data The data to send.
 | 
					     * @param data The data to send.
 | 
				
			||||||
 | 
					     * @param formSubmitted Whether a form was submitted.
 | 
				
			||||||
     * @return Promise resolved when done.
 | 
					     * @return Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected processPage(data: any): Promise<any> {
 | 
					    protected processPage(data: any, formSubmitted?: boolean): Promise<any> {
 | 
				
			||||||
        this.loaded = false;
 | 
					        this.loaded = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const args = [this.lesson, this.courseId, this.pageData, data, this.password, this.review, this.offline, this.accessInfo,
 | 
					        const args = [this.lesson, this.courseId, this.pageData, data, this.password, this.review, this.offline, this.accessInfo,
 | 
				
			||||||
                this.jumps];
 | 
					                this.jumps];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.callFunction(this.lessonProvider.processPage.bind(this.lessonProvider), args, 6, 8).then((result) => {
 | 
					        return this.callFunction(this.lessonProvider.processPage.bind(this.lessonProvider), args, 6, 8).then((result) => {
 | 
				
			||||||
 | 
					            if (formSubmitted) {
 | 
				
			||||||
 | 
					                this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                    form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                    online: result.sent,
 | 
				
			||||||
 | 
					                }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!this.offline && !this.review && this.lessonProvider.isLessonOffline(this.lesson)) {
 | 
					            if (!this.offline && !this.review && this.lessonProvider.isLessonOffline(this.lesson)) {
 | 
				
			||||||
                // Lesson allows offline and the user changed some data in server. Update cached data.
 | 
					                // Lesson allows offline and the user changed some data in server. Update cached data.
 | 
				
			||||||
                const retake = this.accessInfo.attemptscount;
 | 
					                const retake = this.accessInfo.attemptscount;
 | 
				
			||||||
@ -637,7 +646,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        // Use getRawValue to include disabled values.
 | 
					        // Use getRawValue to include disabled values.
 | 
				
			||||||
        const data = this.lessonHelper.prepareQuestionData(this.question, this.questionForm.getRawValue());
 | 
					        const data = this.lessonHelper.prepareQuestionData(this.question, this.questionForm.getRawValue());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.processPage(data).finally(() => {
 | 
					        this.processPage(data, true).finally(() => {
 | 
				
			||||||
            this.loaded = true;
 | 
					            this.loaded = true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -3089,6 +3089,7 @@ export class AddonModLessonProvider {
 | 
				
			|||||||
                result.warnings = [];
 | 
					                result.warnings = [];
 | 
				
			||||||
                result.displaymenu = pageData.displaymenu; // Keep the same value since we can't calculate it in offline.
 | 
					                result.displaymenu = pageData.displaymenu; // Keep the same value since we can't calculate it in offline.
 | 
				
			||||||
                result.messages = this.getPageProcessMessages(lesson, accessInfo, result, review, jumps);
 | 
					                result.messages = this.getPageProcessMessages(lesson, accessInfo, result, review, jumps);
 | 
				
			||||||
 | 
					                result.sent = false;
 | 
				
			||||||
                Object.assign(result, calculatedData);
 | 
					                Object.assign(result, calculatedData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return result;
 | 
					                return result;
 | 
				
			||||||
@ -3104,6 +3105,8 @@ export class AddonModLessonProvider {
 | 
				
			|||||||
                review: review
 | 
					                review: review
 | 
				
			||||||
            }, this.sitesProvider.getCurrentSiteId());
 | 
					            }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            response.sent = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return response;
 | 
					            return response;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -45,7 +45,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Questions -->
 | 
					        <!-- Questions -->
 | 
				
			||||||
        <form name="addon-mod_quiz-player-form" *ngIf="questions && questions.length && !quizAborted && !showSummary">
 | 
					        <form name="addon-mod_quiz-player-form" *ngIf="questions && questions.length && !quizAborted && !showSummary" #quizForm>
 | 
				
			||||||
            <div *ngFor="let question of questions">
 | 
					            <div *ngFor="let question of questions">
 | 
				
			||||||
                <ion-card id="addon-mod_quiz-question-{{question.slot}}">
 | 
					                <ion-card id="addon-mod_quiz-question-{{question.slot}}">
 | 
				
			||||||
                    <!-- "Header" of the question. -->
 | 
					                    <!-- "Header" of the question. -->
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef, ViewChildren, QueryList } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef, ViewChildren, QueryList, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavParams, Content, PopoverController, ModalController, Modal, NavController } from 'ionic-angular';
 | 
					import { IonicPage, NavParams, Content, PopoverController, ModalController, Modal, NavController } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { CoreEventsProvider } from '@providers/events';
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
@ -41,6 +41,7 @@ import { Subscription } from 'rxjs';
 | 
				
			|||||||
export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
 | 
					export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
 | 
				
			||||||
    @ViewChild(Content) content: Content;
 | 
					    @ViewChild(Content) content: Content;
 | 
				
			||||||
    @ViewChildren(CoreQuestionComponent) questionComponents: QueryList<CoreQuestionComponent>;
 | 
					    @ViewChildren(CoreQuestionComponent) questionComponents: QueryList<CoreQuestionComponent>;
 | 
				
			||||||
 | 
					    @ViewChild('quizForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    quiz: any; // The quiz the attempt belongs to.
 | 
					    quiz: any; // The quiz the attempt belongs to.
 | 
				
			||||||
    attempt: any; // The attempt being attempted.
 | 
					    attempt: any; // The attempt being attempted.
 | 
				
			||||||
@ -585,6 +586,11 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
 | 
				
			|||||||
            // Answers saved, cancel auto save.
 | 
					            // Answers saved, cancel auto save.
 | 
				
			||||||
            this.autoSave.cancelAutoSave();
 | 
					            this.autoSave.cancelAutoSave();
 | 
				
			||||||
            this.autoSave.hideAutoSaveError();
 | 
					            this.autoSave.hideAutoSaveError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: !this.offline,
 | 
				
			||||||
 | 
					            }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@
 | 
				
			|||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content padding class="addon-mod_quiz-preflight-modal">
 | 
					<ion-content padding class="addon-mod_quiz-preflight-modal">
 | 
				
			||||||
    <core-loading [hideUntil]="loaded">
 | 
					    <core-loading [hideUntil]="loaded">
 | 
				
			||||||
        <form ion-list [formGroup]="preflightForm" (ngSubmit)="sendData($event)">
 | 
					        <form ion-list [formGroup]="preflightForm" (ngSubmit)="sendData($event)" #preflightFormEl>
 | 
				
			||||||
            <!-- Access rules. -->
 | 
					            <!-- Access rules. -->
 | 
				
			||||||
            <ng-container *ngFor="let data of accessRulesData; let last = last">
 | 
					            <ng-container *ngFor="let data of accessRulesData; let last = last">
 | 
				
			||||||
                <core-dynamic-component [component]="data.component" [data]="data.data">
 | 
					                <core-dynamic-component [component]="data.component" [data]="data.data">
 | 
				
			||||||
 | 
				
			|||||||
@ -12,10 +12,11 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, Injector, ViewChild } from '@angular/core';
 | 
					import { Component, OnInit, Injector, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, ViewController, NavParams, Content } from 'ionic-angular';
 | 
					import { IonicPage, ViewController, NavParams, Content } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { FormBuilder, FormGroup } from '@angular/forms';
 | 
					import { FormBuilder, FormGroup } from '@angular/forms';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
import { CoreSitesProvider } from '@providers/sites';
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate';
 | 
					import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate';
 | 
				
			||||||
@ -31,6 +32,7 @@ import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-del
 | 
				
			|||||||
export class AddonModQuizPreflightModalPage implements OnInit {
 | 
					export class AddonModQuizPreflightModalPage implements OnInit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChild(Content) content: Content;
 | 
					    @ViewChild(Content) content: Content;
 | 
				
			||||||
 | 
					    @ViewChild('preflightFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    preflightForm: FormGroup;
 | 
					    preflightForm: FormGroup;
 | 
				
			||||||
    title: string;
 | 
					    title: string;
 | 
				
			||||||
@ -43,9 +45,15 @@ export class AddonModQuizPreflightModalPage implements OnInit {
 | 
				
			|||||||
    protected siteId: string;
 | 
					    protected siteId: string;
 | 
				
			||||||
    protected rules: string[];
 | 
					    protected rules: string[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(params: NavParams, fb: FormBuilder, translate: TranslateService, sitesProvider: CoreSitesProvider,
 | 
					    constructor(params: NavParams,
 | 
				
			||||||
            protected viewCtrl: ViewController, protected accessRuleDelegate: AddonModQuizAccessRuleDelegate,
 | 
					            fb: FormBuilder,
 | 
				
			||||||
            protected injector: Injector, protected domUtils: CoreDomUtilsProvider) {
 | 
					            translate: TranslateService,
 | 
				
			||||||
 | 
					            sitesProvider: CoreSitesProvider,
 | 
				
			||||||
 | 
					            protected viewCtrl: ViewController,
 | 
				
			||||||
 | 
					            protected accessRuleDelegate: AddonModQuizAccessRuleDelegate,
 | 
				
			||||||
 | 
					            protected injector: Injector,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.title = params.get('title') || translate.instant('addon.mod_quiz.startattempt');
 | 
					        this.title = params.get('title') || translate.instant('addon.mod_quiz.startattempt');
 | 
				
			||||||
        this.quiz = params.get('quiz');
 | 
					        this.quiz = params.get('quiz');
 | 
				
			||||||
@ -112,6 +120,11 @@ export class AddonModQuizPreflightModalPage implements OnInit {
 | 
				
			|||||||
                this.domUtils.showErrorModal('core.errorinvalidform', true);
 | 
					                this.domUtils.showErrorModal('core.errorinvalidform', true);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: false,
 | 
				
			||||||
 | 
					            }, this.siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.viewCtrl.dismiss(this.preflightForm.value);
 | 
					            this.viewCtrl.dismiss(this.preflightForm.value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@
 | 
				
			|||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <core-loading [hideUntil]="loaded">
 | 
					    <core-loading [hideUntil]="loaded">
 | 
				
			||||||
        <form ion-list [formGroup]="pageForm">
 | 
					        <form ion-list [formGroup]="pageForm" #editPageForm>
 | 
				
			||||||
            <ion-item text-wrap *ngIf="canEditTitle" class="item-title">
 | 
					            <ion-item text-wrap *ngIf="canEditTitle" class="item-title">
 | 
				
			||||||
                <ion-input name="title" type="text" [placeholder]="'addon.mod_wiki.newpagetitle' | translate" [formControlName]="'title'"></ion-input>
 | 
					                <ion-input name="title" type="text" [placeholder]="'addon.mod_wiki.newpagetitle' | translate" [formControlName]="'title'"></ion-input>
 | 
				
			||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { FormControl, FormGroup, FormBuilder } from '@angular/forms';
 | 
					import { FormControl, FormGroup, FormBuilder } from '@angular/forms';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
@ -37,6 +37,8 @@ import { AddonModWikiSyncProvider, AddonModWikiSyncSubwikiResult } from '../../p
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModWikiEditPage implements OnInit, OnDestroy {
 | 
					export class AddonModWikiEditPage implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('editPageForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    title: string; // Title to display.
 | 
					    title: string; // Title to display.
 | 
				
			||||||
    pageForm: FormGroup; // The form group.
 | 
					    pageForm: FormGroup; // The form group.
 | 
				
			||||||
    contentControl: FormControl; // The FormControl for the page content.
 | 
					    contentControl: FormControl; // The FormControl for the page content.
 | 
				
			||||||
@ -423,6 +425,12 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        if (this.editing) {
 | 
					        if (this.editing) {
 | 
				
			||||||
            // Edit existing page.
 | 
					            // Edit existing page.
 | 
				
			||||||
            promise = this.wikiProvider.editPage(this.pageId, text, this.section).then(() => {
 | 
					            promise = this.wikiProvider.editPage(this.pageId, text, this.section).then(() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                    form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                    online: true,
 | 
				
			||||||
 | 
					                }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Invalidate page since it changed.
 | 
					                // Invalidate page since it changed.
 | 
				
			||||||
                return this.wikiProvider.invalidatePage(this.pageId).then(() => {
 | 
					                return this.wikiProvider.invalidatePage(this.pageId).then(() => {
 | 
				
			||||||
                    return this.gotoPage(title);
 | 
					                    return this.gotoPage(title);
 | 
				
			||||||
@ -456,6 +464,12 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy {
 | 
				
			|||||||
                let wikiId = this.wikiId || (this.module && this.module.instance);
 | 
					                let wikiId = this.wikiId || (this.module && this.module.instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return this.wikiProvider.newPage(title, text, this.subwikiId, wikiId, this.userId, this.groupId).then((id) => {
 | 
					                return this.wikiProvider.newPage(title, text, this.subwikiId, wikiId, this.userId, this.groupId).then((id) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                        form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                        online: id > 0,
 | 
				
			||||||
 | 
					                    }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (id > 0) {
 | 
					                    if (id > 0) {
 | 
				
			||||||
                        // Page was created, get its data and go to the page.
 | 
					                        // Page was created, get its data and go to the page.
 | 
				
			||||||
                        this.pageId = id;
 | 
					                        this.pageId = id;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
<h3 padding>{{ 'addon.mod_workshop.assessmentform' | translate }}</h3>
 | 
					<h3 padding>{{ 'addon.mod_workshop.assessmentform' | translate }}</h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<form name="mma-mod_workshop-assessment-form">
 | 
					<form name="mma-mod_workshop-assessment-form" #assessmentForm>
 | 
				
			||||||
    <core-loading [hideUntil]="assessmentStrategyLoaded">
 | 
					    <core-loading [hideUntil]="assessmentStrategyLoaded">
 | 
				
			||||||
        <ng-container *ngIf="componentClass && assessmentStrategyLoaded">
 | 
					        <ng-container *ngIf="componentClass && assessmentStrategyLoaded">
 | 
				
			||||||
            <core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
 | 
					            <core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Input, OnInit, Injector } from '@angular/core';
 | 
					import { Component, Input, OnInit, Injector, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { FormControl } from '@angular/forms';
 | 
					import { FormControl } from '@angular/forms';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { CoreSyncProvider } from '@providers/sync';
 | 
					import { CoreSyncProvider } from '@providers/sync';
 | 
				
			||||||
@ -44,6 +44,8 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit {
 | 
				
			|||||||
    @Input() strategy: string;
 | 
					    @Input() strategy: string;
 | 
				
			||||||
    @Input() edit?: boolean;
 | 
					    @Input() edit?: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('assessmentForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentClass: any;
 | 
					    componentClass: any;
 | 
				
			||||||
    data = {
 | 
					    data = {
 | 
				
			||||||
        workshopId: 0,
 | 
					        workshopId: 0,
 | 
				
			||||||
@ -292,7 +294,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit {
 | 
				
			|||||||
                // Save assessment in offline.
 | 
					                // Save assessment in offline.
 | 
				
			||||||
                return this.workshopOffline.saveAssessment(this.workshop.id, this.assessmentId, this.workshop.course,
 | 
					                return this.workshopOffline.saveAssessment(this.workshop.id, this.assessmentId, this.workshop.course,
 | 
				
			||||||
                        assessmentData).then(() => {
 | 
					                        assessmentData).then(() => {
 | 
				
			||||||
                    // Don't return anything.
 | 
					                    return false;
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -301,6 +303,12 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit {
 | 
				
			|||||||
            return this.workshopProvider.updateAssessment(this.workshop.id, this.assessmentId, this.workshop.course,
 | 
					            return this.workshopProvider.updateAssessment(this.workshop.id, this.assessmentId, this.workshop.course,
 | 
				
			||||||
                assessmentData, false, allowOffline);
 | 
					                assessmentData, false, allowOffline);
 | 
				
			||||||
        }).then((grade) => {
 | 
					        }).then((grade) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: !!grade,
 | 
				
			||||||
 | 
					            }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const promises = [];
 | 
					            const promises = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If sent to the server, invalidate and clean.
 | 
					            // If sent to the server, invalidate and clean.
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <addon-mod-workshop-assessment-strategy *ngIf="assessment && assessmentId && showGrade(assessment.grade) && workshop && access" [workshop]="workshop" [access]="access" [assessmentId]="assessmentId" [userId]="profile && profile.id" [strategy]="strategy"></addon-mod-workshop-assessment-strategy>
 | 
					        <addon-mod-workshop-assessment-strategy *ngIf="assessment && assessmentId && showGrade(assessment.grade) && workshop && access" [workshop]="workshop" [access]="access" [assessmentId]="assessmentId" [userId]="profile && profile.id" [strategy]="strategy"></addon-mod-workshop-assessment-strategy>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <form ion-list [formGroup]="evaluateForm" *ngIf="evaluating">
 | 
					        <form ion-list [formGroup]="evaluateForm" *ngIf="evaluating" #evaluateFormEl>
 | 
				
			||||||
            <ion-item text-wrap>
 | 
					            <ion-item text-wrap>
 | 
				
			||||||
                <h2>{{ 'addon.mod_workshop.assessmentsettings' | translate }}</h2>
 | 
					                <h2>{{ 'addon.mod_workshop.assessmentsettings' | translate }}</h2>
 | 
				
			||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
					import { IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
				
			||||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
 | 
					import { FormGroup, FormBuilder, Validators } from '@angular/forms';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
@ -39,6 +39,8 @@ import { AddonModWorkshopSyncProvider } from '../../providers/sync';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy {
 | 
					export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('evaluateFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assessment: any;
 | 
					    assessment: any;
 | 
				
			||||||
    submission: any;
 | 
					    submission: any;
 | 
				
			||||||
    profile: any;
 | 
					    profile: any;
 | 
				
			||||||
@ -340,7 +342,13 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Try to send it to server.
 | 
					        // Try to send it to server.
 | 
				
			||||||
        return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text,
 | 
					        return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text,
 | 
				
			||||||
                inputData.weight, inputData.grade).then(() => {
 | 
					                inputData.weight, inputData.grade).then((result) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: !!result,
 | 
				
			||||||
 | 
					            }, this.siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const data = {
 | 
					            const data = {
 | 
				
			||||||
                workshopId: this.workshopId,
 | 
					                workshopId: this.workshopId,
 | 
				
			||||||
                assessmentId: this.assessmentId,
 | 
					                assessmentId: this.assessmentId,
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@
 | 
				
			|||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <core-loading [hideUntil]="loaded">
 | 
					    <core-loading [hideUntil]="loaded">
 | 
				
			||||||
        <form ion-list [formGroup]="editForm" *ngIf="workshop">
 | 
					        <form ion-list [formGroup]="editForm" *ngIf="workshop" #editFormEl>
 | 
				
			||||||
            <ion-item text-wrap>
 | 
					            <ion-item text-wrap>
 | 
				
			||||||
                <ion-label stacked core-mark-required="true">{{ 'addon.mod_workshop.submissiontitle' | translate }}</ion-label>
 | 
					                <ion-label stacked core-mark-required="true">{{ 'addon.mod_workshop.submissiontitle' | translate }}</ion-label>
 | 
				
			||||||
                <ion-input name="title" type="text" [placeholder]="'addon.mod_workshop.submissiontitle' | translate" formControlName="title"></ion-input>
 | 
					                <ion-input name="title" type="text" [placeholder]="'addon.mod_workshop.submissiontitle' | translate" formControlName="title"></ion-input>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
					import { IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
				
			||||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
 | 
					import { FormGroup, FormBuilder, Validators } from '@angular/forms';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
@ -37,6 +37,8 @@ import { AddonModWorkshopOfflineProvider } from '../../providers/offline';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy {
 | 
					export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('editFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    module: any;
 | 
					    module: any;
 | 
				
			||||||
    courseId: number;
 | 
					    courseId: number;
 | 
				
			||||||
    access: any;
 | 
					    access: any;
 | 
				
			||||||
@ -352,7 +354,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy {
 | 
				
			|||||||
                    // Save submission in offline.
 | 
					                    // Save submission in offline.
 | 
				
			||||||
                    return this.workshopOffline.saveSubmission(this.workshopId, this.courseId, inputData.title,
 | 
					                    return this.workshopOffline.saveSubmission(this.workshopId, this.courseId, inputData.title,
 | 
				
			||||||
                            inputData.content, attachmentsId, submissionId, 'update').then(() => {
 | 
					                            inputData.content, attachmentsId, submissionId, 'update').then(() => {
 | 
				
			||||||
                        // Don't return anything.
 | 
					                        return false;
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -366,7 +368,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy {
 | 
				
			|||||||
                // Save submission in offline.
 | 
					                // Save submission in offline.
 | 
				
			||||||
                return this.workshopOffline.saveSubmission(this.workshopId, this.courseId, inputData.title, inputData.content,
 | 
					                return this.workshopOffline.saveSubmission(this.workshopId, this.courseId, inputData.title, inputData.content,
 | 
				
			||||||
                        attachmentsId, submissionId, 'add').then(() => {
 | 
					                        attachmentsId, submissionId, 'add').then(() => {
 | 
				
			||||||
                    // Don't return anything.
 | 
					                    return false;
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -375,6 +377,12 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy {
 | 
				
			|||||||
            return this.workshopProvider.addSubmission(this.workshopId, this.courseId, inputData.title, inputData.content,
 | 
					            return this.workshopProvider.addSubmission(this.workshopId, this.courseId, inputData.title, inputData.content,
 | 
				
			||||||
                attachmentsId, undefined, submissionId, allowOffline);
 | 
					                attachmentsId, undefined, submissionId, allowOffline);
 | 
				
			||||||
        }).then((newSubmissionId) => {
 | 
					        }).then((newSubmissionId) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: !!newSubmissionId,
 | 
				
			||||||
 | 
					            }, this.siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const data = {
 | 
					            const data = {
 | 
				
			||||||
                workshopId: this.workshopId,
 | 
					                workshopId: this.workshopId,
 | 
				
			||||||
                cmId: this.module.cmid
 | 
					                cmId: this.module.cmid
 | 
				
			||||||
 | 
				
			|||||||
@ -65,7 +65,7 @@
 | 
				
			|||||||
            <addon-mod-workshop-assessment *ngFor="let reviewer of submissionInfo.reviewerof" [assessment]="reviewer" [courseId]="courseId" summary="true" [workshop]="workshop" [access]="access"></addon-mod-workshop-assessment>
 | 
					            <addon-mod-workshop-assessment *ngFor="let reviewer of submissionInfo.reviewerof" [assessment]="reviewer" [courseId]="courseId" summary="true" [workshop]="workshop" [access]="access"></addon-mod-workshop-assessment>
 | 
				
			||||||
        </ion-list>
 | 
					        </ion-list>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <form ion-list [formGroup]="feedbackForm" *ngIf="canAddFeedback">
 | 
					        <form ion-list [formGroup]="feedbackForm" *ngIf="canAddFeedback" #feedbackFormEl>
 | 
				
			||||||
            <ion-item text-wrap>
 | 
					            <ion-item text-wrap>
 | 
				
			||||||
                <h2>{{ 'addon.mod_workshop.feedbackauthor' | translate }}</h2>
 | 
					                <h2>{{ 'addon.mod_workshop.feedbackauthor' | translate }}</h2>
 | 
				
			||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy, Optional, ViewChild } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, Optional, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { Content, IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
					import { Content, IonicPage, NavParams, NavController } from 'ionic-angular';
 | 
				
			||||||
import { FormGroup, FormBuilder } from '@angular/forms';
 | 
					import { FormGroup, FormBuilder } from '@angular/forms';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
@ -41,6 +41,7 @@ import { AddonModWorkshopSyncProvider } from '../../providers/sync';
 | 
				
			|||||||
export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy {
 | 
					export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChild(AddonModWorkshopAssessmentStrategyComponent) assessmentStrategy: AddonModWorkshopAssessmentStrategyComponent;
 | 
					    @ViewChild(AddonModWorkshopAssessmentStrategyComponent) assessmentStrategy: AddonModWorkshopAssessmentStrategyComponent;
 | 
				
			||||||
 | 
					    @ViewChild('feedbackFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    module: any;
 | 
					    module: any;
 | 
				
			||||||
    workshop: any;
 | 
					    workshop: any;
 | 
				
			||||||
@ -444,7 +445,13 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Try to send it to server.
 | 
					        // Try to send it to server.
 | 
				
			||||||
        return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text,
 | 
					        return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text,
 | 
				
			||||||
                inputData.published, inputData.grade).then(() => {
 | 
					                inputData.published, inputData.grade).then((result) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: !!result,
 | 
				
			||||||
 | 
					            }, this.siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const data = {
 | 
					            const data = {
 | 
				
			||||||
                workshopId: this.workshopId,
 | 
					                workshopId: this.workshopId,
 | 
				
			||||||
                cmId: this.module.cmid,
 | 
					                cmId: this.module.cmid,
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@
 | 
				
			|||||||
    </ion-navbar>
 | 
					    </ion-navbar>
 | 
				
			||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <form name="itemEdit" (ngSubmit)="addNote($event)">
 | 
					    <form name="itemEdit" (ngSubmit)="addNote($event)" #itemEdit>
 | 
				
			||||||
        <ion-item>
 | 
					        <ion-item>
 | 
				
			||||||
            <ion-label>{{ 'addon.notes.publishstate' | translate }}</ion-label>
 | 
					            <ion-label>{{ 'addon.notes.publishstate' | translate }}</ion-label>
 | 
				
			||||||
            <ion-select [(ngModel)]="type" name="publishState" interface="popover">
 | 
					            <ion-select [(ngModel)]="type" name="publishState" interface="popover">
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,11 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, ViewController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, ViewController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { AddonNotesProvider } from '../../providers/notes';
 | 
					import { AddonNotesProvider } from '../../providers/notes';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,14 +29,22 @@ import { AddonNotesProvider } from '../../providers/notes';
 | 
				
			|||||||
    templateUrl: 'add.html',
 | 
					    templateUrl: 'add.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class AddonNotesAddPage {
 | 
					export class AddonNotesAddPage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('itemEdit') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    userId: number;
 | 
					    userId: number;
 | 
				
			||||||
    courseId: number;
 | 
					    courseId: number;
 | 
				
			||||||
    type = 'personal';
 | 
					    type = 'personal';
 | 
				
			||||||
    text = '';
 | 
					    text = '';
 | 
				
			||||||
    processing = false;
 | 
					    processing = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(params: NavParams, private viewCtrl: ViewController, private appProvider: CoreAppProvider,
 | 
					    constructor(params: NavParams,
 | 
				
			||||||
            private domUtils: CoreDomUtilsProvider, private notesProvider: AddonNotesProvider) {
 | 
					            protected viewCtrl: ViewController,
 | 
				
			||||||
 | 
					            protected appProvider: CoreAppProvider,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected notesProvider: AddonNotesProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) {
 | 
				
			||||||
        this.userId = params.get('userId');
 | 
					        this.userId = params.get('userId');
 | 
				
			||||||
        this.courseId = params.get('courseId');
 | 
					        this.courseId = params.get('courseId');
 | 
				
			||||||
        this.type = params.get('type') || 'personal';
 | 
					        this.type = params.get('type') || 'personal';
 | 
				
			||||||
@ -54,6 +64,12 @@ export class AddonNotesAddPage {
 | 
				
			|||||||
        // Freeze the add note button.
 | 
					        // Freeze the add note button.
 | 
				
			||||||
        this.processing = true;
 | 
					        this.processing = true;
 | 
				
			||||||
        this.notesProvider.addNote(this.userId, this.courseId, this.type, this.text).then((sent) => {
 | 
					        this.notesProvider.addNote(this.userId, this.courseId, this.type, this.text).then((sent) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: sent,
 | 
				
			||||||
 | 
					            }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.viewCtrl.dismiss({type: this.type, sent: true}).finally(() => {
 | 
					            this.viewCtrl.dismiss({type: this.type, sent: true}).finally(() => {
 | 
				
			||||||
                this.domUtils.showToast(sent ? 'addon.notes.eventnotecreated' : 'core.datastoredoffline', true, 3000);
 | 
					                this.domUtils.showToast(sent ? 'addon.notes.eventnotecreated' : 'core.datastoredoffline', true, 3000);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
<form (ngSubmit)="changeName(newFileName, $event)">
 | 
					<form (ngSubmit)="changeName(newFileName, $event)" #nameForm>
 | 
				
			||||||
    <a ion-item text-wrap stacked class="item-media" [class.item-input]="editMode" (click)="fileClicked($event)" detail-none>
 | 
					    <a ion-item text-wrap stacked class="item-media" [class.item-input]="editMode" (click)="fileClicked($event)" detail-none>
 | 
				
			||||||
        <img [src]="fileIcon" alt="{{fileExtension}}" role="presentation" item-start />
 | 
					        <img [src]="fileIcon" alt="{{fileExtension}}" role="presentation" item-start />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -12,8 +12,10 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core';
 | 
					import { Component, Input, Output, OnInit, EventEmitter, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
import { CoreFileProvider } from '@providers/file';
 | 
					import { CoreFileProvider } from '@providers/file';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
 | 
					import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
 | 
				
			||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
 | 
					import { CoreTextUtilsProvider } from '@providers/utils/text';
 | 
				
			||||||
@ -38,6 +40,8 @@ export class CoreLocalFileComponent implements OnInit {
 | 
				
			|||||||
    @Output() onRename?: EventEmitter<any>; // Will notify when the file is renamed. Receives the FileEntry as the param.
 | 
					    @Output() onRename?: EventEmitter<any>; // Will notify when the file is renamed. Receives the FileEntry as the param.
 | 
				
			||||||
    @Output() onClick?: EventEmitter<void>; // Will notify when the file is clicked. Only if overrideClick is true.
 | 
					    @Output() onClick?: EventEmitter<void>; // Will notify when the file is clicked. Only if overrideClick is true.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('nameForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fileName: string;
 | 
					    fileName: string;
 | 
				
			||||||
    fileIcon: string;
 | 
					    fileIcon: string;
 | 
				
			||||||
    fileExtension: string;
 | 
					    fileExtension: string;
 | 
				
			||||||
@ -47,12 +51,14 @@ export class CoreLocalFileComponent implements OnInit {
 | 
				
			|||||||
    editMode: boolean;
 | 
					    editMode: boolean;
 | 
				
			||||||
    relativePath: string;
 | 
					    relativePath: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(private mimeUtils: CoreMimetypeUtilsProvider,
 | 
					    constructor(protected mimeUtils: CoreMimetypeUtilsProvider,
 | 
				
			||||||
            private utils: CoreUtilsProvider,
 | 
					            protected utils: CoreUtilsProvider,
 | 
				
			||||||
            private textUtils: CoreTextUtilsProvider,
 | 
					            protected textUtils: CoreTextUtilsProvider,
 | 
				
			||||||
            private fileProvider: CoreFileProvider,
 | 
					            protected fileProvider: CoreFileProvider,
 | 
				
			||||||
            private domUtils: CoreDomUtilsProvider,
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
            private timeUtils: CoreTimeUtilsProvider) {
 | 
					            protected timeUtils: CoreTimeUtilsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider) {
 | 
				
			||||||
        this.onDelete = new EventEmitter();
 | 
					        this.onDelete = new EventEmitter();
 | 
				
			||||||
        this.onRename = new EventEmitter();
 | 
					        this.onRename = new EventEmitter();
 | 
				
			||||||
        this.onClick = new EventEmitter();
 | 
					        this.onClick = new EventEmitter();
 | 
				
			||||||
@ -152,6 +158,12 @@ export class CoreLocalFileComponent implements OnInit {
 | 
				
			|||||||
        }).catch(() => {
 | 
					        }).catch(() => {
 | 
				
			||||||
            // File doesn't exist, move it.
 | 
					            // File doesn't exist, move it.
 | 
				
			||||||
            return this.fileProvider.moveFile(this.relativePath, newPath).then((fileEntry) => {
 | 
					            return this.fileProvider.moveFile(this.relativePath, newPath).then((fileEntry) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                    form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                    online: false,
 | 
				
			||||||
 | 
					                }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this.editMode = false;
 | 
					                this.editMode = false;
 | 
				
			||||||
                this.file = fileEntry;
 | 
					                this.file = fileEntry;
 | 
				
			||||||
                this.loadFileBasicData();
 | 
					                this.loadFileBasicData();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										100
									
								
								src/components/search-box/search-box.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/components/search-box/search-box.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					// (C) Copyright 2015 Moodle Pty Ltd.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// 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, Input, Output, EventEmitter, OnInit, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
 | 
					import { CoreUtilsProvider } from '@providers/utils/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component to display a "search box".
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @description
 | 
				
			||||||
 | 
					 * This component will display a standalone search box with its search button in order to have a better UX.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Example usage:
 | 
				
			||||||
 | 
					 * <core-search-box (onSubmit)="search($event)" [placeholder]="'core.courses.search' | translate"
 | 
				
			||||||
 | 
					 *     [searchLabel]="'core.courses.search' | translate" autoFocus="true"></core-search-box>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					    selector: 'core-search-box',
 | 
				
			||||||
 | 
					    templateUrl: 'core-search-box.html'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class CoreSearchBoxComponent implements OnInit {
 | 
				
			||||||
 | 
					    @Input() searchLabel?: string; // Label to be used on action button.
 | 
				
			||||||
 | 
					    @Input() placeholder?: string; // Placeholder text for search text input.
 | 
				
			||||||
 | 
					    @Input() autocorrect = 'on'; // Enables/disable Autocorrection on search text input.
 | 
				
			||||||
 | 
					    @Input() spellcheck?: string | boolean = true; // Enables/disable Spellchecker on search text input.
 | 
				
			||||||
 | 
					    @Input() autoFocus?: string | boolean; // Enables/disable Autofocus when entering view.
 | 
				
			||||||
 | 
					    @Input() lengthCheck = 3; // Check value length before submit. If 0, any string will be submitted.
 | 
				
			||||||
 | 
					    @Input() showClear = true; // Show/hide clear button.
 | 
				
			||||||
 | 
					    @Input() disabled = false; // Disables the input text.
 | 
				
			||||||
 | 
					    @Input() initialSearch: string; // Initial search text.
 | 
				
			||||||
 | 
					    @Output() onSubmit: EventEmitter<string>; // Send data when submitting the search form.
 | 
				
			||||||
 | 
					    @Output() onClear: EventEmitter<void>; // Send event when clearing the search form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('searchForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    searched = false;
 | 
				
			||||||
 | 
					    searchText = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(protected translate: TranslateService,
 | 
				
			||||||
 | 
					            protected utils: CoreUtilsProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) {
 | 
				
			||||||
 | 
					        this.onSubmit = new EventEmitter<string>();
 | 
				
			||||||
 | 
					        this.onClear = new EventEmitter<void>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ngOnInit(): void {
 | 
				
			||||||
 | 
					        this.searchLabel = this.searchLabel || this.translate.instant('core.search');
 | 
				
			||||||
 | 
					        this.placeholder = this.placeholder || this.translate.instant('core.search');
 | 
				
			||||||
 | 
					        this.spellcheck = this.utils.isTrueOrOne(this.spellcheck);
 | 
				
			||||||
 | 
					        this.showClear = this.utils.isTrueOrOne(this.showClear);
 | 
				
			||||||
 | 
					        this.searchText = this.initialSearch || '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Form submitted.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param e Event.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    submitForm(e: Event): void {
 | 
				
			||||||
 | 
					        e.preventDefault();
 | 
				
			||||||
 | 
					        e.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.searchText.length < this.lengthCheck) {
 | 
				
			||||||
 | 
					            // The view should handle this case, but we check it here too just in case.
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					            form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					            online: false,
 | 
				
			||||||
 | 
					        }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.searched = true;
 | 
				
			||||||
 | 
					        this.onSubmit.emit(this.searchText);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Form submitted.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    clearForm(): void {
 | 
				
			||||||
 | 
					        this.searched = false;
 | 
				
			||||||
 | 
					        this.searchText = '';
 | 
				
			||||||
 | 
					        this.onClear.emit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
<form>
 | 
					<form #messageForm>
 | 
				
			||||||
    <textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows [(ngModel)]="message" name="message" (onResize)="textareaResized()" (keydown.enter)="enterClicked($event)" (keydown.control.enter)="enterClicked($event, 'control')" (keydown.meta.enter)="enterClicked($event, 'meta')" aria-multiline="true"></textarea>
 | 
					    <textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows [(ngModel)]="message" name="message" (onResize)="textareaResized()" (keydown.enter)="enterClicked($event)" (keydown.control.enter)="enterClicked($event, 'control')" (keydown.meta.enter)="enterClicked($event, 'meta')" aria-multiline="true"></textarea>
 | 
				
			||||||
    <ion-buttons end>
 | 
					    <ion-buttons end>
 | 
				
			||||||
        <button ion-button icon-only clear="true" type="submit" [disabled]="!message || sendDisabled" [attr.aria-label]="'core.send' | translate" [core-suppress-events] (onClick)="submitForm($event)">
 | 
					        <button ion-button icon-only clear="true" type="submit" [disabled]="!message || sendDisabled" [attr.aria-label]="'core.send' | translate" [core-suppress-events] (onClick)="submitForm($event)">
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
 | 
					import { Component, Input, Output, EventEmitter, OnInit, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
import { CoreConfigProvider } from '@providers/config';
 | 
					import { CoreConfigProvider } from '@providers/config';
 | 
				
			||||||
import { CoreEventsProvider } from '@providers/events';
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
@ -43,10 +43,16 @@ export class CoreSendMessageFormComponent implements OnInit {
 | 
				
			|||||||
    @Output() onSubmit: EventEmitter<string>; // Send data when submitting the message form.
 | 
					    @Output() onSubmit: EventEmitter<string>; // Send data when submitting the message form.
 | 
				
			||||||
    @Output() onResize: EventEmitter<void>; // Emit when resizing the textarea.
 | 
					    @Output() onResize: EventEmitter<void>; // Emit when resizing the textarea.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('messageForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected sendOnEnter: boolean;
 | 
					    protected sendOnEnter: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider, configProvider: CoreConfigProvider,
 | 
					    constructor(protected utils: CoreUtilsProvider,
 | 
				
			||||||
            eventsProvider: CoreEventsProvider, sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider) {
 | 
					            protected textUtils: CoreTextUtilsProvider,
 | 
				
			||||||
 | 
					            configProvider: CoreConfigProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider,
 | 
				
			||||||
 | 
					            protected appProvider: CoreAppProvider) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.onSubmit = new EventEmitter();
 | 
					        this.onSubmit = new EventEmitter();
 | 
				
			||||||
        this.onResize = new EventEmitter();
 | 
					        this.onResize = new EventEmitter();
 | 
				
			||||||
@ -82,6 +88,11 @@ export class CoreSendMessageFormComponent implements OnInit {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        this.message = ''; // Reset the form.
 | 
					        this.message = ''; // Reset the form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					            form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					            online: false,
 | 
				
			||||||
 | 
					        }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        value = this.textUtils.replaceNewLines(value, '<br>');
 | 
					        value = this.textUtils.replaceNewLines(value, '<br>');
 | 
				
			||||||
        this.onSubmit.emit(value);
 | 
					        this.onSubmit.emit(value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@
 | 
				
			|||||||
    </ion-navbar>
 | 
					    </ion-navbar>
 | 
				
			||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <form name="itemEdit" (ngSubmit)="addComment($event)">
 | 
					    <form name="itemEdit" (ngSubmit)="addComment($event)" #commentForm>
 | 
				
			||||||
        <ion-item>
 | 
					        <ion-item>
 | 
				
			||||||
            <ion-textarea placeholder="{{ 'core.comments.addcomment' | translate }}" rows="5" [(ngModel)]="content" name="content" required="required"></ion-textarea>
 | 
					            <ion-textarea placeholder="{{ 'core.comments.addcomment' | translate }}" rows="5" [(ngModel)]="content" name="content" required="required"></ion-textarea>
 | 
				
			||||||
        </ion-item>
 | 
					        </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,11 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, ViewController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, ViewController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreCommentsProvider } from '../../providers/comments';
 | 
					import { CoreCommentsProvider } from '../../providers/comments';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,6 +29,8 @@ import { CoreCommentsProvider } from '../../providers/comments';
 | 
				
			|||||||
    templateUrl: 'add.html',
 | 
					    templateUrl: 'add.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class CoreCommentsAddPage {
 | 
					export class CoreCommentsAddPage {
 | 
				
			||||||
 | 
					    @ViewChild('commentForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected contextLevel: string;
 | 
					    protected contextLevel: string;
 | 
				
			||||||
    protected instanceId: number;
 | 
					    protected instanceId: number;
 | 
				
			||||||
    protected componentName: string;
 | 
					    protected componentName: string;
 | 
				
			||||||
@ -36,8 +40,13 @@ export class CoreCommentsAddPage {
 | 
				
			|||||||
    content = '';
 | 
					    content = '';
 | 
				
			||||||
    processing = false;
 | 
					    processing = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(params: NavParams, private viewCtrl: ViewController, private appProvider: CoreAppProvider,
 | 
					    constructor(params: NavParams,
 | 
				
			||||||
            private domUtils: CoreDomUtilsProvider, private commentsProvider: CoreCommentsProvider) {
 | 
					            protected viewCtrl: ViewController,
 | 
				
			||||||
 | 
					            protected appProvider: CoreAppProvider,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected commentsProvider: CoreCommentsProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) {
 | 
				
			||||||
        this.contextLevel = params.get('contextLevel');
 | 
					        this.contextLevel = params.get('contextLevel');
 | 
				
			||||||
        this.instanceId = params.get('instanceId');
 | 
					        this.instanceId = params.get('instanceId');
 | 
				
			||||||
        this.componentName = params.get('componentName');
 | 
					        this.componentName = params.get('componentName');
 | 
				
			||||||
@ -61,6 +70,12 @@ export class CoreCommentsAddPage {
 | 
				
			|||||||
        this.processing = true;
 | 
					        this.processing = true;
 | 
				
			||||||
        this.commentsProvider.addComment(this.content, this.contextLevel, this.instanceId, this.componentName, this.itemId,
 | 
					        this.commentsProvider.addComment(this.content, this.contextLevel, this.instanceId, this.componentName, this.itemId,
 | 
				
			||||||
                this.area).then((commentsResponse) => {
 | 
					                this.area).then((commentsResponse) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: !!commentsResponse,
 | 
				
			||||||
 | 
					            }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.viewCtrl.dismiss({comments: commentsResponse}).finally(() => {
 | 
					            this.viewCtrl.dismiss({comments: commentsResponse}).finally(() => {
 | 
				
			||||||
                this.domUtils.showToast(commentsResponse ? 'core.comments.eventcommentcreated' : 'core.datastoredoffline', true,
 | 
					                this.domUtils.showToast(commentsResponse ? 'core.comments.eventcommentcreated' : 'core.datastoredoffline', true,
 | 
				
			||||||
                    3000);
 | 
					                    3000);
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,7 @@ export class CoreCommentsProvider {
 | 
				
			|||||||
        // Convenience function to store a comment to be synchronized later.
 | 
					        // Convenience function to store a comment to be synchronized later.
 | 
				
			||||||
        const storeOffline = (): Promise<any> => {
 | 
					        const storeOffline = (): Promise<any> => {
 | 
				
			||||||
            return this.commentsOffline.saveComment(content, contextLevel, instanceId, component, itemId, area, siteId).then(() => {
 | 
					            return this.commentsOffline.saveComment(content, contextLevel, instanceId, component, itemId, area, siteId).then(() => {
 | 
				
			||||||
                return Promise.resolve(false);
 | 
					                return false;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@
 | 
				
			|||||||
    </ion-navbar>
 | 
					    </ion-navbar>
 | 
				
			||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <form ion-list #f="ngForm" (ngSubmit)="submitPassword($event, f.value.password)">
 | 
					    <form ion-list #f="ngForm" (ngSubmit)="submitPassword($event, f.value.password)" #enrolPasswordForm>
 | 
				
			||||||
        <ion-item>
 | 
					        <ion-item>
 | 
				
			||||||
            <core-show-password item-content [name]="'password'">
 | 
					            <core-show-password item-content [name]="'password'">
 | 
				
			||||||
                <ion-input text-wrap class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.courses.password' | translate }}" ngModel [core-auto-focus] [clearOnEdit]="false"></ion-input>
 | 
					                <ion-input text-wrap class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.courses.password' | translate }}" ngModel [core-auto-focus] [clearOnEdit]="false"></ion-input>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,8 +12,10 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, ViewController } from 'ionic-angular';
 | 
					import { IonicPage, ViewController } from 'ionic-angular';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Page that displays a form to enter a password to self enrol in a course.
 | 
					 * Page that displays a form to enter a password to self enrol in a course.
 | 
				
			||||||
@ -24,7 +26,12 @@ import { IonicPage, ViewController } from 'ionic-angular';
 | 
				
			|||||||
    templateUrl: 'self-enrol-password.html',
 | 
					    templateUrl: 'self-enrol-password.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class CoreCoursesSelfEnrolPasswordPage {
 | 
					export class CoreCoursesSelfEnrolPasswordPage {
 | 
				
			||||||
    constructor(private viewCtrl: ViewController) { }
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('enrolPasswordForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(protected viewCtrl: ViewController,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Close help modal.
 | 
					     * Close help modal.
 | 
				
			||||||
@ -43,6 +50,11 @@ export class CoreCoursesSelfEnrolPasswordPage {
 | 
				
			|||||||
        e.preventDefault();
 | 
					        e.preventDefault();
 | 
				
			||||||
        e.stopPropagation();
 | 
					        e.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					            form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					            online: false,
 | 
				
			||||||
 | 
					        }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.viewCtrl.dismiss(password);
 | 
					        this.viewCtrl.dismiss(password);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,8 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    protected valueChangeSubscription: Subscription;
 | 
					    protected valueChangeSubscription: Subscription;
 | 
				
			||||||
    protected keyboardObs: any;
 | 
					    protected keyboardObs: any;
 | 
				
			||||||
    protected initHeightInterval;
 | 
					    protected resetObs: any;
 | 
				
			||||||
 | 
					    protected initHeightInterval: NodeJS.Timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rteEnabled = false;
 | 
					    rteEnabled = false;
 | 
				
			||||||
    editorSupported = true;
 | 
					    editorSupported = true;
 | 
				
			||||||
@ -175,11 +176,11 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.shouldAutoSaveDrafts()) {
 | 
					        if (this.shouldAutoSaveDrafts()) {
 | 
				
			||||||
            // Recover drafts.
 | 
					 | 
				
			||||||
            this.restoreDraft();
 | 
					            this.restoreDraft();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Auto save drafts every certain time.
 | 
					 | 
				
			||||||
            this.autoSaveDrafts();
 | 
					            this.autoSaveDrafts();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.deleteDraftOnSubmit();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -780,6 +781,25 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe
 | 
				
			|||||||
        }, this.DRAFT_AUTOSAVE_FREQUENCY);
 | 
					        }, this.DRAFT_AUTOSAVE_FREQUENCY);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Delete the draft when the form is submitted.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected deleteDraftOnSubmit(): void {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.resetObs = this.events.on(CoreEventsProvider.FORM_SUBMITTED, async (data) => {
 | 
				
			||||||
 | 
					            const form = this.element.closest('form');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (data.form && form && data.form == form) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    await this.editorOffline.deleteDraft(this.contextLevel, this.contextInstanceId, this.elementId,
 | 
				
			||||||
 | 
					                            this.draftExtraParams);
 | 
				
			||||||
 | 
					                } catch (error) {
 | 
				
			||||||
 | 
					                    // Error deleting draft. Shouldn't happen.
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Show a message.
 | 
					     * Show a message.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@ -824,5 +844,6 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe
 | 
				
			|||||||
        this.keyboardObs && this.keyboardObs.off();
 | 
					        this.keyboardObs && this.keyboardObs.off();
 | 
				
			||||||
        clearInterval(this.autoSaveInterval);
 | 
					        clearInterval(this.autoSaveInterval);
 | 
				
			||||||
        clearTimeout(this.hideMessageTimeout);
 | 
					        clearTimeout(this.hideMessageTimeout);
 | 
				
			||||||
 | 
					        this.resetObs && this.resetObs.off();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,7 @@
 | 
				
			|||||||
                <p *ngIf="siteName" padding class="item-heading core-sitename"><core-format-text [text]="siteName" [filter]="false"></core-format-text></p>
 | 
					                <p *ngIf="siteName" padding class="item-heading core-sitename"><core-format-text [text]="siteName" [filter]="false"></core-format-text></p>
 | 
				
			||||||
                <p *ngIf="siteName" class="core-siteurl">{{siteUrl}}</p>
 | 
					                <p *ngIf="siteName" class="core-siteurl">{{siteUrl}}</p>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <form ion-list [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form">
 | 
					            <form ion-list [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #credentialsForm>
 | 
				
			||||||
                <ion-item *ngIf="siteChecked && !isBrowserSSO">
 | 
					                <ion-item *ngIf="siteChecked && !isBrowserSSO">
 | 
				
			||||||
                    <ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input>
 | 
					                    <ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input>
 | 
				
			||||||
                </ion-item>
 | 
					                </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
@ -32,6 +32,9 @@ import { CoreConfigConstants } from '../../../../configconstants';
 | 
				
			|||||||
    templateUrl: 'credentials.html',
 | 
					    templateUrl: 'credentials.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class CoreLoginCredentialsPage {
 | 
					export class CoreLoginCredentialsPage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('credentialsForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    credForm: FormGroup;
 | 
					    credForm: FormGroup;
 | 
				
			||||||
    siteUrl: string;
 | 
					    siteUrl: string;
 | 
				
			||||||
    siteChecked = false;
 | 
					    siteChecked = false;
 | 
				
			||||||
@ -242,6 +245,11 @@ export class CoreLoginCredentialsPage {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }).finally(() => {
 | 
					        }).finally(() => {
 | 
				
			||||||
            modal.dismiss();
 | 
					            modal.dismiss();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: true,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
    <core-loading [hideUntil]="settingsLoaded" *ngIf="!isMinor">
 | 
					    <core-loading [hideUntil]="settingsLoaded" *ngIf="!isMinor">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Age verification. -->
 | 
					        <!-- Age verification. -->
 | 
				
			||||||
        <form ion-list *ngIf="settingsLoaded && settings && ageDigitalConsentVerification" [formGroup]="ageVerificationForm" (ngSubmit)="verifyAge($event)">
 | 
					        <form ion-list *ngIf="settingsLoaded && settings && ageDigitalConsentVerification" [formGroup]="ageVerificationForm" (ngSubmit)="verifyAge($event)" #ageForm>
 | 
				
			||||||
            <ion-item-divider text-wrap>
 | 
					            <ion-item-divider text-wrap>
 | 
				
			||||||
                <p class="item-heading">{{ 'core.agelocationverification' | translate }}</p>
 | 
					                <p class="item-heading">{{ 'core.agelocationverification' | translate }}</p>
 | 
				
			||||||
            </ion-item-divider>
 | 
					            </ion-item-divider>
 | 
				
			||||||
@ -47,7 +47,7 @@
 | 
				
			|||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Signup form. -->
 | 
					        <!-- Signup form. -->
 | 
				
			||||||
        <form ion-list *ngIf="settingsLoaded && settings && !ageDigitalConsentVerification" [formGroup]="signupForm" (ngSubmit)="create($event)">
 | 
					        <form ion-list *ngIf="settingsLoaded && settings && !ageDigitalConsentVerification" [formGroup]="signupForm" (ngSubmit)="create($event)" #signupFormEl>
 | 
				
			||||||
            <ion-item text-wrap text-center>
 | 
					            <ion-item text-wrap text-center>
 | 
				
			||||||
                <!-- If no sitename show big siteurl. -->
 | 
					                <!-- If no sitename show big siteurl. -->
 | 
				
			||||||
                <p *ngIf="!siteName" padding class="item-heading">{{siteUrl}}</p>
 | 
					                <p *ngIf="!siteName" padding class="item-heading">{{siteUrl}}</p>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,10 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, ViewChild } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavController, NavParams, Content } from 'ionic-angular';
 | 
					import { IonicPage, NavController, NavParams, Content } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
import { CoreSitesProvider } from '@providers/sites';
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
 | 
					import { CoreTextUtilsProvider } from '@providers/utils/text';
 | 
				
			||||||
@ -35,6 +36,8 @@ import { CoreConfigConstants } from '../../../../configconstants';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class CoreLoginEmailSignupPage {
 | 
					export class CoreLoginEmailSignupPage {
 | 
				
			||||||
    @ViewChild(Content) content: Content;
 | 
					    @ViewChild(Content) content: Content;
 | 
				
			||||||
 | 
					    @ViewChild('ageForm') ageFormElement: ElementRef;
 | 
				
			||||||
 | 
					    @ViewChild('signupFormEl') signupFormElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    signupForm: FormGroup;
 | 
					    signupForm: FormGroup;
 | 
				
			||||||
    siteUrl: string;
 | 
					    siteUrl: string;
 | 
				
			||||||
@ -66,10 +69,18 @@ export class CoreLoginEmailSignupPage {
 | 
				
			|||||||
    policyErrors: any;
 | 
					    policyErrors: any;
 | 
				
			||||||
    namefieldsErrors: any;
 | 
					    namefieldsErrors: any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(private navCtrl: NavController, navParams: NavParams, private fb: FormBuilder, private wsProvider: CoreWSProvider,
 | 
					    constructor(protected navCtrl: NavController,
 | 
				
			||||||
            private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
 | 
					            navParams: NavParams,
 | 
				
			||||||
            private domUtils: CoreDomUtilsProvider, private translate: TranslateService, private utils: CoreUtilsProvider,
 | 
					            protected fb: FormBuilder,
 | 
				
			||||||
            private textUtils: CoreTextUtilsProvider, private userProfileFieldDelegate: CoreUserProfileFieldDelegate) {
 | 
					            protected wsProvider: CoreWSProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider,
 | 
				
			||||||
 | 
					            protected loginHelper: CoreLoginHelperProvider,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected translate: TranslateService,
 | 
				
			||||||
 | 
					            protected utils: CoreUtilsProvider,
 | 
				
			||||||
 | 
					            protected textUtils: CoreTextUtilsProvider,
 | 
				
			||||||
 | 
					            protected userProfileFieldDelegate: CoreUserProfileFieldDelegate,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.siteUrl = navParams.get('siteUrl');
 | 
					        this.siteUrl = navParams.get('siteUrl');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -265,6 +276,12 @@ export class CoreLoginEmailSignupPage {
 | 
				
			|||||||
                    return this.wsProvider.callAjax('auth_email_signup_user', params, { siteUrl: this.siteUrl });
 | 
					                    return this.wsProvider.callAjax('auth_email_signup_user', params, { siteUrl: this.siteUrl });
 | 
				
			||||||
                }).then((result) => {
 | 
					                }).then((result) => {
 | 
				
			||||||
                    if (result.success) {
 | 
					                    if (result.success) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                            form: this.signupFormElement.nativeElement,
 | 
				
			||||||
 | 
					                            online: true,
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // Show alert and ho back.
 | 
					                        // Show alert and ho back.
 | 
				
			||||||
                        const message = this.translate.instant('core.login.emailconfirmsent', { $a: params.email });
 | 
					                        const message = this.translate.instant('core.login.emailconfirmsent', { $a: params.email });
 | 
				
			||||||
                        this.domUtils.showAlert(this.translate.instant('core.success'), message);
 | 
					                        this.domUtils.showAlert(this.translate.instant('core.success'), message);
 | 
				
			||||||
@ -334,6 +351,12 @@ export class CoreLoginEmailSignupPage {
 | 
				
			|||||||
        params.age = parseInt(params.age, 10); // Use just the integer part.
 | 
					        params.age = parseInt(params.age, 10); // Use just the integer part.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.wsProvider.callAjax('core_auth_is_minor', params, {siteUrl: this.siteUrl}).then((result) => {
 | 
					        this.wsProvider.callAjax('core_auth_is_minor', params, {siteUrl: this.siteUrl}).then((result) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.ageFormElement.nativeElement,
 | 
				
			||||||
 | 
					                online: true,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!result.status) {
 | 
					            if (!result.status) {
 | 
				
			||||||
                if (this.countryControl.value) {
 | 
					                if (this.countryControl.value) {
 | 
				
			||||||
                    this.signUpCountryControl.setValue(this.countryControl.value);
 | 
					                    this.signUpCountryControl.setValue(this.countryControl.value);
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@
 | 
				
			|||||||
        </ion-item>
 | 
					        </ion-item>
 | 
				
			||||||
    </ion-list>
 | 
					    </ion-list>
 | 
				
			||||||
    <ion-card>
 | 
					    <ion-card>
 | 
				
			||||||
        <form ion-list [formGroup]="myForm" (ngSubmit)="resetPassword($event)">
 | 
					        <form ion-list [formGroup]="myForm" (ngSubmit)="resetPassword($event)" #resetPasswordForm>
 | 
				
			||||||
            <ion-item-divider text-wrap>
 | 
					            <ion-item-divider text-wrap>
 | 
				
			||||||
                {{ 'core.login.searchby' | translate }}
 | 
					                {{ 'core.login.searchby' | translate }}
 | 
				
			||||||
            </ion-item-divider>
 | 
					            </ion-item-divider>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,11 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreLoginHelperProvider } from '../../providers/helper';
 | 
					import { CoreLoginHelperProvider } from '../../providers/helper';
 | 
				
			||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
					import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
				
			||||||
@ -28,11 +30,20 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
				
			|||||||
    templateUrl: 'forgotten-password.html',
 | 
					    templateUrl: 'forgotten-password.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class CoreLoginForgottenPasswordPage {
 | 
					export class CoreLoginForgottenPasswordPage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('resetPasswordForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    myForm: FormGroup;
 | 
					    myForm: FormGroup;
 | 
				
			||||||
    siteUrl: string;
 | 
					    siteUrl: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(private navCtrl: NavController, navParams: NavParams, fb: FormBuilder, private translate: TranslateService,
 | 
					    constructor(protected navCtrl: NavController,
 | 
				
			||||||
            private loginHelper: CoreLoginHelperProvider, private domUtils: CoreDomUtilsProvider) {
 | 
					            navParams: NavParams,
 | 
				
			||||||
 | 
					            fb: FormBuilder,
 | 
				
			||||||
 | 
					            protected translate: TranslateService,
 | 
				
			||||||
 | 
					            protected loginHelper: CoreLoginHelperProvider,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.siteUrl = navParams.get('siteUrl');
 | 
					        this.siteUrl = navParams.get('siteUrl');
 | 
				
			||||||
        this.myForm = fb.group({
 | 
					        this.myForm = fb.group({
 | 
				
			||||||
@ -71,6 +82,11 @@ export class CoreLoginForgottenPasswordPage {
 | 
				
			|||||||
                this.domUtils.showErrorModal(response.notice);
 | 
					                this.domUtils.showErrorModal(response.notice);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // Success.
 | 
					                // Success.
 | 
				
			||||||
 | 
					                this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                    form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                    online: true,
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this.domUtils.showAlert(this.translate.instant('core.success'), response.notice);
 | 
					                this.domUtils.showAlert(this.translate.instant('core.success'), response.notice);
 | 
				
			||||||
                this.navCtrl.pop();
 | 
					                this.navCtrl.pop();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@
 | 
				
			|||||||
                <ion-icon padding name="alert"></ion-icon> {{ 'core.login.reconnectdescription' | translate }}
 | 
					                <ion-icon padding name="alert"></ion-icon> {{ 'core.login.reconnectdescription' | translate }}
 | 
				
			||||||
            </p>
 | 
					            </p>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <form ion-list *ngIf="!isOAuth" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form">
 | 
					        <form ion-list *ngIf="!isOAuth" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #reconnectForm>
 | 
				
			||||||
            <ion-item text-wrap class="core-username">
 | 
					            <ion-item text-wrap class="core-username">
 | 
				
			||||||
                <p>{{username}}</p>
 | 
					                <p>{{username}}</p>
 | 
				
			||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,10 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, NavController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
import { CoreSitesProvider } from '@providers/sites';
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreLoginHelperProvider } from '../../providers/helper';
 | 
					import { CoreLoginHelperProvider } from '../../providers/helper';
 | 
				
			||||||
@ -29,6 +30,9 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
				
			|||||||
    templateUrl: 'reconnect.html',
 | 
					    templateUrl: 'reconnect.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class CoreLoginReconnectPage {
 | 
					export class CoreLoginReconnectPage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('reconnectForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    credForm: FormGroup;
 | 
					    credForm: FormGroup;
 | 
				
			||||||
    siteUrl: string;
 | 
					    siteUrl: string;
 | 
				
			||||||
    username: string;
 | 
					    username: string;
 | 
				
			||||||
@ -47,13 +51,14 @@ export class CoreLoginReconnectPage {
 | 
				
			|||||||
    protected isLoggedOut: boolean;
 | 
					    protected isLoggedOut: boolean;
 | 
				
			||||||
    protected siteId: string;
 | 
					    protected siteId: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(private navCtrl: NavController,
 | 
					    constructor(protected navCtrl: NavController,
 | 
				
			||||||
            navParams: NavParams,
 | 
					            navParams: NavParams,
 | 
				
			||||||
            fb: FormBuilder,
 | 
					            fb: FormBuilder,
 | 
				
			||||||
            private appProvider: CoreAppProvider,
 | 
					            protected appProvider: CoreAppProvider,
 | 
				
			||||||
            private sitesProvider: CoreSitesProvider,
 | 
					            protected sitesProvider: CoreSitesProvider,
 | 
				
			||||||
            private loginHelper: CoreLoginHelperProvider,
 | 
					            protected loginHelper: CoreLoginHelperProvider,
 | 
				
			||||||
            private domUtils: CoreDomUtilsProvider) {
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const currentSite = this.sitesProvider.getCurrentSite();
 | 
					        const currentSite = this.sitesProvider.getCurrentSite();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -175,6 +180,12 @@ export class CoreLoginReconnectPage {
 | 
				
			|||||||
        // Start the authentication process.
 | 
					        // Start the authentication process.
 | 
				
			||||||
        this.sitesProvider.getUserToken(siteUrl, username, password).then((data) => {
 | 
					        this.sitesProvider.getUserToken(siteUrl, username, password).then((data) => {
 | 
				
			||||||
            return this.sitesProvider.updateSiteToken(this.infoSiteUrl, username, data.token, data.privateToken).then(() => {
 | 
					            return this.sitesProvider.updateSiteToken(this.infoSiteUrl, username, data.token, data.privateToken).then(() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                    form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                    online: true,
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Update site info too because functions might have changed (e.g. unisntall local_mobile).
 | 
					                // Update site info too because functions might have changed (e.g. unisntall local_mobile).
 | 
				
			||||||
                return this.sitesProvider.updateSiteInfoByUrl(this.infoSiteUrl, username).then(() => {
 | 
					                return this.sitesProvider.updateSiteInfoByUrl(this.infoSiteUrl, username).then(() => {
 | 
				
			||||||
                    // Reset fields so the data is not in the view anymore.
 | 
					                    // Reset fields so the data is not in the view anymore.
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
        <div text-center padding>
 | 
					        <div text-center padding>
 | 
				
			||||||
            <img src="assets/img/login_logo.png" class="avatar-full login-logo" role="presentation">
 | 
					            <img src="assets/img/login_logo.png" class="avatar-full login-logo" role="presentation">
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <form ion-list [formGroup]="siteForm" (ngSubmit)="connect($event, siteForm.value.siteUrl)" *ngIf="!fixedSites || fixedDisplay == 'select'">
 | 
					        <form ion-list [formGroup]="siteForm" (ngSubmit)="connect($event, siteForm.value.siteUrl)" *ngIf="!fixedSites || fixedDisplay == 'select'" #siteFormEl>
 | 
				
			||||||
            <!-- Form to input the site URL if there are no fixed sites. -->
 | 
					            <!-- Form to input the site URL if there are no fixed sites. -->
 | 
				
			||||||
            <ng-container *ngIf="!fixedSites">
 | 
					            <ng-container *ngIf="!fixedSites">
 | 
				
			||||||
                <p padding>{{ 'core.login.newsitedescription' | translate }}</p>
 | 
					                <p padding>{{ 'core.login.newsitedescription' | translate }}</p>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,10 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component } from '@angular/core';
 | 
					import { Component, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, NavController, ModalController, NavParams } from 'ionic-angular';
 | 
					import { IonicPage, NavController, ModalController, NavParams } from 'ionic-angular';
 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
import { CoreSitesProvider, CoreSiteCheckResponse } from '@providers/sites';
 | 
					import { CoreSitesProvider, CoreSiteCheckResponse } from '@providers/sites';
 | 
				
			||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreConfigConstants } from '../../../../configconstants';
 | 
					import { CoreConfigConstants } from '../../../../configconstants';
 | 
				
			||||||
@ -31,6 +32,9 @@ import { CoreUrl } from '@classes/utils/url';
 | 
				
			|||||||
    templateUrl: 'site.html',
 | 
					    templateUrl: 'site.html',
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class CoreLoginSitePage {
 | 
					export class CoreLoginSitePage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('siteFormEl') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    siteForm: FormGroup;
 | 
					    siteForm: FormGroup;
 | 
				
			||||||
    fixedSites: any[];
 | 
					    fixedSites: any[];
 | 
				
			||||||
    filteredSites: any[];
 | 
					    filteredSites: any[];
 | 
				
			||||||
@ -38,9 +42,15 @@ export class CoreLoginSitePage {
 | 
				
			|||||||
    showKeyboard = false;
 | 
					    showKeyboard = false;
 | 
				
			||||||
    filter = '';
 | 
					    filter = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(navParams: NavParams, private navCtrl: NavController, fb: FormBuilder, private appProvider: CoreAppProvider,
 | 
					    constructor(navParams: NavParams,
 | 
				
			||||||
            private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
 | 
					            protected navCtrl: NavController,
 | 
				
			||||||
            private modalCtrl: ModalController, private domUtils: CoreDomUtilsProvider) {
 | 
					            fb: FormBuilder,
 | 
				
			||||||
 | 
					            protected appProvider: CoreAppProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider,
 | 
				
			||||||
 | 
					            protected loginHelper: CoreLoginHelperProvider,
 | 
				
			||||||
 | 
					            protected modalCtrl: ModalController,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.showKeyboard = !!navParams.get('showKeyboard');
 | 
					        this.showKeyboard = !!navParams.get('showKeyboard');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -96,6 +106,12 @@ export class CoreLoginSitePage {
 | 
				
			|||||||
            // It's a demo site.
 | 
					            // It's a demo site.
 | 
				
			||||||
            this.sitesProvider.getUserToken(siteData.url, siteData.username, siteData.password).then((data) => {
 | 
					            this.sitesProvider.getUserToken(siteData.url, siteData.username, siteData.password).then((data) => {
 | 
				
			||||||
                return this.sitesProvider.newSite(data.siteUrl, data.token, data.privateToken).then(() => {
 | 
					                return this.sitesProvider.newSite(data.siteUrl, data.token, data.privateToken).then(() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                        form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                        online: true,
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return this.loginHelper.goToSiteInitialPage();
 | 
					                    return this.loginHelper.goToSiteInitialPage();
 | 
				
			||||||
                }, (error) => {
 | 
					                }, (error) => {
 | 
				
			||||||
                    this.loginHelper.treatUserTokenError(siteData.url, error, siteData.username, siteData.password);
 | 
					                    this.loginHelper.treatUserTokenError(siteData.url, error, siteData.username, siteData.password);
 | 
				
			||||||
@ -175,6 +191,12 @@ export class CoreLoginSitePage {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async login(response: CoreSiteCheckResponse): Promise<void> {
 | 
					    protected async login(response: CoreSiteCheckResponse): Promise<void> {
 | 
				
			||||||
        return this.sitesProvider.checkRequiredMinimumVersion(response.config).then(() => {
 | 
					        return this.sitesProvider.checkRequiredMinimumVersion(response.config).then(() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, {
 | 
				
			||||||
 | 
					                form: this.formElement.nativeElement,
 | 
				
			||||||
 | 
					                online: true,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (response.warning) {
 | 
					            if (response.warning) {
 | 
				
			||||||
                this.domUtils.showErrorModal(response.warning, true, 4000);
 | 
					                this.domUtils.showErrorModal(response.warning, true, 4000);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
<ion-card>
 | 
					<ion-card>
 | 
				
			||||||
    <form #f="ngForm" (ngSubmit)="submitForm($event)" role="search">
 | 
					    <form #f="ngForm" (ngSubmit)="submitForm($event)" role="search" #searchForm>
 | 
				
			||||||
        <ion-item>
 | 
					        <ion-item>
 | 
				
			||||||
            <ion-input type="search" name="search" [(ngModel)]="searchText" [placeholder]="placeholder" [autocorrect]="autocorrect" [spellcheck]="spellcheck" [core-auto-focus]="autoFocus" [disabled]="disabled" role="searchbox" (focus)="showHistory()" (blur)="hideHistory()"></ion-input>
 | 
					            <ion-input type="search" name="search" [(ngModel)]="searchText" [placeholder]="placeholder" [autocorrect]="autocorrect" [spellcheck]="spellcheck" [core-auto-focus]="autoFocus" [disabled]="disabled" role="searchbox" (focus)="showHistory()" (blur)="hideHistory()"></ion-input>
 | 
				
			||||||
            <button item-end ion-button clear icon-only type="submit" class="button-small" [attr.aria-label]="searchLabel" [disabled]="disabled || !searchText || (searchText.length < lengthCheck)">
 | 
					            <button item-end ion-button clear icon-only type="submit" class="button-small" [attr.aria-label]="searchLabel" [disabled]="disabled || !searchText || (searchText.length < lengthCheck)">
 | 
				
			||||||
 | 
				
			|||||||
@ -12,8 +12,11 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
 | 
					import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from '@providers/sites';
 | 
				
			||||||
 | 
					import { CoreDomUtilsProvider } from '@providers/utils/dom';
 | 
				
			||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
 | 
					import { CoreUtilsProvider } from '@providers/utils/utils';
 | 
				
			||||||
import { CoreSearchHistoryProvider, CoreSearchHistoryItem } from '../../providers/search-history';
 | 
					import { CoreSearchHistoryProvider, CoreSearchHistoryItem } from '../../providers/search-history';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -47,6 +50,8 @@ export class CoreSearchBoxComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
    @Output() onSubmit: EventEmitter<string>; // Send data when submitting the search form.
 | 
					    @Output() onSubmit: EventEmitter<string>; // Send data when submitting the search form.
 | 
				
			||||||
    @Output() onClear: EventEmitter<void>; // Send event when clearing the search form.
 | 
					    @Output() onClear: EventEmitter<void>; // Send event when clearing the search form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('searchForm') formElement: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    searched = ''; // Last search emitted.
 | 
					    searched = ''; // Last search emitted.
 | 
				
			||||||
    searchText = '';
 | 
					    searchText = '';
 | 
				
			||||||
    history: CoreSearchHistoryItem[];
 | 
					    history: CoreSearchHistoryItem[];
 | 
				
			||||||
@ -58,6 +63,9 @@ export class CoreSearchBoxComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
    constructor(protected translate: TranslateService,
 | 
					    constructor(protected translate: TranslateService,
 | 
				
			||||||
            protected utils: CoreUtilsProvider,
 | 
					            protected utils: CoreUtilsProvider,
 | 
				
			||||||
            protected searchHistoryProvider: CoreSearchHistoryProvider,
 | 
					            protected searchHistoryProvider: CoreSearchHistoryProvider,
 | 
				
			||||||
 | 
					            protected eventsProvider: CoreEventsProvider,
 | 
				
			||||||
 | 
					            protected sitesProvider: CoreSitesProvider,
 | 
				
			||||||
 | 
					            protected domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        this.onSubmit = new EventEmitter<string>();
 | 
					        this.onSubmit = new EventEmitter<string>();
 | 
				
			||||||
        this.onClear = new EventEmitter<void>();
 | 
					        this.onClear = new EventEmitter<void>();
 | 
				
			||||||
@ -95,6 +103,8 @@ export class CoreSearchBoxComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
            this.saveSearchToHistory(this.searchText);
 | 
					            this.saveSearchToHistory(this.searchText);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.searched = this.searchText;
 | 
					        this.searched = this.searchText;
 | 
				
			||||||
        this.onSubmit.emit(this.searchText);
 | 
					        this.onSubmit.emit(this.searchText);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -64,6 +64,7 @@ export class CoreEventsProvider {
 | 
				
			|||||||
    static SELECT_COURSE_TAB = 'select_course_tab';
 | 
					    static SELECT_COURSE_TAB = 'select_course_tab';
 | 
				
			||||||
    static WS_CACHE_INVALIDATED = 'ws_cache_invalidated';
 | 
					    static WS_CACHE_INVALIDATED = 'ws_cache_invalidated';
 | 
				
			||||||
    static SITE_STORAGE_DELETED = 'site_storage_deleted';
 | 
					    static SITE_STORAGE_DELETED = 'site_storage_deleted';
 | 
				
			||||||
 | 
					    static FORM_SUBMITTED = 'form_submitted';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected logger;
 | 
					    protected logger;
 | 
				
			||||||
    protected observables: { [s: string]: Subject<any> } = {};
 | 
					    protected observables: { [s: string]: Subject<any> } = {};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user