diff --git a/src/BackgroundCells.js b/src/BackgroundCells.js index 56d94f4d7..50262f11a 100644 --- a/src/BackgroundCells.js +++ b/src/BackgroundCells.js @@ -4,7 +4,7 @@ import clsx from 'clsx' import { notify } from './utils/helpers' import { dateCellSelection, getSlotAtX, pointInBox } from './utils/selection' -import Selection, { getBoundsForNode, isEvent } from './Selection' +import Selection, { getBoundsForNode, isEvent, isShowMore } from './Selection' class BackgroundCells extends React.Component { constructor(props, context) { @@ -77,7 +77,7 @@ class BackgroundCells extends React.Component { })) let selectorClicksHandler = (point, actionType) => { - if (!isEvent(node, point)) { + if (!isEvent(node, point) && !isShowMore(node, point)) { let rowBox = getBoundsForNode(node) let { range, rtl } = this.props diff --git a/src/Calendar.js b/src/Calendar.js index f008227c4..ec3a7344f 100644 --- a/src/Calendar.js +++ b/src/Calendar.js @@ -603,6 +603,15 @@ class Calendar extends React.Component { */ showMultiDayTimes: PropTypes.bool, + /** + * Determines a maximum amount of rows of events to display in the all day + * section for Week and Day views, will display `showMore` button if + * events excede this number. + * + * Defaults to `Infinity` + */ + allDayMaxRows: PropTypes.number, + /** * Constrains the minimum _time_ of the Day and Week views. */ @@ -865,6 +874,7 @@ class Calendar extends React.Component { views: [views.MONTH, views.WEEK, views.DAY, views.AGENDA], step: 30, length: 30, + allDayMaxRows: Infinity, doShowMoreDrillDown: true, drilldownView: views.DAY, diff --git a/src/EventEndingRow.js b/src/EventEndingRow.js index 79d9ac94e..fd2d8a699 100644 --- a/src/EventEndingRow.js +++ b/src/EventEndingRow.js @@ -83,7 +83,7 @@ class EventEndingRow extends React.Component { type="button" key={'sm_' + slot} className={clsx('rbc-button-link', 'rbc-show-more')} - onClick={e => this.showMore(slot, e)} + onClick={(e) => this.showMore(slot, e)} > {localizer.messages.showMore(count)} diff --git a/src/Selection.js b/src/Selection.js index b2714c17e..015691c06 100644 --- a/src/Selection.js +++ b/src/Selection.js @@ -15,10 +15,19 @@ export function getEventNodeFromPoint(node, { clientX, clientY }) { return closest(target, '.rbc-event', node) } +export function getShowMoreNodeFromPoint(node, { clientX, clientY }) { + let target = document.elementFromPoint(clientX, clientY) + return closest(target, '.rbc-show-more', node) +} + export function isEvent(node, bounds) { return !!getEventNodeFromPoint(node, bounds) } +export function isShowMore(node, bounds) { + return !!getShowMoreNodeFromPoint(node, bounds) +} + function getEventCoordinates(e) { let target = e @@ -38,7 +47,10 @@ const clickTolerance = 5 const clickInterval = 250 class Selection { - constructor(node, { global = false, longPressThreshold = 250, validContainers = [] } = {}) { + constructor( + node, + { global = false, longPressThreshold = 250, validContainers = [] } = {} + ) { this.isDetached = false this.container = node this.globalMouse = !node || global @@ -307,15 +319,14 @@ class Selection { // Check whether provided event target element // - is contained within a valid container _isWithinValidContainer(e) { - const eventTarget = e.target; - const containers = this.validContainers; + const eventTarget = e.target + const containers = this.validContainers if (!containers || !containers.length || !eventTarget) { - return true; + return true } - return containers.some( - (target) => !!eventTarget.closest(target)); + return containers.some((target) => !!eventTarget.closest(target)) } _handleTerminatingEvent(e) { diff --git a/src/TimeGrid.js b/src/TimeGrid.js index 197037a1e..6391cf28a 100644 --- a/src/TimeGrid.js +++ b/src/TimeGrid.js @@ -73,6 +73,11 @@ export default class TimeGrid extends Component { notify(this.props.onSelectEvent, args) } + handleShowMore = (...args) => { + this.clearSelection() + notify(this.props.onShowMore, args) + } + handleSelectAllDaySlot = (slots, slotInfo) => { const { onSelectSlot } = this.props @@ -211,6 +216,7 @@ export default class TimeGrid extends Component { getNow={getNow} localizer={localizer} selected={selected} + allDayMaxRows={this.props.allDayMaxRows} resources={this.memoizedResources(resources, accessors)} selectable={this.props.selectable} accessors={accessors} @@ -221,6 +227,7 @@ export default class TimeGrid extends Component { longPressThreshold={longPressThreshold} onSelectSlot={this.handleSelectAllDaySlot} onSelectEvent={this.handleSelectAlldayEvent} + onShowMore={this.handleShowMore} onDoubleClickEvent={this.props.onDoubleClickEvent} onKeyPressEvent={this.props.onKeyPressEvent} onDrillDown={this.props.onDrillDown} @@ -341,6 +348,8 @@ TimeGrid.propTypes = { getters: PropTypes.object.isRequired, localizer: PropTypes.object.isRequired, + allDayMaxRows: PropTypes.number, + selected: PropTypes.object, selectable: PropTypes.oneOf([true, false, 'ignoreEvents']), longPressThreshold: PropTypes.number, @@ -350,6 +359,7 @@ TimeGrid.propTypes = { onSelectEnd: PropTypes.func, onSelectStart: PropTypes.func, onSelectEvent: PropTypes.func, + onShowMore: PropTypes.func, onDoubleClickEvent: PropTypes.func, onKeyPressEvent: PropTypes.func, onDrillDown: PropTypes.func, diff --git a/src/TimeGridHeader.js b/src/TimeGridHeader.js index 73cb5c924..74877bba3 100644 --- a/src/TimeGridHeader.js +++ b/src/TimeGridHeader.js @@ -85,6 +85,7 @@ class TimeGridHeader extends React.Component { rtl={rtl} getNow={getNow} minRows={2} + maxRows={this.props.allDayMaxRows} range={range} events={eventsToDisplay} resourceId={resourceId} @@ -96,6 +97,7 @@ class TimeGridHeader extends React.Component { getters={getters} localizer={localizer} onSelect={this.props.onSelectEvent} + onShowMore={this.props.onShowMore} onDoubleClick={this.props.onDoubleClickEvent} onKeyPress={this.props.onKeyPressEvent} onSelectSlot={this.props.onSelectSlot} @@ -172,6 +174,7 @@ class TimeGridHeader extends React.Component { rtl={rtl} getNow={getNow} minRows={2} + maxRows={this.props.allDayMaxRows} range={range} events={groupedEvents.get(id) || []} resourceId={resource && id} @@ -183,6 +186,7 @@ class TimeGridHeader extends React.Component { getters={getters} localizer={localizer} onSelect={this.props.onSelectEvent} + onShowMore={this.props.onShowMore} onDoubleClick={this.props.onDoubleClickEvent} onKeyPress={this.props.onKeyPressEvent} onSelectSlot={this.props.onSelectSlot} @@ -216,11 +220,14 @@ TimeGridHeader.propTypes = { selectable: PropTypes.oneOf([true, false, 'ignoreEvents']), longPressThreshold: PropTypes.number, + allDayMaxRows: PropTypes.number, + onSelectSlot: PropTypes.func, onSelectEvent: PropTypes.func, onDoubleClickEvent: PropTypes.func, onKeyPressEvent: PropTypes.func, onDrillDown: PropTypes.func, + onShowMore: PropTypes.func, getDrilldownView: PropTypes.func.isRequired, scrollRef: PropTypes.any, } diff --git a/stories/props/API.stories.mdx b/stories/props/API.stories.mdx index e1befb987..76506b668 100644 --- a/stories/props/API.stories.mdx +++ b/stories/props/API.stories.mdx @@ -257,6 +257,16 @@ The end date/time of the event. Must resolve to a JavaScript `Date` object. Determines whether the event should be considered an "all day" event and ignore time. Must resolve to a `boolean` value. +### allDayMaxRows + +- type: `number` +- default: `Infinity` +- + Example + + +Determines a maximum amount of rows of events to display in the all day section for Week and Day views, will display `showMore` button if events excede this number. + ### resources - type: `arrayOf(Resource)` diff --git a/stories/props/allDayMaxRows.mdx b/stories/props/allDayMaxRows.mdx new file mode 100644 index 000000000..e6a9c5dbc --- /dev/null +++ b/stories/props/allDayMaxRows.mdx @@ -0,0 +1,10 @@ +import { Canvas, Story } from '@storybook/addon-docs' + +# allDayMaxRows + +- type: `number` +- default: `Infinity` + +Determines a maximum amount of rows of events to display in the all day section for Week and Day views, will display `showMore` button if events excede this number. + + diff --git a/stories/props/allDayMaxRows.stories.js b/stories/props/allDayMaxRows.stories.js new file mode 100644 index 000000000..4efb1af39 --- /dev/null +++ b/stories/props/allDayMaxRows.stories.js @@ -0,0 +1,38 @@ +import React from 'react' +import moment from 'moment' +import { Calendar, Views, momentLocalizer } from '../../src' +import allDayEvents from '../resources/allDayEvents' +import mdx from './allDayMaxRows.mdx' + +const mLocalizer = momentLocalizer(moment) + +export default { + title: 'props', + component: Calendar, + argTypes: { + localizer: { control: { type: null } }, + events: { control: { type: null } }, + defaultDate: { control: { type: null } }, + }, + parameters: { + docs: { + page: mdx, + }, + }, +} + +const Template = (args) => ( +
+ +
+) + +export const AllDayMaxRows = Template.bind({}) +AllDayMaxRows.storyName = 'allDayMaxRows' +AllDayMaxRows.args = { + defaultDate: new Date(2015, 3, 1), + defaultView: Views.WEEK, + events: allDayEvents, + localizer: mLocalizer, + allDayMaxRows: 2, +} diff --git a/stories/resources/allDayEvents.js b/stories/resources/allDayEvents.js new file mode 100644 index 000000000..0b8dffdeb --- /dev/null +++ b/stories/resources/allDayEvents.js @@ -0,0 +1,23 @@ +export default [ + { + id: 0, + title: 'All Day Event very long title', + allDay: true, + start: new Date(2015, 3, 0), + end: new Date(2015, 3, 1), + }, + { + id: 1, + title: '#2 All Day Event very long title', + allDay: true, + start: new Date(2015, 3, 0), + end: new Date(2015, 3, 2), + }, + { + id: 2, + title: '#3 All Day Event very long title', + allDay: true, + start: new Date(2015, 3, 0), + end: new Date(2015, 3, 1), + }, +]