diff --git a/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_collection.ts b/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_collection.ts index f1a32bc4f6c3..5fba5e7e9fee 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_collection.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/m_appointment_collection.ts @@ -43,6 +43,7 @@ import type { AppointmentCollectorViewModel, AppointmentItemViewModel, AppointmentViewModelPlain, + SortedEntity, } from '../view_model/types'; import { AgendaAppointment } from './appointment/agenda_appointment'; import { Appointment } from './appointment/m_appointment'; @@ -68,7 +69,7 @@ interface ViewModelDiff { class SchedulerAppointments extends CollectionWidget { // NOTE: The key of this array is `sortedIndex` of appointment rendered in Element - renderedElementsBySortedIndex: dxElementWrapper[] = []; + $itemBySortedIndex: dxElementWrapper[] = []; _appointmentClickTimeout: any; @@ -82,17 +83,19 @@ class SchedulerAppointments extends CollectionWidget { private _kbn!: AppointmentsKeyboardNavigation; + private _focusedItemIndexBeforeRender!: number; + private _isResizing = false; public get isResizing(): boolean { return this._isResizing; } - get isAgendaView() { + get isAgendaView(): boolean { return this.invoke('isCurrentViewAgenda'); } - get isVirtualScrolling() { + get isVirtualScrolling(): boolean { return this.invoke('isVirtualScrolling'); } @@ -104,6 +107,10 @@ class SchedulerAppointments extends CollectionWidget { return this.option('dataAccessors') as AppointmentDataAccessor; } + get sortedItems(): SortedEntity[] { + return this.option('getSortedAppointments')() as SortedEntity[]; + } + getResourceManager(): ResourceManager { return this.option('getResourceManager')(); } @@ -138,7 +145,11 @@ class SchedulerAppointments extends CollectionWidget { const parentValue = super._supportedKeys(); const kbnValue = this._kbn.getSupportedKeys(); - return extend(parentValue, kbnValue) as SupportedKeys; + return { + enter: parentValue.enter, + space: parentValue.space, + ...kbnValue, + }; } public getAppointmentSettings($item: dxElementWrapper): AppointmentViewModelPlain { @@ -152,8 +163,26 @@ class SchedulerAppointments extends CollectionWidget { } _renderFocusTarget() { - const $item = this._kbn.getFocusableItemBySortedIndex(0); - this._kbn.resetTabIndex($item); + this._kbn.resetTabIndex(); + } + + _cleanFocusState(): void { + this._focusedItemIndexBeforeRender = this._kbn.isNavigating + ? this._kbn.focusedItemSortIndex + : -1; + + super._cleanFocusState(); + } + + _renderFocusState(): void { + super._renderFocusState(); + + if (this._focusedItemIndexBeforeRender !== -1) { + this._kbn.focusedItemSortIndex = this._focusedItemIndexBeforeRender; + this._kbn.isNavigating = false; + this._kbn.focus(); + this._focusedItemIndexBeforeRender = -1; + } } _focusInHandler(e) { @@ -162,7 +191,7 @@ class SchedulerAppointments extends CollectionWidget { } _focusOutHandler(e) { - this._kbn.focusOutHandler(); + this._kbn.focusOutHandler(e); super._focusOutHandler(e); } @@ -192,7 +221,7 @@ class SchedulerAppointments extends CollectionWidget { value: AppointmentViewModelPlain[] = [], ): ViewModelDiff[] { const elementsInRenderOrder = previousValue - .map(({ sortedIndex }) => this.renderedElementsBySortedIndex[sortedIndex]); + .map(({ sortedIndex }) => this.$itemBySortedIndex[sortedIndex]); const diff = getViewModelDiff(previousValue, value, this.appointmentDataSource); diff .filter((item) => !isNeedToAdd(item)) @@ -206,7 +235,7 @@ class SchedulerAppointments extends CollectionWidget { _optionChanged(args) { switch (args.name) { case 'items': - (this as any)._cleanFocusState(); + this._cleanFocusState(); if (this.isAgendaView) { this.forceRepaintAllAppointments(args.value || []); @@ -225,12 +254,11 @@ class SchedulerAppointments extends CollectionWidget { case 'allowResize': case 'allowDelete': case 'allowAllDayResize': - (this as any)._cleanFocusState(); + this._cleanFocusState(); this.forceRepaintAllAppointments(this.option('items') || []); this._attachAppointmentsEvents(); break; case 'focusedElement': - this._kbn.resetTabIndex($(args.value)); super._optionChanged(args); break; case 'focusStateEnabled': @@ -251,7 +279,7 @@ class SchedulerAppointments extends CollectionWidget { } protected forceRepaintAllAppointments(items: AppointmentViewModelPlain[]): void { - this.renderedElementsBySortedIndex = []; + this.$itemBySortedIndex = []; this._renderByFragments(($commonFragment, $allDayFragment) => { this._getAppointmentContainer(true).html(''); this._getAppointmentContainer(false).html(''); @@ -269,10 +297,12 @@ class SchedulerAppointments extends CollectionWidget { } protected repaintAppointments(diff: ViewModelDiff[]): void { - this.renderedElementsBySortedIndex = []; + this.$itemBySortedIndex = []; + this._renderByFragments(($commonFragment, $allDayFragment) => { - const isRepaintAll = this.isAgendaView - || !diff.some((item) => item.needToAdd === undefined && item.needToRemove === undefined); + const isRepaintAll = diff.every( + (item) => Boolean(item.needToAdd ?? item.needToRemove), + ); if (isRepaintAll) { this._getAppointmentContainer(true).html(''); @@ -303,7 +333,7 @@ class SchedulerAppointments extends CollectionWidget { if (item.element) { item.element.data(APPOINTMENT_SETTINGS_KEY, item.item); - this.renderedElementsBySortedIndex[item.item.sortedIndex] = item.element; + this.$itemBySortedIndex[item.item.sortedIndex] = item.element; } }); }); @@ -334,14 +364,14 @@ class SchedulerAppointments extends CollectionWidget { } _attachAppointmentsEvents() { - (this as any)._attachClickEvent(); - (this as any)._attachHoldEvent(); - (this as any)._attachContextMenuEvent(); - (this as any)._attachAppointmentDblClick(); + this._attachClickEvent(); + this._attachHoldEvent(); + this._attachContextMenuEvent(); + this._attachAppointmentDblClick(); - (this as any)._renderFocusState(); - (this as any)._attachFeedbackEvents(); - (this as any)._attachHoverEvents(); + this._renderFocusState(); + this._attachFeedbackEvents(); + this._attachHoverEvents(); } _clearDropDownItemsElements() { @@ -390,7 +420,8 @@ class SchedulerAppointments extends CollectionWidget { _init() { super._init(); this._kbn = new AppointmentsKeyboardNavigation(this); - (this as any).$element().addClass(COMPONENT_CLASS); + this._focusedItemIndexBeforeRender = -1; + this.$element().addClass(COMPONENT_CLASS); this._preventSingleAppointmentClick = false; } @@ -519,12 +550,13 @@ class SchedulerAppointments extends CollectionWidget { const $item = super._renderItem(index, item.itemData, container); $item.data(APPOINTMENT_SETTINGS_KEY, item); + if (item.sortedIndex !== -1) { // NOTE: fallback for integration testing - if (!this.renderedElementsBySortedIndex) { - this.renderedElementsBySortedIndex = []; + if (!this.$itemBySortedIndex) { + this.$itemBySortedIndex = []; } - this.renderedElementsBySortedIndex[item.sortedIndex] = $item; + this.$itemBySortedIndex[item.sortedIndex] = $item; } return $item; @@ -673,7 +705,7 @@ class SchedulerAppointments extends CollectionWidget { const $appointment = $(e.element); this._isResizing = true; - this._kbn.$focusedItem = $appointment; + this._kbn.focus($appointment); if (this.invoke('needRecalculateResizableArea')) { const updatedArea = this._calculateResizableArea( @@ -983,13 +1015,13 @@ class SchedulerAppointments extends CollectionWidget { allowDrag: this.option('allowDrag'), isCompact: appointment.isCompact, }); - this.renderedElementsBySortedIndex[appointment.sortedIndex] = $item; + this.$itemBySortedIndex[appointment.sortedIndex] = $item; return $item; } moveAppointmentBack(dragEvent?) { - const $appointment = this._kbn.$focusedItem; + const $appointment = this._kbn.$focusTarget(); const size = this._initialSize; const coords = this._initialCoordinates; @@ -1005,7 +1037,7 @@ class SchedulerAppointments extends CollectionWidget { } } - if ($appointment && !dragEvent) { + if ($appointment.get(0) && !dragEvent) { if (coords) { move($appointment, coords); delete this._initialSize; diff --git a/packages/devextreme/js/__internal/scheduler/appointments/m_appointments_kbn.ts b/packages/devextreme/js/__internal/scheduler/appointments/m_appointments_kbn.ts index 56c01578c029..b489383636ad 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/m_appointments_kbn.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/m_appointments_kbn.ts @@ -5,18 +5,21 @@ import { getPublicElement } from '@ts/core/m_element'; import type { SupportedKeys } from '@ts/core/widget/widget'; import eventsEngine from '@ts/events/core/m_events_engine'; +import type { SortedEntity } from '../view_model/types'; import type SchedulerAppointments from './m_appointment_collection'; -import { getNextElement, getPrevElement } from './utils/sorted_index_utils'; export class AppointmentsKeyboardNavigation { private readonly _collection: SchedulerAppointments; - public $focusedItem: dxElementWrapper | null = null; + public focusedItemSortIndex = -1; + + public isNavigating = false; constructor(collection: SchedulerAppointments) { this._collection = collection; } + // TODO: make disabled appointments focusable and remove this method public getFocusableItems(): dxElementWrapper { const appts = this._collection._itemElements().not('.dx-state-disabled'); const collectors = this._collection.$element().find('.dx-scheduler-appointment-collector'); @@ -24,34 +27,60 @@ export class AppointmentsKeyboardNavigation { return appts.add(collectors); } - public getFocusableItemBySortedIndex(sortedIndex: number): dxElementWrapper { - const $items = this.getFocusableItems(); - const itemElement = $items.toArray().filter((itemElement: Element) => { - const $item = $(itemElement); - const itemData = this._collection.getAppointmentSettings($item); - return itemData.sortedIndex === sortedIndex; - }); + public focus($item?: dxElementWrapper): void { + const $target = $item ?? this.$focusTarget(); - return $(itemElement); + if ($target.length) { + eventsEngine.trigger($target, 'focus'); + } } - public focus(): void { - if (this.$focusedItem) { - const focusedElement = getPublicElement(this.$focusedItem); + public $focusTarget(): dxElementWrapper { + const $items = this._collection.$itemBySortedIndex; + + if (!$items) { + return $(); + } - this._collection.option('focusedElement', focusedElement); - eventsEngine.trigger(focusedElement, 'focus'); + if (this.focusedItemSortIndex !== -1) { + const $item = $items[this.focusedItemSortIndex]; + return $item || $(); } + + const $itemsPlainArray = Object.values($items); + + const $firstItem = this._collection.isVirtualScrolling + ? $itemsPlainArray.find(($item) => this.isItemVisibleInViewport($item)) ?? $() + : $($itemsPlainArray[0]); + + return $firstItem; + } + + public resetTabIndex(): void { + this.getFocusableItems().attr('tabIndex', -1); + this.$focusTarget().attr('tabIndex', this._collection.option('tabIndex')); } public focusInHandler(e: DxEvent): void { - this.$focusedItem = $(e.target); - this._collection.option('focusedElement', getPublicElement(this.$focusedItem)); + const $target = $(e.target); + const itemData = this._collection.getAppointmentSettings($target); + + this.focusedItemSortIndex = itemData.sortedIndex; + this.resetTabIndex(); + this._collection.option('focusedElement', getPublicElement(e.target)); } - public focusOutHandler(): void { - const $item = this.getFocusableItemBySortedIndex(0); - this._collection.option('focusedElement', getPublicElement($item)); + public focusOutHandler(e: DxEvent): void { + const $container = this._collection._itemContainer(); + const isFocusInside = $(e.relatedTarget as Element).closest($container).length > 0; + + if (isFocusInside || this.isNavigating) { + return; + } + + this.focusedItemSortIndex = -1; + this.resetTabIndex(); + this._collection.option('focusedElement', null); } public getSupportedKeys(): SupportedKeys { @@ -64,35 +93,6 @@ export class AppointmentsKeyboardNavigation { }; } - public resetTabIndex($appointment: dxElementWrapper): void { - this.getFocusableItems().attr('tabIndex', -1); - $appointment.attr('tabIndex', this._collection.option('tabIndex')); - } - - private tabHandler(e): void { - if (!this.$focusedItem) { - return; - } - - const $focusableItems = this.getFocusableItems(); - let index = this._collection.getAppointmentSettings(this.$focusedItem).sortedIndex; - let $nextAppointment = e.shiftKey - ? getPrevElement(index, this._collection.renderedElementsBySortedIndex) - : getNextElement(index, this._collection.renderedElementsBySortedIndex); - const lastIndex = $focusableItems.length - 1; - - if ($nextAppointment || (index > 0 && e.shiftKey) || (index < lastIndex && !e.shiftKey)) { - e.preventDefault(); - - if (!$nextAppointment) { - e.shiftKey ? index-- : index++; - $nextAppointment = this.getFocusableItemBySortedIndex(index); - } - - this.focusItem($nextAppointment); - } - } - private delHandler(e: DxEvent): void { if (this._collection.option('allowDelete')) { e.preventDefault(); @@ -108,7 +108,7 @@ export class AppointmentsKeyboardNavigation { this._collection.moveAppointmentBack(); - const resizableInstance = (this.$focusedItem as any).dxResizable('instance'); + const resizableInstance = (this.$focusTarget() as any).dxResizable('instance'); if (resizableInstance) { resizableInstance._detachEventHandlers(); @@ -117,32 +117,77 @@ export class AppointmentsKeyboardNavigation { } } - private homeHandler(e: DxEvent): void { + private tabHandler(e: DxEvent): void { + const items = this._collection.sortedItems; + const nextIndex = this.focusedItemSortIndex + (e.shiftKey ? -1 : 1); + const nextItemData = items[nextIndex]; + + if (!nextItemData) { + return; + } + e.preventDefault(); + this.focusByItemData(nextItemData); + } - const $firstItem = this.getFocusableItems().first(); + private homeHandler(e: DxEvent): void { + const items = this._collection.sortedItems; + const nextItemData = items[0]; - if (this.$focusedItem && $firstItem.is(this.$focusedItem)) { + if (!nextItemData) { return; } - this.focusItem($firstItem); + e.preventDefault(); + this.focusByItemData(nextItemData); } - private endHandler(e: DxEvent): void { + private endHandler(e: DxEvent): void { + const items = this._collection.sortedItems; + const nextItemData = items[items.length - 1]; + + if (!nextItemData) { + return; + } + e.preventDefault(); + this.focusByItemData(nextItemData); + } - const $lastItem = this.getFocusableItems().last(); + private focusByItemData(itemData: SortedEntity): void { + this.focusedItemSortIndex = itemData.sortedIndex; - if (this.$focusedItem && $lastItem.is(this.$focusedItem)) { - return; + if (this._collection.isVirtualScrolling) { + this.isNavigating = true; + this.scrollToByItemData(itemData); } - this.focusItem($lastItem); + this.focus(); } - private focusItem($item: dxElementWrapper): void { - this.resetTabIndex($item); - eventsEngine.trigger($item, 'focus'); + private scrollToByItemData(itemData: SortedEntity): void { + const date = new Date(Math.max( + this._collection.invoke('getStartViewDate').getTime(), + itemData.source.startDate, + )); + + this._collection.option('scrollTo')( + date, + { + group: itemData.itemData, + allDay: itemData.allDay, + }, + ); + } + + private isItemVisibleInViewport($item: dxElementWrapper): boolean { + const $container = this._collection.$element().closest('.dx-scrollable-container'); + const containerRect = $container.get(0).getBoundingClientRect(); + const itemRect = $item.get(0).getBoundingClientRect(); + + return (itemRect.top < containerRect.bottom + && itemRect.bottom > containerRect.top + && itemRect.left < containerRect.right + && itemRect.right > containerRect.left); } } diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index 73054577d215..5f78323305ee 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -874,6 +874,7 @@ class Scheduler extends SchedulerOptionsBaseWidget { this._appointments.option('items', viewModel); this.appointmentDataSource.cleanState(); + if (this._isAgenda()) { this._workSpace.renderAgendaLayout(viewModel); } @@ -1234,8 +1235,9 @@ class Scheduler extends SchedulerOptionsBaseWidget { _appointmentsConfig() { const config = { getResourceManager: () => this.resourceManager, - getAppointmentDataSource: () => this.appointmentDataSource, + getSortedAppointments: () => this._layoutManager.sortedItems, + scrollTo: this.scrollTo.bind(this), dataAccessors: this._dataAccessors, notifyScheduler: this._notifyScheduler, onItemRendered: this._getAppointmentRenderedAction(), @@ -1372,9 +1374,7 @@ class Scheduler extends SchedulerOptionsBaseWidget { schedulerWidth: this.option('width'), allDayPanelMode: this.option('allDayPanelMode'), onSelectedCellsClick: this.showAddAppointmentPopup.bind(this), - onRenderAppointments: () => { - this._renderAppointments(); - }, + renderAppointments: () => { this._renderAppointments(); }, onShowAllDayPanel: (value) => this.option('showAllDayPanel', value), getHeaderHeight: () => utils.DOM.getHeaderHeight(this._header), onScrollEnd: () => this._appointments.updateResizableArea(), diff --git a/packages/devextreme/js/__internal/scheduler/view_model/appointments_layout_manager.ts b/packages/devextreme/js/__internal/scheduler/view_model/appointments_layout_manager.ts index 6ea190eaa0dc..43939828151a 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/appointments_layout_manager.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/appointments_layout_manager.ts @@ -5,7 +5,7 @@ import { filterAppointments } from './filtration/filter_appointments'; import type { Occurrence } from './filtration/get_occurrences'; import { getOccurrences } from './filtration/get_occurrences'; import { generateAgendaViewModel } from './generate_view_model/generate_agenda_view_model'; -import { generateGridViewModel } from './generate_view_model/generate_grid_view_model'; +import { generateGridViewModel, sortAppointments } from './generate_view_model/generate_grid_view_model'; import type { RealSize } from './generate_view_model/steps/add_geometry/types'; import { getAgendaAppointmentInfo, getAppointmentInfo } from './get_appointment_info'; import { prepareAppointments } from './preparation/prepare_appointments'; @@ -16,6 +16,7 @@ import type { AppointmentViewModelPlain, ListEntity, MinimalAppointmentEntity, + SortedEntity, UTCDatesBeforeSplit, } from './types'; @@ -24,6 +25,12 @@ class AppointmentLayoutManager { filteredItems: ListEntity[] = []; + private _sortedItems: SortedEntity[] = []; + + public get sortedItems(): SortedEntity[] { return this._sortedItems; } + + viewModel: AppointmentViewModelPlain[] = []; + // NOTE: Here we should pass global store. But right now scheduler component is global store constructor(public schedulerStore: Scheduler) {} @@ -35,6 +42,10 @@ class AppointmentLayoutManager { this.filteredItems = filterAppointments(this.schedulerStore, this.preparedItems); } + private sortAppointments(): void { + this._sortedItems = sortAppointments(this.schedulerStore, this.filteredItems); + } + public getOccurrences( startDate: Date, endDate: Date, @@ -66,10 +77,11 @@ class AppointmentLayoutManager { })); } + this.sortAppointments(); const isSkipResizing = (appointment: ListEntity): boolean => appointment.isAllDayPanelOccupied && viewType === 'day' && this.schedulerStore.currentView.intervalCount === 1; - const viewModel = generateGridViewModel(this.schedulerStore, this.filteredItems); + const viewModel = generateGridViewModel(this.schedulerStore, this._sortedItems); const toItem = (item: AppointmentEntity): AppointmentItemViewModel => ({ itemData: item.itemData, allDay: item.isAllDayPanelOccupied, @@ -101,6 +113,7 @@ class AppointmentLayoutManager { height: item.height, info: getAppointmentInfo(item), } as unknown as AppointmentItemViewModel); + return viewModel.map((item) => { if (item.items.length) { return { diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts index b91034f26441..b91e47257dc3 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts @@ -1,5 +1,5 @@ import type Scheduler from '../../m_scheduler'; -import type { AppointmentEntity, ListEntity } from '../types'; +import type { AppointmentEntity, ListEntity, SortedEntity } from '../types'; import { OptionManager } from './options/option_manager'; import { addCollector } from './steps/add_collector/add_collector'; import { addDirection } from './steps/add_direction'; @@ -16,22 +16,17 @@ import { splitByParts } from './steps/split_by_parts/split_by_parts'; import { cropByVirtualScreen } from './steps/virtual_screen_crop'; import { filterByVirtualScreen } from './steps/virtual_screen_filter'; -export const generateGridViewModel = ( +export const sortAppointments = ( schedulerStore: Scheduler, items: ListEntity[], -): AppointmentEntity[] => { +): SortedEntity[] => { const optionManager = new OptionManager(schedulerStore); const { - viewOrientation, isMonthView, - isAdaptivityEnabled, - isTimelineView, hasAllDayPanel, - isVirtualScrolling, viewOffset, compareOptions: { endDayHour }, } = optionManager.options; - const { viewDataProvider } = schedulerStore._workSpace; const step2 = maybeSplit(items, hasAllDayPanel, (entities, panelName) => { const byGroup = groupByGroupIndex(entities); @@ -57,8 +52,27 @@ export const generateGridViewModel = ( }); const step3 = addSortedIndex(step2); + + return step3; +}; + +export const generateGridViewModel = ( + schedulerStore: Scheduler, + items: SortedEntity[], +): AppointmentEntity[] => { + const optionManager = new OptionManager(schedulerStore); + const { + viewOrientation, + isMonthView, + isAdaptivityEnabled, + isTimelineView, + hasAllDayPanel, + isVirtualScrolling, + } = optionManager.options; + const { viewDataProvider } = schedulerStore._workSpace; + const step4 = filterByVirtualScreen( - step3, + items, viewDataProvider, isVirtualScrolling, ); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/types.ts b/packages/devextreme/js/__internal/scheduler/view_model/types.ts index 84fc9e34853d..591d2be66ccc 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/types.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/types.ts @@ -149,14 +149,16 @@ export interface Direction { direction: Orientation; } -export type AppointmentEntity = ListEntity - & UTCDatesBeforeSplit +export type SortedEntity = ListEntity & AppointmentPart - & Level & Position + & Level + & AppointmentCollector + & SortedIndex; + +export type AppointmentEntity = SortedEntity & Direction & Empty - & SortedIndex & Geometry & AppointmentCollectorWithGeometry; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_virtual_scrolling.ts index 944f7e3b8616..55523a568f96 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_virtual_scrolling.ts @@ -691,11 +691,11 @@ export class VirtualScrollingRenderer { clearTimeout(this._renderAppointmentTimeoutID); this._renderAppointmentTimeoutID = setTimeout( - () => this.workspace.updateAppointments(), + () => this.workspace.renderAppointments(), renderTimeout, ); } else { - this.workspace.updateAppointments(); + this.workspace.renderAppointments(); } } } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts index 6105e50b0732..e2756dab6488 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -2285,7 +2285,7 @@ class SchedulerWorkSpace extends Widget { draggingMode: 'outlook', onScrollEnd: () => {}, getHeaderHeight: undefined, - onRenderAppointments: () => {}, + renderAppointments: () => {}, onShowAllDayPanel: () => {}, onSelectedCellsClick: () => {}, timeZoneCalculator: undefined, @@ -2363,7 +2363,7 @@ class SchedulerWorkSpace extends Widget { break; case 'allDayPanelMode': this.updateShowAllDayPanel(); - this.updateAppointments(); + this.renderAppointments(); break; case 'width': // @ts-expect-error @@ -2888,8 +2888,8 @@ class SchedulerWorkSpace extends Widget { this.renderer._renderGrid(); } - updateAppointments() { - (this.option('onRenderAppointments') as any)(); + renderAppointments() { + (this.option('renderAppointments') as any)(); this.dragBehavior?.updateDragSource(); }