diff --git a/server/schema/event/event.mutation.js b/server/schema/event/event.mutation.js index e69de29b..ab1aea22 100644 --- a/server/schema/event/event.mutation.js +++ b/server/schema/event/event.mutation.js @@ -0,0 +1,72 @@ +/** + * @module app.schema.EventMutation + * @description Event Mutation + * + * @requires module:app.schema.scalars + * + * @version v1 + * @since 0.1.0 + */ + +const { + GraphQLObjectType, + GraphQLString, + // GraphQLSchema, + GraphQLID, + //GraphQLList, + // GraphQLBoolean, + GraphQLInt, + GraphQLNonNull, + // GraphQLDate, + // GraphQLTime, + GraphQLDateTime, + //GraphQLJSON, + //GraphQLJSONObject, +} = require('../scalars'); +const { createEvent, updateEvent, deleteEvent } = require('./event.resolver'); +const EventType = require('./event.type'); + +module.exports = new GraphQLObjectType({ + name: 'EventMutation', + fields: { + createEvent: { + description: 'Creates an event', + type: EventType, + args: { + name: { type: GraphQLNonNull(GraphQLString) }, + startTS: { type: GraphQLNonNull(GraphQLDateTime) }, + endTS: { type: GraphQLNonNull(GraphQLDateTime) }, + poster: { type: GraphQLID }, + type: { type: GraphQLInt, description: '0- Club, 1- Institute, 2- Fest, 3- Holiday' }, + host: { type: GraphQLID }, + url: { type: GraphQLString }, + venue: { type: GraphQLNonNull(GraphQLString) }, + }, + resolve: createEvent, + }, + updateEvent: { + description: 'Updates a pre-existing event', + type: EventType, + args: { + id: { type: GraphQLID }, + name: { type: GraphQLString }, + startTS: { type: GraphQLDateTime }, + endTS: { type: GraphQLDateTime }, + poster: { type: GraphQLID }, + type: { type: GraphQLInt }, + host: { type: GraphQLID }, + url: { type: GraphQLString }, + venue: { type: GraphQLString }, + }, + resolve: updateEvent, + }, + deleteEvent: { + description: 'Deletes a pre-existing event using mongo ID', + type: EventType, + args: { + id: { type: GraphQLID }, + }, + resolve: deleteEvent, + }, + }, +}); diff --git a/server/schema/event/event.query.js b/server/schema/event/event.query.js index e69de29b..164dc853 100644 --- a/server/schema/event/event.query.js +++ b/server/schema/event/event.query.js @@ -0,0 +1,60 @@ +/** + * @module app.schema.EventQuery + * @description Event Query + * + * @requires module:app.schema.scalars + * + * @version v1 + * @since 0.1.0 + */ + +const { + GraphQLObjectType, + GraphQLString, + // GraphQLSchema, + GraphQLID, + GraphQLList, + // GraphQLBoolean, + // GraphQLInt, + GraphQLNonNull, + // GraphQLDate, + // GraphQLTime, + // GraphQLDateTime, + // GraphQLJSON, + // GraphQLJSONObject, +} = require('../scalars'); +const EventType = require('./event.type'); +const { getEventByID, listEvents, searchEvents } = require('./event.resolver'); + +module.exports = new GraphQLObjectType({ + name: 'EventQuery', + fields: { + getEventByID: { + description: 'Retrieves a single event', + type: EventType, + args: { + id: { + type: GraphQLNonNull(GraphQLID), + description: "The event's mongo ID.", + }, + }, + resolve: getEventByID, + }, + listEvents: { + type: GraphQLList(EventType), + description: 'Retrieves a list of all the Events sorted from the lastest to the oldest.', + resolve: listEvents, + }, + searchEvents: { + description: 'Searches a event by keywords', + type: GraphQLList(EventType), + args: { + keywords: { + description: 'The search keywords', + type: new GraphQLNonNull(GraphQLString), + }, + }, + resolve: searchEvents, + }, + }, +}); diff --git a/server/schema/event/event.resolver.js b/server/schema/event/event.resolver.js index e69de29b..df79824f 100644 --- a/server/schema/event/event.resolver.js +++ b/server/schema/event/event.resolver.js @@ -0,0 +1,156 @@ +/** + * @module app.schema.EventResolver + * @description Event Resolver + * + * @requires module:app.schema.EventType + * @requires module:app.schema.EventModel + * @requires module:app.authorization + * @version v1 + * @since 0.1.0 + */ + +const { GraphQLError, APIError } = require('../../helpers/errorHandler'); +const { Model } = require('mongoose'); + +/** + * @type {Model} + */ +//const { HasPermission } = require('../../helpers/authorization'); +const EventModel = require('./event.model'); + +const DEF_LIMIT = 10; +const DEF_OFFSET = 0; +module.exports = { + getEventByID: async (parent, { id }, context, info, _EventModel = EventModel) => { + try { + const _event = await _EventModel.findById(id); + if (!_event) { + return APIError('NOT_FOUND'); + } + return _event; + } catch (e) { + if (e instanceof GraphQLError) { + return e; + } + return APIError(null, e); + } + }, + + createEvent: async ( + parent, + { name, startTS, endTS, poster, type, host, url, venue }, + context, + info, + _EventModel = EventModel + ) => { + try { + /** + * Checks if the start time of the event is before the end time of the + * event and if the event is scheduled after the current time. + */ + if (new Date(startTS) > new Date(endTS) || new Date(startTS) < Date.now()) { + return APIError('BAD_REQUEST'); + } + const _event = await _EventModel.create({ + name, + startTS, + endTS, + poster, + type, + host, + url, + venue, + }); + return _event; + } catch (e) { + if (e instanceof GraphQLError) { + return e; + } + return APIError(null, e); + } + }, + + updateEvent: async ( + parent, + { id, name, startTS, endTS, poster, type, host, url, venue }, + context, + info, + _EventModel = EventModel + ) => { + try { + if (!(await _EventModel.exists({ id }))) { + return APIError('NOT_FOUND'); + } + + //TODO: Resolver for search events to be written after the approach is finalised. + /** + * The getUpdateObject function returns an object that contains the + * key-value pairs of the event fields that are needed to be updated. + */ + const getUpdateObject = (propertiesObject) => { + /**propertiesObject + * Initialises an empty object that stores the updated fields. + */ + const updateObject = {}; + /** + * The propertiesObject(an object which contains the event fields that + * can be updated) is looped through and only the fields that are + * required to be updated are added to updateObject. + */ + for (key in propertiesObject) { + if (propertiesObject[key]) { + updateObject[key] = propertiesObject[key]; + } + } + + return updateObject; + }; + + const updateEvent = getUpdateObject({ name, startTS, endTS, poster, type, host, url, venue }); + const _event = await _EventModel.findByIdAndUpdate(id, updateEvent); + return _event; + } catch (e) { + if (e instanceof GraphQLError) { + return e; + } + return APIError(null, e); + } + }, + listEvents: async (parent, { limit = DEF_LIMIT, offset = DEF_OFFSET }, context, info, _EventModel = EventModel) => { + try { + /** + * _allEvents is returned when all the events including the old events are + * required in the descending order(mainly for admin pannel) while + * _upcomingEvents is returned when only the upcoming events are + * required in an ascending order (mainly for the client). + */ + const _events = await _EventModel.find().skip(offset).limit(limit); + const _allEvents = await _EventModel.find().skip(offset).limit(limit).sort({ startTS: 'desc' }); + + const _upcomingEvents = _events.filter((event) => Date.now() < new Date(event.endTS)); + + return _upcomingEvents; + } catch (e) { + if (e instanceof GraphQLError) { + return e; + } + return APIError(null, e); + } + }, + deleteEvent: async (parent, { id }, context, info, _EventModel = EventModel) => { + try { + if (!(await _EventModel.exists({ id }))) { + return APIError('NOT_FOUND'); + } + const _event = await _EventModel.findByIdAndDelete(id); + return _event; + } catch (e) { + if (e instanceof GraphQLError) { + return e; + } + return APIError(null, e); + } + }, + //TODO: Resolver for search events to be written after the approach is finalised. + searchEvents: async (parent, args, context, info, _EventModel = EventModel) => {}, +}; diff --git a/server/schema/event/event.schema.js b/server/schema/event/event.schema.js new file mode 100644 index 00000000..a8daa901 --- /dev/null +++ b/server/schema/event/event.schema.js @@ -0,0 +1,34 @@ +/** + * @module app.schema.Event + * @description Event Schema + * + * @requires module:app.schema.scalars + * @requires module:app.schema.Event Query + * @requires module:app.schema.Event Mutation + * + * @version v1 + * @since 0.1.0 + */ + +const { + // GraphQLObjectType, + // GraphQLString, + GraphQLSchema, + // GraphQLID, + // GraphQLList, + // GraphQLBoolean, + // GraphQLInt, + // GraphQLNonNull, + // GraphQLDate, + // GraphQLTime, + // GraphQLDateTime, + // GraphQLJSON, + // GraphQLJSONObject, +} = require('../scalars'); +const EventMutation = require('./event.mutation'); +const EventQuery = require('./event.query'); + +module.exports = new GraphQLSchema({ + query: EventQuery, + mutation: EventMutation, +}); diff --git a/server/schema/event/event.type.js b/server/schema/event/event.type.js index e69de29b..ed777408 100644 --- a/server/schema/event/event.type.js +++ b/server/schema/event/event.type.js @@ -0,0 +1,48 @@ +/** + * @module app.schema.EventType + * @description User Type + * + * @requires module:app.schema.scalars + * + * @version v1 + * @since 0.1.0 + */ + +const { + GraphQLObjectType, + GraphQLString, + //GraphQLSchema, + GraphQLID, + //GraphQLList, + // GraphQLBoolean, + GraphQLInt, + // GraphQLNonNull, + // GraphQLDate, + // GraphQLTime, + GraphQLDateTime, + // GraphQLJSON, + // GraphQLJSONObject, +} = require('../scalars'); + +const EventType = new GraphQLObjectType({ + name: 'Event', + fields: () => ({ + id: { type: GraphQLID }, + name: { type: GraphQLString }, + startTS: { type: GraphQLDateTime }, + endTS: { type: GraphQLDateTime }, + poster: { type: GraphQLID }, + type: { type: GraphQLInt }, + host: { type: GraphQLID }, + url: { type: GraphQLString }, + venue: { type: GraphQLString }, + hits: { type: GraphQLInt }, + createdAt: { type: GraphQLID }, + createdBy: { type: GraphQLID }, + updatedAt: { type: GraphQLDateTime }, + updatedBy: { type: GraphQLID }, + schemaVersion: { type: GraphQLInt }, + }), +}); + +module.exports = EventType; diff --git a/server/schema/index.js b/server/schema/index.js index c2e8c2ca..7946a480 100644 --- a/server/schema/index.js +++ b/server/schema/index.js @@ -13,7 +13,8 @@ const { mergeSchemas } = require('graphql-tools'); const UserSchema = require('./user/user.schema'); +const EventSchema = require('./event/event.schema'); module.exports = mergeSchemas({ - schemas: [UserSchema], + schemas: [UserSchema, EventSchema], });