react-big-schedule 8.1.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -1129
- package/dist/calendar/Calendar.d.ts +28 -0
- package/dist/calendar/Calendar.js +95 -0
- package/dist/calendar/Toolbar.d.ts +18 -0
- package/dist/calendar/Toolbar.js +6 -0
- package/dist/calendar/recurrence.check.d.ts +1 -0
- package/dist/calendar/recurrence.check.js +49 -0
- package/dist/calendar/recurrence.d.ts +8 -0
- package/dist/calendar/recurrence.js +90 -0
- package/dist/calendar/timezone.d.ts +6 -0
- package/dist/calendar/timezone.js +14 -0
- package/dist/calendar/types.d.ts +187 -0
- package/dist/calendar/types.js +1 -0
- package/dist/calendar/useEventSources.d.ts +11 -0
- package/dist/calendar/useEventSources.js +89 -0
- package/dist/calendar/useRecurrence.d.ts +4 -0
- package/dist/calendar/useRecurrence.js +15 -0
- package/dist/calendar/utils.d.ts +38 -0
- package/dist/calendar/utils.js +143 -0
- package/dist/calendar/views/DayGridView.d.ts +3 -0
- package/dist/calendar/views/DayGridView.js +375 -0
- package/dist/calendar/views/ListView.d.ts +4 -0
- package/dist/calendar/views/ListView.js +56 -0
- package/dist/calendar/views/MultiMonthView.d.ts +4 -0
- package/dist/calendar/views/MultiMonthView.js +36 -0
- package/dist/calendar/views/TimeGridView.d.ts +3 -0
- package/dist/calendar/views/TimeGridView.js +334 -0
- package/dist/calendar/views/daygrid/DayCell.d.ts +19 -0
- package/dist/calendar/views/daygrid/DayCell.js +17 -0
- package/dist/calendar/views/daygrid/EventChip.d.ts +19 -0
- package/dist/calendar/views/daygrid/EventChip.js +40 -0
- package/dist/calendar/views/daygrid/layout.d.ts +30 -0
- package/dist/calendar/views/daygrid/layout.js +63 -0
- package/dist/calendar/views/list/bucket.d.ts +8 -0
- package/dist/calendar/views/list/bucket.js +37 -0
- package/dist/calendar/views/multimonth/Cell.d.ts +12 -0
- package/dist/calendar/views/multimonth/Cell.js +44 -0
- package/dist/calendar/views/multimonth/Continuous.d.ts +8 -0
- package/dist/calendar/views/multimonth/Continuous.js +28 -0
- package/dist/calendar/views/multimonth/MonthGrid.d.ts +10 -0
- package/dist/calendar/views/multimonth/MonthGrid.js +36 -0
- package/dist/calendar/views/multimonth/shared.d.ts +27 -0
- package/dist/calendar/views/multimonth/shared.js +40 -0
- package/dist/calendar/views/timegrid/DayColumn.d.ts +49 -0
- package/dist/calendar/views/timegrid/DayColumn.js +86 -0
- package/dist/calendar/views/timegrid/model.d.ts +55 -0
- package/dist/calendar/views/timegrid/model.js +102 -0
- package/dist/components/AddMore.d.ts +13 -0
- package/dist/components/AddMore.js +9 -42
- package/dist/components/AddMorePopover.d.ts +13 -0
- package/dist/components/AddMorePopover.js +24 -95
- package/dist/components/AgendaEventItem.d.ts +10 -0
- package/dist/components/AgendaEventItem.js +33 -81
- package/dist/components/AgendaResourceEvents.d.ts +10 -0
- package/dist/components/AgendaResourceEvents.js +37 -91
- package/dist/components/AgendaView.d.ts +9 -0
- package/dist/components/AgendaView.js +10 -69
- package/dist/components/BodyView.d.ts +11 -0
- package/dist/components/BodyView.js +36 -67
- package/dist/components/DnDContext.d.ts +48 -0
- package/dist/components/DnDContext.js +200 -221
- package/dist/components/DnDSource.d.ts +49 -0
- package/dist/components/DnDSource.js +125 -120
- package/dist/components/EventItem.d.ts +41 -0
- package/dist/components/EventItem.js +585 -787
- package/dist/components/EventItemPopover.d.ts +12 -0
- package/dist/components/EventItemPopover.js +19 -143
- package/dist/components/HeaderView.d.ts +14 -0
- package/dist/components/HeaderView.js +123 -186
- package/dist/components/ResourceEvents.d.ts +54 -0
- package/dist/components/ResourceEvents.js +534 -703
- package/dist/components/ResourceView.d.ts +26 -0
- package/dist/components/ResourceView.js +64 -184
- package/dist/components/SchedulerData.d.ts +136 -0
- package/dist/components/SchedulerData.js +1296 -1226
- package/dist/components/SchedulerHeader.d.ts +25 -0
- package/dist/components/SchedulerHeader.js +50 -150
- package/dist/components/SelectedArea.d.ts +8 -0
- package/dist/components/SelectedArea.js +11 -26
- package/dist/components/Summary.d.ts +11 -0
- package/dist/components/Summary.js +21 -50
- package/dist/components/WrapperFun.d.ts +2 -0
- package/dist/components/WrapperFun.js +5 -10
- package/dist/components/index.d.ts +44 -0
- package/dist/components/index.js +428 -654
- package/dist/components/ui/Icons.d.ts +8 -0
- package/dist/components/ui/Icons.js +7 -0
- package/dist/components/ui/MiniCalendar.d.ts +9 -0
- package/dist/components/ui/MiniCalendar.js +17 -0
- package/dist/components/ui/Popover.d.ts +13 -0
- package/dist/components/ui/Popover.js +80 -0
- package/dist/config/default.d.ts +36 -0
- package/dist/config/default.js +17 -26
- package/dist/config/i18n.d.ts +27 -0
- package/dist/config/i18n.js +21 -37
- package/dist/config/scheduler.d.ts +12 -0
- package/dist/config/scheduler.js +126 -119
- package/dist/css/style.css +2 -316
- package/dist/helper/behaviors.d.ts +14 -0
- package/dist/helper/behaviors.js +75 -75
- package/dist/helper/utility.d.ts +26 -0
- package/dist/helper/utility.js +23 -30
- package/dist/index.d.ts +6 -477
- package/dist/index.js +4 -2
- package/dist/sample-data/sample1.d.ts +11 -0
- package/dist/sample-data/sample1.js +427 -372
- package/dist/types.d.ts +267 -0
- package/dist/types.js +1 -0
- package/package.json +35 -26
|
@@ -1,730 +1,561 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { PureComponent } from 'react';
|
|
3
3
|
import { useDrop } from 'react-dnd';
|
|
4
4
|
import { CellUnit, DATETIME_FORMAT, DnDTypes, SummaryPos } from '../config/default';
|
|
5
|
+
import { toDate } from '../helper/behaviors';
|
|
5
6
|
import { getPos, normalizeEventEnd, normalizeEventStart } from '../helper/utility';
|
|
6
7
|
import AddMore from './AddMore';
|
|
7
8
|
import EventItem from './EventItem';
|
|
8
9
|
import SelectedArea from './SelectedArea';
|
|
9
10
|
import Summary from './Summary';
|
|
10
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
11
|
const DEFAULT_ROW_HEIGHT = 50;
|
|
12
|
+
// Drag handlers take the mouse/touch union; DOM listeners are typed for plain Event.
|
|
13
|
+
const asListener = (fn) => fn;
|
|
12
14
|
class ResourceEvents extends PureComponent {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
viewEvent2Text: PropTypes.string,
|
|
30
|
-
newEvent: PropTypes.func,
|
|
31
|
-
eventItemTemplateResolver: PropTypes.func,
|
|
32
|
-
eventItemPopoverTemplateResolver: PropTypes.func,
|
|
33
|
-
onSelectionChange: PropTypes.func,
|
|
34
|
-
isRowSelected: PropTypes.bool,
|
|
35
|
-
selectionPreview: PropTypes.shape({
|
|
36
|
-
isSelecting: PropTypes.bool,
|
|
37
|
-
left: PropTypes.number,
|
|
38
|
-
width: PropTypes.number
|
|
39
|
-
})
|
|
40
|
-
};
|
|
41
|
-
constructor(props) {
|
|
42
|
-
super(props);
|
|
43
|
-
this.state = {
|
|
44
|
-
isSelecting: false,
|
|
45
|
-
left: 0,
|
|
46
|
-
width: 0,
|
|
47
|
-
// Add vertical selection tracking
|
|
48
|
-
originalStartRowIndex: -1,
|
|
49
|
-
startRowIndex: -1,
|
|
50
|
-
endRowIndex: -1,
|
|
51
|
-
// where the dragged item would land (set from the drop target's hover)
|
|
52
|
-
dropPreview: null
|
|
53
|
-
};
|
|
54
|
-
this.supportTouch = false; // 'ontouchstart' in window;
|
|
55
|
-
}
|
|
56
|
-
componentDidMount() {
|
|
57
|
-
const {
|
|
58
|
-
schedulerData
|
|
59
|
-
} = this.props;
|
|
60
|
-
const {
|
|
61
|
-
config
|
|
62
|
-
} = schedulerData;
|
|
63
|
-
this.supportTouch = 'ontouchstart' in window;
|
|
64
|
-
if (config.creatable === true) {
|
|
65
|
-
this.supportTouchHelper();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
componentDidUpdate(prevProps) {
|
|
69
|
-
const prevCreatable = prevProps.schedulerData?.config?.creatable;
|
|
70
|
-
const currentCreatable = this.props.schedulerData?.config?.creatable;
|
|
71
|
-
if (prevCreatable !== currentCreatable) {
|
|
72
|
-
this.supportTouchHelper('remove');
|
|
73
|
-
if (currentCreatable) {
|
|
74
|
-
this.supportTouchHelper();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
componentWillUnmount() {
|
|
79
|
-
this.cleanupDragInteraction();
|
|
80
|
-
this.supportTouchHelper('remove');
|
|
81
|
-
this.emitSelectionChange(false, [], {
|
|
82
|
-
left: 0,
|
|
83
|
-
width: 0
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
setDropPreview = dropPreview => {
|
|
87
|
-
if (!Number.isFinite(dropPreview.left) || !Number.isFinite(dropPreview.width)) return;
|
|
88
|
-
const current = this.state.dropPreview;
|
|
89
|
-
if (current?.left === dropPreview.left && current?.width === dropPreview.width) return;
|
|
90
|
-
this.setState({
|
|
91
|
-
dropPreview
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
cleanupDragInteraction = () => {
|
|
95
|
-
document.documentElement.removeEventListener('touchmove', this.doDrag, false);
|
|
96
|
-
document.documentElement.removeEventListener('touchend', this.stopDrag, false);
|
|
97
|
-
document.documentElement.removeEventListener('touchcancel', this.cancelDrag, false);
|
|
98
|
-
document.documentElement.removeEventListener('mousemove', this.doDrag, false);
|
|
99
|
-
document.documentElement.removeEventListener('mouseup', this.stopDrag, false);
|
|
100
|
-
document.onselectstart = null;
|
|
101
|
-
document.ondragstart = null;
|
|
102
|
-
};
|
|
103
|
-
supportTouchHelper = (evType = 'add') => {
|
|
104
|
-
const ev = evType === 'add' ? this.eventContainer.addEventListener : this.eventContainer.removeEventListener;
|
|
105
|
-
if (this.supportTouch) {
|
|
106
|
-
// ev('touchstart', this.initDrag, false);
|
|
107
|
-
} else {
|
|
108
|
-
ev('mousedown', this.initDrag, false);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
initDrag = ev => {
|
|
112
|
-
const {
|
|
113
|
-
isSelecting
|
|
114
|
-
} = this.state;
|
|
115
|
-
if (isSelecting) return;
|
|
116
|
-
if ((ev.srcElement || ev.target) !== this.eventContainer) return;
|
|
117
|
-
ev.stopPropagation();
|
|
118
|
-
const {
|
|
119
|
-
resourceEvents
|
|
120
|
-
} = this.props;
|
|
121
|
-
if (resourceEvents.groupOnly) return;
|
|
122
|
-
const [clientX, toReturn] = this.dragHelper(ev, 'init');
|
|
123
|
-
if (toReturn) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const {
|
|
127
|
-
schedulerData
|
|
128
|
-
} = this.props;
|
|
129
|
-
const cellWidth = schedulerData.getContentCellWidth();
|
|
130
|
-
const pos = getPos(this.eventContainer);
|
|
131
|
-
const startX = clientX - pos.x;
|
|
132
|
-
const leftIndex = Math.floor(startX / cellWidth);
|
|
133
|
-
const left = leftIndex * cellWidth;
|
|
134
|
-
const rightIndex = Math.ceil(startX / cellWidth);
|
|
135
|
-
const width = (rightIndex - leftIndex) * cellWidth;
|
|
136
|
-
|
|
137
|
-
// Get the row index of this resource
|
|
138
|
-
const startRowIndex = this.getResourceRowIndex(resourceEvents.slotId);
|
|
139
|
-
this.setState({
|
|
140
|
-
startX,
|
|
141
|
-
left,
|
|
142
|
-
leftIndex,
|
|
143
|
-
width,
|
|
144
|
-
rightIndex,
|
|
145
|
-
isSelecting: true,
|
|
146
|
-
originalStartRowIndex: startRowIndex,
|
|
147
|
-
startRowIndex,
|
|
148
|
-
endRowIndex: startRowIndex // Initially same as start
|
|
149
|
-
});
|
|
150
|
-
this.emitSelectionChange(true, this.getSelectedResourceIds(startRowIndex, startRowIndex), {
|
|
151
|
-
left,
|
|
152
|
-
width
|
|
153
|
-
});
|
|
154
|
-
if (this.supportTouch) {
|
|
155
|
-
document.documentElement.addEventListener('touchmove', this.doDrag, false);
|
|
156
|
-
document.documentElement.addEventListener('touchend', this.stopDrag, false);
|
|
157
|
-
document.documentElement.addEventListener('touchcancel', this.cancelDrag, false);
|
|
158
|
-
} else {
|
|
159
|
-
document.documentElement.addEventListener('mousemove', this.doDrag, false);
|
|
160
|
-
document.documentElement.addEventListener('mouseup', this.stopDrag, false);
|
|
161
|
-
}
|
|
162
|
-
document.onselectstart = () => false;
|
|
163
|
-
document.ondragstart = () => false;
|
|
164
|
-
};
|
|
165
|
-
doDrag = ev => {
|
|
166
|
-
ev.stopPropagation();
|
|
167
|
-
const [clientX, toReturn] = this.dragHelper(ev, 'do');
|
|
168
|
-
if (toReturn) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
const {
|
|
172
|
-
startX,
|
|
173
|
-
originalStartRowIndex
|
|
174
|
-
} = this.state;
|
|
175
|
-
const {
|
|
176
|
-
schedulerData
|
|
177
|
-
} = this.props;
|
|
178
|
-
const {
|
|
179
|
-
headers
|
|
180
|
-
} = schedulerData;
|
|
181
|
-
const cellWidth = schedulerData.getContentCellWidth();
|
|
182
|
-
const pos = getPos(this.eventContainer);
|
|
183
|
-
const currentX = clientX - pos.x;
|
|
184
|
-
let leftIndex = Math.floor(Math.min(startX, currentX) / cellWidth);
|
|
185
|
-
leftIndex = leftIndex < 0 ? 0 : leftIndex;
|
|
186
|
-
const left = leftIndex * cellWidth;
|
|
187
|
-
let rightIndex = Math.ceil(Math.max(startX, currentX) / cellWidth);
|
|
188
|
-
rightIndex = rightIndex > headers.length ? headers.length : rightIndex;
|
|
189
|
-
const width = (rightIndex - leftIndex) * cellWidth;
|
|
190
|
-
|
|
191
|
-
// Calculate current row based on per-row heights (not a uniform row height assumption).
|
|
192
|
-
let clientY = ev.clientY;
|
|
193
|
-
if (this.supportTouch && ev.changedTouches && ev.changedTouches.length > 0) {
|
|
194
|
-
clientY = ev.changedTouches[0].clientY;
|
|
195
|
-
}
|
|
196
|
-
const currentY = clientY - pos.y;
|
|
197
|
-
const displayRenderData = this.getDisplayRenderData();
|
|
198
|
-
if (displayRenderData.length === 0) {
|
|
199
|
-
this.setState({
|
|
200
|
-
leftIndex,
|
|
201
|
-
left,
|
|
202
|
-
rightIndex,
|
|
203
|
-
width,
|
|
204
|
-
isSelecting: true,
|
|
205
|
-
startRowIndex: -1,
|
|
206
|
-
endRowIndex: -1
|
|
207
|
-
});
|
|
208
|
-
this.emitSelectionChange(true, [], {
|
|
209
|
-
left,
|
|
210
|
-
width
|
|
211
|
-
});
|
|
212
|
-
return;
|
|
15
|
+
eventContainer = null;
|
|
16
|
+
supportTouch;
|
|
17
|
+
constructor(props) {
|
|
18
|
+
super(props);
|
|
19
|
+
this.state = {
|
|
20
|
+
isSelecting: false,
|
|
21
|
+
left: 0,
|
|
22
|
+
width: 0,
|
|
23
|
+
// Add vertical selection tracking
|
|
24
|
+
originalStartRowIndex: -1,
|
|
25
|
+
startRowIndex: -1,
|
|
26
|
+
endRowIndex: -1,
|
|
27
|
+
// where the dragged item would land (set from the drop target's hover)
|
|
28
|
+
dropPreview: null,
|
|
29
|
+
};
|
|
30
|
+
this.supportTouch = false; // 'ontouchstart' in window;
|
|
213
31
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (absoluteY < cumulativeHeight) {
|
|
222
|
-
currentRowIndex = i;
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
32
|
+
componentDidMount() {
|
|
33
|
+
const { schedulerData } = this.props;
|
|
34
|
+
const { config } = schedulerData;
|
|
35
|
+
this.supportTouch = 'ontouchstart' in window;
|
|
36
|
+
if (config.creatable === true) {
|
|
37
|
+
this.supportTouchHelper();
|
|
38
|
+
}
|
|
225
39
|
}
|
|
226
|
-
|
|
227
|
-
|
|
40
|
+
componentDidUpdate(prevProps) {
|
|
41
|
+
const prevCreatable = prevProps.schedulerData?.config?.creatable;
|
|
42
|
+
const currentCreatable = this.props.schedulerData?.config?.creatable;
|
|
43
|
+
if (prevCreatable !== currentCreatable) {
|
|
44
|
+
this.supportTouchHelper('remove');
|
|
45
|
+
if (currentCreatable) {
|
|
46
|
+
this.supportTouchHelper();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
228
49
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const clampedMinRow = Math.max(0, minRowIndex);
|
|
234
|
-
const clampedMaxRow = Math.min(displayRenderData.length - 1, maxRowIndex);
|
|
235
|
-
this.setState({
|
|
236
|
-
leftIndex,
|
|
237
|
-
left,
|
|
238
|
-
rightIndex,
|
|
239
|
-
width,
|
|
240
|
-
isSelecting: true,
|
|
241
|
-
startRowIndex: clampedMinRow,
|
|
242
|
-
endRowIndex: clampedMaxRow
|
|
243
|
-
});
|
|
244
|
-
this.emitSelectionChange(true, this.getSelectedResourceIds(clampedMinRow, clampedMaxRow), {
|
|
245
|
-
left,
|
|
246
|
-
width
|
|
247
|
-
});
|
|
248
|
-
};
|
|
249
|
-
dragHelper = (ev, dragType) => {
|
|
250
|
-
let clientX = 0;
|
|
251
|
-
if (this.supportTouch) {
|
|
252
|
-
if (ev.changedTouches.length === 0) return [clientX, true];
|
|
253
|
-
const touch = ev.changedTouches[0];
|
|
254
|
-
clientX = touch.pageX;
|
|
255
|
-
} else if (dragType === 'init') {
|
|
256
|
-
if (ev.buttons !== undefined && ev.buttons !== 1) return [clientX, true];
|
|
257
|
-
clientX = ev.clientX;
|
|
258
|
-
} else {
|
|
259
|
-
clientX = ev.clientX;
|
|
50
|
+
componentWillUnmount() {
|
|
51
|
+
this.cleanupDragInteraction();
|
|
52
|
+
this.supportTouchHelper('remove');
|
|
53
|
+
this.emitSelectionChange(false, [], { left: 0, width: 0 });
|
|
260
54
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
resourceEvents
|
|
269
|
-
} = this.props;
|
|
270
|
-
const {
|
|
271
|
-
headers,
|
|
272
|
-
events,
|
|
273
|
-
config,
|
|
274
|
-
cellUnit,
|
|
275
|
-
localeDayjs
|
|
276
|
-
} = schedulerData;
|
|
277
|
-
const {
|
|
278
|
-
leftIndex,
|
|
279
|
-
rightIndex
|
|
280
|
-
} = this.state;
|
|
281
|
-
this.cleanupDragInteraction();
|
|
282
|
-
const resetSelection = () => {
|
|
283
|
-
this.setState({
|
|
284
|
-
startX: 0,
|
|
285
|
-
leftIndex: 0,
|
|
286
|
-
left: 0,
|
|
287
|
-
rightIndex: 0,
|
|
288
|
-
width: 0,
|
|
289
|
-
isSelecting: false,
|
|
290
|
-
originalStartRowIndex: -1,
|
|
291
|
-
startRowIndex: -1,
|
|
292
|
-
endRowIndex: -1
|
|
293
|
-
});
|
|
294
|
-
this.emitSelectionChange(false, [], {
|
|
295
|
-
left: 0,
|
|
296
|
-
width: 0
|
|
297
|
-
});
|
|
55
|
+
setDropPreview = (dropPreview) => {
|
|
56
|
+
if (!Number.isFinite(dropPreview.left) || !Number.isFinite(dropPreview.width))
|
|
57
|
+
return;
|
|
58
|
+
const current = this.state.dropPreview;
|
|
59
|
+
if (current?.left === dropPreview.left && current?.width === dropPreview.width)
|
|
60
|
+
return;
|
|
61
|
+
this.setState({ dropPreview });
|
|
298
62
|
};
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
const isVertical = schedulerData.isVerticalResourceView();
|
|
318
|
-
// vertical view: rows are time slots and columns are resources, so the roles swap
|
|
319
|
-
const selectedRowIds = this.getSelectedResourceIds();
|
|
320
|
-
let startTime, endTime;
|
|
321
|
-
if (isVertical) {
|
|
322
|
-
startTime = selectedRowIds[0] ?? resourceEvents.slotId;
|
|
323
|
-
const lastRowId = selectedRowIds[selectedRowIds.length - 1] ?? startTime;
|
|
324
|
-
endTime = localeDayjs(new Date(lastRowId)).add(config.minuteStep, 'minutes').format(DATETIME_FORMAT);
|
|
325
|
-
} else {
|
|
326
|
-
startTime = headers[safeLeftIndex].time;
|
|
327
|
-
endTime = resourceEvents.headerItems[safeRightIndex - 1].end;
|
|
328
|
-
if (cellUnit !== CellUnit.Hour) {
|
|
329
|
-
endTime = localeDayjs(new Date(resourceEvents.headerItems[safeRightIndex - 1].start)).hour(23).minute(59).second(59).format(DATETIME_FORMAT);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Get selected resource IDs
|
|
334
|
-
const selectedResourceIds = isVertical ? headers.slice(safeLeftIndex, safeRightIndex).map(header => header.id) : selectedRowIds;
|
|
335
|
-
const slotId = selectedResourceIds.length > 0 ? selectedResourceIds[0] : resourceEvents.slotId;
|
|
336
|
-
const slotName = selectedResourceIds.length > 0 ? schedulerData.getResourceById(slotId)?.name || slotId : resourceEvents.slotName;
|
|
337
|
-
this.setState({
|
|
338
|
-
startX: 0,
|
|
339
|
-
leftIndex: 0,
|
|
340
|
-
left: 0,
|
|
341
|
-
rightIndex: 0,
|
|
342
|
-
width: 0,
|
|
343
|
-
isSelecting: false,
|
|
344
|
-
originalStartRowIndex: -1,
|
|
345
|
-
startRowIndex: -1,
|
|
346
|
-
endRowIndex: -1
|
|
347
|
-
});
|
|
348
|
-
this.emitSelectionChange(false, [], {
|
|
349
|
-
left: 0,
|
|
350
|
-
width: 0
|
|
351
|
-
});
|
|
352
|
-
let hasConflict = false;
|
|
353
|
-
if (config.checkConflict) {
|
|
354
|
-
const start = localeDayjs(new Date(startTime));
|
|
355
|
-
const end = localeDayjs(endTime);
|
|
356
|
-
events.forEach(e => {
|
|
357
|
-
const eventResourceIds = e.resourceIds || [e.resourceId];
|
|
358
|
-
const hasOverlap = selectedResourceIds.some(selectedId => eventResourceIds.includes(selectedId));
|
|
359
|
-
if (hasOverlap) {
|
|
360
|
-
const eStart = localeDayjs(e.start);
|
|
361
|
-
const eEnd = localeDayjs(e.end);
|
|
362
|
-
if (start >= eStart && start < eEnd || end > eStart && end <= eEnd || eStart >= start && eStart < end || eEnd > start && eEnd <= end) hasConflict = true;
|
|
63
|
+
cleanupDragInteraction = () => {
|
|
64
|
+
document.documentElement.removeEventListener('touchmove', asListener(this.doDrag), false);
|
|
65
|
+
document.documentElement.removeEventListener('touchend', asListener(this.stopDrag), false);
|
|
66
|
+
document.documentElement.removeEventListener('touchcancel', asListener(this.cancelDrag), false);
|
|
67
|
+
document.documentElement.removeEventListener('mousemove', asListener(this.doDrag), false);
|
|
68
|
+
document.documentElement.removeEventListener('mouseup', asListener(this.stopDrag), false);
|
|
69
|
+
document.onselectstart = null;
|
|
70
|
+
document.ondragstart = null;
|
|
71
|
+
};
|
|
72
|
+
supportTouchHelper = (evType = 'add') => {
|
|
73
|
+
const container = this.eventContainer;
|
|
74
|
+
if (!container)
|
|
75
|
+
return;
|
|
76
|
+
const ev = evType === 'add' ? container.addEventListener : container.removeEventListener;
|
|
77
|
+
if (this.supportTouch) {
|
|
78
|
+
// ev('touchstart', this.initDrag, false);
|
|
363
79
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
}
|
|
386
|
-
} else if (newEvent !== undefined) {
|
|
387
|
-
// Pass resourceIds for multi-resource events
|
|
388
|
-
newEvent(schedulerData, slotId, slotName, startTime, endTime, undefined, {
|
|
389
|
-
resourceIds: selectedResourceIds.length > 1 ? selectedResourceIds : undefined
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
cancelDrag = ev => {
|
|
394
|
-
if (ev?.stopPropagation) ev.stopPropagation();
|
|
395
|
-
const {
|
|
396
|
-
isSelecting
|
|
397
|
-
} = this.state;
|
|
398
|
-
if (isSelecting) {
|
|
399
|
-
this.cleanupDragInteraction();
|
|
400
|
-
this.setState({
|
|
401
|
-
startX: 0,
|
|
402
|
-
leftIndex: 0,
|
|
403
|
-
left: 0,
|
|
404
|
-
rightIndex: 0,
|
|
405
|
-
width: 0,
|
|
406
|
-
isSelecting: false,
|
|
407
|
-
originalStartRowIndex: -1,
|
|
408
|
-
startRowIndex: -1,
|
|
409
|
-
endRowIndex: -1
|
|
410
|
-
});
|
|
411
|
-
this.emitSelectionChange(false, [], {
|
|
412
|
-
left: 0,
|
|
413
|
-
width: 0
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
};
|
|
417
|
-
emitSelectionChange = (isSelecting, selectedResourceIds, preview = {}) => {
|
|
418
|
-
const {
|
|
419
|
-
onSelectionChange
|
|
420
|
-
} = this.props;
|
|
421
|
-
if (onSelectionChange) {
|
|
422
|
-
onSelectionChange(isSelecting, selectedResourceIds, preview);
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
onAddMoreClick = headerItem => {
|
|
426
|
-
const {
|
|
427
|
-
onSetAddMoreState,
|
|
428
|
-
resourceEvents,
|
|
429
|
-
schedulerData
|
|
430
|
-
} = this.props;
|
|
431
|
-
if (onSetAddMoreState) {
|
|
432
|
-
const {
|
|
433
|
-
config
|
|
434
|
-
} = schedulerData;
|
|
435
|
-
const cellWidth = schedulerData.getContentCellWidth();
|
|
436
|
-
const index = resourceEvents.headerItems.indexOf(headerItem);
|
|
437
|
-
if (index !== -1) {
|
|
438
|
-
let left = index * (cellWidth - 1);
|
|
80
|
+
else {
|
|
81
|
+
// keeps the original unbound call, as ev is not invoked on the container
|
|
82
|
+
ev.call(container, 'mousedown', asListener(this.initDrag), false);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
initDrag = (ev) => {
|
|
86
|
+
const { isSelecting } = this.state;
|
|
87
|
+
if (isSelecting)
|
|
88
|
+
return;
|
|
89
|
+
if (ev.target !== this.eventContainer)
|
|
90
|
+
return;
|
|
91
|
+
ev.stopPropagation();
|
|
92
|
+
const { resourceEvents } = this.props;
|
|
93
|
+
if (resourceEvents.groupOnly)
|
|
94
|
+
return;
|
|
95
|
+
const [clientX, toReturn] = this.dragHelper(ev, 'init');
|
|
96
|
+
if (toReturn) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const { schedulerData } = this.props;
|
|
100
|
+
const cellWidth = schedulerData.getContentCellWidth();
|
|
439
101
|
const pos = getPos(this.eventContainer);
|
|
440
|
-
|
|
441
|
-
const
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
102
|
+
const startX = clientX - pos.x;
|
|
103
|
+
const leftIndex = Math.floor(startX / cellWidth);
|
|
104
|
+
const left = leftIndex * cellWidth;
|
|
105
|
+
const rightIndex = Math.ceil(startX / cellWidth);
|
|
106
|
+
const width = (rightIndex - leftIndex) * cellWidth;
|
|
107
|
+
// Get the row index of this resource
|
|
108
|
+
const startRowIndex = this.getResourceRowIndex(resourceEvents.slotId);
|
|
109
|
+
this.setState({
|
|
110
|
+
startX,
|
|
111
|
+
left,
|
|
112
|
+
leftIndex,
|
|
113
|
+
width,
|
|
114
|
+
rightIndex,
|
|
115
|
+
isSelecting: true,
|
|
116
|
+
originalStartRowIndex: startRowIndex,
|
|
117
|
+
startRowIndex,
|
|
118
|
+
endRowIndex: startRowIndex, // Initially same as start
|
|
448
119
|
});
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
const cellMaxEvents = schedulerData.getCellMaxEvents();
|
|
513
|
-
const rowWidth = schedulerData.getContentTableWidth();
|
|
514
|
-
const selectedArea = isSelecting ? /*#__PURE__*/_jsx(SelectedArea, {
|
|
515
|
-
schedulerData: schedulerData,
|
|
516
|
-
left: left,
|
|
517
|
-
width: width
|
|
518
|
-
}) : /*#__PURE__*/_jsx("div", {});
|
|
519
|
-
const sharedSelecting = this.props.selectionPreview?.isSelecting;
|
|
520
|
-
const isSharedSelectedRow = sharedSelecting && this.props.isRowSelected;
|
|
521
|
-
const sharedLeft = this.props.selectionPreview?.left || 0;
|
|
522
|
-
const sharedWidth = this.props.selectionPreview?.width || 0;
|
|
523
|
-
const sharedSelectedArea = !isSelecting && isSharedSelectedRow ? /*#__PURE__*/_jsx(SelectedArea, {
|
|
524
|
-
schedulerData: schedulerData,
|
|
525
|
-
left: sharedLeft,
|
|
526
|
-
width: sharedWidth
|
|
527
|
-
}) : null;
|
|
528
|
-
|
|
529
|
-
// Add vertical selection overlay
|
|
530
|
-
const verticalSelectionOverlay = isSelecting && startRowIndex !== endRowIndex ? /*#__PURE__*/_jsx("div", {
|
|
531
|
-
className: "vertical-selection-overlay"
|
|
532
|
-
}) : null;
|
|
533
|
-
const eventList = [];
|
|
534
|
-
resourceEvents.headerItems.forEach((headerItem, index) => {
|
|
535
|
-
if (headerItem.count > 0 || headerItem.summary !== undefined) {
|
|
536
|
-
const isTop = config.summaryPos === SummaryPos.TopRight || config.summaryPos === SummaryPos.Top || config.summaryPos === SummaryPos.TopLeft;
|
|
537
|
-
const marginTop = resourceEvents.hasSummary && isTop ? 1 + config.eventItemLineHeight : 1;
|
|
538
|
-
const renderEventsMaxIndex = headerItem.addMore === 0 ? cellMaxEvents : headerItem.addMoreIndex;
|
|
539
|
-
headerItem.events.forEach((evt, idx) => {
|
|
540
|
-
if (idx < renderEventsMaxIndex && evt !== undefined && evt.render) {
|
|
541
|
-
let durationStart = localeDayjs(new Date(startDate));
|
|
542
|
-
let durationEnd = localeDayjs(endDate);
|
|
543
|
-
if (cellUnit === CellUnit.Hour) {
|
|
544
|
-
durationStart = localeDayjs(new Date(startDate)).add(config.dayStartFrom, 'hours');
|
|
545
|
-
durationEnd = localeDayjs(endDate).add(config.dayStopTo + 1, 'hours');
|
|
546
|
-
}
|
|
547
|
-
const eventStart = normalizeEventStart(evt.eventItem.start);
|
|
548
|
-
const eventEnd = normalizeEventEnd(evt.eventItem.end);
|
|
549
|
-
const isStart = eventStart >= durationStart;
|
|
550
|
-
const isEnd = eventEnd <= durationEnd;
|
|
551
|
-
let left = index * cellWidth + (index > 0 ? 2 : 3);
|
|
552
|
-
let width = evt.span * cellWidth - (index > 0 ? 5 : 6) > 0 ? evt.span * cellWidth - (index > 0 ? 5 : 6) : 0;
|
|
553
|
-
if (cellUnit === CellUnit.Day || cellUnit === CellUnit.Hour) {
|
|
554
|
-
// Clamp the event to the cells it covers, then position it proportionally inside the
|
|
555
|
-
// first and last cell (each cell's own duration, so DST days and sub-slot times are handled).
|
|
556
|
-
const lastHeaderItem = resourceEvents.headerItems[index + evt.span - 1] ?? headerItem;
|
|
557
|
-
const firstCellStart = localeDayjs(new Date(headerItem.start));
|
|
558
|
-
const firstCellEnd = localeDayjs(new Date(headerItem.end));
|
|
559
|
-
const lastCellStart = localeDayjs(new Date(lastHeaderItem.start));
|
|
560
|
-
const lastCellEnd = localeDayjs(new Date(lastHeaderItem.end));
|
|
561
|
-
const clampedStart = eventStart.isAfter(firstCellStart) ? eventStart : firstCellStart;
|
|
562
|
-
const clampedEnd = eventEnd.isBefore(lastCellEnd) ? eventEnd : lastCellEnd;
|
|
563
|
-
const startFraction = clampedStart.diff(firstCellStart) / firstCellEnd.diff(firstCellStart);
|
|
564
|
-
const endFraction = clampedEnd.diff(lastCellStart) / lastCellEnd.diff(lastCellStart);
|
|
565
|
-
const usableWidth = evt.span * cellWidth - (index > 0 ? 5 : 6);
|
|
566
|
-
left = index * cellWidth + (index > 0 ? 2 : 3) + usableWidth * startFraction / evt.span;
|
|
567
|
-
width = Math.max(1, usableWidth * (evt.span - 1 + endFraction - startFraction) / evt.span);
|
|
568
|
-
} else {
|
|
569
|
-
width = evt.span * cellWidth - (index > 0 ? 5 : 6) > 0 ? evt.span * cellWidth - (index > 0 ? 5 : 6) : 0;
|
|
120
|
+
this.emitSelectionChange(true, this.getSelectedResourceIds(startRowIndex, startRowIndex), { left, width });
|
|
121
|
+
if (this.supportTouch) {
|
|
122
|
+
document.documentElement.addEventListener('touchmove', asListener(this.doDrag), false);
|
|
123
|
+
document.documentElement.addEventListener('touchend', asListener(this.stopDrag), false);
|
|
124
|
+
document.documentElement.addEventListener('touchcancel', asListener(this.cancelDrag), false);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
document.documentElement.addEventListener('mousemove', asListener(this.doDrag), false);
|
|
128
|
+
document.documentElement.addEventListener('mouseup', asListener(this.stopDrag), false);
|
|
129
|
+
}
|
|
130
|
+
document.onselectstart = () => false;
|
|
131
|
+
document.ondragstart = () => false;
|
|
132
|
+
};
|
|
133
|
+
doDrag = (ev) => {
|
|
134
|
+
ev.stopPropagation();
|
|
135
|
+
const [clientX, toReturn] = this.dragHelper(ev, 'do');
|
|
136
|
+
if (toReturn) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const { originalStartRowIndex } = this.state;
|
|
140
|
+
const startX = this.state.startX ?? 0;
|
|
141
|
+
const { schedulerData } = this.props;
|
|
142
|
+
const { headers } = schedulerData;
|
|
143
|
+
const cellWidth = schedulerData.getContentCellWidth();
|
|
144
|
+
const pos = getPos(this.eventContainer);
|
|
145
|
+
const currentX = clientX - pos.x;
|
|
146
|
+
let leftIndex = Math.floor(Math.min(startX, currentX) / cellWidth);
|
|
147
|
+
leftIndex = leftIndex < 0 ? 0 : leftIndex;
|
|
148
|
+
const left = leftIndex * cellWidth;
|
|
149
|
+
let rightIndex = Math.ceil(Math.max(startX, currentX) / cellWidth);
|
|
150
|
+
rightIndex = rightIndex > headers.length ? headers.length : rightIndex;
|
|
151
|
+
const width = (rightIndex - leftIndex) * cellWidth;
|
|
152
|
+
// Calculate current row based on per-row heights (not a uniform row height assumption).
|
|
153
|
+
let clientY = ev.clientY;
|
|
154
|
+
const { changedTouches } = ev;
|
|
155
|
+
if (this.supportTouch && changedTouches && changedTouches.length > 0) {
|
|
156
|
+
clientY = changedTouches[0].clientY;
|
|
157
|
+
}
|
|
158
|
+
const currentY = clientY - pos.y;
|
|
159
|
+
const displayRenderData = this.getDisplayRenderData();
|
|
160
|
+
if (displayRenderData.length === 0) {
|
|
161
|
+
this.setState({
|
|
162
|
+
leftIndex,
|
|
163
|
+
left,
|
|
164
|
+
rightIndex,
|
|
165
|
+
width,
|
|
166
|
+
isSelecting: true,
|
|
167
|
+
startRowIndex: -1,
|
|
168
|
+
endRowIndex: -1,
|
|
169
|
+
});
|
|
170
|
+
this.emitSelectionChange(true, [], { left, width });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const rowHeights = displayRenderData.map(row => row?.rowHeight || DEFAULT_ROW_HEIGHT);
|
|
174
|
+
const startRowTop = rowHeights.slice(0, Math.max(0, originalStartRowIndex)).reduce((sum, h) => sum + h, 0);
|
|
175
|
+
const absoluteY = startRowTop + currentY;
|
|
176
|
+
let cumulativeHeight = 0;
|
|
177
|
+
let currentRowIndex = rowHeights.length - 1;
|
|
178
|
+
for (let i = 0; i < rowHeights.length; i += 1) {
|
|
179
|
+
cumulativeHeight += rowHeights[i];
|
|
180
|
+
if (absoluteY < cumulativeHeight) {
|
|
181
|
+
currentRowIndex = i;
|
|
182
|
+
break;
|
|
570
183
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
184
|
+
}
|
|
185
|
+
if (absoluteY < 0) {
|
|
186
|
+
currentRowIndex = 0;
|
|
187
|
+
}
|
|
188
|
+
const minRowIndex = Math.min(originalStartRowIndex, currentRowIndex);
|
|
189
|
+
const maxRowIndex = Math.max(originalStartRowIndex, currentRowIndex);
|
|
190
|
+
// Clamp to valid row indices
|
|
191
|
+
const clampedMinRow = Math.max(0, minRowIndex);
|
|
192
|
+
const clampedMaxRow = Math.min(displayRenderData.length - 1, maxRowIndex);
|
|
193
|
+
this.setState({
|
|
194
|
+
leftIndex,
|
|
195
|
+
left,
|
|
196
|
+
rightIndex,
|
|
197
|
+
width,
|
|
198
|
+
isSelecting: true,
|
|
199
|
+
startRowIndex: clampedMinRow,
|
|
200
|
+
endRowIndex: clampedMaxRow,
|
|
201
|
+
});
|
|
202
|
+
this.emitSelectionChange(true, this.getSelectedResourceIds(clampedMinRow, clampedMaxRow), { left, width });
|
|
203
|
+
};
|
|
204
|
+
dragHelper = (ev, dragType) => {
|
|
205
|
+
let clientX = 0;
|
|
206
|
+
if (this.supportTouch) {
|
|
207
|
+
const { changedTouches } = ev;
|
|
208
|
+
if (changedTouches.length === 0)
|
|
209
|
+
return [clientX, true];
|
|
210
|
+
const touch = changedTouches[0];
|
|
211
|
+
clientX = touch.pageX;
|
|
212
|
+
}
|
|
213
|
+
else if (dragType === 'init') {
|
|
214
|
+
const { buttons } = ev;
|
|
215
|
+
if (buttons !== undefined && buttons !== 1)
|
|
216
|
+
return [clientX, true];
|
|
217
|
+
clientX = ev.clientX;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
clientX = ev.clientX;
|
|
221
|
+
}
|
|
222
|
+
return [clientX, false];
|
|
223
|
+
};
|
|
224
|
+
stopDrag = (ev) => {
|
|
225
|
+
if (ev?.stopPropagation)
|
|
226
|
+
ev.stopPropagation();
|
|
227
|
+
const { schedulerData, newEvent, resourceEvents } = this.props;
|
|
228
|
+
const { headers, events, config, cellUnit, localeDayjs } = schedulerData;
|
|
229
|
+
const { leftIndex, rightIndex } = this.state;
|
|
230
|
+
this.cleanupDragInteraction();
|
|
231
|
+
const resetSelection = () => {
|
|
232
|
+
this.setState({
|
|
233
|
+
startX: 0,
|
|
234
|
+
leftIndex: 0,
|
|
235
|
+
left: 0,
|
|
236
|
+
rightIndex: 0,
|
|
237
|
+
width: 0,
|
|
238
|
+
isSelecting: false,
|
|
239
|
+
originalStartRowIndex: -1,
|
|
240
|
+
startRowIndex: -1,
|
|
241
|
+
endRowIndex: -1,
|
|
242
|
+
});
|
|
243
|
+
this.emitSelectionChange(false, [], { left: 0, width: 0 });
|
|
244
|
+
};
|
|
245
|
+
if (headers.length === 0 || !resourceEvents.headerItems || resourceEvents.headerItems.length === 0) {
|
|
246
|
+
resetSelection();
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// a cell width of 0 (container not measured yet) makes the drag indexes NaN or Infinity
|
|
250
|
+
const toIndex = (value, fallback) => value !== undefined && Number.isFinite(value) ? value : fallback;
|
|
251
|
+
const maxLeftIndex = headers.length - 1;
|
|
252
|
+
const safeLeftIndex = Math.max(0, Math.min(toIndex(leftIndex, 0), maxLeftIndex));
|
|
253
|
+
const maxRightIndex = Math.min(headers.length, resourceEvents.headerItems.length);
|
|
254
|
+
let safeRightIndex = Math.max(1, toIndex(rightIndex, 1), safeLeftIndex + 1);
|
|
255
|
+
safeRightIndex = Math.min(safeRightIndex, maxRightIndex);
|
|
256
|
+
// headers and headerItems can be out of step while the view rebuilds; drop the selection instead of throwing
|
|
257
|
+
if (!headers[safeLeftIndex] || !resourceEvents.headerItems[safeRightIndex - 1]) {
|
|
258
|
+
resetSelection();
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const isVertical = schedulerData.isVerticalResourceView();
|
|
262
|
+
// vertical view: rows are time slots and columns are resources, so the roles swap
|
|
263
|
+
const selectedRowIds = this.getSelectedResourceIds();
|
|
264
|
+
let startTime;
|
|
265
|
+
let endTime;
|
|
266
|
+
if (isVertical) {
|
|
267
|
+
// in the vertical view slot ids are the row's time string
|
|
268
|
+
startTime = (selectedRowIds[0] ?? resourceEvents.slotId);
|
|
269
|
+
const lastRowId = selectedRowIds[selectedRowIds.length - 1] ?? startTime;
|
|
270
|
+
endTime = localeDayjs(new Date(lastRowId)).add(config.minuteStep, 'minutes').format(DATETIME_FORMAT);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
startTime = headers[safeLeftIndex].time;
|
|
274
|
+
endTime = resourceEvents.headerItems[safeRightIndex - 1].end;
|
|
275
|
+
if (cellUnit !== CellUnit.Hour) {
|
|
276
|
+
endTime = localeDayjs(new Date(resourceEvents.headerItems[safeRightIndex - 1].start))
|
|
277
|
+
.hour(23)
|
|
278
|
+
.minute(59)
|
|
279
|
+
.second(59)
|
|
280
|
+
.format(DATETIME_FORMAT);
|
|
578
281
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
eventItemTemplateResolver: this.props.eventItemTemplateResolver,
|
|
602
|
-
eventItemPopoverTemplateResolver: this.props.eventItemPopoverTemplateResolver,
|
|
603
|
-
subtitleGetter: this.props.subtitleGetter,
|
|
604
|
-
updateEventStart: this.props.updateEventStart,
|
|
605
|
-
updateEventEnd: this.props.updateEventEnd,
|
|
606
|
-
moveEvent: this.props.moveEvent,
|
|
607
|
-
conflictOccurred: this.props.conflictOccurred
|
|
608
|
-
}, eventKey);
|
|
609
|
-
eventList.push(eventItem);
|
|
610
|
-
}
|
|
282
|
+
}
|
|
283
|
+
// Get selected resource IDs
|
|
284
|
+
const selectedResourceIds = isVertical
|
|
285
|
+
? headers
|
|
286
|
+
.slice(safeLeftIndex, safeRightIndex)
|
|
287
|
+
.map(header => header.id)
|
|
288
|
+
.filter((id) => id !== undefined)
|
|
289
|
+
: selectedRowIds;
|
|
290
|
+
const slotId = selectedResourceIds.length > 0 ? selectedResourceIds[0] : resourceEvents.slotId;
|
|
291
|
+
const slotName = selectedResourceIds.length > 0
|
|
292
|
+
? String(schedulerData.getResourceById(slotId)?.name || slotId)
|
|
293
|
+
: resourceEvents.slotName;
|
|
294
|
+
this.setState({
|
|
295
|
+
startX: 0,
|
|
296
|
+
leftIndex: 0,
|
|
297
|
+
left: 0,
|
|
298
|
+
rightIndex: 0,
|
|
299
|
+
width: 0,
|
|
300
|
+
isSelecting: false,
|
|
301
|
+
originalStartRowIndex: -1,
|
|
302
|
+
startRowIndex: -1,
|
|
303
|
+
endRowIndex: -1,
|
|
611
304
|
});
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
305
|
+
this.emitSelectionChange(false, [], { left: 0, width: 0 });
|
|
306
|
+
let hasConflict = false;
|
|
307
|
+
if (config.checkConflict) {
|
|
308
|
+
const start = localeDayjs(new Date(startTime));
|
|
309
|
+
const end = localeDayjs(endTime);
|
|
310
|
+
events.forEach(e => {
|
|
311
|
+
const eventResourceIds = e.resourceIds || [e.resourceId];
|
|
312
|
+
const hasOverlap = selectedResourceIds.some(selectedId => eventResourceIds.includes(selectedId));
|
|
313
|
+
if (hasOverlap) {
|
|
314
|
+
const eStart = localeDayjs(e.start);
|
|
315
|
+
const eEnd = localeDayjs(e.end);
|
|
316
|
+
if ((start >= eStart && start < eEnd) ||
|
|
317
|
+
(end > eStart && end <= eEnd) ||
|
|
318
|
+
(eStart >= start && eStart < end) ||
|
|
319
|
+
(eEnd > start && eEnd <= end))
|
|
320
|
+
hasConflict = true;
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
if (hasConflict) {
|
|
325
|
+
const { conflictOccurred } = this.props;
|
|
326
|
+
if (conflictOccurred !== undefined) {
|
|
327
|
+
conflictOccurred(schedulerData, 'New', {
|
|
328
|
+
id: undefined,
|
|
329
|
+
start: startTime,
|
|
330
|
+
end: endTime,
|
|
331
|
+
resourceId: slotId, // Keep for backward compatibility
|
|
332
|
+
resourceIds: selectedResourceIds, // Add multi-resource support
|
|
333
|
+
slotId,
|
|
334
|
+
slotName,
|
|
335
|
+
title: undefined,
|
|
336
|
+
}, DnDTypes.EVENT, slotId, slotName, startTime, endTime);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
console.log('Conflict occurred, set conflictOccurred func in Scheduler to handle it');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
else if (newEvent !== undefined) {
|
|
343
|
+
// Pass resourceIds for multi-resource events
|
|
344
|
+
newEvent(schedulerData, slotId, slotName, startTime, endTime, undefined, {
|
|
345
|
+
resourceIds: selectedResourceIds.length > 1 ? selectedResourceIds : undefined,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
cancelDrag = (ev) => {
|
|
350
|
+
if (ev?.stopPropagation)
|
|
351
|
+
ev.stopPropagation();
|
|
352
|
+
const { isSelecting } = this.state;
|
|
353
|
+
if (isSelecting) {
|
|
354
|
+
this.cleanupDragInteraction();
|
|
355
|
+
this.setState({
|
|
356
|
+
startX: 0,
|
|
357
|
+
leftIndex: 0,
|
|
358
|
+
left: 0,
|
|
359
|
+
rightIndex: 0,
|
|
360
|
+
width: 0,
|
|
361
|
+
isSelecting: false,
|
|
362
|
+
originalStartRowIndex: -1,
|
|
363
|
+
startRowIndex: -1,
|
|
364
|
+
endRowIndex: -1,
|
|
365
|
+
});
|
|
366
|
+
this.emitSelectionChange(false, [], { left: 0, width: 0 });
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
emitSelectionChange = (isSelecting, selectedResourceIds, preview = {}) => {
|
|
370
|
+
const { onSelectionChange } = this.props;
|
|
371
|
+
if (onSelectionChange) {
|
|
372
|
+
onSelectionChange(isSelecting, selectedResourceIds, preview);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
onAddMoreClick = (headerItem) => {
|
|
376
|
+
const { onSetAddMoreState, resourceEvents, schedulerData } = this.props;
|
|
377
|
+
if (onSetAddMoreState) {
|
|
378
|
+
const { config } = schedulerData;
|
|
379
|
+
const cellWidth = schedulerData.getContentCellWidth();
|
|
380
|
+
const index = resourceEvents.headerItems.indexOf(headerItem);
|
|
381
|
+
if (index !== -1) {
|
|
382
|
+
let left = index * (cellWidth - 1);
|
|
383
|
+
const pos = getPos(this.eventContainer);
|
|
384
|
+
left += pos.x;
|
|
385
|
+
const top = pos.y;
|
|
386
|
+
const height = ((headerItem.count ?? 0) + 1) * config.eventItemLineHeight + 20;
|
|
387
|
+
onSetAddMoreState({
|
|
388
|
+
headerItem,
|
|
389
|
+
left,
|
|
390
|
+
top,
|
|
391
|
+
height,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
eventContainerRef = (element) => {
|
|
397
|
+
this.eventContainer = element;
|
|
398
|
+
// Also set the drop ref if it exists
|
|
399
|
+
const { dropRef } = this.props;
|
|
400
|
+
if (dropRef) {
|
|
401
|
+
dropRef(element);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
getResourceRowIndex = (slotId) => {
|
|
405
|
+
return this.getDisplayRenderData().findIndex(row => row.slotId === slotId);
|
|
406
|
+
};
|
|
407
|
+
getDisplayRenderData = () => {
|
|
408
|
+
const { schedulerData } = this.props;
|
|
409
|
+
return schedulerData.renderData.filter(row => row.render);
|
|
410
|
+
};
|
|
411
|
+
getSelectedResourceIds = (startOverride, endOverride) => {
|
|
412
|
+
const { startRowIndex, endRowIndex } = this.state;
|
|
413
|
+
const displayRenderData = this.getDisplayRenderData();
|
|
414
|
+
const from = startOverride !== undefined ? startOverride : startRowIndex;
|
|
415
|
+
const to = endOverride !== undefined ? endOverride : endRowIndex;
|
|
416
|
+
if (from === -1 || to === -1) {
|
|
417
|
+
return [];
|
|
626
418
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
schedulerData: schedulerData,
|
|
634
|
-
summary: headerItem.summary,
|
|
635
|
-
left: left,
|
|
636
|
-
width: width,
|
|
637
|
-
top: top
|
|
638
|
-
}, key);
|
|
639
|
-
eventList.push(summary);
|
|
419
|
+
const selectedResourceIds = [];
|
|
420
|
+
for (let i = from; i <= to; i++) {
|
|
421
|
+
const row = displayRenderData[i];
|
|
422
|
+
if (row && !row.groupOnly) {
|
|
423
|
+
selectedResourceIds.push(row.slotId);
|
|
424
|
+
}
|
|
640
425
|
}
|
|
641
|
-
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
426
|
+
return selectedResourceIds;
|
|
427
|
+
};
|
|
428
|
+
render() {
|
|
429
|
+
const { resourceEvents, schedulerData, dndSource } = this.props;
|
|
430
|
+
const { cellUnit, startDate, endDate, config, localeDayjs } = schedulerData;
|
|
431
|
+
const { isSelecting, left, width, startRowIndex, endRowIndex } = this.state;
|
|
432
|
+
const cellWidth = schedulerData.getContentCellWidth();
|
|
433
|
+
const cellMaxEvents = schedulerData.getCellMaxEvents();
|
|
434
|
+
const rowWidth = schedulerData.getContentTableWidth();
|
|
435
|
+
const selectedArea = isSelecting ? (_jsx(SelectedArea, { schedulerData: schedulerData, left: left, width: width })) : (_jsx("div", {}));
|
|
436
|
+
const sharedSelecting = this.props.selectionPreview?.isSelecting;
|
|
437
|
+
const isSharedSelectedRow = sharedSelecting && this.props.isRowSelected;
|
|
438
|
+
const sharedLeft = this.props.selectionPreview?.left || 0;
|
|
439
|
+
const sharedWidth = this.props.selectionPreview?.width || 0;
|
|
440
|
+
const sharedSelectedArea = !isSelecting && isSharedSelectedRow ? (_jsx(SelectedArea, { schedulerData: schedulerData, left: sharedLeft, width: sharedWidth })) : null;
|
|
441
|
+
// Add vertical selection overlay
|
|
442
|
+
const verticalSelectionOverlay = isSelecting && startRowIndex !== endRowIndex ? _jsx("div", { className: "vertical-selection-overlay" }) : null;
|
|
443
|
+
const eventList = [];
|
|
444
|
+
resourceEvents.headerItems.forEach((headerItem, index) => {
|
|
445
|
+
if ((headerItem.count ?? 0) > 0 || headerItem.summary !== undefined) {
|
|
446
|
+
const isTop = config.summaryPos === SummaryPos.TopRight ||
|
|
447
|
+
config.summaryPos === SummaryPos.Top ||
|
|
448
|
+
config.summaryPos === SummaryPos.TopLeft;
|
|
449
|
+
const marginTop = resourceEvents.hasSummary && isTop ? 1 + config.eventItemLineHeight : 1;
|
|
450
|
+
const renderEventsMaxIndex = headerItem.addMore === 0 ? cellMaxEvents : (headerItem.addMoreIndex ?? 0);
|
|
451
|
+
headerItem.events.forEach((evt, idx) => {
|
|
452
|
+
if (idx < renderEventsMaxIndex && evt !== undefined && evt.render) {
|
|
453
|
+
let durationStart = localeDayjs(toDate(startDate));
|
|
454
|
+
let durationEnd = localeDayjs(endDate);
|
|
455
|
+
if (cellUnit === CellUnit.Hour) {
|
|
456
|
+
durationStart = localeDayjs(toDate(startDate)).add(config.dayStartFrom, 'hours');
|
|
457
|
+
durationEnd = localeDayjs(endDate).add(config.dayStopTo + 1, 'hours');
|
|
458
|
+
}
|
|
459
|
+
const eventStart = normalizeEventStart(evt.eventItem.start);
|
|
460
|
+
const eventEnd = normalizeEventEnd(evt.eventItem.end);
|
|
461
|
+
const isStart = eventStart >= durationStart;
|
|
462
|
+
const isEnd = eventEnd <= durationEnd;
|
|
463
|
+
let left = index * cellWidth + (index > 0 ? 2 : 3);
|
|
464
|
+
let width = evt.span * cellWidth - (index > 0 ? 5 : 6) > 0 ? evt.span * cellWidth - (index > 0 ? 5 : 6) : 0;
|
|
465
|
+
if (cellUnit === CellUnit.Day || cellUnit === CellUnit.Hour) {
|
|
466
|
+
// Clamp the event to the cells it covers, then position it proportionally inside the
|
|
467
|
+
// first and last cell (each cell's own duration, so DST days and sub-slot times are handled).
|
|
468
|
+
const lastHeaderItem = resourceEvents.headerItems[index + evt.span - 1] ?? headerItem;
|
|
469
|
+
const firstCellStart = localeDayjs(new Date(headerItem.start));
|
|
470
|
+
const firstCellEnd = localeDayjs(new Date(headerItem.end));
|
|
471
|
+
const lastCellStart = localeDayjs(new Date(lastHeaderItem.start));
|
|
472
|
+
const lastCellEnd = localeDayjs(new Date(lastHeaderItem.end));
|
|
473
|
+
const clampedStart = eventStart.isAfter(firstCellStart) ? eventStart : firstCellStart;
|
|
474
|
+
const clampedEnd = eventEnd.isBefore(lastCellEnd) ? eventEnd : lastCellEnd;
|
|
475
|
+
const startFraction = clampedStart.diff(firstCellStart) / firstCellEnd.diff(firstCellStart);
|
|
476
|
+
const endFraction = clampedEnd.diff(lastCellStart) / lastCellEnd.diff(lastCellStart);
|
|
477
|
+
const usableWidth = evt.span * cellWidth - (index > 0 ? 5 : 6);
|
|
478
|
+
left = index * cellWidth + (index > 0 ? 2 : 3) + (usableWidth * startFraction) / evt.span;
|
|
479
|
+
width = Math.max(1, (usableWidth * (evt.span - 1 + endFraction - startFraction)) / evt.span);
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
width = evt.span * cellWidth - (index > 0 ? 5 : 6) > 0 ? evt.span * cellWidth - (index > 0 ? 5 : 6) : 0;
|
|
483
|
+
}
|
|
484
|
+
const top = schedulerData.isVerticalResourceView() ? 0 : marginTop + idx * config.eventItemLineHeight;
|
|
485
|
+
const height = schedulerData.isVerticalResourceView() ? resourceEvents.rowHeight : undefined;
|
|
486
|
+
if (schedulerData.isVerticalResourceView()) {
|
|
487
|
+
const eventCount = headerItem.count ?? 0;
|
|
488
|
+
const itemWidth = (cellWidth - (index > 0 ? 5 : 6)) / eventCount;
|
|
489
|
+
left = index * cellWidth + (index > 0 ? 2 : 3) + idx * itemWidth;
|
|
490
|
+
width = itemWidth;
|
|
491
|
+
}
|
|
492
|
+
const eventKey = `${evt.eventItem.id}_${resourceEvents.slotId}_${index}`;
|
|
493
|
+
const eventItem = (_jsx(EventItem, { schedulerData: schedulerData, eventItem: evt.eventItem, dndSource: dndSource, isStart: isStart, isEnd: isEnd, isInPopover: false, slotId: resourceEvents.slotId, left: left, width: width, top: top, height: height, leftIndex: index, rightIndex: index + evt.span,
|
|
494
|
+
// Passing through functional props
|
|
495
|
+
eventItemClick: this.props.eventItemClick, viewEventClick: this.props.viewEventClick, viewEventText: this.props.viewEventText, viewEvent2Click: this.props.viewEvent2Click, viewEvent2Text: this.props.viewEvent2Text, eventItemTemplateResolver: this.props.eventItemTemplateResolver, eventItemPopoverTemplateResolver: this.props.eventItemPopoverTemplateResolver, subtitleGetter: this.props.subtitleGetter, updateEventStart: this.props.updateEventStart, updateEventEnd: this.props.updateEventEnd, moveEvent: this.props.moveEvent, conflictOccurred: this.props.conflictOccurred }, eventKey));
|
|
496
|
+
eventList.push(eventItem);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
if (headerItem.addMore !== undefined && headerItem.addMore > 0) {
|
|
500
|
+
const left = index * cellWidth + (index > 0 ? 2 : 3);
|
|
501
|
+
const width = cellWidth - (index > 0 ? 5 : 6);
|
|
502
|
+
const top = marginTop + (headerItem.addMoreIndex ?? 0) * config.eventItemLineHeight;
|
|
503
|
+
const addMoreItem = (_jsx(AddMore, { schedulerData: schedulerData, headerItem: headerItem, number: headerItem.addMore, left: left, width: width, top: top, clickAction: this.onAddMoreClick }, `add-more-${headerItem.time}`));
|
|
504
|
+
eventList.push(addMoreItem);
|
|
505
|
+
}
|
|
506
|
+
if (headerItem.summary !== undefined) {
|
|
507
|
+
const top = isTop ? 1 : resourceEvents.rowHeight - config.eventItemLineHeight + 1;
|
|
508
|
+
const left = index * cellWidth + (index > 0 ? 2 : 3);
|
|
509
|
+
const width = cellWidth - (index > 0 ? 5 : 6);
|
|
510
|
+
const key = `${resourceEvents.slotId}_${headerItem.time}`;
|
|
511
|
+
const summary = (_jsx(Summary, { schedulerData: schedulerData, summary: headerItem.summary, left: left, width: width, top: top }, key));
|
|
512
|
+
eventList.push(summary);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
// drop preview: styled box where the item being dragged over this row would be placed
|
|
517
|
+
const { dropPreview } = this.state;
|
|
518
|
+
const dropPreviewBox = this.props.isOver && this.props.canDrop && config.dropPreviewEnabled !== false && dropPreview ? (_jsx("div", { className: `drop-preview${config.dropPreviewClassName ? ` ${config.dropPreviewClassName}` : ''}`, style: { left: dropPreview.left, width: dropPreview.width, ...config.dropPreviewStyle } })) : null;
|
|
519
|
+
const eventContainer = (_jsxs("div", { ref: this.eventContainerRef, className: "event-container", "data-slot-id": resourceEvents.slotId, style: { height: resourceEvents.rowHeight }, children: [selectedArea, sharedSelectedArea, verticalSelectionOverlay, dropPreviewBox, eventList] }));
|
|
520
|
+
return (_jsx("tr", { children: _jsx("td", { style: { width: rowWidth }, children: eventContainer }) }));
|
|
521
|
+
}
|
|
674
522
|
}
|
|
675
|
-
|
|
676
523
|
// Wrapper component to use useDrop hook
|
|
677
|
-
const ResourceEventsWithDnD = props => {
|
|
678
|
-
|
|
679
|
-
schedulerData
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
drop: (_item, monitor) => spec.drop(propsRef.current, monitor, componentRef.current),
|
|
713
|
-
hover: (_item, monitor) => spec.hover(propsRef.current, monitor, componentRef.current),
|
|
714
|
-
canDrop: (_item, monitor) => spec.canDrop(propsRef.current, monitor),
|
|
715
|
-
collect: monitor => ({
|
|
716
|
-
isOver: monitor.isOver(),
|
|
717
|
-
canDrop: monitor.canDrop()
|
|
718
|
-
})
|
|
719
|
-
};
|
|
720
|
-
}, [dndContext, config.dragAndDropEnabled]);
|
|
721
|
-
return /*#__PURE__*/_jsx(ResourceEvents, {
|
|
722
|
-
ref: componentRef,
|
|
723
|
-
...props,
|
|
724
|
-
dropRef: dropRef,
|
|
725
|
-
isOver: isOver,
|
|
726
|
-
canDrop: canDrop
|
|
727
|
-
});
|
|
524
|
+
const ResourceEventsWithDnD = (props) => {
|
|
525
|
+
const { schedulerData, dndContext } = props;
|
|
526
|
+
const { config } = schedulerData;
|
|
527
|
+
const componentRef = React.useRef(null);
|
|
528
|
+
const propsRef = React.useRef(props);
|
|
529
|
+
// Keep propsRef up to date
|
|
530
|
+
React.useEffect(() => {
|
|
531
|
+
propsRef.current = props;
|
|
532
|
+
}, [props]);
|
|
533
|
+
// Always call useDrop unconditionally (Rules of Hooks)
|
|
534
|
+
// Disable functionality when drag and drop is not enabled
|
|
535
|
+
const [{ isOver, canDrop }, dropRef] = useDrop(() => {
|
|
536
|
+
// If drag and drop is disabled, return a no-op spec
|
|
537
|
+
if (!config.dragAndDropEnabled || !dndContext) {
|
|
538
|
+
return {
|
|
539
|
+
accept: [],
|
|
540
|
+
collect: () => ({ isOver: false, canDrop: false }),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
const spec = dndContext.getDropSpec();
|
|
544
|
+
return {
|
|
545
|
+
accept: [...dndContext.sourceMap.keys()],
|
|
546
|
+
drop: (_item, monitor) => componentRef.current ? spec.drop(propsRef.current, monitor, componentRef.current) : undefined,
|
|
547
|
+
hover: (_item, monitor) => {
|
|
548
|
+
if (componentRef.current)
|
|
549
|
+
spec.hover(propsRef.current, monitor, componentRef.current);
|
|
550
|
+
},
|
|
551
|
+
canDrop: (_item, monitor) => spec.canDrop(propsRef.current, monitor),
|
|
552
|
+
collect: monitor => ({
|
|
553
|
+
isOver: monitor.isOver(),
|
|
554
|
+
canDrop: monitor.canDrop(),
|
|
555
|
+
}),
|
|
556
|
+
};
|
|
557
|
+
}, [dndContext, config.dragAndDropEnabled]);
|
|
558
|
+
return _jsx(ResourceEvents, { ref: componentRef, ...props, dropRef: dropRef, isOver: isOver, canDrop: canDrop });
|
|
728
559
|
};
|
|
729
560
|
ResourceEventsWithDnD.displayName = 'ResourceEventsWithDnD';
|
|
730
|
-
export default
|
|
561
|
+
export default React.memo(ResourceEventsWithDnD);
|