Skip to content

Commit 29c71cb

Browse files
Spike onSelectionEnd
1 parent a0daf39 commit 29c71cb

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import {
2+
afterEach, beforeEach, describe, expect, it, jest,
3+
} from '@jest/globals';
4+
import $ from '@js/core/renderer';
5+
6+
import fx from '../../../common/core/animation/fx';
7+
import { createScheduler } from './__mock__/create_scheduler';
8+
import { setupSchedulerTestEnvironment } from './__mock__/m_mock_scheduler';
9+
10+
const CLASSES = {
11+
scheduler: 'dx-scheduler',
12+
dateTableCell: 'dx-scheduler-date-table-cell',
13+
};
14+
15+
describe('onSelectionEnd Event', () => {
16+
beforeEach(() => {
17+
fx.off = true;
18+
setupSchedulerTestEnvironment({ height: 600 });
19+
});
20+
21+
afterEach(() => {
22+
const $scheduler = $(document.querySelector(`.${CLASSES.scheduler}`));
23+
if ($scheduler.length > 0) {
24+
// @ts-expect-error
25+
$scheduler.dxScheduler('dispose');
26+
}
27+
document.body.innerHTML = '';
28+
fx.off = false;
29+
});
30+
31+
it('should trigger onSelectionEnd event when selecting multiple cells with mouse', async () => {
32+
const onSelectionEnd = jest.fn();
33+
34+
const { scheduler, POM, container } = await createScheduler({
35+
currentView: 'week',
36+
views: ['week'],
37+
currentDate: new Date(2024, 0, 1),
38+
startDayHour: 9,
39+
endDayHour: 18,
40+
height: 600,
41+
onSelectionEnd,
42+
});
43+
44+
const firstCell = POM.getDateTableCell(0, 0);
45+
const thirdCell = POM.getDateTableCell(2, 0);
46+
47+
firstCell.dispatchEvent(new MouseEvent('mousedown', {
48+
bubbles: true,
49+
cancelable: true,
50+
clientX: 100,
51+
clientY: 100,
52+
}));
53+
54+
const secondCell = POM.getDateTableCell(1, 0);
55+
secondCell.dispatchEvent(new MouseEvent('mousemove', {
56+
bubbles: true,
57+
cancelable: true,
58+
clientX: 100,
59+
clientY: 150,
60+
}));
61+
62+
thirdCell.dispatchEvent(new MouseEvent('mousemove', {
63+
bubbles: true,
64+
cancelable: true,
65+
clientX: 100,
66+
clientY: 200,
67+
}));
68+
69+
thirdCell.dispatchEvent(new MouseEvent('mouseup', {
70+
bubbles: true,
71+
cancelable: true,
72+
clientX: 100,
73+
clientY: 200,
74+
}));
75+
76+
expect(onSelectionEnd).toHaveBeenCalledTimes(1);
77+
78+
expect(onSelectionEnd).toHaveBeenCalledWith(
79+
expect.objectContaining({
80+
component: scheduler,
81+
element: container,
82+
selectedCellData: expect.arrayContaining([
83+
expect.objectContaining({
84+
startDate: new Date('2023-12-31T12:00:00.000Z'),
85+
endDate: new Date('2023-12-31T12:30:00.000Z'),
86+
}),
87+
]),
88+
}),
89+
);
90+
});
91+
});

packages/devextreme/js/__internal/scheduler/m_scheduler.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,7 @@ class Scheduler extends SchedulerOptionsBaseWidget {
958958
onAppointmentDeleted: this._createActionByOption(StoreEventNames.DELETED),
959959
onAppointmentFormOpening: this._createActionByOption('onAppointmentFormOpening'),
960960
onAppointmentTooltipShowing: this._createActionByOption('onAppointmentTooltipShowing'),
961+
onSelectionEnd: this._createActionByOption('onSelectionEnd'),
961962
};
962963
}
963964

