Skip to content

Commit d1b6dec

Browse files
#681 DrawTool Templating from intersected GeoDatasets (#683)
* #681 geodatasets/intersect endpoint * #681 CusorInfo locking * #681 minor * #681 DrawTool Templating from intersected GeoDatasets
1 parent 0b69379 commit d1b6dec

File tree

16 files changed

+795
-57
lines changed

16 files changed

+795
-57
lines changed

API/Backend/Geodatasets/routes/geodatasets.js

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,145 @@ function get(reqtype, req, res, next) {
468468
});
469469
}
470470

471+
router.post("/intersect", function (req, res, next) {
472+
let layer = req.body.layer;
473+
let noDuplicates = null;
474+
475+
if (req.body.noDuplicates === true || req.body.noDuplicates === "true")
476+
noDuplicates = true;
477+
478+
//First Find the table name
479+
Geodatasets.findOne({ where: { name: layer } })
480+
.then((result) => {
481+
if (result) {
482+
let table = result.dataValues.table;
483+
484+
let distinct = "";
485+
if (noDuplicates === true) {
486+
if (result.dataValues.group_id_field != null)
487+
distinct = ` DISTINCT ON (group_id)`;
488+
else distinct = ` DISTINCT ON (geom)`;
489+
}
490+
491+
let q = `SELECT${distinct} properties, ST_AsGeoJSON(geom) FROM ${Utils.forceAlphaNumUnder(
492+
table
493+
)}`;
494+
495+
// Intersect
496+
q += ` WHERE ST_Intersects(geom, ST_GeomFromGeoJSON(:intersect))`;
497+
498+
let startProp = "start_time";
499+
let start_time = "";
500+
let endProp = "end_time";
501+
let end_time = "";
502+
if (req.body?.endtime != null) {
503+
const format = req.body?.format || "YYYY-MM-DDTHH:MI:SSZ";
504+
let t = ` `;
505+
t += `AND `;
506+
507+
if (
508+
req.body?.starttime == null ||
509+
req.body?.starttime.indexOf(`'`) != -1 ||
510+
req.body?.endtime == null ||
511+
req.body?.endtime.indexOf(`'`) != -1 ||
512+
format.indexOf(`'`) != -1
513+
) {
514+
res.send({
515+
status: "failure",
516+
message: "Missing inner or malformed time parameters.",
517+
});
518+
return;
519+
}
520+
521+
start_time = new Date(
522+
req.body.starttime || "1970-01-01T00:00:00Z"
523+
).getTime();
524+
end_time = new Date(req.body.endtime).getTime();
525+
526+
startProp = Utils.forceAlphaNumUnder(req.body.startProp || startProp);
527+
endProp = Utils.forceAlphaNumUnder(req.body.endProp || endProp);
528+
// prettier-ignore
529+
t += [
530+
`((`,
531+
`${startProp} IS NOT NULL AND ${endProp} IS NOT NULL AND`,
532+
` ${startProp} >= ${start_time}`,
533+
` AND ${endProp} <= ${end_time}`,
534+
`)`,
535+
` OR `,
536+
`(`,
537+
`${startProp} IS NULL AND ${endProp} IS NOT NULL AND`,
538+
` ${endProp} >= ${start_time}`,
539+
` AND ${endProp} <= ${end_time}`,
540+
`))`
541+
].join('')
542+
q += t;
543+
}
544+
545+
const replacements = {
546+
intersect:
547+
typeof req.body.intersect === "string"
548+
? req.body.intersect
549+
: JSON.stringify(req.body.intersect),
550+
startProp: startProp,
551+
start_time: start_time,
552+
endProp: endProp,
553+
end_time: end_time,
554+
};
555+
556+
q += `;`;
557+
558+
sequelize
559+
.query(q, {
560+
replacements: replacements,
561+
})
562+
.then(([results]) => {
563+
let geojson = { type: "FeatureCollection", features: [] };
564+
for (let i = 0; i < results.length; i++) {
565+
let properties = results[i].properties;
566+
properties._ = properties._ || {};
567+
properties._.idx = results[i].id;
568+
let feature = {};
569+
feature.type = "Feature";
570+
feature.properties = properties;
571+
572+
feature.geometry = JSON.parse(results[i].st_asgeojson);
573+
geojson.features.push(feature);
574+
}
575+
576+
res.setHeader("Access-Control-Allow-Origin", "*");
577+
578+
res.send({
579+
status: "success",
580+
body: geojson,
581+
});
582+
583+
return null;
584+
})
585+
.catch((err) => {
586+
logger(
587+
"error",
588+
"Geodataset query SQL error.",
589+
req.originalUrl,
590+
req,
591+
err
592+
);
593+
res.send({
594+
status: "failure",
595+
message: "Failed to query Geodataset.",
596+
});
597+
});
598+
} else {
599+
res.send({ status: "failure", message: "Not Found" });
600+
}
601+
602+
return null;
603+
})
604+
.catch((err) => {
605+
logger("error", "Failure finding geodataset.", req.originalUrl, req, err);
606+
res.send({ status: "failure", message: "Failure finding geodataset." });
607+
});
608+
});
609+
471610
/*
472611
req.query.layer
473612
req.query.limit

configure/public/contours.png

-3.2 KB
Loading

configure/public/toolConfigs.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/essence/Ancillary/CursorInfo.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ var CursorInfo = {
1212
//The div that will follow the mouse around
1313
cursorInfoDiv: null,
1414
forcedPos: false,
15+
_lockTimeout: null,
16+
_locked: false,
1517
//Creates that div and adds the mousemove event so it follows the cursor
1618
init: function () {
1719
CursorInfo.cursorInfoDiv = d3
@@ -39,6 +41,9 @@ var CursorInfo = {
3941
},
4042
//Use jquery to fade in out then set display to none and clear inner html
4143
hide: function (immediate) {
44+
if (CursorInfo._locked) {
45+
return
46+
}
4247
if (immediate) {
4348
CursorInfo.cursorInfoDiv.style('display', 'none').html('')
4449
} else {
@@ -58,8 +63,20 @@ var CursorInfo = {
5863
forceFontColor,
5964
asHTML,
6065
withBorder,
61-
withoutPadding
66+
withoutPadding,
67+
lockMS
6268
) {
69+
if (CursorInfo._locked) {
70+
return
71+
}
72+
if (lockMS != null && lockMS > 0) {
73+
CursorInfo._locked = true
74+
clearTimeout(CursorInfo._lockTimeout)
75+
CursorInfo._lockTimeout = setTimeout(() => {
76+
CursorInfo._locked = false
77+
}, lockMS)
78+
}
79+
6380
if (position) {
6481
CursorInfo.forcedPos = true
6582
CursorInfo.cursorInfoDiv

src/essence/Ancillary/Modal.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,14 @@
3838
left: 50%;
3939
top: 50%;
4040
}
41+
42+
.mmgisModal .dropdown {
43+
background-color: #2c2f30;
44+
border: none;
45+
margin: 1px 0px;
46+
width: 120px;
47+
height: 28px;
48+
font-size: 14px;
49+
color: var(--color-f);
50+
padding: 0px 2px;
51+
}

src/essence/Basics/Layers_/Layers_.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3561,6 +3561,18 @@ const L_ = {
35613561
$('#dataLoadingSpinner').css({ opacity: 0 })
35623562
}
35633563
},
3564+
getListOfUsedGeoDatasets() {
3565+
const list = []
3566+
Object.keys(L_.layers.data).forEach((key) => {
3567+
const d = L_.layers.data[key]
3568+
if (d.url && d.url.startsWith('geodatasets:'))
3569+
list.push({
3570+
display_name: d.display_name,
3571+
geodataset: d.url.replace('geodatasets:', ''),
3572+
})
3573+
})
3574+
return list
3575+
},
35643576
}
35653577

35663578
//Takes in a configData object and does a depth-first search through its

src/essence/Basics/Map_/Map_.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ let Map_ = {
413413
}
414414
}
415415
}
416+
416417
Map_.map.addLayer(L_.layers.layer[L_._layersOrdered[hasIndex[i]]])
417418

418419
// If image layer, reorder the z index and redraw the layer
@@ -444,6 +445,20 @@ let Map_ = {
444445
)
445446
)
446447
}
448+
449+
// Now bring any Drawn layers back to the front:
450+
Object.keys(L_.layers.layer).forEach((key) => {
451+
if (
452+
key.startsWith('DrawTool_') &&
453+
Array.isArray(L_.layers.layer[key])
454+
) {
455+
L_.layers.layer[key].forEach((l) => {
456+
try {
457+
l.bringToFront()
458+
} catch (err) {}
459+
})
460+
}
461+
})
447462
},
448463
refreshLayer: async function (layerObj, cb, skipOrderedBringToFront) {
449464
// If it's a dynamic extent layer, just re-call its function

src/essence/Tools/Draw/DrawTool.css

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242

4343
.drawToolButton1 {
4444
background: #067ca7;
45-
padding: 3px 8px;
45+
padding: 5px 8px 2px 8px;
46+
border-radius: 2px;
4647
margin: 5px 0px;
4748
text-align: center;
4849
color: #ededed;
@@ -2372,7 +2373,33 @@
23722373
.drawToolContextMenuPropertiesTitle {
23732374
height: 30px;
23742375
line-height: 30px;
2375-
color: var(--color-query);
2376+
color: #91c676;
2377+
}
2378+
.drawToolContextMenuPropertiesRecomputeTemplate {
2379+
margin-top: -1px;
2380+
display: flex;
2381+
cursor: pointer;
2382+
}
2383+
.drawToolContextMenuPropertiesRecomputeTemplate > div {
2384+
background: var(--color-a-1);
2385+
border: 1px solid var(--color-a-5);
2386+
color: var(--color-a6);
2387+
border-radius: 3px;
2388+
padding: 4px 8px 3px 4px;
2389+
margin-bottom: 6px;
2390+
display: flex;
2391+
transition: all 0.2s ease-out;
2392+
}
2393+
.drawToolContextMenuPropertiesRecomputeTemplate > div > i {
2394+
margin-right: 4px;
2395+
}
2396+
.drawToolContextMenuPropertiesRecomputeTemplate > div > div {
2397+
font-size: 12px;
2398+
line-height: 20px;
2399+
}
2400+
.drawToolContextMenuPropertiesRecomputeTemplate > div:hover {
2401+
color: white;
2402+
background: var(--color-a2);
23762403
}
23772404
.drawToolContextMenuPropertiesExtended {
23782405
margin-bottom: 12px;

src/essence/Tools/Draw/DrawTool.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,6 @@ var DrawTool = {
740740
null,
741741
d
742742
)
743-
744743
Viewer_.changeImages(layer.feature, layer)
745744
Globe_.highlight(
746745
Globe_.findSpriteObject(
@@ -1170,15 +1169,17 @@ var DrawTool = {
11701169
}
11711170
)
11721171
},
1173-
addDrawing: function (body, callback, failure) {
1172+
addDrawing: async function (body, callback, failure) {
11741173
// Add template property defaults
11751174
const file = DrawTool.getFileObjectWithId(body.file_id)
11761175
if (file?.template?.template && body?.properties) {
11771176
let newProps = JSON.parse(body.properties)
1178-
const templateDefaults = DrawTool_Templater.getTemplateDefaults(
1179-
file?.template?.template,
1180-
L_.layers.layer[`DrawTool_${body.file_id}`]
1181-
)
1177+
const templateDefaults =
1178+
await DrawTool_Templater.getTemplateDefaults(
1179+
file?.template?.template,
1180+
L_.layers.layer[`DrawTool_${body.file_id}`],
1181+
body
1182+
)
11821183

11831184
newProps = { ...newProps, ...templateDefaults }
11841185
body.properties = JSON.stringify(newProps)

src/essence/Tools/Draw/DrawTool_Editing.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,16 @@ var Editing = {
618618
"</div>",
619619
(file.template != null ) ? [
620620
"<div class='drawToolContextMenuPropertiesCollapsible'>",
621-
`<div class='drawToolContextMenuPropertiesTitle'><div>Template (${file.template?.name})</div><i class='mdi mdi-chevron-down mdi-24px'></i></div>`,
622-
"<div id='drawToolContextMenuPropertiesTemplate'></div>",
621+
`<div class='drawToolContextMenuPropertiesTitle'>`,
622+
`<div style='display: flex;'>`,
623+
`<div>Template (${file.template?.name})</div>`,
624+
`</div>`,
625+
`<i class='mdi mdi-chevron-down mdi-24px'></i>`,
626+
`</div>`,
627+
`<div>`,
628+
`<div class='drawToolContextMenuPropertiesRecomputeTemplate'><div><i class='mdi mdi-restore mdi-18px'></i><div>Recompute Templated Fields</div></div></div>`,
629+
"<div id='drawToolContextMenuPropertiesTemplate'></div>",
630+
`</div>`,
623631
"</div>"].join('\n') : "",
624632
"<div class='drawToolContextMenuPropertiesCollapsible state-collapsed'>",
625633
"<div class='drawToolContextMenuPropertiesTitle'><div>Metrics</div><i class='mdi mdi-chevron-down mdi-24px'></i></div>",
@@ -894,6 +902,31 @@ var Editing = {
894902
).on('click', function () {
895903
$(this).parent().toggleClass('state-collapsed')
896904
})
905+
$(`.drawToolContextMenuPropertiesRecomputeTemplate`).on(
906+
'click',
907+
async () => {
908+
const templateDefaults =
909+
await DrawTool_Templater.getTemplateDefaults(
910+
file?.template?.template,
911+
L_.layers.layer[`DrawTool_${file.file_id}`],
912+
{
913+
geometry: JSON.stringify(
914+
DrawTool.contextMenuLayer?.feature?.geometry
915+
),
916+
}
917+
)
918+
919+
$('#drawToolContextMenuPropertiesTemplate').empty()
920+
templater = DrawTool_Templater.renderTemplate(
921+
'drawToolContextMenuPropertiesTemplate',
922+
file.template,
923+
{
924+
...DrawTool.contextMenuLayer?.feature?.properties,
925+
...templateDefaults,
926+
}
927+
)
928+
}
929+
)
897930
UserInterface_.openRightPanel(360)
898931

899932
$('#drawToolContextMenuPropertiesDescription').text(description)

0 commit comments

Comments
 (0)