feat: recurrence expansion.
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -1,46 +1,11 @@
|
||||
import type { EntityObject } from '@ChronoManager/models/entity'
|
||||
import type { EventObject } from '@ChronoManager/models/event'
|
||||
import type {
|
||||
CalendarOccurrence,
|
||||
CalendarOccurrenceIndex,
|
||||
} from '../types/occurrence'
|
||||
import type { VisibleDateRange } from '../types'
|
||||
import { shiftLocalDays, startOfLocalDay } from './dateRanges'
|
||||
|
||||
const MINIMUM_DURATION_MS = 1
|
||||
|
||||
function eventTimestamp(value: string | null | undefined): number | null {
|
||||
if (!value) return null
|
||||
|
||||
const timestamp = Date.parse(value)
|
||||
return Number.isFinite(timestamp) ? timestamp : null
|
||||
}
|
||||
|
||||
function occurrenceFromEntity(entity: EntityObject): CalendarOccurrence | null {
|
||||
const event = entity.properties as EventObject
|
||||
const startMs = eventTimestamp(event.startsOn)
|
||||
if (startMs === null) return null
|
||||
|
||||
const parsedEndMs = eventTimestamp(event.endsOn)
|
||||
const endMs = parsedEndMs !== null && parsedEndMs > startMs
|
||||
? parsedEndMs
|
||||
: startMs + MINIMUM_DURATION_MS
|
||||
const dayStartMs = startOfLocalDay(new Date(startMs)).getTime()
|
||||
const lastOccupiedDayMs = startOfLocalDay(new Date(endMs - 1)).getTime()
|
||||
const entityKey = String(entity.identifier)
|
||||
|
||||
return {
|
||||
key: `${entityKey}:master`,
|
||||
entity,
|
||||
occurrenceId: null,
|
||||
startMs,
|
||||
endMs,
|
||||
dayStartMs,
|
||||
durationMs: endMs - startMs,
|
||||
timeless: event.timeless === true || lastOccupiedDayMs !== dayStartMs,
|
||||
multiDay: lastOccupiedDayMs !== dayStartMs,
|
||||
}
|
||||
}
|
||||
import { expandEntityOccurrences } from './recurrence'
|
||||
|
||||
function appendToDayBuckets(index: CalendarOccurrenceIndex, occurrence: CalendarOccurrence) {
|
||||
const lastOccupiedDayMs = startOfLocalDay(new Date(occurrence.endMs - 1)).getTime()
|
||||
@@ -63,7 +28,10 @@ function sortOccurrences(occurrences: CalendarOccurrence[]) {
|
||||
))
|
||||
}
|
||||
|
||||
export function buildOccurrenceIndex(entities: EntityObject[]): CalendarOccurrenceIndex {
|
||||
export function buildOccurrenceIndex(
|
||||
entities: EntityObject[],
|
||||
range?: VisibleDateRange,
|
||||
): CalendarOccurrenceIndex {
|
||||
const index: CalendarOccurrenceIndex = {
|
||||
byDay: new Map(),
|
||||
byEntity: new Map(),
|
||||
@@ -71,12 +39,14 @@ export function buildOccurrenceIndex(entities: EntityObject[]): CalendarOccurren
|
||||
}
|
||||
|
||||
for (const entity of entities) {
|
||||
const occurrence = occurrenceFromEntity(entity)
|
||||
if (!occurrence) continue
|
||||
const entityOccurrences = expandEntityOccurrences(entity, range)
|
||||
if (entityOccurrences.length === 0) continue
|
||||
|
||||
index.sorted.push(occurrence)
|
||||
index.byEntity.set(String(entity.identifier), [occurrence])
|
||||
appendToDayBuckets(index, occurrence)
|
||||
index.byEntity.set(String(entity.identifier), entityOccurrences)
|
||||
for (const occurrence of entityOccurrences) {
|
||||
index.sorted.push(occurrence)
|
||||
appendToDayBuckets(index, occurrence)
|
||||
}
|
||||
}
|
||||
|
||||
sortOccurrences(index.sorted)
|
||||
|
||||
Reference in New Issue
Block a user