diff --git a/src/Calendar.js b/src/Calendar.js
index cbb6e9c09..ff8504d96 100644
--- a/src/Calendar.js
+++ b/src/Calendar.js
@@ -80,6 +80,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.
*
diff --git a/src/DayColumn.js b/src/DayColumn.js
index c86f2a9e4..3014ad6e9 100644
--- a/src/DayColumn.js
+++ b/src/DayColumn.js
@@ -57,6 +57,7 @@ class DaySlot extends React.Component {
dayWrapperComponent: elementType,
eventComponent: elementType,
eventWrapperComponent: elementType.isRequired,
+ resource: React.PropTypes.string
};
static defaultProps = { dragThroughEvents: true };
@@ -299,6 +300,7 @@ class DaySlot extends React.Component {
slots,
start: startDate,
end: endDate,
+ resourceId: this.props.resource,
action
})
};
diff --git a/src/TimeColumn.js b/src/TimeColumn.js
index e4ef95aeb..22f409056 100644
--- a/src/TimeColumn.js
+++ b/src/TimeColumn.js
@@ -19,6 +19,7 @@ export default class TimeColumn extends Component {
timeGutterFormat: PropTypes.string,
type: PropTypes.string.isRequired,
className: PropTypes.string,
+ resource: PropTypes.string,
dayWrapperComponent: elementType,
}
@@ -31,7 +32,7 @@ export default class TimeColumn extends Component {
dayWrapperComponent: BackgroundWrapper,
}
- renderTimeSliceGroup(key, isNow, date) {
+ renderTimeSliceGroup(key, isNow, date, resource) {
const { dayWrapperComponent, timeslots, showLabels, step, timeGutterFormat, culture } = this.props;
return (
@@ -42,6 +43,7 @@ export default class TimeColumn extends Component {
step={step}
culture={culture}
timeslots={timeslots}
+ resource={resource}
showLabels={showLabels}
timeGutterFormat={timeGutterFormat}
dayWrapperComponent={dayWrapperComponent}
@@ -50,7 +52,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 = []
@@ -69,7 +71,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 34c75cc4d..1309b0f1d 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(
@@ -141,6 +142,7 @@ export default class TimeGrid extends Component {
, width
, startAccessor
, endAccessor
+ , resources
, allDayAccessor } = this.props;
width = width || this.state.gutterWidth;
@@ -174,10 +176,14 @@ export default class TimeGrid extends Component {
let gutterRef = ref => this._gutters[1] = ref && findDOMNode(ref);
+ let eventsRendered = resources ?
+ this.renderEventsWithResource(range, rangeEvents, this.props.now, resources) :
+ this.renderEvents(range, rangeEvents, this.props.now);
+
return (
- {this.renderHeader(range, allDayEvents, width)}
+ {this.renderHeader(range, allDayEvents, width, resources)}
@@ -189,22 +195,55 @@ export default class TimeGrid extends Component {
ref={gutterRef}
className='rbc-time-gutter'
/>
-
- {this.renderEvents(range, rangeEvents, this.props.now)}
+ {eventsRendered}
);
}
+ renderEventsWithResource(range, events, today, resources) {
+ let { min, max, endAccessor, startAccessor, components } = this.props;
+
+ return range.map((date, idx) => {
+ let daysEvents = events.filter(
+ event => dates.inRange(date,
+ get(event, startAccessor),
+ get(event, endAccessor), 'day')
+ )
+
+ return resources.map((resource, id) => {
+
+ let eventsToDisplay = daysEvents.filter(
+ event => event.resourceId === resource.id
+ )
+
+ return (
+
+ )
+ })
+ })
+ }
- renderEvents(range, events, today){
+ renderEvents(range, events, today, id){
let { min, max, endAccessor, startAccessor, components } = this.props;
return range.map((date, idx) => {
let daysEvents = events.filter(
event => dates.inRange(date,
get(event, startAccessor),
- get(event, endAccessor), 'day')
+ get(event, endAccessor), 'day') && event.resourceId === id
)
return (
@@ -225,7 +264,7 @@ export default class TimeGrid extends Component {
})
}
- renderHeader(range, events, width) {
+ renderHeader(range, events, width, resources) {
let { messages, rtl, selectable, components, now } = this.props;
let { isOverflowing } = this.state || {};
@@ -233,6 +272,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}
@@ -282,6 +332,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, getDrilldownView } = this.props;
let HeaderComponent = components.header || Header
diff --git a/src/TimeSlot.js b/src/TimeSlot.js
index bb03b9c4f..db4353379 100644
--- a/src/TimeSlot.js
+++ b/src/TimeSlot.js
@@ -11,7 +11,8 @@ export default class TimeSlot extends Component {
isNow: PropTypes.bool,
showLabel: PropTypes.bool,
content: PropTypes.string,
- culture: PropTypes.string
+ culture: PropTypes.string,
+ resource: PropTypes.string
}
static defaultProps = {
@@ -21,11 +22,11 @@ export default class TimeSlot extends Component {
}
render() {
- const { value } = this.props;
+ const { value, resource } = this.props;
const Wrapper = this.props.dayWrapperComponent;
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 3e55f88eb..dfc712a57 100644
--- a/stories/Calendar.js
+++ b/stories/Calendar.js
@@ -1,12 +1,17 @@
import { storiesOf, action } from '@kadira/storybook';
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 (
@@ -78,6 +102,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