commit
3e6eeb88f8
|
@ -317,6 +317,10 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy {
|
||||||
// Clear temporary data from plugins.
|
// Clear temporary data from plugins.
|
||||||
await this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, inputData);
|
await this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, inputData);
|
||||||
|
|
||||||
|
if (sent) {
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'assign' });
|
||||||
|
}
|
||||||
|
|
||||||
// Submission saved, trigger events.
|
// Submission saved, trigger events.
|
||||||
this.domUtils.triggerFormSubmittedEvent(this.formElement, sent, this.sitesProvider.getCurrentSiteId());
|
this.domUtils.triggerFormSubmittedEvent(this.formElement, sent, this.sitesProvider.getCurrentSiteId());
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ export class AddonModChatChatPage {
|
||||||
* Runs when the page is about to leave and no longer be the active page.
|
* Runs when the page is about to leave and no longer be the active page.
|
||||||
*/
|
*/
|
||||||
ionViewWillLeave(): void {
|
ionViewWillLeave(): void {
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'chat' });
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import { Component, Optional, Injector } from '@angular/core';
|
import { Component, Optional, Injector } from '@angular/core';
|
||||||
import { Content } from 'ionic-angular';
|
import { Content } from 'ionic-angular';
|
||||||
|
import { CoreEvents, CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||||
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
||||||
import { AddonModChoiceProvider, AddonModChoiceChoice, AddonModChoiceOption, AddonModChoiceResult } from '../../providers/choice';
|
import { AddonModChoiceProvider, AddonModChoiceChoice, AddonModChoiceOption, AddonModChoiceResult } from '../../providers/choice';
|
||||||
|
@ -51,9 +52,14 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
protected hasAnsweredOnline = false;
|
protected hasAnsweredOnline = false;
|
||||||
protected now: number;
|
protected now: number;
|
||||||
|
|
||||||
constructor(injector: Injector, private choiceProvider: AddonModChoiceProvider, @Optional() content: Content,
|
constructor(
|
||||||
private choiceOffline: AddonModChoiceOfflineProvider, private choiceSync: AddonModChoiceSyncProvider,
|
injector: Injector,
|
||||||
private timeUtils: CoreTimeUtilsProvider) {
|
protected choiceProvider: AddonModChoiceProvider,
|
||||||
|
@Optional() content: Content,
|
||||||
|
protected choiceOffline: AddonModChoiceOfflineProvider,
|
||||||
|
protected choiceSync: AddonModChoiceSyncProvider,
|
||||||
|
protected timeUtils: CoreTimeUtilsProvider,
|
||||||
|
) {
|
||||||
super(injector, content);
|
super(injector, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,6 +365,10 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata);
|
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata);
|
||||||
this.domUtils.scrollToTop(this.content);
|
this.domUtils.scrollToTop(this.content);
|
||||||
|
|
||||||
|
if (online) {
|
||||||
|
CoreEvents.instance.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: this.moduleName });
|
||||||
|
}
|
||||||
|
|
||||||
return this.dataUpdated(online);
|
return this.dataUpdated(online);
|
||||||
}).catch((message) => {
|
}).catch((message) => {
|
||||||
this.domUtils.showErrorModalDefault(message, 'addon.mod_choice.cannotsubmit', true);
|
this.domUtils.showErrorModalDefault(message, 'addon.mod_choice.cannotsubmit', true);
|
||||||
|
|
|
@ -217,6 +217,10 @@ export class AddonModDataEditPage {
|
||||||
|
|
||||||
this.domUtils.triggerFormSubmittedEvent(this.formElement, result.sent, this.siteId);
|
this.domUtils.triggerFormSubmittedEvent(this.formElement, result.sent, this.siteId);
|
||||||
|
|
||||||
|
if (result.sent) {
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'data' });
|
||||||
|
}
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
this.entryId = this.entryId || result.newentryid;
|
this.entryId = this.entryId || result.newentryid;
|
||||||
|
|
|
@ -280,6 +280,8 @@ export class AddonModFeedbackFormPage implements OnDestroy {
|
||||||
promises.push(this.feedbackProvider.invalidateFeedbackAccessInformationData(this.feedback.id));
|
promises.push(this.feedbackProvider.invalidateFeedbackAccessInformationData(this.feedback.id));
|
||||||
promises.push(this.feedbackProvider.invalidateResumePageData(this.feedback.id));
|
promises.push(this.feedbackProvider.invalidateResumePageData(this.feedback.id));
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'feedback' });
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
return this.fetchAccessData();
|
return this.fetchAccessData();
|
||||||
});
|
});
|
||||||
|
|
|
@ -473,6 +473,8 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
|
||||||
if (discussionIds) {
|
if (discussionIds) {
|
||||||
// Data sent to server, delete stored files (if any).
|
// Data sent to server, delete stored files (if any).
|
||||||
this.forumHelper.deleteNewDiscussionStoredFiles(this.forumId, discTimecreated);
|
this.forumHelper.deleteNewDiscussionStoredFiles(this.forumId, discTimecreated);
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'forum' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discussionIds && discussionIds.length < groupIds.length) {
|
if (discussionIds && discussionIds.length < groupIds.length) {
|
||||||
|
|
|
@ -246,6 +246,7 @@ export class AddonModGlossaryEditPage implements OnInit {
|
||||||
if (entryId) {
|
if (entryId) {
|
||||||
// Data sent to server, delete stored files (if any).
|
// Data sent to server, delete stored files (if any).
|
||||||
this.glossaryHelper.deleteStoredFiles(this.glossary.id, this.entry.concept, timecreated);
|
this.glossaryHelper.deleteStoredFiles(this.glossary.id, this.entry.concept, timecreated);
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'glossary' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
|
|
@ -18,7 +18,6 @@ import { IonicPage, NavParams, Content, PopoverController, ModalController, Moda
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider } from '@providers/app';
|
import { CoreAppProvider } from '@providers/app';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreLoggerProvider } from '@providers/logger';
|
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreSyncProvider } from '@providers/sync';
|
import { CoreSyncProvider } from '@providers/sync';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
@ -80,7 +79,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
|
||||||
protected loadingMenu: boolean; // Whether the lesson menu is being loaded.
|
protected loadingMenu: boolean; // Whether the lesson menu is being loaded.
|
||||||
protected lessonPages: any[]; // Lesson pages (for the lesson menu).
|
protected lessonPages: any[]; // Lesson pages (for the lesson menu).
|
||||||
|
|
||||||
constructor(protected navParams: NavParams, logger: CoreLoggerProvider, protected translate: TranslateService,
|
constructor(protected navParams: NavParams, protected translate: TranslateService,
|
||||||
protected eventsProvider: CoreEventsProvider, protected sitesProvider: CoreSitesProvider,
|
protected eventsProvider: CoreEventsProvider, protected sitesProvider: CoreSitesProvider,
|
||||||
protected syncProvider: CoreSyncProvider, protected domUtils: CoreDomUtilsProvider, popoverCtrl: PopoverController,
|
protected syncProvider: CoreSyncProvider, protected domUtils: CoreDomUtilsProvider, popoverCtrl: PopoverController,
|
||||||
protected timeUtils: CoreTimeUtilsProvider, protected lessonProvider: AddonModLessonProvider,
|
protected timeUtils: CoreTimeUtilsProvider, protected lessonProvider: AddonModLessonProvider,
|
||||||
|
@ -369,6 +368,8 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
|
||||||
this.messages = this.messages.concat(data.messages);
|
this.messages = this.messages.concat(data.messages);
|
||||||
this.processData = undefined;
|
this.processData = undefined;
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'lesson' });
|
||||||
|
|
||||||
// Format activity link if present.
|
// Format activity link if present.
|
||||||
if (this.eolData && this.eolData.activitylink) {
|
if (this.eolData && this.eolData.activitylink) {
|
||||||
this.eolData.activitylink.value = this.lessonHelper.formatActivityLink(this.eolData.activitylink.value);
|
this.eolData.activitylink.value = this.lessonHelper.formatActivityLink(this.eolData.activitylink.value);
|
||||||
|
|
|
@ -376,6 +376,8 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
|
||||||
synced: !this.offline
|
synced: !this.offline
|
||||||
}, this.sitesProvider.getCurrentSiteId());
|
}, this.sitesProvider.getCurrentSiteId());
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'quiz' });
|
||||||
|
|
||||||
// Leave the player.
|
// Leave the player.
|
||||||
this.forceLeave = true;
|
this.forceLeave = true;
|
||||||
this.navCtrl.pop();
|
this.navCtrl.pop();
|
||||||
|
|
|
@ -310,6 +310,8 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
|
||||||
* Page will leave.
|
* Page will leave.
|
||||||
*/
|
*/
|
||||||
ionViewWillUnload(): void {
|
ionViewWillUnload(): void {
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'scorm' });
|
||||||
|
|
||||||
// Empty src when leaving the state so unload event is triggered in the iframe.
|
// Empty src when leaving the state so unload event is triggered in the iframe.
|
||||||
this.src = '';
|
this.src = '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import { Component, Optional, Injector } from '@angular/core';
|
import { Component, Optional, Injector } from '@angular/core';
|
||||||
import { Content } from 'ionic-angular';
|
import { Content } from 'ionic-angular';
|
||||||
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
||||||
|
import { CoreEvents, CoreEventsProvider } from '@providers/events';
|
||||||
import { AddonModSurveyProvider, AddonModSurveySurvey } from '../../providers/survey';
|
import { AddonModSurveyProvider, AddonModSurveySurvey } from '../../providers/survey';
|
||||||
import { AddonModSurveyHelperProvider, AddonModSurveyQuestionFormatted } from '../../providers/helper';
|
import { AddonModSurveyHelperProvider, AddonModSurveyQuestionFormatted } from '../../providers/helper';
|
||||||
import { AddonModSurveyOfflineProvider } from '../../providers/offline';
|
import { AddonModSurveyOfflineProvider } from '../../providers/offline';
|
||||||
|
@ -38,9 +39,14 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
protected userId: number;
|
protected userId: number;
|
||||||
protected syncEventName = AddonModSurveySyncProvider.AUTO_SYNCED;
|
protected syncEventName = AddonModSurveySyncProvider.AUTO_SYNCED;
|
||||||
|
|
||||||
constructor(injector: Injector, private surveyProvider: AddonModSurveyProvider, @Optional() content: Content,
|
constructor(
|
||||||
private surveyHelper: AddonModSurveyHelperProvider, private surveyOffline: AddonModSurveyOfflineProvider,
|
injector: Injector,
|
||||||
private surveySync: AddonModSurveySyncProvider) {
|
protected surveyProvider: AddonModSurveyProvider,
|
||||||
|
@Optional() content: Content,
|
||||||
|
protected surveyHelper: AddonModSurveyHelperProvider,
|
||||||
|
protected surveyOffline: AddonModSurveyOfflineProvider,
|
||||||
|
protected surveySync: AddonModSurveySyncProvider,
|
||||||
|
) {
|
||||||
super(injector, content);
|
super(injector, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +191,8 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.surveyProvider.submitAnswers(this.survey.id, this.survey.name, this.courseId, answers).then((online) => {
|
return this.surveyProvider.submitAnswers(this.survey.id, this.survey.name, this.courseId, answers).then((online) => {
|
||||||
|
CoreEvents.instance.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: this.moduleName });
|
||||||
|
|
||||||
if (online && this.isPrefetched()) {
|
if (online && this.isPrefetched()) {
|
||||||
// The survey is downloaded, update the data.
|
// The survey is downloaded, update the data.
|
||||||
return this.surveySync.prefetchAfterUpdate(this.module, this.courseId).then(() => {
|
return this.surveySync.prefetchAfterUpdate(this.module, this.courseId).then(() => {
|
||||||
|
|
|
@ -465,6 +465,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy {
|
||||||
this.domUtils.triggerFormSubmittedEvent(this.formElement, id > 0, this.sitesProvider.getCurrentSiteId());
|
this.domUtils.triggerFormSubmittedEvent(this.formElement, id > 0, this.sitesProvider.getCurrentSiteId());
|
||||||
|
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'wiki' });
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
|
|
|
@ -388,6 +388,8 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy {
|
||||||
data['submissionId'] = newSubmissionId;
|
data['submissionId'] = newSubmissionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.ACTIVITY_DATA_SENT, { module: 'workshop' });
|
||||||
|
|
||||||
const promise = newSubmissionId ? this.workshopProvider.invalidateSubmissionData(this.workshopId, newSubmissionId) :
|
const promise = newSubmissionId ? this.workshopProvider.invalidateSubmissionData(this.workshopId, newSubmissionId) :
|
||||||
Promise.resolve();
|
Promise.resolve();
|
||||||
|
|
||||||
|
|
|
@ -94,5 +94,12 @@
|
||||||
"statusbarlighttextremotetheme": true,
|
"statusbarlighttextremotetheme": true,
|
||||||
"enableanalytics": false,
|
"enableanalytics": false,
|
||||||
"forceColorScheme": "",
|
"forceColorScheme": "",
|
||||||
"webviewscheme": "moodleappfs"
|
"webviewscheme": "moodleappfs",
|
||||||
|
"appstores": {
|
||||||
|
"android": "com.moodle.moodlemobile",
|
||||||
|
"ios": "id633359593",
|
||||||
|
"windows": "moodle-desktop/9p9bwvhdc8c8",
|
||||||
|
"mac": "id1255924440",
|
||||||
|
"linux": "https://download.moodle.org/desktop/download.php?platform=linux&arch=64"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,7 +277,11 @@ export class CoreLoginSitePage {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
this.domUtils.showAlertWithButtons(this.translate.instant('core.cannotconnect'), message, buttons);
|
this.domUtils.showAlertWithOptions({
|
||||||
|
title: this.translate.instant('core.cannotconnect'),
|
||||||
|
message,
|
||||||
|
buttons,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -369,10 +373,11 @@ export class CoreLoginSitePage {
|
||||||
*/
|
*/
|
||||||
showInstructionsAndScanQR(): void {
|
showInstructionsAndScanQR(): void {
|
||||||
// Show some instructions first.
|
// Show some instructions first.
|
||||||
this.domUtils.showAlertWithButtons(
|
this.domUtils.showAlertWithOptions({
|
||||||
this.translate.instant('core.login.faqwhereisqrcode'),
|
title: this.translate.instant('core.login.faqwhereisqrcode'),
|
||||||
this.translate.instant('core.login.faqwhereisqrcodeanswer', {$image: CoreLoginHelperProvider.FAQ_QRCODE_IMAGE_HTML}),
|
message: this.translate.instant('core.login.faqwhereisqrcodeanswer',
|
||||||
[
|
{$image: CoreLoginHelperProvider.FAQ_QRCODE_IMAGE_HTML}),
|
||||||
|
buttons: [
|
||||||
{
|
{
|
||||||
text: this.translate.instant('core.cancel'),
|
text: this.translate.instant('core.cancel'),
|
||||||
role: 'cancel'
|
role: 'cancel'
|
||||||
|
@ -383,8 +388,8 @@ export class CoreLoginSitePage {
|
||||||
this.scanQR();
|
this.scanQR();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Platform, AlertController, NavController, NavOptions } from 'ionic-angular';
|
import { Platform, AlertController, NavController, NavOptions } from 'ionic-angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider } from '@providers/app';
|
import { CoreAppProvider, CoreStoreConfig } from '@providers/app';
|
||||||
import { CoreConfigProvider } from '@providers/config';
|
import { CoreConfigProvider } from '@providers/config';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreInitDelegate } from '@providers/init';
|
import { CoreInitDelegate } from '@providers/init';
|
||||||
|
@ -1180,13 +1180,7 @@ export class CoreLoginHelperProvider {
|
||||||
* @param message The warning message.
|
* @param message The warning message.
|
||||||
*/
|
*/
|
||||||
protected showWorkplaceNoticeModal(message: string): void {
|
protected showWorkplaceNoticeModal(message: string): void {
|
||||||
let link;
|
const link = this.appProvider.getAppStoreUrl({android: 'com.moodle.workplace', ios: 'id1470929705' });
|
||||||
|
|
||||||
if (this.platform.is('android')) {
|
|
||||||
link = 'market://details?id=com.moodle.workplace';
|
|
||||||
} else if (this.platform.is('ios')) {
|
|
||||||
link = 'itms-apps://itunes.apple.com/app/id1470929705';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showDownloadAppNoticeModal(message, link);
|
this.showDownloadAppNoticeModal(message, link);
|
||||||
}
|
}
|
||||||
|
@ -1197,20 +1191,12 @@ export class CoreLoginHelperProvider {
|
||||||
* @param message The warning message.
|
* @param message The warning message.
|
||||||
*/
|
*/
|
||||||
protected showMoodleAppNoticeModal(message: string): void {
|
protected showMoodleAppNoticeModal(message: string): void {
|
||||||
let link;
|
const storesConfig: CoreStoreConfig = CoreConfigConstants.appstores;
|
||||||
|
storesConfig.desktop = 'https://download.moodle.org/desktop/';
|
||||||
|
storesConfig.mobile = 'https://download.moodle.org/mobile/';
|
||||||
|
storesConfig.default = 'https://download.moodle.org/mobile/';
|
||||||
|
|
||||||
if (this.appProvider.isWindows()) {
|
const link = this.appProvider.getAppStoreUrl(storesConfig);
|
||||||
link = 'https://download.moodle.org/desktop/download.php?platform=windows';
|
|
||||||
} else if (this.appProvider.isLinux()) {
|
|
||||||
link = 'https://download.moodle.org/desktop/download.php?platform=linux&arch=' +
|
|
||||||
(this.appProvider.is64Bits() ? '64' : '32');
|
|
||||||
} else if (this.appProvider.isMac()) {
|
|
||||||
link = 'itms-apps://itunes.apple.com/app/id1255924440';
|
|
||||||
} else if (this.platform.is('android')) {
|
|
||||||
link = 'market://details?id=com.moodle.moodlemobile';
|
|
||||||
} else if (this.platform.is('ios')) {
|
|
||||||
link = 'itms-apps://itunes.apple.com/app/id633359593';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showDownloadAppNoticeModal(message, link);
|
this.showDownloadAppNoticeModal(message, link);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<ion-header>
|
||||||
|
<ion-navbar>
|
||||||
|
<ion-title>{{ title }}</ion-title>
|
||||||
|
</ion-navbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<div class="prompt-message"><core-format-text [text]="message"></core-format-text></div>
|
||||||
|
<ion-textarea rows="1" core-auto-rows name="feedback" [attr.aria-multiline]="true" [(ngModel)]="text" [placeholder]="placeholder"></ion-textarea>
|
||||||
|
<div class="prompt-button-group">
|
||||||
|
<button *ngFor="let button of buttons" ion-button="prompt-button" (click)="buttonClicked(button)" [ngClass]="button.cssClass">
|
||||||
|
{{ button.text }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
|
@ -0,0 +1,36 @@
|
||||||
|
// (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 { NgModule } from '@angular/core';
|
||||||
|
import { IonicPageModule } from 'ionic-angular';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { CoreViewerTextAreaPage } from './textarea';
|
||||||
|
import { CoreComponentsModule } from '@components/components.module';
|
||||||
|
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module to lazy load the page.
|
||||||
|
*/
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
CoreViewerTextAreaPage
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CoreComponentsModule,
|
||||||
|
CoreDirectivesModule,
|
||||||
|
IonicPageModule.forChild(CoreViewerTextAreaPage),
|
||||||
|
TranslateModule.forChild()
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class CoreViewerTextAreaPageModule {}
|
|
@ -0,0 +1,187 @@
|
||||||
|
$core-modal-promt-min-width: 320px;
|
||||||
|
|
||||||
|
ion-app.app-root ion-modal.core-modal-prompt {
|
||||||
|
/* Some styles have been copied from ionic alert component. */
|
||||||
|
@include position(0, 0, 0, 0);
|
||||||
|
position: absolute;
|
||||||
|
z-index: $z-index-overlay;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
contain: strict;
|
||||||
|
|
||||||
|
ion-backdrop {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
&::after {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
.toolbar-background {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-button-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.prompt-button {
|
||||||
|
@include margin(0);
|
||||||
|
|
||||||
|
z-index: 0;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
font-size: $alert-button-font-size;
|
||||||
|
line-height: $alert-button-line-height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-textarea {
|
||||||
|
@include placeholder($alert-input-placeholder-color);
|
||||||
|
@include padding($alert-md-message-padding-top, $alert-md-message-padding-end, $alert-md-message-padding-bottom, $alert-md-message-padding-start);
|
||||||
|
border: 0;
|
||||||
|
background: inherit;
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-message {
|
||||||
|
@include deprecated-variable(padding, $alert-md-message-padding) {
|
||||||
|
@include padding($alert-md-message-padding-top, $alert-md-message-padding-end, $alert-md-message-padding-bottom, $alert-md-message-padding-start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-wrapper {
|
||||||
|
z-index: $z-index-overlay-wrapper;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: $core-modal-promt-min-width;
|
||||||
|
max-height: $alert-max-height;
|
||||||
|
opacity: 0;
|
||||||
|
contain: content;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
page-core-viewer-textarea,
|
||||||
|
ion-content,
|
||||||
|
.fixed-content,
|
||||||
|
.scroll-content {
|
||||||
|
position: relative;
|
||||||
|
background: $white;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.fixed-content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.scroll-content {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-md .prompt-button-group {
|
||||||
|
flex-wrap: $alert-md-button-group-flex-wrap;
|
||||||
|
justify-content: $alert-md-button-group-justify-content;
|
||||||
|
|
||||||
|
@include deprecated-variable(padding, $alert-md-button-group-padding) {
|
||||||
|
@include padding($alert-md-button-group-padding-top, $alert-md-button-group-padding-end, $alert-md-button-group-padding-bottom, $alert-md-button-group-padding-start);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-button {
|
||||||
|
@include text-align($alert-md-button-text-align);
|
||||||
|
@include border-radius($alert-md-button-border-radius);
|
||||||
|
|
||||||
|
// necessary for ripple to work properly
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
font-weight: $alert-md-button-font-weight;
|
||||||
|
text-transform: $alert-md-button-text-transform;
|
||||||
|
color: $alert-md-button-text-color;
|
||||||
|
background-color: $alert-md-button-background-color;
|
||||||
|
|
||||||
|
@include deprecated-variable(margin, $alert-md-button-margin) {
|
||||||
|
@include margin($alert-md-button-margin-top, $alert-md-button-margin-end, $alert-md-button-margin-bottom, $alert-md-button-margin-start);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include deprecated-variable(padding, $alert-md-button-padding) {
|
||||||
|
@include padding($alert-md-button-padding-top, $alert-md-button-padding-end, $alert-md-button-padding-bottom, $alert-md-button-padding-start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-button.activated {
|
||||||
|
background-color: $alert-md-button-background-color-activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-button .button-inner {
|
||||||
|
justify-content: $alert-md-button-group-justify-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-ios .prompt-button-group {
|
||||||
|
@include margin-horizontal(null, -$alert-ios-button-border-width);
|
||||||
|
|
||||||
|
flex-wrap: $alert-ios-button-group-flex-wrap;
|
||||||
|
.prompt-button {
|
||||||
|
@include margin($alert-ios-button-margin);
|
||||||
|
@include border-radius($alert-ios-button-border-radius);
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
flex: $alert-ios-button-flex;
|
||||||
|
|
||||||
|
min-width: $alert-ios-button-min-width;
|
||||||
|
height: $alert-ios-button-min-height;
|
||||||
|
|
||||||
|
border-top: $alert-ios-button-border-width $alert-ios-button-border-style $alert-ios-button-border-color;
|
||||||
|
border-right: $alert-ios-button-border-width $alert-ios-button-border-style $alert-ios-button-border-color;
|
||||||
|
font-size: $alert-ios-button-font-size;
|
||||||
|
color: $alert-ios-button-text-color;
|
||||||
|
background-color: $alert-ios-button-background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-button:last-child {
|
||||||
|
border-right: 0;
|
||||||
|
font-weight: $alert-ios-button-main-font-weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-button.activated {
|
||||||
|
background-color: $alert-ios-button-background-color-activated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-app.app-root-md ion-modal.core-modal-prompt {
|
||||||
|
.modal-wrapper {
|
||||||
|
@include border-radius($alert-md-border-radius);
|
||||||
|
max-width: $alert-md-max-width;
|
||||||
|
background-color: $alert-md-background-color;
|
||||||
|
box-shadow: $alert-md-box-shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-content .toolbar-title {
|
||||||
|
color: $alert-md-message-text-color;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-app.app-root-ios ion-modal.core-modal-prompt {
|
||||||
|
.modal-wrapper {
|
||||||
|
@include border-radius($alert-ios-border-radius);
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: $alert-ios-max-width;
|
||||||
|
background-color: $alert-ios-background;
|
||||||
|
box-shadow: $alert-ios-box-shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-content .toolbar-title {
|
||||||
|
color: $alert-ios-message-text-color;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-title {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
// (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 } from '@angular/core';
|
||||||
|
import { IonicPage, ViewController, NavParams, AlertButton } from 'ionic-angular';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page to render a textarea prompt.
|
||||||
|
*/
|
||||||
|
@IonicPage({ segment: 'core-viewer-textarea' })
|
||||||
|
@Component({
|
||||||
|
selector: 'page-core-viewer-textarea',
|
||||||
|
templateUrl: 'textarea.html',
|
||||||
|
})
|
||||||
|
export class CoreViewerTextAreaPage {
|
||||||
|
title: string;
|
||||||
|
message: string;
|
||||||
|
placeholder: string;
|
||||||
|
buttons: AlertButton[];
|
||||||
|
text = '';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected viewCtrl: ViewController,
|
||||||
|
params: NavParams,
|
||||||
|
) {
|
||||||
|
this.title = params.get('title');
|
||||||
|
this.message = params.get('message');
|
||||||
|
this.placeholder = params.get('placeholder') || '';
|
||||||
|
|
||||||
|
const buttons = params.get('buttons');
|
||||||
|
|
||||||
|
this.buttons = buttons.map((button) => {
|
||||||
|
if (typeof button === 'string') {
|
||||||
|
return { text: button };
|
||||||
|
}
|
||||||
|
|
||||||
|
return button;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button clicked.
|
||||||
|
*
|
||||||
|
* @param button: Clicked button.
|
||||||
|
*/
|
||||||
|
buttonClicked(button: AlertButton): void {
|
||||||
|
let shouldDismiss = true;
|
||||||
|
if (button.handler) {
|
||||||
|
// A handler has been provided, execute it pass the handler the values from the inputs
|
||||||
|
if (button.handler(this.text) === false) {
|
||||||
|
// If the return value of the handler is false then do not dismiss
|
||||||
|
shouldDismiss = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldDismiss) {
|
||||||
|
this.viewCtrl.dismiss(button.role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,6 +50,51 @@ export interface CoreRedirectData {
|
||||||
timemodified?: number;
|
timemodified?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store config data.
|
||||||
|
*/
|
||||||
|
export interface CoreStoreConfig {
|
||||||
|
/**
|
||||||
|
* ID of the Apple store where the desktop Mac app is uploaded.
|
||||||
|
*/
|
||||||
|
mac?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the Windows store where the desktop Windows app is uploaded.
|
||||||
|
*/
|
||||||
|
windows?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Url with the desktop linux download link.
|
||||||
|
*/
|
||||||
|
linux?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback URL when the desktop options is not set.
|
||||||
|
*/
|
||||||
|
desktop?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the Apple store where the mobile iOS app is uploaded.
|
||||||
|
*/
|
||||||
|
ios?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the Google play store where the android app is uploaded.
|
||||||
|
*/
|
||||||
|
android?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback URL when the mobile options is not set.
|
||||||
|
*/
|
||||||
|
mobile?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback URL when the other fallbacks options are not set.
|
||||||
|
*/
|
||||||
|
default?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App DB schema and migration function.
|
* App DB schema and migration function.
|
||||||
*/
|
*/
|
||||||
|
@ -255,6 +300,44 @@ export class CoreAppProvider {
|
||||||
return this.appCtrl.getRootNavs()[0];
|
return this.appCtrl.getRootNavs()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get app store URL.
|
||||||
|
*
|
||||||
|
* @param storesConfig Config params to send the user to the right place.
|
||||||
|
* @return Store URL.
|
||||||
|
*/
|
||||||
|
getAppStoreUrl(storesConfig: CoreStoreConfig): string {
|
||||||
|
if (this.isMac() && storesConfig.mac) {
|
||||||
|
return 'itms-apps://itunes.apple.com/app/' + storesConfig.mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isWindows() && storesConfig.windows) {
|
||||||
|
return 'https://www.microsoft.com/p/' + storesConfig.windows;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isLinux() && storesConfig.linux) {
|
||||||
|
return storesConfig.linux;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isDesktop() && storesConfig.desktop) {
|
||||||
|
return storesConfig.desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isIOS() && storesConfig.ios) {
|
||||||
|
return 'itms-apps://itunes.apple.com/app/' + storesConfig.ios;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isAndroid() && storesConfig.android) {
|
||||||
|
return 'market://details?id=' + storesConfig.android;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isMobile() && storesConfig.mobile) {
|
||||||
|
return storesConfig.mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return storesConfig.default || null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the user agent is controlled by automation. I.e. Behat testing.
|
* Returns whether the user agent is controlled by automation. I.e. Behat testing.
|
||||||
*
|
*
|
||||||
|
|
|
@ -67,6 +67,7 @@ export class CoreEventsProvider {
|
||||||
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_ACTION = 'form_action';
|
static FORM_ACTION = 'form_action';
|
||||||
|
static ACTIVITY_DATA_SENT = 'activity_data_sent';
|
||||||
|
|
||||||
protected logger;
|
protected logger;
|
||||||
protected observables: { [s: string]: Subject<any> } = {};
|
protected observables: { [s: string]: Subject<any> } = {};
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider, CoreAppSchema } from './app';
|
import { CoreAppProvider, CoreAppSchema, CoreStoreConfig } from './app';
|
||||||
import { CoreEventsProvider } from './events';
|
import { CoreEventsProvider } from './events';
|
||||||
import { CoreLoggerProvider } from './logger';
|
import { CoreLoggerProvider } from './logger';
|
||||||
import { CoreSitesFactoryProvider } from './sites-factory';
|
import { CoreSitesFactoryProvider } from './sites-factory';
|
||||||
|
@ -1001,19 +1001,15 @@ export class CoreSitesProvider {
|
||||||
appVersion = this.convertVersionName(CoreConfigConstants.versionname);
|
appVersion = this.convertVersionName(CoreConfigConstants.versionname);
|
||||||
|
|
||||||
if (requiredVersion > appVersion) {
|
if (requiredVersion > appVersion) {
|
||||||
let downloadUrl = '';
|
const storesConfig: CoreStoreConfig = {
|
||||||
|
android: config.tool_mobile_androidappid || false,
|
||||||
|
ios: config.tool_mobile_iosappid || false,
|
||||||
|
desktop: config.tool_mobile_setuplink || 'https://download.moodle.org/desktop/',
|
||||||
|
mobile: config.tool_mobile_setuplink || 'https://download.moodle.org/mobile/',
|
||||||
|
default: config.tool_mobile_setuplink,
|
||||||
|
};
|
||||||
|
|
||||||
if (this.appProvider.isAndroid() && config.tool_mobile_androidappid) {
|
const downloadUrl = this.appProvider.getAppStoreUrl(storesConfig);
|
||||||
downloadUrl = 'market://details?id=' + config.tool_mobile_androidappid;
|
|
||||||
} else if (this.appProvider.isIOS() && config.tool_mobile_iosappid) {
|
|
||||||
downloadUrl = 'itms-apps://itunes.apple.com/app/id' + config.tool_mobile_iosappid;
|
|
||||||
} else if (config.tool_mobile_setuplink) {
|
|
||||||
downloadUrl = config.tool_mobile_setuplink;
|
|
||||||
} else if (this.appProvider.isMobile()) {
|
|
||||||
downloadUrl = 'https://download.moodle.org/mobile/';
|
|
||||||
} else {
|
|
||||||
downloadUrl = 'https://download.moodle.org/desktop/';
|
|
||||||
}
|
|
||||||
|
|
||||||
siteId = siteId || this.getCurrentSiteId();
|
siteId = siteId || this.getCurrentSiteId();
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { Injectable, SimpleChange, ElementRef } from '@angular/core';
|
import { Injectable, SimpleChange, ElementRef } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content, PopoverController,
|
LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content, PopoverController,
|
||||||
ModalController, AlertButton
|
ModalController, AlertButton, AlertOptions
|
||||||
} from 'ionic-angular';
|
} from 'ionic-angular';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
@ -1139,41 +1139,36 @@ export class CoreDomUtilsProvider {
|
||||||
* @return Promise resolved with the alert modal.
|
* @return Promise resolved with the alert modal.
|
||||||
*/
|
*/
|
||||||
async showAlert(title: string, message: string, buttonText?: string, autocloseTime?: number): Promise<CoreAlert> {
|
async showAlert(title: string, message: string, buttonText?: string, autocloseTime?: number): Promise<CoreAlert> {
|
||||||
const buttons = [buttonText || this.translate.instant('core.ok')];
|
return this.showAlertWithOptions({
|
||||||
|
title: title,
|
||||||
return this.showAlertWithButtons(title, message, buttons, autocloseTime);
|
message,
|
||||||
|
buttons: [buttonText || this.translate.instant('core.ok')]
|
||||||
|
}, autocloseTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show an alert modal with some buttons.
|
* General show an alert modal.
|
||||||
*
|
*
|
||||||
* @param title Title to show.
|
* @param options Alert options to pass to the alert.
|
||||||
* @param message Message to show.
|
|
||||||
* @param buttons Buttons objects or texts.
|
|
||||||
* @param autocloseTime Number of milliseconds to wait to close the modal. If not defined, modal won't be closed.
|
* @param autocloseTime Number of milliseconds to wait to close the modal. If not defined, modal won't be closed.
|
||||||
* @return Promise resolved with the alert modal.
|
* @return Promise resolved with the alert modal.
|
||||||
*/
|
*/
|
||||||
async showAlertWithButtons(title: string, message: string, buttons: (string | AlertButton)[], autocloseTime?: number):
|
async showAlertWithOptions(options: AlertOptions = {}, autocloseTime?: number): Promise<CoreAlert> {
|
||||||
Promise<CoreAlert> {
|
const hasHTMLTags = this.textUtils.hasHTMLTags(options.message || '');
|
||||||
const hasHTMLTags = this.textUtils.hasHTMLTags(message);
|
|
||||||
|
|
||||||
if (hasHTMLTags) {
|
if (hasHTMLTags) {
|
||||||
// Format the text.
|
// Format the text.
|
||||||
message = await this.textUtils.formatText(message);
|
options.message = await this.textUtils.formatText(options.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const alertId = <string> Md5.hashAsciiStr((title || '') + '#' + (message || ''));
|
const alertId = <string> Md5.hashAsciiStr((options.title || '') + '#' + (options.message || ''));
|
||||||
|
|
||||||
if (this.displayedAlerts[alertId]) {
|
if (this.displayedAlerts[alertId]) {
|
||||||
// There's already an alert with the same message and title. Return it.
|
// There's already an alert with the same message and title. Return it.
|
||||||
return this.displayedAlerts[alertId];
|
return this.displayedAlerts[alertId];
|
||||||
}
|
}
|
||||||
|
|
||||||
const alert: CoreAlert = <any> this.alertCtrl.create({
|
const alert: CoreAlert = <any> this.alertCtrl.create(options);
|
||||||
title: title,
|
|
||||||
message: message,
|
|
||||||
buttons: buttons,
|
|
||||||
});
|
|
||||||
|
|
||||||
alert.present().then(() => {
|
alert.present().then(() => {
|
||||||
if (hasHTMLTags) {
|
if (hasHTMLTags) {
|
||||||
|
@ -1202,8 +1197,18 @@ export class CoreDomUtilsProvider {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (autocloseTime > 0) {
|
if (autocloseTime > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(async () => {
|
||||||
alert.dismiss();
|
await alert.dismiss();
|
||||||
|
|
||||||
|
if (options.buttons) {
|
||||||
|
// Execute dismiss function if any.
|
||||||
|
const cancelButton = <AlertButton> options.buttons.find((button) => {
|
||||||
|
return typeof button != 'string' && typeof button.role != 'undefined' &&
|
||||||
|
typeof button.handler != 'undefined' && button.role == 'cancel';
|
||||||
|
});
|
||||||
|
cancelButton && cancelButton.handler(null);
|
||||||
|
}
|
||||||
|
|
||||||
}, autocloseTime);
|
}, autocloseTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1250,52 +1255,33 @@ export class CoreDomUtilsProvider {
|
||||||
* @param options More options. See https://ionicframework.com/docs/v3/api/components/alert/AlertController/
|
* @param options More options. See https://ionicframework.com/docs/v3/api/components/alert/AlertController/
|
||||||
* @return Promise resolved if the user confirms and rejected with a canceled error if he cancels.
|
* @return Promise resolved if the user confirms and rejected with a canceled error if he cancels.
|
||||||
*/
|
*/
|
||||||
showConfirm(message: string, title?: string, okText?: string, cancelText?: string, options?: any): Promise<any> {
|
showConfirm(message: string, title?: string, okText?: string, cancelText?: string, options: AlertOptions = {}): Promise<any> {
|
||||||
return new Promise<void>((resolve, reject): void => {
|
return new Promise<void>((resolve, reject): void => {
|
||||||
const hasHTMLTags = this.textUtils.hasHTMLTags(message);
|
|
||||||
let promise;
|
|
||||||
|
|
||||||
if (hasHTMLTags) {
|
options.title = title;
|
||||||
// Format the text.
|
options.message = message;
|
||||||
promise = this.textUtils.formatText(message);
|
|
||||||
} else {
|
options.buttons = [
|
||||||
promise = Promise.resolve(message);
|
{
|
||||||
|
text: cancelText || this.translate.instant('core.cancel'),
|
||||||
|
role: 'cancel',
|
||||||
|
handler: (): void => {
|
||||||
|
reject(this.createCanceledError());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: okText || this.translate.instant('core.ok'),
|
||||||
|
handler: (data: any): void => {
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!title) {
|
||||||
|
options.cssClass = 'core-nohead';
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.then((message) => {
|
this.showAlertWithOptions(options, 0);
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
options.message = message;
|
|
||||||
options.title = title;
|
|
||||||
if (!title) {
|
|
||||||
options.cssClass = 'core-nohead';
|
|
||||||
}
|
|
||||||
options.buttons = [
|
|
||||||
{
|
|
||||||
text: cancelText || this.translate.instant('core.cancel'),
|
|
||||||
role: 'cancel',
|
|
||||||
handler: (): void => {
|
|
||||||
reject(this.createCanceledError());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: okText || this.translate.instant('core.ok'),
|
|
||||||
handler: (data: any): void => {
|
|
||||||
resolve(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const alert = this.alertCtrl.create(options);
|
|
||||||
|
|
||||||
alert.present().then(() => {
|
|
||||||
if (hasHTMLTags) {
|
|
||||||
// Treat all anchors so they don't override the app.
|
|
||||||
const alertMessageEl: HTMLElement = alert.pageRef().nativeElement.querySelector('.alert-message');
|
|
||||||
this.treatAnchors(alertMessageEl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1414,59 +1400,67 @@ export class CoreDomUtilsProvider {
|
||||||
* @param title Modal title.
|
* @param title Modal title.
|
||||||
* @param placeholder Placeholder of the input element. By default, "Password".
|
* @param placeholder Placeholder of the input element. By default, "Password".
|
||||||
* @param type Type of the input element. By default, password.
|
* @param type Type of the input element. By default, password.
|
||||||
|
* @param options More options to pass to the alert.
|
||||||
* @return Promise resolved with the input data if the user clicks OK, rejected if cancels.
|
* @return Promise resolved with the input data if the user clicks OK, rejected if cancels.
|
||||||
*/
|
*/
|
||||||
showPrompt(message: string, title?: string, placeholder?: string, type: string = 'password'): Promise<any> {
|
showPrompt(message: string, title?: string, placeholder?: string, type: string = 'password'): Promise<any> {
|
||||||
return new Promise((resolve, reject): void => {
|
return new Promise((resolve, reject): any => {
|
||||||
const hasHTMLTags = this.textUtils.hasHTMLTags(message);
|
placeholder = typeof placeholder == 'undefined' || placeholder == null ?
|
||||||
let promise;
|
this.translate.instant('core.login.password') : placeholder;
|
||||||
|
|
||||||
if (hasHTMLTags) {
|
const options: AlertOptions = {
|
||||||
// Format the text.
|
title,
|
||||||
promise = this.textUtils.formatText(message);
|
message,
|
||||||
} else {
|
inputs: [
|
||||||
promise = Promise.resolve(message);
|
{
|
||||||
}
|
name: 'promptinput',
|
||||||
|
placeholder: placeholder,
|
||||||
promise.then((message) => {
|
type: type
|
||||||
const alert = this.alertCtrl.create({
|
|
||||||
message: message,
|
|
||||||
title: title,
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
name: 'promptinput',
|
|
||||||
placeholder: placeholder || this.translate.instant('core.login.password'),
|
|
||||||
type: type
|
|
||||||
}
|
|
||||||
],
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: this.translate.instant('core.cancel'),
|
|
||||||
role: 'cancel',
|
|
||||||
handler: (): void => {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: this.translate.instant('core.ok'),
|
|
||||||
handler: (data): void => {
|
|
||||||
resolve(data.promptinput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
alert.present().then(() => {
|
|
||||||
if (hasHTMLTags) {
|
|
||||||
// Treat all anchors so they don't override the app.
|
|
||||||
const alertMessageEl: HTMLElement = alert.pageRef().nativeElement.querySelector('.alert-message');
|
|
||||||
this.treatAnchors(alertMessageEl);
|
|
||||||
}
|
}
|
||||||
});
|
],
|
||||||
});
|
buttons: [
|
||||||
|
{
|
||||||
|
text: this.translate.instant('core.cancel'),
|
||||||
|
role: 'cancel',
|
||||||
|
handler: (): void => {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: this.translate.instant('core.ok'),
|
||||||
|
handler: (data): void => {
|
||||||
|
resolve(data.promptinput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
this.showAlertWithOptions(options);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a prompt modal to input a textarea.
|
||||||
|
*
|
||||||
|
* @param title Modal title.
|
||||||
|
* @param message Modal message.
|
||||||
|
* @param buttons Buttons to pass to the modal.
|
||||||
|
* @param placeholder Placeholder of the input element if any.
|
||||||
|
* @return Promise resolved when modal presented.
|
||||||
|
*/
|
||||||
|
showTextareaPrompt(title: string, message: string, buttons: (string | AlertButton)[], placeholder?: string): Promise<any> {
|
||||||
|
const params = {
|
||||||
|
title: title,
|
||||||
|
message: message,
|
||||||
|
placeholder: placeholder,
|
||||||
|
buttons: buttons,
|
||||||
|
};
|
||||||
|
|
||||||
|
const modal = this.modalCtrl.create('CoreViewerTextAreaPage', params, { cssClass: 'core-modal-prompt' });
|
||||||
|
|
||||||
|
return modal.present();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays an autodimissable toast modal window.
|
* Displays an autodimissable toast modal window.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue