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

#3013 create/edit checklist modal #3092

Merged
17 changes: 4 additions & 13 deletions src/backend/src/controllers/onboarding.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ export default class OnboardingController {
}
}

static async getGeneralChecklists(req: Request, res: Response, next: NextFunction) {
try {
const generalChecklists = await OnboardingServices.getGeneralChecklists(req.organization);
res.status(200).json(generalChecklists);
} catch (error: unknown) {
return next(error);
}
}

static async getCheckedChecklists(req: Request, res: Response, next: NextFunction) {
try {
const checkedChecklists = await OnboardingServices.getCheckedChecklists(req.currentUser, req.organization);
Expand All @@ -46,11 +37,11 @@ export default class OnboardingController {
req.currentUser,
name,
descriptions,
isOptional,
teamId,
teamTypeId,
parentChecklistId,
req.organization
req.organization,
isOptional
);
res.status(200).json(checklist);
} catch (error: unknown) {
Expand All @@ -67,11 +58,11 @@ export default class OnboardingController {
checklistId,
name,
descriptions,
isOptional,
teamId,
teamTypeId,
parentChecklistId,
req.organization
req.organization,
isOptional
);
res.status(200).json(checklist);
} catch (error: unknown) {
Expand Down
32 changes: 16 additions & 16 deletions src/backend/src/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1947,88 +1947,88 @@ const performSeed: () => Promise<void> = async () => {
[
'Slack is our primary method of communication outside of meetings and the shop. To join, you must use your @northeastern.edu email (No personal emails!). We do not send email reminders for meetings, so you will need to stay in the loop via Slack and Google Calandar.'
],
false,
null,
null,
null,
ner
ner,
false
);

await OnboardingServices.createChecklist(
batman,
'Put your name and pronouns',
[],
false,
null,
null,
joinSlackChecklist.checklistId,
ner
ner,
false
);

await OnboardingServices.createChecklist(
batman,
'Include your team and/or subteam',
[],
false,
null,
null,
joinSlackChecklist.checklistId,
ner
ner,
false
);

await OnboardingServices.createChecklist(
batman,
'Include your major and/or year',
[],
false,
null,
null,
joinSlackChecklist.checklistId,
ner
ner,
true
);

await OnboardingServices.createChecklist(
batman,
'Turn on notifications',
[],
false,
null,
null,
joinSlackChecklist.checklistId,
ner
ner,
false
);

const engageChecklist = await OnboardingServices.createChecklist(
batman,
'Engage',
['Join NER on engage. This is what Northeastern uses to keep track of our roster'],
false,
null,
null,
null,
ner
ner,
false
);

const learnGitChecklist = await OnboardingServices.createChecklist(
batman,
'Learn how to use git',
['Go online and learn how to use git'],
false,
null,
software.teamTypeId,
null,
ner
ner,
false
);

await OnboardingServices.createChecklist(
batman,
'Create your first project',
[],
false,
null,
software.teamTypeId,
learnGitChecklist.checklistId,
ner
ner,
false
);
};

Expand Down
6 changes: 2 additions & 4 deletions src/backend/src/routes/onboarding.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ const onboardingRouter = express.Router();
/* Checklists Section */
onboardingRouter.get('/checklists', OnboardingController.getAllChecklists);

onboardingRouter.get('/checklists/general', OnboardingController.getGeneralChecklists);

onboardingRouter.get('/checklists/checked', OnboardingController.getCheckedChecklists);

onboardingRouter.get('/checklists/usersChecklists', OnboardingController.getUsersChecklists);
Expand All @@ -19,10 +17,10 @@ onboardingRouter.post(
nonEmptyString(body('name')),
body('descriptions').isArray(),
nonEmptyString(body('descriptions.*')),
nonEmptyString(body('isOptional').isBoolean()),
nonEmptyString(body('teamId').optional()),
nonEmptyString(body('teamTypeId').optional()),
nonEmptyString(body('parentChecklistId').optional()),
body('isOptional').isBoolean().optional(),
validateInputs,
OnboardingController.createChecklist
);
Expand All @@ -32,10 +30,10 @@ onboardingRouter.post(
nonEmptyString(body('name')),
body('descriptions').isArray(),
nonEmptyString(body('descriptions.*')),
nonEmptyString(body('isOptional').isBoolean()),
nonEmptyString(body('teamId').optional()),
nonEmptyString(body('teamTypeId').optional()),
nonEmptyString(body('parentChecklistId').optional()),
body('isOptional').isBoolean().optional(),
validateInputs,
OnboardingController.editChecklist
);
Expand Down
73 changes: 26 additions & 47 deletions src/backend/src/services/onboarding.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { AccessDeniedAdminOnlyException, DeletedException, HttpException, NotFou
import { downloadImageFile } from '../utils/google-integration.utils';

export default class OnboardingServices {
/* Checklist section */

/**
* gets all checklists for the given organization
* @param organization the organization of the checklists
Expand All @@ -16,31 +14,12 @@ export default class OnboardingServices {
static async getAllChecklists(organization: Organization) {
const allChecklists = await prisma.checklist.findMany({
where: { organizationId: organization.organizationId, dateDeleted: null, parentChecklistId: null },
include: { subtasks: true, teamType: true, usersChecked: true }
include: { subtasks: { where: { dateDeleted: null } }, teamType: true, usersChecked: true }
});

return allChecklists;
}

/**
* Gets all the general checklists for the given organization
* @param organization the organization of the checklists
* @returns all the general checklists for the given organization
*/
static async getGeneralChecklists(organization: Organization) {
const generalChecklists = await prisma.checklist.findMany({
where: {
organizationId: organization.organizationId,
teamId: null,
teamTypeId: null,
dateDeleted: null,
parentChecklistId: null
},
include: { subtasks: true, teamType: true, usersChecked: true }
});
return generalChecklists;
}

/**
* Gets all the checklists that this user has checked
* @param user the user who has checked the checklists
Expand All @@ -50,7 +29,7 @@ export default class OnboardingServices {
static async getCheckedChecklists(user: User, organization: Organization) {
const allChecklists = await prisma.checklist.findMany({
where: { organizationId: organization.organizationId, dateDeleted: null },
include: { subtasks: true, usersChecked: true }
include: { subtasks: { where: { dateDeleted: null } }, usersChecked: true }
});

const checkedChecklists = allChecklists.filter((checklist) =>
Expand Down Expand Up @@ -84,7 +63,7 @@ export default class OnboardingServices {
teamTypeId: { in: teamTypeIds },
parentChecklistId: null
},
include: { subtasks: true, teamType: true }
include: { subtasks: { where: { dateDeleted: null } }, teamType: true }
});

const teamChecklists = await prisma.checklist.findMany({
Expand All @@ -94,7 +73,7 @@ export default class OnboardingServices {
teamId: { in: teamIds },
parentChecklistId: null
},
include: { subtasks: true, team: true }
include: { subtasks: { where: { dateDeleted: null } }, team: true }
});

return [...teamTypeChecklists, ...teamChecklists];
Expand All @@ -115,11 +94,11 @@ export default class OnboardingServices {
creator: User,
name: string,
descriptions: string[],
isOptional: boolean,
teamId: string | null,
teamTypeId: string | null,
parentChecklistId: string | null,
organization: Organization
organization: Organization,
isOptional?: boolean
) {
if (!(await userHasPermission(creator.userId, organization.organizationId, isAdmin))) {
throw new AccessDeniedAdminOnlyException('create a checklist');
Expand Down Expand Up @@ -161,8 +140,11 @@ export default class OnboardingServices {
throw new NotFoundException('Checklist', parentChecklistId);
}

if (parentChecklist.teamId !== teamId || parentChecklist.teamTypeId !== teamTypeId) {
throw new HttpException(400, 'Parent checklist must have the same teamId or teamTypeId');
if (
(parentChecklist.teamId ?? null) !== (teamId ?? null) ||
(parentChecklist.teamTypeId ?? null) !== (teamTypeId ?? null)
) {
throw new HttpException(400, 'Parent checklist must have the same teamId and teamTypeId');
}

if (parentChecklist.dateDeleted) {
Expand Down Expand Up @@ -203,11 +185,11 @@ export default class OnboardingServices {
checklistId: string,
name: string,
descriptions: string[],
isOptional: boolean,
teamId: string | null,
teamTypeId: string | null,
parentChecklistId: string | null,
organization: Organization
organization: Organization,
isOptional?: boolean
) {
if (!(await userHasPermission(editor.userId, organization.organizationId, isAdmin))) {
throw new AccessDeniedAdminOnlyException('edit a checklist');
Expand All @@ -218,19 +200,12 @@ export default class OnboardingServices {
}

if (!teamId && !teamTypeId) {
const generalChecklist = await prisma.checklist.findFirst({
where: { organizationId: organization.organizationId, teamId: null, teamTypeId: null, dateDeleted: null }
});

if (generalChecklist && parentChecklistId) {
if (generalChecklist.checklistId !== parentChecklistId) {
throw new HttpException(400, 'Parent checklist must be the general checklist');
if (parentChecklistId) {
const parentChecklist = await prisma.checklist.findFirst({ where: { checklistId: parentChecklistId } });
if (parentChecklist?.teamId || parentChecklist?.teamTypeId) {
throw new HttpException(400, 'Parent checklist must also be a general checklist');
}
}

if (generalChecklist && !parentChecklistId) {
throw new HttpException(400, 'General checklist already exists');
}
}

if (teamId) {
Expand All @@ -256,12 +231,15 @@ export default class OnboardingServices {
throw new NotFoundException('Checklist', parentChecklistId);
}

if (parentChecklist.dateDeleted) {
throw new DeletedException('Checklist', parentChecklistId);
if (
(parentChecklist.teamId ?? null) !== (teamId ?? null) ||
(parentChecklist.teamTypeId ?? null) !== (teamTypeId ?? null)
) {
throw new HttpException(400, 'Parent checklist must have the same teamId and teamTypeId');
}

if (parentChecklist.teamId !== teamId || parentChecklist.teamTypeId !== teamTypeId) {
throw new HttpException(400, 'Parent checklist must have the same teamId or teamTypeId');
if (parentChecklist.dateDeleted) {
throw new DeletedException('Checklist', parentChecklistId);
}
}

Expand All @@ -275,7 +253,7 @@ export default class OnboardingServices {
throw new DeletedException('Checklist', checklistId);
}

const editedChecklist: Checklist = await prisma.checklist.update({
const editedChecklist = await prisma.checklist.update({
where: { checklistId },
data: {
name,
Expand Down Expand Up @@ -424,6 +402,7 @@ export default class OnboardingServices {
}
}
}

const updatedChecklist = await prisma.checklist.findUnique({
where: { checklistId },
include: { usersChecked: true }
Expand Down
Loading
Loading