@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
JavaScript
/**-----------------------------------------------------------------------------------------
* 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
}] } });