event.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { refineProps } from '../util/misc'
  2. import { parseClassName, ClassNameInput } from '../util/html'
  3. import { DateInput } from '../datelib/env'
  4. import Calendar from '../Calendar'
  5. import { assignTo } from '../util/object'
  6. import { DateRange } from '../datelib/date-range'
  7. /*
  8. Utils for parsing event-input data. Each util parses a subset of the event-input's data.
  9. It's up to the caller to stitch them together into an aggregate object like an EventStore.
  10. */
  11. export type EventRenderingChoice = '' | 'background' | 'inverse-background' | 'none'
  12. export interface EventNonDateInput {
  13. id?: string | number
  14. groupId?: string | number
  15. title?: string
  16. url?: string
  17. editable?: boolean
  18. startEditable?: boolean
  19. durationEditable?: boolean
  20. constraint?: any
  21. overlap?: any
  22. rendering?: EventRenderingChoice
  23. className?: ClassNameInput
  24. color?: string
  25. backgroundColor?: string
  26. borderColor?: string
  27. textColor?: string
  28. extendedProps?: object
  29. [extendedProp: string]: any
  30. }
  31. export interface EventDateInput {
  32. start?: DateInput
  33. end?: DateInput
  34. date?: DateInput
  35. isAllDay?: boolean
  36. }
  37. export type EventInput = EventNonDateInput & EventDateInput
  38. export interface EventDef {
  39. defId: string
  40. sourceId: string
  41. publicId: string
  42. groupId: string
  43. hasEnd: boolean
  44. isAllDay: boolean
  45. title: string
  46. url: string
  47. editable: boolean | null
  48. startEditable: boolean | null
  49. durationEditable: boolean | null
  50. constraint: any
  51. overlap: any
  52. rendering: EventRenderingChoice
  53. className: string[]
  54. backgroundColor: string
  55. borderColor: string
  56. textColor: string
  57. extendedProps: object
  58. }
  59. export interface EventInstance {
  60. instanceId: string
  61. defId: string
  62. range: DateRange
  63. forcedStartTzo: number | null
  64. forcedEndTzo: number | null
  65. }
  66. // information about an event's dates.
  67. // only used as an intermediate object. never stored anywhere.
  68. export interface EventDateSpan {
  69. isAllDay: boolean
  70. hasEnd: boolean
  71. range: DateRange
  72. forcedStartTzo: number | null
  73. forcedEndTzo: number | null
  74. }
  75. export type EventInstanceHash = { [instanceId: string]: EventInstance }
  76. export type EventDefHash = { [defId: string]: EventDef }
  77. const NON_DATE_PROPS = {
  78. groupId: String,
  79. title: String,
  80. url: String,
  81. editable: Boolean,
  82. startEditable: Boolean,
  83. durationEditable: Boolean,
  84. constraint: null,
  85. overlap: null,
  86. rendering: String,
  87. className: parseClassName,
  88. color: String,
  89. backgroundColor: String,
  90. borderColor: String,
  91. textColor: String,
  92. extendedProps: null
  93. }
  94. const DATE_PROPS = {
  95. start: null,
  96. date: null,
  97. end: null,
  98. isAllDay: null
  99. }
  100. let uid = 0
  101. export function parseEventDef(raw: EventNonDateInput, sourceId: string, isAllDay: boolean, hasEnd: boolean): EventDef {
  102. let leftovers = {} as any
  103. let props = refineProps(raw, NON_DATE_PROPS, {}, leftovers) as EventDef
  104. props.defId = String(uid++)
  105. props.sourceId = sourceId
  106. props.isAllDay = isAllDay
  107. props.hasEnd = hasEnd
  108. if ('id' in leftovers) {
  109. props.publicId = String(leftovers.id)
  110. delete leftovers.id
  111. }
  112. if ('color' in leftovers) {
  113. if (!props.backgroundColor) {
  114. props.backgroundColor = leftovers.color
  115. }
  116. if (!props.borderColor) {
  117. props.borderColor = leftovers.color
  118. }
  119. delete leftovers.color
  120. }
  121. props.extendedProps = assignTo(leftovers, props.extendedProps || {})
  122. return props
  123. }
  124. export function createEventInstance(
  125. defId: string,
  126. range: DateRange,
  127. forcedStartTzo: number | null = null,
  128. forcedEndTzo: number | null = null
  129. ): EventInstance {
  130. let instanceId = String(uid++)
  131. return { instanceId, defId, range, forcedStartTzo, forcedEndTzo }
  132. }
  133. export function parseEventDateSpan(
  134. raw: EventDateInput,
  135. sourceId: string,
  136. calendar: Calendar,
  137. leftovers: object
  138. ): EventDateSpan | null {
  139. let dateProps = refineProps(raw, DATE_PROPS, {}, leftovers)
  140. let rawStart = dateProps.start
  141. let startMeta
  142. let hasEnd = false
  143. let endMeta = null
  144. let endMarker = null
  145. if (rawStart == null) {
  146. rawStart = dateProps.date
  147. }
  148. if (rawStart != null) {
  149. startMeta = calendar.dateEnv.createMarkerMeta(rawStart)
  150. }
  151. if (!startMeta) {
  152. return null
  153. }
  154. if (dateProps.end != null) {
  155. endMeta = calendar.dateEnv.createMarkerMeta(dateProps.end)
  156. }
  157. let isAllDay = dateProps.isAllDay
  158. if (isAllDay == null && sourceId) {
  159. let source = calendar.state.eventSources[sourceId]
  160. isAllDay = source.allDayDefault
  161. }
  162. if (isAllDay == null) {
  163. isAllDay = calendar.opt('allDayDefault')
  164. }
  165. if (isAllDay == null) {
  166. isAllDay = startMeta.isTimeUnspecified && (!endMeta || endMeta.isTimeUnspecified)
  167. }
  168. if (endMeta) {
  169. endMarker = endMeta.marker
  170. if (endMarker <= startMeta.marker) {
  171. endMarker = null
  172. }
  173. }
  174. if (endMarker) {
  175. hasEnd = true
  176. } else {
  177. hasEnd = calendar.opt('forceEventDuration') || false
  178. endMarker = calendar.dateEnv.add(
  179. startMeta.marker,
  180. isAllDay ?
  181. calendar.defaultAllDayEventDuration :
  182. calendar.defaultTimedEventDuration
  183. )
  184. }
  185. return {
  186. isAllDay,
  187. hasEnd,
  188. range: { start: startMeta.marker, end: endMarker },
  189. forcedStartTzo: startMeta.forcedTzo,
  190. forcedEndTzo: endMeta ? endMeta.forcedTzo : null
  191. }
  192. }