UNPKG

@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.

243 lines (242 loc) 10.4 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Input, Output, EventEmitter, Directive } from '@angular/core'; import { SchedulerComponent } from '../scheduler.component'; import { merge } from 'rxjs'; import { LocalDataChangesService } from '../editing/local-data-changes.service'; import { LocalEditService } from './local-edit.service'; import { DialogsService } from '../editing/dialogs.service'; import { EditMode, CrudOperation } from '../types'; import { AddEvent } from '../events'; import { groupResources, assignValues, clone, setField, getField } from '../common/util'; import { diff, areEqual, seriesDate, updateRecurrenceRule } from './utils'; import { FocusService } from '../navigation'; import * as i0 from "@angular/core"; import * as i1 from "../scheduler.component"; import * as i2 from "../editing/local-data-changes.service"; import * as i3 from "../editing/dialogs.service"; import * as i4 from "../navigation"; /** * @hidden */ export class EditingDirectiveBase { scheduler; localDataChangesService; dialogsService; focusService; /** * Fires before the editing directive renders the **Add** dialog. */ add = new EventEmitter(); /** * Fires before the editing directive renders the **Edit** dialog. */ edit = new EventEmitter(); /** * The edit service that will handle the editing operations. */ set editService(value) { this.userEditService = value; } get editService() { return this.userEditService || this.defaultEditService; } defaultTitle = 'No title'; subscriptions; defaultEditService; userEditService; constructor(scheduler, localDataChangesService, dialogsService, focusService) { this.scheduler = scheduler; this.localDataChangesService = localDataChangesService; this.dialogsService = dialogsService; this.focusService = focusService; this.defaultEditService = this.createDefaultService(); this.scheduler.editable = true; } /** * @hidden */ ngOnInit() { this.subscriptions = merge(this.scheduler.slotDblClick, this.scheduler.create).subscribe(this.addHandler.bind(this)); this.subscriptions.add(this.scheduler.removeConfirmed.subscribe(this.removeHandler.bind(this))); this.subscriptions.add(this.scheduler.cancel.subscribe(this.cancelHandler.bind(this))); this.subscriptions.add(this.scheduler.resizeEndConfirmed.subscribe(this.resizeEndHandler.bind(this))); this.subscriptions.add(this.scheduler.dragEndConfirmed.subscribe(this.dragEndHandler.bind(this))); } /** * @hidden */ ngOnDestroy() { this.subscriptions.unsubscribe(); } createDefaultService() { return new LocalEditService(this.scheduler, this.localDataChangesService); } addHandler(args) { this.closeEditor(); if (!this.isEnabled('add')) { return; } const fields = this.scheduler.modelFields; const dataItem = {}; setField(dataItem, fields.start, args.start); setField(dataItem, fields.end, args.end); setField(dataItem, fields.isAllDay, args.isAllDay); setField(dataItem, fields.title, args.title); const resources = groupResources(this.scheduler.group, this.scheduler.resources); const slotResources = args.resources; for (let idx = 0; idx < resources.length; idx++) { const resource = resources[idx]; const value = getField(slotResources[idx], resource.valueField); setField(dataItem, resource.field, resource.multiple ? [value] : value); } const addArgs = new AddEvent(this.scheduler, { dataItem }); this.add.emit(addArgs); if (!addArgs.isDefaultPrevented()) { this.scheduler.addEvent(this.createModel({ action: 'add', isNew: true, dataItem, sender: this.scheduler, })); } } removeHandler({ dataItem }) { if (!this.isEnabled('remove')) { return; } if (this.editService.isRecurring(dataItem)) { this.dialogsService.openRecurringConfirmationDialog(CrudOperation.Remove) .subscribe((editMode) => { if (editMode !== undefined) { this.handleRemove(dataItem, editMode); this.focusService.focusContent(); } }); } else { this.dialogsService.openRemoveConfirmationDialog() .subscribe((shouldRemove) => { if (shouldRemove) { this.handleRemove(dataItem, EditMode.Event); this.focusService.focusContent(); } }); } } cancelHandler() { this.closeEditor(); } closeEditor() { this.scheduler.closeEvent(); } handleUpdate(item, value, mode) { const svc = this.editService; if (mode === EditMode.Occurrence) { // eslint-disable-next-line no-unused-expressions svc.isException(item) ? svc.update(item, value) : svc.createException(item, value); } else { // Item is not recurring or we're editing the entire series svc.update(item, value); } } handleRemove(item, mode) { const svc = this.editService; if (mode === EditMode.Series) { svc.removeSeries(item); } else if (mode === EditMode.Occurrence) { svc.isException(item) ? svc.remove(item) : svc.removeOccurrence(item); } else { // Item is not recurring svc.remove(item); } } resizeEndHandler({ event, start, end }) { if (areEqual(start, event.start) && areEqual(end, event.end)) { return; } const dataItem = event.dataItem; const fields = this.scheduler.modelFields; let value = {}; setField(value, fields.start, start); setField(value, fields.end, end); if (this.editService.isRecurring(dataItem)) { this.dialogsService.openRecurringConfirmationDialog(CrudOperation.Edit) .subscribe((result) => { let target = dataItem; if (result === EditMode.Series) { target = this.editService.findRecurrenceMaster(dataItem); setField(value, fields.start, seriesDate(target, dataItem, value, fields.start)); setField(value, fields.end, seriesDate(target, dataItem, value, fields.end)); } else if (result !== undefined) { value = assignValues(clone(dataItem), value); } this.handleUpdate(target, value, result); }); } else { this.editService.update(dataItem, value); } } dragEndHandler({ event: { dataItem }, start, end, resources, isAllDay }) { const modelFields = this.scheduler.modelFields; const resourceFields = groupResources(this.scheduler.group, this.scheduler.resources).map(r => r.field); const fields = [modelFields.start, modelFields.end, modelFields.isAllDay].concat(resourceFields); let value = clone(resources); setField(value, modelFields.start, start); setField(value, modelFields.end, end); setField(value, modelFields.isAllDay, isAllDay); if (!diff(dataItem, value, fields)) { return; } if (this.editService.isRecurring(dataItem)) { this.dialogsService.openRecurringConfirmationDialog(CrudOperation.Edit) .subscribe((result) => { let target = dataItem; if (result === EditMode.Series) { target = this.editService.findRecurrenceMaster(dataItem); if (dataItem.recurrenceRule) { const newRecurrenceRule = updateRecurrenceRule(dataItem, value); if (newRecurrenceRule !== dataItem?.recurrenceRule) { setField(value, modelFields.recurrenceRule, newRecurrenceRule); } } setField(value, modelFields.start, seriesDate(target, dataItem, value, modelFields.start)); setField(value, modelFields.end, seriesDate(target, dataItem, value, modelFields.end)); } else if (result !== undefined) { value = assignValues(clone(dataItem), value); } this.handleUpdate(target, value, result); }); } else { this.editService.update(dataItem, value); } } isEnabled(action) { const editable = this.scheduler.editable; return editable && editable[action] !== false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EditingDirectiveBase, deps: [{ token: i1.SchedulerComponent }, { token: i2.LocalDataChangesService }, { token: i3.DialogsService }, { token: i4.FocusService }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: EditingDirectiveBase, inputs: { editService: "editService" }, outputs: { add: "add", edit: "edit" }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EditingDirectiveBase, decorators: [{ type: Directive }], ctorParameters: function () { return [{ type: i1.SchedulerComponent }, { type: i2.LocalDataChangesService }, { type: i3.DialogsService }, { type: i4.FocusService }]; }, propDecorators: { add: [{ type: Output }], edit: [{ type: Output }], editService: [{ type: Input }] } });