commit
b1839c6f1e
|
@ -122,7 +122,7 @@
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
|
<plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
|
||||||
<plugin name="cordova-plugin-zip" spec="^3.1.0" />
|
<plugin name="cordova-plugin-zip" spec="^3.1.0" />
|
||||||
<plugin name="cordova-plugin-local-notifications-mm" spec="^1.0.10" />
|
<plugin name="cordova-plugin-local-notifications-mm" spec="^1.0.11" />
|
||||||
<plugin name="cordova-plugin-file-opener2" spec="^2.0.19" />
|
<plugin name="cordova-plugin-file-opener2" spec="^2.0.19" />
|
||||||
<plugin name="com-darryncampbell-cordova-plugin-intent" spec="^1.1.0" />
|
<plugin name="com-darryncampbell-cordova-plugin-intent" spec="^1.1.0" />
|
||||||
<plugin name="cordova-sqlite-evcore-extbuild-free" spec="^0.9.7" />
|
<plugin name="cordova-sqlite-evcore-extbuild-free" spec="^0.9.7" />
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
"ionic:build:before": "gulp",
|
"ionic:build:before": "gulp",
|
||||||
"ionic:watch:before": "gulp",
|
"ionic:watch:before": "gulp",
|
||||||
"ionic:build:after": "gulp copy-component-templates",
|
"ionic:build:after": "gulp copy-component-templates",
|
||||||
|
"preionic:build": "gulp",
|
||||||
"postionic:build": "gulp copy-component-templates",
|
"postionic:build": "gulp copy-component-templates",
|
||||||
"desktop.pack": "electron-builder --dir",
|
"desktop.pack": "electron-builder --dir",
|
||||||
"desktop.dist": "electron-builder",
|
"desktop.dist": "electron-builder",
|
||||||
|
|
|
@ -92,23 +92,6 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if we can leave the page or not.
|
|
||||||
*
|
|
||||||
* @return {boolean|Promise<void>} Resolved if we can leave it, rejected if not.
|
|
||||||
*/
|
|
||||||
ionViewCanLeave(): boolean | Promise<void> {
|
|
||||||
// If split view is enabled, check if we can leave the details page.
|
|
||||||
if (this.splitviewCtrl.isOn()) {
|
|
||||||
const detailsPage = this.splitviewCtrl.getDetailsNav().getActive().instance;
|
|
||||||
if (detailsPage && detailsPage.ionViewCanLeave) {
|
|
||||||
return detailsPage.ionViewCanLeave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch assignment data.
|
* Fetch assignment data.
|
||||||
*
|
*
|
||||||
|
|
|
@ -50,9 +50,10 @@ export class AddonModDataFieldNumberHandler extends AddonModDataFieldTextHandler
|
||||||
*/
|
*/
|
||||||
hasFieldDataChanged(field: any, inputData: any, originalFieldData: any): Promise<boolean> | boolean {
|
hasFieldDataChanged(field: any, inputData: any, originalFieldData: any): Promise<boolean> | boolean {
|
||||||
const fieldName = 'f_' + field.id,
|
const fieldName = 'f_' + field.id,
|
||||||
input = typeof inputData[fieldName] != 'undefined' ? parseFloat(inputData[fieldName]) : '';
|
input = typeof inputData[fieldName] != 'undefined' && inputData[fieldName] !== null ?
|
||||||
|
parseFloat(inputData[fieldName]) : '';
|
||||||
|
|
||||||
originalFieldData = (originalFieldData && typeof originalFieldData.content != 'undefined') ?
|
originalFieldData = (originalFieldData && typeof originalFieldData.content != 'undefined' && originalFieldData !== null) ?
|
||||||
parseFloat(originalFieldData.content) : '';
|
parseFloat(originalFieldData.content) : '';
|
||||||
|
|
||||||
return input != originalFieldData;
|
return input != originalFieldData;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
||||||
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||||
import { AddonModDataProvider } from './data';
|
import { AddonModDataProvider } from './data';
|
||||||
|
@ -31,7 +32,8 @@ export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
pattern = /\/mod\/data\/view\.php.*([\?\&](d|delete)=\d+)/;
|
pattern = /\/mod\/data\/view\.php.*([\?\&](d|delete)=\d+)/;
|
||||||
|
|
||||||
constructor(private dataProvider: AddonModDataProvider, private courseProvider: CoreCourseProvider,
|
constructor(private dataProvider: AddonModDataProvider, private courseProvider: CoreCourseProvider,
|
||||||
private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider) {
|
private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider,
|
||||||
|
private translate: TranslateService) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,11 +68,13 @@ export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
return [{
|
return [{
|
||||||
action: (siteId, navCtrl?): void => {
|
action: (siteId, navCtrl?): void => {
|
||||||
|
|
||||||
|
this.domUtils.showConfirm(this.translate.instant('addon.mod_data.confirmdeleterecord')).then(() => {
|
||||||
const modal = this.domUtils.showModalLoading(),
|
const modal = this.domUtils.showModalLoading(),
|
||||||
dataId = parseInt(params.d, 10),
|
dataId = parseInt(params.d, 10),
|
||||||
entryId = parseInt(params.delete, 10);
|
entryId = parseInt(params.delete, 10);
|
||||||
|
|
||||||
this.getActivityCourseIdIfNotSet(dataId, siteId, courseId).then((cId) => {
|
return this.getActivityCourseIdIfNotSet(dataId, siteId, courseId).then((cId) => {
|
||||||
courseId = cId;
|
courseId = cId;
|
||||||
|
|
||||||
// Delete entry.
|
// Delete entry.
|
||||||
|
@ -93,6 +97,9 @@ export class AddonModDataDeleteLinkHandler extends CoreContentLinksHandlerBase {
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
modal.dismiss();
|
modal.dismiss();
|
||||||
});
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
// Nothing to do.
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { NavController, NavOptions } from 'ionic-angular';
|
import { NavController, NavOptions } from 'ionic-angular';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate';
|
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate';
|
||||||
import { CoreAppProvider } from '@providers/app';
|
import { CoreAppProvider } from '@providers/app';
|
||||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
|
@ -36,7 +37,8 @@ export class AddonModLtiModuleHandler implements CoreCourseModuleHandler {
|
||||||
private domUtils: CoreDomUtilsProvider,
|
private domUtils: CoreDomUtilsProvider,
|
||||||
private filepoolProvider: CoreFilepoolProvider,
|
private filepoolProvider: CoreFilepoolProvider,
|
||||||
private sitesProvider: CoreSitesProvider,
|
private sitesProvider: CoreSitesProvider,
|
||||||
private ltiProvider: AddonModLtiProvider) {}
|
private ltiProvider: AddonModLtiProvider,
|
||||||
|
private sanitizer: DomSanitizer) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the handler is enabled on a site level.
|
* Check if the handler is enabled on a site level.
|
||||||
|
@ -100,11 +102,11 @@ export class AddonModLtiModuleHandler implements CoreCourseModuleHandler {
|
||||||
// Get the internal URL.
|
// Get the internal URL.
|
||||||
return this.filepoolProvider.getSrcByUrl(siteId, icon, AddonModLtiProvider.COMPONENT, module.id);
|
return this.filepoolProvider.getSrcByUrl(siteId, icon, AddonModLtiProvider.COMPONENT, module.id);
|
||||||
}).then((url) => {
|
}).then((url) => {
|
||||||
data.icon = url;
|
data.icon = this.sanitizer.bypassSecurityTrustUrl(url);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// Error downloading. If we're online we'll set the online url.
|
// Error downloading. If we're online we'll set the online url.
|
||||||
if (this.appProvider.isOnline()) {
|
if (this.appProvider.isOnline()) {
|
||||||
data.icon = icon;
|
data.icon = this.sanitizer.bypassSecurityTrustUrl(icon);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ export class AddonNotificationsListPage {
|
||||||
// Check if mark all notifications as read is enabled and there are some to read.
|
// Check if mark all notifications as read is enabled and there are some to read.
|
||||||
if (this.notificationsProvider.isMarkAllNotificationsAsReadEnabled()) {
|
if (this.notificationsProvider.isMarkAllNotificationsAsReadEnabled()) {
|
||||||
promises.push(this.notificationsProvider.getUnreadNotificationsCount().then((unread) => {
|
promises.push(this.notificationsProvider.getUnreadNotificationsCount().then((unread) => {
|
||||||
this.canMarkAllNotificationsAsRead = unread > 0
|
this.canMarkAllNotificationsAsRead = unread > 0;
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
this.canMarkAllNotificationsAsRead = false;
|
this.canMarkAllNotificationsAsRead = false;
|
||||||
|
|
|
@ -244,10 +244,10 @@ export class AddonNotificationsProvider {
|
||||||
const params = {
|
const params = {
|
||||||
useridto: this.sitesProvider.getCurrentSiteUserId()
|
useridto: this.sitesProvider.getCurrentSiteUserId()
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.sitesProvider.getCurrentSite().write('core_message_mark_all_notifications_as_read', params);
|
return this.sitesProvider.getCurrentSite().write('core_message_mark_all_notifications_as_read', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark message notification as read.
|
* Mark message notification as read.
|
||||||
*
|
*
|
||||||
|
|
|
@ -109,6 +109,10 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy {
|
||||||
handleCanLeave(): void {
|
handleCanLeave(): void {
|
||||||
// Listen for the didEnter event on the details nav to detect everytime a page is loaded.
|
// Listen for the didEnter event on the details nav to detect everytime a page is loaded.
|
||||||
this.detailsDidEnterSubscription = this.detailNav.viewDidEnter.subscribe((detailsViewController: ViewController) => {
|
this.detailsDidEnterSubscription = this.detailNav.viewDidEnter.subscribe((detailsViewController: ViewController) => {
|
||||||
|
if (!this.isOn()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const masterViewController = this.masterNav.getActive();
|
const masterViewController = this.masterNav.getActive();
|
||||||
|
|
||||||
if (this.masterCanLeaveOverridden) {
|
if (this.masterCanLeaveOverridden) {
|
||||||
|
@ -133,7 +137,7 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
if (this.originalMasterCanLeave) {
|
if (this.originalMasterCanLeave) {
|
||||||
// First call the master canLeave.
|
// First call the master canLeave.
|
||||||
const result = this.originalMasterCanLeave();
|
const result = this.originalMasterCanLeave.apply(masterViewController.instance);
|
||||||
if (typeof result == 'boolean' && !result) {
|
if (typeof result == 'boolean' && !result) {
|
||||||
// User cannot leave, return a rejected promise so the details canLeave isn't executed.
|
// User cannot leave, return a rejected promise so the details canLeave isn't executed.
|
||||||
return Promise.reject(null);
|
return Promise.reject(null);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { NavController, NavOptions } from 'ionic-angular';
|
import { NavController, NavOptions } from 'ionic-angular';
|
||||||
|
import { SafeUrl } from '@angular/platform-browser';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreLoggerProvider } from '@providers/logger';
|
import { CoreLoggerProvider } from '@providers/logger';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
|
@ -77,7 +78,7 @@ export interface CoreCourseModuleHandlerData {
|
||||||
* The image to use as icon (path to the image).
|
* The image to use as icon (path to the image).
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
icon?: string;
|
icon?: string | SafeUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class to assign to the item.
|
* The class to assign to the item.
|
||||||
|
|
|
@ -149,8 +149,11 @@ export class CoreSitePluginsProvider {
|
||||||
* @return {any} An object with the data to pass to the JS.
|
* @return {any} An object with the data to pass to the JS.
|
||||||
*/
|
*/
|
||||||
createDataForJS(initResult: any, contentResult?: any): any {
|
createDataForJS(initResult: any, contentResult?: any): any {
|
||||||
|
let data;
|
||||||
|
|
||||||
|
if (initResult) {
|
||||||
// First of all, add the data returned by the init JS (if any).
|
// First of all, add the data returned by the init JS (if any).
|
||||||
let data = this.utils.clone(initResult.jsResult || {});
|
data = this.utils.clone(initResult.jsResult || {});
|
||||||
if (typeof data == 'boolean') {
|
if (typeof data == 'boolean') {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
@ -158,6 +161,7 @@ export class CoreSitePluginsProvider {
|
||||||
// Now add some data returned by the init WS call.
|
// Now add some data returned by the init WS call.
|
||||||
data.INIT_TEMPLATES = this.utils.objectToKeyValueMap(initResult.templates, 'id', 'html');
|
data.INIT_TEMPLATES = this.utils.objectToKeyValueMap(initResult.templates, 'id', 'html');
|
||||||
data.INIT_OTHERDATA = initResult.otherdata;
|
data.INIT_OTHERDATA = initResult.otherdata;
|
||||||
|
}
|
||||||
|
|
||||||
if (contentResult) {
|
if (contentResult) {
|
||||||
// Now add the data returned by the content WS call.
|
// Now add the data returned by the content WS call.
|
||||||
|
|
|
@ -125,6 +125,7 @@ export class CoreLocalNotificationsProvider {
|
||||||
this.appDB = appProvider.getDB();
|
this.appDB = appProvider.getDB();
|
||||||
this.appDB.createTablesFromSchema(this.tablesSchema);
|
this.appDB.createTablesFromSchema(this.tablesSchema);
|
||||||
|
|
||||||
|
platform.ready().then(() => {
|
||||||
localNotifications.on('trigger', (notification, state) => {
|
localNotifications.on('trigger', (notification, state) => {
|
||||||
this.trigger(notification);
|
this.trigger(notification);
|
||||||
});
|
});
|
||||||
|
@ -137,6 +138,7 @@ export class CoreLocalNotificationsProvider {
|
||||||
this.notifyClick(data);
|
this.notifyClick(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
eventsProvider.on(CoreEventsProvider.SITE_DELETED, (site) => {
|
eventsProvider.on(CoreEventsProvider.SITE_DELETED, (site) => {
|
||||||
if (site) {
|
if (site) {
|
||||||
|
|
|
@ -149,6 +149,9 @@ $tabs-ios-tab-color-inactive: $tabs-tab-color-inactive;
|
||||||
$button-ios-outline-background-color: $core-button-outline-background-color;
|
$button-ios-outline-background-color: $core-button-outline-background-color;
|
||||||
$toolbar-ios-height: 44px + 8; // Avoid toolbar with different heights.
|
$toolbar-ios-height: 44px + 8; // Avoid toolbar with different heights.
|
||||||
$checkbox-ios-icon-border-radius: 0px !default;
|
$checkbox-ios-icon-border-radius: 0px !default;
|
||||||
|
$radio-ios-disabled-opacity: .5 !default;
|
||||||
|
$checkbox-ios-disabled-opacity: .5 !default;
|
||||||
|
$toggle-ios-disabled-opacity: .5 !default;
|
||||||
|
|
||||||
// App Material Design Variables
|
// App Material Design Variables
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
@ -163,6 +166,9 @@ $spinner-md-crescent-color: $core-spinner-color;
|
||||||
$tabs-md-tab-color-inactive: $tabs-tab-color-inactive;
|
$tabs-md-tab-color-inactive: $tabs-tab-color-inactive;
|
||||||
$button-md-outline-background-color: $core-button-outline-background-color;
|
$button-md-outline-background-color: $core-button-outline-background-color;
|
||||||
$font-family-md-base: "Roboto", "Noto Sans", "Helvetica Neue", sans-serif !default;
|
$font-family-md-base: "Roboto", "Noto Sans", "Helvetica Neue", sans-serif !default;
|
||||||
|
$radio-md-disabled-opacity: .5 !default;
|
||||||
|
$checkbox-md-disabled-opacity: .5 !default;
|
||||||
|
$toggle-md-disabled-opacity: .5 !default;
|
||||||
|
|
||||||
// App Windows Variables
|
// App Windows Variables
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
@ -175,7 +181,9 @@ $loading-wp-spinner-color: $core-loading-spinner-color;
|
||||||
$spinner-wp-circles-color: $core-spinner-color;
|
$spinner-wp-circles-color: $core-spinner-color;
|
||||||
$tabs-wp-tab-color-inactive: $tabs-tab-color-inactive;
|
$tabs-wp-tab-color-inactive: $tabs-tab-color-inactive;
|
||||||
$button-wp-outline-background-color: $core-button-outline-background-color;
|
$button-wp-outline-background-color: $core-button-outline-background-color;
|
||||||
|
$radio-wp-disabled-opacity: .5 !default;
|
||||||
|
$checkbox-wp-disabled-opacity: .5 !default;
|
||||||
|
$toggle-wp-disabled-opacity: .5 !default;
|
||||||
|
|
||||||
// App Theme
|
// App Theme
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue