Skip to content

Commit

Permalink
merge conclude, finish adding current activity layer geo
Browse files Browse the repository at this point in the history
  • Loading branch information
plasticviking committed Jan 21, 2025
2 parents fc09027 + fba8798 commit 5973b21
Show file tree
Hide file tree
Showing 34 changed files with 760 additions and 412 deletions.
18 changes: 12 additions & 6 deletions api/src/paths/v2/iapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,23 @@ export function getIAPPSQLv2(filterObject: any) {
sqlStatement = fromStatement(sqlStatement, filterObject);
sqlStatement = whereStatement(sqlStatement, filterObject);
sqlStatement = groupByStatement(sqlStatement, filterObject);
if (!filterObject.vt_request) {
if (!filterObject.vt_request && !filterObject.boundingBoxOnly) {
sqlStatement = orderByStatement(sqlStatement, filterObject);
sqlStatement = limitStatement(sqlStatement, filterObject);
sqlStatement = offSetStatement(sqlStatement, filterObject);
} else {
} else if (filterObject.vt_request) {
sqlStatement.append(` ) SELECT ST_AsMVT(mvtgeom.*, 'data', 4096, 'geom', 'feature_id') as data from mvtgeom;`);
} else if (filterObject.boundingBoxOnly) {
// wrap the whole thing into a subquery for the aggregate function
const wrappedStatement = SQL` WITH userQuery AS ( `.append(sqlStatement.text).append(` )
SELECT ST_AsText(ST_Extent(geometry(geog))) as bbox
FROM invasivesbc.iapp_spatial
WHERE geog IS not null
AND site_id in (SELECT site_id
FROM userQuery) `);
return wrappedStatement;
}

//defaultLog.debug({ label: 'getIAPPBySearchFilterCriteria', message: 'sql', body: sqlStatement });
return sqlStatement;
} catch (e) {
defaultLog.debug({ label: 'getIAPPBySearchFilterCriteria', message: 'error', body: e.message });
Expand Down Expand Up @@ -593,9 +601,7 @@ function whereStatement(sqlStatement: SQLStatement, filterObject: any) {
break;
case 'all_species_on_site':
where.append(
`${filter.operator2} LOWER(sites.all_species_on_site) ${filter.operator === 'CONTAINS' ? 'like' : 'not like'} LOWER('%${
filter.filter
}%') `
`${filter.operator2} LOWER(sites.all_species_on_site) ${filter.operator === 'CONTAINS' ? 'like' : 'not like'} LOWER('%${filter.filter}%') `
);
break;
case 'max_survey':
Expand Down
113 changes: 113 additions & 0 deletions api/src/paths/v2/iapp/bbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { RequestHandler } from 'express';
import { Operation } from 'express-openapi';
import { SQLStatement } from 'sql-template-strings';
import { ALL_ROLES, SECURITY_ON } from 'constants/misc';
import { getLogger } from 'utils/logger';
import { getDBConnection } from 'database/db';
import { getIAPPSQLv2, sanitizeIAPPFilterObject } from '../iapp';

const NAMESPACE = 'IAPP-bbox';

const defaultLog = getLogger(NAMESPACE);
export const POST: Operation = [postHandler()];

POST.apiDoc = {
description: 'Fetch bounding box based on search criteria',
tags: [NAMESPACE],
security: SECURITY_ON ? [{ Bearer: ALL_ROLES }] : [],
requestBody: {
description: 'Recordset search filter criteria',
content: {
'application/json': {
schema: {
properties: {}
}
}
}
},
responses: {
200: {
description: 'Bounding box response object',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
bbox: {
type: 'string',
description: 'Bounding box for the given filters'
}
}
}
}
}
},
401: {
$ref: '#/components/responses/401'
},
503: {
$ref: '#/components/responses/503'
},
default: {
$ref: '#/components/responses/default'
}
}
};

