Skip to content

Commit

Permalink
fix overlapping background events (#2510)
Browse files Browse the repository at this point in the history
fixes #2452 (Thanks to @chazzlabs)
  • Loading branch information
chazzlabs authored Feb 21, 2024
1 parent 95e6b0b commit d2b7c23
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 39 deletions.
26 changes: 9 additions & 17 deletions src/TimeGridEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ function TimeGridEvent(props) {

let userProps = getters.eventProp(event, start, end, selected)

let { height, top, width, xOffset } = style
const inner = [
<div key="1" className="rbc-event-label">
{label}
Expand All @@ -41,22 +40,15 @@ function TimeGridEvent(props) {
</div>,
]

const eventStyle = isBackgroundEvent
? {
...userProps.style,
top: stringifyPercent(top),
height: stringifyPercent(height),
// Adding 10px to take events container right margin into account
width: `calc(${width} + 10px)`,
[rtl ? 'right' : 'left']: stringifyPercent(Math.max(0, xOffset)),
}
: {
...userProps.style,
top: stringifyPercent(top),
width: stringifyPercent(width),
height: stringifyPercent(height),
[rtl ? 'right' : 'left']: stringifyPercent(xOffset),
}
const { height, top, width, xOffset } = style

const eventStyle = {
...userProps.style,
top: stringifyPercent(top),
height: stringifyPercent(height),
width: stringifyPercent(width),
[rtl ? 'right' : 'left']: stringifyPercent(xOffset),
}

return (
<EventWrapper type="time" {...props}>
Expand Down
104 changes: 104 additions & 0 deletions stories/Layout.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,107 @@ export const ZeroDurationOverlap = () => {
/>
)
}

export const OverlappingBackgroundEventsOverlap = Template.bind({})
OverlappingBackgroundEventsOverlap.storyName =
"Overlapping Background Events - 'overlap'"
OverlappingBackgroundEventsOverlap.args = {
defaultDate: new Date(2016, 11, 3),
dayLayoutAlgorithm: 'overlap',
defaultView: Views.WEEK,
scrollToTime: new Date(2016, 11, 1, 7, 0),
backgroundEvents: [
{
title: 'First Event',
start: new Date(2016, 10, 28, 10, 30),
end: new Date(2016, 10, 28, 18, 0),
},
{
title: 'Second Event',
start: new Date(2016, 10, 28, 12, 0),
end: new Date(2016, 10, 28, 16, 30),
},
{
title: 'Third Event',
start: new Date(2016, 10, 29, 8, 0),
end: new Date(2016, 10, 29, 21, 0),
},
{
title: 'Fourth Event',
start: new Date(2016, 10, 29, 9, 30),
end: new Date(2016, 10, 29, 19, 30),
},
{
title: 'Fifth Event',
start: new Date(2016, 10, 29, 11, 0),
end: new Date(2016, 10, 29, 18, 0),
},
{
title: 'Sixth Event',
start: new Date(2016, 11, 1, 9, 0),
end: new Date(2016, 11, 1, 14, 0),
},
{
title: 'Seventh Event',
start: new Date(2016, 11, 1, 11, 0),
end: new Date(2016, 11, 1, 16, 0),
},
{
title: 'Eighth Event',
start: new Date(2016, 11, 1, 13, 0),
end: new Date(2016, 11, 1, 18, 0),
},
],
}

export const OverlappingBackgroundEventsNoOverlap = Template.bind({})
OverlappingBackgroundEventsNoOverlap.storyName =
"Overlapping Background Events - 'no-overlap'"
OverlappingBackgroundEventsNoOverlap.args = {
defaultDate: new Date(2016, 11, 3),
dayLayoutAlgorithm: 'no-overlap',
defaultView: Views.WEEK,
scrollToTime: new Date(2016, 11, 1, 7, 0),
backgroundEvents: [
{
title: 'First Event',
start: new Date(2016, 10, 28, 10, 30),
end: new Date(2016, 10, 28, 18, 0),
},
{
title: 'Second Event',
start: new Date(2016, 10, 28, 12, 0),
end: new Date(2016, 10, 28, 16, 30),
},
{
title: 'Third Event',
start: new Date(2016, 10, 29, 8, 0),
end: new Date(2016, 10, 29, 21, 0),
},
{
title: 'Fourth Event',
start: new Date(2016, 10, 29, 9, 30),
end: new Date(2016, 10, 29, 19, 30),
},
{
title: 'Fifth Event',
start: new Date(2016, 10, 29, 11, 0),
end: new Date(2016, 10, 29, 18, 0),
},
{
title: 'Sixth Event',
start: new Date(2016, 11, 1, 9, 0),
end: new Date(2016, 11, 1, 14, 0),
},
{
title: 'Seventh Event',
start: new Date(2016, 11, 1, 11, 0),
end: new Date(2016, 11, 1, 16, 0),
},
{
title: 'Eighth Event',
start: new Date(2016, 11, 1, 13, 0),
end: new Date(2016, 11, 1, 18, 0),
},
],
}
150 changes: 128 additions & 22 deletions test/utils/DayEventLayout.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,9 @@ describe('getStyledEvents', () => {
localizer,
})
const accessors = { start: (e) => e.start, end: (e) => e.end }
const dayLayoutAlgorithm = 'overlap'

describe('matrix', () => {
function compare(title, events, expectedResults) {
it(title, () => {
const styledEvents = getStyledEvents({
events,
accessors,
slotMetrics,
minimumStartDifference: 10,
dayLayoutAlgorithm,
})
const results = styledEvents.map((result) => ({
width: Math.floor(result.style.width),
xOffset: Math.floor(result.style.xOffset),
}))
expect(results).toEqual(expectedResults)
})
}

const toCheck = [
describe('with overlap dayLayoutAlgorithm', () => {
it.each([
[
'single event',
[{ start: d(11), end: d(12) }],
Expand Down Expand Up @@ -123,7 +105,131 @@ describe('getStyledEvents', () => {
{ width: 33, xOffset: 66 },
],
],
]
toCheck.forEach((args) => compare(...args))
])('%s', (_, events, expectedStyles) => {
const dayLayoutAlgorithm = 'overlap'

const styledEvents = getStyledEvents({
events,
accessors,
slotMetrics,
minimumStartDifference: 10,
dayLayoutAlgorithm,
})

const results = styledEvents.map((result) => ({
width: Math.floor(result.style.width),
xOffset: Math.floor(result.style.xOffset),
}))

expect(results).toEqual(expectedStyles)
})
})

describe('with no-overlap dayLayoutAlgorithm', () => {
it.each([
[
'single event',
[{ start: d(11), end: d(12) }],
[{ width: 'calc(100% - 0px)', xOffset: 'calc(0% + 0px)' }],
],
[
'two consecutive events',
[
{ start: d(11), end: d(11, 10) },
{ start: d(11, 10), end: d(11, 20) },
],
[
{ width: 'calc(100% - 0px)', xOffset: 'calc(0% + 0px)' },
{ width: 'calc(100% - 0px)', xOffset: 'calc(0% + 0px)' },
],
],
[
'two consecutive events too close together',
[
{ start: d(11), end: d(11, 5) },
{ start: d(11, 5), end: d(11, 10) },
],
[
{ width: 'calc(100% - 0px)', xOffset: 'calc(0% + 0px)' },
{ width: 'calc(100% - 0px)', xOffset: 'calc(0% + 0px)' },
],
],
[
'two overlapping events',
[
{ start: d(11), end: d(12) },
{ start: d(11), end: d(12) },
],
[
{ width: 'calc(50% - 0px)', xOffset: 'calc(0% + 0px)' },
{ width: 'calc(50% - 3px)', xOffset: 'calc(50% + 3px)' },
],
],
[
'three overlapping events',
[
{ start: d(11), end: d(12) },
{ start: d(11), end: d(12) },
{ start: d(11), end: d(12) },
],
[
{
width: 'calc(33.333333333333336% - 0px)',
xOffset: 'calc(0% + 0px)',
},
{
width: 'calc(33.333333333333336% - 3px)',
xOffset: 'calc(33.333333333333336% + 3px)',
},
{
width: 'calc(33.33333333333333% - 3px)',
xOffset: 'calc(66.66666666666667% + 3px)',
},
],
],
[
'one big event overlapping with two consecutive events',
[
{ start: d(11), end: d(12) },
{ start: d(11), end: d(11, 30) },
{ start: d(11, 30), end: d(12) },
],
[
{ width: 'calc(50% - 0px)', xOffset: 'calc(0% + 0px)' },
{ width: 'calc(50% - 3px)', xOffset: 'calc(50% + 3px)' },
{ width: 'calc(50% - 3px)', xOffset: 'calc(50% + 3px)' },
],
],
[
'one big event overlapping with two consecutive events starting too close together',
[
{ start: d(11), end: d(12) },
{ start: d(11), end: d(11, 5) },
{ start: d(11, 5), end: d(11, 10) },
],
[
{ width: 'calc(50% - 0px)', xOffset: 'calc(0% + 0px)' },
{ width: 'calc(50% - 3px)', xOffset: 'calc(50% + 3px)' },
{ width: 'calc(50% - 3px)', xOffset: 'calc(50% + 3px)' },
],
],
])('%s', (_, events, expectedStyles) => {
const dayLayoutAlgorithm = 'no-overlap'

const styledEvents = getStyledEvents({
events,
accessors,
slotMetrics,
minimumStartDifference: 10,
dayLayoutAlgorithm,
})

const results = styledEvents.map((result) => ({
width: result.style.width,
xOffset: result.style.xOffset,
}))

expect(results).toEqual(expectedStyles)
})
})
})

0 comments on commit d2b7c23

Please sign in to comment.