Skip to content

Commit dcbe73d

Browse files
authored
Merge pull request #3464 from Northeastern-Electric-Racing/#3393-submission-guide
#3393 submission guide
2 parents 6375b6b + 5fa33f6 commit dcbe73d

37 files changed

Lines changed: 1476 additions & 124 deletions

src/backend/src/controllers/part-review.controllers.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,8 @@ export default class PartReviewController {
234234
static async deletePartTag(req: Request, res: Response, next: NextFunction) {
235235
try {
236236
const { partTagId } = req.params;
237-
const deletedPartTag = await PartReviewService.deletePartTag(
238-
partTagId,
239-
req.currentUser,
240-
req.organization.organizationId
241-
);
242-
res.status(200).send(deletedPartTag);
237+
await PartReviewService.deletePartTag(partTagId, req.currentUser, req.organization.organizationId);
238+
res.status(200).send({ message: 'Successfully deleted part tag' });
243239
} catch (error: unknown) {
244240
next(error);
245241
}
@@ -328,12 +324,8 @@ export default class PartReviewController {
328324
static async deleteCommonMistake(req: Request, res: Response, next: NextFunction) {
329325
try {
330326
const { commonMistakeId } = req.params;
331-
const commonMistake = await PartReviewService.deleteCommonMistake(
332-
commonMistakeId,
333-
req.currentUser,
334-
req.organization.organizationId
335-
);
336-
res.status(200).json(commonMistake);
327+
await PartReviewService.deleteCommonMistake(commonMistakeId, req.currentUser, req.organization.organizationId);
328+
res.status(200).json({ message: 'Successfully deleted common mistake' });
337329
} catch (error: unknown) {
338330
next(error);
339331
}
@@ -438,4 +430,29 @@ export default class PartReviewController {
438430
return next(error);
439431
}
440432
}
433+
434+
static async setPartReviewSampleImage(req: Request, res: Response, next: NextFunction) {
435+
try {
436+
if (!req.file) {
437+
throw new HttpException(400, 'Invalid or undefined image data');
438+
}
439+
440+
const updatedOrg = await PartReviewService.setPartReviewSampleImage(req.file, req.currentUser, req.organization);
441+
442+
res.status(200).json(updatedOrg);
443+
} catch (error: unknown) {
444+
next(error);
445+
}
446+
}
447+
448+
static async getPartReviewSampleImage(req: Request, res: Response, next: NextFunction) {
449+
try {
450+
const { organization } = req;
451+
452+
const partReviewSampleImageId = await PartReviewService.getPartReviewSampleImage(organization.organizationId);
453+
res.status(200).json(partReviewSampleImageId);
454+
} catch (error: unknown) {
455+
next(error);
456+
}
457+
}
441458
}

src/backend/src/routes/parts.routes.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,22 @@ partsRouter.get('/tags', PartReviewController.getAllPartTags);
6565
partsRouter.get('/faqs', PartReviewController.getAllPartReviewFAQS);
6666

6767
partsRouter.post(
68-
'/partTag/create',
68+
'/tag/create',
6969
nonEmptyString(body('name')),
7070
nonEmptyString(body('colorHexCode')),
7171
validateInputs,
7272
PartReviewController.createPartTag
7373
);
7474

7575
partsRouter.post(
76-
'/partTag/:partTagId/update',
76+
'/tag/:partTagId/update',
7777
nonEmptyString(body('name')),
7878
nonEmptyString(body('colorHexCode')),
7979
validateInputs,
8080
PartReviewController.updatePartTag
8181
);
8282

83-
partsRouter.post('/partTag/:partTagId/delete', PartReviewController.deletePartTag);
83+
partsRouter.post('/tag/:partTagId/delete', PartReviewController.deletePartTag);
8484

8585
partsRouter.post(
8686
'/faqs/create',
@@ -143,6 +143,13 @@ partsRouter.post(
143143
PartReviewController.updatePartReviewPopup
144144
);
145145

146+
partsRouter.post(
147+
'/partReviewSampleImage/update',
148+
upload.single('partReviewSampleImage'),
149+
PartReviewController.setPartReviewSampleImage
150+
);
151+
partsRouter.get('/partReviewSampleImage', PartReviewController.getPartReviewSampleImage);
152+
146153
partsRouter.post('/common-mistake/:commonMistakeId/delete', PartReviewController.deleteCommonMistake);
147154
partsRouter.post('/popup/:popupId/delete', PartReviewController.deletePartReviewPopup);
148155

src/backend/src/services/part-review.services.ts

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ export default class PartReviewService {
603603
* @returns the delted part tag
604604
* @throws if there are existing parts with this tag
605605
*/
606-
static async deletePartTag(partTagId: string, deleter: User, organizationId: string): Promise<PartTag> {
606+
static async deletePartTag(partTagId: string, deleter: User, organizationId: string) {
607607
if (!(await userHasPermission(deleter.userId, organizationId, isAdmin))) {
608608
throw new AccessDeniedAdminOnlyException('delete part review tag');
609609
}
@@ -620,23 +620,21 @@ export default class PartReviewService {
620620
}
621621

622622
if (
623-
!partTagWithParts.parts.every((part) => {
624-
return !part.dateDeleted;
623+
partTagWithParts.parts.some((part) => {
624+
return part.dateDeleted === null;
625625
})
626626
) {
627627
throw new HttpException(409, `Cannot delete part tag ${partTagId} because it has associated parts`);
628628
}
629629

630-
const deletedPartTag = await prisma.partTag.update({
630+
await prisma.partTag.update({
631631
where: {
632632
partTagId
633633
},
634634
data: {
635635
dateDeleted: new Date()
636636
}
637637
});
638-
639-
return deletedPartTag;
640638
}
641639

642640
/**
@@ -800,7 +798,7 @@ export default class PartReviewService {
800798
creator: User,
801799
organizationId: string
802800
): Promise<PartReviewCommonMistake> {
803-
if (!(await userHasPermission(creator.userId, organizationId, isAdmin))) {
801+
if (starred && !(await userHasPermission(creator.userId, organizationId, isAdmin))) {
804802
throw new AccessDeniedAdminOnlyException('create common mistake');
805803
}
806804

@@ -882,11 +880,7 @@ export default class PartReviewService {
882880
* @param organizationId the orgainization
883881
* @returns the deleted common mistake
884882
*/
885-
static async deleteCommonMistake(
886-
commonMistakeId: string,
887-
deleter: User,
888-
organizationId: string
889-
): Promise<PartReviewCommonMistake> {
883+
static async deleteCommonMistake(commonMistakeId: string, deleter: User, organizationId: string) {
890884
const commonMistake = await prisma.partReviewCommonMistake.findUnique({
891885
where: {
892886
partReviewCommonMistakeId: commonMistakeId
@@ -901,7 +895,7 @@ export default class PartReviewService {
901895
throw new AccessDeniedAdminOnlyException('delete common mistake');
902896
}
903897

904-
const deletedCommonMistake = await prisma.partReviewCommonMistake.update({
898+
await prisma.partReviewCommonMistake.update({
905899
where: {
906900
partReviewCommonMistakeId: commonMistakeId
907901
},
@@ -914,8 +908,6 @@ export default class PartReviewService {
914908
dateDeleted: new Date()
915909
}
916910
});
917-
918-
return partsReviewCommonMistakeTransformer(deletedCommonMistake);
919911
}
920912

921913
/**
@@ -1157,4 +1149,54 @@ export default class PartReviewService {
11571149
if (!fileData) throw new NotFoundException('File', fileId);
11581150
return fileData;
11591151
}
1152+
1153+
/**
1154+
* Sets the part review sample image for an organization, User must be admin
1155+
* @param image the image which will be uploaded and have its id stored in the org
1156+
* @param submitter the user submitting the sample image
1157+
* @param organization the organization who's sample image is being set
1158+
* @returns the updated organization
1159+
* @throws if the user is not an admin
1160+
*/
1161+
static async setPartReviewSampleImage(
1162+
image: Express.Multer.File,
1163+
submitter: User,
1164+
organization: Organization
1165+
): Promise<Organization> {
1166+
if (!(await userHasPermission(submitter.userId, organization.organizationId, isAdmin))) {
1167+
throw new AccessDeniedAdminOnlyException('update part review sample image');
1168+
}
1169+
1170+
const previewImageData = await uploadFile(image);
1171+
1172+
if (!previewImageData?.name) {
1173+
throw new HttpException(500, 'Image Name not found');
1174+
}
1175+
1176+
const updatedOrg = await prisma.organization.update({
1177+
where: { organizationId: organization.organizationId },
1178+
data: {
1179+
partReviewSampleImageId: previewImageData.id
1180+
}
1181+
});
1182+
1183+
return updatedOrg;
1184+
}
1185+
1186+
/**
1187+
* Gets the part review sample image of the organization
1188+
* @param organizationId the id of the organization
1189+
* @returns the id of the image
1190+
*/
1191+
static async getPartReviewSampleImage(organizationId: string): Promise<string | null> {
1192+
const organization = await prisma.organization.findUnique({
1193+
where: { organizationId }
1194+
});
1195+
1196+
if (!organization) {
1197+
throw new NotFoundException('Organization', organizationId);
1198+
}
1199+
1200+
return organization.partReviewSampleImageId;
1201+
}
11601202
}

0 commit comments

Comments
 (0)