UNPKG

devextreme

Version:

JavaScript/TypeScript Component Suite for Responsive Web Development

862 lines (860 loc) • 39 kB
/** * DevExtreme (cjs/__internal/scheduler/appointments/m_appointment_collection.js) * Version: 25.2.7 * Build date: Tue May 05 2026 * * Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _translator = require("../../../common/core/animation/translator"); var _events_engine = _interopRequireDefault(require("../../../common/core/events/core/events_engine")); var _double_click = require("../../../common/core/events/double_click"); var _index = require("../../../common/core/events/utils/index"); var _component_registrator = _interopRequireDefault(require("../../../core/component_registrator")); var _dom_adapter = _interopRequireDefault(require("../../../core/dom_adapter")); var _renderer = _interopRequireDefault(require("../../../core/renderer")); var _common = require("../../../core/utils/common"); var _date = _interopRequireDefault(require("../../../core/utils/date")); var _dom = require("../../../core/utils/dom"); var _extend = require("../../../core/utils/extend"); var _iterator = require("../../../core/utils/iterator"); var _position = require("../../../core/utils/position"); var _size = require("../../../core/utils/size"); var _type = require("../../../core/utils/type"); var _date2 = require("../../core/utils/date"); var _collection_widget = _interopRequireDefault(require("../../ui/collection/collection_widget.edit")); var _constants = require("../constants"); var _m_classes = require("../m_classes"); var _m_utils_time_zone = _interopRequireDefault(require("../m_utils_time_zone")); var _appointment_adapter = require("../utils/appointment_adapter/appointment_adapter"); var _get_targeted_appointment = require("../utils/get_targeted_appointment"); var _appointment_groups_utils = require("../utils/resource_manager/appointment_groups_utils"); var _group_utils = require("../utils/resource_manager/group_utils"); var _agenda_appointment = require("./appointment/agenda_appointment"); var _m_appointment = require("./appointment/m_appointment"); var _m_appointment_layout = require("./m_appointment_layout"); var _m_appointments_kbn = require("./m_appointments_kbn"); var _m_text_utils = require("./m_text_utils"); var _m_core = require("./resizing/m_core"); var _get_arrays_diff = require("./utils/get_arrays_diff"); var _get_view_model_diff = require("./utils/get_view_model_diff"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } const COMPONENT_CLASS = "dx-scheduler-scrollable-appointments"; const DBLCLICK_EVENT_NAME = (0, _index.addNamespace)(_double_click.name, "dxSchedulerAppointment"); const toMs = _date.default.dateToMilliseconds; class SchedulerAppointments extends _collection_widget.default { constructor() { super(...arguments); this._isResizing = false } get isResizing() { return this._isResizing } get isAgendaView() { return this.invoke("isCurrentViewAgenda") } get isVirtualScrolling() { return this.invoke("isVirtualScrolling") } get appointmentDataSource() { return this.option("getAppointmentDataSource")() } get dataAccessors() { return this.option("dataAccessors") } get sortedItems() { return this.option("getSortedAppointments")() } getResourceManager() { return this.option("getResourceManager")() } option(optionName, value) { return super.option(...arguments) } notifyObserver(subject, args) { const notifyScheduler = this.option("notifyScheduler"); if (notifyScheduler) { notifyScheduler.invoke(subject, args) } } invoke(funcName) { const notifyScheduler = this.option("notifyScheduler"); if (notifyScheduler) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key] } return notifyScheduler.invoke(funcName, ...args) } } _dispose() { clearTimeout(this._appointmentClickTimeout); super._dispose() } _supportedKeys() { const parentValue = super._supportedKeys(); const kbnValue = this._kbn.getSupportedKeys(); return Object.assign({ enter: parentValue.enter, space: parentValue.space }, kbnValue) } getAppointmentSettings($item) { return $item.data(_constants.APPOINTMENT_SETTINGS_KEY) } _moveFocus() {} _focusTarget() { return this._kbn.getFocusableItems() } _renderFocusTarget() { var _this$$itemBySortedIn; if (null !== (_this$$itemBySortedIn = this.$itemBySortedIndex) && void 0 !== _this$$itemBySortedIn && _this$$itemBySortedIn.length) { this._kbn.resetTabIndex(this._kbn.getFirstVisibleItem()) } } _cleanFocusState() { this._focusedItemIndexBeforeRender = this._kbn.isNavigating ? this._kbn.focusedItemSortIndex : -1; super._cleanFocusState() } _renderFocusState() { super._renderFocusState(); if (-1 !== this._focusedItemIndexBeforeRender) { this._kbn.focusedItemSortIndex = this._focusedItemIndexBeforeRender; this._kbn.isNavigating = false; this._kbn.focus(); this._focusedItemIndexBeforeRender = -1 } else { this._kbn.focusedItemSortIndex = -1 } } _focusInHandler(e) { super._focusInHandler(e); this._kbn.focusInHandler(e) } _focusOutHandler(e) { this._kbn.focusOutHandler(); super._focusOutHandler(e) } _eventBindingTarget() { return this._itemContainer() } _getDefaultOptions() { return (0, _extend.extend)(super._getDefaultOptions(), { noDataText: null, activeStateEnabled: true, hoverStateEnabled: true, tabIndex: 0, fixedContainer: null, allDayContainer: null, allowDrag: true, allowResize: true, allowAllDayResize: true, onAppointmentDblClick: null, groups: [], resources: [] }) } getItemsDiff() { let previousValue = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : []; let value = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : []; const elementsInRenderOrder = previousValue.map(_ref => { let { sortedIndex: sortedIndex } = _ref; return this.$itemBySortedIndex[sortedIndex] }); const diff = (0, _get_view_model_diff.getViewModelDiff)(previousValue, value, this.appointmentDataSource); diff.filter(item => !(0, _get_arrays_diff.isNeedToAdd)(item)).forEach((item, index) => { item.element = elementsInRenderOrder[index] }); return diff } _optionChanged(args) { switch (args.name) { case "items": this._cleanFocusState(); if (this.isAgendaView) { this.forceRepaintAllAppointments(args.value || []) } else { const diff = this.getItemsDiff(args.previousValue, args.value); this.repaintAppointments(diff) } this._attachAppointmentsEvents(); break; case "fixedContainer": case "allDayContainer": case "onAppointmentDblClick": case "allowDelete": break; case "allowDrag": case "allowResize": case "allowAllDayResize": this._cleanFocusState(); this.forceRepaintAllAppointments(this.option("items") || []); this._attachAppointmentsEvents(); break; case "focusedElement": this._kbn.resetTabIndex((0, _renderer.default)(args.value)); super._optionChanged(args); break; case "focusStateEnabled": this._clearDropDownItemsElements(); this.renderDropDownAppointments(); super._optionChanged(args); break; default: super._optionChanged(args) } } _applyFragment(fragment, allDay) { if (fragment.children().length > 0) { this._getAppointmentContainer(allDay).append(fragment) } } forceRepaintAllAppointments(items) { this.$itemBySortedIndex = []; this._renderByFragments(($commonFragment, $allDayFragment) => { this._getAppointmentContainer(true).html(""); this._getAppointmentContainer(false).html(""); if (0 === items.length) { this._cleanItemContainer() } items.forEach((item, index) => { const container = item.allDay ? $allDayFragment : $commonFragment; this._renderItem(index, item, container) }) }) } repaintAppointments(diff) { this.$itemBySortedIndex = []; this._renderByFragments(($commonFragment, $allDayFragment) => { const isRepaintAll = diff.every(item => Boolean(item.needToAdd ?? item.needToRemove)); if (isRepaintAll) { this._getAppointmentContainer(true).html(""); this._getAppointmentContainer(false).html("") } if (0 === diff.length) { this._cleanItemContainer() } diff.forEach((item, index) => { if (isRepaintAll && item.needToRemove) { return } if (item.needToRemove) { var _item$element, _item$element2; null === (_item$element = item.element) || void 0 === _item$element || _item$element.detach(); null === (_item$element2 = item.element) || void 0 === _item$element2 || _item$element2.remove(); return } if (item.needToAdd) { const container = item.item.allDay ? $allDayFragment : $commonFragment; this._renderItem(index, item.item, container); return } if (item.element) { item.element.data(_constants.APPOINTMENT_SETTINGS_KEY, item.item); this.$itemBySortedIndex[item.item.sortedIndex] = item.element } }) }) } _renderByFragments(renderFunction) { if (this.isVirtualScrolling) { const $commonFragment = (0, _renderer.default)(_dom_adapter.default.createDocumentFragment()); const $allDayFragment = (0, _renderer.default)(_dom_adapter.default.createDocumentFragment()); renderFunction($commonFragment, $allDayFragment); this._applyFragment($commonFragment, false); this._applyFragment($allDayFragment, true) } else { renderFunction(this._getAppointmentContainer(false), this._getAppointmentContainer(true)) } } _refreshActiveDescendant() {} _attachAppointmentsEvents() { this._attachClickEvent(); this._attachHoldEvent(); this._attachContextMenuEvent(); this._attachAppointmentDblClick(); this._renderFocusState(); this._attachFeedbackEvents(); this._attachHoverEvents() } _clearDropDownItemsElements() { this.invoke("clearCompactAppointments") } _findItemElementByItem(item) { const result = []; const that = this; this.itemElements().each(function() { const $item = (0, _renderer.default)(this); if ($item.data(that._itemDataKey()) === item) { result.push($item) } }); return result } _itemClass() { return _m_classes.APPOINTMENT_ITEM_CLASS } _itemContainer() { const $container = super._itemContainer(); let $result = $container; const $allDayContainer = this.option("allDayContainer"); if ($allDayContainer) { $result = $container.add($allDayContainer) } return $result } _cleanItemContainer() { super._cleanItemContainer(); const $allDayContainer = this.option("allDayContainer"); if ($allDayContainer) { $allDayContainer.empty() } } _init() { super._init(); this.$itemBySortedIndex = []; this._kbn = new _m_appointments_kbn.AppointmentsKeyboardNavigation(this); this._focusedItemIndexBeforeRender = -1; this.$element().addClass(COMPONENT_CLASS); this._preventSingleAppointmentClick = false } _renderAppointmentTemplate($container, appointment, model) { const config = { isAllDay: appointment.allDay, isRecurrence: appointment.recurrenceRule, html: (0, _type.isPlainObject)(appointment) && appointment.html ? appointment.html : void 0 }; let { targetedAppointmentData: targetedAppointmentData } = model; if (this._currentAppointmentSettings && "isAgendaModel" in this._currentAppointmentSettings) { targetedAppointmentData = (0, _get_targeted_appointment.getTargetedAppointmentFromInfo)(this._currentAppointmentSettings.itemData, this._currentAppointmentSettings, this.dataAccessors, this.getResourceManager(), true) } const formatText = this.invoke("createFormattedDateText", appointment, targetedAppointmentData, appointment.allDay ? _m_text_utils.DateFormatType.DATE : _m_text_utils.DateFormatType.TIME); $container.append(this.isAgendaView ? (0, _m_appointment_layout.createAgendaAppointmentLayout)(formatText, config) : (0, _m_appointment_layout.createAppointmentLayout)(formatText, config)); if (!this.isAgendaView) { $container.parent().prepend((0, _renderer.default)("<div>").addClass(_m_classes.APPOINTMENT_CONTENT_CLASSES.STRIP)) } } _executeItemRenderAction(index, itemData, itemElement) { const action = this._getItemRenderAction(); if (action) { action(this.invoke("mapAppointmentFields", { itemData: itemData, itemElement: itemElement })) } delete this._currentAppointmentSettings } _itemClickHandler(e) { super._itemClickHandler(e, {}, { afterExecute: function(e) { this._processItemClick(e.args[0].event) }.bind(this) }) } _processItemClick(e) { const $target = (0, _renderer.default)(e.currentTarget); const data = this._getItemData($target); if ($target.is(".dx-scheduler-appointment-collector")) { return } if ("keydown" === e.type || (0, _index.isFakeClickEvent)(e)) { this.notifyObserver("showEditAppointmentPopup", { data: data, target: $target }); return } this._appointmentClickTimeout = setTimeout(() => { if (!this._preventSingleAppointmentClick && (0, _dom.isElementInDom)($target)) { this.notifyObserver("showAppointmentTooltip", { data: data, target: $target }) } this._preventSingleAppointmentClick = false }, 300) } _extendActionArgs($itemElement) { const args = super._extendActionArgs($itemElement); return this.invoke("mapAppointmentFields", args) } _render() { super._render(); this._attachAppointmentDblClick() } _attachAppointmentDblClick() { const that = this; const itemSelector = that._itemSelector(); const itemContainer = this._itemContainer(); _events_engine.default.off(itemContainer, DBLCLICK_EVENT_NAME, itemSelector); _events_engine.default.on(itemContainer, DBLCLICK_EVENT_NAME, itemSelector, e => { that._itemDXEventHandler(e, "onAppointmentDblClick", {}, { afterExecute(e) { that._dblClickHandler(e.args[0].event) } }) }) } _dblClickHandler(e) { const $targetAppointment = (0, _renderer.default)(e.currentTarget); const appointmentData = this._getItemData($targetAppointment); clearTimeout(this._appointmentClickTimeout); this._preventSingleAppointmentClick = true; this.notifyObserver("showEditAppointmentPopup", { data: appointmentData, target: $targetAppointment }) } _renderItem(index, item, container) { if ("items" in item) { return this.renderDropDownAppointment(container, item) } this._currentAppointmentSettings = item; const $item = super._renderItem(index, item.itemData, container); $item.data(_constants.APPOINTMENT_SETTINGS_KEY, item); if (-1 !== item.sortedIndex) { this.$itemBySortedIndex[item.sortedIndex] = $item } return $item } _getItemContent($itemFrame) { $itemFrame.data(_constants.APPOINTMENT_SETTINGS_KEY, this._currentAppointmentSettings); const $itemContent = super._getItemContent($itemFrame); return $itemContent } _createItemByTemplate(itemTemplate, renderArgs) { const { itemData: itemData, container: container, index: index } = renderArgs; const parent = (0, _renderer.default)(container).parent(); parent.prepend((0, _renderer.default)("<span>").addClass(_m_classes.APPOINTMENT_CONTENT_CLASSES.ARIA_DESCRIPTION).attr("hidden", true)); return itemTemplate.render({ model: { appointmentData: itemData, targetedAppointmentData: this.invoke("getTargetedAppointmentData", itemData, parent) }, container: container, index: index }) } _getAppointmentContainer(allDay) { const $allDayContainer = this.option("allDayContainer"); const $container = this.itemsContainer().not($allDayContainer); return allDay && $allDayContainer ? $allDayContainer : $container } _postprocessRenderItem(args) { this.renderAppointment(args.itemElement, this._currentAppointmentSettings) } renderAppointment(element, settings) { element.data(_constants.APPOINTMENT_SETTINGS_KEY, settings); this._applyResourceDataAttr(element); if (this.isAgendaView) { this.renderAgendaAppointment(element, settings); return } this.renderGeneralAppointment(element, settings) } renderAgendaAppointment(element, settings) { if (settings.isLastInGroup) { element.addClass(_m_classes.AGENDA_LAST_IN_DATE_APPOINTMENT_CLASS) } const { groups: groups, groupsLeafs: groupsLeafs, resourceById: resourceById } = this.getResourceManager(); const config = { data: settings.itemData, groupIndex: settings.groupIndex, groupTexts: (0, _group_utils.getGroupTexts)(groups, groupsLeafs, resourceById, settings.groupIndex), notifyScheduler: this.option("notifyScheduler"), geometry: settings, allowResize: false, allowDrag: false, groups: this.option("groups"), dataAccessors: this.option("dataAccessors"), timeZoneCalculator: this.option("timeZoneCalculator"), getResourceManager: this.option("getResourceManager") }; this._createComponent(element, _agenda_appointment.AgendaAppointment, config) } renderGeneralAppointment(element, settings) { var _settings$info; const allowResize = this.option("allowResize") && !settings.skipResizing; const allowDrag = this.option("allowDrag"); const { allDay: allDay } = settings; const { groups: groups, groupsLeafs: groupsLeafs, resourceById: resourceById } = this.getResourceManager(); const isGroupByDate = this.option("groupByDate"); const config = { data: settings.itemData, groupIndex: settings.groupIndex, groupTexts: (0, _group_utils.getGroupTexts)(groups, groupsLeafs, resourceById, settings.groupIndex), notifyScheduler: this.option("notifyScheduler"), geometry: settings, direction: settings.direction || "vertical", allowResize: allowResize, allowDrag: allowDrag, allDay: allDay, reduced: isGroupByDate ? void 0 : settings.reduced, startDate: new Date(null === (_settings$info = settings.info) || void 0 === _settings$info ? void 0 : _settings$info.appointment.startDate), cellWidth: this.invoke("getCellWidth"), cellHeight: this.invoke("getCellHeight"), resizableConfig: this._resizableConfig(settings.itemData, settings), groups: this.option("groups"), partIndex: settings.partIndex, partTotalCount: settings.partTotalCount, dataAccessors: this.option("dataAccessors"), timeZoneCalculator: this.option("timeZoneCalculator"), getResizableStep: this.option("getResizableStep"), getResourceManager: this.option("getResourceManager") }; this._createComponent(element, _m_appointment.Appointment, config) } _applyResourceDataAttr($appointment) { const { resources: resources } = this.getResourceManager(); const rawAppointment = this._getItemData($appointment); const appointmentGroups = (0, _appointment_groups_utils.getAppointmentGroupValues)(rawAppointment, resources); Object.entries(appointmentGroups).forEach(_ref2 => { let [resourceIndex, resourceIds] = _ref2; if (resourceIds.length) { const prefix = `data-${(0,_common.normalizeKey)(resourceIndex.toLowerCase())}-`; resourceIds.forEach(value => $appointment.attr(prefix + (0, _common.normalizeKey)(value), true)) } }) } _resizableConfig(appointmentData, itemSetting) { return { area: this._calculateResizableArea(itemSetting, appointmentData), onResizeStart: e => { const $appointment = (0, _renderer.default)(e.element); this._isResizing = true; this._kbn.focus($appointment); if (this.invoke("needRecalculateResizableArea")) { const updatedArea = this._calculateResizableArea(this.getAppointmentSettings($appointment), $appointment.data("dxItemData")); e.component.option("area", updatedArea); e.component._renderDragOffsets(e.event) } this._initialSize = { width: e.width, height: e.height }; this._initialCoordinates = (0, _translator.locate)($appointment) }, onResizeEnd: e => { this._isResizing = false; this._resizeEndHandler(e) } } } _calculateResizableArea(itemSetting, appointmentData) { const area = this.$element().closest(".dx-scrollable-content"); return this.invoke("getResizableAppointmentArea", { coordinates: { left: itemSetting.left, top: 0, groupIndex: itemSetting.groupIndex }, allDay: itemSetting.allDay }) || area } _resizeEndHandler(e) { const $element = (0, _renderer.default)(e.element); const { allDay: allDay, info: info } = $element.data(_constants.APPOINTMENT_SETTINGS_KEY); const sourceAppointment = this._getItemData($element); const viewOffset = this.invoke("getViewOffsetMs"); let dateRange; if (allDay) { dateRange = this.resizeAllDay(e) } else { const startDate = this._getEndResizeAppointmentStartDate(e, sourceAppointment, info.appointment); const { endDate: endDate } = info.appointment; const shiftedStartDate = _date2.dateUtilsTs.addOffsets(startDate, -viewOffset); const shiftedEndDate = _date2.dateUtilsTs.addOffsets(endDate, -viewOffset); dateRange = this.getDateRange(e, shiftedStartDate, shiftedEndDate); dateRange.startDate = _date2.dateUtilsTs.addOffsets(dateRange.startDate, viewOffset); dateRange.endDate = _date2.dateUtilsTs.addOffsets(dateRange.endDate, viewOffset) } this.updateResizedAppointment($element, dateRange, this.dataAccessors, this.option("timeZoneCalculator")) } resizeAllDay(e) { const $element = (0, _renderer.default)(e.element); const timeZoneCalculator = this.option("timeZoneCalculator"); return (0, _m_core.getAppointmentDateRange)({ handles: e.handles, appointmentSettings: $element.data(_constants.APPOINTMENT_SETTINGS_KEY), isVerticalGroupedWorkSpace: this.option("isVerticalGroupedWorkSpace")(), appointmentRect: (0, _position.getBoundingRect)($element[0]), parentAppointmentRect: (0, _position.getBoundingRect)($element.parent()[0]), viewDataProvider: this.option("getViewDataProvider")(), isDateAndTimeView: this.option("isDateAndTimeView")(), startDayHour: this.invoke("getStartDayHour"), endDayHour: this.invoke("getEndDayHour"), timeZoneCalculator: timeZoneCalculator, dataAccessors: this.dataAccessors, rtlEnabled: this.option("rtlEnabled"), DOMMetaData: this.option("getDOMElementsMetaData")(), viewOffset: this.invoke("getViewOffsetMs") }) } updateResizedAppointment($element, dateRange, dataAccessors, timeZoneCalculator) { const sourceAppointment = this._getItemData($element); const gridAdapter = new _appointment_adapter.AppointmentAdapter(sourceAppointment, dataAccessors).clone(); gridAdapter.startDate = new Date(dateRange.startDate); gridAdapter.endDate = new Date(dateRange.endDate); const convertedBackAdapter = gridAdapter.clone().calculateDates(timeZoneCalculator, "fromGrid").calculateDates(timeZoneCalculator, "toGrid"); const startDateDelta = gridAdapter.startDate.getTime() - convertedBackAdapter.startDate.getTime(); const endDateDelta = gridAdapter.endDate.getTime() - convertedBackAdapter.endDate.getTime(); gridAdapter.startDate = _date2.dateUtilsTs.addOffsets(gridAdapter.startDate, startDateDelta); gridAdapter.endDate = _date2.dateUtilsTs.addOffsets(gridAdapter.endDate, endDateDelta); const data = gridAdapter.calculateDates(timeZoneCalculator, "fromGrid").source; this.notifyObserver("updateAppointmentAfterResize", { target: sourceAppointment, data: data, $appointment: $element }) } _getEndResizeAppointmentStartDate(e, rawAppointment, appointmentInfo) { const timeZoneCalculator = this.option("timeZoneCalculator"); const appointmentAdapter = new _appointment_adapter.AppointmentAdapter(rawAppointment, this.dataAccessors); let { startDate: startDate } = appointmentInfo; const { startDateTimeZone: startDateTimeZone, isRecurrent: isRecurrent } = appointmentAdapter; const isAllDay = this.invoke("isAllDay", rawAppointment); if (!e.handles.top && !isRecurrent && !isAllDay) { startDate = timeZoneCalculator.createDate(appointmentAdapter.startDate, "toGrid", startDateTimeZone) } return startDate } getDateRange(e, startDate, endDate) { const itemData = this._getItemData(e.element); const deltaTime = this.invoke("getDeltaTime", e, this._initialSize, itemData); const renderingStrategyDirection = this.invoke("getRenderingStrategyDirection"); let isStartDateChanged = false; const isAllDay = this.invoke("isAllDay", itemData); const needCorrectDates = this.invoke("needCorrectAppointmentDates") && !isAllDay; let startTime; let endTime; if ("vertical" !== renderingStrategyDirection || isAllDay) { isStartDateChanged = this.option("rtlEnabled") ? e.handles.right : e.handles.left } else { isStartDateChanged = e.handles.top } if (isStartDateChanged) { startTime = needCorrectDates ? this._correctStartDateByDelta(startDate, deltaTime) : startDate.getTime() - deltaTime; startTime += _m_utils_time_zone.default.getTimezoneOffsetChangeInMs(startDate, endDate, startTime, endDate); endTime = endDate.getTime() } else { startTime = startDate.getTime(); endTime = needCorrectDates ? this._correctEndDateByDelta(endDate, deltaTime) : endDate.getTime() + deltaTime; endTime -= _m_utils_time_zone.default.getTimezoneOffsetChangeInMs(startDate, endDate, startDate, endTime) } return { startDate: new Date(startTime), endDate: new Date(endTime) } } _correctEndDateByDelta(endDate, deltaTime) { const endDayHour = this.invoke("getEndDayHour"); const startDayHour = this.invoke("getStartDayHour"); const maxDate = new Date(endDate); const minDate = new Date(endDate); const correctEndDate = new Date(endDate); minDate.setHours(startDayHour, 0, 0, 0); maxDate.setHours(endDayHour, 0, 0, 0); if (correctEndDate > maxDate) { correctEndDate.setHours(endDayHour, 0, 0, 0) } let result = correctEndDate.getTime() + deltaTime; const visibleDayDuration = (endDayHour - startDayHour) * toMs("hour"); const daysCount = deltaTime > 0 ? Math.ceil(deltaTime / visibleDayDuration) : Math.floor(deltaTime / visibleDayDuration); if (result > maxDate.getTime() || result <= minDate.getTime()) { const tailOfCurrentDay = maxDate.getTime() - correctEndDate.getTime(); const tailOfPrevDays = deltaTime - tailOfCurrentDay; const correctedEndDate = new Date(correctEndDate).setDate(correctEndDate.getDate() + daysCount); const lastDay = new Date(correctedEndDate); lastDay.setHours(startDayHour, 0, 0, 0); result = lastDay.getTime() + tailOfPrevDays - visibleDayDuration * (daysCount - 1) } return result } _correctStartDateByDelta(startDate, deltaTime) { const endDayHour = this.invoke("getEndDayHour"); const startDayHour = this.invoke("getStartDayHour"); const maxDate = new Date(startDate); const minDate = new Date(startDate); const correctStartDate = new Date(startDate); minDate.setHours(startDayHour, 0, 0, 0); maxDate.setHours(endDayHour, 0, 0, 0); if (correctStartDate < minDate) { correctStartDate.setHours(startDayHour, 0, 0, 0) } let result = correctStartDate.getTime() - deltaTime; const visibleDayDuration = (endDayHour - startDayHour) * toMs("hour"); const daysCount = deltaTime > 0 ? Math.ceil(deltaTime / visibleDayDuration) : Math.floor(deltaTime / visibleDayDuration); if (result < minDate.getTime() || result >= maxDate.getTime()) { const tailOfCurrentDay = correctStartDate.getTime() - minDate.getTime(); const tailOfPrevDays = deltaTime - tailOfCurrentDay; const firstDay = new Date(correctStartDate.setDate(correctStartDate.getDate() - daysCount)); firstDay.setHours(endDayHour, 0, 0, 0); result = firstDay.getTime() - tailOfPrevDays + visibleDayDuration * (daysCount - 1) } return result } renderDropDownAppointments() { this._renderByFragments(($commonFragment, $allDayFragment) => { const items = this.option("items") || []; items.forEach(item => { if ("items" in item) { const $fragment = item.allDay ? $allDayFragment : $commonFragment; this.renderDropDownAppointment($fragment, item) } }) }) } renderDropDownAppointment($fragment, appointment) { const virtualItems = appointment.items; const items = []; virtualItems.forEach(item => { const appointmentConfig = { itemData: item.itemData, groupIndex: appointment.groupIndex, groups: this.option("groups") }; const resourceManager = this.getResourceManager(); items.push({ appointment: item.itemData, targetedAppointment: (0, _get_targeted_appointment.getTargetedAppointment)(item.itemData, item, this.dataAccessors, resourceManager), color: resourceManager.getAppointmentColor(appointmentConfig), settings: item }) }); const $item = this.invoke("renderCompactAppointments", { $container: $fragment, coordinates: { top: appointment.top, left: appointment.left }, items: items, buttonColor: items[0].color, sortedIndex: appointment.sortedIndex, width: appointment.width, height: appointment.height, onAppointmentClick: this.option("onItemClick"), allowDrag: this.option("allowDrag"), isCompact: appointment.isCompact }); this.$itemBySortedIndex[appointment.sortedIndex] = $item; return $item } moveAppointmentBack(dragEvent) { const $appointment = this._kbn.$focusTarget(); const size = this._initialSize; const coords = this._initialCoordinates; this._isResizing = false; if (dragEvent) { this._removeDragSourceClassFromDraggedAppointment(); if ((0, _type.isDeferred)(dragEvent.cancel)) { dragEvent.cancel.resolve(true) } else { dragEvent.cancel = true } } if ($appointment.get(0) && !dragEvent) { if (coords) { (0, _translator.move)($appointment, coords); delete this._initialSize } if (size) { (0, _size.setOuterWidth)($appointment, size.width); (0, _size.setOuterHeight)($appointment, size.height); delete this._initialCoordinates } } } focus() { this._kbn.focus() } _removeDragSourceClassFromDraggedAppointment() { const $appointments = this._itemElements().filter(`.${_m_classes.APPOINTMENT_DRAG_SOURCE_CLASS}`); $appointments.each((_, element) => { const appointmentInstance = (0, _renderer.default)(element).dxSchedulerAppointment("instance"); appointmentInstance.option("isDragSource", false) }) } _setDragSourceAppointment(appointment, settings) { const $appointments = this._findItemElementByItem(appointment); const { startDate: startDate, endDate: endDate } = settings.info.sourceAppointment; const { groupIndex: groupIndex } = settings; $appointments.forEach($item => { const { info: itemInfo, groupIndex: itemGroupIndex } = $item.data(_constants.APPOINTMENT_SETTINGS_KEY); const { startDate: itemStartDate, endDate: itemEndDate } = itemInfo.sourceAppointment; const appointmentInstance = $item.dxSchedulerAppointment("instance"); const isDragSource = startDate.getTime() === itemStartDate.getTime() && endDate.getTime() === itemEndDate.getTime() && groupIndex === itemGroupIndex; appointmentInstance.option("isDragSource", isDragSource) }) } updateResizableArea() { const $allResizableElements = this.$element().find(".dx-scheduler-appointment.dx-resizable"); const horizontalResizables = (0, _common.grep)($allResizableElements, el => { const $el = (0, _renderer.default)(el); const resizableInst = $el.dxResizable("instance"); const { area: area, handles: handles } = resizableInst.option(); return ("right left" === handles || "left right" === handles) && (0, _type.isPlainObject)(area) }); (0, _iterator.each)(horizontalResizables, (_, el) => { const $el = (0, _renderer.default)(el); const position = (0, _translator.locate)($el); const appointmentData = this._getItemData($el); const area = this._calculateResizableArea({ left: position.left }, appointmentData); $el.dxResizable("instance").option("area", area) }) } }(0, _component_registrator.default)("dxSchedulerAppointments", SchedulerAppointments); var _default = exports.default = SchedulerAppointments;