Skip to content

Commit

Permalink
cherry-pick
Browse files Browse the repository at this point in the history
wip

wip: create location and date sections on form

wip: style subcount form

wip: adding measurements to subcounts

add dual autocomplete

subcount form

subcount table on create observation page

fix measurement search

show measurement options in subcount table on create observation page

wip: formik validation

add subcount sign placeholder to create request

wip: environments incorrectly formatted in handlesubmit

fix incorrect key

fix environments on create observations page

fix measurement interfaces

SIMSBIOHUB-659: Add Pagination to System Alerts on Admin Page (#1459)

Add Pagination to System Alerts on Admin Page

---------

Co-authored-by: Nick Phura <[email protected]>

Update CSV Error Import Dialog Styling (#1456)

- update csv import error dialog
- replace failure snackbar & add frontend pagination to csv import errors

BugFix: Fix Type for Capture Attachments (#1460)

- modifying critter index file

---------

Co-authored-by: Macgregor Aubertin-Young <[email protected]>
Co-authored-by: Macgregor Aubertin-Young <[email protected]>

BugFix: Method Attributes SQL (#1462)

- fix sql

Added DualAutocompleteUnitField.tsx to help reduce the size of the DualAutocompleteField.tsx.
Renamed some of the dual autocomplete field props, just to make them more consistent/predictable.
Fixed missing props in create/edit technique vantages (missing category data type prop).
Add formik snackbar error component to observation form.
Addressed a few react missing dependency warnings.

Update missed jsdoc comments.

Update missed jsdoc comments 2.

WIP: Add create observation sampling fields.

Working sampling fields.

Enhancements to sampling fields
  • Loading branch information
mauberti-bc authored and NickPhura committed Jan 21, 2025
1 parent b3e073e commit b7317db
Show file tree
Hide file tree
Showing 36 changed files with 2,855 additions and 255 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,25 @@ export const PUT: Operation = [
putObservations()
];

export const POST: Operation = [
authorizeRequestHandler((req) => {
return {
or: [
{
validProjectPermissions: [PROJECT_PERMISSION.COORDINATOR, PROJECT_PERMISSION.COLLABORATOR],
surveyId: Number(req.params.surveyId),
discriminator: 'ProjectPermission'
},
{
validSystemRoles: [SYSTEM_ROLE.DATA_ADMINISTRATOR],
discriminator: 'SystemRole'
}
]
};
}),
postObservations()
];

GET.apiDoc = {
description: 'Get all observations for the survey.',
tags: ['observation'],
Expand Down Expand Up @@ -360,6 +379,228 @@ PUT.apiDoc = {
}
};

POST.apiDoc = {
description: 'Insert/update/delete observations for the survey.',
tags: ['observation'],
security: [
{
Bearer: []
}
],
parameters: [
{
in: 'path',
name: 'projectId',
required: true
},
{
in: 'path',
name: 'surveyId',
required: true
}
],
requestBody: {
description: 'Survey observation record data',
required: true,
content: {
'application/json': {
schema: {
description: 'A single survey observation record.',
type: 'object',
additionalProperties: false,
required: ['standardColumns', 'subcounts'],
properties: {
standardColumns: {
description: 'Standard column data for an observation record.',
type: 'object',
additionalProperties: false,
required: ['itis_tsn'],
properties: {
survey_observation_id: {
type: 'integer',
minimum: 1,
description: 'Primary key of the observation record',
nullable: true
},
itis_tsn: {
type: 'integer'
},
itis_scientific_name: {
type: 'string',
nullable: true
},
survey_sample_site_id: {
type: 'integer',
minimum: 1,
nullable: true
},
survey_sample_method_id: {
type: 'integer',
minimum: 1,
nullable: true
},
survey_sample_period_id: {
type: 'integer',
minimum: 1,
nullable: true
},
count: {
type: 'integer',
description: "The observation record's count.",
nullable: true
},
latitude: {
type: 'number',
nullable: true
},
longitude: {
type: 'number',
nullable: true
},
observation_date: {
type: 'string',
nullable: true
},
observation_time: {
type: 'string',
nullable: true
},
revision_count: {
type: 'integer',
minimum: 0
}
}
},
subcounts: {
description: 'An array of observation subcount records.',
type: 'array',
items: {
type: 'object',
additionalProperties: false,
required: [
'subcount',
'comment',
'qualitative_measurements',
'quantitative_measurements',
'qualitative_environments',
'quantitative_environments'
],
properties: {
observation_subcount_id: {
type: 'integer',
minimum: 1,
description: 'Primary key of the subcount record',
nullable: true
},
observation_subcount_sign_id: {
type: 'integer',
minimum: 1,
description:
'The observation subcount sign ID, indicating whether the subcount was a direct sighting, footprints, scat, etc.',
nullable: true
},
comment: {
type: 'string',
nullable: true,
description: 'A comment or note about the subcount'
},
subcount: {
type: 'number',
description: "The subcount record's count."
},
qualitative_measurements: {
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
measurement_id: {
type: 'string'
},
measurement_option_id: {
type: 'string'
}
}
}
},
quantitative_measurements: {
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
measurement_id: {
type: 'string'
},
measurement_value: {
type: 'number'
}
}
}
},
qualitative_environments: {
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
environment_qualitative_id: {
type: 'string',
format: 'uuid'
},
environment_qualitative_option_id: {
type: 'string',
format: 'uuid'
}
}
}
},
quantitative_environments: {
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
environment_quantitative_id: {
type: 'string',
format: 'uuid'
},
value: {
type: 'number'
}
}
}
}
}
}
}
}
}
}
}
},
responses: {
204: {
description: 'Create observations OK'
},
400: {
$ref: '#/components/responses/400'
},
401: {
$ref: '#/components/responses/401'
},
403: {
$ref: '#/components/responses/403'
},
500: {
$ref: '#/components/responses/500'
},
default: {
$ref: '#/components/responses/default'
}
}
};

