Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GraphQL Operations for Event #66

Closed
72 changes: 72 additions & 0 deletions server/schema/event/event.mutation.js
Original file line number Diff line number Diff line change
@@ -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({
rutajdash marked this conversation as resolved.
Show resolved Hide resolved
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,
},
},
});
60 changes: 60 additions & 0 deletions server/schema/event/event.query.js
Original file line number Diff line number Diff line change
@@ -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),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add description

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this resolver not yet done?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seach events isn't being done rn as @rutajdash told the approach we though of following was very expensive. After we decide on how to do it, it'll be done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a TODO or create an issue

},
},
});
156 changes: 156 additions & 0 deletions server/schema/event/event.resolver.js
Original file line number Diff line number Diff line change
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a check to see if an event of that ID exists
Only Future events should be updated

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) => {},
};
34 changes: 34 additions & 0 deletions server/schema/event/event.schema.js
Original file line number Diff line number Diff line change
@@ -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,
});
48 changes: 48 additions & 0 deletions server/schema/event/event.type.js
Original file line number Diff line number Diff line change
@@ -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 },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poster of type GraphQLID?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to what we've planned, we'll be having a media collection, and we would just refer to the id of that media where ever required.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'll be a an ID in database but should resolve to poster and its blurhash here, isn't it?

type: { type: GraphQLInt },
host: { type: GraphQLID },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we resolving the host from its ID?

url: { type: GraphQLString },
venue: { type: GraphQLString },
hits: { type: GraphQLInt },
createdAt: { type: GraphQLID },
createdBy: { type: GraphQLID },
updatedAt: { type: GraphQLDateTime },
updatedBy: { type: GraphQLID },
schemaVersion: { type: GraphQLInt },
Comment on lines +40 to +44
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these five needed in GraphQL?

}),
});

module.exports = EventType;
3 changes: 2 additions & 1 deletion server/schema/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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],
});