Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
0016a32
Scheduler — Add hiddenDays option to hide arbitrary days of the week
aleksei-semikozov Apr 7, 2026
2467600
Scheduler — Rename hiddenDays option to hiddenWeekDays per spec
aleksei-semikozov Apr 8, 2026
fbeace8
Scheduler — Add hiddenWeekDays to scheduler.d.ts source for ts-bundle…
aleksei-semikozov Apr 8, 2026
18943b8
Revert "Scheduler — Add hiddenWeekDays to scheduler.d.ts source for t…
sjbur Apr 8, 2026
c385706
Revert "Scheduler — Rename hiddenDays option to hiddenWeekDays per spec"
sjbur Apr 8, 2026
7cadb02
feat: rename hiddenDays to hiddenWeekDays and fix .d.ts
sjbur Apr 8, 2026
bbb309c
Merge branch '26_1' into feature/scheduler-hidden-days-impl-26_1
sjbur Apr 8, 2026
97f1fe8
feat: add storybook
sjbur Apr 8, 2026
4904ffa
refactor: fix typing
sjbur Apr 8, 2026
a4b0767
refactor: fix typing
sjbur Apr 8, 2026
f4ac369
feat: create helper for skipped days
sjbur Apr 8, 2026
91d780d
fix: fix calculating hiddenDays for timeline
sjbur Apr 8, 2026
b1263af
fix: fix hiddenDays for timelineMonth
sjbur Apr 8, 2026
2a11d14
refactor: optimize ts
sjbur Apr 8, 2026
19f3964
fix: fix bug for view_generator for workWeek
sjbur Apr 9, 2026
d414219
fix: fix test
sjbur Apr 9, 2026
2ab9e9b
refactor: remove useless typing
sjbur Apr 9, 2026
d9cedc5
fix: fix hiddenWeekDays for workWeek
sjbur Apr 9, 2026
da7160f
refactor: revert SkippedDaysAnchorKind
sjbur Apr 9, 2026
1bcb103
refactor: optimize
sjbur Apr 9, 2026
2b82fa5
feat: allow hiddenWeekDays for agenda
sjbur Apr 9, 2026
9c71b48
refactor: optimize
sjbur Apr 9, 2026
e32349a
refactor: optimize
sjbur Apr 9, 2026
b341ca6
feat: create type WeekdayIndex for skippedDays
sjbur Apr 9, 2026
6a2a314
feat: update agenda and header logic to support hiddenWeekDays
sjbur Apr 10, 2026
9c81b76
feat: change agenda logic to show only calendar dates in interval min…
sjbur Apr 10, 2026
e30a7bd
fix: fix anchor day for workWeek
sjbur Apr 10, 2026
54283e7
feat: remove WeekDayIndex interface because it requires too much main…
sjbur Apr 10, 2026
2ccc554
fix: fix tests
sjbur Apr 10, 2026
faf52d4
test: update snapshot for santiago timezone for workWeek
sjbur Apr 10, 2026
c1b4969
test: fix test
sjbur Apr 10, 2026
1fd1356
feat: update W1029 error text
sjbur Apr 13, 2026
f58d384
refactor: remove weekends logic from workspace
sjbur Apr 13, 2026
433c33f
fix: fix defaults for skippedDays in workWeek
sjbur Apr 13, 2026
418467c
fix: undo default value for skipWeekDays
sjbur Apr 13, 2026
11f6b4f
fix: fix column rendering for workWeek
sjbur Apr 13, 2026
3c255b3
fix: fix caption in navigator for week view
sjbur Apr 13, 2026
5e87ccc
test: optimize tests
sjbur Apr 13, 2026
862fffe
refactor: undo typing
sjbur Apr 13, 2026
33e2a6b
test: add tests for work week layout with skippedDays scenarios
sjbur Apr 13, 2026
8a9989c
feat: make global hiddenWeekDays affect timelineWorkWeek and workweek
sjbur Apr 13, 2026
daa6e6c
fix: fix test
sjbur Apr 13, 2026
9d82f1c
fix: remove infinite loop risk from util functions
sjbur Apr 14, 2026
3950716
Apply suggestion from @arman-boyakhchyan
sjbur Apr 15, 2026
60b6e24
feat: update .d.ts for DayOfWeek type
sjbur Apr 15, 2026
00ee28b
fix: fix singlequote error
sjbur Apr 15, 2026
dd3a8ab
refactor: change visibility of getVisibleDayOffset method to private
sjbur Apr 15, 2026
47e7828
refactor: rename isSkippedDate to isDateSkipped
sjbur Apr 15, 2026
3c408f6
refactor: simplify date increment logic using getFirstVisibleDate uti…
sjbur Apr 15, 2026
8ccbb06
refactor: consolidate date handling for week and workWeek steps
sjbur Apr 15, 2026
5886172
refactor: unify date handling functions for week and workWeek calcula…
sjbur Apr 15, 2026
0f5a329
refactor: update getSkippedDaysCount parameter order for consistency …
sjbur Apr 15, 2026
a7c1825
refactor: streamline daysInInterval calculation for improved readability
sjbur Apr 15, 2026
fd13c8a
test: fix test
sjbur Apr 15, 2026
1b666f2
feat: add support for day and timelineday
sjbur Apr 15, 2026
1ed0d64
fix: fix tests
sjbur Apr 15, 2026
7313053
refactor: unify week and workWeek date handling in getIntervalStartDa…
sjbur Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { Meta, StoryObj } from "@storybook/react-webpack5";
import dxScheduler from "devextreme/ui/scheduler";
import { wrapDxWithReact } from "../utils";
import { data, resources } from "./data";

