commit
5b45d4a335
|
@ -96,6 +96,7 @@
|
||||||
"addon.calendar.errorloadevents": "local_moodlemobileapp",
|
"addon.calendar.errorloadevents": "local_moodlemobileapp",
|
||||||
"addon.calendar.eventduration": "calendar",
|
"addon.calendar.eventduration": "calendar",
|
||||||
"addon.calendar.eventendtime": "calendar",
|
"addon.calendar.eventendtime": "calendar",
|
||||||
|
"addon.calendar.eventkind": "calendar",
|
||||||
"addon.calendar.eventname": "calendar",
|
"addon.calendar.eventname": "calendar",
|
||||||
"addon.calendar.eventstarttime": "calendar",
|
"addon.calendar.eventstarttime": "calendar",
|
||||||
"addon.calendar.eventtype": "calendar",
|
"addon.calendar.eventtype": "calendar",
|
||||||
|
@ -106,6 +107,9 @@
|
||||||
"addon.calendar.noevents": "local_moodlemobileapp",
|
"addon.calendar.noevents": "local_moodlemobileapp",
|
||||||
"addon.calendar.nopermissiontoupdatecalendar": "error",
|
"addon.calendar.nopermissiontoupdatecalendar": "error",
|
||||||
"addon.calendar.reminders": "local_moodlemobileapp",
|
"addon.calendar.reminders": "local_moodlemobileapp",
|
||||||
|
"addon.calendar.repeatedevents": "calendar",
|
||||||
|
"addon.calendar.repeateditall": "calendar",
|
||||||
|
"addon.calendar.repeateditthis": "calendar",
|
||||||
"addon.calendar.repeatevent": "calendar",
|
"addon.calendar.repeatevent": "calendar",
|
||||||
"addon.calendar.repeatweeksl": "calendar",
|
"addon.calendar.repeatweeksl": "calendar",
|
||||||
"addon.calendar.setnewreminder": "local_moodlemobileapp",
|
"addon.calendar.setnewreminder": "local_moodlemobileapp",
|
||||||
|
@ -1490,6 +1494,7 @@
|
||||||
"core.image": "local_moodlemobileapp",
|
"core.image": "local_moodlemobileapp",
|
||||||
"core.imageviewer": "local_moodlemobileapp",
|
"core.imageviewer": "local_moodlemobileapp",
|
||||||
"core.info": "moodle",
|
"core.info": "moodle",
|
||||||
|
"core.invalidformdata": "error",
|
||||||
"core.ios": "local_moodlemobileapp",
|
"core.ios": "local_moodlemobileapp",
|
||||||
"core.labelsep": "langconfig",
|
"core.labelsep": "langconfig",
|
||||||
"core.lastaccess": "moodle",
|
"core.lastaccess": "moodle",
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"errorloadevents": "Error loading events.",
|
"errorloadevents": "Error loading events.",
|
||||||
"eventduration": "Duration",
|
"eventduration": "Duration",
|
||||||
"eventendtime": "End time",
|
"eventendtime": "End time",
|
||||||
|
"eventkind": "Type of event",
|
||||||
"eventname": "Event title",
|
"eventname": "Event title",
|
||||||
"eventstarttime": "Start time",
|
"eventstarttime": "Start time",
|
||||||
"eventtype": "Event type",
|
"eventtype": "Event type",
|
||||||
|
@ -22,6 +23,9 @@
|
||||||
"noevents": "There are no events",
|
"noevents": "There are no events",
|
||||||
"nopermissiontoupdatecalendar": "Sorry, but you do not have permission to update the calendar event",
|
"nopermissiontoupdatecalendar": "Sorry, but you do not have permission to update the calendar event",
|
||||||
"reminders": "Reminders",
|
"reminders": "Reminders",
|
||||||
|
"repeatedevents": "Repeated events",
|
||||||
|
"repeateditall": "Also apply changes to the other {{$a}} events in this repeat series",
|
||||||
|
"repeateditthis": "Apply changes to this event only",
|
||||||
"repeatevent": "Repeat this event",
|
"repeatevent": "Repeat this event",
|
||||||
"repeatweeksl": "Repeat weekly, creating altogether",
|
"repeatweeksl": "Repeat weekly, creating altogether",
|
||||||
"setnewreminder": "Set a new reminder",
|
"setnewreminder": "Set a new reminder",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-navbar core-back-button>
|
<ion-navbar core-back-button>
|
||||||
<ion-title><core-format-text [text]="title | translate"></core-format-text></ion-title>
|
<ion-title>{{ title | translate }}</ion-title>
|
||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<form ion-list [formGroup]="eventForm">
|
<form ion-list [formGroup]="eventForm" *ngIf="!error">
|
||||||
<!-- 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>
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
<!-- Type. -->
|
<!-- Type. -->
|
||||||
<ion-item text-wrap class="addon-calendar-eventtype-container">
|
<ion-item text-wrap class="addon-calendar-eventtype-container">
|
||||||
<ion-label id="addon-calendar-eventtype-label"><h2 [core-mark-required]="true">{{ 'addon.calendar.eventtype' | translate }}</h2></ion-label>
|
<ion-label id="addon-calendar-eventtype-label"><h2 [core-mark-required]="true">{{ 'addon.calendar.eventkind' | translate }}</h2></ion-label>
|
||||||
<ion-select [formControlName]="'eventtype'" aria-labelledby="addon-calendar-eventtype-label" interface="action-sheet" [disabled]="eventTypes.length == 1">
|
<ion-select [formControlName]="'eventtype'" aria-labelledby="addon-calendar-eventtype-label" interface="action-sheet" [disabled]="eventTypes.length == 1">
|
||||||
<ion-option *ngFor="let type of eventTypes" [value]="type.value">{{ type.name | translate }}</ion-option>
|
<ion-option *ngFor="let type of eventTypes" [value]="type.value">{{ type.name | translate }}</ion-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
<ion-item text-wrap *ngIf="eventTypeControl.value == 'course'">
|
<ion-item text-wrap *ngIf="eventTypeControl.value == 'course'">
|
||||||
<ion-label id="addon-calendar-course-label"><h2 [core-mark-required]="true">{{ 'core.course' | translate }}</h2></ion-label>
|
<ion-label id="addon-calendar-course-label"><h2 [core-mark-required]="true">{{ 'core.course' | translate }}</h2></ion-label>
|
||||||
<ion-select [formControlName]="'courseid'" aria-labelledby="addon-calendar-course-label" interface="action-sheet" [placeholder]="'core.noselection' | translate">
|
<ion-select [formControlName]="'courseid'" aria-labelledby="addon-calendar-course-label" interface="action-sheet" [placeholder]="'core.noselection' | translate">
|
||||||
<ion-option *ngFor="let course of courses" [value]="course.id"><core-format-text [text]="course.fullname"></core-format-text></ion-option>
|
<ion-option *ngFor="let course of courses" [value]="course.id">{{ course.fullname }}</ion-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
<ion-item text-wrap>
|
<ion-item text-wrap>
|
||||||
<ion-label id="addon-calendar-groupcourse-label"><h2 [core-mark-required]="true">{{ 'core.course' | translate }}</h2></ion-label>
|
<ion-label id="addon-calendar-groupcourse-label"><h2 [core-mark-required]="true">{{ 'core.course' | translate }}</h2></ion-label>
|
||||||
<ion-select [formControlName]="'groupcourseid'" aria-labelledby="addon-calendar-groupcourse-label" interface="action-sheet" [placeholder]="'core.noselection' | translate" (ionChange)="groupCourseSelected($event)">
|
<ion-select [formControlName]="'groupcourseid'" aria-labelledby="addon-calendar-groupcourse-label" interface="action-sheet" [placeholder]="'core.noselection' | translate" (ionChange)="groupCourseSelected($event)">
|
||||||
<ion-option *ngFor="let course of courses" [value]="course.id"><core-format-text [text]="course.fullname"></core-format-text></ion-option>
|
<ion-option *ngFor="let course of courses" [value]="course.id">{{ course.fullname }}</ion-option>
|
||||||
</ion-select>
|
</ion-select>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<!-- The course has no groups. -->
|
<!-- The course has no groups. -->
|
||||||
|
@ -96,8 +96,8 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Duration. -->
|
<!-- Duration. -->
|
||||||
<div text-wrap radio-group [formControlName]="'duration'" class="addon-calendar-duration-container">
|
<div text-wrap radio-group [formControlName]="'duration'" class="addon-calendar-radio-container">
|
||||||
<ion-item class="addon-calendar-duration-title"><h2>{{ 'addon.calendar.eventduration' | translate }}</h2></ion-item>
|
<ion-item class="addon-calendar-radio-title"><h2>{{ 'addon.calendar.eventduration' | translate }}</h2></ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>{{ 'addon.calendar.durationnone' | translate }}</ion-label>
|
<ion-label>{{ 'addon.calendar.durationnone' | translate }}</ion-label>
|
||||||
<ion-radio [value]="0"></ion-radio>
|
<ion-radio [value]="0"></ion-radio>
|
||||||
|
@ -118,15 +118,30 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Repeat. -->
|
<!-- Repeat (for new events). -->
|
||||||
<ion-item text-wrap>
|
<ng-container *ngIf="!eventId || eventId < 0">
|
||||||
<ion-label><h2>{{ 'addon.calendar.repeatevent' | translate }}</h2></ion-label>
|
<ion-item text-wrap>
|
||||||
<ion-checkbox item-end [formControlName]="'repeat'"></ion-checkbox>
|
<ion-label><h2>{{ 'addon.calendar.repeatevent' | translate }}</h2></ion-label>
|
||||||
</ion-item>
|
<ion-checkbox item-end [formControlName]="'repeat'"></ion-checkbox>
|
||||||
<ion-item text-wrap *ngIf="eventForm.controls.repeat.value">
|
</ion-item>
|
||||||
<ion-label stacked><h2>{{ 'addon.calendar.repeatweeksl' | translate }}</h2></ion-label>
|
<ion-item text-wrap *ngIf="eventForm.controls.repeat.value">
|
||||||
<ion-input type="number" name="repeats" [formControlName]="'repeats'"></ion-input>
|
<ion-label stacked><h2>{{ 'addon.calendar.repeatweeksl' | translate }}</h2></ion-label>
|
||||||
</ion-item>
|
<ion-input type="number" name="repeats" [formControlName]="'repeats'"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Apply to all events or just this one (editing repeated events). -->
|
||||||
|
<div *ngIf="event && event.repeatid" text-wrap radio-group [formControlName]="'repeateditall'" class="addon-calendar-radio-container">
|
||||||
|
<ion-item class="addon-calendar-radio-title"><h2>{{ 'addon.calendar.repeatedevents' | translate }}</h2></ion-item>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>{{ 'addon.calendar.repeateditall' | translate:{$a: event.othereventscount} }}</ion-label>
|
||||||
|
<ion-radio [value]="1"></ion-radio>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>{{ 'addon.calendar.repeateditthis' | translate }}</ion-label>
|
||||||
|
<ion-radio [value]="0"></ion-radio>
|
||||||
|
</ion-item>
|
||||||
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
|
@ -134,7 +149,7 @@
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<button ion-button block (click)="submit()" [disabled]="!eventForm.valid">{{ 'core.save' | translate }}</button>
|
<button ion-button block (click)="submit()" [disabled]="!eventForm.valid">{{ 'core.save' | translate }}</button>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col *ngIf="hasOffline">
|
<ion-col *ngIf="hasOffline && eventId < 0">
|
||||||
<button ion-button block color="light" (click)="discard()">{{ 'core.discard' | translate }}</button>
|
<button ion-button block color="light" (click)="discard()">{{ 'core.discard' | translate }}</button>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
ion-app.app-root page-addon-calendar-edit-event {
|
ion-app.app-root page-addon-calendar-edit-event {
|
||||||
.addon-calendar-duration-container ion-item:not(.addon-calendar-duration-title) {
|
.addon-calendar-radio-container ion-item:not(.addon-calendar-radio-title) {
|
||||||
&.item-ios {
|
&.item-ios {
|
||||||
@include padding-horizontal($item-ios-padding-start * 2, null);
|
@include padding-horizontal($item-ios-padding-start * 2, null);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { CoreGroupsProvider } from '@providers/groups';
|
||||||
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';
|
||||||
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||||
|
@ -57,6 +58,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
courseGroupSet = false;
|
courseGroupSet = false;
|
||||||
advanced = false;
|
advanced = false;
|
||||||
errors: any;
|
errors: any;
|
||||||
|
event: any; // The event object (when editing an event).
|
||||||
|
|
||||||
// Form variables.
|
// Form variables.
|
||||||
eventForm: FormGroup;
|
eventForm: FormGroup;
|
||||||
|
@ -71,11 +73,14 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
protected types: any; // Object with the supported types.
|
protected types: any; // Object with the supported types.
|
||||||
protected showAll: boolean;
|
protected showAll: boolean;
|
||||||
protected isDestroyed = false;
|
protected isDestroyed = false;
|
||||||
|
protected error = false;
|
||||||
|
protected gotEventData = false;
|
||||||
|
|
||||||
constructor(navParams: NavParams,
|
constructor(navParams: NavParams,
|
||||||
private navCtrl: NavController,
|
private navCtrl: NavController,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private domUtils: CoreDomUtilsProvider,
|
private domUtils: CoreDomUtilsProvider,
|
||||||
|
private textUtils: CoreTextUtilsProvider,
|
||||||
private timeUtils: CoreTimeUtilsProvider,
|
private timeUtils: CoreTimeUtilsProvider,
|
||||||
private eventsProvider: CoreEventsProvider,
|
private eventsProvider: CoreEventsProvider,
|
||||||
private groupsProvider: CoreGroupsProvider,
|
private groupsProvider: CoreGroupsProvider,
|
||||||
|
@ -125,6 +130,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
this.eventForm.addControl('timedurationminutes', this.fb.control(''));
|
this.eventForm.addControl('timedurationminutes', this.fb.control(''));
|
||||||
this.eventForm.addControl('repeat', this.fb.control(false));
|
this.eventForm.addControl('repeat', this.fb.control(false));
|
||||||
this.eventForm.addControl('repeats', this.fb.control('1'));
|
this.eventForm.addControl('repeats', this.fb.control('1'));
|
||||||
|
this.eventForm.addControl('repeateditall', this.fb.control(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,6 +152,8 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
protected fetchData(refresh?: boolean): Promise<any> {
|
protected fetchData(refresh?: boolean): Promise<any> {
|
||||||
let accessInfo;
|
let accessInfo;
|
||||||
|
|
||||||
|
this.error = false;
|
||||||
|
|
||||||
// Get access info.
|
// Get access info.
|
||||||
return this.calendarProvider.getAccessInformation(this.courseId).then((info) => {
|
return this.calendarProvider.getAccessInformation(this.courseId).then((info) => {
|
||||||
accessInfo = info;
|
accessInfo = info;
|
||||||
|
@ -161,8 +169,8 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
return Promise.reject(this.translate.instant('addon.calendar.nopermissiontoupdatecalendar'));
|
return Promise.reject(this.translate.instant('addon.calendar.nopermissiontoupdatecalendar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.eventId && !refresh) {
|
if (this.eventId && !this.gotEventData) {
|
||||||
// If editing an event, get offline data. Wait for sync first.
|
// Editing an event, get the event data. Wait for sync first.
|
||||||
|
|
||||||
promises.push(this.calendarSync.waitForSync(AddonCalendarSyncProvider.SYNC_ID).then(() => {
|
promises.push(this.calendarSync.waitForSync(AddonCalendarSyncProvider.SYNC_ID).then(() => {
|
||||||
// Do not block if the scope is already destroyed.
|
// Do not block if the scope is already destroyed.
|
||||||
|
@ -170,29 +178,39 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
this.syncProvider.blockOperation(AddonCalendarProvider.COMPONENT, this.eventId);
|
this.syncProvider.blockOperation(AddonCalendarProvider.COMPONENT, this.eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the event data if there's any.
|
const promises = [];
|
||||||
return this.calendarOffline.getEvent(this.eventId).then((event) => {
|
|
||||||
|
// Get the event offline data if there's any.
|
||||||
|
promises.push(this.calendarOffline.getEvent(this.eventId).then((event) => {
|
||||||
this.hasOffline = true;
|
this.hasOffline = true;
|
||||||
|
|
||||||
// Load the data in the form.
|
return event;
|
||||||
this.eventForm.controls.name.setValue(event.name);
|
|
||||||
this.eventForm.controls.timestart.setValue(this.timeUtils.toDatetimeFormat(event.timestart * 1000));
|
|
||||||
this.eventForm.controls.eventtype.setValue(event.eventtype);
|
|
||||||
this.eventForm.controls.categoryid.setValue(event.categoryid || '');
|
|
||||||
this.eventForm.controls.courseid.setValue(event.courseid || '');
|
|
||||||
this.eventForm.controls.groupcourseid.setValue(event.groupcourseid || '');
|
|
||||||
this.eventForm.controls.groupid.setValue(event.groupid || '');
|
|
||||||
this.eventForm.controls.description.setValue(event.description);
|
|
||||||
this.eventForm.controls.location.setValue(event.location);
|
|
||||||
this.eventForm.controls.duration.setValue(event.duration);
|
|
||||||
this.eventForm.controls.timedurationuntil.setValue(
|
|
||||||
this.timeUtils.toDatetimeFormat((event.timedurationuntil * 1000) || Date.now()));
|
|
||||||
this.eventForm.controls.timedurationminutes.setValue(event.timedurationminutes || '');
|
|
||||||
this.eventForm.controls.repeat.setValue(!!event.repeat);
|
|
||||||
this.eventForm.controls.repeats.setValue(event.repeats || '1');
|
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// No offline data.
|
// No offline data.
|
||||||
this.hasOffline = false;
|
this.hasOffline = false;
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (this.eventId > 0) {
|
||||||
|
// It's an online event. get its data from server.
|
||||||
|
promises.push(this.calendarProvider.getEventById(this.eventId).then((event) => {
|
||||||
|
this.event = event;
|
||||||
|
if (event && event.repeatid) {
|
||||||
|
event.othereventscount = event.eventcount ? event.eventcount - 1 : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(promises).then((result) => {
|
||||||
|
this.gotEventData = true;
|
||||||
|
|
||||||
|
const event = result[0] || result[1]; // Use offline data first.
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
// Load the data in the form.
|
||||||
|
return this.loadEventData(event, !!result[0]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -220,12 +238,24 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort courses by name.
|
// Format the name of the courses.
|
||||||
this.courses = courses.sort((a, b) => {
|
const subPromises = [];
|
||||||
const compareA = a.fullname.toLowerCase(),
|
courses.forEach((course) => {
|
||||||
compareB = b.fullname.toLowerCase();
|
subPromises.push(this.textUtils.formatText(course.fullname).then((text) => {
|
||||||
|
course.fullname = text;
|
||||||
|
}).catch(() => {
|
||||||
|
// Ignore errors.
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
return compareA.localeCompare(compareB);
|
return Promise.all(subPromises).then(() => {
|
||||||
|
// Sort courses by name.
|
||||||
|
this.courses = courses.sort((a, b) => {
|
||||||
|
const compareA = a.fullname.toLowerCase(),
|
||||||
|
compareB = b.fullname.toLowerCase();
|
||||||
|
|
||||||
|
return compareA.localeCompare(compareB);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -245,11 +275,70 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
this.domUtils.showErrorModalDefault(error, 'Error getting data.');
|
this.domUtils.showErrorModalDefault(error, 'Error getting data.');
|
||||||
this.originalData = null; // Avoid asking for confirmation.
|
this.error = true;
|
||||||
this.navCtrl.pop();
|
|
||||||
|
if (!this.svComponent || !this.svComponent.isOn()) {
|
||||||
|
this.originalData = null; // Avoid asking for confirmation.
|
||||||
|
this.navCtrl.pop();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an event data into the form.
|
||||||
|
*
|
||||||
|
* @param {any} event Event data.
|
||||||
|
* @param {boolean} isOffline Whether the data is from offline or not.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected loadEventData(event: any, isOffline: boolean): Promise<any> {
|
||||||
|
const courseId = event.course ? event.course.id : event.courseid;
|
||||||
|
|
||||||
|
this.eventForm.controls.name.setValue(event.name);
|
||||||
|
this.eventForm.controls.timestart.setValue(this.timeUtils.toDatetimeFormat(event.timestart * 1000));
|
||||||
|
this.eventForm.controls.eventtype.setValue(event.eventtype);
|
||||||
|
this.eventForm.controls.categoryid.setValue(event.categoryid || '');
|
||||||
|
this.eventForm.controls.courseid.setValue(courseId || '');
|
||||||
|
this.eventForm.controls.groupcourseid.setValue(event.groupcourseid || courseId || '');
|
||||||
|
this.eventForm.controls.groupid.setValue(event.groupid || '');
|
||||||
|
this.eventForm.controls.description.setValue(event.description);
|
||||||
|
this.eventForm.controls.location.setValue(event.location);
|
||||||
|
|
||||||
|
if (isOffline) {
|
||||||
|
// It's an offline event, use the data as it is.
|
||||||
|
this.eventForm.controls.duration.setValue(event.duration);
|
||||||
|
this.eventForm.controls.timedurationuntil.setValue(
|
||||||
|
this.timeUtils.toDatetimeFormat((event.timedurationuntil * 1000) || Date.now()));
|
||||||
|
this.eventForm.controls.timedurationminutes.setValue(event.timedurationminutes || '');
|
||||||
|
this.eventForm.controls.repeat.setValue(!!event.repeat);
|
||||||
|
this.eventForm.controls.repeats.setValue(event.repeats || '1');
|
||||||
|
this.eventForm.controls.repeateditall.setValue(event.repeateditall || 1);
|
||||||
|
} else {
|
||||||
|
// Online event, we'll have to calculate the data.
|
||||||
|
|
||||||
|
if (event.timeduration > 0) {
|
||||||
|
this.eventForm.controls.duration.setValue(1);
|
||||||
|
this.eventForm.controls.timedurationuntil.setValue(this.timeUtils.toDatetimeFormat(
|
||||||
|
(event.timestart + event.timeduration) * 1000));
|
||||||
|
} else {
|
||||||
|
// No duration.
|
||||||
|
this.eventForm.controls.duration.setValue(0);
|
||||||
|
this.eventForm.controls.timedurationuntil.setValue(this.timeUtils.toDatetimeFormat());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eventForm.controls.timedurationminutes.setValue('');
|
||||||
|
this.eventForm.controls.repeat.setValue(!!event.repeatid);
|
||||||
|
this.eventForm.controls.repeats.setValue(event.eventcount || '1');
|
||||||
|
this.eventForm.controls.repeateditall.setValue(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.eventtype == 'group' && courseId) {
|
||||||
|
return this.loadGroups(courseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pull to refresh.
|
* Pull to refresh.
|
||||||
*
|
*
|
||||||
|
@ -292,20 +381,33 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
const modal = this.domUtils.showModalLoading();
|
const modal = this.domUtils.showModalLoading();
|
||||||
this.loadingGroups = true;
|
|
||||||
|
|
||||||
this.groupsProvider.getUserGroupsInCourse(courseId).then((groups) => {
|
this.loadGroups(courseId).then(() => {
|
||||||
this.groups = groups;
|
|
||||||
this.courseGroupSet = true;
|
|
||||||
this.groupControl.setValue('');
|
this.groupControl.setValue('');
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
this.domUtils.showErrorModalDefault(error, 'Error getting data.');
|
this.domUtils.showErrorModalDefault(error, 'Error getting data.');
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loadingGroups = false;
|
|
||||||
modal.dismiss();
|
modal.dismiss();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load groups of a certain course.
|
||||||
|
*
|
||||||
|
* @param {number} courseId Course ID.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected loadGroups(courseId: number): Promise<any> {
|
||||||
|
this.loadingGroups = true;
|
||||||
|
|
||||||
|
return this.groupsProvider.getUserGroupsInCourse(courseId).then((groups) => {
|
||||||
|
this.groups = groups;
|
||||||
|
this.courseGroupSet = true;
|
||||||
|
}).finally(() => {
|
||||||
|
this.loadingGroups = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show or hide advanced form fields.
|
* Show or hide advanced form fields.
|
||||||
*/
|
*/
|
||||||
|
@ -378,8 +480,13 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
data.repeats = formData.repeats;
|
data.repeats = formData.repeats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.event && this.event.repeatid) {
|
||||||
|
data.repeatid = this.event.repeatid;
|
||||||
|
data.repeateditall = formData.repeateditall;
|
||||||
|
}
|
||||||
|
|
||||||
// Send the data.
|
// Send the data.
|
||||||
const modal = this.domUtils.showModalLoading('core.sending');
|
const modal = this.domUtils.showModalLoading('core.sending', true);
|
||||||
|
|
||||||
this.calendarProvider.submitEvent(this.eventId, data).then((result) => {
|
this.calendarProvider.submitEvent(this.eventId, data).then((result) => {
|
||||||
this.returnToList(result.event);
|
this.returnToList(result.event);
|
||||||
|
@ -399,13 +506,21 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
||||||
// Unblock the sync because the view will be destroyed and the sync process could be triggered before ngOnDestroy.
|
// Unblock the sync because the view will be destroyed and the sync process could be triggered before ngOnDestroy.
|
||||||
this.unblockSync();
|
this.unblockSync();
|
||||||
|
|
||||||
if (event) {
|
if (this.eventId > 0) {
|
||||||
|
// Editing an event.
|
||||||
const data: any = {
|
const data: any = {
|
||||||
event: event
|
event: event
|
||||||
};
|
};
|
||||||
this.eventsProvider.trigger(AddonCalendarProvider.NEW_EVENT_EVENT, data, this.currentSite.getId());
|
this.eventsProvider.trigger(AddonCalendarProvider.EDIT_EVENT_EVENT, data, this.currentSite.getId());
|
||||||
} else {
|
} else {
|
||||||
this.eventsProvider.trigger(AddonCalendarProvider.NEW_EVENT_DISCARDED_EVENT, {}, this.currentSite.getId());
|
if (event) {
|
||||||
|
const data: any = {
|
||||||
|
event: event
|
||||||
|
};
|
||||||
|
this.eventsProvider.trigger(AddonCalendarProvider.NEW_EVENT_EVENT, data, this.currentSite.getId());
|
||||||
|
} else {
|
||||||
|
this.eventsProvider.trigger(AddonCalendarProvider.NEW_EVENT_DISCARDED_EVENT, {}, this.currentSite.getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.svComponent && this.svComponent.isOn()) {
|
if (this.svComponent && this.svComponent.isOn()) {
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-navbar core-back-button>
|
<ion-navbar core-back-button>
|
||||||
<ion-title><core-format-text [text]="title"></core-format-text></ion-title>
|
<ion-title><core-format-text [text]="title"></core-format-text></ion-title>
|
||||||
|
<ion-buttons end>
|
||||||
|
<!-- The context menu will be added in here. -->
|
||||||
|
</ion-buttons>
|
||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
<core-navbar-buttons end>
|
||||||
|
<core-context-menu>
|
||||||
|
<core-context-menu-item [hidden]="isSplitViewOn || !eventLoaded || !hasOffline || !isOnline" [priority]="400" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
|
<core-context-menu-item [hidden]="!canEdit || !event || !event.canedit" [priority]="300" [content]="'core.edit' | translate" (action)="openEdit()" [iconAction]="'create'"></core-context-menu-item>
|
||||||
|
</core-context-menu>
|
||||||
|
</core-navbar-buttons>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-refresher [enabled]="eventLoaded" (ionRefresh)="refreshEvent($event)">
|
<ion-refresher [enabled]="eventLoaded" (ionRefresh)="doRefresh($event)">
|
||||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<core-loading [hideUntil]="eventLoaded">
|
<core-loading [hideUntil]="eventLoaded">
|
||||||
|
<!-- There is data to be synchronized -->
|
||||||
|
<ion-card class="core-warning-card" icon-start *ngIf="hasOffline">
|
||||||
|
<ion-icon name="warning"></ion-icon> {{ 'core.hasdatatosync' | translate:{$a: 'addon.calendar.calendarevent' | translate} }}
|
||||||
|
</ion-card>
|
||||||
|
|
||||||
<ion-card>
|
<ion-card>
|
||||||
<ion-card-content *ngIf="event">
|
<ion-card-content *ngIf="event">
|
||||||
<ion-item text-wrap>
|
<ion-item text-wrap>
|
||||||
|
@ -26,10 +40,10 @@
|
||||||
<h2>{{ 'core.course' | translate}}</h2>
|
<h2>{{ 'core.course' | translate}}</h2>
|
||||||
<p><core-format-text [text]="courseName"></core-format-text></p>
|
<p><core-format-text [text]="courseName"></core-format-text></p>
|
||||||
</a>
|
</a>
|
||||||
<a ion-item text-wrap *ngIf="groupName">
|
<ion-item text-wrap *ngIf="groupName">
|
||||||
<h2>{{ 'core.group' | translate}}</h2>
|
<h2>{{ 'core.group' | translate}}</h2>
|
||||||
<p>{{ groupName }}</p>
|
<p>{{ groupName }}</p>
|
||||||
</a>
|
</ion-item>
|
||||||
<a ion-item text-wrap *ngIf="categoryPath">
|
<a ion-item text-wrap *ngIf="categoryPath">
|
||||||
<h2>{{ 'core.category' | translate}}</h2>
|
<h2>{{ 'core.category' | translate}}</h2>
|
||||||
<p><core-format-text [text]="categoryPath"></core-format-text></p>
|
<p><core-format-text [text]="categoryPath"></core-format-text></p>
|
||||||
|
|
|
@ -12,12 +12,16 @@
|
||||||
// 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, Optional, OnDestroy, NgZone } from '@angular/core';
|
||||||
import { IonicPage, Content, NavParams } from 'ionic-angular';
|
import { IonicPage, Content, NavParams, NavController } from 'ionic-angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { AddonCalendarProvider } from '../../providers/calendar';
|
import { AddonCalendarProvider } from '../../providers/calendar';
|
||||||
import { AddonCalendarHelperProvider } from '../../providers/helper';
|
import { AddonCalendarHelperProvider } from '../../providers/helper';
|
||||||
|
import { AddonCalendarOfflineProvider } from '../../providers/calendar-offline';
|
||||||
|
import { AddonCalendarSyncProvider } from '../../providers/calendar-sync';
|
||||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||||
|
import { CoreAppProvider } from '@providers/app';
|
||||||
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
|
@ -25,6 +29,8 @@ import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||||
import { CoreGroupsProvider } from '@providers/groups';
|
import { CoreGroupsProvider } from '@providers/groups';
|
||||||
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
|
import { Network } from '@ionic-native/network';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a single calendar event.
|
* Page that displays a single calendar event.
|
||||||
|
@ -34,11 +40,17 @@ import { CoreGroupsProvider } from '@providers/groups';
|
||||||
selector: 'page-addon-calendar-event',
|
selector: 'page-addon-calendar-event',
|
||||||
templateUrl: 'event.html',
|
templateUrl: 'event.html',
|
||||||
})
|
})
|
||||||
export class AddonCalendarEventPage {
|
export class AddonCalendarEventPage implements OnDestroy {
|
||||||
@ViewChild(Content) content: Content;
|
@ViewChild(Content) content: Content;
|
||||||
|
|
||||||
protected eventId;
|
protected eventId;
|
||||||
protected siteHomeId: number;
|
protected siteHomeId: number;
|
||||||
|
protected editEventObserver: any;
|
||||||
|
protected syncObserver: any;
|
||||||
|
protected manualSyncObserver: any;
|
||||||
|
protected onlineObserver: any;
|
||||||
|
protected currentSiteId: string;
|
||||||
|
|
||||||
eventLoaded: boolean;
|
eventLoaded: boolean;
|
||||||
notificationFormat: string;
|
notificationFormat: string;
|
||||||
notificationMin: string;
|
notificationMin: string;
|
||||||
|
@ -55,17 +67,31 @@ export class AddonCalendarEventPage {
|
||||||
currentTime: number;
|
currentTime: number;
|
||||||
defaultTime: number;
|
defaultTime: number;
|
||||||
reminders: any[];
|
reminders: any[];
|
||||||
|
canEdit = false;
|
||||||
|
hasOffline = false;
|
||||||
|
isOnline = false;
|
||||||
|
syncIcon: string; // Sync icon.
|
||||||
|
isSplitViewOn = false;
|
||||||
|
|
||||||
constructor(private translate: TranslateService, private calendarProvider: AddonCalendarProvider, navParams: NavParams,
|
constructor(private translate: TranslateService, private calendarProvider: AddonCalendarProvider, navParams: NavParams,
|
||||||
private domUtils: CoreDomUtilsProvider, private coursesProvider: CoreCoursesProvider,
|
private domUtils: CoreDomUtilsProvider, private coursesProvider: CoreCoursesProvider,
|
||||||
private calendarHelper: AddonCalendarHelperProvider, private sitesProvider: CoreSitesProvider,
|
private calendarHelper: AddonCalendarHelperProvider, private sitesProvider: CoreSitesProvider,
|
||||||
localNotificationsProvider: CoreLocalNotificationsProvider, private courseProvider: CoreCourseProvider,
|
localNotificationsProvider: CoreLocalNotificationsProvider, private courseProvider: CoreCourseProvider,
|
||||||
private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider,
|
private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider,
|
||||||
private groupsProvider: CoreGroupsProvider) {
|
private groupsProvider: CoreGroupsProvider, @Optional() private svComponent: CoreSplitViewComponent,
|
||||||
|
private navCtrl: NavController, private eventsProvider: CoreEventsProvider, network: Network, zone: NgZone,
|
||||||
|
private calendarSync: AddonCalendarSyncProvider, private appProvider: CoreAppProvider,
|
||||||
|
private calendarOffline: AddonCalendarOfflineProvider) {
|
||||||
|
|
||||||
this.eventId = navParams.get('id');
|
this.eventId = navParams.get('id');
|
||||||
this.notificationsEnabled = localNotificationsProvider.isAvailable();
|
this.notificationsEnabled = localNotificationsProvider.isAvailable();
|
||||||
this.siteHomeId = sitesProvider.getCurrentSite().getSiteHomeId();
|
this.siteHomeId = sitesProvider.getCurrentSite().getSiteHomeId();
|
||||||
|
this.currentSiteId = sitesProvider.getCurrentSiteId();
|
||||||
|
this.isSplitViewOn = this.svComponent && this.svComponent.isOn();
|
||||||
|
|
||||||
|
// Check if site supports editing. No need to check allowed types, event.canedit already does it.
|
||||||
|
this.canEdit = this.calendarProvider.canEditEventsInSite();
|
||||||
|
|
||||||
if (this.notificationsEnabled) {
|
if (this.notificationsEnabled) {
|
||||||
this.calendarProvider.getEventReminders(this.eventId).then((reminders) => {
|
this.calendarProvider.getEventReminders(this.eventId).then((reminders) => {
|
||||||
this.reminders = reminders;
|
this.reminders = reminders;
|
||||||
|
@ -79,34 +105,105 @@ export class AddonCalendarEventPage {
|
||||||
this.notificationFormat = this.timeUtils.fixFormatForDatetime(this.timeUtils.convertPHPToMoment(
|
this.notificationFormat = this.timeUtils.fixFormatForDatetime(this.timeUtils.convertPHPToMoment(
|
||||||
this.translate.instant('core.strftimedatetime')));
|
this.translate.instant('core.strftimedatetime')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listen for event edited. If current event is edited, reload the data.
|
||||||
|
this.editEventObserver = eventsProvider.on(AddonCalendarProvider.EDIT_EVENT_EVENT, (data) => {
|
||||||
|
if (data && data.event && data.event.id == this.eventId) {
|
||||||
|
this.eventLoaded = false;
|
||||||
|
this.refreshEvent(true, false);
|
||||||
|
}
|
||||||
|
}, this.currentSiteId);
|
||||||
|
|
||||||
|
// Refresh data if this calendar event is synchronized automatically.
|
||||||
|
this.syncObserver = eventsProvider.on(AddonCalendarSyncProvider.AUTO_SYNCED, this.checkSyncResult.bind(this, false),
|
||||||
|
this.currentSiteId);
|
||||||
|
|
||||||
|
// Refresh data if calendar events are synchronized manually but not by this page.
|
||||||
|
this.manualSyncObserver = eventsProvider.on(AddonCalendarSyncProvider.MANUAL_SYNCED, this.checkSyncResult.bind(this, true),
|
||||||
|
this.currentSiteId);
|
||||||
|
|
||||||
|
// Refresh online status when changes.
|
||||||
|
this.onlineObserver = network.onchange().subscribe((online) => {
|
||||||
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
|
zone.run(() => {
|
||||||
|
this.isOnline = online;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View loaded.
|
* View loaded.
|
||||||
*/
|
*/
|
||||||
ionViewDidLoad(): void {
|
ionViewDidLoad(): void {
|
||||||
this.fetchEvent().finally(() => {
|
this.syncIcon = 'spinner';
|
||||||
this.eventLoaded = true;
|
|
||||||
});
|
this.fetchEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the event and updates the view.
|
* Fetches the event and updates the view.
|
||||||
*
|
*
|
||||||
|
* @param {boolean} [sync] Whether it should try to synchronize offline events.
|
||||||
|
* @param {boolean} [showErrors] Whether to show sync errors to the user.
|
||||||
* @return {Promise<any>} Promise resolved when done.
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
fetchEvent(): Promise<any> {
|
fetchEvent(sync?: boolean, showErrors?: boolean): Promise<any> {
|
||||||
const currentSite = this.sitesProvider.getCurrentSite(),
|
const currentSite = this.sitesProvider.getCurrentSite(),
|
||||||
canGetById = this.calendarProvider.isGetEventByIdAvailable();
|
canGetById = this.calendarProvider.isGetEventByIdAvailable();
|
||||||
let promise;
|
let promise;
|
||||||
|
|
||||||
if (canGetById) {
|
this.isOnline = this.appProvider.isOnline();
|
||||||
promise = this.calendarProvider.getEventById(this.eventId);
|
|
||||||
|
if (sync) {
|
||||||
|
// Try to synchronize offline events.
|
||||||
|
promise = this.calendarSync.syncEvents().then((result) => {
|
||||||
|
if (result.warnings && result.warnings.length) {
|
||||||
|
this.domUtils.showErrorModal(result.warnings[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.updated) {
|
||||||
|
// Trigger a manual sync event.
|
||||||
|
result.source = 'event';
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(AddonCalendarSyncProvider.MANUAL_SYNCED, result, this.currentSiteId);
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
if (showErrors) {
|
||||||
|
this.domUtils.showErrorModalDefault(error, 'core.errorsync', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
promise = this.calendarProvider.getEvent(this.eventId);
|
promise = Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then((event) => {
|
return promise.then(() => {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
// Get the event data.
|
||||||
|
if (canGetById) {
|
||||||
|
promises.push(this.calendarProvider.getEventById(this.eventId));
|
||||||
|
} else {
|
||||||
|
promises.push(this.calendarProvider.getEvent(this.eventId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get offline data.
|
||||||
|
promises.push(this.calendarOffline.getEvent(this.eventId).catch(() => {
|
||||||
|
// No offline data.
|
||||||
|
}));
|
||||||
|
|
||||||
|
return Promise.all(promises).then((results) => {
|
||||||
|
if (results[1]) {
|
||||||
|
// There is offline data, apply it.
|
||||||
|
this.hasOffline = true;
|
||||||
|
Object.assign(results[0], results[1]);
|
||||||
|
} else {
|
||||||
|
this.hasOffline = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return results[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
}).then((event) => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
this.calendarHelper.formatEventData(event);
|
this.calendarHelper.formatEventData(event);
|
||||||
|
@ -196,6 +293,9 @@ export class AddonCalendarEventPage {
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
this.domUtils.showErrorModalDefault(error, 'addon.calendar.errorloadevent', true);
|
this.domUtils.showErrorModalDefault(error, 'addon.calendar.errorloadevent', true);
|
||||||
|
}).finally(() => {
|
||||||
|
this.eventLoaded = true;
|
||||||
|
this.syncIcon = 'sync';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,16 +346,77 @@ export class AddonCalendarEventPage {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the data.
|
||||||
|
*
|
||||||
|
* @param {any} [refresher] Refresher.
|
||||||
|
* @param {Function} [done] Function to call when done.
|
||||||
|
* @param {boolean} [showErrors] Whether to show sync errors to the user.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
doRefresh(refresher?: any, done?: () => void, showErrors?: boolean): Promise<any> {
|
||||||
|
if (this.eventLoaded) {
|
||||||
|
return this.refreshEvent(true, showErrors).finally(() => {
|
||||||
|
refresher && refresher.complete();
|
||||||
|
done && done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the event.
|
* Refresh the event.
|
||||||
*
|
*
|
||||||
* @param {any} refresher Refresher.
|
* @param {boolean} [sync] Whether it should try to synchronize offline events.
|
||||||
|
* @param {boolean} [showErrors] Whether to show sync errors to the user.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
refreshEvent(refresher: any): void {
|
refreshEvent(sync?: boolean, showErrors?: boolean): Promise<any> {
|
||||||
this.calendarProvider.invalidateEvent(this.eventId).finally(() => {
|
this.syncIcon = 'spinner';
|
||||||
this.fetchEvent().finally(() => {
|
|
||||||
refresher.complete();
|
return this.calendarProvider.invalidateEvent(this.eventId).catch(() => {
|
||||||
});
|
// Ignore errors.
|
||||||
|
}).then(() => {
|
||||||
|
return this.fetchEvent(sync, showErrors);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the page to edit the event.
|
||||||
|
*/
|
||||||
|
openEdit(): void {
|
||||||
|
// Decide which navCtrl to use. If this page is inside a split view, use the split view's master nav.
|
||||||
|
const navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl;
|
||||||
|
navCtrl.push('AddonCalendarEditEventPage', {eventId: this.eventId});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the result of an automatic sync or a manual sync not done by this page.
|
||||||
|
*
|
||||||
|
* @param {boolean} isManual Whether it's a manual sync.
|
||||||
|
* @param {any} data Sync result.
|
||||||
|
*/
|
||||||
|
protected checkSyncResult(isManual: boolean, data: any): void {
|
||||||
|
if (data && data.events && (!isManual || data.source != 'event')) {
|
||||||
|
const event = data.events.find((ev) => {
|
||||||
|
return ev.id == this.eventId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
this.eventLoaded = false;
|
||||||
|
this.refreshEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page destroyed.
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.editEventObserver && this.editEventObserver.off();
|
||||||
|
this.syncObserver && this.syncObserver.off();
|
||||||
|
this.manualSyncObserver && this.manualSyncObserver.off();
|
||||||
|
this.onlineObserver && this.onlineObserver.unsubscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
</button>
|
</button>
|
||||||
<core-context-menu>
|
<core-context-menu>
|
||||||
<core-context-menu-item [hidden]="!notificationsEnabled" [priority]="600" [content]="'core.settings.settings' | translate" (action)="openSettings()" [iconAction]="'cog'"></core-context-menu-item>
|
<core-context-menu-item [hidden]="!notificationsEnabled" [priority]="600" [content]="'core.settings.settings' | translate" (action)="openSettings()" [iconAction]="'cog'"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="eventsLoaded && hasOffline && isOnline" [priority]="400" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [hidden]="!eventsLoaded || !hasOffline || !isOnline" [priority]="400" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
|
@ -26,20 +26,6 @@
|
||||||
<core-empty-box *ngIf="!filteredEvents || !filteredEvents.length" icon="calendar" [message]="'addon.calendar.noevents' | translate">
|
<core-empty-box *ngIf="!filteredEvents || !filteredEvents.length" icon="calendar" [message]="'addon.calendar.noevents' | translate">
|
||||||
</core-empty-box>
|
</core-empty-box>
|
||||||
|
|
||||||
<ion-list *ngIf="offlineEvents && offlineEvents.length" no-margin>
|
|
||||||
<ng-container *ngFor="let event of offlineEvents">
|
|
||||||
<ion-item-divider> {{ 'core.notsent' | translate }}</ion-item-divider>
|
|
||||||
<a ion-item text-wrap [title]="event.name" (click)="gotoEvent(event.id)" [class.core-split-item-selected]="event.id == eventId">
|
|
||||||
<core-icon *ngIf="event.icon" [name]="event.icon" item-start></core-icon>
|
|
||||||
<h2><core-format-text [text]="event.name"></core-format-text></h2>
|
|
||||||
<p>
|
|
||||||
{{ event.timestart * 1000 | coreFormatDate: "strftimedatetimeshort" }}
|
|
||||||
<span *ngIf="event.timeduration"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimedatetimeshort" }}</span>
|
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
</ng-container>
|
|
||||||
</ion-list>
|
|
||||||
|
|
||||||
<ion-list *ngIf="filteredEvents && filteredEvents.length" no-margin>
|
<ion-list *ngIf="filteredEvents && filteredEvents.length" no-margin>
|
||||||
<ng-container *ngFor="let event of filteredEvents">
|
<ng-container *ngFor="let event of filteredEvents">
|
||||||
<ion-item-divider *ngIf="event.showDate">
|
<ion-item-divider *ngIf="event.showDate">
|
||||||
|
@ -54,6 +40,10 @@
|
||||||
<span *ngIf="event.timeduration && event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimetime" }}</span>
|
<span *ngIf="event.timeduration && event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimetime" }}</span>
|
||||||
<span *ngIf="event.timeduration && !event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimedatetimeshort" }}</span>
|
<span *ngIf="event.timeduration && !event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimedatetimeshort" }}</span>
|
||||||
</p>
|
</p>
|
||||||
|
<ion-note *ngIf="event.offline" item-end>
|
||||||
|
<ion-icon name="time"></ion-icon>
|
||||||
|
{{ 'core.notsent' | translate }}
|
||||||
|
</ion-note>
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { AddonCalendarHelperProvider } from '../../providers/helper';
|
||||||
import { AddonCalendarSyncProvider } from '../../providers/calendar-sync';
|
import { AddonCalendarSyncProvider } from '../../providers/calendar-sync';
|
||||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||||
|
@ -30,6 +31,7 @@ import { CoreAppProvider } from '@providers/app';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import { Network } from '@ionic-native/network';
|
import { Network } from '@ionic-native/network';
|
||||||
|
import { CoreConstants } from '@core/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the list of calendar events.
|
* Page that displays the list of calendar events.
|
||||||
|
@ -43,6 +45,7 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
@ViewChild(Content) content: Content;
|
@ViewChild(Content) content: Content;
|
||||||
@ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent;
|
@ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent;
|
||||||
|
|
||||||
|
protected initialTime = 0;
|
||||||
protected daysLoaded = 0;
|
protected daysLoaded = 0;
|
||||||
protected emptyEventsTimes = 0; // Variable to identify consecutive calls returning 0 events.
|
protected emptyEventsTimes = 0; // Variable to identify consecutive calls returning 0 events.
|
||||||
protected categoriesRetrieved = false;
|
protected categoriesRetrieved = false;
|
||||||
|
@ -59,12 +62,16 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
protected preSelectedCourseId: number;
|
protected preSelectedCourseId: number;
|
||||||
protected newEventObserver: any;
|
protected newEventObserver: any;
|
||||||
protected discardedObserver: any;
|
protected discardedObserver: any;
|
||||||
|
protected editEventObserver: any;
|
||||||
protected syncObserver: any;
|
protected syncObserver: any;
|
||||||
|
protected manualSyncObserver: any;
|
||||||
protected onlineObserver: any;
|
protected onlineObserver: any;
|
||||||
|
protected currentSiteId: string;
|
||||||
|
|
||||||
courses: any[];
|
courses: any[];
|
||||||
eventsLoaded = false;
|
eventsLoaded = false;
|
||||||
events = [];
|
events = []; // Events (both online and offline).
|
||||||
|
onlineEvents = [];
|
||||||
offlineEvents = [];
|
offlineEvents = [];
|
||||||
notificationsEnabled = false;
|
notificationsEnabled = false;
|
||||||
filteredEvents = [];
|
filteredEvents = [];
|
||||||
|
@ -80,20 +87,21 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
|
|
||||||
constructor(private translate: TranslateService, private calendarProvider: AddonCalendarProvider, navParams: NavParams,
|
constructor(private translate: TranslateService, private calendarProvider: AddonCalendarProvider, navParams: NavParams,
|
||||||
private domUtils: CoreDomUtilsProvider, private coursesProvider: CoreCoursesProvider, private utils: CoreUtilsProvider,
|
private domUtils: CoreDomUtilsProvider, private coursesProvider: CoreCoursesProvider, private utils: CoreUtilsProvider,
|
||||||
private calendarHelper: AddonCalendarHelperProvider, private sitesProvider: CoreSitesProvider, zone: NgZone,
|
private calendarHelper: AddonCalendarHelperProvider, sitesProvider: CoreSitesProvider, zone: NgZone,
|
||||||
localNotificationsProvider: CoreLocalNotificationsProvider, private popoverCtrl: PopoverController,
|
localNotificationsProvider: CoreLocalNotificationsProvider, private popoverCtrl: PopoverController,
|
||||||
private eventsProvider: CoreEventsProvider, private navCtrl: NavController, private appProvider: CoreAppProvider,
|
private eventsProvider: CoreEventsProvider, private navCtrl: NavController, private appProvider: CoreAppProvider,
|
||||||
private calendarOffline: AddonCalendarOfflineProvider, private calendarSync: AddonCalendarSyncProvider,
|
private calendarOffline: AddonCalendarOfflineProvider, private calendarSync: AddonCalendarSyncProvider,
|
||||||
network: Network) {
|
network: Network, private timeUtils: CoreTimeUtilsProvider) {
|
||||||
|
|
||||||
this.siteHomeId = sitesProvider.getCurrentSite().getSiteHomeId();
|
this.siteHomeId = sitesProvider.getCurrentSite().getSiteHomeId();
|
||||||
this.notificationsEnabled = localNotificationsProvider.isAvailable();
|
this.notificationsEnabled = localNotificationsProvider.isAvailable();
|
||||||
|
this.currentSiteId = sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
if (this.notificationsEnabled) {
|
if (this.notificationsEnabled) {
|
||||||
// Re-schedule events if default time changes.
|
// Re-schedule events if default time changes.
|
||||||
this.obsDefaultTimeChange = eventsProvider.on(AddonCalendarProvider.DEFAULT_NOTIFICATION_TIME_CHANGED, () => {
|
this.obsDefaultTimeChange = eventsProvider.on(AddonCalendarProvider.DEFAULT_NOTIFICATION_TIME_CHANGED, () => {
|
||||||
calendarProvider.scheduleEventsNotifications(this.events);
|
calendarProvider.scheduleEventsNotifications(this.onlineEvents);
|
||||||
}, sitesProvider.getCurrentSiteId());
|
}, this.currentSiteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.eventId = navParams.get('eventId') || false;
|
this.eventId = navParams.get('eventId') || false;
|
||||||
|
@ -116,7 +124,7 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, sitesProvider.getCurrentSiteId());
|
}, this.currentSiteId);
|
||||||
|
|
||||||
// Listen for new event discarded event. When it does, reload the data.
|
// Listen for new event discarded event. When it does, reload the data.
|
||||||
this.discardedObserver = eventsProvider.on(AddonCalendarProvider.NEW_EVENT_DISCARDED_EVENT, () => {
|
this.discardedObserver = eventsProvider.on(AddonCalendarProvider.NEW_EVENT_DISCARDED_EVENT, () => {
|
||||||
|
@ -127,13 +135,29 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
|
|
||||||
this.eventsLoaded = false;
|
this.eventsLoaded = false;
|
||||||
this.refreshEvents(true, false);
|
this.refreshEvents(true, false);
|
||||||
}, sitesProvider.getCurrentSiteId());
|
}, this.currentSiteId);
|
||||||
|
|
||||||
|
// Listen for events edited. When an event is edited, reload the data.
|
||||||
|
this.editEventObserver = eventsProvider.on(AddonCalendarProvider.EDIT_EVENT_EVENT, (data) => {
|
||||||
|
if (data && data.event) {
|
||||||
|
this.eventsLoaded = false;
|
||||||
|
this.refreshEvents(true, false);
|
||||||
|
}
|
||||||
|
}, this.currentSiteId);
|
||||||
|
|
||||||
// Refresh data if calendar events are synchronized automatically.
|
// Refresh data if calendar events are synchronized automatically.
|
||||||
this.syncObserver = eventsProvider.on(AddonCalendarSyncProvider.AUTO_SYNCED, (data) => {
|
this.syncObserver = eventsProvider.on(AddonCalendarSyncProvider.AUTO_SYNCED, (data) => {
|
||||||
this.eventsLoaded = false;
|
this.eventsLoaded = false;
|
||||||
this.refreshEvents();
|
this.refreshEvents();
|
||||||
}, sitesProvider.getCurrentSiteId());
|
}, this.currentSiteId);
|
||||||
|
|
||||||
|
// Refresh data if calendar events are synchronized manually but not by this page.
|
||||||
|
this.manualSyncObserver = eventsProvider.on(AddonCalendarSyncProvider.MANUAL_SYNCED, (data) => {
|
||||||
|
if (data && data.source != 'list') {
|
||||||
|
this.eventsLoaded = false;
|
||||||
|
this.refreshEvents();
|
||||||
|
}
|
||||||
|
}, this.currentSiteId);
|
||||||
|
|
||||||
// Refresh online status when changes.
|
// Refresh online status when changes.
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe((online) => {
|
||||||
|
@ -157,8 +181,12 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
|
|
||||||
this.fetchData(false, true, false).then(() => {
|
this.fetchData(false, true, false).then(() => {
|
||||||
if (!this.eventId && this.splitviewCtrl.isOn() && this.events.length > 0) {
|
if (!this.eventId && this.splitviewCtrl.isOn() && this.events.length > 0) {
|
||||||
// Take first and load it.
|
// Take first online event and load it. If no online event, load the first offline.
|
||||||
this.gotoEvent(this.events[0].id);
|
if (this.onlineEvents[0]) {
|
||||||
|
this.gotoEvent(this.onlineEvents[0].id);
|
||||||
|
} else {
|
||||||
|
this.gotoEvent(this.offlineEvents[0].id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -172,6 +200,7 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
* @return {Promise<any>} Promise resolved when done.
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
fetchData(refresh?: boolean, sync?: boolean, showErrors?: boolean): Promise<any> {
|
fetchData(refresh?: boolean, sync?: boolean, showErrors?: boolean): Promise<any> {
|
||||||
|
this.initialTime = this.timeUtils.timestamp();
|
||||||
this.daysLoaded = 0;
|
this.daysLoaded = 0;
|
||||||
this.emptyEventsTimes = 0;
|
this.emptyEventsTimes = 0;
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
|
@ -187,9 +216,9 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
|
|
||||||
if (result.updated) {
|
if (result.updated) {
|
||||||
// Trigger a manual sync event.
|
// Trigger a manual sync event.
|
||||||
this.eventsProvider.trigger(AddonCalendarSyncProvider.MANUAL_SYNCED, {
|
result.source = 'list';
|
||||||
source: 'list'
|
|
||||||
}, this.sitesProvider.getCurrentSiteId());
|
this.eventsProvider.trigger(AddonCalendarSyncProvider.MANUAL_SYNCED, result, this.currentSiteId);
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
if (showErrors) {
|
if (showErrors) {
|
||||||
|
@ -229,8 +258,11 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
this.hasOffline = !!events.length;
|
this.hasOffline = !!events.length;
|
||||||
|
|
||||||
// Format data and sort by timestart.
|
// Format data and sort by timestart.
|
||||||
events.forEach(this.calendarHelper.formatEventData.bind(this.calendarHelper));
|
events.forEach((event) => {
|
||||||
this.offlineEvents = events.sort((a, b) => a.timestart - b.timestart);
|
event.offline = true;
|
||||||
|
this.calendarHelper.formatEventData(event);
|
||||||
|
});
|
||||||
|
this.offlineEvents = this.sortEvents(events);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
@ -249,38 +281,38 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
fetchEvents(refresh?: boolean): Promise<any> {
|
fetchEvents(refresh?: boolean): Promise<any> {
|
||||||
this.loadMoreError = false;
|
this.loadMoreError = false;
|
||||||
|
|
||||||
return this.calendarProvider.getEventsList(this.daysLoaded, AddonCalendarProvider.DAYS_INTERVAL).then((events) => {
|
return this.calendarProvider.getEventsList(this.initialTime, this.daysLoaded, AddonCalendarProvider.DAYS_INTERVAL)
|
||||||
this.daysLoaded += AddonCalendarProvider.DAYS_INTERVAL;
|
.then((onlineEvents) => {
|
||||||
if (events.length === 0) {
|
|
||||||
|
if (onlineEvents.length === 0) {
|
||||||
this.emptyEventsTimes++;
|
this.emptyEventsTimes++;
|
||||||
if (this.emptyEventsTimes > 5) { // Stop execution if we retrieve empty list 6 consecutive times.
|
if (this.emptyEventsTimes > 5) { // Stop execution if we retrieve empty list 6 consecutive times.
|
||||||
this.canLoadMore = false;
|
this.canLoadMore = false;
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
this.events = [];
|
this.onlineEvents = [];
|
||||||
this.filteredEvents = [];
|
this.filteredEvents = [];
|
||||||
|
this.events = this.offlineEvents;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No events returned, load next events.
|
// No events returned, load next events.
|
||||||
|
this.daysLoaded += AddonCalendarProvider.DAYS_INTERVAL;
|
||||||
|
|
||||||
return this.fetchEvents();
|
return this.fetchEvents();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
events.forEach(this.calendarHelper.formatEventData.bind(this.calendarHelper));
|
onlineEvents.forEach(this.calendarHelper.formatEventData.bind(this.calendarHelper));
|
||||||
|
|
||||||
// Sort the events by timestart, they're ordered by id.
|
// Get the merged events of this period.
|
||||||
events.sort((a, b) => {
|
const events = this.mergeEvents(onlineEvents);
|
||||||
if (a.timestart == b.timestart) {
|
|
||||||
return a.timeduration - b.timeduration;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.timestart - b.timestart;
|
this.getCategories = this.shouldLoadCategories(onlineEvents);
|
||||||
});
|
|
||||||
|
|
||||||
this.getCategories = this.shouldLoadCategories(events);
|
|
||||||
|
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
|
this.onlineEvents = onlineEvents;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
} else {
|
} else {
|
||||||
// Filter events with same ID. Repeated events are returned once per WS call, show them only once.
|
// Filter events with same ID. Repeated events are returned once per WS call, show them only once.
|
||||||
|
this.onlineEvents = this.utils.mergeArraysWithoutDuplicates(this.onlineEvents, onlineEvents, 'id');
|
||||||
this.events = this.utils.mergeArraysWithoutDuplicates(this.events, events, 'id');
|
this.events = this.utils.mergeArraysWithoutDuplicates(this.events, events, 'id');
|
||||||
}
|
}
|
||||||
this.filteredEvents = this.getFilteredEvents();
|
this.filteredEvents = this.getFilteredEvents();
|
||||||
|
@ -293,7 +325,9 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
this.canLoadMore = true;
|
this.canLoadMore = true;
|
||||||
|
|
||||||
// Schedule notifications for the events retrieved (might have new events).
|
// Schedule notifications for the events retrieved (might have new events).
|
||||||
this.calendarProvider.scheduleEventsNotifications(this.events);
|
this.calendarProvider.scheduleEventsNotifications(this.onlineEvents);
|
||||||
|
|
||||||
|
this.daysLoaded += AddonCalendarProvider.DAYS_INTERVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize the content so infinite loading is able to calculate if it should load more items or not.
|
// Resize the content so infinite loading is able to calculate if it should load more items or not.
|
||||||
|
@ -416,6 +450,61 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge a period of online events with the offline events of that period.
|
||||||
|
*
|
||||||
|
* @param {any[]} onlineEvents Online events.
|
||||||
|
* @return {any[]} Merged events.
|
||||||
|
*/
|
||||||
|
protected mergeEvents(onlineEvents: any[]): any[] {
|
||||||
|
if (!this.offlineEvents || !this.offlineEvents.length) {
|
||||||
|
// No offline events, nothing to merge.
|
||||||
|
return onlineEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = this.initialTime + (CoreConstants.SECONDS_DAY * this.daysLoaded),
|
||||||
|
end = start + (CoreConstants.SECONDS_DAY * AddonCalendarProvider.DAYS_INTERVAL) - 1;
|
||||||
|
|
||||||
|
// First of all, remove the online events that were modified in offline.
|
||||||
|
let result = onlineEvents.filter((event) => {
|
||||||
|
const offlineEvent = this.offlineEvents.find((ev) => {
|
||||||
|
return ev.id == event.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
return !offlineEvent;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now get the offline events that belong to this period.
|
||||||
|
const periodOfflineEvents = this.offlineEvents.filter((event) => {
|
||||||
|
if (this.daysLoaded == 0 && event.timestart < start) {
|
||||||
|
// Display offline events that are previous to current time to allow editing them.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (event.timestart >= start || event.timestart + event.timeduration >= start) && event.timestart <= end;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Merge both arrays and sort them.
|
||||||
|
result = result.concat(periodOfflineEvents);
|
||||||
|
|
||||||
|
return this.sortEvents(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort events by timestart.
|
||||||
|
*
|
||||||
|
* @param {any[]} events List to sort.
|
||||||
|
*/
|
||||||
|
protected sortEvents(events: any[]): any[] {
|
||||||
|
return events.sort((a, b) => {
|
||||||
|
if (a.timestart == b.timestart) {
|
||||||
|
return a.timeduration - b.timeduration;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.timestart - b.timestart;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the data.
|
* Refresh the data.
|
||||||
*
|
*
|
||||||
|
@ -530,6 +619,8 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
* @param {number} [eventId] Event ID to edit.
|
* @param {number} [eventId] Event ID to edit.
|
||||||
*/
|
*/
|
||||||
openEdit(eventId?: number): void {
|
openEdit(eventId?: number): void {
|
||||||
|
this.eventId = undefined;
|
||||||
|
|
||||||
const params: any = {};
|
const params: any = {};
|
||||||
|
|
||||||
if (eventId) {
|
if (eventId) {
|
||||||
|
@ -574,7 +665,9 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
this.obsDefaultTimeChange && this.obsDefaultTimeChange.off();
|
this.obsDefaultTimeChange && this.obsDefaultTimeChange.off();
|
||||||
this.newEventObserver && this.newEventObserver.off();
|
this.newEventObserver && this.newEventObserver.off();
|
||||||
this.discardedObserver && this.discardedObserver.off();
|
this.discardedObserver && this.discardedObserver.off();
|
||||||
|
this.editEventObserver && this.editEventObserver.off();
|
||||||
this.syncObserver && this.syncObserver.off();
|
this.syncObserver && this.syncObserver.off();
|
||||||
this.onlineObserver && this.onlineObserver.off();
|
this.manualSyncObserver && this.manualSyncObserver.off();
|
||||||
|
this.onlineObserver && this.onlineObserver.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,14 @@ export class AddonCalendarOfflineProvider {
|
||||||
name: 'repeats',
|
name: 'repeats',
|
||||||
type: 'TEXT',
|
type: 'TEXT',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'repeatid',
|
||||||
|
type: 'INTEGER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'repeateditall',
|
||||||
|
type: 'INTEGER',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'userid',
|
name: 'userid',
|
||||||
type: 'INTEGER',
|
type: 'INTEGER',
|
||||||
|
@ -202,6 +210,8 @@ export class AddonCalendarOfflineProvider {
|
||||||
timedurationminutes: data.timedurationminutes,
|
timedurationminutes: data.timedurationminutes,
|
||||||
repeat: data.repeat ? 1 : 0,
|
repeat: data.repeat ? 1 : 0,
|
||||||
repeats: data.repeats,
|
repeats: data.repeats,
|
||||||
|
repeatid: data.repeatid,
|
||||||
|
repeateditall: data.repeateditall ? 1 : 0,
|
||||||
timecreated: timeCreated,
|
timecreated: timeCreated,
|
||||||
userid: site.getUserId()
|
userid: site.getUserId()
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,8 +37,6 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
static MANUAL_SYNCED = 'addon_calendar_manual_synced';
|
static MANUAL_SYNCED = 'addon_calendar_manual_synced';
|
||||||
static SYNC_ID = 'calendar';
|
static SYNC_ID = 'calendar';
|
||||||
|
|
||||||
protected componentTranslate: string;
|
|
||||||
|
|
||||||
constructor(translate: TranslateService,
|
constructor(translate: TranslateService,
|
||||||
appProvider: CoreAppProvider,
|
appProvider: CoreAppProvider,
|
||||||
courseProvider: CoreCourseProvider,
|
courseProvider: CoreCourseProvider,
|
||||||
|
@ -54,8 +52,6 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
|
|
||||||
super('AddonCalendarSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
|
super('AddonCalendarSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
|
||||||
timeUtils);
|
timeUtils);
|
||||||
|
|
||||||
this.componentTranslate = this.translate.instant('addon.calendar.calendarevent');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +62,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
syncAllEvents(siteId?: string, force?: boolean): Promise<any> {
|
syncAllEvents(siteId?: string, force?: boolean): Promise<any> {
|
||||||
return this.syncOnSites('all calendars', this.syncAllEventsFunc.bind(this), [force], siteId);
|
return this.syncOnSites('all calendar events', this.syncAllEventsFunc.bind(this), [force], siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,6 +73,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
protected syncAllEventsFunc(siteId: string, force?: boolean): Promise<any> {
|
protected syncAllEventsFunc(siteId: string, force?: boolean): Promise<any> {
|
||||||
|
|
||||||
const promise = force ? this.syncEvents(siteId) : this.syncEventsIfNeeded(siteId);
|
const promise = force ? this.syncEvents(siteId) : this.syncEventsIfNeeded(siteId);
|
||||||
|
|
||||||
return promise.then((result) => {
|
return promise.then((result) => {
|
||||||
|
@ -196,7 +193,8 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
if (this.syncProvider.isBlocked(AddonCalendarProvider.COMPONENT, event.id, siteId)) {
|
if (this.syncProvider.isBlocked(AddonCalendarProvider.COMPONENT, event.id, siteId)) {
|
||||||
this.logger.debug('Cannot sync event ' + event.name + ' because it is blocked.');
|
this.logger.debug('Cannot sync event ' + event.name + ' because it is blocked.');
|
||||||
|
|
||||||
return Promise.reject(this.translate.instant('core.errorsyncblocked', {$a: this.componentTranslate}));
|
return Promise.reject(this.translate.instant('core.errorsyncblocked',
|
||||||
|
{$a: this.translate.instant('addon.calendar.calendarevent')}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to send the data.
|
// Try to send the data.
|
||||||
|
@ -216,7 +214,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
return this.calendarOffline.deleteEvent(event.id, siteId).then(() => {
|
return this.calendarOffline.deleteEvent(event.id, siteId).then(() => {
|
||||||
// Event deleted, add a warning.
|
// Event deleted, add a warning.
|
||||||
result.warnings.push(this.translate.instant('core.warningofflinedatadeleted', {
|
result.warnings.push(this.translate.instant('core.warningofflinedatadeleted', {
|
||||||
component: this.componentTranslate,
|
component: this.translate.instant('addon.calendar.calendarevent'),
|
||||||
name: event.name,
|
name: event.name,
|
||||||
error: this.textUtils.getErrorMessageFromError(error)
|
error: this.textUtils.getErrorMessageFromError(error)
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { CoreConfigProvider } from '@providers/config';
|
||||||
import { ILocalNotification } from '@ionic-native/local-notifications';
|
import { ILocalNotification } from '@ionic-native/local-notifications';
|
||||||
import { SQLiteDB } from '@classes/sqlitedb';
|
import { SQLiteDB } from '@classes/sqlitedb';
|
||||||
import { AddonCalendarOfflineProvider } from './calendar-offline';
|
import { AddonCalendarOfflineProvider } from './calendar-offline';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to handle calendar events.
|
* Service to handle calendar events.
|
||||||
|
@ -40,6 +41,7 @@ export class AddonCalendarProvider {
|
||||||
static DEFAULT_NOTIFICATION_TIME = 60;
|
static DEFAULT_NOTIFICATION_TIME = 60;
|
||||||
static NEW_EVENT_EVENT = 'addon_calendar_new_event';
|
static NEW_EVENT_EVENT = 'addon_calendar_new_event';
|
||||||
static NEW_EVENT_DISCARDED_EVENT = 'addon_calendar_new_event_discarded';
|
static NEW_EVENT_DISCARDED_EVENT = 'addon_calendar_new_event_discarded';
|
||||||
|
static EDIT_EVENT_EVENT = 'addon_calendar_edit_event';
|
||||||
static TYPE_CATEGORY = 'category';
|
static TYPE_CATEGORY = 'category';
|
||||||
static TYPE_COURSE = 'course';
|
static TYPE_COURSE = 'course';
|
||||||
static TYPE_GROUP = 'group';
|
static TYPE_GROUP = 'group';
|
||||||
|
@ -218,7 +220,7 @@ export class AddonCalendarProvider {
|
||||||
private coursesProvider: CoreCoursesProvider, private timeUtils: CoreTimeUtilsProvider,
|
private coursesProvider: CoreCoursesProvider, private timeUtils: CoreTimeUtilsProvider,
|
||||||
private localNotificationsProvider: CoreLocalNotificationsProvider, private configProvider: CoreConfigProvider,
|
private localNotificationsProvider: CoreLocalNotificationsProvider, private configProvider: CoreConfigProvider,
|
||||||
private utils: CoreUtilsProvider, private calendarOffline: AddonCalendarOfflineProvider,
|
private utils: CoreUtilsProvider, private calendarOffline: AddonCalendarOfflineProvider,
|
||||||
private appProvider: CoreAppProvider) {
|
private appProvider: CoreAppProvider, private translate: TranslateService) {
|
||||||
this.logger = logger.getInstance('AddonCalendarProvider');
|
this.logger = logger.getInstance('AddonCalendarProvider');
|
||||||
this.sitesProvider.registerSiteSchema(this.siteSchema);
|
this.sitesProvider.registerSiteSchema(this.siteSchema);
|
||||||
}
|
}
|
||||||
|
@ -535,16 +537,20 @@ export class AddonCalendarProvider {
|
||||||
* Get the events in a certain period. The period is calculated like this:
|
* Get the events in a certain period. The period is calculated like this:
|
||||||
* start time: now + daysToStart
|
* start time: now + daysToStart
|
||||||
* end time: start time + daysInterval
|
* end time: start time + daysInterval
|
||||||
* E.g. using provider.getEventsList(30, 30) is going to get the events starting after 30 days from now
|
* E.g. using provider.getEventsList(undefined, 30, 30) is going to get the events starting after 30 days from now
|
||||||
* and ending before 60 days from now.
|
* and ending before 60 days from now.
|
||||||
*
|
*
|
||||||
* @param {number} [daysToStart=0] Number of days from now to start getting events.
|
* @param {number} [initialTime] Timestamp when the first fetch was done. If not defined, current time.
|
||||||
|
* @param {number} [daysToStart=0] Number of days from now to start getting events.
|
||||||
* @param {number} [daysInterval=30] Number of days between timestart and timeend.
|
* @param {number} [daysInterval=30] Number of days between timestart and timeend.
|
||||||
* @param {string} [siteId] Site to get the events from. If not defined, use current site.
|
* @param {string} [siteId] Site to get the events from. If not defined, use current site.
|
||||||
* @return {Promise<any[]>} Promise to be resolved when the participants are retrieved.
|
* @return {Promise<any[]>} Promise to be resolved when the participants are retrieved.
|
||||||
*/
|
*/
|
||||||
getEventsList(daysToStart: number = 0, daysInterval: number = AddonCalendarProvider.DAYS_INTERVAL, siteId?: string)
|
getEventsList(initialTime?: number, daysToStart: number = 0, daysInterval: number = AddonCalendarProvider.DAYS_INTERVAL,
|
||||||
: Promise<any[]> {
|
siteId?: string): Promise<any[]> {
|
||||||
|
|
||||||
|
initialTime = initialTime || this.timeUtils.timestamp();
|
||||||
|
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
siteId = site.getId();
|
siteId = site.getId();
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
@ -559,9 +565,8 @@ export class AddonCalendarProvider {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
const now = this.timeUtils.timestamp(),
|
const start = initialTime + (CoreConstants.SECONDS_DAY * daysToStart),
|
||||||
start = now + (CoreConstants.SECONDS_DAY * daysToStart),
|
end = start + (CoreConstants.SECONDS_DAY * daysInterval) - 1,
|
||||||
end = start + (CoreConstants.SECONDS_DAY * daysInterval),
|
|
||||||
data = {
|
data = {
|
||||||
options: {
|
options: {
|
||||||
userevents: 1,
|
userevents: 1,
|
||||||
|
@ -586,6 +591,7 @@ export class AddonCalendarProvider {
|
||||||
const preSets = {
|
const preSets = {
|
||||||
cacheKey: this.getEventsListCacheKey(daysToStart, daysInterval),
|
cacheKey: this.getEventsListCacheKey(daysToStart, daysInterval),
|
||||||
getCacheUsingCacheKey: true,
|
getCacheUsingCacheKey: true,
|
||||||
|
uniqueCacheKey: true,
|
||||||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES
|
updateFrequency: CoreSite.FREQUENCY_SOMETIMES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -731,7 +737,7 @@ export class AddonCalendarProvider {
|
||||||
return this.isDisabled(siteId).then((disabled) => {
|
return this.isDisabled(siteId).then((disabled) => {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
// Get first events.
|
// Get first events.
|
||||||
return this.getEventsList(undefined, undefined, siteId).then((events) => {
|
return this.getEventsList(undefined, undefined, undefined, siteId).then((events) => {
|
||||||
return this.scheduleEventsNotifications(events, siteId);
|
return this.scheduleEventsNotifications(events, siteId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -980,7 +986,12 @@ export class AddonCalendarProvider {
|
||||||
formData.userid = site.getUserId();
|
formData.userid = site.getUserId();
|
||||||
formData.visible = 1;
|
formData.visible = 1;
|
||||||
formData.instance = 0;
|
formData.instance = 0;
|
||||||
formData['_qf__core_calendar_local_event_forms_create'] = 1;
|
|
||||||
|
if (eventId > 0) {
|
||||||
|
formData['_qf__core_calendar_local_event_forms_update'] = 1;
|
||||||
|
} else {
|
||||||
|
formData['_qf__core_calendar_local_event_forms_create'] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
formdata: this.utils.objectToGetParams(formData)
|
formdata: this.utils.objectToGetParams(formData)
|
||||||
|
@ -988,7 +999,11 @@ export class AddonCalendarProvider {
|
||||||
|
|
||||||
return site.write('core_calendar_submit_create_update_form', params).then((result) => {
|
return site.write('core_calendar_submit_create_update_form', params).then((result) => {
|
||||||
if (result.validationerror) {
|
if (result.validationerror) {
|
||||||
return Promise.reject(this.utils.createFakeWSError(''));
|
// Simulate a WS error.
|
||||||
|
return Promise.reject({
|
||||||
|
message: this.translate.instant('core.invalidformdata'),
|
||||||
|
errorcode: 'validationerror'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.event;
|
return result.event;
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
"addon.calendar.errorloadevents": "Error loading events.",
|
"addon.calendar.errorloadevents": "Error loading events.",
|
||||||
"addon.calendar.eventduration": "Duration",
|
"addon.calendar.eventduration": "Duration",
|
||||||
"addon.calendar.eventendtime": "End time",
|
"addon.calendar.eventendtime": "End time",
|
||||||
|
"addon.calendar.eventkind": "Type of event",
|
||||||
"addon.calendar.eventname": "Event title",
|
"addon.calendar.eventname": "Event title",
|
||||||
"addon.calendar.eventstarttime": "Start time",
|
"addon.calendar.eventstarttime": "Start time",
|
||||||
"addon.calendar.eventtype": "Event type",
|
"addon.calendar.eventtype": "Event type",
|
||||||
|
@ -106,6 +107,9 @@
|
||||||
"addon.calendar.noevents": "There are no events",
|
"addon.calendar.noevents": "There are no events",
|
||||||
"addon.calendar.nopermissiontoupdatecalendar": "Sorry, but you do not have permission to update the calendar event",
|
"addon.calendar.nopermissiontoupdatecalendar": "Sorry, but you do not have permission to update the calendar event",
|
||||||
"addon.calendar.reminders": "Reminders",
|
"addon.calendar.reminders": "Reminders",
|
||||||
|
"addon.calendar.repeatedevents": "Repeated events",
|
||||||
|
"addon.calendar.repeateditall": "Also apply changes to the other {{$a}} events in this repeat series",
|
||||||
|
"addon.calendar.repeateditthis": "Apply changes to this event only",
|
||||||
"addon.calendar.repeatevent": "Repeat this event",
|
"addon.calendar.repeatevent": "Repeat this event",
|
||||||
"addon.calendar.repeatweeksl": "Repeat weekly, creating altogether",
|
"addon.calendar.repeatweeksl": "Repeat weekly, creating altogether",
|
||||||
"addon.calendar.setnewreminder": "Set a new reminder",
|
"addon.calendar.setnewreminder": "Set a new reminder",
|
||||||
|
@ -1492,6 +1496,7 @@
|
||||||
"core.image": "Image",
|
"core.image": "Image",
|
||||||
"core.imageviewer": "Image viewer",
|
"core.imageviewer": "Image viewer",
|
||||||
"core.info": "Information",
|
"core.info": "Information",
|
||||||
|
"core.invalidformdata": "Incorrect form data",
|
||||||
"core.ios": "iOS",
|
"core.ios": "iOS",
|
||||||
"core.labelsep": ":",
|
"core.labelsep": ":",
|
||||||
"core.lastaccess": "Last access",
|
"core.lastaccess": "Last access",
|
||||||
|
|
|
@ -115,6 +115,7 @@
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"imageviewer": "Image viewer",
|
"imageviewer": "Image viewer",
|
||||||
"info": "Information",
|
"info": "Information",
|
||||||
|
"invalidformdata": "Incorrect form data",
|
||||||
"ios": "iOS",
|
"ios": "iOS",
|
||||||
"labelsep": ":",
|
"labelsep": ":",
|
||||||
"lastaccess": "Last access",
|
"lastaccess": "Last access",
|
||||||
|
|
|
@ -1085,7 +1085,7 @@ export class CoreUtilsProvider {
|
||||||
* Convert an object to a format of GET param. E.g.: {a: 1, b: 2} -> a=1&b=2
|
* Convert an object to a format of GET param. E.g.: {a: 1, b: 2} -> a=1&b=2
|
||||||
*
|
*
|
||||||
* @param {any} object Object to convert.
|
* @param {any} object Object to convert.
|
||||||
* @param {boolean} [removeEmpty=true] Whether to remove params whose value is empty/null/undefined.
|
* @param {boolean} [removeEmpty=true] Whether to remove params whose value is null/undefined.
|
||||||
* @return {string} GET params.
|
* @return {string} GET params.
|
||||||
*/
|
*/
|
||||||
objectToGetParams(object: any, removeEmpty: boolean = true): string {
|
objectToGetParams(object: any, removeEmpty: boolean = true): string {
|
||||||
|
@ -1097,7 +1097,7 @@ export class CoreUtilsProvider {
|
||||||
for (const name in flattened) {
|
for (const name in flattened) {
|
||||||
let value = flattened[name];
|
let value = flattened[name];
|
||||||
|
|
||||||
if (removeEmpty && (value === null || typeof value == 'undefined' || value === '')) {
|
if (removeEmpty && (value === null || typeof value == 'undefined')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue