@progress/kendo-angular-scheduler
Version:
Kendo UI Scheduler Angular - Outlook or Google-style angular scheduler calendar. Full-featured and customizable embedded scheduling from the creator developers trust for professional UI components.
123 lines (122 loc) • 4.48 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { isPresent, isRecurring, isException, readEvent, getField, setField, assignValues, clone } from '../common/util';
import { isDevMode } from '@angular/core';
import { guid } from '@progress/kendo-angular-common';
const isRecurrenceMaster = (ev) => !!(ev.id && ev.recurrenceRule);
/**
* @hidden
*/
export class LocalEditService {
scheduler;
localDataChangesService;
get fields() {
return this.scheduler.modelFields;
}
get hasLocalData() {
return isPresent(this.localDataChangesService.data);
}
get data() {
if (this.hasLocalData) {
return this.localDataChangesService.data;
}
return this.scheduler.events;
}
constructor(scheduler, localDataChangesService) {
this.scheduler = scheduler;
this.localDataChangesService = localDataChangesService;
}
create(item) {
const idField = this.fields.id;
const id = getField(item, idField);
if (!isPresent(id)) {
setField(item, idField, this.nextId());
}
this.data.push(item);
this.dataChanged();
}
createException(item, value) {
const exception = this.buildException(value);
this.removeOccurrenceInternal(item);
this.create(exception);
}
update(item, value) {
assignValues(item, value);
this.dataChanged();
}
remove(item) {
const idField = this.fields.id;
const itemId = getField(item, idField);
const data = this.data;
for (let idx = 0; idx < data.length; idx++) {
if (itemId === getField(data[idx], idField)) {
data.splice(idx, 1);
break;
}
}
this.dataChanged();
}
removeSeries(item) {
const event = readEvent(item, this.fields);
const isHead = isRecurrenceMaster(event);
this.removeItemAndExceptions(isHead ? event.id : event.recurrenceId);
this.dataChanged();
}
removeOccurrence(item) {
this.removeOccurrenceInternal(item);
this.dataChanged();
}
findRecurrenceMaster(item) {
const fields = this.scheduler.modelFields;
const event = readEvent(item, fields);
const headId = isRecurrenceMaster(event) ? event.id : event.recurrenceId;
return this.data.find((dataItem) => getField(dataItem, fields.id) === headId);
}
isRecurring(event) {
return isRecurring(event, this.scheduler.modelFields);
}
isException(event) {
return isException(event, this.scheduler.modelFields);
}
nextId() {
return guid();
}
buildException(item) {
const fields = this.fields;
const head = this.findRecurrenceMaster(item);
if (!head) {
if (isDevMode()) {
throw new Error('Unable to find recurrence head for event. Please check that recurrenceId is set and refers to an existing event.');
}
return;
}
const exception = clone(item);
setField(exception, fields.id, this.nextId());
setField(exception, fields.recurrenceId, getField(head, fields.id));
setField(exception, fields.recurrenceRule, null);
return exception;
}
removeItemAndExceptions(itemId) {
const data = this.data;
const fields = this.scheduler.modelFields;
for (let idx = data.length - 1; idx >= 0; idx--) {
if (itemId === getField(data[idx], fields.recurrenceId) || itemId === getField(data[idx], fields.id)) {
data.splice(idx, 1);
}
}
}
removeOccurrenceInternal(item) {
const fields = this.fields;
const head = this.findRecurrenceMaster(item);
const exceptionDate = getField(item, fields.start);
const currentExceptions = getField(head, fields.recurrenceExceptions) || [];
setField(head, fields.recurrenceExceptions, [...currentExceptions, exceptionDate]);
}
dataChanged() {
if (this.hasLocalData) {
this.localDataChangesService.changes.emit();
}
}
}