UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

411 lines (405 loc) • 19.3 kB
/** * DevExtreme (cjs/__internal/scheduler/appointments/rendering_strategies/m_strategy_vertical.js) * Version: 23.2.6 * Build date: Wed May 01 2024 * * Copyright (c) 2012 - 2024 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 _date = _interopRequireDefault(require("../../../../core/utils/date")); var _extend = require("../../../../core/utils/extend"); var _math = require("../../../../core/utils/math"); var _type = require("../../../../core/utils/type"); var _utils = _interopRequireDefault(require("../../../../ui/scheduler/utils.timeZone")); var _index = require("../../../scheduler/r1/utils/index"); var _m_appointment_adapter = require("../../m_appointment_adapter"); var _m_expression_utils = require("../../m_expression_utils"); var _m_strategy_base = _interopRequireDefault(require("./m_strategy_base")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } } function _extends() { _extends = Object.assign ? Object.assign.bind() : function(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key] } } } return target }; return _extends.apply(this, arguments) } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass) } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(o, p) { o.__proto__ = p; return o }; return _setPrototypeOf(o, p) } const ALLDAY_APPOINTMENT_MIN_VERTICAL_OFFSET = 5; const ALLDAY_APPOINTMENT_MAX_VERTICAL_OFFSET = 20; const toMs = _date.default.dateToMilliseconds; let VerticalRenderingStrategy = function(_BaseAppointmentsStra) { _inheritsLoose(VerticalRenderingStrategy, _BaseAppointmentsStra); function VerticalRenderingStrategy() { return _BaseAppointmentsStra.apply(this, arguments) || this } var _proto = VerticalRenderingStrategy.prototype; _proto.getDeltaTime = function(args, initialSize, appointment) { let deltaTime = 0; if (this.isAllDay(appointment)) { deltaTime = this._getDeltaWidth(args, initialSize) * toMs("day") } else { const deltaHeight = args.height - initialSize.height; deltaTime = toMs("minute") * Math.round(deltaHeight / this.cellHeight * this.cellDurationInMinutes) } return deltaTime }; _proto._correctCollectorCoordinatesInAdaptive = function(coordinates, isAllDay) { if (isAllDay) { _BaseAppointmentsStra.prototype._correctCollectorCoordinatesInAdaptive.call(this, coordinates, isAllDay) } else if (0 === this._getMaxAppointmentCountPerCellByType()) { const { cellHeight: cellHeight } = this; const { cellWidth: cellWidth } = this; coordinates.top += (cellHeight - this.getDropDownButtonAdaptiveSize()) / 2; coordinates.left += (cellWidth - this.getDropDownButtonAdaptiveSize()) / 2 } }; _proto.getAppointmentGeometry = function(coordinates) { let geometry = null; if (coordinates.allDay) { geometry = this._getAllDayAppointmentGeometry(coordinates) } else { geometry = this.isAdaptive && coordinates.isCompact ? this._getAdaptiveGeometry(coordinates) : this._getVerticalAppointmentGeometry(coordinates) } return _BaseAppointmentsStra.prototype.getAppointmentGeometry.call(this, geometry) }; _proto._getAdaptiveGeometry = function(coordinates) { const config = this._calculateGeometryConfig(coordinates); return this._customizeCoordinates(coordinates, config.height, config.appointmentCountPerCell, config.offset) }; _proto._getItemPosition = function(initialAppointment) { const allDay = this.isAllDay(initialAppointment); if (allDay) { return _BaseAppointmentsStra.prototype._getItemPosition.call(this, initialAppointment) } const appointment = _BaseAppointmentsStra.prototype.shiftAppointmentByViewOffset.call(this, initialAppointment); const adapter = (0, _m_appointment_adapter.createAppointmentAdapter)(appointment, this.dataAccessors, this.timeZoneCalculator); const isRecurring = !!adapter.recurrenceRule; const appointmentStartDate = adapter.calculateStartDate("toGrid"); const appointmentEndDate = adapter.calculateEndDate("toGrid"); const appointmentDuration = appointmentEndDate - appointmentStartDate; const appointmentBeginInCurrentView = this.options.startViewDate < appointmentStartDate; const isAppointmentTakesSeveralDays = !_utils.default.isSameAppointmentDates(appointmentStartDate, appointmentEndDate); const settings = this.generateAppointmentSettings(appointment); let result = []; for (let j = 0; j < settings.length; j++) { const currentSetting = settings[j]; const height = this.calculateAppointmentHeight(appointment, currentSetting); const width = this.calculateAppointmentWidth(appointment, currentSetting); let resultHeight = height; let appointmentReduced = null; let multiDaysAppointmentParts = []; const currentMaxAllowedPosition = currentSetting.vMax; if (this._isMultiViewAppointment(currentSetting, height) || isAppointmentTakesSeveralDays && !isRecurring) { const trimmedStartDate = _date.default.trimTime(appointmentStartDate); const trimmedSettingStartDate = _date.default.trimTime(currentSetting.info.appointment.startDate); const reduceHead = trimmedStartDate <= trimmedSettingStartDate || isRecurring; if (reduceHead) { resultHeight = this._reduceMultiDayAppointment(height, { top: currentSetting.top, bottom: currentMaxAllowedPosition }); multiDaysAppointmentParts = this._getAppointmentParts({ sourceAppointmentHeight: height, reducedHeight: resultHeight, width: width }, currentSetting) } const { startDate: currentSettingStartDate, normalizedEndDate: currentSettingNormalizedEndDate } = currentSetting.info.appointment; const currentSettingDuration = currentSettingNormalizedEndDate - currentSettingStartDate; const hasNextParts = currentSettingDuration < appointmentDuration; appointmentReduced = hasNextParts ? appointmentBeginInCurrentView ? "head" : "body" : appointmentBeginInCurrentView ? "head" : "tail" }(0, _extend.extend)(currentSetting, { height: resultHeight, width: width, allDay: allDay, appointmentReduced: appointmentReduced }); result = this._getAppointmentPartsPosition(multiDaysAppointmentParts, currentSetting, result) } return result }; _proto._isMultiViewAppointment = function(_ref, height) { let { vMax: vMax, top: top } = _ref; const fullAppointmentHeight = (0, _math.roundFloatPart)(height, 2); const remainingHeight = (0, _math.roundFloatPart)(vMax - top, 2); return fullAppointmentHeight > remainingHeight }; _proto._reduceMultiDayAppointment = function(sourceAppointmentHeight, bound) { return Math.min(sourceAppointmentHeight, bound.bottom - Math.floor(bound.top)) }; _proto._getGroupHeight = function() { return this.cellHeight * this.rowCount }; _proto._getGroupTopOffset = function(appointmentSettings) { const { groupIndex: groupIndex } = appointmentSettings; const groupTop = Math.max(0, this.positionHelper.getGroupTop({ groupIndex: groupIndex, showAllDayPanel: this.showAllDayPanel, isGroupedAllDayPanel: this.isGroupedAllDayPanel })); const allDayPanelOffset = this.positionHelper.getOffsetByAllDayPanel({ groupIndex: groupIndex, supportAllDayRow: this.allDaySupported(), showAllDayPanel: this.showAllDayPanel }); const appointmentGroupTopOffset = appointmentSettings.top - groupTop - allDayPanelOffset; return appointmentGroupTopOffset }; _proto._getTailHeight = function(appointmentGeometry, appointmentSettings) { if (!this.isVirtualScrolling) { return appointmentGeometry.sourceAppointmentHeight - appointmentGeometry.reducedHeight } const appointmentGroupTopOffset = this._getGroupTopOffset(appointmentSettings); const { sourceAppointmentHeight: sourceAppointmentHeight } = appointmentGeometry; const groupHeight = this._getGroupHeight(); const tailHeight = appointmentGroupTopOffset + sourceAppointmentHeight - groupHeight; return tailHeight }; _proto._getAppointmentParts = function(appointmentGeometry, appointmentSettings) { const { width: width } = appointmentGeometry; const result = []; let currentPartTop = Math.max(0, this.positionHelper.getGroupTop({ groupIndex: appointmentSettings.groupIndex, showAllDayPanel: this.showAllDayPanel, isGroupedAllDayPanel: this.isGroupedAllDayPanel })); const cellsDiff = this.isGroupedByDate ? this.groupCount : 1; const offset = this.cellWidth * cellsDiff; const allDayPanelOffset = this.positionHelper.getOffsetByAllDayPanel({ groupIndex: appointmentSettings.groupIndex, supportAllDayRow: this.allDaySupported(), showAllDayPanel: this.showAllDayPanel }); currentPartTop += allDayPanelOffset; const minHeight = this.getAppointmentMinSize(); const { vMax: vMax, hMax: hMax } = appointmentSettings; const hasTailPart = this.options.endViewDate > appointmentSettings.info.appointment.endDate; let left = Math.round(appointmentSettings.left + offset); let tailHeight = this._getTailHeight(appointmentGeometry, appointmentSettings); let { columnIndex: columnIndex } = appointmentSettings; while (tailHeight > 0 && left < hMax) { tailHeight = Math.max(minHeight, tailHeight); columnIndex += cellsDiff; const height = Math.min(tailHeight, vMax); result.push(_extends(_extends({}, appointmentSettings), { top: currentPartTop, left: left, height: height, width: width, appointmentReduced: "body", rowIndex: 0, columnIndex: columnIndex })); left += offset; tailHeight -= vMax } if (hasTailPart && result.length > 0) { result[result.length - 1].appointmentReduced = "tail" } return result }; _proto._getMinuteHeight = function() { return this.cellHeight / this.cellDurationInMinutes }; _proto._getCompactLeftCoordinate = function(itemLeft, index) { const cellWidth = this.cellWidth || this.getAppointmentMinSize(); return itemLeft + (1 + cellWidth) * index }; _proto._getVerticalAppointmentGeometry = function(coordinates) { const config = this._calculateVerticalGeometryConfig(coordinates); return this._customizeVerticalCoordinates(coordinates, config.width, config.appointmentCountPerCell, config.offset) }; _proto._customizeVerticalCoordinates = function(coordinates, width, appointmentCountPerCell, topOffset, isAllDay) { const appointmentWidth = Math.max(width / appointmentCountPerCell, width / coordinates.count); const { height: height } = coordinates; const appointmentLeft = coordinates.left + coordinates.index * appointmentWidth; const { top: top } = coordinates; if (coordinates.isCompact) { this._markAppointmentAsVirtual(coordinates, isAllDay) } return { height: height, width: appointmentWidth, top: top, left: appointmentLeft, empty: this._isAppointmentEmpty(height, width) } }; _proto._calculateVerticalGeometryConfig = function(coordinates) { const overlappingMode = this.maxAppointmentsPerCell; const offsets = this._getOffsets(); const appointmentDefaultOffset = this._getAppointmentDefaultOffset(); let appointmentCountPerCell = this._getAppointmentCount(overlappingMode, coordinates); let ratio = this._getDefaultRatio(coordinates, appointmentCountPerCell); let maxWidth = this._getMaxWidth(); if (!appointmentCountPerCell) { appointmentCountPerCell = coordinates.count; ratio = (maxWidth - offsets.unlimited) / maxWidth } let topOffset = (1 - ratio) * maxWidth; if ("auto" === overlappingMode || (0, _type.isNumeric)(overlappingMode)) { ratio = 1; maxWidth -= appointmentDefaultOffset; topOffset = 0 } return { width: ratio * maxWidth, appointmentCountPerCell: appointmentCountPerCell, offset: topOffset } }; _proto._getMaxWidth = function() { return this.cellWidth }; _proto.isAllDay = function(appointmentData) { return (0, _index.getAppointmentTakesAllDay)((0, _m_appointment_adapter.createAppointmentAdapter)(appointmentData, this.dataAccessors, this.timeZoneCalculator), this.allDayPanelMode) }; _proto._getAppointmentMaxWidth = function() { return this.cellWidth - this._getAppointmentDefaultOffset() }; _proto.calculateAppointmentWidth = function(appointment, position) { if (!this.isAllDay(appointment)) { return 0 } const { startDate: startDateWithTime, endDate: endDate, normalizedEndDate: normalizedEndDate } = position.info.appointment; const startDate = _date.default.trimTime(startDateWithTime); const cellWidth = this.cellWidth || this.getAppointmentMinSize(); const durationInHours = (normalizedEndDate.getTime() - startDate.getTime()) / toMs("hour"); const skippedHours = (0, _index.getSkippedHoursInRange)(startDate, endDate, appointment.allDay, this.viewDataProvider); let width = Math.ceil((durationInHours - skippedHours) / 24) * cellWidth; width = this.cropAppointmentWidth(width, cellWidth); return width }; _proto.calculateAppointmentHeight = function(appointment, position) { if (this.isAllDay(appointment)) { return 0 } const { startDate: startDate, normalizedEndDate: normalizedEndDate } = position.info.appointment; const allDay = _m_expression_utils.ExpressionUtils.getField(this.dataAccessors, "allDay", appointment); const duration = this.getAppointmentDurationInMs(startDate, normalizedEndDate, allDay); const durationInMinutes = this._adjustDurationByDaylightDiff(duration, startDate, normalizedEndDate) / toMs("minute"); const height = durationInMinutes * this._getMinuteHeight(); return height }; _proto.getDirection = function() { return "vertical" }; _proto._sortCondition = function(a, b) { if (!!a.allDay !== !!b.allDay) { return a.allDay ? 1 : -1 } const isAllDay = a.allDay && b.allDay; return "vertical" === this.groupOrientation && isAllDay ? this._columnCondition(a, b) : this._rowCondition(a, b) }; _proto.allDaySupported = function() { return true }; _proto._getAllDayAppointmentGeometry = function(coordinates) { const config = this._calculateGeometryConfig(coordinates); return this._customizeCoordinates(coordinates, config.height, config.appointmentCountPerCell, config.offset, true) }; _proto._calculateGeometryConfig = function(coordinates) { if (!this.allowResizing || !this.allowAllDayResizing) { coordinates.skipResizing = true } const config = _BaseAppointmentsStra.prototype._calculateGeometryConfig.call(this, coordinates); const minAppointmentCountPerCell = Math.min(config.appointmentCountPerCell, this._getDynamicAppointmentCountPerCell().allDay); if (coordinates.allDay && coordinates.count <= minAppointmentCountPerCell) { config.offset = 0 } return config }; _proto._getAppointmentCount = function(overlappingMode, coordinates) { return "auto" !== overlappingMode && 1 === coordinates.count && !(0, _type.isNumeric)(overlappingMode) ? coordinates.count : this._getMaxAppointmentCountPerCellByType(coordinates.allDay) }; _proto._getDefaultRatio = function(coordinates, appointmentCountPerCell) { return coordinates.count > this.appointmentCountPerCell ? .65 : 1 }; _proto._getOffsets = function() { return { unlimited: 5, auto: 20 } }; _proto._getMaxHeight = function() { return this.allDayHeight || this.getAppointmentMinSize() }; _proto._needVerticalGroupBounds = function(allDay) { return !allDay }; _proto._needHorizontalGroupBounds = function() { return false }; _proto.getPositionShift = function(timeShift, isAllDay) { if (!isAllDay && this.isAdaptive && 0 === this._getMaxAppointmentCountPerCellByType(isAllDay)) { return { top: 0, left: 0, cellPosition: 0 } } return _BaseAppointmentsStra.prototype.getPositionShift.call(this, timeShift, isAllDay) }; return VerticalRenderingStrategy }(_m_strategy_base.default); var _default = VerticalRenderingStrategy; exports.default = _default;