const Scheduler = wrapDxWithReact(dxScheduler);

const viewNames = ['day', 'week', 'workWeek', 'month', 'agenda', 'timelineDay', 'timelineWeek', 'timelineWorkWeek', 'timelineMonth'];

const meta: Meta<typeof Scheduler> = {
title: 'Components/Scheduler/HiddenWeekDays',
component: Scheduler,
parameters: { layout: 'padded' },
};

export default meta;

type Story = StoryObj<typeof Scheduler>;

export const Overview: Story = {
args: {
height: 600,
views: viewNames,
currentView: 'week',
currentDate: new Date(2021, 3, 26),
firstDayOfWeek: 0,
startDayHour: 9,
endDayHour: 22,
dataSource: data,
resources,
hiddenWeekDays: [],
},
argTypes: {
height: { control: 'number' },
views: { control: 'object' },
hiddenWeekDays: { control: 'object' },
currentView: { control: 'select', options: viewNames },
},
};
28 changes: 24 additions & 4 deletions packages/devextreme-angular/src/ui/scheduler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {

import type dxSortable from 'devextreme/ui/sortable';
import type dxDraggable from 'devextreme/ui/draggable';
import type { default as dxScheduler, AllDayPanelMode, ViewType, dxSchedulerAppointment, AppointmentFormProperties, CellAppointmentsLimit, AppointmentAddedEvent, AppointmentAddingEvent, AppointmentClickEvent, AppointmentContextMenuEvent, AppointmentDblClickEvent, AppointmentDeletedEvent, AppointmentDeletingEvent, AppointmentFormOpeningEvent, AppointmentRenderedEvent, AppointmentTooltipShowingEvent, AppointmentUpdatedEvent, AppointmentUpdatingEvent, CellClickEvent, CellContextMenuEvent, ContentReadyEvent, DisposingEvent, InitializedEvent, OptionChangedEvent, RecurrenceEditMode, dxSchedulerScrolling, SnapToCellsMode, dxSchedulerToolbar } from 'devextreme/ui/scheduler';
import type { default as dxScheduler, AllDayPanelMode, ViewType, dxSchedulerAppointment, AppointmentFormProperties, DayOfWeek, CellAppointmentsLimit, AppointmentAddedEvent, AppointmentAddingEvent, AppointmentClickEvent, AppointmentContextMenuEvent, AppointmentDblClickEvent, AppointmentDeletedEvent, AppointmentDeletingEvent, AppointmentFormOpeningEvent, AppointmentRenderedEvent, AppointmentTooltipShowingEvent, AppointmentUpdatedEvent, AppointmentUpdatingEvent, CellClickEvent, CellContextMenuEvent, ContentReadyEvent, DisposingEvent, InitializedEvent, OptionChangedEvent, RecurrenceEditMode, dxSchedulerScrolling, SnapToCellsMode, dxSchedulerToolbar } from 'devextreme/ui/scheduler';
import type { event } from 'devextreme/events/events.types';
import type { default as DataSource, DataSourceOptions } from 'devextreme/data/data_source';
import type { Store } from 'devextreme/data/store';
Expand Down Expand Up @@ -515,6 +515,16 @@ export class DxSchedulerComponent extends DxComponent implements OnDestroy, OnCh
}



