Skip to content

Commit

Permalink
#505 Dynamic vector layers
Browse files Browse the repository at this point in the history
  • Loading branch information
tariqksoliman committed Mar 5, 2024
1 parent e4e082c commit 77b2260
Show file tree
Hide file tree
Showing 10 changed files with 399 additions and 218 deletions.
73 changes: 28 additions & 45 deletions API/Backend/Geodatasets/routes/geodatasets.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ const Geodatasets = geodatasets.Geodatasets;
const makeNewGeodatasetTable = geodatasets.makeNewGeodatasetTable;

//Returns a geodataset table as a geojson
router.post("/get", function (req, res, next) {
get("post", req, res, next);
});
router.get("/get/:layer", function (req, res, next) {
req.query.layer = req.params.layer;
get("get", req, res, next);
Expand Down Expand Up @@ -58,48 +55,34 @@ function get(reqtype, req, res, next) {
let q = `SELECT properties, ST_AsGeoJSON(geom) FROM ${table}`;

let hasBounds = false;
if (req.body?.bounds) {
const bounds = req.body.bounds;
if (
bounds.southWest &&
bounds.southWest.lng != null &&
bounds.southWest.lat != null &&
bounds.northEast &&
bounds.northEast.lng != null &&
bounds.northEast.lat != null
) {
// ST_MakeEnvelope is (xmin, ymin, xmax, ymax, srid)
q += ` WHERE ST_Intersects(ST_MakeEnvelope(${parseFloat(
bounds.southWest.lng
)}, ${parseFloat(bounds.southWest.lat)}, ${parseFloat(
bounds.northEast.lng
)}, ${parseFloat(bounds.northEast.lat)}, 4326), geom)`;
hasBounds = true;
} else {
res.send({
status: "failure",
message:
"If 'bounds' is set, the 'bounds' object must be like {northEast:{lat:,lng:}, southWest:{lat:,lng:}}",
});
return;
}
let minx = req.query?.minx;
let miny = req.query?.miny;
let maxx = req.query?.maxx;
let maxy = req.query?.maxy;
if (minx != null && miny != null && maxx != null && maxy != null) {
// ST_MakeEnvelope is (xmin, ymin, xmax, ymax, srid)
q += ` WHERE ST_Intersects(ST_MakeEnvelope(${parseFloat(
minx
)}, ${parseFloat(miny)}, ${parseFloat(maxx)}, ${parseFloat(
maxy
)}, 4326), geom)`;
hasBounds = true;
}
if (req.body?.time) {
const time = req.body.time;
const format = req.body.time.format || "YYYY-MM-DDTHH:MI:SSZ";
if (req.query?.endtime != null) {
const format = req.query?.format || "YYYY-MM-DDTHH:MI:SSZ";
let t = ` `;
if (!hasBounds) t += `WHERE `;
else t += `AND `;

if (
time.startProp == null ||
time.startProp.indexOf(`'`) != -1 ||
time.endProp == null ||
time.endProp.indexOf(`'`) != -1 ||
time.start == null ||
time.start.indexOf(`'`) != -1 ||
time.end == null ||
time.end.indexOf(`'`) != -1 ||
req.query?.startProp == null ||
req.query?.startProp.indexOf(`'`) != -1 ||
req.query?.endProp == null ||
req.query?.endProp.indexOf(`'`) != -1 ||
req.query?.starttime == null ||
req.query?.starttime.indexOf(`'`) != -1 ||
req.query?.endtime == null ||
req.query?.endtime.indexOf(`'`) != -1 ||
format.indexOf(`'`) != -1
) {
res.send({
Expand All @@ -112,15 +95,15 @@ function get(reqtype, req, res, next) {
// prettier-ignore
t += [
`(`,
`properties->>'${time.startProp}' IS NOT NULL AND properties->>'${time.endProp}' IS NOT NULL AND`,
` date_part('epoch', to_timestamp(properties->>'${time.startProp}', '${format}'::text)) >= date_part('epoch', to_timestamp('${time.start}'::text, '${format}'::text))`,
` AND date_part('epoch', to_timestamp(properties->>'${time.endProp}', '${format}'::text)) <= date_part('epoch', to_timestamp('${time.end}'::text, '${format}'::text))`,
`properties->>'${req.query.startProp}' IS NOT NULL AND properties->>'${req.query.endProp}' IS NOT NULL AND`,
` date_part('epoch', to_timestamp(properties->>'${req.query.startProp}', '${format}'::text)) >= date_part('epoch', to_timestamp('${req.query.starttime}'::text, '${format}'::text))`,
` AND date_part('epoch', to_timestamp(properties->>'${req.query.endProp}', '${format}'::text)) <= date_part('epoch', to_timestamp('${req.query.endtime}'::text, '${format}'::text))`,
`)`,
` OR `,
`(`,
`properties->>'${time.startProp}' IS NULL AND properties->>'${time.endProp}' IS NOT NULL AND`,
` date_part('epoch', to_timestamp(properties->>'${time.endProp}', '${format}'::text)) >= date_part('epoch', to_timestamp('${time.start}'::text, '${format}'::text))`,
` AND date_part('epoch', to_timestamp(properties->>'${time.endProp}', '${format}'::text)) >= date_part('epoch', to_timestamp('${time.end}'::text, '${format}'::text))`,
`properties->>'${req.query.startProp}' IS NULL AND properties->>'${req.query.endProp}' IS NOT NULL AND`,
` date_part('epoch', to_timestamp(properties->>'${req.query.endProp}', '${format}'::text)) >= date_part('epoch', to_timestamp('${req.query.starttime}'::text, '${format}'::text))`,
` AND date_part('epoch', to_timestamp(properties->>'${req.query.endProp}', '${format}'::text)) >= date_part('epoch', to_timestamp('${req.query.endtime}'::text, '${format}'::text))`,
`)`
].join('')
q += t;
Expand Down
3 changes: 3 additions & 0 deletions config/js/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2796,6 +2796,9 @@ function layerPopulateVariable(modalId, layerType) {
value: "Example",
},
];
currentLayerVars.dynamicExtent = currentLayerVars.dynamicExtent || false;
currentLayerVars.dynamicExtentMoveThreshold =
currentLayerVars.dynamicExtentMoveThreshold || null;
currentLayerVars.shortcutSuffix = currentLayerVars.shortcutSuffix || null;

if (layerType == "tile") {
Expand Down
12 changes: 12 additions & 0 deletions config/js/keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ var Keys = {
"<div class='example_title'>Uploading CSVs</div>",
'<div>curl -i -X POST -H "Authorization:Bearer <span>&lt;token&gt;</span>" -F "name={dataset_name}" -F "upsert=true" -F "header=[\"File\",\"Target\",\"ShotNumber\",\"Distance(m)\",\"LaserPower\",\"SpectrumTotal\",\"SiO2\",\"TiO2\",\"Al2O3\",\"FeOT\",\"MgO\",\"CaO\",\"Na2O\",\"K2O\",\"Total\",\"SiO2_RMSEP\",\"TiO2_RMSEP\",\"Al2O3_RMSEP\",\"FeOT_RMSEP\",\"MgO_RMSEP\",\"CaO_RMSEP\",\"Na2O_RMSEP\",\"K2O_RMSEP\"]" -F "data=@{path/to.csv};type=text/csv" ' + location.origin + '/api/datasets/upload</div>',
"</li>",
"<li class='row'>",
"<div class='example_title'>Upserting a Geodataset</div>",
'<div>curl -i -X POST -H "Authorization:Bearer <span>&lt;token&gt;</span>" -H "Content-Type: application/json" --data-binary "@{path_to_your_file}.json" ' + location.origin + '/api/geodatasets/recreate/{geodataset_name}</div>',
"</li>",
"<li class='row'>",
"<div class='example_title'>Appending to an existing Geodataset</div>",
'<div>curl -i -X POST -H "Authorization:Bearer <span>&lt;token&gt;</span>" -H "Content-Type: application/json" --data-binary "@{path_to_your_file_to_append}.json" ' + location.origin + '/api/geodatasets/append/{geodataset_name}</div>',
"</li>",
"<li class='row'>",
"<div class='example_title'>Get an existing Geodataset</div>",
'<div>curl -i -X GET -H "Authorization:Bearer <span>&lt;token&gt;</span>" -H "Content-Type: application/json" ' + location.origin + '/api/geodatasets/get/{geodataset_name}</div>',
"</li>",
"</ul>",
"</div>",
"</div>"
Expand Down
6 changes: 5 additions & 1 deletion docs/pages/Configure/Layers/Vector/Vector.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ A file path that points to a geojson. If the path is relative, it will be relati

#### Controlled

_type:_ bool
_type:_ bool
Whether the layer can be dynamically updated or not. If true, the layer can be dynamically updated and the URL is not required.

If true and a URL is set and Time Enabled is true, the initial url query will be performed.
Expand Down Expand Up @@ -127,6 +127,8 @@ Example:
```javascript
{
"useKeyAsName": "propKey || [propKey1, propKey2, ...]",
"dynamicExtent": false,
"dynamicExtentMoveThreshold": "100000000/z",
"shortcutSuffix": "single letter to 'ATL + {letter}' toggle the layer on and off",
"hideMainFeature": false,
"datasetLinks": [
Expand Down Expand Up @@ -254,6 +256,8 @@ Example:
```

- `useKeyAsName`: The property key whose value should be the hover text of each feature. If left unset, the hover key and value will be the first one listed in the feature's properties. This may also be an array of keys.
- `dynamicExtent`: If true, tries to only query the vector features present in the user's current map viewport. Pan and zooming causes requeries. If used with a geodataset, the time and extent queries will work out-of-the-box. Otherwise, if using an external server, the following parameters in `{}` will be automatically replaced on query in the url: `starttime={starttime}&endtime={endtime}&startprop={startprop}&endprop={endprop}&crscode={crscode}&zoom={zoom}&minx={minx}&miny={miny}&maxx={maxx}&maxy={maxy}`
- `dynamicExtentMoveThreshold`: If `dynamicExtent` is true, only requery if the map was panned past the stated threshold. Unit is in meters. If a zoom-dependent threshold is desired, set this value to a string ending in `/z`. This will then internally use `dynamicExtentMoveThreshold / Math.pow(2, zoom)` as the threshold value.
- `shortcutSuffix`: A single letter to 'ALT + {letter}' toggle the layer on and off. Please verify that your chosen shortcut does not conflict with other system or browser-level keyboard shortcuts.
- `hideMainFeature`: If true, hides all typically rendered features. This is useful if showing only `*Attachments` sublayers is desired. Default false
- `datasetLinks`: Datasets are csvs uploaded from the "Manage Datasets" page accessible on the lower left. Every time a feature from this layer is clicked with datasetLinks configured, it will request the data from the server and include it with it's regular geojson properties. This is especially useful when single features need a lot of metadata to perform a task as it loads it only as needed.
Expand Down
5 changes: 5 additions & 0 deletions src/essence/Ancillary/Description.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ const Description = {

this.inited = true
if (this.waitingOnUpdate) this.updateInfo()

$(window).on('resize', () => {
$('#mainDescPointLinks > dl.dropy').removeClass('open')
$(`#mainDescPointLinks_global`).empty()
})
},
updateInfo(force) {
if (force !== true) {
Expand Down
Loading

0 comments on commit 77b2260

Please sign in to comment.