182 lines
4.4 KiB
TypeScript
182 lines
4.4 KiB
TypeScript
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
BaseEntity,
|
|
OneToMany,
|
|
ManyToOne,
|
|
ManyToMany,
|
|
JoinTable,
|
|
} from "typeorm"
|
|
import { User } from "../Auth/User.entity"
|
|
import { DateTime } from "luxon"
|
|
import { rrulestr } from "rrule"
|
|
import { EventTag } from "./EventTag.entity"
|
|
import { format } from "date-fns"
|
|
import { EventImage } from "../Image/EventImage.entity";
|
|
|
|
export const breakTime = (isoString: string) => {
|
|
const tSplit = isoString.split("T")
|
|
return {
|
|
date: tSplit[0],
|
|
time: tSplit[1].substr(0, 8),
|
|
}
|
|
}
|
|
|
|
export class EventLocation {
|
|
@Column({ nullable: true })
|
|
address?: string
|
|
@Column({ nullable: true })
|
|
name?: string
|
|
}
|
|
|
|
/**
|
|
* EventTime documents the time in the local mindset of the user created the event
|
|
* therefore all times are string and not Date objects. TODO: Add joi validation
|
|
*/
|
|
|
|
export class EventTime {
|
|
@Column()
|
|
timeZone: string
|
|
|
|
@Column()
|
|
start: string
|
|
|
|
@Column()
|
|
end: string
|
|
|
|
@Column({ nullable: true })
|
|
recurrence?: string
|
|
|
|
@Column({ nullable: true })
|
|
exceptions?: string
|
|
}
|
|
|
|
@Entity()
|
|
export class Event extends BaseEntity {
|
|
@PrimaryGeneratedColumn("uuid")
|
|
id: number
|
|
|
|
@ManyToOne(type => User, user => user.events)
|
|
owner: Promise<User>
|
|
|
|
@OneToMany(type => EventOccurrence, occurrence => occurrence.event, {
|
|
cascade: true,
|
|
})
|
|
occurrences: Promise<EventOccurrence[]>
|
|
|
|
@OneToMany(type => EventInformation, eventInfo => eventInfo.event, {
|
|
cascade: true,
|
|
})
|
|
infos: Promise<EventInformation[]>
|
|
|
|
@Column(type => EventTime)
|
|
time: EventTime
|
|
|
|
@ManyToMany(type => EventTag)
|
|
@JoinTable()
|
|
tags: Promise<EventTag[]>
|
|
|
|
@Column({
|
|
default: "confirmed",
|
|
})
|
|
status: string
|
|
|
|
@OneToMany(type => EventImage, image => image.event, {
|
|
onDelete: 'CASCADE'
|
|
})
|
|
images: Promise<EventImage[]>
|
|
|
|
@Column(type => EventLocation)
|
|
location: EventLocation
|
|
|
|
getOccurrences(): EventOccurrence[] {
|
|
const occurences = []
|
|
const justTime = {
|
|
start: format(new Date(this.time.start), "HH:mm"),
|
|
end: format(new Date(this.time.end), "HH:mm"),
|
|
}
|
|
if (!this.time.recurrence) {
|
|
const occ = new EventOccurrence()
|
|
occ.during = `[${this.time.start},${this.time.end}]`
|
|
occ.start = format(new Date(this.time.start),"yyyy-MM-dd'T'HH:mm")
|
|
occ.end = format(new Date(this.time.end),"yyyy-MM-dd'T'HH:mm")
|
|
occurences.push(occ)
|
|
} else {
|
|
const dates = rrulestr(this.time.recurrence).all(
|
|
(occurrenceDate, i) => i < 30
|
|
)
|
|
const eventDuration =
|
|
new Date(this.time.end).getTime() - new Date(this.time.start).getTime()
|
|
|
|
dates.forEach(recurrenceDateStart => {
|
|
const recurrenceDateEnd = new Date(
|
|
recurrenceDateStart.getTime() + eventDuration
|
|
)
|
|
|
|
const occ = new EventOccurrence()
|
|
occ.event = Promise.resolve(this)
|
|
const brokenRecurrenceDateStart = breakTime(
|
|
recurrenceDateStart.toISOString()
|
|
)
|
|
const brokenRecurrenceDateEnd = breakTime(
|
|
DateTime.fromJSDate(recurrenceDateStart)
|
|
.plus(eventDuration)
|
|
.toISO()
|
|
)
|
|
const userInputStart = breakTime(this.time.start)
|
|
const userInputEnd = breakTime(this.time.end)
|
|
|
|
const duringFrom = `${brokenRecurrenceDateStart.date} ${userInputStart.time} ${this.time.timeZone}`
|
|
const duringTo = `${brokenRecurrenceDateEnd.date} ${userInputEnd.time} ${this.time.timeZone}`
|
|
occ.during = `[${duringFrom}, ${duringTo}]`
|
|
occ.start = `${format(recurrenceDateStart, "yyyy-MM-dd")}T${
|
|
justTime.start
|
|
}`
|
|
occ.end = `${format(recurrenceDateStart, "yyyy-MM-dd")}T${justTime.end}`
|
|
occ.event = Promise.resolve(this)
|
|
occurences.push(occ)
|
|
})
|
|
}
|
|
console.log('the occurrences calculated', occurences)
|
|
return occurences
|
|
}
|
|
}
|
|
|
|
@Entity()
|
|
export class EventInformation {
|
|
@PrimaryGeneratedColumn("uuid")
|
|
id: string
|
|
@Column()
|
|
language: string
|
|
@Column()
|
|
title: string
|
|
@Column({ nullable: true })
|
|
description: string
|
|
@ManyToOne(type => Event, event => event.infos, {
|
|
onDelete: "CASCADE",
|
|
})
|
|
event: Event
|
|
}
|
|
|
|
@Entity()
|
|
export class EventOccurrence extends BaseEntity {
|
|
@PrimaryGeneratedColumn("uuid")
|
|
id: number
|
|
|
|
@ManyToOne(type => Event, event => event.occurrences, {
|
|
nullable: false,
|
|
onDelete: "CASCADE",
|
|
})
|
|
event: Promise<Event>
|
|
|
|
@Column({ type: "tstzrange", nullable: true })
|
|
during: string
|
|
|
|
@Column()
|
|
start: string
|
|
|
|
@Column()
|
|
end: string
|
|
}
|