@Input()
get hiddenWeekDays(): Array<DayOfWeek> {
return this._getOption('hiddenWeekDays');
}
set hiddenWeekDays(value: Array<DayOfWeek>) {
this._setOption('hiddenWeekDays', value);
}


/**
* [descr:WidgetOptions.hint]

Expand Down Expand Up @@ -894,10 +904,10 @@ export class DxSchedulerComponent extends DxComponent implements OnDestroy, OnCh

*/
@Input()
get views(): Array<Record<string, any> | string> | { agendaDuration?: number, allDayPanelMode?: AllDayPanelMode, appointmentCollectorTemplate?: any, appointmentTemplate?: any, appointmentTooltipTemplate?: any, cellDuration?: number, dataCellTemplate?: any, dateCellTemplate?: any, endDayHour?: number, firstDayOfWeek?: FirstDayOfWeek | undefined, groupByDate?: boolean, groupOrientation?: Orientation, groups?: Array<string>, intervalCount?: number, maxAppointmentsPerCell?: CellAppointmentsLimit | number, name?: string | undefined, offset?: number, resourceCellTemplate?: any, scrolling?: dxSchedulerScrolling, snapToCellsMode?: SnapToCellsMode, startDate?: Date | number | string | undefined, startDayHour?: number, timeCellTemplate?: any, type?: undefined | ViewType }[] {
get views(): Array<Record<string, any> | string> | { agendaDuration?: number, allDayPanelMode?: AllDayPanelMode, appointmentCollectorTemplate?: any, appointmentTemplate?: any, appointmentTooltipTemplate?: any, cellDuration?: number, dataCellTemplate?: any, dateCellTemplate?: any, endDayHour?: number, firstDayOfWeek?: FirstDayOfWeek | undefined, groupByDate?: boolean, groupOrientation?: Orientation, groups?: Array<string>, hiddenWeekDays?: Array<DayOfWeek>, intervalCount?: number, maxAppointmentsPerCell?: CellAppointmentsLimit | number, name?: string | undefined, offset?: number, resourceCellTemplate?: any, scrolling?: dxSchedulerScrolling, snapToCellsMode?: SnapToCellsMode, startDate?: Date | number | string | undefined, startDayHour?: number, timeCellTemplate?: any, type?: undefined | ViewType }[] {
return this._getOption('views');
}
set views(value: Array<Record<string, any> | string> | { agendaDuration?: number, allDayPanelMode?: AllDayPanelMode, appointmentCollectorTemplate?: any, appointmentTemplate?: any, appointmentTooltipTemplate?: any, cellDuration?: number, dataCellTemplate?: any, dateCellTemplate?: any, endDayHour?: number, firstDayOfWeek?: FirstDayOfWeek | undefined, groupByDate?: boolean, groupOrientation?: Orientation, groups?: Array<string>, intervalCount?: number, maxAppointmentsPerCell?: CellAppointmentsLimit | number, name?: string | undefined, offset?: number, resourceCellTemplate?: any, scrolling?: dxSchedulerScrolling, snapToCellsMode?: SnapToCellsMode, startDate?: Date | number | string | undefined, startDayHour?: number, timeCellTemplate?: any, type?: undefined | ViewType }[]) {
set views(value: Array<Record<string, any> | string> | { agendaDuration?: number, allDayPanelMode?: AllDayPanelMode, appointmentCollectorTemplate?: any, appointmentTemplate?: any, appointmentTooltipTemplate?: any, cellDuration?: number, dataCellTemplate?: any, dateCellTemplate?: any, endDayHour?: number, firstDayOfWeek?: FirstDayOfWeek | undefined, groupByDate?: boolean, groupOrientation?: Orientation, groups?: Array<string>, hiddenWeekDays?: Array<DayOfWeek>, intervalCount?: number, maxAppointmentsPerCell?: CellAppointmentsLimit | number, name?: string | undefined, offset?: number, resourceCellTemplate?: any, scrolling?: dxSchedulerScrolling, snapToCellsMode?: SnapToCellsMode, startDate?: Date | number | string | undefined, startDayHour?: number, timeCellTemplate?: any, type?: undefined | ViewType }[]) {
this._setOption('views', value);
}

Expand Down Expand Up @@ -1274,6 +1284,13 @@ export class DxSchedulerComponent extends DxComponent implements OnDestroy, OnCh
*/
@Output() heightChange: EventEmitter<number | string | undefined>;

/**

* This member supports the internal infrastructure and is not intended to be used directly from your code.

*/
@Output() hiddenWeekDaysChange: EventEmitter<Array<DayOfWeek>>;

/**

* This member supports the internal infrastructure and is not intended to be used directly from your code.
Expand Down Expand Up @@ -1482,7 +1499,7 @@ export class DxSchedulerComponent extends DxComponent implements OnDestroy, OnCh
* This member supports the internal infrastructure and is not intended to be used directly from your code.

*/
@Output() viewsChange: EventEmitter<Array<Record<string, any> | string> | { agendaDuration?: number, allDayPanelMode?: AllDayPanelMode, appointmentCollectorTemplate?: any, appointmentTemplate?: any, appointmentTooltipTemplate?: any, cellDuration?: number, dataCellTemplate?: any, dateCellTemplate?: any, endDayHour?: number, firstDayOfWeek?: FirstDayOfWeek | undefined, groupByDate?: boolean, groupOrientation?: Orientation, groups?: Array<string>, intervalCount?: number, maxAppointmentsPerCell?: CellAppointmentsLimit | number, name?: string | undefined, offset?: number, resourceCellTemplate?: any, scrolling?: dxSchedulerScrolling, snapToCellsMode?: SnapToCellsMode, startDate?: Date | number | string | undefined, startDayHour?: number, timeCellTemplate?: any, type?: undefined | ViewType }[]>;
@Output() viewsChange: EventEmitter<Array<Record<string, any> | string> | { agendaDuration?: number, allDayPanelMode?: AllDayPanelMode, appointmentCollectorTemplate?: any, appointmentTemplate?: any, appointmentTooltipTemplate?: any, cellDuration?: number, dataCellTemplate?: any, dateCellTemplate?: any, endDayHour?: number, firstDayOfWeek?: FirstDayOfWeek | undefined, groupByDate?: boolean, groupOrientation?: Orientation, groups?: Array<string>, hiddenWeekDays?: Array<DayOfWeek>, intervalCount?: number, maxAppointmentsPerCell?: CellAppointmentsLimit | number, name?: string | undefined, offset?: number, resourceCellTemplate?: any, scrolling?: dxSchedulerScrolling, snapToCellsMode?: SnapToCellsMode, startDate?: Date | number | string | undefined, startDayHour?: number, timeCellTemplate?: any, type?: undefined | ViewType }[]>;

/**

Expand Down Expand Up @@ -1558,6 +1575,7 @@ export class DxSchedulerComponent extends DxComponent implements OnDestroy, OnCh
{ emit: 'groupByDateChange' },
{ emit: 'groupsChange' },
{ emit: 'heightChange' },
{ emit: 'hiddenWeekDaysChange' },
{ emit: 'hintChange' },
{ emit: 'indicatorUpdateIntervalChange' },
{ emit: 'maxChange' },
Expand Down Expand Up @@ -1610,6 +1628,7 @@ export class DxSchedulerComponent extends DxComponent implements OnDestroy, OnCh
super.ngOnChanges(changes);
this.setupChanges('dataSource', changes);
this.setupChanges('groups', changes);
this.setupChanges('hiddenWeekDays', changes);
this.setupChanges('resources', changes);
this.setupChanges('selectedCellData', changes);
this.setupChanges('views', changes);
Expand All @@ -1624,6 +1643,7 @@ export class DxSchedulerComponent extends DxComponent implements OnDestroy, OnCh
ngDoCheck() {
this._idh.doCheck('dataSource');
this._idh.doCheck('groups');
this._idh.doCheck('hiddenWeekDays');
this._idh.doCheck('resources');
this._idh.doCheck('selectedCellData');
this._idh.doCheck('views');
Expand Down
10 changes: 9 additions & 1 deletion packages/devextreme-angular/src/ui/scheduler/nested/view-dxi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {



import type { AllDayPanelMode, CellAppointmentsLimit, dxSchedulerScrolling, SnapToCellsMode, ViewType } from 'devextreme/ui/scheduler';
import type { AllDayPanelMode, DayOfWeek, CellAppointmentsLimit, dxSchedulerScrolling, SnapToCellsMode, ViewType } from 'devextreme/ui/scheduler';
import type { FirstDayOfWeek, Orientation } from 'devextreme/common';

import {
Expand Down Expand Up @@ -142,6 +142,14 @@ export class DxiSchedulerViewComponent extends CollectionNestedOption {
this._setOption('groups', value);
}

@Input()
get hiddenWeekDays(): Array<DayOfWeek> {
return this._getOption('hiddenWeekDays');
}
set hiddenWeekDays(value: Array<DayOfWeek>) {
this._setOption('hiddenWeekDays', value);
}

@Input()
get intervalCount(): number {
return this._getOption('intervalCount');
Expand Down
1 change: 1 addition & 0 deletions packages/devextreme-metadata/make-angular-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Ng.makeMetadata({
removeMembers(/\/scheduler:dxSchedulerOptions\.editing\.popup/),
removeMembers(/\/scheduler:dxSchedulerOptions\.resources\.icon/),
removeMembers(/\/scheduler:.*\.snapToCellsMode/),
removeMembers(/\/scheduler:.*\.hiddenWeekDays/),
removeMembers(/\/stepper:/),
removeMembers(/\/speech_to_text:/),
removeMembers(/\/tree_list:dxTreeListColumnButton.onClick/),
Expand Down
3 changes: 2 additions & 1 deletion packages/devextreme-react/src/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import dxScheduler, {
import { Component as BaseComponent, IHtmlOptions, ComponentRef, NestedComponentMeta } from "./core/component";
import NestedOption from "./core/nested-option";

import type { ViewType, AppointmentAddedEvent, AppointmentAddingEvent, AppointmentClickEvent, AppointmentContextMenuEvent, AppointmentDblClickEvent, AppointmentDeletedEvent, AppointmentDeletingEvent, AppointmentFormOpeningEvent, AppointmentRenderedEvent, AppointmentTooltipShowingEvent, AppointmentUpdatedEvent, AppointmentUpdatingEvent, CellClickEvent, CellContextMenuEvent, ContentReadyEvent, DisposingEvent, InitializedEvent, AppointmentFormProperties, AppointmentFormIconsShowMode, SchedulerPredefinedToolbarItem, DateNavigatorItemProperties, SchedulerPredefinedDateNavigatorItem, dxSchedulerToolbarItem, AllDayPanelMode, AppointmentCollectorTemplateData, AppointmentTemplateData, AppointmentTooltipTemplateData, CellAppointmentsLimit, dxSchedulerScrolling, SnapToCellsMode } from "devextreme/ui/scheduler";
import type { ViewType, AppointmentAddedEvent, AppointmentAddingEvent, AppointmentClickEvent, AppointmentContextMenuEvent, AppointmentDblClickEvent, AppointmentDeletedEvent, AppointmentDeletingEvent, AppointmentFormOpeningEvent, AppointmentRenderedEvent, AppointmentTooltipShowingEvent, AppointmentUpdatedEvent, AppointmentUpdatingEvent, CellClickEvent, CellContextMenuEvent, ContentReadyEvent, DisposingEvent, InitializedEvent, AppointmentFormProperties, AppointmentFormIconsShowMode, SchedulerPredefinedToolbarItem, DateNavigatorItemProperties, SchedulerPredefinedDateNavigatorItem, dxSchedulerToolbarItem, AllDayPanelMode, AppointmentCollectorTemplateData, AppointmentTemplateData, AppointmentTooltipTemplateData, DayOfWeek, CellAppointmentsLimit, dxSchedulerScrolling, SnapToCellsMode } from "devextreme/ui/scheduler";
import type { ContentReadyEvent as ButtonContentReadyEvent, DisposingEvent as ButtonDisposingEvent, InitializedEvent as ButtonInitializedEvent, dxButtonOptions, ClickEvent, OptionChangedEvent } from "devextreme/ui/button";
import type { ContentReadyEvent as FormContentReadyEvent, DisposingEvent as FormDisposingEvent, InitializedEvent as FormInitializedEvent, FormItemType, FormPredefinedButtonItem, OptionChangedEvent as FormOptionChangedEvent, dxFormSimpleItem, dxFormGroupItem, dxFormTabbedItem, dxFormEmptyItem, dxFormButtonItem, LabelLocation, FormLabelMode, EditorEnterKeyEvent, FieldDataChangedEvent, SmartPastedEvent, SmartPastingEvent, FormItemComponent } from "devextreme/ui/form";
import type { ContentReadyEvent as ButtonGroupContentReadyEvent, DisposingEvent as ButtonGroupDisposingEvent, InitializedEvent as ButtonGroupInitializedEvent, OptionChangedEvent as ButtonGroupOptionChangedEvent, dxButtonGroupItem, ItemClickEvent, SelectionChangedEvent } from "devextreme/ui/button_group";
Expand Down Expand Up @@ -1454,6 +1454,7 @@ type IViewProps = React.PropsWithChildren<{
groupByDate?: boolean;
groupOrientation?: Orientation;
groups?: Array<string>;
hiddenWeekDays?: Array<DayOfWeek>;
intervalCount?: number;
maxAppointmentsPerCell?: CellAppointmentsLimit | number;
name?: string | undefined;
Expand Down
6 changes: 6 additions & 0 deletions packages/devextreme-vue/src/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
AllDayPanelMode,
ViewType,
dxSchedulerAppointment,
DayOfWeek,
CellAppointmentsLimit,
AppointmentAddedEvent,
AppointmentAddingEvent,
Expand Down Expand Up @@ -161,6 +162,7 @@ type AccessibleOptions = Pick<Properties,
"groupByDate" |
"groups" |
"height" |
"hiddenWeekDays" |
"hint" |
"indicatorUpdateInterval" |
"max" |
Expand Down Expand Up @@ -248,6 +250,7 @@ const componentConfig = {
groupByDate: Boolean,
groups: Array as PropType<Array<string>>,
height: [Number, String],
hiddenWeekDays: Array as PropType<Array<DayOfWeek>>,
hint: String,
indicatorUpdateInterval: Number,
max: [Date, Number, String],
Expand Down Expand Up @@ -331,6 +334,7 @@ const componentConfig = {
"update:groupByDate": null,
"update:groups": null,
"update:height": null,
"update:hiddenWeekDays": null,
"update:hint": null,
"update:indicatorUpdateInterval": null,
"update:max": null,
Expand Down Expand Up @@ -1774,6 +1778,7 @@ const DxViewConfig = {
"update:groupByDate": null,
"update:groupOrientation": null,
"update:groups": null,
"update:hiddenWeekDays": null,
"update:intervalCount": null,
"update:maxAppointmentsPerCell": null,
"update:name": null,
Expand All @@ -1800,6 +1805,7 @@ const DxViewConfig = {
groupByDate: Boolean,
groupOrientation: String as PropType<Orientation>,
groups: Array as PropType<Array<string>>,
hiddenWeekDays: Array as PropType<Array<DayOfWeek>>,
intervalCount: Number,
maxAppointmentsPerCell: [String, Number] as PropType<CellAppointmentsLimit | number>,
name: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`scheduler should render correct workspace in Santiago DST for view: Day DST 1`] = `
[
Expand Down Expand Up @@ -307,7 +307,7 @@ exports[`scheduler should render correct workspace in Santiago DST for view: Tim
"Wed 4",
"Thu 5",
"Fri 6",
"Sat 7",
"Mon 9",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snapshot changed "Sat 7""Mon 9" in TimelineWorkWeek — is this intentional? Old snapshot had Mon-Sat (7 days), now skips Sat/Sun. Please confirm the new incrementDate logic correctly handles TimelineWorkWeek headers.

Copy link
Copy Markdown
Contributor

@sjbur sjbur Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intended. This is bug not related with timezone. In the snapshot we saved a buggy state that no one noticed is buggy. In timelineWorkWeek we can't have weekend days. You can see the bug here: https://codepen.io/sjbur/pen/Kwgbqdr

Also attaching two screenshots: the first is original state with bug, second one is current implementation without bug.

Image Image

"12:00 AM",
"6:00 AM",
"12:00 PM",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type WorkspaceConstructor<T> = new (container: Element, options?: any) => T;
const createWorkspace = <T extends SchedulerWorkSpace>(
WorkSpace: WorkspaceConstructor<T>,
currentView: string,
options?: any,
): { workspace: T; container: Element } => {
const container = document.createElement('div');
const workspace = new WorkSpace(container, {
Expand All @@ -52,6 +53,7 @@ const createWorkspace = <T extends SchedulerWorkSpace>(
currentDate: new Date(2017, 4, 25),
firstDayOfWeek: 0,
getResourceManager: () => getResourceManagerMock([]),
...options,
});
(workspace as any)._isVisible = () => true;
expect(container.classList).toContain('dx-scheduler-work-space');
Expand Down Expand Up @@ -193,3 +195,81 @@ describe('scheduler workspace scrollTo', () => {
expect(scrollableContainer.scrollLeft).toBeCloseTo(-11125);
});
});

describe('scheduler workspace skipped days support', () => {
beforeEach(() => {
setupSchedulerTestEnvironment();
});

it('should count configured skipped days in week workspace interval math', () => {
const { workspace } = createWorkspace(SchedulerWorkSpaceWeek, 'week', {
skippedDays: [1, 3],
});

expect((workspace as any).getSkippedDaysCount(new Date(2026, 3, 5), 7)).toBe(2);
});

it('should use full week layout for work week when skippedDays override is empty', () => {
const { workspace } = createWorkspace(SchedulerWorkSpaceWorkWeek, 'workWeek', {
currentDate: new Date(2026, 3, 1), // Wednesday
firstDayOfWeek: 0, // Sunday
skippedDays: [],
});

expect(workspace.getStartViewDate()).toEqual(new Date(2026, 2, 29));
expect((workspace as any)._getCellCount()).toBe(7);
});

it('should use custom skippedDays in work week runtime layout', () => {
const { workspace } = createWorkspace(SchedulerWorkSpaceWorkWeek, 'workWeek', {
currentDate: new Date(2026, 3, 1), // Wednesday
firstDayOfWeek: 0, // Sunday
skippedDays: [3], // Wednesday
});

expect(workspace.getStartViewDate()).toEqual(new Date(2026, 2, 29));
expect((workspace as any)._getCellCount()).toBe(6);
});

it('should skip configured hidden days when incrementing timeline header dates', () => {
const { workspace } = createWorkspace(SchedulerTimelineWeek, 'timelineWeek', {
skippedDays: [3],
});
const date = new Date(2026, 3, 7); // Tuesday

(workspace as any).incrementDate(date);

expect(date).toEqual(new Date(2026, 3, 9)); // Thursday
});

it('should skip hidden days when incrementing timeline day dates', () => {
const { workspace } = createWorkspace(SchedulerTimelineDay, 'timelineDay', {
skippedDays: [0, 6],
});
const date = new Date(2026, 3, 10); // Friday

(workspace as any).incrementDate(date);

expect(date).toEqual(new Date(2026, 3, 13)); // Monday
});

it('should respect empty skippedDays override in timeline work week', () => {
const { workspace } = createWorkspace(SchedulerTimelineWorkWeek, 'timelineWorkWeek', {
skippedDays: [],
});
const date = new Date(2026, 3, 10); // Friday

(workspace as any).incrementDate(date);

expect(date).toEqual(new Date(2026, 3, 11)); // Saturday
});

it('should skip weekend by default in timeline work week', () => {
const { workspace } = createWorkspace(SchedulerTimelineWorkWeek, 'timelineWorkWeek');
const date = new Date(2026, 3, 10); // Friday

(workspace as any).incrementDate(date);

expect(date).toEqual(new Date(2026, 3, 13)); // Monday
});
});
Loading
Loading