From 28650c3a5f9b5e7619980c4a57cdc0e31fb706c1 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 2 Jun 2026 13:27:28 +0200 Subject: [PATCH 01/22] refactor: refactor ts --- .../scheduler/workspaces/m_agenda.ts | 302 ++++++++++-------- .../scheduler/workspaces/m_timeline.ts | 188 ++++++----- .../scheduler/workspaces/m_timeline_day.ts | 7 +- .../scheduler/workspaces/m_timeline_month.ts | 48 +-- .../scheduler/workspaces/m_timeline_week.ts | 5 +- .../scheduler/workspaces/m_work_space.ts | 122 +++++-- .../scheduler/workspaces/m_work_space_day.ts | 7 +- .../workspaces/m_work_space_indicator.ts | 101 +++--- .../workspaces/m_work_space_month.ts | 78 +++-- .../scheduler/workspaces/m_work_space_week.ts | 7 +- 10 files changed, 531 insertions(+), 334 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 6fbc5e2ada1d..624e111583d1 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -2,12 +2,13 @@ import dateLocalization from '@js/common/core/localization/date'; import registerComponent from '@js/core/component_registrator'; import domAdapter from '@js/core/dom_adapter'; import { getPublicElement } from '@js/core/element'; -import $ from '@js/core/renderer'; +import $, { type dxElementWrapper } from '@js/core/renderer'; import { noop } from '@js/core/utils/common'; import dateUtils from '@js/core/utils/date'; import { extend } from '@js/core/utils/extend'; import { each } from '@js/core/utils/iterator'; import { setHeight, setOuterHeight } from '@js/core/utils/size'; +import type { OptionChanged } from '@ts/core/widget/types'; import { EMPTY_ACTIVE_STATE_UNIT } from '@ts/core/widget/widget'; import { @@ -23,7 +24,7 @@ import { VIEWS } from '../utils/options/constants_view'; import { reduceResourcesTree } from '../utils/resource_manager/agenda_group_utils'; import type { GroupNode } from '../utils/resource_manager/types'; import type { ListEntity } from '../view_model/types'; -import WorkSpace from './m_work_space'; +import WorkSpace, { type WorkspaceDateTableScrollableConfig, type WorkspaceOptionChangedOptions, type WorkspaceOptionsInternal } from './m_work_space'; const { tableCreator } = tableCreatorModule; @@ -40,40 +41,57 @@ const LAST_ROW_CLASS = 'dx-scheduler-date-table-last-row'; const INNER_CELL_MARGIN = 5; const OUTER_CELL_MARGIN = 20; +interface AgendaDefaultOptions extends WorkspaceOptionsInternal { + agendaDuration: number; + rowHeight: number; + noDataText: string; +} + +interface AgendaRenderOptions { + container: Element; + rowCount?: number; + cellCount?: number; + rowClass?: string; + cellClass?: string; + cellTemplate?: unknown; + getStartDate?: (rowIndex: number) => Date; +} + class SchedulerAgenda extends WorkSpace { - private startViewDate: any; + private startViewDate!: Date; private rows: number[][] = []; - private $rows: any; + private $rows: dxElementWrapper[] = []; - private $noDataContainer: any; + private $noDataContainer?: dxElementWrapper; - // eslint-disable-next-line class-methods-use-this protected _activeStateUnit(): string { return EMPTY_ACTIVE_STATE_UNIT; } - get type() { return VIEWS.AGENDA; } + get type(): string { return VIEWS.AGENDA; } - getStartViewDate() { + getStartViewDate(): Date { return this.startViewDate; } - _init() { + _init(): void { super._init(); } - _getDefaultOptions() { - return extend(super._getDefaultOptions(), { + _getDefaultOptions(): AgendaDefaultOptions { + const defaultOptions = extend(super._getDefaultOptions(), { // Number | "month" agendaDuration: 7, rowHeight: 60, noDataText: '', - }); + }) as AgendaDefaultOptions; + + return defaultOptions; } - _optionChanged(args) { + _optionChanged(args: OptionChanged): void { const { name } = args; const { value } = args; @@ -85,7 +103,7 @@ class SchedulerAgenda extends WorkSpace { this.recalculateAgenda(this.rows); break; case 'groups': - if (!value?.length) { + if (!Array.isArray(value) || !value.length) { if (this.$groupTable) { this.$groupTable.remove(); this.$groupTable = null; @@ -102,41 +120,41 @@ class SchedulerAgenda extends WorkSpace { } } - _renderFocusState() { return noop(); } + _renderFocusState(): void { return noop(); } - _renderFocusTarget() { return noop(); } + _renderFocusTarget(): void { return noop(); } - _cleanFocusState() { return noop(); } + _cleanFocusState(): void { return noop(); } - supportAllDayRow() { + supportAllDayRow(): boolean { return false; } - protected override isVerticalGroupedWorkSpace() { + protected override isVerticalGroupedWorkSpace(): boolean { return false; } - protected override getElementClass() { + protected override getElementClass(): string { return AGENDA_CLASS; } - protected override getRowCount() { + protected override getRowCount(): number { return this.option('agendaDuration') as number; } - getCellCount() { + getCellCount(): number { return 1; } - protected override getTimePanelRowCount() { + protected override getTimePanelRowCount(): number { return this.option('agendaDuration') as number; } - protected renderAllDayPanel() { return noop(); } + protected renderAllDayPanel(): void { return noop(); } - protected override updateAllDayVisibility() { return noop(); } + protected override updateAllDayVisibility(): void { return noop(); } - protected override initWorkSpaceUnits() { + protected override initWorkSpaceUnits(): void { this.initGroupTable(); this.$timePanel = $('').attr('aria-hidden', true).addClass(TIME_PANEL_CLASS); this.$dateTable = $('
').attr('aria-hidden', true).addClass(DATE_TABLE_CLASS); @@ -144,14 +162,14 @@ class SchedulerAgenda extends WorkSpace { this.$dateTableContainer = $('
').addClass('dx-scheduler-date-table-container'); } - private initGroupTable() { + private initGroupTable(): void { const groups = this.option('groups'); if (groups?.length) { this.$groupTable = $('
').attr('aria-hidden', true).addClass(GROUP_TABLE_CLASS); } } - protected override renderView() { + protected override renderView(): void { this.startViewDate = agendaUtils.calculateStartViewDate( this.option('currentDate'), this.option('startDayHour'), @@ -159,8 +177,8 @@ class SchedulerAgenda extends WorkSpace { this.rows = []; } - private recalculateAgenda(rows) { - let cellTemplates = []; + private recalculateAgenda(rows: number[][]): void { + let cellTemplates: unknown[] = []; this.cleanView(); if (this.rowsIsEmpty(rows)) { @@ -180,21 +198,26 @@ class SchedulerAgenda extends WorkSpace { this.$dateTableScrollable.update(); } - private renderNoData() { + private renderNoData(): void { this.$noDataContainer = $('
').addClass(NODATA_CONTAINER_CLASS) - .html(this.option('noDataText') as any); + .html(this.option('noDataText') as string); this.$dateTableScrollable.$content().append(this.$noDataContainer); } - protected override setTableSizes() { return noop(); } + protected override setTableSizes(): void { return noop(); } - protected override toggleHorizontalScrollClass() { return noop(); } + protected override toggleHorizontalScrollClass(): void { return noop(); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected override createCrossScrollingConfig(argument?: any) { return noop(); } + protected override createCrossScrollingConfig(): Pick { + return { + direction: 'both', + onScroll: noop, + onEnd: noop, + }; + } - private setGroupHeaderCellsHeight() { + private setGroupHeaderCellsHeight(): void { const $cells = this.getGroupHeaderCells().filter((_, element) => !element.getAttribute('rowSpan')); const rows = this.removeEmptyRows(this.rows); @@ -202,72 +225,58 @@ class SchedulerAgenda extends WorkSpace { return; } - for (let i = 0; i < $cells.length; i++) { + for (let i = 0; i < $cells.length; i += 1) { const $cellContent = $cells.eq(i).find('.dx-scheduler-group-header-content'); setOuterHeight($cellContent, this.getGroupRowHeight(rows[i])); } } - private rowsIsEmpty(rows) { - let result = true; - - for (let i = 0; i < rows.length; i++) { - const groupRow = rows[i]; - - for (let j = 0; j < groupRow.length; j++) { - if (groupRow[j]) { - result = false; - break; - } - } - } - - return result; + private rowsIsEmpty(rows: number[][]): boolean { + return rows.every((groupRow) => groupRow.every((cell) => !cell)); } - protected override attachGroupCountClass() { + protected override attachGroupCountClass(): void { const className = getVerticalGroupCountClass(this.option('groups')); - (this.$element() as any).addClass(className); - } - - private removeEmptyRows(rows) { - const result: any[] = []; - const isEmpty = function (data) { - return !data.some((value) => value > 0); - }; - - for (let i = 0; i < rows.length; i++) { - if (rows[i].length && !isEmpty(rows[i])) { - result.push(rows[i]); - } + if (className) { + this.$element().addClass(className); } + } - return result; + private removeEmptyRows(rows: number[][]): number[][] { + const isEmpty = (data: number[]): boolean => !data.some((value) => value > 0); + return rows.filter((row) => row.length && !isEmpty(row)); } - protected override getGroupHeaderContainer() { - return this.$groupTable; + protected override getGroupHeaderContainer(): dxElementWrapper | null { + return this.$groupTable as dxElementWrapper | null; } - protected override makeGroupRows() { + protected override makeGroupRows(): { elements: dxElementWrapper; cellTemplates: unknown[] } { const resourceManager = this.option('getResourceManager')(); - const allAppointments = (this.option('getFilteredItems') as any)() as ListEntity[]; + const allAppointments = (this.option('getFilteredItems') as () => ListEntity[])(); const tree = reduceResourcesTree( resourceManager.resourceById, resourceManager.groupsTree, allAppointments, ); - const cellTemplate: any = this.option('resourceCellTemplate'); + const cellTemplate = this.option('resourceCellTemplate') as { + render?: (model: unknown) => unknown; + }; const getGroupHeaderContentClass = GROUP_HEADER_CONTENT_CLASS; - const cellTemplates: any[] = []; + const cellTemplates: unknown[] = []; const table = tableCreator.makeGroupedTableFromJSON(tree, { cellTag: 'th', groupTableClass: GROUP_TABLE_CLASS, groupRowClass: GROUP_ROW_CLASS, groupCellClass: this.getGroupHeaderClass(), - groupCellCustomContent(cell: HTMLDivElement, cellTextElement: HTMLElement, index: number, node: GroupNode) { + groupCellCustomContent( + cell: HTMLDivElement, + cellTextElement: HTMLElement, + index: number, + node: GroupNode, + ) { const container = domAdapter.createElement('div'); container.className = getGroupHeaderContentClass; const value = node.grouped[node.resourceIndex]; @@ -305,7 +314,7 @@ class SchedulerAgenda extends WorkSpace { }; } - protected override cleanView() { + protected override cleanView(): void { this.$dateTable.empty(); this.$timePanel.empty(); @@ -321,11 +330,11 @@ class SchedulerAgenda extends WorkSpace { } } - protected override createWorkSpaceElements() { + protected override createWorkSpaceElements(): void { this.createWorkSpaceStaticElements(); } - protected override createWorkSpaceStaticElements() { + protected override createWorkSpaceStaticElements(): void { this.$dateTableContainer.append(this.$dateTable); this.$dateTableScrollable.$content().append(this.$dateTableScrollableContent); @@ -337,7 +346,7 @@ class SchedulerAgenda extends WorkSpace { this.$element().append(this.$dateTableScrollable.$element()); } - protected renderDateTable() { + protected renderDateTable(): void { this.renderTableBody({ container: getPublicElement(this.$dateTable), rowClass: DATE_TABLE_ROW_CLASS, @@ -345,15 +354,29 @@ class SchedulerAgenda extends WorkSpace { }); } - protected override attachTablesEvents() { return noop(); } + protected override attachTablesEvents(): void { return noop(); } - protected override attachEvents() { return noop(); } + protected override attachEvents(): void { return noop(); } - isIndicationAvailable() { + isIndicationAvailable(): boolean { return false; } - private prepareCellTemplateOptions(text, date, rowIndex, $cell) { + private prepareCellTemplateOptions( + text: string, + date: Date | undefined, + rowIndex: number, + $cell: dxElementWrapper, + ): { + model: { + text: string; + date: Date | undefined; + groups: Record; + groupIndex: number | undefined; + }; + container: Element; + index: number; + } { const leaf = this.resourceManager.groupsLeafs[rowIndex]; const groups = leaf?.grouped ?? {}; const groupIndex = leaf?.groupIndex; @@ -370,31 +393,42 @@ class SchedulerAgenda extends WorkSpace { }; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected renderTableBody(options: any, delayCellTemplateRendering?: any) { - const cellTemplates: any[] = []; - const cellTemplateOpt = options.cellTemplate; + protected renderTableBody( + options: AgendaRenderOptions, + delayCellTemplateRendering?: unknown, + ): void { + if (delayCellTemplateRendering) { + noop(); + } + const cellTemplates: unknown[] = []; + const cellTemplateOpt = options.cellTemplate as { + render?: (templateOptions: unknown) => unknown; + } | undefined; this.$rows = []; - let i; + let i = 0; - const fillTableBody = function (rowIndex, rowSize) { + const fillTableBody = (rowIndex: number, rowSize: number): void => { if (rowSize) { - let date; - let cellDateNumber; - let cellDayName; + const date = options.getStartDate?.(rowIndex); + let cellDateNumber = ''; + let cellDayName = ''; const $row = $('
'); const $td = $('
'); setHeight($td, this.getRowHeight(rowSize)); - if (options.getStartDate) { - date = options.getStartDate?.(rowIndex); - cellDateNumber = dateLocalization.format(date, 'd'); - cellDayName = dateLocalization.format(date, formatWeekday); + if (date) { + cellDateNumber = String(dateLocalization.format(date, 'd')); + cellDayName = String(dateLocalization.format(date, formatWeekday)); } if (cellTemplateOpt?.render) { - const templateOptions = this.prepareCellTemplateOptions(`${cellDateNumber} ${cellDayName}`, date, i, $td); + const templateOptions = this.prepareCellTemplateOptions( + `${cellDateNumber} ${cellDayName}`, + date, + i, + $td, + ); cellTemplates.push(cellTemplateOpt.render.bind(cellTemplateOpt, templateOptions)); } else if (cellDateNumber && cellDayName) { @@ -412,10 +446,10 @@ class SchedulerAgenda extends WorkSpace { $row.append($td); this.$rows.push($row); } - }.bind(this); + }; - for (i = 0; i < this.rows.length; i++) { - each(this.rows[i], fillTableBody); + for (i = 0; i < this.rows.length; i += 1) { + each(this.rows[i], fillTableBody.bind(this)); this.setLastRowClass(); } @@ -423,7 +457,7 @@ class SchedulerAgenda extends WorkSpace { this.applyCellTemplates(cellTemplates); } - private setLastRowClass() { + private setLastRowClass(): void { if (this.rows.length > 1 && this.$rows.length) { const $lastRow = this.$rows[this.$rows.length - 1]; @@ -431,7 +465,7 @@ class SchedulerAgenda extends WorkSpace { } } - protected renderTimePanel() { + protected renderTimePanel(): void { this.renderTableBody({ container: getPublicElement(this.$timePanel), rowCount: this.getTimePanelRowCount(), @@ -443,32 +477,26 @@ class SchedulerAgenda extends WorkSpace { }); } - private getTimePanelStartDate(rowIndex) { + private getTimePanelStartDate(rowIndex: number): Date { return agendaUtils.getDateByIndex( this.getStartViewDate(), rowIndex, ); } - private getRowHeight(rowSize) { - const baseHeight = this.option('rowHeight') as any; + private getRowHeight(rowSize: number): number { + const baseHeight = this.option('rowHeight') as number; const innerOffset = (rowSize - 1) * INNER_CELL_MARGIN; return rowSize ? (baseHeight * rowSize) + innerOffset + OUTER_CELL_MARGIN : 0; } - private getGroupRowHeight(groupRows) { + private getGroupRowHeight(groupRows: number[] | undefined): number { if (!groupRows) { - return; - } - - let result = 0; - - for (let i = 0; i < groupRows.length; i++) { - result += this.getRowHeight(groupRows[i]); + return 0; } - return result; + return groupRows.reduce((result, groupRow) => result + this.getRowHeight(groupRow), 0); } renderAgendaLayout(appointments: ListEntity[]): void { @@ -483,36 +511,44 @@ class SchedulerAgenda extends WorkSpace { this.recalculateAgenda(rows); } - getAgendaVerticalStepHeight() { - return this.option('rowHeight'); + getAgendaVerticalStepHeight(): number { + return this.option('rowHeight') as number; } - getEndViewDate() { + getEndViewDate(): Date { return agendaUtils.calculateEndViewDate( this.getStartViewDate(), - this.option('endDayHour') as any, - this.option('agendaDuration') as any, + this.option('endDayHour'), + this.option('agendaDuration') as number, ); } - getEndViewDateByEndDayHour() { + getEndViewDateByEndDayHour(): Date { return this.getEndViewDate(); } - updateScrollPosition(date) { + updateScrollPosition(date: Date): void { const newDate = this.timeZoneCalculator.createDate(date, 'toGrid'); const bounds = this.getVisibleBounds(); - const startDateHour = newDate.getHours(); - const startDateMinutes = newDate.getMinutes(); - if (this.needUpdateScrollPosition(startDateHour, startDateMinutes, bounds, newDate)) { + if (this.needUpdateScrollPosition(newDate, bounds)) { this.scrollTo(newDate); } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - needUpdateScrollPosition(hours, minutes, bounds, newData?: any) { + needUpdateScrollPosition( + date: Date, + appointmentGroupValues?: unknown, + inAllDayRow?: boolean, + ): boolean { + if (appointmentGroupValues || inAllDayRow) { + noop(); + } + + const bounds = this.getVisibleBounds(); + const hours = date.getHours(); + const minutes = date.getMinutes(); let isUpdateNeeded = false; if (hours < bounds.top.hours || hours > bounds.bottom.hours) { @@ -530,15 +566,18 @@ class SchedulerAgenda extends WorkSpace { return isUpdateNeeded; } - renovatedRenderSupported() { return false; } + renovatedRenderSupported(): boolean { return false; } - override isVirtualScrolling() { return false; } + override isVirtualScrolling(): boolean { return false; } - protected override getTotalViewDuration() { - return dateUtils.dateToMilliseconds('day') * (this.option('intervalCount') as any); + protected override getTotalViewDuration(): number { + return dateUtils.dateToMilliseconds('day') * this.option('intervalCount'); } - getDOMElementsMetaData() { + getDOMElementsMetaData(): { + dateTableCellsMeta: Record[][]; + allDayPanelCellsMeta: Record[]; + } { return { dateTableCellsMeta: [[{}]], allDayPanelCellsMeta: [{}], @@ -546,6 +585,7 @@ class SchedulerAgenda extends WorkSpace { } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerAgenda', SchedulerAgenda as any); export default SchedulerAgenda; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts index 4628643d9f52..83a999dd6090 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts @@ -1,13 +1,13 @@ import registerComponent from '@js/core/component_registrator'; -import $ from '@js/core/renderer'; +import $, { type dxElementWrapper } from '@js/core/renderer'; import { noop } from '@js/core/utils/common'; import dateUtils from '@js/core/utils/date'; import { extend } from '@js/core/utils/extend'; import { getBoundingRect } from '@js/core/utils/position'; import { getOuterHeight, getOuterWidth, setHeight } from '@js/core/utils/size'; import { hasWindow } from '@js/core/utils/window'; +import type { dxSchedulerOptions } from '@js/ui/scheduler'; import { getGlobalFormatByDataType } from '@ts/core/m_global_format_config'; -// NOTE: Renovation component import. import { HeaderPanelTimelineComponent } from '@ts/scheduler/r1/components/index'; import { timelineWeekUtils } from '@ts/scheduler/r1/utils/index'; @@ -19,7 +19,9 @@ import tableCreatorModule from '../m_table_creator'; import timezoneUtils from '../m_utils_time_zone'; import HorizontalShader from '../shaders/current_time_shader_horizontal'; import { getFirstVisibleDate } from '../utils/skipped_days'; -import SchedulerWorkSpace from './m_work_space_indicator'; +import type { WorkspaceDateTableScrollableConfig, WorkspaceHeaderScrollableConfig } from './m_work_space'; +import SchedulerWorkSpace, { type WorkSpaceIndicatorDefaultOptions } from './m_work_space_indicator'; +import type { ViewDataProviderOptions } from './view_model/m_types'; const { tableCreator } = tableCreatorModule; @@ -34,80 +36,94 @@ const HEADER_PANEL_WEEK_CELL_CLASS = 'dx-scheduler-header-panel-week-cell'; const HORIZONTAL = 'horizontal'; const toMs = dateUtils.dateToMilliseconds; +interface TimelineDefaultOptions extends WorkSpaceIndicatorDefaultOptions { + groupOrientation: 'vertical'; +} + class SchedulerTimeline extends SchedulerWorkSpace { - protected override $sidebarTable: any; + protected override $sidebarTable!: dxElementWrapper; - get verticalGroupTableClass() { return GROUP_TABLE_CLASS; } + get verticalGroupTableClass(): string { return GROUP_TABLE_CLASS; } readonly viewDirection = 'horizontal'; - get renovatedHeaderPanelComponent() { return HeaderPanelTimelineComponent; } + get renovatedHeaderPanelComponent(): typeof HeaderPanelTimelineComponent { + return HeaderPanelTimelineComponent; + } - getGroupTableWidth() { - return this.$sidebarTable ? getOuterWidth(this.$sidebarTable) : 0; + getGroupTableWidth(): number { + return this.$sidebarTable ? getOuterWidth(this.$sidebarTable) as number : 0; } - protected override getTotalRowCount(groupCount) { + protected override getTotalRowCount( + groupCount: number, + includeAllDayPanelRows?: unknown, + ): number { + if (includeAllDayPanelRows !== undefined) { + noop(); + } + if (this.isHorizontalGroupedWorkSpace()) { return this.getRowCount(); } - groupCount = groupCount || 1; - return this.getRowCount() * groupCount; + const totalGroupCount = groupCount || 1; + return this.getRowCount() * totalGroupCount; } - protected override getFormat(): any { - return getGlobalFormatByDataType('time') || 'shorttime'; + protected override getFormat(): string { + const format = getGlobalFormatByDataType('time'); + return typeof format === 'string' ? format : 'shorttime'; } - private getWorkSpaceHeight() { + private getWorkSpaceHeight(): number { if (this.option('crossScrollingEnabled') && hasWindow()) { - return getBoundingRect(this.$dateTable.get(0)).height; + return getBoundingRect(this.$dateTable.get(0)).height as number; } - return getBoundingRect((this.$element() as any).get(0)).height; + return getBoundingRect(this.$element().get(0)).height as number; } - protected override dateTableScrollableConfig() { + protected override dateTableScrollableConfig(): WorkspaceDateTableScrollableConfig { const config = super.dateTableScrollableConfig(); const timelineConfig = { direction: HORIZONTAL, }; - return this.option('crossScrollingEnabled') ? config : extend(config, timelineConfig); + return this.option('crossScrollingEnabled') ? config : extend(config, timelineConfig) as WorkspaceDateTableScrollableConfig; } - protected override needCreateCrossScrolling() { + protected override needCreateCrossScrolling(): boolean { return true; } - protected override headerScrollableConfig() { + protected override headerScrollableConfig(): WorkspaceHeaderScrollableConfig { const config = super.headerScrollableConfig(); return extend(config, { scrollByContent: true, - }); + }) as WorkspaceHeaderScrollableConfig; } - supportAllDayRow() { + supportAllDayRow(): boolean { return false; } - protected override getGroupHeaderContainer() { + protected override getGroupHeaderContainer(): dxElementWrapper { if (this.isHorizontalGroupedWorkSpace()) { - return this.$thead; + return this.$thead as dxElementWrapper; } return this.$sidebarTable; } - protected override insertAllDayRowsIntoDateTable() { + protected override insertAllDayRowsIntoDateTable(): boolean { return false; } - protected needRenderWeekHeader() { + protected needRenderWeekHeader(): boolean { return false; } - protected incrementDate(date) { + protected incrementDate(date: Date): void { const skippedDays = this.option('skippedDays') ?? []; const nextDate = new Date(date); nextDate.setDate(nextDate.getDate() + 1); @@ -115,7 +131,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { const nextVisibleDate = getFirstVisibleDate( nextDate, skippedDays, - (currentDate) => { + (currentDate: Date) => { const result = new Date(currentDate); result.setDate(result.getDate() + 1); return result; @@ -125,12 +141,12 @@ class SchedulerTimeline extends SchedulerWorkSpace { date.setTime(nextVisibleDate.getTime()); } - getIndicationCellCount() { + getIndicationCellCount(): number { const timeDiff = this.getTimeDiff(); return this.calculateDurationInCells(timeDiff); } - private getTimeDiff() { + private getTimeDiff(): number { let today = this.getToday(); const date = this.getIndicationFirstViewDate(); @@ -144,16 +160,16 @@ class SchedulerTimeline extends SchedulerWorkSpace { return today.getTime() - date.getTime(); } - protected calculateDurationInCells(timeDiff) { + protected calculateDurationInCells(timeDiff: number): number { const today = this.getToday(); const differenceInDays = Math.floor(timeDiff / toMs('day')); const skippedDaysCount = this.getSkippedDaysCount( this.getIndicationFirstViewDate(), differenceInDays, ); - let duration = (timeDiff - differenceInDays * toMs('day') - (this.option('startDayHour') as any) * toMs('hour')) / this.getCellDuration(); + let duration = (timeDiff - differenceInDays * toMs('day') - this.option('startDayHour') * toMs('hour')) / this.getCellDuration(); - if (today.getHours() > (this.option('endDayHour') as any)) { + if (today.getHours() > this.option('endDayHour')) { duration = this.getCellCountInDay(); } @@ -163,7 +179,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { return (differenceInDays - skippedDaysCount) * this.getCellCountInDay() + duration; } - getIndicationWidth() { + getIndicationWidth(): number { if (this.isGroupedByDate()) { const cellCount = this.getIndicationCellCount(); const integerPart = Math.floor(cellCount); @@ -174,15 +190,15 @@ class SchedulerTimeline extends SchedulerWorkSpace { return this.getIndicationCellCount() * this.getCellWidth(); } - protected override isVerticalShader() { + protected override isVerticalShader(): boolean { return false; } - protected override isCurrentTimeHeaderCell() { + protected override isCurrentTimeHeaderCell(): boolean { return false; } - protected override setTableSizes() { + protected override setTableSizes(): void { super.setTableSizes(); const minHeight = this.getWorkSpaceMinHeight(); @@ -192,7 +208,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { this.virtualScrollingDispatcher.updateDimensions(); } - private getWorkSpaceMinHeight() { + private getWorkSpaceMinHeight(): number { let minHeight = this.getWorkSpaceHeight(); const workspaceContainerHeight = getOuterHeight(this.$flexContainer, true); @@ -204,32 +220,37 @@ class SchedulerTimeline extends SchedulerWorkSpace { return minHeight; } - protected override getCellCoordinatesByIndex(index) { + protected override getCellCoordinatesByIndex( + index: number, + ): { columnIndex: number; rowIndex: number } { return { columnIndex: index % this.getCellCount(), rowIndex: 0, }; } - protected override getCellElementByPosition(cellCoordinates, groupIndex) { + protected override getCellElementByPosition( + cellCoordinates: { rowIndex: number; columnIndex: number }, + groupIndex: number, + ): dxElementWrapper { const indexes = this.groupedStrategy.prepareCellIndexes(cellCoordinates, groupIndex); return this.$dateTable .find('tr') .eq(indexes.rowIndex) .find('td') - .eq(indexes.columnIndex); + .eq(indexes.columnIndex) as dxElementWrapper; } - protected override getWorkSpaceWidth() { - return getOuterWidth(this.$dateTable, true); + protected override getWorkSpaceWidth(): number { + return getOuterWidth(this.$dateTable, true) as number; } - private getIndicationFirstViewDate() { - return dateUtils.trimTime(new Date(this.getStartViewDate())); + private getIndicationFirstViewDate(): Date { + return dateUtils.trimTime(new Date(this.getStartViewDate())) as Date; } - protected override getIntervalBetween(currentDate, allDay) { + protected override getIntervalBetween(currentDate: Date, allDay?: boolean): number { const startDayHour = this.option('startDayHour'); const endDayHour = this.option('endDayHour'); const firstViewDate = this.getStartViewDate(); @@ -244,7 +265,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { const skippedDaysCount = this.getSkippedDaysCount(firstViewDate, fullDays); const cellCount = this.getCellCountInDay() * (fullDays - skippedDaysCount); const gapBeforeAppt = apptStart - dateUtils.trimTime(new Date(currentDate)).getTime(); - let result = cellCount * (this.option('hoursInterval') as any) * toMs('hour'); + let result = cellCount * this.option('hoursInterval') * toMs('hour'); if (!allDay) { const hour = currentDate.getHours(); @@ -272,34 +293,33 @@ class SchedulerTimeline extends SchedulerWorkSpace { return result; } - getAllDayContainer() { + getAllDayContainer(): null { return null; } - getTimePanelWidth() { + getTimePanelWidth(): number { return 0; } // eslint-disable-next-line @typescript-eslint/no-unused-vars - getIntervalDuration(allDay) { + getIntervalDuration(allDay: boolean): number { return this.getCellDuration(); } - getCellMinWidth() { + getCellMinWidth(): number { return 0; } - getWorkSpaceLeftOffset() { + getWorkSpaceLeftOffset(): number { return 0; } - renderRAllDayPanel() {} + renderRAllDayPanel(): void {} - renderRTimeTable() {} + renderRTimeTable(): void {} - // eslint-disable-next-line @typescript-eslint/no-unused-vars - generateRenderOptions(argument?: any) { - const options = super.generateRenderOptions(true); + generateRenderOptions(isProvideVirtualCellsWidth?: boolean): ViewDataProviderOptions { + const options = super.generateRenderOptions(isProvideVirtualCellsWidth ?? true); return { ...options, @@ -312,39 +332,42 @@ class SchedulerTimeline extends SchedulerWorkSpace { // We need these methods for now but they are useless for renovation // ------------- - _init() { + _init(): void { super._init(); - (this.$element() as any).addClass(TIMELINE_CLASS); + this.$element().addClass(TIMELINE_CLASS); this.$sidebarTable = $('
') .addClass(GROUP_TABLE_CLASS); } - protected override getDefaultGroupStrategy() { + protected override getDefaultGroupStrategy(): 'vertical' { return 'vertical'; } - protected override toggleGroupingDirectionClass() { - (this.$element() as any).toggleClass(HORIZONTAL_GROUPED_WORKSPACE_CLASS, this.isHorizontalGroupedWorkSpace()); + protected override toggleGroupingDirectionClass(): void { + this.$element().toggleClass( + HORIZONTAL_GROUPED_WORKSPACE_CLASS, + this.isHorizontalGroupedWorkSpace(), + ); } - _getDefaultOptions() { + _getDefaultOptions(): TimelineDefaultOptions { return extend(super._getDefaultOptions(), { groupOrientation: 'vertical', - }); + }) as TimelineDefaultOptions; } - protected override createWorkSpaceElements() { + protected override createWorkSpaceElements(): void { this.createWorkSpaceScrollableElements(); } - protected override updateAllDayVisibility() { return noop(); } + protected override updateAllDayVisibility(): void { return noop(); } - protected override getDateHeaderTemplate() { + protected override getDateHeaderTemplate(): dxSchedulerOptions['timeCellTemplate'] { return this.option('timeCellTemplate'); } - protected override renderView() { + protected override renderView(): void { this.renderWorkSpace(); this.virtualScrollingDispatcher.updateDimensions(); @@ -359,14 +382,14 @@ class SchedulerTimeline extends SchedulerWorkSpace { this.updateHeaderEmptyCellWidth(); } - protected override setHorizontalGroupHeaderCellsHeight() { return noop(); } + protected override setHorizontalGroupHeaderCellsHeight(): void { return noop(); } - protected override getTimePanelCells() { - return (this.$element() as any) + protected override getTimePanelCells(): dxElementWrapper { + return this.$element() .find(`.${HEADER_PANEL_CELL_CLASS}:not(.${HEADER_PANEL_WEEK_CELL_CLASS})`); } - getCurrentTimePanelCellIndices() { + getCurrentTimePanelCellIndices(): number[] { const columnCountPerGroup = this.getCellCount(); const today = this.getToday(); const index = this.getCellIndexByDate(today); @@ -384,8 +407,17 @@ class SchedulerTimeline extends SchedulerWorkSpace { .map((_, groupIndex) => columnCountPerGroup * groupIndex + currentTimeColumnIndex); } - protected override renderIndicator(height, rtlOffset, $container, groupCount) { - let $indicator; + protected override renderIndicator( + height: number, + rtlOffset: number, + $container: dxElementWrapper, + groupCount: number, + ): void { + if (height !== undefined) { + noop(); + } + // eslint-disable-next-line @typescript-eslint/init-declarations + let $indicator: dxElementWrapper | undefined; const width = this.getIndicationWidth(); if (this.option('groupOrientation') === 'vertical') { @@ -393,8 +425,9 @@ class SchedulerTimeline extends SchedulerWorkSpace { setHeight($indicator, getBoundingRect($container.get(0)).height); $indicator.css('left', rtlOffset ? rtlOffset - width : width); } else { - for (let i = 0; i < groupCount; i++) { - const offset = this.isGroupedByDate() ? i * this.getCellWidth() : this.getCellCount() * this.getCellWidth() * i; + for (let i = 0; i < groupCount; i += 1) { + const offset = this.isGroupedByDate() ? i * this.getCellWidth() + : this.getCellCount() * this.getCellWidth() * i; $indicator = this.createIndicator($container); setHeight($indicator, getBoundingRect($container.get(0)).height); @@ -403,7 +436,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { } } - protected override makeGroupRows(groups, groupByDate) { + protected override makeGroupRows(groups: unknown[], groupByDate: boolean): unknown { const tableCreatorStrategy = this.option('groupOrientation') === 'vertical' ? tableCreator.VERTICAL : tableCreator.HORIZONTAL; return tableCreator.makeGroupedTable( @@ -423,5 +456,6 @@ class SchedulerTimeline extends SchedulerWorkSpace { } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerTimeline', SchedulerTimeline as any); export default SchedulerTimeline; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_day.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_day.ts index 415c4a32cd01..1d905c9b4db8 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_day.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_day.ts @@ -6,17 +6,18 @@ import SchedulerTimeline from './m_timeline'; const TIMELINE_CLASS = 'dx-scheduler-timeline-day'; class SchedulerTimelineDay extends SchedulerTimeline { - get type() { return VIEWS.TIMELINE_DAY; } + get type(): string { return VIEWS.TIMELINE_DAY; } - protected override getElementClass() { + protected override getElementClass(): string { return TIMELINE_CLASS; } - protected override needRenderWeekHeader() { + protected override needRenderWeekHeader(): boolean { return this.isWorkSpaceWithCount(); } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerTimelineDay', SchedulerTimelineDay as any); export default SchedulerTimelineDay; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts index 96478987146a..98e20e61fa83 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts @@ -1,76 +1,86 @@ import registerComponent from '@js/core/component_registrator'; +import type { template } from '@js/core/templates/template'; import dateUtils from '@js/core/utils/date'; -// NOTE: Renovation component import. import { HeaderPanelComponent } from '@ts/scheduler/r1/components/index'; import { formatWeekdayAndDay, monthUtils } from '@ts/scheduler/r1/utils/index'; import { VIEWS } from '../utils/options/constants_view'; import SchedulerTimeline from './m_timeline'; +import type { ViewDataProviderOptions } from './view_model/m_types'; const TIMELINE_CLASS = 'dx-scheduler-timeline-month'; class SchedulerTimelineMonth extends SchedulerTimeline { - get type() { return VIEWS.TIMELINE_MONTH; } + get type(): string { return VIEWS.TIMELINE_MONTH; } readonly viewDirection = 'horizontal'; - get renovatedHeaderPanelComponent() { return HeaderPanelComponent; } + get renovatedHeaderPanelComponent(): typeof HeaderPanelComponent { return HeaderPanelComponent; } - protected override renderView() { + protected override renderView(): void { super.renderView(); this.updateScrollable(); } - protected override getElementClass() { + protected override getElementClass(): string { return TIMELINE_CLASS; } - protected override getDateHeaderTemplate() { + protected override getDateHeaderTemplate(): template | undefined { return this.option('dateCellTemplate'); } - protected override calculateDurationInCells(timeDiff) { + protected override calculateDurationInCells(timeDiff: number): number { return timeDiff / this.getCellDuration(); } - isIndicatorVisible() { + isIndicatorVisible(): boolean { return true; } - protected override getFormat() { + // @ts-expect-error + protected override getFormat(): (date: Date) => string { return formatWeekdayAndDay; } - protected override getIntervalBetween(currentDate) { + protected override getIntervalBetween(currentDate: Date): number { const firstViewDate = this.getStartViewDate(); const timeZoneOffset = dateUtils.getTimezonesDifference(firstViewDate, currentDate); + const startDayHour = this.option('startDayHour'); - return currentDate.getTime() - (firstViewDate.getTime() - (this.option('startDayHour') as any) * 3600000) - timeZoneOffset; + return currentDate.getTime() + - (firstViewDate.getTime() - startDayHour * 3600000) + - timeZoneOffset; } - protected override getViewStartByOptions() { + protected override getViewStartByOptions(): Date { + const currentDate: Date = this.option('currentDate') ?? new Date(); + const startDate: Date = this.option('startDate') ?? currentDate; + const firstMonthDate = dateUtils.getFirstMonthDate(startDate) ?? startDate; + return monthUtils.getViewStartByOptions( - this.option('startDate') as any, - this.option('currentDate') as any, - this.option('intervalCount') as any, - dateUtils.getFirstMonthDate(this.option('startDate') as any) as any, + startDate, + currentDate, + this.option('intervalCount'), + firstMonthDate, ); } - generateRenderOptions() { + generateRenderOptions(): ViewDataProviderOptions { const options = super.generateRenderOptions(true); return { ...options, - getDateForHeaderText: (_, date) => date, + getDateForHeaderText: (_, date: Date): Date => date, }; } - keepOriginalHours() { + keepOriginalHours(): boolean { return true; } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerTimelineMonth', SchedulerTimelineMonth as any); export default SchedulerTimelineMonth; 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 0d1a9eec32b4..941b85ccd88c 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts @@ -11,13 +11,14 @@ export default class SchedulerTimelineWeek extends SchedulerTimeline { return this.option('type') ?? VIEWS.TIMELINE_WEEK; } - protected override getElementClass() { + protected override getElementClass(): string { return this.type === VIEWS.TIMELINE_WORK_WEEK ? TIMELINE_WORK_WEEK_CLASS : TIMELINE_CLASS; } - protected override needRenderWeekHeader() { + protected override needRenderWeekHeader(): boolean { return true; } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerTimelineWeek', SchedulerTimelineWeek as any); 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 42e146c7bbfb..92ce47c8412a 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -29,9 +29,11 @@ import { import { isDefined } from '@js/core/utils/type'; import { getWindow, hasWindow } from '@js/core/utils/window'; import type { dxSchedulerOptions } from '@js/ui/scheduler'; +import type { ScrollEvent } from '@js/ui/scroll_view'; import errors from '@js/ui/widget/ui.errors'; import Widget from '@js/ui/widget/ui.widget'; import { getMemoizeScrollTo } from '@ts/core/utils/scroll'; +import type { OptionChanged } from '@ts/core/widget/types'; import { AllDayPanelTitleComponent, AllDayTableComponent, @@ -107,6 +109,40 @@ interface RenderRWorkspaceOptions { generateNewData: boolean; } +export interface ViewDateGenerationOptions { + startDayHour: number; + endDayHour: number; + hoursInterval: number; + interval?: number; + intervalCount: number; + startViewDate: Date; + firstDayOfWeek: number; + skippedDays?: number[]; + viewOffset: number; + viewType: ViewType; +} + +export interface WorkspaceDateTableScrollableConfig { + useKeyboard: boolean; + bounceEnabled: boolean; + updateManually: boolean; + onScroll: (event: ScrollEvent) => void; + onInitialized: (args: { component: Scrollable }) => void; + onOptionChanged: (args: { fullName: string; value: unknown; component: Scrollable }) => void; + direction?: 'both'; + onEnd?: () => void; +} + +export interface WorkspaceHeaderScrollableConfig { + useKeyboard: boolean; + showScrollbar: 'never'; + direction: 'horizontal'; + useNative: false; + updateManually: true; + bounceEnabled: false; + onScroll: (event: ScrollEvent) => void; +} + const { tableCreator } = tableCreatorModule; // The constant is needed so that the dragging is not sharp. To prevent small twitches @@ -190,7 +226,7 @@ const DEFAULT_WORKSPACE_RENDER_OPTIONS: RenderRWorkspaceOptions = { generateNewData: true, }; -type WorkspaceOptionsInternal = Omit & { +export type WorkspaceOptionsInternal = Omit & { groups: ResourceLoader[]; getResourceManager: () => ResourceManager; startDate?: Date; @@ -202,6 +238,30 @@ type WorkspaceOptionsInternal = Omit & { skippedDays?: number[]; type?: ViewType; }; + +export type WorkspaceOptionChangedOptions = WorkspaceOptionsInternal & { + onSelectionChanged?: unknown; + onSelectionEnd?: unknown; + onCellClick?: unknown; + onCellContextMenu?: unknown; + viewOffset?: number; + groupOrientation?: 'horizontal' | 'vertical'; + timeZoneCalculator?: unknown; + allDayExpanded?: boolean; + width?: number | string; + allowMultipleCellSelection?: boolean; + selectedCellData?: unknown; + scrolling?: unknown; + schedulerHeight?: number; + schedulerWidth?: number; + agendaDuration?: number | 'month'; + rowHeight?: number; + noDataText?: string; + showCurrentTimeIndicator?: boolean; + indicatorTime?: Date; + indicatorUpdateInterval?: number; + shadeUntilCurrentTime?: boolean; +}; class SchedulerWorkSpace extends Widget { private viewDataProviderValue: any; @@ -661,8 +721,8 @@ class SchedulerWorkSpace extends Widget { this.$allDayTitle = $('
').appendTo(this.$headerPanelEmptyCell); } - protected dateTableScrollableConfig() { - let config: any = { + protected dateTableScrollableConfig(): WorkspaceDateTableScrollableConfig { + let config: WorkspaceDateTableScrollableConfig = { useKeyboard: false, bounceEnabled: false, updateManually: true, @@ -675,14 +735,14 @@ class SchedulerWorkSpace extends Widget { // To prevent scroll container focus in native mode we set tabindex -1 to container // In simulated mode focusable behavior prevented by useKeyboard: false private option onInitialized: ({ component }) => { - const useKeyboardDisabled = component.option('useKeyboard') === false; - const useNativeEnabled = component.option('useNative') === true; + const useKeyboardDisabled = component.option('useKeyboard'); + const useNativeEnabled = component.option('useNative'); if (useKeyboardDisabled && useNativeEnabled) { $(component.container()).attr('tabindex', -1); } }, onOptionChanged: ({ fullName, value, component }) => { - const useKeyboardDisabled = component.option('useKeyboard') === false; + const useKeyboardDisabled = component.option('useKeyboard'); if (useKeyboardDisabled && fullName === 'useNative' && value === true) { $(component.container()).attr('tabindex', -1); } @@ -699,7 +759,7 @@ class SchedulerWorkSpace extends Widget { const currentOnScroll = config.onScroll; config = { ...config, - onScroll: (e) => { + onScroll: (e: ScrollEvent) => { currentOnScroll?.(e); this.virtualScrollingDispatcher.handleOnScrollEvent(e?.scrollOffset); @@ -710,14 +770,24 @@ class SchedulerWorkSpace extends Widget { return config; } - protected createCrossScrollingConfig({ onScroll }): any { + protected createCrossScrollingConfig( + { onScroll }: Pick, + ): Pick { return { direction: 'both', - onScroll: (event) => { - onScroll?.(); + onScroll: (event: ScrollEvent) => { + onScroll?.(event); + + const top = event.scrollOffset?.top; + const left = event.scrollOffset?.left; + + if (top !== undefined) { + this.scrollSync.sidebar({ top }); + } - this.scrollSync.sidebar({ top: event.scrollOffset.top }); - this.scrollSync.header({ left: event.scrollOffset.left }); + if (left !== undefined) { + this.scrollSync.header({ left }); + } }, onEnd: () => { (this.option('onScrollEnd') as any)(); @@ -725,7 +795,7 @@ class SchedulerWorkSpace extends Widget { }; } - protected headerScrollableConfig() { + protected headerScrollableConfig(): WorkspaceHeaderScrollableConfig { return { useKeyboard: false, showScrollbar: 'never', @@ -733,7 +803,7 @@ class SchedulerWorkSpace extends Widget { useNative: false, updateManually: true, bounceEnabled: false, - onScroll: (event) => { + onScroll: (event: ScrollEvent) => { this.scrollSync.dateTable({ left: event.scrollOffset.left }); }, }; @@ -862,14 +932,14 @@ class SchedulerWorkSpace extends Widget { ); } - generateRenderOptions(isProvideVirtualCellsWidth?: any): ViewDataProviderOptions { + generateRenderOptions(isProvideVirtualCellsWidth = false): ViewDataProviderOptions { const groupCount = this.getGroupCount(); const groupOrientation = groupCount > 0 ? this.option('groupOrientation') : this.getDefaultGroupStrategy(); - const options = { + const options: ViewDataProviderOptions = { groupByDate: this.option('groupByDate'), startRowIndex: 0, startCellIndex: 0, @@ -1305,7 +1375,7 @@ class SchedulerWorkSpace extends Widget { }; } - protected getDateGenerationOptions() { + protected getDateGenerationOptions(): ViewDateGenerationOptions { return { startDayHour: this.option('startDayHour'), endDayHour: this.option('endDayHour'), @@ -1316,7 +1386,7 @@ class SchedulerWorkSpace extends Widget { firstDayOfWeek: this.firstDayOfWeek(), skippedDays: this.option('skippedDays'), viewOffset: 0, - viewType: this.type, + viewType: this.type as ViewType, }; } @@ -2297,9 +2367,9 @@ class SchedulerWorkSpace extends Widget { this.virtualScrollingDispatcher.dispose(); } - _getDefaultOptions() { + _getDefaultOptions(): WorkspaceOptionsInternal { // @ts-expect-error - return extend(super._getDefaultOptions(), { + const defaultOptions = extend(super._getDefaultOptions(), { currentDate: new Date(), intervalCount: 1, startDate: null, @@ -2333,18 +2403,20 @@ class SchedulerWorkSpace extends Widget { allDayPanelMode: 'all', height: undefined, draggingMode: 'outlook', - onScrollEnd: () => {}, + onScrollEnd: noop, getHeaderHeight: undefined, - renderAppointments: () => {}, - onShowAllDayPanel: () => {}, - onSelectedCellsClick: () => {}, + renderAppointments: noop, + onShowAllDayPanel: noop, + onSelectedCellsClick: noop, timeZoneCalculator: undefined, schedulerHeight: undefined, schedulerWidth: undefined, }); + + return defaultOptions; } - _optionChanged(args) { + _optionChanged(args: OptionChanged): void { switch (args.name) { case 'startDayHour': case 'endDayHour': diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_day.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_day.ts index 1d6c689f2c7b..d36bd53066c9 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_day.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_day.ts @@ -6,13 +6,13 @@ import SchedulerWorkSpaceVertical from './m_work_space_vertical'; const DAY_CLASS = 'dx-scheduler-work-space-day'; class SchedulerWorkSpaceDay extends SchedulerWorkSpaceVertical { - get type() { return VIEWS.DAY; } + get type(): string { return VIEWS.DAY; } - protected override getElementClass() { + protected override getElementClass(): string { return DAY_CLASS; } - renderRHeaderPanel() { + renderRHeaderPanel(): void { if (this.option('intervalCount') === 1) { super.renderRHeaderPanel(false); } else { @@ -21,6 +21,7 @@ class SchedulerWorkSpaceDay extends SchedulerWorkSpaceVertical { } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerWorkSpaceDay', SchedulerWorkSpaceDay as any); export default SchedulerWorkSpaceDay; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts index 637110fc6e29..2f4dcece1e0b 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts @@ -1,23 +1,34 @@ import registerComponent from '@js/core/component_registrator'; -import $ from '@js/core/renderer'; +import $, { type dxElementWrapper } from '@js/core/renderer'; import dateUtils from '@js/core/utils/date'; import { extend } from '@js/core/utils/extend'; import { getBoundingRect } from '@js/core/utils/position'; import { setWidth } from '@js/core/utils/size'; import { hasWindow } from '@js/core/utils/window'; import { dateUtilsTs } from '@ts/core/utils/date'; +import type { OptionChanged } from '@ts/core/widget/types'; import { getToday } from '@ts/scheduler/r1/utils/index'; import { HEADER_CURRENT_TIME_CELL_CLASS } from '../m_classes'; import timezoneUtils from '../m_utils_time_zone'; -import SchedulerWorkSpace from './m_work_space'; +import SchedulerWorkSpace, { + type WorkspaceOptionChangedOptions, + type WorkspaceOptionsInternal, +} from './m_work_space'; const toMs = dateUtils.dateToMilliseconds; const SCHEDULER_DATE_TIME_INDICATOR_CLASS = 'dx-scheduler-date-time-indicator'; +export interface WorkSpaceIndicatorDefaultOptions extends WorkspaceOptionsInternal { + showCurrentTimeIndicator: boolean; + indicatorTime: Date; + indicatorUpdateInterval: number; + shadeUntilCurrentTime: boolean; +} + class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { - private indicatorInterval: any; + private indicatorInterval?: ReturnType; protected getToday(): Date { const viewOffset = this.option('viewOffset') as number; @@ -35,7 +46,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return false; } - isIndicationAvailable() { + isIndicationAvailable(): boolean { if (!hasWindow()) { return false; } @@ -45,7 +56,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return today >= dateUtils.trimTime(new Date(this.getStartViewDate())); } - isIndicatorVisible() { + isIndicatorVisible(): boolean { const today = this.getToday(); // Subtracts 1 ms from the real endViewDate instead of 1 minute @@ -57,10 +68,15 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return dateUtils.dateInRange(today, firstViewDate, endViewDate); } - protected renderIndicator(height, rtlOffset, $container, groupCount) { + protected renderIndicator( + height: number, + rtlOffset: number, + $container: dxElementWrapper, + groupCount: number, + ): void { const groupedByDate = this.isGroupedByDate(); const repeatCount = groupedByDate ? 1 : groupCount; - for (let i = 0; i < repeatCount; i++) { + Array.from({ length: repeatCount }).forEach((_, i) => { const $indicator = this.createIndicator($container); setWidth( @@ -68,44 +84,53 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { groupedByDate ? this.getCellWidth() * groupCount : this.getCellWidth(), ); this.groupedStrategy.shiftIndicator($indicator, height, rtlOffset, i); - } + }); } - protected createIndicator($container) { + protected createIndicator($container: dxElementWrapper): dxElementWrapper { const $indicator = $('
').addClass(SCHEDULER_DATE_TIME_INDICATOR_CLASS); $container.append($indicator); return $indicator; } - private getRtlOffset(width) { + private getRtlOffset(width: number): number { return this.option('rtlEnabled') ? getBoundingRect(this.$dateTableScrollable.$content().get(0)).width - this.getTimePanelWidth() - width : 0; } - protected setIndicationUpdateInterval() { + protected setIndicationUpdateInterval(): void { if (!this.option('showCurrentTimeIndicator') || this.option('indicatorUpdateInterval') === 0) { return; } this.clearIndicatorUpdateInterval(); - this.indicatorInterval = setInterval(() => { + const scheduleIndicatorUpdate = (): void => { this.renderCurrentDateTimeIndication(); - }, this.option('indicatorUpdateInterval')); + this.indicatorInterval = setTimeout( + scheduleIndicatorUpdate, + this.option('indicatorUpdateInterval'), + ); + }; + + this.indicatorInterval = setTimeout( + scheduleIndicatorUpdate, + this.option('indicatorUpdateInterval'), + ); } - private clearIndicatorUpdateInterval() { + private clearIndicatorUpdateInterval(): void { if (this.indicatorInterval) { - clearInterval(this.indicatorInterval); - delete this.indicatorInterval; + clearTimeout(this.indicatorInterval); + this.indicatorInterval = undefined; } } - protected isVerticalShader() { + protected isVerticalShader(): boolean { return true; } - getIndicationWidth() { + getIndicationWidth(): number { const cellCount = this.getCellCount(); const cellSpan = Math.min(this.getIndicatorDaysSpan(), cellCount); const width = cellSpan * this.getCellWidth(); @@ -114,7 +139,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return Math.min(width, maxWidth); } - getIndicatorOffset() { + getIndicatorOffset(): number { const cellSpan = this.getIndicatorDaysSpan() - 1; const offset = cellSpan * this.getCellWidth(); @@ -137,7 +162,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return Math.ceil((timeDiff + 1) / toMs('day')); } - getIndicationHeight() { + getIndicationHeight(): number { const today = timezoneUtils.getDateWithoutTimezoneChange(this.getToday()); const cellHeight = this.getCellHeight(); const date = new Date(this.getStartViewDate()); @@ -152,9 +177,9 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return cellCount * cellHeight; } - _dispose() { + _dispose(): void { this.clearIndicatorUpdateInterval(); - super._dispose.apply(this, arguments as any); + super._dispose(); } renderCurrentDateTimeIndication(): void { @@ -186,8 +211,8 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return false; } - protected override getHeaderPanelCellClass(i) { - const cellClass = super.getHeaderPanelCellClass(i); + protected override getHeaderPanelCellClass(i: number): string { + const cellClass = super.getHeaderPanelCellClass(i) as string; if (this.isCurrentTimeHeaderCell(i)) { return `${cellClass} ${HEADER_CURRENT_TIME_CELL_CLASS}`; @@ -196,30 +221,30 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return cellClass; } - protected override cleanView() { + protected override cleanView(): void { super.cleanView(); this.cleanDateTimeIndicator(); } - _dimensionChanged() { + _dimensionChanged(): void { super._dimensionChanged(); this.renderCurrentDateTimeLineAndShader(); } - private cleanDateTimeIndicator() { - (this.$element() as any).find(`.${SCHEDULER_DATE_TIME_INDICATOR_CLASS}`).remove(); + private cleanDateTimeIndicator(): void { + this.$element().find(`.${SCHEDULER_DATE_TIME_INDICATOR_CLASS}`).remove(); } - protected override cleanWorkSpace() { + protected override cleanWorkSpace(): void { super.cleanWorkSpace(); this.renderDateTimeIndication(); this.setIndicationUpdateInterval(); } - _optionChanged(args) { + _optionChanged(args: OptionChanged): void { switch (args.name) { case 'showCurrentTimeIndicator': case 'indicatorTime': @@ -242,16 +267,16 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { } } - _getDefaultOptions() { + _getDefaultOptions(): WorkSpaceIndicatorDefaultOptions { return extend(super._getDefaultOptions(), { showCurrentTimeIndicator: true, indicatorTime: new Date(), indicatorUpdateInterval: 5 * toMs('minute'), shadeUntilCurrentTime: true, - }); + }) as WorkSpaceIndicatorDefaultOptions; } - protected getCurrentTimePanelCellIndices() { + protected getCurrentTimePanelCellIndices(): number[] { const rowCountPerGroup = this.getTimePanelRowCount(); const today = this.getToday(); const index = this.getCellIndexByDate(today); @@ -261,10 +286,9 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { return []; } - let cellIndices; - if (currentTimeRowIndex === 0) { - cellIndices = [currentTimeRowIndex]; - } else { + let cellIndices: number[] = [currentTimeRowIndex]; + + if (currentTimeRowIndex !== 0) { cellIndices = currentTimeRowIndex % 2 === 0 ? [currentTimeRowIndex - 1, currentTimeRowIndex] : [currentTimeRowIndex, currentTimeRowIndex + 1]; @@ -275,7 +299,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { : 1; return [...new Array(verticalGroupCount)] - .reduce((currentIndices, _, groupIndex) => [ + .reduce((currentIndices, _, groupIndex) => [ ...currentIndices, ...cellIndices.map((cellIndex) => rowCountPerGroup * groupIndex + cellIndex), ], []); @@ -307,5 +331,6 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerWorkSpace', SchedulerWorkSpaceIndicator as any); export default SchedulerWorkSpaceIndicator; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts index 7585eb598a71..f53be27fa317 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts @@ -3,12 +3,12 @@ import { noop } from '@js/core/utils/common'; import dateUtils from '@js/core/utils/date'; import { getBoundingRect } from '@js/core/utils/position'; import { hasWindow } from '@js/core/utils/window'; -// NOTE: Renovation component import. import { DateTableMonthComponent } from '@ts/scheduler/r1/components/index'; import { formatWeekday, monthUtils } from '@ts/scheduler/r1/utils/index'; import { utils } from '../m_utils'; import { VIEWS } from '../utils/options/constants_view'; +import type { ViewDateGenerationOptions } from './m_work_space'; import SchedulerWorkSpace from './m_work_space_indicator'; const MONTH_CLASS = 'dx-scheduler-work-space-month'; @@ -16,24 +16,28 @@ const MONTH_CLASS = 'dx-scheduler-work-space-month'; const toMs = dateUtils.dateToMilliseconds; class SchedulerWorkSpaceMonth extends SchedulerWorkSpace { - get type() { return VIEWS.MONTH; } + get type(): string { return VIEWS.MONTH; } - protected override getElementClass() { + protected override getElementClass(): string { return MONTH_CLASS; } - protected override getFormat() { + protected override getFormat(): (date: Date) => string { return formatWeekday; } - protected override getIntervalBetween(currentDate) { + protected override getIntervalBetween(currentDate: Date): number { const firstViewDate = this.getStartViewDate(); const timeZoneOffset = dateUtils.getTimezonesDifference(firstViewDate, currentDate); + const startDayHour = this.option('startDayHour'); - return currentDate.getTime() - (firstViewDate.getTime() - (this.option('startDayHour') as any) * 3600000) - timeZoneOffset; + return currentDate.getTime() + - (firstViewDate.getTime() - startDayHour * 3600000) + - timeZoneOffset; } - protected override getDateGenerationOptions() { + protected override getDateGenerationOptions(): ViewDateGenerationOptions + & { cellCountInDay: number } { return { ...super.getDateGenerationOptions(), cellCountInDay: 1, @@ -45,8 +49,8 @@ class SchedulerWorkSpaceMonth extends SchedulerWorkSpace { * getCellWidth method need remove. Details in T712431 there is a test for this bug, * when changing the layout, the test will also be useless */ - getCellWidth() { - return this.cache.memo('cellWidth', () => { + getCellWidth(): number | undefined { + const cellWidth = this.cache.memo('cellWidth', (): number | undefined => { const DAYS_IN_WEEK = 7; let averageWidth = 0; @@ -57,13 +61,17 @@ class SchedulerWorkSpaceMonth extends SchedulerWorkSpace { return cells.length === 0 ? undefined : averageWidth / DAYS_IN_WEEK; }); + + return cellWidth as number | undefined; } - protected override insertAllDayRowsIntoDateTable() { + protected override insertAllDayRowsIntoDateTable(): boolean { return false; } - protected override getCellCoordinatesByIndex(index) { + protected override getCellCoordinatesByIndex( + index: number, + ): { rowIndex: number; columnIndex: number } { const rowIndex = Math.floor(index / this.getCellCount()); const columnIndex = index - this.getCellCount() * rowIndex; @@ -73,61 +81,64 @@ class SchedulerWorkSpaceMonth extends SchedulerWorkSpace { }; } - protected override needCreateCrossScrolling() { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - return this.option('crossScrollingEnabled') || this.isVerticalGroupedWorkSpace(); + protected override needCreateCrossScrolling(): boolean { + return this.option('crossScrollingEnabled') ?? this.isVerticalGroupedWorkSpace(); } - protected override getViewStartByOptions() { + protected override getViewStartByOptions(): Date { + const currentDate: Date = this.option('currentDate') ?? new Date(); + const startDate: Date = this.option('startDate') ?? currentDate; + const firstMonthDate = dateUtils.getFirstMonthDate(startDate) ?? startDate; + return monthUtils.getViewStartByOptions( - this.option('startDate') as any, - this.option('currentDate') as any, - this.option('intervalCount') as any, - dateUtils.getFirstMonthDate(this.option('startDate')) as any, + startDate, + currentDate, + this.option('intervalCount'), + firstMonthDate, ); } - protected override updateIndex(index) { + protected override updateIndex(index: number): number { return index; } - isIndicationAvailable() { + isIndicationAvailable(): boolean { return false; } - getIntervalDuration() { + getIntervalDuration(): number { return toMs('day'); } - getTimePanelWidth() { + getTimePanelWidth(): number { return 0; } - supportAllDayRow() { + supportAllDayRow(): boolean { return false; } - keepOriginalHours() { + keepOriginalHours(): boolean { return true; } - getWorkSpaceLeftOffset() { + getWorkSpaceLeftOffset(): number { return 0; } - needApplyCollectorOffset() { + needApplyCollectorOffset(): boolean { return true; } - protected override getHeaderDate() { + protected override getHeaderDate(): Date { return this.getViewStartByOptions(); } - renderRAllDayPanel() {} + renderRAllDayPanel(): void {} - renderRTimeTable() {} + renderRTimeTable(): void {} - renderRDateTable() { + renderRDateTable(): void { utils.renovation.renderComponent( this, this.$dateTable, @@ -141,7 +152,7 @@ class SchedulerWorkSpaceMonth extends SchedulerWorkSpace { // We need these methods for now but they are useless for renovation // ------------- - protected override createWorkSpaceElements() { + protected override createWorkSpaceElements(): void { if (this.isVerticalGroupedWorkSpace()) { this.createWorkSpaceScrollableElements(); } else { @@ -149,9 +160,10 @@ class SchedulerWorkSpaceMonth extends SchedulerWorkSpace { } } - protected override updateAllDayVisibility() { return noop(); } + protected override updateAllDayVisibility(): void { return noop(); } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerWorkSpaceMonth', SchedulerWorkSpaceMonth as any); export default SchedulerWorkSpaceMonth; 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 62087a0b31e6..3676aae58f25 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 @@ -11,15 +11,16 @@ class SchedulerWorkSpaceWeek extends SchedulerWorkSpaceVertical { return this.option('type') ?? VIEWS.WEEK; } - protected override getElementClass() { + protected override getElementClass(): string { return this.type === VIEWS.WORK_WEEK ? WORK_WEEK_CLASS : WEEK_CLASS; } - protected override calculateViewStartDate() { - return weekUtils.calculateViewStartDate(this.option('startDate') as any, this.firstDayOfWeek()); + protected override calculateViewStartDate(): Date { + return weekUtils.calculateViewStartDate(this.option('startDate') as Date, this.firstDayOfWeek()); } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any registerComponent('dxSchedulerWorkSpaceWeek', SchedulerWorkSpaceWeek as any); export default SchedulerWorkSpaceWeek; From 37966bab1a5a581f5dd1b1e3c14dba9cb878e794 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 2 Jun 2026 13:35:40 +0200 Subject: [PATCH 02/22] fix: small fixes --- .../scheduler/workspaces/m_agenda.ts | 1 - .../scheduler/workspaces/m_work_space.ts | 6 +++--- .../workspaces/m_work_space_indicator.ts | 18 +++++------------- .../scheduler/workspaces/m_work_space_month.ts | 12 ++++-------- 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 624e111583d1..09f5b3bb6bb9 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -211,7 +211,6 @@ class SchedulerAgenda extends WorkSpace { protected override createCrossScrollingConfig(): Pick { return { - direction: 'both', onScroll: noop, onEnd: noop, }; 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 92ce47c8412a..7705dc9b6c18 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -735,14 +735,14 @@ class SchedulerWorkSpace extends Widget { // To prevent scroll container focus in native mode we set tabindex -1 to container // In simulated mode focusable behavior prevented by useKeyboard: false private option onInitialized: ({ component }) => { - const useKeyboardDisabled = component.option('useKeyboard'); - const useNativeEnabled = component.option('useNative'); + const useKeyboardDisabled = !(component.option('useKeyboard') as unknown as boolean); + const useNativeEnabled = component.option('useNative') as unknown as boolean; if (useKeyboardDisabled && useNativeEnabled) { $(component.container()).attr('tabindex', -1); } }, onOptionChanged: ({ fullName, value, component }) => { - const useKeyboardDisabled = component.option('useKeyboard'); + const useKeyboardDisabled = !(component.option('useKeyboard') as unknown as boolean); if (useKeyboardDisabled && fullName === 'useNative' && value === true) { $(component.container()).attr('tabindex', -1); } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts index 2f4dcece1e0b..776fbfdf7b88 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts @@ -105,24 +105,16 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { this.clearIndicatorUpdateInterval(); - const scheduleIndicatorUpdate = (): void => { + // eslint-disable-next-line no-restricted-globals + this.indicatorInterval = setInterval(() => { this.renderCurrentDateTimeIndication(); - this.indicatorInterval = setTimeout( - scheduleIndicatorUpdate, - this.option('indicatorUpdateInterval'), - ); - }; - - this.indicatorInterval = setTimeout( - scheduleIndicatorUpdate, - this.option('indicatorUpdateInterval'), - ); + }, this.option('indicatorUpdateInterval')); } private clearIndicatorUpdateInterval(): void { if (this.indicatorInterval) { - clearTimeout(this.indicatorInterval); - this.indicatorInterval = undefined; + clearInterval(this.indicatorInterval); + delete this.indicatorInterval; } } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts index f53be27fa317..3f48e543ac2e 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts @@ -82,19 +82,15 @@ class SchedulerWorkSpaceMonth extends SchedulerWorkSpace { } protected override needCreateCrossScrolling(): boolean { - return this.option('crossScrollingEnabled') ?? this.isVerticalGroupedWorkSpace(); + return this.option('crossScrollingEnabled') || this.isVerticalGroupedWorkSpace(); } protected override getViewStartByOptions(): Date { - const currentDate: Date = this.option('currentDate') ?? new Date(); - const startDate: Date = this.option('startDate') ?? currentDate; - const firstMonthDate = dateUtils.getFirstMonthDate(startDate) ?? startDate; - return monthUtils.getViewStartByOptions( - startDate, - currentDate, + this.option('startDate'), + this.option('currentDate'), this.option('intervalCount'), - firstMonthDate, + dateUtils.getFirstMonthDate(this.option('startDate')) as Date, ); } From a336d68448ba16d81f8523394936adbe4de74254 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 3 Jun 2026 11:35:51 +0200 Subject: [PATCH 03/22] refactor: changes --- packages/devextreme/js/__internal/scheduler/m_scheduler.ts | 5 +++-- .../js/__internal/scheduler/workspaces/m_work_space.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index 985099ed3a92..812a805e0809 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -33,6 +33,7 @@ import type { } from '@js/ui/scheduler'; import errors from '@js/ui/widget/ui.errors'; import { dateUtilsTs } from '@ts/core/utils/date'; +import type { OptionChanged } from '@ts/core/widget/types'; import { createA11yStatusContainer } from './a11y_status/a11y_status_render'; import { getA11yStatusText } from './a11y_status/a11y_status_text'; @@ -79,7 +80,7 @@ import type { IFieldExpr } from './utils/index'; import { macroTaskArray } from './utils/index'; import { isAgendaWorkspaceComponent } from './utils/is_agenda_workpace_component'; import { VIEWS } from './utils/options/constants_view'; -import type { NormalizedView } from './utils/options/types'; +import type { NormalizedView, SafeSchedulerOptions } from './utils/options/types'; import { getAppointmentGroupValues, setAppointmentGroupValues } from './utils/resource_manager/appointment_groups_utils'; import { ResourceManager } from './utils/resource_manager/resource_manager'; import AppointmentLayoutManager from './view_model/appointments_layout_manager'; @@ -266,7 +267,7 @@ class Scheduler extends SchedulerOptionsBaseWidget { return resolveCallbacks.promise(); } - _optionChanged(args) { + _optionChanged(args: OptionChanged): void { this.schedulerOptionChanged(args); const { value, name } = args; 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 7705dc9b6c18..cf4f65294486 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -28,7 +28,6 @@ import { } from '@js/core/utils/size'; import { isDefined } from '@js/core/utils/type'; import { getWindow, hasWindow } from '@js/core/utils/window'; -import type { dxSchedulerOptions } from '@js/ui/scheduler'; import type { ScrollEvent } from '@js/ui/scroll_view'; import errors from '@js/ui/widget/ui.errors'; import Widget from '@js/ui/widget/ui.widget'; @@ -74,6 +73,7 @@ import tableCreatorModule from '../m_table_creator'; import { utils } from '../m_utils'; import VerticalShader from '../shaders/current_time_shader_vertical'; import type { ResourceLoader } from '../utils/loader/resource_loader'; +import type { SafeSchedulerOptions } from '../utils/options/types'; import { getAppointmentGroupIndex, getSafeGroupValues, @@ -226,7 +226,7 @@ const DEFAULT_WORKSPACE_RENDER_OPTIONS: RenderRWorkspaceOptions = { generateNewData: true, }; -export type WorkspaceOptionsInternal = Omit & { +export type WorkspaceOptionsInternal = Omit & { groups: ResourceLoader[]; getResourceManager: () => ResourceManager; startDate?: Date; @@ -262,6 +262,7 @@ export type WorkspaceOptionChangedOptions = WorkspaceOptionsInternal & { indicatorUpdateInterval?: number; shadeUntilCurrentTime?: boolean; }; + class SchedulerWorkSpace extends Widget { private viewDataProviderValue: any; From 6843e773d26e63bc139aff2dcb5e76296c0c03db Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 3 Jun 2026 12:16:21 +0200 Subject: [PATCH 04/22] fix: fix build --- packages/devextreme/js/__internal/scheduler/m_scheduler.ts | 1 + .../devextreme/js/__internal/scheduler/workspaces/m_agenda.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index 812a805e0809..d231a0e591f1 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -540,6 +540,7 @@ class Scheduler extends SchedulerOptionsBaseWidget { this.updateOption('workSpace', name, value); this.repaint(); break; + // @ts-expect-error case 'skippedDays': break; case 'indicatorTime': diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 09f5b3bb6bb9..272814f925c8 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -200,7 +200,7 @@ class SchedulerAgenda extends WorkSpace { private renderNoData(): void { this.$noDataContainer = $('
').addClass(NODATA_CONTAINER_CLASS) - .html(this.option('noDataText') as string); + .html(this.option('noDataText')); this.$dateTableScrollable.$content().append(this.$noDataContainer); } From 90b3df655ce34c383578c0f3e5268bcdb0db842e Mon Sep 17 00:00:00 2001 From: Sergei Burkatskii Date: Wed, 3 Jun 2026 13:33:53 +0200 Subject: [PATCH 05/22] fix: fix type for interval var Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Sergei Burkatskii --- .../__internal/scheduler/workspaces/m_work_space_indicator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts index 776fbfdf7b88..beffb15deae3 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts @@ -28,7 +28,7 @@ export interface WorkSpaceIndicatorDefaultOptions extends WorkspaceOptionsIntern } class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { - private indicatorInterval?: ReturnType; + private indicatorInterval?: ReturnType; protected getToday(): Date { const viewOffset = this.option('viewOffset') as number; From 2266d69038001b9a5f28f311ff2a3f19f838eb79 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 3 Jun 2026 13:42:04 +0200 Subject: [PATCH 06/22] fix: copilot review --- .../js/__internal/scheduler/m_scheduler.ts | 1 - .../scheduler/utils/options/types.ts | 1 + .../scheduler/workspaces/m_agenda.ts | 24 +++++-------------- .../scheduler/workspaces/m_timeline.ts | 13 +++------- .../scheduler/workspaces/m_timeline_month.ts | 1 - .../scheduler/workspaces/m_work_space.ts | 21 +++++++++------- .../workspaces/m_work_space_indicator.ts | 4 ++-- 7 files changed, 24 insertions(+), 41 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index d231a0e591f1..812a805e0809 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -540,7 +540,6 @@ class Scheduler extends SchedulerOptionsBaseWidget { this.updateOption('workSpace', name, value); this.repaint(); break; - // @ts-expect-error case 'skippedDays': break; case 'indicatorTime': diff --git a/packages/devextreme/js/__internal/scheduler/utils/options/types.ts b/packages/devextreme/js/__internal/scheduler/utils/options/types.ts index 9fe83fedd2b9..c526fe3868bc 100644 --- a/packages/devextreme/js/__internal/scheduler/utils/options/types.ts +++ b/packages/devextreme/js/__internal/scheduler/utils/options/types.ts @@ -30,6 +30,7 @@ export interface SchedulerInternalOptions { disabledExpr: string; visibleExpr: string; allowMultipleCellSelection: boolean; + skippedDays?: number[]; } export interface SchedulerOptionsRule { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 272814f925c8..e3ba339dda82 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -24,7 +24,7 @@ import { VIEWS } from '../utils/options/constants_view'; import { reduceResourcesTree } from '../utils/resource_manager/agenda_group_utils'; import type { GroupNode } from '../utils/resource_manager/types'; import type { ListEntity } from '../view_model/types'; -import WorkSpace, { type WorkspaceDateTableScrollableConfig, type WorkspaceOptionChangedOptions, type WorkspaceOptionsInternal } from './m_work_space'; +import WorkSpace, { type WorkspaceOptionChangedOptions, type WorkspaceOptionsInternal } from './m_work_space'; const { tableCreator } = tableCreatorModule; @@ -394,11 +394,9 @@ class SchedulerAgenda extends WorkSpace { protected renderTableBody( options: AgendaRenderOptions, + // eslint-disable-next-line @typescript-eslint/no-unused-vars delayCellTemplateRendering?: unknown, ): void { - if (delayCellTemplateRendering) { - noop(); - } const cellTemplates: unknown[] = []; const cellTemplateOpt = options.cellTemplate as { render?: (templateOptions: unknown) => unknown; @@ -448,7 +446,7 @@ class SchedulerAgenda extends WorkSpace { }; for (i = 0; i < this.rows.length; i += 1) { - each(this.rows[i], fillTableBody.bind(this)); + each(this.rows[i], fillTableBody); this.setLastRowClass(); } @@ -529,22 +527,12 @@ class SchedulerAgenda extends WorkSpace { updateScrollPosition(date: Date): void { const newDate = this.timeZoneCalculator.createDate(date, 'toGrid'); - const bounds = this.getVisibleBounds(); - - if (this.needUpdateScrollPosition(newDate, bounds)) { + if (this.needUpdateScrollPosition(newDate)) { this.scrollTo(newDate); } } - needUpdateScrollPosition( - date: Date, - appointmentGroupValues?: unknown, - inAllDayRow?: boolean, - ): boolean { - if (appointmentGroupValues || inAllDayRow) { - noop(); - } - + override needUpdateScrollPosition(date: Date): boolean { const bounds = this.getVisibleBounds(); const hours = date.getHours(); const minutes = date.getMinutes(); @@ -558,7 +546,7 @@ class SchedulerAgenda extends WorkSpace { isUpdateNeeded = true; } - if (hours === bounds.bottom.hours && minutes > bounds.top.minutes) { + if (hours === bounds.bottom.hours && minutes > bounds.bottom.minutes) { isUpdateNeeded = true; } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts index 83a999dd6090..62559283e671 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts @@ -57,12 +57,9 @@ class SchedulerTimeline extends SchedulerWorkSpace { protected override getTotalRowCount( groupCount: number, + // eslint-disable-next-line @typescript-eslint/no-unused-vars includeAllDayPanelRows?: unknown, ): number { - if (includeAllDayPanelRows !== undefined) { - noop(); - } - if (this.isHorizontalGroupedWorkSpace()) { return this.getRowCount(); } @@ -70,9 +67,8 @@ class SchedulerTimeline extends SchedulerWorkSpace { return this.getRowCount() * totalGroupCount; } - protected override getFormat(): string { - const format = getGlobalFormatByDataType('time'); - return typeof format === 'string' ? format : 'shorttime'; + protected override getFormat(): string | ((date: Date) => string) { + return getGlobalFormatByDataType('time') as string | ((date: Date) => string) || 'shorttime'; } private getWorkSpaceHeight(): number { @@ -413,9 +409,6 @@ class SchedulerTimeline extends SchedulerWorkSpace { $container: dxElementWrapper, groupCount: number, ): void { - if (height !== undefined) { - noop(); - } // eslint-disable-next-line @typescript-eslint/init-declarations let $indicator: dxElementWrapper | undefined; const width = this.getIndicationWidth(); diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts index 98e20e61fa83..da37cfd36648 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts @@ -39,7 +39,6 @@ class SchedulerTimelineMonth extends SchedulerTimeline { return true; } - // @ts-expect-error protected override getFormat(): (date: Date) => string { return formatWeekdayAndDay; } 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 cf4f65294486..d513d1b3c288 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -10,6 +10,7 @@ import { import pointerEvents from '@js/common/core/events/pointer'; import { addNamespace, isMouseEvent } from '@js/common/core/events/utils/index'; import domAdapter from '@js/core/dom_adapter'; +import type { OptionChangedEventInfo } from '@js/core/dom_component'; import { getPublicElement } from '@js/core/element'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; @@ -28,6 +29,7 @@ import { } from '@js/core/utils/size'; import { isDefined } from '@js/core/utils/type'; import { getWindow, hasWindow } from '@js/core/utils/window'; +import type { InitializedEventInfo } from '@js/events'; import type { ScrollEvent } from '@js/ui/scroll_view'; import errors from '@js/ui/widget/ui.errors'; import Widget from '@js/ui/widget/ui.widget'; @@ -127,9 +129,9 @@ export interface WorkspaceDateTableScrollableConfig { bounceEnabled: boolean; updateManually: boolean; onScroll: (event: ScrollEvent) => void; - onInitialized: (args: { component: Scrollable }) => void; - onOptionChanged: (args: { fullName: string; value: unknown; component: Scrollable }) => void; - direction?: 'both'; + onInitialized: (args: InitializedEventInfo) => void; + onOptionChanged: (args: OptionChangedEventInfo) => void; + direction?: 'horizontal' | 'vertical' | 'both'; onEnd?: () => void; } @@ -140,6 +142,7 @@ export interface WorkspaceHeaderScrollableConfig { useNative: false; updateManually: true; bounceEnabled: false; + scrollByContent?: boolean; onScroll: (event: ScrollEvent) => void; } @@ -254,7 +257,7 @@ export type WorkspaceOptionChangedOptions = WorkspaceOptionsInternal & { scrolling?: unknown; schedulerHeight?: number; schedulerWidth?: number; - agendaDuration?: number | 'month'; + agendaDuration?: number; rowHeight?: number; noDataText?: string; showCurrentTimeIndicator?: boolean; @@ -736,14 +739,14 @@ class SchedulerWorkSpace extends Widget { // To prevent scroll container focus in native mode we set tabindex -1 to container // In simulated mode focusable behavior prevented by useKeyboard: false private option onInitialized: ({ component }) => { - const useKeyboardDisabled = !(component.option('useKeyboard') as unknown as boolean); - const useNativeEnabled = component.option('useNative') as unknown as boolean; + const useKeyboardDisabled = (component?.option('useKeyboard') as unknown as boolean | undefined) === false; + const useNativeEnabled = (component?.option('useNative') as unknown as boolean | undefined) === true; if (useKeyboardDisabled && useNativeEnabled) { - $(component.container()).attr('tabindex', -1); + $(component?.container()).attr('tabindex', -1); } }, onOptionChanged: ({ fullName, value, component }) => { - const useKeyboardDisabled = !(component.option('useKeyboard') as unknown as boolean); + const useKeyboardDisabled = (component.option('useKeyboard') as unknown as boolean | undefined) === false; if (useKeyboardDisabled && fullName === 'useNative' && value === true) { $(component.container()).attr('tabindex', -1); } @@ -1320,7 +1323,7 @@ class SchedulerWorkSpace extends Widget { }); } - protected getFormat() { return abstract(); } + protected getFormat(): string | ((date: Date) => string) { return abstract(); } getWorkArea() { return this.$dateTableContainer; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts index beffb15deae3..0a2e1e043517 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts @@ -76,7 +76,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { ): void { const groupedByDate = this.isGroupedByDate(); const repeatCount = groupedByDate ? 1 : groupCount; - Array.from({ length: repeatCount }).forEach((_, i) => { + for (let i = 0; i < repeatCount; i += 1) { const $indicator = this.createIndicator($container); setWidth( @@ -84,7 +84,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { groupedByDate ? this.getCellWidth() * groupCount : this.getCellWidth(), ); this.groupedStrategy.shiftIndicator($indicator, height, rtlOffset, i); - }); + } } protected createIndicator($container: dxElementWrapper): dxElementWrapper { From 404d3c25bcf3aecc814f78a3edf1a8609827ed9c Mon Sep 17 00:00:00 2001 From: Sergei Burkatskii Date: Wed, 3 Jun 2026 15:41:36 +0200 Subject: [PATCH 07/22] fix: copilot review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Sergei Burkatskii --- .../js/__internal/scheduler/workspaces/m_agenda.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index e3ba339dda82..5ad361ff14f9 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -209,11 +209,8 @@ class SchedulerAgenda extends WorkSpace { protected override toggleHorizontalScrollClass(): void { return noop(); } - protected override createCrossScrollingConfig(): Pick { - return { - onScroll: noop, - onEnd: noop, - }; + protected override needCreateCrossScrolling(): boolean { + return false; } private setGroupHeaderCellsHeight(): void { From b2a6ae9420f5dd123635cde8b06eea62809a9b81 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 3 Jun 2026 16:31:12 +0200 Subject: [PATCH 08/22] fix: copilot review --- .../js/__internal/scheduler/workspaces/m_timeline.ts | 4 ++-- .../js/__internal/scheduler/workspaces/m_timeline_month.ts | 2 +- .../js/__internal/scheduler/workspaces/m_work_space.ts | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts index 62559283e671..1a2a1dcb2dda 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts @@ -1,3 +1,4 @@ +import type { template } from '@js/common'; import registerComponent from '@js/core/component_registrator'; import $, { type dxElementWrapper } from '@js/core/renderer'; import { noop } from '@js/core/utils/common'; @@ -6,7 +7,6 @@ import { extend } from '@js/core/utils/extend'; import { getBoundingRect } from '@js/core/utils/position'; import { getOuterHeight, getOuterWidth, setHeight } from '@js/core/utils/size'; import { hasWindow } from '@js/core/utils/window'; -import type { dxSchedulerOptions } from '@js/ui/scheduler'; import { getGlobalFormatByDataType } from '@ts/core/m_global_format_config'; import { HeaderPanelTimelineComponent } from '@ts/scheduler/r1/components/index'; import { timelineWeekUtils } from '@ts/scheduler/r1/utils/index'; @@ -359,7 +359,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { protected override updateAllDayVisibility(): void { return noop(); } - protected override getDateHeaderTemplate(): dxSchedulerOptions['timeCellTemplate'] { + protected override getDateHeaderTemplate(): template | undefined | null { return this.option('timeCellTemplate'); } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts index da37cfd36648..4dd986dd57a3 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts @@ -27,7 +27,7 @@ class SchedulerTimelineMonth extends SchedulerTimeline { return TIMELINE_CLASS; } - protected override getDateHeaderTemplate(): template | undefined { + protected override getDateHeaderTemplate(): template | undefined | null { return this.option('dateCellTemplate'); } 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 d513d1b3c288..aaece1f81c15 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -1,3 +1,4 @@ +import type { template } from '@js/common'; import { locate, resetPosition } from '@js/common/core/animation/translator'; import { name as clickEventName } from '@js/common/core/events/click'; import { name as contextMenuEventName } from '@js/common/core/events/contextmenu'; @@ -2899,7 +2900,7 @@ class SchedulerWorkSpace extends Widget { this.$element().addClass(className); } - protected getDateHeaderTemplate() { + protected getDateHeaderTemplate(): template | undefined | null { return this.option('dateCellTemplate'); } From 9123940e31d6539baae1226a0eddab7a9f1052df Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 12:25:03 +0200 Subject: [PATCH 09/22] refactor: remove unkown type for cellTemplate --- .../scheduler/workspaces/m_agenda.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 5ad361ff14f9..892e9fbfb0b9 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -3,6 +3,7 @@ import registerComponent from '@js/core/component_registrator'; import domAdapter from '@js/core/dom_adapter'; import { getPublicElement } from '@js/core/element'; import $, { type dxElementWrapper } from '@js/core/renderer'; +import type { TemplateBase } from '@js/core/templates/template_base'; import { noop } from '@js/core/utils/common'; import dateUtils from '@js/core/utils/date'; import { extend } from '@js/core/utils/extend'; @@ -53,7 +54,7 @@ interface AgendaRenderOptions { cellCount?: number; rowClass?: string; cellClass?: string; - cellTemplate?: unknown; + cellTemplate?: TemplateBase; getStartDate?: (rowIndex: number) => Date; } @@ -178,7 +179,7 @@ class SchedulerAgenda extends WorkSpace { } private recalculateAgenda(rows: number[][]): void { - let cellTemplates: unknown[] = []; + let cellTemplates: (() => dxElementWrapper)[] = []; this.cleanView(); if (this.rowsIsEmpty(rows)) { @@ -247,7 +248,10 @@ class SchedulerAgenda extends WorkSpace { return this.$groupTable as dxElementWrapper | null; } - protected override makeGroupRows(): { elements: dxElementWrapper; cellTemplates: unknown[] } { + protected override makeGroupRows(): { + elements: dxElementWrapper; + cellTemplates: (() => dxElementWrapper)[]; + } { const resourceManager = this.option('getResourceManager')(); const allAppointments = (this.option('getFilteredItems') as () => ListEntity[])(); const tree = reduceResourcesTree( @@ -256,11 +260,9 @@ class SchedulerAgenda extends WorkSpace { allAppointments, ); - const cellTemplate = this.option('resourceCellTemplate') as { - render?: (model: unknown) => unknown; - }; + const cellTemplate = this.option('resourceCellTemplate') as TemplateBase | undefined; const getGroupHeaderContentClass = GROUP_HEADER_CONTENT_CLASS; - const cellTemplates: unknown[] = []; + const cellTemplates: (() => dxElementWrapper)[] = []; const table = tableCreator.makeGroupedTableFromJSON(tree, { cellTag: 'th', @@ -394,10 +396,8 @@ class SchedulerAgenda extends WorkSpace { // eslint-disable-next-line @typescript-eslint/no-unused-vars delayCellTemplateRendering?: unknown, ): void { - const cellTemplates: unknown[] = []; - const cellTemplateOpt = options.cellTemplate as { - render?: (templateOptions: unknown) => unknown; - } | undefined; + const cellTemplates: (() => dxElementWrapper)[] = []; + const cellTemplateOpt = options.cellTemplate; this.$rows = []; let i = 0; @@ -466,7 +466,7 @@ class SchedulerAgenda extends WorkSpace { cellCount: 1, rowClass: TIME_PANEL_ROW_CLASS, cellClass: TIME_PANEL_CELL_CLASS, - cellTemplate: this.option('dateCellTemplate'), + cellTemplate: this.option('dateCellTemplate') as TemplateBase | undefined, getStartDate: this.getTimePanelStartDate.bind(this), }); } From decdf71d1d6f536ea32de5fa1b0ca8672b035232 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 12:35:59 +0200 Subject: [PATCH 10/22] refactor: remove unknown type from agenda --- .../scheduler/workspaces/m_agenda.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 892e9fbfb0b9..0ab5bdd0bc78 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -12,6 +12,7 @@ import { setHeight, setOuterHeight } from '@js/core/utils/size'; import type { OptionChanged } from '@ts/core/widget/types'; import { EMPTY_ACTIVE_STATE_UNIT } from '@ts/core/widget/widget'; +import type { Rect } from '../appointments/resizing/types'; import { DATE_TABLE_CLASS, DATE_TABLE_ROW_CLASS, @@ -21,6 +22,7 @@ import { } from '../m_classes'; import tableCreatorModule from '../m_table_creator'; import { agendaUtils, formatWeekday, getVerticalGroupCountClass } from '../r1/utils/index'; +import type { ResourceId } from '../utils/loader/types'; import { VIEWS } from '../utils/options/constants_view'; import { reduceResourcesTree } from '../utils/resource_manager/agenda_group_utils'; import type { GroupNode } from '../utils/resource_manager/types'; @@ -369,7 +371,7 @@ class SchedulerAgenda extends WorkSpace { model: { text: string; date: Date | undefined; - groups: Record; + groups: Record; groupIndex: number | undefined; }; container: Element; @@ -394,7 +396,7 @@ class SchedulerAgenda extends WorkSpace { protected renderTableBody( options: AgendaRenderOptions, // eslint-disable-next-line @typescript-eslint/no-unused-vars - delayCellTemplateRendering?: unknown, + delayCellTemplateRendering?: boolean, ): void { const cellTemplates: (() => dxElementWrapper)[] = []; const cellTemplateOpt = options.cellTemplate; @@ -559,12 +561,16 @@ class SchedulerAgenda extends WorkSpace { } getDOMElementsMetaData(): { - dateTableCellsMeta: Record[][]; - allDayPanelCellsMeta: Record[]; + dateTableCellsMeta: Rect[][]; + allDayPanelCellsMeta: Rect[]; } { return { - dateTableCellsMeta: [[{}]], - allDayPanelCellsMeta: [{}], + dateTableCellsMeta: [[{ + top: 0, left: 0, width: 0, height: 0, + }]], + allDayPanelCellsMeta: [{ + top: 0, left: 0, width: 0, height: 0, + }], }; } } From fb492129d4b15f725a3a5784bfb9d5e731461df9 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 12:43:40 +0200 Subject: [PATCH 11/22] refactor: remove unknown type from timeline --- .../js/__internal/scheduler/workspaces/m_timeline.ts | 8 ++++++-- .../js/__internal/scheduler/workspaces/m_work_space.ts | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts index 1a2a1dcb2dda..730a752dd033 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts @@ -18,6 +18,7 @@ import { import tableCreatorModule from '../m_table_creator'; import timezoneUtils from '../m_utils_time_zone'; import HorizontalShader from '../shaders/current_time_shader_horizontal'; +import type { ResourceLoader } from '../utils/loader/resource_loader'; import { getFirstVisibleDate } from '../utils/skipped_days'; import type { WorkspaceDateTableScrollableConfig, WorkspaceHeaderScrollableConfig } from './m_work_space'; import SchedulerWorkSpace, { type WorkSpaceIndicatorDefaultOptions } from './m_work_space_indicator'; @@ -58,7 +59,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { protected override getTotalRowCount( groupCount: number, // eslint-disable-next-line @typescript-eslint/no-unused-vars - includeAllDayPanelRows?: unknown, + includeAllDayPanelRows?: boolean, ): number { if (this.isHorizontalGroupedWorkSpace()) { return this.getRowCount(); @@ -429,7 +430,10 @@ class SchedulerTimeline extends SchedulerWorkSpace { } } - protected override makeGroupRows(groups: unknown[], groupByDate: boolean): unknown { + protected override makeGroupRows(groups: ResourceLoader[], groupByDate: boolean): { + elements: dxElementWrapper | dxElementWrapper[]; + cellTemplates: (() => dxElementWrapper)[]; + } { const tableCreatorStrategy = this.option('groupOrientation') === 'vertical' ? tableCreator.VERTICAL : tableCreator.HORIZONTAL; return tableCreator.makeGroupedTable( 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 aaece1f81c15..6dac098766f6 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -1210,7 +1210,7 @@ class SchedulerWorkSpace extends Widget { return this.groupedStrategy.getTotalCellCount(groupCount); } - protected getTotalRowCount(groupCount, includeAllDayPanelRows?: any) { + protected getTotalRowCount(groupCount: number, includeAllDayPanelRows?: boolean) { let result = this.groupedStrategy.getTotalRowCount(groupCount); if (includeAllDayPanelRows && this.isAllDayPanelVisible) { @@ -3011,7 +3011,7 @@ class SchedulerWorkSpace extends Widget { protected renderGroupHeader() { const $container = this.getGroupHeaderContainer(); const groupCount = this.getGroupCount(); - let cellTemplates = []; + let cellTemplates: (() => dxElementWrapper)[] = []; if (groupCount) { const groupRows = this.makeGroupRows(this.option('groups'), this.option('groupByDate')); this.attachGroupCountClass(); @@ -3030,7 +3030,10 @@ class SchedulerWorkSpace extends Widget { }); } - protected makeGroupRows(groups, groupByDate): any { + protected makeGroupRows(groups: ResourceLoader[], groupByDate: boolean): { + elements: dxElementWrapper | dxElementWrapper[]; + cellTemplates: (() => dxElementWrapper)[]; + } { const tableCreatorStrategy = this.isVerticalGroupedWorkSpace() ? tableCreator.VERTICAL : tableCreator.HORIZONTAL; return tableCreator.makeGroupedTable( From 96bedd08057bb89f884260e18c54b70ef0d3ef2f Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 13:02:20 +0200 Subject: [PATCH 12/22] refactor: remove unknown from WorkspaceOptionChangedOptions --- .../scheduler/workspaces/m_work_space.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) 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 6dac098766f6..40bb7105a169 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -12,6 +12,7 @@ import pointerEvents from '@js/common/core/events/pointer'; import { addNamespace, isMouseEvent } from '@js/common/core/events/utils/index'; import domAdapter from '@js/core/dom_adapter'; import type { OptionChangedEventInfo } from '@js/core/dom_component'; +import type { DxElement } from '@js/core/element'; import { getPublicElement } from '@js/core/element'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; @@ -45,6 +46,7 @@ import { TimePanelComponent, } from '@ts/scheduler/r1/components/index'; import type { ViewContext } from '@ts/scheduler/r1/components/types'; +import type { TimeZoneCalculator } from '@ts/scheduler/r1/timezone_calculator/calculator'; import { calculateIsGroupedAllDayPanel, calculateViewStartDate, @@ -75,6 +77,7 @@ import type { SubscribeKey, SubscribeMethods } from '../m_subscribes'; import tableCreatorModule from '../m_table_creator'; import { utils } from '../m_utils'; import VerticalShader from '../shaders/current_time_shader_vertical'; +import type { ViewCellData } from '../types'; import type { ResourceLoader } from '../utils/loader/resource_loader'; import type { SafeSchedulerOptions } from '../utils/options/types'; import { @@ -244,18 +247,22 @@ export type WorkspaceOptionsInternal = Omit & { }; export type WorkspaceOptionChangedOptions = WorkspaceOptionsInternal & { - onSelectionChanged?: unknown; - onSelectionEnd?: unknown; - onCellClick?: unknown; - onCellContextMenu?: unknown; + onSelectionChanged?: (args: { selectedCellData: ViewCellData[] }) => void; + onSelectionEnd?: (args: { selectedCellData: ViewCellData[] }) => void; + onCellClick?: (args: { cellData: ViewCellData; cellElement: DxElement; event: Event }) => void; + onCellContextMenu?: (args: { + cellData: ViewCellData; + cellElement: DxElement; + event: Event; + }) => void; viewOffset?: number; groupOrientation?: 'horizontal' | 'vertical'; - timeZoneCalculator?: unknown; + timeZoneCalculator?: TimeZoneCalculator; allDayExpanded?: boolean; width?: number | string; allowMultipleCellSelection?: boolean; - selectedCellData?: unknown; - scrolling?: unknown; + selectedCellData?: ViewCellData[]; + scrolling?: SafeSchedulerOptions['scrolling']; schedulerHeight?: number; schedulerWidth?: number; agendaDuration?: number; From dfdc39fc9b91ac7bfd87a0610c7062697fe6eb09 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 13:04:22 +0200 Subject: [PATCH 13/22] refactor: remove unknown from m_work_space --- .../js/__internal/scheduler/workspaces/m_work_space.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 40bb7105a169..128f91d52179 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -747,14 +747,14 @@ class SchedulerWorkSpace extends Widget { // To prevent scroll container focus in native mode we set tabindex -1 to container // In simulated mode focusable behavior prevented by useKeyboard: false private option onInitialized: ({ component }) => { - const useKeyboardDisabled = (component?.option('useKeyboard') as unknown as boolean | undefined) === false; - const useNativeEnabled = (component?.option('useNative') as unknown as boolean | undefined) === true; + const useKeyboardDisabled = component?.option().useKeyboard === false; + const useNativeEnabled = component?.option().useNative === true; if (useKeyboardDisabled && useNativeEnabled) { $(component?.container()).attr('tabindex', -1); } }, onOptionChanged: ({ fullName, value, component }) => { - const useKeyboardDisabled = (component.option('useKeyboard') as unknown as boolean | undefined) === false; + const useKeyboardDisabled = component.option().useKeyboard === false; if (useKeyboardDisabled && fullName === 'useNative' && value === true) { $(component.container()).attr('tabindex', -1); } From d4a8fa1134e5a8c48cd8ca97afbcf3ec3d69372c Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 13:12:36 +0200 Subject: [PATCH 14/22] fix: copilot review --- .../js/__internal/scheduler/workspaces/m_agenda.ts | 8 +++++--- .../js/__internal/scheduler/workspaces/m_work_space.ts | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 0ab5bdd0bc78..8573c9707b96 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -114,7 +114,9 @@ class SchedulerAgenda extends WorkSpace { } } else if (!this.$groupTable) { this.initGroupTable(); - this.$dateTableScrollable.$content().prepend(this.$groupTable); + if (this.$groupTable) { + this.$dateTableScrollable.$content().prepend(this.$groupTable); + } } super._optionChanged(args); break; @@ -246,8 +248,8 @@ class SchedulerAgenda extends WorkSpace { return rows.filter((row) => row.length && !isEmpty(row)); } - protected override getGroupHeaderContainer(): dxElementWrapper | null { - return this.$groupTable as dxElementWrapper | null; + protected override getGroupHeaderContainer(): dxElementWrapper | null | undefined { + return this.$groupTable; } protected override makeGroupRows(): { 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 128f91d52179..9dc2f5a94ec9 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -333,7 +333,7 @@ class SchedulerWorkSpace extends Widget { private contextMenuAction: any; - protected $groupTable: any; + protected $groupTable: dxElementWrapper | null | undefined; protected $thead: any; From addb52b42f86e491167c104fa56b6edbab9c027f Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 13:12:56 +0200 Subject: [PATCH 15/22] fix: copilot review --- .../devextreme/js/__internal/scheduler/workspaces/m_agenda.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts index 8573c9707b96..e44ba1e9562c 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts @@ -85,7 +85,6 @@ class SchedulerAgenda extends WorkSpace { _getDefaultOptions(): AgendaDefaultOptions { const defaultOptions = extend(super._getDefaultOptions(), { - // Number | "month" agendaDuration: 7, rowHeight: 60, noDataText: '', From 43c130f2b003faf83499481dfaa5849d21abf889 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 13:24:59 +0200 Subject: [PATCH 16/22] fix: fix test --- .../tests/DevExpress.ui.widgets.scheduler/agenda.tests.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js index d326f8bdb558..03d11c28917a 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js @@ -186,8 +186,12 @@ module('Agenda', {}, () => { assert.deepEqual( instance.getDOMElementsMetaData(), { - dateTableCellsMeta: [[{}]], - allDayPanelCellsMeta: [{}], + dateTableCellsMeta: [[{ + top: 0, left: 0, width: 0, height: 0, + }]], + allDayPanelCellsMeta: [{ + top: 0, left: 0, width: 0, height: 0, + }], }, 'Correct DOM meta data', ); From fb60e914544b0a03b3dc7612f92302d798dfad30 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 14:37:22 +0200 Subject: [PATCH 17/22] refactor: remove WorkspaceDateTableScrollableConfig and WorkspaceHeaderScrollableConfig --- .../scheduler/workspaces/m_timeline.ts | 10 +++--- .../scheduler/workspaces/m_work_space.ts | 36 ++++--------------- 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts index 730a752dd033..ab0ec872b6ad 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts @@ -10,6 +10,7 @@ import { hasWindow } from '@js/core/utils/window'; import { getGlobalFormatByDataType } from '@ts/core/m_global_format_config'; import { HeaderPanelTimelineComponent } from '@ts/scheduler/r1/components/index'; import { timelineWeekUtils } from '@ts/scheduler/r1/utils/index'; +import type { ScrollableProperties } from '@ts/ui/scroll_view/scrollable'; import { GROUP_HEADER_CONTENT_CLASS, @@ -20,7 +21,6 @@ import timezoneUtils from '../m_utils_time_zone'; import HorizontalShader from '../shaders/current_time_shader_horizontal'; import type { ResourceLoader } from '../utils/loader/resource_loader'; import { getFirstVisibleDate } from '../utils/skipped_days'; -import type { WorkspaceDateTableScrollableConfig, WorkspaceHeaderScrollableConfig } from './m_work_space'; import SchedulerWorkSpace, { type WorkSpaceIndicatorDefaultOptions } from './m_work_space_indicator'; import type { ViewDataProviderOptions } from './view_model/m_types'; @@ -80,25 +80,25 @@ class SchedulerTimeline extends SchedulerWorkSpace { return getBoundingRect(this.$element().get(0)).height as number; } - protected override dateTableScrollableConfig(): WorkspaceDateTableScrollableConfig { + protected override dateTableScrollableConfig(): ScrollableProperties { const config = super.dateTableScrollableConfig(); const timelineConfig = { direction: HORIZONTAL, }; - return this.option('crossScrollingEnabled') ? config : extend(config, timelineConfig) as WorkspaceDateTableScrollableConfig; + return this.option('crossScrollingEnabled') ? config : extend(config, timelineConfig) as ScrollableProperties; } protected override needCreateCrossScrolling(): boolean { return true; } - protected override headerScrollableConfig(): WorkspaceHeaderScrollableConfig { + protected override headerScrollableConfig(): ScrollableProperties { const config = super.headerScrollableConfig(); return extend(config, { scrollByContent: true, - }) as WorkspaceHeaderScrollableConfig; + }) as ScrollableProperties; } supportAllDayRow(): boolean { 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 9dc2f5a94ec9..ba00c089982e 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -11,7 +11,6 @@ import { import pointerEvents from '@js/common/core/events/pointer'; import { addNamespace, isMouseEvent } from '@js/common/core/events/utils/index'; import domAdapter from '@js/core/dom_adapter'; -import type { OptionChangedEventInfo } from '@js/core/dom_component'; import type { DxElement } from '@js/core/element'; import { getPublicElement } from '@js/core/element'; import type { dxElementWrapper } from '@js/core/renderer'; @@ -31,7 +30,6 @@ import { } from '@js/core/utils/size'; import { isDefined } from '@js/core/utils/type'; import { getWindow, hasWindow } from '@js/core/utils/window'; -import type { InitializedEventInfo } from '@js/events'; import type { ScrollEvent } from '@js/ui/scroll_view'; import errors from '@js/ui/widget/ui.errors'; import Widget from '@js/ui/widget/ui.widget'; @@ -56,7 +54,7 @@ import { isDateAndTimeView, } from '@ts/scheduler/r1/utils/index'; import type { ViewType } from '@ts/scheduler/types'; -import Scrollable from '@ts/ui/scroll_view/scrollable'; +import Scrollable, { type ScrollableProperties } from '@ts/ui/scroll_view/scrollable'; import type NotifyScheduler from '../base/widget_notify_scheduler'; import { APPOINTMENT_SETTINGS_KEY } from '../constants'; @@ -128,28 +126,6 @@ export interface ViewDateGenerationOptions { viewType: ViewType; } -export interface WorkspaceDateTableScrollableConfig { - useKeyboard: boolean; - bounceEnabled: boolean; - updateManually: boolean; - onScroll: (event: ScrollEvent) => void; - onInitialized: (args: InitializedEventInfo) => void; - onOptionChanged: (args: OptionChangedEventInfo) => void; - direction?: 'horizontal' | 'vertical' | 'both'; - onEnd?: () => void; -} - -export interface WorkspaceHeaderScrollableConfig { - useKeyboard: boolean; - showScrollbar: 'never'; - direction: 'horizontal'; - useNative: false; - updateManually: true; - bounceEnabled: false; - scrollByContent?: boolean; - onScroll: (event: ScrollEvent) => void; -} - const { tableCreator } = tableCreatorModule; // The constant is needed so that the dragging is not sharp. To prevent small twitches @@ -733,8 +709,8 @@ class SchedulerWorkSpace extends Widget { this.$allDayTitle = $('
').appendTo(this.$headerPanelEmptyCell); } - protected dateTableScrollableConfig(): WorkspaceDateTableScrollableConfig { - let config: WorkspaceDateTableScrollableConfig = { + protected dateTableScrollableConfig(): ScrollableProperties { + let config: ScrollableProperties = { useKeyboard: false, bounceEnabled: false, updateManually: true, @@ -783,8 +759,8 @@ class SchedulerWorkSpace extends Widget { } protected createCrossScrollingConfig( - { onScroll }: Pick, - ): Pick { + { onScroll }: Pick, + ): Pick { return { direction: 'both', onScroll: (event: ScrollEvent) => { @@ -807,7 +783,7 @@ class SchedulerWorkSpace extends Widget { }; } - protected headerScrollableConfig(): WorkspaceHeaderScrollableConfig { + protected headerScrollableConfig(): ScrollableProperties { return { useKeyboard: false, showScrollbar: 'never', From 7667f58e96b90f965be49db1e450301871995254 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 14:38:43 +0200 Subject: [PATCH 18/22] refactor: type getHeaderPanelCellClass --- .../js/__internal/scheduler/workspaces/m_work_space.ts | 2 +- .../__internal/scheduler/workspaces/m_work_space_indicator.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 ba00c089982e..ead10492f0e2 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -3049,7 +3049,7 @@ class SchedulerWorkSpace extends Widget { return {}; } - protected getHeaderPanelCellClass(i) { + protected getHeaderPanelCellClass(i: number): string { const cellClass = `${HEADER_PANEL_CELL_CLASS} ${HORIZONTAL_SIZES_CLASS}`; return this.groupedStrategy.addAdditionalGroupCellClasses(cellClass, i + 1, undefined, undefined, this.isGroupedByDate()); diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts index 0a2e1e043517..35a758137815 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts @@ -204,7 +204,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { } protected override getHeaderPanelCellClass(i: number): string { - const cellClass = super.getHeaderPanelCellClass(i) as string; + const cellClass = super.getHeaderPanelCellClass(i); if (this.isCurrentTimeHeaderCell(i)) { return `${cellClass} ${HEADER_CURRENT_TIME_CELL_CLASS}`; From a3c94ff4451762519784aa5cb68686bbefdf116f Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 15:24:05 +0200 Subject: [PATCH 19/22] refactor: rename files --- .../__tests__/workspace.base.test.ts | 12 +++---- .../js/__internal/scheduler/m_scheduler.ts | 14 ++++---- .../__internal/scheduler/m_table_creator.ts | 33 +++++++++++++++---- .../workspaces/{m_agenda.ts => agenda.ts} | 7 ++-- .../scheduler/workspaces/m_work_space.ts | 7 ++-- .../workspaces/m_work_space_vertical.ts | 2 +- .../workspaces/{m_timeline.ts => timeline.ts} | 12 +++---- .../{m_timeline_day.ts => timeline_day.ts} | 2 +- ...{m_timeline_month.ts => timeline_month.ts} | 2 +- .../{m_timeline_week.ts => timeline_week.ts} | 2 +- ...{m_work_space_day.ts => work_space_day.ts} | 0 ...e_indicator.ts => work_space_indicator.ts} | 0 ...ork_space_month.ts => work_space_month.ts} | 2 +- ..._work_space_week.ts => work_space_week.ts} | 0 14 files changed, 54 insertions(+), 41 deletions(-) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_agenda.ts => agenda.ts} (98%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_timeline.ts => timeline.ts} (98%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_timeline_day.ts => timeline_day.ts} (93%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_timeline_month.ts => timeline_month.ts} (98%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_timeline_week.ts => timeline_week.ts} (94%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_work_space_day.ts => work_space_day.ts} (100%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_work_space_indicator.ts => work_space_indicator.ts} (100%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_work_space_month.ts => work_space_month.ts} (98%) rename packages/devextreme/js/__internal/scheduler/workspaces/{m_work_space_week.ts => work_space_week.ts} (100%) 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 aa107fcc7977..04865c7268f1 100644 --- a/packages/devextreme/js/__internal/scheduler/__tests__/workspace.base.test.ts +++ b/packages/devextreme/js/__internal/scheduler/__tests__/workspace.base.test.ts @@ -4,13 +4,13 @@ import { import { logger } from '@ts/core/utils/m_console'; 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 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 SchedulerTimelineDay from '../workspaces/timeline_day'; +import SchedulerTimelineMonth from '../workspaces/timeline_month'; +import SchedulerTimelineWeek from '../workspaces/timeline_week'; +import SchedulerWorkSpaceDay from '../workspaces/work_space_day'; +import SchedulerWorkSpaceMonth from '../workspaces/work_space_month'; +import SchedulerWorkSpaceWeek from '../workspaces/work_space_week'; import { setupSchedulerTestEnvironment } from './__mock__/m_mock_scheduler'; jest.mock('@ts/core/m_devices', () => { diff --git a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts index 812a805e0809..2c8eafe77a85 100644 --- a/packages/devextreme/js/__internal/scheduler/m_scheduler.ts +++ b/packages/devextreme/js/__internal/scheduler/m_scheduler.ts @@ -86,13 +86,13 @@ import { ResourceManager } from './utils/resource_manager/resource_manager'; import AppointmentLayoutManager from './view_model/appointments_layout_manager'; import { AppointmentDataSource } from './view_model/m_appointment_data_source'; import type { AppointmentViewModelPlain } from './view_model/types'; -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 SchedulerWorkSpaceDay from './workspaces/m_work_space_day'; -import SchedulerWorkSpaceMonth from './workspaces/m_work_space_month'; -import SchedulerWorkSpaceWeek from './workspaces/m_work_space_week'; +import SchedulerAgenda from './workspaces/agenda'; +import SchedulerTimelineDay from './workspaces/timeline_day'; +import SchedulerTimelineMonth from './workspaces/timeline_month'; +import SchedulerTimelineWeek from './workspaces/timeline_week'; +import SchedulerWorkSpaceDay from './workspaces/work_space_day'; +import SchedulerWorkSpaceMonth from './workspaces/work_space_month'; +import SchedulerWorkSpaceWeek from './workspaces/work_space_week'; const toMs = dateUtils.dateToMilliseconds; diff --git a/packages/devextreme/js/__internal/scheduler/m_table_creator.ts b/packages/devextreme/js/__internal/scheduler/m_table_creator.ts index 766e45e5bee2..105ea92fbd77 100644 --- a/packages/devextreme/js/__internal/scheduler/m_table_creator.ts +++ b/packages/devextreme/js/__internal/scheduler/m_table_creator.ts @@ -1,13 +1,28 @@ +import type { Orientation, template } from '@js/common'; import domAdapter from '@js/core/dom_adapter'; import { getPublicElement } from '@js/core/element'; import { data as elementData } from '@js/core/element_data'; +import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; import { isFunction } from '@js/core/utils/type'; +import type { ResourceLoader } from './utils/loader/resource_loader'; import type { GroupNode } from './utils/resource_manager/types'; const ROW_SELECTOR = 'tr'; +export interface GroupCssClasses { + groupHeaderRowClass?: string; + groupRowClass?: string; + groupHeaderClass: string | ((index: number) => string); + groupHeaderContentClass?: string; +} + +export interface GroupRows { + elements: dxElementWrapper | dxElementWrapper[]; + cellTemplates: (() => dxElementWrapper)[]; +} + class SchedulerTableCreator { readonly VERTICAL = 'vertical'; @@ -129,16 +144,20 @@ class SchedulerTableCreator { return templateCallbacks; } - makeGroupedTable(type, groups, cssClasses, cellCount, cellTemplate, rowCount, groupByDate) { - let rows: any = []; - + makeGroupedTable( + type: Orientation, + groups: ResourceLoader[], + cssClasses: GroupCssClasses, + cellCount: number, + cellTemplate: template | null | undefined, + rowCount: number, + groupByDate: boolean, + ): GroupRows { if (type === this.VERTICAL) { - rows = this.makeVerticalGroupedRows(groups, cssClasses, cellTemplate, rowCount); - } else { - rows = this.makeHorizontalGroupedRows(groups, cssClasses, cellCount, cellTemplate, groupByDate); + return this.makeVerticalGroupedRows(groups, cssClasses, cellTemplate, rowCount); } - return rows; + return this.makeHorizontalGroupedRows(groups, cssClasses, cellCount, cellTemplate, groupByDate); } makeGroupedTableFromJSON(tree: GroupNode[], config?) { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts similarity index 98% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts index e44ba1e9562c..d177dba09c9c 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts @@ -20,7 +20,7 @@ import { GROUP_ROW_CLASS, TIME_PANEL_CLASS, } from '../m_classes'; -import tableCreatorModule from '../m_table_creator'; +import tableCreatorModule, { type GroupRows } from '../m_table_creator'; import { agendaUtils, formatWeekday, getVerticalGroupCountClass } from '../r1/utils/index'; import type { ResourceId } from '../utils/loader/types'; import { VIEWS } from '../utils/options/constants_view'; @@ -251,10 +251,7 @@ class SchedulerAgenda extends WorkSpace { return this.$groupTable; } - protected override makeGroupRows(): { - elements: dxElementWrapper; - cellTemplates: (() => dxElementWrapper)[]; - } { + protected override makeGroupRows(): GroupRows { const resourceManager = this.option('getResourceManager')(); const allAppointments = (this.option('getFilteredItems') as () => ListEntity[])(); const tree = reduceResourcesTree( 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 ead10492f0e2..b22c632e0b87 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -72,7 +72,7 @@ import { } from '../m_classes'; import { CompactAppointmentsHelper } from '../m_compact_appointments_helper'; import type { SubscribeKey, SubscribeMethods } from '../m_subscribes'; -import tableCreatorModule from '../m_table_creator'; +import tableCreatorModule, { type GroupRows } from '../m_table_creator'; import { utils } from '../m_utils'; import VerticalShader from '../shaders/current_time_shader_vertical'; import type { ViewCellData } from '../types'; @@ -3013,10 +3013,7 @@ class SchedulerWorkSpace extends Widget { }); } - protected makeGroupRows(groups: ResourceLoader[], groupByDate: boolean): { - elements: dxElementWrapper | dxElementWrapper[]; - cellTemplates: (() => dxElementWrapper)[]; - } { + protected makeGroupRows(groups: ResourceLoader[], groupByDate: boolean): GroupRows { const tableCreatorStrategy = this.isVerticalGroupedWorkSpace() ? tableCreator.VERTICAL : tableCreator.HORIZONTAL; return tableCreator.makeGroupedTable( diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_vertical.ts b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_vertical.ts index 428b6e95d240..efc3e7a20fc5 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_vertical.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_vertical.ts @@ -1,6 +1,6 @@ import { formatWeekdayAndDay } from '@ts/scheduler/r1/utils/index'; -import SchedulerWorkSpaceIndicator from './m_work_space_indicator'; +import SchedulerWorkSpaceIndicator from './work_space_indicator'; class SchedulerWorkspaceVertical extends SchedulerWorkSpaceIndicator { protected override getFormat() { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts b/packages/devextreme/js/__internal/scheduler/workspaces/timeline.ts similarity index 98% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/timeline.ts index ab0ec872b6ad..e7bfcb951291 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/timeline.ts @@ -16,13 +16,13 @@ import { GROUP_HEADER_CONTENT_CLASS, GROUP_ROW_CLASS, } from '../m_classes'; -import tableCreatorModule from '../m_table_creator'; +import tableCreatorModule, { type GroupRows } from '../m_table_creator'; import timezoneUtils from '../m_utils_time_zone'; import HorizontalShader from '../shaders/current_time_shader_horizontal'; import type { ResourceLoader } from '../utils/loader/resource_loader'; import { getFirstVisibleDate } from '../utils/skipped_days'; -import SchedulerWorkSpace, { type WorkSpaceIndicatorDefaultOptions } from './m_work_space_indicator'; import type { ViewDataProviderOptions } from './view_model/m_types'; +import SchedulerWorkSpace, { type WorkSpaceIndicatorDefaultOptions } from './work_space_indicator'; const { tableCreator } = tableCreatorModule; @@ -430,10 +430,10 @@ class SchedulerTimeline extends SchedulerWorkSpace { } } - protected override makeGroupRows(groups: ResourceLoader[], groupByDate: boolean): { - elements: dxElementWrapper | dxElementWrapper[]; - cellTemplates: (() => dxElementWrapper)[]; - } { + protected override makeGroupRows( + groups: ResourceLoader[], + groupByDate: boolean, + ): GroupRows { const tableCreatorStrategy = this.option('groupOrientation') === 'vertical' ? tableCreator.VERTICAL : tableCreator.HORIZONTAL; return tableCreator.makeGroupedTable( diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_day.ts b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_day.ts similarity index 93% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_day.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/timeline_day.ts index 1d905c9b4db8..96bedf714a6e 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_day.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_day.ts @@ -1,7 +1,7 @@ import registerComponent from '@js/core/component_registrator'; import { VIEWS } from '../utils/options/constants_view'; -import SchedulerTimeline from './m_timeline'; +import SchedulerTimeline from './timeline'; const TIMELINE_CLASS = 'dx-scheduler-timeline-day'; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_month.ts similarity index 98% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/timeline_month.ts index 4dd986dd57a3..e023106ceebb 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_month.ts @@ -5,7 +5,7 @@ import { HeaderPanelComponent } from '@ts/scheduler/r1/components/index'; import { formatWeekdayAndDay, monthUtils } from '@ts/scheduler/r1/utils/index'; import { VIEWS } from '../utils/options/constants_view'; -import SchedulerTimeline from './m_timeline'; +import SchedulerTimeline from './timeline'; import type { ViewDataProviderOptions } from './view_model/m_types'; const TIMELINE_CLASS = 'dx-scheduler-timeline-month'; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_week.ts similarity index 94% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/timeline_week.ts index 941b85ccd88c..8b1bba366d13 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_timeline_week.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_week.ts @@ -1,7 +1,7 @@ import registerComponent from '@js/core/component_registrator'; import { VIEWS } from '../utils/options/constants_view'; -import SchedulerTimeline from './m_timeline'; +import SchedulerTimeline from './timeline'; const TIMELINE_CLASS = 'dx-scheduler-timeline-week'; const TIMELINE_WORK_WEEK_CLASS = 'dx-scheduler-timeline-work-week'; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_day.ts b/packages/devextreme/js/__internal/scheduler/workspaces/work_space_day.ts similarity index 100% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_day.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/work_space_day.ts diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/work_space_indicator.ts similarity index 100% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_indicator.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/work_space_indicator.ts diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/work_space_month.ts similarity index 98% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/work_space_month.ts index 3f48e543ac2e..b0b81f198bb8 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/work_space_month.ts @@ -9,7 +9,7 @@ import { formatWeekday, monthUtils } from '@ts/scheduler/r1/utils/index'; import { utils } from '../m_utils'; import { VIEWS } from '../utils/options/constants_view'; import type { ViewDateGenerationOptions } from './m_work_space'; -import SchedulerWorkSpace from './m_work_space_indicator'; +import SchedulerWorkSpace from './work_space_indicator'; const MONTH_CLASS = 'dx-scheduler-work-space-month'; diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_week.ts b/packages/devextreme/js/__internal/scheduler/workspaces/work_space_week.ts similarity index 100% rename from packages/devextreme/js/__internal/scheduler/workspaces/m_work_space_week.ts rename to packages/devextreme/js/__internal/scheduler/workspaces/work_space_week.ts From 778b3e7efb9ce8a89f1c9ce9862f5bb725d32387 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Thu, 4 Jun 2026 15:25:41 +0200 Subject: [PATCH 20/22] refactor: rename files in tests --- .../DevExpress.ui.widgets.scheduler/agenda.tests.js | 2 +- .../appointments.tests.js | 2 +- .../common.options.tests.js | 2 +- .../currentTimeIndicator.tests.js | 10 +++++----- .../timeline.markup.tests.js | 8 ++++---- .../timeline.tests.js | 8 ++++---- .../workSpace.api.tests.js | 4 ++-- .../workSpace.base.tests.js | 12 ++++++------ .../workSpace.day.tests.js | 2 +- .../workSpace.month.tests.js | 2 +- .../workSpace.navigation.tests.js | 6 +++--- .../workSpace.renovation.tests.js | 12 ++++++------ .../workSpace.viewOffset.tests.js | 10 +++++----- .../workSpace.week.tests.js | 2 +- 14 files changed, 41 insertions(+), 41 deletions(-) diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js index 03d11c28917a..c797bb82269a 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/agenda.tests.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import SchedulerAgenda from '__internal/scheduler/workspaces/m_agenda'; +import SchedulerAgenda from '__internal/scheduler/workspaces/agenda'; import dateLocalization from 'common/core/localization/date'; import { getEmptyResourceManager } from '../../helpers/scheduler/mockResourceManager.js'; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointments.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointments.tests.js index b8b92505bdcb..f53b5fb8b4e2 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointments.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointments.tests.js @@ -6,7 +6,7 @@ import { mockDataAccessor } from '../../helpers/scheduler/mockDataAccessor.js'; import { getEmptyResourceManager } from '../../helpers/scheduler/mockResourceManager.js'; import $ from 'jquery'; -import '__internal/scheduler/workspaces/m_work_space_week'; +import '__internal/scheduler/workspaces/work_space_week'; import SchedulerAppointments from '__internal/scheduler/appointments/m_appointment_collection'; import dblclickEvent from 'common/core/events/dblclick'; import translator from 'common/core/animation/translator'; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js index 575f8438f9cd..a69ec3fa47e1 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/common.options.tests.js @@ -7,7 +7,7 @@ import 'fluent_blue_light.css!'; import { triggerHidingEvent, triggerShownEvent } from 'common/core/events/visibility_change'; import $ from 'jquery'; -import dxSchedulerWorkSpaceDay from '__internal/scheduler/workspaces/m_work_space_day'; +import dxSchedulerWorkSpaceDay from '__internal/scheduler/workspaces/work_space_day'; import keyboardMock from '../../helpers/keyboardMock.js'; import pointerMock from '../../helpers/pointerMock.js'; import { createWrapper, initTestMarkup } from '../../helpers/scheduler/helpers.js'; 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 4f59b1b9f1ee..7b9b551e61aa 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 @@ -17,11 +17,11 @@ const SCHEDULER_DATE_TIME_INDICATOR_CLASS = 'dx-scheduler-date-time-indicator'; import 'fluent_blue_light.css!'; -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_month'; +import '__internal/scheduler/workspaces/work_space_day'; +import '__internal/scheduler/workspaces/work_space_week'; +import '__internal/scheduler/workspaces/timeline_day'; +import '__internal/scheduler/workspaces/timeline_week'; +import '__internal/scheduler/workspaces/timeline_month'; QUnit.testStart(function() { $('#qunit-fixture').html('
'); 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 edf90f87d420..c86c7e5a2290 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 @@ -1,8 +1,8 @@ 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 SchedulerTimelineMonth from '__internal/scheduler/workspaces/m_timeline_month'; +import SchedulerTimeline from '__internal/scheduler/workspaces/timeline'; +import SchedulerTimelineDay from '__internal/scheduler/workspaces/timeline_day'; +import SchedulerTimelineWeek from '__internal/scheduler/workspaces/timeline_week'; +import SchedulerTimelineMonth from '__internal/scheduler/workspaces/timeline_month'; import dateLocalization from 'common/core/localization/date'; import SchedulerWorkSpaceVerticalStrategy from '__internal/scheduler/workspaces/m_work_space_grouped_strategy_vertical'; import SchedulerWorkSpaceHorizontalStrategy from '__internal/scheduler/workspaces/m_work_space_grouped_strategy_horizontal'; 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 260f29480ce7..46cf4849d49d 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 @@ -5,10 +5,10 @@ import resizeCallbacks from 'core/utils/resize_callbacks'; import { triggerHidingEvent, triggerShownEvent } from 'common/core/events/visibility_change'; import 'fluent_blue_light.css!'; import $ from 'jquery'; -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/timeline'; +import '__internal/scheduler/workspaces/timeline_day'; +import '__internal/scheduler/workspaces/timeline_month'; +import '__internal/scheduler/workspaces/timeline_week'; import keyboardMock from '../../helpers/keyboardMock.js'; import pointerMock from '../../helpers/pointerMock.js'; import { diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.api.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.api.tests.js index 98202db67e19..e989cec079e4 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.api.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.api.tests.js @@ -1,8 +1,8 @@ import 'fluent_blue_light.css!'; import $ from 'jquery'; -import '__internal/scheduler/workspaces/m_work_space_month'; -import '__internal/scheduler/workspaces/m_work_space_week'; +import '__internal/scheduler/workspaces/work_space_month'; +import '__internal/scheduler/workspaces/work_space_week'; import { applyWorkspaceGroups, diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.base.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.base.tests.js index adf684903370..f7196289aba7 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.base.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.base.tests.js @@ -4,12 +4,12 @@ import 'fluent_blue_light.css!'; import $ from 'jquery'; import dateLocalization from 'common/core/localization/date'; -import '__internal/scheduler/workspaces/m_work_space_day'; -import '__internal/scheduler/workspaces/m_work_space_week'; -import '__internal/scheduler/workspaces/m_work_space_month'; -import '__internal/scheduler/workspaces/m_timeline_day'; -import '__internal/scheduler/workspaces/m_timeline_week'; -import '__internal/scheduler/workspaces/m_timeline_month'; +import '__internal/scheduler/workspaces/work_space_day'; +import '__internal/scheduler/workspaces/work_space_week'; +import '__internal/scheduler/workspaces/work_space_month'; +import '__internal/scheduler/workspaces/timeline_day'; +import '__internal/scheduler/workspaces/timeline_week'; +import '__internal/scheduler/workspaces/timeline_month'; import { getEmptyResourceManager } from '../../helpers/scheduler/mockResourceManager.js'; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.day.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.day.tests.js index ff8b429828d3..1cafe7833db2 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.day.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.day.tests.js @@ -4,7 +4,7 @@ import $ from 'jquery'; import resizeCallbacks from 'core/utils/resize_callbacks'; import dateLocalization from 'common/core/localization/date'; -import '__internal/scheduler/workspaces/m_work_space_day'; +import '__internal/scheduler/workspaces/work_space_day'; import { applyWorkspaceGroups, diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.month.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.month.tests.js index 8b30fd37d9a2..70f6af424931 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.month.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.month.tests.js @@ -3,7 +3,7 @@ import resizeCallbacks from 'core/utils/resize_callbacks'; import 'fluent_blue_light.css!'; import $ from 'jquery'; -import '__internal/scheduler/workspaces/m_work_space_month'; +import '__internal/scheduler/workspaces/work_space_month'; import { getGroupWidth } from '__internal/scheduler/workspaces/helpers/m_position_helper'; import { getEmptyResourceManager, getWorkspaceResourceConfig } from '../../helpers/scheduler/mockResourceManager.js'; 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 c36905404fdf..e37dccf31854 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 @@ -3,9 +3,9 @@ import { noop } from 'core/utils/common'; import { isRenderer } from 'core/utils/type'; 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_week'; +import '__internal/scheduler/workspaces/work_space_day'; +import '__internal/scheduler/workspaces/work_space_month'; +import '__internal/scheduler/workspaces/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.renovation.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.renovation.tests.js index 551cc2999625..1bb8cb716820 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.renovation.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.renovation.tests.js @@ -5,13 +5,13 @@ import $ from 'jquery'; import { supportedScrollingModes } from '../../helpers/scheduler/helpers.js'; -import '__internal/scheduler/workspaces/m_work_space_day'; -import '__internal/scheduler/workspaces/m_work_space_month'; -import '__internal/scheduler/workspaces/m_work_space_week'; +import '__internal/scheduler/workspaces/work_space_day'; +import '__internal/scheduler/workspaces/work_space_month'; +import '__internal/scheduler/workspaces/work_space_week'; -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/timeline_day'; +import '__internal/scheduler/workspaces/timeline_month'; +import '__internal/scheduler/workspaces/timeline_week'; import keyboardMock from '../../helpers/keyboardMock.js'; import { applyWorkspaceGroups, getEmptyResourceManager } from '../../helpers/scheduler/mockResourceManager.js'; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.viewOffset.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.viewOffset.tests.js index b51e7d6b42bc..ecc6fe4c8302 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.viewOffset.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/workSpace.viewOffset.tests.js @@ -1,11 +1,11 @@ import $ from 'jquery'; // workspace imports -import '__internal/scheduler/workspaces/m_work_space_day'; -import '__internal/scheduler/workspaces/m_work_space_week'; -import '__internal/scheduler/workspaces/m_work_space_month'; -import '__internal/scheduler/workspaces/m_timeline_day'; -import '__internal/scheduler/workspaces/m_timeline_month'; +import '__internal/scheduler/workspaces/work_space_day'; +import '__internal/scheduler/workspaces/work_space_week'; +import '__internal/scheduler/workspaces/work_space_month'; +import '__internal/scheduler/workspaces/timeline_day'; +import '__internal/scheduler/workspaces/timeline_month'; import { getEmptyResourceManager } from '../../helpers/scheduler/mockResourceManager.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 30fa89fd58fe..9894ae7fcd55 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 @@ -3,7 +3,7 @@ import { triggerShownEvent } from 'common/core/events/visibility_change'; import 'fluent_blue_light.css!'; import $ from 'jquery'; -import '__internal/scheduler/workspaces/m_work_space_week'; +import '__internal/scheduler/workspaces/work_space_week'; import { applyWorkspaceGroups, From e0289f95d893e6f0b1a91c81fe81422a65bbe66e Mon Sep 17 00:00:00 2001 From: Sergei Burkatskii Date: Fri, 5 Jun 2026 11:19:41 +0200 Subject: [PATCH 21/22] refactor: review --- .../__internal/scheduler/m_table_creator.ts | 5 +- .../__internal/scheduler/workspaces/agenda.ts | 36 ++--- .../scheduler/workspaces/m_work_space.ts | 138 ++++++++++-------- .../scheduler/workspaces/timeline.ts | 15 +- .../scheduler/workspaces/timeline_month.ts | 4 +- .../workspaces/work_space_indicator.ts | 18 +-- 6 files changed, 110 insertions(+), 106 deletions(-) diff --git a/packages/devextreme/js/__internal/scheduler/m_table_creator.ts b/packages/devextreme/js/__internal/scheduler/m_table_creator.ts index 105ea92fbd77..d38fdba2f3f1 100644 --- a/packages/devextreme/js/__internal/scheduler/m_table_creator.ts +++ b/packages/devextreme/js/__internal/scheduler/m_table_creator.ts @@ -1,9 +1,10 @@ -import type { Orientation, template } from '@js/common'; +import type { Orientation } from '@js/common'; import domAdapter from '@js/core/dom_adapter'; import { getPublicElement } from '@js/core/element'; import { data as elementData } from '@js/core/element_data'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; +import type { TemplateBase } from '@js/core/templates/template_base'; import { isFunction } from '@js/core/utils/type'; import type { ResourceLoader } from './utils/loader/resource_loader'; @@ -149,7 +150,7 @@ class SchedulerTableCreator { groups: ResourceLoader[], cssClasses: GroupCssClasses, cellCount: number, - cellTemplate: template | null | undefined, + cellTemplate: TemplateBase | null | undefined, rowCount: number, groupByDate: boolean, ): GroupRows { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts b/packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts index d177dba09c9c..777d5b59a30a 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts @@ -27,7 +27,7 @@ import { VIEWS } from '../utils/options/constants_view'; import { reduceResourcesTree } from '../utils/resource_manager/agenda_group_utils'; import type { GroupNode } from '../utils/resource_manager/types'; import type { ListEntity } from '../view_model/types'; -import WorkSpace, { type WorkspaceOptionChangedOptions, type WorkspaceOptionsInternal } from './m_work_space'; +import WorkSpace, { type WorkspaceOptionsInternal } from './m_work_space'; const { tableCreator } = tableCreatorModule; @@ -44,19 +44,13 @@ const LAST_ROW_CLASS = 'dx-scheduler-date-table-last-row'; const INNER_CELL_MARGIN = 5; const OUTER_CELL_MARGIN = 20; -interface AgendaDefaultOptions extends WorkspaceOptionsInternal { - agendaDuration: number; - rowHeight: number; - noDataText: string; -} - interface AgendaRenderOptions { container: Element; rowCount?: number; cellCount?: number; rowClass?: string; cellClass?: string; - cellTemplate?: TemplateBase; + cellTemplate?: TemplateBase | null; getStartDate?: (rowIndex: number) => Date; } @@ -83,17 +77,15 @@ class SchedulerAgenda extends WorkSpace { super._init(); } - _getDefaultOptions(): AgendaDefaultOptions { - const defaultOptions = extend(super._getDefaultOptions(), { + _getDefaultOptions(): WorkspaceOptionsInternal { + return extend(super._getDefaultOptions(), { agendaDuration: 7, rowHeight: 60, noDataText: '', - }) as AgendaDefaultOptions; - - return defaultOptions; + }) as WorkspaceOptionsInternal; } - _optionChanged(args: OptionChanged): void { + _optionChanged(args: OptionChanged): void { const { name } = args; const { value } = args; @@ -143,7 +135,7 @@ class SchedulerAgenda extends WorkSpace { } protected override getRowCount(): number { - return this.option('agendaDuration') as number; + return this.option('agendaDuration'); } getCellCount(): number { @@ -151,7 +143,7 @@ class SchedulerAgenda extends WorkSpace { } protected override getTimePanelRowCount(): number { - return this.option('agendaDuration') as number; + return this.option('agendaDuration'); } protected renderAllDayPanel(): void { return noop(); } @@ -260,7 +252,7 @@ class SchedulerAgenda extends WorkSpace { allAppointments, ); - const cellTemplate = this.option('resourceCellTemplate') as TemplateBase | undefined; + const cellTemplate = this.option('resourceCellTemplate'); const getGroupHeaderContentClass = GROUP_HEADER_CONTENT_CLASS; const cellTemplates: (() => dxElementWrapper)[] = []; @@ -466,7 +458,7 @@ class SchedulerAgenda extends WorkSpace { cellCount: 1, rowClass: TIME_PANEL_ROW_CLASS, cellClass: TIME_PANEL_CELL_CLASS, - cellTemplate: this.option('dateCellTemplate') as TemplateBase | undefined, + cellTemplate: this.option('dateCellTemplate'), getStartDate: this.getTimePanelStartDate.bind(this), }); } @@ -479,7 +471,7 @@ class SchedulerAgenda extends WorkSpace { } private getRowHeight(rowSize: number): number { - const baseHeight = this.option('rowHeight') as number; + const baseHeight = this.option('rowHeight'); const innerOffset = (rowSize - 1) * INNER_CELL_MARGIN; return rowSize ? (baseHeight * rowSize) + innerOffset + OUTER_CELL_MARGIN : 0; @@ -498,7 +490,7 @@ class SchedulerAgenda extends WorkSpace { const rows = agendaUtils.calculateRows( appointments, - this.option('agendaDuration') as number, + this.option('agendaDuration'), this.getStartViewDate(), this.resourceManager.groupCount(), ); @@ -506,14 +498,14 @@ class SchedulerAgenda extends WorkSpace { } getAgendaVerticalStepHeight(): number { - return this.option('rowHeight') as number; + return this.option('rowHeight'); } getEndViewDate(): Date { return agendaUtils.calculateEndViewDate( this.getStartViewDate(), this.option('endDayHour'), - this.option('agendaDuration') as number, + this.option('agendaDuration'), ); } 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 b22c632e0b87..ca2f14f7f3cb 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -1,4 +1,3 @@ -import type { template } from '@js/common'; import { locate, resetPosition } from '@js/common/core/animation/translator'; import { name as clickEventName } from '@js/common/core/events/click'; import { name as contextMenuEventName } from '@js/common/core/events/contextmenu'; @@ -11,10 +10,10 @@ import { import pointerEvents from '@js/common/core/events/pointer'; import { addNamespace, isMouseEvent } from '@js/common/core/events/utils/index'; import domAdapter from '@js/core/dom_adapter'; -import type { DxElement } from '@js/core/element'; import { getPublicElement } from '@js/core/element'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; +import type { TemplateBase } from '@js/core/templates/template_base'; import { noop } from '@js/core/utils/common'; import { compileGetter } from '@js/core/utils/data'; import dateUtils from '@js/core/utils/date'; @@ -30,6 +29,7 @@ import { } from '@js/core/utils/size'; import { isDefined } from '@js/core/utils/type'; import { getWindow, hasWindow } from '@js/core/utils/window'; +import type { AllDayPanelMode, CellClickEvent, CellContextMenuEvent } from '@js/ui/scheduler'; import type { ScrollEvent } from '@js/ui/scroll_view'; import errors from '@js/ui/widget/ui.errors'; import Widget from '@js/ui/widget/ui.widget'; @@ -53,7 +53,7 @@ import { getViewStartByOptions, isDateAndTimeView, } from '@ts/scheduler/r1/utils/index'; -import type { ViewType } from '@ts/scheduler/types'; +import type { GroupOrientation, ViewType } from '@ts/scheduler/types'; import Scrollable, { type ScrollableProperties } from '@ts/ui/scroll_view/scrollable'; import type NotifyScheduler from '../base/widget_notify_scheduler'; @@ -77,7 +77,6 @@ import { utils } from '../m_utils'; import VerticalShader from '../shaders/current_time_shader_vertical'; import type { ViewCellData } from '../types'; import type { ResourceLoader } from '../utils/loader/resource_loader'; -import type { SafeSchedulerOptions } from '../utils/options/types'; import { getAppointmentGroupIndex, getSafeGroupValues, @@ -86,6 +85,7 @@ import { getLeafGroupValues } from '../utils/resource_manager/group_utils'; import type { ResourceManager } from '../utils/resource_manager/resource_manager'; import type { GroupValues, RawGroupValues } from '../utils/resource_manager/types'; import { getSkippedDaysCount as countSkippedDays } from '../utils/skipped_days'; +import type { ListEntity } from '../view_model/types'; import { getAllDayHeight, getCellHeight, @@ -209,46 +209,68 @@ const DEFAULT_WORKSPACE_RENDER_OPTIONS: RenderRWorkspaceOptions = { generateNewData: true, }; -export type WorkspaceOptionsInternal = Omit & { - groups: ResourceLoader[]; +export interface WorkspaceOptionsInternal { + newAppointments: boolean; + resources: ResourceLoader[]; getResourceManager: () => ResourceManager; - startDate?: Date; - currentDate: Date; - intervalCount: number; - hoursInterval: number; + getFilteredItems: () => ListEntity[]; + noDataText: string; + firstDayOfWeek: number; startDayHour: number; endDayHour: number; - skippedDays?: number[]; - type?: ViewType; -}; + viewOffset: number; + tabIndex: number; + accessKey: string; + focusStateEnabled: boolean; + showAllDayPanel: boolean; + showCurrentTimeIndicator: boolean; + indicatorTime: Date; + indicatorUpdateInterval: number; + shadeUntilCurrentTime: boolean; + crossScrollingEnabled: boolean; + dataCellTemplate: TemplateBase | null; + timeCellTemplate: TemplateBase | null; + resourceCellTemplate: TemplateBase | null; + dateCellTemplate: TemplateBase | null; + allowMultipleCellSelection: boolean; + selectedCellData: ViewCellData[]; + onSelectionChanged: ((args: { selectedCellData: ViewCellData[] }) => void); + onSelectionEnd: ((args: { selectedCellData: ViewCellData[] }) => void); + groupByDate: boolean; + skippedDays: number[]; + scrolling: { + mode: 'standard' | 'virtual'; + orientation: 'horizontal' | 'vertical' | 'both'; + }; + draggingMode: 'outlook' | 'default'; + timeZoneCalculator: TimeZoneCalculator; + schedulerHeight: string | number | undefined; + schedulerWidth: string | number | undefined; + allDayPanelMode: AllDayPanelMode; + onSelectedCellsClick: (result: object, groups: GroupValues) => void; + renderAppointments: () => void; + onShowAllDayPanel: (isVisible: boolean) => void; + getHeaderHeight: (() => number); + onScrollEnd: () => void; + onInitialized: (e: { element: dxElementWrapper }) => void; + onDisposing: () => void; + + notifyScheduler: NotifyScheduler; + groups: ResourceLoader[]; + onCellClick: ((e: CellClickEvent) => void) | undefined; + onCellContextMenu: ((e: CellContextMenuEvent) => void) | undefined; + currentDate: Date; + hoursInterval: number; + allDayExpanded: boolean; -export type WorkspaceOptionChangedOptions = WorkspaceOptionsInternal & { - onSelectionChanged?: (args: { selectedCellData: ViewCellData[] }) => void; - onSelectionEnd?: (args: { selectedCellData: ViewCellData[] }) => void; - onCellClick?: (args: { cellData: ViewCellData; cellElement: DxElement; event: Event }) => void; - onCellContextMenu?: (args: { - cellData: ViewCellData; - cellElement: DxElement; - event: Event; - }) => void; - viewOffset?: number; - groupOrientation?: 'horizontal' | 'vertical'; - timeZoneCalculator?: TimeZoneCalculator; - allDayExpanded?: boolean; - width?: number | string; - allowMultipleCellSelection?: boolean; - selectedCellData?: ViewCellData[]; - scrolling?: SafeSchedulerOptions['scrolling']; - schedulerHeight?: number; - schedulerWidth?: number; - agendaDuration?: number; - rowHeight?: number; - noDataText?: string; - showCurrentTimeIndicator?: boolean; - indicatorTime?: Date; - indicatorUpdateInterval?: number; - shadeUntilCurrentTime?: boolean; -}; + agendaDuration: number; + intervalCount: number; + rowHeight: number; + startDate?: Date; + type?: ViewType; + groupOrientation: GroupOrientation; + width: number +} class SchedulerWorkSpace extends Widget { private viewDataProviderValue: any; @@ -742,8 +764,8 @@ class SchedulerWorkSpace extends Widget { } if (this.isVirtualScrolling() - && (this.virtualScrollingDispatcher.horizontalScrollingAllowed - || this.virtualScrollingDispatcher.height)) { + && (this.virtualScrollingDispatcher.horizontalScrollingAllowed + || this.virtualScrollingDispatcher.height)) { const currentOnScroll = config.onScroll; config = { ...config, @@ -1593,8 +1615,8 @@ class SchedulerWorkSpace extends Widget { isGroupedByDate() { return this.option('groupByDate') - && this.isHorizontalGroupedWorkSpace() - && this.getGroupCount() > 0; + && this.isHorizontalGroupedWorkSpace() + && this.getGroupCount() > 0; } // TODO: refactor current time indicator @@ -1827,9 +1849,9 @@ class SchedulerWorkSpace extends Widget { const cellEndTime = cellEndDate.getTime(); if (((!inAllDayRow && cellStartTime <= time - && time < cellEndTime) - || (inAllDayRow && trimmedTime === cellStartTime)) - && groupIndex === cellGroupIndex) { + && time < cellEndTime) + || (inAllDayRow && trimmedTime === cellStartTime)) + && groupIndex === cellGroupIndex) { return false; } return currentResult; @@ -1870,9 +1892,9 @@ class SchedulerWorkSpace extends Widget { const rowIndex = index / totalColumnCount; if (scrolledColumnCount <= columnIndex - && columnIndex < columnCount - && scrolledRowCount <= rowIndex - && rowIndex < rowCount) { + && columnIndex < columnCount + && scrolledRowCount <= rowIndex + && rowIndex < rowCount) { result.push($cell); } }); @@ -1926,7 +1948,7 @@ class SchedulerWorkSpace extends Widget { } private isValidScrollDate(date, throwWarning = true) { - const viewOffset = this.option('viewOffset') as number; + const viewOffset = this.option('viewOffset'); const min = new Date(this.getStartViewDate().getTime() + viewOffset); const max = new Date(this.getEndViewDate().getTime() + viewOffset); @@ -2241,7 +2263,7 @@ class SchedulerWorkSpace extends Widget { const elements = (domAdapter as any).elementsFromPoint(point.x, point.y); const cell = elements.find((element) => element.classList.contains('dx-scheduler-date-table-cell') - || element.classList.contains('dx-scheduler-all-day-table-cell')); + || element.classList.contains('dx-scheduler-all-day-table-cell')); return cell ? $(cell) : null; } @@ -2404,7 +2426,7 @@ class SchedulerWorkSpace extends Widget { return defaultOptions; } - _optionChanged(args: OptionChanged): void { + _optionChanged(args: OptionChanged): void { switch (args.name) { case 'startDayHour': case 'endDayHour': @@ -2883,7 +2905,7 @@ class SchedulerWorkSpace extends Widget { this.$element().addClass(className); } - protected getDateHeaderTemplate(): template | undefined | null { + protected getDateHeaderTemplate(): TemplateBase | null | undefined { return this.option('dateCellTemplate'); } @@ -3169,10 +3191,10 @@ const createDragBehaviorConfig = ( const isCurrentSchedulerElement = dateTables.find(el).length === 1; return isCurrentSchedulerElement - && ( - classList.contains(DATE_TABLE_CELL_CLASS) - || classList.contains(ALL_DAY_TABLE_CELL_CLASS) - ); + && ( + classList.contains(DATE_TABLE_CELL_CLASS) + || classList.contains(ALL_DAY_TABLE_CELL_CLASS) + ); }); if (droppableCell) { diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/timeline.ts b/packages/devextreme/js/__internal/scheduler/workspaces/timeline.ts index e7bfcb951291..5cd7ab0abd71 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/timeline.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/timeline.ts @@ -1,6 +1,6 @@ -import type { template } from '@js/common'; import registerComponent from '@js/core/component_registrator'; import $, { type dxElementWrapper } from '@js/core/renderer'; +import type { TemplateBase } from '@js/core/templates/template_base'; import { noop } from '@js/core/utils/common'; import dateUtils from '@js/core/utils/date'; import { extend } from '@js/core/utils/extend'; @@ -21,8 +21,9 @@ import timezoneUtils from '../m_utils_time_zone'; import HorizontalShader from '../shaders/current_time_shader_horizontal'; import type { ResourceLoader } from '../utils/loader/resource_loader'; import { getFirstVisibleDate } from '../utils/skipped_days'; +import type { WorkspaceOptionsInternal } from './m_work_space'; import type { ViewDataProviderOptions } from './view_model/m_types'; -import SchedulerWorkSpace, { type WorkSpaceIndicatorDefaultOptions } from './work_space_indicator'; +import SchedulerWorkSpace from './work_space_indicator'; const { tableCreator } = tableCreatorModule; @@ -37,10 +38,6 @@ const HEADER_PANEL_WEEK_CELL_CLASS = 'dx-scheduler-header-panel-week-cell'; const HORIZONTAL = 'horizontal'; const toMs = dateUtils.dateToMilliseconds; -interface TimelineDefaultOptions extends WorkSpaceIndicatorDefaultOptions { - groupOrientation: 'vertical'; -} - class SchedulerTimeline extends SchedulerWorkSpace { protected override $sidebarTable!: dxElementWrapper; @@ -348,10 +345,10 @@ class SchedulerTimeline extends SchedulerWorkSpace { ); } - _getDefaultOptions(): TimelineDefaultOptions { + _getDefaultOptions(): WorkspaceOptionsInternal { return extend(super._getDefaultOptions(), { groupOrientation: 'vertical', - }) as TimelineDefaultOptions; + }) as WorkspaceOptionsInternal; } protected override createWorkSpaceElements(): void { @@ -360,7 +357,7 @@ class SchedulerTimeline extends SchedulerWorkSpace { protected override updateAllDayVisibility(): void { return noop(); } - protected override getDateHeaderTemplate(): template | undefined | null { + protected override getDateHeaderTemplate(): TemplateBase | null | undefined { return this.option('timeCellTemplate'); } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/timeline_month.ts b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_month.ts index e023106ceebb..3e0301003fc9 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/timeline_month.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/timeline_month.ts @@ -1,5 +1,5 @@ import registerComponent from '@js/core/component_registrator'; -import type { template } from '@js/core/templates/template'; +import type { TemplateBase } from '@js/core/templates/template_base'; import dateUtils from '@js/core/utils/date'; import { HeaderPanelComponent } from '@ts/scheduler/r1/components/index'; import { formatWeekdayAndDay, monthUtils } from '@ts/scheduler/r1/utils/index'; @@ -27,7 +27,7 @@ class SchedulerTimelineMonth extends SchedulerTimeline { return TIMELINE_CLASS; } - protected override getDateHeaderTemplate(): template | undefined | null { + protected override getDateHeaderTemplate(): TemplateBase | null | undefined { return this.option('dateCellTemplate'); } diff --git a/packages/devextreme/js/__internal/scheduler/workspaces/work_space_indicator.ts b/packages/devextreme/js/__internal/scheduler/workspaces/work_space_indicator.ts index 35a758137815..443cb28b4c2b 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/work_space_indicator.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/work_space_indicator.ts @@ -12,7 +12,6 @@ import { getToday } from '@ts/scheduler/r1/utils/index'; import { HEADER_CURRENT_TIME_CELL_CLASS } from '../m_classes'; import timezoneUtils from '../m_utils_time_zone'; import SchedulerWorkSpace, { - type WorkspaceOptionChangedOptions, type WorkspaceOptionsInternal, } from './m_work_space'; @@ -20,19 +19,12 @@ const toMs = dateUtils.dateToMilliseconds; const SCHEDULER_DATE_TIME_INDICATOR_CLASS = 'dx-scheduler-date-time-indicator'; -export interface WorkSpaceIndicatorDefaultOptions extends WorkspaceOptionsInternal { - showCurrentTimeIndicator: boolean; - indicatorTime: Date; - indicatorUpdateInterval: number; - shadeUntilCurrentTime: boolean; -} - class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { private indicatorInterval?: ReturnType; protected getToday(): Date { - const viewOffset = this.option('viewOffset') as number; - const today = getToday(this.option('indicatorTime') as Date, this.timeZoneCalculator); + const viewOffset = this.option('viewOffset'); + const today = getToday(this.option('indicatorTime'), this.timeZoneCalculator); return dateUtilsTs.addOffsets(today, -viewOffset); } @@ -236,7 +228,7 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { this.setIndicationUpdateInterval(); } - _optionChanged(args: OptionChanged): void { + _optionChanged(args: OptionChanged): void { switch (args.name) { case 'showCurrentTimeIndicator': case 'indicatorTime': @@ -259,13 +251,13 @@ class SchedulerWorkSpaceIndicator extends SchedulerWorkSpace { } } - _getDefaultOptions(): WorkSpaceIndicatorDefaultOptions { + _getDefaultOptions(): WorkspaceOptionsInternal { return extend(super._getDefaultOptions(), { showCurrentTimeIndicator: true, indicatorTime: new Date(), indicatorUpdateInterval: 5 * toMs('minute'), shadeUntilCurrentTime: true, - }) as WorkSpaceIndicatorDefaultOptions; + }) as WorkspaceOptionsInternal; } protected getCurrentTimePanelCellIndices(): number[] { From d7abc5b747b98567c95b89c227140435927afc2b Mon Sep 17 00:00:00 2001 From: Sergei Burkatskii Date: Fri, 5 Jun 2026 11:43:48 +0200 Subject: [PATCH 22/22] fix: copilot review --- .../js/__internal/scheduler/workspaces/m_work_space.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ca2f14f7f3cb..c98fb1299f0f 100644 --- a/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts +++ b/packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts @@ -269,7 +269,7 @@ export interface WorkspaceOptionsInternal { startDate?: Date; type?: ViewType; groupOrientation: GroupOrientation; - width: number + width?: number | string | undefined; } class SchedulerWorkSpace extends Widget {