UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

540 lines (539 loc) • 23.6 kB
/** * DevExtreme (esm/ui/scheduler/subscribes.js) * Version: 21.1.4 * Build date: Mon Jun 21 2021 * * Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import $ from "../../core/renderer"; import { wrapToArray, inArray } from "../../core/utils/array"; import { isDefined, isPlainObject } from "../../core/utils/type"; import dateUtils from "../../core/utils/date"; import { each } from "../../core/utils/iterator"; import errors from "../widget/ui.errors"; import { locate } from "../../animation/translator"; import { grep } from "../../core/utils/common"; import { extend } from "../../core/utils/extend"; import { Deferred } from "../../core/utils/deferred"; import dateLocalization from "../../localization/date"; import timeZoneUtils from "./utils.timeZone"; import { AGENDA_LAST_IN_DATE_APPOINTMENT_CLASS } from "./constants"; import utils from "./utils"; import { getFieldExpr as getResourceFieldExpr } from "./resources/utils"; var toMs = dateUtils.dateToMilliseconds; var subscribes = { getTimeZoneCalculator: function() { return this.timeZoneCalculator }, isCurrentViewAgenda: function() { return "agenda" === this.option("currentView") }, currentViewUpdated: function(currentView) { this.option("currentView", currentView) }, currentDateUpdated: function(date) { this.option("currentDate", date) }, getOption: function(name) { return this.option(name) }, isVirtualScrolling: function() { return this.isVirtualScrolling() }, setCellDataCacheAlias: function(appointment, geometry) { this._workSpace.setCellDataCacheAlias(appointment, geometry) }, createAppointmentSettings: function(appointment) { return this._getAppointmentSettingsGenerator().create(appointment) }, isGroupedByDate: function() { return this.getWorkSpace().isGroupedByDate() }, showAppointmentTooltip: function(options) { var targetedAppointment = this.getTargetedAppointment(options.data, options.target); this.showAppointmentTooltip(options.data, options.target, targetedAppointment) }, hideAppointmentTooltip: function() { this.hideAppointmentTooltip() }, showAddAppointmentPopup: function(cellData, cellGroups) { var appointmentAdapter = this.createAppointmentAdapter({}); appointmentAdapter.allDay = cellData.allDay; appointmentAdapter.startDate = this.timeZoneCalculator.createDate(cellData.startDate, { path: "fromGrid" }); appointmentAdapter.endDate = this.timeZoneCalculator.createDate(cellData.endDate, { path: "fromGrid" }); var resultAppointment = extend(appointmentAdapter.source(), cellGroups); this.showAppointmentPopup(resultAppointment, true) }, showEditAppointmentPopup: function(options) { var targetedData = this.getTargetedAppointment(options.data, options.target); this.showAppointmentPopup(options.data, false, targetedData) }, updateAppointmentAfterResize: function(options) { var info = utils.dataAccessors.getAppointmentInfo(options.$appointment); var exceptionDate = info.sourceAppointment.exceptionDate; this._checkRecurringAppointment(options.target, options.data, exceptionDate, function() { this._updateAppointment(options.target, options.data, (function() { this._appointments.moveAppointmentBack() })) }.bind(this)) }, getUpdatedData: function(rawAppointment) { return this._getUpdatedData(rawAppointment) }, updateAppointmentAfterDrag: function(_ref) { var { event: event, element: element, rawAppointment: rawAppointment, coordinates: coordinates } = _ref; var info = utils.dataAccessors.getAppointmentInfo(element); var appointment = this.createAppointmentAdapter(rawAppointment); var targetedAppointment = this.createAppointmentAdapter(extend({}, rawAppointment, this._getUpdatedData(rawAppointment))); var targetedRawAppointment = targetedAppointment.source(); var newCellIndex = this._workSpace.getDroppableCellIndex(); var oldCellIndex = this._workSpace.getCellIndexByCoordinates(coordinates); var becomeAllDay = targetedAppointment.allDay; var wasAllDay = appointment.allDay; var movedBetweenAllDayAndSimple = this._workSpace.supportAllDayRow() && (wasAllDay && !becomeAllDay || !wasAllDay && becomeAllDay); if (newCellIndex !== oldCellIndex || movedBetweenAllDayAndSimple) { this._checkRecurringAppointment(rawAppointment, targetedRawAppointment, info.sourceAppointment.exceptionDate, function() { this._updateAppointment(rawAppointment, targetedRawAppointment, (function() { this._appointments.moveAppointmentBack(event) }), event) }.bind(this), void 0, void 0, event) } else { this._appointments.moveAppointmentBack(event) } }, onDeleteButtonPress: function(options) { var targetedData = this.getTargetedAppointment(options.data, $(options.target)); this.checkAndDeleteAppointment(options.data, targetedData); this.hideAppointmentTooltip() }, getAppointmentColor: function(options) { var resourcesManager = this._resourcesManager; var resourceForPainting = resourcesManager.getResourceForPainting(this._getCurrentViewOption("groups")); var response = (new Deferred).resolve().promise(); if (resourceForPainting) { var field = getResourceFieldExpr(resourceForPainting); var groupIndex = options.groupIndex; var groups = this._workSpace._getCellGroups(groupIndex); var resourceValues = wrapToArray(resourcesManager.getDataAccessors(field, "getter")(options.itemData)); var groupId = resourceValues.length ? resourceValues[0] : void 0; for (var i = 0; i < groups.length; i++) { if (groups[i].name === field) { groupId = groups[i].id; break } } response = resourcesManager.getResourceColor(field, groupId) } return response }, getHeaderHeight: function() { return this._header._$element && parseInt(this._header._$element.outerHeight(), 10) }, getResourcesFromItem: function(itemData) { return this._resourcesManager.getResourcesFromItem(itemData) }, appointmentTakesSeveralDays: function(appointment) { return this._appointmentModel.appointmentTakesSeveralDays(appointment) }, getTextAndFormatDate(appointmentRaw, targetedAppointmentRaw, format) { var appointmentAdapter = this.createAppointmentAdapter(appointmentRaw); var targetedAdapter = this.createAppointmentAdapter(targetedAppointmentRaw || appointmentRaw); var startDate = this.timeZoneCalculator.createDate(targetedAdapter.startDate, { path: "toGrid" }); var endDate = this.timeZoneCalculator.createDate(targetedAdapter.endDate, { path: "toGrid" }); var formatType = format || this.fire("_getTypeFormat", startDate, endDate, targetedAdapter.allDay); return { text: targetedAdapter.text || appointmentAdapter.text, formatDate: this.fire("_formatDates", startDate, endDate, formatType) } }, _getTypeFormat(startDate, endDate, isAllDay) { if (isAllDay) { return "DATE" } if ("month" !== this.option("currentView") && dateUtils.sameDate(startDate, endDate)) { return "TIME" } return "DATETIME" }, _createAppointmentTitle(data) { if (isPlainObject(data)) { return data.text } return String(data) }, _formatDates(startDate, endDate, formatType) { var isSameDate = startDate.getDate() === endDate.getDate(); switch (formatType) { case "DATETIME": return [dateLocalization.format(startDate, "monthandday"), " ", dateLocalization.format(startDate, "shorttime"), " - ", isSameDate ? "" : dateLocalization.format(endDate, "monthandday") + " ", dateLocalization.format(endDate, "shorttime")].join(""); case "TIME": return "".concat(dateLocalization.format(startDate, "shorttime"), " - ").concat(dateLocalization.format(endDate, "shorttime")); case "DATE": return "".concat(dateLocalization.format(startDate, "monthandday")).concat(isSameDate ? "" : " - " + dateLocalization.format(endDate, "monthandday")) } }, getResizableAppointmentArea: function(options) { var allDay = options.allDay; var groups = this._getCurrentViewOption("groups"); if (groups && groups.length) { if (allDay || this.getLayoutManager().getRenderingStrategyInstance()._needHorizontalGroupBounds()) { var horizontalGroupBounds = this._workSpace.getGroupBounds(options.coordinates); return { left: horizontalGroupBounds.left, right: horizontalGroupBounds.right, top: 0, bottom: 0 } } if (this.getLayoutManager().getRenderingStrategyInstance()._needVerticalGroupBounds(allDay) && this._workSpace._isVerticalGroupedWorkSpace()) { var verticalGroupBounds = this._workSpace.getGroupBounds(options.coordinates); return { left: 0, right: 0, top: verticalGroupBounds.top, bottom: verticalGroupBounds.bottom } } } }, needRecalculateResizableArea: function() { return this.getWorkSpace().needRecalculateResizableArea() }, getAppointmentGeometry: function(settings) { return this.getLayoutManager().getRenderingStrategyInstance().getAppointmentGeometry(settings) }, isAllDay: function(appointmentData) { return this.getLayoutManager().getRenderingStrategyInstance().isAllDay(appointmentData) }, getDeltaTime: function(e, initialSize, itemData) { return this.getLayoutManager().getRenderingStrategyInstance().getDeltaTime(e, initialSize, itemData) }, getDropDownAppointmentWidth: function(isAllDay) { return this.getLayoutManager().getRenderingStrategyInstance().getDropDownAppointmentWidth(this._getViewCountConfig().intervalCount, isAllDay) }, getDropDownAppointmentHeight: function() { return this.getLayoutManager().getRenderingStrategyInstance().getDropDownAppointmentHeight() }, getCellWidth: function() { return this.getWorkSpace().getCellWidth() }, getCellHeight: function() { return this.getWorkSpace().getCellHeight() }, getResizableStep: function() { var workSpace = this.getWorkSpace(); var cellWidth = workSpace.getCellWidth(); if (workSpace.isGroupedByDate()) { return workSpace._getGroupCount() * cellWidth } return cellWidth }, getRenderingStrategy: function() { return this._getAppointmentsRenderingStrategy() }, getMaxAppointmentCountPerCellByType: function(isAllDay) { return this.getRenderingStrategyInstance()._getMaxAppointmentCountPerCellByType(isAllDay) }, needCorrectAppointmentDates: function() { return this.getRenderingStrategyInstance().needCorrectAppointmentDates() }, getRenderingStrategyDirection: function() { return this.getRenderingStrategyInstance().getDirection() }, getWorkSpaceDateTableOffset: function() { return this.getWorkSpaceDateTableOffset() }, getFullWeekAppointmentWidth: function(options) { var groupIndex = options.groupIndex; return this._workSpace.getGroupWidth(groupIndex) }, getMaxAppointmentWidth: function(options) { var workSpace = this._workSpace; return workSpace.getCellCountToLastViewDate(options.date) * workSpace.getCellWidth() }, updateAppointmentStartDate: function(options) { var appointment = options.appointment; var firstViewDate = this._workSpace.getStartViewDate(); var startDate = new Date(options.startDate); var startDayHour = this._getCurrentViewOption("startDayHour"); var updatedStartDate; if (this.appointmentTakesAllDay(appointment)) { updatedStartDate = dateUtils.normalizeDate(startDate, firstViewDate) } else { if (startDate < firstViewDate) { startDate = firstViewDate } updatedStartDate = dateUtils.normalizeDate(options.startDate, new Date(startDate)) } return dateUtils.roundDateByStartDayHour(updatedStartDate, startDayHour) }, updateAppointmentEndDate: function(options) { var endDate = options.endDate; var endDayHour = this._getCurrentViewOption("endDayHour"); var startDayHour = this._getCurrentViewOption("startDayHour"); var updatedEndDate = endDate; if (endDate.getHours() >= endDayHour) { updatedEndDate.setHours(endDayHour, 0, 0, 0) } else if (!options.isSameDate && startDayHour > 0 && 60 * endDate.getHours() + endDate.getMinutes() < 60 * startDayHour) { updatedEndDate = new Date(updatedEndDate.getTime() - toMs("day")); updatedEndDate.setHours(endDayHour, 0, 0, 0) } return updatedEndDate }, renderCompactAppointments: function(options) { this._compactAppointmentsHelper.render(options) }, clearCompactAppointments: function() { this._compactAppointmentsHelper.clear() }, supportCompactDropDownAppointments: function() { return this._workSpace._supportCompactDropDownAppointments() }, isApplyCompactAppointmentOffset: function() { return this._workSpace._isApplyCompactAppointmentOffset() }, getGroupCount: function() { return this._workSpace._getGroupCount() }, mapAppointmentFields: function(config) { var { itemData: itemData, itemElement: itemElement, targetedAppointment: targetedAppointment } = config; var targetedData = targetedAppointment || this.getTargetedAppointment(itemData, itemElement); return { appointmentData: config.itemData, appointmentElement: config.itemElement, targetedAppointmentData: targetedData } }, getOffsetByAllDayPanel: function(groupIndex) { return this._workSpace._getOffsetByAllDayPanel(groupIndex) }, getGroupTop: function(groupIndex) { return this._workSpace._getGroupTop(groupIndex) }, updateResizableArea: function() { var $allResizableElements = this.$element().find(".dx-scheduler-appointment.dx-resizable"); var horizontalResizables = grep($allResizableElements, (function(el) { var $el = $(el); var resizableInst = $el.dxResizable("instance"); var area = resizableInst.option("area"); return inArray(resizableInst.option("handles"), ["right left", "left right"]) > -1 && isPlainObject(area) })); each(horizontalResizables, function(_, el) { var $el = $(el); var position = locate($el); var appointmentData = this._appointments._getItemData($el); var area = this._appointments._calculateResizableArea({ left: position.left }, appointmentData); $el.dxResizable("instance").option("area", area) }.bind(this)) }, getField: function(field, obj) { if (!isDefined(this._dataAccessors.getter[field])) { return } return this._dataAccessors.getter[field](obj) }, setField: function(field, obj, value) { if (!isDefined(this._dataAccessors.setter[field])) { return } var splitExprStr = this.option(field + "Expr").split("."); var rootField = splitExprStr[0]; if (void 0 === obj[rootField] && splitExprStr.length > 1) { var emptyChain = function(arr) { var result = {}; var tmp = result; var arrLength = arr.length - 1; for (var i = 1; i < arrLength; i++) { tmp = tmp[arr[i]] = {} } return result }(splitExprStr); obj[rootField] = emptyChain } this._dataAccessors.setter[field](obj, value); return obj }, renderAppointments: function() { this._renderAppointments() }, dayHasAppointment: function(day, appointment, trimTime) { return this.dayHasAppointment(day, appointment, trimTime) }, createResourcesTree: function() { return this._resourcesManager.createResourcesTree(this._loadedResources) }, getResourceTreeLeaves: function(tree, appointmentResources) { return this._resourcesManager.getResourceTreeLeaves(tree, appointmentResources) }, createReducedResourcesTree: function() { var tree = this._resourcesManager.createResourcesTree(this._loadedResources); return this._resourcesManager.reduceResourcesTree(tree, this.getFilteredItems()) }, groupAppointmentsByResources: function(appointments) { var result = { 0: appointments }; var groups = this._getCurrentViewOption("groups"); if (groups && groups.length && this._resourcesManager.getResourcesData().length) { result = this._resourcesManager.groupAppointmentsByResources(appointments, this._loadedResources) } var totalResourceCount = 0; each(this._loadedResources, (function(i, resource) { if (!i) { totalResourceCount = resource.items.length } else { totalResourceCount *= resource.items.length } })); for (var j = 0; j < totalResourceCount; j++) { var index = j.toString(); if (result[index]) { continue } result[index] = [] } return result }, getLayoutManager: function() { return this._layoutManager }, getAgendaVerticalStepHeight: function() { return this.getWorkSpace().getAgendaVerticalStepHeight() }, getAgendaDuration: function() { return this._getCurrentViewOption("agendaDuration") }, getStartViewDate: function() { return this.getStartViewDate() }, getEndViewDate: function() { return this.getEndViewDate() }, getMaxAppointmentsPerCell: function() { return this.getMaxAppointmentsPerCell() }, forceMaxAppointmentPerCell: function() { return this.forceMaxAppointmentPerCell() }, onAgendaReady: function(rows) { var $appts = this.getAppointmentsInstance()._itemElements(); var total = 0; var applyClass = function(_, count) { var index = count + total - 1; $appts.eq(index).addClass(AGENDA_LAST_IN_DATE_APPOINTMENT_CLASS); total += count }; for (var i = 0; i < rows.length; i++) { each(rows[i], applyClass) } }, getTimezone: function() { return this._getTimezoneOffsetByOption() }, getTargetedAppointmentData: function(appointment, element) { return this.getTargetedAppointment(appointment, element) }, getAppointmentDurationInMs: function(options) { var startDate = options.startDate; var endDate = options.endDate; var allDay = options.allDay; var appointmentDuration = endDate.getTime() - startDate.getTime(); var dayDuration = toMs("day"); var visibleDayDuration = this._workSpace.getVisibleDayDuration(); var result = 0; if (allDay) { var ceilQuantityOfDays = Math.ceil(appointmentDuration / dayDuration); result = ceilQuantityOfDays * visibleDayDuration } else { var isDifferentDates = !timeZoneUtils.isSameAppointmentDates(startDate, endDate); var floorQuantityOfDays = Math.floor(appointmentDuration / dayDuration); var tailDuration; if (isDifferentDates) { var startDateEndHour = new Date(new Date(startDate).setHours(this.option("endDayHour"), 0, 0)); var hiddenDayDuration = dayDuration - visibleDayDuration - (startDate.getTime() > startDateEndHour.getTime() ? startDate.getTime() - startDateEndHour.getTime() : 0); tailDuration = appointmentDuration - (floorQuantityOfDays ? floorQuantityOfDays * dayDuration : hiddenDayDuration); var startDayTime = this.option("startDayHour") * toMs("hour"); var endPartDuration = endDate - dateUtils.trimTime(endDate); if (endPartDuration < startDayTime) { if (floorQuantityOfDays) { tailDuration -= hiddenDayDuration } tailDuration += startDayTime - endPartDuration } } else { tailDuration = appointmentDuration % dayDuration } if (tailDuration > visibleDayDuration) { tailDuration = visibleDayDuration } result = floorQuantityOfDays * visibleDayDuration + tailDuration || toMs("minute") } return result }, replaceWrongEndDate: function(appointment, startDate, endDate) { this._appointmentModel.replaceWrongEndDate(appointment, startDate, endDate) }, calculateAppointmentEndDate: function(isAllDay, startDate) { return this._appointmentModel._calculateAppointmentEndDate(isAllDay, startDate) }, getEndDayHour: function() { return this._workSpace.option("endDayHour") || this.option("endDayHour") }, getStartDayHour: function() { return this._workSpace.option("startDayHour") || this.option("startDayHour") }, isAdaptive: function() { return this.option("adaptivityEnabled") }, validateDayHours: function() { var endDayHour = this._getCurrentViewOption("endDayHour"); var startDayHour = this._getCurrentViewOption("startDayHour"); if (startDayHour >= endDayHour) { throw errors.Error("E1058") } }, removeDroppableCellClass: function() { this._workSpace.removeDroppableCellClass() } }; export default subscribes;