From 1195c579cbb9662293325343f76e114880f5a956 Mon Sep 17 00:00:00 2001 From: Alliyya Mo Date: Sun, 25 Nov 2018 06:05:16 -0500 Subject: [PATCH] Mutation for edit events #21 --- api/src/migrations/002_create_sample_data.sql | 4 +- api/src/mutations/event.js | 161 +++++++++++++++++- api/src/mutations/index.js | 15 +- api/src/resolvers/event.js | 19 ++- api/src/schema.js | 2 + api/src/types/Event.js | 21 ++- 6 files changed, 211 insertions(+), 11 deletions(-) diff --git a/api/src/migrations/002_create_sample_data.sql b/api/src/migrations/002_create_sample_data.sql index 39a1c81..903c5b0 100644 --- a/api/src/migrations/002_create_sample_data.sql +++ b/api/src/migrations/002_create_sample_data.sql @@ -15,7 +15,7 @@ INSERT INTO doom_user (first_name, last_name, email, privacy_settings, password_ -- 3 events insert into Event (creator_id, name, start_time, end_time, capacity_type, max_capacity, current_capacity, website, location_link) values (3,'CUSEC',TIMESTAMP '2019-10-23 8:30:00+02', TIMESTAMP '2019-11-27 10:30:00+02', 'FCFS_E',6,0,'http://2018.cusec.net/','https://goo.gl/maps/w38KNq2BNLB2'); INSERT INTO Event (creator_id, name, start_time, end_time, capacity_type, max_capacity) VALUES (2,'Animefest',TIMESTAMP '2019-10-21 12:30:00+02', TIMESTAMP '2019-11-29 10:30:00+02', 'FCFS_P',3); -INSERT INTO Event (creator_id, name, start_time, end_time, capacity_type) VALUES (1,'Doomsday convention',TIMESTAMP '2018-10-30 1:00:00', TIMESTAMP '2018-11-02 10:30:00', 'FFA'); +INSERT INTO Event (creator_id, name, start_time, end_time, capacity_type) VALUES (1,'Doomsday convention',TIMESTAMP '2018-09-04 1:00:00', TIMESTAMP '2018-12-13 10:30:00', 'FFA'); INSERT INTO Event (creator_id, name, start_time, end_time, capacity_type,max_capacity) VALUES (6,'Avenger Meetup',TIMESTAMP '2019-05-03 10:30:00', TIMESTAMP '2019-11-24 10:30:00', 'FCFS_E',5); INSERT INTO Event (creator_id, name, start_time, end_time, capacity_type,max_capacity) VALUES (5,'Wizarding War',TIMESTAMP '2018-11-03 10:30:00', TIMESTAMP '2019-12-24 10:30:00', 'FCFS_P',10); @@ -31,7 +31,7 @@ insert into Event_Organizer (user_id, event_id) values (5,5); -INSERT INTO Seminar (event_id, name, start_time, end_time, capacity_type) VALUES (3,'Preparing for your doom',TIMESTAMP '2019-10-20 10:30:00+02', TIMESTAMP '2019-11-20 12:30:00+02', 'FFA'); +INSERT INTO Seminar (event_id, name, start_time, end_time, capacity_type) VALUES (3,'Preparing for your doom',TIMESTAMP '2018-09-10 10:30:00+02', TIMESTAMP '2018-10-22 12:30:00+02', 'FFA'); INSERT INTO Seminar (event_id, name, start_time, end_time, capacity_type, max_capacity) VALUES (2,'How to Weeb',TIMESTAMP '2019-10-22 12:30:00+02', TIMESTAMP '2019-11-22 13:30:00+02', 'FCFS_E',2); INSERT INTO Seminar (event_id, name, start_time, end_time, capacity_type, max_capacity) VALUES (1,'Hackathon',TIMESTAMP '2019-10-24 8:30:00+02', TIMESTAMP '2019-11-24 10:30:00+02', 'FCFS_P',6); INSERT INTO Seminar (event_id, name, start_time, end_time, capacity_type, max_capacity) VALUES (3,'Alpha Demo',TIMESTAMP '2018-10-31 14:50:00', TIMESTAMP '2018-10-31 15:00:00', 'FCFS_P',5); diff --git a/api/src/mutations/event.js b/api/src/mutations/event.js index 24d297a..39b47d6 100644 --- a/api/src/mutations/event.js +++ b/api/src/mutations/event.js @@ -1,5 +1,5 @@ const { db } = require("../db"); -const { queryEventByID } = require("../resolvers/event"); +const { queryEventByID, getEventByID } = require("../resolvers/event"); const { querySeminarsByEventID } = require("../resolvers/seminar"); const { alreadyAttendingEvent } = require("../resolvers/user"); const { @@ -102,6 +102,162 @@ async function insertNewEvent(eventInput) { }; } +/* +NOTE: Remember she'll always give me the whole object + +*/ +async function updateEvent(eventid, event) { + let { + name, + description, + location, + picture_path, + website, + location_link, + start_time, + end_time, + capacity_type, + max_capacity, + organizer_ids + } = event; + + let simpleEvent = { + name, + description, + location, + picture_path, + website, + location_link + }; + + if (Object.keys(simpleEvent).length === 0) return; + + let queryString = `UPDATE event SET`; + let first = 1; + + // Adding basic properties of simpleEvent to queryString + for (var key in simpleEvent) { + if (simpleEvent[key] !== null && simpleEvent[key] !== undefined) { + if (!first) queryString = `${queryString}, `; + first = 0; + queryString = `${queryString} ${key} = '${simpleEvent[key]}'`; + } + } + originalEvent = await getEventByID(eventid); + + // Validating the event start time with its end time + const event_start_time = new Date(start_time); + const event_end_time = new Date(end_time); + + if (event_start_time > event_end_time) { + console.log("Invalid Start Time: Event cannot start after Event ends"); + return new Error( + "Unable to create a Event: Invalid Start Time: Event cannot start after Event ends" + ); + } + // Validating the event start time/end time with its seminar's start/end + earliestStart = null; + latestEnd = null; + firstSem = null; + lastSem = null; + originalEvent["seminars"].forEach(seminar => { + if ( + earliestStart == null || + Date.parse(seminar.start_time) < earliestStart + ) { + earliestStart = seminar.start_time; + firstSem = seminar.name; + } + if (latestEnd == null || Date.parse(seminar.end_time) > latestEnd) { + latestEnd = seminar.end_time; + lastSem = seminar.name; + } + }); + + if (event_start_time > Date.parse(earliestStart)) { + return new Error( + "Invalid Event start date: First Seminar: ", + firstSem, + " starts at ", + earliestStart, + ", event must start prior" + ); + } + if (event_end_time < Date.parse(latestEnd)) { + return new Error( + "Invalid Event end date: Last Seminar: " + + lastSem + + " ends at " + + latestEnd + + "+ event must end after" + ); + } + if (max_capacity < originalEvent["current_capacity"]) { + return new Error("Max Capacity cannot be less than Current Capacity"); + } + queryString = `${queryString}, start_time = '${event_start_time.toISOString()}'`; + queryString = `${queryString}, end_time = '${event_end_time.toISOString()}'`; + queryString = `${queryString}, capacity_type = '${capacity_type}'`; + + if (capacity_type == "FFA") { + max_capacity = null; + queryString = `${queryString}, max_capacity = ${max_capacity}`; + } else { + queryString = `${queryString}, max_capacity = '${max_capacity}'`; + } + queryString = `${queryString} WHERE id = ? RETURNING *;`; + await db.raw(queryString, [eventid]); + // Check if there are people on the waitlist and updates accordingly + if ( + (max_capacity > originalEvent["max_capacity"] && + originalEvent["max_capacity"] == originalEvent["current_capacity"]) || + max_capacity == null + ) { + var top = await getWaitlistTop(eventid); + var newCapacity = await updateCurrentCapacity(eventid); + while ( + (top && newCapacity < max_capacity) || + (top && max_capacity == null) + ) { + if (top) { + await updateEventWaitlist(top, eventid, false); + await updateEventParticipation({ + userid: top, + participationType: "ATTENDING", + eventid: eventid + }); + } + top = await getWaitlistTop(eventid); + newCapacity = await updateCurrentCapacity(eventid); + } + } + await updateCurrentCapacity(eventid); + + var oldOrganizerIDs = []; + originalEvent["organizers"].forEach(organizer => { + oldOrganizerIDs.push(organizer.id); + }); + + // NOTE: revise this method to make use of set operations + // Simplest sol'n atm was remove all organizers then add them all back + // Cannot remove creator of event + for (var i = 0; i < oldOrganizerIDs.length; i++) { + const queryString = `delete from event_organizer where user_id = ? and event_id = ?; `; + if (originalEvent["creator_id"] != oldOrganizerIDs[i]) { + await db.raw(`${queryString}`, [oldOrganizerIDs[i], eventid]); + } + } + + for (var i = 0; i < organizer_ids.length; i++) { + const queryString = `INSERT INTO Event_Organizer + (user_id,event_id) VALUES (?, ?); `; + if (originalEvent["creator_id"] != organizer_ids[i]) { + await db.raw(`${queryString}`, [organizer_ids[i], eventid]); + } + } + return; +} + async function updateCurrentCapacity(eventid) { // Will recalculate and update the table's current capacity var queryString = `UPDATE "event" @@ -245,5 +401,6 @@ async function updateEventParticipation( module.exports = { insertNewEvent, updateEventParticipation, - updateEventWaitlist + updateEventWaitlist, + updateEvent }; diff --git a/api/src/mutations/index.js b/api/src/mutations/index.js index 4ff561d..fe754f8 100644 --- a/api/src/mutations/index.js +++ b/api/src/mutations/index.js @@ -1,7 +1,8 @@ const { insertNewEvent, updateEventParticipation, - updateEventWaitlist + updateEventWaitlist, + updateEvent } = require("./event"); const { insertNewSeminar, @@ -10,6 +11,7 @@ const { } = require("./seminar"); const { registerUser, editUserProfile } = require("./user"); const { insertNewAnnouncement } = require("./announcement"); +const { queryEventByID, getEventByID } = require("../resolvers/event"); const mutations = { Mutation: { @@ -146,6 +148,17 @@ const mutations = { console.log(err); return new Error("Unable to update user profile"); } + }, + async editEvent(_, args) { + const { eventID, event } = args; + try { + errors = await updateEvent(eventID, event); + if (errors) return errors; + return await getEventByID(eventID); + } catch (err) { + console.log(err); + return new Error("Unable to update event"); + } } } }; diff --git a/api/src/resolvers/event.js b/api/src/resolvers/event.js index c6ce84e..3a2bfc8 100644 --- a/api/src/resolvers/event.js +++ b/api/src/resolvers/event.js @@ -1,5 +1,7 @@ const { db } = require("../db"); - +const { querySeminarsByEventID } = require("./seminar"); +const { queryAnnouncementByTypeID } = require("./announcement"); +const { queryOrganizerByTypeID } = require("./searchResults"); async function queryEventByID(id) { return await db .raw("select * from Event where id = ?;", [id]) @@ -12,4 +14,17 @@ async function queryEventByID(id) { }); } -module.exports = { queryEventByID }; +async function getEventByID(id) { + try { + const newEvent = await queryEventByID(id); + newEvent.announcements = await queryAnnouncementByTypeID(id, "Event"); + newEvent.organizers = await queryOrganizerByTypeID(id, "Event"); + newEvent.seminars = await querySeminarsByEventID(id); + return newEvent; + } catch (err) { + console.log(err); + return new Error("Unable to retrieve event"); + } +} + +module.exports = { queryEventByID, getEventByID }; diff --git a/api/src/schema.js b/api/src/schema.js index 41b8561..a876cae 100644 --- a/api/src/schema.js +++ b/api/src/schema.js @@ -63,6 +63,8 @@ const SchemaDefinition = ` createSeminarAnnouncement(announcement: AnnouncementInput!): Announcement! editProfile(userID: Int!, user: UserUpdateInput!): User! + + editEvent(eventID: Int!, event: EventUpdateInput!): Event! } `; diff --git a/api/src/types/Event.js b/api/src/types/Event.js index 8260e9e..52a94ab 100644 --- a/api/src/types/Event.js +++ b/api/src/types/Event.js @@ -19,7 +19,6 @@ const Event = ` # still need to add photo picture_path: String - #Testing attaching announcements to an event announcements: [Announcement!] organizers: [User!] seminars: [Seminar!] @@ -47,15 +46,29 @@ const Event = ` website: String } + input EventUpdateInput { + name: String + description: String + + start_time: String + end_time: String + + capacity_type: capacity_type + max_capacity: Int + + organizer_ids: [Int!] + + location: String + location_link: String + picture_path: String + website: String + } input EventParticipationInput { userid: Int! eventid: Int! participationType: participation_type! - } - - `; module.exports = { Event };