Skip to content

Commit 0654dce

Browse files
authored
Scheduler refactor (#29568)
Co-authored-by: Vladimir Bushmanov <vladimir.bushmanov@devexpress.com>
1 parent e48653b commit 0654dce

61 files changed

Lines changed: 409 additions & 475 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_appointment_data_provider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import config from '@js/core/config';
22
import { combineRemoteFilter } from '@ts/scheduler/r1/filterting/index';
3+
import type { AppointmentDataItem, SafeAppointment } from '@ts/scheduler/types';
34
import type { AppointmentDataAccessor } from '@ts/scheduler/utils';
45

56
import { AppointmentDataSource } from './m_appointment_data_source';
@@ -101,7 +102,7 @@ export class AppointmentDataProvider {
101102
}
102103

103104
// Filter mapping
104-
filter(preparedItems) {
105+
filter(preparedItems: AppointmentDataItem[]): SafeAppointment[] {
105106
return this.getFilterStrategy().filter(preparedItems);
106107
}
107108

packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_appointment_filter.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import dateUtils from '@js/core/utils/date';
44
import { map } from '@js/core/utils/iterator';
55
import { isDefined, isFunction } from '@js/core/utils/type';
66
import { dateUtilsTs } from '@ts/core/utils/date';
7-
import type { AppointmentDataItem } from '@ts/scheduler/r1/types';
87
import {
98
getDatesWithoutTime, hasResourceValue, isAppointmentTakesAllDay, isTimelineView,
109
} from '@ts/scheduler/r1/utils/index';
10+
import type { AppointmentDataItem, SafeAppointment } from '@ts/scheduler/types';
1111
import type { AppointmentDataAccessor } from '@ts/scheduler/utils';
12+
import type ViewDataProvider from '@ts/scheduler/workspaces/view_model/m_view_data_provider';
1213

1314
import { createAppointmentAdapter } from '../../m_appointment_adapter';
1415
import { getRecurrenceProcessor } from '../../m_recurrence';
@@ -60,7 +61,7 @@ export class AppointmentFilterBaseStrategy {
6061

6162
get groupCount() { return this._resolveOption('groupCount'); }
6263

63-
get viewDataProvider() { return this._resolveOption('viewDataProvider'); }
64+
get viewDataProvider(): ViewDataProvider { return this._resolveOption('viewDataProvider'); }
6465

6566
get allDayPanelMode() { return this._resolveOption('allDayPanelMode'); }
6667

@@ -71,7 +72,7 @@ export class AppointmentFilterBaseStrategy {
7172
: result;
7273
}
7374

74-
filter(preparedItems: AppointmentDataItem[]) {
75+
filter(preparedItems: AppointmentDataItem[]): SafeAppointment[] {
7576
const [min, max] = this.dateRange;
7677
const { viewOffset } = this.options;
7778
const allDay = !this.showAllDayPanel && this.supportAllDayRow
@@ -304,12 +305,12 @@ export class AppointmentFilterBaseStrategy {
304305
return result;
305306
}
306307

307-
filterLoadedAppointments(filterOptions, preparedItems: AppointmentDataItem[]) {
308+
filterLoadedAppointments(filterOptions, preparedItems: AppointmentDataItem[]): SafeAppointment[] {
308309
const filteredItems = this.filterPreparedItems(filterOptions, preparedItems);
309310
return filteredItems.map(({ rawAppointment }) => rawAppointment);
310311
}
311312

312-
filterPreparedItems(filterOptions, preparedItems: AppointmentDataItem[]) {
313+
filterPreparedItems(filterOptions, preparedItems: AppointmentDataItem[]): AppointmentDataItem[] {
313314
const combinedFilter = this._createCombinedFilter(filterOptions);
314315

315316
// @ts-expect-error
@@ -319,7 +320,7 @@ export class AppointmentFilterBaseStrategy {
319320
.toArray();
320321
}
321322

322-
filterAllDayAppointments(preparedItems: AppointmentDataItem[]) {
323+
filterAllDayAppointments(preparedItems: AppointmentDataItem[]): SafeAppointment[] {
323324
const combinedFilter = this._createAllDayAppointmentFilter();
324325
// @ts-expect-error
325326
return query(preparedItems)

packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_appointment_filter_virtual.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import query from '@js/common/data/query';
22
import dateUtils from '@js/core/utils/date';
33
import { dateUtilsTs } from '@ts/core/utils/date';
4-
import type { AppointmentDataItem } from '@ts/scheduler/r1/types';
54
import { isDateAndTimeView, isTimelineView } from '@ts/scheduler/r1/utils/index';
5+
import type { AppointmentDataItem, SafeAppointment } from '@ts/scheduler/types';
66

77
import {
88
getResourcesDataByGroups,
@@ -18,7 +18,7 @@ export class AppointmentFilterVirtualStrategy extends AppointmentFilterBaseStrat
1818

1919
get resources() { return this.options.resources; }
2020

21-
filter(preparedItems: AppointmentDataItem[]) {
21+
filter(preparedItems: AppointmentDataItem[]): SafeAppointment[] {
2222
const { viewOffset } = this.options;
2323
const hourMs = toMs('hour');
2424
const isCalculateStartAndEndDayHour = isDateAndTimeView(this.viewType);
@@ -78,7 +78,10 @@ export class AppointmentFilterVirtualStrategy extends AppointmentFilterBaseStrat
7878
}, preparedItems);
7979
}
8080

81-
filterPreparedItems({ filterOptions, groupCount }, preparedItems: AppointmentDataItem[]) {
81+
filterPreparedItems(
82+
{ filterOptions, groupCount },
83+
preparedItems: AppointmentDataItem[],
84+
): AppointmentDataItem[] {
8285
const combinedFilters: any = [];
8386

8487
let itemsToFilter = preparedItems;
@@ -110,7 +113,7 @@ export class AppointmentFilterVirtualStrategy extends AppointmentFilterBaseStrat
110113
.toArray();
111114
}
112115

113-
hasAllDayAppointments(filteredItems, preparedItems: AppointmentDataItem[]) {
116+
hasAllDayAppointments(filteredItems, preparedItems: AppointmentDataItem[]): boolean {
114117
return this.filterAllDayAppointments(preparedItems).length > 0;
115118
}
116119

packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_utils.test.ts

Lines changed: 0 additions & 44 deletions
This file was deleted.

packages/devextreme/js/__internal/scheduler/appointments/data_provider/m_utils.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ export const compareDateWithEndDayHour = (options) => {
6868

6969
export const getAppointmentTakesSeveralDays = (adapter) => !dateUtils.sameDate(adapter.startDate, adapter.endDate);
7070

71-
// eslint-disable-next-line @typescript-eslint/naming-convention
72-
export const _isEndDateWrong = (startDate, endDate) => !endDate || isNaN(endDate.getTime()) || startDate.getTime() > endDate.getTime();
73-
7471
// eslint-disable-next-line @typescript-eslint/naming-convention
7572
export const _appointmentPartInInterval = (startDate, endDate, startDayHour, endDayHour) => {
7673
const apptStartDayHour = startDate.getHours();
@@ -124,29 +121,6 @@ export const _convertRecurrenceException = (exceptionString, startDate, timeZone
124121
return exceptionString;
125122
};
126123

127-
export const replaceWrongEndDate = (
128-
rawAppointment,
129-
startDate,
130-
endDate,
131-
appointmentDuration,
132-
dataAccessors: AppointmentDataAccessor,
133-
) => {
134-
const calculateAppointmentEndDate = (isAllDay, startDate) => {
135-
if (isAllDay) {
136-
return dateUtils.setToDayEnd(new Date(startDate));
137-
}
138-
139-
return new Date(startDate.getTime() + appointmentDuration * toMs('minute'));
140-
};
141-
142-
if (_isEndDateWrong(startDate, endDate)) {
143-
const isAllDay = Boolean(dataAccessors.get('allDay', rawAppointment));
144-
145-
const calculatedEndDate = calculateAppointmentEndDate(isAllDay, startDate);
146-
dataAccessors.set('endDate', rawAppointment, calculatedEndDate);
147-
}
148-
};
149-
150124
export const sortAppointmentsByStartDate = (
151125
appointments,
152126
dataAccessors: AppointmentDataAccessor,

packages/devextreme/js/__internal/scheduler/appointments/m_appointment_collection.ts

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ import {
2525
import CollectionWidget from '@js/ui/collection/ui.collection_widget.edit';
2626
import { dateUtilsTs } from '@ts/core/utils/date';
2727

28+
import { APPOINTMENT_SETTINGS_KEY } from '../constants';
2829
import { createAppointmentAdapter } from '../m_appointment_adapter';
2930
import { APPOINTMENT_CONTENT_CLASSES, APPOINTMENT_DRAG_SOURCE_CLASS, APPOINTMENT_ITEM_CLASS } from '../m_classes';
30-
import { APPOINTMENT_SETTINGS_KEY } from '../m_constants';
3131
import { getRecurrenceProcessor } from '../m_recurrence';
3232
import timeZoneUtils from '../m_utils_time_zone';
3333
import { getPathToLeaf } from '../resources/m_utils';
34+
import type { AppointmentViewModel } from '../types';
3435
import type { AppointmentDataAccessor } from '../utils';
3536
import { getAppointmentTakesSeveralDays, sortAppointmentsByStartDate } from './data_provider/m_utils';
3637
import { AgendaAppointment, Appointment } from './m_appointment';
@@ -43,6 +44,10 @@ const COMPONENT_CLASS = 'dx-scheduler-scrollable-appointments';
4344
const DBLCLICK_EVENT_NAME = addNamespace(dblclickEvent, 'dxSchedulerAppointment');
4445

4546
const toMs = dateUtils.dateToMilliseconds;
47+
const isAllDayAppointment = (
48+
appointment: AppointmentViewModel,
49+
): boolean => Boolean(appointment.settings[0]?.allDay);
50+
4651
// @ts-expect-error
4752
class SchedulerAppointments extends CollectionWidget {
4853
_virtualAppointments: any;
@@ -179,7 +184,7 @@ class SchedulerAppointments extends CollectionWidget {
179184
_moveFocus() {}
180185

181186
_focusTarget() {
182-
return (this as any)._getNavigatableItems();
187+
return this._getNavigatableItems();
183188
}
184189

185190
_renderFocusTarget() {
@@ -259,67 +264,48 @@ class SchedulerAppointments extends CollectionWidget {
259264
}
260265
}
261266

262-
_isAllDayAppointment(appointment) {
263-
return appointment.settings.length && appointment.settings[0].allDay || false;
264-
}
265-
266-
_isRepaintAppointment(appointment) {
267-
return !isDefined(appointment.needRepaint) || appointment.needRepaint === true;
268-
}
269-
270-
_isRepaintAll(appointments) {
271-
if (this.isAgendaView) {
272-
return true;
273-
}
274-
for (let i = 0; i < appointments.length; i++) {
275-
if (!this._isRepaintAppointment(appointments[i])) {
276-
return false;
277-
}
278-
}
279-
return true;
267+
_isRepaintAll(appointments: AppointmentViewModel[]): boolean {
268+
return this.isAgendaView || appointments.every((item) => item.needRepaint);
280269
}
281270

282-
_applyFragment(fragment, allDay) {
271+
_applyFragment(fragment: dxElementWrapper, allDay: boolean): void {
283272
if (fragment.children().length > 0) {
284273
this._getAppointmentContainer(allDay).append(fragment);
285274
}
286275
}
287276

288-
_onEachAppointment(appointment, index, container, isRepaintAll) {
289-
const repaintAppointment = () => {
290-
appointment.needRepaint = false;
291-
this._clearItem(appointment);
292-
this._renderItem(index, appointment, container);
293-
};
294-
295-
if (appointment?.needRemove === true) {
296-
this._clearItem(appointment);
297-
} else if (isRepaintAll || this._isRepaintAppointment(appointment)) {
298-
repaintAppointment();
299-
}
300-
}
301-
302-
_repaintAppointments(appointments) {
277+
_repaintAppointments(appointments: AppointmentViewModel[]): void {
303278
this._renderByFragments(($commonFragment, $allDayFragment) => {
304279
const isRepaintAll = this._isRepaintAll(appointments);
305280

306281
if (isRepaintAll) {
307282
this._getAppointmentContainer(true).html('');
308283
this._getAppointmentContainer(false).html('');
309284
}
310-
311-
!appointments.length && this._cleanItemContainer();
285+
if (!appointments.length) {
286+
this._cleanItemContainer();
287+
}
312288

313289
appointments.forEach((appointment, index) => {
314-
const container = this._isAllDayAppointment(appointment)
290+
const container = isAllDayAppointment(appointment)
315291
? $allDayFragment
316292
: $commonFragment;
317-
this._onEachAppointment(appointment, index, container, isRepaintAll);
293+
294+
if (appointment.needRemove) {
295+
this._clearItem(appointment);
296+
} else if (isRepaintAll || appointment.needRepaint) {
297+
appointment.needRepaint = false;
298+
this._clearItem(appointment);
299+
this._renderItem(index, appointment, container);
300+
}
318301
});
319302
});
320303
}
321304

322-
_renderByFragments(renderFunction) {
305+
_renderByFragments(renderFunction: (
306+
$commonFragment: dxElementWrapper,
307+
$allDayFragment: dxElementWrapper,
308+
) => void): void {
323309
if (this.isVirtualScrolling) {
324310
const $commonFragment = $(domAdapter.createDocumentFragment() as any);
325311
const $allDayFragment = $(domAdapter.createDocumentFragment() as any);
@@ -351,7 +337,7 @@ class SchedulerAppointments extends CollectionWidget {
351337
(this as any)._attachHoverEvents();
352338
}
353339

354-
_clearItem(item) {
340+
_clearItem(item: AppointmentViewModel): void {
355341
const $items = this._findItemElementByItem(item.itemData);
356342
if (!$items.length) {
357343
return;
@@ -526,9 +512,13 @@ class SchedulerAppointments extends CollectionWidget {
526512
this.notifyObserver('showEditAppointmentPopup', { data: appointmentData, target: $targetAppointment });
527513
}
528514

529-
_renderItem(index, item, container) {
515+
_renderItem(
516+
index: number,
517+
item: AppointmentViewModel,
518+
container: dxElementWrapper,
519+
): dxElementWrapper[] {
530520
const { itemData } = item;
531-
const $items: any = [];
521+
const $items: dxElementWrapper[] = [];
532522

533523
for (let i = 0; i < item.settings.length; i++) {
534524
const setting = item.settings[i];
@@ -562,15 +552,11 @@ class SchedulerAppointments extends CollectionWidget {
562552
});
563553
}
564554

565-
_getAppointmentContainer(allDay) {
555+
_getAppointmentContainer(allDay: boolean): dxElementWrapper {
566556
const $allDayContainer = this.option('allDayContainer');
567-
let $container = (this as any).itemsContainer().not($allDayContainer);
568-
569-
if (allDay && $allDayContainer) {
570-
$container = $allDayContainer;
571-
}
557+
const $container = (this as any).itemsContainer().not($allDayContainer);
572558

573-
return $container;
559+
return allDay && $allDayContainer ? $allDayContainer : $container;
574560
}
575561

576562
_postprocessRenderItem(args) {

0 commit comments

Comments
 (0)