-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathwithDragAndDrop.js
More file actions
172 lines (152 loc) · 5.07 KB
/
Copy pathwithDragAndDrop.js
File metadata and controls
172 lines (152 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import PropTypes from 'prop-types'
import React from 'react'
import { DragDropContext } from 'react-dnd'
import cn from 'classnames'
import { accessor } from '../../utils/propTypes'
import DraggableEventWrapper from './DraggableEventWrapper'
import { DroppableDayWrapper, DroppableDateCellWrapper } from './DropWrappers'
let html5Backend
try {
html5Backend = require('react-dnd-html5-backend')
} catch (err) {
/* optional dep missing */
}
/**
* Creates a higher-order component (HOC) supporting drag & drop and optionally resizing
* of events:
*
* ```js
* import Calendar from 'react-big-calendar'
* import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'
* export default withDragAndDrop(Calendar)
* ```
* (you can optionally pass any dnd backend as an optional second argument to `withDragAndDrop`.
* It defaults to `react-dnd-html5-backend` which you should probably include in
* your project if using this default).
*
* Set `resizable` to true in your calendar if you want events to be resizable.
*
* The HOC adds `onEventDrop` and `onEventResize` callback properties if the events are
* moved or resized. They are called with these signatures:
*
* ```js
* function onEventDrop({ event, start, end, allDay }) {...}
* function onEventResize(type, { event, start, end, allDay }) {...} // type is always 'drop'
* ```
*
* Moving and resizing of events has some subtlety which one should be aware of.
*
* In some situations, non-allDay events are displayed in "row" format where they
* are rendered horizontally. This is the case for ALL events in a month view. It
* is also occurs with multi-day events in a day or week view (unless `showMultiDayTimes`
* is set).
*
* When dropping or resizing non-allDay events into a the header area or when
* resizing them horizontally because they are displayed in row format, their
* times are preserved, only their date is changed.
*
* If you care about these corner cases, you can examine the `allDay` param suppled
* in the callback to determine how the user dropped or resized the event.
*
* @param {*} Calendar
* @param {*} backend
*/
export default function withDragAndDrop(
Calendar,
{ backend = html5Backend } = {}
) {
class DragAndDropCalendar extends React.Component {
static propTypes = {
onEventDrop: PropTypes.func,
onEventResize: PropTypes.func,
startAccessor: accessor,
endAccessor: accessor,
allDayAccessor: accessor,
draggableAccessor: accessor,
resizableAccessor: accessor,
selectable: PropTypes.oneOf([true, false, 'ignoreEvents']),
resizable: PropTypes.bool,
components: PropTypes.object,
step: PropTypes.number,
}
static defaultProps = {
// TODO: pick these up from Calendar.defaultProps
components: {},
startAccessor: 'start',
endAccessor: 'end',
allDayAccessor: 'allDay',
draggableAccessor: null,
resizableAccessor: null,
step: 30,
}
static contextTypes = {
dragDropManager: PropTypes.object,
}
static childContextTypes = {
onEventDrop: PropTypes.func,
onEventResize: PropTypes.func,
components: PropTypes.object,
startAccessor: accessor,
endAccessor: accessor,
draggableAccessor: accessor,
resizableAccessor: accessor,
step: PropTypes.number,
}
getChildContext() {
return {
onEventDrop: this.props.onEventDrop,
onEventResize: this.props.onEventResize,
components: this.props.components,
startAccessor: this.props.startAccessor,
endAccessor: this.props.endAccessor,
step: this.props.step,
draggableAccessor: this.props.draggableAccessor,
resizableAccessor: this.props.resizableAccessor,
}
}
constructor(...args) {
super(...args)
this.state = { isDragging: false }
}
componentWillMount() {
let monitor = this.context.dragDropManager.getMonitor()
this.monitor = monitor
this.unsubscribeToStateChange = monitor.subscribeToStateChange(
this.handleStateChange
)
}
componentWillUnmount() {
this.monitor = null
this.unsubscribeToStateChange()
}
handleStateChange = () => {
const isDragging = !!this.monitor.getItem()
if (isDragging !== this.state.isDragging) {
setTimeout(() => this.setState({ isDragging }))
}
}
render() {
const { selectable, components, ...props } = this.props
delete props.onEventDrop
delete props.onEventResize
props.selectable = selectable ? 'ignoreEvents' : false
props.className = cn(
props.className,
'rbc-addons-dnd',
this.state.isDragging && 'rbc-addons-dnd-is-dragging'
)
props.components = {
...components,
dateCellWrapper: DroppableDateCellWrapper,
dayWrapper: DroppableDayWrapper,
eventWrapper: DraggableEventWrapper,
}
return <Calendar {...props} />
}
}
if (backend === false) {
return DragAndDropCalendar
} else {
return DragDropContext(backend)(DragAndDropCalendar)
}
}