@@ -1375,6 +1376,13 @@ class Scheduler extends SchedulerOptionsBaseWidget {
13751376
onSelectionChanged: (args) => {
13761377
this.option('selectedCellData', args.selectedCellData);
13771378
},
1379+
onSelectionEnd: (args) => {
1380+
this._actions.onSelectionEnd({
1381+
component: this,
1382+
selectedCellData: args.selectedCellData,
1383+
selectedCells: args.selectedCells,
1384+
});
1385+
},
13781386
groupByDate: this.getViewOption('groupByDate'),
13791387
scrolling,
13801388
draggingMode: this.option('_draggingMode'),

packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ const SCHEDULER_CELL_DXCLICK_EVENT_NAME = addNamespace(clickEventName, 'dxSchedu
170170

171171
const SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME = addNamespace(pointerEvents.down, 'dxSchedulerDateTable');
172172
const SCHEDULER_CELL_DXPOINTERUP_EVENT_NAME = addNamespace(pointerEvents.up, 'dxSchedulerDateTable');
173+
const SCHEDULER_TABLE_DXPOINTERUP_EVENT_NAME = addNamespace(pointerEvents.up, 'dxSchedulerTable');
173174

174175
const SCHEDULER_CELL_DXPOINTERMOVE_EVENT_NAME = addNamespace(pointerEvents.move, 'dxSchedulerDateTable');
175176

@@ -218,8 +219,12 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
218219

219220
_selectionChangedAction: any;
220221

222+
_selectionEndAction: any;
223+
221224
_isCellClick: any;
222225

226+
_isSelectionStartedOnCell = false;
227+
223228
_contextMenuHandled: any;
224229

225230
_disposed: any;
@@ -969,6 +974,7 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
969974

970975
_attachEvents() {
971976
this._createSelectionChangedAction();
977+
this._createSelectionEndAction();
972978
this._attachClickEvent();
973979
this._attachContextMenuEvent();
974980
}
@@ -986,6 +992,8 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
986992

987993
(eventsEngine.off as any)($element, SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME);
988994
(eventsEngine.off as any)($element, SCHEDULER_CELL_DXCLICK_EVENT_NAME);
995+
(eventsEngine.off as any)(domAdapter.getDocument(), SCHEDULER_TABLE_DXPOINTERUP_EVENT_NAME);
996+
989997
eventsEngine.on($element, SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME, (e) => {
990998
if (isMouseEvent(e) && e.which > 1) {
991999
e.preventDefault();
@@ -997,6 +1005,13 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
9971005
const $cell = $(e.target);
9981006
that._cellClickAction({ event: e, cellElement: getPublicElement($cell), cellData: that.getCellData($cell) });
9991007
});
1008+
1009+
eventsEngine.on(domAdapter.getDocument(), SCHEDULER_TABLE_DXPOINTERUP_EVENT_NAME, () => {
1010+
if (that._isSelectionStartedOnCell) {
1011+
that._fireSelectionEndEvent();
1012+
that._isSelectionStartedOnCell = false;
1013+
}
1014+
});
10001015
}
10011016

10021017
_createCellClickAction() {
@@ -1009,10 +1024,15 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
10091024
this._selectionChangedAction = this._createActionByOption('onSelectionChanged');
10101025
}
10111026

1027+
_createSelectionEndAction() {
1028+
this._selectionEndAction = this._createActionByOption('onSelectionEnd');
1029+
}
1030+
10121031
// eslint-disable-next-line @typescript-eslint/no-unused-vars
10131032
_cellClickHandler(argument?: any) {
10141033
if (this._showPopup) {
10151034
delete this._showPopup;
1035+
this._isSelectionStartedOnCell = false;
10161036
this._handleSelectedCellsClick();
10171037
}
10181038
}
@@ -1022,10 +1042,12 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
10221042

10231043
if (!$target.hasClass(DATE_TABLE_CELL_CLASS) && !$target.hasClass(ALL_DAY_TABLE_CELL_CLASS)) {
10241044
this._isCellClick = false;
1045+
this._isSelectionStartedOnCell = false;
10251046
return;
10261047
}
10271048

10281049
this._isCellClick = true;
1050+
this._isSelectionStartedOnCell = true;
10291051
if ($target.hasClass(DATE_TABLE_FOCUSED_CELL_CLASS)) {
10301052
this._showPopup = true;
10311053
} else {
@@ -1932,6 +1954,17 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
19321954
this._selectionChangedAction({ selectedCellData });
19331955
}
19341956

1957+
_fireSelectionEndEvent() {
1958+
const selectedCellData = this.option('selectedCellData') ?? [];
1959+
if (selectedCellData.length > 0 && this._selectionEndAction) {
1960+
const selectedCells = this.cellsSelectionState.getSelectedCells();
1961+
this._selectionEndAction({
1962+
selectedCellData,
1963+
selectedCells: $(selectedCells),
1964+
});
1965+
}
1966+
}
1967+
19351968
_getCellByData(cellData) {
19361969
const {
19371970
startDate, groupIndex, allDay, index,
@@ -2369,6 +2402,9 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
23692402
case 'onSelectionChanged':
23702403
this._createSelectionChangedAction();
23712404
break;
2405+
case 'onSelectionEnd':
2406+
this._createSelectionEndAction();
2407+
break;
23722408
case 'onCellClick':
23732409
this._createCellClickAction();
23742410
break;

packages/devextreme/playground/scheduler-example.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ window.addEventListener('load', () =>
4242
allowResizing: true,
4343
allowDragging: true
4444
},
45+
onSelectionEnd: ({component, selectedCellData}) => {
46+
component.showAppointmentPopup({
47+
startDate: selectedCellData[0].startDate,
48+
endDate: selectedCellData[selectedCellData.length - 1].endDate,
49+
allDay: false
50+
}, true);
51+
},
4552
onAppointmentAdded: (e) => {
4653
console.log('Appointment added:', e.appointmentData);
4754
},

0 commit comments

Comments
 (0)