Translations and set tags to events
This commit is contained in:
parent
e61ed72dc9
commit
f66a297e23
|
@ -109,13 +109,14 @@ declare namespace GQL {
|
|||
|
||||
interface IEventTag {
|
||||
__typename: 'EventTag';
|
||||
ID: string;
|
||||
id: string;
|
||||
name: string;
|
||||
translations: Array<IEventTagTranslation>;
|
||||
}
|
||||
|
||||
interface IEventTagTranslation {
|
||||
__typename: 'EventTagTranslation';
|
||||
id: string;
|
||||
language: string;
|
||||
text: string;
|
||||
}
|
||||
|
|
|
@ -5,24 +5,25 @@ import {
|
|||
BaseEntity,
|
||||
OneToMany,
|
||||
ManyToOne,
|
||||
} from "typeorm"
|
||||
import {User} from "../Auth/User.entity"
|
||||
import {DateTime} from "luxon"
|
||||
import {rrulestr} from "rrule"
|
||||
import { EventTag } from "./EventTag.entity";
|
||||
ManyToMany, JoinTable
|
||||
} from "typeorm";
|
||||
import { User } from "../Auth/User.entity"
|
||||
import { DateTime } from "luxon"
|
||||
import { rrulestr } from "rrule"
|
||||
import { EventTag } from "./EventTag.entity"
|
||||
|
||||
export const breakTime = (isoString: string) => {
|
||||
const tSplit = isoString.split('T')
|
||||
const tSplit = isoString.split("T")
|
||||
return {
|
||||
date: tSplit[0],
|
||||
time: tSplit[1].substr(0, 8)
|
||||
time: tSplit[1].substr(0, 8),
|
||||
}
|
||||
}
|
||||
|
||||
export class EventLocation {
|
||||
@Column({nullable: true})
|
||||
@Column({ nullable: true })
|
||||
address?: string
|
||||
@Column({nullable: true})
|
||||
@Column({ nullable: true })
|
||||
name?: string
|
||||
}
|
||||
|
||||
|
@ -31,7 +32,6 @@ export class EventLocation {
|
|||
* therefore all times are string and not Date objects. TODO: Add joi validation
|
||||
*/
|
||||
|
||||
|
||||
export class EventTime {
|
||||
@Column()
|
||||
timeZone: string
|
||||
|
@ -42,10 +42,10 @@ export class EventTime {
|
|||
@Column()
|
||||
end: string
|
||||
|
||||
@Column({nullable: true})
|
||||
@Column({ nullable: true })
|
||||
recurrence?: string
|
||||
|
||||
@Column({nullable: true})
|
||||
@Column({ nullable: true })
|
||||
exceptions?: string
|
||||
}
|
||||
|
||||
|
@ -58,23 +58,24 @@ export class Event extends BaseEntity {
|
|||
owner: Promise<User>
|
||||
|
||||
@OneToMany(type => EventOccurrence, occurrence => occurrence.event, {
|
||||
cascade: true
|
||||
cascade: true,
|
||||
})
|
||||
occurrences: Promise<EventOccurrence[]>
|
||||
|
||||
@OneToMany(type => EventInformation, eventInfo => eventInfo.event, {
|
||||
cascade: true
|
||||
cascade: true,
|
||||
})
|
||||
infos: Promise<EventInformation[]>
|
||||
|
||||
@Column(type => EventTime)
|
||||
time: EventTime
|
||||
|
||||
@OneToMany(type => EventTag, tag => tag.events)
|
||||
@ManyToMany(type => EventTag, tag => tag.events)
|
||||
@JoinTable()
|
||||
tags: Promise<EventTag[]>
|
||||
|
||||
@Column({
|
||||
default: "confirmed"
|
||||
default: "confirmed",
|
||||
})
|
||||
status: string
|
||||
|
||||
|
@ -83,19 +84,29 @@ export class Event extends BaseEntity {
|
|||
|
||||
getOccurrences(): EventOccurrence[] {
|
||||
const occurences = []
|
||||
console.log('this.time.recurrence', this.time.recurrence)
|
||||
console.log("this.time.recurrence", this.time.recurrence)
|
||||
if (!this.time.recurrence) {
|
||||
const occ = new EventOccurrence()
|
||||
occ.during = `[${this.time.start},${this.time.end}]`
|
||||
occurences.push(occ)
|
||||
} else {
|
||||
const dates = rrulestr(this.time.recurrence).all((occurenceDate, i) => i < 30)
|
||||
const eventDuration = DateTime.fromISO(this.time.start).diff(DateTime.fromISO(this.time.end))
|
||||
const dates = rrulestr(this.time.recurrence).all(
|
||||
(occurenceDate, i) => i < 30
|
||||
)
|
||||
const eventDuration = DateTime.fromISO(this.time.start).diff(
|
||||
DateTime.fromISO(this.time.end)
|
||||
)
|
||||
|
||||
dates.forEach(recurrenceDateStart => {
|
||||
const occ = new EventOccurrence()
|
||||
const brokenRecurrenceDateStart = breakTime(recurrenceDateStart.toISOString())
|
||||
const brokenRecurrenceDateEnd = breakTime(DateTime.fromJSDate(recurrenceDateStart).plus(eventDuration).toISO())
|
||||
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)
|
||||
|
||||
|
@ -103,7 +114,6 @@ export class Event extends BaseEntity {
|
|||
const duringTo = `${brokenRecurrenceDateEnd.date} ${userInputEnd.time} ${this.time.timeZone}`
|
||||
occ.during = `[${duringFrom}, ${duringTo}]`
|
||||
})
|
||||
|
||||
}
|
||||
occurences.forEach(occ => {
|
||||
occ.start = this.time.start
|
||||
|
@ -123,10 +133,10 @@ export class EventInformation {
|
|||
language: string
|
||||
@Column()
|
||||
title: string
|
||||
@Column({nullable: true})
|
||||
@Column({ nullable: true })
|
||||
description: string
|
||||
@ManyToOne(type => Event, event => event.infos, {
|
||||
onDelete: "CASCADE"
|
||||
onDelete: "CASCADE",
|
||||
})
|
||||
event: Event
|
||||
}
|
||||
|
@ -138,11 +148,11 @@ export class EventOccurrence extends BaseEntity {
|
|||
|
||||
@ManyToOne(type => Event, event => event.occurrences, {
|
||||
nullable: false,
|
||||
onDelete: "CASCADE"
|
||||
onDelete: "CASCADE",
|
||||
})
|
||||
event: Promise<Event>
|
||||
|
||||
@Column({type: "tstzrange", nullable: true})
|
||||
@Column({ type: "tstzrange", nullable: true })
|
||||
during: string
|
||||
|
||||
@Column()
|
||||
|
@ -150,5 +160,4 @@ export class EventOccurrence extends BaseEntity {
|
|||
|
||||
@Column()
|
||||
end: string
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
import { BaseEntity, Column, Entity, ManyToMany, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
Entity,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn
|
||||
} from "typeorm";
|
||||
import { Event } from "./Event.entity";
|
||||
|
||||
@Entity()
|
||||
|
@ -12,7 +21,9 @@ export class EventTag extends BaseEntity {
|
|||
@ManyToMany(type => Event, event => event.tags)
|
||||
events: Promise<Event[]>
|
||||
|
||||
@OneToMany(type => EventTagTranslation, translation => translation.tag)
|
||||
@OneToMany(type => EventTagTranslation, translation => translation.tag, {
|
||||
cascade: true
|
||||
})
|
||||
translations: Promise<EventTagTranslation[]>
|
||||
}
|
||||
|
||||
|
@ -21,7 +32,9 @@ export class EventTagTranslation extends BaseEntity {
|
|||
@PrimaryGeneratedColumn("uuid")
|
||||
id: number
|
||||
|
||||
@ManyToOne(type => EventTag, tag => tag.translations)
|
||||
@ManyToOne(type => EventTag, tag => tag.translations, {
|
||||
nullable: false
|
||||
})
|
||||
tag: Promise<EventTag>
|
||||
|
||||
@Column("varchar")
|
||||
|
|
|
@ -7,7 +7,7 @@ const adminOrThrow = async (context: Context) => {
|
|||
throw new Error("Only admin can create and modify tags")
|
||||
}
|
||||
}
|
||||
const resolvers: ResolverMap = {
|
||||
export const tagResolvers: ResolverMap = {
|
||||
Mutation: {
|
||||
createEventTag: async (
|
||||
_,
|
||||
|
@ -20,6 +20,7 @@ const resolvers: ResolverMap = {
|
|||
tag.name = req.input.name
|
||||
tag.events = Promise.resolve([])
|
||||
|
||||
|
||||
const translations: EventTagTranslation[] = req.input.translations.map(
|
||||
translationInput => {
|
||||
const translation = new EventTagTranslation()
|
||||
|
@ -40,6 +41,7 @@ const resolvers: ResolverMap = {
|
|||
) => {
|
||||
await adminOrThrow(context)
|
||||
const tag = await EventTag.findOne(req.input.id)
|
||||
tag.name = req.input.name
|
||||
const translations = await tag.translations
|
||||
const langToExistingTranslation: {[lang: string]: EventTagTranslation} = {}
|
||||
const langToInputTranslations: {[lang: string]: GQL.ICreateModifyEventTagTranslationInput} = {}
|
||||
|
@ -49,6 +51,7 @@ const resolvers: ResolverMap = {
|
|||
|
||||
const removedTranslationsPromises = Object.keys(langToExistingTranslation).map((existingLang) => {
|
||||
if (!langToInputTranslations[existingLang]) {
|
||||
translations.splice(translations.findIndex(translation => translation.language === existingLang), 1)
|
||||
return langToExistingTranslation[existingLang].remove()
|
||||
}
|
||||
return null
|
||||
|
@ -58,11 +61,8 @@ const resolvers: ResolverMap = {
|
|||
const changedTranslationsPromises = Object.keys(langToExistingTranslation).map(existingLang => {
|
||||
const existingTranslation = langToExistingTranslation[existingLang]
|
||||
const matchingInput = langToInputTranslations[existingLang]
|
||||
if (!(existingTranslation && matchingInput)) {
|
||||
throw new Error("Coding error, existing translation and matching input must both exist")
|
||||
}
|
||||
|
||||
if (existingTranslation.text !== matchingInput.text ) {
|
||||
if (existingTranslation && matchingInput && existingTranslation.text !== matchingInput.text ) {
|
||||
existingTranslation.text = matchingInput.text
|
||||
return existingTranslation.save()
|
||||
}
|
||||
|
@ -74,13 +74,16 @@ const resolvers: ResolverMap = {
|
|||
if (!langToExistingTranslation[inputLang]) {
|
||||
const newTranslation = new EventTagTranslation()
|
||||
newTranslation.tag = Promise.resolve(tag)
|
||||
translations.push(newTranslation)
|
||||
newTranslation.language = inputLang
|
||||
newTranslation.text = langToInputTranslations[inputLang].text
|
||||
return newTranslation
|
||||
return newTranslation.save()
|
||||
}
|
||||
return null
|
||||
})
|
||||
await Promise.all(newTranslationsPromises.filter(Boolean))
|
||||
tag.translations = Promise.resolve(translations)
|
||||
return tag.save()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ const resolvers: ResolverMap = {
|
|||
const infos = await event.infos
|
||||
return infos.find(info => info.language === req.lang)
|
||||
},
|
||||
tags: async (event: Event) => {
|
||||
return event.tags
|
||||
}
|
||||
},
|
||||
|
||||
EventOccurrence: {
|
||||
|
|
|
@ -9,6 +9,7 @@ import {PostOffice} from "./post_office"
|
|||
import {Session} from "./Auth/Session.entity"
|
||||
import {Context} from "./@types/graphql-utils"
|
||||
import SessionManager from "./Auth/SessionManager"
|
||||
import { tagResolvers } from "./Calendar/tagsResolvers";
|
||||
|
||||
interface Dependencies {
|
||||
typeormConnection: Connection
|
||||
|
@ -46,12 +47,15 @@ export const createServer = async (dependencies: Dependencies) => {
|
|||
...EventQueryResolvers,
|
||||
...authResolvers.Query,
|
||||
...UserQueryResolvers,
|
||||
...tagResolvers.Query
|
||||
|
||||
},
|
||||
Mutation: {
|
||||
...resolvers.Mutation,
|
||||
...EventResolversMutation,
|
||||
...authResolvers.Mutation,
|
||||
...UserMutationResolvers,
|
||||
...tagResolvers.Mutation
|
||||
},
|
||||
UserSession: {
|
||||
...authResolvers.UserSession
|
||||
|
|
|
@ -66,12 +66,13 @@ type CalendarEvent {
|
|||
}
|
||||
|
||||
type EventTag {
|
||||
ID: ID!
|
||||
id: ID!
|
||||
name: String!
|
||||
translations: [EventTagTranslation!]!
|
||||
}
|
||||
|
||||
type EventTagTranslation {
|
||||
id: ID!
|
||||
language: String!
|
||||
text: String!
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue