diff --git a/src/Calendar.js b/src/Calendar.js
index 67cd073ca..d87ab1ac5 100644
--- a/src/Calendar.js
+++ b/src/Calendar.js
@@ -81,6 +81,11 @@ class Calendar extends React.Component {
*/
events: PropTypes.arrayOf(PropTypes.object),
+ /**
+ * An array of resource objects that map events to a specific resource
+ */
+ resources: PropTypes.arrayOf(PropTypes.object),
+
/**
* Callback fired when the `date` value changes.
*
@@ -575,6 +580,7 @@ class Calendar extends React.Component {
allDayAccessor: 'allDay',
startAccessor: 'start',
endAccessor: 'end',
+ resourceIdAccessor: 'resourceId',
longPressThreshold: 250,
};
diff --git a/src/DayColumn.js b/src/DayColumn.js
index ad9fdda03..061090c5d 100644
--- a/src/DayColumn.js
+++ b/src/DayColumn.js
@@ -68,6 +68,7 @@ class DayColumn extends React.Component {
dayWrapperComponent: elementType,
eventComponent: elementType,
eventWrapperComponent: elementType.isRequired,
+ resource: PropTypes.string
}
static defaultProps = {
@@ -367,6 +368,7 @@ class DayColumn extends React.Component {
slots,
start: startDate,
end: endDate,
+ resourceId: this.props.resource,
action,
})
}
diff --git a/src/TimeColumn.js b/src/TimeColumn.js
index 262a82790..fffd8525f 100644
--- a/src/TimeColumn.js
+++ b/src/TimeColumn.js
@@ -19,6 +19,7 @@ export default class TimeColumn extends Component {
timeGutterFormat: dateFormat,
type: PropTypes.string.isRequired,
className: PropTypes.string,
+ resource: PropTypes.string,
slotPropGetter: PropTypes.func,
dayPropGetter: PropTypes.func,
@@ -33,7 +34,7 @@ export default class TimeColumn extends Component {
dayWrapperComponent: BackgroundWrapper,
}
- renderTimeSliceGroup(key, isNow, date) {
+ renderTimeSliceGroup(key, isNow, date, resource) {
const { dayWrapperComponent, timeslots, showLabels, step, slotPropGetter, dayPropGetter, timeGutterFormat, culture } = this.props;
return (
@@ -46,6 +47,7 @@ export default class TimeColumn extends Component {
dayPropGetter={dayPropGetter}
culture={culture}
timeslots={timeslots}
+ resource={resource}
showLabels={showLabels}
timeGutterFormat={timeGutterFormat}
dayWrapperComponent={dayWrapperComponent}
@@ -54,7 +56,7 @@ export default class TimeColumn extends Component {
}
render() {
- const { className, children, style, now, min, max, step, timeslots } = this.props;
+ const { className, children, style, now, min, max, step, timeslots, resource } = this.props;
const totalMin = dates.diff(min, max, 'minutes')
const numGroups = Math.ceil(totalMin / (step * timeslots))
const renderedSlots = []
@@ -73,7 +75,7 @@ export default class TimeColumn extends Component {
)
next = dates.add(date, groupLengthInMinutes, 'minutes');
- renderedSlots.push(this.renderTimeSliceGroup(i, isNow, date))
+ renderedSlots.push(this.renderTimeSliceGroup(i, isNow, date, resource))
date = next
}
diff --git a/src/TimeGrid.js b/src/TimeGrid.js
index fc58e02e4..0ca6936d7 100644
--- a/src/TimeGrid.js
+++ b/src/TimeGrid.js
@@ -26,6 +26,7 @@ export default class TimeGrid extends Component {
static propTypes = {
events: PropTypes.array.isRequired,
+ resources: PropTypes.array,
step: PropTypes.number,
range: PropTypes.arrayOf(
@@ -49,6 +50,7 @@ export default class TimeGrid extends Component {
allDayAccessor: accessor.isRequired,
startAccessor: accessor.isRequired,
endAccessor: accessor.isRequired,
+ resourceIdAccessor: accessor.isRequired,
selected: PropTypes.object,
selectable: PropTypes.oneOf([true, false, 'ignoreEvents']),
@@ -146,6 +148,7 @@ export default class TimeGrid extends Component {
, width
, startAccessor
, endAccessor
+ , resources
, allDayAccessor
, showMultiDayTimes} = this.props;
@@ -178,10 +181,12 @@ export default class TimeGrid extends Component {
let gutterRef = ref => this._gutters[1] = ref && findDOMNode(ref);
+ let eventsRendered = this.renderEvents(range, rangeEvents, this.props.now, resources || [{}]);
+
return (
- {this.renderHeader(range, allDayEvents, width)}
+ {this.renderHeader(range, allDayEvents, width, resources)}
@@ -193,43 +198,49 @@ export default class TimeGrid extends Component {
ref={gutterRef}
className='rbc-time-gutter'
/>
-
- {this.renderEvents(range, rangeEvents, this.props.now)}
+ {eventsRendered}
);
}
-
- renderEvents(range, events, today){
- let { min, max, endAccessor, startAccessor, components } = this.props;
+ renderEvents(range, events, today, resources) {
+ let { min, max, endAccessor, startAccessor, resourceIdAccessor, components } = this.props;
return range.map((date, idx) => {
let daysEvents = events.filter(
- event => dates.inRange(date,
- get(event, startAccessor),
- get(event, endAccessor), 'day')
+ event => dates.inRange(date,
+ get(event, startAccessor),
+ get(event, endAccessor), 'day')
)
- return (
-
- )
+ return resources.map((resource, id) => {
+
+ let eventsToDisplay = daysEvents.filter(
+ event => get(event, resourceIdAccessor) === resource.id
+ )
+
+ return (
+
+ )
+ })
})
}
- renderHeader(range, events, width) {
+ renderHeader(range, events, width, resources) {
let { messages, rtl, selectable, components, now } = this.props;
let { isOverflowing } = this.state || {};
@@ -237,6 +248,10 @@ export default class TimeGrid extends Component {
if (isOverflowing)
style[rtl ? 'marginLeft' : 'marginRight'] = scrollbarSize() + 'px';
+ let headerRendered = resources ?
+ this.renderHeaderResources(range, resources) :
+ message(messages).allDay;
+
return (
{ this.renderHeaderCells(range) }
+ { resources && }
this._gutters[0] = ref}
@@ -289,6 +311,27 @@ export default class TimeGrid extends Component {
)
}
+ renderHeaderResources(range, resources) {
+ return range.map((date, i) => {
+ return resources.map((resource, j) => {
+ return (
+
+
+ {resource.title}
+
+
+ )
+ })
+ })
+ }
+
renderHeaderCells(range){
let { dayFormat, culture, components, dayPropGetter, getDrilldownView } = this.props;
let HeaderComponent = components.header || Header
diff --git a/src/TimeSlot.js b/src/TimeSlot.js
index 34caf8500..121affc3d 100644
--- a/src/TimeSlot.js
+++ b/src/TimeSlot.js
@@ -13,6 +13,7 @@ export default class TimeSlot extends Component {
content: PropTypes.string,
culture: PropTypes.string,
slotPropGetter: PropTypes.func,
+ resource: PropTypes.string
}
static defaultProps = {
@@ -22,12 +23,12 @@ export default class TimeSlot extends Component {
}
render() {
- const { value, slotPropGetter } = this.props;
+ const { value, slotPropGetter, resource } = this.props;
const Wrapper = this.props.dayWrapperComponent;
const { className, style } = (slotPropGetter && slotPropGetter(value)) || {};
return (
-
+
.rbc-row.rbc-row-resource {
+ border-bottom: 1px solid @cell-border;
+ }
+
.rbc-gutter-cell {
flex: none;
}
diff --git a/stories/Calendar.js b/stories/Calendar.js
index e89541d42..22132705e 100644
--- a/stories/Calendar.js
+++ b/stories/Calendar.js
@@ -1,12 +1,17 @@
import { storiesOf, action } from '@storybook/react';
import moment from 'moment';
import React from 'react';
+import HTML5Backend from 'react-dnd-html5-backend';
+import { DragDropContext } from 'react-dnd';
import Calendar from '../src';
import momentLocalizer from '../src/localizers/moment.js'
import '../src/less/styles.less'
+import '../src/addons/dragAndDrop/styles.less'
import demoEvents from '../examples/events';
import createEvents from './createEvents';
+import resources from './resourceEvents';
+import withDragAndDrop from '../src/addons/dragAndDrop';
// Setup the localizer by providing the moment (or globalize) Object
// to the correct localizer.
@@ -38,6 +43,25 @@ const events = [{
allDay: true
}]
+const DragAndDropCalendar = withDragAndDrop(Calendar)
+
+const DragCalendar = () => {
+ return (
+ { action(event) }}
+ onSelectEvent={action('event selected')}
+ onSelectSlot={action('slot selected')}
+ defaultDate={new Date(2015, 3, 1)}
+ />
+ )
+}
+
+const DragableCalendar = DragDropContext(HTML5Backend)(DragCalendar)
+
storiesOf('module.Calendar.week', module)
.add('demo', () => {
return (
@@ -77,6 +101,13 @@ storiesOf('module.Calendar.week', module)
)
})
+ .add('resource', () => {
+ return (
+
+
+
+ )
+ })
.add('selectable', () => {
return (
diff --git a/stories/resourceEvents.js b/stories/resourceEvents.js
new file mode 100644
index 000000000..d99ab5975
--- /dev/null
+++ b/stories/resourceEvents.js
@@ -0,0 +1,43 @@
+export default {
+ events: [ {
+ 'title': 'Rencontre',
+ 'resourceId': 'a',
+ 'start': new Date(2015, 3, 2, 5, 30, 0, 0),
+ 'end': new Date(2015, 3, 2, 10, 30, 0, 0),
+ }, {
+ 'title': 'Another Meeting',
+ 'resourceId': 'b',
+ 'start': new Date(2015, 3, 1, 2, 30, 0, 0),
+ 'end': new Date(2015, 3, 1, 4, 30, 0, 0),
+ },
+ {
+ 'title': 'A',
+ 'resourceId': 'a',
+ 'start': new Date(2015, 3, 4, 5, 30, 0, 0),
+ 'end': new Date(2015, 3, 4, 10, 30, 0, 0),
+ },
+ {
+ 'title': 'B',
+ 'resourceId': 'b',
+ 'start': new Date(2015, 3, 4, 5, 30, 0, 0),
+ 'end': new Date(2015, 3, 4, 10, 30, 0, 0),
+ },
+ {
+ 'title': 'C',
+ 'resourceId': 'c',
+ 'start': new Date(2015, 3, 4, 5, 30, 0, 0),
+ 'end': new Date(2015, 3, 4, 10, 30, 0, 0),
+ }
+ ],
+
+ list: [{
+ id: 'a',
+ title: 'Room A'
+ }, {
+ id: 'b',
+ title: 'Room B'
+ }, {
+ id: 'c',
+ title: 'Room C'
+ }]
+}
\ No newline at end of file