import { schema } from 'nexus' import { Event as EventClient } from 'nexus-plugin-prisma/client' import * as SegmentController from '../../controllers/segment' import moment from 'moment' import * as Auth from '../../utils/auth' import GeneralUtils from '../../utils/general' import { logger } from '../../utils/logger' import { send as sendNotifications } from '../../utils/notification' const EVENT_FIELDS = { id: true, start: true, end: true, title: true, description: true, isForManagingCompany: true, type: true, segments: { select: { id: true, }, }, project: { select: { id: true, name: true, active: true, users: { select: { id: true, }, }, managingCompany: { select: { id: true, shortName: true, longName: true, email: true, phone: { select: { number: true, }, }, address: { select: { address1: true, country: true, zip: true, city: true, apartmentNumber: true, state: true, }, }, logo: { select: { url: true, }, }, }, }, }, }, } export const Event = schema.objectType({ name: 'Event', definition(t) { t.model.id() t.model.createdAt() t.model.updatedAt() t.model.type() t.model.title() t.model.description() t.model.repeat() t.model.location() t.model.entryPrice() t.model.hasAttendees() t.model.requiredNumberOfParticipants() t.model.start() t.model.end() t.model.isForManagingCompany() t.model.hasAlertReminder() t.model.firstReminderSentAt() t.model.secondReminderSentAt() t.model.assemblyDate() t.model.assemblyLocation() t.model.assemblyTime() t.model.address() t.model.coverImage() t.model.project() t.model.notifications() t.model.seenBy() // t.model.//()Event_A // t.model.//()Event_B t.model.segments() t.model.cantGoUsers() t.model.goingUsers() t.model.interestedUsers() }, }) export const EventMutation = schema.extendType({ type: 'Mutation', definition: (t) => { t.crud.createOneEvent({ alias: 'createEvent' }) t.crud.updateOneEvent({ alias: 'updateEvent' }) t.crud.deleteOneEvent({ alias: 'deleteEvent' }) t.field('createEvent', { type: 'Event', args: { data: schema.arg({ type: 'EventCreateInput' }) }, resolve: async (parent, { data }, ctx: NexusContext) => { const createdEvent = await ctx.prisma.event.create({ data: data, select: { id: true, start: true, end: true, title: true, description: true, isForManagingCompany: true, type: true, segments: { select: { id: true, }, }, project: { select: { id: true, name: true, active: true, users: { select: { id: true, }, }, managingCompany: { select: { id: true, shortName: true, longName: true, email: true, phone: { select: { number: true, }, }, address: { select: { address1: true, country: true, zip: true, city: true, apartmentNumber: true, state: true, }, }, logo: { select: { url: true, }, }, }, }, }, }, }, }) // VERIFY with thierry if this is OK if (!createdEvent.isForManagingCompany && createdEvent.type !== 'PRIVATE') { try { // Now that we have segment. We might want to send to post to certain people only const usersThatWillReceiveTheNotification = createdEvent.segments.length > 0 ? await SegmentController.getUsersForSegments(createdEvent.segments) : createdEvent.project.users await sendNotifications({ projectId: createdEvent.project.id, users: usersThatWillReceiveTheNotification, title: createdEvent.title, message: `${ createdEvent.description ? `${GeneralUtils.removeRichTextareaLineBreak(createdEvent.description)}\n\n` : '' }${moment(createdEvent.start).format('LL')}${ createdEvent.end ? ` - ${moment(createdEvent.end).format('LL')}` : '' }\n\nGet more details about it in the Walter app.`, messageFr: `${ createdEvent.description ? `${createdEvent.description}\n\n` : '' }${moment(createdEvent.start).locale('fr').format('LL')}${ createdEvent.end ? ` - ${moment(createdEvent.end).locale('fr').format('LL')}` : '' }\n\nConsultez les détails de celle-ci dans l'application Walter.`, type: 'NEW_EVENT', data: { id: createdEvent.id, }, }) } catch (error) { logger.error(error) } } return ctx.prisma.event.findOne({ where: { id: createdEvent.id } }) }, }) t.field('updateEvent', { type: 'Event', args: { data: schema.arg({ type: 'EventUpdateInput' }), where: schema.arg({ type: 'EventWhereUniqueInput' }), }, resolve: async (parent, { where, data }, ctx: NexusContext) => { const oldEvent = await ctx.prisma.event.findOne({ where, select: EVENT_FIELDS }) const updatedEvent = await ctx.prisma.event.update({ where, data, select: EVENT_FIELDS, }) // NOTIFICATIONS if (!updatedEvent.isForManagingCompany && updatedEvent.type !== 'PRIVATE') { const differenceBetweenOldAndUpdatedEvent = GeneralUtils.difference( oldEvent, updatedEvent ) // Only send notification if there's a difference if (Object.keys(differenceBetweenOldAndUpdatedEvent).length > 0) { // Now that we have segment. We might want to send to post to certain people only const usersThatWillReceiveTheNotification = updatedEvent.segments.length > 0 ? await SegmentController.getUsersForSegments(updatedEvent.segments) : updatedEvent.project.users await sendNotifications({ projectId: updatedEvent.project.id, users: usersThatWillReceiveTheNotification, title: 'Event updated', titleFr: 'Événement mis à jour', subtitle: updatedEvent.title, // prettier-ignore message: `${updatedEvent.description ? `${updatedEvent.description}\n\n` : ''}${moment(updatedEvent.start).format('LL')}${updatedEvent.end ? ` - ${moment(updatedEvent.end).format('LL')}` : ''}\n\nGet more details about it in the Walter app.`, // prettier-ignore messageFr: `${updatedEvent.description ? `${updatedEvent.description}\n\n` : ''}${moment(updatedEvent.start).locale('fr').format('LL')}${updatedEvent.end ? ` - ${moment(updatedEvent.end).locale('fr').format('LL')}` : ''}\n\nConsultez les détails de celle-ci dans l'application Walter.`, type: 'UPDATE_EVENT', data: { id: updatedEvent.id, }, }) } } return (updatedEvent as unknown) as EventClient }, }) }, }) export const EventQuery = schema.extendType({ type: 'Query', definition(t) { t.crud.event() t.crud.events({ filtering: true, ordering: true }) t.field('events', { list: true, type: 'Event', args: { where: schema.arg({ type: 'EventWhereInput' }) }, resolve: async (parent, args, ctx: NexusContext) => { const userId = Auth.getUserId(ctx) const user = await ctx.prisma.user.findOne({ where: { id: userId }, select: { id: true, role: true, }, }) // Make sure to not return events that are segmented to the wrong people if (user.role === 'RESIDENT') { const eventsWithData = await ctx.prisma.event.findMany({ where: args.where, select: { id: true, type: true, isForManagingCompany: true, segments: { select: { id: true, }, }, }, }) const validEvents = await Promise.all( eventsWithData .filter((event) => !event.isForManagingCompany && event.type !== 'PRIVATE') .map(async (event) => !event.segments.length || (await SegmentController.getUsersForSegments(event.segments)).some( (u) => u.id === user.id ) ? event : null ) ) return ctx.prisma.event.findMany({ where: { ...args.where, id: { in: validEvents.filter(Boolean).map((event: Partial) => event.id), }, }, }) } return ctx.prisma.event.findMany({ where: { ...args.where } }) }, }) }, })