UNPKG

devextreme

Version:

JavaScript/TypeScript Component Suite for Responsive Web Development

366 lines (364 loc) • 16.9 kB
/** * DevExtreme (cjs/__internal/scheduler/appointments_new/appointments.js) * Version: 26.1.3 * Build date: Wed Jun 10 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.Appointments = void 0; var _component_registrator = _interopRequireDefault(require("../../../core/component_registrator")); var _renderer = _interopRequireDefault(require("../../../core/renderer")); var _m_dom_adapter = require("../../core/m_dom_adapter"); var _m_element = require("../../core/m_element"); var _m_empty_template = require("../../core/templates/m_empty_template"); var _m_dom = require("../../core/utils/m_dom"); var _dom_component = _interopRequireDefault(require("../../core/widget/dom_component")); var _agenda_appointment = require("./appointment/agenda_appointment"); var _base_appointment = require("./appointment/base_appointment"); var _grid_appointment = require("./appointment/grid_appointment"); var _appointment_collector = require("./appointment_collector"); var _appointments = require("./appointments.focus_controller"); var _const = require("./const"); var _get_targeted_appointment = require("./utils/get_targeted_appointment"); var _get_view_model_diff = require("./utils/get_view_model_diff"); var _type_helpers = require("./utils/type_helpers"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } const SHOW_TOOLTIP_TIMEOUT = 300; class Appointments extends _dom_component.default { constructor() { super(...arguments); this.appointmentClickTimeout = null; this.viewItemBySortedIndex = {}; this.viewItems = [] } getViewItemByIndex(index) { return this.viewItems[index] } getViewItemBySortedIndex(sortedIndex) { return this.viewItemBySortedIndex[sortedIndex] } getViewModelBySortedIndex(sortedIndex) { const result = this.option().viewModel.find(viewModel => viewModel.sortedIndex === sortedIndex); return result } getAppointmentData($element) { const viewItem = this.viewItems.find(item => item.$element().is($element)); return { appointmentData: viewItem.appointmentData, targetedAppointmentData: viewItem.targetedAppointmentData } } get $allDayContainer() { return this.option().$allDayContainer } get $commonContainer() { return this.$element() } _init() { super._init(); this.focusController = new _appointments.AppointmentsFocusController(this, { onAppointmentEnterKeyDown: this.onAppointmentDblClick.bind(this) }); this._templateManager.addDefaultTemplates({ appointment: new _m_empty_template.EmptyTemplate, appointmentCollector: new _m_empty_template.EmptyTemplate }); if ("item" === this.option().appointmentTemplate) { this.option("appointmentTemplate", "appointment") } } _dispose() { super._dispose(); if (this.appointmentClickTimeout) { clearTimeout(this.appointmentClickTimeout) } } _initMarkup() { super._initMarkup(); this.$element().addClass(_const.APPOINTMENTS_CONTAINER_CLASS) } _getDefaultOptions() { const noop = () => {}; return Object.assign({}, super._getDefaultOptions(), { tabIndex: 0, viewModel: [], $allDayContainer: null, appointmentTemplate: "appointment", appointmentCollectorTemplate: "appointmentCollector", onAppointmentRendered: noop, onAppointmentClick: noop, onAppointmentDblClick: noop, onAppointmentContextMenu: noop, allowDelete: false, onDeleteKeyPress: noop }) } _optionChanged(args) { switch (args.name) { case "items": this.option("viewModel", args.value); break; case "viewModel": { if ("agenda" === this.option().currentView) { this.renderViewModel(args.value); break } const diff = this.getViewModelDiff(args.previousValue ?? [], args.value ?? []); const isRepaintAll = diff.every(item => Boolean(item.needToAdd ?? item.needToRemove)); if (isRepaintAll) { this.renderViewModel(args.value); break } this.renderViewModelDiff(diff); break } case "appointmentCollectorTemplate": case "appointmentTemplate": if ("appointmentTemplate" === args.name && "item" === args.value) { this.option("appointmentTemplate", "appointment"); break } this.renderViewModel(this.option().viewModel); break; case "tabIndex": this.focusController.resetTabIndex() } } updateResizableArea() {} moveAppointmentBack() {} focus() {} _renderAppointmentTemplate() {} getViewModelDiff(oldViewModel, newViewModel) { const isPreviousAgenda = oldViewModel.length && (0, _type_helpers.isAgendaAppointmentViewModel)(oldViewModel[0]); const normalizedOldViewModel = isPreviousAgenda ? [] : oldViewModel; return (0, _get_view_model_diff.getViewModelDiff)(normalizedOldViewModel, newViewModel, this.option().getAppointmentDataSource()) } renderViewModel() { var _this$$allDayContaine, _this$$allDayContaine2; let viewModel = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : []; const allDayFragment = _m_dom_adapter.domAdapter.createDocumentFragment(); const commonFragment = _m_dom_adapter.domAdapter.createDocumentFragment(); this.viewItemBySortedIndex = {}; null === (_this$$allDayContaine = this.$allDayContainer) || void 0 === _this$$allDayContaine || _this$$allDayContaine.empty(); this.$commonContainer.empty(); viewModel.forEach((viewModelItem, index) => { const viewItem = this.renderViewItem(viewModelItem, index); this.viewItemBySortedIndex[viewModelItem.sortedIndex] = viewItem; const container = "agenda" === this.option().currentView || !viewModelItem.allDay ? commonFragment : allDayFragment; container.appendChild(viewItem.$element().get(0)) }); this.viewItems = Object.values(this.viewItemBySortedIndex); null === (_this$$allDayContaine2 = this.$allDayContainer) || void 0 === _this$$allDayContaine2 || _this$$allDayContaine2.get(0).appendChild(allDayFragment); this.$commonContainer.get(0).appendChild(commonFragment); this.focusController.resetTabIndex() } renderViewModelDiff(viewModelDiff) { var _this$$allDayContaine3; const allDayFragment = _m_dom_adapter.domAdapter.createDocumentFragment(); const commonFragment = _m_dom_adapter.domAdapter.createDocumentFragment(); const newViewItemBySortedIndex = {}; viewModelDiff.forEach((diffItem, index) => { const { allDay: allDay, sortedIndex: sortedIndex } = diffItem.item; const lookupIndex = diffItem.oldSortedIndex ?? sortedIndex; const viewItem = this.viewItemBySortedIndex[lookupIndex]; switch (true) { case diffItem.needToRemove: viewItem.$element().remove(); break; case diffItem.needToAdd: { const newViewItem = this.renderViewItem(diffItem.item, index); newViewItemBySortedIndex[sortedIndex] = newViewItem; const fragment = allDay ? allDayFragment : commonFragment; fragment.appendChild(newViewItem.$element().get(0)); break } default: if (diffItem.needToResize) { viewItem.resize({ height: diffItem.item.height, width: diffItem.item.width, top: diffItem.item.top, left: diffItem.item.left }) } viewItem.option("sortedIndex", sortedIndex); newViewItemBySortedIndex[sortedIndex] = viewItem } }); this.viewItemBySortedIndex = newViewItemBySortedIndex; this.viewItems = Object.values(this.viewItemBySortedIndex); null === (_this$$allDayContaine3 = this.$allDayContainer) || void 0 === _this$$allDayContaine3 || _this$$allDayContaine3.get(0).appendChild(allDayFragment); this.$commonContainer.get(0).appendChild(commonFragment); this.focusController.resetTabIndex() } renderViewItem(appointmentViewModel, index) { const $element = (0, _renderer.default)("<div>"); const targetedAppointmentData = this.getTargetedAppointmentData(appointmentViewModel); const baseViewItemConfig = { tabIndex: -1, sortedIndex: appointmentViewModel.sortedIndex, onFocusIn: this.focusController.onViewItemFocusIn.bind(this.focusController), onFocusOut: this.focusController.onViewItemFocusOut.bind(this.focusController), onKeyDown: this.focusController.onViewItemKeyDown.bind(this.focusController) }; if ((0, _type_helpers.isCollectorViewModel)(appointmentViewModel)) { return this._createComponent($element, _appointment_collector.AppointmentCollector, Object.assign({}, baseViewItemConfig, { items: appointmentViewModel.items, isCompact: appointmentViewModel.isCompact, geometry: { height: appointmentViewModel.height, width: appointmentViewModel.width, top: appointmentViewModel.top, left: appointmentViewModel.left }, targetedAppointmentData: targetedAppointmentData, appointmentCollectorTemplate: this._getTemplateByOption("appointmentCollectorTemplate"), onClick: this.onCollectorClick.bind(this) })) } const baseAppointmentViewConfig = Object.assign({}, baseViewItemConfig, { index: index, appointmentTemplate: this._getTemplateByOption("appointmentTemplate"), appointmentData: appointmentViewModel.itemData, targetedAppointmentData: targetedAppointmentData, onRendered: this.option().onAppointmentRendered, getResourceColor: this.getResourceColor.bind(this, appointmentViewModel), getDataAccessor: this.option().getDataAccessor, onClick: this.onAppointmentClick.bind(this), onDblClick: this.onAppointmentDblClick.bind(this), onContextMenu: this.onAppointmentContextMenu.bind(this) }); if ((0, _type_helpers.isGridAppointmentViewModel)(appointmentViewModel)) { return this._createComponent($element, _grid_appointment.GridAppointmentView, Object.assign({}, baseAppointmentViewConfig, { geometry: { height: appointmentViewModel.height, width: appointmentViewModel.width, top: appointmentViewModel.top, left: appointmentViewModel.left }, modifiers: { empty: appointmentViewModel.empty } })) } return this._createComponent($element, _agenda_appointment.AgendaAppointmentView, Object.assign({}, baseAppointmentViewConfig, { modifiers: { isLastInGroup: appointmentViewModel.isLastInGroup }, geometry: { height: appointmentViewModel.height, width: appointmentViewModel.width }, getResourcesValues: this.getResourcesValues.bind(this) })) } renderDragClone(appointmentViewModel) { return this.renderViewItem(appointmentViewModel, this.viewItems.length).$element() } getTargetedAppointmentData(appointmentViewModel) { const normalizedAppointmentViewModel = (0, _type_helpers.isCollectorViewModel)(appointmentViewModel) ? appointmentViewModel.items[0] : appointmentViewModel; return (0, _get_targeted_appointment.getTargetedAppointment)(normalizedAppointmentViewModel, this.option().getDataAccessor(), this.option().getResourceManager()) } getResourceColor(appointmentViewModel) { const resourceManager = this.option().getResourceManager(); return resourceManager.getAppointmentColor({ itemData: appointmentViewModel.itemData, groupIndex: appointmentViewModel.groupIndex }) } getResourcesValues(appointmentData) { const resourceManager = this.option().getResourceManager(); return resourceManager.getAppointmentResourcesValues(appointmentData) } onAppointmentClick(appointmentView, event) { this.focusController.onViewItemClick(appointmentView); const $target = appointmentView.$element(); const e = { appointmentElement: (0, _m_element.getPublicElement)($target), appointmentData: appointmentView.appointmentData, targetedAppointmentData: appointmentView.targetedAppointmentData, event: event }; this.option().onAppointmentClick(e); if (e.cancel) { return } if (null != this.appointmentClickTimeout) { clearTimeout(this.appointmentClickTimeout) } this.appointmentClickTimeout = window.setTimeout(() => { this.appointmentClickTimeout = null; if ((0, _m_dom.isElementInDom)($target)) { this.option().showAppointmentTooltip($target, this.getTooltipItems(appointmentView)) } }, 300) } onAppointmentDblClick(appointmentView, event) { const e = { appointmentElement: (0, _m_element.getPublicElement)(appointmentView.$element()), appointmentData: appointmentView.appointmentData, targetedAppointmentData: appointmentView.targetedAppointmentData, event: event }; if (this.appointmentClickTimeout) { clearTimeout(this.appointmentClickTimeout); this.appointmentClickTimeout = null } this.option().onAppointmentDblClick(e); if (e.cancel) { return } this.option().showEditAppointmentPopup(appointmentView.appointmentData, appointmentView.targetedAppointmentData) } onAppointmentContextMenu(appointmentView, event) { const e = { appointmentElement: (0, _m_element.getPublicElement)(appointmentView.$element()), appointmentData: appointmentView.appointmentData, targetedAppointmentData: appointmentView.targetedAppointmentData, event: event }; this.option().onAppointmentContextMenu(e) } onCollectorClick(collector) { this.focusController.onViewItemClick(collector); this.option().showAppointmentTooltip(collector.$element(), this.getTooltipItems(collector), { isButtonClick: true, tabFocusLoopEnabled: true }) } getTooltipItems(viewItem) { if (viewItem instanceof _appointment_collector.AppointmentCollector) { const tooltipItems = viewItem.option().items.map(appointmentViewModel => ({ appointment: appointmentViewModel.itemData, targetedAppointment: this.getTargetedAppointmentData(appointmentViewModel), color: this.getResourceColor(appointmentViewModel), settings: appointmentViewModel })); return tooltipItems } if (viewItem instanceof _base_appointment.BaseAppointmentView) { const viewModel = this.getViewModelBySortedIndex(viewItem.option().sortedIndex); return [{ appointment: viewItem.appointmentData, targetedAppointment: viewItem.targetedAppointmentData, color: this.getResourceColor(viewItem.option()), settings: viewModel }] } return [] } } exports.Appointments = Appointments; (0, _component_registrator.default)("dxSchedulerNewAppointments", Appointments);