/**
* @desc Create Bounding box based on the filter properties for a given recordset
*/
function postHandler(): RequestHandler {
return async (req, res) => {
const connection = await getDBConnection();
if (!connection) {
return res.status(503).json({
message: 'Database connection unavailable',
namespace: NAMESPACE,
code: 503
});
}
try {
defaultLog.debug({ label: NAMESPACE, message: 'postHandler', body: req.body });
if (req.body?.filterObjects?.[0]) {
const filterObject = sanitizeIAPPFilterObject(req.body.filterObjects[0], req);
filterObject.boundingBoxOnly = true;
const iappSql: SQLStatement = getIAPPSQLv2(filterObject);
const response = await connection.query(iappSql.text, iappSql.values);

if (response.rowCount > 0) {
return res.status(200).json(response.rows[0]);
} else {
return res.status(404).json({
message: 'No Results',
request: req.body,
namespace: NAMESPACE,
code: 404
});
}
} else {
return res.status(400).json({
message: 'Missing filter Objects from request',
request: req.body,
namespace: NAMESPACE,
code: 400
});
}
} catch (error) {
defaultLog.debug({
label: NAMESPACE,
message: 'error',
error
});
return res.status(500).json({
message: 'Server Error occured',
request: req.body,
namespace: NAMESPACE,
code: 500,
error
});
} finally {
connection.release();
}
};
}
3 changes: 2 additions & 1 deletion app/src/UI/LegacyMap/LayerPicker/LayerPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { MOBILE } from 'state/build-time-config';
import LayersIcon from '@mui/icons-material/Layers';
import CloseIcon from '@mui/icons-material/Close';
import { IconButton, Switch } from '@mui/material';
import './LayerPicker.css';
import { useState } from 'react';
import LpModules from 'constants/LpModules';
import LayerPickerPathOption from './LayerPickerPathRow';
Expand All @@ -14,6 +13,8 @@ import Accordion from 'UI/Accordion/Accordion';
import { useDispatch, useSelector } from 'utils/use_selector';
import UserSettings from 'state/actions/userSettings/UserSettings';

import './LayerPicker.css';

