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