diff --git a/packages/devextreme/js/__internal/scheduler/__tests__/workspace.base.test.ts b/packages/devextreme/js/__internal/scheduler/__tests__/workspace.base.test.ts index 03c0cad2e4dc..1ea57bd2cd9b 100644 --- a/packages/devextreme/js/__internal/scheduler/__tests__/workspace.base.test.ts +++ b/packages/devextreme/js/__internal/scheduler/__tests__/workspace.base.test.ts @@ -7,12 +7,10 @@ import { getResourceManagerMock } from '../__mock__/resource_manager.mock'; import SchedulerTimelineDay from '../workspaces/m_timeline_day'; import SchedulerTimelineMonth from '../workspaces/m_timeline_month'; import SchedulerTimelineWeek from '../workspaces/m_timeline_week'; -import SchedulerTimelineWorkWeek from '../workspaces/m_timeline_work_week'; import type SchedulerWorkSpace from '../workspaces/m_work_space'; import SchedulerWorkSpaceDay from '../workspaces/m_work_space_day'; import SchedulerWorkSpaceMonth from '../workspaces/m_work_space_month'; import SchedulerWorkSpaceWeek from '../workspaces/m_work_space_week'; -import SchedulerWorkSpaceWorkWeek from '../workspaces/m_work_space_work_week'; import { setupSchedulerTestEnvironment } from './__mock__/m_mock_scheduler'; jest.mock('@ts/core/m_devices', () => { @@ -67,11 +65,11 @@ const workSpaces: { }[] = [ { currentView: 'day', WorkSpace: SchedulerWorkSpaceDay }, { currentView: 'week', WorkSpace: SchedulerWorkSpaceWeek }, - { currentView: 'workWeek', WorkSpace: SchedulerWorkSpaceWorkWeek }, + { currentView: 'workWeek', WorkSpace: SchedulerWorkSpaceWeek }, { currentView: 'month', WorkSpace: SchedulerWorkSpaceMonth }, { currentView: 'timelineDay', WorkSpace: SchedulerTimelineDay }, { currentView: 'timelineWeek', WorkSpace: SchedulerTimelineWeek }, - { currentView: 'timelineWorkWeek', WorkSpace: SchedulerTimelineWorkWeek }, + { currentView: 'timelineWorkWeek', WorkSpace: SchedulerTimelineWeek }, { currentView: 'timelineMonth', WorkSpace: SchedulerTimelineMonth }, ]; @@ -210,7 +208,7 @@ describe('scheduler workspace skipped days support', () => { }); it('should use full week layout for work week when skippedDays override is empty', () => { - const { workspace } = createWorkspace(SchedulerWorkSpaceWorkWeek, 'workWeek', { + const { workspace } = createWorkspace(SchedulerWorkSpaceWeek, 'workWeek', { currentDate: new Date(2026, 3, 1), // Wednesday firstDayOfWeek: 0, // Sunday skippedDays: [], @@ -221,7 +219,7 @@ describe('scheduler workspace skipped days support', () => { }); it('should use custom skippedDays in work week runtime layout', () => { - const { workspace } = createWorkspace(SchedulerWorkSpaceWorkWeek, 'workWeek', { + const { workspace } = createWorkspace(SchedulerWorkSpaceWeek, 'workWeek', { currentDate: new Date(2026, 3, 1), // Wednesday firstDayOfWeek: 0, // Sunday skippedDays: [3], // Wednesday diff --git a/packages/devextreme/js/__internal/scheduler/header/m_utils.test.ts b/packages/devextreme/js/__internal/scheduler/header/m_utils.test.ts index 4d08bac989c5..9d74b10bcbaf 100644 --- a/packages/devextreme/js/__internal/scheduler/header/m_utils.test.ts +++ b/packages/devextreme/js/__internal/scheduler/header/m_utils.test.ts @@ -60,11 +60,11 @@ describe('day hiddenWeekDays support in header utils', () => { }); }); -describe('workWeek hiddenWeekDays support in header utils', () => { - it('should keep Mon-Fri caption for default skippedDays', () => { +describe('week hiddenWeekDays support in header utils', () => { + it('should keep Mon-Fri caption for weekend skippedDays', () => { expect(getCaptionInterval({ date: new Date(2026, 3, 8), // Wednesday - step: 'workWeek', + step: 'week', intervalCount: 1, skippedDays: [0, 6], firstDayOfWeek: 0, @@ -77,7 +77,7 @@ describe('workWeek hiddenWeekDays support in header utils', () => { it('should use full week caption when skippedDays override is empty', () => { expect(getCaptionInterval({ date: new Date(2026, 3, 8), // Wednesday - step: 'workWeek', + step: 'week', intervalCount: 1, skippedDays: [], firstDayOfWeek: 0, @@ -90,7 +90,7 @@ describe('workWeek hiddenWeekDays support in header utils', () => { it('should use first and last visible days for custom skippedDays', () => { expect(getCaptionInterval({ date: new Date(2026, 3, 8), // Wednesday - step: 'workWeek', + step: 'week', intervalCount: 1, skippedDays: [1, 2], firstDayOfWeek: 0, @@ -99,9 +99,6 @@ describe('workWeek hiddenWeekDays support in header utils', () => { endDate: new Date(2026, 3, 11, 23, 59, 59, 999), }); }); -}); - -describe('week hiddenWeekDays support in header utils', () => { it('should use first and last visible day for week caption', () => { expect(getCaptionInterval({ date: new Date(2026, 3, 8), // Wednesday diff --git a/packages/devextreme/js/__internal/scheduler/header/m_utils.ts b/packages/devextreme/js/__internal/scheduler/header/m_utils.ts index 32ba82f1f869..749132ec8bf9 100644 --- a/packages/devextreme/js/__internal/scheduler/header/m_utils.ts +++ b/packages/devextreme/js/__internal/scheduler/header/m_utils.ts @@ -97,8 +97,7 @@ const getIntervalStartDate = (options: IntervalOptions): Date => { ); case 'month': return getPeriodStart(date, step, false, firstDayOfWeek) as Date; - case 'week': - case 'workWeek': { + case 'week': { const weekStart = getPeriodStart(date, 'week', false, firstDayOfWeek) as Date; return getFirstVisibleDate(weekStart, skippedDays, nextDay); } @@ -120,7 +119,6 @@ const getPeriodEndDate = ( day: () => nextDay(currentPeriodStartDate), week: () => getDateAfterWeek(currentPeriodStartDate, firstDayOfWeek, skippedDays), month: () => nextMonth(currentPeriodStartDate), - workWeek: () => getDateAfterWeek(currentPeriodStartDate, firstDayOfWeek, skippedDays), agenda: () => nextAgendaStart(currentPeriodStartDate, agendaDuration), }; @@ -134,7 +132,7 @@ const getNextPeriodStartDate = ( ): Date => { let date = addMS(currentPeriodEndDate); - if (step === 'day' || step === 'week' || step === 'workWeek') { + if (step === 'day' || step === 'week') { date = getFirstVisibleDate(date, skippedDays, nextDay); } @@ -204,7 +202,6 @@ export const getNextIntervalDate = (options: IntervalOptions, direction: Directi direction, ); case 'week': - case 'workWeek': dayDuration = 7 * intervalCount; break; case 'agenda': @@ -342,11 +339,11 @@ export const getCaption = (options: IntervalOptions, isShort: boolean, customiza const STEP_MAP: Record = { day: 'day', week: 'week', - workWeek: 'workWeek', + workWeek: 'week', month: 'month', timelineDay: 'day', timelineWeek: 'week', - timelineWorkWeek: 'workWeek', + timelineWorkWeek: 'week', timelineMonth: 'month', agenda: 'agenda', } as const; diff --git a/packages/devextreme/js/__internal/scheduler/header/types.ts b/packages/devextreme/js/__internal/scheduler/header/types.ts index 7fdb106fa6be..3da8d5eac4d9 100644 --- a/packages/devextreme/js/__internal/scheduler/header/types.ts +++ b/packages/devextreme/js/__internal/scheduler/header/types.ts @@ -23,7 +23,7 @@ export interface HeaderOptions { _useShortDateFormat?: boolean; } -export type Step = 'day' | 'week' | 'workWeek' | 'month' | 'agenda'; +export type Step = 'day' | 'week' | 'month' | 'agenda'; export interface IntervalOptions { date: Date; diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index 66fa3dcb5f61..3eb3d5f87ab6 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -87,11 +87,9 @@ import SchedulerAgenda from './workspaces/m_agenda'; import SchedulerTimelineDay from './workspaces/m_timeline_day'; import SchedulerTimelineMonth from './workspaces/m_timeline_month'; import SchedulerTimelineWeek from './workspaces/m_timeline_week'; -import SchedulerTimelineWorkWeek from './workspaces/m_timeline_work_week'; import SchedulerWorkSpaceDay from './workspaces/m_work_space_day'; import SchedulerWorkSpaceMonth from './workspaces/m_work_space_month'; import SchedulerWorkSpaceWeek from './workspaces/m_work_space_week'; -import SchedulerWorkSpaceWorkWeek from './workspaces/m_work_space_work_week'; const toMs = dateUtils.dateToMilliseconds; @@ -115,7 +113,7 @@ const VIEWS_CONFIG = { renderingStrategy: 'vertical', }, workWeek: { - workSpace: SchedulerWorkSpaceWorkWeek, + workSpace: SchedulerWorkSpaceWeek, renderingStrategy: 'vertical', }, month: { @@ -131,7 +129,7 @@ const VIEWS_CONFIG = { renderingStrategy: 'horizontal', }, timelineWorkWeek: { - workSpace: SchedulerTimelineWorkWeek, + workSpace: SchedulerTimelineWeek, renderingStrategy: 'horizontal', }, timelineMonth: { diff --git a/packages/devextreme/js/__internal/scheduler/r1/utils/index.ts b/packages/devextreme/js/__internal/scheduler/r1/utils/index.ts index 744de1c99b8a..e1a2585159ad 100644 --- a/packages/devextreme/js/__internal/scheduler/r1/utils/index.ts +++ b/packages/devextreme/js/__internal/scheduler/r1/utils/index.ts @@ -35,9 +35,6 @@ import { getIntervalDuration, getTimePanelCellText, } from './week'; -import { - calculateStartViewDate as workWeekCalculateStartViewDate, -} from './work_week'; export { calculateCellIndex, @@ -104,10 +101,6 @@ export const weekUtils = { calculateViewStartDate: weekCalculateViewStartDate, }; -export const workWeekUtils = { - calculateStartViewDate: workWeekCalculateStartViewDate, -}; - export const monthUtils = { getViewStartByOptions, getCellText, diff --git a/packages/devextreme/js/__internal/scheduler/r1/utils/week.ts b/packages/devextreme/js/__internal/scheduler/r1/utils/week.ts index 96601f02c80a..599a4d213286 100644 --- a/packages/devextreme/js/__internal/scheduler/r1/utils/week.ts +++ b/packages/devextreme/js/__internal/scheduler/r1/utils/week.ts @@ -3,6 +3,7 @@ import dateUtils from '@js/core/utils/date'; import type { CalculateStartViewDate } from '../../types'; import { formatImplicitSchedulerTime } from '../../utils/global_formats'; +import { getFirstVisibleDate } from '../../utils/skipped_days'; import { getCalculatedFirstDayOfWeek, getValidCellDateForLocalTimeFormat, @@ -50,6 +51,7 @@ export const calculateStartViewDate: CalculateStartViewDate = ( startDate, intervalDuration, firstDayOfWeekOption, + skippedDays = [], ) => { const firstDayOfWeek = getCalculatedFirstDayOfWeek(firstDayOfWeekOption); const viewStart = getViewStartByOptions( @@ -59,7 +61,12 @@ export const calculateStartViewDate: CalculateStartViewDate = ( getValidStartDate(startDate, firstDayOfWeek), ); - const firstViewDate = dateUtils.getFirstWeekDate(viewStart, firstDayOfWeek); + const weekStartDate = dateUtils.getFirstWeekDate(viewStart, firstDayOfWeek); + const firstViewDate = getFirstVisibleDate( + weekStartDate, + skippedDays, + (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1), + ); return setOptionHour(firstViewDate, startDayHour); }; diff --git a/packages/devextreme/js/__internal/scheduler/r1/utils/work_week.ts b/packages/devextreme/js/__internal/scheduler/r1/utils/work_week.ts deleted file mode 100644 index 7067e4689238..000000000000 --- a/packages/devextreme/js/__internal/scheduler/r1/utils/work_week.ts +++ /dev/null @@ -1,29 +0,0 @@ -import dateUtils from '@js/core/utils/date'; - -import { getFirstVisibleDate } from '../../utils/skipped_days'; -import { getViewStartByOptions, setOptionHour } from './base'; -import { getValidStartDate } from './week'; - -export const calculateStartViewDate = ( - currentDate: Date, - startDayHour: number, - startDate: Date, - intervalDuration: number, - firstDayOfWeek: number | undefined, - skippedDays: number[] = [0, 6], -): Date => { - const viewStart = getViewStartByOptions( - startDate, - currentDate, - intervalDuration, - getValidStartDate(startDate, firstDayOfWeek), - ); - - const firstViewDate = getFirstVisibleDate( - dateUtils.getFirstWeekDate(viewStart, firstDayOfWeek), - skippedDays, - (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1), - ); - - return setOptionHour(firstViewDate, startDayHour); -}; diff --git a/packages/devextreme/js/__internal/scheduler/types.ts b/packages/devextreme/js/__internal/scheduler/types.ts index c6f84c390050..1abc50a69362 100644 --- a/packages/devextreme/js/__internal/scheduler/types.ts +++ b/packages/devextreme/js/__internal/scheduler/types.ts @@ -75,6 +75,7 @@ export type CalculateStartViewDate = ( startDate: Date, intervalCount: number, firstDayOfWeekOption?: number, + skippedDays?: number[], ) => Date; export interface ViewCellData { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts index 96851eb816b5..0d1a9eec32b4 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts @@ -4,12 +4,15 @@ import { VIEWS } from '../utils/options/constants_view'; import SchedulerTimeline from './m_timeline'; const TIMELINE_CLASS = 'dx-scheduler-timeline-week'; +const TIMELINE_WORK_WEEK_CLASS = 'dx-scheduler-timeline-work-week'; export default class SchedulerTimelineWeek extends SchedulerTimeline { - get type() { return VIEWS.TIMELINE_WEEK; } + get type(): string { + return this.option('type') ?? VIEWS.TIMELINE_WEEK; + } protected override getElementClass() { - return TIMELINE_CLASS; + return this.type === VIEWS.TIMELINE_WORK_WEEK ? TIMELINE_WORK_WEEK_CLASS : TIMELINE_CLASS; } protected override needRenderWeekHeader() { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_work_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_work_week.ts deleted file mode 100644 index 155d5868a52f..000000000000 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_work_week.ts +++ /dev/null @@ -1,18 +0,0 @@ -import registerComponent from '@js/core/component_registrator'; - -import { VIEWS } from '../utils/options/constants_view'; -import SchedulerTimelineWeek from './m_timeline_week'; - -const TIMELINE_CLASS = 'dx-scheduler-timeline-work-week'; - -class SchedulerTimelineWorkWeek extends SchedulerTimelineWeek { - get type() { return VIEWS.TIMELINE_WORK_WEEK; } - - protected override getElementClass() { - return TIMELINE_CLASS; - } -} - -registerComponent('dxSchedulerTimelineWorkWeek', SchedulerTimelineWorkWeek as any); - -export default SchedulerTimelineWorkWeek; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts index 17d913039329..d89814b209a0 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -207,6 +207,7 @@ type WorkspaceOptionsInternal = Omit & { startDayHour: number; endDayHour: number; skippedDays?: number[]; + type?: ViewType; }; class SchedulerWorkSpace extends Widget { private viewDataProviderValue: any; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_week.ts index e756a49ad902..62087a0b31e6 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_week.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_week.ts @@ -5,11 +5,14 @@ import { VIEWS } from '../utils/options/constants_view'; import SchedulerWorkSpaceVertical from './m_work_space_vertical'; const WEEK_CLASS = 'dx-scheduler-work-space-week'; +const WORK_WEEK_CLASS = 'dx-scheduler-work-space-work-week'; class SchedulerWorkSpaceWeek extends SchedulerWorkSpaceVertical { - get type() { return VIEWS.WEEK; } + get type(): string { + return this.option('type') ?? VIEWS.WEEK; + } protected override getElementClass() { - return WEEK_CLASS; + return this.type === VIEWS.WORK_WEEK ? WORK_WEEK_CLASS : WEEK_CLASS; } protected override calculateViewStartDate() { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_work_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_work_week.ts deleted file mode 100644 index 57c27f341df9..000000000000 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_work_week.ts +++ /dev/null @@ -1,17 +0,0 @@ -import registerComponent from '@js/core/component_registrator'; - -import { VIEWS } from '../utils/options/constants_view'; -import SchedulerWorkSpaceWeek from './m_work_space_week'; - -const WORK_WEEK_CLASS = 'dx-scheduler-work-space-work-week'; -class SchedulerWorkSpaceWorkWeek extends SchedulerWorkSpaceWeek { - get type() { return VIEWS.WORK_WEEK; } - - protected override getElementClass() { - return WORK_WEEK_CLASS; - } -} - -registerComponent('dxSchedulerWorkSpaceWorkWeek', SchedulerWorkSpaceWorkWeek as any); - -export default SchedulerWorkSpaceWorkWeek; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.test.ts b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.test.ts index ce69888eb7f7..c434fb023315 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.test.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.test.ts @@ -5,7 +5,6 @@ import { ViewDataGeneratorDay } from './m_view_data_generator_day'; import { ViewDataGeneratorMonth } from './m_view_data_generator_month'; import { ViewDataGeneratorTimelineMonth } from './m_view_data_generator_timeline_month'; import { ViewDataGeneratorWeek } from './m_view_data_generator_week'; -import { ViewDataGeneratorWorkWeek } from './m_view_data_generator_work_week'; describe('ViewDataGenerator hiddenWeekDays support', () => { describe('daysInInterval getter', () => { @@ -15,14 +14,14 @@ describe('ViewDataGenerator hiddenWeekDays support', () => { expect(gen.daysInInterval).toBe(6); }); - it('workWeek view: 5 with default skippedDays [0,6]', () => { - const gen = new ViewDataGeneratorWorkWeek('workWeek' as ViewType); + it('week view: 5 with skippedDays [0,6]', () => { + const gen = new ViewDataGeneratorWeek('week' as ViewType); gen.skippedDays = [0, 6]; expect(gen.daysInInterval).toBe(5); }); - it('workWeek view: 7 with empty skippedDays override', () => { - const gen = new ViewDataGeneratorWorkWeek('workWeek' as ViewType); + it('week view: 7 with empty skippedDays override', () => { + const gen = new ViewDataGeneratorWeek('week' as ViewType); gen.skippedDays = []; expect(gen.daysInInterval).toBe(7); }); @@ -99,33 +98,33 @@ describe('ViewDataGenerator hiddenWeekDays support', () => { expect(callGetVisibleDayOffset(gen, 0, 4, 0, 1)).toBe(3); }); - it('timelineWorkWeek with multiple cells in day uses day index', () => { - const timelineWorkWeekGen = new ViewDataGeneratorWorkWeek('timelineWorkWeek' as ViewType); - timelineWorkWeekGen.skippedDays = [0, 6]; + it('timelineWeek with hidden days and multiple cells in day uses day index', () => { + const timelineWeekGen = new ViewDataGeneratorWeek('timelineWeek' as ViewType); + timelineWeekGen.skippedDays = [0, 6]; - const timelineWorkWeek = timelineWorkWeekGen as unknown as ViewDataGeneratorWeek; + const timelineWeek = timelineWeekGen as unknown as ViewDataGeneratorWeek; // 2 cells per day, first visible week day is Monday (firstDayOfWeek=1) // Both cells of the first day must have the same offset. - expect(callGetVisibleDayOffset(timelineWorkWeek, 0, 0, 1, 2)).toBe(0); - expect(callGetVisibleDayOffset(timelineWorkWeek, 0, 1, 1, 2)).toBe(0); + expect(callGetVisibleDayOffset(timelineWeek, 0, 0, 1, 2)).toBe(0); + expect(callGetVisibleDayOffset(timelineWeek, 0, 1, 1, 2)).toBe(0); // The first cell of next visible day still has zero offset. - expect(callGetVisibleDayOffset(timelineWorkWeek, 0, 2, 1, 2)).toBe(0); + expect(callGetVisibleDayOffset(timelineWeek, 0, 2, 1, 2)).toBe(0); // After 5 visible days (10 cells), the next day jumps over weekend (+2 days). - expect(callGetVisibleDayOffset(timelineWorkWeek, 0, 10, 1, 2)).toBe(2); + expect(callGetVisibleDayOffset(timelineWeek, 0, 10, 1, 2)).toBe(2); }); - it('vertical workWeek layout uses column index as day index', () => { - const workWeekGen = new ViewDataGeneratorWorkWeek('workWeek' as ViewType); - workWeekGen.skippedDays = [0, 6]; + it('vertical week layout with hidden days uses column index as day index', () => { + const weekGen = new ViewDataGeneratorWeek('week' as ViewType); + weekGen.skippedDays = [0, 6]; - const verticalWorkWeek = workWeekGen as unknown as ViewDataGeneratorWeek; + const verticalWeek = weekGen as unknown as ViewDataGeneratorWeek; - expect(callGetVisibleDayOffset(verticalWorkWeek, 0, 0, 3, 24)).toBe(0); - expect(callGetVisibleDayOffset(verticalWorkWeek, 0, 1, 3, 24)).toBe(0); - expect(callGetVisibleDayOffset(verticalWorkWeek, 0, 2, 3, 24)).toBe(0); - expect(callGetVisibleDayOffset(verticalWorkWeek, 0, 3, 3, 24)).toBe(2); - expect(callGetVisibleDayOffset(verticalWorkWeek, 0, 4, 3, 24)).toBe(2); + expect(callGetVisibleDayOffset(verticalWeek, 0, 0, 3, 24)).toBe(0); + expect(callGetVisibleDayOffset(verticalWeek, 0, 1, 3, 24)).toBe(0); + expect(callGetVisibleDayOffset(verticalWeek, 0, 2, 3, 24)).toBe(0); + expect(callGetVisibleDayOffset(verticalWeek, 0, 3, 3, 24)).toBe(2); + expect(callGetVisibleDayOffset(verticalWeek, 0, 4, 3, 24)).toBe(2); }); }); @@ -209,9 +208,9 @@ describe('ViewDataGenerator hiddenWeekDays support', () => { }); }); - describe('WorkWeek hiddenWeekDays support', () => { + describe('Week hiddenWeekDays start date support', () => { it('uses week start when skippedDays override is empty', () => { - const gen = new ViewDataGeneratorWorkWeek('workWeek' as ViewType); + const gen = new ViewDataGeneratorWeek('week' as ViewType); gen.skippedDays = []; const startViewDate = gen.getStartViewDate({ @@ -226,9 +225,9 @@ describe('ViewDataGenerator hiddenWeekDays support', () => { expect(startViewDate.getDate()).toBe(29); }); - it('uses first visible day of week for custom skippedDays', () => { - const gen = new ViewDataGeneratorWorkWeek('workWeek' as ViewType); - gen.skippedDays = [1, 2]; + it('uses first visible day of week for hidden weekends', () => { + const gen = new ViewDataGeneratorWeek('week' as ViewType); + gen.skippedDays = [0, 6]; const startViewDate = gen.getStartViewDate({ currentDate: new Date(2026, 3, 1), // Wednesday @@ -238,12 +237,12 @@ describe('ViewDataGenerator hiddenWeekDays support', () => { firstDayOfWeek: 0, // Sunday }); - expect(startViewDate.getDay()).toBe(0); - expect(startViewDate.getDate()).toBe(29); + expect(startViewDate.getDay()).toBe(1); + expect(startViewDate.getDate()).toBe(30); }); it('keeps first visible column on Monday when startViewDate is already Monday', () => { - const gen = new ViewDataGeneratorWorkWeek('workWeek' as ViewType); + const gen = new ViewDataGeneratorWeek('week' as ViewType); gen.skippedDays = [0, 6]; const options = { @@ -256,7 +255,7 @@ describe('ViewDataGenerator hiddenWeekDays support', () => { intervalCount: 1, viewOffset: 0, currentDate: new Date(2026, 3, 1), - viewType: 'workWeek' as ViewType, + viewType: 'week' as ViewType, }; const date = gen.getDateByCellIndices(options, 0, 0); diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.ts index 9c5161a4060a..5890ad93e797 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator.ts @@ -53,13 +53,6 @@ export class ViewDataGenerator { : 1; } - public isWorkWeekView(): boolean { - return [ - VIEWS.WORK_WEEK, - VIEWS.TIMELINE_WORK_WEEK, - ].includes(this.viewType); - } - protected usesMonthDayLayout(): boolean { return false; } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator_week.ts index eb69dc885954..3bd52dc7772b 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator_week.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator_week.ts @@ -13,6 +13,16 @@ export class ViewDataGeneratorWeek extends ViewDataGenerator { options.startDate, this._getIntervalDuration(options.intervalCount), this.getFirstDayOfWeek(options.firstDayOfWeek), + options.skippedDays ?? this.skippedDays, ); } + + protected override getSkippedDaysAnchorDay( + firstDayOfWeekOption: number | undefined, + startViewDate: Date, + ): number { + return this.skippedDays.length > 0 + ? startViewDate.getDay() + : this.getFirstDayOfWeek(firstDayOfWeekOption) ?? 0; + } } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator_work_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator_work_week.ts deleted file mode 100644 index 0be766ea5383..000000000000 --- a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/m_view_data_generator_work_week.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { workWeekUtils } from '../../r1/utils/index'; -import { ViewDataGeneratorWeek } from './m_view_data_generator_week'; - -export class ViewDataGeneratorWorkWeek extends ViewDataGeneratorWeek { - public skippedDays: number[] = [0, 6]; - - protected override calculateStartViewDate(options: any): Date { - return workWeekUtils.calculateStartViewDate( - options.currentDate, - options.startDayHour, - options.startDate, - this._getIntervalDuration(options.intervalCount), - this.getFirstDayOfWeek(options.firstDayOfWeek), - options.skippedDays ?? this.skippedDays, - ); - } - - // eslint-disable-next-line class-methods-use-this - public override getFirstDayOfWeek(firstDayOfWeekOption: number | undefined): number { - return firstDayOfWeekOption ?? 0; - } - - protected override getSkippedDaysAnchorDay( - firstDayOfWeekOption: number | undefined, - startViewDate: Date, - ): number { - return this.skippedDays.length > 0 - ? startViewDate.getDay() - : this.getFirstDayOfWeek(firstDayOfWeekOption); - } -} diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/utils/view_provider_utils.ts b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/utils/view_provider_utils.ts index 0fa21be40834..df1be4972e6a 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/view_model/utils/view_provider_utils.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/view_model/utils/view_provider_utils.ts @@ -1,28 +1,30 @@ import type { ViewType } from '../../../types'; -import { VIEWS } from '../../../utils/options/constants_view'; +import { DEFAULT_VIEW_OPTIONS, VIEWS } from '../../../utils/options/constants_view'; import { ViewDataGenerator } from '../m_view_data_generator'; import { ViewDataGeneratorDay } from '../m_view_data_generator_day'; import { ViewDataGeneratorMonth } from '../m_view_data_generator_month'; import { ViewDataGeneratorTimelineMonth } from '../m_view_data_generator_timeline_month'; import { ViewDataGeneratorWeek } from '../m_view_data_generator_week'; -import { ViewDataGeneratorWorkWeek } from '../m_view_data_generator_work_week'; + +type ViewDataGeneratorConstructor = new (viewType: ViewType) => ViewDataGenerator; + +const VIEW_DATA_GENERATOR_BY_VIEW_TYPE: Partial> = { + [VIEWS.MONTH]: ViewDataGeneratorMonth, + [VIEWS.TIMELINE_MONTH]: ViewDataGeneratorTimelineMonth, + [VIEWS.DAY]: ViewDataGeneratorDay, + [VIEWS.TIMELINE_DAY]: ViewDataGeneratorDay, + [VIEWS.WEEK]: ViewDataGeneratorWeek, + [VIEWS.TIMELINE_WEEK]: ViewDataGeneratorWeek, + [VIEWS.WORK_WEEK]: ViewDataGeneratorWeek, + [VIEWS.TIMELINE_WORK_WEEK]: ViewDataGeneratorWeek, +}; export const getViewDataGeneratorByViewType = (viewType: ViewType): ViewDataGenerator => { - switch (viewType) { - case VIEWS.MONTH: - return new ViewDataGeneratorMonth(viewType); - case VIEWS.TIMELINE_MONTH: - return new ViewDataGeneratorTimelineMonth(viewType); - case VIEWS.DAY: - case VIEWS.TIMELINE_DAY: - return new ViewDataGeneratorDay(viewType); - case VIEWS.WEEK: - case VIEWS.TIMELINE_WEEK: - return new ViewDataGeneratorWeek(viewType); - case VIEWS.WORK_WEEK: - case VIEWS.TIMELINE_WORK_WEEK: - return new ViewDataGeneratorWorkWeek(viewType); - default: - return new ViewDataGenerator(viewType); - } + const Generator = VIEW_DATA_GENERATOR_BY_VIEW_TYPE[viewType] ?? ViewDataGenerator; + const generator = new Generator(viewType); + const defaultViewOptions = DEFAULT_VIEW_OPTIONS[viewType]; + + generator.skippedDays = defaultViewOptions ? defaultViewOptions.skippedDays : []; + + return generator; }; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/currentTimeIndicator.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/currentTimeIndicator.tests.js index 645eace9fbc5..711f28e7b936 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/currentTimeIndicator.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/currentTimeIndicator.tests.js @@ -21,7 +21,6 @@ import '__internal/scheduler/workspaces/m_work_space_day'; import '__internal/scheduler/workspaces/m_work_space_week'; import '__internal/scheduler/workspaces/m_timeline_day'; import '__internal/scheduler/workspaces/m_timeline_week'; -import '__internal/scheduler/workspaces/m_timeline_work_week'; import '__internal/scheduler/workspaces/m_timeline_month'; QUnit.testStart(function() { diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.timeline.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.timeline.tests.js index e84213ba1619..af442ecb8401 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.timeline.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.timeline.tests.js @@ -76,7 +76,7 @@ QUnit.test('Scheduler should have a right timeline work space', async function(a scheduler.instance.option('currentView', 'timelineWorkWeek'); await waitAsync(0); - assert.ok(scheduler.workSpace.getWorkSpace().dxSchedulerTimelineWorkWeek('instance'), 'Work space is timelineWorkWeek after change option '); + assert.strictEqual(scheduler.workSpace.getWorkSpace().dxSchedulerTimelineWeek('instance').option('type'), 'timelineWorkWeek', 'Work space is timelineWorkWeek after change option '); scheduler.instance.option('currentView', 'timelineMonth'); await waitAsync(0); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.markup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.markup.tests.js index 746cb1d679f7..622ca406c49f 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.markup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.markup.tests.js @@ -2,7 +2,6 @@ import $ from 'jquery'; import SchedulerTimeline from '__internal/scheduler/workspaces/m_timeline'; import SchedulerTimelineDay from '__internal/scheduler/workspaces/m_timeline_day'; import SchedulerTimelineWeek from '__internal/scheduler/workspaces/m_timeline_week'; -import SchedulerTimelineWorkWeek from '__internal/scheduler/workspaces/m_timeline_work_week'; import SchedulerTimelineMonth from '__internal/scheduler/workspaces/m_timeline_month'; import dataUtils from 'core/element_data'; import dateLocalization from 'common/core/localization/date'; @@ -790,21 +789,23 @@ QUnit.module('TimelineWeek with horizontal grouping markup', timelineWeekModuleC let timelineWorkWeekModuleConfig = { beforeEach: function() { - this.instance = $('#scheduler-timeline').dxSchedulerTimelineWorkWeek({ + this.instance = $('#scheduler-timeline').dxSchedulerTimelineWeek({ + type: 'timelineWorkWeek', + skippedDays: [0, 6], getResourceManager: getEmptyResourceManager, - }).dxSchedulerTimelineWorkWeek('instance'); + }).dxSchedulerTimelineWeek('instance'); } }; QUnit.module('TimelineWorkWeek markup', timelineWorkWeekModuleConfig, () => { QUnit.test('Scheduler timeline work week should be initialized', async function(assert) { - assert.ok(this.instance instanceof SchedulerTimelineWorkWeek, 'dxSchedulerTimeLineWorkWeek was initialized'); + assert.ok(this.instance instanceof SchedulerTimelineWeek, 'timelineWorkWeek uses SchedulerTimelineWeek'); }); QUnit.test('Scheduler timeline work week should have a right css class', async function(assert) { const $element = this.instance.$element(); - assert.ok($element.hasClass('dx-scheduler-timeline'), 'dxSchedulerTimelineWorkWeek has \'dx-scheduler-timeline\' css class'); - assert.ok($element.hasClass('dx-scheduler-timeline-work-week'), 'dxSchedulerTimelineWorkWeek has \'dx-scheduler-timeline-work-week\' css class'); + assert.ok($element.hasClass('dx-scheduler-timeline'), 'timelineWorkWeek has \'dx-scheduler-timeline\' css class'); + assert.ok($element.hasClass('dx-scheduler-timeline-work-week'), 'timelineWorkWeek has \'dx-scheduler-timeline-work-week\' css class'); }); QUnit.test('Scheduler timeline work week view should have right cell & row count', async function(assert) { @@ -860,10 +861,12 @@ QUnit.module('TimelineWorkWeek markup', timelineWorkWeekModuleConfig, () => { timelineWorkWeekModuleConfig = { beforeEach: function() { - this.instance = $('#scheduler-timeline').dxSchedulerTimelineWorkWeek({ + this.instance = $('#scheduler-timeline').dxSchedulerTimelineWeek({ + type: 'timelineWorkWeek', + skippedDays: [0, 6], currentDate: new Date(2015, 9, 16), getResourceManager: getEmptyResourceManager, - }).dxSchedulerTimelineWorkWeek('instance'); + }).dxSchedulerTimelineWeek('instance'); } }; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.tests.js index c1fee638ddf0..798d29578cf8 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.tests.js @@ -9,7 +9,6 @@ import '__internal/scheduler/workspaces/m_timeline'; import '__internal/scheduler/workspaces/m_timeline_day'; import '__internal/scheduler/workspaces/m_timeline_month'; import '__internal/scheduler/workspaces/m_timeline_week'; -import '__internal/scheduler/workspaces/m_timeline_work_week'; import keyboardMock from '../../helpers/keyboardMock.js'; import pointerMock from '../../helpers/pointerMock.js'; import { @@ -691,10 +690,12 @@ QUnit.module('Mouse Interaction', () => { QUnit.module('TimelineWorkWeek with intervalCount', { beforeEach: function() { - this.instance = $('#scheduler-timeline').dxSchedulerTimelineWorkWeek({ + this.instance = $('#scheduler-timeline').dxSchedulerTimelineWeek({ + type: 'timelineWorkWeek', + skippedDays: [0, 6], currentDate: new Date(2015, 9, 16), getResourceManager: getEmptyResourceManager, - }).dxSchedulerTimelineWorkWeek('instance'); + }).dxSchedulerTimelineWeek('instance'); } }); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.markup-1.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.markup-1.tests.js index 70d5ba7d38e8..8183086e3087 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.markup-1.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.markup-1.tests.js @@ -586,9 +586,11 @@ QUnit.module('Workspace Week markup with vertical grouping', weekWithGroupingMod const workWeekModuleConfig = { beforeEach: function() { - this.instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWorkWeek({ + this.instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWeek({ + type: 'workWeek', + skippedDays: [0, 6], getResourceManager: getEmptyResourceManager, - }).dxSchedulerWorkSpaceWorkWeek('instance'); + }).dxSchedulerWorkSpaceWeek('instance'); } }; @@ -596,7 +598,7 @@ QUnit.module('Workspace Work Week markup', workWeekModuleConfig, () => { QUnit.test('Scheduler workspace work week should have a right css class', async function(assert) { const $element = this.instance.$element(); - assert.ok($element.hasClass('dx-scheduler-work-space-work-week'), 'dxSchedulerWorkSpaceWorkWeek has \'dx-scheduler-workspace-work-week\' css class'); + assert.ok($element.hasClass('dx-scheduler-work-space-work-week'), 'workWeek has \'dx-scheduler-workspace-work-week\' css class'); }); QUnit.test('Scheduler all day panel should contain one row & 5 cells', async function(assert) { @@ -682,10 +684,12 @@ QUnit.module('Workspace Work Week markup', workWeekModuleConfig, () => { }); QUnit.test('Scheduler workspace work week view should be correct with any first day of week', async function(assert) { - const instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWorkWeek({ + const instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWeek({ + type: 'workWeek', + skippedDays: [0, 6], firstDayOfWeek: 2, currentDate: new Date(2015, 1, 4) - }).dxSchedulerWorkSpaceWorkWeek('instance'); + }).dxSchedulerWorkSpaceWeek('instance'); const $element = instance.$element(); @@ -710,10 +714,12 @@ QUnit.module('Workspace Work Week markup', workWeekModuleConfig, () => { }); QUnit.test('Scheduler workspace work week view should be correct with any first day of week, if currentDate is Sunday', async function(assert) { - const instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWorkWeek({ + const instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWeek({ + type: 'workWeek', + skippedDays: [0, 6], currentDate: new Date(2016, 0, 10), firstDayOfWeek: 3 - }).dxSchedulerWorkSpaceWorkWeek('instance'); + }).dxSchedulerWorkSpaceWeek('instance'); const $element = instance.$element(); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.navigation.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.navigation.tests.js index e81889df6bfd..d8a97c4c6ee8 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.navigation.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.navigation.tests.js @@ -5,7 +5,7 @@ import $ from 'jquery'; import '__internal/scheduler/workspaces/m_work_space_day'; import '__internal/scheduler/workspaces/m_work_space_month'; -import '__internal/scheduler/workspaces/m_work_space_work_week'; +import '__internal/scheduler/workspaces/m_work_space_week'; import keyboardMock from '../../helpers/keyboardMock.js'; import memoryLeaksHelper from '../../helpers/memoryLeaksHelper.js'; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.week.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.week.tests.js index 59b8c3390b21..24a4e1fe43a8 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.week.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.week.tests.js @@ -4,7 +4,6 @@ import 'fluent_blue_light.css!'; import $ from 'jquery'; import '__internal/scheduler/workspaces/m_work_space_week'; -import '__internal/scheduler/workspaces/m_work_space_work_week'; import { applyWorkspaceGroups, @@ -611,9 +610,11 @@ module('Work Space Week', () => { module('Work Space Work Week', () => { module('Default', { beforeEach: function() { - this.instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWorkWeek({ + this.instance = $('#scheduler-work-space').dxSchedulerWorkSpaceWeek({ + type: 'workWeek', + skippedDays: [0, 6], getResourceManager: getEmptyResourceManager, - }).dxSchedulerWorkSpaceWorkWeek('instance'); + }).dxSchedulerWorkSpaceWeek('instance'); } }, () => { skip('Work space should find cell coordinates by date', async function(assert) { @@ -670,11 +671,13 @@ module('Work Space Work Week', () => { beforeEach: function() { this.createInstance = function(options) { this.instance = $('#scheduler-work-space') - .dxSchedulerWorkSpaceWorkWeek({ + .dxSchedulerWorkSpaceWeek({ + type: 'workWeek', + skippedDays: [0, 6], getResourceManager: getEmptyResourceManager, ...options, }) - .dxSchedulerWorkSpaceWorkWeek('instance'); + .dxSchedulerWorkSpaceWeek('instance'); }; } }, () => {