From dc3f608f2e664ea3e44046a88ee15168da548a1b Mon Sep 17 00:00:00 2001 From: Anthony Bernardi Date: Tue, 19 Jul 2022 20:16:37 -0400 Subject: [PATCH 1/3] #767 - feeling risky --- src/backend/functions/risks.ts | 96 ++++++++++++++++++++++++++++ src/utils/src/api-routes.ts | 9 ++- src/utils/src/index.ts | 1 + src/utils/src/types/project-types.ts | 2 + src/utils/src/types/risk-types.ts | 20 ++++++ src/utils/src/types/user-types.ts | 2 + 6 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/backend/functions/risks.ts create mode 100644 src/utils/src/types/risk-types.ts diff --git a/src/backend/functions/risks.ts b/src/backend/functions/risks.ts new file mode 100644 index 00000000..e26da94b --- /dev/null +++ b/src/backend/functions/risks.ts @@ -0,0 +1,96 @@ +/* + * This file is part of NER's PM Dashboard and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import { Handler } from '@netlify/functions'; +import { Prisma, PrismaClient, WBS_Element } from '@prisma/client'; +import { + ApiRoute, + ApiRouteFunction, + apiRoutes, + API_URL, + buildClientFailureResponse, + buildServerFailureResponse, + buildNotFoundResponse, + buildSuccessResponse, + routeMatcher, + User, + Risk, + WbsNumber +} from 'utils'; + +const prisma = new PrismaClient(); + +const wbsNumOf = (element: WBS_Element): WbsNumber => ({ + carNumber: element.carNumber, + projectNumber: element.projectNumber, + workPackageNumber: element.workPackageNumber +}); + +const riskQueryArgs = Prisma.validator()({ + include: { + project: { include: { wbsElement: true } }, + createdBy: true, + resolvedBy: true, + deletedBy: true + } +}); + +const riskTransformer = (risk: Prisma.RiskGetPayload): Risk => { + return { + id: risk.id, + project: { + id: risk.project.projectId, + name: risk.project.wbsElement.name, + wbsNum: wbsNumOf(risk.project.wbsElement) + }, + detail: risk.detail, + isResolved: risk.isResolved, + dateCreated: risk.dateCreated, + createdBy: { + userId: risk.createdBy.userId, + firstName: risk.createdBy.firstName, + lastName: risk.createdBy.lastName, + email: risk.createdBy.email, + role: risk.createdBy.role + } + }; +}; + +const getRisksForProject: ApiRouteFunction = async (params: { projectId: string }) => { + const projectId = parseInt(params.projectId); + const requestedProject = await prisma.project.findUnique({ + where: { projectId } + }); + + if (!requestedProject) return buildNotFoundResponse('project', `#${projectId}`); + + const risks = await prisma.risk.findMany({ + where: { projectId }, + ...riskQueryArgs + }); + + return buildSuccessResponse(risks.map(riskTransformer)); +}; + +// Define all valid routes for the endpoint +const routes: ApiRoute[] = [ + { + path: `${API_URL}${apiRoutes.RISKS_BY_PROJECT}`, + httpMethod: 'GET', + func: getRisksForProject + } +]; + +// Handler for incoming requests +const handler: Handler = async (event, context) => { + try { + return routeMatcher(routes, event, context); + } catch (error: any) { + console.error(error); + return buildServerFailureResponse(error.message); + } +}; + +export { handler }; diff --git a/src/utils/src/api-routes.ts b/src/utils/src/api-routes.ts index 9735966f..db8a10ea 100644 --- a/src/utils/src/api-routes.ts +++ b/src/utils/src/api-routes.ts @@ -27,6 +27,10 @@ const CHANGE_REQUESTS_NEW: string = `${CHANGE_REQUESTS}-new`; const CHANGE_REQUESTS_BY_ID: string = `${CHANGE_REQUESTS}/:id`; const CHANGE_REQUESTS_REVIEW: string = `${CHANGE_REQUESTS}-review`; +/**************** Risks Endpoint ****************/ +const RISKS: string = `/risks`; +const RISKS_BY_PROJECT: string = `${RISKS}/:projectId`; + export const apiRoutes = { USERS, USERS_BY_ID, @@ -44,5 +48,8 @@ export const apiRoutes = { CHANGE_REQUESTS, CHANGE_REQUESTS_NEW, CHANGE_REQUESTS_BY_ID, - CHANGE_REQUESTS_REVIEW + CHANGE_REQUESTS_REVIEW, + + RISKS, + RISKS_BY_PROJECT }; diff --git a/src/utils/src/index.ts b/src/utils/src/index.ts index c5b0ffea..b8694cd7 100644 --- a/src/utils/src/index.ts +++ b/src/utils/src/index.ts @@ -8,6 +8,7 @@ export * from './types/project-types'; export * from './types/user-types'; export * from './types/work-package-types'; export * from './types/api-utils-types'; +export * from './types/risk-types'; export * from './backend-supports/project-supports'; diff --git a/src/utils/src/types/project-types.ts b/src/utils/src/types/project-types.ts index b6e751d0..3bfd36af 100644 --- a/src/utils/src/types/project-types.ts +++ b/src/utils/src/types/project-types.ts @@ -47,6 +47,8 @@ export interface Project extends WbsElement { workPackages: WorkPackage[]; } +export type ProjectPreview = Pick; + export interface WorkPackage extends WbsElement { orderInProject: number; progress: number; diff --git a/src/utils/src/types/risk-types.ts b/src/utils/src/types/risk-types.ts new file mode 100644 index 00000000..4e0f70c5 --- /dev/null +++ b/src/utils/src/types/risk-types.ts @@ -0,0 +1,20 @@ +/* + * This file is part of NER's PM Dashboard and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import { ProjectPreview } from './project-types'; +import { UserPreview } from './user-types'; + +export interface Risk { + id: String; + project: ProjectPreview; + detail: string; + isResolved: boolean; + dateDeleted?: Date; + dateCreated: Date; + createdBy: UserPreview; + resolvedBy?: UserPreview; + resolvedAt?: Date; + deletedBy?: UserPreview; +} diff --git a/src/utils/src/types/user-types.ts b/src/utils/src/types/user-types.ts index fc1d20bb..dfc4ceaf 100644 --- a/src/utils/src/types/user-types.ts +++ b/src/utils/src/types/user-types.ts @@ -13,4 +13,6 @@ export interface User { role: Role; } +export type UserPreview = Pick; + export type Role = 'APP_ADMIN' | 'ADMIN' | 'LEADERSHIP' | 'MEMBER' | 'GUEST'; From 822c74672ec55de3fced42f36090252f616f86ab Mon Sep 17 00:00:00 2001 From: Anthony Bernardi Date: Tue, 19 Jul 2022 20:19:58 -0400 Subject: [PATCH 2/3] #767 - better transformer --- src/backend/functions/risks.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/backend/functions/risks.ts b/src/backend/functions/risks.ts index e26da94b..0412e9ee 100644 --- a/src/backend/functions/risks.ts +++ b/src/backend/functions/risks.ts @@ -17,7 +17,8 @@ import { routeMatcher, User, Risk, - WbsNumber + WbsNumber, + UserPreview } from 'utils'; const prisma = new PrismaClient(); @@ -37,6 +38,16 @@ const riskQueryArgs = Prisma.validator()({ } }); +const userTransformer = (user: Prisma.UserGetPayload): UserPreview => { + return { + userId: user.userId, + firstName: user.firstName, + lastName: user.lastName, + email: user.email, + role: user.role + }; +}; + const riskTransformer = (risk: Prisma.RiskGetPayload): Risk => { return { id: risk.id, @@ -47,14 +58,12 @@ const riskTransformer = (risk: Prisma.RiskGetPayload): Ris }, detail: risk.detail, isResolved: risk.isResolved, + dateDeleted: risk.dateDeleted ?? undefined, dateCreated: risk.dateCreated, - createdBy: { - userId: risk.createdBy.userId, - firstName: risk.createdBy.firstName, - lastName: risk.createdBy.lastName, - email: risk.createdBy.email, - role: risk.createdBy.role - } + createdBy: userTransformer(risk.createdBy), + resolvedBy: risk.resolvedBy ? userTransformer(risk.resolvedBy) : undefined, + resolvedAt: risk.resolvedAt ?? undefined, + deletedBy: risk.deletedBy ? userTransformer(risk.deletedBy) : undefined }; }; From 58fcf1a5382a26e83b0e25e2a18a65b98d478222 Mon Sep 17 00:00:00 2001 From: Anthony Bernardi Date: Tue, 19 Jul 2022 20:20:14 -0400 Subject: [PATCH 3/3] #767 - lint --- src/backend/functions/risks.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/functions/risks.ts b/src/backend/functions/risks.ts index 0412e9ee..526dd7a0 100644 --- a/src/backend/functions/risks.ts +++ b/src/backend/functions/risks.ts @@ -10,12 +10,10 @@ import { ApiRouteFunction, apiRoutes, API_URL, - buildClientFailureResponse, buildServerFailureResponse, buildNotFoundResponse, buildSuccessResponse, routeMatcher, - User, Risk, WbsNumber, UserPreview