UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

341 lines (340 loc) • 14.1 kB
/** * DevExtreme (esm/__internal/scheduler/r1/utils/base.js) * Version: 24.2.6 * Build date: Mon Mar 17 2025 * * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import _extends from "@babel/runtime/helpers/esm/extends"; import dateLocalization from "../../../../common/core/localization/date"; import { equalByValue } from "../../../../core/utils/common"; import dateUtils from "../../../../core/utils/date"; import { isDefined } from "../../../../core/utils/type"; import { dateUtilsTs } from "../../../core/utils/date"; import { VERTICAL_GROUP_COUNT_CLASSES } from "../../m_classes"; import { VIEWS } from "../../m_constants"; import timeZoneUtils from "../../m_utils_time_zone"; import { HORIZONTAL_GROUP_ORIENTATION, TIMELINE_VIEWS, VERTICAL_GROUP_ORIENTATION } from "../const"; const toMs = dateUtils.dateToMilliseconds; const DAY_HOURS = 24; const HOUR_IN_MS = 36e5; const SATURDAY_INDEX = 6; const SUNDAY_INDEX = 0; const getDurationInHours = (startDate, endDate) => Math.floor((endDate.getTime() - startDate.getTime()) / toMs("hour")); export const getDatesWithoutTime = (min, max) => { const newMin = dateUtils.trimTime(min); const newMax = dateUtils.trimTime(max); newMax.setDate(newMax.getDate() + 1); return [newMin, newMax] }; export const getAppointmentRenderingStrategyName = viewType => { const { renderingStrategy: renderingStrategy } = { day: { renderingStrategy: "vertical" }, week: { renderingStrategy: "week" }, workWeek: { renderingStrategy: "week" }, month: { renderingStrategy: "horizontalMonth" }, timelineDay: { renderingStrategy: "horizontal" }, timelineWeek: { renderingStrategy: "horizontal" }, timelineWorkWeek: { renderingStrategy: "horizontal" }, timelineMonth: { renderingStrategy: "horizontalMonthLine" }, agenda: { renderingStrategy: "agenda" } } [viewType]; return renderingStrategy }; export const getAppointmentTakesAllDay = (appointmentAdapter, allDayPanelMode) => { const { startDate: startDate, endDate: endDate, allDay: allDay } = appointmentAdapter; switch (allDayPanelMode) { case "hidden": return false; case "allDay": return allDay; default: if (allDay) { return true } if (!isDefined(endDate)) { return false } return getDurationInHours(startDate, endDate) >= 24 } }; export const getAppointmentKey = geometry => { const { left: left, top: top, width: width, height: height } = geometry; return `${left}-${top}-${width}-${height}` }; export const hasResourceValue = (resourceValues, itemValue) => isDefined(resourceValues.find((value => equalByValue(value, itemValue)))); export const getOverflowIndicatorColor = (color, colors) => !colors.length || 0 === colors.filter((item => item !== color)).length ? color : void 0; export const getVerticalGroupCountClass = groups => { switch (null === groups || void 0 === groups ? void 0 : groups.length) { case 1: return VERTICAL_GROUP_COUNT_CLASSES[0]; case 2: return VERTICAL_GROUP_COUNT_CLASSES[1]; case 3: return VERTICAL_GROUP_COUNT_CLASSES[2]; default: return } }; export const setOptionHour = (date, optionHour) => { const nextDate = new Date(date); if (!isDefined(optionHour)) { return nextDate } nextDate.setHours(optionHour, optionHour % 1 * 60, 0, 0); return nextDate }; export const calculateDayDuration = (startDayHour, endDayHour) => endDayHour - startDayHour; export const getStartViewDateTimeOffset = (startViewDate, startDayHour) => { const validStartDayHour = Math.floor(startDayHour); const isDSTChange = timeZoneUtils.isTimezoneChangeInDate(startViewDate); if (isDSTChange && validStartDayHour !== startViewDate.getHours()) { return dateUtils.dateToMilliseconds("hour") } return 0 }; export const getValidCellDateForLocalTimeFormat = (date, _ref) => { let { startViewDate: startViewDate, startDayHour: startDayHour, cellIndexShift: cellIndexShift, viewOffset: viewOffset } = _ref; const originDate = dateUtilsTs.addOffsets(date, [-viewOffset]); const localTimeZoneChangedInOriginDate = timeZoneUtils.isTimezoneChangeInDate(originDate); if (!localTimeZoneChangedInOriginDate) { return date } const startViewDateWithoutDST = new Date(new Date(startViewDate).setDate(startViewDate.getDate() + 2)); const startViewDateOffset = getStartViewDateTimeOffset(startViewDate, startDayHour); return dateUtilsTs.addOffsets(startViewDateWithoutDST, [viewOffset, cellIndexShift, -startViewDateOffset]) }; export const getTotalCellCountByCompleteData = completeData => completeData[completeData.length - 1].length; export const getDisplayedCellCount = (displayedCellCount, completeData) => displayedCellCount ?? getTotalCellCountByCompleteData(completeData); export const getHeaderCellText = (headerIndex, date, headerCellTextFormat, getDateForHeaderText, additionalOptions) => { const validDate = getDateForHeaderText(headerIndex, date, additionalOptions); return dateLocalization.format(validDate, headerCellTextFormat) }; export const isVerticalGroupingApplied = (groups, groupOrientation) => groupOrientation === VERTICAL_GROUP_ORIENTATION && !!groups.length; export const getGroupCount = groups => { let result = 0; for (let i = 0, len = groups.length; i < len; i += 1) { if (!i) { result = groups[i].items.length } else { result *= groups[i].items.length } } return result }; export const getHorizontalGroupCount = (groups, groupOrientation) => { const groupCount = getGroupCount(groups) || 1; const isVerticalGrouping = isVerticalGroupingApplied(groups, groupOrientation); return isVerticalGrouping ? 1 : groupCount }; export const isTimelineView = viewType => !!TIMELINE_VIEWS[viewType]; export const isDateAndTimeView = viewType => viewType !== VIEWS.TIMELINE_MONTH && viewType !== VIEWS.MONTH; export const isHorizontalView = viewType => { switch (viewType) { case VIEWS.TIMELINE_DAY: case VIEWS.TIMELINE_WEEK: case VIEWS.TIMELINE_WORK_WEEK: case VIEWS.TIMELINE_MONTH: case VIEWS.MONTH: return true; default: return false } }; export const isDateInRange = (date, startDate, endDate, diff) => diff > 0 ? dateUtils.dateInRange(date, startDate, new Date(endDate.getTime() - 1)) : dateUtils.dateInRange(date, endDate, startDate, "date"); export const isFirstCellInMonthWithIntervalCount = (cellDate, intervalCount) => 1 === cellDate.getDate() && intervalCount > 1; export const getViewStartByOptions = (startDate, currentDate, intervalDuration, startViewDate) => { if (!startDate) { return new Date(currentDate) } let currentStartDate = dateUtils.trimTime(startViewDate); const diff = currentStartDate.getTime() <= currentDate.getTime() ? 1 : -1; let endDate = new Date(currentStartDate.getTime() + intervalDuration * diff); while (!isDateInRange(currentDate, currentStartDate, endDate, diff)) { currentStartDate = endDate; endDate = new Date(currentStartDate.getTime() + intervalDuration * diff) } return diff > 0 ? currentStartDate : endDate }; export const calculateIsGroupedAllDayPanel = (groups, groupOrientation, isAllDayPanelVisible) => isVerticalGroupingApplied(groups, groupOrientation) && isAllDayPanelVisible; export const calculateViewStartDate = startDateOption => startDateOption; export const getCellDuration = (viewType, startDayHour, endDayHour, hoursInterval) => { switch (viewType) { case "month": return 36e5 * calculateDayDuration(startDayHour, endDayHour); case "timelineMonth": return dateUtils.dateToMilliseconds("day"); default: return 36e5 * hoursInterval } }; export const calculateCellIndex = (rowIndex, columnIndex, rowCount) => columnIndex * rowCount + rowIndex; export const getTotalRowCountByCompleteData = completeData => completeData.length; export const getDisplayedRowCount = (displayedRowCount, completeData) => displayedRowCount ?? getTotalRowCountByCompleteData(completeData); export const getStartViewDateWithoutDST = (startViewDate, startDayHour) => { const newStartViewDate = timeZoneUtils.getDateWithoutTimezoneChange(startViewDate); newStartViewDate.setHours(startDayHour); return newStartViewDate }; export const getIsGroupedAllDayPanel = (hasAllDayRow, isVerticalGrouping) => hasAllDayRow && isVerticalGrouping; export const getKeyByGroup = (groupIndex, isVerticalGrouping) => { if (isVerticalGrouping && !!groupIndex) { return groupIndex.toString() } return "0" }; export const getToday = (indicatorTime, timeZoneCalculator) => { const todayDate = indicatorTime ?? new Date; return (null === timeZoneCalculator || void 0 === timeZoneCalculator ? void 0 : timeZoneCalculator.createDate(todayDate, { path: "toGrid" })) || todayDate }; export const getCalculatedFirstDayOfWeek = firstDayOfWeekOption => isDefined(firstDayOfWeekOption) ? firstDayOfWeekOption : dateLocalization.firstDayOfWeekIndex(); export const isHorizontalGroupingApplied = (groups, groupOrientation) => groupOrientation === HORIZONTAL_GROUP_ORIENTATION && !!groups.length; export const isGroupingByDate = (groups, groupOrientation, groupByDate) => { const isHorizontalGrouping = isHorizontalGroupingApplied(groups, groupOrientation); return groupByDate && isHorizontalGrouping }; export const getSkippedHoursInRange = (startDate, endDate, allDay, viewDataProvider) => { const isAllDay = allDay && !viewDataProvider.viewType.includes("timeline"); let result = 0; const currentDate = new Date(startDate); currentDate.setDate(currentDate.getDate() + 1); currentDate.setHours(0, 0, 0, 0); const endDateWithStartHour = new Date(endDate); endDateWithStartHour.setHours(0, 0, 0, 0); const { startDayHour: startDayHour, endDayHour: endDayHour } = viewDataProvider.getViewOptions(); const dayHours = isAllDay ? 24 : endDayHour - startDayHour; while (currentDate < endDateWithStartHour) { if (viewDataProvider.isSkippedDate(currentDate)) { result += dayHours } currentDate.setDate(currentDate.getDate() + 1) } const startDateHours = startDate.getHours(); const endDateHours = endDate.getHours() + endDate.getTime() % 36e5 / 36e5; if (viewDataProvider.isSkippedDate(startDate)) { if (isAllDay) { result += 24 } else if (startDateHours < startDayHour) { result += dayHours } else if (startDateHours < endDayHour) { result += endDayHour - startDateHours } } if (viewDataProvider.isSkippedDate(endDate)) { if (isAllDay) { result += 24 } else if (endDateHours > endDayHour) { result += dayHours } else if (endDateHours > startDayHour) { result += endDateHours - startDayHour } } return result }; export const isDataOnWeekend = date => { const day = date.getDay(); return 6 === day || 0 === day }; export const getWeekendsCount = days => 2 * Math.floor(days / 7); export const extendGroupItemsForGroupingByDate = (groupRenderItems, columnCountPerGroup) => [...new Array(columnCountPerGroup)].reduce(((currentGroupItems, _, index) => groupRenderItems.map(((groupsRow, rowIndex) => { const currentRow = currentGroupItems[rowIndex] || []; return [...currentRow, ...groupsRow.map(((item, columnIndex) => _extends({}, item, { key: `${item.key}_group_by_date_${index}`, isFirstGroupCell: 0 === columnIndex, isLastGroupCell: columnIndex === groupsRow.length - 1 })))] }))), []); export const getGroupPanelData = (groups, columnCountPerGroup, groupByDate, baseColSpan) => { let repeatCount = 1; let groupPanelItems = groups.map((group => { const result = []; const { name: resourceName, items: items, data: data } = group; for (let iterator = 0; iterator < repeatCount; iterator += 1) { result.push(...items.map(((_ref2, index) => { let { id: id, text: text, color: color } = _ref2; return { id: id, text: text, color: color, key: `${iterator}_${resourceName}_${id}`, resourceName: resourceName, data: null === data || void 0 === data ? void 0 : data[index] } }))) } repeatCount *= items.length; return result })); if (groupByDate) { groupPanelItems = extendGroupItemsForGroupingByDate(groupPanelItems, columnCountPerGroup) } return { groupPanelItems: groupPanelItems, baseColSpan: baseColSpan } }; export const splitNumber = (value, splitValue) => Array.from({ length: Math.ceil(value / splitValue) }, ((_, index) => Math.min(value - splitValue * index, splitValue)));