UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

403 lines (401 loc) • 18.2 kB
/** * DevExtreme (cjs/__internal/scheduler/appointment_popup/m_popup.js) * Version: 25.2.3 * Build date: Fri Dec 12 2025 * * Copyright (c) 2012 - 2025 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.AppointmentPopup = exports.APPOINTMENT_POPUP_CLASS = exports.ACTION_TO_APPOINTMENT = void 0; var _visibility_change = require("../../../common/core/events/visibility_change"); var _message = _interopRequireDefault(require("../../../common/core/localization/message")); var _renderer = _interopRequireDefault(require("../../../core/renderer")); var _date = _interopRequireDefault(require("../../../core/utils/date")); var _deferred = require("../../../core/utils/deferred"); var _extend = require("../../../core/utils/extend"); var _size = require("../../../core/utils/size"); var _window = require("../../../core/utils/window"); var _ui = _interopRequireDefault(require("../../../ui/popup/ui.popup")); var _themes = require("../../../ui/themes"); var _m_loading = require("../m_loading"); var _appointment_adapter = require("../utils/appointment_adapter/appointment_adapter"); var _appointment_groups_utils = require("../utils/resource_manager/appointment_groups_utils"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } const APPOINTMENT_POPUP_CLASS = exports.APPOINTMENT_POPUP_CLASS = "dx-scheduler-appointment-popup"; const POPUP_FULL_SCREEN_MODE_WINDOW_WIDTH_THRESHOLD = 485; const DAY_IN_MS = _date.default.dateToMilliseconds("day"); const ACTION_TO_APPOINTMENT = exports.ACTION_TO_APPOINTMENT = { CREATE: 0, UPDATE: 1, EXCLUDE_FROM_SERIES: 2 }; class AppointmentPopup { get popup() { return this._popup } get visible() { var _this$_popup; return Boolean(null === (_this$_popup = this._popup) || void 0 === _this$_popup ? void 0 : _this$_popup.option("visible")) } constructor(scheduler, form) { this.scheduler = scheduler; this.form = form; this.state = { action: null, lastEditData: null, saveChangesLocker: false, appointment: { data: null } } } show(appointment, config) { this.state.appointment.data = appointment; this.state.action = config.action; this.state.allowSaving = config.allowSaving; this.state.excludeInfo = config.excludeInfo; if (!this._popup) { const popupConfig = this._createPopupConfig(); this._createPopup(popupConfig) } this._popup.show() } hide() { var _this$_popup2; null === (_this$_popup2 = this._popup) || void 0 === _this$_popup2 || _this$_popup2.hide() } dispose() { var _this$_popup3; this.form.dispose(); null === (_this$_popup3 = this._popup) || void 0 === _this$_popup3 || _this$_popup3.dispose(); this._popup = void 0 } _createPopup(options) { const popupElement = (0, _renderer.default)("<div>").addClass(APPOINTMENT_POPUP_CLASS).appendTo(this.scheduler.getElement()); this.scheduler.createComponent(popupElement, _ui.default, options) } _createPopupConfig() { const editingConfig = this.scheduler.getEditingConfig(); const customPopupOptions = (null === editingConfig || void 0 === editingConfig ? void 0 : editingConfig.popup) ?? {}; this.customPopupOptions = customPopupOptions; const defaultPopupConfig = { height: "auto", maxHeight: "90%", showCloseButton: false, showTitle: false, preventScrollEvents: false, enableBodyScroll: false, _ignorePreventScrollEventsDeprecation: true, onInitialized: e => { var _customPopupOptions$o; this._popup = e.component; null === customPopupOptions || void 0 === customPopupOptions || null === (_customPopupOptions$o = customPopupOptions.onInitialized) || void 0 === _customPopupOptions$o || _customPopupOptions$o.call(customPopupOptions, e) }, onHiding: e => { var _customPopupOptions$o2; this.scheduler.focus(); null === customPopupOptions || void 0 === customPopupOptions || null === (_customPopupOptions$o2 = customPopupOptions.onHiding) || void 0 === _customPopupOptions$o2 || _customPopupOptions$o2.call(customPopupOptions, e) }, contentTemplate: () => { this.form.create({ dxPopup: this.popup, updateToolbarForMainGroup: () => this.updateToolbarForMainGroup(), updateToolbarForRecurrenceGroup: () => this.updateToolbarForRecurrenceGroup() }); return this.form.dxForm.$element() }, onShowing: e => { var _customPopupOptions$o3; this._onShowing(e); null === customPopupOptions || void 0 === customPopupOptions || null === (_customPopupOptions$o3 = customPopupOptions.onShowing) || void 0 === _customPopupOptions$o3 || _customPopupOptions$o3.call(customPopupOptions, e) }, wrapperAttr: { class: APPOINTMENT_POPUP_CLASS } }; return (0, _extend.extend)(true, {}, defaultPopupConfig, customPopupOptions, { onInitialized: defaultPopupConfig.onInitialized, onHiding: defaultPopupConfig.onHiding, onShowing: defaultPopupConfig.onShowing }) } _onShowing(e) { this._updateForm(); e.component.$overlayContent().attr("aria-label", _message.default.format("dxScheduler-ariaEditForm")); const arg = { form: this.form.dxForm, popup: this.popup, appointmentData: this.state.appointment.data, cancel: false }; this.scheduler.getAppointmentFormOpening()(arg); this.scheduler.processActionResult(arg, (canceled => { if (canceled) { e.cancel = true } else { this.updatePopupFullScreenMode() } })) } _isReadOnly(appointmentAdapter) { if (Boolean(appointmentAdapter.source) && appointmentAdapter.disabled) { return true } if (this.state.action === ACTION_TO_APPOINTMENT.CREATE) { return false } return !this.scheduler.getEditingConfig().allowUpdating } _createAppointmentAdapter(rawAppointment) { return new _appointment_adapter.AppointmentAdapter(rawAppointment, this.scheduler.getDataAccessors()) } _updateForm() { const rawAppointment = this.state.appointment.data; const appointmentAdapter = this._createAppointmentAdapter(rawAppointment).clone().calculateDates(this.scheduler.getTimeZoneCalculator(), "toAppointment"); const formData = this._createFormData(appointmentAdapter); this.form.readOnly = this._isReadOnly(appointmentAdapter); this.form.formData = formData; this.form.showMainGroup() } _createFormData(appointmentAdapter) { const { resources: resources } = this.scheduler.getResourceManager(); const groupValues = (0, _appointment_groups_utils.getRawAppointmentGroupValues)(appointmentAdapter.source, resources); const { allDayExpr: allDayExpr, recurrenceRuleExpr: recurrenceRuleExpr } = this.scheduler.getDataAccessors().expr; return Object.assign({}, appointmentAdapter.source, groupValues, { [allDayExpr]: Boolean(appointmentAdapter.allDay), [recurrenceRuleExpr]: appointmentAdapter.recurrenceRule }) } triggerResize() { var _this$popup; if (null !== (_this$popup = this.popup) && void 0 !== _this$popup && _this$popup.$element()) { (0, _visibility_change.triggerResizeEvent)(this.popup.$element()) } } getMaxWidth() { var _this$customPopupOpti, _this$customPopupOpti2; if (void 0 !== (null === (_this$customPopupOpti = this.customPopupOptions) || void 0 === _this$customPopupOpti ? void 0 : _this$customPopupOpti.maxWidth)) { return this.customPopupOptions.maxWidth } if (void 0 !== (null === (_this$customPopupOpti2 = this.customPopupOptions) || void 0 === _this$customPopupOpti2 ? void 0 : _this$customPopupOpti2.width)) { return this.customPopupOptions.width } return (0, _themes.isFluent)((0, _themes.current)()) ? 380 : 420 } updatePopupFullScreenMode() { if (this.visible) { var _this$customPopupOpti3; const isPopupFullScreenNeeded = () => { const window = (0, _window.getWindow)(); const width = window && (0, _size.getWidth)(window); return width < 485 }; const isFullScreen = isPopupFullScreenNeeded(); this.popup.option("fullScreen", isFullScreen); if (void 0 !== (null === (_this$customPopupOpti3 = this.customPopupOptions) || void 0 === _this$customPopupOpti3 ? void 0 : _this$customPopupOpti3.width)) { this.popup.option("width", this.customPopupOptions.width) } const maxWidth = this.getMaxWidth(); this.popup.option("maxWidth", isFullScreen ? "100%" : maxWidth) } } saveChangesAsync(isShowLoadPanel) { this.form.saveRecurrenceValue(); const deferred = new _deferred.Deferred; const validation = this.form.dxForm.validate(); isShowLoadPanel && this._showLoadPanel(); (0, _deferred.when)((null === validation || void 0 === validation ? void 0 : validation.complete) ?? validation).done((validation => { if (validation && !validation.isValid) { (0, _m_loading.hide)(); deferred.resolve(false); return } const adapter = this._createAppointmentAdapter(this.form.formData); const clonedAdapter = adapter.clone().calculateDates(this.scheduler.getTimeZoneCalculator(), "fromAppointment"); this._addMissingDSTTime(adapter, clonedAdapter); const appointment = clonedAdapter.source; switch (this.state.action) { case ACTION_TO_APPOINTMENT.CREATE: this.scheduler.addAppointment(appointment).done(deferred.resolve); break; case ACTION_TO_APPOINTMENT.UPDATE: this.scheduler.updateAppointment(this.state.appointment.data, appointment).done(deferred.resolve); break; case ACTION_TO_APPOINTMENT.EXCLUDE_FROM_SERIES: this.scheduler.updateAppointment(this.state.excludeInfo.sourceAppointment, this.state.excludeInfo.updatedAppointment); this.scheduler.addAppointment(appointment).done(deferred.resolve) } deferred.done((() => { (0, _m_loading.hide)(); this.state.lastEditData = appointment })) })); return deferred.promise() } _saveButtonClickHandler(e) { e.cancel = true; this.saveEditDataAsync() } saveEditDataAsync() { const deferred = new _deferred.Deferred; if (this._tryLockSaveChanges()) { (0, _deferred.when)(this.saveChangesAsync(true)).done((() => { if (this.state.lastEditData) { const adapter = this._createAppointmentAdapter(this.state.lastEditData); const { startDate: startDate, endDate: endDate, allDay: allDay } = adapter; const startTime = startDate.getTime(); const endTime = endDate.getTime(); const inAllDayRow = allDay || endTime - startTime >= DAY_IN_MS; const resourceManager = this.scheduler.getResourceManager(); const appointmentGroupValues = (0, _appointment_groups_utils.getAppointmentGroupValues)(this.state.lastEditData, resourceManager.resources); this.scheduler.updateScrollPosition(startDate, appointmentGroupValues, inAllDayRow); this.state.lastEditData = null } this._unlockSaveChanges(); deferred.resolve() })) } return deferred.promise() } _showLoadPanel() { const container = this.popup.$overlayContent(); (0, _m_loading.show)({ container: container, position: { of: container } }) } _tryLockSaveChanges() { if (false === this.state.saveChangesLocker) { this.state.saveChangesLocker = true; return true } return false } _unlockSaveChanges() { this.state.saveChangesLocker = false } _addMissingDSTTime(formAppointmentAdapter, clonedAppointmentAdapter) { const timeZoneCalculator = this.scheduler.getTimeZoneCalculator(); clonedAppointmentAdapter.startDate = this._addMissingDSTShiftToDate(timeZoneCalculator, formAppointmentAdapter.startDate, clonedAppointmentAdapter.startDate); if (clonedAppointmentAdapter.endDate) { clonedAppointmentAdapter.endDate = this._addMissingDSTShiftToDate(timeZoneCalculator, formAppointmentAdapter.endDate, clonedAppointmentAdapter.endDate) } } _addMissingDSTShiftToDate(timeZoneCalculator, originFormDate, clonedDate) { var _timeZoneCalculator$g, _timeZoneCalculator$g2; const originTimezoneShift = null === (_timeZoneCalculator$g = timeZoneCalculator.getOffsets(originFormDate)) || void 0 === _timeZoneCalculator$g ? void 0 : _timeZoneCalculator$g.common; const clonedTimezoneShift = null === (_timeZoneCalculator$g2 = timeZoneCalculator.getOffsets(clonedDate)) || void 0 === _timeZoneCalculator$g2 ? void 0 : _timeZoneCalculator$g2.common; const shiftDifference = originTimezoneShift - clonedTimezoneShift; return shiftDifference ? new Date(clonedDate.getTime() + shiftDifference * _date.default.dateToMilliseconds("hour")) : clonedDate } tryApplyCustomToolbarItems() { var _this$customPopupOpti4; if (null !== (_this$customPopupOpti4 = this.customPopupOptions) && void 0 !== _this$customPopupOpti4 && _this$customPopupOpti4.toolbarItems) { this.popup.option("toolbarItems", this.customPopupOptions.toolbarItems); return true } return false } updateToolbarForMainGroup() { if (this.tryApplyCustomToolbarItems()) { return } const isCreating = this.state.action === ACTION_TO_APPOINTMENT.CREATE; const formTitleKey = isCreating ? "dxScheduler-newPopupTitle" : "dxScheduler-editPopupTitle"; const toolbarItems = [{ toolbar: "top", location: "before", text: _message.default.format(formTitleKey), cssClass: "dx-toolbar-label" }]; const canSave = !this.form.readOnly; if (canSave) { toolbarItems.push({ toolbar: "top", location: "after", options: { onClick: e => this._saveButtonClickHandler(e), stylingMode: "contained", type: "default", text: _message.default.format("dxScheduler-editPopupSaveButtonText") }, shortcut: "done" }) } toolbarItems.push({ toolbar: "top", location: "after", shortcut: "cancel", options: { stylingMode: "outlined" } }); this.popup.option("toolbarItems", toolbarItems) } updateToolbarForRecurrenceGroup() { if (this.tryApplyCustomToolbarItems()) { return } const toolbarItems = [{ toolbar: "top", location: "before", widget: "dxButton", options: { icon: "arrowleft", stylingMode: "text", onClick: () => { this.form.saveRecurrenceValue(); this.form.showMainGroup() } } }, { toolbar: "top", location: "before", text: _message.default.format("dxScheduler-editorLabelRecurrence"), cssClass: "dx-toolbar-label" }]; const canSave = !this.form.readOnly; if (canSave) { toolbarItems.push({ toolbar: "top", location: "after", options: { onClick: e => this._saveButtonClickHandler(e), stylingMode: "contained", type: "default", text: _message.default.format("dxScheduler-editPopupSaveButtonText") }, shortcut: "done" }) } toolbarItems.push({ toolbar: "top", location: "after", shortcut: "cancel", options: { stylingMode: "outlined" } }); this.popup.option("toolbarItems", toolbarItems) } } exports.AppointmentPopup = AppointmentPopup;