/**
* This record maps observation table sampling site site ID columns to sampling data
* columns that can be sorted on.
Expand Down Expand Up @@ -436,7 +677,7 @@ export function putObservations(): RequestHandler {
const surveyId = Number(req.params.surveyId);
const observationRows: InsertUpdateObservations[] = req.body.surveyObservations;

defaultLog.debug({ label: 'insertUpdateSurveyObservations', surveyId });
defaultLog.debug({ label: 'putObservations', surveyId });

await connection.open();

Expand Down Expand Up @@ -471,3 +712,53 @@ export function putObservations(): RequestHandler {
}
};
}

/**
* Inserts new observation records.
*
* @export
* @return {*} {RequestHandler}
*/
export function postObservations(): RequestHandler {
return async (req, res) => {
const connection = getDBConnection(req.keycloak_token);

try {
const surveyId = Number(req.params.surveyId);
const observationRow: InsertUpdateObservations = req.body;

defaultLog.debug({ label: 'postSurveyObservations', surveyId });

await connection.open();

const observationService = new ObservationService(connection);

// Validate measurement data against fetched measurement definition
const critterBaseService = new CritterbaseService(getCritterbaseUser(req));
const observationSubCountEnvironmentService = new ObservationSubCountEnvironmentService(connection);

const isValid = await observationService.validateSurveyObservations(
[observationRow],
critterBaseService,
observationSubCountEnvironmentService
);

if (!isValid) {
throw new Error('Failed to save observation data, failed data validation.');
}

// Insert/update observation records
await observationService.insertUpdateManualSurveyObservations(surveyId, [observationRow]);

await connection.commit();

return res.status(204).send();
} catch (error) {
defaultLog.error({ label: 'postObservations', message: 'error', error });
await connection.rollback();
throw error;
} finally {
connection.release();
}
};
}
Loading

0 comments on commit b7317db

Please sign in to comment.