Fixed some tests
This commit is contained in:
parent
91329860de
commit
e61ed72dc9
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": false
|
||||
}
|
|
@ -70,7 +70,7 @@ declare namespace GQL {
|
|||
status: any;
|
||||
location: ILocation;
|
||||
occurrences: Array<IEventOccurrence | null> | null;
|
||||
meta: IEventMeta | null;
|
||||
tags: Array<IEventTag | null> | null;
|
||||
}
|
||||
|
||||
interface IInfoOnCalendarEventArguments {
|
||||
|
@ -107,9 +107,17 @@ declare namespace GQL {
|
|||
end: string;
|
||||
}
|
||||
|
||||
interface IEventMeta {
|
||||
__typename: 'EventMeta';
|
||||
tags: Array<string | null>;
|
||||
interface IEventTag {
|
||||
__typename: 'EventTag';
|
||||
ID: string;
|
||||
name: string;
|
||||
translations: Array<IEventTagTranslation>;
|
||||
}
|
||||
|
||||
interface IEventTagTranslation {
|
||||
__typename: 'EventTagTranslation';
|
||||
language: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface IUserRole {
|
||||
|
@ -144,6 +152,8 @@ declare namespace GQL {
|
|||
createEvent: ICalendarEvent | null;
|
||||
updateEvent: ICalendarEvent | null;
|
||||
deleteEvent: IUser;
|
||||
createEventTag: IEventTag | null;
|
||||
modifyEventTag: IEventTag | null;
|
||||
}
|
||||
|
||||
interface ISignupOnMutationArguments {
|
||||
|
@ -178,6 +188,14 @@ declare namespace GQL {
|
|||
id: string;
|
||||
}
|
||||
|
||||
interface ICreateEventTagOnMutationArguments {
|
||||
input: ICreateEventTagInput;
|
||||
}
|
||||
|
||||
interface IModifyEventTagOnMutationArguments {
|
||||
input: IModifyEventTagInput;
|
||||
}
|
||||
|
||||
interface ISignupInput {
|
||||
email: string;
|
||||
username: string;
|
||||
|
@ -215,7 +233,7 @@ declare namespace GQL {
|
|||
time: IEventTimeInput;
|
||||
infos: Array<IEventInformationInput | null>;
|
||||
location: IEventLocationInput;
|
||||
meta: IEventMetaInput;
|
||||
tagNames: Array<string>;
|
||||
status: string;
|
||||
}
|
||||
|
||||
|
@ -238,19 +256,44 @@ declare namespace GQL {
|
|||
name?: string | null;
|
||||
}
|
||||
|
||||
interface IEventMetaInput {
|
||||
tags: Array<string | null>;
|
||||
}
|
||||
|
||||
interface IUpdateEventInput {
|
||||
id: string;
|
||||
time?: IEventTimeInput | null;
|
||||
infos?: Array<IEventInformationInput> | null;
|
||||
location?: IEventLocationInput | null;
|
||||
meta?: IEventMetaInput | null;
|
||||
tagNames: Array<string>;
|
||||
status?: string | null;
|
||||
}
|
||||
|
||||
interface ICreateEventTagInput {
|
||||
name: string;
|
||||
translations: Array<ICreateModifyEventTagTranslationInput>;
|
||||
}
|
||||
|
||||
interface ICreateModifyEventTagTranslationInput {
|
||||
language: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface IModifyEventTagInput {
|
||||
id: string;
|
||||
name: string;
|
||||
translations: Array<ICreateModifyEventTagTranslationInput>;
|
||||
}
|
||||
|
||||
interface ITag {
|
||||
__typename: 'Tag';
|
||||
id: string;
|
||||
name: string;
|
||||
translations: Array<any>;
|
||||
}
|
||||
|
||||
interface ITagTranslation {
|
||||
__typename: 'TagTranslation';
|
||||
language: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface IRevokeRoleInput {
|
||||
userId: string;
|
||||
roleType: any;
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
"ramda": "^0.26.1",
|
||||
"random-string": "^0.2.0",
|
||||
"rrule": "^2.6.2",
|
||||
"typeorm": "^0.2.18",
|
||||
"typescript": "^3.5.3",
|
||||
"typeorm": "^0.2.20",
|
||||
"typescript": "^3.7.2",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -47,8 +47,7 @@
|
|||
"prettier": "^1.18.2",
|
||||
"ts-jest": "^24.0.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"tslint": "^5.18.0",
|
||||
"typescript": "^3.5.3"
|
||||
"tslint": "^5.18.0"
|
||||
},
|
||||
"jest": {
|
||||
"globalSetup": "./jest-setup.js",
|
||||
|
|
|
@ -18,6 +18,7 @@ describe('Authentication', () => {
|
|||
connection = await createConnection({
|
||||
...testConfig,
|
||||
logging: null
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -27,7 +28,8 @@ describe('Authentication', () => {
|
|||
const server = await createServer({
|
||||
typeormConnection: connection,
|
||||
sendEmail: sendEmailMock as PostOffice,
|
||||
domain: 'example.com'
|
||||
domain: 'example.com',
|
||||
sessionManager: jest.fn(() => Promise.resolve(true)) as any
|
||||
})
|
||||
testClient = await createTestClient(server as any)
|
||||
})
|
||||
|
|
|
@ -9,16 +9,7 @@ import {
|
|||
import {User} from "../Auth/User.entity"
|
||||
import {DateTime} from "luxon"
|
||||
import {rrulestr} from "rrule"
|
||||
|
||||
export const toUTC = (isoTime: string, ianaTZ: string): DateTime => {
|
||||
const parsed = DateTime.fromISO(isoTime, {zone: ianaTZ})
|
||||
if (parsed.invalidReason) {
|
||||
throw new Error(
|
||||
`${parsed.invalidReason}: ${isoTime} with time-zone: ${ianaTZ}`
|
||||
)
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
import { EventTag } from "./EventTag.entity";
|
||||
|
||||
export const breakTime = (isoString: string) => {
|
||||
const tSplit = isoString.split('T')
|
||||
|
@ -58,11 +49,6 @@ export class EventTime {
|
|||
exceptions?: string
|
||||
}
|
||||
|
||||
export class EventMeta {
|
||||
@Column({type: "varchar", array: true})
|
||||
tags: string[]
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class Event extends BaseEntity {
|
||||
@PrimaryGeneratedColumn("uuid")
|
||||
|
@ -84,8 +70,8 @@ export class Event extends BaseEntity {
|
|||
@Column(type => EventTime)
|
||||
time: EventTime
|
||||
|
||||
@Column(type => EventMeta)
|
||||
meta: EventMeta
|
||||
@OneToMany(type => EventTag, tag => tag.events)
|
||||
tags: Promise<EventTag[]>
|
||||
|
||||
@Column({
|
||||
default: "confirmed"
|
||||
|
@ -95,7 +81,7 @@ export class Event extends BaseEntity {
|
|||
@Column(type => EventLocation)
|
||||
location: EventLocation
|
||||
|
||||
getOccurrences() {
|
||||
getOccurrences(): EventOccurrence[] {
|
||||
const occurences = []
|
||||
console.log('this.time.recurrence', this.time.recurrence)
|
||||
if (!this.time.recurrence) {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { BaseEntity, Column, Entity, ManyToMany, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Event } from "./Event.entity";
|
||||
|
||||
@Entity()
|
||||
export class EventTag extends BaseEntity {
|
||||
@PrimaryGeneratedColumn("uuid")
|
||||
id: number
|
||||
|
||||
@Column({type: "varchar", unique: true})
|
||||
name: string
|
||||
|
||||
@ManyToMany(type => Event, event => event.tags)
|
||||
events: Promise<Event[]>
|
||||
|
||||
@OneToMany(type => EventTagTranslation, translation => translation.tag)
|
||||
translations: Promise<EventTagTranslation[]>
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class EventTagTranslation extends BaseEntity {
|
||||
@PrimaryGeneratedColumn("uuid")
|
||||
id: number
|
||||
|
||||
@ManyToOne(type => EventTag, tag => tag.translations)
|
||||
tag: Promise<EventTag>
|
||||
|
||||
@Column("varchar")
|
||||
language: string
|
||||
|
||||
@Column("varchar")
|
||||
text: string
|
||||
}
|
|
@ -1,18 +1,7 @@
|
|||
import { createConnection } from "typeorm"
|
||||
import { User } from "../../Auth/User.entity"
|
||||
import { Event, EventInformation, EventOccurrence } from "../Event.entity"
|
||||
import { DateTime } from "luxon"
|
||||
import testConfig from "../../__tests__/testORMConfig";
|
||||
|
||||
const toUTC = (isoTime: string, ianaTZ: string) => {
|
||||
const parsed = DateTime.fromISO(isoTime, { zone: ianaTZ })
|
||||
if (parsed.invalidReason) {
|
||||
throw new Error(
|
||||
`${parsed.invalidReason}: ${isoTime} with time-zone: ${ianaTZ}`
|
||||
)
|
||||
}
|
||||
return parsed.toUTC().toISO()
|
||||
}
|
||||
import testConfig from "../../__tests__/testORMConfig"
|
||||
|
||||
let owner: User = null
|
||||
|
||||
|
@ -20,7 +9,7 @@ let connection
|
|||
describe("Recurring events", () => {
|
||||
beforeAll(async () => {
|
||||
connection = await createConnection({
|
||||
...testConfig
|
||||
...testConfig,
|
||||
})
|
||||
owner = new User()
|
||||
owner.username = "onetimeguy"
|
||||
|
@ -39,27 +28,26 @@ describe("Recurring events", () => {
|
|||
|
||||
info.title = "Test one time event"
|
||||
info.description = "This is a test event that has no repetition rules"
|
||||
event.owner = owner
|
||||
event.owner = Promise.resolve(owner)
|
||||
event.time = {
|
||||
timeZone: "Europe/Madrid",
|
||||
start: "2019-02-01T10:00Z",
|
||||
end: "2019-02-01T11:00Z"
|
||||
end: "2019-02-01T11:00Z",
|
||||
}
|
||||
|
||||
await event.save()
|
||||
await event.updateOccurrences()
|
||||
|
||||
event.occurrences = Promise.resolve(event.getOccurrences())
|
||||
await event.save()
|
||||
|
||||
const occurences = await EventOccurrence.find({
|
||||
where: { eventId: event.id }
|
||||
where: { eventId: event.id },
|
||||
})
|
||||
expect(occurences).toHaveLength(1)
|
||||
expect((await occurences[0].event).time.timeZone).toEqual(event.time.timeZone)
|
||||
expect((await occurences[0].event).time.timeZone).toEqual(
|
||||
event.time.timeZone
|
||||
)
|
||||
done()
|
||||
})
|
||||
|
||||
it("Event happening once a week", () => {
|
||||
it("Event happening once a week", async () => {
|
||||
const event = new Event()
|
||||
const info = new EventInformation()
|
||||
info.language = "en"
|
||||
|
@ -67,7 +55,7 @@ describe("Recurring events", () => {
|
|||
info.description = "This event takes place every monday at 2pm"
|
||||
|
||||
event.infos = Promise.resolve([info])
|
||||
event.owner = owner
|
||||
event.owner = Promise.resolve(owner)
|
||||
|
||||
// from 2019-03-04 to 2019-03-25 every monday
|
||||
// March 2019
|
||||
|
@ -84,10 +72,10 @@ describe("Recurring events", () => {
|
|||
start: "2019-03-04T14:00",
|
||||
end: "2019-03-04T15:00",
|
||||
recurrence:
|
||||
"DTSTART:20190304T140000Z\nRRULE:FREQ=WEEKLY;BYDAY=MO;INTERVAL=1;UNTIL=20190325T230000Z" // until 15/04/2019
|
||||
"DTSTART:20190304T140000Z\nRRULE:FREQ=WEEKLY;BYDAY=MO;INTERVAL=1;UNTIL=20190325T230000Z", // until 15/04/2019
|
||||
}
|
||||
|
||||
event.updateOccurrences()
|
||||
expect(event.occurrences).toHaveLength(4)
|
||||
event.occurrences = Promise.resolve(event.getOccurrences())
|
||||
expect(await event.occurrences).toHaveLength(4)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { Connection, createConnection } from "typeorm"
|
||||
import { createServer } from "../../graphql"
|
||||
import { PostOffice } from "../../post_office"
|
||||
import { createTestClient } from "apollo-server-testing"
|
||||
import { User } from "../../Auth/User.entity"
|
||||
import { Session } from "../../Auth/Session.entity"
|
||||
import { Event, EventInformation } from "../../Calendar/Event.entity"
|
||||
import gql from "graphql-tag"
|
||||
import testConfig from "../../__tests__/testORMConfig"
|
||||
|
||||
let testClient
|
||||
let connection: Connection = null
|
||||
let sendEmailMock
|
||||
let sessionManagerMock
|
||||
|
||||
describe("Tags resolver", () => {
|
||||
beforeAll(async () => {
|
||||
return (connection = await createConnection({
|
||||
...testConfig
|
||||
}))
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
sendEmailMock = jest.fn(() => Promise.resolve(true))
|
||||
sessionManagerMock = jest.fn(() => Promise.resolve(true))
|
||||
|
||||
const server = await createServer({
|
||||
typeormConnection: connection,
|
||||
sendEmail: sendEmailMock as PostOffice,
|
||||
sessionManager: sessionManagerMock
|
||||
})
|
||||
return (testClient = await createTestClient(server as any))
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await connection.close()
|
||||
})
|
||||
|
||||
it("Create some tags", async done => {
|
||||
done()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,86 @@
|
|||
import { Context, ResolverMap } from "../@types/graphql-utils"
|
||||
import { EventTag, EventTagTranslation } from "./EventTag.entity"
|
||||
|
||||
const adminOrThrow = async (context: Context) => {
|
||||
const roles = await context.user?.roles
|
||||
if (!roles?.find(role => role.type === "admin")) {
|
||||
throw new Error("Only admin can create and modify tags")
|
||||
}
|
||||
}
|
||||
const resolvers: ResolverMap = {
|
||||
Mutation: {
|
||||
createEventTag: async (
|
||||
_,
|
||||
req: GQL.ICreateEventTagOnMutationArguments,
|
||||
context: Context,
|
||||
info: any
|
||||
): Promise<EventTag> => {
|
||||
await adminOrThrow(context)
|
||||
const tag = new EventTag()
|
||||
tag.name = req.input.name
|
||||
tag.events = Promise.resolve([])
|
||||
|
||||
const translations: EventTagTranslation[] = req.input.translations.map(
|
||||
translationInput => {
|
||||
const translation = new EventTagTranslation()
|
||||
translation.tag = Promise.resolve(tag)
|
||||
translation.language = translationInput.language
|
||||
translation.text = translationInput.text
|
||||
return translation
|
||||
}
|
||||
)
|
||||
|
||||
tag.translations = Promise.resolve(translations)
|
||||
return tag.save()
|
||||
},
|
||||
modifyEventTag: async (
|
||||
_,
|
||||
req: GQL.IModifyEventTagOnMutationArguments,
|
||||
context: Context
|
||||
) => {
|
||||
await adminOrThrow(context)
|
||||
const tag = await EventTag.findOne(req.input.id)
|
||||
const translations = await tag.translations
|
||||
const langToExistingTranslation: {[lang: string]: EventTagTranslation} = {}
|
||||
const langToInputTranslations: {[lang: string]: GQL.ICreateModifyEventTagTranslationInput} = {}
|
||||
|
||||
translations.forEach(existingTranslation => langToExistingTranslation[existingTranslation.language] = existingTranslation)
|
||||
req.input.translations.forEach(translationInput => langToInputTranslations[translationInput.language] = translationInput)
|
||||
|
||||
const removedTranslationsPromises = Object.keys(langToExistingTranslation).map((existingLang) => {
|
||||
if (!langToInputTranslations[existingLang]) {
|
||||
return langToExistingTranslation[existingLang].remove()
|
||||
}
|
||||
return null
|
||||
})
|
||||
await Promise.all(removedTranslationsPromises.filter(Boolean))
|
||||
|
||||
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 ) {
|
||||
existingTranslation.text = matchingInput.text
|
||||
return existingTranslation.save()
|
||||
}
|
||||
return null
|
||||
})
|
||||
await Promise.all(changedTranslationsPromises.filter(Boolean))
|
||||
|
||||
const newTranslationsPromises = Object.keys(langToInputTranslations).map(inputLang => {
|
||||
if (!langToExistingTranslation[inputLang]) {
|
||||
const newTranslation = new EventTagTranslation()
|
||||
newTranslation.tag = Promise.resolve(tag)
|
||||
newTranslation.language = inputLang
|
||||
newTranslation.text = langToInputTranslations[inputLang].text
|
||||
return newTranslation
|
||||
}
|
||||
return null
|
||||
})
|
||||
await Promise.all(newTranslationsPromises.filter(Boolean))
|
||||
},
|
||||
},
|
||||
}
|
|
@ -3,8 +3,16 @@ import {
|
|||
EventInformation,
|
||||
EventOccurrence
|
||||
} from "../Calendar/Event.entity"
|
||||
import { EventTag } from "../Calendar/EventTag.entity";
|
||||
|
||||
export default class EventsService {
|
||||
|
||||
export const getTags = async (tagNames: string[]): Promise<EventTag[]> => {
|
||||
const tagPromises = tagNames.map(tagName =>
|
||||
EventTag.findOne({
|
||||
where: {
|
||||
name: tagName,
|
||||
},
|
||||
})
|
||||
)
|
||||
const tags = await Promise.all(tagPromises)
|
||||
return tags
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import testConfig from "../../__tests__/testORMConfig"
|
|||
let testClient
|
||||
let connection: Connection = null
|
||||
let sendEmailMock
|
||||
let sessionManagerMock
|
||||
|
||||
const createKiteflyingEvent = async () => {
|
||||
const owner = new User()
|
||||
|
@ -26,12 +27,12 @@ const createKiteflyingEvent = async () => {
|
|||
await session.save()
|
||||
|
||||
const event = new Event()
|
||||
event.owner = owner
|
||||
event.infos = [{
|
||||
event.owner = Promise.resolve(owner)
|
||||
event.infos = Promise.resolve([{
|
||||
language: "en",
|
||||
title: "Kite Flying Test Event",
|
||||
description: "Description for test event starting at 3pm"
|
||||
}]
|
||||
} as EventInformation])
|
||||
event.time = {
|
||||
timeZone: "Europe/Madrid",
|
||||
start: "2019-10-10T13:00",
|
||||
|
@ -55,19 +56,20 @@ const createKinttingEvent = async () => {
|
|||
await session.save()
|
||||
|
||||
const event = new Event()
|
||||
event.owner = owner
|
||||
event.infos = [{
|
||||
event.owner = Promise.resolve(owner)
|
||||
event.infos = Promise.resolve([{
|
||||
language: "en",
|
||||
title: "Knitting Test Event",
|
||||
description: "Description for test event starting at 3pm"
|
||||
}]
|
||||
} as EventInformation])
|
||||
event.time = {
|
||||
timeZone: "Europe/Madrid",
|
||||
start: "2019-10-10T14:00",
|
||||
end: "2019-10-10T15:00"
|
||||
}
|
||||
event.status = "Scheduled"
|
||||
return await event.updateOccurrences().save()
|
||||
event.occurrences = Promise.resolve(event.getOccurrences())
|
||||
return await event.save()
|
||||
}
|
||||
|
||||
describe("Events resolver", () => {
|
||||
|
@ -79,10 +81,12 @@ describe("Events resolver", () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
sendEmailMock = jest.fn(() => Promise.resolve(true))
|
||||
sessionManagerMock = jest.fn(() => Promise.resolve(true))
|
||||
|
||||
const server = await createServer({
|
||||
typeormConnection: connection,
|
||||
sendEmail: sendEmailMock as PostOffice
|
||||
sendEmail: sendEmailMock as PostOffice,
|
||||
sessionManager: sessionManagerMock
|
||||
})
|
||||
return (testClient = await createTestClient(server as any))
|
||||
})
|
||||
|
@ -99,7 +103,8 @@ describe("Events resolver", () => {
|
|||
query {
|
||||
events(filter: { limit: 10 }) {
|
||||
id
|
||||
info {
|
||||
info(lang: "en") {
|
||||
language
|
||||
title
|
||||
description
|
||||
}
|
||||
|
@ -127,7 +132,7 @@ describe("Events resolver", () => {
|
|||
query GetEvent($ownerId: ID!) {
|
||||
events(filter: { limit: 10, owner: $ownerId }) {
|
||||
id
|
||||
info {
|
||||
info(lang: "en") {
|
||||
title
|
||||
description
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {User} from "../../Auth/User.entity"
|
||||
import {Session} from "../../Auth/Session.entity"
|
||||
import {Event, EventInformation, toUTC} from "../../Calendar/Event.entity"
|
||||
import {Event, EventInformation} from "../../Calendar/Event.entity"
|
||||
import {Frequency, RRule} from 'rrule'
|
||||
import {Connection, createConnection} from "typeorm"
|
||||
import testConfig from "../../__tests__/testORMConfig";
|
||||
|
@ -49,12 +49,12 @@ describe('Occurrences', async () => {
|
|||
recurrence: new RRule({
|
||||
freq: Frequency.WEEKLY,
|
||||
interval: 1,
|
||||
dtstart: new Date(toUTC(new Date("2019-03-01T13:00Z"), "Europe/Madrid"))
|
||||
dtstart: new Date("2019-03-01T13:00Z+02:00")
|
||||
}).toString()
|
||||
}
|
||||
event.status = "Scheduled"
|
||||
event.occurrences = Promise.resolve(event.getOccurrences())
|
||||
|
||||
event.updateOccurrences()
|
||||
await event.save()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import {
|
||||
Event,
|
||||
EventInformation,
|
||||
EventOccurrence
|
||||
EventOccurrence,
|
||||
} from "../Calendar/Event.entity"
|
||||
import { Context, ResolverMap } from "../@types/graphql-utils"
|
||||
import EventsService from './EventsService'
|
||||
import { equals } from 'ramda'
|
||||
import { User } from "../Auth/User.entity";
|
||||
import { hasAnyRole } from "../Auth/authUtils";
|
||||
|
||||
const eventsService = new EventsService()
|
||||
import { getTags } from "./EventsService"
|
||||
import { equals } from "ramda"
|
||||
import { User } from "../Auth/User.entity"
|
||||
import { hasAnyRole } from "../Auth/authUtils"
|
||||
import { EventTag } from "../Calendar/EventTag.entity"
|
||||
|
||||
const resolvers: ResolverMap = {
|
||||
Query: {
|
||||
|
@ -22,17 +21,14 @@ const resolvers: ResolverMap = {
|
|||
where:
|
||||
req.filter && req.filter.owner
|
||||
? `"ownerId"='${req.filter.owner}'`
|
||||
: null
|
||||
: null,
|
||||
})
|
||||
},
|
||||
occurrences: async (
|
||||
_,
|
||||
req: GQL.IOccurrencesOnQueryArguments,
|
||||
) => {
|
||||
occurrences: async (_, req: GQL.IOccurrencesOnQueryArguments) => {
|
||||
const { from, to } = req.filter
|
||||
return EventOccurrence.find({
|
||||
where: `during && tstzrange('${from}', '${to}')`,
|
||||
take: req.filter.limit
|
||||
take: req.filter.limit,
|
||||
})
|
||||
},
|
||||
occurrence: async (_, req: GQL.IOccurrenceOnQueryArguments) => {
|
||||
|
@ -41,7 +37,7 @@ const resolvers: ResolverMap = {
|
|||
throw new Error(`No occurrence found for id ${req.id}`)
|
||||
}
|
||||
return occ
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
CalendarEvent: {
|
||||
|
@ -59,10 +55,10 @@ const resolvers: ResolverMap = {
|
|||
|
||||
EventOccurrence: {
|
||||
start: (eOcc: EventOccurrence) => {
|
||||
return eOcc.during.split(',')[0].substring(2, 21)
|
||||
return eOcc.during.split(",")[0].substring(2, 21)
|
||||
},
|
||||
end: (eOcc: EventOccurrence) => {
|
||||
return eOcc.during.split(',')[1].substring(2, 21)
|
||||
return eOcc.during.split(",")[1].substring(2, 21)
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -70,13 +66,19 @@ const resolvers: ResolverMap = {
|
|||
createEvent: async (
|
||||
_,
|
||||
{ input }: GQL.ICreateEventOnMutationArguments,
|
||||
context: Context,
|
||||
context: Context
|
||||
) => {
|
||||
if (!context.user) {
|
||||
throw Error("not authenticated")
|
||||
}
|
||||
|
||||
if (!hasAnyRole(await context.user.roles, ['admin','embassador','organizer'])) {
|
||||
if (
|
||||
!hasAnyRole(await context.user.roles, [
|
||||
"admin",
|
||||
"embassador",
|
||||
"organizer",
|
||||
])
|
||||
) {
|
||||
throw Error("Cannot create event, please validate as organizer")
|
||||
}
|
||||
|
||||
|
@ -96,11 +98,12 @@ const resolvers: ResolverMap = {
|
|||
recurrence: input.time.recurrence,
|
||||
timeZone: input.time.timeZone,
|
||||
start: input.time.start,
|
||||
end: input.time.end
|
||||
end: input.time.end,
|
||||
}
|
||||
if (input.tagNames) {
|
||||
event.tags = getTags(input.tagNames)
|
||||
}
|
||||
event.meta = input.meta
|
||||
event.location = input.location
|
||||
|
||||
event.occurrences = Promise.resolve(event.getOccurrences())
|
||||
await event.save()
|
||||
return event
|
||||
|
@ -108,9 +111,9 @@ const resolvers: ResolverMap = {
|
|||
updateEvent: async (
|
||||
_,
|
||||
{ input }: GQL.IUpdateEventOnMutationArguments,
|
||||
context: Context,
|
||||
context: Context
|
||||
) => {
|
||||
const {id, ...fields} = input
|
||||
const { id, ...fields } = input
|
||||
|
||||
if (!context.user) {
|
||||
throw Error("not authenticated")
|
||||
|
@ -123,10 +126,16 @@ const resolvers: ResolverMap = {
|
|||
throw Error("No change detected")
|
||||
}
|
||||
if (input.time && !equals(input.time, event.time)) {
|
||||
console.log(`Event time changed from: ${JSON.stringify(event.time)} to: ${JSON.stringify(input.time)}`)
|
||||
console.log(
|
||||
`Event time changed from: ${JSON.stringify(
|
||||
event.time
|
||||
)} to: ${JSON.stringify(input.time)}`
|
||||
)
|
||||
event.time = input.time
|
||||
const existingOccurrences = await event.occurrences
|
||||
await Promise.all(existingOccurrences.map(occ => EventOccurrence.delete(occ.id)))
|
||||
await Promise.all(
|
||||
existingOccurrences.map(occ => EventOccurrence.delete(occ.id))
|
||||
)
|
||||
event.occurrences = Promise.resolve(event.getOccurrences())
|
||||
}
|
||||
if (input.infos) {
|
||||
|
@ -143,31 +152,27 @@ const resolvers: ResolverMap = {
|
|||
if (input.location) {
|
||||
event.location = input.location
|
||||
}
|
||||
if (input.meta) {
|
||||
event.meta = input.meta
|
||||
if (input.tagNames) {
|
||||
event.tags = getTags(input.tagNames)
|
||||
}
|
||||
if (input.location) {
|
||||
event.location = input.location
|
||||
}
|
||||
console.log(JSON.stringify(event,null,'\t'))
|
||||
console.log(JSON.stringify(event, null, "\t"))
|
||||
return event.save()
|
||||
},
|
||||
deleteEvent: async (
|
||||
_,
|
||||
id: string,
|
||||
context: Context,
|
||||
): Promise<User> => {
|
||||
deleteEvent: async (_, id: string, context: Context): Promise<User> => {
|
||||
const event = await Event.findOne(id)
|
||||
if ((await event.owner).id !== context.user.id) {
|
||||
throw Error("Only the owner can delete this event")
|
||||
}
|
||||
|
||||
console.log('will try to remove event now', event.id)
|
||||
console.log("will try to remove event now", event.id)
|
||||
const removeEventResult = await Event.remove(event)
|
||||
console.log('removeEventResult', JSON.stringify(removeEventResult))
|
||||
console.log("removeEventResult", JSON.stringify(removeEventResult))
|
||||
return context.user
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default resolvers
|
||||
|
|
|
@ -4,7 +4,8 @@ import {ConnectionOptions} from "typeorm"
|
|||
export const testConfig: ConnectionOptions = {
|
||||
...config,
|
||||
database: 'qpa-test',
|
||||
dropSchema: true
|
||||
dropSchema: true,
|
||||
synchronize: true
|
||||
}
|
||||
|
||||
export default testConfig
|
||||
|
|
|
@ -7,12 +7,25 @@ type User {
|
|||
roles: [UserRole!]
|
||||
}
|
||||
|
||||
type Tag {
|
||||
id: ID!
|
||||
name: String!
|
||||
translations: [Translations!]!
|
||||
}
|
||||
|
||||
type TagTranslation {
|
||||
language: String!
|
||||
text: String!
|
||||
}
|
||||
|
||||
type UserRole {
|
||||
user: User!
|
||||
type: RoleType!
|
||||
}
|
||||
|
||||
scalar Date
|
||||
scalar RoleType
|
||||
scalar Translations
|
||||
|
||||
type UserSession {
|
||||
hash: String!
|
||||
|
@ -49,11 +62,18 @@ type CalendarEvent {
|
|||
status: EventStatus!
|
||||
location: Location!
|
||||
occurrences: [EventOccurrence]
|
||||
meta: EventMeta
|
||||
tags: [EventTag]
|
||||
}
|
||||
|
||||
type EventMeta {
|
||||
tags: [String]!
|
||||
type EventTag {
|
||||
ID: ID!
|
||||
name: String!
|
||||
translations: [EventTagTranslation!]!
|
||||
}
|
||||
|
||||
type EventTagTranslation {
|
||||
language: String!
|
||||
text: String!
|
||||
}
|
||||
|
||||
type EventOccurrence {
|
||||
|
@ -132,15 +152,11 @@ input EventLocationInput {
|
|||
name: String
|
||||
}
|
||||
|
||||
input EventMetaInput {
|
||||
tags: [String]!
|
||||
}
|
||||
|
||||
input CreateEventInput {
|
||||
time: EventTimeInput!
|
||||
infos: [EventInformationInput]!
|
||||
location: EventLocationInput!
|
||||
meta: EventMetaInput!
|
||||
tagNames: [String!]!
|
||||
status: String!
|
||||
}
|
||||
|
||||
|
@ -149,7 +165,7 @@ input UpdateEventInput {
|
|||
time: EventTimeInput
|
||||
infos: [EventInformationInput!]
|
||||
location: EventLocationInput
|
||||
meta: EventMetaInput
|
||||
tagNames: [String!]!
|
||||
status: String
|
||||
}
|
||||
|
||||
|
@ -168,6 +184,23 @@ type Error {
|
|||
message: String!
|
||||
}
|
||||
|
||||
input CreateModifyEventTagTranslationInput {
|
||||
language: String!
|
||||
text: String!
|
||||
}
|
||||
|
||||
input CreateEventTagInput {
|
||||
name: String!
|
||||
translations: [CreateModifyEventTagTranslationInput!]!
|
||||
}
|
||||
|
||||
|
||||
input ModifyEventTagInput {
|
||||
id: ID!
|
||||
name: String!
|
||||
translations: [CreateModifyEventTagTranslationInput!]!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
# Auth
|
||||
signup(input: SignupInput!): [Error]
|
||||
|
@ -180,6 +213,10 @@ type Mutation {
|
|||
createEvent(input: CreateEventInput!): CalendarEvent
|
||||
updateEvent(input: UpdateEventInput!): CalendarEvent
|
||||
deleteEvent(id: ID!): User!
|
||||
|
||||
# Tags
|
||||
createEventTag(input: CreateEventTagInput!): EventTag
|
||||
modifyEventTag(input: ModifyEventTagInput!): EventTag
|
||||
}
|
||||
|
||||
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -5400,10 +5400,10 @@ type-is@^1.6.16, type-is@~1.6.17, type-is@~1.6.18:
|
|||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typeorm@^0.2.18:
|
||||
version "0.2.18"
|
||||
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.18.tgz#8ae1d21104117724af41ddc11035c40a705e1de8"
|
||||
integrity sha512-S553GwtG5ab268+VmaLCN7gKDqFPIzUw0eGMTobJ9yr0Np62Ojfx8j1Oa9bIeh5p7Pz1/kmGabAHoP1MYK05pA==
|
||||
typeorm@^0.2.20:
|
||||
version "0.2.20"
|
||||
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.20.tgz#efb60f2e55a7d08fc365f281ec2a71c87a9ebba5"
|
||||
integrity sha512-VxB+9qH8D+PM19MIx18Zs3Fqv/ZINnnQvUGmBEiLYDrB9etdSdamgSTCIhWdFNndeJ6ldH4jbD0Z6HWsepMPlA==
|
||||
dependencies:
|
||||
app-root-path "^2.0.1"
|
||||
buffer "^5.1.0"
|
||||
|
@ -5420,10 +5420,10 @@ typeorm@^0.2.18:
|
|||
yargonaut "^1.1.2"
|
||||
yargs "^13.2.1"
|
||||
|
||||
typescript@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
|
||||
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
|
||||
typescript@^3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
|
||||
integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.6.0"
|
||||
|
|
Loading…
Reference in New Issue