Browse Source

Region/district/city bounds routes

mantine
cracklesparkle 4 months ago
parent
commit
e6b3dc05d3
  1. 46
      client/package-lock.json
  2. 1
      client/package.json
  3. 26
      client/yarn.lock
  4. 3
      ems/package.json
  5. 65
      ems/src/api/gis/index.ts
  6. 37
      ems/src/utils/postgres.ts

46
client/package-lock.json

@ -43,6 +43,7 @@
"dayjs": "^1.11.13",
"embla-carousel-react": "^8.3.0",
"file-type": "^19.0.0",
"jspdf": "^2.5.2",
"ol": "^10.0.0",
"ol-ext": "^4.0.23",
"proj4": "^2.12.0",
@ -4002,8 +4003,7 @@
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
"optional": true,
"peer": true
"optional": true
},
"node_modules/@types/react": {
"version": "18.3.3",
@ -4516,7 +4516,6 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
"peer": true,
"bin": {
"atob": "bin/atob.js"
},
@ -4644,7 +4643,6 @@
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
"optional": true,
"peer": true,
"engines": {
"node": ">= 0.6.0"
}
@ -4922,7 +4920,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
"peer": true,
"bin": {
"btoa": "bin/btoa.js"
},
@ -5071,7 +5068,6 @@
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz",
"integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==",
"optional": true,
"peer": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
"@types/raf": "^3.4.0",
@ -5090,8 +5086,7 @@
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"optional": true,
"peer": true
"optional": true
},
"node_modules/chalk": {
"version": "4.1.2",
@ -5430,7 +5425,6 @@
"integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==",
"hasInstallScript": true,
"optional": true,
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
@ -5567,7 +5561,6 @@
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"optional": true,
"peer": true,
"dependencies": {
"utrie": "^1.0.2"
}
@ -5945,8 +5938,7 @@
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.6.tgz",
"integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==",
"optional": true,
"peer": true
"optional": true
},
"node_modules/earcut": {
"version": "3.0.0",
@ -6545,10 +6537,9 @@
}
},
"node_modules/fflate": {
"version": "0.4.8",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz",
"integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==",
"peer": true
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
@ -7148,7 +7139,6 @@
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"optional": true,
"peer": true,
"dependencies": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
@ -7874,20 +7864,19 @@
}
},
"node_modules/jspdf": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz",
"integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==",
"peer": true,
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz",
"integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
"dependencies": {
"@babel/runtime": "^7.14.0",
"@babel/runtime": "^7.23.2",
"atob": "^2.1.2",
"btoa": "^1.2.1",
"fflate": "^0.4.8"
"fflate": "^0.8.1"
},
"optionalDependencies": {
"canvg": "^3.0.6",
"core-js": "^3.6.0",
"dompurify": "^2.2.0",
"dompurify": "^2.5.4",
"html2canvas": "^1.0.0-rc.5"
}
},
@ -8704,8 +8693,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
"optional": true,
"peer": true
"optional": true
},
"node_modules/picocolors": {
"version": "1.1.0",
@ -9309,7 +9297,6 @@
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"optional": true,
"peer": true,
"dependencies": {
"performance-now": "^2.1.0"
}
@ -9878,7 +9865,6 @@
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
"optional": true,
"peer": true,
"engines": {
"node": ">= 0.8.15"
}
@ -10751,7 +10737,6 @@
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
"optional": true,
"peer": true,
"engines": {
"node": ">=0.1.14"
}
@ -11100,7 +11085,6 @@
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
"optional": true,
"peer": true,
"engines": {
"node": ">=12.0.0"
}
@ -11227,7 +11211,6 @@
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"optional": true,
"peer": true,
"dependencies": {
"utrie": "^1.0.2"
}
@ -11749,7 +11732,6 @@
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"optional": true,
"peer": true,
"dependencies": {
"base64-arraybuffer": "^1.0.2"
}

1
client/package.json

@ -46,6 +46,7 @@
"dayjs": "^1.11.13",
"embla-carousel-react": "^8.3.0",
"file-type": "^19.0.0",
"jspdf": "^2.5.2",
"ol": "^10.0.0",
"ol-ext": "^4.0.23",
"proj4": "^2.12.0",

26
client/yarn.lock

@ -936,7 +936,7 @@
resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.20.13", "@babel/runtime@^7.25.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.20.13", "@babel/runtime@^7.23.2", "@babel/runtime@^7.25.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
version "7.26.0"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz"
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
@ -2909,7 +2909,7 @@ domain-browser@^4.22.0:
resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-4.23.0.tgz"
integrity sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA==
dompurify@^2.2.0:
dompurify@^2.5.4:
version "2.5.6"
resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.5.6.tgz"
integrity sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==
@ -3303,10 +3303,10 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
fflate@^0.4.8:
version "0.4.8"
resolved "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz"
integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
fflate@^0.8.1:
version "0.8.2"
resolved "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz"
integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==
file-entry-cache@^6.0.1:
version "6.0.1"
@ -4062,19 +4062,19 @@ jsonpointer@^5.0.0:
resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz"
integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==
jspdf@^2.5.1:
version "2.5.1"
resolved "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz"
integrity sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==
jspdf@^2.5.1, jspdf@^2.5.2:
version "2.5.2"
resolved "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz"
integrity sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==
dependencies:
"@babel/runtime" "^7.14.0"
"@babel/runtime" "^7.23.2"
atob "^2.1.2"
btoa "^1.2.1"
fflate "^0.4.8"
fflate "^0.8.1"
optionalDependencies:
canvg "^3.0.6"
core-js "^3.6.0"
dompurify "^2.2.0"
dompurify "^2.5.4"
html2canvas "^1.0.0-rc.5"
keyv@^4.5.3:

3
ems/package.json

@ -23,7 +23,7 @@
"ioredis": "^5.4.1",
"md5": "^2.3.0",
"multer": "^1.4.5-lts.1",
"pg": "^8.13.0",
"pg": "^8.13.1",
"pump": "^3.0.0",
"sharp": "^0.33.5",
"tedious": "^18.6.1"
@ -35,6 +35,7 @@
"@types/md5": "^2.3.5",
"@types/multer": "^1.4.12",
"@types/node": "^22.4.1",
"@types/pg": "^8.11.10",
"@types/pump": "^1.1.3",
"@types/redis": "^4.0.11",
"nodemon": "^3.1.4",

65
ems/src/api/gis/index.ts

@ -1,8 +1,73 @@
import express, { Request, Response } from 'express';
import { tediousQuery } from '../../utils/tedious';
import { GeneralDB, GisDB } from '../../constants/db';
import { pgQuery } from '../../utils/postgres';
const router = express.Router()
router.get('/bounds/:entity_type', async (req: Request, res: Response) => {
try {
const { entity_type } = req.params
const result = await pgQuery(
`
SELECT * FROM bounds
WHERE entity_type = $1
`,
[entity_type]
)
if (Array.isArray(result)) {
if (result.length > 0) {
const geometries = result.map((bound: { id: number, entity_id: number, entity_type: string, geometry: JSON, published_at: string, deleted_at: string | null }) => {
return {
...bound.geometry,
properties: {
id: bound.id,
entity_id: bound.entity_id,
entity_type: bound.entity_type
}
}
})
res.status(200).json(geometries)
} else {
res.status(404).json('not found')
}
} else {
res.status(404).json('not found')
}
} catch (err) {
res.status(500)
}
})
router.get('/bounds/:entity_type/:entity_id', async (req: Request, res: Response) => {
try {
const { entity_type, entity_id } = req.params
const result = await pgQuery(
`
SELECT * FROM bounds
WHERE entity_type = $1
AND entity_id = $2
`,
[entity_type, entity_id]
)
if (Array.isArray(result)) {
if (result.length > 0) {
res.status(200).json(result[0].geometry)
} else {
res.status(404).json('not found')
}
} else {
res.status(404).json('not found')
}
} catch (err) {
res.status(500)
}
})
router.get('/images/all', async (req: Request, res: Response) => {
try {
const { offset, limit, city_id } = req.query

37
ems/src/utils/postgres.ts

@ -0,0 +1,37 @@
import { Pool } from 'pg';
import 'dotenv/config';
// Environment variables for database configuration
const PG_HOST = process.env.PG_HOST || 'localhost';
const PG_PORT = Number(process.env.PG_PORT) || 5432;
const PG_USER = process.env.PG_USER || 'postgres';
const PG_PASSWORD = process.env.PG_PASSWORD || '';
const PG_DB = process.env.PG_DB || 'postgres';
// Create a connection pool
const pool = new Pool({
host: PG_HOST,
port: PG_PORT,
user: PG_USER,
password: PG_PASSWORD,
database: PG_DB,
});
export async function pgQuery(query: string, params: any[] = []) {
try {
// Get a client from the pool
const client = await pool.connect();
try {
// Execute the query with parameters
const result = await client.query(query, params);
return result.rows; // Return only the rows
} finally {
// Release the client back to the pool
client.release();
}
} catch (err) {
// Log error and rethrow it
console.error(`Error executing query: ${query}`, err);
throw err;
}
}
Loading…
Cancel
Save