Skip to content

Commit

Permalink
render a more-link in timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Apr 22, 2021
1 parent 08f10cb commit c5ccc94
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 50 deletions.
2 changes: 1 addition & 1 deletion packages/common/src/component/DateComponent.ts
Expand Up @@ -99,7 +99,7 @@ export abstract class DateComponent<Props=Dictionary, State=Dictionary> extends

isValidDateDownEl(el: HTMLElement) {
return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
!elementClosest(el, '.fc-daygrid-more-link') && // a "more.." link
!elementClosest(el, '.fc-event-more') && // a "more.." link
!elementClosest(el, 'a[data-navlink]') && // a clickable nav link
!elementClosest(el, '.fc-popover') // hack
}
Expand Down
2 changes: 1 addition & 1 deletion packages/daygrid/src/TableCell.tsx
Expand Up @@ -156,7 +156,7 @@ export class TableCell extends DateComponent<TableCellProps> {
{(rootElRef, classNames, innerElRef, innerContent) => (
<a
ref={rootElRef}
className={['fc-daygrid-more-link'].concat(classNames).join(' ')}
className={['fc-daygrid-more-link', 'fc-event-more'].concat(classNames).join(' ')}
onClick={this.handleMoreLinkClick}
>
{innerContent}
Expand Down
80 changes: 49 additions & 31 deletions packages/timegrid/src/TimeCol.tsx
Expand Up @@ -5,7 +5,7 @@ import {
} from '@fullcalendar/common'
import { TimeColsSeg } from './TimeColsSeg'
import { TimeColsSlatsCoords } from './TimeColsSlatsCoords'
import { computeFgSegPlacements, TimeColSegRect } from './event-placement'
import { computeFgSegPlacements, SegEntryGroup, TimeColSegRect } from './event-placement'
import { TimeColEvent } from './TimeColEvent'
import { TimeColMisc } from './TimeColMisc'

Expand Down Expand Up @@ -157,37 +157,55 @@ export class TimeCol extends BaseComponent<TimeColProps> {
let { eventSelection, todayRange, nowDate } = this.props
let isMirror = isDragging || isResizing || isDateSelecting
let segInputs = this.buildSegInputs(segs)
let segRects = isMirror ? computeFgSegPlacements(segInputs) : // don't use memoized
let { segRects, hiddenGroups } = isMirror ? computeFgSegPlacements(segInputs) : // don't use memoized
this.computeFgSegPlacements(segInputs, this.context.options.timeGridEventMaxStack)

return segRects.map((segRect) => {
let seg = segs[segRect.segInput.index] as TimeColsSeg
let instanceId = seg.eventRange.instance.instanceId
let positionCss = {
...this.computeSegTopBottomCss(segRect.segInput),
// mirrors will span entire column width
// also, won't assign z-index, which is good, fc-event-mirror will overpower other harnesses
...(isMirror ? { left: 0, right: 0 } : this.computeSegLeftRightCss(segRect)),
}
return (
<Fragment>
{this.renderHiddenGroups(hiddenGroups, segs)}
{segRects.map((segRect) => {
let seg = segs[segRect.segInput.index] as TimeColsSeg
let instanceId = seg.eventRange.instance.instanceId
let positionCss = {
...this.computeSegTopBottomCss(segRect.segInput),
// mirrors will span entire column width
// also, won't assign z-index, which is good, fc-event-mirror will overpower other harnesses
...(isMirror ? { left: 0, right: 0 } : this.computeSegLeftRightCss(segRect)),
}

return (
<div
className={'fc-timegrid-event-harness' + (segRect.stackForward > 0 ? ' fc-timegrid-event-harness-inset' : '')}
key={instanceId}
style={{
visibility: segIsInvisible[instanceId] ? 'hidden' : ('' as any),
...positionCss,
}}
>
<TimeColEvent
seg={seg}
isDragging={isDragging}
isResizing={isResizing}
isDateSelecting={isDateSelecting}
isSelected={instanceId === eventSelection}
isCondensed={(seg.bottom - seg.top) < config.timeGridEventCondensedHeight}
{...getSegMeta(seg, todayRange, nowDate)}
/>
</div>
)
})}
</Fragment>
)
}

// will already have eventMinHeight applied because segInputs already had it
renderHiddenGroups(hiddenGroups: SegEntryGroup[], segs: TimeColsSeg[]) {
return hiddenGroups.map((hiddenGroup) => {
let positionCss = this.computeSegTopBottomCss(hiddenGroup)

return (
<div
className={'fc-timegrid-event-harness' + (segRect.stackForward > 0 ? ' fc-timegrid-event-harness-inset' : '')}
key={instanceId}
style={{
visibility: segIsInvisible[instanceId] ? 'hidden' : ('' as any),
...positionCss,
}}
>
<TimeColEvent
seg={seg}
isDragging={isDragging}
isResizing={isResizing}
isDateSelecting={isDateSelecting}
isSelected={instanceId === eventSelection}
isCondensed={(seg.bottom - seg.top) < config.timeGridEventCondensedHeight}
{...getSegMeta(seg, todayRange, nowDate)}
/>
<div className='fc-event-more fc-timegrid-event-more' style={positionCss}>
+{hiddenGroup.entries.length}{/* TODO: more customizable way to build this text. search buildMoreLinkText */}
</div>
)
})
Expand Down Expand Up @@ -262,10 +280,10 @@ export class TimeCol extends BaseComponent<TimeColProps> {
))
}

computeSegTopBottomCss(segInput: SegInput) {
computeSegTopBottomCss(segLike: { spanStart: number, spanEnd: number }) {
return {
top: segInput.spanStart,
bottom: -segInput.spanEnd,
top: segLike.spanStart,
bottom: -segLike.spanEnd,
}
}

Expand Down
27 changes: 15 additions & 12 deletions packages/timegrid/src/event-placement.ts
Expand Up @@ -25,22 +25,33 @@ export interface TimeColSegRect extends SegRect {
stackForward: number
}

export interface SegEntryGroup {
spanStart: number
spanEnd: number
entries: SegEntry[]
}

// segInputs assumed sorted
export function computeFgSegPlacements(
segInputs: SegInput[],
maxStack?: number,
): TimeColSegRect[] {
): {
segRects: TimeColSegRect[],
hiddenGroups: SegEntryGroup[]
} {
let hierarchy = new SegHierarchy()
if (maxStack != null) {
hierarchy.maxStackCnt = maxStack
}

let hiddenSegs = hierarchy.addSegs(segInputs)
console.log(hiddenSegs)
let hiddenEntries = hierarchy.addSegs(segInputs)
let hiddenGroups = groupIntersectingEntries(hiddenEntries)

let web = buildWeb(hierarchy)
web = stretchWeb(web, 1) // all levelCoords/thickness will have 0.0-1.0
return webToRects(web)
let segRects = webToRects(web)

return { segRects, hiddenGroups }
}

function buildWeb(hierarchy: SegHierarchy): SegNode[] {
Expand Down Expand Up @@ -201,13 +212,6 @@ function webToRects(topLevelNodes: SegNode[]): TimeColSegRect[] {
return rects // TODO: sort rects by levelCoord to be consistent with toRects?
}

/* TODO: for event-limit display
interface SegEntryGroup {
spanStart: number
spanEnd: number
entries: SegEntry[]
}
// returns in no specific order
function groupIntersectingEntries(entries: SegEntry[]): SegEntryGroup[] {
let groups: SegEntryGroup[] = []
Expand Down Expand Up @@ -238,7 +242,6 @@ function groupIntersectingEntries(entries: SegEntry[]): SegEntryGroup[] {

return groups
}
*/

// TODO: move to general util

Expand Down
31 changes: 26 additions & 5 deletions packages/timegrid/src/styles/timegrid-event.css
@@ -1,14 +1,17 @@

.fc-timegrid-event-harness-inset .fc-timegrid-event,
.fc-timegrid-event.fc-event-mirror {
.fc-timegrid-event.fc-event-mirror,
.fc-timegrid-event-more {
box-shadow: 0px 0px 0px 1px var(--fc-page-bg-color);
}

.fc-timegrid-event { // events need to be root

.fc-timegrid-event,
.fc-timegrid-event-more { // events need to be root
font-size: var(--fc-small-font-size);
border-radius: 3px;
}

.fc-timegrid-event { // events need to be root
& .fc-event-main {
padding: 1px 1px 0;
}
Expand All @@ -18,7 +21,27 @@
font-size: var(--fc-small-font-size);
margin-bottom: 1px;
}
}

.fc-timegrid-event-more {
position: absolute;
z-index: 999; // hack
background: #ccc; // TODO: variable?
padding: 2px;
margin-bottom: 1px; // match the space below each event
cursor: pointer;
}


.fc-direction-ltr {
& .fc-timegrid-event-more {
right: 0;
}
}
.fc-direction-rtl {
& .fc-timegrid-event-more {
left: 0;
}
}

.fc-timegrid-event-condensed {
Expand All @@ -35,7 +58,6 @@
& .fc-event-title {
font-size: var(--fc-small-font-size)
}

}

.fc-media-screen {
Expand All @@ -47,5 +69,4 @@
left: 0;
right: 0;
}

}

0 comments on commit c5ccc94

Please sign in to comment.