export const LayerPicker = () => {
const closeLayerPicker = () => {
setShowLayerPicker(false);
Expand Down
17 changes: 15 additions & 2 deletions app/src/UI/LegacyMap/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
rebuildLayersOnTableHashUpdate,
refreshColoursOnColourUpdate,
refreshVisibilityOnToggleUpdate,
removeDeletedRecordSetLayersOnRecordSetDelete,
removeLayersOnNetworkConnectivityChange
} from 'UI/LegacyMap/helpers/functional/recordset-layers';
import {
Expand All @@ -41,7 +40,9 @@ import { PMTiles, Protocol } from 'pmtiles';
import { TileCacheService } from 'utils/tile-cache';
import { Coordinates } from 'UI/LegacyMap/helpers/components/Coordinates';
import { ReactiveLayers } from 'UI/LegacyMap/helpers/components/ReactiveLayers';
import { CurrentActivityLayer } from 'UI/LegacyMap/helpers/components/CurrentActivityLayer';
import { DrawControls } from 'UI/LegacyMap/helpers/components/DrawControls';
import { toggleLayerOnBool } from 'UI/LegacyMap/helpers/functional/utility-functions';

/*
Expand Down Expand Up @@ -255,7 +256,6 @@ export const Map = ({ children }) => {
rebuildLayersOnTableHashUpdate(storeLayers, map, MapMode, API_BASE, connectedToNetwork);
refreshColoursOnColourUpdate(storeLayers, map);
refreshVisibilityOnToggleUpdate(storeLayers, map);
removeDeletedRecordSetLayersOnRecordSetDelete(storeLayers, map);
}, [storeLayers, map, mapReady, connectedToNetwork, loggedInOrWorkingOffline]);

// Layer picker:
Expand Down Expand Up @@ -310,6 +310,18 @@ export const Map = ({ children }) => {
}, 1000);
}, [map]);

// toggle public map pmtile layer
useEffect(() => {
if (!mapReady) return;
if (!map) return;
if (loggedInOrWorkingOffline) {
toggleLayerOnBool(map, 'invasivesbc-pmtile-vector', false);
toggleLayerOnBool(map, 'iapp-pmtile-vector', false);
toggleLayerOnBool(map, 'invasivesbc-pmtile-vector-label', false);
toggleLayerOnBool(map, 'iapp-pmtile-vector-label', false);
}
}, [loggedInOrWorkingOffline, map, mapReady]);

return (
<div className="map-containing-block">
<div className="MapWrapper">
Expand All @@ -323,6 +335,7 @@ export const Map = ({ children }) => {
<DrawControls />
<ReactiveLayers mapReady={mapReady} />
<PositionMarkers mapReady={mapReady} />
<CurrentActivityLayer mapReady={mapReady} />
</MapContext.Provider>

{children}
Expand Down
99 changes: 99 additions & 0 deletions app/src/UI/LegacyMap/helpers/components/CurrentActivityLayer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { useContext, useEffect, useState } from 'react';
import { MapContext } from 'UI/LegacyMap/helpers/components/MapContext';
import { LAYER_Z_FOREGROUND } from 'UI/LegacyMap/helpers/functional/layer-definitions';
import { useSelector } from 'utils/use_selector';

const CurrentActivityLayer = ({ mapReady }) => {
const map = useContext(MapContext);
const [geo, setGeo] = useState(null);

const activityGeometryArray = useSelector((state) => state.ActivityPage.activity?.geometry);
const { url } = useSelector((state) => state.AppMode);

// react to changes in the geometry or current page and set our rendered geo appropriately
// render if a) we're on the Activity page and b) There is a geo object in the Activity
useEffect(() => {
if (activityGeometryArray && activityGeometryArray[0] && url?.includes('Activity')) {
setGeo(activityGeometryArray[0]);
} else {
setGeo(null);
}
}, [activityGeometryArray, url]);

useEffect(() => {
if (!map) return;
if (!mapReady) return;

// add the layer if needed

const LAYER_ID = 'current-activity-';

const SHAPE_LAYER = `${LAYER_ID}-shape`;
const OUTLINE_LAYER = `${LAYER_ID}-outline`;
const ZOOM_CIRCLE_LAYER = `${LAYER_ID}-zoomoutcircle`;

if (geo) {
map
.addSource(LAYER_ID, {
type: 'geojson',
data: geo
})
.addLayer(
{
id: SHAPE_LAYER,
source: LAYER_ID,
type: 'fill',
paint: {
'fill-color': 'white',
'fill-outline-color': 'black',
'fill-opacity': 0.7
},
minzoom: 0,
maxzoom: 24
},
LAYER_Z_FOREGROUND
)
.addLayer(
{
id: OUTLINE_LAYER,
source: LAYER_ID,
type: 'line',
paint: {
'line-color': 'black',
'line-opacity': 1,
'line-width': 3
},
minzoom: 0,
maxzoom: 24
},
LAYER_Z_FOREGROUND
)
.addLayer(
{
id: ZOOM_CIRCLE_LAYER,
source: LAYER_ID,
type: 'circle',
paint: {
'circle-color': 'white',
'circle-radius': 3
},
minzoom: 0,
maxzoom: 24
},
LAYER_Z_FOREGROUND
);

return () => {
// cleanup effect -- remove created entries in reverse
map.removeLayer(ZOOM_CIRCLE_LAYER);
map.removeLayer(OUTLINE_LAYER);
map.removeLayer(SHAPE_LAYER);
map.removeSource(LAYER_ID);
};
}
}, [geo]);

return null;
};

export { CurrentActivityLayer };
Loading

0 comments on commit 5973b21

Please sign in to comment.