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

SIMSBIOHUB 347/341 - Names from shapefiles #1146

Merged
merged 8 commits into from
Oct 31, 2023
17 changes: 11 additions & 6 deletions api/src/repositories/sample-location-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export const SampleLocationRecord = z.object({
export type SampleLocationRecord = z.infer<typeof SampleLocationRecord>;

// Insert Object for Sample Locations
export type InsertSampleLocationRecord = Pick<SampleLocationRecord, 'survey_id' | 'name' | 'description' | 'geojson'>;
export type InsertSampleLocationRecord = Pick<SampleLocationRecord, 'survey_id' | 'description' | 'geojson'> & {
name: string | undefined;
};

// Update Object for Sample Locations
export type UpdateSampleLocationRecord = Pick<
Expand Down Expand Up @@ -152,6 +154,10 @@ export class SampleLocationRepository extends BaseRepository {
* @memberof SampleLocationRepository
*/
async insertSampleLocation(sample: InsertSampleLocationRecord): Promise<SampleLocationRecord> {
const shapeNameOrQuery = sample.name
? SQL`${sample.name}`
: SQL`(SELECT concat('Sample Site ', (SELECT count(survey_sample_site_id) + 1 FROM survey_sample_site sss WHERE survey_id = ${sample.survey_id})))`;

const sqlStatement = SQL`
INSERT INTO survey_sample_site (
survey_id,
Expand All @@ -160,11 +166,10 @@ export class SampleLocationRepository extends BaseRepository {
geojson,
geography
) VALUES (
${sample.survey_id},
(SELECT concat('Sample Site ', (SELECT count(survey_sample_site_id) + 1 FROM survey_sample_site sss WHERE survey_id = ${sample.survey_id}))),
${sample.description},
${sample.geojson},
`;
${sample.survey_id},`.append(shapeNameOrQuery).append(SQL`,
${sample.description},
${sample.geojson},
`);
const geometryCollectionSQL = generateGeometryCollectionSQL(sample.geojson);

sqlStatement.append(SQL`
Expand Down
28 changes: 23 additions & 5 deletions api/src/services/sample-location-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Feature } from '@turf/helpers';
import { Feature, Geometry, GeometryCollection, Properties } from '@turf/helpers';
import { IDBConnection } from '../database/db';
import {
SampleLocationRecord,
Expand Down Expand Up @@ -58,19 +58,37 @@ export class SampleLocationService extends DBService {
/**
* Inserts survey Sample Locations.
*
* It is a business requirement to use strings from the properties field of provided geometry
* to determine the name and description of sampling locations when possible.
*
* If there is no string contained in the fields 'name', 'label' to be used in our db,
* the system will auto-generate a name of 'Sampling Site #x', where x is taken from the greatest value
* integer id + 1 in the db.
*
* @param {PostSampleLocations} sampleLocations
* @return {*} {Promise<SampleLocationRecord[]>}
* @memberof SampleLocationService
*/
async insertSampleLocations(sampleLocations: PostSampleLocations): Promise<SampleLocationRecord[]> {
const methodService = new SampleMethodService(this.connection);

const shapeFileFeatureName = (geometry: Feature<Geometry | GeometryCollection, Properties>): string | undefined => {
const nameKey = Object.keys(geometry.properties ?? {}).find(
(key) => key.toLowerCase() === 'name' || key.toLowerCase() === 'label'
);
return nameKey && geometry.properties ? geometry.properties[nameKey].substring(0, 50) : undefined;
};
const shapeFileFeatureDesc = (geometry: Feature<Geometry | GeometryCollection, Properties>): string | undefined => {
const descKey = Object.keys(geometry.properties ?? {}).find(
(key) => key.toLowerCase() === 'desc' || key.toLowerCase() === 'descr' || key.toLowerCase() === 'des'
);
return descKey && geometry.properties ? geometry.properties[descKey].substring(0, 250) : undefined;
};
// Create a sample location for each feature found
const promises = sampleLocations.survey_sample_sites.map((item, index) => {
const promises = sampleLocations.survey_sample_sites.map((item) => {
const sampleLocation = {
survey_id: sampleLocations.survey_id,
name: `Sample Site ${index + 1}`, // Business requirement to default the names to Sample Site # on creation
description: sampleLocations.description,
name: shapeFileFeatureName(item), // If this function returns undefined, insertSampleLocation will auto-generate a name instead.
description: shapeFileFeatureDesc(item) || sampleLocations.description,
geojson: item
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface ISampleSiteEditFormProps {

export const samplingSiteYupSchema = yup.object({
sampleSite: yup.object({
name: yup.string().default(''),
name: yup.string().default('').max(50, 'Maximum 50 characters.'),
description: yup.string().default('').nullable(),
survey_sample_sites: yup
.array(yup.object())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ const SampleSiteGeneralInformationForm: React.FC = (props) => {
<CustomTextField
name="sampleSite.name"
label="Name"
other={{
required: true
}}
other={{ placeholder: 'Maximum 50 characters', required: true }}
/>
</Grid>
<Grid item xs={12}>
Expand Down
Loading