From ee2aed9b1ce4de6196eb0c34c593c0a199e345dc Mon Sep 17 00:00:00 2001 From: Vin Bui <75594943+vinnie4k@users.noreply.github.com> Date: Mon, 25 Sep 2023 20:49:24 -0400 Subject: [PATCH] Create `editFlyer` mutation (#105) * Add `editFlyer` * Address PR comments --- src/middlewares/FlyerMiddleware.ts | 9 ++++-- src/repos/FlyerRepo.ts | 47 ++++++++++++++++++++++++++++++ src/resolvers/FlyerResolver.ts | 29 ++++++++++++++++++ src/tests/flyer.test.ts | 24 ++++++++++++++- 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/middlewares/FlyerMiddleware.ts b/src/middlewares/FlyerMiddleware.ts index 23fc64a..7201777 100644 --- a/src/middlewares/FlyerMiddleware.ts +++ b/src/middlewares/FlyerMiddleware.ts @@ -4,8 +4,13 @@ import utils from '../utils'; const FlyerUploadErrorInterceptor: MiddlewareFn = async ({ args, context }, next) => { try { - // Upload image to our upload service - context.imageURL = await utils.uploadImage(args.imageB64); + // Upload image to our upload service (if not null) + if (args.imageB64) { + context.imageURL = await utils.uploadImage(args.imageB64); + return await next(); + } + + // If null, move on return await next(); } catch (err) { throw new Error('An error occured while uploading the flyer image.'); diff --git a/src/repos/FlyerRepo.ts b/src/repos/FlyerRepo.ts index dc40f63..3be379c 100644 --- a/src/repos/FlyerRepo.ts +++ b/src/repos/FlyerRepo.ts @@ -261,9 +261,56 @@ const deleteFlyer = async (id: string): Promise => { return flyer; }; +/** + * Edit an existing flyer. + * + * @param {string} id the ID of the flyer to edit + * @param {string} categorySlug the slug for this flyer's category + * @param {string} endDate the end date for this flyer's event in UTC ISO8601 format + * @param {string} flyerURL the URL for this flyer when tapped + * @param {string} imageURL the URL representing this flyer's image + * @param {string} location the location for this flyer's event + * @param {string} startDate the start date for this flyer's event in UTC ISO8601 format + * @param {string} title the title for this flyer + * @returns the edited Flyer + */ +const editFlyer = async ( + id: string, + categorySlug: string = null, + endDate: string = null, + flyerURL: string = null, + imageURL: string = null, + location: string = null, + startDate: string = null, + title: string = null, +): Promise => { + // Fetch flyer given flyer ID + const flyer = await FlyerModel.findById(new ObjectId(id)); + + if (flyer) { + // Remove existing image from our servers (if not null) + if (imageURL) await utils.removeImage(flyer.imageURL); + + // Update flyer fields (if not nul) + if (categorySlug) flyer.categorySlug = categorySlug; + if (endDate) flyer.endDate = new Date(endDate); + if (flyerURL) flyer.flyerURL = flyerURL; + if (imageURL) flyer.imageURL = imageURL; + if (location) flyer.location = location; + if (startDate) flyer.startDate = new Date(startDate); + if (title) flyer.title = title; + + return flyer.save(); + } + + // Flyer not found + return flyer; +}; + export default { createFlyer, deleteFlyer, + editFlyer, getAllFlyers, getFlyerByID, getFlyersAfterDate, diff --git a/src/resolvers/FlyerResolver.ts b/src/resolvers/FlyerResolver.ts index 34312cb..d649f0e 100644 --- a/src/resolvers/FlyerResolver.ts +++ b/src/resolvers/FlyerResolver.ts @@ -202,6 +202,35 @@ class FlyerResolver { async deleteFlyer(@Arg('id') id: string) { return FlyerRepo.deleteFlyer(id); } + + @Mutation((_returns) => Flyer, { + description: `Edit with ID via given , , , , , , and . + <startDate> and <endDate> must be in UTC ISO8601 format (e.g. YYYY-mm-ddTHH:MM:ssZ). + <imageB64> must be a Base64 encrypted string without 'data:image/png;base64,' prepended`, + }) + @UseMiddleware(FlyerMiddleware.FlyerUploadErrorInterceptor) + async editFlyer( + @Arg('id') id: string, + @Arg('categorySlug', { nullable: true }) categorySlug: string, + @Arg('endDate', { nullable: true }) endDate: string, + @Arg('flyerURL', { nullable: true }) flyerURL: string, + @Arg('imageB64', { nullable: true }) imageB64: string, + @Arg('location', { nullable: true }) location: string, + @Arg('startDate', { nullable: true }) startDate: string, + @Arg('title', { nullable: true }) title: string, + @Ctx() ctx: Context, + ) { + return FlyerRepo.editFlyer( + id, + categorySlug, + endDate, + flyerURL, + ctx.imageURL, + location, + startDate, + title, + ); + } } export default FlyerResolver; diff --git a/src/tests/flyer.test.ts b/src/tests/flyer.test.ts index 95e5cf7..3c0bb13 100644 --- a/src/tests/flyer.test.ts +++ b/src/tests/flyer.test.ts @@ -294,4 +294,26 @@ describe('deleteFlyer tests', () => { const deleteFlyerResponse = await FlyerRepo.deleteFlyer('64811792f910705ca1a981f8'); expect(deleteFlyerResponse).toBeNull(); }); -}); \ No newline at end of file +}); + +describe('editFlyer tests', () => { + test('flyer with ID exists with changes', async () => { + const flyers = await FlyerFactory.create(2); + await FlyerModel.insertMany(flyers); + + const fetchedFlyers = await FlyerRepo.getAllFlyers(); + const firstFlyer = fetchedFlyers[0]; + + const randomSlug = Math.random().toString(); + const editFlyerResponse = await FlyerRepo.editFlyer(firstFlyer.id, randomSlug); + expect(editFlyerResponse.categorySlug).toStrictEqual(randomSlug); + }); + + test('flyer with ID does not exist', async () => { + const flyers = await FlyerFactory.create(2); + await FlyerModel.insertMany(flyers); + + const editFlyerResponse = await FlyerRepo.editFlyer('64811792f910705ca1a981f8'); + expect(editFlyerResponse).toBeNull(); + }); +});