|
|
@@ -1,4 +1,4 @@
|
|
|
-import TableSeg, { splitSegsByFirstCol } from './TableSeg'
|
|
|
+import TableSeg from './TableSeg'
|
|
|
import { sortEventSegs } from '@fullcalendar/core'
|
|
|
|
|
|
|
|
|
@@ -13,14 +13,14 @@ export function computeFgSegPlacement( // for one row. TODO: print mode?
|
|
|
segs: TableSeg[],
|
|
|
dayMaxEvents: boolean | number,
|
|
|
dayMaxEventRows: boolean | number,
|
|
|
- eventHeights: { [instanceId: string]: number } | null,
|
|
|
+ eventHeights: { [instanceId: string]: number },
|
|
|
maxContentHeight: number | null,
|
|
|
colCnt: number,
|
|
|
eventOrderSpecs: any
|
|
|
) {
|
|
|
let colPlacements: TableSegPlacement[][] = [] // if event spans multiple cols, its present in each col
|
|
|
let moreCnts: number[] = [] // by-col
|
|
|
- let segIsNoDisplay: { [instanceId: string]: boolean } = {}
|
|
|
+ let segIsHidden: { [instanceId: string]: boolean } = {}
|
|
|
let segTops: { [instanceId: string]: number } = {} // always populated for each seg
|
|
|
let segMarginTops: { [instanceId: string]: number } = {} // simetimes populated for each seg
|
|
|
let moreTops: { [col: string]: number } = {}
|
|
|
@@ -36,74 +36,71 @@ export function computeFgSegPlacement( // for one row. TODO: print mode?
|
|
|
|
|
|
segs = sortEventSegs(segs, eventOrderSpecs) as TableSeg[]
|
|
|
|
|
|
- if (eventHeights) {
|
|
|
-
|
|
|
- // TODO: try all seg placements and choose the topmost! dont quit after first
|
|
|
- // SOLUTION: when placed, insert into colPlacements
|
|
|
- for (let seg of segs) {
|
|
|
- placeSeg(seg, eventHeights[seg.eventRange.instance.instanceId])
|
|
|
- }
|
|
|
+ // TODO: try all seg placements and choose the topmost! dont quit after first
|
|
|
+ // SOLUTION: when placed, insert into colPlacements
|
|
|
+ for (let seg of segs) {
|
|
|
+ let { instanceId } = seg.eventRange.instance
|
|
|
+ let eventHeight = eventHeights[instanceId]
|
|
|
|
|
|
- // sort. for dayMaxEvents and segTops computation
|
|
|
- for (let placements of colPlacements) {
|
|
|
- placements.sort(cmpPlacements) // sorts in-place
|
|
|
- }
|
|
|
+ placeSeg(seg, eventHeight || 0)
|
|
|
+ }
|
|
|
|
|
|
- if (dayMaxEvents === true || dayMaxEventRows === true) {
|
|
|
- limitByMaxHeight(moreCnts, segIsNoDisplay, colPlacements, maxContentHeight) // populates moreCnts/segIsNoDisplay
|
|
|
+ // sort. for dayMaxEvents and segTops computation
|
|
|
+ for (let placements of colPlacements) {
|
|
|
+ placements.sort(cmpPlacements) // sorts in-place
|
|
|
+ }
|
|
|
|
|
|
- } else if (typeof dayMaxEvents === 'number') {
|
|
|
- limitByMaxEvents(moreCnts, segIsNoDisplay, colPlacements, dayMaxEvents) // populates moreCnts/segIsNoDisplay
|
|
|
+ if (dayMaxEvents === true || dayMaxEventRows === true) {
|
|
|
+ limitByMaxHeight(moreCnts, segIsHidden, colPlacements, maxContentHeight) // populates moreCnts/segIsHidden
|
|
|
|
|
|
- } else if (typeof dayMaxEventRows === 'number') {
|
|
|
- limitByMaxRows(moreCnts, segIsNoDisplay, colPlacements, dayMaxEventRows) // populates moreCnts/segIsNoDisplay
|
|
|
- }
|
|
|
+ } else if (typeof dayMaxEvents === 'number') {
|
|
|
+ limitByMaxEvents(moreCnts, segIsHidden, colPlacements, dayMaxEvents) // populates moreCnts/segIsHidden
|
|
|
|
|
|
- // computes segTops/segMarginTops/moreTops/paddingBottoms
|
|
|
- for (let col = 0; col < colCnt; col++) {
|
|
|
- let placements = colPlacements[col]
|
|
|
- let currentBottom = 0
|
|
|
- let currentExtraSpace = 0
|
|
|
+ } else if (typeof dayMaxEventRows === 'number') {
|
|
|
+ limitByMaxRows(moreCnts, segIsHidden, colPlacements, dayMaxEventRows) // populates moreCnts/segIsHidden
|
|
|
+ }
|
|
|
|
|
|
- for (let placement of placements) {
|
|
|
- let seg = placement.seg
|
|
|
+ // computes segTops/segMarginTops/moreTops/paddingBottoms
|
|
|
+ for (let col = 0; col < colCnt; col++) {
|
|
|
+ let placements = colPlacements[col]
|
|
|
+ let currentBottom = 0
|
|
|
+ let currentExtraSpace = 0
|
|
|
|
|
|
- if (!segIsNoDisplay[seg.eventRange.instance.instanceId]) {
|
|
|
+ for (let placement of placements) {
|
|
|
+ let seg = placement.seg
|
|
|
|
|
|
- segTops[seg.eventRange.instance.instanceId] = placement.top // from top of container
|
|
|
+ if (!segIsHidden[seg.eventRange.instance.instanceId]) {
|
|
|
|
|
|
- if (seg.firstCol === seg.lastCol && seg.isStart && seg.isEnd) { // TODO: simpler way? NOT DRY
|
|
|
+ segTops[seg.eventRange.instance.instanceId] = placement.top // from top of container
|
|
|
|
|
|
- segMarginTops[seg.eventRange.instance.instanceId] =
|
|
|
- placement.top - currentBottom // from previous seg bottom
|
|
|
- + currentExtraSpace
|
|
|
+ if (seg.firstCol === seg.lastCol && seg.isStart && seg.isEnd) { // TODO: simpler way? NOT DRY
|
|
|
|
|
|
- currentExtraSpace = 0
|
|
|
+ segMarginTops[seg.eventRange.instance.instanceId] =
|
|
|
+ placement.top - currentBottom // from previous seg bottom
|
|
|
+ + currentExtraSpace
|
|
|
|
|
|
- } else { // multi-col event, abs positioned
|
|
|
- currentExtraSpace += placement.bottom - placement.top // for future non-abs segs
|
|
|
- }
|
|
|
+ currentExtraSpace = 0
|
|
|
|
|
|
- currentBottom = placement.bottom
|
|
|
+ } else { // multi-col event, abs positioned
|
|
|
+ currentExtraSpace += placement.bottom - placement.top // for future non-abs segs
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (currentExtraSpace) {
|
|
|
- if (moreCnts[col]) {
|
|
|
- moreTops[col] = currentExtraSpace
|
|
|
- } else {
|
|
|
- paddingBottoms[col] = currentExtraSpace
|
|
|
- }
|
|
|
+ currentBottom = placement.bottom
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- segsByFirstCol = colPlacements.map(extractFirstColSegs) // operates on the sorted cols
|
|
|
- finalSegsByCol = colPlacements.map(extractAllColSegs)
|
|
|
-
|
|
|
- } else {
|
|
|
- segsByFirstCol = splitSegsByFirstCol(segs, colCnt) // unsorted. that's ok
|
|
|
+ if (currentExtraSpace) {
|
|
|
+ if (moreCnts[col]) {
|
|
|
+ moreTops[col] = currentExtraSpace
|
|
|
+ } else {
|
|
|
+ paddingBottoms[col] = currentExtraSpace
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ segsByFirstCol = colPlacements.map(extractFirstColSegs) // operates on the sorted cols
|
|
|
+ finalSegsByCol = colPlacements.map(extractAllColSegs)
|
|
|
+
|
|
|
function placeSeg(seg, segHeight) {
|
|
|
if (!tryPlaceSegAt(seg, segHeight, 0)) {
|
|
|
for (let col = seg.firstCol; col <= seg.lastCol; col++) {
|
|
|
@@ -142,10 +139,16 @@ export function computeFgSegPlacement( // for one row. TODO: print mode?
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
+ for (let instanceId in eventHeights) {
|
|
|
+ if (!eventHeights[instanceId]) {
|
|
|
+ segIsHidden[instanceId] = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return {
|
|
|
finalSegsByCol,
|
|
|
segsByFirstCol,
|
|
|
- segIsNoDisplay,
|
|
|
+ segIsHidden,
|
|
|
segTops,
|
|
|
segMarginTops,
|
|
|
moreCnts,
|
|
|
@@ -184,34 +187,34 @@ function cmpPlacements(placement0, placement1) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-function limitByMaxHeight(hiddenCnts, segIsNoDisplay, colPlacements, maxContentHeight) {
|
|
|
- limitEvents(hiddenCnts, segIsNoDisplay, colPlacements, true, (placement) => {
|
|
|
+function limitByMaxHeight(hiddenCnts, segIsHidden, colPlacements, maxContentHeight) {
|
|
|
+ limitEvents(hiddenCnts, segIsHidden, colPlacements, true, (placement) => {
|
|
|
return placement.bottom <= maxContentHeight
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
-function limitByMaxEvents(hiddenCnts, segIsNoDisplay, colPlacements, dayMaxEvents) {
|
|
|
- limitEvents(hiddenCnts, segIsNoDisplay, colPlacements, false, (placement, levelIndex) => {
|
|
|
+function limitByMaxEvents(hiddenCnts, segIsHidden, colPlacements, dayMaxEvents) {
|
|
|
+ limitEvents(hiddenCnts, segIsHidden, colPlacements, false, (placement, levelIndex) => {
|
|
|
return levelIndex < dayMaxEvents
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
-function limitByMaxRows(hiddenCnts, segIsNoDisplay, colPlacements, dayMaxEventRows) {
|
|
|
- limitEvents(hiddenCnts, segIsNoDisplay, colPlacements, true, (placement, levelIndex) => {
|
|
|
+function limitByMaxRows(hiddenCnts, segIsHidden, colPlacements, dayMaxEventRows) {
|
|
|
+ limitEvents(hiddenCnts, segIsHidden, colPlacements, true, (placement, levelIndex) => {
|
|
|
return levelIndex < dayMaxEventRows
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
-populates the given hiddenCnts/segIsNoDisplay, which are supplied empty.
|
|
|
+populates the given hiddenCnts/segIsHidden, which are supplied empty.
|
|
|
TODO: return them instead
|
|
|
*/
|
|
|
-function limitEvents(hiddenCnts, segIsNoDisplay, colPlacements, moreLinkConsumesLevel, isPlacementInBounds) {
|
|
|
+function limitEvents(hiddenCnts, segIsHidden, colPlacements, moreLinkConsumesLevel, isPlacementInBounds) {
|
|
|
let colCnt = hiddenCnts.length
|
|
|
- let segIsVisible = {} as any // TODO: instead, use segIsNoDisplay with true/false?
|
|
|
+ let segIsVisible = {} as any // TODO: instead, use segIsHidden with true/false?
|
|
|
let visibleColPlacements = [] // will mirror colPlacements
|
|
|
|
|
|
for (let col = 0; col < colCnt; col++) {
|
|
|
@@ -220,16 +223,20 @@ function limitEvents(hiddenCnts, segIsNoDisplay, colPlacements, moreLinkConsumes
|
|
|
|
|
|
for (let col = 0; col < colCnt; col++) {
|
|
|
let placements = colPlacements[col]
|
|
|
+ let level = 0
|
|
|
|
|
|
- for (let level = 0; level < placements.length; level++) {
|
|
|
- let placement = placements[level]
|
|
|
+ for (let placement of placements) {
|
|
|
|
|
|
if (isPlacementInBounds(placement, level)) {
|
|
|
recordVisible(placement)
|
|
|
-
|
|
|
} else {
|
|
|
recordHidden(placement)
|
|
|
}
|
|
|
+
|
|
|
+ // only considered a level if the seg had height
|
|
|
+ if (placement.top !== placement.bottom) {
|
|
|
+ level++
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -250,8 +257,8 @@ function limitEvents(hiddenCnts, segIsNoDisplay, colPlacements, moreLinkConsumes
|
|
|
let { seg } = placement
|
|
|
let { instanceId } = seg.eventRange.instance
|
|
|
|
|
|
- if (!segIsNoDisplay[instanceId]) {
|
|
|
- segIsNoDisplay[instanceId] = true
|
|
|
+ if (!segIsHidden[instanceId]) {
|
|
|
+ segIsHidden[instanceId] = true
|
|
|
|
|
|
for (let col = seg.firstCol; col <= seg.lastCol; col++) {
|
|
|
let hiddenCnt = ++hiddenCnts[col]
|