Skip to content

Conversation

@sjbur
Copy link
Contributor

@sjbur sjbur commented Jan 21, 2026

No description provided.

@sjbur sjbur self-assigned this Jan 21, 2026
@sjbur sjbur added the 26_1 label Jan 21, 2026
@sjbur sjbur marked this pull request as ready for review January 22, 2026 12:07
@sjbur sjbur requested a review from a team as a code owner January 22, 2026 12:07
Copilot AI review requested due to automatic review settings January 22, 2026 12:07
Copy link
Contributor

Copilot AI left a 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.ts functionality into m_date_navigator.ts and removed the separate file
  • Converted all methods in header-related files to have explicit return type annotations
  • Changed async methods in SchedulerCalendar and SchedulerHeader to 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);
Copy link

Copilot AI Jan 22, 2026

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'.

Suggested change
?? (toolbar.visible === undefined && toolbar.items.length);
?? toolbar.items.length > 0;

Copilot uses AI. Check for mistakes.
sourceType: 'script',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: `${__dirname}/js/__internal`,
Copy link

Copilot AI Jan 22, 2026

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.

Copilot uses AI. Check for mistakes.
@@ -1,4 +1,3 @@
import '@js/ui/button_group';
import '@js/ui/drop_down_button';
Copy link

Copilot AI Jan 22, 2026

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.

Suggested change
import '@js/ui/drop_down_button';
import '@js/ui/drop_down_button';
import '@js/ui/button_group';

Copilot uses AI. Check for mistakes.
return subMS(date);
};

const getNextPeriodStartDate = (currentPeriodEndDate: Date, step): Date => {
Copy link
Contributor

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

Copy link
Contributor Author

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 = (
Copy link
Contributor

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]());
};

Copy link
Contributor Author

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>
Copilot AI review requested due to automatic review settings January 22, 2026 14:07
Copy link
Contributor

Copilot AI left a 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.

Comment on lines +244 to 247
onValueChanged: async (e) => {
this._updateCurrentDate(e.value);
this._calendar.hide();
await this._calendar?.hide();
},
Copy link

Copilot AI Jan 22, 2026

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.

Copilot uses AI. Check for mistakes.
case 'week':
case 'month':
return getPeriodStart(date, step, false, firstDayOfWeek);
return getPeriodStart(date, step, false, firstDayOfWeek) as Date;
Copy link

Copilot AI Jan 22, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines 31 to 38
this._calendar?._keyboardHandler(opts);
return true;
Copy link

Copilot AI Jan 22, 2026

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.

Suggested change
this._calendar?._keyboardHandler(opts);
return true;
const handled = this._calendar?._keyboardHandler(opts);
if (typeof handled === 'boolean') {
return handled;
}
return !!this._calendar;

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings January 23, 2026 09:27
Copy link
Contributor

Copilot AI left a 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.

Copilot AI review requested due to automatic review settings January 26, 2026 08:23
Copy link
Contributor

Copilot AI left a 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.

return extend(super._getDefaultOptions(), {
_useShortDateFormat: !devices.real().generic || devices.isSimulator(),
});
}) as HeaderOptions & { _useShortDateFormat: boolean };
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, will add

Copy link
Contributor Author

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?

Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, Done.

Copilot AI review requested due to automatic review settings January 26, 2026 12:45
Copy link
Contributor

Copilot AI left a 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.

Comment on lines 285 to +286

_updateDateByDirection(direction: Direction) {
public _updateDateByDirection(direction: Direction): void {
Copy link

Copilot AI Jan 26, 2026

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.

Copilot uses AI. Check for mistakes.
@sjbur sjbur merged commit c667df3 into DevExpress:26_1 Jan 26, 2026
94 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants