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.

221 lines (220 loc) 11.1 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { ChangeDetectorRef, Directive, NgZone } from '@angular/core'; import { Keys } from '@progress/kendo-angular-common'; import { ZonedDate } from '@progress/kendo-date-math'; import { Subscription } from 'rxjs'; import { FocusService } from './focus.service'; import { Modifiers, noModifiers, withModifiers } from '../common/modifiers'; import { groupResources } from '../common/util'; import { SchedulerComponent } from '../scheduler.component'; import { DomEventsService } from '../views/common/dom-events.service'; import { take } from 'rxjs/operators'; import { ViewStateService } from '../views/view-state.service'; import { hasClasses } from '../common/dom-queries'; import { DialogsService } from '../editing/dialogs.service'; import * as i0 from "@angular/core"; import * as i1 from "../scheduler.component"; import * as i2 from "../views/common/dom-events.service"; import * as i3 from "./focus.service"; import * as i4 from "../views/view-state.service"; import * as i5 from "../editing/dialogs.service"; const isContentWrapper = element => hasClasses(element, 'k-scheduler-content'); const CALENDAR_TAG = 'KENDO-CALENDAR-HORIZONTAL'; /** * @hidden */ export class ShortcutsDirective { scheduler; domEvents; focusService; zone; changeDetector; viewState; dialogsService; shortcuts = [{ match: e => e.keyCode === Keys.KeyC && noModifiers(e), action: e => { const scheduler = this.scheduler; const hours = new Date().getHours(); const selected = scheduler.selectedDate; const start = new Date(selected.getFullYear(), selected.getMonth(), selected.getDate(), hours + 1); const end = new Date(selected.getFullYear(), selected.getMonth(), selected.getDate(), hours + 2); let firstResource; if (scheduler.group) { const resources = scheduler.resources || []; const group = scheduler.group || {}; const grouped = groupResources(group, resources); if (grouped.length > 0) { firstResource = grouped[0].data[0]; } } scheduler.create.emit({ start: ZonedDate.fromLocalDate(start, scheduler.timezone).toLocalDate(), end: ZonedDate.fromLocalDate(end, scheduler.timezone).toLocalDate(), isAllDay: false, resources: [firstResource], originalEvent: e, sender: scheduler }); } }, { match: e => e.keyCode >= Keys.Digit1 && e.keyCode <= Keys.Digit9 && withModifiers(e, Modifiers.AltKey), action: e => { const scheduler = this.scheduler; const viewIndex = e.keyCode - Keys.Digit0 - 1; const views = scheduler.views.toArray(); const view = views[viewIndex]; if (view) { this.zone.run(() => { const prevented = scheduler.onNavigationAction({ type: 'view-change', view }); if (!prevented) { this.changeDetector.markForCheck(); this.focusWait(); } }); } } }, { match: e => e.keyCode === Keys.F10 && noModifiers(e), action: (e) => { this.zone.run(() => { e.preventDefault(); this.scheduler.onNavigationAction({ type: 'focus-toolbar' }); this.focusWait(); }); } }, { match: e => e.keyCode === Keys.KeyT && noModifiers(e), action: () => { this.zone.run(() => { this.scheduler.onNavigationAction({ type: 'today' }); this.focusWait(); }); } }, { match: e => e.keyCode === Keys.KeyB && noModifiers(e), action: () => { this.zone.run(() => { this.scheduler.onNavigationAction({ type: 'toggle-business-hours' }); this.focusWait(); }); } }, { match: (e) => (e.keyCode === Keys.ArrowLeft || e.keyCode === Keys.ArrowRight) && withModifiers(e, Modifiers.ShiftKey), action: (e) => { const type = e.keyCode === Keys.ArrowLeft ? 'prev' : 'next'; this.zone.run(() => { this.scheduler.onNavigationAction({ type }); this.focusWait(); }); } }, { match: e => (e.keyCode === Keys.ArrowUp || e.keyCode === Keys.ArrowLeft) && noModifiers(e) && !isContentWrapper(e.target), action: e => { //use the MultiViewCalendar navigation for Year View if (e.target.tagName === CALENDAR_TAG) { return; } // do nothing if the shortcut is executed on an element inside the kendoSchedulerToolbarTemplate if (this.isInToolbarTemplate(e.target)) { return; } const prevented = this.scheduler.onNavigationAction({ type: 'focus-prev' }); if (!prevented) { const item = this.focusService.activeItem; const isFirstEvent = item.containerType === 'content' && item.element.nativeElement.matches(':first-of-type'); const isUpArrow = e.keyCode === Keys.ArrowUp; // eslint-disable-next-line no-unused-expressions isFirstEvent && isUpArrow ? this.focusService.focusToolbar() : this.focusService.focusNext({ offset: -1 }); e.preventDefault(); } } }, { match: e => (e.keyCode === Keys.ArrowDown || e.keyCode === Keys.ArrowRight) && noModifiers(e) && !isContentWrapper(e.target), action: e => { //use the MultiViewCalendar navigation for Year View if (e.target.tagName === CALENDAR_TAG) { return; } // do nothing if the shortcut is executed on an element inside the kendoSchedulerToolbarTemplate if (this.isInToolbarTemplate(e.target)) { return; } const prevented = this.scheduler.onNavigationAction({ type: 'focus-next' }); if (!prevented) { const isInToolbar = this.focusService.activeItem.containerType === 'toolbar'; const offset = 1; if (e.keyCode === Keys.ArrowDown && isInToolbar) { const focusableElementsArray = Array.from(this.focusService.focusableItems); const firstFocusableContentElementIndex = focusableElementsArray.findIndex(item => item.containerType === 'content'); if (firstFocusableContentElementIndex > -1) { this.focusService.focusByIndex(firstFocusableContentElementIndex); e.preventDefault(); return; } } this.focusService.focusNext({ offset }); e.preventDefault(); } } }]; taskShortcuts = [{ match: e => (e.keyCode === Keys.Delete || e.keyCode === Keys.Backspace) && noModifiers(e), action: (e, event) => { this.viewState.emitEvent('remove', { event: event, dataItem: event.dataItem }); e.preventDefault(); } }, { match: e => e.keyCode === Keys.Enter && noModifiers(e), action: (e, event) => { this.viewState.emitEvent('eventDblClick', { type: 'dblclick', event: event, originalEvent: e }); e.preventDefault(); } }]; subs = new Subscription(); constructor(scheduler, domEvents, focusService, zone, changeDetector, viewState, dialogsService) { this.scheduler = scheduler; this.domEvents = domEvents; this.focusService = focusService; this.zone = zone; this.changeDetector = changeDetector; this.viewState = viewState; this.dialogsService = dialogsService; this.subs.add(this.domEvents.keydown.subscribe(e => this.onKeydown(e))); this.subs.add(this.scheduler.eventKeydown.subscribe(e => this.onEventKeydown(e))); } onKeydown(e) { const match = this.shortcuts.find(shortcut => shortcut.match(e)); if (match && !this.dialogsService.isOpen) { match.action(e); } } onEventKeydown(e) { const match = this.taskShortcuts.find(shortcut => shortcut.match(e.originalEvent)); if (match && !this.dialogsService.isOpen) { match.action(e.originalEvent, e.event); } } focusWait() { this.viewState.layoutEnd.pipe(take(1)).subscribe(() => this.focusService.focus()); } isInToolbarTemplate(element) { const isInToolbar = element.closest('.k-scheduler-toolbar'); const isInBuiltInElement = element.closest('.k-toolbar-group') || element.closest('.k-scheduler-views') || element.closest('.k-views-dropdown'); return isInToolbar && !isInBuiltInElement; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ShortcutsDirective, deps: [{ token: i1.SchedulerComponent }, { token: i2.DomEventsService }, { token: i3.FocusService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i4.ViewStateService }, { token: i5.DialogsService }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ShortcutsDirective, isStandalone: true, selector: "kendo-scheduler", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ShortcutsDirective, decorators: [{ type: Directive, args: [{ selector: 'kendo-scheduler', standalone: true }] }], ctorParameters: function () { return [{ type: i1.SchedulerComponent }, { type: i2.DomEventsService }, { type: i3.FocusService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i4.ViewStateService }, { type: i5.DialogsService }]; } });