diff --git a/api/src/models/project-update.ts b/api/src/models/project-update.ts index 7bbf2451f3..b8efb82c24 100644 --- a/api/src/models/project-update.ts +++ b/api/src/models/project-update.ts @@ -3,6 +3,25 @@ import { getLogger } from '../utils/logger'; const defaultLog = getLogger('models/project-update'); +export class PutIUCNData { + classificationDetails: IGetPutIUCN[]; + + constructor(obj?: any) { + defaultLog.debug({ label: 'PutIUCNData', message: 'params', obj }); + + this.classificationDetails = + (obj?.classificationDetails?.length && + obj.classificationDetails.map((item: any) => { + return { + classification: item.classification, + subClassification1: item.subClassification1, + subClassification2: item.subClassification2 + }; + })) || + []; + } +} + export class PutProjectData { name: string; type: number; @@ -114,7 +133,7 @@ export class GetPartnershipsData { } } -interface IGetIUCN { +interface IGetPutIUCN { classification: number; subClassification1: number; subClassification2: number; @@ -127,7 +146,7 @@ interface IGetIUCN { * @class GetIUCNClassificationData */ export class GetIUCNClassificationData { - classificationDetails: IGetIUCN[]; + classificationDetails: IGetPutIUCN[]; constructor(iucnClassificationData?: any[]) { defaultLog.debug({ diff --git a/api/src/paths/project/{projectId}/update.ts b/api/src/paths/project/{projectId}/update.ts index e1923ba935..abbeaa59d9 100644 --- a/api/src/paths/project/{projectId}/update.ts +++ b/api/src/paths/project/{projectId}/update.ts @@ -10,7 +10,8 @@ import { PutCoordinatorData, PutLocationData, PutObjectivesData, - PutProjectData + PutProjectData, + PutIUCNData } from '../../../models/project-update'; import { GetSpeciesData } from '../../../models/project-view-update'; import { @@ -24,6 +25,7 @@ import { getIndigenousPartnershipsByProjectSQL, getIUCNActionClassificationByProjectSQL } from '../../../queries/project/project-update-queries'; +import { deleteIUCNSQL } from '../../../queries/project/project-delete-queries'; import { getStakeholderPartnershipsByProjectSQL, getFocalSpeciesByProjectSQL, @@ -31,6 +33,7 @@ import { } from '../../../queries/project/project-view-update-queries'; import { getLogger } from '../../../utils/logger'; import { logRequest } from '../../../utils/path-utils'; +import { postProjectIUCNSQL } from '../../../queries/project/project-create-queries'; const defaultLog = getLogger('paths/project/{projectId}'); @@ -386,6 +389,10 @@ function updateProject(): RequestHandler { promises.push(updateProjectData(projectId, entities, connection)); } + if (entities?.iucn) { + promises.push(updateProjectIUCNData(projectId, entities, connection)); + } + await Promise.all(promises); await connection.commit(); @@ -400,6 +407,40 @@ function updateProject(): RequestHandler { }; } +export const updateProjectIUCNData = async ( + projectId: number, + entities: IUpdateProject, + connection: IDBConnection +): Promise => { + const putIUCNData = (entities?.iucn && new PutIUCNData(entities.iucn)) || null; + + const sqlDeleteStatement = deleteIUCNSQL(projectId); + + if (!sqlDeleteStatement) { + throw new HTTP400('Failed to build SQL statement'); + } + + const deleteResult = await connection.query(sqlDeleteStatement.text, sqlDeleteStatement.values); + + if (!deleteResult || !deleteResult.rowCount) { + throw new HTTP409('Failed to delete project IUCN data'); + } + + putIUCNData?.classificationDetails.forEach(async (iucnClassification) => { + const sqlInsertStatement = postProjectIUCNSQL(iucnClassification.subClassification2, projectId); + + if (!sqlInsertStatement) { + throw new HTTP400('Failed to build SQL statement'); + } + + const insertResult = await connection.query(sqlInsertStatement.text, sqlInsertStatement.values); + + if (!insertResult || !insertResult.rowCount) { + throw new HTTP409('Failed to insert project IUCN data'); + } + }); +}; + export const updateProjectData = async ( projectId: number, entities: IUpdateProject, diff --git a/api/src/queries/project/project-delete-queries.test.ts b/api/src/queries/project/project-delete-queries.test.ts new file mode 100644 index 0000000000..06eb98eac1 --- /dev/null +++ b/api/src/queries/project/project-delete-queries.test.ts @@ -0,0 +1,17 @@ +import { expect } from 'chai'; +import { describe } from 'mocha'; +import { deleteIUCNSQL } from './project-delete-queries'; + +describe('deleteIUCNSQL', () => { + it('returns null response when null projectId provided', () => { + const response = deleteIUCNSQL((null as unknown) as number); + + expect(response).to.be.null; + }); + + it('returns non null response when valid projectId provided', () => { + const response = deleteIUCNSQL(1); + + expect(response).to.not.be.null; + }); +}); diff --git a/api/src/queries/project/project-delete-queries.ts b/api/src/queries/project/project-delete-queries.ts new file mode 100644 index 0000000000..1d3ad38f48 --- /dev/null +++ b/api/src/queries/project/project-delete-queries.ts @@ -0,0 +1,40 @@ +import { SQL, SQLStatement } from 'sql-template-strings'; +import { getLogger } from '../../utils/logger'; + +const defaultLog = getLogger('queries/project/project-delete-queries'); + +/** + * SQL query to delete project IUCN rows. + * + * @param {projectId} projectId + * @returns {SQLStatement} sql query object + */ +export const deleteIUCNSQL = (projectId: number): SQLStatement | null => { + defaultLog.debug({ + label: 'deleteIUCNSQL', + message: 'params', + projectId + }); + + if (!projectId) { + return null; + } + + const sqlStatement: SQLStatement = SQL` + DELETE + from project_iucn_action_classification + WHERE + p_id = ${projectId} + RETURNING + *; + `; + + defaultLog.debug({ + label: 'deleteProjectSQL', + message: 'sql', + 'sqlStatement.text': sqlStatement.text, + 'sqlStatement.values': sqlStatement.values + }); + + return sqlStatement; +}; diff --git a/app/src/features/projects/components/ProjectIUCNForm.tsx b/app/src/features/projects/components/ProjectIUCNForm.tsx index 3511121e88..6d5cc16343 100644 --- a/app/src/features/projects/components/ProjectIUCNForm.tsx +++ b/app/src/features/projects/components/ProjectIUCNForm.tsx @@ -23,9 +23,8 @@ const useStyles = makeStyles((theme) => ({ overflowX: 'hidden' }, iucnInput: { - flex: '1 0 200px', - width: '33.333%', - maxWidth: '200px' + flex: '0 0 auto', + width: '33.333%' } })); @@ -98,8 +97,8 @@ const ProjectIUCNForm: React.FC = (props) => { return ( - - + + Classification = (props) => { {subClassification1Meta.error} - + Sub-classification