// (C) Copyright 2015 Moodle Pty Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import { Injectable } from '@angular/core'; import { SQLiteDBRecordValues } from '@classes/sqlitedb'; import { CoreSites } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton } from '@singletons'; import { AddonCalendarSubmitCreateUpdateFormDataWSParams } from './calendar'; import { AddonCalendarOfflineDeletedEventDBRecord, AddonCalendarOfflineEventDBRecord, DELETED_EVENTS_TABLE, EVENTS_TABLE, } from './database/calendar-offline'; /** * Service to handle offline calendar events. */ @Injectable({ providedIn: 'root' }) export class AddonCalendarOfflineProvider { /** * Delete an offline event. * * @param eventId Event ID. * @param siteId Site ID. If not defined, current site. * @return Promise resolved if deleted, rejected if failure. */ async deleteEvent(eventId: number, siteId?: string): Promise { const site = await CoreSites.getSite(siteId); const conditions: SQLiteDBRecordValues = { id: eventId, }; await site.getDb().deleteRecords(EVENTS_TABLE, conditions); } /** * Get the IDs of all the events created/edited/deleted in offline. * * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the IDs. */ async getAllEventsIds(siteId?: string): Promise { const promises: Promise[] = []; promises.push(this.getAllDeletedEventsIds(siteId)); promises.push(this.getAllEditedEventsIds(siteId)); const result = await Promise.all(promises); return CoreUtils.mergeArraysWithoutDuplicates(result[0], result[1]); } /** * Get all the events deleted in offline. * * @param siteId Site ID. If not defined, current site. * @return Promise resolved with all the events deleted in offline. */ async getAllDeletedEvents(siteId?: string): Promise { const site = await CoreSites.getSite(siteId); return await site.getDb().getRecords(DELETED_EVENTS_TABLE); } /** * Get the IDs of all the events deleted in offline. * * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the IDs of all the events deleted in offline. */ async getAllDeletedEventsIds(siteId?: string): Promise { const events = await this.getAllDeletedEvents(siteId); return events.map((event) => event.id); } /** * Get all the events created/edited in offline. * * @param siteId Site ID. If not defined, current site. * @return Promise resolved with events. */ async getAllEditedEvents(siteId?: string): Promise { const site = await CoreSites.getSite(siteId); return await site.getDb().getRecords(EVENTS_TABLE); } /** * Get the IDs of all the events created/edited in offline. * * @param siteId Site ID. If not defined, current site. * @return Promise resolved with events IDs. */ async getAllEditedEventsIds(siteId?: string): Promise { const events = await this.getAllEditedEvents(siteId); return events.map((event) => event.id!); } /** * Get an event deleted in offline. * * @param eventId Event ID. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the deleted event. */ async getDeletedEvent(eventId: number, siteId?: string): Promise { const site = await CoreSites.getSite(siteId); const conditions: SQLiteDBRecordValues = { id: eventId, }; return await site.getDb().getRecord(DELETED_EVENTS_TABLE, conditions); } /** * Get an offline event. * * @param eventId Event ID. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the event. */ async getEvent(eventId: number, siteId?: string): Promise { const site = await CoreSites.getSite(siteId); const conditions: SQLiteDBRecordValues = { id: eventId, }; return await site.getDb().getRecord(EVENTS_TABLE, conditions); } /** * Check if there are offline events to send. * * @param siteId Site ID. If not defined, current site. * @return Promise resolved with boolean: true if has offline events, false otherwise. */ async hasEditedEvents(siteId?: string): Promise { try { const events = await this.getAllEditedEvents(siteId); return !!events.length; } catch { // No offline data found, return false. return false; } } /** * Check whether there's offline data for a site. * * @param siteId Site ID. If not defined, current site. * @return Promise resolved with boolean: true if has offline data, false otherwise. */ async hasOfflineData(siteId?: string): Promise { const ids = await this.getAllEventsIds(siteId); return ids.length > 0; } /** * Check if an event is deleted. * * @param eventId Event ID. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with boolean: whether the event is deleted. */ async isEventDeleted(eventId: number, siteId?: string): Promise { try { const event = await this.getDeletedEvent(eventId, siteId); return !!event; } catch { return false; } } /** * Mark an event as deleted. * * @param eventId Event ID to delete. * @param name Name of the event to delete. * @param deleteAll If it's a repeated event. whether to delete all events of the series. * @param siteId Site ID. If not defined, current site. * @return Promise resolved when done. */ async markDeleted(eventId: number, name: string, deleteAll?: boolean, siteId?: string): Promise { const site = await CoreSites.getSite(siteId); const event: AddonCalendarOfflineDeletedEventDBRecord = { id: eventId, name: name || '', repeat: deleteAll ? 1 : 0, timemodified: Date.now(), }; return await site.getDb().insertRecord(DELETED_EVENTS_TABLE, event); } /** * Offline version for adding a new discussion to a forum. * * @param eventId Event ID. If it's a new event, set it to undefined/null. * @param data Event data. * @param timeCreated The time the event was created. If not defined, current time. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the stored event. */ async saveEvent( eventId: number | undefined, data: AddonCalendarSubmitCreateUpdateFormDataWSParams, timeCreated?: number, siteId?: string, ): Promise { const site = await CoreSites.getSite(siteId); timeCreated = timeCreated || Date.now(); const event: AddonCalendarOfflineEventDBRecord = { id: eventId || -timeCreated, name: data.name, timestart: data.timestart, eventtype: data.eventtype, categoryid: data.categoryid, courseid: data.courseid, groupcourseid: data.groupcourseid, groupid: data.groupid, description: data.description && data.description.text, location: data.location, duration: data.duration, timedurationuntil: data.timedurationuntil, timedurationminutes: data.timedurationminutes, repeat: data.repeat ? 1 : 0, repeats: data.repeats, repeatid: data.repeatid, repeateditall: data.repeateditall ? 1 : 0, timecreated: timeCreated, userid: site.getUserId(), }; await site.getDb().insertRecord(EVENTS_TABLE, event); return event; } /** * Unmark an event as deleted. * * @param eventId Event ID. * @param siteId Site ID. If not defined, current site. * @return Promise resolved if deleted, rejected if failure. */ async unmarkDeleted(eventId: number, siteId?: string): Promise { const site = await CoreSites.getSite(siteId); const conditions: SQLiteDBRecordValues = { id: eventId, }; await site.getDb().deleteRecords(DELETED_EVENTS_TABLE, conditions); } } export const AddonCalendarOffline = makeSingleton(AddonCalendarOfflineProvider);