diff --git a/packages/devextreme/js/__internal/scheduler/scheduler.ts b/packages/devextreme/js/__internal/scheduler/scheduler.ts index bc3810c7abf9..faab89515299 100644 --- a/packages/devextreme/js/__internal/scheduler/scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/scheduler.ts @@ -2089,8 +2089,11 @@ class Scheduler extends SchedulerOptionsBaseWidget { if ( appointment.allDay - && !this._workSpace.supportAllDayRow() && !this._workSpace.keepOriginalHours() + && ( + !this._workSpace.supportAllDayRow() + || this.option('allDayPanelMode') === 'hidden' + ) ) { const dateCopy = new Date(resultedStartDate); dateCopy.setHours(0); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts index b3d23b419944..d31997c40ab5 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_grid_view_model.ts @@ -25,8 +25,9 @@ export const sortAppointments = ( hasAllDayPanel, snapToCellsMode, viewOffset, - compareOptions: { endDayHour }, + compareOptions: { endDayHour, startDayHour }, } = optionManager.options; + const ignoreAllDayHours = !hasAllDayPanel && !isMonthView; const step2 = maybeSplit(items, hasAllDayPanel, (entities, panelName) => { const byGroup = groupByGroupIndex(entities); @@ -35,7 +36,11 @@ export const sortAppointments = ( sortByStartDate(group); const innerStep0 = isMonthView || panelName === 'allDayPanel' ? expandAllDayAllDayPanel(group, endDayHour, viewOffset) - : expandAllDayRegularPanel(group); + : expandAllDayRegularPanel(group, { + startDayHour, + viewOffsetMs: viewOffset, + ignoreAllDayHours, + }); const innerStep1 = splitByParts(innerStep0, optionManager.getSplitIntervals(panelName)); sortByDuration(innerStep1); sortByStartDate(innerStep1); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.test.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.test.ts index 789c5eec5e6a..31e942a35d7c 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.test.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.test.ts @@ -2,6 +2,12 @@ import { describe, expect, it } from '@jest/globals'; import { expandAllDayAllDayPanel, expandAllDayRegularPanel } from './expand_all_day'; +const defaultRegularPanelOptions = { + startDayHour: 0, + viewOffsetMs: 0, + ignoreAllDayHours: false, +}; + describe('expandAllDay', () => { describe('expandAllDayAllDayPanel', () => { it('should not expand regular appointment', () => { @@ -89,7 +95,7 @@ describe('expandAllDay', () => { allDay: false, startDateUTC: Date.UTC(2020, 0, 10, 0), endDateUTC: Date.UTC(2020, 0, 10, 1), - }])).toEqual([ + }], defaultRegularPanelOptions)).toEqual([ { allDay: false, startDateUTC: Date.UTC(2020, 0, 10, 0), @@ -113,7 +119,7 @@ describe('expandAllDay', () => { startDateUTC: Date.UTC(2020, 0, 11, 23), endDateUTC: Date.UTC(2020, 0, 12), }, - ])).toEqual([ + ], defaultRegularPanelOptions)).toEqual([ { allDay: true, startDateUTC: Date.UTC(2020, 0, 10), @@ -129,5 +135,101 @@ describe('expandAllDay', () => { }, ]); }); + + it('should ignore hours in all day appointment dates when ignoreAllDayHours is true', () => { + expect(expandAllDayRegularPanel([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 5), + endDateUTC: Date.UTC(2020, 0, 10, 5), + }, { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 4), + endDateUTC: Date.UTC(2020, 0, 11, 5), + }, + ], { + startDayHour: 8, + viewOffsetMs: 0, + ignoreAllDayHours: true, + })).toEqual([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 8), + endDateUTC: Date.UTC(2020, 0, 11, 8), + }, { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 8), + endDateUTC: Date.UTC(2020, 0, 12, 8), + }, + ]); + }); + + it('should ignore hours for timeline all day appointment the same way as for week view', () => { + expect(expandAllDayRegularPanel([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 5), + endDateUTC: Date.UTC(2020, 0, 10, 17), + }, + ], { + startDayHour: 0, + viewOffsetMs: 0, + ignoreAllDayHours: true, + })).toEqual([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 0), + endDateUTC: Date.UTC(2020, 0, 11, 0), + }, + ]); + }); + + it('should ignore hours and keep calendar dates so view offset can shift them like timed appointments', () => { + expect(expandAllDayRegularPanel([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 20, 30), + endDateUTC: Date.UTC(2020, 0, 10, 23, 30), + }, { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 2), + endDateUTC: Date.UTC(2020, 0, 11, 2), + }, + ], { + startDayHour: 0, + viewOffsetMs: -735 * 60_000, + ignoreAllDayHours: true, + })).toEqual([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 0), + endDateUTC: Date.UTC(2020, 0, 11, 0), + }, { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 0), + endDateUTC: Date.UTC(2020, 0, 12, 0), + }, + ]); + }); + + it('should not compensate a full-day view offset on all day appointments', () => { + expect(expandAllDayRegularPanel([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 20, 30), + endDateUTC: Date.UTC(2020, 0, 10, 23, 30), + }, + ], { + startDayHour: 0, + viewOffsetMs: -1440 * 60_000, + ignoreAllDayHours: true, + })).toEqual([ + { + allDay: true, + startDateUTC: Date.UTC(2020, 0, 10, 0), + endDateUTC: Date.UTC(2020, 0, 11, 0), + }, + ]); + }); }); }); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts index 99c414167557..cf76bc3b07b7 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts @@ -72,13 +72,32 @@ export const expandAllDayAllDayPanel = >( - entities: T[], -): T[] => entities.map((entity) => { +interface ExpandAllDayRegularPanelOptions { + startDayHour: number; + viewOffsetMs: number; + ignoreAllDayHours: boolean; +} + +const expandAllDayRegularPanelEntity = >( + entity: T, + { startDayHour, ignoreAllDayHours }: ExpandAllDayRegularPanelOptions, +): T => { if (!entity.allDay) { return entity; } + if (ignoreAllDayHours) { + const startDayHourMs = startDayHour * toMs('hour'); + const startOfCalendarDay = new Date(entity.startDateUTC).setUTCHours(0, 0, 0, 0); + const endOfNextCalendarDay = new Date(entity.endDateUTC).setUTCHours(0, 0, 0, 0) + DAY_MS; + + return { + ...entity, + startDateUTC: startOfCalendarDay + startDayHourMs, + endDateUTC: endOfNextCalendarDay + startDayHourMs, + }; + } + const startDate = new Date(entity.startDateUTC); const endDate = new Date(entity.endDateUTC); endDate.setDate(endDate.getDate() + 1); @@ -93,4 +112,9 @@ export const expandAllDayRegularPanel = >( + entities: T[], + options: ExpandAllDayRegularPanelOptions, +): T[] => entities.map((entity) => expandAllDayRegularPanelEntity(entity, options));