-
Notifications
You must be signed in to change notification settings - Fork 664
Scheduler: refactor Header module #32258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This reverts commit 2ea8c28.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request refactors the Scheduler Header module to improve TypeScript type safety. The changes add strict TypeScript rules for the scheduler/header directory, remove the separate today.ts file by consolidating its functionality into m_date_navigator.ts, and add comprehensive type annotations throughout the module.
Changes:
- Added strict TypeScript ESLint rules for scheduler/header files including explicit return types and no-explicit-any
- Consolidated
today.tsfunctionality intom_date_navigator.tsand removed the separate file - Converted all methods in header-related files to have explicit return type annotations
- Changed async methods in
SchedulerCalendarandSchedulerHeaderto return Promises - Updated import paths for Widget and Calendar components to use TypeScript module paths
- Added proper typing for event handlers, options interfaces, and method parameters
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
packages/devextreme/eslint.config.mjs |
Added strict TypeScript rules configuration for scheduler/header files |
packages/devextreme/js/__internal/scheduler/m_scheduler.ts |
Added return type and type assertions for getFirstDayOfWeek method |
packages/devextreme/js/__internal/scheduler/header/types.ts |
Added new interfaces HeaderCalendarOptions and EventMapHandler type |
packages/devextreme/js/__internal/scheduler/header/today.ts |
Removed file (functionality moved to m_date_navigator.ts) |
packages/devextreme/js/__internal/scheduler/header/m_header.ts |
Added explicit type annotations, made calendar methods async, updated imports |
packages/devextreme/js/__internal/scheduler/header/m_calendar.ts |
Converted to use strict typing, made show/hide async, improved type safety |
packages/devextreme/js/__internal/scheduler/header/m_date_navigator.ts |
Moved getTodayButtonOptions from deleted file, added type annotations |
packages/devextreme/js/__internal/scheduler/header/m_view_switcher.ts |
Added explicit return types and improved theme API usage |
packages/devextreme/js/__internal/scheduler/header/m_utils.ts |
Added return type annotations and minor refactoring improvements |
packages/devextreme/js/__internal/scheduler/header/m_date_navigator.test.ts |
Updated type assertions in tests |
| || (toolbarOptions.visible === undefined && toolbarOptions.items.length); | ||
| const { toolbar } = this.option(); | ||
| const isHeaderShown = toolbar.visible | ||
| ?? (toolbar.visible === undefined && toolbar.items.length); |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for determining 'isHeaderShown' is incorrect. The expression uses the nullish coalescing operator '??' but evaluates 'toolbar.visible' twice. When 'toolbar.visible' is defined, the right-hand side of '??' will never be evaluated. The condition should be: 'toolbar.visible ?? toolbar.items.length > 0' or the original logic should be preserved with proper boolean conversion: 'toolbar.visible !== undefined ? toolbar.visible : toolbar.items.length > 0'.
| ?? (toolbar.visible === undefined && toolbar.items.length); | |
| ?? toolbar.items.length > 0; |
| sourceType: 'script', | ||
| parserOptions: { | ||
| project: './tsconfig.json', | ||
| tsconfigRootDir: `${__dirname}/js/__internal`, |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'tsconfigRootDir' path appears to be incorrect. It's set to '${__dirname}/js/__internal', but the tsconfig.json is located at the package root. This should likely be just '__dirname' or the path should correctly resolve to where tsconfig.json exists. This misconfiguration could cause TypeScript parsing issues in the ESLint rules.
| @@ -1,4 +1,3 @@ | |||
| import '@js/ui/button_group'; | |||
| import '@js/ui/drop_down_button'; | |||
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The side-effect import 'import "@js/ui/button_group"' was removed from this file, but ButtonGroup widgets are still being used in the dateNavigator and viewSwitcher toolbar items (via 'widget: "dxButtonGroup"'). This import is necessary to ensure the ButtonGroup component is registered and available when these toolbar items are rendered. Without this import, the ButtonGroup widgets may not be properly initialized.
| import '@js/ui/drop_down_button'; | |
| import '@js/ui/drop_down_button'; | |
| import '@js/ui/button_group'; |
| return subMS(date); | ||
| }; | ||
|
|
||
| const getNextPeriodStartDate = (currentPeriodEndDate: Date, step): Date => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are forget here step: Step
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrote about this in DM
|
|
||
| const getPeriodEndDate = (currentPeriodStartDate: Date, step: Step, agendaDuration: number): Date => { | ||
| let date; | ||
| const getPeriodEndDate = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can rewrite simple without eslint issues and without create redundant default value;
let date: Date = new Date();
const getPeriodEndDate = (
currentPeriodStartDate: Date,
step: Step,
agendaDuration: number,
): Date => {
const calculators: Record<Step, () => Date> = {
day: () => nextDay(currentPeriodStartDate),
week: () => nextWeek(currentPeriodStartDate),
month: () => nextMonth(currentPeriodStartDate),
workWeek: () => getDateAfterWorkWeek(currentPeriodStartDate),
agenda: () => nextAgendaStart(currentPeriodStartDate, agendaDuration),
};
return subMS(calculators[step]());
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will apply this change to function
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Sergei Burkatskii <sergei.burkatskii@devexpress.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
| onValueChanged: async (e) => { | ||
| this._updateCurrentDate(e.value); | ||
| this._calendar.hide(); | ||
| await this._calendar?.hide(); | ||
| }, |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The onValueChanged callback doesn't need to be async since _updateCurrentDate is synchronous and the await expression is the last statement. Either make this a regular function with this._calendar?.hide() (without await), or if the async nature is intentional for future changes, add a comment explaining why.
| case 'week': | ||
| case 'month': | ||
| return getPeriodStart(date, step, false, firstDayOfWeek); | ||
| return getPeriodStart(date, step, false, firstDayOfWeek) as Date; |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type assertion as Date suggests that getPeriodStart may return undefined or another type. Consider adding a default case that returns a valid Date instead of relying on type assertion, or update the return type of getIntervalStartDate to match what getPeriodStart actually returns.
| this._calendar?._keyboardHandler(opts); | ||
| return true; |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method always returns true regardless of whether _calendar exists or what _calendar._keyboardHandler returns. This could mask keyboard handling failures. Consider returning false when _calendar is undefined, or returning the result from _calendar._keyboardHandler(opts) if it returns a boolean.
| this._calendar?._keyboardHandler(opts); | |
| return true; | |
| const handled = this._calendar?._keyboardHandler(opts); | |
| if (typeof handled === 'boolean') { | |
| return handled; | |
| } | |
| return !!this._calendar; |
packages/devextreme/js/__internal/scheduler/header/m_calendar.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
packages/devextreme/js/__internal/scheduler/header/m_calendar.ts
Outdated
Show resolved
Hide resolved
packages/devextreme/js/__internal/scheduler/header/m_calendar.ts
Outdated
Show resolved
Hide resolved
| return extend(super._getDefaultOptions(), { | ||
| _useShortDateFormat: !devices.real().generic || devices.isSimulator(), | ||
| }); | ||
| }) as HeaderOptions & { _useShortDateFormat: boolean }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add _useShortDateFormat to HeaderOptions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, will add
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the type to HeaderOptions and noticed that we need to pass this property in m_scheduler.ts I decided to remove override default props and just pass _useShortDateFormat directly from m_scheduler.ts
What do you think about this approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this property optional in HeaderOptions type and set its value in m_header.ts? This would be better as m_scheduler doesn't need to know about this option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
|
|
||
| _updateDateByDirection(direction: Direction) { | ||
| public _updateDateByDirection(direction: Direction): void { |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type mismatch: e.element is of type DxElement (from NativeEventInfo in ItemClickEvent), but the show method signature expects HTMLElement. While DxElement<HTMLElement> may resolve to HTMLElement at runtime in builds without jQuery, TypeScript's type system may not recognize this compatibility, potentially causing compilation errors with the strict TypeScript rules enabled for this directory. Consider explicitly typing the parameter as DxElement or using a type assertion to ensure type safety.
No description provided.